Skip to content

SUVFactorCalculator ignores date: wrong SUV for multi-day decay (Y-90 post-therapy PET, delayed imaging) #28

@cemturkan97

Description

@cemturkan97

Summary

SUVFactorCalculatorCLI/SUVFactorCalculator.cxx computes decay time using only HH:MM:SS (via ConvertTimeToSeconds), ignoring the date component of RadiopharmaceuticalStartDateTime / SeriesReferenceTime. This yields incorrect SUV values when the scan and injection occur on different days — for example:

  • Y-90 post-therapy PET (scan several days after infusion)
  • Delayed FDG imaging / overnight protocols
  • Dual-time-point FDG where delayed phase crosses midnight

Same-day scans (typical FDG/choline uptake) are unaffected because the date-carrying bug doesn't manifest.

Location

https://github.com/QIICR/Slicer-PETDICOMExtension/blob/master/SUVFactorCalculatorCLI/SUVFactorCalculator.cxx#L173-L188

double DecayCorrection(parameters & list, double injectedDose )
{
  double scanTimeSeconds = ConvertTimeToSeconds(list.seriesReferenceTime.c_str());
  double startTimeSeconds = ConvertTimeToSeconds(list.injectionTime.c_str());
  double halfLife = atof(list.radionuclideHalfLife.c_str());
  double decayTime = scanTimeSeconds - startTimeSeconds;   // <-- date ignored
  double decayedDose = injectedDose * pow(2.0, -(decayTime / halfLife));
  return decayedDose;
}

list.injectionTime and list.seriesReferenceTime are stored as HH:MM:SS strings (see lines 380-395 and 640-655 — tag parsing extracts only the time portion of RadiopharmaceuticalStartDateTime / SeriesTime).

Reproduction — real Y-90 post-therapy PET

  • Patient weight: 85 kg
  • Injected activity: 11 GBq (Y-90 microspheres)
  • Half-life: 230760 s (Y-90)
  • Injection: 2025-06-29 19:00:00 (RadiopharmaceuticalStartDateTime = 20250629190000)
  • Scan: 2025-07-04 08:47:22 (SeriesDate/AcquisitionDate = 20250704, AcquisitionTime = 084722)
  • True decay time: +395242 s (≈ 4.57 days) → decay factor 0.305 → decayed dose 3.36 GBq → SUVbw factor 2.533e-05

What the calculator computes instead:

  • decayTime = 8:47:22 − 19:00:00 = −36758 s (negative)
  • pow(2, −(−36758/230760)) = 1.1167 (> 1 — physically impossible for forward-time decay)
  • decayedDose = 11e9 × 1.1167 = 12.28 GBq
  • Produced RWV slope SUVbw: 6.9195e-06 — off by factor ~3.66× from the correct value

Verified on current master against a real dataset; the RWV file produced by the extension contains:

RealWorldValueSlope: 6.9195e-06
Unit: Standardized Uptake Value body weight
Manufacturer: https://github.com/QIICR/Slicer-SUVFactorCalculator

The same DICOM processed with a date-aware implementation gives SUVbw slope 2.533e-05 (computed by hand and by an independent Python pipeline using full datetime from RadiopharmaceuticalStartDateTime vs AcquisitionDate+AcquisitionTime).

Suggested fix

Parse and subtract full datetimes rather than time-of-day strings. Sources that should be used:

  • RadiopharmaceuticalStartDateTime (0018,1078) — preferred, already dated
  • Otherwise combine SeriesDate (0008,0021) + RadiopharmaceuticalStartTime (0018,1072), but fall back to AcquisitionDate (0008,0022) if injection is known to be on a different day (hard to detect without StartDateTime)
  • seriesReferenceTime should likewise be composed with SeriesDate / AcquisitionDate

A minimal patch would replace ConvertTimeToSeconds with a helper that takes (date, time) pairs and returns seconds since epoch, making the subtraction date-aware.

Impact

Any institution running dosimetry / radiomics pipelines for Y-90 microsphere therapy that relies on Slicer's PET DICOM extension-generated RWV SUV maps will silently get wrong SUVbw/SUVlbm values. Discrepancy in our case was ~3.66×, large enough to invalidate downstream dose-response analyses.

Happy to contribute a patch and test data if that would help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions