Commit 5e1cbbabd929e9894e5ec50b1db86d3db588d730

Authored by dmayerich
1 parent 6f131540

Bug fixes. UI updates.

@@ -63,11 +63,11 @@ calculate_near_field @@ -63,11 +63,11 @@ calculate_near_field
63 near_field_plane_coord 63 near_field_plane_coord
64 1 64 1
65 near_field_plane_position 65 near_field_plane_position
66 -0.d0 66 +0.0
67 near_field_plane_vertices 67 near_field_plane_vertices
68 --20.d0,-20.d0,20.d0,20.d0 68 +-20.0,-20.0,20.0,20.0
69 spacial_step_size 69 spacial_step_size
70 -.2d0 70 +.20
71 polarization_angle_deg 71 polarization_angle_deg
72 0.d0 72 0.d0
73 near_field_output_file 73 near_field_output_file
@@ -13,6 +13,8 @@ from PyQt4 import uic @@ -13,6 +13,8 @@ from PyQt4 import uic
13 13
14 #Matplotlib libraries 14 #Matplotlib libraries
15 import matplotlib.pyplot as plt 15 import matplotlib.pyplot as plt
  16 +from matplotlib.patches import Patch
  17 +from pylab import *
16 18
17 class GuiWindow(QtGui.QMainWindow): 19 class GuiWindow(QtGui.QMainWindow):
18 20
@@ -22,37 +24,64 @@ class GuiWindow(QtGui.QMainWindow): @@ -22,37 +24,64 @@ class GuiWindow(QtGui.QMainWindow):
22 #update the Gui based on values in the parameters structure 24 #update the Gui based on values in the parameters structure
23 self.ui.spinStartLambda.setValue(self.params.minLambda) 25 self.ui.spinStartLambda.setValue(self.params.minLambda)
24 self.ui.spinEndLambda.setValue(self.params.maxLambda) 26 self.ui.spinEndLambda.setValue(self.params.maxLambda)
  27 + self.ui.spinNearFieldLambda.setValue(self.params.snapshotLambda)
25 self.ui.spinNumSamples.setValue(self.params.nSamples) 28 self.ui.spinNumSamples.setValue(self.params.nSamples)
26 self.ui.spinNumSpheres.setValue(int(self.params['number_spheres'])) 29 self.ui.spinNumSpheres.setValue(int(self.params['number_spheres']))
  30 + #near field stuff
  31 + self.ui.cmbPlaneSlice.setCurrentIndex(int(self.params['near_field_plane_coord']) - 1)
  32 + verts = self.params['near_field_plane_vertices']
  33 + self.ui.spinNearFieldWidth.setValue(verts[2] - verts[0])
  34 + self.ui.spinNearFieldHeight.setValue(verts[3] - verts[1])
  35 + self.ui.spinNearFieldSteps.setValue(self.params.nSteps)
27 36
28 fi = QtCore.QFileInfo(self.params.matFilename) 37 fi = QtCore.QFileInfo(self.params.matFilename)
29 self.ui.txtMaterial.setText(fi.baseName()) 38 self.ui.txtMaterial.setText(fi.baseName())
30 39
31 #update global parameters for the dimer simulation 40 #update global parameters for the dimer simulation
32 - self.ui.spinSpacing.setValue(d) 41 + self.ui.spinSpacing.setValue(self.params.d)
  42 + self.ui.spinRadius.setValue(self.params.a)
33 43
34 def getParams(self): 44 def getParams(self):
35 self.params.minLambda = self.ui.spinStartLambda.value() 45 self.params.minLambda = self.ui.spinStartLambda.value()
36 self.params.maxLambda = self.ui.spinEndLambda.value() 46 self.params.maxLambda = self.ui.spinEndLambda.value()
  47 + self.params.snapshotLambda = self.ui.spinNearFieldLambda.value()
37 self.params.nSamples = self.ui.spinNumSamples.value() 48 self.params.nSamples = self.ui.spinNumSamples.value()
38 self.params.nSpheres = self.ui.spinNumSpheres.value() 49 self.params.nSpheres = self.ui.spinNumSpheres.value()
39 - self.params['incident_azimuth_angle_deg'] = self.ui.spinAlpha.value()  
40 - self.params['incident_polar_angle_deg'] = self.ui.spinBeta.value()  
41 - self.params.showOutput = self.ui.chkShowOutput.isChecked()  
42 - self.params.inWater = self.ui.chkInWater.isChecked() 50 +
  51 + #incident light properties
43 if self.ui.chkRandomOrientation.isChecked(): 52 if self.ui.chkRandomOrientation.isChecked():
44 self.params['fixed_or_random_orientation'] = 1 53 self.params['fixed_or_random_orientation'] = 1
45 else: 54 else:
46 self.params['fixed_or_random_orientation'] = 0 55 self.params['fixed_or_random_orientation'] = 0
  56 + self.params['incident_azimuth_angle_deg'] = self.ui.spinAlpha.value()
  57 + self.params['incident_polar_angle_deg'] = self.ui.spinBeta.value()
  58 + self.params['polarization_angle_deg'] = self.ui.spinGamma.value()
  59 +
  60 + self.params.showOutput = self.ui.chkShowOutput.isChecked()
47 61
  62 + self.params.inWater = self.ui.chkInWater.isChecked()
  63 +
  64 +
  65 + #near field
  66 + if self.ui.chkNearField.isChecked():
  67 + self.params['calculate_near_field'] = 1
  68 + else:
  69 + self.params['calculate_near_field'] = 0
  70 + self.params['near_field_plane_coord'] = self.ui.cmbPlaneSlice.currentIndex() + 1
  71 + width = (self.ui.spinNearFieldWidth.value()/2)
  72 + height = (self.ui.spinNearFieldHeight.value()/2)
  73 + self.params['near_field_plane_vertices'] = [-width, -height, width, height]
  74 + dx = self.ui.spinNearFieldWidth.value() / (self.ui.spinNearFieldSteps.value() - 1)
  75 + self.params['spacial_step_size'] = dx
