autods_pet.imaging#

Imaging subpackage: DICOM, normalization, registration, segmentation.

autods_pet.imaging.compute_suvbw(pet_bqml, weight_kg, dose_bq)[source]#

Convert a PET image from Bq/mL to SUV body-weight.

Parameters:
  • pet_bqml (Image) – PET image in Bq/mL units.

  • weight_kg (float) – Patient body weight in kg.

  • dose_bq (float) – Effective injected dose in Bq (after decay correction if needed).

Returns:

PET image in SUVbw units (float64).

Return type:

Image

autods_pet.imaging.decay_dose(dose_bq, half_life_s, elapsed_s)[source]#

Apply radioactive decay: dose * exp(-lambda * t).

Parameters:
  • dose_bq (float) – Initial dose in Bq.

  • half_life_s (float) – Radionuclide half-life in seconds.

  • elapsed_s (float) – Time elapsed since injection in seconds.

Returns:

Decayed dose in Bq.

Return type:

float

Examples

>>> from autods_pet.imaging.normalization import decay_dose
>>> round(decay_dose(370e6, 6586.2, 3600), 1)
253314180.2
autods_pet.imaging.dicom_series_to_nifti(dicom_files, output_path)[source]#

Convert a DICOM series to a NIfTI file.

Uses SimpleITK’s ImageSeriesReader with GDCM-based spatial ordering to ensure correct slice order.

Parameters:
  • dicom_files (Sequence[str | Path]) – File paths belonging to a single DICOM series.

  • output_path (str | Path) – Where to write the NIfTI file.

Returns:

The loaded image (also written to output_path).

Return type:

Image

autods_pet.imaging.effective_dose(total_dose_bq, half_life_s, elapsed_s, decay_correction)[source]#

Determine the effective reference dose depending on the DICOM DecayCorrection tag.

Parameters:
  • total_dose_bq (float) – Injected radionuclide dose in Bq.

  • half_life_s (float) – Radionuclide half-life in seconds.

  • elapsed_s (float) – Seconds between injection and acquisition.

  • decay_correction (str) – DICOM DecayCorrection value (e.g. "NONE", "START", "ADMIN").

Returns:

Dose in Bq to use as the SUV denominator.

Return type:

float

autods_pet.imaging.extract_ct_tags(dicom_path)[source]#

Extract CT metadata tags from a single DICOM file.

Returns:

CT-relevant tags. Missing tags are set to None.

Return type:

dict[str, Any]

Parameters:

dicom_path (str | Path)

autods_pet.imaging.extract_patient_weight(dicom_path)[source]#

Extract patient weight (kg) from a DICOM file.

Returns:

Weight in kg, or None if the tag is absent or zero.

Return type:

float | None

Parameters:

dicom_path (str | Path)

autods_pet.imaging.extract_pet_tags(dicom_path)[source]#

Extract PET metadata tags from a single DICOM file.

Handles nested RadiopharmaceuticalInformationSequence with top-level fallback for dose and half-life tags.

Returns:

Keys match the metadata expected by normalize_pet(): PatientID, StudyDate, AcquisitionTime, Units, DecayCorrection, RadiopharmaceuticalStartTime, RadionuclideTotalDose, RadionuclideHalfLife, SeriesInstanceUID, StudyInstanceUID. Missing tags are set to None.

Return type:

dict[str, Any]

Parameters:

dicom_path (str | Path)

autods_pet.imaging.find_dicom_files(patient_dir, size_threshold_kb=100)[source]#

Recursively find .dcm files above a size threshold.

Parameters:
  • patient_dir (str | Path) – Root directory to search.

  • size_threshold_kb (int (default: 100)) – Minimum file size in KB. Files smaller than this are skipped (e.g. tiny overlay or presentation-state files).

Returns:

Sorted list of matching file paths.

Return type:

list[Path]

autods_pet.imaging.find_series_by_modality(patient_dir, size_threshold_kb=100)[source]#

Find the primary CT and PT DICOM series in a patient directory.

Groups .dcm files by (Modality, SeriesInstanceUID), then picks the series with the most files for each modality.

Note

This function reads DICOM headers for every .dcm file sequentially (O(n) disk reads, no parallelism). For directories with 1000+ files on network-attached storage this may be slow. Consider parallel header reads for high-throughput deployments.

