#/*##########################################################################
# 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.PyMcaCore import EventHandler
from PyMca5.PyMcaMath.fitting import Specfit
from PyMca5.PyMcaGui import PyMcaQt as qt
QTVERSION = qt.qVersion()
from . import FitConfigGui
from . import MultiParameters
from . import FitActionsGui
from . import FitStatusGui
from . import QScriptOption
DEBUG = 0
[docs]class SpecfitGui(qt.QWidget):
sigSpecfitGuiSignal = qt.pyqtSignal(object)
def __init__(self,parent = None,name = None,fl = 0, specfit = None,
config = 0, status = 0, buttons = 0, eh = None):
if name == None:
name = "SpecfitGui"
qt.QWidget.__init__(self, parent)
self.setWindowTitle(name)
layout= qt.QVBoxLayout(self)
#layout.setAutoAdd(1)
if eh == None:
self.eh = EventHandler.EventHandler()
else:
self.eh = eh
if specfit is None:
self.specfit = Specfit.Specfit(eh=self.eh)
else:
self.specfit = specfit
#initialize the default fitting functions in case
#none is present
if not len(self.specfit.theorylist):
funsFile = "SpecfitFunctions.py"
if not os.path.exists(funsFile):
funsFile = os.path.join(os.path.dirname(Specfit.__file__),\
funsFile)
self.specfit.importfun(funsFile)
#copy specfit configure method for direct access
self.configure=self.specfit.configure
self.fitconfig=self.specfit.fitconfig
self.setdata=self.specfit.setdata
self.guiconfig=None
if config:
self.guiconfig = FitConfigGui.FitConfigGui(self)
self.guiconfig.MCACheckBox.stateChanged[int].connect(self.mcaevent)
self.guiconfig.WeightCheckBox.stateChanged[int].connect(self.weightevent)
self.guiconfig.AutoFWHMCheckBox.stateChanged[int].connect(self.autofwhmevent)
self.guiconfig.AutoScalingCheckBox.stateChanged[int].connect(self.autoscaleevent)
self.guiconfig.ConfigureButton.clicked.connect(self.__configureGuiSlot)
self.guiconfig.PrintPushButton.clicked.connect(self.printps)
self.guiconfig.BkgComBox.activated[str].connect(self.bkgevent)
self.guiconfig.FunComBox.activated[str].connect(self.funevent)
layout.addWidget(self.guiconfig)
self.guiparameters = MultiParameters.ParametersTab(self)
layout.addWidget(self.guiparameters)
self.guiparameters.sigMultiParametersSignal.connect(self.__forward)
if config:
for key in self.specfit.bkgdict.keys():
self.guiconfig.BkgComBox.addItem(str(key))
for key in self.specfit.theorylist:
self.guiconfig.FunComBox.addItem(str(key))
configuration={}
if specfit is not None:
configuration = specfit.configure()
if configuration['fittheory'] is None:
self.guiconfig.FunComBox.setCurrentIndex(1)
self.funevent(self.specfit.theorylist[0])
else:
self.funevent(configuration['fittheory'])
if configuration['fitbkg'] is None:
self.guiconfig.BkgComBox.setCurrentIndex(1)
self.bkgevent(list(self.specfit.bkgdict.keys())[0])
else:
self.bkgevent(configuration['fitbkg'])
else:
self.guiconfig.BkgComBox.setCurrentIndex(1)
self.guiconfig.FunComBox.setCurrentIndex(1)
self.funevent(self.specfit.theorylist[0])
self.bkgevent(list(self.specfit.bkgdict.keys())[0])
configuration.update(self.configure())
if configuration['McaMode']:
self.guiconfig.MCACheckBox.setChecked(1)
else:
self.guiconfig.MCACheckBox.setChecked(0)
if configuration['WeightFlag']:
self.guiconfig.WeightCheckBox.setChecked(1)
else:
self.guiconfig.WeightCheckBox.setChecked(0)
if configuration['AutoFwhm']:
self.guiconfig.AutoFWHMCheckBox.setChecked(1)
else:
self.guiconfig.AutoFWHMCheckBox.setChecked(0)
if configuration['AutoScaling']:
self.guiconfig.AutoScalingCheckBox.setChecked(1)
else:
self.guiconfig.AutoScalingCheckBox.setChecked(0)
if status:
self.guistatus = FitStatusGui.FitStatusGui(self)
self.eh.register('FitStatusChanged',self.fitstatus)
layout.addWidget(self.guistatus)
if buttons:
self.guibuttons = FitActionsGui.FitActionsGui(self)
self.guibuttons.EstimateButton.clicked.connect(self.estimate)
self.guibuttons.StartfitButton.clicked.connect(self.startfit)
self.guibuttons.DismissButton.clicked.connect(self.dismiss)
layout.addWidget(self.guibuttons)
[docs] def updateGui(self,configuration=None):
self.__configureGui(configuration)
def _emitSignal(self, ddict):
self.sigSpecfitGuiSignal.emit(ddict)
def __configureGuiSlot(self):
self.__configureGui()
def __configureGui(self, newconfiguration=None):
if self.guiconfig is not None:
#get current dictionary
#print "before ",self.specfit.fitconfig['fitbkg']
configuration=self.configure()
#get new dictionary
if newconfiguration is None:
newconfiguration=self.configureGui(configuration)
#update configuration
configuration.update(self.configure(**newconfiguration))
#print "after =",self.specfit.fitconfig['fitbkg']
#update Gui
#current function
#self.funevent(self.specfit.theorylist[0])
try:
i=1+self.specfit.theorylist.index(self.specfit.fitconfig['fittheory'])
self.guiconfig.FunComBox.setCurrentIndex(i)
self.funevent(self.specfit.fitconfig['fittheory'])
except:
print("Function not in list %s" %\
self.specfit.fitconfig['fittheory'])
self.funevent(self.specfit.theorylist[0])
#current background
try:
#the list conversion is needed in python 3.
i=1+list(self.specfit.bkgdict.keys()).index(self.specfit.fitconfig['fitbkg'])
self.guiconfig.BkgComBox.setCurrentIndex(i)
except:
print("Background not in list %s" %\
self.specfit.fitconfig['fitbkg'])
self.bkgevent(list(self.specfit.bkgdict.keys())[0])
#and all the rest
if configuration['McaMode']:
self.guiconfig.MCACheckBox.setChecked(1)
else:
self.guiconfig.MCACheckBox.setChecked(0)
if configuration['WeightFlag']:
self.guiconfig.WeightCheckBox.setChecked(1)
else:
self.guiconfig.WeightCheckBox.setChecked(0)
if configuration['AutoFwhm']:
self.guiconfig.AutoFWHMCheckBox.setChecked(1)
else:
self.guiconfig.AutoFWHMCheckBox.setChecked(0)
if configuration['AutoScaling']:
self.guiconfig.AutoScalingCheckBox.setChecked(1)
else:
self.guiconfig.AutoScalingCheckBox.setChecked(0)
#update the Gui
self.__initialparameters()
#this method can be overwritten for custom
#it should give back a new dictionary
newconfiguration={}
newconfiguration.update(oldconfiguration)
if (0):
#example to force a given default configuration
newconfiguration['FitTheory']="Pseudo-Voigt Line"
newconfiguration['AutoFwhm']=1
newconfiguration['AutoScaling']=1
#example script options like
if (1):
sheet1={'notetitle':'Restrains',
'fields':(["CheckField",'HeightAreaFlag','Force positive Height/Area'],
["CheckField",'PositionFlag','Force position in interval'],
["CheckField",'PosFwhmFlag','Force positive FWHM'],
["CheckField",'SameFwhmFlag','Force same FWHM'],
["CheckField",'EtaFlag','Force Eta between 0 and 1'],
["CheckField",'NoConstrainsFlag','Ignore Restrains'])}
sheet2={'notetitle':'Search',
'fields':(["EntryField",'FwhmPoints', 'Fwhm Points: '],
["EntryField",'Sensitivity','Sensitivity: '],
["EntryField",'Yscaling', 'Y Factor : '],
["CheckField",'ForcePeakPresence', 'Force peak presence '])}
w=QScriptOption.QScriptOption(self,name='Fit Configuration',
sheets=(sheet1,sheet2),
default=oldconfiguration)
w.show()
w.exec_()
if w.result():
newconfiguration.update(w.output)
#we do not need the dialog any longer
del w
newconfiguration['FwhmPoints']=int(float(newconfiguration['FwhmPoints']))
newconfiguration['Sensitivity']=float(newconfiguration['Sensitivity'])
newconfiguration['Yscaling']=float(newconfiguration['Yscaling'])
return newconfiguration
[docs] def estimate(self):
if self.specfit.fitconfig['McaMode']:
try:
mcaresult=self.specfit.mcafit()
except:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("Error on mcafit")
msg.exec_()
ddict={}
ddict['event'] = 'FitError'
self._emitSignal(ddict)
if DEBUG:
raise
return
self.guiparameters.fillfrommca(mcaresult)
ddict={}
ddict['event'] = 'McaFitFinished'
ddict['data'] = mcaresult
self._emitSignal(ddict)
#self.guiparameters.removeallviews(keep='Region 1')
else:
try:
if self.specfit.theorydict[self.specfit.fitconfig['fittheory']][2] is not None:
self.specfit.estimate()
else:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Information)
text = "Function does not define a way to estimate\n"
text += "the initial parameters. Please, fill them\n"
text += "yourself in the table and press Start Fit\n"
msg.setText(text)
msg.setWindowTitle('SpecfitGui Message')
msg.exec_()
return
except:
if DEBUG:
raise
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("Error on estimate: %s" % sys.exc_info()[1])
msg.exec_()
return
self.guiparameters.fillfromfit(self.specfit.paramlist,current='Fit')
self.guiparameters.removeallviews(keep='Fit')
ddict={}
ddict['event'] = 'EstimateFinished'
ddict['data'] = self.specfit.paramlist
self._emitSignal(ddict)
return
def __forward(self,ddict):
self._emitSignal(ddict)
[docs] def startfit(self):
if self.specfit.fitconfig['McaMode']:
try:
mcaresult=self.specfit.mcafit()
except:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("Error on mcafit: %s" % sys.exc_info()[1])
msg.exec_()
if DEBUG:
raise
return
self.guiparameters.fillfrommca(mcaresult)
ddict={}
ddict['event'] = 'McaFitFinished'
ddict['data'] = mcaresult
self._emitSignal(ddict)
#self.guiparameters.removeview(view='Fit')
else:
#for param in self.specfit.paramlist:
# print param['name'],param['group'],param['estimation']
self.specfit.paramlist=self.guiparameters.fillfitfromtable()
if DEBUG:
for param in self.specfit.paramlist:
print(param['name'],param['group'],param['estimation'])
print("TESTING")
self.specfit.startfit()
try:
self.specfit.startfit()
except:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("Error on Fit")
msg.exec_()
if DEBUG:
raise
return
self.guiparameters.fillfromfit(self.specfit.paramlist,current='Fit')
self.guiparameters.removeallviews(keep='Fit')
ddict={}
ddict['event'] = 'FitFinished'
ddict['data'] = self.specfit.paramlist
self._emitSignal(ddict)
return
[docs] def printps(self,**kw):
text = self.guiparameters.gettext(**kw)
if __name__ == "__main__":
self.__printps(text)
else:
ddict={}
ddict['event'] = 'print'
ddict['text'] = text
self._emitSignal(ddict)
return
def __printps(self, text):
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("Sorry, Qt4 printing not implemented yet")
msg.exec_()
[docs] def mcaevent(self,item):
if int(item):
self.configure(McaMode=1)
mode = 1
else:
self.configure(McaMode=0)
mode = 0
self.__initialparameters()
ddict={}
ddict['event'] = 'McaModeChanged'
ddict['data'] = mode
self._emitSignal(ddict)
return
[docs] def weightevent(self,item):
if int(item):
self.configure(WeightFlag=1)
else:
self.configure(WeightFlag=0)
return
[docs] def autofwhmevent(self,item):
if int(item):
self.configure(AutoFwhm=1)
else:
self.configure(AutoFwhm=0)
return
[docs] def autoscaleevent(self,item):
if int(item):
self.configure(AutoScaling=1)
else:
self.configure(AutoScaling=0)
return
[docs] def bkgevent(self,item):
item=str(item)
if item in self.specfit.bkgdict.keys():
self.specfit.setbackground(item)
else:
qt.QMessageBox.information(self, "Info", "Function not implemented")
return
i=1+self.specfit.bkgdict.keys().index(self.specfit.fitconfig['fitbkg'])
self.guiconfig.BkgComBox.setCurrentIndex(i)
self.__initialparameters()
return
[docs] def funevent(self,item):
item=str(item)
if item in self.specfit.theorylist:
self.specfit.settheory(item)
else:
# TODO why this strange condition
if 1:
fn = qt.QFileDialog.getOpenFileName()
else:
dlg=qt.QFileDialog(qt.QString.null,qt.QString.null,self,None,1)
dlg.show()
fn=dlg.selectedFile()
if fn.isEmpty():
functionsfile = ""
else:
functionsfile="%s" % fn
if len(functionsfile):
try:
if self.specfit.importfun(functionsfile):
qt.QMessageBox.critical(self, "ERROR",
"Function not imported")
return
else:
#empty the ComboBox
n=self.guiconfig.FunComBox.count()
while(self.guiconfig.FunComBox.count()>1):
self.guiconfig.FunComBox.removeItem(1)
#and fill it again
for key in self.specfit.theorylist:
if QTVERSION < '4.0.0':
self.guiconfig.FunComBox.insertItem(str(key))
else:
self.guiconfig.FunComBox.addItem(str(key))
except:
qt.QMessageBox.critical(self, "ERROR",
"Function not imported")
i=1+self.specfit.theorylist.index(self.specfit.fitconfig['fittheory'])
if QTVERSION < '4.0.0':
self.guiconfig.FunComBox.setCurrentItem(i)
else:
self.guiconfig.FunComBox.setCurrentIndex(i)
self.__initialparameters()
return
def __initialparameters(self):
self.specfit.final_theory=[]
self.specfit.paramlist=[]
for pname in self.specfit.bkgdict[self.specfit.fitconfig['fitbkg']][1]:
self.specfit.final_theory.append(pname)
self.specfit.paramlist.append({'name':pname,
'estimation':0,
'group':0,
'code':'FREE',
'cons1':0,
'cons2':0,
'fitresult':0.0,
'sigma':0.0,
'xmin':None,
'xmax':None})
if self.specfit.fitconfig['fittheory'] is not None:
for pname in self.specfit.theorydict[self.specfit.fitconfig['fittheory']][1]:
self.specfit.final_theory.append(pname+"1")
self.specfit.paramlist.append({'name':pname+"1",
'estimation':0,
'group':1,
'code':'FREE',
'cons1':0,
'cons2':0,
'fitresult':0.0,
'sigma':0.0,
'xmin':None,
'xmax':None})
if self.specfit.fitconfig['McaMode']:
self.guiparameters.fillfromfit(self.specfit.paramlist,current='Region 1')
self.guiparameters.removeallviews(keep='Region 1')
else:
self.guiparameters.fillfromfit(self.specfit.paramlist,current='Fit')
self.guiparameters.removeallviews(keep='Fit')
return
[docs] def fitstatus(self,data):
if 'chisq' in data:
if data['chisq'] is None:
self.guistatus.ChisqLine.setText(" ")
else:
chisq=data['chisq']
self.guistatus.ChisqLine.setText("%6.2f" % chisq)
if 'status' in data:
status=data['status']
self.guistatus.StatusLine.setText(str(status))
return
[docs] def dismiss(self):
self.close()
return
if __name__ == "__main__":
import numpy
from PyMca5 import SpecfitFunctions
a=SpecfitFunctions.SpecfitFunctions()
x = numpy.arange(2000).astype(numpy.float)
p1 = numpy.array([1500,100.,30.0])
p2 = numpy.array([1500,300.,30.0])
p3 = numpy.array([1500,500.,30.0])
p4 = numpy.array([1500,700.,30.0])
p5 = numpy.array([1500,900.,30.0])
p6 = numpy.array([1500,1100.,30.0])
p7 = numpy.array([1500,1300.,30.0])
p8 = numpy.array([1500,1500.,30.0])
p9 = numpy.array([1500,1700.,30.0])
p10 = numpy.array([1500,1900.,30.0])
y = a.gauss(p1,x)+1
y = y + a.gauss(p2,x)
y = y + a.gauss(p3,x)
y = y + a.gauss(p4,x)
y = y + a.gauss(p5,x)
#y = y + a.gauss(p6,x)
#y = y + a.gauss(p7,x)
#y = y + a.gauss(p8,x)
#y = y + a.gauss(p9,x)
#y = y + a.gauss(p10,x)
y=y/1000.0
a = qt.QApplication(sys.argv)
a.lastWindowClosed.connect(a.quit)
w = SpecfitGui(config=1, status=1, buttons=1)
w.setdata(x=x,y=y)
w.show()
a.exec_()