#/*##########################################################################
# Copyright (C) 2004-2014 V.A. Sole, European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
__author__ = "V.A. Sole - ESRF Data Analysis"
__contact__ = "sole@esrf.fr"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
import sys
import os
from PyMca5.PyMcaGui import PyMcaQt as qt
from PyMca5.PyMcaMath.fitting import SimpleFitModule
from . import SimpleFitConfigurationGui
from PyMca5.PyMcaMath.fitting import SimpleFitUserEstimatedFunctions
from . import Parameters
from PyMca5.PyMcaGui import PlotWindow
DEBUG = 0
[docs]class SimpleFitGui(qt.QWidget):
sigSimpleFitSignal = qt.pyqtSignal(object)
def __init__(self, parent=None, fit=None, graph=None, actions=True):
qt.QWidget.__init__(self, parent)
self.setWindowTitle("SimpleFitGui")
if fit is None:
self.fitModule = SimpleFitModule.SimpleFit()
self.fitModule.importFunctions(SimpleFitUserEstimatedFunctions)
else:
self.fitModule = fit
if graph is None:
self.__useTab = True
self.graph = PlotWindow.PlotWindow(newplot=False,
plugins=False,
fit=False)
else:
self.__useTab = False
self.graph = graph
self._configurationDialog = None
self.mainLayout = qt.QVBoxLayout(self)
self.mainLayout.setContentsMargins(2, 2, 2, 2)
self.mainLayout.setSpacing(2)
self.topWidget = TopWidget(self)
config = self.fitModule.getConfiguration()
self.topWidget.setFunctions(config['fit']['functions'])
config = None
if self.__useTab:
self.mainTab = qt.QTabWidget(self)
self.mainLayout.addWidget(self.mainTab)
self.parametersTable = Parameters.Parameters()
self.mainTab.addTab(self.graph, 'GRAPH')
self.mainTab.addTab(self.parametersTable, 'FIT')
else:
self.parametersTable = Parameters.Parameters(self)
self.statusWidget = StatusWidget(self)
self.mainLayout.addWidget(self.topWidget)
if self.__useTab:
self.mainLayout.addWidget(self.mainTab)
else:
self.mainLayout.addWidget(self.parametersTable)
self.mainLayout.addWidget(self.statusWidget)
if actions:
#build the actions widget
self.fitActions = qt.QWidget(self)
self.fitActions.mainLayout = qt.QHBoxLayout(self.fitActions)
self.fitActions.mainLayout.setContentsMargins(2, 2, 2, 2)
self.fitActions.mainLayout.setSpacing(2)
self.fitActions.estimateButton = qt.QPushButton(self.fitActions)
self.fitActions.estimateButton.setText("Estimate")
self.fitActions.startFitButton = qt.QPushButton(self.fitActions)
self.fitActions.startFitButton.setText("Start Fit")
self.fitActions.dismissButton = qt.QPushButton(self.fitActions)
self.fitActions.dismissButton.setText("Dismiss")
self.fitActions.mainLayout.addWidget(self.fitActions.estimateButton)
self.fitActions.mainLayout.addWidget(self.fitActions.startFitButton)
self.fitActions.mainLayout.addWidget(self.fitActions.dismissButton)
self.mainLayout.addWidget(self.fitActions)
#connect top widget
self.topWidget.addFunctionButton.clicked.connect(\
self.importFunctions)
self.topWidget.fitFunctionCombo.currentIndexChanged[int].connect(\
self.fitFunctionComboSlot)
self.topWidget.backgroundCombo.currentIndexChanged[int].connect(\
self.backgroundComboSlot)
self.topWidget.configureButton.clicked.connect(\
self.configureButtonSlot)
if actions:
#connect actions
self.fitActions.estimateButton.clicked.connect(self.estimate)
self.fitActions.startFitButton.clicked.connect(self.startFit)
self.fitActions.dismissButton.clicked.connect(self.dismiss)
[docs] def importFunctions(self, functionsfile=None):
if functionsfile is None:
fn = qt.QFileDialog.getOpenFileName()
if fn.isEmpty():
functionsfile = ""
else:
functionsfile= qt.safe_str(fn)
if not len(functionsfile):
return
if DEBUG:
self.fitModule.importFunctions(functionsfile)
else:
try:
self.fitModule.importFunctions(functionsfile)
except:
qt.QMessageBox.critical(self, "ERROR",
"Function not imported")
config = self.fitModule.getConfiguration()
self.topWidget.setFunctions(config['fit']['functions'])
[docs] def fitFunctionComboSlot(self, idx):
if idx <= 0:
fname = "None"
else:
fname = qt.safe_str(self.topWidget.fitFunctionCombo.itemText(idx))
self.fitModule.setFitFunction(fname)
[docs] def backgroundComboSlot(self, idx):
if idx <= 0:
fname = "None"
else:
fname = qt.safe_str(self.topWidget.backgroundCombo.itemText(idx))
self.setBackgroundFunction(fname)
#self.estimate()
[docs] def setFitFunction(self, fname):
current = self.fitModule.getFitFunction()
if current != fname:
self.fitModule.setFitFunction(fname)
idx = self.topWidget.fitFunctionCombo.findText(fname)
self.topWidget.fitFunctionCombo.setCurrentIndex(idx)
[docs] def setBackgroundFunction(self, fname):
current = self.fitModule.getBackgroundFunction()
if current != fname:
self.fitModule.setBackgroundFunction(fname)
idx = self.topWidget.backgroundCombo.findText(fname)
self.topWidget.backgroundCombo.setCurrentIndex(idx)
[docs] def setData(self, *var, **kw):
returnValue = self.fitModule.setData(*var, **kw)
if self.__useTab:
if hasattr(self.graph, "addCurve"):
self.graph.addCurve(self.fitModule._x,
self.fitModule._y,
legend='Data',
replace=True)
elif hasattr(self.graph, "newCurve"):
self.graph.clearCurves()
self.graph.newCurve('Data',
self.fitModule._x,
self.fitModule._y)
self.graph.replot()
return returnValue
[docs] def estimate(self):
self.setStatus("Estimate started")
self.statusWidget.chi2Line.setText("")
try:
x = self.fitModule._x
y = self.fitModule._y
if hasattr(self.graph, "addCurve"):
self.graph.addCurve(x, y, 'Data')
elif hasattr(self.graph, "newCurve"):
self.graph.newCurve('Data', x, y)
self.graph.removeCurve("Fit")
self.graph.removeCurve("Background", replot=True)
self.fitModule.estimate()
self.setStatus()
self.parametersTable.fillTableFromFit(self.fitModule.paramlist)
except:
if DEBUG:
raise
text = "%s:%s" % (sys.exc_info()[0], sys.exc_info()[1])
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText(text)
msg.exec_()
self.setStatus("Ready (after estimate error)")
[docs] def setStatus(self, text=None):
if text is None:
text = "%s" % self.fitModule.getStatus()
self.statusWidget.statusLine.setText(text)
#get parameters from table
self.fitModule.paramlist = self.parametersTable.fillFitFromTable()
try:
values,chisq,sigma,niter,lastdeltachi = self.fitModule.startFit()
self.setStatus()
except:
if DEBUG:
raise
text = "%s:%s" % (sys.exc_info()[0], sys.exc_info()[1])
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText(text)
msg.exec_()
self.setStatus("Ready (after fit error)")
return
self.parametersTable.fillTableFromFit(self.fitModule.paramlist)
self.statusWidget.chi2Line.setText("%f" % chisq)
ddict = {}
ddict['event'] = "FitFinished"
ddict['x'] = self.fitModule._x
ddict['y'] = self.fitModule._y
ddict['yfit'] = self.evaluateDefinedFunction()
self.sigSimpleFitSignal.emit(ddict)
self.updateGraph()
#this is to be overwritten and for test purposes
if self.graph is None:
return
ddict = {}
ddict['event'] = "FitFinished"
ddict['x'] = self.fitModule._x
ddict['y'] = self.fitModule._y
ddict['yfit'] = self.evaluateDefinedFunction()
ddict['background'] = self.fitModule._evaluateBackground()
if hasattr(self.graph, "addCurve"):
self.graph.addCurve(ddict['x'], ddict['y'], 'Data')
self.graph.addCurve(ddict['x'], ddict['yfit'], 'Fit')
self.graph.addCurve(ddict['x'], ddict['background'], 'Background')
elif hasattr(self.graph, "newCurve"):
self.graph.newCurve('Data', ddict['x'], ddict['y'])
self.graph.newCurve('Fit', ddict['x'], ddict['yfit'])
self.graph.newCurve('Background', ddict['x'], ddict['background'])
self.graph.replot()
self.graph.show()
[docs] def dismiss(self):
self.close()
[docs] def evaluateDefinedFunction(self, x=None):
return self.fitModule.evaluateDefinedFunction()
[docs]def test():
import numpy
#import DefaultFitFunctions as SpecfitFunctions
from PyMca import SpecfitFunctions
a=SpecfitFunctions.SpecfitFunctions()
x = numpy.arange(1000).astype(numpy.float)
p1 = numpy.array([1500,100.,50.0])
p2 = numpy.array([1500,700.,50.0])
y = a.gauss(p1, x)
y = y + a.gauss(p2,x) + x * 5.
if 0:
fit = SimpleFitModule.SimpleFit()
fit.importFunctions(SpecfitFunctions)
fit.setFitFunction('Gaussians')
#fit.setBackgroundFunction('Gaussians')
#fit.setBackgroundFunction('Constant')
fit.setData(x, y)
w = SimpleFitGui(fit=fit)
w.show()
else:
fit=None
w = SimpleFitGui(fit=fit)
w.setData(x, y, xmin=x[0], xmax=x[-1])
w.show()
import SimpleFitUserEstimatedFunctions
fname = SimpleFitUserEstimatedFunctions.__file__
w.importFunctions(fname)
w.setFitFunction('User Estimated Gaussians')
return w
if __name__=="__main__":
DEBUG = 0
app = qt.QApplication([])
w = test()
app.exec_()