48 76
49 #global parameters for dimers 77 #global parameters for dimers
50 - d = self.ui.spinSpacing.value()  
51 - 78 + self.params.d = self.ui.spinSpacing.value()
  79 + self.params.a = self.ui.spinRadius.value()
  80 +
52 return self.params 81 return self.params
53 82
54 def simulate(self): 83 def simulate(self):
55 - self.results = RunSimulation() 84 + self.results = RunSimulation(True)
56 85
57 #plot results of interest 86 #plot results of interest
58 wl = self.results['lambda'] 87 wl = self.results['lambda']
@@ -67,12 +96,58 @@ class GuiWindow(QtGui.QMainWindow): @@ -67,12 +96,58 @@ class GuiWindow(QtGui.QMainWindow):
67 else: 96 else:
68 total = self.results['extinction_total'] 97 total = self.results['extinction_total']
69 plt.plot(wl, total, 'r-', label='extinction') 98 plt.plot(wl, total, 'r-', label='extinction')
  99 +
  100 + #plot the near field maximum values if available
  101 +
  102 + if self.params['calculate_near_field']:
  103 + maxima = self.results.maxNearField
  104 + print(len(wl))
  105 + print(len(maxima))
  106 + plt.plot(wl, maxima)
  107 +
  108 +
70 109
71 plt.legend(loc = 'upper left') 110 plt.legend(loc = 'upper left')
72 plt.ylabel('Extinction') 111 plt.ylabel('Extinction')
73 plt.xlabel('Wavelength (um)') 112 plt.xlabel('Wavelength (um)')
74 plt.show() 113 plt.show()
75 114
  115 + def func3(self, x,y):
  116 + return (1- x/2 + x**5 + y**3)*exp(-x**2-y**2)
  117 +
  118 + def snapshot(self):
  119 +
  120 + self.results = RunSimulation(False)
  121 +
  122 + if self.params['calculate_near_field']:
  123 + #verts = self.params['near_field_plane_vertices']
  124 + #dx = (verts[2] - verts[0])/(self.params.nSteps)
  125 + #x = arange(verts[0], verts[2], dx)
  126 + #print(len(x))
  127 + #y = arange(verts[1], verts[3], dx)
  128 + #X, Y = meshgrid(x, y)
  129 + E = array(self.results.gridNearField)
  130 + #pcolor(X, Y, E, cmap=cm.RdBu)
  131 + #colorbar()
  132 + #axis([verts[0], verts[2], verts[1], verts[3]])
  133 +
  134 + pcolor(E, cmap=cm.RdBu)
  135 + colorbar()
  136 +
  137 + # make these smaller to increase the resolution
  138 + #dx, dy = 0.05, 0.05
  139 +
  140 + #x = arange(-3.0, 3.0001, dx)
  141 + #y = arange(-3.0, 3.0001, dy)
  142 + #X,Y = meshgrid(x, y)
  143 +
  144 + #Z = self.func3(X, Y)
  145 + #pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
  146 + #colorbar()
  147 + #axis([-3,3,-3,3])
  148 +
  149 + show()
  150 +
76 def saveresults(self): 151 def saveresults(self):
77 fileName = QtGui.QFileDialog.getSaveFileName(w, 'Save Spectral Results', '', 'DAT data files (*.dat)') 152 fileName = QtGui.QFileDialog.getSaveFileName(w, 'Save Spectral Results', '', 'DAT data files (*.dat)')
78 if fileName: 153 if fileName:
@@ -85,6 +160,10 @@ class GuiWindow(QtGui.QMainWindow): @@ -85,6 +160,10 @@ class GuiWindow(QtGui.QMainWindow):
85 160
86 fi = QtCore.QFileInfo(fileName) 161 fi = QtCore.QFileInfo(fileName)
87 self.ui.txtMaterial.setText(fi.baseName()) 162 self.ui.txtMaterial.setText(fi.baseName())
  163 +
  164 + def spherenum(self, i):
  165 + self.ui.tblSpheres.setRowCount(i)
  166 + print(i)
88 167
89 def __init__(self): 168 def __init__(self):
90 QtGui.QWidget.__init__(self) 169 QtGui.QWidget.__init__(self)
@@ -100,10 +179,13 @@ class GuiWindow(QtGui.QMainWindow): @@ -100,10 +179,13 @@ class GuiWindow(QtGui.QMainWindow):
100 #display the UI 179 #display the UI
101 self.ui.show() 180 self.ui.show()
102 181
103 - #simulation button 182 + #controls
104 self.connect(self.ui.btnSimulate, QtCore.SIGNAL("clicked()"), self.simulate) 183 self.connect(self.ui.btnSimulate, QtCore.SIGNAL("clicked()"), self.simulate)
  184 + self.connect(self.ui.btnEvaluateNearField, QtCore.SIGNAL("clicked()"), self.snapshot)
105 self.connect(self.ui.mnuSaveResults, QtCore.SIGNAL("triggered()"), self.saveresults) 185 self.connect(self.ui.mnuSaveResults, QtCore.SIGNAL("triggered()"), self.saveresults)
106 self.connect(self.ui.mnuLoadMaterial, QtCore.SIGNAL("triggered()"), self.loadmaterial) 186 self.connect(self.ui.mnuLoadMaterial, QtCore.SIGNAL("triggered()"), self.loadmaterial)
  187 + self.connect(self.ui.spinNumSpheres, QtCore.SIGNAL("valueChanged(int)"), self.spherenum)
  188 +
