def mask_image(self,folder,in_path,out_path): """ This function for creating mask_image. It is dependent on the class name: func. folder : read the string, new folder's name. in_path : read the list, element: string, directory address of data. out_path : read the string, name of the new data. For complete details, see the BET() documentation. <https://nipype.readthedocs.io/en/latest/interfaces.html> """ print('#################_Mask_image_started_#######################') preprocessing = time.time() # Check and if not make the directory if not os.path.isdir(folder): func.newfolder(folder) # Create, and save the data : anatomy and whole brain mask image for i in range(len(in_path)): output = folder+'/'+out_path[i] print(in_path[i], "mask image started") skullstrip = BET(in_file=in_path[i], out_file=output, mask=True) skullstrip.run() print(output,"mask image completed") print("computation_time :","%.2fs" %(time.time() - preprocessing)) print('#################_Mask_image_completed_#####################')
def bet(record): import nipype from nipype.interfaces.fsl import BET from nipype.utils.filemanip import hash_infile nipype.config.enable_provenance() in_file_uri = record['t1_uri'] os.chdir('/tmp') fname = 'anatomy.nii.gz' with open(fname, 'wb') as fd: response = requests.get(in_file_uri, stream=True) if not response.ok: response.raise_for_status() for chunk in response.iter_content(1024): fd.write(chunk) # Check if interface has run with this input before sha = hash_infile(os.path.abspath(fname), crypto=hashlib.sha512) select = SelectQuery(config=app.config) res = select.execute_select('E0921842-1EDB-49F8-A4B3-BA51B85AD407') sha_recs = res[res.sha512.str.contains(sha)] bet_recs = res[res.interface.str.contains('BET')] results = dict() if sha_recs.empty or \ (not sha_recs.empty and bet_recs.empty): better = BET() better.inputs.in_file = os.path.abspath(fname) result = better.run() prov = result.provenance.rdf().serialize(format='json-ld') results.update({'prov': prov}) else: results.update({'prov': res.to_json(orient='records')}) return results
def skullstrip(infile: Path) -> Tuple[Path, Path]: cmd = BET() cmd.inputs.in_file = str(infile) cmd.inputs.out_file = str(infile).replace(SLICETIME_SUFFIX, BET_SUFFIX) cmd.inputs.output_type = "NIFTI_GZ" cmd.inputs.functional = True cmd.inputs.mask = True results = cmd.run() return results.outputs.out_file, results.outputs.mask_file
def mask_CTBrain(CT_dir, T1_dir, frac): # nav to dir with T1 images os.chdir(T1_dir) # run BET to extract brain from T1 bet = BET() bet.inputs.in_file = T1_dir + '/T1.nii' bet.inputs.frac = frac bet.inputs.robust = True bet.inputs.mask = True print "::: Extracting Brain mask from T1 using BET :::" bet.run() # use flrit to correg CT to T1 flirt = FLIRT() flirt.inputs.in_file = CT_dir + '/CT.nii' flirt.inputs.reference = T1_dir + '/T1.nii' flirt.inputs.cost_func = 'mutualinfo' print "::: Estimating corregistration from CT to T1 using FLIRT :::" flirt.run() # get inverse of estimated coreg of CT tp T1 print "::: Estimating inverse affine for Brain mask of CT :::" os.system('convert_xfm -omat inv_CT_flirt.mat -inverse CT_flirt.mat') os.system('mv inv_CT_flirt.mat %s' % (CT_dir)) # apply inverse affine coreg to get brain mask in CT space applyxfm = ApplyXfm() applyxfm.inputs.in_file = T1_dir + '/T1_brain_mask.nii.gz' applyxfm.inputs.in_matrix_file = CT_dir + '/inv_CT_flirt.mat' applyxfm.inputs.out_file = CT_dir + '/CT_mask.nii.gz' applyxfm.inputs.reference = CT_dir + '/CT.nii' applyxfm.inputs.apply_xfm = True print "::: Applying inverse affine to Brain mask to get CT mask :::" applyxfm.run() # dilate brain mask to make sure all elecs are in final masked img CT_mask = nib.load(CT_dir + '/CT_mask.nii.gz') CT_mask_dat = CT_mask.get_data() kernel = np.ones((5, 5), np.uint8) print "::: Dilating CT mask :::" dilated = cv2.dilate(CT_mask_dat, kernel, iterations=1) hdr = CT_mask.get_header() affine = CT_mask.get_affine() N = nib.Nifti1Image(dilated, affine, hdr) new_fname = CT_dir + '/dilated_CT_mask.nii' N.to_filename(new_fname) # apply mask to CT os.chdir(CT_dir) print "::: masking CT with dilated brain mask :::" os.system( "fslmaths 'CT.nii' -mas 'dilated_CT_mask.nii.gz' 'masked_CT.nii'") os.system('gunzip masked_CT.nii.gz')
def mask_CTBrain(CT_dir, T1_dir, frac): # nav to dir with T1 images os.chdir(T1_dir) # run BET to extract brain from T1 bet = BET() bet.inputs.in_file = T1_dir + "/T1.nii" bet.inputs.frac = frac bet.inputs.robust = True bet.inputs.mask = True print "::: Extracting Brain mask from T1 using BET :::" bet.run() # use flrit to correg CT to T1 flirt = FLIRT() flirt.inputs.in_file = CT_dir + "/CT.nii" flirt.inputs.reference = T1_dir + "/T1.nii" flirt.inputs.cost_func = "mutualinfo" print "::: Estimating corregistration from CT to T1 using FLIRT :::" flirt.run() # get inverse of estimated coreg of CT tp T1 print "::: Estimating inverse affine for Brain mask of CT :::" os.system("convert_xfm -omat inv_CT_flirt.mat -inverse CT_flirt.mat") os.system("mv inv_CT_flirt.mat %s" % (CT_dir)) # apply inverse affine coreg to get brain mask in CT space applyxfm = ApplyXfm() applyxfm.inputs.in_file = T1_dir + "/T1_brain_mask.nii.gz" applyxfm.inputs.in_matrix_file = CT_dir + "/inv_CT_flirt.mat" applyxfm.inputs.out_file = CT_dir + "/CT_mask.nii.gz" applyxfm.inputs.reference = CT_dir + "/CT.nii" applyxfm.inputs.apply_xfm = True print "::: Applying inverse affine to Brain mask to get CT mask :::" applyxfm.run() # dilate brain mask to make sure all elecs are in final masked img CT_mask = nib.load(CT_dir + "/CT_mask.nii.gz") CT_mask_dat = CT_mask.get_data() kernel = np.ones((5, 5), np.uint8) print "::: Dilating CT mask :::" dilated = cv2.dilate(CT_mask_dat, kernel, iterations=1) hdr = CT_mask.get_header() affine = CT_mask.get_affine() N = nib.Nifti1Image(dilated, affine, hdr) new_fname = CT_dir + "/dilated_CT_mask.nii" N.to_filename(new_fname) # apply mask to CT os.chdir(CT_dir) print "::: masking CT with dilated brain mask :::" os.system("fslmaths 'CT.nii' -mas 'dilated_CT_mask.nii.gz' 'masked_CT.nii'") os.system("gunzip masked_CT.nii.gz")
def run_bet( skip_existing: bool = True ): full_pattern = os.path.join(DATA_DIR, PATTERN) scans = glob.iglob(full_pattern, recursive=True) for scan in scans: print(f'\nCurrent series: {scan}') if skip_existing: print('Checking for existing skull-stripping output...', end='\t') dest = get_default_destination(scan) if skip_existing and os.path.isfile(dest): print(f'\u2714') continue print(f'\u2718') print('Running skull-stripping with BET...') try: bet = Node(BET(robust=True), name='bet_node') bet.inputs.in_file = scan bet.inputs.out_file = dest bet.run() print(f'\u2714\tDone!') except Exception as e: print(f'\u2718') print(e.args) break
def init_mpm_wf(me_params, mtsat_params): inputnode = Node(IdentityInterface(fields=['pdw_file', 't1w_file', 'mtw_file', 'pdw_cal', 't1w_cal', 'mtw_cal']), name='inputnode') outputnode = Node(IdentityInterface(fields=['pd_map', 'r1_map', 'r2s_map', 'mtsat_map']), name='outputnode') bet = Node(BET(mask=True, no_output=True), name='brain_mask') mpm = Node(MPMR2s(sequence=me_params, verbose=True), name='MPM_R2s') mtsat = Node(MTSat(sequence=mtsat_params, verbose=True), name='MPM_MTSat') wf = Workflow(name='Multi-Parametric-Mapping') wf.connect([(inputnode, bet, [('t1w_file', 'in_file')]), (inputnode, mpm, [('pdw_file', 'pdw_file'), ('t1w_file', 't1w_file'), ('mtw_file', 'mtw_file')]), (bet, mpm, [('mask_file', 'mask_file')]), (mpm, mtsat, [('s0_pdw', 'pdw_file'), ('s0_t1w', 't1w_file'), ('s0_mtw', 'mtw_file')]), (bet, mtsat, [('mask_file', 'mask_file')]), (mpm, outputnode, [('r2s_map', 'r2s_map')]), (mtsat, outputnode, [('s0_map', 'pd_map'), ('r1_map', 'r1_map'), ('delta_map', 'mtsat_map')])]) return wf
def run_brain_extraction_bet(image, frac, subject_label, bids_dir): """ Setup and FSLs brainextraction (BET) workflow. Parameters ---------- image : str Path to image that should be defaced. frac : float Fractional intensity threshold (0 - 1). outfile : str Name of the defaced file. bids_dir : str Path to BIDS root directory. """ import os outfile = os.path.join( bids_dir, "sourcedata/bidsonym/sub-%s" % subject_label, image[image.rfind('/') + 1:image.rfind('.nii')] + '_brainmask_desc-nondeid.nii.gz') brainextraction_wf = pe.Workflow('brainextraction_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') bet = pe.Node(BET(mask=False), name='bet') brainextraction_wf.connect([ (inputnode, bet, [('in_file', 'in_file')]), ]) inputnode.inputs.in_file = image bet.inputs.frac = float(frac) bet.inputs.out_file = outfile brainextraction_wf.run()
def fmri_bmsk_workflow(name='fMRIBrainMask', use_bet=False): """Comute brain mask of an fmri dataset""" workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode') if not use_bet: afni_msk = pe.Node(afni.Automask( outputtype='NIFTI_GZ'), name='afni_msk') # Connect brain mask extraction workflow.connect([ (inputnode, afni_msk, [('in_file', 'in_file')]), (afni_msk, outputnode, [('out_file', 'out_file')]) ]) else: from nipype.interfaces.fsl import BET, ErodeImage bet_msk = pe.Node(BET(mask=True, functional=True), name='bet_msk') erode = pe.Node(ErodeImage(kernel_shape='box', kernel_size=1.0), name='erode') # Connect brain mask extraction workflow.connect([ (inputnode, bet_msk, [('in_file', 'in_file')]), (bet_msk, erode, [('mask_file', 'in_file')]), (erode, outputnode, [('out_file', 'out_file')]) ]) return workflow
def run_quickshear(image, outfile): """ Setup and run quickshear workflow. Parameters ---------- image : str Path to image that should be defaced. outfile : str Name of the defaced file. """ deface_wf = pe.Workflow('deface_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') bet = pe.Node(BET(mask=True, frac=0.5), name='bet') quickshear = pe.Node(Quickshear(buff=50), name='quickshear') deface_wf.connect([ (inputnode, bet, [('in_file', 'in_file')]), (inputnode, quickshear, [('in_file', 'in_file')]), (bet, quickshear, [('mask_file', 'mask_file')]), ]) inputnode.inputs.in_file = image quickshear.inputs.out_file = outfile deface_wf.run()
def create_workflow_coreg_epi2t1w(): input_node = Node(IdentityInterface(fields=[ 'bold_mean', 't2star_fov', 't2star_whole', 't1w', ]), name='input') output = Node(IdentityInterface(fields=[ 'mat_epi2t1w', ]), name='output') # node skull skull = Node(interface=BET(), name="skull_stripping") coreg_epi2fov = Node(FLIRT(), name='epi_2_fov') coreg_epi2fov.inputs.cost = 'mutualinfo' coreg_epi2fov.inputs.dof = 12 coreg_epi2fov.inputs.no_search = True coreg_epi2fov.inputs.output_type = 'NIFTI_GZ' coreg_fov2whole = Node(FLIRT(), name='fov_2_whole') coreg_fov2whole.inputs.cost = 'mutualinfo' coreg_fov2whole.inputs.dof = 6 coreg_fov2whole.inputs.output_type = 'NIFTI_GZ' coreg_whole2t1w = Node(EpiReg(), name='whole_2_t1w') concat_fov2t1w = Node(interface=ConvertXFM(), name='mat_fov2t1w') concat_fov2t1w.inputs.concat_xfm = True concat_epi2t1w = Node(interface=ConvertXFM(), name='mat_epi2t1w') concat_epi2t1w.inputs.concat_xfm = True w = Workflow('coreg_epi2t1w') w.connect(input_node, 'bold_mean', coreg_epi2fov, 'in_file') w.connect(input_node, 't2star_fov', coreg_epi2fov, 'reference') w.connect(input_node, 't2star_fov', coreg_fov2whole, 'in_file') w.connect(input_node, 't2star_whole', coreg_fov2whole, 'reference') w.connect(input_node, 't1w', skull, 'in_file') w.connect(input_node, 't2star_whole', coreg_whole2t1w, 'epi') w.connect(skull, 'out_file', coreg_whole2t1w, 't1_brain') w.connect(input_node, 't1w', coreg_whole2t1w, 't1_head') w.connect(coreg_fov2whole, 'out_matrix_file', concat_fov2t1w, 'in_file') w.connect(coreg_whole2t1w, 'epi2str_mat', concat_fov2t1w, 'in_file2') w.connect(coreg_epi2fov, 'out_matrix_file', concat_epi2t1w, 'in_file') w.connect(concat_fov2t1w, 'out_file', concat_epi2t1w, 'in_file2') w.connect(concat_epi2t1w, 'out_file', output, 'mat_epi2t1w') return w
def test_skull_stripping_ids_only(): data_dir = os.path.abspath('.') + '/data/ds114' pipeline_name = 'test_skullStrippingTransformer_ds114' IDS = ['01', '02', '03'] sessions = ['test', 'retest'] transformer = SkullStrippingTransformer( data_dir=data_dir, pipeline_name=pipeline_name, search_param=dict(extensions='T1w.nii.gz'), variant='skullStrippingIDsOnly') transformer.fit_transform(IDS) for subject in IDS: for session in sessions: in_file = build_T1w_in_file_path(data_dir, subject, session) out_file = build_T1w_out_file_path(data_dir, pipeline_name, subject, session, 'skullStrippingIDsOnly', 'neededBrain') dirname = os.path.dirname(out_file) if not os.path.exists(dirname): os.makedirs(dirname) betfsl = BET(in_file=in_file, out_file=out_file) betfsl.run() res_file = build_T1w_out_file_path(data_dir, pipeline_name, subject, session, 'skullStrippingIDsOnly', 'brain') result_mat = nib.load(res_file).affine output_mat = nib.load(out_file).affine assert np.allclose(result_mat, output_mat) os.remove(res_file) os.remove(out_file)
def test_global_CommandLine_output(tmpdir): """Ensures CommandLine.set_default_terminal_output works""" from nipype.interfaces.fsl import BET ci = nib.CommandLine(command='ls -l') assert ci.terminal_output == 'stream' # default case ci = BET() assert ci.terminal_output == 'stream' # default case nib.CommandLine.set_default_terminal_output('allatonce') ci = nib.CommandLine(command='ls -l') assert ci.terminal_output == 'allatonce' nib.CommandLine.set_default_terminal_output('file') ci = nib.CommandLine(command='ls -l') assert ci.terminal_output == 'file' # Check default affects derived interfaces ci = BET() assert ci.terminal_output == 'file'
def test_global_CommandLine_output(tmpdir): """Ensures CommandLine.set_default_terminal_output works""" from nipype.interfaces.fsl import BET ci = nib.CommandLine(command="ls -l") assert ci.terminal_output == "stream" # default case ci = BET() assert ci.terminal_output == "stream" # default case nib.CommandLine.set_default_terminal_output("allatonce") ci = nib.CommandLine(command="ls -l") assert ci.terminal_output == "allatonce" nib.CommandLine.set_default_terminal_output("file") ci = nib.CommandLine(command="ls -l") assert ci.terminal_output == "file" # Check default affects derived interfaces ci = BET() assert ci.terminal_output == "file"
def process_data_files(self, analysis, options): # since the conversion takes a while, change cursor to hourglass QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) if analysis == 'eddy': process = EddyCorrect() elif analysis == 'bet': process = BET() else: process = [] for opt, value in options.items(): process.inputs.__setattr__(opt, value) # get selected files in_files, out_files, temp_files = self.return_selected_files(analysis) for in_file, out_file, temp_file in zip(in_files, out_files, temp_files): if not os.path.isdir(os.path.split(out_file)[0]): os.mkdir(os.path.split(out_file)[0]) process.inputs.in_file = in_file process.inputs.out_file = out_file if os.path.isfile(out_file): overwrite = self.overwrite_prompt(out_file) if not overwrite: out_file = os.path.join( os.path.split(out_file)[0], 'new_' + os.path.split(out_file)[1]) elif overwrite is None: return try: out = process.run() except RuntimeError as err: self.logFile += str(err) else: self.logFile += out.runtime.stdout if temp_file: self.move_from_temp(out_file) if temp_file: self.move_from_temp(in_file) # update GUI self.scanDirectory(self.baseDir) self.updateGUI(0) self.updateFileNavigator(['.nii']) QApplication.restoreOverrideCursor() self.postProcessDisplayUpdate()
def run_bet(robust: bool = True, skip_existing: bool = True): scans = get_scans(LOCATION_DICT["raw"]) for scan in scans: print(f"\nCurrent series: {scan}") if skip_existing: print("Checking for existing skull-stripping output...", end="\t") dest = get_default_destination(scan) if skip_existing and os.path.isfile(dest): print(f"\u2714") continue print(f"\u2718") print("Running skull-stripping with BET...", end="\t") try: bet = BET(robust=True) bet.inputs.in_file = scan bet.inputs.out_file = dest bet.run() print(f"\u2714\tDone!") except Exception as e: print(f"\u2718") print(e.args) break
def run_quickshear(image, outfile): deface_wf = pe.Workflow('deface_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') bet = pe.Node(BET(mask=True, frac=0.5), name='bet') quickshear = pe.Node(Quickshear(buff=50), name='quickshear') deface_wf.connect([ (inputnode, bet, [('in_file', 'in_file')]), (inputnode, quickshear, [('in_file', 'in_file')]), (bet, quickshear, [('mask_file', 'mask_file')]), ]) inputnode.inputs.in_file = image quickshear.inputs.out_file = outfile deface_wf.run()
def init_complex_mcf(name='', ref=False, fix_ge=True, negate=True): inputnode = Node( IdentityInterface(fields=['real_file', 'imag_file', 'ref_file']), name='inputnode') outputnode = Node( IdentityInterface(fields=['x_file', 'ref_file', 'mask_file']), name='outputnode') ri = Node(Complex(fix_ge=fix_ge, negate=negate, magnitude_out_file=name + '_mag.nii.gz', real_out_file=name + '_r.nii.gz', imag_out_file=name + '_i.nii.gz'), name='ri_' + name) moco = Node(MCFLIRT(mean_vol=not ref, save_mats=True), name='moco_' + name) apply_r = Node(ApplyXfm4D(four_digit=True), name='apply_r' + name) apply_i = Node(ApplyXfm4D(four_digit=True), name='apply_i' + name) x = Node(Complex(complex_out_file=name + '_x.nii.gz'), name='x_' + name) f = Node(Filter(complex_in=True, complex_out=True, filter_spec='Tukey'), name='filter_' + name) wf = Workflow(name='prep_' + name) wf.connect([(inputnode, ri, [('real_file', 'real')]), (inputnode, ri, [('imag_file', 'imag')]), (ri, moco, [('magnitude_out_file', 'in_file')]), (ri, apply_r, [('real_out_file', 'in_file')]), (ri, apply_i, [('imag_out_file', 'in_file')]), (moco, apply_r, [('mat_dir', 'trans_dir')]), (moco, apply_i, [('mat_dir', 'trans_dir')]), (apply_r, x, [('out_file', 'real')]), (apply_i, x, [('out_file', 'imag')]), (x, f, [('complex_out_file', 'in_file')]), (f, outputnode, [('out_file', 'x_file')])]) if not ref: mask = Node(BET(mask=True, no_output=True), name='mask') wf.connect([(moco, mask, [('mean_img', 'in_file')]), (moco, apply_r, [('mean_img', 'ref_vol')]), (moco, apply_i, [('mean_img', 'ref_vol')]), (moco, outputnode, [('mean_img', 'ref_file')]), (mask, outputnode, [('mask_file', 'mask_file')])]) else: wf.connect([(inputnode, moco, [('ref_file', 'ref_file')]), (inputnode, apply_r, [('ref_file', 'ref_vol')]), (inputnode, apply_i, [('ref_file', 'ref_vol')])]) return wf
def run_quickshear(image, outfile): # quickshear anat_file mask_file defaced_file [buffer] deface_wf = pe.Workflow("deface_wf") inputnode = pe.Node(niu.IdentityInterface(["in_file"]), name="inputnode") outputnode = pe.Node(niu.IdentityInterface(["out_file"]), name="outputnode") bet = pe.Node(BET(mask=True, frac=0.5), name="bet") quickshear = pe.Node(Quickshear(buff=50), name="quickshear") deface_wf.connect( [ (inputnode, bet, [("in_file", "in_file")]), (inputnode, quickshear, [("in_file", "in_file")]), (bet, quickshear, [("mask_file", "mask_file")]), ] ) inputnode.inputs.in_file = image quickshear.inputs.out_file = outfile res = deface_wf.run()
def run_brain_extraction_bet(image, frac, subject_label, bids_dir): import os outfile = os.path.join( bids_dir, "sourcedata/bidsonym/sub-%s" % subject_label, "sub-%s_space-native_brainmask.nii.gz" % subject_label) brainextraction_wf = pe.Workflow('brainextraction_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') bet = pe.Node(BET(mask=True), name='bet') brainextraction_wf.connect([ (inputnode, bet, [('in_file', 'in_file')]), ]) inputnode.inputs.in_file = image bet.inputs.frac = float(frac) bet.inputs.out_file = outfile brainextraction_wf.run()
def runNipypeBet(controller, subject_list, anatomical_id, proj_directory): infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id', subject_list)] #anat_file = opj('{subject_id}','{subject_id}_{anatomical_id}.nii') seperator = '' concat_words = ('{subject_id}_', anatomical_id, '.nii.gz') anat_file_name = seperator.join(concat_words) if controller.b_radiological_convention.get() == True: anat_file = opj('{subject_id}', anat_file_name) else: anat_file = opj('{subject_id}', 'Intermediate_Files', 'Original_Files', anat_file_name) templates = {'anat': anat_file} selectfiles = Node(SelectFiles(templates, base_directory=proj_directory), name="selectfiles") skullstrip = Node(BET(robust=True, frac=0.5, vertical_gradient=0, output_type='NIFTI_GZ'), name="skullstrip") # Datasink - creates output folder for important outputs datasink = Node(DataSink(base_directory=proj_directory), name="datasink") wf_sub = Workflow(name="wf_sub") wf_sub.base_dir = proj_directory wf_sub.connect(infosource, "subject_id", selectfiles, "subject_id") wf_sub.connect(selectfiles, "anat", skullstrip, "in_file") wf_sub.connect(skullstrip, "out_file", datasink, "bet.@out_file") substitutions = [('%s_brain' % (anatomical_id), 'brain')] # Feed the substitution strings to the DataSink node datasink.inputs.substitutions = substitutions # Run the workflow again with the substitutions in place wf_sub.run(plugin='MultiProc') return 'brain'
def deface(in_file): deface_wf = pe.Workflow('deface_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') # outputnode = pe.Node(niu.IdentityInterface(['out_file']), # name='outputnode') bet = pe.Node(BET(mask=True), name='bet') quickshear = pe.Node(Quickshear(), name='quickshear') sinker = pe.Node(DataSink(), name='store_results') sinker.inputs.base_directory = os.getcwd() deface_wf.connect([ (inputnode, bet, [('in_file', 'in_file')]), (inputnode, quickshear, [('in_file', 'in_file')]), (bet, quickshear, [('mask_file', 'mask_file')]), (quickshear, sinker, [('out_file', '@')]), ]) inputnode.inputs.in_file = in_file res = deface_wf.run()
def fmri_bmsk_workflow(name='fMRIBrainMask', use_bet=False): """ Computes a brain mask for the input :abbr:`fMRI (functional MRI)` dataset .. workflow:: from mriqc.workflows.functional import fmri_bmsk_workflow wf = fmri_bmsk_workflow() """ workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode') if not use_bet: afni_msk = pe.Node(afni.Automask(outputtype='NIFTI_GZ'), name='afni_msk') # Connect brain mask extraction workflow.connect([(inputnode, afni_msk, [('in_file', 'in_file')]), (afni_msk, outputnode, [('out_file', 'out_file')])]) else: from nipype.interfaces.fsl import BET, ErodeImage bet_msk = pe.Node(BET(mask=True, functional=True), name='bet_msk') erode = pe.Node(ErodeImage(), name='erode') # Connect brain mask extraction workflow.connect([(inputnode, bet_msk, [('in_file', 'in_file')]), (bet_msk, erode, [('mask_file', 'in_file')]), (erode, outputnode, [('out_file', 'out_file')])]) return workflow
def iterPipeline(resultsDir, workDir, subDir, subid): ANAT_DIR = abspath(join(subDir, 'ses-test/anat')) ANAT_T1W = abspath(join(ANAT_DIR, subid + '_ses-test_T1w.nii.gz')) ANAT_BET_T1W=abspath(join(resultsDir, subid + '_ses-test_T1w_bet.nii.gz')) betNodeInputs={} betNodeInputs['in_file']=ANAT_T1W betNodeInputs['mask']=True skullstrip = createNiPypeNode(BET(),'skullstrip',betNodeInputs) smoothNodeInputs = {} isosmooth = createNiPypeNode(IsotropicSmooth(),'isosmooth',smoothNodeInputs) isosmooth.iterables = ("fwhm", [4, 8, 16]) # Create the workflow wfName = "isosmoothflow" wf = Workflow(name=wfName) WF_DIR=abspath(join(workDir, wfName)) wf.base_dir = WF_DIR wf.connect(skullstrip, 'out_file', isosmooth, 'in_file') # Run it in parallel (one core for each smoothing kernel) wf.run('MultiProc', plugin_args={'n_procs': 3}) #graph showing summary of embedded workflow wfGraph='smoothflow_graph.dot' wf.write_graph(join(WF_DIR,wfGraph), graph2use='exec', format='png', simple_form=True) wfImg = plt.imread(join(WF_DIR,wfGraph+'.png')) plt.imshow(wfImg) plt.gca().set_axis_off() plt.show() # First, let's specify the list of input variables subject_list = ['sub-01', 'sub-02', 'sub-03', 'sub-04', 'sub-05'] session_list = ['ses-retest', 'ses-test'] fwhm_widths = [4, 8]
def canonical(subjects_participants, regdir, f2s, template = "~/GitHub/mriPipeline/templates/waxholm/WHS_SD_rat_T2star_v1.01_downsample3.nii.gz", f_file_format = "~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_SE_EPI/f_bru2nii/", s_file_format = "~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_T2_TurboRARE/s_bru2nii/", ): """Warp a functional image based on the functional-to-structural and the structural-to-template registrations. Currently this approach is failing because the functiona-to-structural registration pushes the brain stem too far down. This may be """ template = os.path.expanduser(template) for subject_participant in subjects_participants: func_image_dir = os.path.expanduser(f_file_format.format(**subject_participant)) struct_image_dir = os.path.expanduser(s_file_format.format(**subject_participant)) try: for myfile in os.listdir(func_image_dir): if myfile.endswith((".nii.gz", ".nii")): func_image = os.path.join(func_image_dir,myfile) for myfile in os.listdir(struct_image_dir): if myfile.endswith((".nii.gz", ".nii")): struct_image = os.path.join(struct_image_dir,myfile) except FileNotFoundError: pass else: #struct n4 = ants.N4BiasFieldCorrection() n4.inputs.dimension = 3 n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. n4.inputs.bspline_fitting_distance = 100 n4.inputs.shrink_factor = 2 n4.inputs.n_iterations = [200,200,200,200] n4.inputs.convergence_threshold = 1e-11 n4.inputs.output_image = '{}/ss_n4_{}_ofM{}.nii.gz'.format(regdir,participant,i) n4_res = n4.run() _n4 = ants.N4BiasFieldCorrection() _n4.inputs.dimension = 3 _n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. _n4.inputs.bspline_fitting_distance = 95 _n4.inputs.shrink_factor = 2 _n4.inputs.n_iterations = [500,500,500,500] _n4.inputs.convergence_threshold = 1e-14 _n4.inputs.output_image = '{}/ss__n4_{}_ofM{}.nii.gz'.format(regdir,participant,i) _n4_res = _n4.run() #we do this on a separate bias-corrected image to remove hyperintensities which we have to create in order to prevent brain regions being caught by the negative threshold struct_cutoff = ImageMaths() struct_cutoff.inputs.op_string = "-thrP 20 -uthrp 98" struct_cutoff.inputs.in_file = _n4_res.outputs.output_image struct_cutoff_res = struct_cutoff.run() struct_BET = BET() struct_BET.inputs.mask = True struct_BET.inputs.frac = 0.3 struct_BET.inputs.robust = True struct_BET.inputs.in_file = struct_cutoff_res.outputs.out_file struct_BET_res = struct_BET.run() struct_mask = ApplyMask() struct_mask.inputs.in_file = n4_res.outputs.output_image struct_mask.inputs.mask_file = struct_BET_res.outputs.mask_file struct_mask_res = struct_mask.run() struct_registration = ants.Registration() struct_registration.inputs.fixed_image = template struct_registration.inputs.output_transform_prefix = "output_" struct_registration.inputs.transforms = ['Affine', 'SyN'] ## struct_registration.inputs.transform_parameters = [(1.0,), (1.0, 3.0, 5.0)] ## struct_registration.inputs.number_of_iterations = [[2000, 1000, 500], [100, 100, 100]] # struct_registration.inputs.dimension = 3 struct_registration.inputs.write_composite_transform = True struct_registration.inputs.collapse_output_transforms = True struct_registration.inputs.initial_moving_transform_com = True # Tested on Affine transform: CC takes too long; Demons does not tilt, but moves the slices too far caudally; GC tilts too much on struct_registration.inputs.metric = ['MeanSquares', 'Mattes'] struct_registration.inputs.metric_weight = [1, 1] struct_registration.inputs.radius_or_number_of_bins = [16, 32] # struct_registration.inputs.sampling_strategy = ['Random', None] struct_registration.inputs.sampling_percentage = [0.3, 0.3] struct_registration.inputs.convergence_threshold = [1.e-11, 1.e-8] # struct_registration.inputs.convergence_window_size = [20, 20] struct_registration.inputs.smoothing_sigmas = [[4, 2, 1], [4, 2, 1]] struct_registration.inputs.sigma_units = ['vox', 'vox'] struct_registration.inputs.shrink_factors = [[3, 2, 1],[3, 2, 1]] struct_registration.inputs.use_estimate_learning_rate_once = [True, True] # if the fixed_image is not acquired similarly to the moving_image (e.g. RARE to histological (e.g. AMBMC)) this should be False struct_registration.inputs.use_histogram_matching = [False, False] struct_registration.inputs.winsorize_lower_quantile = 0.005 struct_registration.inputs.winsorize_upper_quantile = 0.98 struct_registration.inputs.args = '--float' struct_registration.inputs.num_threads = 6 struct_registration.inputs.moving_image = struct_mask_res.outputs.out_file struct_registration.inputs.output_warped_image = '{}/s_{}_ofM{}.nii.gz'.format(regdir,participant,i) struct_registration_res = struct_registration.run() #func func_n4 = ants.N4BiasFieldCorrection() func_n4.inputs.dimension = 3 func_n4.inputs.input_image = func_image func_n4.inputs.bspline_fitting_distance = 100 func_n4.inputs.shrink_factor = 2 func_n4.inputs.n_iterations = [200,200,200,200] func_n4.inputs.convergence_threshold = 1e-11 func_n4.inputs.output_image = '{}/f_n4_{}_ofM{}.nii.gz'.format(regdir,participant,i) func_n4_res = func_n4.run() func_registration = ants.Registration() func_registration.inputs.fixed_image = n4_res.outputs.output_image func_registration.inputs.output_transform_prefix = "func_" func_registration.inputs.transforms = [f2s] func_registration.inputs.transform_parameters = [(0.1,)] func_registration.inputs.number_of_iterations = [[40, 20, 10]] func_registration.inputs.dimension = 3 func_registration.inputs.write_composite_transform = True func_registration.inputs.collapse_output_transforms = True func_registration.inputs.initial_moving_transform_com = True func_registration.inputs.metric = ['MeanSquares'] func_registration.inputs.metric_weight = [1] func_registration.inputs.radius_or_number_of_bins = [16] func_registration.inputs.sampling_strategy = ["Regular"] func_registration.inputs.sampling_percentage = [0.3] func_registration.inputs.convergence_threshold = [1.e-2] func_registration.inputs.convergence_window_size = [8] func_registration.inputs.smoothing_sigmas = [[4, 2, 1]] # [1,0.5,0] func_registration.inputs.sigma_units = ['vox'] func_registration.inputs.shrink_factors = [[3, 2, 1]] func_registration.inputs.use_estimate_learning_rate_once = [True] func_registration.inputs.use_histogram_matching = [False] func_registration.inputs.winsorize_lower_quantile = 0.005 func_registration.inputs.winsorize_upper_quantile = 0.995 func_registration.inputs.args = '--float' func_registration.inputs.num_threads = 6 func_registration.inputs.moving_image = func_n4_res.outputs.output_image func_registration.inputs.output_warped_image = '{}/f_{}_ofM{}.nii.gz'.format(regdir,participant,i) func_registration_res = func_registration.run() warp = ants.ApplyTransforms() warp.inputs.reference_image = template warp.inputs.input_image_type = 3 warp.inputs.interpolation = 'Linear' warp.inputs.invert_transform_flags = [False, False] warp.inputs.terminal_output = 'file' warp.inputs.output_image = '{}/{}_ofM{}.nii.gz'.format(regdir,participant,i) warp.num_threads = 6 warp.inputs.input_image = func_image warp.inputs.transforms = [func_registration_res.outputs.composite_transform, struct_registration_res.outputs.composite_transform] warp.run()
#from mriqc.motion import plot_frame_displacement # #test_workflow = Workflow(name="qc_workflow") # #test_workflow.base_dir = work_dir #from nipype import SelectFiles #templates = dict(T1="*_{subject_id}_*/T1w_MPR_BIC_v1/*00001.nii*") #file_list = Node(SelectFiles(templates), name = "EPI_and_T1_File_Selection") #file_list.inputs.base_directory = data_dir #file_list.iterables = [("subject_id", subject_list), ("p_dir", ["LR", "RL"])] from nipype.interfaces.fsl import BET mask_gen = BET() mask_gen.inputs.in_file = "/Users/craigmoodie/Documents/AA_Connectivity_Psychosis/AA_Connectivity_Analysis/10_Subject_ICA_test/Subject_1/T1w_MPR_BIC_v1/S1543TWL_P126317_1_19_00001.nii" mask_gen.inputs.mask = True mask_gen.inputs.out_file = "bet_mean" mask_gen.run() #mask_gen = MapNode(BET(), name="Mask_Generation", iterfield="in_file") #from spatial_qc import summary_mask, ghost_all, ghost_direction, ghost_mask, fwhm, artifacts, efc, cnr, snr # # #summary_mask()
def create_workflow(subject_id, outdir, file_url): """Create a workflow for a single participant""" sink_directory = os.path.join(outdir, subject_id) wf = Workflow(name=subject_id) getter = Node(Function(input_names=['url'], output_names=['localfile'], function=download_file), name="download_url") getter.inputs.url = file_url orienter = Node(Reorient2Std(), name='reorient_brain') wf.connect(getter, 'localfile', orienter, 'in_file') better = Node(BET(), name='extract_brain') wf.connect(orienter, 'out_file', better, 'in_file') faster = Node(FAST(), name='segment_brain') wf.connect(better, 'out_file', faster, 'in_files') firster = Node(FIRST(), name='parcellate_brain') structures = [ 'L_Hipp', 'R_Hipp', 'L_Accu', 'R_Accu', 'L_Amyg', 'R_Amyg', 'L_Caud', 'R_Caud', 'L_Pall', 'R_Pall', 'L_Puta', 'R_Puta', 'L_Thal', 'R_Thal' ] firster.inputs.list_of_specific_structures = structures wf.connect(orienter, 'out_file', firster, 'in_file') fslstatser = MapNode(ImageStats(), iterfield=['op_string'], name="compute_segment_stats") fslstatser.inputs.op_string = [ '-l {thr1} -u {thr2} -v'.format(thr1=val + 0.5, thr2=val + 1.5) for val in range(3) ] wf.connect(faster, 'partial_volume_map', fslstatser, 'in_file') jsonfiler = Node(Function( input_names=['stats', 'seg_file', 'structure_map', 'struct_file'], output_names=['out_file'], function=toJSON), name='save_json') structure_map = [('Background', 0), ('Left-Thalamus-Proper', 10), ('Left-Caudate', 11), ('Left-Putamen', 12), ('Left-Pallidum', 13), ('Left-Hippocampus', 17), ('Left-Amygdala', 18), ('Left-Accumbens-area', 26), ('Right-Thalamus-Proper', 49), ('Right-Caudate', 50), ('Right-Putamen', 51), ('Right-Pallidum', 52), ('Right-Hippocampus', 53), ('Right-Amygdala', 54), ('Right-Accumbens-area', 58)] jsonfiler.inputs.structure_map = structure_map wf.connect(fslstatser, 'out_stat', jsonfiler, 'stats') wf.connect(firster, 'segmentation_file', jsonfiler, 'seg_file') sinker = Node(DataSink(), name='store_results') sinker.inputs.base_directory = sink_directory wf.connect(better, 'out_file', sinker, 'brain') wf.connect(faster, 'bias_field', sinker, 'segs.@bias_field') wf.connect(faster, 'partial_volume_files', sinker, 'segs.@partial_files') wf.connect(faster, 'partial_volume_map', sinker, 'segs.@partial_map') wf.connect(faster, 'probability_maps', sinker, 'segs.@prob_maps') wf.connect(faster, 'restored_image', sinker, 'segs.@restored') wf.connect(faster, 'tissue_class_files', sinker, 'segs.@tissue_files') wf.connect(faster, 'tissue_class_map', sinker, 'segs.@tissue_map') wf.connect(firster, 'bvars', sinker, 'parcels.@bvars') wf.connect(firster, 'original_segmentations', sinker, 'parcels.@origsegs') wf.connect(firster, 'segmentation_file', sinker, 'parcels.@segfile') wf.connect(firster, 'vtk_surfaces', sinker, 'parcels.@vtk') wf.connect(jsonfiler, 'out_file', sinker, '@stats') return wf
import os from os.path import abspath from datetime import datetime from IPython.display import Image import pydot from nipype import Workflow, Node, MapNode, Function, config from nipype.interfaces.fsl import TOPUP, ApplyTOPUP, BET, ExtractROI, Eddy, FLIRT, FUGUE from nipype.interfaces.fsl.maths import MathsCommand import nipype.interfaces.utility as util import nipype.interfaces.mrtrix3 as mrt #Requirements for the workflow to run smoothly: All files as in NIfTI-format and named according to the following standard: #Images are from the tonotopy DKI sequences on the 7T Philips Achieva scanner in Lund. It should work with any DKI sequence and possibly also a standard DTI but the setting for B0-corrections, epi-distortion corrections and eddy current corrections will be wrong. #DKI file has a base name shared with bvec and bval in FSL format. E.g. "DKI.nii.gz" "DKI.bvec" and "DKI.bval". #There is one b0-volume with reversed (P->A) phase encoding called DKIbase+_revenc. E.g. "DKI_revenc.nii.gz". #Philips B0-map magnitude and phase offset (in Hz) images. #One input file for topup describing the images as specified by topup. #Set nbrOfThreads to number of available CPU threads to run the analyses. ### Need to make better revenc for the 15 version if we choose to use it (i.e. same TE and TR) #Set to relevant directory/parameters datadir=os.path.abspath("/Users/ling-men/Documents/MRData/testDKI") rawDKI_base='DKI_15' B0map_base = 'B0map' nbrOfThreads=6 print_graph = True acqparam_file = os.path.join(datadir,'acqparams.txt') index_file = os.path.join(datadir,'index.txt') #### #config.enable_debug_mode() DKI_nii=os.path.join(datadir, rawDKI_base+'.nii.gz') DKI_bval=os.path.join(datadir, rawDKI_base+'.bval')
delimiter=','), name='extract_confounds_global_signal') signal_extraction = Node(SignalExtraction( time_series_out_file='time_series.csv', correlation_matrix_out_file='correlation_matrix.png', atlas_identifier='cort-maxprob-thr25-2mm', tr=TR, plot=True), name='signal_extraction') art_remotion = Node(ArtifacRemotion(out_file='fmri_art_removed.nii'), name='artifact_remotion') # BET - Skullstrip anatomical anf funtional images bet_t1 = Node(BET(frac=0.55, robust=True, mask=True, output_type='NIFTI_GZ'), name="bet_t1") bet_fmri = Node(BET(frac=0.6, functional=True, output_type='NIFTI_GZ'), name="bet_fmri") # FAST - Image Segmentation segmentation = Node(FAST(output_type='NIFTI'), name="segmentation") # Normalize - normalizes functional and structural images to the MNI template normalize_fmri = Node(Normalize12(jobtype='estwrite', tpm=template, write_voxel_sizes=[2, 2, 2], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_fmri")
delimiter=','), name='extract_confounds_global_signal') signal_extraction = Node(SignalExtraction( time_series_out_file='time_series.csv', correlation_matrix_out_file='correlation_matrix.png', atlas_identifier='cort-maxprob-thr25-2mm', tr=TR, plot=True), name='signal_extraction') art_remotion = Node(ArtifacRemotion(out_file='fmri_art_removed.nii'), name='artifact_remotion') # BET - Skullstrip anatomical anf funtional images bet_t1 = Node(BET(frac=0.5, robust=True, mask=True, output_type='NIFTI_GZ'), name="bet_t1") # FAST - Image Segmentation segmentation = Node(FAST(output_type='NIFTI'), name="segmentation") # Normalize - normalizes functional and structural images to the MNI template normalize_fmri = Node(Normalize12(jobtype='estwrite', tpm=template, write_voxel_sizes=[2, 2, 2], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_fmri") gunzip = Node(Gunzip(), name="gunzip")
def __init__(self, parent, dir_dic, bids): super().__init__(parent, dir_dic, bids) # Create interfaces ============================================================================================ # BET T1w_BET = Node(BET(), name="T1w_BET") T1w_BET.btn_string = 'T1w Brain Extraction' self.interfaces.append(T1w_BET) T1w_gad_BET = Node(BET(), name="T1w_gad_BET") T1w_gad_BET.btn_string = 'T1w Gadolinium Enhanced Brain Extraction' self.interfaces.append(T1w_gad_BET) T2w_dbs_BET = Node(BET(), name="T2w_dbs_BET") T2w_dbs_BET.btn_string = 'T2w DBS Acquisition Brain Extraction' self.interfaces.append(T2w_dbs_BET) dwi_BET = Node(BET(), name="dwi_BET") dwi_BET.btn_string = 'dwi Brain Extraction' self.interfaces.append(dwi_BET) # BFC T1w_BFC = Node(N4BiasFieldCorrection(), name="T1w_BFC") T1w_BFC.btn_string = 'T1w Bias Field Correction' self.interfaces.append(T1w_BFC) # Split dwi_ROI_b0 = Node(ExtractROI(), name="dwi_ROI_b0") dwi_ROI_b0.btn_string = 'dwi Extract b0' self.interfaces.append(dwi_ROI_b0) # Eddy current correction dwi_Eddy = Node(Eddy(), name="dwi_Eddy") dwi_Eddy.btn_string = 'dwi Eddy Current Correction' self.interfaces.append(dwi_Eddy) # Distortion correction # as this section is script/comment heavy it was put into a function self.distortion_correction_workflow() # Data output (i.e. sink) ====================================================================================== self.sink = Node(DataSink(), name="sink") self.sink.btn_string = 'data sink' self.sink.inputs.base_directory = self.dir_dic['data_dir'] self.jsink = Node(JSONFileSink(), name="jsink") self.jsink.btn_string = 'json sink' self.jsink.inputs.base_directory = self.dir_dic['data_dir'] # Initialize workflow ========================================================================================== self.wf = Workflow(name='pre_processing') # T1w BET to ants N4BiasFieldCorrection self.wf.connect([(self.return_interface("T1w_BET"), self.return_interface("T1w_BFC"), [("out_file", "input_image")])]) self.wf.connect([(self.return_interface("T1w_BET"), self.return_interface("T1w_BFC"), [("mask_file", "mask_image")])]) # Eddy self.wf.connect([(self.return_interface("dwi_BET"), self.return_interface("dwi_Eddy"), [("out_file", "in_file")])]) self.wf.connect([(self.return_interface("dwi_BET"), self.return_interface("dwi_Eddy"), [("mask_file", "in_mask")])]) # ROI b0 self.wf.connect([(self.return_interface("dwi_Eddy"), self.return_interface("dwi_ROI_b0"), [("out_corrected", "in_file")])]) # Distortion Correction: # b0_T1_Reg: # -i: moving image # -r: T1 # -x: T1 mask self.wf.connect([(self.return_interface("dwi_ROI_b0"), self.return_interface("b0_T1w_Reg"), [("roi_file", "moving_image")])]) self.wf.connect([(self.return_interface("T1w_BFC"), self.return_interface("b0_T1w_Reg"), [("output_image", "fixed_image")])]) # test remove as doesn't seem useful (see self.distortion_correction_workflow()) and causes a crash when added # self.wf.connect([(self.return_interface("T1w_BET"), self.return_interface("b0_T1w_Reg"), # [("mask_file", "fixed_image_mask")])]) # dwi_T1_Tran: # -i: Eddy corrected image # -r: Eddy corrected b0 # -t: transforms self.wf.connect([(self.return_interface("dwi_Eddy"), self.return_interface("dwi_T1w_Tran"), [("out_corrected", "input_image")])]) self.wf.connect([(self.return_interface("dwi_ROI_b0"), self.return_interface("dwi_T1w_Tran"), [("roi_file", "reference_image")])]) self.wf.connect([(self.return_interface("b0_T1w_Reg"), self.return_interface("dwi_T1w_Tran"), [("composite_transform", "transforms")])]) # BaseInterface generates a dict mapping button strings to the workflow nodes # self.map_workflow() graph_file = self.wf.write_graph("pre_processing", graph2use='flat') self.graph_file = graph_file.replace("pre_processing.png", "pre_processing_detailed.png") self.init_settings() self.init_ui()
def canonical( subjects_participants, regdir, f2s, template="~/GitHub/mriPipeline/templates/waxholm/WHS_SD_rat_T2star_v1.01_downsample3.nii.gz", f_file_format="~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_SE_EPI/f_bru2nii/", s_file_format="~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_T2_TurboRARE/s_bru2nii/", ): """Warp a functional image based on the functional-to-structural and the structural-to-template registrations. Currently this approach is failing because the functiona-to-structural registration pushes the brain stem too far down. This may be """ template = os.path.expanduser(template) for subject_participant in subjects_participants: func_image_dir = os.path.expanduser( f_file_format.format(**subject_participant)) struct_image_dir = os.path.expanduser( s_file_format.format(**subject_participant)) try: for myfile in os.listdir(func_image_dir): if myfile.endswith((".nii.gz", ".nii")): func_image = os.path.join(func_image_dir, myfile) for myfile in os.listdir(struct_image_dir): if myfile.endswith((".nii.gz", ".nii")): struct_image = os.path.join(struct_image_dir, myfile) except FileNotFoundError: pass else: #struct n4 = ants.N4BiasFieldCorrection() n4.inputs.dimension = 3 n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. n4.inputs.bspline_fitting_distance = 100 n4.inputs.shrink_factor = 2 n4.inputs.n_iterations = [200, 200, 200, 200] n4.inputs.convergence_threshold = 1e-11 n4.inputs.output_image = '{}/ss_n4_{}_ofM{}.nii.gz'.format( regdir, participant, i) n4_res = n4.run() _n4 = ants.N4BiasFieldCorrection() _n4.inputs.dimension = 3 _n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. _n4.inputs.bspline_fitting_distance = 95 _n4.inputs.shrink_factor = 2 _n4.inputs.n_iterations = [500, 500, 500, 500] _n4.inputs.convergence_threshold = 1e-14 _n4.inputs.output_image = '{}/ss__n4_{}_ofM{}.nii.gz'.format( regdir, participant, i) _n4_res = _n4.run() #we do this on a separate bias-corrected image to remove hyperintensities which we have to create in order to prevent brain regions being caught by the negative threshold struct_cutoff = ImageMaths() struct_cutoff.inputs.op_string = "-thrP 20 -uthrp 98" struct_cutoff.inputs.in_file = _n4_res.outputs.output_image struct_cutoff_res = struct_cutoff.run() struct_BET = BET() struct_BET.inputs.mask = True struct_BET.inputs.frac = 0.3 struct_BET.inputs.robust = True struct_BET.inputs.in_file = struct_cutoff_res.outputs.out_file struct_BET_res = struct_BET.run() struct_mask = ApplyMask() struct_mask.inputs.in_file = n4_res.outputs.output_image struct_mask.inputs.mask_file = struct_BET_res.outputs.mask_file struct_mask_res = struct_mask.run() struct_registration = ants.Registration() struct_registration.inputs.fixed_image = template struct_registration.inputs.output_transform_prefix = "output_" struct_registration.inputs.transforms = ['Affine', 'SyN'] ## struct_registration.inputs.transform_parameters = [(1.0, ), (1.0, 3.0, 5.0) ] ## struct_registration.inputs.number_of_iterations = [[ 2000, 1000, 500 ], [100, 100, 100]] # struct_registration.inputs.dimension = 3 struct_registration.inputs.write_composite_transform = True struct_registration.inputs.collapse_output_transforms = True struct_registration.inputs.initial_moving_transform_com = True # Tested on Affine transform: CC takes too long; Demons does not tilt, but moves the slices too far caudally; GC tilts too much on struct_registration.inputs.metric = ['MeanSquares', 'Mattes'] struct_registration.inputs.metric_weight = [1, 1] struct_registration.inputs.radius_or_number_of_bins = [16, 32] # struct_registration.inputs.sampling_strategy = ['Random', None] struct_registration.inputs.sampling_percentage = [0.3, 0.3] struct_registration.inputs.convergence_threshold = [1.e-11, 1.e-8] # struct_registration.inputs.convergence_window_size = [20, 20] struct_registration.inputs.smoothing_sigmas = [[4, 2, 1], [4, 2, 1]] struct_registration.inputs.sigma_units = ['vox', 'vox'] struct_registration.inputs.shrink_factors = [[3, 2, 1], [3, 2, 1]] struct_registration.inputs.use_estimate_learning_rate_once = [ True, True ] # if the fixed_image is not acquired similarly to the moving_image (e.g. RARE to histological (e.g. AMBMC)) this should be False struct_registration.inputs.use_histogram_matching = [False, False] struct_registration.inputs.winsorize_lower_quantile = 0.005 struct_registration.inputs.winsorize_upper_quantile = 0.98 struct_registration.inputs.args = '--float' struct_registration.inputs.num_threads = 6 struct_registration.inputs.moving_image = struct_mask_res.outputs.out_file struct_registration.inputs.output_warped_image = '{}/s_{}_ofM{}.nii.gz'.format( regdir, participant, i) struct_registration_res = struct_registration.run() #func func_n4 = ants.N4BiasFieldCorrection() func_n4.inputs.dimension = 3 func_n4.inputs.input_image = func_image func_n4.inputs.bspline_fitting_distance = 100 func_n4.inputs.shrink_factor = 2 func_n4.inputs.n_iterations = [200, 200, 200, 200] func_n4.inputs.convergence_threshold = 1e-11 func_n4.inputs.output_image = '{}/f_n4_{}_ofM{}.nii.gz'.format( regdir, participant, i) func_n4_res = func_n4.run() func_registration = ants.Registration() func_registration.inputs.fixed_image = n4_res.outputs.output_image func_registration.inputs.output_transform_prefix = "func_" func_registration.inputs.transforms = [f2s] func_registration.inputs.transform_parameters = [(0.1, )] func_registration.inputs.number_of_iterations = [[40, 20, 10]] func_registration.inputs.dimension = 3 func_registration.inputs.write_composite_transform = True func_registration.inputs.collapse_output_transforms = True func_registration.inputs.initial_moving_transform_com = True func_registration.inputs.metric = ['MeanSquares'] func_registration.inputs.metric_weight = [1] func_registration.inputs.radius_or_number_of_bins = [16] func_registration.inputs.sampling_strategy = ["Regular"] func_registration.inputs.sampling_percentage = [0.3] func_registration.inputs.convergence_threshold = [1.e-2] func_registration.inputs.convergence_window_size = [8] func_registration.inputs.smoothing_sigmas = [[4, 2, 1]] # [1,0.5,0] func_registration.inputs.sigma_units = ['vox'] func_registration.inputs.shrink_factors = [[3, 2, 1]] func_registration.inputs.use_estimate_learning_rate_once = [True] func_registration.inputs.use_histogram_matching = [False] func_registration.inputs.winsorize_lower_quantile = 0.005 func_registration.inputs.winsorize_upper_quantile = 0.995 func_registration.inputs.args = '--float' func_registration.inputs.num_threads = 6 func_registration.inputs.moving_image = func_n4_res.outputs.output_image func_registration.inputs.output_warped_image = '{}/f_{}_ofM{}.nii.gz'.format( regdir, participant, i) func_registration_res = func_registration.run() warp = ants.ApplyTransforms() warp.inputs.reference_image = template warp.inputs.input_image_type = 3 warp.inputs.interpolation = 'Linear' warp.inputs.invert_transform_flags = [False, False] warp.inputs.terminal_output = 'file' warp.inputs.output_image = '{}/{}_ofM{}.nii.gz'.format( regdir, participant, i) warp.num_threads = 6 warp.inputs.input_image = func_image warp.inputs.transforms = [ func_registration_res.outputs.composite_transform, struct_registration_res.outputs.composite_transform ] warp.run()
def structural_to_functional_per_participant_test( subjects_sessions, template="~/GitHub/mriPipeline/templates/waxholm/new/WHS_SD_masked.nii.gz", f_file_format="~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_SE_EPI/f_bru2nii/", s_file_format="~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_T2_TurboRARE/s_bru2nii/", num_threads=3, ): template = os.path.expanduser(template) for subject_session in subjects_sessions: func_image_dir = os.path.expanduser( f_file_format.format(**subject_session)) struct_image_dir = os.path.expanduser( s_file_format.format(**subject_session)) try: for myfile in os.listdir(func_image_dir): if myfile.endswith((".nii.gz", ".nii")): func_image = os.path.join(func_image_dir, myfile) for myfile in os.listdir(struct_image_dir): if myfile.endswith((".nii.gz", ".nii")): struct_image = os.path.join(struct_image_dir, myfile) except FileNotFoundError: pass else: n4 = ants.N4BiasFieldCorrection() n4.inputs.dimension = 3 n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. n4.inputs.bspline_fitting_distance = 100 n4.inputs.shrink_factor = 2 n4.inputs.n_iterations = [200, 200, 200, 200] n4.inputs.convergence_threshold = 1e-11 n4.inputs.output_image = '{}_{}_1_biasCorrection_forRegistration.nii.gz'.format( *subject_session.values()) n4_res = n4.run() _n4 = ants.N4BiasFieldCorrection() _n4.inputs.dimension = 3 _n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. _n4.inputs.bspline_fitting_distance = 95 _n4.inputs.shrink_factor = 2 _n4.inputs.n_iterations = [500, 500, 500, 500] _n4.inputs.convergence_threshold = 1e-14 _n4.inputs.output_image = '{}_{}_1_biasCorrection_forMasking.nii.gz'.format( *subject_session.values()) _n4_res = _n4.run() #we do this on a separate bias-corrected image to remove hyperintensities which we have to create in order to prevent brain regions being caught by the negative threshold struct_cutoff = ImageMaths() struct_cutoff.inputs.op_string = "-thrP 20 -uthrp 98" struct_cutoff.inputs.in_file = _n4_res.outputs.output_image struct_cutoff_res = struct_cutoff.run() struct_BET = BET() struct_BET.inputs.mask = True struct_BET.inputs.frac = 0.3 struct_BET.inputs.robust = True struct_BET.inputs.in_file = struct_cutoff_res.outputs.out_file struct_BET.inputs.out_file = '{}_{}_2_brainExtraction.nii.gz'.format( *subject_session.values()) struct_BET_res = struct_BET.run() # we need/can not apply a fill, because the "holes" if any, will be at the rostral edge (touching it, and thus not counting as holes) struct_mask = ApplyMask() struct_mask.inputs.in_file = n4_res.outputs.output_image struct_mask.inputs.mask_file = struct_BET_res.outputs.mask_file struct_mask.inputs.out_file = '{}_{}_3_brainMasked.nii.gz'.format( *subject_session.values()) struct_mask_res = struct_mask.run() struct_registration = ants.Registration() struct_registration.inputs.fixed_image = template struct_registration.inputs.output_transform_prefix = "output_" struct_registration.inputs.transforms = ['Affine', 'SyN'] ## struct_registration.inputs.transform_parameters = [(1.0, ), (1.0, 3.0, 5.0) ] ## struct_registration.inputs.number_of_iterations = [[ 2000, 1000, 500 ], [100, 100, 100]] # struct_registration.inputs.dimension = 3 struct_registration.inputs.write_composite_transform = True struct_registration.inputs.collapse_output_transforms = True struct_registration.inputs.initial_moving_transform_com = True # Tested on Affine transform: CC takes too long; Demons does not tilt, but moves the slices too far caudally; GC tilts too much on struct_registration.inputs.metric = ['MeanSquares', 'Mattes'] struct_registration.inputs.metric_weight = [1, 1] struct_registration.inputs.radius_or_number_of_bins = [16, 32] # struct_registration.inputs.sampling_strategy = ['Random', None] struct_registration.inputs.sampling_percentage = [0.3, 0.3] struct_registration.inputs.convergence_threshold = [1.e-11, 1.e-8] # struct_registration.inputs.convergence_window_size = [20, 20] struct_registration.inputs.smoothing_sigmas = [[4, 2, 1], [4, 2, 1]] struct_registration.inputs.sigma_units = ['vox', 'vox'] struct_registration.inputs.shrink_factors = [[3, 2, 1], [3, 2, 1]] struct_registration.inputs.use_estimate_learning_rate_once = [ True, True ] # if the fixed_image is not acquired similarly to the moving_image (e.g. RARE to histological (e.g. AMBMC)) this should be False struct_registration.inputs.use_histogram_matching = [False, False] struct_registration.inputs.winsorize_lower_quantile = 0.005 struct_registration.inputs.winsorize_upper_quantile = 0.98 struct_registration.inputs.args = '--float' struct_registration.inputs.num_threads = num_threads struct_registration.inputs.moving_image = struct_mask_res.outputs.out_file struct_registration.inputs.output_warped_image = '{}_{}_4_structuralRegistration.nii.gz'.format( *subject_session.values()) struct_registration_res = struct_registration.run() warp = ants.ApplyTransforms() warp.inputs.reference_image = template warp.inputs.input_image_type = 3 warp.inputs.interpolation = 'Linear' warp.inputs.invert_transform_flags = [False] warp.inputs.terminal_output = 'file' warp.inputs.output_image = '{}_{}_5_functionalWarp.nii.gz'.format( *subject_session.values()) warp.num_threads = num_threads warp.inputs.input_image = func_image warp.inputs.transforms = struct_registration_res.outputs.composite_transform warp.run()
def structural_to_functional_per_participant_test(subjects_sessions, template = "~/GitHub/mriPipeline/templates/waxholm/new/WHS_SD_masked.nii.gz", f_file_format = "~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_SE_EPI/f_bru2nii/", s_file_format = "~/GitHub/mripipeline/base/preprocessing/generic_work/_subject_session_{subject}.{session}/_scan_type_T2_TurboRARE/s_bru2nii/", num_threads = 3, ): template = os.path.expanduser(template) for subject_session in subjects_sessions: func_image_dir = os.path.expanduser(f_file_format.format(**subject_session)) struct_image_dir = os.path.expanduser(s_file_format.format(**subject_session)) try: for myfile in os.listdir(func_image_dir): if myfile.endswith((".nii.gz", ".nii")): func_image = os.path.join(func_image_dir,myfile) for myfile in os.listdir(struct_image_dir): if myfile.endswith((".nii.gz", ".nii")): struct_image = os.path.join(struct_image_dir,myfile) except FileNotFoundError: pass else: n4 = ants.N4BiasFieldCorrection() n4.inputs.dimension = 3 n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. n4.inputs.bspline_fitting_distance = 100 n4.inputs.shrink_factor = 2 n4.inputs.n_iterations = [200,200,200,200] n4.inputs.convergence_threshold = 1e-11 n4.inputs.output_image = '{}_{}_1_biasCorrection_forRegistration.nii.gz'.format(*subject_session.values()) n4_res = n4.run() _n4 = ants.N4BiasFieldCorrection() _n4.inputs.dimension = 3 _n4.inputs.input_image = struct_image # correction bias is introduced (along the z-axis) if the following value is set to under 85. This is likely contingent on resolution. _n4.inputs.bspline_fitting_distance = 95 _n4.inputs.shrink_factor = 2 _n4.inputs.n_iterations = [500,500,500,500] _n4.inputs.convergence_threshold = 1e-14 _n4.inputs.output_image = '{}_{}_1_biasCorrection_forMasking.nii.gz'.format(*subject_session.values()) _n4_res = _n4.run() #we do this on a separate bias-corrected image to remove hyperintensities which we have to create in order to prevent brain regions being caught by the negative threshold struct_cutoff = ImageMaths() struct_cutoff.inputs.op_string = "-thrP 20 -uthrp 98" struct_cutoff.inputs.in_file = _n4_res.outputs.output_image struct_cutoff_res = struct_cutoff.run() struct_BET = BET() struct_BET.inputs.mask = True struct_BET.inputs.frac = 0.3 struct_BET.inputs.robust = True struct_BET.inputs.in_file = struct_cutoff_res.outputs.out_file struct_BET.inputs.out_file = '{}_{}_2_brainExtraction.nii.gz'.format(*subject_session.values()) struct_BET_res = struct_BET.run() # we need/can not apply a fill, because the "holes" if any, will be at the rostral edge (touching it, and thus not counting as holes) struct_mask = ApplyMask() struct_mask.inputs.in_file = n4_res.outputs.output_image struct_mask.inputs.mask_file = struct_BET_res.outputs.mask_file struct_mask.inputs.out_file = '{}_{}_3_brainMasked.nii.gz'.format(*subject_session.values()) struct_mask_res = struct_mask.run() struct_registration = ants.Registration() struct_registration.inputs.fixed_image = template struct_registration.inputs.output_transform_prefix = "output_" struct_registration.inputs.transforms = ['Affine', 'SyN'] ## struct_registration.inputs.transform_parameters = [(1.0,), (1.0, 3.0, 5.0)] ## struct_registration.inputs.number_of_iterations = [[2000, 1000, 500], [100, 100, 100]] # struct_registration.inputs.dimension = 3 struct_registration.inputs.write_composite_transform = True struct_registration.inputs.collapse_output_transforms = True struct_registration.inputs.initial_moving_transform_com = True # Tested on Affine transform: CC takes too long; Demons does not tilt, but moves the slices too far caudally; GC tilts too much on struct_registration.inputs.metric = ['MeanSquares', 'Mattes'] struct_registration.inputs.metric_weight = [1, 1] struct_registration.inputs.radius_or_number_of_bins = [16, 32] # struct_registration.inputs.sampling_strategy = ['Random', None] struct_registration.inputs.sampling_percentage = [0.3, 0.3] struct_registration.inputs.convergence_threshold = [1.e-11, 1.e-8] # struct_registration.inputs.convergence_window_size = [20, 20] struct_registration.inputs.smoothing_sigmas = [[4, 2, 1], [4, 2, 1]] struct_registration.inputs.sigma_units = ['vox', 'vox'] struct_registration.inputs.shrink_factors = [[3, 2, 1],[3, 2, 1]] struct_registration.inputs.use_estimate_learning_rate_once = [True, True] # if the fixed_image is not acquired similarly to the moving_image (e.g. RARE to histological (e.g. AMBMC)) this should be False struct_registration.inputs.use_histogram_matching = [False, False] struct_registration.inputs.winsorize_lower_quantile = 0.005 struct_registration.inputs.winsorize_upper_quantile = 0.98 struct_registration.inputs.args = '--float' struct_registration.inputs.num_threads = num_threads struct_registration.inputs.moving_image = struct_mask_res.outputs.out_file struct_registration.inputs.output_warped_image = '{}_{}_4_structuralRegistration.nii.gz'.format(*subject_session.values()) struct_registration_res = struct_registration.run() warp = ants.ApplyTransforms() warp.inputs.reference_image = template warp.inputs.input_image_type = 3 warp.inputs.interpolation = 'Linear' warp.inputs.invert_transform_flags = [False] warp.inputs.terminal_output = 'file' warp.inputs.output_image = '{}_{}_5_functionalWarp.nii.gz'.format(*subject_session.values()) warp.num_threads = num_threads warp.inputs.input_image = func_image warp.inputs.transforms = struct_registration_res.outputs.composite_transform warp.run()
def main(paths, options_binary_string, ANAT, num_proc=7): json_path = paths[0] base_directory = paths[1] motion_correction_bet_directory = paths[2] parent_wf_directory = paths[3] # functional_connectivity_directory=paths[4] coreg_reg_directory = paths[5] atlas_resize_reg_directory = paths[6] subject_list = paths[7] datasink_name = paths[8] # fc_datasink_name=paths[9] atlasPath = paths[10] # brain_path=paths[11] # mask_path=paths[12] # atlas_path=paths[13] # tr_path=paths[14] # motion_params_path=paths[15] # func2std_mat_path=paths[16] # MNI3mm_path=paths[17] # demographics_file_path = paths[18] # phenotype_file_path = paths[19] data_directory = paths[20] number_of_subjects = len(subject_list) print("Working with ", number_of_subjects, " subjects.") # Create our own custom function - BIDSDataGrabber using a Function Interface. # In[858]: def get_nifti_filenames(subject_id, data_dir): # Remember that all the necesary imports need to be INSIDE the function for the Function Interface to work! from bids.grabbids import BIDSLayout layout = BIDSLayout(data_dir) run = 1 anat_file_path = [ f.filename for f in layout.get( subject=subject_id, type='T1w', extensions=['nii', 'nii.gz']) ] func_file_path = [ f.filename for f in layout.get(subject=subject_id, type='bold', run=run, extensions=['nii', 'nii.gz']) ] if len(anat_file_path) == 0: return None, func_file_path[0] # No Anatomical files present return anat_file_path[0], func_file_path[0] BIDSDataGrabber = Node(Function( function=get_nifti_filenames, input_names=['subject_id', 'data_dir'], output_names=['anat_file_path', 'func_file_path']), name='BIDSDataGrabber') # BIDSDataGrabber.iterables = [('subject_id',subject_list)] BIDSDataGrabber.inputs.data_dir = data_directory # ## Return TR def get_TR(in_file): from bids.grabbids import BIDSLayout data_directory = '/home1/varunk/data/ABIDE1/RawDataBIDs' layout = BIDSLayout(data_directory) metadata = layout.get_metadata(path=in_file) TR = metadata['RepetitionTime'] return TR # ---------------- Added new Node to return TR and other slice timing correction params------------------------------- def _getMetadata(in_file): from bids.grabbids import BIDSLayout import logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # create a file handler handler = logging.FileHandler('progress.log') # add the handlers to the logger logger.addHandler(handler) interleaved = True index_dir = False data_directory = '/home1/varunk/data/ABIDE1/RawDataBIDs' layout = BIDSLayout(data_directory) metadata = layout.get_metadata(path=in_file) print(metadata) logger.info('Extracting Meta Data of file: %s', in_file) try: tr = metadata['RepetitionTime'] except KeyError: print( 'Key RepetitionTime not found in task-rest_bold.json so using a default of 2.0 ' ) tr = 2 logger.error( 'Key RepetitionTime not found in task-rest_bold.json for file %s so using a default of 2.0 ', in_file) try: slice_order = metadata['SliceAcquisitionOrder'] except KeyError: print( 'Key SliceAcquisitionOrder not found in task-rest_bold.json so using a default of interleaved ascending ' ) logger.error( 'Key SliceAcquisitionOrder not found in task-rest_bold.json for file %s so using a default of interleaved ascending', in_file) return tr, index_dir, interleaved if slice_order.split(' ')[0] == 'Sequential': interleaved = False if slice_order.split(' ')[1] == 'Descending': index_dir = True return tr, index_dir, interleaved getMetadata = Node(Function( function=_getMetadata, input_names=['in_file'], output_names=['tr', 'index_dir', 'interleaved']), name='getMetadata') # ### Skipping 4 starting scans # Extract ROI for skipping first 4 scans of the functional data # > **Arguments:** # t_min: (corresponds to time dimension) Denotes the starting time of the inclusion # t_size: Denotes the number of scans to include # # The logic behind skipping 4 initial scans is to take scans after the subject has stabalized in the scanner. # In[863]: # ExtractROI - skip dummy scans extract = Node(ExtractROI(t_min=4, t_size=-1), output_type='NIFTI', name="extract") # ### Slice time correction # Created a Node that does slice time correction # > **Arguments**: # index_dir=False -> Slices were taken bottom to top i.e. in ascending order # interleaved=True means odd slices were acquired first and then even slices [or vice versa(Not sure)] slicetimer = Node(SliceTimer(output_type='NIFTI'), name="slicetimer") # ### Motion Correction # Motion correction is done using fsl's mcflirt. It alligns all the volumes of a functional scan to each other # MCFLIRT - motion correction mcflirt = Node(MCFLIRT(mean_vol=True, save_plots=True, output_type='NIFTI'), name="mcflirt") # Just a dummy node to transfer the output of Mcflirt to the next workflow. Needed if we didnt want to use the Mcflirt from_mcflirt = Node(IdentityInterface(fields=['in_file']), name="from_mcflirt") # ### Skull striping # I used fsl's BET # In[868]: skullStrip = Node(BET(mask=False, frac=0.3, robust=True), name='skullStrip') # # *Note*: Do not include special characters in ```name``` field above coz then wf.writegraph will cause issues # ## Resample # I needed to resample the anatomical file from 1mm to 3mm. Because registering a 1mm file was taking a huge amount of time. # # In[872]: # Resample - resample anatomy to 3x3x3 voxel resolution resample_mni = Node( Resample( voxel_size=(3, 3, 3), resample_mode='Cu', # cubic interpolation outputtype='NIFTI'), name="resample_mni") resample_anat = Node( Resample( voxel_size=(3, 3, 3), resample_mode='Cu', # cubic interpolation outputtype='NIFTI'), name="resample_anat") # In[873]: resample_atlas = Node( Resample( voxel_size=(3, 3, 3), resample_mode='NN', # cubic interpolation outputtype='NIFTI'), name="resample_atlas") resample_atlas.inputs.in_file = atlasPath # # Matrix operations # ### For concatenating the transformation matrices concat_xform = Node(ConvertXFM(concat_xfm=True), name='concat_xform') # Node to calculate the inverse of func2std matrix inv_mat = Node(ConvertXFM(invert_xfm=True), name='inv_mat') # ## Extracting the mean brain meanfunc = Node(interface=ImageMaths(op_string='-Tmean', suffix='_mean'), name='meanfunc') meanfuncmask = Node(interface=BET(mask=True, no_output=True, frac=0.3), name='meanfuncmask') # ## Apply Mask # Does BET (masking) on the whole func scan [Not using this, creates bug for join node] maskfunc = Node(interface=ImageMaths(suffix='_bet', op_string='-mas'), name='maskfunc') # Does BET (masking) on the mean func scan maskfunc4mean = Node(interface=ImageMaths(suffix='_bet', op_string='-mas'), name='maskfunc4mean') # ## Datasink # I needed to define the structure of what files are saved and where. # Create DataSink object dataSink = Node(DataSink(), name='datasink') # Name of the output folder dataSink.inputs.base_directory = opj(base_directory, datasink_name) # Define substitution strings so that the data is similar to BIDS substitutions = [ ('_subject_id_', 'sub-'), ('_resample_brain_flirt.nii_brain', ''), ('_roi_st_mcf_flirt.nii_brain_flirt', ''), ('task-rest_run-1_bold_roi_st_mcf.nii', 'motion_params'), ('T1w_resample_brain_flirt_sub-0050002_task-rest_run-1_bold_roi_st_mcf_mean_bet_flirt', 'fun2std') ] # Feed the substitution strings to the DataSink node dataSink.inputs.substitutions = substitutions # ### Apply Mask to functional data # Mean file of the motion corrected functional scan is sent to # skullStrip to get just the brain and the mask_image. # Mask_image is just a binary file (containing 1 where brain is present and 0 where it isn't). # After getting the mask_image form skullStrip, apply that mask to aligned # functional image to extract its brain and remove the skull # In[889]: # Function # in_file: The file on which you want to apply mask # in_file2 = mask_file: The mask you want to use. Make sure that mask_file has same size as in_file # out_file : Result of applying mask in in_file -> Gives the path of the output file def applyMask_func(in_file, in_file2): import numpy as np import nibabel as nib import os from os.path import join as opj # convert from unicode to string : u'/tmp/tmp8daO2Q/..' -> '/tmp/tmp8daO2Q/..' i.e. removes the prefix 'u' mask_file = in_file2 brain_data = nib.load(in_file) mask_data = nib.load(mask_file) brain = brain_data.get_data().astype('float32') mask = mask_data.get_data() # applying mask by multiplying elementwise to the binary mask if len(brain.shape) == 3: # Anat file brain = np.multiply(brain, mask) elif len(brain.shape) > 3: # Functional File for t in range(brain.shape[-1]): brain[:, :, :, t] = np.multiply(brain[:, :, :, t], mask) else: pass # Saving the brain file path = os.getcwd() in_file_split_list = in_file.split('/') in_file_name = in_file_split_list[-1] out_file = in_file_name + '_brain.nii.gz' # changing name brain_with_header = nib.Nifti1Image(brain, affine=brain_data.affine, header=brain_data.header) nib.save(brain_with_header, out_file) out_file = opj(path, out_file) out_file2 = in_file2 return out_file, out_file2 # #### Things learnt: # 1. I found out that whenever a node is being executed, it becomes the current directory and whatever file you create now, will be stored here. # 2. #from IPython.core.debugger import Tracer; Tracer()() # Debugger doesnt work in nipype # Wrap the above function inside a Node # In[890]: applyMask = Node(Function(function=applyMask_func, input_names=['in_file', 'in_file2'], output_names=['out_file', 'out_file2']), name='applyMask') # ### Some nodes needed for Co-registration and Normalization # Node for getting the xformation matrix func2anat_reg = Node(FLIRT(output_type='NIFTI'), name="func2anat_reg") # Node for applying xformation matrix to functional data func2std_xform = Node(FLIRT(output_type='NIFTI', apply_xfm=True), name="func2std_xform") # Node for applying xformation matrix to functional data std2func_xform = Node(FLIRT(output_type='NIFTI', apply_xfm=True, interp='nearestneighbour'), name="std2func_xform") # Node for Normalizing/Standardizing the anatomical and getting the xformation matrix anat2std_reg = Node(FLIRT(output_type='NIFTI'), name="anat2std_reg") # I wanted to use the MNI file as input to the workflow so I created an Identity # Node that reads the MNI file path and outputs the same MNI file path. # Then I connected this node to whereever it was needed. MNI152_2mm = Node(IdentityInterface(fields=['standard_file', 'mask_file']), name="MNI152_2mm") # Set the mask_file and standard_file input in the Node. This setting sets the input mask_file permanently. MNI152_2mm.inputs.mask_file = os.path.expandvars( '$FSLDIR/data/standard/MNI152_T1_2mm_brain_mask.nii.gz') MNI152_2mm.inputs.standard_file = os.path.expandvars( '$FSLDIR/data/standard/MNI152_T1_2mm_brain.nii.gz') # MNI152_2mm.inputs.mask_file = '/usr/share/fsl/5.0/data/standard/MNI152_T1_2mm_brain_mask.nii.gz' # MNI152_2mm.inputs.standard_file = '/usr/share/fsl/5.0/data/standard/MNI152_T1_2mm_brain.nii.gz' # ## Band Pass Filtering # Let's do a band pass filtering on the data using the code from https://neurostars.org/t/bandpass-filtering-different-outputs-from-fsl-and-nipype-custom-function/824/2 ### AFNI bandpass = Node(afni.Bandpass(highpass=0.008, lowpass=0.08, despike=False, no_detrend=True, notrans=True, outputtype='NIFTI_GZ'), name='bandpass') # ### Following is a Join Node that collects the preprocessed file paths and saves them in a file # In[902]: def save_file_list_function_in_brain(in_brain): import numpy as np import os from os.path import join as opj file_list = np.asarray(in_brain) print('######################## File List ######################: \n', file_list) np.save('brain_file_list', file_list) file_name = 'brain_file_list.npy' out_brain = opj(os.getcwd(), file_name) # path return out_brain def save_file_list_function_in_mask(in_mask): import numpy as np import os from os.path import join as opj file_list2 = np.asarray(in_mask) print('######################## File List ######################: \n', file_list2) np.save('mask_file_list', file_list2) file_name2 = 'mask_file_list.npy' out_mask = opj(os.getcwd(), file_name2) # path return out_mask def save_file_list_function_in_motion_params(in_motion_params): import numpy as np import os from os.path import join as opj file_list3 = np.asarray(in_motion_params) print('######################## File List ######################: \n', file_list3) np.save('motion_params_file_list', file_list3) file_name3 = 'motion_params_file_list.npy' out_motion_params = opj(os.getcwd(), file_name3) # path return out_motion_params def save_file_list_function_in_motion_outliers(in_motion_outliers): import numpy as np import os from os.path import join as opj file_list4 = np.asarray(in_motion_outliers) print('######################## File List ######################: \n', file_list4) np.save('motion_outliers_file_list', file_list4) file_name4 = 'motion_outliers_file_list.npy' out_motion_outliers = opj(os.getcwd(), file_name4) # path return out_motion_outliers def save_file_list_function_in_joint_xformation_matrix( in_joint_xformation_matrix): import numpy as np import os from os.path import join as opj file_list5 = np.asarray(in_joint_xformation_matrix) print('######################## File List ######################: \n', file_list5) np.save('joint_xformation_matrix_file_list', file_list5) file_name5 = 'joint_xformation_matrix_file_list.npy' out_joint_xformation_matrix = opj(os.getcwd(), file_name5) # path return out_joint_xformation_matrix def save_file_list_function_in_tr(in_tr): import numpy as np import os from os.path import join as opj tr_list = np.asarray(in_tr) print('######################## TR List ######################: \n', tr_list) np.save('tr_list', tr_list) file_name6 = 'tr_list.npy' out_tr = opj(os.getcwd(), file_name6) # path return out_tr def save_file_list_function_in_atlas(in_atlas): import numpy as np import os from os.path import join as opj file_list7 = np.asarray(in_atlas) print('######################## File List ######################: \n', file_list7) np.save('atlas_file_list', file_list7) file_name7 = 'atlas_file_list.npy' out_atlas = opj(os.getcwd(), file_name7) # path return out_atlas save_file_list_in_brain = JoinNode(Function( function=save_file_list_function_in_brain, input_names=['in_brain'], output_names=['out_brain']), joinsource="infosource", joinfield=['in_brain'], name="save_file_list_in_brain") save_file_list_in_mask = JoinNode(Function( function=save_file_list_function_in_mask, input_names=['in_mask'], output_names=['out_mask']), joinsource="infosource", joinfield=['in_mask'], name="save_file_list_in_mask") save_file_list_in_motion_outliers = JoinNode( Function(function=save_file_list_function_in_motion_outliers, input_names=['in_motion_outliers'], output_names=['out_motion_outliers']), joinsource="infosource", joinfield=['in_motion_outliers'], name="save_file_list_in_motion_outliers") save_file_list_in_motion_params = JoinNode( Function(function=save_file_list_function_in_motion_params, input_names=['in_motion_params'], output_names=['out_motion_params']), joinsource="infosource", joinfield=['in_motion_params'], name="save_file_list_in_motion_params") save_file_list_in_joint_xformation_matrix = JoinNode( Function(function=save_file_list_function_in_joint_xformation_matrix, input_names=['in_joint_xformation_matrix'], output_names=['out_joint_xformation_matrix']), joinsource="infosource", joinfield=['in_joint_xformation_matrix'], name="save_file_list_in_joint_xformation_matrix") save_file_list_in_tr = JoinNode(Function( function=save_file_list_function_in_tr, input_names=['in_tr'], output_names=['out_tr']), joinsource="infosource", joinfield=['in_tr'], name="save_file_list_in_tr") save_file_list_in_atlas = JoinNode(Function( function=save_file_list_function_in_atlas, input_names=['in_atlas'], output_names=['out_atlas']), joinsource="infosource", joinfield=['in_atlas'], name="save_file_list_in_atlas") # save_file_list = JoinNode(Function(function=save_file_list_function, input_names=['in_brain', 'in_mask', 'in_motion_params','in_motion_outliers','in_joint_xformation_matrix', 'in_tr', 'in_atlas'], # output_names=['out_brain','out_mask','out_motion_params','out_motion_outliers','out_joint_xformation_matrix','out_tr', 'out_atlas']), # joinsource="infosource", # joinfield=['in_brain', 'in_mask', 'in_motion_params','in_motion_outliers','in_joint_xformation_matrix','in_tr', 'in_atlas'], # name="save_file_list") # def save_file_list_function(in_brain, in_mask, in_motion_params, in_motion_outliers, in_joint_xformation_matrix, in_tr, in_atlas): # # Imports # import numpy as np # import os # from os.path import join as opj # # # file_list = np.asarray(in_brain) # print('######################## File List ######################: \n',file_list) # # np.save('brain_file_list',file_list) # file_name = 'brain_file_list.npy' # out_brain = opj(os.getcwd(),file_name) # path # # # file_list2 = np.asarray(in_mask) # print('######################## File List ######################: \n',file_list2) # # np.save('mask_file_list',file_list2) # file_name2 = 'mask_file_list.npy' # out_mask = opj(os.getcwd(),file_name2) # path # # # file_list3 = np.asarray(in_motion_params) # print('######################## File List ######################: \n',file_list3) # # np.save('motion_params_file_list',file_list3) # file_name3 = 'motion_params_file_list.npy' # out_motion_params = opj(os.getcwd(),file_name3) # path # # # file_list4 = np.asarray(in_motion_outliers) # print('######################## File List ######################: \n',file_list4) # # np.save('motion_outliers_file_list',file_list4) # file_name4 = 'motion_outliers_file_list.npy' # out_motion_outliers = opj(os.getcwd(),file_name4) # path # # # file_list5 = np.asarray(in_joint_xformation_matrix) # print('######################## File List ######################: \n',file_list5) # # np.save('joint_xformation_matrix_file_list',file_list5) # file_name5 = 'joint_xformation_matrix_file_list.npy' # out_joint_xformation_matrix = opj(os.getcwd(),file_name5) # path # # tr_list = np.asarray(in_tr) # print('######################## TR List ######################: \n',tr_list) # # np.save('tr_list',tr_list) # file_name6 = 'tr_list.npy' # out_tr = opj(os.getcwd(),file_name6) # path # # # file_list7 = np.asarray(in_atlas) # print('######################## File List ######################: \n',file_list7) # # np.save('atlas_file_list',file_list7) # file_name7 = 'atlas_file_list.npy' # out_atlas = opj(os.getcwd(),file_name7) # path # # # # # return out_brain, out_mask, out_motion_params, out_motion_outliers, out_joint_xformation_matrix, out_tr , out_atlas # # # # save_file_list = JoinNode(Function(function=save_file_list_function, input_names=['in_brain', 'in_mask', 'in_motion_params','in_motion_outliers','in_joint_xformation_matrix', 'in_tr', 'in_atlas'], # output_names=['out_brain','out_mask','out_motion_params','out_motion_outliers','out_joint_xformation_matrix','out_tr', 'out_atlas']), # joinsource="infosource", # joinfield=['in_brain', 'in_mask', 'in_motion_params','in_motion_outliers','in_joint_xformation_matrix','in_tr', 'in_atlas'], # name="save_file_list") # ### Motion outliers motionOutliers = Node(MotionOutliers(no_motion_correction=False, metric='fd', out_metric_plot='fd_plot.png', out_metric_values='fd_raw.txt'), name='motionOutliers') # ## Workflow for atlas registration from std to functional wf_atlas_resize_reg = Workflow(name=atlas_resize_reg_directory) wf_atlas_resize_reg.connect([ # Apply the inverse matrix to the 3mm Atlas to transform it to func space (maskfunc4mean, std2func_xform, [(('out_file', 'reference'))]), (resample_atlas, std2func_xform, [('out_file', 'in_file')]), # Now, applying the inverse matrix (inv_mat, std2func_xform, [('out_file', 'in_matrix_file')] ), # output: Atlas in func space (std2func_xform, save_file_list_in_atlas, [('out_file', 'in_atlas')]), # ---------------------------Save the required files -------------------------------------------- (save_file_list_in_motion_params, dataSink, [('out_motion_params', 'motion_params_paths.@out_motion_params')]), (save_file_list_in_motion_outliers, dataSink, [('out_motion_outliers', 'motion_outliers_paths.@out_motion_outliers') ]), (save_file_list_in_brain, dataSink, [('out_brain', 'preprocessed_brain_paths.@out_brain')]), (save_file_list_in_mask, dataSink, [('out_mask', 'preprocessed_mask_paths.@out_mask')]), (save_file_list_in_joint_xformation_matrix, dataSink, [('out_joint_xformation_matrix', 'joint_xformation_matrix_paths.@out_joint_xformation_matrix')]), (save_file_list_in_tr, dataSink, [('out_tr', 'tr_paths.@out_tr')]), (save_file_list_in_atlas, dataSink, [('out_atlas', 'atlas_paths.@out_atlas')]) ]) # In[909]: wf_coreg_reg = Workflow(name=coreg_reg_directory) # wf_coreg_reg.base_dir = base_directory # Dir where all the outputs will be stored(inside coregistrationPipeline folder). if ANAT == 1: wf_coreg_reg.connect(BIDSDataGrabber, 'anat_file_path', skullStrip, 'in_file') # Resampled the anat file to 3mm wf_coreg_reg.connect(skullStrip, 'out_file', resample_anat, 'in_file') wf_coreg_reg.connect( resample_anat, 'out_file', func2anat_reg, 'reference' ) # Make the resampled file as reference in func2anat_reg # Sec 1. The above 3 steps registers the mean image to resampled anat image and # calculates the xformation matrix .. I hope the xformation matrix will be saved wf_coreg_reg.connect(MNI152_2mm, 'standard_file', resample_mni, 'in_file') wf_coreg_reg.connect(resample_mni, 'out_file', anat2std_reg, 'reference') wf_coreg_reg.connect(resample_anat, 'out_file', anat2std_reg, 'in_file') # Calculates the Xformationmatrix from anat3mm to MNI 3mm # We can get those matrices by refering to func2anat_reg.outputs.out_matrix_file and similarly for anat2std_reg wf_coreg_reg.connect(func2anat_reg, 'out_matrix_file', concat_xform, 'in_file') wf_coreg_reg.connect(anat2std_reg, 'out_matrix_file', concat_xform, 'in_file2') wf_coreg_reg.connect(concat_xform, 'out_file', dataSink, 'tranformation_matrix_fun2std.@out_file') wf_coreg_reg.connect(concat_xform, 'out_file', save_file_list_in_joint_xformation_matrix, 'in_joint_xformation_matrix') # Now inverse the func2std MAT to std2func wf_coreg_reg.connect(concat_xform, 'out_file', wf_atlas_resize_reg, 'inv_mat.in_file') # ------------------------------------------------------------------------------------------------------------------------------ # Registration of Functional to MNI 3mm space w/o using anatomical if ANAT == 0: print('Not using Anatomical high resoulution files') wf_coreg_reg.connect(MNI152_2mm, 'standard_file', resample_mni, 'in_file') wf_coreg_reg.connect( resample_mni, 'out_file', func2anat_reg, 'reference' ) # Make the resampled file as reference in func2anat_reg wf_coreg_reg.connect(func2anat_reg, 'out_matrix_file', dataSink, 'tranformation_matrix_fun2std.@out_file') wf_coreg_reg.connect(func2anat_reg, 'out_matrix_file', save_file_list_in_joint_xformation_matrix, 'in_joint_xformation_matrix') # Now inverse the func2std MAT to std2func wf_coreg_reg.connect(func2anat_reg, 'out_matrix_file', wf_atlas_resize_reg, 'inv_mat.in_file') # ## Co-Registration, Normalization and Bandpass Workflow # 1. Co-registration means alligning the func to anat # 2. Normalization means aligning func/anat to standard # 3. Applied band pass filtering in range - highpass=0.008, lowpass=0.08 # In[910]: wf_motion_correction_bet = Workflow(name=motion_correction_bet_directory) # wf_motion_correction_bet.base_dir = base_directory wf_motion_correction_bet.connect([ (from_mcflirt, meanfunc, [('in_file', 'in_file')]), (meanfunc, meanfuncmask, [('out_file', 'in_file')]), (from_mcflirt, applyMask, [('in_file', 'in_file')]), # 1 (meanfuncmask, applyMask, [ ('mask_file', 'in_file2') ]), # 2 output: 1&2, BET on coregistered fmri scan (meanfunc, maskfunc4mean, [('out_file', 'in_file')]), # 3 (meanfuncmask, maskfunc4mean, [('mask_file', 'in_file2')]), # 4 output: 3&4, BET on mean func scan (applyMask, save_file_list_in_brain, [('out_file', 'in_brain')]), (applyMask, save_file_list_in_mask, [('out_file2', 'in_mask')]), (maskfunc4mean, wf_coreg_reg, [('out_file', 'func2anat_reg.in_file')]) ]) infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id', subject_list)] # Create the workflow wf = Workflow(name=parent_wf_directory) # base_dir = opj(s,'result') wf.base_dir = base_directory # Dir where all the outputs will be stored(inside BETFlow folder). # wf.connect([ (infosource, BIDSDataGrabber, [('subject_id','subject_id')]), # (BIDSDataGrabber, extract, [('func_file_path','in_file')]), # # (BIDSDataGrabber,getMetadata, [('func_file_path','in_file')]), # # (getMetadata,slicetimer, [('tr','time_repetition')]), # # # (getMetadata,slicetimer, [('index_dir','index_dir')]), # # (getMetadata,slicetimer, [('interleaved','interleaved')]), # # (getMetadata,save_file_list_in_tr, [('tr','in_tr')]), # # (extract,slicetimer,[('roi_file','in_file')]), # # (slicetimer, mcflirt,[('slice_time_corrected_file','in_file')]) # (mcflirt,dataSink,[('par_file','motion_params.@par_file')]), # saves the motion parameters calculated before # # (mcflirt,save_file_list_in_motion_params,[('par_file','in_motion_params')]), # # (mcflirt,wf_motion_correction_bet,[('out_file','from_mcflirt.in_file')]) # ]) # # Run it in parallel # wf.run('MultiProc', plugin_args={'n_procs': num_proc}) # # # # # Visualize the detailed graph # # from IPython.display import Image # wf.write_graph(graph2use='flat', format='png', simple_form=True) # Options: # discard 4 Volumes (extract), slicetimer, mcflirt print('Preprocessing Options:') print('Skipping 4 dummy volumes - ', options_binary_string[0]) print('Slicetiming correction - ', options_binary_string[1]) print('Finding Motion Outliers - ', options_binary_string[2]) print('Doing Motion Correction - ', options_binary_string[3]) # ANAT = 0 nodes = [extract, slicetimer, motionOutliers, mcflirt] wf.connect(infosource, 'subject_id', BIDSDataGrabber, 'subject_id') wf.connect(BIDSDataGrabber, 'func_file_path', getMetadata, 'in_file') wf.connect(getMetadata, 'tr', save_file_list_in_tr, 'in_tr') old_node = BIDSDataGrabber old_node_output = 'func_file_path' for idx, include in enumerate(options_binary_string): if old_node == extract: old_node_output = 'roi_file' elif old_node == slicetimer: old_node_output = 'slice_time_corrected_file' # elif old_node == mcflirt: # old_node_output = 'out_file' if int(include): new_node = nodes[idx] if new_node == slicetimer: wf.connect(getMetadata, 'tr', slicetimer, 'time_repetition') wf.connect(getMetadata, 'index_dir', slicetimer, 'index_dir') wf.connect(getMetadata, 'interleaved', slicetimer, 'interleaved') new_node_input = 'in_file' elif new_node == extract: new_node_input = 'in_file' elif new_node == mcflirt: new_node_input = 'in_file' wf.connect(mcflirt, 'par_file', dataSink, 'motion_params.@par_file' ) # saves the motion parameters calculated before wf.connect(mcflirt, 'par_file', save_file_list_in_motion_params, 'in_motion_params') wf.connect(mcflirt, 'out_file', wf_motion_correction_bet, 'from_mcflirt.in_file') elif new_node == motionOutliers: wf.connect(meanfuncmask, 'mask_file', motionOutliers, 'mask') wf.connect(motionOutliers, 'out_file', dataSink, 'motionOutliers.@out_file') wf.connect(motionOutliers, 'out_metric_plot', dataSink, 'motionOutliers.@out_metric_plot') wf.connect(motionOutliers, 'out_metric_values', dataSink, 'motionOutliers.@out_metric_values') wf.connect(motionOutliers, 'out_file', save_file_list_in_motion_outliers, 'in_motion_outliers') new_node_input = 'in_file' wf.connect(old_node, old_node_output, new_node, new_node_input) continue wf.connect(old_node, old_node_output, new_node, new_node_input) old_node = new_node else: if idx == 3: # new_node = from_mcflirt # new_node_input = 'from_mcflirt.in_file' wf.connect(old_node, old_node_output, wf_motion_correction_bet, 'from_mcflirt.in_file') # old_node = new_node TEMP_DIR_FOR_STORAGE = opj(base_directory, 'crash_files') wf.config = {"execution": {"crashdump_dir": TEMP_DIR_FOR_STORAGE}} # Visualize the detailed graph # from IPython.display import Image wf.write_graph(graph2use='flat', format='png', simple_form=True) # Run it in parallel wf.run('MultiProc', plugin_args={'n_procs': num_proc})
def functional_per_participant_test(): for i in ["","_aF","_cF1","_cF2","_pF"]: template = "~/ni_data/templates/ds_QBI_chr.nii.gz" participant = "4008" image_dir = "~/ni_data/ofM.dr/preprocessing/generic_work/_subject_session_{}.ofM{}/_scan_type_7_EPI_CBV/temporal_mean/".format(participant,i) try: for myfile in os.listdir(image_dir): if myfile.endswith(".nii.gz"): mimage = os.path.join(image_dir,myfile) except FileNotFoundError: pass else: n4 = ants.N4BiasFieldCorrection() n4.inputs.dimension = 3 n4.inputs.input_image = mimage n4.inputs.bspline_fitting_distance = 100 n4.inputs.shrink_factor = 2 n4.inputs.n_iterations = [200,200,200,200] n4.inputs.convergence_threshold = 1e-11 n4.inputs.output_image = 'n4_{}_ofM{}.nii.gz'.format(participant,i) n4_res = n4.run() functional_cutoff = ImageMaths() functional_cutoff.inputs.op_string = "-thrP 30" functional_cutoff.inputs.in_file = n4_res.outputs.output_image functional_cutoff_res = functional_cutoff.run() functional_BET = BET() functional_BET.inputs.mask = True functional_BET.inputs.frac = 0.5 functional_BET.inputs.in_file = functional_cutoff_res.outputs.out_file functional_BET_res = functional_BET.run() registration = ants.Registration() registration.inputs.fixed_image = template registration.inputs.output_transform_prefix = "output_" registration.inputs.transforms = ['Affine', 'SyN'] registration.inputs.transform_parameters = [(0.1,), (3.0, 3.0, 5.0)] registration.inputs.number_of_iterations = [[10000, 10000, 10000], [100, 100, 100]] registration.inputs.dimension = 3 registration.inputs.write_composite_transform = True registration.inputs.collapse_output_transforms = True registration.inputs.initial_moving_transform_com = True registration.inputs.metric = ['Mattes'] * 2 + [['Mattes', 'CC']] registration.inputs.metric_weight = [1] * 2 + [[0.5, 0.5]] registration.inputs.radius_or_number_of_bins = [32] * 2 + [[32, 4]] registration.inputs.sampling_strategy = ['Regular'] * 2 + [[None, None]] registration.inputs.sampling_percentage = [0.3] * 2 + [[None, None]] registration.inputs.convergence_threshold = [1.e-8] * 2 + [-0.01] registration.inputs.convergence_window_size = [20] * 2 + [5] registration.inputs.smoothing_sigmas = [[4, 2, 1]] * 2 + [[1, 0.5, 0]] registration.inputs.sigma_units = ['vox'] * 3 registration.inputs.shrink_factors = [[3, 2, 1]]*2 + [[4, 2, 1]] registration.inputs.use_estimate_learning_rate_once = [True] * 3 registration.inputs.use_histogram_matching = [False] * 2 + [True] registration.inputs.winsorize_lower_quantile = 0.005 registration.inputs.winsorize_upper_quantile = 0.995 registration.inputs.args = '--float' registration.inputs.num_threads = 4 registration.plugin_args = {'qsub_args': '-pe orte 4', 'sbatch_args': '--mem=6G -c 4'} registration.inputs.moving_image = functional_BET_res.outputs.out_file registration.inputs.output_warped_image = '{}_ofM{}.nii.gz'.format(participant,i) res = registration.run()