@@ -109,16 +109,42 @@ def _run_interface(self, runtime):
109
109
110
110
ffsim = nb .concat_images ([nb .load (f ) for f in self .inputs .in_frac ])
111
111
ffs = np .squeeze (ffsim .get_data ()) # fiber fractions
112
+ ffs [ffs > 1.0 ] = 1.0
113
+ ffs [ffs < 0.0 ] = 0.0
114
+
112
115
if nsticks == 1 :
113
116
ffs = ffs [..., np .newaxis ]
114
117
118
+ total_ff = np .sum (ffs , axis = 3 )
119
+
120
+ # Fix incongruencies in fiber fractions
121
+ for i in range (1 , nsticks ):
122
+ if np .any (total_ff > 1.0 ):
123
+ errors = np .zeros_like (total_ff )
124
+ errors [total_ff > 1.0 ] = total_ff [total_ff > 1.0 ] - 1.0
125
+ ffs [..., i ] -= errors
126
+ ffs [ffs < 0.0 ] = 0.0
127
+ total_ff = np .sum (ffs , axis = 3 )
128
+
115
129
# Volume fractions of isotropic compartiments
116
130
vfsim = nb .concat_images ([nb .load (f ) for f in self .inputs .in_vfms ])
117
131
vfs = np .squeeze (vfsim .get_data ()) # volume fractions
118
132
119
- total_ff = np .sum (ffs , axis = 3 )
133
+ for i in range (vfs .shape [- 1 ]):
134
+ vfs [..., i ] -= total_ff
135
+ vfs [vfs < 0.0 ] = 0
120
136
total_vf = np .sum (vfs , axis = 3 )
121
137
138
+ newhdr = hdr .copy ()
139
+ newhdr .set_data_dtype (np .float32 )
140
+ for i in range (vfs .shape [- 1 ]):
141
+ nb .Nifti1Image (vfs [..., i ].astype (np .float32 ), aff ,
142
+ newhdr ).to_filename ('vf_iso%02d.nii.gz' % i )
143
+
144
+ for i in range (ffs .shape [- 1 ]):
145
+ nb .Nifti1Image (ffs [..., i ].astype (np .float32 ), aff ,
146
+ newhdr ).to_filename ('vf_ani%02d.nii.gz' % i )
147
+
122
148
# Generate a mask
123
149
if isdefined (self .inputs .in_mask ):
124
150
msk = nb .load (self .inputs .in_mask ).get_data ()
@@ -135,7 +161,7 @@ def _run_interface(self, runtime):
135
161
op .abspath (self .inputs .out_mask ))
136
162
137
163
# Initialize stack of args
138
- args = np . hstack (( vfs [ msk > 0 ], ffs [msk > 0 ]) )
164
+ args = ffs [msk > 0 ]. copy ( )
139
165
140
166
# Stack directions
141
167
for f in self .inputs .in_dirs :
@@ -157,7 +183,7 @@ def _run_interface(self, runtime):
157
183
np .savetxt (op .abspath (self .inputs .out_bval ), gtab .bvals )
158
184
159
185
snr = self .inputs .snr
160
- args = [tuple ([nsticks , gtab , snr ] + r .tolist ()) for r in args ]
186
+ args = [tuple ([nsticks , gtab ] + r .tolist ()) for r in args ]
161
187
162
188
n_proc = self .inputs .n_proc
163
189
if n_proc == 0 :
@@ -171,25 +197,36 @@ def _run_interface(self, runtime):
171
197
iflogger .info (('Starting simulation of %d voxels, %d diffusion'
172
198
' directions.' ) % (len (args ), len (gtab .bvals )))
173
199
200
+ # Simulate sticks using dipy
174
201
result = np .array (pool .map (_compute_voxel , args ))
175
202
176
203
ndirs = len (gtab .bvals )
177
204
if np .shape (result )[1 ] != ndirs :
178
205
raise RuntimeError (('Computed directions do not match number'
179
206
'of b-values.' ))
180
207
181
- simulated = np .zeros ((shape [0 ], shape [1 ], shape [2 ], ndirs ))
182
- simulated [msk > 0 ] = result
208
+ signal = np .zeros ((shape [0 ], shape [1 ], shape [2 ], ndirs ))
209
+ signal [msk > 0 ] = result
210
+
211
+ # Simulate balls
212
+ D_ball = [3000e-6 , 960e-6 , 680e-6 ]
213
+
214
+ for i in range (ndirs ):
215
+ for f0 , d in zip (vfs , D_ball ):
216
+ signal += f0 * np .exp (- gtab .bvals * d )
217
+
218
+ if snr > 0 :
219
+ signal [msk > 0 ] = add_noise (signal [msk > 0 ], snr , 1 )
183
220
184
221
# S0
185
222
b0 = b0_im .get_data ()
186
223
for i in xrange (ndirs ):
187
- simulated [..., i ] *= b0
224
+ signal [..., i ] *= b0
188
225
189
226
simhdr = hdr .copy ()
190
227
simhdr .set_data_dtype (np .float32 )
191
228
simhdr .set_xyzt_units ('mm' , 'sec' )
192
- nb .Nifti1Image (simulated .astype (np .float32 ), aff ,
229
+ nb .Nifti1Image (signal .astype (np .float32 ), aff ,
193
230
simhdr ).to_filename (op .abspath (self .inputs .out_file ))
194
231
195
232
return runtime
@@ -219,18 +256,13 @@ def _compute_voxel(args):
219
256
.. [Pierpaoli1996] Pierpaoli et al., Diffusion tensor MR imaging
220
257
of the human brain, Radiology 201:637-648. 1996.
221
258
"""
222
- D_ball = [3000e-6 , 960e-6 , 680e-6 ]
223
259
sf_evals = [1700e-6 , 200e-6 , 200e-6 ]
224
260
225
261
nf = args [0 ] # number of fibers
226
262
gtab = args [1 ] # gradient table
227
- snr = args [2 ]
228
- vfs = args [3 :6 ]
229
-
230
- vfs = (np .array (vfs ) / np .sum (vfs ))
231
263
232
- sst = 6 + nf
233
- ffs = args [6 :sst ] # single fiber fractions
264
+ sst = 2 + nf
265
+ ffs = args [2 :sst ] # single fiber fractions
234
266
235
267
sticks = [tuple (args [sst + i * 3 :sst + 3 + i * 3 ])
236
268
for i in range (0 , nf )]
@@ -246,16 +278,6 @@ def _compute_voxel(args):
246
278
else :
247
279
signal = np .zeros_like (gtab .bvals , dtype = np .float32 )
248
280
249
- signal *= vfs [2 ] * sf_vf
250
-
251
- # Simulate balls
252
- vfs [2 ] *= (1 - sf_vf )
253
- for f0 , d in zip (vfs , D_ball ):
254
- signal += f0 * np .exp (- gtab .bvals * d )
255
-
256
- if snr > 0 :
257
- signal = add_noise (signal , snr , 1 )
258
-
259
281
return signal .tolist ()
260
282
261
283
0 commit comments