107 189
108 class ProgressBar(QtGui.QWidget): 190 class ProgressBar(QtGui.QWidget):
109 def __init__(self, parent=None, total=20): 191 def __init__(self, parent=None, total=20):
@@ -124,7 +206,7 @@ class ProgressBar(QtGui.QWidget): @@ -124,7 +206,7 @@ class ProgressBar(QtGui.QWidget):
124 self.progressbar.setValue(val) 206 self.progressbar.setValue(val)
125 207
126 208
127 -def RunSimulation(): 209 +def RunSimulation(spectralSim = True):
128 210
129 #set the parameters based on the UI 211 #set the parameters based on the UI
130 parameters = w.getParams() 212 parameters = w.getParams()
@@ -138,10 +220,15 @@ def RunSimulation(): @@ -138,10 +220,15 @@ def RunSimulation():
138 if parameters.inWater: 220 if parameters.inWater:
139 material.addSolution(1.33) 221 material.addSolution(1.33)
140 222
141 - #range for simulation  
142 - minLambda = parameters.minLambda  
143 - maxLambda = parameters.maxLambda  
144 - nSamples = parameters.nSamples 223 + #for a spectral simulation, set the range and number of samples
  224 + if spectralSim:
  225 + minLambda = parameters.minLambda
  226 + maxLambda = parameters.maxLambda
  227 + nSamples = parameters.nSamples
  228 + else:
  229 + minLambda = parameters.snapshotLambda
  230 + maxLambda = parameters.snapshotLambda
  231 + nSamples = 1
145 232
146 #store the simulation results 233 #store the simulation results
147 results = SimParserClass(parameters) 234 results = SimParserClass(parameters)
@@ -153,7 +240,10 @@ def RunSimulation(): @@ -153,7 +240,10 @@ def RunSimulation():
153 #for each wavelength in the material 240 #for each wavelength in the material
154 for i in range(nSamples): 241 for i in range(nSamples):
155 242
156 - l = minLambda + i*(maxLambda - minLambda)/(nSamples - 1) 243 + if i == 0:
  244 + l = minLambda
  245 + else:
  246 + l = minLambda + i*(maxLambda - minLambda)/(nSamples - 1)
157 247
158 248
159 249
@@ -164,16 +254,16 @@ def RunSimulation(): @@ -164,16 +254,16 @@ def RunSimulation():
164 parameters['imag_ref_index_scale_factor'] = n.imag 254 parameters['imag_ref_index_scale_factor'] = n.imag
165 parameters['length_scale_factor'] = (2.0 * 3.14159)/l 255 parameters['length_scale_factor'] = (2.0 * 3.14159)/l
166 parameters['scattering_plane_angle_deg'] = gamma; 256 parameters['scattering_plane_angle_deg'] = gamma;
167 - #parameters['fixed_or_random_orientation'] = 0  
168 - #print(parameters['fixed_or_random_orientation'])  
169 - 257 + parameters['near_field_output_data'] = 0
170 258
  259 + a = parameters.a;
  260 + d = parameters.d;
171 parameters.clearSpheres() 261 parameters.clearSpheres()
172 parameters.addSphere(a, -(d + 2*a)/2, 0, 0) 262 parameters.addSphere(a, -(d + 2*a)/2, 0, 0)
173 parameters.addSphere(a, (d + 2*a)/2, 0, 0) 263 parameters.addSphere(a, (d + 2*a)/2, 0, 0)
174 264
175 #save the scripted input file 265 #save the scripted input file
176 - parameters.saveFile('scriptParams.inp') 266 + parameters.saveFile(l, 'scriptParams.inp')
177 267
178 #run the binary 268 #run the binary
179 from subprocess import call 269 from subprocess import call
@@ -183,11 +273,15 @@ def RunSimulation(): @@ -183,11 +273,15 @@ def RunSimulation():
183 devnull = open('/dev/null', 'w') 273 devnull = open('/dev/null', 'w')
184 call(["./ms-tmatrix", "scriptParams.inp"], stdout=devnull) 274 call(["./ms-tmatrix", "scriptParams.inp"], stdout=devnull)
185 275
  276 + #parse the simulation results
186 results.parseSimFile(l, 'test.dat') 277 results.parseSimFile(l, 'test.dat')
  278 +
  279 + if parameters['calculate_near_field']:
  280 + results.parseNearField('nf-temp.dat')
  281 +
187 282
188 #update the progress bar 283 #update the progress bar
189 pbar.update_progressbar(i+1) 284 pbar.update_progressbar(i+1)
190 - print(i+1)  
191 285
192 #return the results 286 #return the results
193 return results; 287 return results;
@@ -197,10 +291,7 @@ def RunSimulation(): @@ -197,10 +291,7 @@ def RunSimulation():
197 291
198 292
199 293
200 -#sphere radii  
201 -a = 0.025  
202 -#distance between spheres  
203 -d = 0.002 294 +
204 #incident light directions 295 #incident light directions
205 alpha = 0 296 alpha = 0
206 beta = 0 297 beta = 0
@@ -6,27 +6,14 @@ @@ -6,27 +6,14 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 - <width>599</width>  
10 - <height>418</height> 9 + <width>590</width>
  10 + <height>627</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="windowTitle"> 13 <property name="windowTitle">
