Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/pyFAI/detectors/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "16/11/2025"
__date__ = "21/11/2025"
__status__ = "stable"

import logging
Expand Down Expand Up @@ -890,7 +890,7 @@ def save(self, filename):
if self.delta_dummy is not None:
det_grp["delta_dummy"] = self.delta_dummy
det_grp.create_dataset("pixel_size",
data=numpy.array([self.pixel1, self.pixel2], dtype=numpy.float32),
data=numpy.array([self.pixel1, self.pixel2], dtype=numpy.float64),
).attrs["unit"]="m"

det_grp["force_pixel"] = self.force_pixel
Expand Down
6 changes: 4 additions & 2 deletions src/pyFAI/ext/CSR_common.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

__author__ = "Jérôme Kieffer"
__contact__ = "Jerome.kieffer@esrf.fr"
__date__ = "12/03/2025"
__date__ = "21/11/2025"
__status__ = "stable"
__license__ = "MIT"

Expand Down Expand Up @@ -60,15 +60,17 @@ cdef struct float4_t:
float s3
float4_d = numpy.dtype([('s0','f4'),('s1','f4'),('s2','f4'),('s3','f4')])


cdef inline bool cmp(float4_t a, float4_t b) noexcept nogil:
return True if a.s0<b.s0 else False


cdef inline void sort_float4(float4_t[::1] ary) noexcept nogil:
"Sort in place of an array of float4 along first element (s0)"
cdef:
int size
size = ary.shape[0]
sort(&ary[0], &ary[size-1]+1, cmp)
sort(&ary[0], &ary[size-1]+1, &cmp)


cdef class CsrIntegrator(object):
Expand Down
8 changes: 6 additions & 2 deletions src/pyFAI/opencl/preproc.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

__author__ = "Jérôme Kieffer"
__license__ = "MIT"
__date__ = "07/10/2025"
__date__ = "21/11/2025"
__copyright__ = "2015-2025, ESRF, Grenoble"
__contact__ = "jerome.kieffer@esrf.fr"

Expand Down Expand Up @@ -342,8 +342,12 @@ def compile_kernels(self, kernel_files=None):
# concatenate all needed source files into a single openCL module
kernel_files = kernel_files or self.kernel_files
# Explicit handling of fp64 since Apple silicon compiler wrongly clams fp64 support see issue #2339
compile_options = f"-D NIMAGE={self.size}"
fp64_support = 1 if "cl_khr_fp64" in self.ctx.devices[0].extensions else 0
compile_options = f"-D NIMAGE={self.size} -D cl_khr_fp64={fp64_support}"
platform = self.ctx.devices[0].platform
if not(platform.name == "Apple" and platform.get_devices()[0].type == 2):
# not Apple CPU
compile_options += f" -D cl_khr_fp64={fp64_support}"
OpenclProcessing.compile_kernels(self, kernel_files, compile_options)

def send_buffer(self, data, dest, convert=True):
Expand Down
6 changes: 5 additions & 1 deletion src/pyFAI/opencl/test/test_peak_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
__contact__ = "jerome.kieffer@esrf.eu"
__license__ = "MIT"
__copyright__ = "2020-2021 European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "21/05/2024"
__date__ = "21/11/2025"

import logging
import numpy
Expand Down Expand Up @@ -167,6 +167,10 @@ def test_peakfinder(self):
"""
test for peakfinder
"""
valid_opencl = False if ocl.get_platform("Apple") else True
if not valid_opencl:
self.skipTest("Apple platform detected")

unit = "r_m"
msk = self.img < 0
engine = self.ai.setup_sparse_integrator(self.img.shape, 1000, mask=msk, split="no", algo="CSR", unit=unit)
Expand Down
14 changes: 10 additions & 4 deletions src/pyFAI/test/test_azimuthal_integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "10/10/2025"
__date__ = "21/11/2025"

