Nipype - how to fetch several specific runs data according to a text file in the subject folder?

Hi folks, I have multiple runs in each subject specific folder, and also a text file in the subject folder indicating the runs relevant of my interest (e.g., sub001/run01; sub001/run02; sub001/run03; sub001/run04; sub001/run_interest.txt). I’d like to fetch files in the run folders specified by the text file (say run_interest.txt), and the runs specified may be different for different subjects. How to implement this efficiently and elegantly? I know a DataGrabber node can read files specified by “template” or “field_template” argument easily, however, in my case, it seems much more complicated for that I have to firstly build a DataGrabber node and a simple function node to fetch and read from the run_interest.txt in each subject folder to get the runs, and then put the runs interested to a new DataGrabber node to get the image data in each run. It’s overwhelmingly too complicated.

Thank you very much and waiting for your reply.

Best,
Tom

Hi @Jackson,

AFAIK, there is no super easy way to do this. Your best bet would be to read each file per subject, and then extract the runs of interest for that subject. I’ve included a sample below, let me know if you have any questions!

from nipype import Workflow, Node, SelectFiles, Function, MapNode

def get_runs(subject):
    # returns list of runs
    with open('/full/path/to/scan/files/%s/scans.tsv' % subject, 'r') as fp:
        return subject, list(fp.read().strip().split('\n'))
    
getruns = Node(Function(input_names=['subject'],
                        output_names=['subj', 'runs'],
                        function=get_runs),
               name='getruns')
getruns.inputs.subject = 'sub-x'

# substitute runs in name
templates = {'func': '/full/path/to/data/{subject_id}/func/*_{runs!s}_*nii.gz'}
datasource = MapNode(SelectFiles(templates), name='getfiles', iterfield=['runs'])

# list of a list of files for each run [[run1files][run2files]]

# if you want to collapse among runs
def collector(func):
    from functools import reduce
    return reduce(lambda x, y: x+y, func)

allruns = Node(Function(input_names=['func'],
                   output_names=['out'],
                   function=collector),
               name='allruns')

wf = Workflow(base_dir='.', name='delete_me')
wf.connect(getruns, 'subj', datasource, 'subject_id')
wf.connect(getruns, 'runs', datasource, 'runs')
wf.connect(datasource, 'func', allruns, 'func')


eg = wf.run()

Thank you so much! @mgxd