14 <string>Spectral Multi-Sphere T-Matrix Simulation</string> 14 <string>Spectral Multi-Sphere T-Matrix Simulation</string>
15 </property> 15 </property>
16 <widget class="QWidget" name="centralwidget"> 16 <widget class="QWidget" name="centralwidget">
17 - <widget class="QPushButton" name="btnSimulate">  
18 - <property name="geometry">  
19 - <rect>  
20 - <x>400</x>  
21 - <y>70</y>  
22 - <width>89</width>  
23 - <height>23</height>  
24 - </rect>  
25 - </property>  
26 - <property name="text">  
27 - <string>Simulate</string>  
28 - </property>  
29 - </widget>  
30 <widget class="QLabel" name="label_7"> 17 <widget class="QLabel" name="label_7">
31 <property name="geometry"> 18 <property name="geometry">
32 <rect> 19 <rect>
@@ -123,7 +110,7 @@ @@ -123,7 +110,7 @@
123 </rect> 110 </rect>
124 </property> 111 </property>
125 <property name="text"> 112 <property name="text">
126 - <string>Wavelengths(um)</string> 113 + <string>Wavelengths (um)</string>
127 </property> 114 </property>
128 <property name="alignment"> 115 <property name="alignment">
129 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> 116 <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -176,7 +163,7 @@ @@ -176,7 +163,7 @@
176 <property name="geometry"> 163 <property name="geometry">
177 <rect> 164 <rect>
178 <x>10</x> 165 <x>10</x>
179 - <y>150</y> 166 + <y>270</y>
180 <width>361</width> 167 <width>361</width>
181 <height>91</height> 168 <height>91</height>
182 </rect> 169 </rect>
@@ -187,8 +174,8 @@ @@ -187,8 +174,8 @@
187 <widget class="QLabel" name="label_6"> 174 <widget class="QLabel" name="label_6">
188 <property name="geometry"> 175 <property name="geometry">
189 <rect> 176 <rect>
190 - <x>220</x>  
191 - <y>60</y> 177 + <x>330</x>
  178 + <y>30</y>
192 <width>31</width> 179 <width>31</width>
193 <height>21</height> 180 <height>21</height>
194 </rect> 181 </rect>
@@ -216,9 +203,9 @@ @@ -216,9 +203,9 @@
216 <widget class="QLabel" name="label_4"> 203 <widget class="QLabel" name="label_4">
217 <property name="geometry"> 204 <property name="geometry">
218 <rect> 205 <rect>
219 - <x>0</x> 206 + <x>10</x>
220 <y>30</y> 207 <y>30</y>
221 - <width>111</width> 208 + <width>71</width>
222 <height>21</height> 209 <height>21</height>
223 </rect> 210 </rect>
224 </property> 211 </property>
@@ -247,23 +234,55 @@ @@ -247,23 +234,55 @@
247 </widget> 234 </widget>
248 <widget class="QSpinBox" name="spinNumSpheres"> 235 <widget class="QSpinBox" name="spinNumSpheres">
249 <property name="enabled"> 236 <property name="enabled">
250 - <bool>false</bool> 237 + <bool>true</bool>
251 </property> 238 </property>
252 <property name="geometry"> 239 <property name="geometry">
253 <rect> 240 <rect>
254 - <x>120</x> 241 + <x>90</x>
255 <y>30</y> 242 <y>30</y>
256 <width>55</width> 243 <width>55</width>
257 <height>22</height> 244 <height>22</height>
258 </rect> 245 </rect>
259 </property> 246 </property>
260 </widget> 247 </widget>
  248 + <widget class="QLabel" name="label_10">
  249 + <property name="geometry">
  250 + <rect>
  251 + <x>170</x>
  252 + <y>30</y>
  253 + <width>51</width>
  254 + <height>21</height>
  255 + </rect>
  256 + </property>
  257 + <property name="text">
  258 + <string>Radius</string>
  259 + </property>
  260 + <property name="alignment">
  261 + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  262 + </property>
  263 + </widget>
  264 + <widget class="QDoubleSpinBox" name="spinRadius">
  265 + <property name="geometry">
  266 + <rect>
  267 + <x>230</x>
  268 + <y>30</y>
  269 + <width>91</width>
  270 + <height>22</height>
  271 + </rect>
  272 + </property>
  273 + <property name="decimals">
  274 + <number>4</number>
  275 + </property>
  276 + <property name="singleStep">
  277 + <double>0.001000000000000</double>
  278 + </property>
  279 + </widget>
261 </widget> 280 </widget>
262 <widget class="QGroupBox" name="groupBox_3"> 281 <widget class="QGroupBox" name="groupBox_3">
263 <property name="geometry"> 282 <property name="geometry">
264 <rect> 283 <rect>
265 <x>10</x> 284 <x>10</x>
266 - <y>250</y> 285 + <y>150</y>
267 <width>361</width> 286 <width>361</width>
268 <height>111</height> 287 <height>111</height>
269 </rect> 288 </rect>
@@ -274,8 +293,8 @@ @@ -274,8 +293,8 @@
274 <widget class="QLabel" name="label_8"> 293 <widget class="QLabel" name="label_8">
275 <property name="geometry"> 294 <property name="geometry">
276 <rect> 295 <rect>
277 - <x>20</x>  
278 - <y>20</y> 296 + <x>0</x>
  297 + <y>50</y>
279 <width>91</width> 298 <width>91</width>
280 <height>21</height> 299 <height>21</height>
281 </rect> 300 </rect>
@@ -290,8 +309,8 @@ @@ -290,8 +309,8 @@
290 <widget class="QDoubleSpinBox" name="spinAlpha"> 309 <widget class="QDoubleSpinBox" name="spinAlpha">
291 <property name="geometry"> 310 <property name="geometry">
292 <rect> 311 <rect>
293 - <x>120</x>  
294 - <y>20</y> 312 + <x>100</x>
  313 + <y>50</y>
295 <width>91</width> 314 <width>91</width>
296 <height>22</height> 315 <height>22</height>
297 </rect> 316 </rect>
@@ -299,6 +318,9 @@ @@ -299,6 +318,9 @@
299 <property name="decimals"> 318 <property name="decimals">
300 <number>3</number> 319 <number>3</number>
301 </property> 320 </property>
  321 + <property name="maximum">
  322 + <double>180.000000000000000</double>
  323 + </property>
