From 5e1cbbabd929e9894e5ec50b1db86d3db588d730 Mon Sep 17 00:00:00 2001 From: dmayerich Date: Fri, 5 Apr 2013 11:47:32 -0500 Subject: [PATCH] Bug fixes. UI updates. --- msinput.inp | 6 +++--- mstm-gui.py | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ mstm_guiwindow.ui | 433 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------- mstm_parameters.py | 48 +++++++++++++++++++++++++++++++++++++++++++----- mstm_simparser.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 603 insertions(+), 87 deletions(-) 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 + + @@ -368,7 +711,7 @@ 0 0 - 599 + 590 22 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