petpal 0.5.6__tar.gz → 0.5.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {petpal-0.5.6 → petpal-0.5.8}/.gitignore +4 -1
- {petpal-0.5.6 → petpal-0.5.8}/PKG-INFO +1 -1
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_pib_processing.py +2 -3
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_preproc.py +64 -33
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_vat_processing.py +3 -2
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/pipelines.py +0 -3
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/preproc_steps.py +8 -7
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/__init__.py +2 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/decay_correction.py +11 -10
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/image_operations_4d.py +13 -177
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/motion_corr.py +31 -112
- petpal-0.5.8/petpal/preproc/motion_target.py +90 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/regional_tac_extraction.py +3 -3
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/register.py +4 -11
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/segmentation_tools.py +5 -5
- petpal-0.5.8/petpal/preproc/standard_uptake_value.py +159 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/scan_timing.py +66 -19
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/stats.py +21 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/useful_functions.py +106 -5
- {petpal-0.5.6 → petpal-0.5.8}/pyproject.toml +1 -1
- petpal-0.5.8/tests/test_register.py +82 -0
- petpal-0.5.8/tests/test_scan_timing_decay.py +146 -0
- petpal-0.5.8/tests/test_weighted_sum.py +51 -0
- {petpal-0.5.6 → petpal-0.5.8}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/.github/workflows/publish-to-pypi.yml +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/.github/workflows/python-package.yml +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/.readthedocs.yaml +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/LICENSE +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/README.md +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-02.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-02.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-00.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-01.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-02.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_evenly_resampled.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_evenly_resampled_woMax.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/gen_tcms_data.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/readme.md +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-02.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-02.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-00.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-01.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-02.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tac_2tcm_k4zero_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tac_2tcm_k4zero_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-00.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-01.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tacs.pdf +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tacs.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-00.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-01.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/data/tcm_tacs/turku_pet_center_fdg_plasma_clamp.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/Makefile +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/PETPAL_Logo.png +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/index.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/attribute.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/class.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/data.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/exception.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/function.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/method.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/module.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/package.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/_templates/python/property.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/conf.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/index.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/make.bat +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/requirements.txt +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/tutorials/index.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/docs/tutorials/pib_example.rst +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_graphical_analysis.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_graphical_plots.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_idif.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_parametric_images.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_plot_tacs.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_pvc.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_reference_tissue_models.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_stats.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_tac_fitting.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/cli/cli_tac_interpolation.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/input_function/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/input_function/blood_input.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/input_function/idif_necktangle.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/input_function/pca_guided_idif.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/fit_tac_with_rtms.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/graphical_analysis.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/parametric_images.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/reference_tissue_models.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/rtm_analysis.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/tac_fitting.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/tac_interpolation.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/tac_uncertainty.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/kinetic_modeling/tcms_as_convolutions.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/meta/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/meta/label_maps.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/kinetic_modeling_steps.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/pca_guided_idif_steps.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/steps_base.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/pipelines/steps_containers.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/partial_volume_corrections.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/preproc/symmetric_geometric_transfer_matrix.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/bids_utils.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/constants.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/data_driven_image_analyses.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/decorators.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/image_io.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/math_lib.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/metadata.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/testing_utils.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/utils/time_activity_curve.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/visualizations/__init__.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/visualizations/graphical_plots.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/visualizations/image_visualization.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/visualizations/qc_plots.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/petpal/visualizations/tac_plots.py +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/shared/dseg.tsv +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/shared/freesurfer_lmap.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/shared/freesurfer_lmap_lr.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/shared/perl_cyno_lmap.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/shared/perl_cyno_lmap_lr.json +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/test_notebooks/explicit_tac_fitting/01_fitting_TCMs.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/test_notebooks/testing_RTMs/01_testing_RTMs.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/01_testing_on_tcms_database.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/02_testing_parametric_images.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/03_plotting_graphical_anlayses_testbed.ipynb +0 -0
- {petpal-0.5.6 → petpal-0.5.8}/tests/test_importpetpal.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: petpal
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.8
|
|
4
4
|
Summary: PET-PAL (Positron Emission Tomography Processing and Analysis Library)
|
|
5
5
|
Project-URL: Repository, https://github.com/PETPAL-WUSM/PETPAL.git
|
|
6
6
|
Author-email: Noah Goldman <noahg@wustl.edu>, Bradley Judge <bjudge@wustl.edu>, Furqan Dar <dar@wustl.edu>, Kenan Oestreich <kenan.oestreich@wustl.edu>
|
|
@@ -94,12 +94,11 @@ def main():
|
|
|
94
94
|
|
|
95
95
|
# Configure steps for kinetic modeling container
|
|
96
96
|
suvr_step = ImageToImageStep(name='suvr',
|
|
97
|
-
function=petpal.preproc.
|
|
97
|
+
function=petpal.preproc.standard_uptake_value.suvr,
|
|
98
98
|
input_image_path='',
|
|
99
99
|
output_image_path='',
|
|
100
100
|
ref_region=ref_region_label,
|
|
101
|
-
segmentation_image_path=seg_path
|
|
102
|
-
verbose=False)
|
|
101
|
+
segmentation_image_path=seg_path)
|
|
103
102
|
|
|
104
103
|
# Add steps to kinetic modeling container
|
|
105
104
|
kinetic_modeling_container.add_step(step=suvr_step)
|
|
@@ -33,7 +33,7 @@ Examples:
|
|
|
33
33
|
|
|
34
34
|
.. code-block:: bash
|
|
35
35
|
|
|
36
|
-
petpal-preproc register-pet -i /path/to/input_img.nii.gz -o petpal_reg.nii.gz --motion-target 0 600 --anatomical /path/to/anat.nii.gz
|
|
36
|
+
petpal-preproc register-pet -i /path/to/input_img.nii.gz -o petpal_reg.nii.gz --motion-target 0 600 --anatomical /path/to/anat.nii.gz
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
* Write regional tacs:
|
|
@@ -54,7 +54,7 @@ Examples:
|
|
|
54
54
|
|
|
55
55
|
.. code-block:: bash
|
|
56
56
|
|
|
57
|
-
petpal-preproc weighted-series-sum -i /path/to/input_img.nii.gz -o petpal_wss.nii.gz --
|
|
57
|
+
petpal-preproc weighted-series-sum -i /path/to/input_img.nii.gz -o petpal_wss.nii.gz --start-time 1800 --end-time 7200
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
* SUVR Image:
|
|
@@ -95,8 +95,11 @@ import argparse
|
|
|
95
95
|
import ants
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
from ..
|
|
99
|
-
|
|
98
|
+
from ..preproc import (image_operations_4d,
|
|
99
|
+
motion_corr,
|
|
100
|
+
register,
|
|
101
|
+
regional_tac_extraction,
|
|
102
|
+
standard_uptake_value)
|
|
100
103
|
|
|
101
104
|
|
|
102
105
|
_PREPROC_EXAMPLES_ = r"""
|
|
@@ -106,13 +109,13 @@ Examples:
|
|
|
106
109
|
- Windowed moco:
|
|
107
110
|
petpal-preproc windowed-motion-corr -i /path/to/input_img.nii.gz -o petpal_moco.nii.gz --window-size 120 --transform-type QuickRigid
|
|
108
111
|
- Register to anatomical:
|
|
109
|
-
petpal-preproc register-pet -i /path/to/input_img.nii.gz -o petpal_reg.nii.gz --motion-target 0 600 --anatomical /path/to/anat.nii.gz
|
|
112
|
+
petpal-preproc register-pet -i /path/to/input_img.nii.gz -o petpal_reg.nii.gz --motion-target 0 600 --anatomical /path/to/anat.nii.gz
|
|
110
113
|
- Write regional tacs:
|
|
111
114
|
petpal-preproc write-tacs -i /path/to/input_img.nii.gz -p sub-001 -o /tmp/petpal_tacs -s /path/to/segmentation.nii.gz -l perlcyno -x
|
|
112
115
|
- Write tacs, deprecated:
|
|
113
116
|
petpal-preproc write-tacs-old -i /path/to/input_img.nii.gz -o /tmp/petpal_tacs --segmentation /path/to/segmentation.nii.gz --label-map-path /path/to/dseg.tsv
|
|
114
117
|
- Half life weighted sum of series:
|
|
115
|
-
petpal-preproc weighted-series-sum -i /path/to/input_img.nii.gz -o petpal_wss.nii.gz --
|
|
118
|
+
petpal-preproc weighted-series-sum -i /path/to/input_img.nii.gz -o petpal_wss.nii.gz --start-time 1800 --end-time 7200
|
|
116
119
|
- SUVR:
|
|
117
120
|
petpal-preproc suvr -i /path/to/input_img.nii.gz -o petpal_suvr.nii.gz --segmentation /path/to/segmentation.nii.gz --ref-region 1
|
|
118
121
|
- Gauss blur:
|
|
@@ -121,6 +124,8 @@ Examples:
|
|
|
121
124
|
petpal-preproc rescale-image -i /path/to/input_img.nii.gz -o petpal_rescale.nii.gz --scale-factor 1000
|
|
122
125
|
- Warp to atlas:
|
|
123
126
|
petpal-preproc warp-pet-atlas -i /path/to/input_img.nii.gz -o petpal_reg-atlas.nii.gz --anatomical /path/to/anat.nii.gz --reference-atlas /path/to/atlas.nii.gz
|
|
127
|
+
- SUV:
|
|
128
|
+
petpal-preproc suv -i /path/to/input_img.nii.gz -o petpal_suv.nii.gz --weight 75 --dose 250 --start-time 1200 --end-time 3600
|
|
124
129
|
"""
|
|
125
130
|
|
|
126
131
|
|
|
@@ -159,7 +164,7 @@ def _add_common_args(parser: argparse.ArgumentParser) -> None:
|
|
|
159
164
|
"""
|
|
160
165
|
parser.add_argument('-o',
|
|
161
166
|
'--out-img',
|
|
162
|
-
default='
|
|
167
|
+
default='petpal_preproc_output.nii.gz',
|
|
163
168
|
help='Output image filename')
|
|
164
169
|
parser.add_argument('-i', '--input-img',required=True,help='Path to input image.',type=str)
|
|
165
170
|
|
|
@@ -183,10 +188,6 @@ def _generate_args() -> argparse.ArgumentParser:
|
|
|
183
188
|
parser_wss = subparsers.add_parser('weighted-series-sum',
|
|
184
189
|
help='Half-life weighted sum of 4D PET series.')
|
|
185
190
|
_add_common_args(parser_wss)
|
|
186
|
-
parser_wss.add_argument('--half-life',
|
|
187
|
-
required=True,
|
|
188
|
-
help='Half life of radioisotope in seconds.',
|
|
189
|
-
type=float)
|
|
190
191
|
parser_wss.add_argument('--start-time',
|
|
191
192
|
required=False,
|
|
192
193
|
help='Start time of sum in seconds.',
|
|
@@ -215,9 +216,6 @@ def _generate_args() -> argparse.ArgumentParser:
|
|
|
215
216
|
required=True)
|
|
216
217
|
parser_moco.add_argument('--transform-type', required=False,default='Rigid',
|
|
217
218
|
help='Transformation type (Rigid or Affine).',type=str)
|
|
218
|
-
parser_moco.add_argument('--half-life', required=False,
|
|
219
|
-
help='Half life of radioisotope in seconds.'
|
|
220
|
-
'Required for some motion targets.',type=float)
|
|
221
219
|
|
|
222
220
|
parser_tac = subparsers.add_parser('write-tacs',
|
|
223
221
|
help='Write ROI TACs from 4D PET using segmentation masks.')
|
|
@@ -279,9 +277,19 @@ def _generate_args() -> argparse.ArgumentParser:
|
|
|
279
277
|
help='Path to segmentation image in anatomical space.')
|
|
280
278
|
parser_suvr.add_argument('-r',
|
|
281
279
|
'--ref-region',
|
|
282
|
-
help='Reference region to normalize SUVR to.'
|
|
280
|
+
help='Reference region to normalize SUVR to. List multiple regions to '
|
|
281
|
+
'combine as one reference.',
|
|
283
282
|
required=True,
|
|
284
|
-
type=int
|
|
283
|
+
type=int,
|
|
284
|
+
nargs='+')
|
|
285
|
+
parser_suvr.add_argument('--start-time',
|
|
286
|
+
required=True,
|
|
287
|
+
help='Start time for SUVR calculation in seconds from scan start',
|
|
288
|
+
type=float)
|
|
289
|
+
parser_suvr.add_argument('--end-time',
|
|
290
|
+
required=True,
|
|
291
|
+
help='End time for SUVR calculation in seconds from scan start',
|
|
292
|
+
type=float)
|
|
285
293
|
|
|
286
294
|
parser_blur = subparsers.add_parser('gauss-blur',help='Perform 3D gaussian blurring.')
|
|
287
295
|
_add_common_args(parser_blur)
|
|
@@ -328,9 +336,27 @@ def _generate_args() -> argparse.ArgumentParser:
|
|
|
328
336
|
help="Motion target option. Can be an image path, "
|
|
329
337
|
"'weighted_series_sum' or a tuple (i.e. '-t 0 600' for first "
|
|
330
338
|
"ten minutes).")
|
|
331
|
-
parser_reg.add_argument('-l', '--half-life', help='Half life of radioisotope in seconds.',
|
|
332
|
-
type=float)
|
|
333
339
|
|
|
340
|
+
parser_suv = subparsers.add_parser('suv',help='Standard Uptake Value (SUV) calculation')
|
|
341
|
+
_add_common_args(parser_suv)
|
|
342
|
+
parser_suv.add_argument('-w',
|
|
343
|
+
'--weight',
|
|
344
|
+
required=True,
|
|
345
|
+
help='Weight of the participant in kg',
|
|
346
|
+
type=float)
|
|
347
|
+
parser_suv.add_argument('-d',
|
|
348
|
+
'--dose',
|
|
349
|
+
required=True,
|
|
350
|
+
help='Dose of radiotracer injected in MBq',
|
|
351
|
+
type=float)
|
|
352
|
+
parser_suv.add_argument('--start-time',
|
|
353
|
+
required=True,
|
|
354
|
+
help='Start time for SUV calculation in seconds from scan start',
|
|
355
|
+
type=float)
|
|
356
|
+
parser_suv.add_argument('--end-time',
|
|
357
|
+
required=True,
|
|
358
|
+
help='End time for SUV calculation in seconds from scan start',
|
|
359
|
+
type=float)
|
|
334
360
|
return parser
|
|
335
361
|
|
|
336
362
|
|
|
@@ -357,31 +383,27 @@ def main():
|
|
|
357
383
|
|
|
358
384
|
match command:
|
|
359
385
|
case 'weighted_series_sum':
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
end_time=args.end_time,
|
|
365
|
-
verbose=True)
|
|
386
|
+
standard_uptake_value.weighted_sum_for_suv(input_image_path=args.input_img,
|
|
387
|
+
output_image_path=args.out_img,
|
|
388
|
+
start_time=args.start_time,
|
|
389
|
+
end_time=args.end_time)
|
|
366
390
|
case 'auto_crop':
|
|
367
391
|
image_operations_4d.SimpleAutoImageCropper(input_image_path=args.input_img,
|
|
368
392
|
out_image_path=args.out_img,
|
|
369
393
|
thresh_val=args.thresh_val,
|
|
370
394
|
verbose=True)
|
|
371
395
|
case 'motion_correction':
|
|
372
|
-
motion_corr.motion_corr(
|
|
396
|
+
motion_corr.motion_corr(input_image_path=args.input_img,
|
|
373
397
|
out_image_path=args.out_img,
|
|
374
398
|
motion_target_option=motion_target,
|
|
375
399
|
verbose=True,
|
|
376
|
-
type_of_transform=args.transform_type
|
|
377
|
-
half_life=args.half_life)
|
|
400
|
+
type_of_transform=args.transform_type)
|
|
378
401
|
case 'register_pet':
|
|
379
402
|
register.register_pet(input_reg_image_path=args.input_img,
|
|
380
403
|
out_image_path=args.out_img,
|
|
381
404
|
reference_image_path=args.anatomical,
|
|
382
405
|
motion_target_option=motion_target,
|
|
383
|
-
verbose=True
|
|
384
|
-
half_life=args.half_life)
|
|
406
|
+
verbose=True)
|
|
385
407
|
case 'write_tacs_old':
|
|
386
408
|
regional_tac_extraction.write_tacs(input_image_path=args.input_img,
|
|
387
409
|
out_tac_dir=args.out_tac_dir,
|
|
@@ -408,10 +430,12 @@ def main():
|
|
|
408
430
|
verbose=True,
|
|
409
431
|
use_fwhm=True)
|
|
410
432
|
case 'suvr':
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
433
|
+
standard_uptake_value.suvr(input_image_path=args.input_img,
|
|
434
|
+
output_image_path=args.out_img,
|
|
435
|
+
segmentation_image_path=args.segmentation,
|
|
436
|
+
ref_region=args.ref_region,
|
|
437
|
+
start_time=args.start_time,
|
|
438
|
+
end_time=args.end_time)
|
|
415
439
|
case 'windowed_motion_corr':
|
|
416
440
|
motion_corr.windowed_motion_corr_to_target(input_image_path=args.input_img,
|
|
417
441
|
out_image_path=args.out_img,
|
|
@@ -423,6 +447,13 @@ def main():
|
|
|
423
447
|
out_img = image_operations_4d.rescale_image(input_image=input_img,
|
|
424
448
|
rescale_constant=args.scale_factor)
|
|
425
449
|
ants.image_write(image=out_img, filename=args.out_img)
|
|
450
|
+
case 'suv':
|
|
451
|
+
standard_uptake_value.suv(input_image_path=args.input_img,
|
|
452
|
+
output_image_path=args.out_img,
|
|
453
|
+
start_time=args.start_time,
|
|
454
|
+
end_time=args.end_time,
|
|
455
|
+
weight=args.weight,
|
|
456
|
+
dose=args.dose)
|
|
426
457
|
|
|
427
458
|
if __name__ == "__main__":
|
|
428
459
|
main()
|
|
@@ -7,6 +7,7 @@ from petpal.kinetic_modeling import graphical_analysis,rtm_analysis
|
|
|
7
7
|
from petpal.preproc import image_operations_4d, motion_corr, register, segmentation_tools
|
|
8
8
|
from petpal.preproc import symmetric_geometric_transfer_matrix as sgtm
|
|
9
9
|
import petpal.preproc.regional_tac_extraction
|
|
10
|
+
import petpal.preproc.standard_uptake_value
|
|
10
11
|
from petpal.utils.bids_utils import gen_bids_like_dir_path, gen_bids_like_filename, gen_bids_like_filepath
|
|
11
12
|
from petpal.utils.image_io import km_regional_fits_to_tsv
|
|
12
13
|
from petpal.utils import useful_functions
|
|
@@ -199,13 +200,13 @@ def vat_protocol(subjstring: str,
|
|
|
199
200
|
wss_file_path = vat_bids_filepath(suffix='pet',folder='pet',space='mpr',desc='WSS')
|
|
200
201
|
suvr_file_path = vat_bids_filepath(suffix='pet',folder='pet',space='mpr',desc='SUVR')
|
|
201
202
|
if 'suvr' not in skip:
|
|
202
|
-
useful_functions.weighted_series_sum(
|
|
203
|
+
useful_functions.weighted_series_sum(input_image_path=pet_reg_anat_file,
|
|
203
204
|
half_life=half_life,
|
|
204
205
|
verbose=True,
|
|
205
206
|
start_time=suvr_start,
|
|
206
207
|
end_time=suvr_end,
|
|
207
208
|
out_image_path=wss_file_path)
|
|
208
|
-
|
|
209
|
+
petpal.preproc.standard_uptake_value.suvr(input_image_path=wss_file_path,
|
|
209
210
|
out_image_path=suvr_file_path,
|
|
210
211
|
segmentation_image_path=vat_wm_ref_segmentation_file,
|
|
211
212
|
ref_region=1,
|
|
@@ -4,7 +4,6 @@ import copy
|
|
|
4
4
|
from typing import Union
|
|
5
5
|
from .steps_base import *
|
|
6
6
|
from .steps_containers import StepsContainer, StepsPipeline
|
|
7
|
-
from ..utils.image_io import get_half_life_from_nifti
|
|
8
7
|
from ..utils.bids_utils import gen_bids_like_dir_path, gen_bids_like_filepath
|
|
9
8
|
|
|
10
9
|
|
|
@@ -805,9 +804,7 @@ class BIDS_Pipeline(BIDSyPathsForPipelines, StepsPipeline):
|
|
|
805
804
|
containers = obj.step_containers
|
|
806
805
|
|
|
807
806
|
containers["preproc"][0].input_image_path = obj.pet_path
|
|
808
|
-
containers["preproc"][1].kwargs['half_life'] = get_half_life_from_nifti(obj.pet_path)
|
|
809
807
|
containers["preproc"][2].kwargs['reference_image_path'] = obj.anat_path
|
|
810
|
-
containers["preproc"][2].kwargs['half_life'] = get_half_life_from_nifti(obj.pet_path)
|
|
811
808
|
containers["preproc"][3].segmentation_label_map_path = obj.seg_table
|
|
812
809
|
containers["preproc"][3].segmentation_image_path = obj.seg_img
|
|
813
810
|
containers["preproc"][4].raw_blood_tac_path = obj.blood_path
|
|
@@ -612,9 +612,12 @@ class ImageToImageStep(FunctionBasedStep):
|
|
|
612
612
|
Returns:
|
|
613
613
|
ImageToImageStep: A new instance for motion correction frames above mean value.
|
|
614
614
|
"""
|
|
615
|
-
defaults = dict(name=name,
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
defaults = dict(name=name,
|
|
616
|
+
function=motion_corr_frames_above_mean_value,
|
|
617
|
+
input_image_path='',
|
|
618
|
+
output_image_path='',
|
|
619
|
+
motion_target_option='mean_image',
|
|
620
|
+
verbose=verbose)
|
|
618
621
|
override_dict = defaults | overrides
|
|
619
622
|
try:
|
|
620
623
|
return cls(**override_dict)
|
|
@@ -649,7 +652,7 @@ class ImageToImageStep(FunctionBasedStep):
|
|
|
649
652
|
return cls(**defaults)
|
|
650
653
|
|
|
651
654
|
@classmethod
|
|
652
|
-
def default_register_pet_to_t1(cls, name:str = 'register_pet_to_t1', reference_image_path='',
|
|
655
|
+
def default_register_pet_to_t1(cls, name:str = 'register_pet_to_t1', reference_image_path='', verbose=False, **overrides):
|
|
653
656
|
"""
|
|
654
657
|
Creates a default instance for registering PET to T1 image using :func:`register_pet<petpal.preproc.register.register_pet>`.
|
|
655
658
|
All paths are empty-strings.
|
|
@@ -657,8 +660,6 @@ class ImageToImageStep(FunctionBasedStep):
|
|
|
657
660
|
Args:
|
|
658
661
|
name (str): Name of the step. Defaults to 'register_pet_to_t1'
|
|
659
662
|
reference_image_path (str): Path to the reference image.
|
|
660
|
-
half_life (float): Half-life value, in seconds, for the radiotracer. Used to
|
|
661
|
-
generate a weighted_series_sum image.
|
|
662
663
|
verbose (bool): Whether to run in verbose mode.
|
|
663
664
|
**overrides: Override default parameters.
|
|
664
665
|
|
|
@@ -668,7 +669,7 @@ class ImageToImageStep(FunctionBasedStep):
|
|
|
668
669
|
"""
|
|
669
670
|
defaults = dict(name=name, function=register_pet, input_image_path='', output_image_path='',
|
|
670
671
|
reference_image_path=reference_image_path, motion_target_option='weighted_series_sum',
|
|
671
|
-
verbose=verbose
|
|
672
|
+
verbose=verbose)
|
|
672
673
|
override_dict = defaults | overrides
|
|
673
674
|
try:
|
|
674
675
|
return cls(**override_dict)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Tools for preparing PET data for kinetic modeling and visualization"""
|
|
2
|
+
from . import motion_target
|
|
2
3
|
from . import image_operations_4d
|
|
3
4
|
from . import motion_corr
|
|
4
5
|
from . import partial_volume_corrections
|
|
5
6
|
from . import register
|
|
7
|
+
from . import standard_uptake_value
|
|
6
8
|
from . import symmetric_geometric_transfer_matrix
|
|
7
9
|
from . import segmentation_tools
|
|
8
10
|
from . import decay_correction
|
|
@@ -129,21 +129,22 @@ def decay_correct(input_image_path: str,
|
|
|
129
129
|
return corrected_image
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
def calculate_frame_decay_factor(frame_reference_time:
|
|
133
|
-
half_life: float) ->
|
|
134
|
-
"""Calculate decay
|
|
132
|
+
def calculate_frame_decay_factor(frame_reference_time: np.ndarray,
|
|
133
|
+
half_life: float) -> np.ndarray:
|
|
134
|
+
"""Calculate decay correction factors for a scan given the frame reference time and half life.
|
|
135
135
|
|
|
136
136
|
Important:
|
|
137
137
|
The frame reference time should be the time at which average activity occurs,
|
|
138
|
-
not simply the midpoint. See
|
|
139
|
-
|
|
138
|
+
not simply the midpoint. See
|
|
139
|
+
:meth:`~petpal.utils.scan_timing.calculate_frame_reference_time` for more info.
|
|
140
|
+
|
|
140
141
|
Args:
|
|
141
|
-
frame_reference_time (
|
|
142
|
+
frame_reference_time (np.ndarray): Time at which the average activity occurs for the frame.
|
|
142
143
|
half_life (float): Radionuclide half life.
|
|
143
144
|
|
|
144
145
|
Returns:
|
|
145
|
-
|
|
146
|
+
np.ndarray: Decay Correction Factors for each frame in the scan.
|
|
146
147
|
"""
|
|
147
|
-
decay_constant =
|
|
148
|
-
frame_decay_factor =
|
|
149
|
-
return frame_decay_factor
|
|
148
|
+
decay_constant = np.log(2)/half_life
|
|
149
|
+
frame_decay_factor = np.exp((decay_constant)*frame_reference_time)
|
|
150
|
+
return frame_decay_factor
|
|
@@ -17,22 +17,19 @@ TODO:
|
|
|
17
17
|
* (stitch_broken_scans) Assumes non-BIDS key 'DecayFactor' instead of BIDS-required 'DecayCorrectionFactor' for
|
|
18
18
|
ease-of-use with NIL data. Should be changed in the future.
|
|
19
19
|
* (stitch_broken_scans) Currently writes intermediate files even if output_image_path is None.
|
|
20
|
-
* (suvr) Allow list to be passed as ref_region to use multiple regions together as a reference region (i.e. left
|
|
21
|
-
and right cerebellum gray matter).
|
|
22
20
|
|
|
23
21
|
"""
|
|
24
|
-
import os
|
|
25
22
|
import pathlib
|
|
26
23
|
import datetime
|
|
27
|
-
import tempfile
|
|
28
24
|
import ants
|
|
29
25
|
import nibabel
|
|
30
26
|
import numpy as np
|
|
31
27
|
from scipy.ndimage import center_of_mass
|
|
32
28
|
|
|
33
|
-
from
|
|
29
|
+
from .motion_target import determine_motion_target
|
|
30
|
+
|
|
34
31
|
from ..utils import image_io, math_lib
|
|
35
|
-
from
|
|
32
|
+
from .decay_correction import undo_decay_correction, decay_correct
|
|
36
33
|
|
|
37
34
|
def stitch_broken_scans(input_image_path: str,
|
|
38
35
|
output_image_path: str,
|
|
@@ -220,112 +217,18 @@ def rescale_image(input_image: ants.core.ANTsImage, rescale_constant: float, op:
|
|
|
220
217
|
return input_image * rescale_constant
|
|
221
218
|
|
|
222
219
|
|
|
223
|
-
def
|
|
224
|
-
input_image_4d_path: str = None,
|
|
225
|
-
half_life: float = None) -> str:
|
|
226
|
-
"""
|
|
227
|
-
Produce a motion target given the ``motion_target_option`` from a method
|
|
228
|
-
running registrations on PET, i.e. :meth:`motion_correction` or
|
|
229
|
-
:meth:`register_pet`.
|
|
230
|
-
|
|
231
|
-
The motion target option can be a string or a tuple. If it is a string,
|
|
232
|
-
then if this string is a file, use the file as the motion target.
|
|
233
|
-
|
|
234
|
-
If it is the option ``weighted_series_sum``, then run
|
|
235
|
-
:meth:`weighted_series_sum` and return the output path.
|
|
236
|
-
|
|
237
|
-
If it is the option ``mean_image``, then compute the time-average of the
|
|
238
|
-
4D-PET image.
|
|
239
|
-
|
|
240
|
-
If it is a tuple, run a weighted sum on the PET series on a range of
|
|
241
|
-
frames. The elements of the tuple are treated as times in seconds, counted
|
|
242
|
-
from the time of the first frame, i.e. (0,300) would average all frames
|
|
243
|
-
from the first to the frame 300 seconds later. If the two elements are the
|
|
244
|
-
same, returns the one frame closest to the entered time.
|
|
245
|
-
|
|
246
|
-
Args:
|
|
247
|
-
motion_target_option (str | tuple | list): Determines how the method behaves,
|
|
248
|
-
according to the above description. Can be a file, a method
|
|
249
|
-
('weighted_series_sum' or 'mean_image'), or a tuple range e.g. (0,600).
|
|
250
|
-
input_image_4d_path (str): Path to the PET image. This is intended to
|
|
251
|
-
be supplied by the parent method employing this function. Default
|
|
252
|
-
value None.
|
|
253
|
-
half_life (float): Half life of the radiotracer used in the image
|
|
254
|
-
located at ``input_image_4d_path``. Only used if a calculation is
|
|
255
|
-
performed.
|
|
256
|
-
|
|
257
|
-
Returns:
|
|
258
|
-
out_image_file (str): File to use as a target to compute
|
|
259
|
-
transformations on.
|
|
260
|
-
|
|
261
|
-
Raises:
|
|
262
|
-
ValueError: If ``motion_target_option`` does not match an acceptable option, or if
|
|
263
|
-
``half_life`` is not specifiedwhen ``motion_target_option`` is not 'mean_image'
|
|
264
|
-
TypeError: If start and end time are incompatible with ``float`` type.
|
|
265
|
-
"""
|
|
266
|
-
if motion_target_option != 'mean_image' and half_life is None:
|
|
267
|
-
raise ValueError('half_life must be specified if not using "mean_image" for motion_target_option')
|
|
268
|
-
|
|
269
|
-
if isinstance(motion_target_option, str):
|
|
270
|
-
if os.path.exists(motion_target_option):
|
|
271
|
-
return motion_target_option
|
|
272
|
-
|
|
273
|
-
if motion_target_option == 'weighted_series_sum':
|
|
274
|
-
out_image_file = tempfile.mkstemp(suffix='_wss.nii.gz')[1]
|
|
275
|
-
weighted_series_sum(input_image_4d_path=input_image_4d_path,
|
|
276
|
-
out_image_path=out_image_file,
|
|
277
|
-
half_life=half_life,
|
|
278
|
-
verbose=False)
|
|
279
|
-
return out_image_file
|
|
280
|
-
|
|
281
|
-
if motion_target_option == 'mean_image':
|
|
282
|
-
out_image_file = tempfile.mkstemp(suffix='_mean.nii.gz')[1]
|
|
283
|
-
input_img = ants.image_read(input_image_4d_path)
|
|
284
|
-
mean_img = get_average_of_timeseries(input_image=input_img)
|
|
285
|
-
ants.image_write(image=mean_img,filename=out_image_file)
|
|
286
|
-
return out_image_file
|
|
287
|
-
|
|
288
|
-
raise ValueError("motion_target_option did not match a file or 'weighted_series_sum'")
|
|
289
|
-
|
|
290
|
-
if isinstance(motion_target_option, (list, tuple)):
|
|
291
|
-
|
|
292
|
-
start_time = motion_target_option[0]
|
|
293
|
-
end_time = motion_target_option[1]
|
|
294
|
-
|
|
295
|
-
try:
|
|
296
|
-
float(start_time)
|
|
297
|
-
float(end_time)
|
|
298
|
-
except Exception as exc:
|
|
299
|
-
raise TypeError('Start time and end time of calculation must be '
|
|
300
|
-
'able to be cast into float! Provided values are '
|
|
301
|
-
f"{start_time} and {end_time}.") from exc
|
|
302
|
-
|
|
303
|
-
out_image_file = tempfile.mkstemp(suffix='_wss.nii.gz')[1]
|
|
304
|
-
weighted_series_sum(input_image_4d_path=input_image_4d_path,
|
|
305
|
-
out_image_path=out_image_file,
|
|
306
|
-
half_life=half_life,
|
|
307
|
-
verbose=False,
|
|
308
|
-
start_time=float(start_time),
|
|
309
|
-
end_time=float(end_time))
|
|
310
|
-
|
|
311
|
-
return out_image_file
|
|
312
|
-
|
|
313
|
-
raise ValueError('motion_target_option did not match str or tuple type.')
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
def brain_mask(input_image_4d_path: str,
|
|
220
|
+
def brain_mask(input_image_path: str,
|
|
317
221
|
out_image_path: str,
|
|
318
222
|
atlas_image_path: str,
|
|
319
223
|
atlas_mask_path: str,
|
|
320
|
-
motion_target_option='mean_image'
|
|
321
|
-
half_life: float=None):
|
|
224
|
+
motion_target_option='mean_image'):
|
|
322
225
|
"""
|
|
323
226
|
Create a brain mask for a PET image. Create target PET image, which is then warped to a
|
|
324
227
|
provided anatomical atlas. The transformation to atlas space is then applied to transform a
|
|
325
228
|
provided mask in atlas space into PET space. This mask can then by used in various operations.
|
|
326
229
|
|
|
327
230
|
Args:
|
|
328
|
-
|
|
231
|
+
input_image_path (str): Path to input 4D PET image.
|
|
329
232
|
out_image_path (str): Path to which brain mask in PET space is written.
|
|
330
233
|
atlas_image_path (str): Path to anatomical atlas image.
|
|
331
234
|
atlas_mask_path (str): Path to brain mask in atlas space.
|
|
@@ -338,11 +241,9 @@ def brain_mask(input_image_4d_path: str,
|
|
|
338
241
|
"""
|
|
339
242
|
atlas = ants.image_read(atlas_image_path)
|
|
340
243
|
atlas_mask = ants.image_read(atlas_mask_path)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
half_life=half_life
|
|
345
|
-
))
|
|
244
|
+
motion_target = determine_motion_target(motion_target_option=motion_target_option,
|
|
245
|
+
input_image_path=input_image_path)
|
|
246
|
+
pet_ref = ants.image_read(motion_target)
|
|
346
247
|
xfm = ants.registration(
|
|
347
248
|
fixed=atlas,
|
|
348
249
|
moving=pet_ref,
|
|
@@ -370,7 +271,7 @@ def extract_mean_roi_tac_from_nifti_using_segmentation(input_image_4d_numpy: np.
|
|
|
370
271
|
regional values. Currently, only the mean over a single region value is implemented.
|
|
371
272
|
|
|
372
273
|
Args:
|
|
373
|
-
|
|
274
|
+
input_image_path (str): Path to a .nii or .nii.gz file containing a 4D
|
|
374
275
|
PET image, registered to anatomical space.
|
|
375
276
|
segmentation_image_path (str): Path to a .nii or .nii.gz file containing a 3D segmentation
|
|
376
277
|
image, where integer indices label specific regions. Must have same sampling as PET
|
|
@@ -447,71 +348,6 @@ def binarize_image_with_threshold(input_image_numpy: np.ndarray,
|
|
|
447
348
|
return bounded_image
|
|
448
349
|
|
|
449
350
|
|
|
450
|
-
def get_average_of_timeseries(input_image: ants.ANTsImage):
|
|
451
|
-
"""
|
|
452
|
-
Get average of a 4D ANTsImage and return as a 3D ANTsImage.
|
|
453
|
-
"""
|
|
454
|
-
assert len(input_image.shape) == 4, "Input image must be 4D"
|
|
455
|
-
mean_array = input_image.mean(axis=-1)
|
|
456
|
-
mean_image = ants.from_numpy(data=mean_array,
|
|
457
|
-
origin=input_image.origin[:-1],
|
|
458
|
-
spacing=input_image.spacing[:-1],
|
|
459
|
-
direction=input_image.direction[:-1,:-1])
|
|
460
|
-
return mean_image
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
def suvr(input_image_path: str,
|
|
464
|
-
out_image_path: str | None,
|
|
465
|
-
segmentation_image_path: str,
|
|
466
|
-
ref_region: int,
|
|
467
|
-
verbose: bool=False) -> ants.ANTsImage:
|
|
468
|
-
"""
|
|
469
|
-
Computes an ``SUVR`` (Standard Uptake Value Ratio) by taking the average of
|
|
470
|
-
an input image within a reference region, and dividing the input image by
|
|
471
|
-
said average value.
|
|
472
|
-
|
|
473
|
-
Args:
|
|
474
|
-
input_image_path (str): Path to 3D weighted series sum or other
|
|
475
|
-
parametric image on which we compute SUVR.
|
|
476
|
-
out_image_path (str): Path to output image file which is written to. If None, no output is written.
|
|
477
|
-
segmentation_image_path (str): Path to segmentation image, which we use
|
|
478
|
-
to compute average uptake value in the reference region.
|
|
479
|
-
ref_region (int): Region number mapping to the reference region in the
|
|
480
|
-
segmentation image.
|
|
481
|
-
verbose (bool): Set to ``True`` to output processing information. Default is False.
|
|
482
|
-
|
|
483
|
-
Returns:
|
|
484
|
-
ants.ANTsImage: SUVR parametric image
|
|
485
|
-
"""
|
|
486
|
-
pet_img = ants.image_read(filename=input_image_path)
|
|
487
|
-
pet_arr = pet_img.numpy()
|
|
488
|
-
segmentation_img = ants.image_read(filename=segmentation_image_path,
|
|
489
|
-
pixeltype='unsigned int')
|
|
490
|
-
segmentation_arr = segmentation_img.numpy()
|
|
491
|
-
|
|
492
|
-
if len(pet_arr.shape)!=3:
|
|
493
|
-
raise ValueError("SUVR input image is not 3D. If your image is dynamic, try running 'weighted_series_sum'"
|
|
494
|
-
" first.")
|
|
495
|
-
|
|
496
|
-
ref_region_avg = extract_mean_roi_tac_from_nifti_using_segmentation(input_image_4d_numpy=pet_arr,
|
|
497
|
-
segmentation_image_numpy=segmentation_arr,
|
|
498
|
-
region=ref_region,
|
|
499
|
-
verbose=verbose)
|
|
500
|
-
|
|
501
|
-
suvr_arr = pet_arr / ref_region_avg[0]
|
|
502
|
-
|
|
503
|
-
out_img = ants.from_numpy_like(data=suvr_arr,
|
|
504
|
-
image=pet_img)
|
|
505
|
-
|
|
506
|
-
if out_image_path is not None:
|
|
507
|
-
ants.image_write(image=out_img,
|
|
508
|
-
filename=out_image_path)
|
|
509
|
-
image_io.safe_copy_meta(input_image_path=input_image_path,
|
|
510
|
-
out_image_path=out_image_path)
|
|
511
|
-
|
|
512
|
-
return out_img
|
|
513
|
-
|
|
514
|
-
|
|
515
351
|
def gauss_blur(input_image_path: str,
|
|
516
352
|
blur_size_mm: float,
|
|
517
353
|
out_image_path: str,
|
|
@@ -556,7 +392,7 @@ def gauss_blur(input_image_path: str,
|
|
|
556
392
|
return out_image
|
|
557
393
|
|
|
558
394
|
|
|
559
|
-
def roi_tac(
|
|
395
|
+
def roi_tac(input_image_path: str,
|
|
560
396
|
roi_image_path: str,
|
|
561
397
|
region: int,
|
|
562
398
|
out_tac_path: str,
|
|
@@ -573,9 +409,9 @@ def roi_tac(input_image_4d_path: str,
|
|
|
573
409
|
raise ValueError("'time_frame_keyword' must be one of "
|
|
574
410
|
"'FrameReferenceTime' or 'FrameTimesStart'")
|
|
575
411
|
|
|
576
|
-
pet_meta = image_io.load_metadata_for_nifti_with_same_filename(
|
|
412
|
+
pet_meta = image_io.load_metadata_for_nifti_with_same_filename(input_image_path)
|
|
577
413
|
tac_extraction_func = extract_mean_roi_tac_from_nifti_using_segmentation
|
|
578
|
-
pet_numpy = nibabel.load(
|
|
414
|
+
pet_numpy = nibabel.load(input_image_path).get_fdata()
|
|
579
415
|
seg_numpy = nibabel.load(roi_image_path).get_fdata()
|
|
580
416
|
|
|
581
417
|
|