LION.data_loaders.deteCT

Classes

deteCT(mode[, operator_params, parameters])

The 2DeteCT dataset: 5,000 slices of 109 scanned samples (fruit, nuts and other objects), each measured in three modes.


class LION.data_loaders.deteCT.deteCT(mode, operator_params=None, parameters=None)[source]

Bases: LIONDataset

The 2DeteCT dataset: 5,000 slices of 109 scanned samples (fruit, nuts and other objects), each measured in three modes:

             |  mode1   |   mode2  |  mode3
Tube Voltage |   90kV   |   90kV   |  60kV
Tube power   |    3W    |    90W   |  60W
Filter       | Thoraeus | Thoraeus | No Filter
Meaning      | Low Dose | High Dose| Beam hardening

Detectors: the data were acquired with two detectors, recorded in the detector column of the data record. Detector 1: samples 1-63 (slices 1-2830, mixes 1-2); detector 2: samples 64-109 (slices 2831-5000, mixes 2-3). Their noise differs: with the same tube settings, detector 2 gets about a third of the photons of detector 1 (MODE1_I0_PER_DETECTOR). Samples are split in order (training_proportion, validation_proportion), so with the default 0.8/0.1/0.1 the validation and test sets are all detector 2, and the training set is mostly detector 1.

Added noise (add_noise and noise_params): add_sinogram_noise adds Poisson noise and detector cross-talk to the measured (already noisy) sinograms, as in Kiss et al. 2024. noise_params.I0 is either

  • a number: the same I0 for every slice, as LION did before October 2026 and as Kiss et al. 2024 did (I0 = 200 to look like mode1); or

  • a dict {detector: I0}: one I0 per detector, so that the simulated noise follows each detector’s real noise. deteCT.noise_parameters() gives MODE1_I0_PER_DETECTOR, which looks like mode1 on each detector.

Samples are returned on LION’s selected device, default_device() (read and given their added noise on the CPU, so the noise doesn’t depend on the device).

The mode split (“train”, “validation” or “test”) with parameters (default_parameters() if None). operator_params: the geometry, replacing parameters.operator_params if given.

parameters (default_parameters()):

  • path_to_dataset: the pre-processed dataset (2deteCT/pre_process_2deteCT.py);

  • input_mode, target_mode: “mode1”, “mode2” or “mode3” (“mode2”, “mode2”);

  • task: what a sample is: “sino2recon” (default), “sino2sino”, “recon2recon”, “recon2sino”, “recon2seg”, “sino2seg”, “joint” or “groundtruth”;

  • training_proportion, validation_proportion, test_proportion: of the samples, split in order (0.8, 0.1, 0.1);

  • do_recon: reconstruct the images here, with recon_algo (“nag_ls” or “fdk”), instead of loading the dataset’s (False);

  • flat_field_correction, dark_field_correction, log_transform: of the raw projections (True);

  • query: a pandas query of the data record, to select slices (e.g. “detector==1”; “”: all);

  • add_noise: add noise to the sinograms (False), with noise_params (noise_parameters());

  • operator_params: the geometry: 2DeteCT’s (get_default_geometry()), or one with a subset of its angles (the sinograms are subsampled to match; others are refused, as the data are measured).

static default_parameters()[source]

The parameters (see __init__): mode 2 sinograms to mode 2 reconstructions, corrected and log-transformed, no added noise.

static get_default_geometry()[source]

The 2DeteCT geometry (from Max Kiss’s code): fan beam, 3600 angles over 360 degrees, a 956-pixel detector (2x subsampled), 1024x1024 images, lengths in voxels.

static get_default_operator()[source]

The CT operator of the default geometry.

get_operator()[source]

The CT operator of the dataset’s geometry.

sample_ids()[source]

What each sample is, in order: its slice identifier.

sample_groups()[source]

The group of each sample, in order: the physical sample (mix) its slice is from, by which the splits are made.

sample_files()[source]

The files the samples are read from, in order: those of each slice’s input and target modes.

compute_sample_dataframe()[source]

self.sample_dataframe: the first and last slice of each physical sample (mix), from the slice table.

static noise_parameters(I0=None, cross_talk=0.05)[source]

noise_params for add_noise: by default the I0 of each detector that makes mode2 plus the added noise look like that detector’s mode1 (MODE1_I0_PER_DETECTOR). I0 can be a number (the same for every slice, LION’s behaviour before October 2026) or a dict {detector: I0}. cross_talk: fraction of the signal of the neighbouring detector pixels (0.05, from XCIST).

noise_I0(index)[source]

The I0 of the added noise for the slice at index: noise_params.I0 if it is a number, else the I0 of the slice’s detector.

add_sinogram_noise(sinogram, I0, cross_talk=0.05)[source]

The measured sinogram (flat-field corrected and log transformed) with more noise, as if measured with I0 photons per detector pixel (Kiss et al. 2024).

LION’s noise simulation (ct_utils.sinogram_add_noise) assumes a noiseless sinogram; a measured one already has noise. Here the measured sinogram is taken to have photon counts high enough that its own Poisson noise can be ignored: the noise added is the Poisson noise at I0 counts, P, convolved with the detector’s cross-talk (each pixel leaking cross_talk into its two neighbours), so in counts the noisy measurement is I0 exp(-sinogram) + crosstalk(P). An approximation.

The data loader passes noise_I0(index): one I0 per detector when noise_params.I0 is a dict (see the class docstring).

static cite(cite_format='bib')[source]

The 2DeteCT dataset, BibTeX (“bib”) or “MLA”.