I/O Module#

Complete reference for data loading and file I/O.

Loaders by Beamline#

Beamline-specific data loaders for BCDI experiments.

This module provides the abstract base Loader class and beamline-specific implementations for loading detector data, motor positions, and metadata from synchrotron BCDI experiments.

class cdiutils.io.loader.Loader(scan=None, sample_name=None, flat_field=None, alien_mask=None)[source]#

Bases: ABC

Abstract base class for beamline-specific data loaders.

Loaders handle experiment-specific data I/O operations including: - HDF5/NeXus/SPEC file parsing - Detector data extraction with ROI support - Motor angle retrieval - Energy and detector calibration parameter loading - Flat-field correction and bad pixel masking

Use the factory method from_setup() to instantiate the appropriate subclass for your beamline, or directly instantiate beamline-specific loaders (ID01Loader, P10Loader, etc.) for advanced configuration.

Supported beamlines:
  • ID01 (ESRF): ID01Loader

  • P10 (PETRA III): P10Loader

  • SIXS (SOLEIL): SIXSLoader

  • NanoMAX (MAX IV): NanoMAXLoader

  • CRISTAL (SOLEIL): CristalLoader

  • ID27 (ESRF): ID27Loader

scan#

Scan number identifier.

Type:

int

sample_name#

Sample identifier for file organisation.

Type:

str

flat_field#

Flat-field correction array for detector non-uniformity.

Type:

np.ndarray

alien_mask#

Mask for defective detector pixels.

Type:

np.ndarray

detector_name#

Detector type (set by subclass).

Type:

str

rocking_angle#

Name of rocking curve motor (beamline-specific).

Type:

str

See also

BcdiPipeline: Uses loaders automatically ID01Loader: ESRF ID01 beamline implementation P10Loader: PETRA III P10 beamline implementation

Examples

Using factory pattern (recommended):

>>> loader = Loader.from_setup(
...     beamline_setup="id01",
...     sample_name="PtNP",
...     scan=42,
...     data_dir="/data/id01/sample"
... )
>>> data, angles = loader.load_data()

Direct instantiation:

>>> from cdiutils.io import ID01Loader
>>> loader = ID01Loader(
...     sample_name="PtNP",
...     scan=42,
...     experiment_file_path="/data/sample.h5"
... )
__init__(scan=None, sample_name=None, flat_field=None, alien_mask=None)[source]#

Initialise the base Loader.

Typically called by subclass constructors. Users should prefer from_setup() factory method or direct subclass instantiation.

Parameters:
  • scan (int) – Scan number identifier. Required for data loading.

  • sample_name (str) – Sample identifier used in file paths and logging.

  • flat_field (ndarray | str) – Flat-field correction array or path to .npy/.npz file. Applied as multiplicative correction to detector data. Shape must match detector dimensions. Defaults to None (no correction).

  • alien_mask (ndarray | str) – Bad pixel mask array or path to .npy/.npz file. Pixels with value 1 are masked (invalid), 0 are kept. Shape must match detector. Defaults to None (no masking).

Raises:

ValueError – If flat_field or alien_mask path is invalid or file format is unsupported.

get_alien_mask(roi=None)[source]#
classmethod from_setup(beamline_setup, **metadata)[source]#

Factory method to instantiate beamline-specific loader.

Automatically selects and returns the appropriate Loader subclass based on beamline name. This is the recommended way to create loaders as it handles beamline-specific initialisation automatically.

Parameters:
  • beamline_setup (str) –

    Beamline identifier (case-insensitive). Supported values:

    • "id01" or "id01bliss": ESRF ID01 (BLISS format)

    • "id01spec": ESRF ID01 (legacy SPEC format)

    • "sixs2019" or "sixs2022": SOLEIL SIXS (specify year)

    • "p10" or "p10eh2": PETRA III P10 (specify hutch)

    • "cristal": SOLEIL CRISTAL

    • "nanomax": MAX IV NanoMAX

    • "id27": ESRF ID27

  • **metadata

    Beamline-specific keyword arguments passed to loader

    constructor. Common parameters include:

    • scan (int): Scan number

    • sample_name (str): Sample identifier

    • experiment_file_path (str): Path to experiment HDF5/SPEC

    • data_dir (str): Root data directory

    • flat_field (np.ndarray | str): flat-field

    correction
    • alien_mask (np.ndarray | str): bad pixel mask

Returns:

Beamline-specific Loader subclass instance.

Raises:
  • ValueError – If beamline_setup is not recognised.

  • NotImplementedError – If beamline version (e.g., SIXS year) is not specified or unsupported.

Return type:

Loader

Examples

Basic usage:

>>> loader = Loader.from_setup(
...     beamline_setup="id01",
...     scan=42,
...     sample_name="PtNP",
...     experiment_file_path="/data/id01/beamtile_id01.h5"
... )

With version specification:

>>> loader = Loader.from_setup(
...     beamline_setup="sixs2022",
...     scan=100,
...     sample_name="SrTiO3"
... )

With flat-field and mask:

