#/*##########################################################################
# 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.PyMcaGui.math.fitting import SpecfitGui
from PyMca5.PyMcaMath.fitting import Specfit
QTVERSION = qt.qVersion()
[docs]class ScanFit(qt.QWidget):
sigScanFitSignal = qt.pyqtSignal(object)
def __init__(self, parent=None, name="ScanFit", specfit=None, fl=0):
#fl=qt.Qt.WDestructiveClose):
qt.QWidget.__init__(self, parent)
self.setWindowTitle(name)
if specfit is None:
self.specfit = Specfit.Specfit()
else:
self.specfit = specfit
self.info = None
layout = qt.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
##############
self.headerlabel = qt.QLabel(self)
self.headerlabel.setAlignment(qt.Qt.AlignHCenter)
self.setHeader('<b>Fit of XXXXXXXXXX from X XXXXX to XXXX<\b>')
##############
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)
if 'Area Gaussians' not in 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)
self.specfit.settheory('Area Gaussians')
self.specfit.setbackground('Linear')
fitconfig = {}
fitconfig.update(self.specfit.fitconfig)
fitconfig['WeightFlag'] = 0
fitconfig['ForcePeakPresence'] = 1
fitconfig['McaMode'] = 0
self.specfit.configure(**fitconfig)
self.specfitGui = SpecfitGui.SpecfitGui(self, config=1, status=1,
buttons=0,
specfit=self.specfit,
eh=self.specfit.eh)
#self.specfitGui.updateGui(configuration=fitconfig)
#self.setdata = self.specfit.setdata
self.specfitGui.guiconfig.MCACheckBox.setEnabled(1)
palette = self.specfitGui.guiconfig.MCACheckBox.palette()
##############
hbox = qt.QWidget(self)
hboxlayout = qt.QHBoxLayout(hbox)
hboxlayout.setContentsMargins(0, 0, 0, 0)
hboxlayout.setSpacing(0)
self.estimatebutton = qt.QPushButton(hbox)
self.estimatebutton.setText("Estimate")
self.fitbutton = qt.QPushButton(hbox)
self.fitbutton.setText("Fit")
hboxlayout.addWidget(self.estimatebutton)
hboxlayout.addWidget(qt.HorizontalSpacer(hbox))
hboxlayout.addWidget(self.fitbutton)
self.dismissbutton = qt.QPushButton(hbox)
self.dismissbutton.setText("Dismiss")
self.estimatebutton.clicked.connect(self.estimate)
self.fitbutton.clicked.connect(self.fit)
self.dismissbutton.clicked.connect(self.dismiss)
self.specfitGui.sigSpecfitGuiSignal.connect(self._specfitGuiSignal)
hboxlayout.addWidget(qt.HorizontalSpacer(hbox))
hboxlayout.addWidget(self.dismissbutton)
layout.addWidget(self.headerlabel)
layout.addWidget(self.specfitGui)
layout.addWidget(hbox)
[docs] def setData(self, *var, **kw):
self.info = {}
if 'legend' in kw:
self.info['legend'] = kw['legend']
del kw['legend']
else:
self.info['legend'] = 'Unknown Origin'
if 'xlabel' in kw:
self.info['xlabel'] = kw['xlabel']
del kw['xlabel']
else:
self.info['xlabel'] = 'X'
self.specfit.setdata(var, **kw)
try:
self.info['xmin'] = "%.3f" % self.specfit.xdata[0]
except:
self.info['xmin'] = 'First'
try:
self.info['xmax'] = "%.3f" % self.specfit.xdata[-1]
except:
self.info['xmax'] = 'Last'
self.setHeader(text="Fit of %s from %s %s to %s" % (self.info['legend'],
self.info['xlabel'],
self.info['xmin'],
self.info['xmax']))
[docs] def fit(self):
if self.specfit.fitconfig['McaMode']:
fitconfig = {}
fitconfig.update(self.specfit.fitconfig)
self.specfitGui.updateGui(configuration=fitconfig)
#the Gui already takes care of mcafit
self.specfitGui.estimate()
else:
#exception handler to be implemented
#self.specfitGui.estimate()
self.specfitGui.startfit()
[docs] def estimate(self):
fitconfig = {}
fitconfig.update(self.specfit.fitconfig)
self.specfitGui.updateGui(configuration=fitconfig)
self.specfitGui.estimate()
def _specfitGuiSignal(self, ddict):
if not hasattr(ddict, "keys"):
return
if 'event' in ddict:
if ddict['event'].upper() == "PRINT":
h = self.__htmlheader()
if __name__ == "__main__":
self.__print(h + ddict['text'])
else:
ndict = {}
ndict['event'] = "ScanFitPrint"
ndict['text' ] = h + ddict['text']
ndict['info' ] = {}
ndict['info'].update(self.info)
self.sigScanFitSignal.emit(ndict)
else:
if self.info is None:
self.info = {}
ddict['info'] = {}
ddict['info'].update(self.info)
self.sigScanFitSignal.emit(ddict)
[docs] def dismiss(self):
self.close()
def __htmlheader(self):
try:
header = "Fit of %s from %s %s to %s" % (self.info['legend'],
self.info['xlabel'],
self.info['xmin'],
self.info['xmax'])
except:
# I cannot afford any unicode, key or whatever error, so,
# provide a default value for the label.
header = 'Fit of XXXXXXXXXX from Channel XXXXX to XXXX'
if self.specfit.fitconfig['WeightFlag']:
weight = "YES"
else:
weight = "NO"
if self.specfit.fitconfig['McaMode']:
mode = "YES"
else:
mode = "NO"
theory = self.specfit.fitconfig['fittheory']
bkg = self.specfit.fitconfig['fitbkg']
fwhm = self.specfit.fitconfig['FwhmPoints']
scaling = self.specfit.fitconfig['Yscaling']
h = ""
h += " <CENTER>"
h += "<B>%s</B>" % header
h += "<BR></BR>"
h += "<TABLE>"
h += "<TR>"
h += " <TD ALIGN=LEFT><B>Function</B></TD>"
h += " <TD><B>:</B></TD>"
h += " <TD ALIGN=LEFT>%s</TD>" % theory
h += " <TD><SPACER TYPE=BLOCK WIDTH=50></TD>"
h += " <TD ALIGN=RIGHT><B>Weight</B></TD>"
h += " <TD><B>:</B></TD>"
h += " <TD ALIGN=LEFT>%s</TD>" % weight
h += " <TD><SPACER TYPE=BLOCK WIDTH=10></B></TD>"
h += " <TD ALIGN=RIGHT><B>FWHM</B></TD>"
h += " <TD><B>:</B></TD></TD>"
h += " <TD ALIGN=LEFT>%d</TD>" % fwhm
h += "</TR>"
h += "<TR>"
h += " <TD ALIGN=LEFT><B>Background</B></TH>"
h += " <TD><B>:</B></TD>"
h += " <TD ALIGN=LEFT>%s</TD>" % bkg
h += " <TD><SPACER TYPE=BLOCK WIDTH=50></B></TD>"
h += " <TD ALIGN=RIGHT><B>MCA Mode</B></TD>"
h += " <TD><B>:</B></TD>"
h += " <TD ALIGN=LEFT>%s</TD>" % mode
h += " <TD><SPACER TYPE=BLOCK WIDTH=10></B></TD>"
h += " <TD ALIGN=RIGHT><B>Scaling</B></TD>"
h += " <TD><B>:</B></TD>"
h += " <TD ALIGN=LEFT>%g</TD>" % scaling
h += "</TR>"
h += "</TABLE>"
h += "</CENTER>"
return h
def __print(self, text):
printer = qt.QPrinter()
if printer.setup(self):
painter = qt.QPainter()
if not(painter.begin(printer)):
return 0
try:
metrics = qt.QPaintDeviceMetrics(printer)
dpiy = metrics.logicalDpiY()
margin = int((2 / 2.54) * dpiy) # 2cm margin
body = qt.QRect(0.5 * margin, margin, metrics.width() - margin,
metrics.height() - 2 * margin)
richtext = qt.QSimpleRichText(text, qt.QFont(),
qt.QString(""),
#0,
qt.QStyleSheet.defaultSheet(),
qt.QMimeSourceFactory.defaultFactory(),
body.height())
view = qt.QRect(body)
richtext.setWidth(painter,view.width())
page = 1
while(1):
richtext.draw(painter,body.left(),body.top(),
view,qt.QColorGroup())
view.moveBy(0, body.height())
painter.translate(0, -body.height())
painter.drawText(view.right() - painter.fontMetrics().width(qt.QString.number(page)),
view.bottom() - painter.fontMetrics().ascent() + 5,qt.QString.number(page))
if view.top() >= richtext.height():
break
printer.newPage()
page += 1
painter.end()
except:
painter.end()
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setText("%s" % sys.exc_info()[1])
msg.exec_loop()
[docs] def getText(self):
try:
header = "Fit of %s from %s %s to %s" % (self.info['legend'],
self.info['xlabel'],
self.info['xmin'],
self.info['xmax'])
except:
# I cannot afford any unicode, key or whatever error, so,
# provide a default value for the header text.
header = 'Fit of XXXXXXXXXX from Channel XXXXX to XXXX'
text = header + "\n"
if self.specfit.fitconfig['WeightFlag']:
weight = "YES"
else:
weight = "NO"
if self.specfit.fitconfig['McaMode']:
mode = "YES"
else:
mode = "NO"
theory = self.specfit.fitconfig['fittheory']
bkg = self.specfit.fitconfig['fitbkg']
fwhm = self.specfit.fitconfig['FwhmPoints']
scaling = self.specfit.fitconfig['Yscaling']
text += "Fit Function: %s\n" % theory
text += "Background: %s\n" % bkg
text += "Weight: %s McaMode: %s FWHM: %d Yscaling: %f\n" % (weight[0],
mode[0],
fwhm,
scaling)
text += self.specfitGui.guiparameters.getText()
return text
[docs] def getConfiguration(self):
return self.specfit.configure()
[docs] def setConfiguration(self, fitconfig):
self.specfit.configure(**fitconfig)
self.specfitGui.updateGui(configuration=fitconfig)
[docs]def main():
app = qt.QApplication([])
w = ScanFit()
app.lastWindowClosed.connect(app.quit)
w.show()
app.exec_()
if __name__ == "__main__":
main()