Skip to content

Commit

Permalink
Merge pull request #111 from SyneRBI/GE_DMI3_Torso
Browse files Browse the repository at this point in the history
GE_DMI3_Torso dataset
  • Loading branch information
KrisThielemans authored Sep 25, 2024
2 parents 00bc800 + dcc50a6 commit ed633e6
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 2 deletions.
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

0 comments on commit ed633e6

Please sign in to comment.