diff --git a/msinput.inp b/msinput.inp
index 0a9d4e5..5012c29 100755
--- a/msinput.inp
+++ b/msinput.inp
@@ -63,11 +63,11 @@ calculate_near_field
near_field_plane_coord
1
near_field_plane_position
-0.d0
+0.0
near_field_plane_vertices
--20.d0,-20.d0,20.d0,20.d0
+-20.0,-20.0,20.0,20.0
spacial_step_size
-.2d0
+.20
polarization_angle_deg
0.d0
near_field_output_file
diff --git a/mstm-gui.py b/mstm-gui.py
index 0b388a8..97aa743 100755
--- a/mstm-gui.py
+++ b/mstm-gui.py
@@ -13,6 +13,8 @@ from PyQt4 import uic
#Matplotlib libraries
import matplotlib.pyplot as plt
+from matplotlib.patches import Patch
+from pylab import *
class GuiWindow(QtGui.QMainWindow):
@@ -22,37 +24,64 @@ class GuiWindow(QtGui.QMainWindow):
#update the Gui based on values in the parameters structure
self.ui.spinStartLambda.setValue(self.params.minLambda)
self.ui.spinEndLambda.setValue(self.params.maxLambda)
+ self.ui.spinNearFieldLambda.setValue(self.params.snapshotLambda)
self.ui.spinNumSamples.setValue(self.params.nSamples)
self.ui.spinNumSpheres.setValue(int(self.params['number_spheres']))
+ #near field stuff
+ self.ui.cmbPlaneSlice.setCurrentIndex(int(self.params['near_field_plane_coord']) - 1)
+ verts = self.params['near_field_plane_vertices']
+ self.ui.spinNearFieldWidth.setValue(verts[2] - verts[0])
+ self.ui.spinNearFieldHeight.setValue(verts[3] - verts[1])
+ self.ui.spinNearFieldSteps.setValue(self.params.nSteps)
fi = QtCore.QFileInfo(self.params.matFilename)
self.ui.txtMaterial.setText(fi.baseName())
#update global parameters for the dimer simulation
- self.ui.spinSpacing.setValue(d)
+ self.ui.spinSpacing.setValue(self.params.d)
+ self.ui.spinRadius.setValue(self.params.a)
def getParams(self):
self.params.minLambda = self.ui.spinStartLambda.value()
self.params.maxLambda = self.ui.spinEndLambda.value()
+ self.params.snapshotLambda = self.ui.spinNearFieldLambda.value()
self.params.nSamples = self.ui.spinNumSamples.value()
self.params.nSpheres = self.ui.spinNumSpheres.value()
- self.params['incident_azimuth_angle_deg'] = self.ui.spinAlpha.value()
- self.params['incident_polar_angle_deg'] = self.ui.spinBeta.value()
- self.params.showOutput = self.ui.chkShowOutput.isChecked()
- self.params.inWater = self.ui.chkInWater.isChecked()
+
+ #incident light properties
if self.ui.chkRandomOrientation.isChecked():
self.params['fixed_or_random_orientation'] = 1
else:
self.params['fixed_or_random_orientation'] = 0
+ self.params['incident_azimuth_angle_deg'] = self.ui.spinAlpha.value()
+ self.params['incident_polar_angle_deg'] = self.ui.spinBeta.value()
+ self.params['polarization_angle_deg'] = self.ui.spinGamma.value()
+
+ self.params.showOutput = self.ui.chkShowOutput.isChecked()
+ self.params.inWater = self.ui.chkInWater.isChecked()
+
+
+ #near field
+ if self.ui.chkNearField.isChecked():
+ self.params['calculate_near_field'] = 1
+ else:
+ self.params['calculate_near_field'] = 0
+ self.params['near_field_plane_coord'] = self.ui.cmbPlaneSlice.currentIndex() + 1
+ width = (self.ui.spinNearFieldWidth.value()/2)
+ height = (self.ui.spinNearFieldHeight.value()/2)
+ self.params['near_field_plane_vertices'] = [-width, -height, width, height]
+ dx = self.ui.spinNearFieldWidth.value() / (self.ui.spinNearFieldSteps.value() - 1)
+ self.params['spacial_step_size'] = dx
#global parameters for dimers
- d = self.ui.spinSpacing.value()
-
+ self.params.d = self.ui.spinSpacing.value()
+ self.params.a = self.ui.spinRadius.value()
+
return self.params
def simulate(self):
- self.results = RunSimulation()
+ self.results = RunSimulation(True)
#plot results of interest
wl = self.results['lambda']
@@ -67,12 +96,58 @@ class GuiWindow(QtGui.QMainWindow):
else:
total = self.results['extinction_total']
plt.plot(wl, total, 'r-', label='extinction')
+
+ #plot the near field maximum values if available
+
+ if self.params['calculate_near_field']:
+ maxima = self.results.maxNearField
+ print(len(wl))
+ print(len(maxima))
+ plt.plot(wl, maxima)
+
+
plt.legend(loc = 'upper left')
plt.ylabel('Extinction')
plt.xlabel('Wavelength (um)')
plt.show()
+ def func3(self, x,y):
+ return (1- x/2 + x**5 + y**3)*exp(-x**2-y**2)
+
+ def snapshot(self):
+
+ self.results = RunSimulation(False)
+
+ if self.params['calculate_near_field']:
+ #verts = self.params['near_field_plane_vertices']
+ #dx = (verts[2] - verts[0])/(self.params.nSteps)
+ #x = arange(verts[0], verts[2], dx)
+ #print(len(x))
+ #y = arange(verts[1], verts[3], dx)
+ #X, Y = meshgrid(x, y)
+ E = array(self.results.gridNearField)
+ #pcolor(X, Y, E, cmap=cm.RdBu)
+ #colorbar()
+ #axis([verts[0], verts[2], verts[1], verts[3]])
+
+ pcolor(E, cmap=cm.RdBu)
+ colorbar()
+
+ # make these smaller to increase the resolution
+ #dx, dy = 0.05, 0.05
+
+ #x = arange(-3.0, 3.0001, dx)
+ #y = arange(-3.0, 3.0001, dy)
+ #X,Y = meshgrid(x, y)
+
+ #Z = self.func3(X, Y)
+ #pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
+ #colorbar()
+ #axis([-3,3,-3,3])
+
+ show()
+
def saveresults(self):
fileName = QtGui.QFileDialog.getSaveFileName(w, 'Save Spectral Results', '', 'DAT data files (*.dat)')
if fileName:
@@ -85,6 +160,10 @@ class GuiWindow(QtGui.QMainWindow):
fi = QtCore.QFileInfo(fileName)
self.ui.txtMaterial.setText(fi.baseName())
+
+ def spherenum(self, i):
+ self.ui.tblSpheres.setRowCount(i)
+ print(i)
def __init__(self):
QtGui.QWidget.__init__(self)
@@ -100,10 +179,13 @@ class GuiWindow(QtGui.QMainWindow):
#display the UI
self.ui.show()
- #simulation button
+ #controls
self.connect(self.ui.btnSimulate, QtCore.SIGNAL("clicked()"), self.simulate)
+ self.connect(self.ui.btnEvaluateNearField, QtCore.SIGNAL("clicked()"), self.snapshot)
self.connect(self.ui.mnuSaveResults, QtCore.SIGNAL("triggered()"), self.saveresults)
self.connect(self.ui.mnuLoadMaterial, QtCore.SIGNAL("triggered()"), self.loadmaterial)
+ self.connect(self.ui.spinNumSpheres, QtCore.SIGNAL("valueChanged(int)"), self.spherenum)
+
class ProgressBar(QtGui.QWidget):
def __init__(self, parent=None, total=20):
@@ -124,7 +206,7 @@ class ProgressBar(QtGui.QWidget):
self.progressbar.setValue(val)
-def RunSimulation():
+def RunSimulation(spectralSim = True):
#set the parameters based on the UI
parameters = w.getParams()
@@ -138,10 +220,15 @@ def RunSimulation():
if parameters.inWater:
material.addSolution(1.33)
- #range for simulation
- minLambda = parameters.minLambda
- maxLambda = parameters.maxLambda
- nSamples = parameters.nSamples
+ #for a spectral simulation, set the range and number of samples
+ if spectralSim:
+ minLambda = parameters.minLambda
+ maxLambda = parameters.maxLambda
+ nSamples = parameters.nSamples
+ else:
+ minLambda = parameters.snapshotLambda
+ maxLambda = parameters.snapshotLambda
+ nSamples = 1
#store the simulation results
results = SimParserClass(parameters)
@@ -153,7 +240,10 @@ def RunSimulation():
#for each wavelength in the material
for i in range(nSamples):
- l = minLambda + i*(maxLambda - minLambda)/(nSamples - 1)
+ if i == 0:
+ l = minLambda
+ else:
+ l = minLambda + i*(maxLambda - minLambda)/(nSamples - 1)
@@ -164,16 +254,16 @@ def RunSimulation():
parameters['imag_ref_index_scale_factor'] = n.imag
parameters['length_scale_factor'] = (2.0 * 3.14159)/l
parameters['scattering_plane_angle_deg'] = gamma;
- #parameters['fixed_or_random_orientation'] = 0
- #print(parameters['fixed_or_random_orientation'])
-
+ parameters['near_field_output_data'] = 0
+ a = parameters.a;
+ d = parameters.d;
parameters.clearSpheres()
parameters.addSphere(a, -(d + 2*a)/2, 0, 0)
parameters.addSphere(a, (d + 2*a)/2, 0, 0)
#save the scripted input file
- parameters.saveFile('scriptParams.inp')
+ parameters.saveFile(l, 'scriptParams.inp')
#run the binary
from subprocess import call
@@ -183,11 +273,15 @@ def RunSimulation():
devnull = open('/dev/null', 'w')
call(["./ms-tmatrix", "scriptParams.inp"], stdout=devnull)
+ #parse the simulation results
results.parseSimFile(l, 'test.dat')
+
+ if parameters['calculate_near_field']:
+ results.parseNearField('nf-temp.dat')
+
#update the progress bar
pbar.update_progressbar(i+1)
- print(i+1)
#return the results
return results;
@@ -197,10 +291,7 @@ def RunSimulation():
-#sphere radii
-a = 0.025
-#distance between spheres
-d = 0.002
+
#incident light directions
alpha = 0
beta = 0
diff --git a/mstm_guiwindow.ui b/mstm_guiwindow.ui
index 7d377ee..c132e51 100755
--- a/mstm_guiwindow.ui
+++ b/mstm_guiwindow.ui
@@ -6,27 +6,14 @@
0
0
- 599
- 418
+ 590
+ 627
Spectral Multi-Sphere T-Matrix Simulation
-
-
-
- 400
- 70
- 89
- 23
-
-
-
- Simulate
-
-
@@ -123,7 +110,7 @@
- Wavelengths(um)
+ Wavelengths (um)
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -176,7 +163,7 @@
10
- 150
+ 270
361
91
@@ -187,8 +174,8 @@
- 220
- 60
+ 330
+ 30
31
21
@@ -216,9 +203,9 @@
- 0
+ 10
30
- 111
+ 71
21
@@ -247,23 +234,55 @@
- false
+ true
- 120
+ 90
30
55
22
+
+
+
+ 170
+ 30
+ 51
+ 21
+
+
+
+ Radius
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 230
+ 30
+ 91
+ 22
+
+
+
+ 4
+
+
+ 0.001000000000000
+
+
10
- 250
+ 150
361
111
@@ -274,8 +293,8 @@
- 20
- 20
+ 0
+ 50
91
21
@@ -290,8 +309,8 @@
- 120
- 20
+ 100
+ 50
91
22
@@ -299,6 +318,9 @@
3
+
+ 180.000000000000000
+
0.100000000000000
@@ -306,8 +328,8 @@
- 20
- 50
+ 0
+ 80
91
21
@@ -322,8 +344,71 @@
- 120
- 50
+ 100
+ 80
+ 91
+ 22
+
+
+
+ 3
+
+
+ 180.000000000000000
+
+
+ 0.100000000000000
+
+
+
+
+
+ 50
+ 20
+ 111
+ 21
+
+
+
+
+ 75
+ true
+
+
+
+ Light Position
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 230
+ 20
+ 111
+ 21
+
+
+
+
+ 75
+ true
+
+
+
+ Polarization
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ 240
+ 70
91
22
@@ -331,36 +416,294 @@
3
+
+ 180.000000000000000
+
0.100000000000000
+
+
+
+ 240
+ 50
+ 101
+ 21
+
+
+
+ gamma (deg.)
+
+
+ Qt::AlignCenter
+
+
-
+
- 400
- 120
- 131
+ 350
+ 20
+ 83
19
- MS-TM output
+ in water
-
+
- 350
- 20
- 83
- 19
+ 390
+ 250
+ 181
+ 231
-
- in water
+
+ Near Field
+
+
+
+ 20
+ 30
+ 151
+ 19
+
+
+
+ Compute Near Field
+
+
+
+
+
+ 70
+ 60
+ 61
+ 22
+
+
+ -
+
+ Y - Z
+
+
+ -
+
+ Z - X
+
+
+ -
+
+ X - Y
+
+
+
+
+
+
+ 70
+ 100
+ 62
+ 22
+
+
+
+ 0.100000000000000
+
+
+
+
+
+ 20
+ 100
+ 41
+ 21
+
+
+
+ width
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 20
+ 140
+ 41
+ 21
+
+
+
+ height
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 70
+ 140
+ 62
+ 22
+
+
+
+ 0.100000000000000
+
+
+
+
+
+ 20
+ 180
+ 41
+ 21
+
+
+
+ steps
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ 70
+ 180
+ 61
+ 22
+
+
+
+ 9999
+
+
+
+
+
+
+ 390
+ 50
+ 171
+ 191
+
+
+
+ Simulate
+
+
+
+
+ 40
+ 140
+ 101
+ 19
+
+
+
+ MS-TM output
+
+
+
+
+
+ 10
+ 100
+ 151
+ 23
+
+
+
+ Simulate Wavelength
+
+
+
+
+
+ 10
+ 20
+ 151
+ 23
+
+
+
+ Simulate Spectrum
+
+
+
+
+
+ 40
+ 70
+ 91
+ 22
+
+
+
+
+
+
+ 30
+ 50
+ 111
+ 21
+
+
+
+ Wavelength (um)
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ 10
+ 390
+ 361
+ 181
+
+
+
+ 89
+
+
+ 30
+
+
+
+ radius
+
+
+
+
+ pX
+
+
+
+
+ y
+
+
+
+
+ z
+
+
diff --git a/mstm_parameters.py b/mstm_parameters.py
index 1a33bac..89bd3bc 100755
--- a/mstm_parameters.py
+++ b/mstm_parameters.py
@@ -2,9 +2,17 @@ class ParameterClass:
#minimum and maximum wavelengths for the simulation
minLambda = 0.300
maxLambda = 0.700
+ snapshotLambda = 0.300
#number of spectral samples
nSamples = 40
+ #spatial samples
+ nSteps = 100
+
+ #sphere size and separation
+ a = 0.025
+ d = 0.005
+
#material file name
matFilename = 'etaSilver.txt'
#are the sphere's in water?
@@ -25,7 +33,7 @@ class ParameterClass:
return self.paramDict[key];
def __setitem__(self, key, value):
- self.paramDict[key] = str(value);
+ self.paramDict[key] = value;
def clearSpheres(self):
self.sphereList = []
@@ -40,7 +48,8 @@ class ParameterClass:
while 1:
key = inpFID.readline().strip()
-
+
+
#deal with sphere sizes and positions
if key == 'sphere_sizes_and_positions':
@@ -57,13 +66,24 @@ class ParameterClass:
break
elif key == 'end_of_options':
break
+ #deal with the near field plane
+ elif key == 'near_field_plane_vertices':
+ value = inpFID.readline().strip()
+ #self.paramDict[key] = list(map(float, value.split(',')))
+ self.paramDict[key] = [-1, -1, 1, 1]
+
else:
value = inpFID.readline().strip()
self.paramDict[key] = value
+
+ #update the length scale factor to deal with the UI
+ self.paramDict['length_scale_factor'] = (2.0 * 3.14159)/self.snapshotLambda
inpFID.close()
- def saveFile(self, fileName):
+ def saveFile(self, l, fileName):
+
+ #print(self)
#open the output file
outFID = open(fileName, 'w')
@@ -71,7 +91,20 @@ class ParameterClass:
#write the parameters
for key in self.paramDict.keys():
outFID.write(key + '\n')
- outFID.write(self.paramDict[key] + '\n')
+
+ #deal with the near field plane
+ if key == 'near_field_plane_vertices':
+ #these have to be scaled by the length scale factor
+ ls = (2 * 3.14159)/l
+ v = self.paramDict[key]
+ outFID.write(str(v[0]*ls) + ',' + str(v[1]*ls) + ',' + str(v[2]*ls) + ',' + str(v[3]*ls) + '\n')
+ elif key == 'spacial_step_size':
+ ls = (2 * 3.14159)/l
+ dx = self.paramDict[key] * ls
+ outFID.write(str(dx) + '\n')
+
+ else:
+ outFID.write(str(self.paramDict[key]) + '\n')
#write the spheres
outFID.write("sphere_sizes_and_positions\n")
@@ -86,7 +119,12 @@ class ParameterClass:
#print(self.paramDict)
result = ""
for key in self.paramDict.keys():
- result += key + ": " + self.paramDict[key] + '\n'
+ #deal with the near field plane
+ if key == 'near_field_plane_vertices':
+ v = map(str, self.paramDict[key])
+ result += key + ": " + v[0] + ',' + v[1] + ',' + v[2] + ',' + v[3] + '\n'
+ else:
+ result += key + ": " + str(self.paramDict[key]) + '\n'
result += "\n"
result += "Spheres:\n"
diff --git a/mstm_simparser.py b/mstm_simparser.py
index 7a5f89b..a3656ee 100755
--- a/mstm_simparser.py
+++ b/mstm_simparser.py
@@ -1,6 +1,17 @@
+from pylab import *
+
class SimParserClass:
simResults = dict()
+
+ sxNearField = 0
+ syNearField = 0
+ intersectedNearField = 0
+
+ #near field data
+ gridNearField = []
+ maxNearField = []
+
def __init__(self, parameters):
@@ -12,9 +23,11 @@ class SimParserClass:
self.simResults['extinction_parallel'] = list()
self.simResults['extinction_perpendicular'] = list()
self.simResults['extinction_total'] = list()
-
-
-
+
+ self.gridNearField = []
+ self.maxNearField = []
+
+
def parseSimFile(self, l, fileName):
self.simResults['lambda'].append(l)
inFile = open(fileName, 'r')
@@ -38,13 +51,39 @@ class SimParserClass:
self.simResults['extinction_perpendicular'].append(values[0])
else:
- #print('making it here')
- #print(self.params['fixed_or_random_orientation'])
if line == 'scattering matrix elements':
break
elif line == 'total ext, abs, scat efficiencies, w.r.t. xv, and asym. parm':
values = inFile.readline().strip().split(' ')
self.simResults['extinction_total'].append(values[0])
+
+ def parseNearField(self, fileName):
+
+ inFile = open(fileName, 'r')
+
+ #get the size of the near field grid
+ line = inFile.readline().strip()
+ self.sxNearField, self.syNearField = map(int, line.split())
+
+ #get the number of spheres that are intersected
+ line = inFile.readline().strip()
+ self.intersectedNearField = int(line)
+
+ #process intersections here-----------
+
+
+ #get the field values
+ self.gridNearField = []
+ for y in range(self.syNearField):
+ self.gridNearField.append([])
+ for x in range(self.sxNearField):
+ line = inFile.readline().strip()
+ values = map(float, line.split())
+ self.gridNearField[y].append(values[2])
+
+ E = array(self.gridNearField)
+ self.maxNearField.append(pow(E.max(), 2))
+
def saveFile(self, fileName):
outFile = open(fileName, 'w')
@@ -58,9 +97,14 @@ class SimParserClass:
result = '';
for i in range(len(self.simResults['lambda'])):
- result += str(self.simResults['lambda'][i]) + '\t'
- result += str(self.simResults['extinction_unpolarized'][i]) + '\t'
- result += str(self.simResults['extinction_parallel'][i]) + '\t'
- result += str(self.simResults['extinction_perpendicular'][i]) + '\n'
-
+ result += str(self.simResults['lambda'][i])
+ result += '\t' + str(self.simResults['extinction_unpolarized'][i])
+ result += '\t' + str(self.simResults['extinction_parallel'][i])
+ result += '\t' + str(self.simResults['extinction_perpendicular'][i])
+
+ #parse the near field if it is included in the simulation
+ if int(parameters['calculate_near_field']) == 1:
+ result += '\t' + str(maxNearField)
+
+ result += '\n'
return result
--
libgit2 0.21.4