302 <property name="singleStep"> 324 <property name="singleStep">
303 <double>0.100000000000000</double> 325 <double>0.100000000000000</double>
304 </property> 326 </property>
@@ -306,8 +328,8 @@ @@ -306,8 +328,8 @@
306 <widget class="QLabel" name="label_9"> 328 <widget class="QLabel" name="label_9">
307 <property name="geometry"> 329 <property name="geometry">
308 <rect> 330 <rect>
309 - <x>20</x>  
310 - <y>50</y> 331 + <x>0</x>
  332 + <y>80</y>
311 <width>91</width> 333 <width>91</width>
312 <height>21</height> 334 <height>21</height>
313 </rect> 335 </rect>
@@ -322,8 +344,71 @@ @@ -322,8 +344,71 @@
322 <widget class="QDoubleSpinBox" name="spinBeta"> 344 <widget class="QDoubleSpinBox" name="spinBeta">
323 <property name="geometry"> 345 <property name="geometry">
324 <rect> 346 <rect>
325 - <x>120</x>  
326 - <y>50</y> 347 + <x>100</x>
  348 + <y>80</y>
  349 + <width>91</width>
  350 + <height>22</height>
  351 + </rect>
  352 + </property>
  353 + <property name="decimals">
  354 + <number>3</number>
  355 + </property>
  356 + <property name="maximum">
  357 + <double>180.000000000000000</double>
  358 + </property>
  359 + <property name="singleStep">
  360 + <double>0.100000000000000</double>
  361 + </property>
  362 + </widget>
  363 + <widget class="QLabel" name="label_15">
  364 + <property name="geometry">
  365 + <rect>
  366 + <x>50</x>
  367 + <y>20</y>
  368 + <width>111</width>
  369 + <height>21</height>
  370 + </rect>
  371 + </property>
  372 + <property name="font">
  373 + <font>
  374 + <weight>75</weight>
  375 + <bold>true</bold>
  376 + </font>
  377 + </property>
  378 + <property name="text">
  379 + <string>Light Position</string>
  380 + </property>
  381 + <property name="alignment">
  382 + <set>Qt::AlignCenter</set>
  383 + </property>
  384 + </widget>
  385 + <widget class="QLabel" name="label_16">
  386 + <property name="geometry">
  387 + <rect>
  388 + <x>230</x>
  389 + <y>20</y>
  390 + <width>111</width>
  391 + <height>21</height>
  392 + </rect>
  393 + </property>
  394 + <property name="font">
  395 + <font>
  396 + <weight>75</weight>
  397 + <bold>true</bold>
  398 + </font>
  399 + </property>
  400 + <property name="text">
  401 + <string>Polarization</string>
  402 + </property>
  403 + <property name="alignment">
  404 + <set>Qt::AlignCenter</set>
  405 + </property>
  406 + </widget>
  407 + <widget class="QDoubleSpinBox" name="spinGamma">
  408 + <property name="geometry">
  409 + <rect>
  410 + <x>240</x>
  411 + <y>70</y>
327 <width>91</width> 412 <width>91</width>
328 <height>22</height> 413 <height>22</height>
329 </rect> 414 </rect>
@@ -331,36 +416,294 @@ @@ -331,36 +416,294 @@
331 <property name="decimals"> 416 <property name="decimals">
332 <number>3</number> 417 <number>3</number>
333 </property> 418 </property>
  419 + <property name="maximum">
  420 + <double>180.000000000000000</double>
  421 + </property>
334 <property name="singleStep"> 422 <property name="singleStep">
335 <double>0.100000000000000</double> 423 <double>0.100000000000000</double>
336 </property> 424 </property>
337 </widget> 425 </widget>
  426 + <widget class="QLabel" name="label_17">
  427 + <property name="geometry">
  428 + <rect>
  429 + <x>240</x>
  430 + <y>50</y>
  431 + <width>101</width>
  432 + <height>21</height>
  433 + </rect>
  434 + </property>
  435 + <property name="text">
  436 + <string>gamma (deg.)</string>
  437 + </property>
  438 + <property name="alignment">
  439 + <set>Qt::AlignCenter</set>
  440 + </property>
  441 + </widget>
338 </widget> 442 </widget>
339 - <widget class="QCheckBox" name="chkShowOutput"> 443 + <widget class="QCheckBox" name="chkInWater">
340 <property name="geometry"> 444 <property name="geometry">
341 <rect> 445 <rect>
342 - <x>400</x>  
343 - <y>120</y>  
344 - <width>131</width> 446 + <x>350</x>
  447 + <y>20</y>
  448 + <width>83</width>
345 <height>19</height> 449 <height>19</height>
346 </rect> 450 </rect>
347 </property> 451 </property>
348 <property name="text"> 452 <property name="text">
349 - <string>MS-TM output</string> 453 + <string>in water</string>
350 </property> 454 </property>
351 </widget> 455 </widget>
352 - <widget class="QCheckBox" name="chkInWater"> 456 + <widget class="QGroupBox" name="groupBox_4">
353 <property name="geometry"> 457 <property name="geometry">
354 <rect> 458 <rect>
355 - <x>350</x>  
356 - <y>20</y>  
357 - <width>83</width>  
358 - <height>19</height> 459 + <x>390</x>
  460 + <y>250</y>
  461 + <width>181</width>
  462 + <height>231</height>
359 </rect> 463 </rect>
360 </property> 464 </property>
361 - <property name="text">  
362 - <string>in water</string> 465 + <property name="title">
  466 + <string>Near Field</string>
