Esempio n. 1
0
class App(tkinter.ttk.Frame):
    def __init__(self):
        tkinter.ttk.Frame.__init__(self)
        self.master.title("AshCalc")

        self.threadHandler = ThreadHandler()
        self.calculating = False
        self.weibullTimingEstimationFunction = createWeibullTimingEstimationFunction(
        )

        self.calculationFrame = CalculationFrame(self)
        self.calculationFrame.grid(row=0,
                                   column=0,
                                   sticky="NSWE",
                                   padx=10,
                                   pady=10)
        self.calculationFrame.startCalculationB.bind("<Button-1>",
                                                     self.startCalculation)
        self.calculationFrame.endCalculationB.configure(state=tkinter.DISABLED)

        self.isopachFrame = IsopachFrame(self,
                                         self.estimateWeibullCalculationTime)
        self.isopachFrame.grid(row=1, column=0, padx=10, sticky="NSE", pady=10)

        self.modelFrame = ModelFrame(self)
        self.modelFrame.grid(row=0, column=1, sticky="NESW", padx=10, pady=10)
        self.modelFrame.weiNumberOfRuns_E.bind(
            "<KeyRelease>", self.estimateWeibullCalculationTime)
        self.modelFrame.weiIterationsPerRun_E.bind(
            "<KeyRelease>", self.estimateWeibullCalculationTime)
        self.estimateWeibullCalculationTime(None)

        self.resultsFrame = ResultsFrame(self)
        self.resultsFrame.grid(row=1,
                               column=1,
                               padx=10,
                               sticky="NSEW",
                               pady=10)

        self.isopachFrame.loadData([
            Isopach(0.4, 16.25),
            Isopach(0.2, 30.63),
            Isopach(0.1, 58.87),
            Isopach(0.05, 95.75),
            Isopach(0.02, 181.56),
            Isopach(0.01, 275.1)
        ])

        self.createTooltips()

        self.pack()
        self.mainloop()

    def startCalculation(self, event):

        try:
            isopachs = self.isopachFrame.getData()
            modelDetails = self.modelFrame.getModelDetails()
            self.threadHandler.startCalculation(modelDetails[0],
                                                [isopachs] + modelDetails[1:])

        except ValueError as ve:
            messagebox.showerror("Calculation error", ve.args[0])
            return

        self.resultsFrame.clear()

        self.calculationFrame.calculationPB.start(interval=3)
        self.calculationFrame.startCalculationB.configure(
            state=tkinter.DISABLED)
        self.calculationFrame.startCalculationB.unbind("<Button-1>")
        self.calculationFrame.endCalculationB.configure(state=tkinter.ACTIVE)
        self.calculationFrame.endCalculationB.bind("<Button-1>",
                                                   self.finishCalculation)

        self.calculating = True
        self.poll()

    def poll(self):
        result = self.threadHandler.getCurrentCalculationResult()
        if result is not None:
            modelType, results = result
            if modelType == "Error":
                messagebox.showerror("Calculation error", results.args[0])
            else:
                self.resultsFrame.displayNewModel(modelType, results)
            self.finishCalculation(None)
        elif self.calculating:
            self.after(100, self.poll)

    def finishCalculation(self, _):
        self.threadHandler.cancelLastCalculation()
        self.calculating = False
        self.calculationFrame.startCalculationB.configure(state=tkinter.ACTIVE)
        self.calculationFrame.startCalculationB.bind("<Button-1>",
                                                     self.startCalculation)
        self.calculationFrame.endCalculationB.configure(state=tkinter.DISABLED)
        self.calculationFrame.endCalculationB.unbind("<Button-1>")
        self.calculationFrame.calculationPB.stop()

    def estimateWeibullCalculationTime(self, event):
        try:
            numberOfIsopachs = self.isopachFrame.getNumberOfIncludedIsopachs()
            numberOfRuns = int(self.modelFrame.weiNumberOfRuns_E.get())
            iterationsPerRun = int(self.modelFrame.weiIterationsPerRun_E.get())
            if numberOfRuns <= 0 or iterationsPerRun <= 0 or numberOfIsopachs <= 0:
                raise ValueError()
            est = self.weibullTimingEstimationFunction(numberOfIsopachs,
                                                       iterationsPerRun,
                                                       numberOfRuns)
            self.modelFrame.weiEstimatedTime_E.insertNew(
                helper_functions.roundToSF(est, 2))
        except ValueError:
            self.modelFrame.weiEstimatedTime_E.insertNew("N/A")

    def createTooltips(self):
        statsFrame = self.resultsFrame.statsFrame

        tips = [
            (self.modelFrame.weiNumberOfRuns_E, True,
             "The number of possible sets of parameters that are generated. The final parameters returned are the set which best fit the data. See the instruction manual for further details."
             ),
            (self.modelFrame.weiIterationsPerRun_E, True,
             "The number of times the current parameters are adjusted within each run. See the instruction manual for further details."
             ),
            (self.modelFrame.weiEstimatedTime_E, True,
             "A rough estimate of the time required to execute this computation."
             ),
            (self.resultsFrame.statsFrame.totalEstimatedVolume_E, True,
             "The model's estimate for the total volume of the tephra deposit."
             ),
            (self.resultsFrame.statsFrame.relativeSquaredError_E, True,
             "A measure of the goodness of fit of the model. Comparisons are only valid when comparing different models for identical isopach data."
             ),
            (self.resultsFrame.statsFrame.expSegVolume_E, True,
             "The model's estimate for the volume of this segment of the tephra deposit."
             ),
            (self.resultsFrame.statsFrame.powSuggestedProximalLimit_E, True,
             "An estimate for the proximal limit of integration as described in Bonadonna and Houghton 2005. Requires 4 or more isopachs."
             ),
            (self.resultsFrame.errorSurfaceFrame.errorResolutionE, True,
             "The resolution of the error surface, which is modelled by a grid of 'resolution' x 'resolution' points."
             ),
            (self.isopachFrame.loadFromFileButton, False,
             "Load isopach data from a CSV file of the form: \n\tthickness1, \u221AArea1\n\tthickness2, \u221AArea2\n\t...\n\tthicknessN, \u221AAreaN\nwith thickness in metres and \u221AArea in kilometres"
             ),
        ]

        for target, wrap, tip in tips:
            if wrap:
                tip = "\n".join(textwrap.wrap(tip, 60))
            ToolTip(target, tip)
