@@ -839,6 +839,110 @@ def calc_moments(timeseries_file, moment):
839
839
zero = (m2 == 0 )
840
840
return np .where (zero , 0 , m3 / m2 ** (moment / 2.0 ))
841
841
842
+
843
+ class NormalizeProbabilityMapSetInputSpec (TraitedSpec ):
844
+ in_files = InputMultiPath (File (exists = True , mandatory = True ,
845
+ desc = 'The tpms to be normalized' ) )
846
+ in_mask = File (exists = True , mandatory = False ,
847
+ desc = 'Masked voxels must sum up 1.0, 0.0 otherwise.' )
848
+
849
+ class NormalizeProbabilityMapSetOutputSpec (TraitedSpec ):
850
+ out_files = OutputMultiPath (File (exists = True ),
851
+ desc = "normalized maps" )
852
+
853
+
854
+ class NormalizeProbabilityMapSet (BaseInterface ):
855
+ """ Returns the input tissue probability maps (tpms, aka volume fractions)
856
+ normalized to sum up 1.0 at each voxel within the mask.
857
+
858
+ .. note:: Please recall this is not a spatial normalization algorithm
859
+
860
+ Example
861
+ -------
862
+
863
+ >>> import nipype.algorithms.misc as misc
864
+ >>> normalize = misc.NormalizeProbabilityMapSet()
865
+ >>> normalize.inputs.in_files = [ 'tpm_00.nii.gz', 'tpm_01.nii.gz', 'tpm_02.nii.gz' ]
866
+ >>> normalize.inputs.in_mask = 'tpms_msk.nii.gz'
867
+ >>> normalize.run() # doctest: +SKIP
868
+ """
869
+ input_spec = NormalizeProbabilityMapSetInputSpec
870
+ output_spec = NormalizeProbabilityMapSetOutputSpec
871
+
872
+ def _run_interface (self , runtime ):
873
+ mask = None
874
+
875
+ if isdefined ( self .inputs .in_mask ):
876
+ mask = self .inputs .in_mask
877
+
878
+ self ._out_filenames = normalize_tpms ( self .inputs .in_files , mask )
879
+ return runtime
880
+
881
+ def _list_outputs (self ):
882
+ outputs = self .output_spec ().get ()
883
+ outputs ['out_files' ] = self ._out_filenames
884
+ return outputs
885
+
886
+
887
+ def normalize_tpms ( in_files , in_mask = None , out_files = [] ):
888
+ """
889
+ Returns the input tissue probability maps (tpms, aka volume fractions)
890
+ normalized to sum up 1.0 at each voxel within the mask.
891
+ """
892
+ import nibabel as nib
893
+ import numpy as np
894
+ import os .path as op
895
+
896
+ in_files = np .atleast_1d ( in_files ).tolist ()
897
+
898
+ if len (out_files )!= len (in_files ):
899
+ for i ,finname in enumerate ( in_files ):
900
+ fname ,fext = op .splitext ( op .basename ( finname ) )
901
+ if fext == '.gz' :
902
+ fname ,fext2 = op .splitext ( fname )
903
+ fext = fext2 + fext
904
+
905
+ out_file = op .abspath (fname + '_norm' + ('_%02d' % i )+ fext )
906
+ out_files += [out_file ]
907
+
908
+ imgs = [nib .load (fim ) for fim in in_files ]
909
+
910
+ if len (in_files )== 1 :
911
+ img_data = imgs [0 ].get_data ()
912
+ img_data [img_data > 0.0 ] = 1.0
913
+ hdr = imgs [0 ].get_header ().copy ()
914
+ hdr ['data_type' ]= 16
915
+ hdr .set_data_dtype ( 'float32' )
916
+ nib .save ( nib .Nifti1Image ( img_data .astype (np .float32 ), imgs [0 ].get_affine (), hdr ), out_files [0 ] )
917
+ return out_files [0 ]
918
+
919
+ img_data = np .array ( [ im .get_data () for im in imgs ] ).astype ( 'f32' )
920
+ #img_data[img_data>1.0] = 1.0
921
+ img_data [img_data < 0.0 ] = 0.0
922
+ weights = np .sum ( img_data , axis = 0 )
923
+
924
+ msk = np .ones_like ( imgs [0 ].get_data () )
925
+ msk [ weights <= 0 ] = 0
926
+
927
+ if not in_mask is None :
928
+ msk = nib .load ( in_mask ).get_data ()
929
+ msk [ msk <= 0 ] = 0
930
+ msk [ msk > 0 ] = 1
931
+
932
+ msk = np .ma .masked_equal ( msk , 0 )
933
+
934
+
935
+ for i ,out_file in enumerate ( out_files ):
936
+ data = np .ma .masked_equal ( img_data [i ], 0 )
937
+ probmap = data / weights
938
+ hdr = imgs [i ].get_header ().copy ()
939
+ hdr ['data_type' ]= 16
940
+ hdr .set_data_dtype ( 'float32' )
941
+ nib .save ( nib .Nifti1Image ( probmap .astype (np .float32 ), imgs [i ].get_affine (), hdr ), out_file )
942
+
943
+ return out_files
944
+
945
+
842
946
# Deprecated interfaces ---------------------------------------------------------
843
947
class Distance ( nam .Distance ):
844
948
"""Calculates distance between two volumes.
@@ -877,3 +981,4 @@ def __init__(self, **inputs):
877
981
warnings .warn (("This interface has been deprecated since 0.10.0,"
878
982
" please use nipype.algorithms.metrics.FuzzyOverlap" ),
879
983
DeprecationWarning )
984
+
0 commit comments