363 </property> 467 </property>
  468 + <widget class="QCheckBox" name="chkNearField">
  469 + <property name="geometry">
  470 + <rect>
  471 + <x>20</x>
  472 + <y>30</y>
  473 + <width>151</width>
  474 + <height>19</height>
  475 + </rect>
  476 + </property>
  477 + <property name="text">
  478 + <string>Compute Near Field</string>
  479 + </property>
  480 + </widget>
  481 + <widget class="QComboBox" name="cmbPlaneSlice">
  482 + <property name="geometry">
  483 + <rect>
  484 + <x>70</x>
  485 + <y>60</y>
  486 + <width>61</width>
  487 + <height>22</height>
  488 + </rect>
  489 + </property>
  490 + <item>
  491 + <property name="text">
  492 + <string>Y - Z</string>
  493 + </property>
  494 + </item>
  495 + <item>
  496 + <property name="text">
  497 + <string>Z - X</string>
  498 + </property>
  499 + </item>
  500 + <item>
  501 + <property name="text">
  502 + <string>X - Y</string>
  503 + </property>
  504 + </item>
  505 + </widget>
  506 + <widget class="QDoubleSpinBox" name="spinNearFieldWidth">
  507 + <property name="geometry">
  508 + <rect>
  509 + <x>70</x>
  510 + <y>100</y>
  511 + <width>62</width>
  512 + <height>22</height>
  513 + </rect>
  514 + </property>
  515 + <property name="singleStep">
  516 + <double>0.100000000000000</double>
  517 + </property>
  518 + </widget>
  519 + <widget class="QLabel" name="label_12">
  520 + <property name="geometry">
  521 + <rect>
  522 + <x>20</x>
  523 + <y>100</y>
  524 + <width>41</width>
  525 + <height>21</height>
  526 + </rect>
  527 + </property>
  528 + <property name="text">
  529 + <string>width</string>
  530 + </property>
  531 + <property name="alignment">
  532 + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  533 + </property>
  534 + </widget>
  535 + <widget class="QLabel" name="label_13">
  536 + <property name="geometry">
  537 + <rect>
  538 + <x>20</x>
  539 + <y>140</y>
  540 + <width>41</width>
  541 + <height>21</height>
  542 + </rect>
  543 + </property>
  544 + <property name="text">
  545 + <string>height</string>
  546 + </property>
  547 + <property name="alignment">
  548 + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  549 + </property>
  550 + </widget>
  551 + <widget class="QDoubleSpinBox" name="spinNearFieldHeight">
  552 + <property name="geometry">
  553 + <rect>
  554 + <x>70</x>
  555 + <y>140</y>
  556 + <width>62</width>
  557 + <height>22</height>
  558 + </rect>
  559 + </property>
  560 + <property name="singleStep">
  561 + <double>0.100000000000000</double>
  562 + </property>
  563 + </widget>
  564 + <widget class="QLabel" name="label_14">
  565 + <property name="geometry">
  566 + <rect>
  567 + <x>20</x>
  568 + <y>180</y>
  569 + <width>41</width>
  570 + <height>21</height>
  571 + </rect>
  572 + </property>
  573 + <property name="text">
  574 + <string>steps</string>
  575 + </property>
  576 + <property name="alignment">
  577 + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  578 + </property>
  579 + </widget>
  580 + <widget class="QSpinBox" name="spinNearFieldSteps">
  581 + <property name="geometry">
  582 + <rect>
  583 + <x>70</x>
  584 + <y>180</y>
  585 + <width>61</width>
  586 + <height>22</height>
  587 + </rect>
  588 + </property>
  589 + <property name="maximum">
  590 + <number>9999</number>
  591 + </property>
  592 + </widget>
  593 + </widget>
  594 + <widget class="QGroupBox" name="groupBox_5">
  595 + <property name="geometry">
  596 + <rect>
  597 + <x>390</x>
  598 + <y>50</y>
  599 + <width>171</width>
  600 + <height>191</height>
  601 + </rect>
  602 + </property>
  603 + <property name="title">
  604 + <string>Simulate</string>
  605 + </property>
  606 + <widget class="QCheckBox" name="chkShowOutput">
  607 + <property name="geometry">
  608 + <rect>
  609 + <x>40</x>
  610 + <y>140</y>
  611 + <width>101</width>
  612 + <height>19</height>
  613 + </rect>
  614 + </property>
  615 + <property name="text">
  616 + <string>MS-TM output</string>
  617 + </property>
  618 + </widget>
  619 + <widget class="QPushButton" name="btnEvaluateNearField">
  620 + <property name="geometry">
  621 + <rect>
  622 + <x>10</x>
  623 + <y>100</y>
  624 + <width>151</width>
  625 + <height>23</height>
  626 + </rect>
  627 + </property>
  628 + <property name="text">
  629 + <string>Simulate Wavelength</string>
  630 + </property>
  631 + </widget>
  632 + <widget class="QPushButton" name="btnSimulate">
  633 + <property name="geometry">
  634 + <rect>
  635 + <x>10</x>
  636 + <y>20</y>
  637 + <width>151</width>
  638 + <height>23</height>
  639 + </rect>
  640 + </property>
  641 + <property name="text">
  642 + <string>Simulate Spectrum</string>
  643 + </property>
  644 + </widget>
  645 + <widget class="QDoubleSpinBox" name="spinNearFieldLambda">
  646 + <property name="geometry">
  647 + <rect>
  648 + <x>40</x>
  649 + <y>70</y>
  650 + <width>91</width>
  651 + <height>22</height>
  652 + </rect>
  653 + </property>
  654 + </widget>
  655 + <widget class="QLabel" name="label_11">
  656 + <property name="geometry">
  657 + <rect>
  658 + <x>30</x>
  659 + <y>50</y>
  660 + <width>111</width>
  661 + <height>21</height>
  662 + </rect>
  663 + </property>
  664 + <property name="text">
  665 + <string>Wavelength (um)</string>
  666 + </property>
  667 + <property name="alignment">
  668 + <set>Qt::AlignCenter</set>
  669 + </property>
  670 + </widget>
  671 + </widget>
  672 + <widget class="QTableWidget" name="tblSpheres">
  673 + <property name="geometry">
  674 + <rect>
  675 + <x>10</x>
  676 + <y>390</y>
  677 + <width>361</width>
  678 + <height>181</height>
  679 + </rect>
  680 + </property>
  681 + <attribute name="horizontalHeaderDefaultSectionSize">
  682 + <number>89</number>
  683 + </attribute>
  684 + <attribute name="verticalHeaderDefaultSectionSize">
  685 + <number>30</number>
  686 + </attribute>
  687 + <column>
  688 + <property name="text">
  689 + <string>radius</string>
  690 + </property>
  691 + </column>
  692 + <column>
  693 + <property name="text">
  694 + <string>pX</string>
  695 + </property>
  696 + </column>
  697 + <column>
  698 + <property name="text">
  699 + <string>y</string>
  700 + </property>
  701 + </column>
  702 + <column>
  703 + <property name="text">
  704 + <string>z</string>
  705 + </property>
  706 + </column>