Returns:

{"CT": [Path, ...], "PT": [Path, ...]}. Empty lists for modalities that are not found.

Return type:

dict[str, list[Path]]

Parameters:
  • patient_dir (str | Path)

  • size_threshold_kb (int)

autods_pet.imaging.parse_dicom_date(dstr)[source]#

Parse a DICOM DA string (YYYYMMDD) into a datetime.date.

Parameters:

dstr (str) – DICOM DA-format string (e.g. "20230415").

Return type:

date

Raises:

ValueError – If dstr is too short or contains invalid month/day.

Examples

>>> from autods_pet.imaging.normalization import parse_dicom_date
>>> parse_dicom_date("20230415")
datetime.date(2023, 4, 15)
autods_pet.imaging.parse_dicom_time(tstr)[source]#

Parse a DICOM TM string into a datetime.time.

Handles missing leading zeros, fractional seconds, and hours >= 24 (wrapped modulo 24).

Parameters:

tstr (str) – DICOM TM-format string (e.g. "143012.123456").

Return type:

time

Raises:

ValueError – If tstr is empty.

Examples

>>> from autods_pet.imaging.normalization import parse_dicom_time
>>> parse_dicom_time("143012.000000")
datetime.time(14, 30, 12)
>>> parse_dicom_time("090000")
datetime.time(9, 0)
autods_pet.imaging.resolve_patient_folder(basepath, patient_id)[source]#

Case-insensitive lookup for a patient subfolder.

Returns the resolved Path or None if no match is found.

Return type:

Path | None

Parameters:
autods_pet.imaging.rigid_register_pet_to_ct(ct, pet, log_to_console=False, report_path=None)[source]#

Rigidly register pet onto the ct grid.

Parameters:
  • ct (Image) – CT image (fixed / reference frame).

  • pet (Image) – PET image (moving).

  • log_to_console (bool (default: False)) – If True, print Elastix iteration logs to stdout.

  • report_path (Path | None (default: None)) – If set, Elastix writes TransformParameters.0.txt to report_path.parent and it is renamed to report_path.

Returns:

PET resampled onto the CT grid (float64).

Return type:

Image

autods_pet.imaging.run_totalsegmentator(ct_path, output_dir, task='total', fast=False, output_filename=None)[source]#

Run TotalSegmentator on a CT image.

Uses the --ml flag to produce a single multilabel NIfTI file named TOTSEG_FILENAME inside output_dir.

Note

Paths are passed as subprocess arguments (list form, no shell). This mitigates OS command injection (CWE-78), but path traversal (CWE-22) is not validated. If this function is ever exposed via a network service, add explicit path validation.

Parameters:
  • ct_path (Path) – Path to the input CT NIfTI file.

  • output_dir (Path) – Directory where the segmentation output will be written.

  • task (str (default: 'total')) – TotalSegmentator task name (default "total").

  • fast (bool (default: False)) – If True, use the --fast flag for lower resolution but faster inference.

  • output_filename (str | None (default: None)) – Custom filename for the output segmentation file. When None (default), uses TOTSEG_FILENAME.

Returns:

Path to the output segmentation file.

Return type:

Path

autods_pet.imaging.seconds_between(injection, acquisition, max_uptake_hours=6.0)[source]#

Seconds elapsed from injection to acquisition, handling midnight wrap.

If the elapsed time is slightly negative (0 to -max_uptake_hours), assumes the acquisition crossed midnight and adds 24 h. If more negative than -max_uptake_hours, still corrects but logs a warning.

Parameters:
  • injection (datetime) – Radiopharmaceutical injection time.

  • acquisition (datetime) – PET acquisition time.

  • max_uptake_hours (float (default: 6.0)) – Maximum expected injection-to-scan interval in hours. Negative elapsed times within this window are assumed to be midnight wraparounds. The default of 6 h is appropriate for standard 18F-FDG protocols (typical uptake ~60 min). Increase for tracers with longer uptake periods (e.g. 68Ga-DOTATATE).

Returns:

Elapsed seconds (always >= 0 after midnight correction).

Return type:

float

Examples

>>> from datetime import datetime
>>> from autods_pet.imaging.normalization import seconds_between
>>> seconds_between(datetime(2023, 1, 1, 9, 0), datetime(2023, 1, 1, 10, 0))
3600.0