Source code for PyMca5.PyMcaGui.pymca.ScanWindowInfoWidget
#!/usr/bin/env python
#/*##########################################################################
# 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 numpy
from PyMca5.PyMcaGui import PyMcaQt as qt
QTVERSION = qt.qVersion()
"""
This module implements an info widget containing :
- source name, scan name
- h,k,l infos
- peak, peak position
- fwhm, center of fwhm
- center of mass
"""
DEBUG=0
STATISTICS=1
[docs]class SpecArithmetic(object):
"""
This class tries to mimic SPEC operations.
Correct peak positions and fwhm information
have to be made via a fit.
"""
[docs] def search_peak(self, xdata, ydata):
"""
Search a peak and its position in arrays xdata ad ydata.
Return three integer:
- peak position
- peak value
- index of peak position in array xdata
This result may accelerate the fwhm search.
"""
ydata = numpy.array(ydata, copy=False)
ymax = ydata[numpy.isfinite(ydata)].max()
idx = self.__give_index(ymax, ydata)
return xdata[idx], ymax, idx
[docs] def search_com(self, xdata,ydata):
"""
Return the center of mass in arrays xdata and ydata
"""
num = numpy.sum(xdata*ydata)
denom = numpy.sum(ydata)
if abs(denom) > 0:
result = num/denom
else:
result = 0
return result
[docs] def search_fwhm(self, xdata,ydata,peak=None,index=None):
"""
Search a fwhm and its center in arrays xdata and ydatas.
If no fwhm is found, (0,0) is returned.
peak and index which are coming from search_peak result, may
accelerate calculation
"""
if peak is None or index is None:
x,mypeak,index_peak = self.search_peak(xdata,ydata)
else:
mypeak = peak
index_peak = index
hm = mypeak/2
idx = index_peak
try:
while ydata[idx] >= hm:
idx = idx-1
x0 = float(xdata[idx])
x1 = float(xdata[idx+1])
y0 = float(ydata[idx])
y1 = float(ydata[idx+1])
lhmx = (hm*(x1-x0) - (y0*x1)+(y1*x0)) / (y1-y0)
except ZeroDivisionError:
lhmx = 0
except IndexError:
lhmx = xdata[0]
idx = index_peak
try:
while ydata[idx] >= hm:
idx = idx+1
x0 = float(xdata[idx-1])
x1 = float(xdata[idx])
y0 = float(ydata[idx-1])
y1 = float(ydata[idx])
uhmx = (hm*(x1-x0) - (y0*x1)+(y1*x0)) / (y1-y0)
except ZeroDivisionError:
uhmx = 0
except IndexError:
uhmx = xdata[-1]
FWHM = uhmx - lhmx
CFWHM = (uhmx+lhmx)/2
return FWHM,CFWHM
def __give_index(self, elem,array):
"""
Return the index of elem in array
"""
mylist = array.tolist()
return mylist.index(elem)
[docs]class HKL(qt.QWidget):
def __init__(self, parent = None, h= "", k= "", l=""):
qt.QWidget.__init__(self, parent)
layout = qt.QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(2)
hlabel = qt.QLabel(self)
hlabel.setText('H:')
self.h = qt.QLineEdit(self)
self.h.setReadOnly(True)
width = self.h.fontMetrics().width('##.####')
self.h.setFixedWidth(width)
klabel = qt.QLabel(self)
klabel.setText('K:')
self.k = qt.QLineEdit(self)
self.k.setReadOnly(True)
self.k.setFixedWidth(width)
llabel = qt.QLabel(self)
llabel.setText('L:')
self.l = qt.QLineEdit(self)
self.l.setReadOnly(True)
self.l.setFixedWidth(width)
self.setHKL(h, k, l)
layout.addWidget(hlabel)
layout.addWidget(self.h)
layout.addWidget(klabel)
layout.addWidget(self.k)
layout.addWidget(llabel)
layout.addWidget(self.l)
[docs] def setHKL(self, h="", k="", l=""):
dformat = "%.4f"
if type(h) == type (""):
self.h.setText(h)
else:
self.h.setText(dformat % h)
if type(k) == type (""):
self.k.setText(k)
else:
self.k.setText(dformat % k)
if type(l) == type (""):
self.l.setText(l)
else:
self.l.setText(dformat % l)
[docs]class GraphInfoWidget(qt.QWidget):
def __init__(self, parent):
qt.QWidget.__init__(self, parent)
layout = qt.QGridLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(2)
#peak
peak = qt.QLabel(self)
peak.setText("Peak: ")
self.peak = qt.QLineEdit(self)
self.peak.setReadOnly(True)
hboxPeak = qt.QWidget(self)
hboxPeak.l = qt.QHBoxLayout(hboxPeak)
hboxPeak.l.setContentsMargins(0, 0, 0, 0)
hboxPeak.l.setSpacing(0)
peakAt = qt.QLabel(hboxPeak)
peakAt.setText(" at:")
self.peakAt = qt.QLineEdit(hboxPeak)
self.peak.setReadOnly(True)
hboxPeak.l.addWidget(peakAt)
hboxPeak.l.addWidget(self.peakAt)
#fwhm
fwhm = qt.QLabel(self)
fwhm.setText("Fwhm: ")
self.fwhm = qt.QLineEdit(self)
self.fwhm.setReadOnly(True)
hboxFwhm = qt.QWidget(self)
hboxFwhm.l = qt.QHBoxLayout(hboxFwhm)
hboxFwhm.l.setContentsMargins(0, 0, 0, 0)
hboxFwhm.l.setSpacing(0)
fwhmAt = qt.QLabel(hboxFwhm)
fwhmAt.setText(" at:")
self.fwhmAt = qt.QLineEdit(hboxFwhm)
self.fwhm.setReadOnly(True)
hboxFwhm.l.addWidget(fwhmAt)
hboxFwhm.l.addWidget(self.fwhmAt)
#statistics
#COM
com = qt.QLabel(self)
com.setText("COM:")
self.com = qt.QLineEdit(self)
self.com.setReadOnly(True)
#mean
mean = qt.QLabel(self)
mean.setText("Mean:")
self.mean = qt.QLineEdit(self)
self.mean.setReadOnly(True)
#STD
std = qt.QLabel(self)
std.setText("STD:")
self.std = qt.QLineEdit(self)
self.std.setReadOnly(True)
#Max
maximum = qt.QLabel(self)
maximum.setText("Max:")
self.maximum= qt.QLineEdit(self)
self.maximum.setReadOnly(True)
#mean
minimum = qt.QLabel(self)
minimum.setText("Min:")
self.minimum= qt.QLineEdit(self)
self.minimum.setReadOnly(True)
#STD
delta = qt.QLabel(self)
delta.setText("Delta:")
self.delta = qt.QLineEdit(self)
self.delta.setReadOnly(True)
layout.addWidget(peak, 0, 0)
layout.addWidget(self.peak, 0, 1)
layout.addWidget(hboxPeak, 0, 2)
layout.addWidget(com, 0, 3)
layout.addWidget(self.com, 0, 4)
layout.addWidget(mean, 0, 5)
layout.addWidget(self.mean, 0, 6)
layout.addWidget(std, 0, 7)
layout.addWidget(self.std, 0, 8)
layout.addWidget(fwhm, 1, 0)
layout.addWidget(self.fwhm, 1, 1)
layout.addWidget(hboxFwhm, 1, 2)
layout.addWidget(maximum, 1, 3)
layout.addWidget(self.maximum, 1, 4)
layout.addWidget(minimum, 1, 5)
layout.addWidget(self.minimum, 1, 6)
layout.addWidget(delta, 1, 7)
layout.addWidget(self.delta, 1, 8)
self.specArithmetic = SpecArithmetic()
[docs] def updateFromDataObject(self, dataObject):
ydata = numpy.ravel(dataObject.y[0])
ylen = len(ydata)
if ylen:
if dataObject.x is None:
xdata = numpy.arange(ylen).astype(numpy.float)
elif not len(dataObject.x):
xdata = numpy.arange(ylen).astype(numpy.float)
else:
xdata = numpy.ravel(dataObject.x[0])
else:
xdata = None
self.updateFromXY(xdata, ydata)
[docs] def updateFromXY(self, xdata, ydata):
if len(ydata):
peakpos,peak,myidx = self.specArithmetic.search_peak(xdata,ydata)
com = self.specArithmetic.search_com(xdata,ydata)
fwhm,cfwhm = self.specArithmetic.search_fwhm(xdata,ydata,
peak=peak,index=myidx)
ymax = max(ydata)
ymin = min(ydata)
ymean = sum(ydata) / len(ydata)
if len(ydata) > 1:
ystd = numpy.sqrt(sum((ydata-ymean)*(ydata-ymean))/len(ydata))
else:
ystd = 0
delta = ymax - ymin
fformat = "%.7g"
peakpos = fformat % peakpos
peak = fformat % peak
myidx = "%d" % myidx
com = fformat % com
fwhm = fformat % fwhm
cfwhm = fformat % cfwhm
ymean = fformat % ymean
ystd = fformat % ystd
ymax = fformat % ymax
ymin = fformat % ymin
delta = fformat % delta
else:
peakpos = "----"
peak = "----"
myidx = "----"
com = "----"
fwhm = "----"
cfwhm = "----"
ymean = "----"
ystd = "----"
ymax = "----"
ymin = "----"
delta = "----"
self.peak.setText(peak)
self.peakAt.setText(peakpos)
self.fwhm.setText(fwhm)
self.fwhmAt.setText(cfwhm)
self.com.setText(com)
self.mean.setText(ymean)
self.std.setText(ystd)
self.minimum.setText(ymin)
self.maximum.setText(ymax)
self.delta.setText(delta)
[docs] def getInfo(self):
ddict={}
ddict['peak'] = self.peak.text()
ddict['peakat'] = self.peakAt.text()
ddict['fwhm'] = self.fwhm.text()
ddict['fwhmat'] = self.fwhmAt.text()
ddict['com'] = self.com.text()
ddict['mean'] = self.mean.text()
ddict['std'] = self.std.text()
ddict['min'] = self.minimum.text()
ddict['max'] = self.maximum.text()
ddict['delta'] = self.delta.text()
return ddict
[docs]class ScanInfoWidget(qt.QWidget):
def __init__(self, parent = None):
qt.QWidget.__init__(self, parent)
layout = qt.QGridLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(2)
#scan info
hBox = qt.QWidget(self)
hBoxLayout = qt.QHBoxLayout(hBox)
hBoxLayout.setContentsMargins(0, 0, 0, 0)
hBoxLayout.setSpacing(0)
sourceLabel = qt.QLabel(hBox)
sourceLabel.setText('Source:')
self.sourceLabel = qt.QLineEdit(hBox)
self.sourceLabel.setReadOnly(True)
hBoxLayout.addWidget(sourceLabel)
hBoxLayout.addWidget(self.sourceLabel)
scanLabel = qt.QLabel(self)
scanLabel.setText('Scan: ')
self.scanLabel = qt.QLineEdit(self)
self.scanLabel.setReadOnly(True)
self.hkl = HKL(self)
layout.addWidget(hBox, 0, 0, 1, 7)
#layout.addWidget(self.sourceLabel, 0, 1)#, 1, 9)
layout.addWidget(scanLabel, 1, 0)
layout.addWidget(self.scanLabel, 1, 1)
layout.addWidget(self.hkl, 1, 4, 1, 3)
[docs] def updateFromDataObject(self, dataObject):
info = dataObject.info
source = info.get('SourceName', None)
if source is None:
self.sourceLabel.setText("")
else:
if type(source) == type(""):
self.sourceLabel.setText(source)
else:
self.sourceLabel.setText(source[0])
scan = info.get('Header', None)
if scan is None:
scan = ""
if "envdict" in info:
scan = info["envdict"].get('title', "")
self.scanLabel.setText(scan)
else:
self.scanLabel.setText(scan[0])
hkl = info.get('hkl', None)
if hkl is None:
self.hkl.setHKL("----", "----", "----")
else:
self.hkl.setHKL(*hkl)
[docs] def getInfo(self):
ddict = {}
ddict['source'] = self.sourceLabel.text()
ddict['scan'] = self.scanLabel.text()
ddict['hkl'] = ["%s" % self.hkl.h.text(),
"%s" % self.hkl.k.text(),
"%s" % self.hkl.l.text()]
return ddict
[docs]class ScanWindowInfoWidget(qt.QWidget):
def __init__(self, parent = None):
qt.QWidget.__init__(self, parent)
layout = qt.QVBoxLayout(self)
layout.setContentsMargins(2, 2, 2, 2)
layout.setSpacing(2)
self.scanInfo = ScanInfoWidget(self)
self.graphInfo = GraphInfoWidget(self)
layout.addWidget(self.scanInfo)
layout.addWidget(self.graphInfo)
#print "hiding graph info"
#self.graphInfo.hide()
[docs] def updateFromDataObject(self, dataObject):
self.scanInfo.updateFromDataObject(dataObject)
self.graphInfo.updateFromDataObject(dataObject)
[docs] def getInfo(self):
ddict = {}
ddict['scan'] = self.scanInfo.getInfo()
ddict['graph'] = self.graphInfo.getInfo()
return ddict
[docs]def test():
app = qt.QApplication([])
w = ScanWindowInfoWidget()
app.lastWindowClosed.connect(app.quit)
"""
winfo.grid(sticky='wesn')
if STATISTICS:
winfo.configure(h=65,k=45621,l=32132,peak=6666876,
fwhm=0.2154,com=544,
ymax=10.,ymin=4,ystd=1,ymean=5)
else:
winfo.configure(h=65,k=45621,l=32132,peak=6666876,
fwhm=0.2154,com=544)
"""
w.show()
app.exec_()
if __name__ == '__main__':
test()