mirror of https://github.com/silx-kit/pyFAI.git
commit
685e67d8f0
|
@ -8,7 +8,7 @@ Change-log of versions
|
|||
2024.1 UNRELEASED
|
||||
-----------------
|
||||
- Support XRDML formt (compatibility with MAUD software)
|
||||
- Support pathlib for reading PONI files
|
||||
- Support pathlib for reading PONI files
|
||||
- Refactor `pyFAI-benchmark` tool (Thanks Edgar)
|
||||
- Possibility to define the detector orientation:
|
||||
+ It is the position of the origin of the detector at any of the 4 corner of the image
|
||||
|
|
|
@ -30,7 +30,7 @@ __author__ = "Jérôme Kieffer"
|
|||
__contact__ = "Jerome.Kieffer@ESRF.eu"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
||||
__date__ = "21/11/2023"
|
||||
__date__ = "11/01/2024"
|
||||
__status__ = "stable"
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
|
@ -47,7 +47,7 @@ from . import units
|
|||
from .utils import EPS32, deg2rad, crc32
|
||||
from .utils.decorators import deprecated, deprecated_warning
|
||||
from .containers import Integrate1dResult, Integrate2dResult, SeparateResult, ErrorModel
|
||||
from .io import DefaultAiWriter
|
||||
from .io import DefaultAiWriter, save_integrate_result
|
||||
from .io.ponifile import PoniFile
|
||||
error = None
|
||||
from .method_registry import IntegrationMethod
|
||||
|
@ -1099,8 +1099,7 @@ class AzimuthalIntegrator(Geometry):
|
|||
result._set_metadata(metadata)
|
||||
|
||||
if filename is not None:
|
||||
writer = DefaultAiWriter(filename, self)
|
||||
writer.write(result)
|
||||
save_integrate_result(filename, result)
|
||||
|
||||
return result
|
||||
|
||||
|
@ -1600,9 +1599,7 @@ class AzimuthalIntegrator(Geometry):
|
|||
result._set_has_solidangle_correction(correctSolidAngle)
|
||||
|
||||
if filename is not None:
|
||||
writer = DefaultAiWriter(filename, self)
|
||||
writer.write(result)
|
||||
|
||||
save_integrate_result(filename, result)
|
||||
return result
|
||||
|
||||
_integrate1d_ng = integrate1d_ng
|
||||
|
@ -2102,8 +2099,7 @@ class AzimuthalIntegrator(Geometry):
|
|||
result._set_metadata(metadata)
|
||||
|
||||
if filename is not None:
|
||||
writer = DefaultAiWriter(filename, self)
|
||||
writer.write(result)
|
||||
save_integrate_result(filename, result)
|
||||
|
||||
return result
|
||||
|
||||
|
@ -2617,8 +2613,7 @@ class AzimuthalIntegrator(Geometry):
|
|||
result._set_std(sem)
|
||||
|
||||
if filename is not None:
|
||||
writer = DefaultAiWriter(filename, self)
|
||||
writer.write(result)
|
||||
save_integrate_result(filename, result)
|
||||
|
||||
return result
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ __author__ = "Jerome Kieffer"
|
|||
__contact__ = "Jerome.Kieffer@ESRF.eu"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
||||
__date__ = "25/09/2023"
|
||||
__date__ = "11/01/2024"
|
||||
__status__ = "production"
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
|
@ -999,6 +999,9 @@ def save_integrate_result(filename, result, title="title", sample="sample", inst
|
|||
"""
|
||||
if filename.endswith(".nxs"):
|
||||
raise RuntimeError("Implement Nexus writer")
|
||||
elif filename.endswith(".xrdml"):
|
||||
from .xrdml import save_xrdml
|
||||
save_xrdml(filename, result)
|
||||
else:
|
||||
writer = DefaultAiWriter(filename, result.poni)
|
||||
writer.write(result)
|
||||
writer = DefaultAiWriter(filename, result.poni)
|
||||
writer.write(result)
|
||||
|
|
|
@ -6,7 +6,8 @@ py.install_sources(
|
|||
'nexus.py',
|
||||
'ponifile.py',
|
||||
'sparse_frame.py',
|
||||
'spots.py'],
|
||||
'spots.py',
|
||||
'xrdml.py'],
|
||||
pure: false, # Will be installed next to binaries
|
||||
subdir: 'pyFAI/io' # Folder relative to site-packages to install to
|
||||
)
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
# Project: Azimuthal integration
|
||||
# https://github.com/silx-kit/pyFAI
|
||||
#
|
||||
# Copyright (C) 2024-2024 European Synchrotron Radiation Facility, Grenoble, France
|
||||
#
|
||||
# Principal author: Jérôme Kieffer (Jerome.Kieffer@ESRF.eu)
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Module for exporting XRDML powder diffraction files
|
||||
Inspiration from
|
||||
"""
|
||||
|
||||
__author__ = "Jérôme Kieffer"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
||||
__date__ = "11/01/2024"
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
import os
|
||||
from xml.etree import ElementTree as et
|
||||
from .nexus import get_isotime
|
||||
from .. import version as pyFAI_version
|
||||
|
||||
def save_xrdml(filename, result):
|
||||
"""
|
||||
|
||||
https://www.researchgate.net/profile/Mohamed-Ali-392/post/XRD_Refinement_for_TiO2_Anatase_using_MAUD/attachment/60fa1d85647f3906fc8af2f3/AS%3A1048546157539329%401627004293526/download/sample.xrdml
|
||||
"""
|
||||
now = get_isotime()
|
||||
dirname = os.path.dirname(os.path.abspath(filename))
|
||||
if not os.path.isdir(dirname):
|
||||
os.makedirs(dirname, exist_ok=True)
|
||||
|
||||
xrdml = et.Element("xrdMeasurements", {"xmlns":"http://www.xrdml.com/XRDMeasurement/1.0",
|
||||
"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
|
||||
"xsi:schemaLocation": "http://www.xrdml.com/XRDMeasurement/1.3 http://www.xrdml.com/XRDMeasurement/1.3/XRDMeasurement.xsd",
|
||||
"status": "Completed"})
|
||||
sample = et.Element("sample", type="To be analyzed")
|
||||
xid = et.Element("id")
|
||||
xid.text = "000000-0000"
|
||||
sample.append(xid)
|
||||
name = et.Element("name")
|
||||
name.text = "sample"
|
||||
sample.append(name)
|
||||
xrdml.append(sample)
|
||||
measurement = et.Element("xrdMeasurement", {"measurementType":"Scan", "status":"Completed"})
|
||||
wavelength = result.poni.wavelength
|
||||
if wavelength:
|
||||
txtwavelength = str(wavelength*1e10)
|
||||
usedWavelength = et.Element("usedWavelength", intended="K-Alpha")
|
||||
k_alpha1 = et.Element("kAlpha1", unit="Angstrom")
|
||||
k_alpha1.text = txtwavelength
|
||||
usedWavelength.append(k_alpha1)
|
||||
k_alpha2 = et.Element("kAlpha2", unit="Angstrom")
|
||||
k_alpha2.text = txtwavelength
|
||||
usedWavelength.append(k_alpha2)
|
||||
k_beta = et.Element("kBeta", unit="Angstrom")
|
||||
k_beta.text = txtwavelength
|
||||
usedWavelength.append(k_beta)
|
||||
ratio = et.Element("ratioKAlpha2KAlpha1")
|
||||
ratio.text = "0"
|
||||
usedWavelength.append(ratio)
|
||||
measurement.append(usedWavelength)
|
||||
scan = et.Element("scan", {"appendNumber":"0",
|
||||
"mode":"Pre-set time",
|
||||
"measurementType": "Area measurement",
|
||||
"scanAxis":"Gonio",
|
||||
"status":"Completed"})
|
||||
header = et.Element("header")
|
||||
for stamp in ("startTimeStamp", "endTimeStamp"):
|
||||
estamp = et.Element(stamp)
|
||||
estamp.text = now
|
||||
header.append(estamp)
|
||||
author = et.Element("author")
|
||||
name = et.Element("name")
|
||||
name.text = "pyFAI"
|
||||
author.append(name)
|
||||
header.append(author)
|
||||
source = et.Element("source")
|
||||
sw = et.Element("applicationSoftware", version=pyFAI_version)
|
||||
sw.text='pyFAI'
|
||||
source.append(sw)
|
||||
header.append(source)
|
||||
scan.append(header)
|
||||
datapoints = et.Element("dataPoints")
|
||||
positions = et.Element("positions", axis=result.unit.short_name, unit=result.unit.unit_symbol)
|
||||
for pos, idx in {"startPosition": 0, "endPosition":-1}.items():
|
||||
position = et.Element(pos)
|
||||
position.text = str(result.radial[idx])
|
||||
positions.append(position)
|
||||
datapoints.append(positions)
|
||||
ct = et.Element("commonCountingTime", unit="seconds")
|
||||
ct.text = "1.00"
|
||||
datapoints.append(ct)
|
||||
intensities = et.Element("intensities", unit="counts")
|
||||
intensities.text = " ".join(str(i) for i in result.intensity)
|
||||
datapoints.append(intensities)
|
||||
scan.append(datapoints)
|
||||
measurement.append(scan)
|
||||
xrdml.append(measurement)
|
||||
with open(filename, "wb") as w:
|
||||
w.write(et.tostring(xrdml))
|
|
@ -32,7 +32,7 @@ __author__ = "Jérôme Kieffer"
|
|||
__contact__ = "Jerome.Kieffer@ESRF.eu"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
||||
__date__ = "09/01/2024"
|
||||
__date__ = "10/01/2024"
|
||||
|
||||
import unittest
|
||||
import os
|
||||
|
@ -296,6 +296,38 @@ class TestSpotWriter(unittest.TestCase):
|
|||
self.assertGreater(size.st_size, sum(i.size for i in self.spots), "file is large enough")
|
||||
|
||||
|
||||
class TestXrdmlWriter(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls)->None:
|
||||
super(TestXrdmlWriter, cls).setUpClass()
|
||||
cls.img = fabio.open(UtilsTest.getimage("Pilatus1M.edf"))
|
||||
cls.ai = pyFAI.load(UtilsTest.getimage("Pilatus1M.poni"))
|
||||
cls.result = cls.ai.integrate1d(cls.img.data, 200, method=("no", "histogram", "cython"), unit="2th_deg")
|
||||
@classmethod
|
||||
def tearDownClass(cls)->None:
|
||||
super(TestXrdmlWriter, cls).tearDownClass()
|
||||
cls.ai = cls.img = cls.result=None
|
||||
|
||||
def test_xrdml(self):
|
||||
from ..io.xrdml import save_xrdml
|
||||
fd, tmpfile = UtilsTest.tempfile(".xrdml")
|
||||
os.close(fd)
|
||||
save_xrdml(tmpfile, self.result)
|
||||
self.assertGreater(os.path.getsize(tmpfile), 3000)
|
||||
|
||||
def test_integration(self):
|
||||
fd, tmpfile = UtilsTest.tempfile(".xrdml")
|
||||
os.close(fd)
|
||||
self.ai.integrate1d(self.img.data, 200, method=("no", "histogram", "cython"), unit="2th_deg",
|
||||
filename=tmpfile)
|
||||
self.assertGreater(os.path.getsize(tmpfile), 3000)
|
||||
from xml.etree import ElementTree as et
|
||||
with open(tmpfile, "rb") as f:
|
||||
xml = et.fromstring(f.read())
|
||||
|
||||
|
||||
|
||||
def suite():
|
||||
testsuite = unittest.TestSuite()
|
||||
loader = unittest.defaultTestLoader.loadTestsFromTestCase
|
||||
|
@ -304,6 +336,7 @@ def suite():
|
|||
testsuite.addTest(loader(TestHDF5Writer))
|
||||
testsuite.addTest(loader(TestFabIOWriter))
|
||||
testsuite.addTest(loader(TestSpotWriter))
|
||||
testsuite.addTest(loader(TestXrdmlWriter))
|
||||
testsuite.addTest(loader(TestPoniFile))
|
||||
return testsuite
|
||||
|
||||
|
|
Loading…
Reference in New Issue