Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit b8ef0fa

Browse files
committed
enh: added new preprocessing that's probably better
1 parent e117bb8 commit b8ef0fa

File tree

2 files changed

+250
-0
lines changed

2 files changed

+250
-0
lines changed

run_1.py

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
def get_flirt_motion_parameters(eddy_params):
2+
import nipype.interfaces.fsl.utils as fsl
3+
import os
4+
import numpy as np
5+
6+
data = np.genfromtxt(eddy_params)
7+
translations = data[:,:3]
8+
rotations = data[:,3:6]
9+
rigid = np.hstack((rotations, translations))
10+
11+
motion_params = os.path.abspath('motion_parameters.par')
12+
np.savetxt(motion_params, rigid)
13+
14+
return motion_params
15+
16+
17+
def run_preAFQ(dwi_file, dwi_file_AP, dwi_file_PA, bvec_file, bval_file, subjects_dir, working_dir, sink_dir):
18+
"""
19+
This is for HBN diffusion data
20+
Assuming phase-encode direction is AP/PA for topup
21+
"""
22+
import nipype.interfaces.freesurfer as fs
23+
import nipype.interfaces.fsl as fsl
24+
from nipype.interfaces.fsl.utils import AvScale
25+
import nipype.pipeline.engine as pe
26+
import nipype.interfaces.utility as niu
27+
import nipype.interfaces.io as nio
28+
from nipype.workflows.dmri.fsl.epi import create_dmri_preprocessing
29+
from nipype.interfaces.dipy import DTI
30+
from nipype.utils.filemanip import fname_presuffix
31+
import os
32+
from nipype.interfaces.dipy import DTI
33+
from nipype.interfaces.c3 import C3dAffineTool
34+
from nipype.workflows.dmri.fsl.artifacts import all_fsl_pipeline, remove_bias
35+
36+
# some bookkeeping (getting the filename, gettings the BIDS subject name)
37+
dwi_filename = os.path.split(dwi_file)[1].split(".nii.gz")[0]
38+
bids_subject_name = dwi_filename.split("_")[0]
39+
assert bids_subject_name.startswith("sub-")
40+
41+
# Grab the preprocessing all_fsl_pipeline
42+
# AK: watch out, other datasets might be encoded LR
43+
epi_AP = {'echospacing': 66.5e-3, 'enc_dir': 'y-'}
44+
epi_PA = {'echospacing': 66.5e-3, 'enc_dir': 'y'}
45+
prep = all_fsl_pipeline(epi_params=epi_AP, altepi_params=epi_PA)
46+
prep_inputspec = prep.get_node('inputnode')
47+
prep_outputspec = prep.get_node('outputnode')
48+
#print(prep_inputspec, prep_outputspec)
49+
50+
# initialize an overall workflow
51+
wf = pe.Workflow(name="preAFQ")
52+
wf.base_dir = os.path.abspath(working_dir)
53+
# wf.connect([(infosource, datasource, [('subject_id', 'subject_id')]),
54+
# (datasource, prep,
55+
# [('dwi', 'inputnode.in_file'), ('dwi_rev', 'inputnode.alt_file'),
56+
# ('bvals', 'inputnode.in_bval'), ('bvecs', 'inputnode.in_bvec')]),
57+
# (prep, bias, [('outputnode.out_file', 'inputnode.in_file'),
58+
# ('outputnode.out_mask', 'inputnode.in_mask')]),
59+
# (datasource, bias, [('bvals', 'inputnode.in_bval')])])
60+
61+
# wf = create_dmri_preprocessing(name='preAFQ',
62+
# use_fieldmap=False,
63+
# fieldmap_registration=False)
64+
65+
prep.inputs.inputnode.in_file = dwi_file
66+
#prep.inputs.inputnode.alt_file = dwi_file_PA
67+
prep.inputs.inputnode.in_bvec = bvec_file
68+
prep.inputs.inputnode.in_bval = bval_file
69+
#print(prep.inputs)
70+
71+
merge = pe.Node(fsl.Merge(dimension='t'), name="mergeAPPA")
72+
merge.inputs.in_files = [dwi_file_AP, dwi_file_PA]
73+
wf.connect(merge, 'merged_file', prep, 'inputnode.alt_file')
74+
75+
76+
fslroi = pe.Node(fsl.ExtractROI(t_min=0, t_size=1), name="fslroi")
77+
wf.connect(prep, "outputnode.out_file", fslroi, "in_file")
78+
79+
bbreg = pe.Node(fs.BBRegister(contrast_type="t2", init="fsl", out_fsl_file=True,
80+
subjects_dir=subjects_dir,
81+
epi_mask=True),
82+
name="bbreg")
83+
bbreg.inputs.subject_id = 'freesurfer' #bids_subject_name
84+
wf.connect(fslroi,"roi_file", bbreg, "source_file")
85+
86+
get_tensor = pe.Node(DTI(), name="dipy_tensor")
87+
wf.connect(prep, "outputnode.out_file", get_tensor, "in_file")
88+
get_tensor.inputs.in_bval = bval_file
89+
wf.connect(prep, "outputnode.out_bvec", get_tensor, "in_bvec")
90+
91+
scale_tensor = pe.Node(name='scale_tensor', interface=fsl.BinaryMaths())
92+
scale_tensor.inputs.operation = 'mul'
93+
scale_tensor.inputs.operand_value = 1000
94+
wf.connect(get_tensor, 'out_file', scale_tensor, 'in_file')
95+
96+
voltransform = pe.Node(fs.ApplyVolTransform(inverse=True),
97+
iterfield=['source_file', 'reg_file'],
98+
name='transform')
99+
voltransform.inputs.subjects_dir = subjects_dir
100+
101+
vt2 = voltransform.clone("transform_aparcaseg")
102+
vt2.inputs.interp = "nearest"
103+
104+
vt3 = voltransform.clone("transform_orig")
105+
106+
107+
def binarize_aparc(aparc_aseg):
108+
import nibabel as nib
109+
from nipype.utils.filemanip import fname_presuffix
110+
import os
111+
img = nib.load(aparc_aseg)
112+
data, aff = img.get_data(), img.affine
113+
outfile = fname_presuffix(aparc_aseg, suffix="bin.nii.gz", newpath=os.path.abspath("."), use_ext=False)
114+
nib.Nifti1Image((data > 0).astype(float), aff).to_filename(outfile)
115+
return outfile
116+
117+
create_mask = pe.Node(niu.Function(input_names=["aparc_aseg"],
118+
output_names=["outfile"],
119+
function=binarize_aparc),
120+
name="bin_aparc")
121+
122+
def get_aparc_aseg(subjects_dir, sub):
123+
return os.path.join(subjects_dir, sub, "mri", "aparc+aseg.mgz")
124+
125+
def get_orig(subjects_dir, sub):
126+
return os.path.join(subjects_dir, sub, "mri", "orig.mgz")
127+
128+
create_mask.inputs.aparc_aseg = get_aparc_aseg(subjects_dir, 'freesurfer')
129+
wf.connect(create_mask, "outfile", voltransform, "target_file")
130+
131+
wf.connect(fslroi, "roi_file", voltransform, "source_file")
132+
wf.connect(bbreg, "out_reg_file", voltransform, "reg_file")
133+
134+
vt2.inputs.target_file = get_aparc_aseg(subjects_dir, 'freesurfer')
135+
wf.connect(fslroi, "roi_file", vt2, "source_file")
136+
wf.connect(bbreg, "out_reg_file", vt2, "reg_file")
137+
138+
vt3.inputs.target_file = get_orig(subjects_dir, 'freesurfer')
139+
wf.connect(fslroi, "roi_file", vt3, "source_file")
140+
wf.connect(bbreg, "out_reg_file", vt3, "reg_file")
141+
142+
# AK (2017): THIS NODE MIGHT NOT BE NECESSARY
143+
# AK (2018) doesn't know why she said that above..
144+
threshold2 = pe.Node(fs.Binarize(min=0.5, out_type='nii.gz', dilate=1),
145+
iterfield=['in_file'],
146+
name='threshold2')
147+
wf.connect(voltransform, "transformed_file", threshold2, "in_file")
148+
149+
# art detect stuff
150+
151+
motion = pe.Node(niu.Function(input_names=['eddy_params'],
152+
output_names=['motion_file'],
153+
function=get_flirt_motion_parameters),
154+
name="reformat_motion")
155+
156+
wf.connect(prep, "fsl_eddy.out_parameter", motion, "eddy_params")
157+
158+
from nipype.algorithms.rapidart import ArtifactDetect
159+
160+
art = pe.Node(interface=ArtifactDetect(), name="art")
161+
art.inputs.use_differences = [True, True]
162+
art.inputs.save_plot=False
163+
art.inputs.use_norm = True
164+
art.inputs.norm_threshold = 3
165+
art.inputs.zintensity_threshold = 9
166+
art.inputs.mask_type = 'spm_global'
167+
art.inputs.parameter_source = 'FSL'
168+
169+
wf.connect(motion, "motion_file", art, "realignment_parameters")
170+
wf.connect(prep, "outputnode.out_file", art, "realigned_files")
171+
172+
datasink = pe.Node(nio.DataSink(),name="sinker")
173+
datasink.inputs.base_directory = sink_dir
174+
datasink.inputs.substitutions = [("vol0000_flirt_merged.nii.gz", dwi_filename+'.nii.gz'),
175+
("stats.vol0000_flirt_merged.txt", dwi_filename+".art.json"),
176+
("motion_parameters.par", dwi_filename+".motion.txt"),
177+
("_rotated.bvec", ".bvec"),
178+
("art.vol0000_flirt_merged_outliers.txt", dwi_filename+ ".outliers.txt"),
179+
("vol0000_flirt_merged", dwi_filename),
180+
("_roi_bbreg_freesurfer", "_register"),
181+
("dwi/eddy_corrected", "dwi/%s" % dwi_filename),
182+
("dti/eddy_corrected", "dti/%s" % dwi_filename.replace("_dwi", "")),
183+
("reg/eddy_corrected", "reg/%s" % dwi_filename.replace("_dwi", "")),
184+
("aparc+asegbin_warped_thresh", dwi_filename.replace("_dwi", "_mask")),
185+
("aparc+aseg_warped_out", dwi_filename.replace("_dwi", "_aparc+aseg")),
186+
("art.eddy_corrected_outliers", dwi_filename.replace("dwi", "outliers")),
187+
("color_fa", "colorfa"),
188+
("orig_warped_out", dwi_filename.replace("_dwi", "_T1w")),
189+
#("eddy_corrected_", dwi_filename.replace("dwi", "")),
190+
("stats.eddy_corrected", dwi_filename.replace("dwi", "artStats")),
191+
("eddy_corrected.eddy_parameters", dwi_filename+".eddy_parameters"),
192+
("derivatives/preafq", "derivatives/{}/preafq".format(bids_subject_name))]
193+
194+
195+
wf.connect(art, "statistic_files", datasink, "preafq.qc.@artstat")
196+
wf.connect(art, "outlier_files", datasink, "preafq.qc.@artoutlier")
197+
198+
wf.connect(prep, "outputnode.out_file", datasink, "preafq.dwi.@corrected")
199+
wf.connect(prep, "outputnode.out_bvec", datasink, "preafq.dwi.@rotated")
200+
wf.connect(prep, "fsl_eddy.out_parameter", datasink, "preafq.qc.@eddyparams")
201+
202+
wf.connect(get_tensor, "out_file", datasink, "preafq.dti.@tensor")
203+
wf.connect(get_tensor, "fa_file", datasink, "preafq.dti.@fa")
204+
wf.connect(get_tensor, "md_file", datasink, "preafq.dti.@md")
205+
wf.connect(get_tensor, "ad_file", datasink, "preafq.dti.@ad")
206+
wf.connect(get_tensor, "rd_file", datasink, "preafq.dti.@rd")
207+
wf.connect(get_tensor, "color_fa_file", datasink, "preafq.dti.@colorfa")
208+
wf.connect(get_tensor, "out_file", datasink, "preafq.dti.@scaled_tensor")
209+
210+
wf.connect(bbreg, "min_cost_file", datasink, "preafq.reg.@mincost")
211+
wf.connect(bbreg,"out_fsl_file", datasink, "preafq.reg.@fslfile")
212+
wf.connect(bbreg, "out_reg_file", datasink, "preafq.reg.@reg")
213+
wf.connect(threshold2, "binary_file", datasink, "preafq.anat.@mask")
214+
215+
convert = pe.Node(fs.MRIConvert(out_type="niigz"), name="convert2nii")
216+
wf.connect(vt2, "transformed_file", convert, "in_file")
217+
wf.connect(convert, "out_file", datasink, "preafq.anat.@aparc_aseg")
218+
219+
convert1 = convert.clone("convertorig2nii")
220+
wf.connect(vt3, "transformed_file", convert1, "in_file")
221+
wf.connect(convert1, "out_file", datasink, "preafq.anat.@anat")
222+
223+
#wf.base_dir = working_dir
224+
#wf.write_graph()
225+
wf.run()
226+
227+
from glob import glob
228+
import os
229+
from shutil import copyfile
230+
231+
copyfile(bval_file, os.path.join(sink_dir, bids_subject_name, "preafq", "dwi", os.path.split(bval_file)[1]))
232+
233+
# dmri_corrected = glob(os.path.join(sink_dir, '*/preafq/dwi', '*.nii.gz'))[0]
234+
# bvec_rotated = glob(os.path.join(sink_dir, '*/preafq/dwi', '*.bvec'))[0]
235+
# bval_file = glob(os.path.join(sink_dir, '*/preafq/dwi', '*.bval'))[0]
236+
# # art_file = glob(os.path.join(sink_dir, '*/preafq/art', '*.art.json'))[0]
237+
# # motion_file = glob(os.path.join(sink_dir, '*/preafq/art', '*.motion.txt'))[0]
238+
# # outlier_file = glob(os.path.join(sink_dir, '*/preafq/art', '*.outliers.txt'))[0]
239+
# return dmri_corrected, bvec_rotated, #art_file, motion_file, outlier_file

run_data.1.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from run_1 import *
2+
import os
3+
output = run_preAFQ(os.path.abspath("./sub-NDARBA507GCT/dwi/sub-NDARBA507GCT_acq-64dir_dwi.nii.gz"),
4+
os.path.abspath("./sub-NDARBA507GCT/fmap/sub-NDARBA507GCT_dir-AP_acq-dwi_epi.nii.gz"),
5+
os.path.abspath("./sub-NDARBA507GCT/fmap/sub-NDARBA507GCT_dir-PA_acq-dwi_epi.nii.gz"),
6+
os.path.abspath("./sub-NDARBA507GCT/dwi/sub-NDARBA507GCT_acq-64dir_dwi.bvec"),
7+
os.path.abspath("./sub-NDARBA507GCT/dwi/sub-NDARBA507GCT_acq-64dir_dwi.bval"),
8+
os.path.abspath("./derivatives/sub-NDARBA507GCT"),
9+
os.path.abspath("./scratch1"),
10+
os.path.abspath("./derivatives"))
11+
print(output)

0 commit comments

Comments
 (0)