Skip to content

Commit 73d4d70

Browse files
author
mahdieh-dst
committed
tested down to task#4 (rename_on_xnat)
1 parent 1a49c06 commit 73d4d70

10 files changed

+173
-41
lines changed

conftest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ def mr_session(xnat_project, work_dir, request):
5252
user=xnat4tests.config.XNAT_USER,
5353
password=xnat4tests.config.XNAT_PASSWORD,
5454
cache_dir=work_dir / 'cache')
55-
dataset = store.load_dataset(xnat_project.id)
55+
dataset = store.new_dataset(xnat_project.id)
5656
# Access single row of dataset
57-
return dataset.row(id=session_label)
57+
return dataset.row(id=session_label, row_frequency='session')
5858

5959

6060
def make_project_name(dataset_name: str, run_prefix: str=None):

dds4xnat/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from .workflow_dds import dds4xnat_workflow
2-
from .tasks_dds import *
1+
from .dds4xnat_workflow import dds4xnat_workflow
2+
from .dds4xnat_tasks import *

dds4xnat/tasks_dds.py dds4xnat/dds4xnat_tasks.py

+20-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pydicom
77
import yaml
88
from tensorflow.keras.models import load_model
9-
# import Tools.data_IO as data_IO
9+
from .tools import data_IO
1010
import tensorflow as tf
1111
from .preprocessing import DICOM_preparation_functions as DPF
1212
from .preprocessing import NIFTI_preparation_functions as NPF
@@ -23,11 +23,11 @@ def download_from_xnat(row: DataRow) -> Path:
2323
store = row.dataset.store
2424

2525
with store:
26-
xproject = store.login[row.dataset.id]
26+
xproject = store.login.projects[row.dataset.id]
2727
xsession = xproject.experiments[row.id]
2828
xsession.download_dir(str(download_dir))
2929

30-
return download_dir
30+
return str(download_dir)
3131

3232

3333
@mark.task #---task #2----------------------------------------------
@@ -101,13 +101,13 @@ def is_odd(number):
101101
NPF.rescale_image_intensity(nifti_slices_folder)
102102

103103
print('Creating label file....')
104-
NPF.create_label_file(nifti_slices_folder, images_4D_file)
104+
label_file = NPF.create_label_file(nifti_slices_folder, images_4D_file)
105105

106106
elapsed_time = time.time() - start_time
107107

108108
print(elapsed_time)
109109

110-
return label_file, structured_dcm_dir,
110+
return label_file, structured_dcm_dir
111111

112112

113113
@mark.task #---task #3----------------------------------------------
@@ -186,13 +186,18 @@ def load_labels(label_file):
186186

187187

188188
@mark.task #---task #4----------------------------------------------
189+
@mark.annotate({
190+
"return": {
191+
"info_file": Path
192+
}
193+
})
189194

190-
def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
195+
def rename_on_xnat(out_file: str, output_folder: Path, download_dir: str, row: DataRow) -> Path:
191196

192197
store = row.dataset.store
193198

194199
with store:
195-
xproject = store.login[row.dataset.id]
200+
xproject = store.login.projects[row.dataset.id]
196201
xsession = xproject.experiments[row.id]
197202

