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
84 changes: 43 additions & 41 deletions doc/source/usage/cookbook/calibration_with_jupyter.ipynb

Large diffs are not rendered by default.

130 changes: 80 additions & 50 deletions doc/source/usage/cookbook/integration_with_python.ipynb

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/pyFAI/app/average.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__ = "07/10/2025"
__date__ = "16/11/2025"
__status__ = "production"

import os
Expand All @@ -42,6 +42,7 @@
from ..utils import logging_utils
from .. import average
from .. import version as pyFAI_version, date as pyFAI_date, utils
from ..utils.shell import ProgressBar
logging.basicConfig(level=logging.INFO)
logging.captureWarnings(True)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -157,7 +158,7 @@ def __init__(self):

def image_loaded(self, fabio_image, image_index, images_count):
if self.__bar is None:
self.__bar = utils.shell.ProgressBar("Loading", images_count, self.__size)
self.__bar = ProgressBar("Loading", images_count, self.__size)
self.__bar.update(image_index, fabio_image.filename)

def process_started(self):
Expand All @@ -174,7 +175,7 @@ def frame_processed(self, algorithm, frame_index, frames_count):
if self.__bar is None:
title = "Process %s" % algorithm.name
self.__frames_count = frames_count + 1
self.__bar = utils.shell.ProgressBar(title, self.__frames_count, self.__size)
self.__bar = ProgressBar(title, self.__frames_count, self.__size)
self.__bar.update(frame_index, "Feeding frames")

def result_processing(self, algorithm):
Expand Down
10 changes: 3 additions & 7 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__ = "10/11/2025"
__date__ = "16/11/2025"
__status__ = "stable"

import logging
Expand Down Expand Up @@ -558,6 +558,7 @@ def getFit2D(self) -> dict:
"pixelY": self._pixel1 * 1e6,
"splineFile": self._splinefile}

@deprecated(since_version="2025.10", reason="use set_config")
def setPyFAI(self, **kwarg):
"""
Twin method of getPyFAI: setup a detector instance according to a description
Expand All @@ -568,7 +569,7 @@ def setPyFAI(self, **kwarg):
if "detector" in kwarg:
import pyFAI.detectors
config = {}
for key in ("pixel1", "pixel2", 'max_shape', "splineFile", "orientation"):
for key in ("pixel1", "pixel2", 'max_shape', "splineFile", "orientation", "sensor"):
if key in kwarg:
config[key.lower()] = kwarg[key]
self = pyFAI.detectors.detector_factory(kwarg["detector"], config)
Expand Down Expand Up @@ -1626,8 +1627,3 @@ def set_config(self, config:dict|str):
if module_size is not None:
self.module_size = tuple(module_size)
return self





2 changes: 1 addition & 1 deletion src/pyFAI/geometry/fit2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@

import os
import logging
from math import pi, cos, sin, sqrt, acos, asin
from ..utils.dataclasses import case_insensitive_dataclass
from math import pi, cos, sin, sqrt, acos, asin
from ..detectors import Detector
from ..io.ponifile import PoniFile
logger = logging.getLogger(__name__)
Expand Down
16 changes: 11 additions & 5 deletions src/pyFAI/goniometer.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "04/09/2025"
__date__ = "14/11/2025"
__status__ = "development"
__docformat__ = 'restructuredtext'

Expand Down Expand Up @@ -638,23 +638,29 @@ def __init__(self, label, image=None, metadata=None, pos_function=None,
else:
self.detector = None
if isinstance(geometry, Geometry):
dict_geo = geometry.getPyFAI()
dict_geo = geometry.get_config()
elif isinstance(geometry, StringTypes) and os.path.exists(geometry):
dict_geo = Geometry.sload(geometry).getPyFAI()
dict_geo = Geometry.sload(geometry).get_config()
elif isinstance(geometry, dict):
dict_geo = geometry

if self.detector is not None:
dict_geo["detector"] = self.detector
dict_geo.pop("detector_config", None)
elif "detector" in dict_geo:
self.detector = detector_factory(dict_geo["detector"], dict_geo.pop("detector_config", None))
dict_geo["detector"] = self.detector

if self.control_points is not None:
dict_geo["data"] = self.control_points.getList()
if self.calibrant is not None:
dict_geo["calibrant"] = self.calibrant
if self.calibrant.wavelength:
dict_geo["wavelength"] = self.calibrant.wavelength
if "max_shape" in dict_geo:
for key in ("max_shape", "poni_version"):
# not used in constructor
dict_geo.pop("max_shape")
dict_geo.pop(key, None)

self.geometry_refinement = GeometryRefinement(**dict_geo)
if self.detector is None:
self.detector = self.geometry_refinement.detector
Expand Down
10 changes: 5 additions & 5 deletions src/pyFAI/gui/cli_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "11/11/2025"
__date__ = "16/11/2025"
__status__ = "production"

import os
Expand Down Expand Up @@ -584,7 +584,7 @@ def extract_cpt(self, method="massif", pts_per_deg=1.0, max_rings=numpy.iinfo(in
self.peakPicker.reset()
self.peakPicker.init(method, False)
if self.geoRef:
self.ai.set_config(**self.geoRef.get_config())
self.ai.set_config(self.geoRef.get_config())
tth = numpy.array([i for i in self.calibrant.get_2th() if i is not None])
tth = numpy.unique(tth)
tth_min = numpy.zeros_like(tth)
Expand All @@ -601,7 +601,7 @@ def extract_cpt(self, method="massif", pts_per_deg=1.0, max_rings=numpy.iinfo(in
ttha = self.geoRef.center_array(self.peakPicker.data.shape, unit=TTH_RAD, scale=False)
chia = self.geoRef.center_array(self.peakPicker.data.shape, unit=CHI_RAD, scale=False)
else:
ttha = self.center_array(self.peakPicker.data.shape, unit=TTH_RAD, scale=False)
ttha = self.ai.center_array(self.peakPicker.data.shape, unit=TTH_RAD, scale=False)
chia = self.ai.center_array(self.peakPicker.data.shape, unit=CHI_RAD, scale=False)
rings = 0
self.peakPicker.sync_init()
Expand Down Expand Up @@ -1199,7 +1199,7 @@ def validate_calibration(self):
if not self.check_calib:
self.check_calib = CheckCalib()
if self.geoRef:
self.ai.setPyFAI(**self.geoRef.getPyFAI())
self.ai.set_config(self.geoRef.get_config())
self.ai.wavelength = self.geoRef.wavelength
self.check_calib.ai = self.ai
self.check_calib.img = self.peakPicker.data
Expand Down Expand Up @@ -1228,7 +1228,7 @@ def validate_center(self, slices=36):
npt = round_fft(int(math.sqrt(self.peakPicker.data.shape[0] ** 2 + self.peakPicker.data.shape[1] ** 2) + 1))

if self.geoRef:
self.ai.setPyFAI(**self.geoRef.getPyFAI())
self.ai.set_config(self.geoRef.get_config())
self.ai.wavelength = self.geoRef.wavelength
logger.info("Performing autocorrelation on %sx%s, Fourier analysis may take some time", slices, npt)
img, tth, chi = self.ai.integrate2d(self.peakPicker.data, npt, slices, azimuth_range=(-180, 180), unit="r_mm", method="splitpixel")
Expand Down
12 changes: 5 additions & 7 deletions src/pyFAI/integrator/azimuthal.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
__contact__ = "Jerome.Kieffer@ESRF.eu"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "13/11/2025"
__date__ = "16/11/2025"
__status__ = "stable"
__docformat__ = 'restructuredtext'

Expand Down Expand Up @@ -2180,8 +2180,8 @@ def separate(self, data, npt=1024, *,
return result

def inpainting(self, data, mask, npt_rad=1024, npt_azim=512, *,
unit="r_m", method="splitpixel", poissonian=False,
grow_mask=3):
unit="r_m", method=("full", "csr", "cython"),
poissonian=False, grow_mask=3):
"""Re-invent the values of masked pixels