Esempio n. 2
0
class App(tkinter.ttk.Frame):
	
	def __init__(self):
		tkinter.ttk.Frame.__init__(self)
		self.master.title("AshCalc")
		
		self.threadHandler = ThreadHandler()
		self.calculating = False
		self.weibullTimingEstimationFunction = createWeibullTimingEstimationFunction()
		
		self.calculationFrame = CalculationFrame(self)
		self.calculationFrame.grid(row=0,column=0,sticky="NSWE",padx=10,pady=10)
		self.calculationFrame.startCalculationB.bind("<Button-1>",self.startCalculation)
		self.calculationFrame.endCalculationB.configure(state=tkinter.DISABLED)

		self.isopachFrame = IsopachFrame(self,self.estimateWeibullCalculationTime)
		self.isopachFrame.grid(row=1,column=0,padx=10,sticky="NSE",pady=10)
		
		self.modelFrame = ModelFrame(self)
		self.modelFrame.grid(row=0,column=1,sticky="NESW",padx=10,pady=10)
		self.modelFrame.weiNumberOfRuns_E.bind("<KeyRelease>",self.estimateWeibullCalculationTime)
		self.modelFrame.weiIterationsPerRun_E.bind("<KeyRelease>",self.estimateWeibullCalculationTime)
		self.estimateWeibullCalculationTime(None)

		self.resultsFrame = ResultsFrame(self)
		self.resultsFrame.grid(row=1,column=1,padx=10,sticky="NSEW",pady=10)

		self.isopachFrame.loadData([Isopach(0.4, 16.25),Isopach(0.2, 30.63),Isopach(0.1, 58.87),Isopach(0.05, 95.75),Isopach(0.02, 181.56),Isopach(0.01, 275.1)])

		self.createTooltips()

		self.pack()
		self.mainloop()
		
	def startCalculation(self, event):
		
		try:
			isopachs = self.isopachFrame.getData()
			modelDetails = self.modelFrame.getModelDetails()
			self.threadHandler.startCalculation(modelDetails[0], [isopachs] + modelDetails[1:])

		except ValueError as ve:
			messagebox.showerror("Calculation error", ve.args[0])
			return
		
		self.resultsFrame.clear()

		self.calculationFrame.calculationPB.start(interval=3)
		self.calculationFrame.startCalculationB.configure(state=tkinter.DISABLED)
		self.calculationFrame.startCalculationB.unbind("<Button-1>")
		self.calculationFrame.endCalculationB.configure(state=tkinter.ACTIVE)
		self.calculationFrame.endCalculationB.bind("<Button-1>",self.finishCalculation)
		
		self.calculating = True
		self.poll()
		
	def poll(self):
		result = self.threadHandler.getCurrentCalculationResult()
		if result is not None:
			modelType, results = result
			if modelType == "Error":
				messagebox.showerror("Calculation error", results.args[0])
			else:
				self.resultsFrame.displayNewModel(modelType,results)
			self.finishCalculation(None)
		elif self.calculating:
			self.after(100, self.poll)
	
	def finishCalculation(self,_):
		self.threadHandler.cancelLastCalculation()
		self.calculating = False
		self.calculationFrame.startCalculationB.configure(state=tkinter.ACTIVE)
		self.calculationFrame.startCalculationB.bind("<Button-1>", self.startCalculation)
		self.calculationFrame.endCalculationB.configure(state=tkinter.DISABLED)
		self.calculationFrame.endCalculationB.unbind("<Button-1>")
		self.calculationFrame.calculationPB.stop()

	def estimateWeibullCalculationTime(self,event):
		try:
			numberOfIsopachs = self.isopachFrame.getNumberOfIncludedIsopachs()
			numberOfRuns = int(self.modelFrame.weiNumberOfRuns_E.get())
			iterationsPerRun = int(self.modelFrame.weiIterationsPerRun_E.get())
			if numberOfRuns <= 0 or iterationsPerRun <= 0 or numberOfIsopachs <= 0:
				raise ValueError()
			est = self.weibullTimingEstimationFunction(numberOfIsopachs,iterationsPerRun,numberOfRuns)
			self.modelFrame.weiEstimatedTime_E.insertNew(helper_functions.roundToSF(est,2))
		except ValueError:
			self.modelFrame.weiEstimatedTime_E.insertNew("N/A")

	def createTooltips(self):
		statsFrame = self.resultsFrame.statsFrame

		
		tips = [
			(self.modelFrame.weiNumberOfRuns_E,							True, "The number of possible sets of parameters that are generated. The final parameters returned are the set which best fit the data. See the instruction manual for further details."),
			(self.modelFrame.weiIterationsPerRun_E,						True, "The number of times the current parameters are adjusted within each run. See the instruction manual for further details."),
			(self.modelFrame.weiEstimatedTime_E,						True, "A rough estimate of the time required to execute this computation."),

			(self.resultsFrame.statsFrame.totalEstimatedVolume_E, 		True, "The model's estimate for the total volume of the tephra deposit."),
			(self.resultsFrame.statsFrame.relativeSquaredError_E, 		True, "A measure of the goodness of fit of the model. Comparisons are only valid when comparing different models for identical isopach data."),
			(self.resultsFrame.statsFrame.expSegVolume_E, 				True, "The model's estimate for the volume of this segment of the tephra deposit."),
			(self.resultsFrame.statsFrame.powSuggestedProximalLimit_E,	True, "An estimate for the proximal limit of integration as described in Bonadonna and Houghton 2005. Requires 4 or more isopachs."),
			(self.resultsFrame.errorSurfaceFrame.errorResolutionE,		True, "The resolution of the error surface, which is modelled by a grid of 'resolution' x 'resolution' points."),
			
			(self.isopachFrame.loadFromFileButton,						False, "Load isopach data from a CSV file of the form: \n\tthickness1, \u221AArea1\n\tthickness2, \u221AArea2\n\t...\n\tthicknessN, \u221AAreaN\nwith thickness in metres and \u221AArea in kilometres"),
		]

		for target, wrap, tip in tips:
			if wrap:
				tip = "\n".join(textwrap.wrap(tip, 60))
			ToolTip(target, tip)