class InvertDataControl(ProcessingControlBase): def __init__(self, controller, root, accordion): super().__init__("Inversion Analysis", controller, accordion) self.m_parsedData = None self.m_prefactors = [] # self.m_inputFilePath = None self.m_plots["Input Data"] = MPLContainer(self.m_chord.m_notebookRef, "Input Data", "Desorption Rate (arb. U.)", "Temperature (K)", root) self.m_plots["Coverage vs. Temp."] = MPLContainer( self.m_chord.m_notebookRef, "Coverage vs. Temp.", "Coverage", "Temperature (K)", root) self.m_plots["Energy vs. Coverage"] = MPLContainer( self.m_chord.m_notebookRef, "Energy vs. Coverage", "Energy (eV)", "Coverage", root) self.m_plots["Sim. Coverage vs Temp."] = MPLContainer( self.m_chord.m_notebookRef, "Sim. Coverage vs Temp.", "Coverge (ML)", "Temperature (K)", root) self.m_plots["Sim. Desorption Rate vs Coverage"] = MPLContainer( self.m_chord.m_notebookRef, "Sim. Desorption Rate vs Coverage", "Desorption Rate (ML/K)", "Coverage", root) self.m_plots["Chi Squared vs Prefactor"] = MPLContainer( self.m_chord.m_notebookRef, "Chi Squared vs Prefactor", "Chi Squared Value", "Prefactor", root) def checkInput(self): # if(self.m_inputFilePath == None): #check for file selection if (self.m_fileSelectionControl.m_inputFilePath == None): tk.messagebox.showerror( "Input File", "Please select a preprocessed file on which to perform the inversion analysis." ) return False if (self.m_RBVariable.get() == 0): #single prefactor if not self.m_tPrefactorEntry.InputIsValid(): return False else: #prefactor range if not self.m_tPrefactorStartEntry.InputIsValid(): return False if not self.m_tPrefactorEndEntry.InputIsValid(): return False currentEntry = float(self.m_tPrefactorStartEntry.get()) lastEntry = float(self.m_tPrefactorEndEntry.get()) if (self.m_RBVariable.get() == 1): #linear range if not self.m_tPrefactorIncrementEntry.InputIsValid(): return False incrementEntry = float(self.m_tPrefactorIncrementEntry.get()) if ((lastEntry - currentEntry) / incrementEntry > 20): tk.messagebox.showerror( "Number of Data Points", "Too many simulated data points required. Adapt range so that less than 20 simulations are necessary per spectrum." ) # raise ValueError #ridiculous amount of data points else: #multiplicative range if (math.log10(lastEntry) - math.log10(currentEntry) > 20): tk.messagebox.showerror( "Number of Data Points", "Too many simulated data points required. Adapt range so that less than 20 simulations are necessary per spectrum." ) # raise ValueError #ridiculous amount of data points return True def processInput(self): if (not self.checkInput()): return self.m_invertedData = None self.m_parsedData = ProcessedDataWrapper( self.m_fileSelectionControl.m_inputFilePath) self.m_parsedData.parseProcessedDataFile() if (not self.m_parsedData.m_normalized): tk.messagebox.showerror( "Input File", "Please use an input file with normalized coverages!") return if (not self.m_parsedData.m_normalized): return #need a normalized monolayer coverage for inversion + simulation to make sense # self.m_parsedData.clearInvertedData() #incase we are reusing the wrapper # for c in self.m_plots: # c.clearPlots() if (self.m_RBVariable.get() == 0): #single prefactor self.m_prefactors = [ "{:e}".format(float(self.m_tPrefactorEntry.get())) ] elif (self.m_RBVariable.get() == 1): #linear range currentEntry = float(self.m_tPrefactorStartEntry.get()) lastEntry = float(self.m_tPrefactorEndEntry.get()) incrementEntry = float(self.m_tPrefactorIncrementEntry.get()) self.m_prefactors = [] while (currentEntry <= lastEntry): self.m_prefactors.append("{:e}".format(currentEntry)) currentEntry += incrementEntry #increase by order of magnitude else: #multiplicative range currentEntry = float(self.m_tPrefactorStartEntry.get()) lastEntry = float(self.m_tPrefactorEndEntry.get()) self.m_prefactors = [] while (currentEntry <= lastEntry): self.m_prefactors.append("{:e}".format(currentEntry)) currentEntry *= 10.0 #increase by order of magnitude for p in self.m_prefactors: self.m_parsedData.invertProcessedData( float(p)) #do the calculations self.m_parsedData.simulateCoveragesFromInvertedData() self.m_parsedData.evaluateData() #plot chi-squared value vs prefactor for all input coverages self.m_plots["Chi Squared vs Prefactor"].clearPlots() self.m_plots["Chi Squared vs Prefactor"].addPrimaryLinePlots( self.m_parsedData.getChiSquaredVSPrefactor(), self.m_parsedData.getCoverageLabels(), logXAxis=True) #, logYAxis = True) self.m_plots["Chi Squared vs Prefactor"].addPrimaryLinePlots( self.m_parsedData.getChiSquaredSumVSPrefactor(), ["Sum"], logXAxis=True) #, logYAxis = True) self.m_prefactorCB["values"] = self.m_prefactors self.plotDataForSelectedPrefactor() def plotDataForSelectedPrefactor(self, *args, **kwargs): if (len(self.m_prefactors) == 0): return else: selectedPrefactor = self.m_prefactorCB.get() if (selectedPrefactor == ''): self.m_prefactorCB.current(0) #set to first entry selectedPrefactor = self.m_prefactorCB.get() #plot input data self.m_plots["Input Data"].clearPlots() self.m_plots["Input Data"].addPrimaryLinePlots( self.m_parsedData.getInputData(), self.m_parsedData.getCoverageLabels()) #plot coverage vs temperature from experimental data self.m_plots["Coverage vs. Temp."].clearPlots() self.m_plots["Coverage vs. Temp."].addPrimaryLinePlots( self.m_parsedData.getExpCoverageVSTemp( float(selectedPrefactor)), self.m_parsedData.getCoverageLabels()) #plot desorption energy vs coverage from experimental data self.m_plots["Energy vs. Coverage"].clearPlots() for e, lbl in zip( self.m_parsedData.getDesEnergyVSCoverageList( float(selectedPrefactor)), self.m_parsedData.getCoverageLabels()): self.m_plots["Energy vs. Coverage"].addPrimaryLinePlots(e, lbl) #plot simulated coverage vs temperature self.m_plots["Sim. Coverage vs Temp."].clearPlots() # self.m_plots[3].addLinePlots(self.m_parsedData.getExpDesorptionRateVSTemp()) self.m_plots["Sim. Coverage vs Temp."].addPrimaryLinePlots( self.m_parsedData.getSimCoverageVSTemp( float(selectedPrefactor)), self.m_parsedData.getCoverageLabels()) #plot simulated desorption rate vs temperature self.m_plots["Sim. Desorption Rate vs Coverage"].clearPlots() self.m_plots[ "Sim. Desorption Rate vs Coverage"].addPrimaryLinePlots( self.m_parsedData.getSimDesRateVSTemp( float(selectedPrefactor)), self.m_parsedData.getCoverageLabels()) def changeRB(self): self.m_tPrefactorEntry.configure(state='disabled') self.m_tPrefactorIncrementEntry.configure(state='disabled') self.m_tPrefactorStartEntry.configure(state='disabled') self.m_tPrefactorEndEntry.configure(state='disabled') if (self.m_RBVariable.get() == 0): #single prefactor self.m_tPrefactorEntry.configure(state='normal') elif (self.m_RBVariable.get() == 1): #linear range self.m_tPrefactorIncrementEntry.configure(state='normal') self.m_tPrefactorStartEntry.configure(state='normal') self.m_tPrefactorEndEntry.configure(state='normal') else: #multiplicative range self.m_tPrefactorIncrementEntry.configure(state='disabled') self.m_tPrefactorStartEntry.configure(state='normal') self.m_tPrefactorEndEntry.configure(state='normal') def toggleMarkers(self): for c in self.m_plots.values(): c.toggleMarkers() def saveData(self): if (self.m_parsedData == None): return outputFilePath = asksaveasfilename() substrings = outputFilePath.split('/') #consider using s = '/' result = s.join(substrings[x:y]) outputFilePath = substrings[0] for s in substrings[1:-1]: outputFilePath = outputFilePath + '/' + s substrings = substrings[-1].split('.') fileName = substrings[0] if (len(substrings) > 1): for s in substrings[1:-1]: fileName = fileName + '.' + s # dateTimeString = str(datetime.now()).replace('-','').replace(' ', '_').replace(':','') # fileName = fileName + '.' + dateTimeString outputFilePath = outputFilePath + '/' + fileName self.m_parsedData.saveInvertedDataToFile(outputFilePath) def initChordUI(self): self.m_chordFrame = self.m_chord.m_scrollable_frame # File selection self.m_fileSelectionControl = SingleInputFileSelectionControl( self.m_chordFrame) self.m_fileSelectionControl.grid(row=0, column=0, columnspan=4, sticky="nsew") #Options self.m_optionsLabel = ttk.Label( self.m_chordFrame, text="Inversion Options:") #, compound = tk.CENTER) self.m_optionsLabel.grid(row=3, column=0, columnspan=2, sticky="nsw") #Radiobutton var self.m_RBVariable = tk.IntVar(self.m_chordFrame) #Single Prefactor self.m_singleRB = ttk.Radiobutton(self.m_chordFrame, text="Single Prefactor", variable=self.m_RBVariable, value=0, command=self.changeRB) self.m_singleRB.grid(row=4, column=1, sticky="nsw") self.m_tPrefactorLabel = ttk.Label(self.m_chordFrame, text="Prefactor Value:") self.m_tPrefactorLabel.grid(row=5, column=1, sticky="nse") self.m_tPrefactorEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Prefactor Value", errorMessage= "Please enter a float for the prefactor. For example 1e17.") self.m_tPrefactorEntry.grid(row=5, column=2, sticky="nsw") #Or Prefactor Range self.m_linearRB = ttk.Radiobutton(self.m_chordFrame, text="Prefactor Range - Linear", variable=self.m_RBVariable, value=1, command=self.changeRB) self.m_linearRB.grid(row=6, column=1, sticky="nsw") self.m_tPrefactorIncrementLabel = ttk.Label(self.m_chordFrame, text="Increment:") self.m_tPrefactorIncrementLabel.grid(row=7, column=1, sticky="nse") self.m_tPrefactorIncrementEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Increment", errorMessage="Please enter a float for the prefactor increment.") self.m_tPrefactorIncrementEntry.grid(row=7, column=2, sticky="nsw") self.m_multiplicativeRB = ttk.Radiobutton( self.m_chordFrame, text="Prefactor Range - Multiplicative (10x)", variable=self.m_RBVariable, value=2, command=self.changeRB) self.m_multiplicativeRB.grid(row=8, column=1, sticky="nsw") self.m_tPrefactorStartLabel = ttk.Label(self.m_chordFrame, text="Lowest Prefactor:") self.m_tPrefactorStartLabel.grid(row=9, column=1, sticky="nse") self.m_tPrefactorStartEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Lowest Prefactor", errorMessage= "Please enter a float for the lowest prefactor. For example 1e13.") self.m_tPrefactorStartEntry.grid(row=9, column=2, sticky="nsw") self.m_tPrefactorEndLabel = ttk.Label(self.m_chordFrame, text="Highest Prefactor:") self.m_tPrefactorEndLabel.grid(row=10, column=1, sticky="nse") self.m_tPrefactorEndEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Highest Prefactor", errorMessage= "Please enter a float for the highest prefactor. For example 1e21." ) self.m_tPrefactorEndEntry.grid(row=10, column=2, sticky="nsw") #default values self.m_tPrefactorStartEntry.setBackingVar("1e15") self.m_tPrefactorEndEntry.setBackingVar("1e17") self.m_RBVariable.set(2) self.changeRB() #Process Button self.m_processButton = ttk.Button(self.m_chordFrame, text="Process Input", command=self.processInput) self.m_processButton.grid(row=11, column=1, columnspan=2, sticky="nsew") # self.m_prbar = ttk.Progressbar(self.m_chordFrame, orient ="horizontal", mode ="determinate", length = 50) #int(self.m_chordFrame.winfo_width() / 2)) # self.m_prbar.grid(row = 12, column = 1, columnspan = 2, sticky="nsw") # self.m_prbar["value"] = 10 #Display options self.m_displayOptionsLabel = ttk.Label(self.m_chordFrame, text='Display Options:') self.m_displayOptionsLabel.grid(row=12, column=0, columnspan=2, sticky="nsw") self.m_toggleMarkersButton = ttk.Button(self.m_chordFrame, text="Toggle Markers", command=self.toggleMarkers) self.m_toggleMarkersButton.grid(row=13, column=1, columnspan=2, sticky="nsew") self.m_prefactorCBLabel = ttk.Label( self.m_chordFrame, text='Select prefactor to display data for:') self.m_prefactorCBLabel.grid(row=14, column=1, columnspan=2, sticky="nsw") self.m_prefactorCB = ttk.Combobox(self.m_chordFrame) self.m_prefactorCB.bind( "<<ComboboxSelected>>", self.plotDataForSelectedPrefactor ) #binding to event because CB does not have 'command' param self.m_prefactorCB.grid(row=15, column=1, columnspan=2, sticky="nsew") #Save Button self.m_saveDataButton = ttk.Button(self.m_chordFrame, text="Save Inverted Data", command=self.saveData) self.m_saveDataButton.grid(row=16, column=1, columnspan=2, sticky="nsew") for child in self.m_chordFrame.winfo_children(): child.grid_configure(padx=3, pady=3) self.m_chordFrame.grid_columnconfigure(index=0, weight=1) self.m_chordFrame.grid_columnconfigure(index=1, weight=1) self.m_chordFrame.grid_columnconfigure(index=2, weight=1)
class RawDataControl(ProcessingControlBase): def __init__(self, controller, root, accordion): super().__init__("Process TPD Data", controller, accordion) self.m_filePaths = [] self.m_parsedData = [] # self.m_notebook.bind("<<NotebookTabChanged>>", self.onNotebookTabChanged) # self.m_plots.append(MPLContainer(self.m_notebook, "Raw Data", "Desorption Rate", "Temperature (K)")) self.m_plots["Raw Data vs. Temp."] = MPLContainer( self.m_chord.m_notebookRef, "Raw Data vs. Temp.", "Desorption Rate", "Temperature (K)", root) self.m_plots["Raw Data vs. Time"] = MPLContainer( self.m_chord.m_notebookRef, "Raw Data vs. Time.", "Desorption Rate", "Time (ms)", root, secondaryYAxis=True, secondaryYAxisName="Temperature (K)", legendLoc='center right') self.m_plots["Processed Data"] = MPLContainer( self.m_chord.m_notebookRef, "Processed Data", "Desorption Rate", "Temperature (K)", root) self.m_plots["Log Plot (Processed)"] = MPLContainer( self.m_chord.m_notebookRef, "Log Plot (Processed)", "ln(Desorption Rate)", "Temperature (K)", root) self.m_plots["Arrhenius Plot (Processed)"] = MPLContainer( self.m_chord.m_notebookRef, "Arrhenius Plot (Processed)", "ln(Desorption Rate)", "Reciprocal Temperature (1/K)", root, invertXAxis=True) # self.m_plots["Temperature Ramp"] = MPLContainer(self.m_chord.m_notebookRef, "Temperature Ramp", "Temperature (K)", "Time (ms)", root) def onUpdateFileList(self, fileList): self.m_subtractSelection["values"] = fileList self.m_normSelection["values"] = fileList def toggleSubtractCB(self): if (self.m_subtractCB.instate(['!selected'])): self.m_subtractSelection.configure(state=tk.DISABLED) else: self.m_subtractSelection.configure(state='readonly') def toggleNormalizeCB(self): if (self.m_normalizeCB.instate(['!selected'])): self.m_removeBackgroundCB.configure(state=tk.NORMAL) self.m_normSelection.configure(state=tk.DISABLED) else: self.m_removeBackgroundCB.set( 1 ) #if we want to normalize, we also have to remove the background, otherwise it does not make sense self.m_removeBackgroundCB.configure(state=tk.DISABLED) self.m_normSelection.configure(state='readonly') def toggleMarkers(self): for c in self.m_plots.values(): c.toggleMarkers() def plotSelectedMasses(self): for c in self.m_plots.values(): c.clearPlots() tempMasses = self.m_massDisplayOptions.getMassesToDisplay() if (len(tempMasses) == 0): return for d in self.m_parsedData: self.m_plots["Raw Data vs. Temp."].addPrimaryLinePlots( d.getRawDataVSRawTemp(tempMasses), d.getLangmuirLabels(tempMasses)) self.m_plots["Raw Data vs. Time"].addPrimaryLinePlots( d.getRawDataVSRawTime(tempMasses), d.getLangmuirLabels(tempMasses)) self.m_plots["Raw Data vs. Time"].addSecondaryLinePlots( d.getRawTempVSRawTime()) self.m_plots["Processed Data"].addPrimaryLinePlots( d.getProcessedData(tempMasses), d.getCoverageLabels(tempMasses)) self.m_plots["Log Plot (Processed)"].addPrimaryLinePlots( d.getProcessedLNData(tempMasses), d.getCoverageLabels(tempMasses)) self.m_plots["Arrhenius Plot (Processed)"].addPrimaryLinePlots( d.getProcessedArrheniusData(tempMasses), d.getCoverageLabels(tempMasses)) # self.m_plots[3].addPrimaryLinePlots(d.getRawTempVSRawTime(), d.getCoverageLabels(tempMasses)) # self.m_plots[0].setLegendCenterRight() # self.m_plots["Arrhenius Plot (Processed)"].autoScaleTopY() #if(showTempBounds) # self.m_plots["Raw Data vs. Temp."].addVerticalLine(float(self.m_tCutStartEntry.get())) # self.m_plots["Raw Data vs. Temp."].addVerticalLine(float(self.m_tCutEndEntry.get())) def checkInput(self): if (len(self.m_fileSelectionControl.m_filePaths) == 0 ): #check for file selection tk.messagebox.showerror( "Input Files", "Please select at least one file to process.") return False if not self.m_calibOffsetEntry.InputIsValid(): return False if not self.m_calibScaleEntry.InputIsValid(): return False return True def prepareStartStopCutValues(self): t_Minima = [d.getRawTempMin() for d in self.m_parsedData] minStartCut = int(np.amin(t_Minima)) if (minStartCut == 0): minStartCut = 1 #otherwise arrhenius plot will have 1/T -> 1/0 -> Inf value which causes bounds error t_Maxima = [d.getRawTempMax() for d in self.m_parsedData] maxStopCut = int(np.amax(t_Maxima)) if (self.m_lowerBoundEntry.InputIsValid()): if (minStartCut > int(self.m_lowerBoundEntry.get())): self.m_lowerBoundEntry.set(str(minStartCut)) else: self.m_lowerBoundEntry.set(str(minStartCut)) if (self.m_upperBoundEntry.InputIsValid()): if (maxStopCut < int(self.m_upperBoundEntry.get())): self.m_upperBoundEntry.set(str(maxStopCut)) else: self.m_upperBoundEntry.set(str(maxStopCut)) def processInput(self): if (not self.checkInput()): return False self.m_parsedData = [] #TODO: check input, maybe highlight missing entries! for f in self.m_fileSelectionControl.m_filePaths: wrapper = RawDataWrapper(f) wrapper.parseRawDataFile() self.m_parsedData.append(wrapper) self.prepareStartStopCutValues() wrapper.processParsedData( 0, 0, int(self.m_lowerBoundEntry.get()), #lower temperature boundary int(self.m_upperBoundEntry.get()), #upper temperature boundary self.m_removeBackgroundCB.instate(['selected']), self.m_smoothCountsCB.instate(['selected']), float(self.m_calibScaleEntry.get() ), #calibration slope 'm' in y=mx+b float(self.m_calibOffsetEntry.get()) ) #calibration offset 'b' in y=mx+b if (self.m_normalizeCB.instate([ 'selected' ])): #if we want to normalize data to a specific coverage monolayerData = None #find the coverage by fileName for w in self.m_parsedData: if (w.m_fileName == self.m_normSelection.get()): monolayerData = w break if (monolayerData == None): print("No reference coverage file selected") raise ValueError #normalize everything except the reference for w in [d for d in self.m_parsedData if not d == monolayerData]: w.normalizeDataTo(monolayerData) #normalize reference data last monolayerData.normalizeDataTo(monolayerData) #sort input data by coverage indexMapBuffer = [ ] #index i will contain tuple of (oldIndex,coverage) sorted by coverage for i in range(len(self.m_parsedData)): indexMapBuffer.append( (i, self.m_parsedData[i].getParsedCoverageAsFloat() )) #sorting input files by coverage indexMapBuffer.sort(reverse=False, key=lambda a: a[ 1]) #sort, such that old index and coverage are preserved #buffers for different ordering sortedParsedDataBuffer = [] sortedFilePathsBuffer = [] for i in range(len(indexMapBuffer)): sortedParsedDataBuffer.append( self.m_parsedData[indexMapBuffer[i][0]]) sortedFilePathsBuffer.append( self.m_fileSelectionControl.m_filePaths[indexMapBuffer[i][0]]) self.m_fileSelectionControl.m_filePaths = sortedFilePathsBuffer #reference-copy self.m_parsedData = sortedParsedDataBuffer #reference-copy self.m_fileSelectionControl.prepareFileSelections() # self.m_fileSelectionControl.onUpdateSelection(self.m_fileSelectionControl.m_fileList) self.m_massDisplayOptions.resetMasses(self.m_parsedData) self.plotSelectedMasses() def saveData(self): if (len(self.m_parsedData) == 0): tk.messagebox.showerror( "Save Error", "Please process some data before attempting to save it.") return outputFilePath = asksaveasfilename() substrings = outputFilePath.split('/') #consider using s = '/' result = s.join(substrings[x:y]) outputFilePath = substrings[0] for s in substrings[1:-1]: outputFilePath = outputFilePath + '/' + s substrings = substrings[-1].split('.') fileName = substrings[0] if (len(substrings) > 1): for s in substrings[1:-1]: fileName = fileName + '.' + s # dateTimeString = str(datetime.now()).replace('-','').replace(' ', '_').replace(':','') # fileName = fileName + '.' + dateTimeString outputFilePath = outputFilePath + '/' + fileName self.SaveProcessedDataToFile(outputFilePath, self.m_massDisplayOptions.getAllMasses(), self.m_parsedData) def SaveProcessedDataToFile(self, outputFilePath, massList, rawDataWrappers): if (massList == None or rawDataWrappers == None): raise ValueError for m in massList: #generate one .pdat file per mass (cleanest way to seperate data for masses, and keep things in an easily readable format) headerString = "Processed TPD data for mass " + m + \ "\nHeader length is " + str(len(rawDataWrappers) + 4) + \ "\nThe following files are included in this data set:\n" #outputData starts out column-major outputData = rawDataWrappers[0].m_interpolatedTemp.copy( ) # start with temperature column labels = ["Temperature"] coverages = [str(0.0)] for w in rawDataWrappers: #for each raw data file, do.... headerString = headerString + w.m_fileName + "\n" #write filename to header for quick overview outputData = np.vstack( (outputData, w.m_interpolatedData[m] )) #append data column for mass m in outputdata if (w.m_parsedCoverageAvailable): labels.append( w.m_parsedCoverage ) #will append dosed coverage in Langmuir with "L" at the end else: labels.append(w.m_fileName.split(" ") [0]) # this should append file number coverages.append(str(w.m_coverages[m])) headerString = headerString + "Calibration params: Temperature offset = " + str( self.m_calibOffsetEntry.get()) + " Temperature scale = " + str( self.m_calibScaleEntry.get()) if (outputFilePath[-5:] == ".pdat"): outputFilePath = outputFilePath[: -5] #removing .pdat extension from user-written output file path, if it is there #making one file per mass, so making name based on mass number namedOutputFilePath = outputFilePath + ".M" + str( m) + ".pdat" #pdat for processed data if (path.exists(namedOutputFilePath)): tk.messagebox.showerror( "File exists!", "Please choose another name, or explicitly delete the " + outputFilePath + "to overwrite in the file explorer.") stringData = np.vstack( (np.array(labels, dtype=str), np.array(coverages, dtype=str))) with open(namedOutputFilePath, mode='a') as fileHandle: #actually write file #write header and stringData first np.savetxt(fileHandle, stringData, fmt="%s", delimiter=' ', header=headerString) #then write float data (after transposing it) np.savetxt(fileHandle, outputData.transpose(), delimiter=' ') def initChordUI(self): self.m_chordFrame = self.m_chord.m_scrollable_frame # File selection self.m_fileSelectionControl = InputFileListBoxControl( self.m_chordFrame, self.onUpdateFileList) self.m_fileSelectionControl.grid(row=0, column=0, columnspan=4, sticky="nsew") # Processing options: self.m_optionsLabel = ttk.Label( self.m_chordFrame, text="Processing Options:") #, compound = tk.CENTER) self.m_optionsLabel.grid(row=3, column=0, columnspan=2, sticky="nsw") self.m_tCutStartLabel = ttk.Label(self.m_chordFrame, text="Lower Boundary (Temp.):") self.m_tCutStartLabel.grid(row=4, column=1, sticky="nse") self.m_lowerBoundEntry = EnhancedEntry( self.m_chordFrame, inputValueType=int, errorTitle="Lower Boundary (Temp.)", errorMessage= "Please enter an integer for the lower temperature boundary") self.m_lowerBoundEntry.grid(row=4, column=2, sticky="nsw") self.m_tCutEndLabel = ttk.Label(self.m_chordFrame, text="Upper Boundary (Temp.):") self.m_tCutEndLabel.grid(row=5, column=1, sticky="nse") self.m_upperBoundEntry = EnhancedEntry( self.m_chordFrame, inputValueType=int, errorTitle="Upper Boundary (Temp.)", errorMessage= "Please enter an integer for the upper temperature boundary.") self.m_upperBoundEntry.grid(row=5, column=2, sticky="nsw") #Temperature (thermocouple) calibration options: self.m_calibLabel = ttk.Label( self.m_chordFrame, text="Temperature Calibration:") #, compound = tk.CENTER) self.m_calibLabel.grid(row=6, column=0, columnspan=2, sticky="nsw") self.m_calibFormulaLabel = ttk.Label( self.m_chordFrame, text="( T_Calibrated = Scale * T_RawData + Offset )") self.m_calibFormulaLabel.grid(row=7, column=0, columnspan=3) #, sticky = "nse") self.m_calibOffsetLabel = ttk.Label(self.m_chordFrame, text="Offset:") self.m_calibOffsetLabel.grid(row=8, column=1, sticky="nse") self.m_calibOffsetEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Calibration Offset", errorMessage= "Please enter a decimal for the temperature calibration offset.") self.m_calibOffsetEntry.grid(row=8, column=2, sticky="nsw") self.m_calibOffsetEntry.setBackingVar("0.836") #default self.m_calibScaleLabel = ttk.Label(self.m_chordFrame, text="Scale:") self.m_calibScaleLabel.grid(row=9, column=1, sticky="nse") self.m_calibScaleEntry = EnhancedEntry( self.m_chordFrame, inputValueType=float, errorTitle="Calibration Scale", errorMessage= "Please enter a decimal for the temperature calibration scale.") self.m_calibScaleEntry.grid(row=9, column=2, sticky="nsw") self.m_calibScaleEntry.setBackingVar("0.985") #default # Checkbuttons + Comboboxes for options: self.m_smoothTempCB = EnhancedCheckButton(self.m_chordFrame, text="Smooth Temperature") self.m_smoothTempCB.grid(row=10, column=1, sticky="nsw") self.m_smoothTempCB.set(1) self.m_smoothTempCB.configure(state=tk.DISABLED) self.m_smoothCountsCB = EnhancedCheckButton(self.m_chordFrame, text="Smooth Counts/s") self.m_smoothCountsCB.grid(row=10, column=2, sticky="nsw") self.m_normalizeCB = EnhancedCheckButton( self.m_chordFrame, text="Normalize to coverage of (select file):", command=self.toggleNormalizeCB) self.m_normalizeCB.grid(row=11, column=1, sticky="nsw") self.m_removeBackgroundCB = EnhancedCheckButton( self.m_chordFrame, text="Remove Background") self.m_removeBackgroundCB.grid(row=11, column=2, sticky="nsw") self.m_normSelection = ttk.Combobox(self.m_chordFrame, state=tk.DISABLED) self.m_normSelection.grid(row=12, column=1, columnspan=2, sticky="nsew") self.m_subtractCB = EnhancedCheckButton( self.m_chordFrame, text="Subtract Spectrum (select file):", command=self.toggleSubtractCB, state=tk.DISABLED) self.m_subtractCB.grid(row=13, column=1, sticky="nsw") self.m_subtractSelection = ttk.Combobox(self.m_chordFrame, state=tk.DISABLED) self.m_subtractSelection.grid(row=14, column=1, columnspan=2, sticky="nsew") #Process Button self.m_processButton = ttk.Button(self.m_chordFrame, text="Process Input", command=self.processInput) self.m_processButton.grid(row=15, column=1, columnspan=2, sticky="nsew") #Display options self.m_displayOptionsLabel = ttk.Label(self.m_chordFrame, text='Display Options:') self.m_displayOptionsLabel.grid(row=16, column=0, columnspan=2, sticky="nsw") self.m_toggleMarkersButton = ttk.Button(self.m_chordFrame, text="Toggle Markers", command=self.toggleMarkers) self.m_toggleMarkersButton.grid(row=17, column=1, columnspan=2, sticky="nsew") self.m_massDisplayOptions = DisplayOptionsFrame( self.m_chordFrame, self.plotSelectedMasses) self.m_massDisplayOptions.grid(row=18, column=0, columnspan=4, sticky="nsew") # self.m_massDisplayOptions.m_availableMassesListBox self.m_saveDataButton = ttk.Button(self.m_chordFrame, text="Save Processed Data", command=self.saveData) self.m_saveDataButton.grid(row=19, column=1, columnspan=3, sticky="nsew") # for child in self.m_chordFrame.winfo_children(): # child.grid_configure(padx=3, pady=3) # for child in self.m_fileButtonFrame.winfo_children(): # child.pack_configure(padx=3, pady=3) # for child in self.m_massDisplayOptions.winfo_children(): # child.grid_configure(padx=3, pady=3) self.m_chordFrame.grid_columnconfigure(index=0, weight=1) self.m_chordFrame.grid_columnconfigure(index=1, weight=1) self.m_chordFrame.grid_columnconfigure(index=2, weight=1) self.m_chordFrame.grid_columnconfigure(index=3, weight=1)