petpal 0.5.7__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.7 → petpal-0.5.8}/.gitignore +4 -1
- {petpal-0.5.7 → petpal-0.5.8}/PKG-INFO +1 -1
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/decay_correction.py +11 -10
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/scan_timing.py +66 -19
- {petpal-0.5.7 → 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.7 → petpal-0.5.8}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/.github/workflows/publish-to-pypi.yml +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/.github/workflows/python-package.yml +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/.readthedocs.yaml +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/LICENSE +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/README.md +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tac_1tcm_set-02.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tac_1tcm_set-02.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/noise_free/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-00.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-01.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/1tcm/params_1tcm_set-02.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_evenly_resampled.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_evenly_resampled_woMax.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/fdg_plasma_clamp_tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/gen_tcms_data.ipynb +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/readme.md +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tac_2tcm_set-02.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tac_2tcm_set-02.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/noise_free/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-00.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-01.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm/params_serial_2tcm_set-02.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tac_2tcm_k4zero_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tac_2tcm_k4zero_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/gaussian_noise/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-00.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-01.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tacs.pdf +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tacs.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-00.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-01.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/turku_pet_center_fdg_plasma_clamp.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/Makefile +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/PETPAL_Logo.png +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/index.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/attribute.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/class.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/data.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/exception.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/function.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/method.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/module.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/package.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/_templates/python/property.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/conf.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/index.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/make.bat +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/requirements.txt +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/tutorials/index.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/docs/tutorials/pib_example.rst +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_graphical_analysis.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_graphical_plots.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_idif.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_parametric_images.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_pib_processing.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_plot_tacs.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_preproc.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_pvc.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_reference_tissue_models.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_stats.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_tac_fitting.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_tac_interpolation.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/cli/cli_vat_processing.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/input_function/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/input_function/blood_input.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/input_function/idif_necktangle.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/input_function/pca_guided_idif.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/fit_tac_with_rtms.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/graphical_analysis.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/parametric_images.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/reference_tissue_models.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/rtm_analysis.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/tac_fitting.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/tac_interpolation.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/tac_uncertainty.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/kinetic_modeling/tcms_as_convolutions.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/meta/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/meta/label_maps.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/kinetic_modeling_steps.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/pca_guided_idif_steps.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/pipelines.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/preproc_steps.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/steps_base.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/pipelines/steps_containers.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/image_operations_4d.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/motion_corr.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/motion_target.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/partial_volume_corrections.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/regional_tac_extraction.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/register.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/segmentation_tools.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/standard_uptake_value.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/preproc/symmetric_geometric_transfer_matrix.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/bids_utils.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/constants.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/data_driven_image_analyses.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/decorators.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/image_io.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/math_lib.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/metadata.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/stats.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/testing_utils.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/time_activity_curve.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/utils/useful_functions.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/visualizations/__init__.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/visualizations/graphical_plots.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/visualizations/image_visualization.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/visualizations/qc_plots.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/petpal/visualizations/tac_plots.py +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/shared/dseg.tsv +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/shared/freesurfer_lmap.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/shared/freesurfer_lmap_lr.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/shared/perl_cyno_lmap.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/shared/perl_cyno_lmap_lr.json +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/test_notebooks/explicit_tac_fitting/01_fitting_TCMs.ipynb +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/test_notebooks/testing_RTMs/01_testing_RTMs.ipynb +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/01_testing_on_tcms_database.ipynb +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/02_testing_parametric_images.ipynb +0 -0
- {petpal-0.5.7 → petpal-0.5.8}/test_notebooks/testing_graphical_analyses/03_plotting_graphical_anlayses_testbed.ipynb +0 -0
- {petpal-0.5.7 → 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>
|
|
@@ -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
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module to handle timing information of PET scans.
|
|
3
3
|
"""
|
|
4
|
-
import
|
|
4
|
+
from typing import Self
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
@@ -82,8 +82,8 @@ class ScanTimingInfo:
|
|
|
82
82
|
|
|
83
83
|
"""
|
|
84
84
|
duration: np.ndarray[float]
|
|
85
|
-
end: np.ndarray[float]
|
|
86
85
|
start: np.ndarray[float]
|
|
86
|
+
end: np.ndarray[float]
|
|
87
87
|
center: np.ndarray[float]
|
|
88
88
|
decay: np.ndarray[float]
|
|
89
89
|
|
|
@@ -130,7 +130,7 @@ class ScanTimingInfo:
|
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
@classmethod
|
|
133
|
-
def from_metadata(cls, metadata_dict: dict):
|
|
133
|
+
def from_metadata(cls, metadata_dict: dict) -> Self:
|
|
134
134
|
r"""
|
|
135
135
|
Extracts frame timing information and decay factors from a json metadata.
|
|
136
136
|
Expects that the JSON metadata has ``FrameDuration`` and ``DecayFactor`` or
|
|
@@ -155,13 +155,13 @@ class ScanTimingInfo:
|
|
|
155
155
|
"""
|
|
156
156
|
frm_dur = np.asarray(metadata_dict['FrameDuration'], float)
|
|
157
157
|
try:
|
|
158
|
-
|
|
158
|
+
frm_starts = np.asarray(metadata_dict['FrameTimesStart'], float)
|
|
159
159
|
except KeyError:
|
|
160
|
-
|
|
160
|
+
frm_starts = np.cumsum(frm_dur)-frm_dur
|
|
161
161
|
try:
|
|
162
|
-
|
|
162
|
+
frm_ends = np.asarray(metadata_dict['FrameTimesEnd'], float)
|
|
163
163
|
except KeyError:
|
|
164
|
-
|
|
164
|
+
frm_ends = frm_starts+frm_dur
|
|
165
165
|
try:
|
|
166
166
|
decay = np.asarray(metadata_dict['DecayCorrectionFactor'], float)
|
|
167
167
|
except KeyError:
|
|
@@ -178,7 +178,7 @@ class ScanTimingInfo:
|
|
|
178
178
|
decay=decay)
|
|
179
179
|
|
|
180
180
|
@classmethod
|
|
181
|
-
def from_nifti(cls, image_path: str):
|
|
181
|
+
def from_nifti(cls, image_path: str) -> Self:
|
|
182
182
|
r"""
|
|
183
183
|
Extracts frame timing information and decay factors from a NIfTI image metadata.
|
|
184
184
|
Expects that the JSON metadata file has ``FrameDuration`` and ``DecayFactor`` or
|
|
@@ -204,6 +204,49 @@ class ScanTimingInfo:
|
|
|
204
204
|
_meta_data = load_metadata_for_nifti_with_same_filename(image_path=image_path)
|
|
205
205
|
return cls.from_metadata(metadata_dict=_meta_data)
|
|
206
206
|
|
|
207
|
+
@classmethod
|
|
208
|
+
def from_start_end(cls,
|
|
209
|
+
frame_starts: np.ndarray,
|
|
210
|
+
frame_ends: np.ndarray,
|
|
211
|
+
decay_correction_factor: np.ndarray | None=None) -> Self:
|
|
212
|
+
"""Infer timing properties based on start and end time.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
frame_starts (np.ndarray): Start time of each frame.
|
|
216
|
+
frame_ends (np.ndarray): End time of each frame.
|
|
217
|
+
decay_correction_factor (np.ndarray | None): Decay correction factor, which can be
|
|
218
|
+
optionally provided based on the type of analysis being done. If None, frame decay
|
|
219
|
+
will be set to ones. Default None.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
scan_timing_info (ScanTimingInfo): ScanTimingInfo object with the correct start, end,
|
|
223
|
+
duration, midpoint, and (optionally) decay correction for each frame.
|
|
224
|
+
|
|
225
|
+
Raises:
|
|
226
|
+
ValueError: If frame_starts, frame_ends, and decay_correction_factor (if provided) are
|
|
227
|
+
not of identical shape.
|
|
228
|
+
|
|
229
|
+
"""
|
|
230
|
+
if frame_starts.shape != frame_ends.shape:
|
|
231
|
+
raise ValueError("frame_ends must have the same shape as frame_starts")
|
|
232
|
+
|
|
233
|
+
frame_duration = frame_ends - frame_starts
|
|
234
|
+
frame_midpoint = frame_starts + frame_duration / 2
|
|
235
|
+
frame_decay = np.ones_like(frame_starts)
|
|
236
|
+
|
|
237
|
+
if decay_correction_factor is None:
|
|
238
|
+
frame_decay = np.ones_like(frame_starts, dtype=float)
|
|
239
|
+
else:
|
|
240
|
+
frame_decay = np.asarray(decay_correction_factor, dtype=float)
|
|
241
|
+
if frame_decay.shape != frame_starts.shape:
|
|
242
|
+
raise ValueError("decay_correction_factor must have the same shape as frame_starts")
|
|
243
|
+
|
|
244
|
+
return cls(duration=frame_duration,
|
|
245
|
+
start=frame_starts,
|
|
246
|
+
end=frame_ends,
|
|
247
|
+
center=frame_midpoint,
|
|
248
|
+
decay=frame_decay)
|
|
249
|
+
|
|
207
250
|
|
|
208
251
|
def get_window_index_pairs_from_durations(frame_durations: np.ndarray, w_size: float):
|
|
209
252
|
r"""
|
|
@@ -263,25 +306,29 @@ def get_window_index_pairs_for_image(image_path: str, w_size: float):
|
|
|
263
306
|
w_size=w_size)
|
|
264
307
|
|
|
265
308
|
|
|
266
|
-
def calculate_frame_reference_time(frame_duration:
|
|
267
|
-
frame_start:
|
|
268
|
-
half_life: float) ->
|
|
309
|
+
def calculate_frame_reference_time(frame_duration: np.ndarray,
|
|
310
|
+
frame_start: np.ndarray,
|
|
311
|
+
half_life: float) -> np.ndarray:
|
|
269
312
|
r"""Compute frame reference time as the time at which the average activity occurs.
|
|
270
313
|
|
|
271
|
-
Equation comes from the `DICOM standard documentation
|
|
314
|
+
Equation comes from the `DICOM standard documentation
|
|
315
|
+
<https://dicom.innolitics.com/ciods/positron-emission-tomography-image/pet-image/00541300>`_
|
|
272
316
|
|
|
273
317
|
:math:`T_{ave}=\frac{1}{\lambda}ln\frac{\lambda T}{1-e^{-\lambda T}}`
|
|
274
318
|
|
|
275
|
-
where lambda is the decay constant, :math:`\frac{ln2}{T_{1/2}}`, :math:`T_{1/2}` is the half
|
|
319
|
+
where lambda is the decay constant, :math:`\frac{ln2}{T_{1/2}}`, :math:`T_{1/2}` is the half
|
|
320
|
+
life, and :math:`T` is the frame duration.
|
|
276
321
|
|
|
277
322
|
Args:
|
|
278
|
-
frame_duration (
|
|
279
|
-
frame_start (
|
|
280
|
-
half_life (float): Radionuclide half life
|
|
323
|
+
frame_duration (np.ndarray): Duration of each frame in seconds.
|
|
324
|
+
frame_start (np.ndarray): Start time of each frame relative to scan start, in seconds.
|
|
325
|
+
half_life (float): Radionuclide half life in seconds.
|
|
281
326
|
|
|
282
327
|
Returns:
|
|
283
|
-
|
|
328
|
+
np.ndarray: Frame reference time for each frame in the scan in seconds.
|
|
284
329
|
"""
|
|
285
|
-
decay_constant =
|
|
286
|
-
|
|
330
|
+
decay_constant = np.log(2)/half_life
|
|
331
|
+
decay_over_frame = decay_constant*frame_duration
|
|
332
|
+
reference_time_delay = np.log((decay_over_frame)/(1-np.exp(-decay_over_frame)))/decay_constant
|
|
333
|
+
frame_reference_time = frame_start + reference_time_delay
|
|
287
334
|
return frame_reference_time
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from types import SimpleNamespace
|
|
3
|
+
from petpal.preproc.register import register_pet
|
|
4
|
+
|
|
5
|
+
import petpal.preproc.register as reg_mod
|
|
6
|
+
|
|
7
|
+
class DummyImage:
|
|
8
|
+
def __init__(self, dimension, name=None):
|
|
9
|
+
self.dimension = dimension
|
|
10
|
+
self.name = name
|
|
11
|
+
|
|
12
|
+
def make_mocks(monkeypatch, pet_dim, recorded):
|
|
13
|
+
# Mock determine_motion_target to return a path string
|
|
14
|
+
monkeypatch.setattr(reg_mod, "determine_motion_target", lambda motion_target_option, input_image_path: "motion_target.nii")
|
|
15
|
+
# Mock ants.image_read to return DummyImage instances depending on path
|
|
16
|
+
def mock_image_read(path):
|
|
17
|
+
if path == "motion_target.nii":
|
|
18
|
+
img = DummyImage(dimension=3, name="motion_target")
|
|
19
|
+
elif path == "mri.nii":
|
|
20
|
+
img = DummyImage(dimension=3, name="mri")
|
|
21
|
+
elif path == "pet.nii":
|
|
22
|
+
img = DummyImage(dimension=pet_dim, name="pet")
|
|
23
|
+
else:
|
|
24
|
+
img = DummyImage(dimension=0, name=path)
|
|
25
|
+
recorded['image_reads'].append((path, img))
|
|
26
|
+
return img
|
|
27
|
+
monkeypatch.setattr(reg_mod.ants, "image_read", mock_image_read)
|
|
28
|
+
# Mock ants.registration to record args and return transforms
|
|
29
|
+
def mock_registration(*, moving, fixed, type_of_transform, write_composite_transform=True, **kwargs):
|
|
30
|
+
recorded['registration_calls'].append({
|
|
31
|
+
'moving': moving, 'fixed': fixed, 'type_of_transform': type_of_transform, 'kwargs': kwargs
|
|
32
|
+
})
|
|
33
|
+
return {'fwdtransforms': ['/fake/xfm']}
|
|
34
|
+
monkeypatch.setattr(reg_mod.ants, "registration", mock_registration)
|
|
35
|
+
# Mock ants.apply_transforms to record imagetype and return a dummy transformed image
|
|
36
|
+
def mock_apply_transforms(*, moving, fixed, transformlist, interpolator=None, imagetype=None, **kwargs):
|
|
37
|
+
recorded['apply_calls'].append({'moving': moving, 'fixed': fixed, 'transformlist': transformlist, 'imagetype': imagetype})
|
|
38
|
+
return SimpleNamespace(name="transformed_image", imagetype=imagetype)
|
|
39
|
+
monkeypatch.setattr(reg_mod.ants, "apply_transforms", mock_apply_transforms)
|
|
40
|
+
# Mock ants.image_write to record output path
|
|
41
|
+
monkeypatch.setattr(reg_mod.ants, "image_write", lambda img, out: recorded['written'].append((img, out)))
|
|
42
|
+
# Mock image_io.safe_copy_meta
|
|
43
|
+
monkeypatch.setattr(reg_mod.image_io, "safe_copy_meta", lambda input_image_path, out_image_path: recorded['meta_copied'].append((input_image_path, out_image_path)))
|
|
44
|
+
|
|
45
|
+
@pytest.mark.parametrize("pet_dim, expected_imagetype", [
|
|
46
|
+
(4, 3),
|
|
47
|
+
(3, 0),
|
|
48
|
+
])
|
|
49
|
+
def test_register_pet_sets_imagetype_and_writes(monkeypatch, capsys, pet_dim, expected_imagetype):
|
|
50
|
+
recorded = {'image_reads': [], 'registration_calls': [], 'apply_calls': [], 'written': [], 'meta_copied': []}
|
|
51
|
+
make_mocks(monkeypatch, pet_dim=pet_dim, recorded=recorded)
|
|
52
|
+
|
|
53
|
+
# Call function under test
|
|
54
|
+
register_pet(input_reg_image_path="pet.nii",
|
|
55
|
+
out_image_path="out.nii",
|
|
56
|
+
reference_image_path="mri.nii",
|
|
57
|
+
motion_target_option="some_option",
|
|
58
|
+
verbose=True,
|
|
59
|
+
type_of_transform="DenseRigid")
|
|
60
|
+
|
|
61
|
+
# Check registration was called with motion target as moving and mri as fixed
|
|
62
|
+
assert recorded['registration_calls'], "ants.registration was not called"
|
|
63
|
+
reg_call = recorded['registration_calls'][-1]
|
|
64
|
+
assert getattr(reg_call['moving'], "name", None) == "motion_target"
|
|
65
|
+
assert getattr(reg_call['fixed'], "name", None) == "mri"
|
|
66
|
+
assert reg_call['type_of_transform'] == "DenseRigid"
|
|
67
|
+
|
|
68
|
+
# Check apply_transforms was called with correct imagetype based on input dimension
|
|
69
|
+
assert recorded['apply_calls'], "ants.apply_transforms was not called"
|
|
70
|
+
apply_call = recorded['apply_calls'][-1]
|
|
71
|
+
assert apply_call['imagetype'] == expected_imagetype
|
|
72
|
+
|
|
73
|
+
# Check image was written and metadata copied
|
|
74
|
+
assert recorded['written'] and recorded['written'][-1][1] == "out.nii"
|
|
75
|
+
assert recorded['meta_copied'] and recorded['meta_copied'][-1] == ("pet.nii", "out.nii")
|
|
76
|
+
|
|
77
|
+
# Check verbose prints
|
|
78
|
+
captured = capsys.readouterr().out
|
|
79
|
+
print(captured)
|
|
80
|
+
assert "Registration computed transforming image motion_target.nii to mri.nii space" in captured
|
|
81
|
+
assert "Registration applied to pet.nii" in captured
|
|
82
|
+
assert "Transformed image saved to out.nii" in captured
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
from petpal.utils.scan_timing import calculate_frame_reference_time
|
|
4
|
+
from petpal.preproc.decay_correction import calculate_frame_decay_factor
|
|
5
|
+
from petpal.utils.scan_timing import ScanTimingInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_from_metadata_with_all_keys():
|
|
9
|
+
metadata = {
|
|
10
|
+
"FrameDuration": [60, 120, 180],
|
|
11
|
+
"FrameTimesStart": [0, 60, 180],
|
|
12
|
+
"FrameTimesEnd": [60, 180, 360],
|
|
13
|
+
"FrameReferenceTime": [30, 120, 270],
|
|
14
|
+
"DecayCorrectionFactor": [1.0, 0.95, 0.9],
|
|
15
|
+
}
|
|
16
|
+
sti = ScanTimingInfo.from_metadata(metadata)
|
|
17
|
+
np.testing.assert_allclose(sti.duration, np.array([60.0, 120.0, 180.0]))
|
|
18
|
+
np.testing.assert_allclose(sti.start, np.array([0.0, 60.0, 180.0]))
|
|
19
|
+
np.testing.assert_allclose(sti.end, np.array([60.0, 180.0, 360.0]))
|
|
20
|
+
np.testing.assert_allclose(sti.center, np.array([30.0, 120.0, 270.0]))
|
|
21
|
+
np.testing.assert_allclose(sti.decay, np.array([1.0, 0.95, 0.9]))
|
|
22
|
+
assert sti.duration.dtype.kind == "f"
|
|
23
|
+
assert sti.start.dtype.kind == "f"
|
|
24
|
+
assert sti.end.dtype.kind == "f"
|
|
25
|
+
assert sti.center.dtype.kind == "f"
|
|
26
|
+
assert sti.decay.dtype.kind == "f"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_from_metadata_infers_start_end_and_center_and_uses_decayfactor():
|
|
30
|
+
metadata = {
|
|
31
|
+
"FrameDuration": [30, 30, 60],
|
|
32
|
+
# no FrameTimesStart, no FrameTimesEnd, no FrameReferenceTime
|
|
33
|
+
"DecayFactor": [1.0, 0.99, 0.98],
|
|
34
|
+
}
|
|
35
|
+
sti = ScanTimingInfo.from_metadata(metadata)
|
|
36
|
+
expected_starts = np.array([0.0, 30.0, 60.0])
|
|
37
|
+
expected_ends = np.array([30.0, 60.0, 120.0])
|
|
38
|
+
expected_centers = expected_starts + np.array([30.0, 30.0, 60.0]) / 2.0
|
|
39
|
+
np.testing.assert_allclose(sti.start, expected_starts)
|
|
40
|
+
np.testing.assert_allclose(sti.end, expected_ends)
|
|
41
|
+
np.testing.assert_allclose(sti.center, expected_centers)
|
|
42
|
+
np.testing.assert_allclose(sti.duration, np.array([30.0, 30.0, 60.0]))
|
|
43
|
+
np.testing.assert_allclose(sti.decay, np.array([1.0, 0.99, 0.98]))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_from_metadata_prefers_decay_correction_over_decayfactor():
|
|
47
|
+
metadata = {
|
|
48
|
+
"FrameDuration": [10, 20],
|
|
49
|
+
"FrameTimesStart": [0, 10],
|
|
50
|
+
"FrameTimesEnd": [10, 30],
|
|
51
|
+
"DecayFactor": [0.5, 0.6],
|
|
52
|
+
"DecayCorrectionFactor": [0.9, 0.8],
|
|
53
|
+
}
|
|
54
|
+
sti = ScanTimingInfo.from_metadata(metadata)
|
|
55
|
+
# DecayCorrectionFactor should be used when present
|
|
56
|
+
np.testing.assert_allclose(sti.decay, np.array([0.9, 0.8]))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_from_start_end_computes_duration_center_and_default_decay():
|
|
60
|
+
starts = np.array([0.0, 60.0, 180.0])
|
|
61
|
+
ends = np.array([60.0, 180.0, 360.0])
|
|
62
|
+
info = ScanTimingInfo.from_start_end(frame_starts=starts, frame_ends=ends)
|
|
63
|
+
np.testing.assert_allclose(info.duration, np.array([60.0, 120.0, 180.0]))
|
|
64
|
+
np.testing.assert_allclose(info.center, np.array([30.0, 120.0, 270.0]))
|
|
65
|
+
np.testing.assert_allclose(info.decay, np.ones_like(starts))
|
|
66
|
+
|
|
67
|
+
def test_from_start_end_uses_provided_decay_list():
|
|
68
|
+
starts = np.array([0.0, 50.0])
|
|
69
|
+
ends = np.array([25.0, 100.0])
|
|
70
|
+
decay_list = [1.0, 0.9]
|
|
71
|
+
info = ScanTimingInfo.from_start_end(frame_starts=starts, frame_ends=ends, decay_correction_factor=decay_list)
|
|
72
|
+
np.testing.assert_allclose(info.duration, np.array([25.0, 50.0]))
|
|
73
|
+
np.testing.assert_allclose(info.center, np.array([12.5, 75.0]))
|
|
74
|
+
np.testing.assert_allclose(info.decay, np.array(decay_list))
|
|
75
|
+
|
|
76
|
+
def test_ref_time_no_decay_returns_midpoint():
|
|
77
|
+
durations = np.array([5.0, 10.0])
|
|
78
|
+
starts = np.array([0.0, 5.0])
|
|
79
|
+
half_life = 1.0e8 # effectively no decay
|
|
80
|
+
res = calculate_frame_reference_time(durations, starts, half_life)
|
|
81
|
+
expected = starts + durations / 2.0
|
|
82
|
+
np.testing.assert_allclose(res, expected, rtol=1e-2, atol=1e-3)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_ref_time_fast_decay_concentrates_near_start():
|
|
86
|
+
durations = np.array([60.0, 30.0, 15.0])
|
|
87
|
+
starts = np.array([0.0, 5.0, 10.0])
|
|
88
|
+
half_life = 1e-6 # very fast decay
|
|
89
|
+
res = calculate_frame_reference_time(durations, starts, half_life)
|
|
90
|
+
delays = res - starts
|
|
91
|
+
# For very fast decay, the reference time should be very close to frame start
|
|
92
|
+
assert np.all(delays < durations * 0.01)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_ref_time_numeric_integration_agrees():
|
|
96
|
+
# compare against numeric integral definition of weighted average time
|
|
97
|
+
durations = np.array([5.0, 10.0, 60.0])
|
|
98
|
+
starts = np.array([0.0, 5.0, 15.0])
|
|
99
|
+
half_life = 1e4
|
|
100
|
+
res = calculate_frame_reference_time(durations, starts, half_life)
|
|
101
|
+
|
|
102
|
+
expected = []
|
|
103
|
+
for T, s in zip(durations, starts):
|
|
104
|
+
lam = np.log(2) / half_life
|
|
105
|
+
t = np.linspace(0.0, T, 20001)
|
|
106
|
+
w = np.exp(-lam * t)
|
|
107
|
+
num = np.trapezoid(t * w, t)
|
|
108
|
+
den = np.trapezoid(w, t)
|
|
109
|
+
delay = num / den
|
|
110
|
+
expected.append(s + delay)
|
|
111
|
+
expected = np.asarray(expected)
|
|
112
|
+
|
|
113
|
+
np.testing.assert_allclose(res, expected, rtol=1e-3, atol=1e-9)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_ref_time_vectorized_shape_and_broadcast():
|
|
117
|
+
durations = np.array([10.0])
|
|
118
|
+
starts = np.array([2.0])
|
|
119
|
+
half_life = 1.0e3
|
|
120
|
+
res = calculate_frame_reference_time(durations, starts, half_life)
|
|
121
|
+
assert isinstance(res, np.ndarray)
|
|
122
|
+
assert res.shape == (1,)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_basic_powers_of_two():
|
|
126
|
+
half_life = 2.0
|
|
127
|
+
times = np.array([0.0, half_life, 2 * half_life])
|
|
128
|
+
out = calculate_frame_decay_factor(times, half_life)
|
|
129
|
+
expected = np.array([1.0, 2.0, 4.0])
|
|
130
|
+
np.testing.assert_allclose(out, expected, rtol=1e-12, atol=0)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_preserves_shape_and_dtype():
|
|
134
|
+
times = np.array([0.5])
|
|
135
|
+
out = calculate_frame_decay_factor(times, 1.0)
|
|
136
|
+
assert isinstance(out, np.ndarray)
|
|
137
|
+
assert out.shape == times.shape
|
|
138
|
+
np.testing.assert_allclose(out[0], 2 ** 0.5, rtol=1e-12)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_negative_time_and_float_half_life():
|
|
142
|
+
half_life = 1.5
|
|
143
|
+
times = np.array([-half_life, 0.0, half_life])
|
|
144
|
+
out = calculate_frame_decay_factor(times, half_life)
|
|
145
|
+
expected = np.array([0.5, 1.0, 2.0])
|
|
146
|
+
np.testing.assert_allclose(out, expected, rtol=1e-12, atol=0)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
from petpal.utils.math_lib import weighted_sum_computation
|
|
4
|
+
from petpal.utils.scan_timing import calculate_frame_reference_time
|
|
5
|
+
from petpal.preproc.decay_correction import calculate_frame_decay_factor
|
|
6
|
+
|
|
7
|
+
def test_weighted_sum_computation_all_ones_simple():
|
|
8
|
+
# simple case: all voxels = 1, decay_correction = 1, frame_start[0]=0
|
|
9
|
+
pet_series = np.ones((2, 2, 2, 3), dtype=float)
|
|
10
|
+
frame_duration = np.array([10.0, 20.0, 30.0])
|
|
11
|
+
half_life = 100.0
|
|
12
|
+
frame_start = np.array([0.0, 10.0, 30.0])
|
|
13
|
+
decay_correction = np.ones(3)
|
|
14
|
+
|
|
15
|
+
decay_constant = np.log(2.0) / half_life
|
|
16
|
+
image_total_duration = frame_duration.sum()
|
|
17
|
+
total_decay = decay_constant * image_total_duration
|
|
18
|
+
total_decay /= 1.0 - np.exp(-decay_constant * image_total_duration)
|
|
19
|
+
total_decay /= np.exp(-decay_constant * frame_start[0])
|
|
20
|
+
|
|
21
|
+
expected = np.full((2, 2, 2), total_decay)
|
|
22
|
+
out = weighted_sum_computation(pet_series, frame_duration, half_life, frame_start, decay_correction)
|
|
23
|
+
np.testing.assert_allclose(out, expected)
|
|
24
|
+
|
|
25
|
+
def test_weighted_sum_computation_manual_computation():
|
|
26
|
+
# randomized small example, validate against manual numpy computation
|
|
27
|
+
rng = np.random.default_rng(0)
|
|
28
|
+
pet_series = rng.random((3, 2, 1, 4)).astype(float)
|
|
29
|
+
frame_duration = np.array([5.0, 5.0, 10.0, 300.0])
|
|
30
|
+
half_life = 50.0
|
|
31
|
+
frame_start = np.array([1.0, 6.0, 11.0, 21.0])
|
|
32
|
+
frame_ref_time = calculate_frame_reference_time(frame_duration=frame_duration,
|
|
33
|
+
frame_start=frame_start,
|
|
34
|
+
half_life=half_life)
|
|
35
|
+
decay_correction = calculate_frame_decay_factor(frame_reference_time=frame_ref_time,
|
|
36
|
+
half_life=half_life)
|
|
37
|
+
|
|
38
|
+
# manual expected computation following function logic
|
|
39
|
+
decay_constant = np.log(2.0) / half_life
|
|
40
|
+
image_total_duration = frame_duration.sum()
|
|
41
|
+
total_decay = decay_constant * image_total_duration
|
|
42
|
+
total_decay /= 1.0 - np.exp(-decay_constant * image_total_duration)
|
|
43
|
+
total_decay /= np.exp(-decay_constant * frame_start[0])
|
|
44
|
+
|
|
45
|
+
# compute weighted sum: sum_t(pet[...,t] * frame_duration[t] / decay_correction[t])
|
|
46
|
+
scaled = pet_series * frame_duration / decay_correction # broadcasting over last axis
|
|
47
|
+
pet_series_sum_scaled = scaled.sum(axis=3)
|
|
48
|
+
expected = pet_series_sum_scaled * total_decay / image_total_duration
|
|
49
|
+
|
|
50
|
+
out = weighted_sum_computation(pet_series, frame_duration, half_life, frame_start, decay_correction)
|
|
51
|
+
np.testing.assert_allclose(out, expected)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-00.txt
RENAMED
|
File without changes
|
{petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/noise_free/tac_2tcm_k4zero_set-01.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-00.json
RENAMED
|
File without changes
|
{petpal-0.5.7 → petpal-0.5.8}/data/tcm_tacs/serial_2tcm_k4zero/params_serial_2tcm_k4zero_set-01.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|