1
- """Provides interfaces to various commands provided by FreeSurfer
1
+ """Provides interfaces to various commands provided by dcmstack
2
2
3
3
Change directory to provide relative paths for doctests
4
4
>>> import os
9
9
"""
10
10
11
11
from __future__ import absolute_import
12
- import os , string
13
- from os import path
12
+ import os
13
+ import string
14
+ import errno
15
+ from os import path as op
14
16
from glob import glob
15
17
from nipype .interfaces .base import (TraitedSpec ,
16
18
DynamicTraitedSpec ,
33
35
except ImportError :
34
36
have_dcmstack = False
35
37
38
+
36
39
def sanitize_path_comp (path_comp ):
37
40
result = []
38
41
for char in path_comp :
@@ -42,16 +45,18 @@ def sanitize_path_comp(path_comp):
42
45
result .append (char )
43
46
return '' .join (result )
44
47
48
+
45
49
class NiftiGeneratorBaseInputSpec (TraitedSpec ):
46
50
out_format = traits .Str (desc = "String which can be formatted with "
47
51
"meta data to create the output filename(s)" )
48
- out_ext = traits .Str ('.nii.gz' ,
49
- usedefault = True ,
52
+ out_ext = traits .Str ('.nii.gz' , usedefault = True ,
50
53
desc = "Determines output file type" )
54
+ out_path = Directory (desc = 'output path, current working directory if not set' )
55
+
51
56
52
57
class NiftiGeneratorBase (BaseInterface ):
53
58
'''Base class for interfaces that produce Nifti files, potentially with
54
- embeded meta data.'''
59
+ embedded meta data.'''
55
60
def _get_out_path (self , meta , idx = None ):
56
61
'''Return the output path for the gernerated Nifti.'''
57
62
if self .inputs .out_format :
@@ -73,7 +78,22 @@ def _get_out_path(self, meta, idx=None):
73
78
out_fmt = '-' .join (out_fmt )
74
79
out_fn = (out_fmt % meta ) + self .inputs .out_ext
75
80
out_fn = sanitize_path_comp (out_fn )
76
- return path .join (os .getcwd (), out_fn )
81
+
82
+ out_path = os .getcwd ()
83
+ if isdefined (self .inputs .out_path ):
84
+ out_path = op .abspath (self .inputs .out_path )
85
+
86
+ # now, mkdir -p $out_path
87
+ try :
88
+ os .makedirs (out_path )
89
+ except OSError as exc : # Python >2.5
90
+ if exc .errno == errno .EEXIST and op .isdir (out_path ):
91
+ pass
92
+ else :
93
+ raise
94
+
95
+ return op .join (out_path , out_fn )
96
+
77
97
78
98
class DcmStackInputSpec (NiftiGeneratorBaseInputSpec ):
79
99
dicom_files = traits .Either (InputMultiPath (File (exists = True )),
@@ -92,6 +112,7 @@ class DcmStackInputSpec(NiftiGeneratorBaseInputSpec):
92
112
class DcmStackOutputSpec (TraitedSpec ):
93
113
out_file = File (exists = True )
94
114
115
+
95
116
class DcmStack (NiftiGeneratorBase ):
96
117
'''Create one Nifti file from a set of DICOM files. Can optionally embed
97
118
meta data.
@@ -111,8 +132,8 @@ class DcmStack(NiftiGeneratorBase):
111
132
112
133
def _get_filelist (self , trait_input ):
113
134
if isinstance (trait_input , six .string_types ):
114
- if path .isdir (trait_input ):
115
- return glob (path .join (trait_input , '*.dcm' ))
135
+ if op .isdir (trait_input ):
136
+ return glob (op .join (trait_input , '*.dcm' ))
116
137
else :
117
138
return glob (trait_input )
118
139
@@ -147,9 +168,11 @@ def _list_outputs(self):
147
168
outputs ["out_file" ] = self .out_path
148
169
return outputs
149
170
171
+
150
172
class GroupAndStackOutputSpec (TraitedSpec ):
151
173
out_list = traits .List (desc = "List of output nifti files" )
152
174
175
+
153
176
class GroupAndStack (DcmStack ):
154
177
'''Create (potentially) multiple Nifti files for a set of DICOM files.
155
178
'''
@@ -177,6 +200,7 @@ def _list_outputs(self):
177
200
outputs ["out_list" ] = self .out_list
178
201
return outputs
179
202
203
+
180
204
class LookupMetaInputSpec (TraitedSpec ):
181
205
in_file = File (mandatory = True ,
182
206
exists = True ,
@@ -189,8 +213,9 @@ class LookupMetaInputSpec(TraitedSpec):
189
213
"lookup and the values specify the output names" )
190
214
)
191
215
216
+
192
217
class LookupMeta (BaseInterface ):
193
- '''Lookup meta data values from a Nifti with embeded meta data.
218
+ '''Lookup meta data values from a Nifti with embedded meta data.
194
219
195
220
Example
196
221
-------
@@ -225,13 +250,13 @@ def _outputs(self):
225
250
outputs .add_trait (out_name , traits .Any )
226
251
undefined_traits [out_name ] = Undefined
227
252
outputs .trait_set (trait_change_notify = False , ** undefined_traits )
228
- #Not sure why this is needed
253
+ # Not sure why this is needed
229
254
for out_name in self ._meta_keys .values ():
230
255
_ = getattr (outputs , out_name )
231
256
return outputs
232
257
233
258
def _run_interface (self , runtime ):
234
- #If the 'meta_keys' input is a list, covert it to a dict
259
+ # If the 'meta_keys' input is a list, covert it to a dict
235
260
self ._make_name_map ()
236
261
nw = NiftiWrapper .from_filename (self .inputs .in_file )
237
262
self .result = {}
@@ -245,6 +270,7 @@ def _list_outputs(self):
245
270
outputs .update (self .result )
246
271
return outputs
247
272
273
+
248
274
class CopyMetaInputSpec (TraitedSpec ):
249
275
src_file = File (mandatory = True , exists = True )
250
276
dest_file = File (mandatory = True , exists = True )
@@ -254,9 +280,11 @@ class CopyMetaInputSpec(TraitedSpec):
254
280
exclude_classes = traits .List (desc = "List of meta data "
255
281
"classifications to exclude" )
256
282
283
+
257
284
class CopyMetaOutputSpec (TraitedSpec ):
258
285
dest_file = File (exists = True )
259
286
287
+
260
288
class CopyMeta (BaseInterface ):
261
289
'''Copy meta data from one Nifti file to another. Useful for preserving
262
290
meta data after some processing steps.'''
@@ -288,8 +316,8 @@ def _run_interface(self, runtime):
288
316
dest .meta_ext .slice_dim = src .meta_ext .slice_dim
289
317
dest .meta_ext .shape = src .meta_ext .shape
290
318
291
- self .out_path = path .join (os .getcwd (),
292
- path .basename (self .inputs .dest_file ))
319
+ self .out_path = op .join (os .getcwd (),
320
+ op .basename (self .inputs .dest_file ))
293
321
dest .to_filename (self .out_path )
294
322
295
323
return runtime
@@ -299,6 +327,7 @@ def _list_outputs(self):
299
327
outputs ['dest_file' ] = self .out_path
300
328
return outputs
301
329
330
+
302
331
class MergeNiftiInputSpec (NiftiGeneratorBaseInputSpec ):
303
332
in_files = traits .List (mandatory = True ,
304
333
desc = "List of Nifti files to merge" )
@@ -310,16 +339,19 @@ class MergeNiftiInputSpec(NiftiGeneratorBaseInputSpec):
310
339
"specified, the last singular or "
311
340
"non-existant dimension is used." )
312
341
342
+
313
343
class MergeNiftiOutputSpec (TraitedSpec ):
314
344
out_file = File (exists = True , desc = "Merged Nifti file" )
315
345
346
+
316
347
def make_key_func (meta_keys , index = None ):
317
348
def key_func (src_nii ):
318
349
result = [src_nii .get_meta (key , index ) for key in meta_keys ]
319
350
return result
320
351
321
352
return key_func
322
353
354
+
323
355
class MergeNifti (NiftiGeneratorBase ):
324
356
'''Merge multiple Nifti files into one. Merges together meta data
325
357
extensions as well.'''
@@ -353,18 +385,23 @@ def _list_outputs(self):
353
385
outputs ['out_file' ] = self .out_path
354
386
return outputs
355
387
388
+
356
389
class SplitNiftiInputSpec (NiftiGeneratorBaseInputSpec ):
357
390
in_file = File (exists = True , mandatory = True , desc = "Nifti file to split" )
358
391
split_dim = traits .Int (desc = "Dimension to split along. If not "
359
392
"specified, the last dimension is used." )
360
393
394
+
361
395
class SplitNiftiOutputSpec (TraitedSpec ):
362
396
out_list = traits .List (File (exists = True ),
363
397
desc = "Split Nifti files" )
364
398
399
+
365
400
class SplitNifti (NiftiGeneratorBase ):
366
- '''Split one Nifti file into many along the specified dimension. Each
367
- result has an updated meta data extension as well.'''
401
+ '''
402
+ Split one Nifti file into many along the specified dimension. Each
403
+ result has an updated meta data extension as well.
404
+ '''
368
405
input_spec = SplitNiftiInputSpec
369
406
output_spec = SplitNiftiOutputSpec
370
407
0 commit comments