Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mediso NEMA IQ data #102

Merged
merged 7 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
33 changes: 33 additions & 0 deletions SIRF_data_preparation/Mediso_NEMA_IQ/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Data from the Mediso AnyScan at NPL
Initial processing steps
```sh
orgpath=/mnt/share/petric-wip/NEMA_Challenge
#orgpath=~/devel/PETRIC/orgdata/
# cd $orgpath
#wget https://nplanywhere.npl.co.uk/userportal/?v=4.6.1#/shared/public/nrKe5vWynvyMsp7m/e9e3d4b8-8f83-47be-bf2d-17a96a7a8aac
#unzip NEMA_Challenge.zip
cd ~/devel/PETRIC/data
mkdir -p Mediso_NEMA_IQ
cd Mediso_NEMA_IQ/
# trim sinograms to avoid "corner" problems in mult_factors
KrisThielemans marked this conversation as resolved.
Show resolved Hide resolved
for f in additive_term.hs mult_factors.hs prompts.hs; do
SSRB -t 20 $f $orgpath/sinograms/$f;
done
#cp -rp $orgpath/sinograms/* .
KrisThielemans marked this conversation as resolved.
Show resolved Hide resolved
# get rid of NaNs
python prepare.py
mkdir PETRIC
KrisThielemans marked this conversation as resolved.
Show resolved Hide resolved
cp -rp $orgpath/VOIs/* PETRIC
# cp -rp $orgpath/README.md .
cd PETRIC
stir_math VOI_background.hv VOI_backgroung.hv
rm VOI_backgroung.*
rm *ahv
cd ..
python ../../SIRF_data_preparation/create_initial_images.py --template_image=PETRIC/VOI_whole_object.hv .
```
I needed to fix the OSEM header (manual):
```
!imaging modality := PT
```
python ../../SIRF_data_preparation/data_QC
10 changes: 10 additions & 0 deletions SIRF_data_preparation/Mediso_NEMA_IQ/prepare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Set NaNs to zero in additive_term
import sirf.STIR
import numpy as np
additive = sirf.STIR.AcquisitionData('additive_term.hs')
add_arr = additive.as_array()
add_arr = np.nan_to_num(add_arr)
new_add = additive.clone()
new_add.fill(add_arr)
new_add.write('additive_term.hs')

17 changes: 15 additions & 2 deletions SIRF_data_preparation/data_QC.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
--transverse_slice=<i> idx [default: -1]
--coronal_slice=<c> idx [default: -1]
--sagittal_slice=<s> idx [default: -1]
--dataset=<name> dataset name. if set, it is used to override default slices

Note that -1 one means to use middle of image
"""
# Copyright 2024 University College London
# Licence: Apache-2.0
__version__ = '0.2.0'
__version__ = '0.3.0'

import os
import os.path
Expand All @@ -29,6 +30,7 @@
from scipy import ndimage

import sirf.STIR as STIR
from SIRF_data_preparation.dataset_settings import get_settings

STIR.AcquisitionData.set_storage_scheme('memory')

Expand Down Expand Up @@ -119,7 +121,10 @@ def VOI_checks(allVOInames, OSEM_image=None, reference_image=None, srcdir='.', *
print(f"VOI {VOIname} does not exist")
continue
VOI = STIR.ImageData(filename)
COM = np.rint(ndimage.center_of_mass(VOI.as_array()))
VOI_arr = VOI.as_array()
COM = np.rint(ndimage.center_of_mass(VOI_arr))
num_voxels = VOI_arr.sum()
print(f"VOI: {VOIname}: COM (in indices): {COM} voxels {num_voxels} = {num_voxels * np.prod(VOI.spacing)} mm^3")
plt.figure()
plot_image(VOI, save_name=prefix, vmin=0, vmax=1, transverse_slice=int(COM[0]), coronal_slice=int(COM[1]),
sagittal_slice=int(COM[2]))
Expand Down Expand Up @@ -149,13 +154,21 @@ def VOI_checks(allVOInames, OSEM_image=None, reference_image=None, srcdir='.', *

def main(argv=None):
args = docopt(__doc__, argv=argv, version=__version__)
dataset = args['--dataset']
srcdir = args['--srcdir']
skip_sino_profiles = args['--skip_sino_profiles']
slices = {}
slices["transverse_slice"] = literal_eval(args['--transverse_slice'])
slices["coronal_slice"] = literal_eval(args['--coronal_slice'])
slices["sagittal_slice"] = literal_eval(args['--sagittal_slice'])

if (dataset):
settings = get_settings(dataset)
for key in slices.keys():
if slices[key] == -1 and key in settings.slices:
slices[key] = settings.slices[key]
print(slices)

if not skip_sino_profiles:
acquired_data = STIR.AcquisitionData(os.path.join(srcdir, 'prompts.hs'))
additive_term = STIR.AcquisitionData(os.path.join(srcdir, 'additive_term.hs'))
Expand Down
3 changes: 3 additions & 0 deletions SIRF_data_preparation/dataset_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def get_settings(scanID: str):
elif scanID == 'NeuroLF_Hoffman_Dataset':
slices = {'transverse_slice': 72}
num_subsets = 16
elif scanID == 'Mediso_NEMA_IQ':
slices = {'transverse_slice': 22, 'coronal_slice': 89, 'sagittal_slice': 66}
num_subsets = 12
else: # Vision
slices = {}
num_subsets = 5
Expand Down
15 changes: 10 additions & 5 deletions SIRF_data_preparation/plot_BSREM_metrics.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Preliminary file to check evolution of metrics as well as pass_index"""
#%%
# """Preliminary file to check evolution of metrics as well as pass_index"""
# %load_ext autoreload
# %autoreload 2
from pathlib import Path
Expand All @@ -21,7 +22,8 @@

