Skip to content

Commit 10388b0

Browse files
authored
Merge pull request #3263 from aghayoor/afni_corrnet
NF: AFNI 3dNetCorr as afni.NetCorr
2 parents 47fe00b + c00dd2f commit 10388b0

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed

nipype/interfaces/afni/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
LFCD,
3030
Maskave,
3131
Means,
32+
NetCorr,
3233
OutlierCount,
3334
QualityIndex,
3435
ROIStats,

nipype/interfaces/afni/preprocess.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,6 +2556,186 @@ def _format_arg(self, name, trait_spec, value):
25562556
return super(TCorrMap, self)._format_arg(name, trait_spec, value)
25572557

25582558

2559+
class NetCorrInputSpec(AFNICommandInputSpec):
2560+
in_file = File(
2561+
desc="input time series file (4D data set)",
2562+
exists=True,
2563+
argstr="-inset %s",
2564+
mandatory=True)
2565+
in_rois = File(
2566+
desc="input set of ROIs, each labelled with distinct integers",
2567+
exists=True,
2568+
argstr="-in_rois %s",
2569+
mandatory=True)
2570+
mask = File(
2571+
desc="can include a whole brain mask within which to "
2572+
"calculate correlation. Otherwise, data should be "
2573+
"masked already",
2574+
exists=True,
2575+
argstr="-mask %s")
2576+
weight_ts = File(
2577+
desc="input a 1D file WTS of weights that will be applied "
2578+
"multiplicatively to each ROI's average time series. "
2579+
"WTS can be a column- or row-file of values, but it "
2580+
"must have the same length as the input time series "
2581+
"volume. "
2582+
"If the initial average time series was A[n] for "
2583+
"n=0,..,(N-1) time points, then applying a set of "
2584+
"weights W[n] of the same length from WTS would "
2585+
"produce a new time series: B[n] = A[n] * W[n]",
2586+
exists=True,
2587+
argstr="-weight_ts %s")
2588+
fish_z = traits.Bool(
2589+
desc="switch to also output a matrix of Fisher Z-transform "
2590+
"values for the corr coefs (r): "
2591+
"Z = atanh(r) , "
2592+
"(with Z=4 being output along matrix diagonals where "
2593+
"r=1, as the r-to-Z conversion is ceilinged at "
2594+
"Z = atanh(r=0.999329) = 4, which is still *quite* a "
2595+
"high Pearson-r value",
2596+
argstr="-fish_z")
2597+
part_corr = traits.Bool(
2598+
desc="output the partial correlation matrix",
2599+
argstr="-part_corr")
2600+
ts_out = traits.Bool(
2601+
desc="switch to output the mean time series of the ROIs that "
2602+
"have been used to generate the correlation matrices. "
2603+
"Output filenames mirror those of the correlation "
2604+
"matrix files, with a '.netts' postfix",
2605+
argstr="-ts_out")
2606+
ts_label = traits.Bool(
2607+
desc="additional switch when using '-ts_out'. Using this "
2608+
"option will insert the integer ROI label at the start "
2609+
"of each line of the *.netts file created. Thus, for "
2610+
"a time series of length N, each line will have N+1 "
2611+
"numbers, where the first is the integer ROI label "
2612+
"and the subsequent N are scientific notation values",
2613+
argstr="-ts_label")
2614+
ts_indiv = traits.Bool(
2615+
desc="switch to create a directory for each network that "
2616+
"contains the average time series for each ROI in "
2617+
"individual files (each file has one line). "
2618+
"The directories are labelled PREFIX_000_INDIV/, "
2619+
"PREFIX_001_INDIV/, etc. (one per network). Within each "
2620+
"directory, the files are labelled ROI_001.netts, "
2621+
"ROI_002.netts, etc., with the numbers given by the "
2622+
"actual ROI integer labels",
2623+
argstr="-ts_indiv")
2624+
ts_wb_corr = traits.Bool(
2625+
desc="switch to create a set of whole brain correlation maps. "
2626+
"Performs whole brain correlation for each "
2627+
"ROI's average time series; this will automatically "
2628+
"create a directory for each network that contains the "
2629+
"set of whole brain correlation maps (Pearson 'r's). "
2630+
"The directories are labelled as above for '-ts_indiv' "
2631+
"Within each directory, the files are labelled "
2632+
"WB_CORR_ROI_001+orig, WB_CORR_ROI_002+orig, etc., with "
2633+
"the numbers given by the actual ROI integer labels",
2634+
argstr="-ts_wb_corr")
2635+
ts_wb_Z = traits.Bool(
2636+
desc="same as above in '-ts_wb_corr', except that the maps "
2637+
"have been Fisher transformed to Z-scores the relation: "
2638+
"Z=atanh(r). "
2639+
"To avoid infinities in the transform, Pearson values "
2640+
"are effectively capped at |r| = 0.999329 (where |Z| = 4.0). "
2641+
"Files are labelled WB_Z_ROI_001+orig, etc",
2642+
argstr="-ts_wb_Z")
2643+
ts_wb_strlabel = traits.Bool(
2644+
desc="by default, '-ts_wb_{corr,Z}' output files are named "
2645+
"using the int number of a given ROI, such as: "
2646+
"WB_Z_ROI_001+orig. "
2647+
"With this option, one can replace the int (such as '001') "
2648+
"with the string label (such as 'L-thalamus') "
2649+
"*if* one has a labeltable attached to the file",
2650+
argstr="-ts_wb_strlabel")
2651+
nifti = traits.Bool(
2652+
desc="output any correlation map files as NIFTI files "
2653+
"(default is BRIK/HEAD). Only useful if using "
2654+
"'-ts_wb_corr' and/or '-ts_wb_Z'",
2655+
argstr="-nifti")
2656+
output_mask_nonnull = traits.Bool(
2657+
desc="internally, this program checks for where there are "
2658+
"nonnull time series, because we don't like those, in "
2659+
"general. With this flag, the user can output the "
2660+
"determined mask of non-null time series.",
2661+
argstr="-output_mask_nonnull")
2662+
push_thru_many_zeros = traits.Bool(
2663+
desc="by default, this program will grind to a halt and "
2664+
"refuse to calculate if any ROI contains >10 percent "
2665+
"of voxels with null times series (i.e., each point is "
2666+
"0), as of April, 2017. This is because it seems most "
2667+
"likely that hidden badness is responsible. However, "
2668+
"if the user still wants to carry on the calculation "
2669+
"anyways, then this option will allow one to push on "
2670+
"through. However, if any ROI *only* has null time "
2671+
"series, then the program will not calculate and the "
2672+
"user will really, really, really need to address their masking",
2673+
argstr="-push_thru_many_zeros")
2674+
ignore_LT = traits.Bool(
2675+
desc="switch to ignore any label table labels in the "
2676+
"'-in_rois' file, if there are any labels attached",
2677+
argstr="-ignore_LT")
2678+
out_file = File(
2679+
desc="output file name part",
2680+
name_template="%s_netcorr",
2681+
argstr="-prefix %s",
2682+
position=1,
2683+
name_source="in_file",
2684+
)
2685+
2686+
class NetCorrOutputSpec(TraitedSpec):
2687+
out_corr_matrix = File(desc="output correlation matrix between ROIs written to a text file with .netcc suffix")
2688+
out_corr_maps = traits.List(File(), desc="output correlation maps in Pearson and/or Z-scores")
2689+
2690+
class NetCorr(AFNICommand):
2691+
"""Calculate correlation matrix of a set of ROIs (using mean time series of
2692+
each). Several networks may be analyzed simultaneously, one per brick.
2693+
2694+
For complete details, see the `3dNetCorr Documentation
2695+
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dNetCorr.html>`_.
2696+
2697+
Examples
2698+
--------
2699+
>>> from nipype.interfaces import afni
2700+
>>> ncorr = afni.NetCorr()
2701+
>>> ncorr.inputs.in_file = 'functional.nii'
2702+
>>> ncorr.inputs.mask = 'mask.nii'
2703+
>>> ncorr.inputs.in_rois = 'maps.nii'
2704+
>>> ncorr.inputs.ts_wb_corr = True
2705+
>>> ncorr.inputs.ts_wb_Z = True
2706+
>>> ncorr.inputs.fish_z = True
2707+
>>> ncorr.inputs.out_file = 'sub0.tp1.ncorr'
2708+
>>> ncorr.cmdline
2709+
'3dNetCorr -prefix sub0.tp1.ncorr -fish_z -inset functional.nii -in_rois maps.nii -mask mask.nii -ts_wb_Z -ts_wb_corr'
2710+
>>> res = ncorr.run() # doctest: +SKIP
2711+
2712+
"""
2713+
2714+
_cmd = "3dNetCorr"
2715+
input_spec = NetCorrInputSpec
2716+
output_spec = NetCorrOutputSpec
2717+
2718+
def _list_outputs(self):
2719+
import glob
2720+
2721+
outputs = self.output_spec().get()
2722+
2723+
if not isdefined(self.inputs.out_file):
2724+
prefix = self._gen_fname(self.inputs.in_file, suffix="_netcorr")
2725+
else:
2726+
prefix = self.inputs.out_file
2727+
2728+
# All outputs should be in the same directory as the prefix
2729+
odir = os.path.dirname(os.path.abspath(prefix))
2730+
outputs["out_corr_matrix"] = glob.glob(os.path.join(odir, "*.netcc"))[0]
2731+
2732+
if isdefined(self.inputs.ts_wb_corr) or isdefined(self.inputs.ts_Z_corr):
2733+
corrdir = os.path.join(odir, prefix + "_000_INDIV")
2734+
outputs["out_corr_maps"] = glob.glob(os.path.join(corrdir, "*.nii.gz"))
2735+
2736+
return outputs
2737+
2738+
25592739
class TCorrelateInputSpec(AFNICommandInputSpec):
25602740
xset = File(
25612741
desc="input xset",
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from ..preprocess import NetCorr
3+
4+
5+
def test_NetCorr_inputs():
6+
input_map = dict(
7+
args=dict(
8+
argstr="%s",
9+
),
10+
environ=dict(
11+
nohash=True,
12+
usedefault=True,
13+
),
14+
fish_z=dict(
15+
argstr="-fish_z",
16+
),
17+
ignore_LT=dict(
18+
argstr="-ignore_LT",
19+
),
20+
in_file=dict(
21+
argstr="-inset %s",
22+
extensions=None,
23+
mandatory=True,
24+
),
25+
in_rois=dict(
26+
argstr="-in_rois %s",
27+
extensions=None,
28+
mandatory=True,
29+
),
30+
mask=dict(
31+
argstr="-mask %s",
32+
extensions=None,
33+
),
34+
nifti=dict(
35+
argstr="-nifti",
36+
),
37+
num_threads=dict(
38+
nohash=True,
39+
usedefault=True,
40+
),
41+
out_file=dict(
42+
argstr="-prefix %s",
43+
extensions=None,
44+
name_source="in_file",
45+
name_template="%s_netcorr",
46+
position=1,
47+
),
48+
output_mask_nonnull=dict(
49+
argstr="-output_mask_nonnull",
50+
),
51+
outputtype=dict(),
52+
part_corr=dict(
53+
argstr="-part_corr",
54+
),
55+
push_thru_many_zeros=dict(
56+
argstr="-push_thru_many_zeros",
57+
),
58+
ts_indiv=dict(
59+
argstr="-ts_indiv",
60+
),
61+
ts_label=dict(
62+
argstr="-ts_label",
63+
),
64+
ts_out=dict(
65+
argstr="-ts_out",
66+
),
67+
ts_wb_Z=dict(
68+
argstr="-ts_wb_Z",
69+
),
70+
ts_wb_corr=dict(
71+
argstr="-ts_wb_corr",
72+
),
73+
ts_wb_strlabel=dict(
74+
argstr="-ts_wb_strlabel",
75+
),
76+
weight_ts=dict(
77+
argstr="-weight_ts %s",
78+
extensions=None,
79+
),
80+
)
81+
inputs = NetCorr.input_spec()
82+
83+
for key, metadata in list(input_map.items()):
84+
for metakey, value in list(metadata.items()):
85+
assert getattr(inputs.traits()[key], metakey) == value
86+
87+
88+
def test_NetCorr_outputs():
89+
output_map = dict(
90+
out_corr_maps=dict(),
91+
out_corr_matrix=dict(
92+
extensions=None,
93+
),
94+
)
95+
outputs = NetCorr.output_spec()
96+
97+
for key, metadata in list(output_map.items()):
98+
for metakey, value in list(metadata.items()):
99+
assert getattr(outputs.traits()[key], metakey) == value

0 commit comments

Comments
 (0)