import nipype.interfaces.afni.preprocess as e_afni
from CPAC.pipeline import nipype_pipeline_engine as pe
import nipype.interfaces.utility as util
[docs]def create_scrubbing_preproc(wf_name = 'scrubbing'):
"""
This workflow essentially takes the list of offending timepoints that are to be removed
and removes it from the motion corrected input image. Also, it removes the information
of discarded time points from the movement parameters file obtained during motion correction.
Parameters
----------
wf_name : string
Name of the workflow
Returns
-------
scrub : object
Scrubbing workfow object
Notes
-----
`Source <https://github.com/openconnectome/C-PAC/blob/master/CPAC/scrubbing/scrubbing.py>`_
Workflow Inputs::
inputspec.frames_in_ID : string (mat file)
path to file containing list of time points for which FD > threshold
inputspec.movement_parameters : string (mat file)
path to file containing 1D file containing six movement/motion parameters
(3 Translation, 3 Rotations) in different columns
inputspec.preprocessed : string (nifti file)
preprocessed input image path
Workflow Outputs::
outputspec.preprocessed : string (nifti file)
preprocessed scrubbed output image
outputspec.scrubbed_movement_parameters : string (mat file)
path to 1D file containing six movement/motion parameters
for the timepoints which are not discarded by scrubbing
Order of Commands:
- Remove all movement parameters for all the time frames other than those that are present
in the frames_in_1D file
- Remove the discarded timepoints from the input image. For details see `3dcalc <http://afni.nimh.nih.gov/pub/dist/doc/program_help/3dcalc.html>`_::
3dcalc -a bandpassed_demeaned_filtered.nii.gz[0,1,5,6,7,8,9,10,15,16,17,18,19,20,24,25,287,288,289,290,291,292,293,294,295]
-expr 'a' -prefix bandpassed_demeaned_filtered_3dc.nii.gz
High Level Workflow Graph:
.. exec::
from CPAC.scrubbing import create_scrubbing_preproc
wf = create_scrubbing_preproc()
wf.write_graph(
graph2use='orig',
dotfilename='./images/generated/scrubbing.dot'
)
.. image:: ../../images/generated/scrubbing.png
:width: 500
Detailed Workflow Graph:
.. image:: ../../images/generated/scrubbing_detailed.png
:width: 500
Example
-------
>>> from CPAC import scrubbing
>>> sc = scrubbing.create_scrubbing_preproc()
>>> sc.inputs.inputspec.frames_in_ID = 'frames_in.1D' # doctest: +SKIP
>>> sc.inputs.inputpsec.movement_parameters = 'rest_mc.1D' # doctest: +SKIP
>>> sc.inputs.inputpsec.preprocessed = 'rest_pp.nii.gz' # doctest: +SKIP
>>> sc.run() # doctest: +SKIP
"""
scrub = pe.Workflow(name=wf_name)
inputNode = pe.Node(util.IdentityInterface(fields=['frames_in_1D',
'movement_parameters',
'preprocessed'
]),
name='inputspec')
outputNode = pe.Node(util.IdentityInterface(fields=['preprocessed',
'scrubbed_movement_parameters']),
name='outputspec')
craft_scrub_input = pe.Node(util.Function(input_names=['scrub_input', 'frames_in_1D_file'],
output_names=['scrub_input_string'],
function=get_indx),
name = 'scrubbing_craft_input_string')
scrubbed_movement_parameters = pe.Node(util.Function(input_names=['infile_a', 'infile_b'],
output_names=['out_file'],
function=get_mov_parameters),
name='scrubbed_movement_parameters')
# THIS commented out until Nipype has an input for this interface that
# allows for the selection of specific volumes to include
#scrubbed_preprocessed = pe.Node(interface=e_afni.Calc(),
# name='scrubbed_preprocessed')
#scrubbed_preprocessed.inputs.expr = 'a'
#scrubbed_preprocessed.inputs.outputtype = 'NIFTI_GZ'
scrubbed_preprocessed = pe.Node(util.Function(input_names=['scrub_input'],
output_names=['scrubbed_image'],
function=scrub_image),
name='scrubbed_preprocessed')
scrub.connect(inputNode, 'preprocessed', craft_scrub_input, 'scrub_input')
scrub.connect(inputNode, 'frames_in_1D', craft_scrub_input, 'frames_in_1D_file')
scrub.connect(craft_scrub_input, 'scrub_input_string', scrubbed_preprocessed, 'scrub_input')
scrub.connect(inputNode, 'movement_parameters', scrubbed_movement_parameters, 'infile_b')
scrub.connect(inputNode, 'frames_in_1D', scrubbed_movement_parameters, 'infile_a' )
scrub.connect(scrubbed_preprocessed, 'scrubbed_image', outputNode, 'preprocessed')
scrub.connect(scrubbed_movement_parameters, 'out_file', outputNode, 'scrubbed_movement_parameters')
return scrub
[docs]def get_mov_parameters(infile_a, infile_b):
"""
Method to get the new movement parameters
file after removing the offending time frames
(i.e., those exceeding FD 0.5mm/0.2mm threshold)
Parameters
----------
infile_a : string
path to file containing the valid time frames
infile_b : string
path to the file containing motion parameters
Returns
-------
out_file : string
path to the file containing motion parameters
for the valid time frames
"""
import os
import warnings
out_file = os.path.join(os.getcwd(), 'rest_mc_scrubbed.1D')
f1= open(infile_a)
f2=open(infile_b)
l1=f1.readline()
l2=f2.readlines()
f1.close()
f2.close()
if l1:
l1=l1.rstrip(',').split(',')
warnings.warn("number of timepoints remaining after scrubbing -> %d"%len(l1))
else:
raise Exception("No time points remaining after scrubbing.")
f = open(out_file, 'a')
for l in l1:
data=l2[int(l.strip())]
f.write(data)
f.close()
return out_file
[docs]def get_indx(scrub_input, frames_in_1D_file):
"""
Method to get the list of time
frames that are to be included
Parameters
----------
in_file : string
path to file containing the valid time frames
Returns
-------
scrub_input_string : string
input string for 3dCalc in scrubbing workflow,
looks something like " 4dfile.nii.gz[0,1,2,..100] "
"""
with open(frames_in_1D_file, 'r') as f:
line = f.readline()
line = line.strip(',')
if line:
indx = map(int, line.split(","))
else:
raise Exception("No time points remaining after scrubbing.")
scrub_input_string = scrub_input + str(indx).replace(" ", "")
return scrub_input_string
def scrub_image(scrub_input):
"""
Method to run 3dcalc in order to scrub the image. This is used instead of
the Nipype interface for 3dcalc because functionality is needed for
specifying an input file with specifically-selected volumes. For example:
input.nii.gz[2,3,4,..98], etc.
Parameters
----------
scrub_input : string
path to 4D file to be scrubbed, plus with selected volumes to be
included
Returns
-------
scrubbed_image : string
path to the scrubbed 4D file
"""
import os
os.system("3dcalc -a %s -expr 'a' -prefix scrubbed_preprocessed.nii.gz" % scrub_input)
scrubbed_image = os.path.join(os.getcwd(), "scrubbed_preprocessed.nii.gz")
return scrubbed_image