@@ -671,6 +671,149 @@ def _list_outputs(self):
671
671
return outputs
672
672
673
673
674
+ class Normalize12InputSpec (SPMCommandInputSpec ):
675
+ image_to_align = File (exists = True , field = 'subj.vol' ,
676
+ desc = 'file to estimate the normalization parameters with' ,
677
+ xor = ['deformation_file' ],
678
+ mandatory = True , copyfile = True )
679
+ apply_to_files = InputMultiPath (traits .Either (File (exists = True ),
680
+ traits .List (File (exists = True ))),
681
+ field = 'subj.resample' ,
682
+ desc = 'files to apply transformation to' ,
683
+ copyfile = True )
684
+ deformation_file = File (field = 'subj.def' , mandatory = True ,
685
+ xor = ['image_to_align' , 'tpm' ],
686
+ desc = 'file y_*.nii containing 3 deformation fields for the deformation in x, y and z dimension' ,
687
+ copyfile = False )
688
+ jobtype = traits .Enum ('estwrite' , 'est' , 'write' ,
689
+ desc = 'one of: est, write, estwrite (opt, estwrite)' ,
690
+ usedefault = True )
691
+ bias_regularization = traits .Enum (0 , 0.00001 , 0.0001 , 0.001 , 0.01 , 0.1 , 1 , 10 ,
692
+ field = 'eoptions.biasreg' ,
693
+ desc = 'no(0) - extremely heavy (10) (opt)' )
694
+ bias_fwhm = traits .Enum (30 , 40 , 50 , 60 , 70 , 80 , 90 , 100 , 110 , 120 , 130 , 140 , 150 ,
695
+ 'Inf' , field = 'eoptions.biasfwhm' ,
696
+ desc = 'FWHM of Gaussian smoothness of bias (opt)' )
697
+ tpm = File (exists = True , field = 'eoptions.tpm' ,
698
+ desc = 'template in form of a tissue probablitiy map to normalize to (opt)' ,
699
+ mandatory = False , xor = ['deformation_file' ],
700
+ copyfile = False )
701
+ affine_regularization_type = traits .Enum ('mni' , 'size' , 'none' , field = 'eoptions.affreg' ,
702
+ desc = 'mni, size, none (opt)' )
703
+ warping_regularization = traits .List (traits .Float (), field = 'eoptions.reg' ,
704
+ minlen = 5 , maxlen = 5 ,
705
+ desc = 'Controls balance between parameters and data (opt)' )
706
+ smoothness = traits .Float (field = 'eoptions.fwhm' ,
707
+ desc = 'value (in mm) to smooth the data before normalization (opt)' )
708
+ sampling_distance = traits .Float (field = 'eoptions.samp' ,
709
+ desc = 'Sampling distance on data for parameter estimation (opt)' )
710
+ write_bounding_box = traits .List (traits .List (traits .Float (),
711
+ minlen = 3 , maxlen = 3 ),
712
+ field = 'woptions.bb' , minlen = 2 , maxlen = 2 ,
713
+ desc = '3x2-element list of lists representing the bounding box (in mm) to be written (opt)' )
714
+ write_voxel_sizes = traits .List (traits .Float (), field = 'woptions.vox' ,
715
+ minlen = 3 , maxlen = 3 ,
716
+ desc = '3-element list representing the voxel sizes (in mm) of the written normalised images (opt)' )
717
+ write_interp = traits .Range (low = 0 , high = 7 , field = 'woptions.interp' ,
718
+ desc = 'degree of b-spline used for interpolation (opt)' )
719
+
720
+
721
+ class Normalize12OutputSpec (TraitedSpec ):
722
+ deformation_field = OutputMultiPath (File (exists = True ), desc = 'NIfTI file containing 3 deformation fields for the deformation in x, y and z dimension' )
723
+ normalized_image = OutputMultiPath (File (exists = True ), desc = 'Normalized file that needed to be aligned' )
724
+ normalized_files = OutputMultiPath (File (exists = True ), desc = 'Normalized other files' )
725
+
726
+
727
+ class Normalize12 (SPMCommand ):
728
+ """uses SPM12's new Normalise routine for warping an image to a template.
729
+ Spatial normalisation is now done via the segmentation routine (which was
730
+ known as ``New Segment`` in SPM8). Note that the normalisation in SPM12
731
+ is done towards a file containing multiple tissue probability maps, which
732
+ was not the cass in SPM8.
733
+
734
+ http://www.fil.ion.ucl.ac.uk/spm/doc/manual.pdf#page=49
735
+
736
+ Examples
737
+ --------
738
+ >>> import nipype.interfaces.spm as spm
739
+ >>> norm12 = spm.Normalize12()
740
+ >>> norm12.inputs.image_to_align = 'structural.nii'
741
+ >>> norm12.inputs.apply_to_files = 'functional.nii'
742
+ >>> norm12.run() # doctest: +SKIP
743
+
744
+ """
745
+
746
+ input_spec = Normalize12InputSpec
747
+ output_spec = Normalize12OutputSpec
748
+ _jobtype = 'spatial'
749
+ _jobname = 'normalise'
750
+
751
+ def _format_arg (self , opt , spec , val ):
752
+ """Convert input to appropriate format for spm
753
+ """
754
+ if opt == 'tpm' :
755
+ return scans_for_fname (filename_to_list (val ))
756
+ if opt == 'image_to_align' :
757
+ return scans_for_fname (filename_to_list (val ))
758
+ if opt == 'apply_to_files' :
759
+ return scans_for_fnames (filename_to_list (val ))
760
+ if opt == 'deformation_file' :
761
+ return np .array ([list_to_filename (val )], dtype = object )
762
+ if opt in ['nonlinear_regularization' ]:
763
+ if len (val ) != 5 :
764
+ raise ValueError ('%s must have 5 elements' % opt )
765
+ return super (Normalize12 , self )._format_arg (opt , spec , val )
766
+
767
+ def _parse_inputs (self ):
768
+ """validate spm normalize options if set to None ignore
769
+ """
770
+ einputs = super (Normalize12 , self )._parse_inputs (skip = ('jobtype' ,
771
+ 'apply_to_files' ))
772
+ if isdefined (self .inputs .apply_to_files ):
773
+ inputfiles = deepcopy (self .inputs .apply_to_files )
774
+ if isdefined (self .inputs .image_to_align ):
775
+ inputfiles .extend ([self .inputs .image_to_align ])
776
+ einputs [0 ]['subj' ]['resample' ] = scans_for_fnames (inputfiles )
777
+ jobtype = self .inputs .jobtype
778
+ if jobtype in ['estwrite' , 'write' ]:
779
+ if not isdefined (self .inputs .apply_to_files ):
780
+ if isdefined (self .inputs .image_to_align ):
781
+ einputs [0 ]['subj' ]['resample' ] = scans_for_fname (self .inputs .image_to_align )
782
+ return [{'%s' % (jobtype ): einputs [0 ]}]
783
+
784
+ def _list_outputs (self ):
785
+ outputs = self ._outputs ().get ()
786
+
787
+ jobtype = self .inputs .jobtype
788
+ if jobtype .startswith ('est' ):
789
+ outputs ['deformation_field' ] = []
790
+ for imgf in filename_to_list (self .inputs .image_to_align ):
791
+ outputs ['deformation_field' ].append (fname_presuffix (imgf ,prefix = 'y_' ))
792
+ outputs ['deformation_field' ] = list_to_filename (outputs ['deformation_field' ])
793
+
794
+ if self .inputs .jobtype == "estimate" :
795
+ if isdefined (self .inputs .apply_to_files ):
796
+ outputs ['normalized_files' ] = self .inputs .apply_to_files
797
+ outputs ['normalized_image' ] = fname_presuffix (self .inputs .image_to_align ,
798
+ prefix = 'w' )
799
+ elif 'write' in self .inputs .jobtype :
800
+ outputs ['normalized_files' ] = []
801
+ if isdefined (self .inputs .apply_to_files ):
802
+ filelist = filename_to_list (self .inputs .apply_to_files )
803
+ for f in filelist :
804
+ if isinstance (f , list ):
805
+ run = [fname_presuffix (in_f ,prefix = 'w' ) for in_f in f ]
806
+ else :
807
+ run = [fname_presuffix (f ,prefix = 'w' )]
808
+ outputs ['normalized_files' ].extend (run )
809
+ if isdefined (self .inputs .image_to_align ):
810
+ outputs ['normalized_image' ] = fname_presuffix (self .inputs .image_to_align ,
811
+ prefix = 'w' )
812
+
813
+ return outputs
814
+
815
+
816
+
674
817
class SegmentInputSpec (SPMCommandInputSpec ):
675
818
data = InputMultiPath (File (exists = True ), field = 'data' , desc = 'one scan per subject' ,
676
819
copyfile = False , mandatory = True )
0 commit comments