364 </widget> 707 </widget>
365 </widget> 708 </widget>
366 <widget class="QMenuBar" name="menubar"> 709 <widget class="QMenuBar" name="menubar">
@@ -368,7 +711,7 @@ @@ -368,7 +711,7 @@
368 <rect> 711 <rect>
369 <x>0</x> 712 <x>0</x>
370 <y>0</y> 713 <y>0</y>
371 - <width>599</width> 714 + <width>590</width>
372 <height>22</height> 715 <height>22</height>
373 </rect> 716 </rect>
374 </property> 717 </property>
mstm_parameters.py
@@ -2,9 +2,17 @@ class ParameterClass: @@ -2,9 +2,17 @@ class ParameterClass:
2 #minimum and maximum wavelengths for the simulation 2 #minimum and maximum wavelengths for the simulation
3 minLambda = 0.300 3 minLambda = 0.300
4 maxLambda = 0.700 4 maxLambda = 0.700
  5 + snapshotLambda = 0.300
5 #number of spectral samples 6 #number of spectral samples
6 nSamples = 40 7 nSamples = 40
7 8
  9 + #spatial samples
  10 + nSteps = 100
  11 +
  12 + #sphere size and separation
  13 + a = 0.025
  14 + d = 0.005
  15 +
8 #material file name 16 #material file name
9 matFilename = 'etaSilver.txt' 17 matFilename = 'etaSilver.txt'
10 #are the sphere's in water? 18 #are the sphere's in water?
@@ -25,7 +33,7 @@ class ParameterClass: @@ -25,7 +33,7 @@ class ParameterClass:
25 return self.paramDict[key]; 33 return self.paramDict[key];
26 34
27 def __setitem__(self, key, value): 35 def __setitem__(self, key, value):
28 - self.paramDict[key] = str(value); 36 + self.paramDict[key] = value;
29 37
30 def clearSpheres(self): 38 def clearSpheres(self):
31 self.sphereList = [] 39 self.sphereList = []
@@ -40,7 +48,8 @@ class ParameterClass: @@ -40,7 +48,8 @@ class ParameterClass:
40 48
41 while 1: 49 while 1:
42 key = inpFID.readline().strip() 50 key = inpFID.readline().strip()
43 - 51 +
  52 +
44 #deal with sphere sizes and positions 53 #deal with sphere sizes and positions
45 if key == 'sphere_sizes_and_positions': 54 if key == 'sphere_sizes_and_positions':
46 55
@@ -57,13 +66,24 @@ class ParameterClass: @@ -57,13 +66,24 @@ class ParameterClass:
57 break 66 break
58 elif key == 'end_of_options': 67 elif key == 'end_of_options':
59 break 68 break
  69 + #deal with the near field plane
  70 + elif key == 'near_field_plane_vertices':
  71 + value = inpFID.readline().strip()
  72 + #self.paramDict[key] = list(map(float, value.split(',')))
  73 + self.paramDict[key] = [-1, -1, 1, 1]
  74 +
60 else: 75 else:
61 value = inpFID.readline().strip() 76 value = inpFID.readline().strip()
62 self.paramDict[key] = value 77 self.paramDict[key] = value
  78 +
  79 + #update the length scale factor to deal with the UI
  80 + self.paramDict['length_scale_factor'] = (2.0 * 3.14159)/self.snapshotLambda
63 81
64 inpFID.close() 82 inpFID.close()
65 83
66 - def saveFile(self, fileName): 84 + def saveFile(self, l, fileName):
  85 +
  86 + #print(self)
67 87
68 #open the output file 88 #open the output file
69 outFID = open(fileName, 'w') 89 outFID = open(fileName, 'w')
@@ -71,7 +91,20 @@ class ParameterClass: @@ -71,7 +91,20 @@ class ParameterClass:
71 #write the parameters 91 #write the parameters
72 for key in self.paramDict.keys(): 92 for key in self.paramDict.keys():
73 outFID.write(key + '\n') 93 outFID.write(key + '\n')
74 - outFID.write(self.paramDict[key] + '\n') 94 +
  95 + #deal with the near field plane
  96 + if key == 'near_field_plane_vertices':
  97 + #these have to be scaled by the length scale factor
  98 + ls = (2 * 3.14159)/l
  99 + v = self.paramDict[key]
  100 + outFID.write(str(v[0]*ls) + ',' + str(v[1]*ls) + ',' + str(v[2]*ls) + ',' + str(v[3]*ls) + '\n')
  101 + elif key == 'spacial_step_size':
  102 + ls = (2 * 3.14159)/l
  103 + dx = self.paramDict[key] * ls
  104 + outFID.write(str(dx) + '\n')
  105 +
  106 + else:
  107 + outFID.write(str(self.paramDict[key]) + '\n')
