Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions SIRF_data_preparation/GE_DMI3_Torso/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Torso phantom scanned on a GE Discovery MI (3 ring)

This data is from a scan performed by GE of the
Data Spectrum [Antropomorphic Torso Phantom](https://www.spect.com/pdf/anthropomorphic-torso-phantom.pdf)
with additional lesion inserts of diameter 10mm.

Activity ratio between "liver" and "torso" is approximately 2. Lungs
are empty (air). Contrast of the lesions is unfortunately unknown.
,v
"Corrections" were obtained with GE Duetto and converted to STIR Interfile
using internal scripts.

Due to data size issues and count levels, the supplied data is **reduced** from the original scan
by keeping only the "direct" sinograms (segment 0, corresponding to min/max ring differences -1/+1), e.g. on the command line
```
SSRB prompts.hs prompts_f1b1.hs 1 1 0 0 1
```

In addition, as current PETRIC examples do not cope with non-TOF multfactors for TOF data, the
multfactors were expanded to TOF (by duplication).

## VOIs

VOIs were determined by Kris Thielemans on reconstructed images and approximately placed
where some of the lesions are visible. They are not necessarily at the correct location.
85 changes: 85 additions & 0 deletions SIRF_data_preparation/GE_DMI3_Torso/VOI_prep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#%% file to prepare VOIs for the Torso phantom, using coordinates derived manually

import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path
import os
from scipy.ndimage import binary_fill_holes
import sirf.STIR as STIR
import SIRF_data_preparation.data_QC as data_QC
from SIRF_data_preparation.data_utilities import the_data_path, the_orgdata_path
from SIRF_data_preparation.dataset_settings import get_settings
#%%
scanID = 'GE_DMI3_Torso'
data_path = Path(the_data_path(scanID))
output_path = Path(the_data_path(scanID, 'PETRIC'))
os.makedirs(output_path, exist_ok=True)
#%%
image_filename = str(data_path / 'OSEM_image.hv')
image = STIR.ImageData(image_filename)
# %% find whole phantom VOI by thresholding/filling
threshold = image.max() * .05
im_arr = image.as_array() >= threshold
# we want to use binary_fill_holes to fill the spine and lung. However,
# that function does not fill holes connected to the boundary, so let's
# fill the boundary planes first
im_arr[0, :, :] = True
im_arr[-1, :, :] = True
im_arr = binary_fill_holes(im_arr)
# now exclude boundary
im_arr[0, :, :] = False
im_arr[-1, :, :] = False
VOI = image.allocate(0)
VOI.fill(im_arr.astype(np.float32))
VOI.show()
VOI.write(str(output_path / 'VOI_whole_object.hv'))
#%% find centre image as KT got the coordinates from Amide
# note that geo.get_index_to_physical_point_matrix() is still unstable, so we won't use it.
# Warning: the following will likely fail for future versions of SIRF
zcentre = (image.shape[0] - 1)/2 * image.voxel_sizes()[0]
# %% background VOI (in approx middle of torso)
shape = STIR.EllipticCylinder()
shape.set_length(23)
shape.set_radii((120, 120))
shape.set_origin((zcentre + 0, 0, 0))
VOI.fill(0)
VOI.add_shape(shape, scale = 1)
VOI.write(str(output_path / 'VOI_background.hv'))
# %% spine (approximately top half of it)
shape = STIR.EllipticCylinder()
shape.set_length(100)
shape.set_radii((22, 22))
shape.set_origin((zcentre + 42.6, 86.9, 3))
VOI.fill(0)
VOI.add_shape(shape, scale = 1)
VOI.write(str(output_path / 'VOI_spine.hv'))
VOI.show()
# %% lung lesion
shape = STIR.Ellipsoid()
shape.set_radius_z(5)
shape.set_radius_y(5)
shape.set_radius_x(5)
shape.set_origin((zcentre + 25, -42.2, -105.3))
VOI.fill(0)
VOI.add_shape(shape, scale = 1)
VOI.write(str(output_path / 'VOI_lung_lesion.hv'))
# %%
# %% liver lesion
shape = STIR.Ellipsoid()
shape.set_radius_z(5)
shape.set_radius_y(5)
shape.set_radius_x(5)
shape.set_origin((zcentre - 38.2, -38.9, -49.7))
VOI.fill(0)
VOI.add_shape(shape, scale = 1)
VOI.write(str(output_path / 'VOI_liver_lesion.hv'))
# %% lung lesion
shape = STIR.Ellipsoid()
shape.set_radius_z(5)
shape.set_radius_y(5)
shape.set_radius_x(5)
shape.set_origin((zcentre + 47.6, 12.5, 151.5))
VOI.fill(0)
VOI.add_shape(shape, scale = 1)
VOI.write(str(output_path / 'VOI_chest_lesion.hv'))

2 changes: 1 addition & 1 deletion SIRF_data_preparation/dataset_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

DATA_SUBSETS = {
'Siemens_mMR_NEMA_IQ': 7, 'Siemens_mMR_NEMA_IQ_lowcounts': 7, 'Siemens_mMR_ACR': 7, 'NeuroLF_Hoffman_Dataset': 16,
'Mediso_NEMA_IQ': 12, 'Siemens_Vision600_thorax': 5}
'Mediso_NEMA_IQ': 12, 'Siemens_Vision600_thorax': 5, 'GE_DMI3_Torso': 8}


@dataclass
Expand Down
3 changes: 2 additions & 1 deletion petric.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ def get_image(fname):
'Siemens_mMR_ACR': {'transverse_slice': 99},
'NeuroLF_Hoffman_Dataset': {'transverse_slice': 72},
'Mediso_NEMA_IQ': {'transverse_slice': 22, 'coronal_slice': 89, 'sagittal_slice': 66},
'Siemens_Vision600_thorax': {}}
'Siemens_Vision600_thorax': {},
'GE_DMI3_Torso': {}}

if SRCDIR.is_dir():
# create list of existing data
Expand Down