Skip to content

Commit

Permalink
Merge branch 'main' into 2313_medfilt_ng_opencl
Browse files Browse the repository at this point in the history
  • Loading branch information
kif authored Nov 21, 2024
2 parents 16a0b1e + ff512a3 commit f333557
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 188 deletions.
171 changes: 24 additions & 147 deletions src/pyFAI/integrator/fiber.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
__contact__ = "[email protected]"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "13/11/2024"
__date__ = "20/11/2024"
__status__ = "stable"
__docformat__ = 'restructuredtext'

Expand Down Expand Up @@ -155,6 +155,8 @@ def integrate_fiber(self, data,
:param pyFAI.units.UnitFiber/str unit_ip: unit to describe the in-plane axis. If not provided, it takes qip_nm^-1
:param list ip_range: The lower and upper range of the in-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param bool vertical_integration: If True, integrates along unit_ip; if False, integrates along unit_oop
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
:param str filename: output filename in 2/3 column ascii format
:param bool correctSolidAngle: correct for solid angle of each pixel if True
Expand Down Expand Up @@ -183,8 +185,14 @@ def integrate_fiber(self, data,

unit_ip = unit_ip or 'qip_nm^-1'
unit_oop = unit_oop or 'qoop_nm^-1'
unit_ip = parse_fiber_unit(unit=unit_ip, sample_orientation=sample_orientation)
unit_oop = parse_fiber_unit(unit=unit_oop, sample_orientation=unit_ip.sample_orientation)
unit_ip = parse_fiber_unit(unit=unit_ip,
incident_angle=kwargs.get('incident_angle', None),
tilt_angle=kwargs.get('tilt_angle', None),
sample_orientation=sample_orientation)
unit_oop = parse_fiber_unit(unit=unit_oop,
incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
sample_orientation=unit_ip.sample_orientation)

self.reset_integrator(incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
Expand Down Expand Up @@ -262,78 +270,7 @@ def integrate_fiber(self, data,

return result

def integrate_grazing_incidence(self, data,
npt_oop=None, unit_oop=None, oop_range=None,
npt_ip=None, unit_ip=None, ip_range=None,
vertical_integration = True,
incident_angle=None, tilt_angle=None, sample_orientation=None,
filename=None,
correctSolidAngle=True,
mask=None, dummy=None, delta_dummy=None,
polarization_factor=None, dark=None, flat=None,
method=("no", "histogram", "cython"),
normalization_factor=1.0,
**kwargs):
"""Calculate the integrated profile curve along a specific FiberUnit, additional inputs for incident angle, tilt angle and sample_orientation
:param ndarray data: 2D array from the Detector/CCD camera
:param int npt_oop: number of points to be used along the out-of-plane axis
:param pyFAI.units.UnitFiber/str unit_oop: unit to describe the out-of-plane axis. If not provided, it takes qoop_nm^-1
:param list oop_range: The lower and upper range of the out-of-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param int npt_ip: number of points to be used along the in-plane axis
:param pyFAI.units.UnitFiber/str unit_ip: unit to describe the in-plane axis. If not provided, it takes qip_nm^-1
:param list ip_range: The lower and upper range of the in-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param bool vertical_integration: If True, integrates along unit_ip; if False, integrates along unit_oop
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
:param str filename: output filename in 2/3 column ascii format
:param bool correctSolidAngle: correct for solid angle of each pixel if True
:param ndarray mask: array (same size as image) with 1 for masked pixels, and 0 for valid pixels
:param float dummy: value for dead/masked pixels
:param float delta_dummy: precision for dummy value
:param float polarization_factor: polarization factor between -1 (vertical) and +1 (horizontal).
* 0 for circular polarization or random,
* None for no correction,
* True for using the former correction
:param ndarray dark: dark noise image
:param ndarray flat: flat field image
:param IntegrationMethod method: IntegrationMethod instance or 3-tuple with (splitting, algorithm, implementation)
:param float normalization_factor: Value of a normalization monitor
:return: chi bins center positions and regrouped intensity
:rtype: Integrate1dResult
"""
deprecated_params = get_deprecated_params_1d(**kwargs)
npt_oop = deprecated_params.get('npt_oop', None) or npt_oop
npt_ip = deprecated_params.get('npt_ip', None) or npt_ip
unit_oop = deprecated_params.get('unit_oop', None) or unit_oop
unit_ip = deprecated_params.get('unit_ip', None) or unit_ip
oop_range = deprecated_params.get('oop_range', None) or oop_range
ip_range = deprecated_params.get('ip_range', None) or ip_range
vertical_integration = deprecated_params.get('vertical_integration', None) or vertical_integration

unit_ip = unit_ip or 'qip_nm^-1'
unit_oop = unit_oop or 'qoop_nm^-1'
unit_ip = parse_fiber_unit(unit=unit_ip, incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
unit_oop = parse_fiber_unit(unit=unit_oop, incident_angle=unit_ip.incident_angle, tilt_angle=unit_ip.tilt_angle, sample_orientation=unit_ip.sample_orientation)

self.reset_integrator(incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
sample_orientation=unit_ip.sample_orientation)

return self.integrate_fiber(data=data,
npt_oop=npt_oop, unit_oop=unit_oop, oop_range=oop_range,
npt_ip=npt_ip, unit_ip=unit_ip, ip_range=ip_range,
vertical_integration=vertical_integration,
sample_orientation=sample_orientation,
filename=filename,
correctSolidAngle=correctSolidAngle,
mask=mask, dummy=dummy, delta_dummy=delta_dummy,
polarization_factor=polarization_factor, dark=dark, flat=flat,
method=method,
normalization_factor=normalization_factor,
)

integrate_grazing_incidence = integrate_fiber
integrate1d_grazing_incidence = integrate_grazing_incidence
integrate1d_fiber = integrate_fiber

Expand All @@ -356,6 +293,8 @@ def integrate2d_fiber(self, data,
:param int npt_oop: number of points to be used along the out-of-plane axis
:param pyFAI.units.UnitFiber/str unit_oop: unit to describe the out-of-plane axis. If not provided, it takes qoop_nm^-1
:param list oop_range: The lower and upper range of the out-of-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
:param str filename: output filename in 2/3 column ascii format
:param bool correctSolidAngle: correct for solid angle of each pixel if True
Expand Down Expand Up @@ -383,8 +322,15 @@ def integrate2d_fiber(self, data,

unit_ip = unit_ip or 'qip_nm^-1'
unit_oop = unit_oop or 'qoop_nm^-1'
unit_ip = parse_fiber_unit(unit=unit_ip, sample_orientation=sample_orientation)
unit_oop = parse_fiber_unit(unit=unit_oop, sample_orientation=unit_ip.sample_orientation)
unit_ip = parse_fiber_unit(unit=unit_ip,
sample_orientation=sample_orientation,
incident_angle=kwargs.get('incident_angle', None),
tilt_angle=kwargs.get('tilt_angle', None),
)
unit_oop = parse_fiber_unit(unit=unit_oop,
incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
sample_orientation=unit_ip.sample_orientation)

self.reset_integrator(incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
Expand All @@ -404,73 +350,4 @@ def integrate2d_fiber(self, data,
unit=(unit_ip, unit_oop),
filename=filename)

def integrate2d_grazing_incidence(self, data,
npt_ip=1000, unit_ip=None, ip_range=None,
npt_oop=1000, unit_oop=None, oop_range=None,
incident_angle=None, tilt_angle=None, sample_orientation=None,
filename=None,
correctSolidAngle=True,
mask=None, dummy=None, delta_dummy=None,
polarization_factor=None, dark=None, flat=None,
method=("no", "histogram", "cython"),
normalization_factor=1.0, **kwargs):
"""Reshapes the data pattern as a function of two FiberUnits, additional inputs for incident angle, tilt angle and sample_orientation
:param ndarray data: 2D array from the Detector/CCD camera
:param int npt_ip: number of points to be used along the in-plane axis
:param pyFAI.units.UnitFiber/str unit_ip: unit to describe the in-plane axis. If not provided, it takes qip_nm^-1
:param list ip_range: The lower and upper range of the in-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param int npt_oop: number of points to be used along the out-of-plane axis
:param pyFAI.units.UnitFiber/str unit_oop: unit to describe the out-of-plane axis. If not provided, it takes qoop_nm^-1
:param list oop_range: The lower and upper range of the out-of-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
:param str filename: output filename in 2/3 column ascii format
:param bool correctSolidAngle: correct for solid angle of each pixel if True
:param ndarray mask: array (same size as image) with 1 for masked pixels, and 0 for valid pixels
:param float dummy: value for dead/masked pixels
:param float delta_dummy: precision for dummy value
:param float polarization_factor: polarization factor between -1 (vertical) and +1 (horizontal).
* 0 for circular polarization or random,
* None for no correction,
* True for using the former correction
:param ndarray dark: dark noise image
:param ndarray flat: flat field image
:param IntegrationMethod method: IntegrationMethod instance or 3-tuple with (splitting, algorithm, implementation)
:param float normalization_factor: Value of a normalization monitor
:return: regrouped intensity and unit arrays
:rtype: Integrate2dResult
"""
deprecated_params = get_deprecated_params_2d(**kwargs)
npt_oop = deprecated_params.get('npt_oop', None) or npt_oop
npt_ip = deprecated_params.get('npt_ip', None) or npt_ip
unit_oop = deprecated_params.get('unit_oop', None) or unit_oop
unit_ip = deprecated_params.get('unit_ip', None) or unit_ip
oop_range = deprecated_params.get('oop_range', None) or oop_range
ip_range = deprecated_params.get('ip_range', None) or ip_range

unit_ip = unit_ip or 'qip_nm^-1'
unit_oop = unit_oop or 'qoop_nm^-1'
unit_ip = parse_fiber_unit(unit=unit_ip, incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
unit_oop = parse_fiber_unit(unit=unit_oop, incident_angle=unit_ip.incident_angle, tilt_angle=unit_ip.tilt_angle, sample_orientation=unit_ip.sample_orientation)

self.reset_integrator(incident_angle=unit_ip.incident_angle,
tilt_angle=unit_ip.tilt_angle,
sample_orientation=unit_ip.sample_orientation)

if (isinstance(method, (tuple, list)) and method[0] != "no") or (isinstance(method, IntegrationMethod) and method.split != "no"):
logger.warning(f"Method {method} is using a pixel-splitting scheme. GI integration should be use WITHOUT PIXEL-SPLITTING! The results could be wrong!")

return self.integrate2d_fiber(data=data, npt_ip=npt_ip, npt_oop=npt_oop,
unit_ip=unit_ip, unit_oop=unit_oop,
ip_range=ip_range,
oop_range=oop_range,
sample_orientation=sample_orientation,
filename=filename,
correctSolidAngle=correctSolidAngle,
mask=mask, dummy=dummy, delta_dummy=delta_dummy,
polarization_factor=polarization_factor, dark=dark, flat=flat,
method=method,
normalization_factor=normalization_factor,
)
integrate2d_grazing_incidence = integrate2d_fiber
20 changes: 19 additions & 1 deletion src/pyFAI/opencl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
__contact__ = "[email protected]"
__license__ = "MIT"
__copyright__ = "2012-2024 European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "15/04/2024"
__date__ = "19/11/2024"
__status__ = "stable"

import os
Expand Down Expand Up @@ -79,6 +79,24 @@ def get_x87_volatile_option(ctx):
else:
return ""

def get_compiler_options(ctx, x87_volatile=False, apple_gpu=False):
"""Provide a set of common compiler options to work around known bugs:
:x87_volatile: set to true to declare all x87 operation as volatile, needed on PoCL x86 32bits
:apple_gpu: redefine the cl_khr_fp64 to zero when the device is Apple GPU
which wrongly declares fp64 compatibility. See #2339
:return: compilation directive as string.
"""

if x87_volatile:
options = get_x87_volatile_option(ctx)
else:
options = ""
if apple_gpu:
fp64_support = 1 if "cl_khr_fp64" in ctx.devices[0].extensions else 0
options += f" -D cl_khr_fp64={fp64_support}"
return options.strip()


def dtype_converter(dtype):
"convert a numpy dtype as a int8"
Expand Down
14 changes: 9 additions & 5 deletions src/pyFAI/opencl/azim_csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,15 @@ def compile_kernels(self, kernel_file=None):
kernel_file = kernel_file or self.kernel_files[-1]
kernels = self.kernel_files[:-1] + [kernel_file]

compile_options = f"-D NBINS={self.bins} -D NIMAGE={self.size}"
default_compiler_options = self.get_compiler_options(x87_volatile=True)
if default_compiler_options:
compile_options += " " + default_compiler_options
OpenclProcessing.compile_kernels(self, kernels, compile_options)
try:
compile_options = self.get_compiler_options(x87_volatile=True, apple_gpu=True)
except (AttributeError, TypeError): # Silx version too old
logger.warning("Please upgrade to silx v2.2+")
from . import get_compiler_options
compile_options = get_compiler_options(self.ctx, x87_volatile=True, apple_gpu=True)

compile_options += f" -D NBINS={self.bins} -D NIMAGE={self.size}"
OpenclProcessing.compile_kernels(self, kernels, compile_options.strip())
for kernel_name in self.kernels.__dict__:
if kernel_name.startswith("_"):
continue
Expand Down
20 changes: 12 additions & 8 deletions src/pyFAI/opencl/azim_hist.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"""
__author__ = "Jérôme Kieffer"
__license__ = "MIT"
__date__ = "25/04/2024"
__date__ = "19/11/2024"
__copyright__ = "2012-2021, ESRF, Grenoble"
__contact__ = "[email protected]"

Expand All @@ -47,7 +47,7 @@
raise ImportError("pyopencl is not installed")

from . import allocate_cl_buffers, release_cl_buffers, kernel_workgroup_size
from . import concatenate_cl_kernel, get_x87_volatile_option, processing, OpenclProcessing
from . import concatenate_cl_kernel, processing, OpenclProcessing
from ..containers import Integrate1dtpl, Integrate2dtpl, ErrorModel
from ..utils.decorators import deprecated
EventDescription = processing.EventDescription
Expand Down Expand Up @@ -257,13 +257,17 @@ def compile_kernels(self, kernel_file=None):
# concatenate all needed source files into a single openCL module
kernel_file = kernel_file or self.kernel_files[-1]
kernels = self.kernel_files[:-1] + [kernel_file]
default_compiler_options = get_x87_volatile_option(self.ctx)
compile_options = "-D NBINS=%i -D NIMAGE=%i -D WORKGROUP_SIZE=%i" % \
(self.bins, self.size, self.BLOCK_SIZE)
if default_compiler_options:
compile_options += " " + default_compiler_options
try:
OpenclProcessing.compile_kernels(self, kernels, compile_options)
compile_options = self.get_compiler_options(x87_volatile=True, apple_gpu=True)
except (AttributeError, TypeError): # Silx version too old
logger.warning("Please upgrade to silx v2.2+")
from . import get_compiler_options
compile_options = get_compiler_options(self.ctx, x87_volatile=True, apple_gpu=True)


compile_options += f" -D NBINS={self.bins} -D NIMAGE={self.size} -D WORKGROUP_SIZE={self.BLOCK_SIZE}"
try:
OpenclProcessing.compile_kernels(self, kernels, compile_options.strip())
except Exception as error:
# This error may be related to issue #1219. Provides an ugly work around.
if "cl_khr_int64_base_atomics" in self.ctx.devices[0].extensions:
Expand Down
Loading

0 comments on commit f333557

Please sign in to comment.