import unittest
import os
Expand Down Expand Up @@ -262,8 +262,14 @@ def test_separate(self):
def test_medfilt1d(self):
N = 1000
param = {"unit": "2th_deg"}
# legacy version"
if UtilsTest.opencl and pyopencl:
import pyFAI.opencl
valid_opencl = False if pyFAI.opencl.ocl.get_platform("Apple") else True
else:
valid_opencl = False

# legacy version"
if valid_opencl:
with logging_disabled(logging.WARNING):
ref = self.ai.medfilt1d_legacy(self.data, N, method="bbox_csr", **param)
ocl = self.ai.medfilt1d_legacy(self.data, N, method="bbox_ocl_csr", **param)
Expand All @@ -285,7 +291,7 @@ def test_medfilt1d(self):
logger.info("test_medfilt1d ng median Rwp_python = %.3f", rwp_pyt)
self.assertLess(rwp_pyt, 0.1, "Rwp medfilt1d_ng Cython/Python: %.3f" % rwp_pyt)

if UtilsTest.opencl and pyopencl:
if valid_opencl:
ocl = self.ai.medfilt1d_ng(self.data, N, method=("no", "csr", "opencl"), **param)
rwp_ocl = mathutil.rwp(ref, ocl)
logger.info("test_medfilt1d ng median Rwp_opencl = %.3f", rwp_ocl)
Expand All @@ -296,7 +302,7 @@ def test_medfilt1d(self):
rwp_pyt = mathutil.rwp(ref, pyt)
logger.info("test_medfilt1d ng trimmed-mean Rwp_python = %.3f", rwp_pyt)
self.assertLess(rwp_pyt, 2, "Rwp trimmed-mean Cython/Python: %.3f" % rwp_pyt)
if UtilsTest.opencl and pyopencl:
if valid_opencl:
ocl = self.ai.medfilt1d_ng(self.data, N, method=("no", "csr", 'opencl'), percentile=(20, 80), **param)
rwp_ocl = mathutil.rwp(ref, ocl)
logger.info("test_medfilt1d ng trimmed-mean Rwp_opencl = %.3f", rwp_ocl)
Expand Down
7 changes: 7 additions & 0 deletions src/pyFAI/test/test_csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ def tearDownClass(cls):

@unittest.skipIf((utilstest.UtilsTest.opencl is None) or (opencl.ocl is None), "Test on OpenCL disabled")
def test_opencl_csr(self):
if UtilsTest.opencl and opencl.ocl:
valid_opencl = False if opencl.ocl.get_platform("Apple") else True
else:
valid_opencl = False
if not valid_opencl:
self.skipTest("Apple platform detected")

testcases = [8 * 2 ** i for i in range(6)] # [8, 16, 32, 64, 128, 256]
for workgroup_size in testcases:
with self.subTest(workgroup_size=workgroup_size):
Expand Down
5 changes: 4 additions & 1 deletion src/pyFAI/test/test_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
__contact__ = "picca@synchrotron-soleil.fr"
__license__ = "MIT+"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "06/10/2025"
__date__ = "21/11/2025"

import os
import shutil
Expand Down Expand Up @@ -412,6 +412,9 @@ def test_sensor(self):
filename = os.path.join(UtilsTest.tempdir, "test_sensor.h5")
det1.save(filename)
det4 = detector_factory(filename)
print(det2)
print(det4)
print(det2==det4)
self.assertEqual(det2, det4, "after serialization to HDF5")

def test_sensor2(self):
Expand Down
4 changes: 2 additions & 2 deletions src/pyFAI/test/test_parallax.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "08/11/2025"
__date__ = "21/11/2025"

import unittest
import numpy
Expand Down Expand Up @@ -127,7 +127,7 @@ def test_extension(self):
self.assertEqual(indptr.size-1, numpy.prod(ai.detector.shape))
self.assertEqual((indptr[1:] - indptr[:-1]).max(), 8)
self.assertEqual(data.size, indices.size)
self.assertAlmostEqual(data.size/numpy.prod(ai.detector.shape), 3.56, delta=1e-3)
self.assertAlmostEqual(data.size/numpy.prod(ai.detector.shape), 3.56, delta=4e-3)


def suite():
Expand Down