>>> loader = Loader.from_setup(
...     beamline_setup="p10",
...     scan=15,
...     flat_field="/path/to/flatfield.npy",
...     alien_mask="/path/to/badpixels.npy"
... )
static bin_flat_mask(data, roi=None, flat_field=None, alien_mask=None, rocking_angle_binning=None, binning_method='sum')[source]#

Apply preprocessing: binning, flat-field, and masking.

Combines three common preprocessing steps in correct order:

  1. Bin along rocking curve (if requested)

  2. Apply flat-field correction (if provided)

  3. Apply alien mask (if provided)

Parameters:
  • data (ndarray) – 3D detector data with shape (n_frames, n_y, n_x).

  • roi (list) – Region of interest as tuple of slices or integers. If None, uses full array. See _check_roi() for format details.

  • flat_field (ndarray) – 2D array with detector efficiency correction. Shape must match data.shape[1:]. If None, no correction applied.

  • alien_mask (ndarray) – Binary mask of bad pixels (1 = bad, 0 = good). Shape must match data.shape (3D) or data.shape[1:] (2D). If None, no masking applied.

  • rocking_angle_binning (int) – Binning factor along rocking curve axis (frames). If None or 1, no binning performed.

  • binning_method (str) –

    Binning operation. Options:

    • "sum": Sum frames (default, preserves total counts)

    • "mean": Average frames (reduces noise)

    • "max": Maximum projection (peak intensity)

Returns:

