1. User guide¶
1.1. How to start ?¶
RPT_DOSI is a python toolkit for dosimetry in radionuclide therapy.
It is used for example for estimating the absorbed dose from SPECT (or PET) images in 177Lu therapy (neuroendocrine tumors and prostate cancer with PSMA).
1.1.1. Installation¶
The project can be installed as followed:
{tip} We highly recommend creating a specific python environment to 1) be sure all dependencies are handled properly and 2) don’t mix with your other Python modules. For example, you can use venv. Once the environment is created, you need to activate it:
python -m venv rpt_dosi_env
source rpt_dosi_env/bin/activate
or with conda environment:
conda create --name rpt_dosi_env python=3.11
conda activate rpt_dosi_env
Now install, git-lfs to be able to get the test data.
Then, you need to clone the repository and install it (no pypi package yet, but this is planned):
git clone --recurse-submodules https://github.com/dsarrut/rpt_dosi.git
cd rpt_dosi
pip install -e .
Once installed, we recommend to run the tests:
rpt_tests
1.1.2. Quick demo¶
The toolkit contains Python functions and command line tools for several dosimetry methods. Here is a simple example to compute the dose for a ROI (Regions Of Interests) from a SPECT image with the Madsen2018 method:
First, as a command line tool:
rpt_dose --spect spect.nii.gz --input_unit Bq --ct ct.nii.gz --resample_like spect --time_from_injection_h 24 --method madsen2018 --roi spleen.nii.gz spleen 56 --roi liver.nii.gz liver 67
This command computes the dose in the spleen from the activity of the SPECT image. We explicitly states that the SPECT image is in Bq (not Bq/mL), that the SPECT image was acquired 24 hours after injection, and that the spleen has a Teff (effective clearance time) of 67 hours. We will see later how to store units and metadata in companions files. The inputs are:
the spect image: spect.nii.gz (it can be any image file format type, such as mhd or mha)
the pixel unit value for the SPECT: Bq
the acquisition time of the SPECT image according the injection: 24 hours
the ct image: ct.nii.gz (the default pixel unit value is HU)
the mask of the ROI: spleen.nii.gz
the name of the ROI: spleen
the effective clearance time of the ROI: 56 (in hours)
Note: any number of –roi options can be set at the same time
the (Single Time Point) method that we use to compute the dose: madsen2018. There are others methods available, type
rpt_dose -hto get help
The same command can be done via python functions:
ct = rim.read_ct("ct.nii.gz")
spect = rim.read_spect("spect.nii.gz", "Bq")
spect.time_from_injection_h = 24.0
roi1 = read_roi("spleen.nii.gz", "spleen", 56)
roi2 = read_roi("liver.nii.gz", "liver", 67)
d = rd.DoseMadsen2018(ct, spect)
d.resample_like = "spect"
d.gaussian_sigma = 'auto'
# the run function takes a list of rois as input
dose = d.run([roi1, roi2])
print(dose)
1.2. Basic Image Manipulation with Associated Metadata (sidecar JSON file)¶
Metadata This section delves into handling and manipulating medical imaging data within the toolkit. The toolkit proposes functions and classes to manage images together with the associated metadata that are needed for dose computation (such as injected activity of acquisition time and image units: Bq, SUV, etc.). The metadata information are stored in a “sidecar” json file.
Image file format DICOM is the standard format. However, for advanced processing, DICOM images are sometimes converted to more flexible formats like .mhd (MetaImage) or .nii (NIfTI).
1.2.1. MetaImage API¶
Here are the basics CRUD operations (Create Read Update Delete) for the MetaImage.
First, how to CREATE a metadata image:
import rpt_dosi.images as rim
image = rim.new_metaimage('SPECT', "path/spect.nii.gz", unit='Bq')
image.write_metadata()
This script will create a new metaimage with SPECT as image type and ‘Bq’ as unit. The metadata is then written in the path/spect.nii.gz.json file. If the json file already exist, it fails (you need to use the overwrite option). For some image types, such as SPECT or PET, the unit is required, while it is not the case for CT (always HU). Image types are : SPECT, PET, CT, Dose, ROI.
To READ a metadata image:
import rpt_dosi.images as rim
image = rim.read_metaimage("path/spect.nii.gz")
print(image.info())
This script read the image and the associated metadata (fails if it does not exist). Use the option read_header_only to, well, read only the header of the image and not the whole content in memory.
When you expect on given image type, you can use the following shortcuts that will read images and check there are of the required type:
import rpt_dosi.images as rim
spect = rim.read_spect("path/spect.nii.gz")
ct = rim.read_ct("path/ct.nii.gz")
spect2 = rim.read_spect("path/spect.nii.gz", 'Bq')
If the unit is required (like for SPECT) and there is no metadata associated, it fails. You can however set the unit in the read command like for the spect2: unit will be converted (or set if not exist) to Bq.
The classes are MetaImageSPECT, MetaImageCT, etc. See examples below:
import
rpt_dosi.images as rim
spect = rim.MetaImageSPECT(
"path/spect.nii.gz",
reading_mode=True,
create=True,
unit='Bq')
A instance of a metaimage contains some member functions such as the following:
import rpt_dosi.images as rim
spect = rim.read_spect("path/spect.nii.gz")
spect.convert_to_bqml()
spect.body_weight_kg = 80
spect.convert_to_unit('SUV')
print('Total activity in the image', spect.compute_total_activity())
spect.acquisition_datetime = "2020 06 03 12:00"
spect.injection_datetime = "2020 06 03 10:00"
print(spect.info())
print(spect)
spect.write()
spect.write("this_is_a_copy.mhd")
# for a CT
ct = rim.read_spect("path/ct.nii.gz")
densitiy_image = ct.compute_densities()
1.3. Dosimetry methods¶
This section focuses on the tools and methods provided by the toolkit for performing dosimetry calculations, i.e. determining the dose absorbed by tissues in radiopharmaceutical therapies. The tools covered here are primarily from the dosimetry.py module and the rpt_dose command-line tool.
1.3.1. The rpt_dose command line tool, for single time point (STP) methods¶
The main tool command to compute the absorbed dose in ROI from a single time point SPECT image, is rpt_dose:
Usage: rpt_dose [OPTIONS]
Options:
-s, --spect PATH Input SPECT image (use --unit to specify the
image)
-d, --dose_rate PATH Input dose rate image
-u, --input_unit [Bq|Bq/mL|SUV|Gy/s]
SPECT or dose rate unit: ['Bq', 'Bq/mL',
'SUV', 'Gy/s']
-c, --ct PATH Input CT image [required]
-l, --roi_list TEXT Filename : list of ROI filename and name
-r, --roi <TEXT TEXT FLOAT>... ROI: filename + name + Teff
-t, --time_from_injection_h FLOAT
Time in h [required]
--rad TEXT Radionuclide
-m, --method [hanscheid2017|hanscheid2018|madsen2018|madsen2018_dose_rate]
Which method to use
-r, --resample_like [spect|ct] Resample image like spect, dose_rate or ct
--sigma TEXT specify sigma for gauss filter (None=no
gauss, 0 = auto)
-p, --phantom TEXT Phantom ICRP 110 AF or AM (only used by some
methods)
--scaling FLOAT Scaling factor (for dose rate)
-o, --output TEXT Output json filename
-h, --help Show this message and exit.
Here is an example:
rpt_dose --spect spect.nii.gz --input_unit Bq --ct ct.nii.gz --resample_like spect --time_from_injection_h 24 --method madsen2018 --roi spleen.nii.gz spleen 56 --roi liver.nii.gz liver 67
If the images are associated with metadata, the options such as unit or time_from_injection are not required.
ROIs can also be given as a list in a JSON file, for example this file in the tests: oar.json.
The current available methods are the following:
hanscheid2017 DOI. This method need an estimation of the Teff (effective clearance time) of the organs of interest. The equation is: dose = 0.125 * Ct * np.power(2, acq_time_h / roi_time_eff_h) * roi_time_eff_h with Ct the mean activity in the ROI in MBq.
hanscheid2018 DOI. This method used MIRD Svalues and mass scaling of the ROI. Svalue is in mGy/MBq/s and is gathered from the opendose website. The equation is: dose = mass_scaling * At * svalue * (2 * acq_time_h * 3600.0) / np.log(2) / 1000.0 with At the total activity in the ROI (in MBq). The mass scaling is computed according to the reference mass from opendose and the current mass of the ROI computed from the CT.
madsen2018 DOI. The computation is as follows. The delta_lu_e value is set to 0.08532 (MIRD, opendose). The effective clearance time of the ROI must be provided (roi_time_eff_h).
svalue = delta_lu_e / roi_mass_g * 1000
k = np.log(2) / roi_time_eff_h
integrated_activity = At * np.exp(k * acq_time_h) / k
dose = integrated_activity * svalue / 1000
Images (and ROI masks) are all resampled like the CT or like the SPECT image.
Dose computation can also be performed with python scripts as follows:
ct = rim.read_ct("ct.nii.gz")
spect = rim.read_spect("spect.nii.gz", "Bq")
spect.time_from_injection_h = 24.0
roi1 = read_roi("spleen.nii.gz", "spleen", 56)
roi2 = read_roi("liver.nii.gz", "liver", 67)
d = rd.DoseMadsen2018(ct, spect)
d.resample_like = "spect"
d.gaussian_sigma = 'auto'
# the run function takes a list of rois as input
dose = d.run([roi1, roi2])
print(dose)
1.3.2. Method with dose rate¶
TODO