@@ -572,3 +572,70 @@ def nii_ones_like(in_file, value, dtype, newpath=None):
572
572
nii .to_filename (out_file )
573
573
574
574
return out_file
575
+
576
+
577
+ class SignalExtractionInputSpec (BaseInterfaceInputSpec ):
578
+ in_file = File (exists = True , mandatory = True , desc = '4-D fMRI nii file' )
579
+ label_files = InputMultiPath (
580
+ File (exists = True ),
581
+ mandatory = True ,
582
+ desc = 'a 3-D label image, with 0 denoting '
583
+ 'background, or a list of 3-D probability '
584
+ 'maps (one per label) or the equivalent 4D '
585
+ 'file.' )
586
+ class_labels = traits .List (
587
+ mandatory = True ,
588
+ desc = 'Human-readable labels for each segment '
589
+ 'in the label file, in order. The length of '
590
+ 'class_labels must be equal to the number of '
591
+ 'segments (background excluded). This list '
592
+ 'corresponds to the class labels in label_file '
593
+ 'in ascending order' )
594
+ out_file = File (
595
+ 'signals.tsv' ,
596
+ usedefault = True ,
597
+ exists = False ,
598
+ desc = 'The name of the file to output to. '
599
+ 'signals.tsv by default' )
600
+
601
+
602
+ class SignalExtractionOutputSpec (TraitedSpec ):
603
+ out_file = File (
604
+ exists = True ,
605
+ desc = 'tsv file containing the computed '
606
+ 'signals, with as many columns as there are labels and as '
607
+ 'many rows as there are timepoints in in_file, plus a '
608
+ 'header row with values from class_labels' )
609
+
610
+
611
+ class SignalExtraction (SimpleInterface ):
612
+ input_spec = SignalExtractionInputSpec
613
+ output_spec = SignalExtractionOutputSpec
614
+
615
+ def _run_interface (self , runtime ):
616
+ mask_imgs = [nb .load (fname ) for fname in self .inputs .label_files ]
617
+ if len (mask_imgs ) == 1 :
618
+ mask_imgs = nb .four_to_three (mask_imgs [0 ])
619
+
620
+ masks = [mask_img .get_data ().astype (np .bool ) for mask_img in mask_imgs ]
621
+
622
+ n_masks = len (masks )
623
+
624
+ if n_masks != len (self .inputs .class_labels ):
625
+ raise ValueError ("Number of masks must match number of labels" )
626
+
627
+ img = nb .load (self .inputs .in_file )
628
+
629
+ series = np .zeros ((img .shape [3 ], n_masks ))
630
+
631
+ data = img .get_data ()
632
+ for j in range (n_masks ):
633
+ series [:, j ] = data [masks [j ], :].mean (axis = 0 )
634
+
635
+ output = np .vstack ((self .inputs .class_labels , series .astype (str )))
636
+ self ._results ['out_file' ] = os .path .join (runtime .cwd ,
637
+ self .inputs .out_file )
638
+ np .savetxt (
639
+ self ._results ['out_file' ], output , fmt = b'%s' , delimiter = '\t ' )
640
+
641
+ return runtime
0 commit comments