Preprocessed 3D array with same dtype as input. Shape is (n_frames//binning, n_y, n_x) if binned.

Return type:

ndarray

Examples

ROI + flat-field + mask:

>>> roi = (slice(None), slice(100, 400), slice(150, 450))
>>> processed = Loader.bin_flat_mask(
...     data=raw_data,
...     roi=roi,
...     flat_field=flat,
...     alien_mask=mask
... )

Binning only:

>>> binned = Loader.bin_flat_mask(
...     data=raw_data,
...     rocking_angle_binning=2,
...     binning_method="sum"
... )
static bin_rocking_angle_values(values, binning_factor=None)[source]#

Bin rocking angle values to match binned detector frames.

Averages angle values when frames are binned together. Used to maintain synchronisation between data and motor positions.

Parameters:
  • values (list | ndarray) – Rocking angle values for each frame (e.g., delta, omega motor positions). Length must match original number of frames.

  • binning_factor (int) – Number of consecutive frames to average. If None or 1, returns input unchanged.

Returns:

Binned angle values with length len(values)//binning_factor. Uses mean binning to get average angle per binned frame.

Return type:

ndarray

abstract load_energy()[source]#

Load X-ray beam energy for the scan.

Must be implemented by beamline-specific subclass.

Returns:

Beam energy in keV.

abstract load_det_calib_params()[source]#

Load detector calibration parameters from experiment file.

Must be implemented by beamline-specific subclass. Typically reads values stored during detector alignment procedure.

Returns:

Calibration parameters with keys:

  • "direct_beam": (y, x) pixel coordinates of direct beam position

  • "detector_distance": sample-to-detector distance in metres

  • "outofplane_angle": detector rotation delta or gamma in degrees

  • "inplane_angle": detector rotation nu in degrees

Return type:

dict

See also

Detector Geometry Calibration for calibration procedures and parameter definitions.

abstract load_detector_shape()[source]#

Load detector’s native pixel array shape.

Must be implemented by beamline-specific subclass if detector shape cannot be determined from data files.

Returns:

Detector shape as (n_rows, n_columns) tuple, or None if shape is determined from data.

get_detector_name()[source]#

Get canonical detector identifier for this beamline.

Returns the first name from authorised_detector_names, which is the standard identifier for detector geometry calculations.

Returns:

Detector name string (e.g., "Eiger2M", "Maxipix", "Lambda750k").

Return type:

str

static get_rocking_angle(angles)[source]#

Identify which motor was scanned during rocking curve.

Determines whether out-of-plane or in-plane angle was varied based on which array has more than one unique value. Used to automatically detect scan geometry.

Parameters:

angles (dict) –

Dictionary with keys:

  • "sample_outofplane_angle": omega or eta values (scalar or array)

  • "sample_inplane_angle": chi or phi values (scalar or array)

Returns:

Name of scanned angle key, or None if neither angle was scanned (single-frame measurement).

Return type:

str | None

Examples

Out-of-plane scan (typical):

>>> angles = {
...     "sample_outofplane_angle": np.linspace(30.0, 30.5, 51),
...     "sample_inplane_angle": 0.0
... }
>>> Loader.get_rocking_angle(angles)
'sample_outofplane_angle'

In-plane scan (grazing incidence):

>>> angles = {
...     "sample_outofplane_angle": 2.0,
...     "sample_inplane_angle": np.linspace(-10, 10, 41)
... }
>>> Loader.get_rocking_angle(angles)
'sample_inplane_angle'
static format_scanned_counters(*counters, scan_axis_roi=None, rocking_angle_binning=None)[source]#

Preprocess motor positions to match ROI and binning of data.

Applies same binning and ROI selection to motor counter arrays as applied to detector data, maintaining synchronisation between intensity and position information.

Parameters:
  • *counters (float | ndarray | list) –

    One or more motor position values. Each can be:

    • Scalar: Fixed motor position (e.g., 30.0 degrees)

    • Array: Scanned motor positions (one per frame)

  • scan_axis_roi (tuple[slice]) – ROI slice along rocking curve axis (first dimension). Applied after binning. Typically (slice(start, stop),).

  • rocking_angle_binning (int) – Binning factor for scanned arrays. Scalar values are unaffected.

Returns:

Formatted counter(s) with same type as input. If multiple counters provided, returns tuple in same order. If single counter, returns that value directly.

Examples

Single scanned angle with binning:

>>> omega = np.linspace(30.0, 30.5, 100)
>>> formatted = Loader.format_scanned_counters(
...     omega,
...     rocking_angle_binning=2
... )
>>> # Returns array of length 50

Multiple counters with ROI:

>>> omega = np.linspace(30.0, 30.5, 100)
>>> energy = 8.5  # fixed
>>> omega_fmt, energy_fmt = Loader.format_scanned_counters(
...     omega, energy,
...     scan_axis_roi=(slice(10, 90),)
... )
>>> # omega_fmt has 80 values, energy_fmt is 8.5
classmethod get_mask(detector_name=None, channel=None, roi=None)[source]#

Generate detector-specific bad pixel mask.

Returns hardcoded masks for common BCDI detectors, marking chip gaps and known bad pixel regions. Masks are detector-specific due to different chip layouts and geometries.

Parameters:
  • detector_name (str) –

    Detector identifier (case-insensitive). Supported detectors:

    • Maxipix: "maxipix", "mpxgaas", "mpx4inr"

    • Eiger2M: "Eiger2M", "eiger2m"

    • Eiger4M: "Eiger4M", "eiger4m", "e4m"

    • Eiger9M: "eiger9m", "e9m"

    • Eiger500k: "eiger500k", "e2500"

    • Merlin: "merlin"

    If None and called as instance method, uses self.detector_name.

  • channel (int) – If provided, extends 2D mask to 3D by repeating along first axis (for 3D data). Specifies number of frames.

  • roi (tuple[slice]) – ROI applied after mask generation. See _check_roi() for format. Typically (slice(y1,y2), slice(x1,x2)) for 2D.

Returns:

  • 2D: detector_shape if no ROI

  • 2D: cropped to ROI if provided

  • 3D: (channel, n_y, n_x) if channel specified

Return type:

Binary mask array (1 = bad pixel, 0 = good pixel). Shape is

Raises:

ValueError – If detector_name is not recognized or if called as class method without providing detector_name.

Examples

Instance method (uses loader’s detector):

>>> loader = ID01Loader(scan=42, ...)
>>> mask = loader.get_mask(channel=100)
>>> # Returns (100, 2164, 1030) Eiger2M mask

Class method with explicit detector:

>>> mask = Loader.get_mask(detector_name="Maxipix")
>>> # Returns (516, 516) Maxipix mask

With ROI:

>>> roi = (slice(100, 400), slice(200, 800))
>>> mask = Loader.get_mask(
...     detector_name="Eiger2M",
...     roi=roi
... )
>>> # Returns (300, 600) cropped mask

Notes

Eiger masks include:

  • Chip gaps (horizontal and vertical)

  • Module boundaries

  • Known bad pixel clusters

Maxipix masks include central cross gaps (256±3 pixels).

static plot_detector_data(data, title=None, return_fig=False, equal_limits=False, **plot_params)[source]#

Quick visualisation of 2D or 3D detector data.

Creates diagnostic plots showing orthogonal slices (for 3D data) or single 2D image. Uses log-scale colouring by default for dynamic range typical of BCDI diffraction patterns.

Parameters:
  • data (ndarray) – Detector data array. If 3D, shape is (n_frames, n_y, n_x). If 2D, shape is (n_y, n_x).

  • title (str) – Plot title displayed above figure. If None, no title shown.

  • return_fig (bool) – If True, returns Figure object for further customisation. If False (default), displays figure interactively.

  • equal_limits (bool) – If True, uses same axis limits for all subplots (helpful for comparing slice scales). If False, each plot uses its own optimal limits.

  • **plot_params

    Additional arguments passed to matplotlib.pyplot.imshow(). Defaults are:

    • norm="log": Logarithmic colour scale

    • origin="upper": [0,0] at top-left

    • cmap="turbo": Rainbow-like colourmap

Returns:

If return_fig=True, returns matplotlib Figure object. Otherwise, displays interactively and returns None.

Return type:

Figure

Examples

Quick 3D data check:

>>> data = loader.load_data(scan=42)
>>> Loader.plot_detector_data(data, title="Scan 42")

Custom colouring:

>>> Loader.plot_detector_data(
...     data,
...     cmap="viridis",
...     norm="linear",
...     vmin=0,
...     vmax=1e5
... )

Save figure for publication:

>>> fig = Loader.plot_detector_data(data, return_fig=True)
>>> fig.savefig("detector_scan42.png", dpi=300)

Notes

For 3D data, creates 2×3 subplot grid:

  • Top row: Central slices along each axis

  • Bottom row: Sum projections along each axis

This quickly reveals Bragg peak position and rocking curve quality.

cdiutils.io.loader.h5_safe_load(func)[source]#

A wrapper to safely load data in h5 file

class cdiutils.io.loader.H5TypeLoader(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None)[source]#

Bases: Loader

A child class of Loader for H5-type loaders.

__init__(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None)[source]#

Initialise the base Loader.

Typically called by subclass constructors. Users should prefer from_setup() factory method or direct subclass instantiation.

Parameters:
  • scan (int) – Scan number identifier. Required for data loading.

  • sample_name (str) – Sample identifier used in file paths and logging.

  • flat_field (ndarray | str) – Flat-field correction array or path to .npy/.npz file. Applied as multiplicative correction to detector data. Shape must match detector dimensions. Defaults to None (no correction).

  • alien_mask (ndarray | str) – Bad pixel mask array or path to .npy/.npz file. Pixels with value 1 are masked (invalid), 0 are kept. Shape must match detector. Defaults to None (no masking).

Raises:

ValueError – If flat_field or alien_mask path is invalid or file format is unsupported.

load_angles(*args, **kwargs)[source]#
class cdiutils.io.id01.ID01Loader(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, **kwargs)[source]#

Bases: H5TypeLoader

Data loader for ESRF ID01 beamline (BLISS acquisition).

Handles HDF5 master files produced by BLISS control software at ID01, supporting Maxipix and Eiger2M detectors. Provides detector calibration, motor angles, and beam energy from scan metadata.

This loader is for modern BLISS-based experiments. For legacy SPEC format data (pre-2020), use SpecLoader instead.

angle_names#

Mapping from canonical names to ID01 motor names:

  • sample_outofplane_angle -> "eta"

  • sample_inplane_angle -> "phi"

  • detector_outofplane_angle -> "delta"

  • detector_inplane_angle -> "nu"

authorised_detector_names#

Tuple of supported detectors: ("mpxgaas", "mpx1x4", "eiger2M").

Examples

Basic usage with factory pattern:

>>> from cdiutils.io import Loader
>>> loader = Loader.from_setup(
...     beamline_setup="id01",
...     scan=42,
...     sample_name="PtNP",
...     experiment_file_path="/data/id01/sample.h5"
... )

Direct instantiation:

>>> from cdiutils.io.id01 import ID01Loader
>>> loader = ID01Loader(
...     experiment_file_path="/data/id01/sample.h5",
...     scan=42,
...     sample_name="PtNP",
...     detector_name="eiger2M"
... )

Load data with preprocessing:

>>> data, angles = loader.load_data(
...     roi=(100, 400, 150, 450),
...     rocking_angle_binning=2
... )

See also

SpecLoader for legacy SPEC format data. Loader for factory method and base class documentation.

angle_names = {'detector_inplane_angle': 'nu', 'detector_outofplane_angle': 'delta', 'sample_inplane_angle': 'phi', 'sample_outofplane_angle': 'eta'}#
authorised_detector_names = ('mpxgaas', 'mpx1x4', 'eiger2M')#
__init__(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, **kwargs)[source]#

Initialise ID01 data loader with experiment file and metadata.

Parameters:
  • experiment_file_path (str) – Path to BLISS HDF5 master file (typically sample_name.h5). File must contain scan groups in format {sample}_{scan}.1/.

  • scan (int) – Scan number to load. If None, must be specified in subsequent load_data() calls.

  • sample_name (str) – Sample identifier matching HDF5 group names. Required to construct scan paths.

  • detector_name (str) – Detector identifier ("mpxgaas", "mpx1x4", or "eiger2M"). If None, automatically detected from first available scan.

  • flat_field (ndarray | str) – Flat-field correction array or path to .npy/.npz file. Shape must match detector’s 2D frame. Applied multiplicatively to raw data.

  • alien_mask (ndarray | str) – Bad pixel mask array or path. Binary mask with 1 = bad pixel, 0 = good pixel. Combined with detector’s chip gap mask.

  • **kwargs – Additional parameters (currently unused, reserved for future extensions).

Raises:
  • FileNotFoundError – If experiment_file_path does not exist.

  • ValueError – If detector_name is not in authorised_detector_names.

  • KeyError – If scan or sample_name do not match HDF5 structure.

Examples

Minimal setup (auto-detect detector):

>>> loader = ID01Loader(
...     experiment_file_path="/data/id01/PtNP.h5",
...     scan=42,
...     sample_name="PtNP"
... )

With flat-field and detector specification:

>>> loader = ID01Loader(
...     experiment_file_path="/data/id01/sample.h5",
...     scan=100,
...     sample_name="sample",
...     detector_name="eiger2M",
...     flat_field="/path/to/flatfield.npy"
... )
get_detector_name(*args, **kwargs)#

Get canonical detector identifier for this beamline.

Returns the first name from authorised_detector_names, which is the standard identifier for detector geometry calculations.

Returns:

Detector name string (e.g., "Eiger2M", "Maxipix", "Lambda750k").

load_det_calib_params(*args, **kwargs)#

Load detector calibration parameters from experiment file.

Must be implemented by beamline-specific subclass. Typically reads values stored during detector alignment procedure.

Returns:

Calibration parameters with keys:

  • "direct_beam": (y, x) pixel coordinates of direct beam position

  • "detector_distance": sample-to-detector distance in metres

  • "outofplane_angle": detector rotation delta or gamma in degrees

  • "inplane_angle": detector rotation nu in degrees

Return type:

dict

See also

Detector Geometry Calibration for calibration procedures and parameter definitions.

load_detector_shape(*args, **kwargs)#

Load detector’s native pixel array shape.

Must be implemented by beamline-specific subclass if detector shape cannot be determined from data files.

Returns:

Detector shape as (n_rows, n_columns) tuple, or None if shape is determined from data.

load_detector_data(*args, **kwargs)#
load_motor_positions(*args, **kwargs)#
load_energy(*args, **kwargs)#

Load X-ray beam energy for the scan.

Must be implemented by beamline-specific subclass.

Returns:

Beam energy in keV.

show_scan_attributes(*args, **kwargs)#
load_measurement_parameters(*args, **kwargs)#
load_instrument_parameters(*args, **kwargs)#
load_sample_parameters(*args, **kwargs)#
load_plotselect_parameter(*args, **kwargs)#
get_start_time(*args, **kwargs)#
cdiutils.io.id01.safe(func)[source]#
class cdiutils.io.id01.SpecLoader(experiment_file_path, detector_data_path, edf_file_template, detector_name, scan=None, flat_field=None, alien_mask=None, **kwargs)[source]#

Bases: Loader

A loader for loading .spec files.

angle_names = {'detector_inplane_angle': 'nu', 'detector_outofplane_angle': 'del', 'sample_inplane_angle': 'phi', 'sample_outofplane_angle': 'eta'}#
__init__(experiment_file_path, detector_data_path, edf_file_template, detector_name, scan=None, flat_field=None, alien_mask=None, **kwargs)[source]#

Initialise SpecLoader with experiment data and detector information.

Parameters:
  • experiment_file_path (str) – path to the spec master file used for the experiment.

  • detector_data_path (str) – the path to the directory containing the detector data.

  • edf_file_template (str) – the file name template of the detector data frame.

  • detector_name (str) – name of the detector.

  • scan (int, optional) – the scan number. Defaults to None.

  • flat_field (str | np.ndarray, optional) – flat field to account for the non homogeneous counting of the detector. Defaults to None.

  • alien_mask (np.ndarray | str, optional) – array to mask the aliens. Defaults to None.

load_detector_data(*args, **kwargs)[source]#
load_motor_positions(*args, **kwargs)[source]#
load_det_calib_params()[source]#

Load detector calibration parameters from experiment file.

Must be implemented by beamline-specific subclass. Typically reads values stored during detector alignment procedure.

Returns:

Calibration parameters with keys:

  • "direct_beam": (y, x) pixel coordinates of direct beam position

  • "detector_distance": sample-to-detector distance in metres

  • "outofplane_angle": detector rotation delta or gamma in degrees

  • "inplane_angle": detector rotation nu in degrees

Return type:

dict

See also

Detector Geometry Calibration for calibration procedures and parameter definitions.

load_energy()[source]#

Load X-ray beam energy for the scan.

Must be implemented by beamline-specific subclass.

Returns:

Beam energy in keV.

Return type:

float

load_detector_shape()[source]#

Load detector’s native pixel array shape.

Must be implemented by beamline-specific subclass if detector shape cannot be determined from data files.

Returns:

Detector shape as (n_rows, n_columns) tuple, or None if shape is determined from data.

Return type:

tuple

class cdiutils.io.p10.P10Loader(experiment_data_dir_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, hutch='EH1', **kwargs)[source]#

Bases: Loader

Data loader for PETRA III P10 beamline.

Handles HDF5 master files and .fio motor position files from P10 beamline at PETRA III, supporting Eiger4M and Eiger500k detectors. Data is organised in separate directories per scan.

angle_names#

Mapping from canonical names to P10 motor names:

  • sample_outofplane_angle -> "om" (EH1) or "samth" (EH2)

  • sample_inplane_angle -> "phi" (EH1 only)

  • detector_outofplane_angle -> "del" (EH1) or "e2_t02" (EH2)

  • detector_inplane_angle -> "gam" (EH1 only)

authorised_detector_names#

Tuple of supported detectors: ("eiger4m", "e2500").

Notes

EH2 (experimental hutch 2) has different motor names and lacks in-plane rotation stages. Specify hutch="EH2" during initialisation for EH2 experiments.

See also

Loader for factory method and base class documentation.

angle_names = {'detector_inplane_angle': 'gam', 'detector_outofplane_angle': 'del', 'sample_inplane_angle': 'phi', 'sample_outofplane_angle': 'om'}#
authorised_detector_names = ('eiger4m', 'e2500')#
__init__(experiment_data_dir_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, hutch='EH1', **kwargs)[source]#

Initialise P10 data loader.

Parameters:
  • experiment_data_dir_path (str) – Root data directory containing scan subdirectories. Expected structure: {root}/{sample}_{scan:05d}/{detector}/.

  • scan (int) – Scan number (5-digit zero-padded in file paths).

  • sample_name (str) – Sample identifier matching directory names.

  • detector_name (str) – Detector identifier ("eiger4m" or "e2500"). If None, defaults to "e4m".

  • flat_field (ndarray | str) – Flat-field correction array or path to .npy/.npz file.

  • alien_mask (ndarray | str) – Bad pixel mask array or path.

  • hutch (str) – Experimental hutch ("EH1" or "EH2"). Affects motor name mappings. Defaults to "EH1".

  • **kwargs – Additional parameters (reserved for future use).

Raises:

ValueError – If hutch is not "EH1" or "EH2".

load_detector_data(scan=None, sample_name=None, roi=None, rocking_angle_binning=None, binning_method='sum')[source]#

Load raw detector frames from P10 HDF5 file.

Retrieves 3D detector data array with optional ROI, binning, flat-field correction, and masking. Automatically applies detector chip gap mask for Eiger detectors.

Parameters:
  • scan (int) – Scan number. If None, uses self.scan.

  • sample_name (str) – Sample name. If None, uses self.sample_name.

  • roi (tuple[slice]) – Region of interest as tuple of slices or integers.

  • rocking_angle_binning (int) – Binning factor along rocking curve axis.

  • binning_method (str) – Binning operation ("sum", "mean", or "max"). Default "sum".

Returns:

Preprocessed detector data with shape (n_frames//binning, n_y, n_x).

Return type:

None

load_motor_positions(scan=None, sample_name=None, roi=None, rocking_angle_binning=None)[source]#

Load diffractometer motor angles from .fio file.

Parses P10’s text-based .fio files to extract motor positions, applying same ROI and binning as detector data.

Parameters:
  • scan (int) – Scan number. If None, uses self.scan.

  • sample_name (str) – Sample name. If None, uses self.sample_name.

  • roi (tuple[slice]) – ROI tuple. Only first element (rocking curve axis) is used.

  • rocking_angle_binning (int) – Binning factor matching detector binning. Angles are averaged when binned.

Returns:

Motor angles with canonical keys (see angle_names for P10-specific mapping). Values are scalars (fixed motor) or 1D arrays (scanned motor).

Return type:

dict

load_energy(scan=None, sample_name=None)[source]#

Load X-ray beam energy from .fio file.

Parameters:
  • scan (int) – Scan number. If None, uses self.scan.

  • sample_name (str) – Sample name. If None, uses self.sample_name.

Returns:

Beam energy in eV from fmbenergy motor, or None if not found.

Return type:

float

load_det_calib_params()[source]#

Load detector calibration parameters.

Returns:

None. P10 does not store calibration in scan files. Calibration must be determined separately.

Return type:

dict

load_detector_shape(scan=None)[source]#

Load detector shape.

Returns:

None. Shape is determined from data files directly.

Return type:

tuple

class cdiutils.io.sixs.SIXSLoader(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, version=None, **kwargs)[source]#

Bases: H5TypeLoader

A class for loading data from SIXS beamline experiments.

angle_names = {'detector_inplane_angle': 'delta', 'detector_outofplane_angle': 'gamma', 'sample_inplane_angle': 'omega', 'sample_outofplane_angle': 'mu'}#
authorised_detector_names = ('maxipix',)#
__init__(experiment_file_path, scan=None, sample_name=None, detector_name=None, flat_field=None, alien_mask=None, version=None, **kwargs)[source]#

Initialise SIXSLoader with experiment data directory path and detector information.

Parameters:
  • experiment_file_path (str) – path to the experiment file.

  • detector_name (str) – name of the detector.

  • sample_name (str, optional) – name of the sample. Defaults to None.

  • flat_field (np.ndarray | str, optional) – flat field to account for the non homogeneous counting of the detector. Defaults to None.

  • alien_mask (np.ndarray | str, optional) – array to mask the aliens. Defaults to None.

  • version (str, optional) – the version of the loader. Defaults to None.

load_detector_data(*args, **kwargs)#
load_motor_positions(*args, **kwargs)#
load_det_calib_params()[source]#

Load detector calibration parameters from experiment file.

Must be implemented by beamline-specific subclass. Typically reads values stored during detector alignment procedure.

Returns:

Calibration parameters with keys:

  • "direct_beam": (y, x) pixel coordinates of direct beam position

  • "detector_distance": sample-to-detector distance in metres

  • "outofplane_angle": detector rotation delta or gamma in degrees

  • "inplane_angle": detector rotation nu in degrees

Return type:

dict

See also

Detector Geometry Calibration for calibration procedures and parameter definitions.

load_energy(*args, **kwargs)#

Load X-ray beam energy for the scan.

Must be implemented by beamline-specific subclass.

Returns:

Beam energy in keV.

load_detector_shape(*args, **kwargs)#

Load detector’s native pixel array shape.

Must be implemented by beamline-specific subclass if detector shape cannot be determined from data files.

Returns:

Detector shape as (n_rows, n_columns) tuple, or None if shape is determined from data.

Loader for the Nanomax beamline at MAXIV. See: https://www.maxiv.lu.se/beamlines-accelerators/beamlines/nanomax/

class cdiutils.io.nanomax.NanoMAXLoader(experiment_file_path, detector_name='eiger500k', flat_field=None, alien_mask=None, **kwargs)[source]#

Bases: H5TypeLoader

Data loader for MAX IV NanoMAX beamline.

Handles HDF5 files from NanoMAX beamline at MAX IV, supporting Eiger500k detector. NanoMAX has simpler file structure than other beamlines - no separate sample_name or scan number parameters needed.

angle_names#

Mapping from canonical names to NanoMAX motor names:

  • sample_outofplane_angle -> "gontheta"

  • sample_inplane_angle -> "gonphi"

  • detector_outofplane_angle -> "delta"

  • detector_inplane_angle -> "gamma"

authorised_detector_names#

Tuple of supported detectors: ("eiger500k",).

Notes

Unlike other beamlines, NanoMAX stores all data in a single HDF5 file per measurement, eliminating need for sample_name or scan parameters in most methods.

See also

Loader for factory method and base class documentation.

angle_names = {'detector_inplane_angle': 'gamma', 'detector_outofplane_angle': 'delta', 'sample_inplane_angle': 'gonphi', 'sample_outofplane_angle': 'gontheta'}#
authorised_detector_names = ('eiger500k',)#
__init__(experiment_file_path, detector_name='eiger500k', flat_field=None, alien_mask=None, **kwargs)[source]#

Initialise NanoMAX data loader.

Parameters:
  • experiment_file_path (str) – Path to HDF5 scan file. Contains all data and metadata for the measurement.

  • detector_name (str) – Detector identifier. Defaults to "eiger500k".

  • flat_field (ndarray | str) – Flat-field correction array or path to .npy/.npz file.

  • alien_mask (ndarray | str) – Bad pixel mask array or path.

  • **kwargs – Additional parameters (reserved for future use).

load_detector_data(*args, **kwargs)#
load_motor_positions(*args, **kwargs)#
load_energy(*args, **kwargs)#

Load X-ray beam energy for the scan.

Must be implemented by beamline-specific subclass.

Returns:

Beam energy in keV.

load_det_calib_params()[source]#

Load detector calibration parameters from experiment file.

Must be implemented by beamline-specific subclass. Typically reads values stored during detector alignment procedure.

Returns:

Calibration parameters with keys:

  • "direct_beam": (y, x) pixel coordinates of direct beam position

  • "detector_distance": sample-to-detector distance in metres

  • "outofplane_angle": detector rotation delta or gamma in degrees

  • "inplane_angle": detector rotation nu in degrees

Return type:

dict

See also

Detector Geometry Calibration for calibration procedures and parameter definitions.

load_detector_shape(*args, **kwargs)#

Load detector’s native pixel array shape.

Must be implemented by beamline-specific subclass if detector shape cannot be determined from data files.

Returns:

Detector shape as (n_rows, n_columns) tuple, or None if shape is determined from data.

File Formats#

CXI Format#

A submodule for cxi file handling. The CXIFile class provides methods to make CXI-compliant HDF5 files.

class cdiutils.io.cxi.CXIFile(file_path, mode='r')[source]#

Bases: object

CXI-compliant HDF5 file handler for BCDI data storage.

Implements the CXI (Coherent X-ray Imaging) file format specification for storing BCDI reconstruction data, metadata, and processing history. Provides high-level methods for creating groups, datasets, and soft links following NeXus conventions.

The CXI format organises data hierarchically:
  • entry_N: top-level groups for each dataset

  • image_N: detector images and metadata

  • process_N: reconstruction algorithms and parameters

  • result_N: final reconstruction results

See also

CXI format specification: cxidb/CXI

IMAGE_MEMBERS = ('title', 'data', 'data_error', 'data_space', 'data_type', 'detector_', 'dimensionality', 'image_center', 'image_size', 'is_fft_shifted', 'mask', 'process_', 'reciprocal_coordinates', 'source_')#
__init__(file_path, mode='r')[source]#

Initialise CXI file handler.

Parameters:
  • file_path (str) – path to .cxi file.

  • mode (str) – file access mode (‘r’, ‘w’, ‘a’). Defaults to ‘r’ (read-only).

property entry_counters: None#
property current_entry: None#
open(mode=None)[source]#

Open the CXI file in specified mode.

close()[source]#

Close the CXI file.

get_node(path)[source]#

Retrieve the raw node (dataset or group) at the specified path. Allow direct access to entries with cxi[path].

Parameters:

path (str) – Path to the node.

Returns:

The h5py Dataset or Group object.

copy(source_path, dest_file=None, dest_path=None, **kwargs)[source]#

Copy a group or dataset from this CXI file to another location, either within the same file or to a different CXI file.

Parameters:
  • source_path (str) – Path to the object to copy in the source file.

  • dest_file (CXIFile or h5py.File, optional) – Destination file object. If None, the copy will be within the same file. Defaults to None.

  • dest_path (str, optional) – Path in the destination file. If None, defaults to source_path in the destination. Defaults to None.

  • **kwargs – Additional arguments for h5py copy method (e.g., shallow, expand_soft).

Raises:

KeyError – if the source_path does not exist in the CXI file.

set_entry(index=None)[source]#

Create or switch to a specific entry group (e.g., ‘entry_1’).

create_cxi_group(group_type, default=None, index=None, attrs=None, **kwargs)[source]#

Create a CXI-compliant group with optional NeXus class.

Parameters:
  • group_type (str) – the type of group (e.g., ‘image’, ‘process’).

  • default (str, optional) – the default hdf5 attribute. If not provided will use the one stored in GROUP_ATTRIBUTES. Defaults to None.

  • index (int, optional) – explicit index. If None, the next available index is used. Defaults to None.

  • attrs (dict) – Additional attributes for the group.

  • **kwargs – the data to save in the CXI group.

Returns:

The full path of the created group.

Return type:

str

create_group(path, nx_class=None, attrs=None)[source]#

Method to handle the creation of groups in the context of H5 files, not in the context of CXI.

Parameters:
  • path (str) – the path to create the group at

  • nx_class (str, optional) – NeXus class for the group. Defaults to None.

  • attrs (dict, optional) – Additional attributes for the group.

returns: True if the group was created else False (i.e. if

group already exists).

create_cxi_dataset(path, data, dtype=None, nx_class=None, **attrs)[source]#

Create a CXI-compliant dataset with optional NeXus class.

Parameters:
  • path (str) – The path to the dataset.

  • data – The data to store in the dataset (can be a dict).

  • dtype (data-type, optional) – The data type for the dataset. Defaults to None.

  • nx_class (str, optional) – The NeXus class for the dataset, if applicable. Defaults to None.

Returns:

the dataset or group instance created.

Return type:

h5py.Dataset

read_cxi_dataset(path)[source]#

Read a dataset or group and handle inhomogeneous lists.

Parameters:

path (str) – Path to the dataset or group.

Returns:

The reassembled data, either as the original inhomogeneous list or a standard dataset.

Create a soft link at the specified path pointing to an existing target path.

Parameters:
  • path (str) – the path where the soft link will be created.

  • target (str) – the target path that the soft link points to.

Raises:

ValueError – if the target path does not exist in self.file.

stamp()[source]#

Add metadata to the CXI file, recording information about the software and file creation details.

create_cxi_image(data, link_data=True, **members)[source]#

Create a minimal CXI image entry with associated metadata and soft links.

Parameters:
  • data (np.ndarray) – the image data.

  • link_data (bool, optional) – whether to link to a data_N group. Defaults to True.

  • **members – additional members to add to the image group. Keys ending in a digit will be indexed accordingly.

Returns:

The full path of the created group.

Return type:

str

get_explorer()#

Create and return a CXIExplorer for this CXI file.

Returns:

An explorer instance for this file

Return type:

CXIExplorer

cdiutils.io.cxi.save_as_cxi(output_path, **to_be_saved)[source]#

A helper function to quickly save data to a CXI file without dealing with CXIFile complexity. However, this function is less flexible than using CXIFile directly.

Parameters:
  • output_path (str) – the path to save the CXI file.

  • to_be_saved (dict) – the data to save in the CXI file.

cdiutils.io.cxi.load_cxi(path, *key)[source]#

Load a CXI file and return its content as a dictionary.

Parameters:

path (str) – the path to the CXI file.

Returns:

the content of the CXI file. If a single

key_path is provided, returns the corresponding dataset. If multiple key_paths are provided, returns a dictionary with the datasets.

Return type:

np.ndarray or dict

VTK Format#

exception cdiutils.io.vtk.VtkImportError(msg=None)[source]#

Bases: ImportError

Custom exception to handle Vtk import error.

__init__(msg=None)[source]#
cdiutils.io.vtk.load_vtk(file_path)[source]#

Load a vtk file.

Parameters:

file_path (_type_) – the path to the file to open.

Raises:

VtkImportError – if vtk is not installed.

Returns:

the reader output

cdiutils.io.vtk.save_as_vti(output_path, voxel_size, cxi_convention=False, origin=(0, 0, 0), **np_arrays)[source]#

Save numpy arrays to .vti file.