75 108
76 #write the spheres 109 #write the spheres
77 outFID.write("sphere_sizes_and_positions\n") 110 outFID.write("sphere_sizes_and_positions\n")
@@ -86,7 +119,12 @@ class ParameterClass: @@ -86,7 +119,12 @@ class ParameterClass:
86 #print(self.paramDict) 119 #print(self.paramDict)
87 result = "" 120 result = ""
88 for key in self.paramDict.keys(): 121 for key in self.paramDict.keys():
89 - result += key + ": " + self.paramDict[key] + '\n' 122 + #deal with the near field plane
  123 + if key == 'near_field_plane_vertices':
  124 + v = map(str, self.paramDict[key])
  125 + result += key + ": " + v[0] + ',' + v[1] + ',' + v[2] + ',' + v[3] + '\n'
  126 + else:
  127 + result += key + ": " + str(self.paramDict[key]) + '\n'
90 128
91 result += "\n" 129 result += "\n"
92 result += "Spheres:\n" 130 result += "Spheres:\n"
  1 +from pylab import *
  2 +
1 class SimParserClass: 3 class SimParserClass:
2 4
3 simResults = dict() 5 simResults = dict()
  6 +
  7 + sxNearField = 0
  8 + syNearField = 0
  9 + intersectedNearField = 0
  10 +
  11 + #near field data
  12 + gridNearField = []
  13 + maxNearField = []
  14 +
4 15
5 def __init__(self, parameters): 16 def __init__(self, parameters):
6 17
@@ -12,9 +23,11 @@ class SimParserClass: @@ -12,9 +23,11 @@ class SimParserClass:
12 self.simResults['extinction_parallel'] = list() 23 self.simResults['extinction_parallel'] = list()
13 self.simResults['extinction_perpendicular'] = list() 24 self.simResults['extinction_perpendicular'] = list()
14 self.simResults['extinction_total'] = list() 25 self.simResults['extinction_total'] = list()
15 -  
16 -  
17 - 26 +
  27 + self.gridNearField = []
  28 + self.maxNearField = []
  29 +
  30 +
18 def parseSimFile(self, l, fileName): 31 def parseSimFile(self, l, fileName):
19 self.simResults['lambda'].append(l) 32 self.simResults['lambda'].append(l)
20 inFile = open(fileName, 'r') 33 inFile = open(fileName, 'r')
@@ -38,13 +51,39 @@ class SimParserClass: @@ -38,13 +51,39 @@ class SimParserClass:
38 self.simResults['extinction_perpendicular'].append(values[0]) 51 self.simResults['extinction_perpendicular'].append(values[0])
39 52
40 else: 53 else:
41 - #print('making it here')  
42 - #print(self.params['fixed_or_random_orientation'])  
43 if line == 'scattering matrix elements': 54 if line == 'scattering matrix elements':
44 break 55 break
45 elif line == 'total ext, abs, scat efficiencies, w.r.t. xv, and asym. parm': 56 elif line == 'total ext, abs, scat efficiencies, w.r.t. xv, and asym. parm':
46 values = inFile.readline().strip().split(' ') 57 values = inFile.readline().strip().split(' ')
47 self.simResults['extinction_total'].append(values[0]) 58 self.simResults['extinction_total'].append(values[0])
  59 +
  60 + def parseNearField(self, fileName):
  61 +
  62 + inFile = open(fileName, 'r')
  63 +
  64 + #get the size of the near field grid
  65 + line = inFile.readline().strip()
  66 + self.sxNearField, self.syNearField = map(int, line.split())
  67 +
  68 + #get the number of spheres that are intersected
  69 + line = inFile.readline().strip()
  70 + self.intersectedNearField = int(line)
  71 +
  72 + #process intersections here-----------
  73 +
  74 +
  75 + #get the field values
  76 + self.gridNearField = []
  77 + for y in range(self.syNearField):
  78 + self.gridNearField.append([])
  79 + for x in range(self.sxNearField):
  80 + line = inFile.readline().strip()
  81 + values = map(float, line.split())
  82 + self.gridNearField[y].append(values[2])
  83 +
  84 + E = array(self.gridNearField)
  85 + self.maxNearField.append(pow(E.max(), 2))
  86 +
48 87
49 def saveFile(self, fileName): 88 def saveFile(self, fileName):
50 outFile = open(fileName, 'w') 89 outFile = open(fileName, 'w')
@@ -58,9 +97,14 @@ class SimParserClass: @@ -58,9 +97,14 @@ class SimParserClass:
58 result = ''; 97 result = '';
59 98
60 for i in range(len(self.simResults['lambda'])): 99 for i in range(len(self.simResults['lambda'])):
61 - result += str(self.simResults['lambda'][i]) + '\t'  
62 - result += str(self.simResults['extinction_unpolarized'][i]) + '\t'  
63 - result += str(self.simResults['extinction_parallel'][i]) + '\t'  
64 - result += str(self.simResults['extinction_perpendicular'][i]) + '\n'  
65 - 100 + result += str(self.simResults['lambda'][i])
  101 + result += '\t' + str(self.simResults['extinction_unpolarized'][i])
  102 + result += '\t' + str(self.simResults['extinction_parallel'][i])
  103 + result += '\t' + str(self.simResults['extinction_perpendicular'][i])
  104 +
  105 + #parse the near field if it is included in the simulation
  106 + if int(parameters['calculate_near_field']) == 1:
  107 + result += '\t' + str(maxNearField)
  108 +
  109 + result += '\n'
66 return result 110 return result