#/*##########################################################################
#
# The PyMca X-Ray Fluorescence Toolkit
#
# Copyright (c) 2004-2016 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
import tempfile
import subprocess
import time
import shutil
from PyMca5.PyMcaIO import ConfigDict
from . import XMSOParser
getXMSOFileFluorescenceInformation =\
XMSOParser.getXMSOFileFluorescenceInformation
XMIMSIM_PYMCA = None
if sys.platform == "win32":
try:
# try to get the installation directory from the registry
if sys.version < '3.0':
import _winreg as winreg
else:
import winreg
HKLM = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
try:
# 32 bit
softwareKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "Software\XMI-MSIM")
except:
try:
# 64 bit
softwareKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "Software\Wow6432Node\XMI-MSIM")
except:
# XMI-MSIM not installed ...
softwareKey = None
if softwareKey is not None:
subKeyName = "InstallationDirectory"
value = winreg.QueryValueEx(softwareKey, subKeyName)
pathToExecutable = os.path.join(value[0], "bin", "xmimsim-pymca.exe")
if not os.path.exists(pathToExecutable):
pathToExecutable = None
XMIMSIM_PYMCA = pathToExecutable
except:
# this cannot afford failing
pass
else:
try:
testDirectories = ["/Applications", "/usr/local/bin", "/usr/bin", os.getcwd()]
#look in the user PATH
path = os.getenv('PATH')
if path is not None:
testDirectories += path.split(":")
scriptName = "xmimsim-pymca"
if sys.platform == "darwin":
scriptName = os.path.join("XMI-MSIM.app",
"Contents",
"Resources",
scriptName)
for dirName in testDirectories:
pathToExecutable = os.path.join(dirName, scriptName)
if not os.path.exists(pathToExecutable):
pathToExecutable = None
else:
break
XMIMSIM_PYMCA = pathToExecutable
except:
# this cannot afford failing
pass
[docs]def getScriptFile(pathToExecutable=None, args=None, name=None):
if pathToExecutable is None:
pathToExecutable = XMIMSIM_PYMCA
if pathToExecutable is None:
raise ValueError("Path to xmimsim-pymca needed")
if not os.path.exists(pathToExecutable):
raise IOError("xmimsim-pymca executable does not exist")
if args is None:
args = []
executable = os.path.basename(pathToExecutable)
if not executable.startswith("xmimsim-pymca"):
if sys.platform == "win32":
raise ValueError("Path to xmimsim-pymca.exe needed")
else:
raise ValueError("Path to xmimsim-pymca needed")
xmimsim_directory = os.path.dirname(pathToExecutable)
if os.path.basename(xmimsim_directory).lower() == "bin":
xmimsim_directory = os.path.dirname(xmimsim_directory)
if sys.platform == "win32":
binDir = os.path.join(xmimsim_directory, "bin")
libDir = os.path.join(xmimsim_directory, "lib")
gtk2Dir = os.path.join(xmimsim_directory, "GTK2")
path = os.getenv("PATH")
txt = "echo off\n"
txt += "set PATH=%s;%s;%s;%s\n" % (binDir, libDir, gtk2Dir, os.getenv("PATH"))
txt += "%s " % executable
if len(args):
for arg in args:
txt += arg + " ";
txt += "\n"
else:
txt += "%*"
if name is None:
handle, fullPath = tempfile.mkstemp(suffix=".bat", prefix="pymca", text=False)
os.write(handle, txt)
os.close(handle)
else:
fullPath = name
if not fullPath.endswith(".bat"):
fullPath = name + ".bat"
if sys.version < '3.0':
f = open(fullPath, "wb")
else:
f = open(fullPath, "w", newline='')
f.write(txt)
f.close()
elif sys.platform == "darwin":
#the bundle has everything needed
txt = "#!/bin/bash\n"
#this line is critical in order to avoid interference by the bundled PyMca
txt += 'DYLD_LIBRARY_PATH=""\n'
txt += "%s " % pathToExecutable
if len(args):
for arg in args:
txt += arg + " ";
txt += "\n"
else:
txt += "$*"
if name is None:
handle, fullPath = tempfile.mkstemp(suffix=".sh", prefix="pymca", text=False)
os.write(handle, txt)
os.close(handle)
else:
fullPath = name
if not fullPath.endswith(".sh"):
fullPath = name + ".sh"
f = open(fullPath, "wb")
f.write(txt)
f.close()
os.system("chmod +x %s" % fullPath)
else:
binDir = xmimsim_directory
libDir = os.path.join(xmimsim_directory, "lib")
path = os.getenv("PATH")
txt = "#!/bin/bash\n"
txt += "export PATH=%s:%s:%s\n" % (binDir, libDir, os.getenv("PATH"))
txt += "%s " % executable
if len(args):
for arg in args:
txt += arg + " ";
txt += "\n"
else:
txt += "$*"
if name is None:
handle, fullPath = tempfile.mkstemp(suffix=".sh", prefix="pymca", text=False)
os.write(handle, txt)
os.close(handle)
else:
fullPath = name
if not fullPath.endswith(".sh"):
fullPath = name + ".sh"
f = open(fullPath, "wb")
f.write(txt)
f.close()
os.system("chmod +x %s" % fullPath)
return fullPath
[docs]def getOutputFileNames(fitFile, outputDir=None):
if outputDir is None:
outputDir = os.path.dirname(fitFile)
ddict = {}
newFile = os.path.join(outputDir, os.path.basename(fitFile))
if newFile.lower().endswith(".fit"):
rootName = newFile[:-4]
elif newFile.lower().endswith(".cfg"):
rootName = newFile[:-4]
else:
rootName = newFile
scriptName = rootName + "_script"
csvName = rootName + ".csv"
speName = rootName + ".spe"
xmsoName = rootName + ".xmso"
if sys.platform == 'win32':
scriptName = scriptName + ".bat"
fitName = rootName + ".fit"
ddict={}
ddict['fit'] = rootName + ".fit"
ddict['script'] = scriptName
ddict['csv'] = csvName
ddict['spe'] = speName
ddict['xmso'] = xmsoName
return ddict
[docs]def getXRFMCCorrectionFactors(fitConfiguration, xmimsim_pymca=None, verbose=False):
outputDir=tempfile.mkdtemp(prefix="pymcaTmp")
if 'result' in fitConfiguration:
# we have to create a .fit file with the information
ddict = ConfigDict.ConfigDict()
ddict.update(fitConfiguration)
else:
# for the time being we have to build a "fit-like" file with the information
import numpy
from PyMca5.PyMca import ClassMcaTheory
fitConfiguration['fit']['linearfitflag']=1
fitConfiguration['fit']['stripflag']=0
fitConfiguration['fit']['stripiterations']=0
xmin = fitConfiguration['fit']['xmin']
xmax = fitConfiguration['fit']['xmax']
#xdata = numpy.arange(xmin, xmax + 1) * 1.0
xdata = numpy.arange(0, xmax + 1) * 1.0
ydata = 0.0 + 0.1 * xdata
mcaFit = ClassMcaTheory.McaTheory()
mcaFit.configure(fitConfiguration)
#a dummy time
dummyTime = 1.0
if "concentrations" in fitConfiguration:
dummyTime = fitConfiguration["concentrations"].get("time",
dummyTime)
mcaFit.setData(x=xdata, y=ydata,
xmin=xmin, xmax=xmax, time=dummyTime)
mcaFit.estimate()
fitresult, result = mcaFit.startfit(digest=1)
ddict=ConfigDict.ConfigDict()
ddict['result'] = result
ddict['xrfmc'] = fitConfiguration['xrfmc']
handle, fitFile = tempfile.mkstemp(suffix=".fit", prefix="pymca",
dir=outputDir, text=False)
os.close(handle)
ddict.write(fitFile)
ddict = None
# we have the input file ready
fileNamesDict = getOutputFileNames(fitFile, outputDir)
scriptFile = getScriptFile(pathToExecutable=xmimsim_pymca,
name=fileNamesDict['script'])
xmsoName = fileNamesDict['xmso']
# basic parameters
args = [scriptFile,
"--enable-single-run",
#"--set-threads=2",
#"--verbose",
#"--spe-file=%s" % speName,
#"--csv-file=%s" % csvName,
#"--enable-roi-normalization",
#"--disable-roi-normalization", #default
#"--enable-pile-up"
#"--disable-pile-up" #default
#"--enable-poisson",
#"--disable-poisson", #default no noise
#"--set-threads=2", #overwrite default maximum
fitFile,
xmsoName]
if verbose:
args.insert(2, "--verbose")
process = subprocess.Popen(args,
bufsize=0,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
while process.poll() is None:
# process did not finish yet
time.sleep(0.1)
line = process.stdout.readline()
if verbose:
if len(line) > 1:
print("OUTPUT = <%s>" % line[:-1])
returnCode = process.returncode
line = process.stdout.readline()
while len(line) > 1:
if verbose:
print("OUTPUT = %s" % line[:-1])
line = process.stdout.readline()
if returnCode:
text = ""
line = process.stderr.readline()
while len(line) > 1:
text += line
if verbose:
print("ERROR = %s" % line[:-1])
line = process.stderr.readline()
removeDirectory(outputDir)
raise IOError("Program terminated with error code %d:\n%s" % (returnCode, text))
corrections = getXMSOFileFluorescenceInformation(xmsoName)
xmsoName = None
removeDirectory(outputDir)
return corrections
[docs]def removeDirectory(dirName):
if os.path.exists(dirName):
if os.path.isdir(dirName):
shutil.rmtree(dirName)
[docs]def start(fitFile, outputDir, xmimsim_pymca, parameters=None, verbose=True):
args = XRFMCHelper.getBasicSubprocessCommand(fitFile, outputDir, xmimsim_pymca)
if parameters is None:
parameters = ["--enable-single-run",
"--set-threads=2"]
i = 0
for parameter in parameters:
i += 1
args.insert(1, parameter)
process = subprocess.Popen(args,
bufsize=0,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
while process.poll() is None:
# process did not finish yet
time.sleep(0.1)
line = process.stdout.readline()
if verbose:
if len(line) > 1:
print("OUTPUT = <%s>" % line[:-1])
returnCode = process.returncode
line = process.stdout.readline()
while len(line) > 1:
if verbose:
print("OUTPUT = %s" % line[:-1])
line = process.stdout.readline()
if returnCode:
text = ""
line = process.stderr.readline()
while len(line) > 1:
text += line
if verbose:
print("ERROR = %s" % line[:-1])
line = process.stderr.readline()
raise IOError("Program terminated with error code %d:\n%s" % (returnCode, text))
[docs]def getBasicSubprocessCommand(fitFile, outputDir=None, xmimsim_pymca=None):
ddict = getOutputFileNames(fitFile, outputDir)
scriptFile = getScriptFile(pathToExecutable=xmimsim_pymca,
name=ddict['script'])
if ddict['fit'] != fitFile:
if outputDir is None:
# this should never happen
raise ValueError("Inconsistent internal behaviour!")
# recreate input in output directory
new = ConfigDict.ConfigDict()
new.read(fitFile)
if os.path.exists(ddict['fit']):
os.remove(ddict['fit'])
new.write(ddict['fit'])
new = None
speName = ddict['spe']
csvName = ddict['csv']
newFitFile = ddict['fit']
xmsoName = ddict['xmsoName']
args = [scriptFile,
#"--enable-single-run",
"--verbose",
"--spe-file=%s" % speName,
"--csv-file=%s" % csvName,
#"--enable-roi-normalization",
#"--disable-roi-normalization", #default
#"--enable-pile-up"
#"--disable-pile-up" #default
#"--enable-poisson",
#"--disable-poisson", #default no noise
#"--set-threads=2", #overwrite default maximum
newFitFile,
xmsoName]
return args
[docs]def test(filename):
fitConfig = ConfigDict.ConfigDict()
fitConfig.read(filename)
ddict = getXRFMCCorrectionFactors(fitConfig, verbose=True)
fitConfig = None
for element in ddict:
for line in ddict[element]:
if line == "z":
#atomic number
continue
if line in ['K', 'Ka', 'Kb', 'L', 'L1', 'L2', 'L3', 'M']:
correction1 = ddict[element][line]['correction_factor'][1]
correctionn = ddict[element][line]['correction_factor'][-1]
print("Element %s Line %s Correction 2 = %f Correction n = %f" %\
(element, line,correction1, correctionn))
if __name__ == "__main__":
if len(sys.argv) > 1:
test(sys.argv[1])
else:
print("Usage:")
print("python XRFMCHelper.py path_to_cfg_or_fit_file")