def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        self.m_fileSelectionControl = InputFileListBoxControl(
            self.m_chordFrame, lambda e: None)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        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="Cut Data Start Temp.:")
        self.m_tCutStartLabel.grid(row=4, column=1, sticky="nse")

        self.m_tCutStartEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutStartEntry.grid(row=4, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Cut Data End Temp.:")
        self.m_tCutEndLabel.grid(row=5, column=1, sticky="nse")

        self.m_tCutEndEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutEndEntry.grid(row=5, column=2, sticky="nsw")

        self.m_testButton = ttk.Button(self.m_chordFrame,
                                       text="test",
                                       command=self.adaptTransformTest)
        self.m_testButton.grid(row=6, column=0, columnspan=4, sticky="nsew")

        self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        self.m_Label.grid(row=7, column=0, columnspan=4, sticky="nsew")

        self.m_chordFrame.grid_columnconfigure(index=0,
                                               weight=1,
                                               uniform="test1")
        self.m_chordFrame.grid_columnconfigure(index=1,
                                               weight=1,
                                               uniform="test1")
        self.m_chordFrame.grid_columnconfigure(index=2,
                                               weight=1,
                                               uniform="test2")
        self.m_chordFrame.grid_columnconfigure(index=3,
                                               weight=1,
                                               uniform="test3")
Esempio n. 2
0
    def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        # File selection

        self.m_fileSelectionControl = SingleInputFileSelectionControl(
            self.m_chordFrame, onSelect=self.onFileSelected)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        # Spectrum selection

        self.m_spectrumSelectionLabel = ttk.Label(
            self.m_chordFrame, text='Select TPD Spectrum for Integration:')
        self.m_spectrumSelectionLabel.grid(row=1,
                                           column=0,
                                           columnspan=2,
                                           sticky="nsw")

        self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        self.m_spectrumCB.configure(state='readonly')
        self.m_spectrumCB.bind(
            "<<ComboboxSelected>>", self.onSpectrumSelected
        )  #binding to event because CB does not have 'command' param
        self.m_spectrumCB.grid(row=2, column=0, columnspan=3, sticky="nsew")

        # self.m_spectrumSelectionLabel = ttk.Label(self.m_chordFrame, text='Select Mass Spectrum for Integration:')
        # self.m_spectrumSelectionLabel.grid(row = 3, column = 0, columnspan = 2, sticky="nsw")

        # self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        # # self.m_prefactorCB.bind("<<ComboboxSelected>>", self.plotDataForSelectedPrefactor) #binding to event because CB does not have 'command' param
        # self.m_spectrumCB.grid(row = 4, column = 0, columnspan = 3, sticky = "nsew")

        # Integration Options

        self.m_optionsLabel = ttk.Label(
            self.m_chordFrame,
            text="Fitting Options:")  #, compound = tk.CENTER)
        self.m_optionsLabel.grid(row=5, column=0, sticky="nsw")

        self.m_tCutStartLabel = ttk.Label(self.m_chordFrame,
                                          text="Lower Boundary")
        self.m_tCutStartLabel.grid(row=6, column=1, sticky="nse")

        self.m_tCutStartEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutStartEntry.grid(row=6, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Upper Boundary")
        self.m_tCutEndLabel.grid(row=7, column=1, sticky="nse")

        self.m_tCutEndEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutEndEntry.grid(row=7, column=2, sticky="nsw")

        self.m_resultTitleLabel = ttk.Label(self.m_chordFrame,
                                            text="Fitting Results:")
        self.m_resultTitleLabel.grid(row=8, column=1, sticky="nse")

        self.m_resultValueLabel = ttk.Label(self.m_chordFrame, text="N/A")
        self.m_resultValueLabel.grid(row=8, column=2, sticky="nsw")

        self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        self.m_Label.grid(row=9, column=0, columnspan=4, sticky="nsew")
Esempio n. 3
0
class RedheadAnalysisControl(ProcessingControlBase):
    def __init__(self, controller, root, accordion):
        super().__init__("Redhead Analysis (WIP)", controller, accordion)
        self.m_parsedData = None
        self.m_plots["Processed Data"] = MPLContainer(
            self.m_chord.m_notebookRef, "Processed Data",
            "Desorption Rate (arb. U.)", "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)

    def onFileSelected(self):
        self.m_parsedData = ProcessedDataWrapper(
            self.m_fileSelectionControl.m_inputFilePath)
        self.m_parsedData.parseProcessedDataFile()
        if (self.m_parsedData.m_normalized):
            tk.messagebox.showerror(
                "Input Data",
                "Please use processed data which has not been normalized to a monolayer!"
            )
            self.m_spectrumCB["values"] = None
        else:
            self.m_spectrumCB["values"] = self.m_parsedData.m_includedFiles
        # self.m_spectrumCB.current(0)

    def plotBounds(self):
        # for plot in self.m_plots.values():
        #     plot.removeVerticalLines()
        #     plot.addVerticalLine(float(self.m_tCutEndEntry.get()))
        #     plot.addVerticalLine(float(self.m_tCutStartEntry.get()))

        self.m_plots["Processed Data"].removeVerticalLines()
        # if(not self.m_integrated):
        self.m_plots["Processed Data"].addVerticalLine(
            float(self.m_tCutEndEntry.get()))
        self.m_plots["Processed Data"].addVerticalLine(
            float(self.m_tCutStartEntry.get()))

    def plotSelectedSpectrum(self):
        targetData = self.m_parsedData.fileNameToExpDesorptionRateVSTemp(
            self.m_spectrumCB.get())
        targetLabel = self.m_parsedData.fileNameToCoverageLabel(
            self.m_spectrumCB.get())

        arrheniusData = np.vstack(
            (np.reciprocal(targetData[0, :]), np.log(targetData[1, :])))

        self.m_plots["Processed Data"].clearPlots()
        self.m_plots["Processed Data"].addPrimaryLinePlots(targetData,
                                                           targetLabel,
                                                           color='b')

        self.m_plots["Arrhenius Plot (Processed)"].clearPlots()
        self.m_plots["Arrhenius Plot (Processed)"].addPrimaryLinePlots(
            arrheniusData, targetLabel, color='b')

        self.plotBounds()
        # if(self.m_integrated): #shade, currently has performance problems when drawing polygon
        #     t2 = float(self.m_tCutEndEntry.get())
        #     t1 = float(self.m_tCutStartEntry.get())
        #     curve = self.m_parsedData.getProcessedDataBetweenForFile(t1,t2,self.m_spectrumCB.get())
        #     self.m_plots["Processed Data"].shadeBelowCurve(curve[0],curve[1])

    def onSpectrumSelected(self, *args, **kwargs):
        if (self.m_parsedData != None):
            self.m_integrated = False
            self.checkIntegrationBounds()
            self.plotSelectedSpectrum()

    def tryReadStartCutEntry(self):
        if (self.m_tCutStartEntry.get() == ''):
            return False
        try:
            int(self.m_tCutStartEntry.get())
        except ValueError:
            tk.messagebox.showerror(
                "Initial Temperature",
                "Please enter an integer for the temperature at which to start integration."
            )
            return False
        return True

    def tryReadStopCutEntry(self):
        if (self.m_tCutEndEntry.get() == ''):
            return False
        try:
            int(self.m_tCutEndEntry.get())
        except ValueError:
            tk.messagebox.showerror(
                "Final Temperature",
                "Please enter an integer for the temperature at which to end integration."
            )
            return False
        return True

    def checkIntegrationBounds(self):
        minStartCut = int(self.m_parsedData.getMinTemp())
        maxStopCut = int(self.m_parsedData.getMaxTemp())
        if (self.tryReadStartCutEntry()):
            if (minStartCut > int(self.m_tCutStartEntry.get())):
                self.m_tCutStartEntry.set(str(minStartCut))
        else:
            self.m_tCutStartEntry.set(str(minStartCut))
        if (self.tryReadStopCutEntry()):
            if (maxStopCut < int(self.m_tCutEndEntry.get())):
                self.m_tCutEndEntry.set(str(maxStopCut))
        else:
            self.m_tCutEndEntry.set(str(maxStopCut))

    def onBoundsChanged(self):
        self.checkIntegrationBounds()

    def processInput(self):
        self.checkIntegrationBounds()
        t2 = float(self.m_tCutEndEntry.get())
        t1 = float(self.m_tCutStartEntry.get())
        result = self.m_parsedData.integrateDesorptionRate(
            t1, t2, self.m_spectrumCB.get())
        self.m_integrated = True
        self.m_resultValueLabel.configure(text=str(result))
        self.plotSelectedSpectrum(
        )  #should update plot with appropriate shading

    def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        # File selection

        self.m_fileSelectionControl = SingleInputFileSelectionControl(
            self.m_chordFrame, onSelect=self.onFileSelected)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        # Spectrum selection

        self.m_spectrumSelectionLabel = ttk.Label(
            self.m_chordFrame, text='Select TPD Spectrum for Integration:')
        self.m_spectrumSelectionLabel.grid(row=1,
                                           column=0,
                                           columnspan=2,
                                           sticky="nsw")

        self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        self.m_spectrumCB.configure(state='readonly')
        self.m_spectrumCB.bind(
            "<<ComboboxSelected>>", self.onSpectrumSelected
        )  #binding to event because CB does not have 'command' param
        self.m_spectrumCB.grid(row=2, column=0, columnspan=3, sticky="nsew")

        # self.m_spectrumSelectionLabel = ttk.Label(self.m_chordFrame, text='Select Mass Spectrum for Integration:')
        # self.m_spectrumSelectionLabel.grid(row = 3, column = 0, columnspan = 2, sticky="nsw")

        # self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        # # self.m_prefactorCB.bind("<<ComboboxSelected>>", self.plotDataForSelectedPrefactor) #binding to event because CB does not have 'command' param
        # self.m_spectrumCB.grid(row = 4, column = 0, columnspan = 3, sticky = "nsew")

        # Integration Options

        self.m_optionsLabel = ttk.Label(
            self.m_chordFrame,
            text="Fitting Options:")  #, compound = tk.CENTER)
        self.m_optionsLabel.grid(row=5, column=0, sticky="nsw")

        self.m_tCutStartLabel = ttk.Label(self.m_chordFrame,
                                          text="Lower Boundary")
        self.m_tCutStartLabel.grid(row=6, column=1, sticky="nse")

        self.m_tCutStartEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutStartEntry.grid(row=6, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Upper Boundary")
        self.m_tCutEndLabel.grid(row=7, column=1, sticky="nse")

        self.m_tCutEndEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutEndEntry.grid(row=7, column=2, sticky="nsw")

        self.m_resultTitleLabel = ttk.Label(self.m_chordFrame,
                                            text="Fitting Results:")
        self.m_resultTitleLabel.grid(row=8, column=1, sticky="nse")

        self.m_resultValueLabel = ttk.Label(self.m_chordFrame, text="N/A")
        self.m_resultValueLabel.grid(row=8, column=2, sticky="nsw")

        self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        self.m_Label.grid(row=9, column=0, columnspan=4, sticky="nsew")
Esempio n. 4
0
    def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        # File selection

        self.m_fileSelectionControl = SingleInputFileSelectionControl(
            self.m_chordFrame, onSelect=self.onFileSelected)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        # Spectrum selection

        self.m_spectrumSelectionLabel = ttk.Label(
            self.m_chordFrame, text='Select TPD Spectrum for analysis:')
        self.m_spectrumSelectionLabel.grid(row=1,
                                           column=0,
                                           columnspan=2,
                                           sticky="nsw")

        self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        self.m_spectrumCB.configure(state='readonly')
        self.m_spectrumCB.bind(
            "<<ComboboxSelected>>", self.onSpectrumSelected
        )  #binding to event because CB does not have 'command' param
        self.m_spectrumCB.grid(row=2, column=0, columnspan=3, sticky="nsew")

        # self.m_spectrumSelectionLabel = ttk.Label(self.m_chordFrame, text='Select Mass Spectrum for Integration:')
        # self.m_spectrumSelectionLabel.grid(row = 3, column = 0, columnspan = 2, sticky="nsw")

        # self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        # # self.m_prefactorCB.bind("<<ComboboxSelected>>", self.plotDataForSelectedPrefactor) #binding to event because CB does not have 'command' param
        # self.m_spectrumCB.grid(row = 4, column = 0, columnspan = 3, sticky = "nsew")

        # Integration Options

        self.m_optionsLabel = ttk.Label(
            self.m_chordFrame,
            text="Fitting Options:")  #, compound = tk.CENTER)
        self.m_optionsLabel.grid(row=5, column=0, sticky="nsw")

        self.m_tCutStartLabel = ttk.Label(self.m_chordFrame,
                                          text="Lower Boundary (1/T)")
        self.m_tCutStartLabel.grid(row=6, column=1, sticky="nse")

        self.m_lowerBoundEntry = EnhancedEntry(
            self.m_chordFrame,
            inputValueType=float,
            errorTitle="Lower Boundary",
            errorMessage=
            "Please enter a decimal for the lower boundary of the leading edge."
        )
        self.m_lowerBoundEntry.grid(row=6, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Upper Boundary (1/T)")
        self.m_tCutEndLabel.grid(row=7, column=1, sticky="nse")

        self.m_upperBoundEntry = EnhancedEntry(
            self.m_chordFrame,
            inputValueType=float,
            errorTitle="Upper Boundary",
            errorMessage=
            "Please enter a decimal for the upper boundary of the leading edge."
        )
        self.m_upperBoundEntry.grid(row=7, column=2, sticky="nsw")

        self.m_resultsLabel = ttk.Label(
            self.m_chordFrame, text="Result:")  #, compound = tk.CENTER)
        self.m_resultsLabel.grid(row=8, column=0, sticky="nsw")

        self.m_resultTitleLabel = ttk.Label(self.m_chordFrame,
                                            text="Inv. x-intercept (K):")
        self.m_resultTitleLabel.grid(row=9, column=1, sticky="nse")

        self.m_resultValueLabel = ttk.Label(self.m_chordFrame, text="N/A")
        self.m_resultValueLabel.grid(row=9, column=2, sticky="nsw")

        # self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        # self.m_Label.grid(row = 10, column = 0, columnspan = 4, sticky="nsew")

        #Process Button
        self.m_processButton = ttk.Button(self.m_chordFrame,
                                          text="Generate Edge Fit",
                                          command=self.processInput)
        self.m_processButton.grid(row=10,
                                  column=0,
                                  columnspan=4,
                                  sticky="nsew")
class CoverageCalibrationControl(ProcessingControlBase):
    def __init__(self, controller, root, accordion):
        super().__init__("Coverage Calibration (WIP)", controller, accordion)
        self.m_plots["Coverage"] = MPLContainer(self.m_chord.m_notebookRef,
                                                "Coverage", "Desorption Rate",
                                                "Temperature (K)", root)
        self.m_forwardXFactor = 1.0
        self.m_inverseXFactor = 1.0
        self.m_forwardYFactor = 1.0
        self.m_inverseYFactor = 1.0
        self.m_plots["Coverage"].addSecondaryScaledXAxis(
            self.forwardXTransform, self.inverseXTransform)
        self.m_plots["Coverage"].addSecondaryScaledYAxis(
            self.forwardYTransform, self.inverseYTransform)

    def forwardXTransform(self, x):
        return x * self.m_forwardXFactor

    def inverseXTransform(self, x):
        return x * self.m_inverseXFactor

    def forwardYTransform(self, y):
        return y * self.m_forwardYFactor

    def inverseYTransform(self, y):
        return y * self.m_inverseYFactor

    def adaptTransformTest(self):
        self.m_forwardXFactor = 2.0
        self.m_inverseXFactor = 0.5

    def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        self.m_fileSelectionControl = InputFileListBoxControl(
            self.m_chordFrame, lambda e: None)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        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="Cut Data Start Temp.:")
        self.m_tCutStartLabel.grid(row=4, column=1, sticky="nse")

        self.m_tCutStartEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutStartEntry.grid(row=4, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Cut Data End Temp.:")
        self.m_tCutEndLabel.grid(row=5, column=1, sticky="nse")

        self.m_tCutEndEntry = EnhancedEntry(self.m_chordFrame)
        self.m_tCutEndEntry.grid(row=5, column=2, sticky="nsw")

        self.m_testButton = ttk.Button(self.m_chordFrame,
                                       text="test",
                                       command=self.adaptTransformTest)
        self.m_testButton.grid(row=6, column=0, columnspan=4, sticky="nsew")

        self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        self.m_Label.grid(row=7, column=0, columnspan=4, sticky="nsew")

        self.m_chordFrame.grid_columnconfigure(index=0,
                                               weight=1,
                                               uniform="test1")
        self.m_chordFrame.grid_columnconfigure(index=1,
                                               weight=1,
                                               uniform="test1")
        self.m_chordFrame.grid_columnconfigure(index=2,
                                               weight=1,
                                               uniform="test2")
        self.m_chordFrame.grid_columnconfigure(index=3,
                                               weight=1,
                                               uniform="test3")
Esempio n. 6
0
class LeadingEdgeAnalysisControl(ProcessingControlBase):
    def __init__(self, controller, root, accordion):
        super().__init__("Leading Edge Analysis", controller, accordion)
        self.m_parsedData = None
        self.m_1DFitCoefficients = None
        # self.m_plots["Processed Data"] = MPLContainer(self.m_chord.m_notebookRef, "Processed Data", "Desorption Rate (arb. U.)", "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)

    def onFileSelected(self):
        self.m_parsedData = ProcessedDataWrapper(
            self.m_fileSelectionControl.m_inputFilePath)
        self.m_parsedData.parseProcessedDataFile()
        # if(self.m_parsedData.m_normalized):
        #     tk.messagebox.showerror("Input Data", "Please use processed data which has not been normalized to a monolayer!")
        #     self.m_spectrumCB["values"] = None
        # else:
        self.m_spectrumCB["values"] = self.m_parsedData.m_includedFiles
        # self.m_spectrumCB.current(0)

    def calc1DPoly(self, coef, xData):
        result = list()
        for i in range(len(xData)):
            result.append(coef[0] + coef[1] * xData[i])
        return result

    def plotFit(self, coef):
        x1 = float(self.m_lowerBoundEntry.get())
        x2 = float(self.m_upperBoundEntry.get())
        xdat = [x2, x1]
        linearFitData = np.vstack((xdat, self.calc1DPoly(coef, xdat)))
        self.m_plots["Arrhenius Plot (Processed)"].addPrimaryLinePlots(
            linearFitData, "Leading Edge Fit",
            color='g')  #, shouldRelim = False)

    def plotBounds(self):
        # for plot in self.m_plots.values():
        #     plot.removeVerticalLines()
        #     plot.addVerticalLine(float(self.m_tCutEndEntry.get()))
        #     plot.addVerticalLine(float(self.m_tCutStartEntry.get()))

        self.m_plots["Arrhenius Plot (Processed)"].removeVerticalLines()
        # if(not self.m_integrated):
        self.m_plots["Arrhenius Plot (Processed)"].addVerticalLine(
            float(self.m_upperBoundEntry.get()))
        self.m_plots["Arrhenius Plot (Processed)"].addVerticalLine(
            float(self.m_lowerBoundEntry.get()))

    def plotSelectedSpectrum(self):
        targetData = self.m_parsedData.fileNameToExpDesorptionRateVSTemp(
            self.m_spectrumCB.get())
        targetLabel = self.m_parsedData.fileNameToCoverageLabel(
            self.m_spectrumCB.get())

        arrheniusData = np.vstack(
            (np.reciprocal(targetData[0, :]), np.log(targetData[1, :])))

        # self.m_plots["Processed Data"].clearPlots()
        # self.m_plots["Processed Data"].addPrimaryLinePlots(targetData,targetLabel, color = 'b')

        self.m_plots["Arrhenius Plot (Processed)"].clearPlots()
        self.m_plots["Arrhenius Plot (Processed)"].addPrimaryLinePlots(
            arrheniusData, targetLabel, color='b')

        if (self.m_1DFitCoefficients.any()):
            self.plotFit(self.m_1DFitCoefficients)
        self.plotBounds()

        # if(self.m_integrated): #shade, currently has performance problems when drawing polygon
        #     t2 = float(self.m_tCutEndEntry.get())
        #     t1 = float(self.m_tCutStartEntry.get())
        #     curve = self.m_parsedData.getProcessedDataBetweenForFile(t1,t2,self.m_spectrumCB.get())
        #     self.m_plots["Processed Data"].shadeBelowCurve(curve[0],curve[1])

    def onSpectrumSelected(self, *args, **kwargs):
        if (self.m_parsedData != None):
            self.m_fitted = False
            self.checkFitBounds()
            self.plotSelectedSpectrum()

    def checkFitBounds(self):
        minStartCut = float(1.0 / self.m_parsedData.getMaxTemp())
        maxStopCut = float(1.0 / self.m_parsedData.getMinTemp())
        if (self.m_lowerBoundEntry.InputIsValid()):
            if (minStartCut > float(self.m_lowerBoundEntry.get())):
                self.m_lowerBoundEntry.set(str(minStartCut))
        else:
            self.m_lowerBoundEntry.set(str(minStartCut))
        if (self.m_upperBoundEntry.InputIsValid()):
            if (maxStopCut < float(self.m_upperBoundEntry.get())):
                self.m_upperBoundEntry.set(str(maxStopCut))
        else:
            self.m_upperBoundEntry.set(str(maxStopCut))

    def onBoundsChanged(self):
        self.checkFitBounds()

    def processInput(self):
        self.checkFitBounds()
        t2 = float(self.m_upperBoundEntry.get())
        t1 = float(self.m_lowerBoundEntry.get())

        targetData = self.m_parsedData.fileNameToExpDesorptionRateVSTemp(
            self.m_spectrumCB.get())
        # targetLabel = self.m_parsedData.fileNameToCoverageLabel(self.m_spectrumCB.get())
        # arrheniusData = np.vstack((np.reciprocal(targetData[0,:]),np.log(targetData[1,:])))

        reciprocalTemp = np.reciprocal(targetData[0, :])
        logCountRate = np.log(targetData[1, :])
        maxIdx = (np.abs(reciprocalTemp - t1)).argmin()
        minIdx = (np.abs(reciprocalTemp - t2)).argmin()

        # result = self.m_parsedData.integrateDesorptionRate(t1,t2,self.m_spectrumCB.get())
        # coef = np.polyfit(reciprocalTemp,logCountRate,1)
        self.m_1DFitCoefficients = npp.polynomial.polyfit(
            reciprocalTemp[minIdx:maxIdx], logCountRate[minIdx:maxIdx], 1)
        # linearFitPoly = np.poly1d(coef)
        # self.plotFit(self.m_1DFitCoefficients)

        leadingEdgeTempXIntercept = -self.m_1DFitCoefficients[
            1] / self.m_1DFitCoefficients[0]
        self.m_fitted = True
        self.m_resultValueLabel.configure(text=str(leadingEdgeTempXIntercept))
        self.plotSelectedSpectrum(
        )  #should update plot with appropriate shading

    def initChordUI(self):
        self.m_chordFrame = self.m_chord.m_scrollable_frame

        # File selection

        self.m_fileSelectionControl = SingleInputFileSelectionControl(
            self.m_chordFrame, onSelect=self.onFileSelected)
        self.m_fileSelectionControl.grid(row=0,
                                         column=0,
                                         columnspan=4,
                                         sticky="nsew")

        # Spectrum selection

        self.m_spectrumSelectionLabel = ttk.Label(
            self.m_chordFrame, text='Select TPD Spectrum for analysis:')
        self.m_spectrumSelectionLabel.grid(row=1,
                                           column=0,
                                           columnspan=2,
                                           sticky="nsw")

        self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        self.m_spectrumCB.configure(state='readonly')
        self.m_spectrumCB.bind(
            "<<ComboboxSelected>>", self.onSpectrumSelected
        )  #binding to event because CB does not have 'command' param
        self.m_spectrumCB.grid(row=2, column=0, columnspan=3, sticky="nsew")

        # self.m_spectrumSelectionLabel = ttk.Label(self.m_chordFrame, text='Select Mass Spectrum for Integration:')
        # self.m_spectrumSelectionLabel.grid(row = 3, column = 0, columnspan = 2, sticky="nsw")

        # self.m_spectrumCB = ttk.Combobox(self.m_chordFrame)
        # # self.m_prefactorCB.bind("<<ComboboxSelected>>", self.plotDataForSelectedPrefactor) #binding to event because CB does not have 'command' param
        # self.m_spectrumCB.grid(row = 4, column = 0, columnspan = 3, sticky = "nsew")

        # Integration Options

        self.m_optionsLabel = ttk.Label(
            self.m_chordFrame,
            text="Fitting Options:")  #, compound = tk.CENTER)
        self.m_optionsLabel.grid(row=5, column=0, sticky="nsw")

        self.m_tCutStartLabel = ttk.Label(self.m_chordFrame,
                                          text="Lower Boundary (1/T)")
        self.m_tCutStartLabel.grid(row=6, column=1, sticky="nse")

        self.m_lowerBoundEntry = EnhancedEntry(
            self.m_chordFrame,
            inputValueType=float,
            errorTitle="Lower Boundary",
            errorMessage=
            "Please enter a decimal for the lower boundary of the leading edge."
        )
        self.m_lowerBoundEntry.grid(row=6, column=2, sticky="nsw")

        self.m_tCutEndLabel = ttk.Label(self.m_chordFrame,
                                        text="Upper Boundary (1/T)")
        self.m_tCutEndLabel.grid(row=7, column=1, sticky="nse")

        self.m_upperBoundEntry = EnhancedEntry(
            self.m_chordFrame,
            inputValueType=float,
            errorTitle="Upper Boundary",
            errorMessage=
            "Please enter a decimal for the upper boundary of the leading edge."
        )
        self.m_upperBoundEntry.grid(row=7, column=2, sticky="nsw")

        self.m_resultsLabel = ttk.Label(
            self.m_chordFrame, text="Result:")  #, compound = tk.CENTER)
        self.m_resultsLabel.grid(row=8, column=0, sticky="nsw")

        self.m_resultTitleLabel = ttk.Label(self.m_chordFrame,
                                            text="Inv. x-intercept (K):")
        self.m_resultTitleLabel.grid(row=9, column=1, sticky="nse")

        self.m_resultValueLabel = ttk.Label(self.m_chordFrame, text="N/A")
        self.m_resultValueLabel.grid(row=9, column=2, sticky="nsw")

        # self.m_Label = ttk.Label(self.m_chordFrame, text='Work in Progress')
        # self.m_Label.grid(row = 10, column = 0, columnspan = 4, sticky="nsew")

        #Process Button
        self.m_processButton = ttk.Button(self.m_chordFrame,
                                          text="Generate Edge Fit",
                                          command=self.processInput)
        self.m_processButton.grid(row=10,
                                  column=0,
                                  columnspan=4,
                                  sticky="nsew")
    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 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)
Esempio n. 9
0
    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)
Esempio n. 10
0
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)