:param data: input image as 2d numpy array
Expand Down Expand Up @@ -2238,11 +2238,9 @@ def inpainting(self, data, mask, npt_rad=1024, npt_azim=512, *,
"flat": ones_data}

imgb = self.integrate2d(blank_data, **kwargs)
imgp = self.integrate2d(masked, **kwargs)
imgd = self.integrate2d(masked_data, **kwargs)
omask = numpy.ascontiguousarray(numpy.round(imgb.intensity / dummy), numpy.int8)
imask = numpy.ascontiguousarray(numpy.round(imgp.intensity / dummy), numpy.int8)
to_paint = (imask - omask)
omask = (imgb.count == 0).astype(numpy.int8)
to_paint = abs((imgd.count == 0).astype("int8") - omask)

if grow_mask:
# inpaint a bit more than needed to avoid "side" effects.
Expand Down
4 changes: 2 additions & 2 deletions src/pyFAI/io/ponifile.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
__author__ = "Jérôme Kieffer"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "06/10/2025"
__date__ = "16/11/2025"
__docformat__ = 'restructuredtext'

import collections
Expand Down Expand Up @@ -198,7 +198,7 @@ def read_from_dict(self, config:dict) -> None:

if "splinefile" in config:
if config["splinefile"].lower() != "none":
self._detector.set_splineFile(config["splinefile"])
self._detector.splinefile = config["splinefile"]

elif version >=2:
detector_name = config["detector"]
Expand Down
11 changes: 7 additions & 4 deletions src/pyFAI/test/test_bug_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
__contact__ = "Jerome.Kieffer@esrf.fr"
__license__ = "MIT"
__copyright__ = "2015-2025 European Synchrotron Radiation Facility, Grenoble, France"
__date__ = "10/10/2025"
__date__ = "14/11/2025"

import sys
import os
Expand Down Expand Up @@ -537,14 +537,17 @@ def test_bug_1536(self):
detector = detectors.Detector(5e-4, 5e-4, max_shape=(1100, 1000))
ref = AzimuthalIntegrator(detector=detector)
geo = ref.getPyFAI()
# print(geo)
# print(ref.get_config())
obt = AzimuthalIntegrator()
obt.setPyFAI(**geo)
self.assertEqual(ref.detector.max_shape, obt.detector.max_shape, "max_shape matches")

# print(obt)
# same with get/set_config
geo = ref.get_config()
obt = AzimuthalIntegrator()
obt.set_config(geo)
self.assertEqual(ref.detector.max_shape, obt.detector.max_shape, "max_shape matches")


def test_bug_1810(self):
"impossible to deepcopy goniometer calibration"
import pyFAI.control_points
Expand Down
2 changes: 1 addition & 1 deletion src/pyFAI/test/test_export.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__ = "20/02/2024"
__date__ = "16/11/2025"

import unittest
import logging
Expand Down