198203
# Rename "scan types" of sessions
@@ -204,7 +209,7 @@ def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
204209
prediction_file = cfg['post_processing']['prediction_file']
205210
root_dicom_folder = cfg['preprocessing']['root_dicom_folder']
206211
"""
207-
212+
info_file = os.path.join(output_folder, 'info.txt')
208213
base_dir = os.path.dirname(os.path.normpath(download_dir))
209214
structured_dicom_folder = os.path.join(base_dir,'DICOM_STRUCTURED')
210215
#root_out_folder = os.path.join(base_dir, 'DICOM_SORTED')
@@ -248,8 +253,15 @@ def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
248253
print(predicted_scan_type)
249254

250255
scan = xsession.scans[scan_id]
256+
#renaming scan type on xnat
251257
scan.type = prediction_names[i_prediction]
252258

259+
with open(info_file, 'w') as the_file:
260+
out_elements = [scan_id, unpredicted_scan_type, predicted_scan_type]
261+
the_file.write('\t'.join(out_elements) + '\n')
262+
263+
return info_file
264+
253265

254266
@mark.task #----------------------------------------------------------
255267
def cleanup(download_dir: str):

dds4xnat/dds_main/workflow_dds.py dds4xnat/dds4xnat_workflow.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from pydra import Workflow
2-
from .tasks_dds import *
2+
from .dds4xnat_tasks import *
33

4-
def dds4xnat_workflow(name):
4+
WORKFLOW_INPUTS = [
5+
'mr_session', 'dcm2niix_bin', 'fslval_bin',
6+
'model_file', 'output_folder']
7+
8+
9+
def dds4xnat_workflow(name, **kwargs):
510

6-
wf = Workflow(name=name, input_spec=['mr_session',
7-
'dcm2niix_bin',
8-
'fslval_bin',
9-
'model_file',
10-
'output_folder'])
11+
wf = Workflow(name=name, input_spec=WORKFLOW_INPUTS, **kwargs)
1112

1213
# Build workflow here
1314
wf.add(
@@ -39,8 +40,11 @@ def dds4xnat_workflow(name):
3940
rename_on_xnat(
4041
name='rename',
4142
out_file = wf.predict.lzout.out_file,
42-
download_dir=wf.download.lzout.out
43+
download_dir=wf.download.lzout.out,
44+
output_folder=wf.lzin.output_folder
4345
)
4446
)
4547

48+
wf.set_output([("rename_log", wf.rename.lzout.info_file)])
49+
4650
return wf

dds4xnat/dds_main/tasks_dds.py dds4xnat/dds_main/dds4xnat_tasks.py

+22-10
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
import pydicom
77
import yaml
88
from tensorflow.keras.models import load_model
9-
import Tools.data_IO as data_IO
9+
from .tools import data_IO
1010
import tensorflow as tf
11-
from Preprocessing import DICOM_preparation_functions as DPF
12-
from Preprocessing import NIFTI_preparation_functions as NPF
11+
from .preprocessing import DICOM_preparation_functions as DPF
12+
from .preprocessing import NIFTI_preparation_functions as NPF
1313
import time
1414
from arcana.core.data.row import DataRow
1515

@@ -23,11 +23,11 @@ def download_from_xnat(row: DataRow) -> Path:
2323
store = row.dataset.store
2424

2525
with store:
26-
xproject = store.login[row.dataset.id]
26+
xproject = store.login.projects[row.dataset.id]
2727
xsession = xproject.experiments[row.id]
2828
xsession.download_dir(str(download_dir))
2929

30-
return download_dir
30+
return str(download_dir)
3131

3232

3333
@mark.task #---task #2----------------------------------------------
@@ -101,13 +101,13 @@ def is_odd(number):
101101
NPF.rescale_image_intensity(nifti_slices_folder)
102102

103103
print('Creating label file....')
104-
NPF.create_label_file(nifti_slices_folder, images_4D_file)
104+
label_file = NPF.create_label_file(nifti_slices_folder, images_4D_file)
105105

106106
elapsed_time = time.time() - start_time
107107

108108
print(elapsed_time)
109109

110-
return label_file, structured_dcm_dir,
110+
return label_file, structured_dcm_dir
111111

112112

113113
@mark.task #---task #3----------------------------------------------
@@ -186,13 +186,18 @@ def load_labels(label_file):
186186

187187

188188
@mark.task #---task #4----------------------------------------------
189+
@mark.annotate({
190+
"return": {
191+
"info_file": Path
192+
}
193+
})
189194

190-
def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
195+
def rename_on_xnat(out_file: str, output_folder: Path, download_dir: str, row: DataRow) -> Path:
191196

192197
store = row.dataset.store
193198

194199
with store:
195-
xproject = store.login[row.dataset.id]
200+
xproject = store.login.projects[row.dataset.id]
196201
xsession = xproject.experiments[row.id]
197202

198203
# Rename "scan types" of sessions
@@ -204,7 +209,7 @@ def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
204209
prediction_file = cfg['post_processing']['prediction_file']
205210
root_dicom_folder = cfg['preprocessing']['root_dicom_folder']
206211
"""
207-
212+
info_file = os.path.join(output_folder, 'info.txt')
208213
base_dir = os.path.dirname(os.path.normpath(download_dir))
209214
structured_dicom_folder = os.path.join(base_dir,'DICOM_STRUCTURED')
210215
#root_out_folder = os.path.join(base_dir, 'DICOM_SORTED')
@@ -248,8 +253,15 @@ def rename_on_xnat(out_file: str, download_dir: str, row: DataRow) -> Path:
248253
print(predicted_scan_type)
249254

250255
scan = xsession.scans[scan_id]
256+
#renaming scan type on xnat
251257
scan.type = prediction_names[i_prediction]
252258

259+
with open(info_file, 'w') as the_file:
260+
out_elements = [scan_id, unpredicted_scan_type, predicted_scan_type]
261+
the_file.write('\t'.join(out_elements) + '\n')
262+
263+
return info_file
264+
253265

254266
@mark.task #----------------------------------------------------------
255267
def cleanup(download_dir: str):

dds4xnat/workflow_dds.py dds4xnat/dds_main/dds4xnat_workflow.py

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from pydra import Workflow
2-
from .tasks_dds import *
2+
from .dds4xnat_tasks import *
33

4-
def dds4xnat_workflow(name):
4+
WORKFLOW_INPUTS = [
5+
'mr_session', 'dcm2niix_bin', 'fslval_bin',
6+
'model_file', 'output_folder']
7+
8+
9+
def dds4xnat_workflow(name, **kwargs):
510

6-
wf = Workflow(name=name, input_spec=['mr_session',
7-
'dcm2niix_bin',
8-
'fslval_bin',
9-
'model_file',
10-
'output_folder'])
11+
wf = Workflow(name=name, input_spec=WORKFLOW_INPUTS, **kwargs)
1112

