#!/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 os
import sys
import time
from . import McaCustomEvent
from PyMca5.PyMcaIO import ConfigDict
ROIWIDTH = 250.
from PyMca5.PyMcaGui import PyMcaQt as qt
[docs]class Fit2SpecGUI(qt.QWidget):
def __init__(self,parent=None,name="Fit to Spec Conversion",
filelist=None,outputdir=None, actions=0):
qt.QWidget.__init__(self,parent,name)
layout = qt.QVBoxLayout(self)
layout.setAutoAdd(1)
self.setCaption(name)
self.__build(actions)
if filelist is None: filelist = []
self.outputDir = None
self.setFileList(filelist)
self.setOutputDir(outputdir)
def __build(self,actions):
self.__grid= qt.QWidget(self)
#self.__grid.setGeometry(qt.QRect(30,30,288,156))
grid = qt.QGridLayout(self.__grid,2,3,11,6)
grid.setColStretch(0,0)
grid.setColStretch(1,1)
grid.setColStretch(2,0)
#input list
listrow = 0
listlabel = qt.QLabel(self.__grid)
listlabel.setText("Input File list:")
listlabel.setAlignment(qt.QLabel.WordBreak | qt.QLabel.AlignVCenter)
self.__listView = qt.QTextView(self.__grid)
self.__listView.setMaximumHeight(30*listlabel.sizeHint().height())
self.__listButton = qt.QPushButton(self.__grid)
self.__listButton.setText('Browse')
self.__listButton.clicked.connect(self.browseList)
grid.addWidget(listlabel, listrow, 0, qt.Qt.AlignTop|qt.Qt.AlignLeft)
grid.addWidget(self.__listView, listrow, 1)
grid.addWidget(self.__listButton,listrow, 2, qt.Qt.AlignTop|qt.Qt.AlignRight)
#output dir
outrow = 1
outlabel = qt.QLabel(self.__grid)
outlabel.setText("Output dir:")
outlabel.setAlignment(qt.QLabel.WordBreak | qt.QLabel.AlignVCenter)
self.__outLine = qt.QLineEdit(self.__grid)
self.__outLine.setReadOnly(True)
#self.__outLine.setSizePolicy(qt.QSizePolicy(qt.QSizePolicy.Maximum, qt.QSizePolicy.Fixed))
self.__outButton = qt.QPushButton(self.__grid)
self.__outButton.setText('Browse')
self.__outButton.clicked.connect(self.browseOutputDir)
grid.addWidget(outlabel, outrow, 0, qt.Qt.AlignLeft)
grid.addWidget(self.__outLine, outrow, 1)
grid.addWidget(self.__outButton, outrow, 2, qt.Qt.AlignLeft)
if actions: self.__buildActions()
def __buildActions(self):
box = qt.QHBox(self)
qt.HorizontalSpacer(box)
self.__dismissButton = qt.QPushButton(box)
qt.HorizontalSpacer(box)
self.__dismissButton.setText("Close")
self.__startButton = qt.QPushButton(box)
qt.HorizontalSpacer(box)
self.__startButton.setText("Start")
self.__dismissButton.clicked.connect(self.close)
self.__startButton.clicked.connect(self.start)
[docs] def setFileList(self,filelist=None):
if filelist is None:
filelist = []
if True or self.__goodFileList(filelist):
text = ""
filelist.sort()
for ffile in filelist:
text += "%s\n" % ffile
self.fileList = filelist
self.__listView.setText(text)
[docs] def setOutputDir(self,outputdir=None):
if outputdir is None:return
if self.__goodOutputDir(outputdir):
self.outputDir = outputdir
self.__outLine.setText(outputdir)
else:
qt.QMessageBox.critical(self, "ERROR",
"Cannot use output directory:\n%s"% (outputdir))
def __goodFileList(self,filelist):
if not len(filelist):return True
for file in filelist:
if not os.path.exists(file):
qt.QMessageBox.critical(self, "ERROR",'File %s\ndoes not exists' % file)
self.raiseW()
return False
return True
def __goodOutputDir(self,outputdir):
if os.path.isdir(outputdir):return True
else:return False
[docs] def browseList(self):
filedialog = qt.QFileDialog(self,"Open a set of files",1)
filedialog.setMode(filedialog.ExistingFiles)
filedialog.setFilters("Fit Files (*.fit)\n")
if filedialog.exec_loop() == qt.QDialog.Accepted:
filelist0= filedialog.selectedFiles()
else:
self.raiseW()
return
filelist = []
for f in filelist0:
filelist.append(qt.safe_str(f))
if len(filelist):self.setFileList(filelist)
self.raiseW()
[docs] def browseConfig(self):
filename= qt.QFileDialog(self,"Open a new fit config file",1)
filename.setMode(filename.ExistingFiles)
filename.setFilters("Config Files (*.cfg)\nAll files (*)")
if filename.exec_loop() == qt.QDialog.Accepted:
filename = filename.selectedFile()
else:
self.raiseW()
return
filename = qt.safe_str(filename)
if len(filename):
self.setConfigFile(filename)
self.raiseW()
[docs] def browseOutputDir(self):
outfile = qt.QFileDialog(self,"Output Directory Selection",1)
outfile.setMode(outfile.DirectoryOnly)
ret = outfile.exec_loop()
if ret:
outdir = qt.safe_str(outfile.selectedFile())
outfile.close()
del outfile
self.setOutputDir(outdir)
else:
outfile.close()
del outfile
self.raiseW()
[docs] def start(self):
if not len(self.fileList):
qt.QMessageBox.critical(self, "ERROR",'Empty file list')
self.raiseW()
return
if (self.outputDir is None) or (not self.__goodOutputDir(self.outputDir)):
qt.QMessageBox.critical(self, "ERROR",'Invalid output directory')
self.raiseW()
return
name = "Batch from %s to %s " % (os.path.basename(self.fileList[ 0]),
os.path.basename(self.fileList[-1]))
window = Fit2SpecWindow(name="Fit 2 Spec "+name,actions=1)
b = Fit2SpecBatch(window,self.fileList,self.outputDir)
def cleanup():
b.pleasePause = 0
b.pleaseBreak = 1
b.wait()
qApp = qt.QApplication.instance()
qApp.processEvents()
def pause():
if b.pleasePause:
b.pleasePause=0
window.pauseButton.setText("Pause")
else:
b.pleasePause=1
window.pauseButton.setText("Continue")
window.pauseButton.clicked.connect(pause)
window.abortButton.clicked.connect(window.close)
qApp = qt.QApplication.instance()
qApp.aboutToQuit.connect(cleanup)
self.__window = window
self.__b = b
window.show()
b.start()
[docs]class Fit2SpecBatch(qt.QThread):
def __init__(self, parent, filelist=None, outputdir = None):
self._filelist = filelist
self.outputdir = outputdir
qt.QThread.__init__(self)
self.parent = parent
self.pleasePause = 0
[docs] def processList(self):
for fitfile in self._filelist:
self.onNewFile(fitfile, self._filelist)
d = ConfigDict.ConfigDict()
d.read(fitfile)
f = open(os.path.join(self.outputdir,os.path.basename(fitfile)+".dat"),'w+')
npoints = len(d['result']['xdata'])
f.write("\n")
f.write("#S 1 %s\n" % fitfile)
i=0
for parameter in d['result']['parameters']:
f.write("#U%d %s %.6g +/- %.3g\n" % (i, parameter,
d['result']['fittedpar'][i],
d['result']['sigmapar'][i]))
i+=1
f.write("#N 6\n")
f.write("#L Energy channel counts fit continuum pileup\n")
for i in range(npoints):
f.write("%.6g %.6g %.6g %.6g %.6g %.6g\n" % (d['result']['energy'][i],
d['result']['xdata'][i],
d['result']['ydata'][i],
d['result']['yfit'][i],
d['result']['continuum'][i],
d['result']['pileup'][i]))
f.close()
self.onEnd()
[docs] def run(self):
self.processList()
[docs] def onNewFile(self, file, filelist):
self.postEvent(self.parent, McaCustomEvent.McaCustomEvent({'file':file,
'filelist':filelist,
'event':'onNewFile'}))
if self.pleasePause:self.__pauseMethod()
[docs] def onEnd(self):
self.postEvent(self.parent, McaCustomEvent.McaCustomEvent({'event':'onEnd'}))
if self.pleasePause:self.__pauseMethod()
def __pauseMethod(self):
self.postEvent(self.parent, McaCustomEvent.McaCustomEvent({'event':'batchPaused'}))
while(self.pleasePause):
time.sleep(1)
self.postEvent(self.parent, McaCustomEvent.McaCustomEvent({'event':'batchResumed'}))
[docs]class Fit2SpecWindow(qt.QWidget):
def __init__(self,parent=None, name="BatchWindow", fl=0, actions = 0):
qt.QWidget.__init__(self, parent, name, fl)
self.setCaption(name)
self.l = qt.QVBoxLayout(self)
self.l.setAutoAdd(1)
self.bars =qt.QWidget(self)
self.barsLayout = qt.QGridLayout(self.bars,2,3)
self.progressBar = qt.QProgressBar(self.bars)
self.progressLabel = qt.QLabel(self.bars)
self.progressLabel.setText('File Progress:')
self.barsLayout.addWidget(self.progressLabel,0,0)
self.barsLayout.addWidget(self.progressBar,0,1)
self.status = qt.QLabel(self)
self.status.setText(" ")
self.timeLeft = qt.QLabel(self)
self.timeLeft.setText("Estimated time left = ???? min")
self.time0 = None
if actions: self.addButtons()
self.show()
self.raiseW()
[docs] def customEvent(self,event):
if event.dict['event'] == 'onNewFile':self.onNewFile(event.dict['file'],
event.dict['filelist'])
elif event.dict['event'] == 'onEnd': self.onEnd(event.dict)
elif event.dict['event'] == 'batchPaused': self.onPause()
elif event.dict['event'] == 'batchResumed':self.onResume()
else:
print("Unhandled event",event)
[docs] def onNewFile(self, file, filelist):
indexlist = range(0,len(filelist))
index = indexlist.index(filelist.index(file))
nfiles = len(indexlist)
self.status.setText("Processing file %s" % file)
e = time.time()
self.progressBar.setTotalSteps(nfiles)
self.progressBar.setProgress(index)
if self.time0 is not None:
t = (e - self.time0) * (nfiles - index)
self.time0 =e
if t < 120:
self.timeLeft.setText("Estimated time left = %d sec" % (t))
else:
self.timeLeft.setText("Estimated time left = %d min" % (int(t / 60.)))
else:
self.time0 = e
[docs] def onEnd(self,dict):
n = self.progressBar.progress()
self.progressBar.setProgress(n+1)
self.status.setText ("Batch Finished")
self.timeLeft.setText("Estimated time left = 0 sec")
if self.actions:
self.pauseButton.hide()
self.abortButton.setText("OK")
[docs] def onPause(self):
pass
[docs] def onResume(self):
pass
if __name__ == "__main__":
import getopt
options = 'f'
longoptions = ['outdir=', 'listfile=']
filelist = None
outdir = None
listfile = None
opts, args = getopt.getopt(
sys.argv[1:],
options,
longoptions)
for opt,arg in opts:
if opt in ('--outdir'):
outdir = arg
elif opt in ('--listfile'):
listfile = arg
if listfile is None:
filelist=[]
for item in args:
filelist.append(item)
else:
fd = open(listfile)
filelist = fd.readlines()
fd.close()
for i in range(len(filelist)):
filelist[i]=filelist[i].replace('\n','')
app=qt.QApplication(sys.argv)
winpalette = qt.QPalette(qt.QColor(230,240,249),qt.QColor(238,234,238))
app.setPalette(winpalette)
app.lastWindowClosed.conenct(app.quit)
if len(filelist) == 0:
w = Fit2SpecGUI(actions=1)
app.setMainWidget(w)
w.show()
app.exec_()
else:
text = "Batch from %s to %s" % (os.path.basename(filelist[0]), os.path.basename(filelist[-1]))
window = Fit2SpecWindow(name=text,actions=1)
b = Fit2SpecBatch(window,filelist,outdir)
def cleanup():
b.pleasePause = 0
b.pleaseBreak = 1
b.wait()
qApp = qt.QApplication.instance()
qApp.processEvents()
def pause():
if b.pleasePause:
b.pleasePause=0
window.pauseButton.setText("Pause")
else:
b.pleasePause=1
window.pauseButton.setText("Continue")
window.pauseButton.clicked.connect(pause)
window.abortButton.clicked.connect(window.close)
app.aboutToQuit.connect(cleanup)
window.show()
b.start()
app.setMainWidget(window)
app.exec_()
# PyMcaBatch.py --cfg=/mntdirect/_bliss/users/sole/COTTE/WithLead.cfg --outdir=/tmp/ /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0007.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0008.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0009.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0010.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0011.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0012.edf /mntdirect/_bliss/users/sole/COTTE/ch09/ch09__mca_0003_0000_0013.edf &
# PyMcaBatch.exe --cfg=E:/COTTE/WithLead.cfg --outdir=C:/tmp/ E:/COTTE/ch09/ch09__mca_0003_0000_0007.edf E:/COTTE/ch09/ch09__mca_0003_0000_0008.edf