# scanID = 'Siemens_Vision600_thorax'
# scanID = 'NeuroLF_Hoffman_Dataset'
scanID = 'Siemens_mMR_NEMA_IQ'
# scanID = 'Siemens_mMR_NEMA_IQ'
scanID = 'Mediso_NEMA_IQ'

srcdir = SRCDIR / scanID
outdir = OUTDIR / scanID
Expand Down Expand Up @@ -69,16 +71,19 @@
reference_image = STIR.ImageData(str(datadir / 'iter_final.hv'))
qm = QualityMetrics(reference_image, data.whole_object_mask, data.background_mask, tb_summary_writer=None,
voi_mask_dict=data.voi_masks)
#%% get update ("iteration") numbers from objective functions
last_iteration = int(objs[-1, 0] + .5)
iteration_interval = int(objs[-1, 0] - objs[-2, 0] + .5)
# find interval(don't use last value, as that interval can be smaller)
iteration_interval = int(objs[-2, 0] - objs[-3, 0] + .5)
if datadir1.is_dir():
last_iteration = int(objs0[-1, 0] + .5)
iteration_interval = int(objs0[-1, 0] - objs0[-2, 0] + .5) * 2
# %%
iters = range(0, last_iteration, iteration_interval)
m = get_metrics(qm, iters, srcdir=datadir)
# %%
OSEMiters = range(0, 400, 20)
OSEMobjs = read_objectives(OSEMdir)
OSEMiters = OSEMobjs[:, 0].astype(int)
OSEMm = get_metrics(qm, OSEMiters, srcdir=OSEMdir)
# %%
fig = plt.figure()
Expand Down Expand Up @@ -107,7 +112,7 @@
fig.savefig(outdir / f'{scanID}_metrics_BSREM.png')

# %%
idx = pass_index(m, numpy.array([.01, .01, .005, .005, .005]), 10)
idx = pass_index(m, numpy.array([.01, .01] + [.005 for i in range(len(data.voi_masks))]), 10)
iter = iters[idx]
print(iter)
image = STIR.ImageData(str(datadir / f"iter_{iter:04d}.hv"))
Expand Down
2 changes: 1 addition & 1 deletion SIRF_data_preparation/run_OSEM.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
data = get_data(srcdir=srcdir, outdir=outdir)
# %%
algo = main_OSEM.Submission(data, settings.num_subsets, update_objective_interval=20)
algo.run(20, callbacks=[MetricsWithTimeout(**settings.slices, seconds=5000, outdir=outdir)])
algo.run(400, callbacks=[MetricsWithTimeout(**settings.slices, seconds=5000, outdir=outdir)])
# %%
fig = plt.figure()
data_QC.plot_image(algo.get_output(), **settings.slices)
Expand Down
2 changes: 1 addition & 1 deletion petric.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def keys(self):

class MetricsWithTimeout(cil_callbacks.Callback):
"""Stops the algorithm after `seconds`"""
def __init__(self, seconds=600, outdir=OUTDIR, transverse_slice=None, coronal_slice=None, **kwargs):
def __init__(self, seconds=600, outdir=OUTDIR, transverse_slice=None, coronal_slice=None, sagittal_slice=None, **kwargs):
casperdcl marked this conversation as resolved.
Show resolved Hide resolved
super().__init__(**kwargs)
self._seconds = seconds
self.callbacks = [
Expand Down