1213
# Build workflow here
1314
wf.add(
@@ -39,8 +40,11 @@ def dds4xnat_workflow(name):
3940
rename_on_xnat(
4041
name='rename',
4142
out_file = wf.predict.lzout.out_file,
42-
download_dir=wf.download.lzout.out
43+
download_dir=wf.download.lzout.out,
44+
output_folder=wf.lzin.output_folder
4345
)
4446
)
4547

48+
wf.set_output([("rename_log", wf.rename.lzout.info_file)])
49+
4650
return wf

dds4xnat/tools/__init__.py

Whitespace-only changes.

dds4xnat/tools/data_IO.py

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import threading
2+
import numpy as np
3+
import SimpleITK as sitk
4+
5+
6+
class NiftiGenerator2D_ExtraInput(object):
7+
8+
def __init__(self, batch_size, image_locations,
9+
labels, image_size, extra_inputs, random_shuffle=True):
10+
self.n = len(image_locations)
11+
self.batch_size = batch_size
12+
self.batch_index = 0
13+
self.total_batches_seen = 0
14+
self.lock = threading.Lock()
15+
self.index_array = None
16+
self.index_generator = self._flow_index()
17+
self.image_locations = image_locations
18+
self.labels = labels
19+
self.image_size = image_size
20+
self.random_shuffle = random_shuffle
21+
self.extra_inputs = extra_inputs
22+
23+
def _set_index_array(self):
24+
if self.random_shuffle:
25+
self.index_array = np.random.permutation(self.n)
26+
else:
27+
self.index_array = np.arange(self.n)
28+
29+
def __iter__(self):
30+
return self
31+
32+
def __next__(self, *args, **kwargs):
33+
return self.next(*args, **kwargs)
34+
35+
def reset(self):
36+
self.batch_index = 0
37+
self.total_batches_seen = 0
38+
self._set_index_array()
39+
40+
def _flow_index(self):
41+
self.reset()
42+
while 1:
43+
if self.batch_index == 0:
44+
self._set_index_array()
45+
46+
current_index = (self.batch_index * self.batch_size) % self.n
47+
if self.n > current_index + self.batch_size:
48+
self.batch_index += 1
49+
else:
50+
self.batch_index = 0
51+
self.total_batches_seen += 1
52+
53+
if current_index + self.batch_size > self.n:
54+
N_missing_samples = (current_index + self.batch_size) - self.n
55+
batch_indices_leftover = self.index_array[current_index:]
56+
self.reset()
57+
batch_indices_filler = self.index_array[0:N_missing_samples]
58+
batch_indices = np.concatenate((batch_indices_leftover, batch_indices_filler))
59+
else:
60+
batch_indices = self.index_array[current_index:
61+
current_index + self.batch_size]
62+
yield batch_indices
63+
64+
def on_epoch_end(self):
65+
self.reset()
66+
67+
def _get_batch_of_samples(self, index_array):
68+
image_tensor = np.zeros((self.batch_size,
69+
self.image_size[0],
70+
self.image_size[1],
71+
1))
72+
73+
out_labels = self.labels[index_array, :]
74+
out_extra_inputs = self.extra_inputs[index_array, :]
75+
76+
image_locations = self.image_locations[index_array]
77+
78+
for i_sample, i_image_location in enumerate(image_locations):
79+
i_image = sitk.ReadImage(i_image_location, sitk.sitkFloat32)
80+
i_image_array = sitk.GetArrayFromImage(i_image)
81+
image_tensor[i_sample, :, :, 0] = i_image_array[:, :]
82+
83+
return [image_tensor, out_extra_inputs], out_labels
84+
85+
def next(self):
86+
with self.lock:
87+
index_array = next(self.index_generator)
88+
89+
return self._get_batch_of_samples(index_array)
90+
91+
def get_single_image(self, image_path):
92+
full_sample_tensor = np.zeros((1,
93+
self.image_size[0],
94+
self.image_size[1],
95+
1))
96+
i_image = sitk.ReadImage(image_path, sitk.sitkFloat32)
97+
i_image_array = sitk.GetArrayFromImage(i_image)
98+
full_sample_tensor[0, :, :, 0] = i_image_array
99+
return full_sample_tensor

test_requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
arcana
2-
xnat4tests
2+
xnat4tests
3+
tensorflow>=2.9.1

tests/test_dicom_sort.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ def test_dicom_sort(mr_session: DataRow, trained_model_file: Path, work_dir: Pat
1313
name='test_workflow',
1414
mr_session=mr_session,
1515
dcm2niix_bin='/usr/local/bin/dcm2niix',
16-
fslval_bin='/usr/bin/fsl5.0-fslval',
16+
fslval_bin='/usr/local/fsl/bin/fslval',
1717
model_file=trained_model_file,
1818
output_folder=output_dir)
1919

2020
# run workflow
21-
wf()
21+
wf(plugin='serial')
2222

0 commit comments

Comments
 (0)