Source code for PyMca5.PyMcaGui.physics.xrf.PeakTableWidget
#/*##########################################################################
#
# The PyMca X-Ray Fluorescence Toolkit
#
# Copyright (c) 2004-2014 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. Armando Sole - ESRF Data Analysis"
__contact__ = "sole@esrf.fr"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
import sys
from PyMca5.PyMcaGui import PyMcaQt as qt
if hasattr(qt, "QStringList"):
QStringList = qt.QStringList
else:
if hasattr(qt, "QString"):
QString = qt.QString
else:
QString = str
from PyMca5.PyMcaPhysics import Elements
DEBUG=0
QTable = qt.QTableWidget
[docs]class QComboTableItem(qt.QComboBox):
sigCellChanged = qt.pyqtSignal(int,int)
def __init__(self, parent=None, row = None, col = None):
self._row = row
self._col = col
qt.QComboBox.__init__(self,parent)
self.activated[int].connect(self._cellChanged)
def _cellChanged(self, idx):
if DEBUG:
print("cell changed",idx)
self.sigCellChanged.emit(self._row, self._col)
[docs]class QCheckBoxItem(qt.QCheckBox):
sigCellChanged = qt.pyqtSignal(int, int)
def __init__(self, parent=None, row = None, col = None):
self._row = row
self._col = col
qt.QCheckBox.__init__(self,parent)
self.clicked.connect(self._cellChanged)
def _cellChanged(self):
self.sigCellChanged.emit(self._row, self._col)
[docs]class PeakTableWidget(QTable):
sigPeakTableWidgetSignal = qt.pyqtSignal(object)
def __init__(self, *args,**kw):
QTable.__init__(self, *args)
self.setRowCount(0)
self.labels=['Peak','Channel','Element','Line',
'Energy','Use','Calc. Energy']
self.setColumnCount(len(self.labels))
if 'labels' in kw:
self.labels = kw['labels']
for i in range(len(self.labels)):
item = self.horizontalHeaderItem(i)
if item is None:
item = qt.QTableWidgetItem(self.labels[i],
qt.QTableWidgetItem.Type)
item.setText(self.labels[i])
self.setHorizontalHeaderItem(i,item)
self.peaks={}
self.peaklist=[]
if 'peaklist' in kw:
self.peaklist = kw['peaklist']
self.build()
self.cellChanged[int,int].connect(self.myslot)
rheight = self.horizontalHeader().sizeHint().height()
for idx in range(self.rowCount()):
self.setRowHeight(idx, rheight)
[docs] def build(self):
line = 1
oldlist=list(self.peaklist)
self.peaklist=[]
for peak in oldlist:
self.newpeakline(peak,line)
line=line+1
self.resizeColumnToContents(0)
#self.resizeColumnToContents(1)
#self.resizeColumnToContents(2)
self.resizeColumnToContents(5)
#get current number of lines
nlines=self.rowCount()
#if the number of lines is smaller than line resize table
if (line > nlines):
self.setRowCount(line)
linew=line-1
self.peaks[peak]={ 'line':linew,
'fields':['number',
'channel',
'element',
'elementline',
'setenergy',
'use',
'calenergy'],
'number': QString('1'),
'channel': QString('0'),
'element': QString('-'),
'elementline':QString('-'),
'setenergy': QString('0'),
'use': 0,
'calenergy': QString()}
self.peaklist.append(peak)
self.setReadWrite(peak,'setenergy')
self.setReadWrite(peak,'channel')
self.setReadOnly (peak,['number','line','calenergy'])
col = self.peaks[peak]['fields'].index('element')
self.peaks[peak]['element_item']=QPeriodicComboTableItem(self,
row = linew, col= col)
self.setCellWidget(linew,
col,
self.peaks[peak]['element_item'])
self.peaks[peak]['element_item'].sigCellChanged[int,int].connect( \
self.myslot)
a = QStringList()
a.append('-')
col = self.peaks[peak]['fields'].index('elementline')
self.peaks[peak]['elementline_item']= QComboTableItem(self,
row = linew,
col = col)
self.peaks[peak]['elementline_item'].addItems(a)
self.setCellWidget(linew,
col,
self.peaks[peak]['elementline_item'])
self.peaks[peak]['elementline_item'].sigCellChanged[int,int].connect( \
self.myslot)
col = self.peaks[peak]['fields'].index('use')
self.peaks[peak]['use_item'] = QCheckBoxItem(self,
row = linew,
col = col)
self.peaks[peak]['use_item'].setText("")
self.setCellWidget(linew, col,
self.peaks[peak]['use_item'])
self.peaks[peak]['use_item'].sigCellChanged[int,int].connect( \
self.myslot)
self.peaks[peak]['use_item'].setChecked(self.peaks[peak]['use'])
[docs] def myslot(self, row, col):
if DEBUG:
print("Passing by myslot",
self.peaks[self.peaklist[row]]['fields'][col])
peak=self.peaklist[row]
field=self.peaks[peak]['fields'][col]
if (field == "element") or (field == "elementline"):
key = field+"_item"
newvalue=self.peaks[peak][key].currentText()
elif field == "use":
pass
else:
newvalue = self.item(row, col).text()
if field == "element":
if str(newvalue) == '-':
#no element
#set line to -
options = QStringList()
options.append('-')
self.peaks[peak]["elementline_item"].insertItems(0, options)
self.peaks[peak]["elementline_item"].setCurrentIndex(0)
else:
#get the emission energies
ele = str(newvalue).split()[0]
options = QStringList()
energies = QStringList()
options.append('-')
energies.append('0.000')
emax = 0.0
for rays in Elements.Element[ele]['rays']:
for transition in Elements.Element[ele][rays]:
options.append("%s (%.5f)" % (transition,
Elements.Element[ele][transition]['rate']))
energies.append("%.5f " % (Elements.Element[ele][transition]['energy']))
emax = max(emax,Elements.Element[ele][transition]['rate'])
energies[0] = "%.5f " % emax
#lineitem=qttable.QComboTableItem(self,options)
self.peaks[peak]["elementline_item"].insertItems(0, options)
self.peaks[peak]["elementline_item"].setCurrentIndex(0)
#self.setItem(row,
# col+1,
# lineitem)
self.peaks[peak][field] = newvalue
if field == "elementline":
if str(newvalue) == '-':
#no element
#set energy to rw
self.setReadWrite(peak,'setenergy')
else:
#get the element energy
#newvalue=QString(self.text(row,col-1))
elevalue=self.peaks[peak]["element_item"].currentText()
ele = str(elevalue).split()[0]
energy = "0.0"
for rays in Elements.Element[ele]['rays']:
for transition in Elements.Element[ele][rays]:
option = QString("%s (%.5f)" % (transition,
Elements.Element[ele][transition]['rate']))
if option == newvalue:
energy = "%.5f " % (Elements.Element[ele][transition]['energy'])
break
if energy == "0.0":
print("Something is wrong")
else:
self.configure(name=peak,setenergy=energy)
self.setReadOnly(peak,'setenergy')
self.peaks[peak][field] = newvalue
if field == "setenergy":
oldvalue = self.peaks[peak]["setenergy"]
try:
value = float(str(newvalue))
except:
print(field, " newvalue = ", newvalue, "taking old value", oldvalue)
item = self.item(row, col)
item.setText("%s" % oldvalue)
value = float(str(oldvalue))
self.peaks[peak][field] = value
ddict={}
ddict['event'] = 'use'
self.sigPeakTableWidgetSignal.emit(ddict)
if field == "channel":
oldvalue = self.peaks[peak]["channel"]
try:
value = float(str(newvalue))
except:
print(field, " newvalue = ", newvalue, "taking old value", oldvalue)
item = self.item(row, col)
item.setText("%s" % oldvalue)
value = float(str(oldvalue))
self.peaks[peak][field] = value
ddict={}
ddict['event'] = 'use'
self.sigPeakTableWidgetSignal.emit(ddict)
if field == "use":
if self.peaks[peak][field+"_item"].isChecked():
self.peaks[peak][field] = 1
else:
self.peaks[peak][field] = 0
ddict={}
ddict['event'] = 'use'
self.sigPeakTableWidgetSignal.emit(ddict)
[docs] def setReadOnly(self,parameter,fields):
if DEBUG:
print("peak ",parameter,"fields = ",fields,"asked to be read only")
self.setfield(parameter, fields,
qt.Qt.ItemIsSelectable|qt.Qt.ItemIsEnabled)
[docs] def setReadWrite(self,parameter,fields):
if DEBUG:
print("peak ",parameter,"fields = ",fields,"asked to be read write")
self.setfield(parameter, fields,
qt.Qt.ItemIsEditable|qt.Qt.ItemIsSelectable|qt.Qt.ItemIsEnabled)
[docs] def setfield(self,peak,fields,EditType):
if DEBUG:
print("setfield. peak =",peak,"fields = ",fields)
if type(peak) == type (()) or \
type(peak) == type ([]):
peaklist=peak
else:
peaklist=[peak]
if type(fields) == type (()) or \
type(fields) == type ([]):
fieldlist=fields
else:
fieldlist=[fields]
for peak in peaklist:
if peak in self.peaklist:
try:
row=self.peaklist.index(peak)
except ValueError:
row=-1
if row >= 0:
for field in fieldlist:
if field in self.peaks[peak]['fields']:
col=self.peaks[peak]['fields'].index(field)
if (field != 'element') and (field != 'elementline'):
key=field+"_item"
item = self.item(row, col)
text = "%s" % self.peaks[peak][field]
if item is None:
item = qt.QTableWidgetItem(text,
qt.QTableWidgetItem.Type)
self.setItem(row, col, item)
else:
item.setText(str(text))
item.setFlags(EditType)
[docs] def configure(self,*vars,**kw):
if DEBUG:
print("configure called with **kw = ",kw)
print("configure called with *vars = ",vars)
name=None
error=0
if 'name' in kw:
name=kw['name']
elif 'number' in kw:
name=kw['number']
else:
return 1
keylist = []
if "channel" in kw:
keylist=["channel"]
for key in kw.keys():
if key != "setenergy":
if key not in keylist:
keylist.append(key)
if "setenergy" in kw.keys():
keylist.append("setenergy")
if name in self.peaks:
row=self.peaks[name]['line']
for key in keylist:
if key is not 'name':
if key in self.peaks[name]['fields']:
col=self.peaks[name]['fields'].index(key)
oldvalue=self.peaks[name][key]
if key is 'code':
newvalue = QString(str(kw[key]))
elif key is 'element':
newvalue = str(kw[key]).split()[0]
if newvalue == "-":
self.peaks[name][key+"_item"].setCurrentIndex(0)
else:
self.peaks[name][key+"_item"].setSelection(newvalue)
try:
self.myslot(row,col)
except:
print("Error setting element")
elif key is 'elementline':
try:
iv = self.peaks[name][key+"_item"].findText(QString(kw[key]))
self.peaks[name][key+"_item"].setCurrentIndex(iv)
except:
print("Error setting elementline")
elif key is 'use':
if kw[key]:
self.peaks[name][key] = 1
else:
self.peaks[name][key] = 0
self.peaks[name][key+"_item"].setChecked(self.peaks[name][key])
elif key == 'number':
if len(str(kw[key])):
newvalue=float(str(kw[key]))
newvalue= QString("%3d" % newvalue)
self.peaks[name][key]=newvalue
else:
self.peaks[name][key]=oldvalue
text = self.peaks[name][key]
item = self.item(row, col)
if item is None:
item = qt.QTableWidgetItem(text,
qt.QTableWidgetItem.Type)
self.setItem(row, col, item)
else:
item.setText(text)
elif key == 'channel':
if DEBUG:
print("setting channel in configure")
if len(str(kw[key])):
newvalue=float(str(kw[key]))
newvalue= QString("%.3f" % newvalue)
self.peaks[name][key]=newvalue
else:
self.peaks[name][key]=oldvalue
text = self.peaks[name][key]
item = self.item(row, col)
if item is None:
item = qt.QTableWidgetItem(text,
qt.QTableWidgetItem.Type)
self.setItem(row, col, item)
else:
item.setText(text)
elif (key == 'setenergy') or (key == 'calenergy'):
if len(str(kw[key])):
newvalue=float(str(kw[key]))
newvalue= QString("%.4f" % newvalue)
self.peaks[name][key]=newvalue
else:
self.peaks[name][key]=oldvalue
text = self.peaks[name][key]
item = self.item(row, col)
if item is None:
item = qt.QTableWidgetItem(text,
qt.QTableWidgetItem.Type)
self.setItem(row, col, item)
else:
item.setText(text)
#self.myslot(row,col)
else:
if len(str(kw[key])):
newvalue=float(str(kw[key]))
if key is 'sigma':
newvalue= "%6.3g" % newvalue
else:
newvalue= "%8g" % newvalue
else:
newvalue=""
newvalue=QString(newvalue)
return error
[docs] def validate(self,name,key,oldvalue,newvalue):
if (key == 'setenergy') or (key == 'number') or (key == 'calcenergy'):
try:
float(str(newvalue))
except:
return 0
return 1
[docs] def getdict(self, *var):
print("PeakTableWidget.getdict deprecated. Use getDict")
return self.getDict(*var)
[docs] def getDict(self,*var):
ddict={}
if len(var) == 0:
#asked for the dict of dicts
for peak in self.peaks.keys():
ddict[peak] = {}
ddict[peak]['number'] = float(str(self.peaks[peak]['number']))
ddict[peak]['channel'] = float(str(self.peaks[peak]['channel']))
ddict[peak]['element'] = str(self.peaks[peak]['element'])
ddict[peak]['elementline'] = str(self.peaks[peak]['elementline'])
ddict[peak]['setenergy'] = float(str(self.peaks[peak]['setenergy']))
ddict[peak]['use'] = self.peaks[peak]['use']
if len(str(self.peaks[peak]['calenergy'])):
ddict[peak]['calenergy'] = float(str(self.peaks[peak]['calenergy']))
else:
ddict[peak]['calenergy'] = ""
else:
peak=var[0]
if peak in self.peaks.keys():
ddict['number'] = float(str(self.peaks[peak]['number']))
ddict['channel'] = float(str(self.peaks[peak]['channel']))
ddict['element'] = str(self.peaks[peak]['element'])
ddict['elementline'] = str(self.peaks[peak]['elementline'])
ddict['setenergy'] = float(str(self.peaks[peak]['setenergy']))
ddict['use'] = self.peaks[peak]['use']
if len(str(self.peaks[peak]['calenergy'])):
ddict['calenergy'] = float(str(self.peaks[peak]['calenergy']))
else:
ddict['calenergy'] = ""
return ddict
[docs]class QPeriodicComboTableItem(QComboTableItem):
""" Periodic Table Combo List to be used in a QTable
Init options:
table (mandatory)= parent QTable
addnone= 1 (default) add "-" in the list to provide possibility
to select no specific element.
0 only element list.
detailed= 1 (default) display element symbol, Z and name
0 display only element symbol and Z
Public methods:
setSelection(eltsymbol):
Set the element selected given its symbol
getSelection():
Return symbol of element selected
Signals:
sigValueChanged(int,int)
"""
sigValueChanged = qt.pyqtSignal(int, int)
def __init__(self, table=None, addnone=1, detailed=0, row=None, col=None):
strlist = QStringList()
self.addnone= (addnone==1)
if self.addnone: strlist.append("-")
for (symbol, Z, x, y, name, mass, density) in Elements.ElementsInfo:
if detailed: txt= "%2s (%d) - %s"%(symbol, Z, name)
else: txt= "%2s (%d)"%(symbol, Z)
strlist.append(txt)
if row is None:
row = 0
if col is None:
col = 0
self._row = row
self._col = col
qt.QComboBox.__init__(self)
self.addItems(strlist)
self.activated[int].connect(self._cellChanged)
def _cellChanged(self, idx):
self.sigCellChanged.emit(self._row, self._col)
[docs] def setSelection(self, symbol=None):
if symbol is None:
if self.addnone:
self.setCurrentIndex(0)
else:
idx= self.addnone+Elements.getz(symbol)-1
self.setCurrentIndex(idx)
[docs] def getSelection(self):
idx = self.currentIndex()
if self.addnone and not idx:
return None
else:
return Elements.ElementList[idx - self.addnone]
[docs]def main(args):
app=qt.QApplication(args)
win=qt.QMainWindow()
#tab = Parameters(labels=['Parameter','Estimation','Fit Value','Sigma',
# 'Restrains','Min/Parame','Max/Factor/Delta/'],
# paramlist=['Height','Position','FWHM'])
tab = PeakTableWidget(labels= ['Peak','Channel','Element','Line','Set Energy','Use',
'Cal. Energy'],
peaklist=['1'])
tab.showGrid()
tab.configure(name='1',number=24,channel='1234',use=1,
setenergy=12.5,calenergy=24.0)
tab.show()
app.exec_()
if __name__=="__main__":
main(sys.argv)