Skip to content

Commit

Permalink
tidying up doc strings like victre pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
brandon.nelson committed May 31, 2024
1 parent cd2dceb commit ff55806
Showing 1 changed file with 64 additions and 41 deletions.
105 changes: 64 additions & 41 deletions src/pediatricIQphantoms/make_phantoms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""Functions and classes for interactively running CT simulations
This module provides classes and functions to interactively run CT simulations and make phantom datasets
"""

from pathlib import Path
import argparse
import tomli
Expand All @@ -13,27 +18,40 @@

class CTobj():
"""
A class to hold CT simulation data and run simulations
:param phantom: phantom object to be scanned, options include ['CCT189', 'CTP404']
:param patient_diameter: Optional, effective diameter in mm. See `AAPM TG220 <https://www.aapm.org/pubs/reports/detail.asp?docid=146>`_ for more details.
:param reference_diameter: Optional, reference effective diameter in mm for computing automatic exposure control (aec) noise index. For example if a 200 mm reference phantom has a noise level of 24 HU at I0=3e5, smaller phantoms will scale I0 to match that noise level. Note this only applies if 'aec_on`=True.
:param I0: Optional float, fluence at the detector in the projection data for determining quantum noise default 3e5 units of photons.
:param ndetectors: Optional int, number of detector columns
:param nangles: Optional int, number of views in a rotation (na=1160 based on `Zeng et al 2015 <https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4629802/>`_)
:param detector_size: Optional float, detector column size in mm
:param sid: Optional float, source-to-isocenter distance in mm
:param sdd: Optional float, source-to-detector distance in mm
:param detector_offset: Optional float, lateral shift of detector (1.25 = quarter pixel offset)
:param has_bowtie: Optional bool, whether to add a patient fitting bowtie (TODO add different bowtie sizes.)
:param add_noise: Optional bool, if true adds Poisson noise, noise magnitude set by `reference_dose_level`, noise texture set by reconstructed field of view (currently fov = 110% patient_diameter)
:param aec_on: Optional bool, 'aec' = automatic exposure control, when `true`, it ensures constant noise levels for all `patient_diameters` (see `reference_dose_level` for more info)
:param matrix_size: Optional int, reconstructed matrix size in pixels (square, equal on both sides)
:param fov: Optional float, reconstructed field of view (FOV) units mm
:param fbp_kernel: Optional str, `hanning,xxx`, xxx = the cutoff frequency, see `fbp2_window.m in MIRT <https://github.com/JeffFessler/mirt/blob/main/fbp/fbp2_window.m>`_ for details. E.g. 'hanning,2.05' approximates a sharp kernel D45 in Siemens Force and 'hanning, 0.85' approximates a smooth kernel B30.
:param nsims: Optional int, number of simulations to perform with different noise instantiations
:param lesion_diameter: Optional bool | list | float | int, if False lesions scale with phantom size, if model=='CTP404' lesion_diameter > 1 interpret as absolute diameter in mm, if lesion_diameter < 1 interpret as scale relative to phantom diameter. If model=='CCT189' a list of 4 diameters must be provided for the four inserts in contrast order 14, 7, 5, 3 HU. (only applies for CCCT189 MITA and CTP404 phantoms)
:param framework: Optional, CT simulation framework options include `['MIRT'] <https://github.com/JeffFessler/mirt>`_
A class to hold CT simulation data and run simulations
:param phantom: phantom object to be scanned, options include ['CCT189', 'CTP404']
:param patient_diameter: Optional, effective diameter in mm.
See `AAPM TG220 <https://www.aapm.org/pubs/reports/detail.asp?docid=146>`_ for more details.
:param reference_diameter: Optional, reference effective diameter in mm for computing automatic exposure control (aec) noise index.
For example if a 200 mm reference phantom has a noise level of 24 HU at I0=3e5, smaller phantoms will scale I0 to match that noise level.
Note this only applies if 'aec_on`=True.
:param I0: Optional float, fluence at the detector in the projection data for determining quantum noise default 3e5 units of photons.
:param ndetectors: Optional int, number of detector columns
:param nangles: Optional int, number of views in a rotation
(na=1160 based on `Zeng et al 2015 <https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4629802/>`_)
:param detector_size: Optional float, detector column size in mm
:param sid: Optional float, source-to-isocenter distance in mm
:param sdd: Optional float, source-to-detector distance in mm
:param detector_offset: Optional float, lateral shift of detector (1.25 = quarter pixel offset)
:param has_bowtie: Optional bool, whether to add a patient fitting bowtie (TODO add different bowtie sizes.)
:param add_noise: Optional bool, if true adds Poisson noise, noise magnitude set by `reference_dose_level`,
noise texture set by reconstructed field of view (currently fov = 110% patient_diameter)
:param aec_on: Optional bool, 'aec' = automatic exposure control,
when `true`, it ensures constant noise levels for all `patient_diameters` (see `reference_dose_level` for more info)
:param matrix_size: Optional int, reconstructed matrix size in pixels (square, equal on both sides)
:param fov: Optional float, reconstructed field of view (FOV) units mm
:param fbp_kernel: Optional str, `hanning,xxx`, xxx = the cutoff frequency,
see `fbp2_window.m in MIRT <https://github.com/JeffFessler/mirt/blob/main/fbp/fbp2_window.m>`_ for details.
E.g. 'hanning,2.05' approximates a sharp kernel D45 in Siemens Force and 'hanning, 0.85' approximates a smooth kernel B30.
:param nsims: Optional int, number of simulations to perform with different noise instantiations
:param lesion_diameter: Optional bool | list | float | int, if False lesions scale with phantom size,
if model=='CTP404' lesion_diameter > 1 interpret as absolute diameter in mm,
if lesion_diameter < 1 interpret as scale relative to phantom diameter.
If model=='CCT189' a list of 4 diameters must be provided for the four inserts in contrast order 14, 7, 5, 3 HU.
(only applies for CCCT189 MITA and CTP404 phantoms)
:param framework: Optional, CT simulation framework options include `['MIRT'] <https://github.com/JeffFessler/mirt>`_
:returns: None
"""
def __init__(self, phantom='CCT189', patient_diameter=200, reference_diameter=200,
reference_fov=340, I0=3e5, ndetectors=900, nangles=580, detector_size=1, sid=595, sdd=1085.6,
Expand Down Expand Up @@ -90,9 +108,9 @@ def __repr__(self) -> str:

def run(self, verbose=False):
"""
Runs the CT simulation using the stored parameters.
Runs the CT simulation using the stored parameters.
:param verbose: optional boolean, if True prints out status updates, if False they are suppressed.
:param verbose: optional boolean, if True prints out status updates, if False they are suppressed.
"""
phantom=self.phantom
patient_diameter=self.patient_diameter
Expand Down Expand Up @@ -123,12 +141,14 @@ def run(self, verbose=False):
self.groundtruth = resdict['ground_truth']
return self

def write_to_dicom(self, fname:str|Path, groundtruth=False):
def write_to_dicom(self, fname:str|Path, groundtruth=False) -> list[Path]:
"""
write ct data to DICOM file
write ct data to DICOM file
:param fname: filename to save image to (preferably with '.dcm` or related extension)
:param groundtruth: Optional, whether to save the ground truth phantom image (no noise, blurring, or other artifacts). If True, 'self.groundtruth` is saved, if False (default) `self.recon` which contains blurring (and noise if 'add_noise`True)
:param fname: filename to save image to (preferably with '.dcm` or related extension)
:param groundtruth: Optional, whether to save the ground truth phantom image (no noise, blurring, or other artifacts).
If True, 'self.groundtruth` is saved, if False (default) `self.recon` which contains blurring (and noise if 'add_noise`True)
:returns: list[Path]
"""
fpath = pydicom.data.get_testdata_file("CT_small.dcm")
ds = pydicom.dcmread(fpath)
Expand Down Expand Up @@ -212,9 +232,11 @@ def write_to_dicom(self, fname:str|Path, groundtruth=False):

def mirt_sim(phantom='CCT189', patient_diameter=200, reference_diameter=200, reference_fov=340,
I0=3e5, nb=900, na=580, ds=1, sid=595, sdd=1085.6, offset_s=1.25, down=1, has_bowtie=False,
add_noise=True, aec_on=True, nx=512, fov=340, fbp_kernel='hanning,2.05', nsims=1, lesion_diameter=False, verbose=True):
add_noise=True, aec_on=True, nx=512, fov=340, fbp_kernel='hanning,2.05', nsims=1, lesion_diameter=False, verbose=True) -> dict:
"""
Python wrapper for calling Michigan Image Reconstruction Toolbox (MIRT) Octave function
Python wrapper for calling Michigan Image Reconstruction Toolbox (MIRT) Octave function
:returns: dict with keys for recon, projection data, ground truth recon.
"""
if phantom in ['MITA-LCD', 'MITA', 'MITALCD', 'LCD']: phantom = 'CCT189'

Expand Down Expand Up @@ -250,7 +272,7 @@ def round_to_decile(age): return age - age % 10

def age_to_eff_diameter(age):
"""
Equation A-3 from TG204 <https://www.aapm.org/pubs/reports/rpt_204.pdf>
Equation A-3 from TG204 <https://www.aapm.org/pubs/reports/rpt_204.pdf>
"""
if age > 22:
return adult_waist_circumferences_cm[round_to_decile(age)]
Expand Down Expand Up @@ -314,20 +336,21 @@ def dicom_meta_to_dataframe(fname:str|Path) -> pd.DataFrame:

def run_batch_sim(image_directory: str, model=['MITA-LCD'], diameter=[200], full_dose=3e5, dose_level=[1.0], fbp_kernel='fbp', verbose=True, **kwargs) -> pd.DataFrame:
"""
Running simulations in batch mode
Running simulations in batch mode
`run_batch_sim` takes lists of parameters (phantoms, diameters, and dose levels) and iterates through all combinations
`run_batch_sim` takes lists of parameters (phantoms, diameters, and dose levels) and iterates through all combinations
:param image_directory: Directory to save simulated outputs
:type image_directory: str
:param model: Optional list, list of phantom models to simulate (can be length 1) options include ['CTP404', 'Uniform', 'MITA-LCD']
:type model: list[str]
:param diameter: Optional list, list of simulated phantom diameters in mm (can be length 1)
:param full_dose: Optional int, units of photons per pixel, multiplied by `dose_level` to determine quantum noise level in projections
:param dose_level: Optional list, units of photons
:param verbose: Optional bool, whether to print update information
:param image_directory: Directory to save simulated outputs
:type image_directory: str
:param model: Optional list, list of phantom models to simulate (can be length 1) options include ['CTP404', 'Uniform', 'MITA-LCD']
:type model: list[str]
:param diameter: Optional list, list of simulated phantom diameters in mm (can be length 1)
:param full_dose: Optional int, units of photons per pixel, multiplied by `dose_level` to determine quantum noise level in projections
:param dose_level: Optional list, units of photons
:param verbose: Optional bool, whether to print update information
:returns: pd.DataFrame
See `CTobj` for remaining keyword arguments
See `CTobj` for remaining keyword arguments
"""
image_directory = Path(os.path.abspath(image_directory))
print(image_directory)
Expand Down

0 comments on commit ff55806

Please sign in to comment.