def calculate_realignment_cost(target_id: str, cost_function: str, serialize: bool = True): realigned_subject_dirs = generate_subject_dirs("realigned", target_id, cost_function) target_scan = get_target_scan(target_id) costs = {} for subject_dir in realigned_subject_dirs: subject_id = subject_dir.split("/")[-2] registered, mat_file = get_realigned_subject_data(subject_id) print(f"Calculating cost function value...", end="\t") flirt = FLIRT() flirt.inputs.in_file = registered flirt.inputs.reference = target_scan flirt.inputs.schedule = "/usr/local/fsl/etc/flirtsch/measurecost1.sch" flirt.inputs.in_matrix_file = mat_file tmp = os.path.join(subject_dir, "tmp") flirt.inputs.out_file = os.path.join(tmp, "cost.nii.gz") flirt.inputs.out_matrix_file = os.path.join(tmp, "cost.mat") os.makedirs(tmp, exist_ok=True) f = flirt.run() result = float(f.runtime.stdout.split()[0]) print(f"done! [{result}]") shutil.rmtree(tmp) costs[subject_id] = result if serialize: serialize_results(target_id, cost_function, costs) return costs
def init_b1_mcf(rf_pulse=None, scale=150): inputnode = Node(IdentityInterface(fields=['2db1map_file', 'ref_file']), name='inputnode') outputnode = Node(IdentityInterface(fields=['b1_plus', 'b1_pulse']), name='outputnode') b1_b1 = Node(ExtractROI(t_min=0, t_size=1), name='b1_extract_b1') b1_filter = Node(Filter(filter_spec='Gauss,3.0'), name='b1_filter') b1_mag = Node(ExtractROI(t_min=1, t_size=1), name='b1_extract_mag') b1_reg = Node(FLIRT(out_file='b1mag_reg.nii.gz', out_matrix_file='b1mag_reg.mat'), name='b1_reg') b1_invert = Node(ConvertXFM(invert_xfm=True), name='b1_invert') b1_apply = Node(FLIRT(apply_xfm=True), name='b1_reg_apply') b1_scale = Node(ImageMaths(op_string='-div %f' % scale), name='b1_scale') wf = Workflow(name='b1_prep') wf.connect([(inputnode, b1_b1, [('2db1map_file', 'in_file')]), (inputnode, b1_mag, [('2db1map_file', 'in_file')]), (inputnode, b1_reg, [('ref_file', 'in_file')]), (inputnode, b1_apply, [('ref_file', 'reference')]), (b1_mag, b1_reg, [('roi_file', 'reference')]), (b1_reg, b1_invert, [('out_matrix_file', 'in_file')]), (b1_invert, b1_apply, [('out_file', 'in_matrix_file')]), (b1_b1, b1_filter, [('roi_file', 'in_file')]), (b1_filter, b1_apply, [('out_file', 'in_file')]), (b1_apply, b1_scale, [('out_file', 'in_file')]), (b1_scale, outputnode, [('out_file', 'b1_plus')])]) if rf_pulse: b1_rf = Node(RFProfile(rf=rf_pulse, out_file='b1_rf.nii.gz'), name='b1_rf') wf.connect([(b1_scale, b1_rf, [('out_file', 'in_file')]), (b1_rf, outputnode, [('out_file', 'b1_pulse')])]) return wf
def flirt_t1_epi(subject_id, data_dir, run, sink_dir): def get_niftis(subject_id, data_dir, run, sink_dir): from os.path import join, exists t1 = join( data_dir, subject_id, "session-1", "anatomical", "anatomical-0", "anatomical.nii.gz", ) # t1_brain_mask = join(data_dir, subject, 'session-1', 'anatomical', 'anatomical-0', 'fsl', 'anatomical-bet.nii.gz') ex_func = join( sink_dir, subject_id, "{0}-{1}_retr-example_func.nii.gz".format(subject_id, run), ) assert exists(t1), "t1 does not exist" assert exists(ex_func), "example func does not exist" standard = "/home/applications/fsl/5.0.8/data/standard/MNI152_T1_2mm.nii.gz" return t1, ex_func, standard coreg = join(sink_dir, "qa", "{0}-{1}_t1_flirt.png".format(subject, run)) data = Function( function=get_niftis, input_names=["subject_id", "data_dir", "run", "sink_dir"], output_names=["t1", "ex_func", "standard"], ) data.inputs.data_dir = data_dir data.inputs.sink_dir = sink_dir data.inputs.subject_id = subject data.inputs.run = run grabber = data.run() re_flit = FLIRT( cost_func="normmi", dof=12, searchr_x=[-90, 90], searchr_y=[-90, 90], searchr_z=[-90, 90], interp="trilinear", bins=256, ) re_flit.inputs.reference = grabber.outputs.ex_func re_flit.inputs.in_file = grabber.outputs.t1 re_flit.inputs.out_file = join( sink_dir, subject, "{0}-{1}_t1-flirt-retr.nii.gz".format(subject, run)) re_flit.inputs.out_matrix_file = join( sink_dir, subject, "{0}-{1}_t1-flirt-retr.mat".format(subject, run)) reg_func = re_flit.run() display = plotting.plot_anat(grabber.outputs.ex_func, dim=0) display.add_edges(reg_func.outputs.out_file) display.savefig(coreg, dpi=300) return
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 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 func_register(img_original,img_template, img_registered): # img_original : original T2 or FLAIR image file # img_template : isovoxel T1C file used for registration template # img_registered :file name that stores registered (isovoxel) T2 or FLAIR file coregi_iso = FLIRT(bins=640, cost_func='mutualinfo', dof=12, output_type="NIFTI_GZ", verbose=0, datatype = 'float', interp = 'trilinear', in_file = img_original, reference = img_template, out_file = img_registered) coregi_iso.run()
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 isotropic_voxels(): if verbose: print('Resampling to isotropic voxels') orig = nib.load('%s/opposedphase.nii.gz' % tmpdir) for f in ['opposedphase', 'inphase']: iso = FLIRT() iso.inputs.in_file = '%s/%s.nii.gz' % (tmpdir, f) iso.inputs.reference = '%s/%s.nii.gz' % (tmpdir, f) iso.inputs.out_file = '%s/%s_iso.nii.gz' % (tmpdir, f) iso.inputs.apply_isoxfm = orig.header.get_zooms()[0] iso.run()
def make_w_coreg_7T_3T(ttype=''): n_in = Node(IdentityInterface(fields=[ 'T1w_7T', 'T1w_3T', ]), name='input') n_out = Node(IdentityInterface(fields=[ 'mat_t1w3t_to_t1w7t', 'mat_t1w7t_to_t1w3t', ]), name='output') n_7T = Node(Reorient2Std(), '7T') n_3T = Node(Reorient2Std(), '3T') n_coarse = Node(FLIRT(), 'coarse') n_coarse.inputs.no_search = True n_coarse.inputs.schedule = environ[ 'FSLDIR'] + '/etc/flirtsch/sch3Dtrans_3dof' n_coarse.inputs.dof = 6 n_fine = Node(FLIRT(), 'fine') n_fine.inputs.no_search = True # n_fine.inputs.cost = 'normcorr' n_fine.inputs.dof = 7 n_3t_7t = Node(ConvertXFM(), name='t1w3t_to_t1w7t') n_3t_7t.inputs.concat_xfm = True n_3t_7t.inputs.out_file = 'mat_t1w3t_to_t1w7t.mat' n_7t_3t = Node(ConvertXFM(), name='t1w7t_to_t1w3t') n_7t_3t.inputs.invert_xfm = True n_7t_3t.inputs.out_file = 'mat_t1w7t_to_t1w3t.mat' w = Workflow('coreg_3T_7T' + ttype) w.connect(n_in, 'T1w_7T', n_7T, 'in_file') w.connect(n_in, 'T1w_3T', n_3T, 'in_file') w.connect(n_7T, 'out_file', n_coarse, 'reference') w.connect(n_3T, 'out_file', n_coarse, 'in_file') w.connect(n_7T, 'out_file', n_fine, 'reference') w.connect(n_coarse, 'out_file', n_fine, 'in_file') w.connect(n_coarse, 'out_matrix_file', n_3t_7t, 'in_file') w.connect(n_fine, 'out_matrix_file', n_3t_7t, 'in_file2') w.connect(n_3t_7t, 'out_file', n_7t_3t, 'in_file') w.connect(n_3t_7t, 'out_file', n_out, 'mat_t1w3t_to_t1w7t') w.connect(n_7t_3t, 'out_file', n_out, 'mat_t1w7t_to_t1w3t') return w
def _flirt_linear_coreg_pipeline(self, **name_maps): """ Registers a MR scan to a refernce MR scan using FSL's FLIRT command """ pipeline = self.new_pipeline( name='linear_coreg', name_maps=name_maps, desc="Registers a MR scan against a reference image using FLIRT", citations=[fsl_cite]) pipeline.add( 'flirt', FLIRT(dof=self.parameter('flirt_degrees_of_freedom'), cost=self.parameter('flirt_cost_func'), cost_func=self.parameter('flirt_cost_func'), output_type='NIFTI_GZ'), inputs={ 'in_file': ('mag_preproc', nifti_gz_format), 'reference': ('coreg_ref', nifti_gz_format)}, outputs={ 'mag_coreg': ('out_file', nifti_gz_format), 'coreg_fsl_mat': ('out_matrix_file', text_matrix_format)}, requirements=[fsl_req.v('5.0.8')], wall_time=5) return pipeline
def _qform_transform_factory(self, name, to_reg, ref, qformed, qformed_mat, **kwargs): pipeline = self.create_pipeline( name=name, inputs=[ DatasetSpec(to_reg, nifti_gz_format), DatasetSpec(ref, nifti_gz_format) ], outputs=[ DatasetSpec(qformed, nifti_gz_format), DatasetSpec(qformed_mat, text_matrix_format) ], desc="Registers a MR scan against a reference image", version=1, citations=[fsl_cite], **kwargs) flirt = pipeline.create_node(interface=FLIRT(), name='flirt', requirements=[fsl5_req], wall_time=5) flirt.inputs.uses_qform = True flirt.inputs.apply_xfm = True # Connect inputs pipeline.connect_input(to_reg, flirt, 'in_file') pipeline.connect_input(ref, flirt, 'reference') # Connect outputs pipeline.connect_output(qformed, flirt, 'out_file') pipeline.connect_output(qformed_mat, flirt, 'out_matrix_file') return pipeline
def create_workflow_hrfpattern_7T(glm='spm'): input_node = Node(IdentityInterface(fields=[ 'bold', 'events', 't2star_fov', 't2star_whole', 't1w', ]), name='input') coreg_tstat = Node(interface=FLIRT(), name='realign_result_to_anat') coreg_tstat.inputs.apply_xfm = True w = Workflow('hrf_7T') w_preproc = create_workflow_preproc_spm() if glm == 'spm': w_hrfpattern = create_workflow_hrfpattern_spm() elif glm == 'fsl': w_hrfpattern = create_workflow_hrfpattern_fsl() w_coreg = create_workflow_coreg_epi2t1w() w.connect(input_node, 'bold', w_preproc, 'input.bold') w.connect(input_node, 'events', w_hrfpattern, 'input.events') w.connect(input_node, 't2star_fov', w_coreg, 'input.t2star_fov') w.connect(input_node, 't2star_whole', w_coreg, 'input.t2star_whole') w.connect(input_node, 't1w', w_coreg, 'input.t1w') w.connect(input_node, 't1w', coreg_tstat, 'reference') w.connect(w_preproc, 'realign.realigned_files', w_hrfpattern, 'input.bold') w.connect(w_preproc, 'realign.mean_image', w_coreg, 'input.bold_mean') w.connect(w_hrfpattern, 'output.T_image', coreg_tstat, 'in_file') w.connect(w_coreg, 'output.mat_epi2t1w', coreg_tstat, 'in_matrix_file') return w
def qform_transform_pipeline(self, **name_maps): pipeline = self.new_pipeline( name='qform_transform', name_maps=name_maps, desc="Registers a MR scan against a reference image", citations=[fsl_cite]) if self.provided('coreg_ref'): in_file = 'mag_preproc' reference = 'coreg_ref' elif self.provided('coreg_ref_brain'): in_file = 'brain' reference = 'coreg_ref_brain' else: raise BananaUsageError( "'coreg_ref' or 'coreg_ref_brain' need to be provided to " "study in order to run qform_transform") pipeline.add( 'flirt', FLIRT( uses_qform=True, apply_xfm=True, output_type='NIFTI_GZ'), inputs={ 'in_file': (in_file, nifti_gz_format), 'reference': (reference, nifti_gz_format)}, outputs={ 'qformed': ('out_file', nifti_gz_format), 'qform_mat': ('out_matrix_file', text_matrix_format)}, requirements=[fsl_req.v('5.0.8')], wall_time=5) return pipeline
def register_T1_to_simnibs(self): ### run flirt registartion if it has not been run before dest_img = os.path.join(self.mesh_dir, 'm2m_' + self.subject, 'T1fs_conform.nii.gz') if not os.path.exists( os.path.join(self.wf_base_dir, 'T1_to_simnibs_registration')): flirt = Node(FLIRT(), name='flirt') flirt.inputs.in_file = os.path.join(self.mesh_dir, 'm2m_' + self.subject, 'T1fs.nii.gz') flirt.inputs.reference = dest_img flirt.inputs.out_file = 'T1_in_Simnibs.nii.gz' flirt.inputs.out_matrix_file = 'T12Simnibs.mat' flirt.inputs.searchr_x = [-180, 180] flirt.inputs.searchr_y = [-180, 180] flirt.inputs.searchr_z = [-180, 180] wf = Workflow(name='T1_to_simnibs_registration', base_dir=self.wf_base_dir) wf.add_nodes([flirt]) wf.run() ## path to registration file t12simnibs_reg = os.path.join(self.wf_base_dir, 'T1_to_simnibs_registration', 'flirt', 'T12Simnibs.mat') return t12simnibs_reg
def run_t2w_deface(image, t1w_deface_mask, outfile): """ Setup and run t2w defacing workflow. Parameters ---------- image : str Path to image that should be defaced. t1w_deface_mask : str Path to the defaced T1w image that will be used as defacing mask. outfile : str Name of the defaced file. """ from bidsonym.utils import deface_t2w deface_wf = pe.Workflow('deface_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') flirtnode = pe.Node(FLIRT(cost_func='mutualinfo', output_type="NIFTI_GZ"), name='flirtnode') deface_t2w = pe.Node(Function(input_names=['image', 'warped_mask', 'outfile'], output_names=['outfile'], function=deface_t2w), name='deface_t2w') deface_wf.connect([(inputnode, flirtnode, [('in_file', 'reference')]), (inputnode, deface_t2w, [('in_file', 'image')]), (flirtnode, deface_t2w, [('out_file', 'warped_mask')])]) inputnode.inputs.in_file = image flirtnode.inputs.in_file = t1w_deface_mask deface_t2w.inputs.outfile = outfile deface_wf.run()
def create_workflow_temporalpatterns_7T(subjects, runs): input_node = Node(IdentityInterface(fields=[ 'bold', 'events', 't2star_fov', 't2star_whole', 't1w', ]), name='input') coreg_tstat = MapNode( interface=FLIRT(), name='realign_result_to_anat', iterfield=['in_file', ]) coreg_tstat.inputs.apply_xfm = True w = Workflow('temporalpatterns_7T') w_preproc = create_workflow_preproc_spm() w_spatialobject = create_workflow_temporalpatterns_fsl() w_coreg = create_workflow_coreg_epi2t1w() w.connect(input_node, 'bold', w_preproc, 'input.bold') w.connect(input_node, 'events', w_spatialobject, 'input.events') w.connect(input_node, 't2star_fov', w_coreg, 'input.t2star_fov') w.connect(input_node, 't2star_whole', w_coreg, 'input.t2star_whole') w.connect(input_node, 't1w', w_coreg, 'input.t1w') w.connect(input_node, 't1w', coreg_tstat, 'reference') w.connect(w_preproc, 'realign.realigned_files', w_spatialobject, 'input.bold') w.connect(w_preproc, 'realign.mean_image', w_coreg, 'input.bold_mean') w.connect(w_spatialobject, 'output.T_image', coreg_tstat, 'in_file') w.connect(w_coreg, 'output.mat_epi2t1w', coreg_tstat, 'in_matrix_file') return w
def func_regi2mni(path_T1C_isovoxel, path_mask_isovoxel): matrix_2mni = 'matrix_2mni.mat' mni_reference = 'MNI152_T1_1mm_brain.nii.gz' coregi_t1gd2mni= FLIRT(bins=640, cost_func='mutualinfo', dof=12, output_type="NIFTI_GZ", verbose=0, datatype = 'float', interp = 'trilinear', in_file = path_T1C_isovoxel, reference = mni_reference, out_file = 'img_2mni.nii.gz', out_matrix_file = matrix_2mni) coregi_t1gd2mni.run() coregi_mask2MNI = ApplyXFM(in_file = path_mask_isovoxel, in_matrix_file = matrix_2mni, out_file = 'mask_2mni.nii.gz', reference= mni_reference) coregi_mask2MNI.run()
def resample_to_umap(DeepX, reference): if verbose: print('Resampling to umap resolution') # Rehape to in-phase resolution DeepX = np.swapaxes(np.flipud(np.fliplr(DeepX)), 2, 0) DeepX_padded = np.zeros(reference.shape) DeepX_padded[96:288, 6:198, :192] = DeepX DeepX_nii = nib.Nifti1Image(DeepX_padded, reference.affine, reference.header) nib.save(DeepX_nii, '%s/DeepDixon.nii.gz' % tmpdir) # Resample to UMAP resolution DeepX_rsl = FLIRT() DeepX_rsl.inputs.in_file = '%s/DeepDixon.nii.gz' % tmpdir DeepX_rsl.inputs.reference = '%s/umap.nii.gz' % tmpdir DeepX_rsl.inputs.out_file = '%s/DeepDixon_rsl.nii.gz' % tmpdir DeepX_rsl.run() DeepX = nib.load('%s/DeepDixon_rsl.nii.gz' % tmpdir).get_fdata() DeepX = DeepX.astype(np.uint16) DeepX = np.fliplr(np.flipud(np.swapaxes(np.swapaxes(DeepX, 0, 1), 1, 2))) return DeepX
def _flirt_factory(self, name, to_reg, ref, reg, matrix, **kwargs): """ Registers a MR scan to a refernce MR scan using FSL's FLIRT command Parameters ---------- name : str Name for the generated pipeline to_reg : str Name of the DatasetSpec to register ref : str Name of the DatasetSpec to use as a reference reg : str Name of the DatasetSpec to output as registered image matrix : str Name of the DatasetSpec to output as registration matrix """ pipeline = self.create_pipeline( name=name, inputs=[ DatasetSpec(to_reg, nifti_gz_format), DatasetSpec(ref, nifti_gz_format) ], outputs=[ DatasetSpec(reg, nifti_gz_format), DatasetSpec(matrix, text_matrix_format) ], desc="Registers a MR scan against a reference image using FLIRT", version=1, citations=[fsl_cite], **kwargs) flirt = pipeline.create_node(interface=FLIRT(), name='flirt', requirements=[fsl5_req], wall_time=5) # Set registration parameters flirt.inputs.dof = self.parameter('flirt_degrees_of_freedom') flirt.inputs.cost = self.parameter('flirt_cost_func') flirt.inputs.cost_func = self.parameter('flirt_cost_func') flirt.inputs.output_type = 'NIFTI_GZ' # Connect inputs pipeline.connect_input(to_reg, flirt, 'in_file') pipeline.connect_input(ref, flirt, 'reference') # Connect outputs pipeline.connect_output(reg, flirt, 'out_file') pipeline.connect_output(matrix, flirt, 'out_matrix_file') return pipeline
def make_w_masking(): w_mask = Workflow('masking') n_in = Node( IdentityInterface(fields=[ 'T1w', 'subject', # without sub- 'freesurfer2func', 'func', ]), name='input') n_out = Node(IdentityInterface(fields=[ 'func', ]), name='output') n_fl = Node(FLIRT(), name='flirt') n_fl.inputs.output_type = 'NIFTI_GZ' n_fl.inputs.apply_xfm = True n_fl.inputs.interp = 'nearestneighbour' n_conv = Node(MRIConvert(), name='convert') n_conv.inputs.out_type = 'niigz' reconall = Node(ReconAll(), name='reconall') reconall.inputs.directive = 'all' reconall.inputs.subjects_dir = '/Fridge/R01_BAIR/freesurfer' w_mask.connect(n_in, 'T1w', reconall, 'T1_files') w_mask.connect(n_in, 'subject', reconall, 'subject_id') n_mul = Node(interface=BinaryMaths(), name='mul') n_mul.inputs.operation = 'mul' w_mask.connect(reconall, ('ribbon', select_ribbon), n_conv, 'in_file') w_mask.connect(n_conv, 'out_file', n_fl, 'in_file') w_mask.connect(n_in, 'func', n_fl, 'reference') w_mask.connect(n_in, 'freesurfer2func', n_fl, 'in_matrix_file') w_mask.connect(n_in, 'func', n_mul, 'in_file') w_mask.connect(n_fl, 'out_file', n_mul, 'operand_file') w_mask.connect(n_mul, 'out_file', n_out, 'func') return w_mask
def run_t2w_deface(image, t1w_deface_mask, outfile): from bidsonym.utils import deface_t2w deface_wf = pe.Workflow('deface_wf') inputnode = pe.Node(niu.IdentityInterface(['in_file']), name='inputnode') flirtnode = pe.Node(FLIRT(cost_func='mutualinfo', output_type="NIFTI_GZ")) deface_t2w = pe.Node(Function( input_names=['image', 'warped_mask', 'outfile'], output_names=['outfile'], function=deface_t2w), name='deface_t2w') deface_wf.connect([(inputnode, flirtnode, [('in_file', 'reference')]), (inputnode, deface_t2w, [('in_file', 'outfile')]), (flirtnode, deface_t2w, [('out_file', 'warped_mask')])]) inputnode.inputs.in_file = image flirtnode.inputs.in_file = t1w_deface_mask deface_t2w.inputs.image = image deface_wf.run()
def qform_transform_pipeline(self, **name_maps): pipeline = self.new_pipeline( name='qform_transform', name_maps=name_maps, desc="Registers a MR scan against a reference image", references=[fsl_cite]) pipeline.add('flirt', FLIRT(uses_qform=True, apply_xfm=True), inputs={ 'in_file': ('brain', nifti_gz_format), 'reference': ('coreg_ref_brain', nifti_gz_format) }, outputs={ 'out_file': ('qformed', nifti_gz_format), 'out_matrix_file': ('qform_mat', text_matrix_format) }, requirements=[fsl_req.v('5.0.8')], wall_time=5) return pipeline
def wf_transform_anat(in_file_list, in_matrix_file_list, reference): func2std_xform = MapNode( FLIRT(output_type='NIFTI', apply_xfm=True), name="func2std_xform", iterfield=['in_file', 'in_matrix_file', 'reference']) inputspec = Node(IdentityInterface( fields=['in_file_list', 'in_matrix_file_list', 'reference']), name="inputspec") inputspec.inputs.in_file_list = in_file_list inputspec.inputs.in_matrix_file_list = in_matrix_file_list inputspec.inputs.reference = reference wf_transform_anat = Workflow(name="wf_transform_anat") wf_transform_anat.connect(inputspec, 'in_file_list', func2std_xform, 'in_file') wf_transform_anat.connect(inputspec, 'in_matrix_file_list', func2std_xform, 'in_matrix_file') wf_transform_anat.connect(inputspec, 'reference', func2std_xform, 'reference') return wf_transform_anat
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})
""" for i in range(len(path_t1)): mask_ana(os.path.join(path_t1[i], "T1.nii"), os.path.join(path_t1[i], "mask.nii"), background_bright=False) for i in range(len(path_epi)): mask_epi(os.path.join(path_epi[i], "bepi.nii"), os.path.join(path_t1[i], "pT1.nii"), os.path.join(path_t1[i], "mask.nii"), niter_mask, sigma_mask, file_cmap) """ flirt """ os.chdir(path_flirt) flirt = FLIRT() flirt.inputs.cost_func = "corratio" flirt.inputs.dof = 6 flirt.inputs.interp = "trilinear" # trilinear, nearestneighbour, sinc or spline flirt.inputs.in_file = os.path.join(path_epi_target, "pbepi.nii") flirt.inputs.reference = os.path.join(path_epi_source, "pbepi.nii") flirt.inputs.output_type = "NIFTI" flirt.inputs.out_file = os.path.join(path_flirt, "flirt.nii") flirt.inputs.out_matrix_file = os.path.join(path_flirt, "flirt_matrix.mat") flirt.run() """ invert matrix """ invt = ConvertXFM() invt.inputs.in_file = os.path.join(path_flirt, "flirt_matrix.mat") invt.inputs.invert_xfm = True
def elecDetect(CT_dir, fs_dir,img, thresh_f, thresh_c, frac, num_gridStrips, n_elects): # run CT_electhresh print "::: Thresholding CT at %f stdv :::" %(thresh); CT_img = CT_dir + img; electhresh(CT_img,thresh_f, thresh_c); # run im_filt to gaussian smooth thresholded image fname = CT_dir + "thresh_" + img; print "::: Applying guassian smooth of 2.5mm to thresh-CT :::"; img_filt(fname); # compute hough transform to find electrode center coordinates mlab = matlab.MatlabCommand(); mlab.inputs.script = "addpath(genpath('/Volumes/Thunderbolt_Duo/Scripts/Matlab/SphericalHough')); \ img = readFileNifti('%s/smoothed_thresh_CT.nii');img = img.data(); \ fltr4LM_R = 3; obj_cint = 0.0; radrange = [0.1, 3]; multirad = 0.3; \ grdthres = 0.33;\ [center_img,sphere_img,sphcen2,sphrad]=SphericalHough(img,radrange,grdthres, \ fltr4LM_R, multirad, obj_cint); save('%s/elec_spheres.mat', 'sphere_img'); \ save('%s/elec_centers.mat', 'center_img'); \ save('%s/3d_hough_elect_coords.mat', 'sphcen2');" %(CT_dir, CT_dir , CT_dir, CT_dir); print "::: Applying 3D hough transform to smoothed thresh-CT :::"; out = mlab.run(); # run the hough and get errors if any ocur # save txt version of hough putputs coords = scipy.io.loadmat(CT_dir + '/'+ '3dHough_coords.mat').get('coords') np.savetxt('dirty_elecsAll.txt', coords, delimiter=' ', fmt='%-7.1f'); # run fsl FLIRT to compute CT-MRI registration flirt = FLIRT(); flirt.inputs.in_file = CT_dir + '/CT.nii'; flirt.inputs.reference = fs_dir + '/orig.nii'; flirt.inputs.cost_func = 'mutualinfo'; print "::: Computing corregistration between CT and MRI using FLIRT :::"; flirt.run(); # use fsl to calc voxel coords for elec centers in CT registered to orig # in RAS voxel coordinates using affine from FLIRT print "::: Applying FLIRT transformation to 3d Hough ouput :::"; orig_brain = fs_dir + '/orig.nii'; os.system('cat %s/dirty_elecsAll.txt | img2imgcoord -src %s/CT.nii -dest %s \ -xfm %s/CT_flirt.mat -vox > %s/dirty_elecsAll_RAS.txt' %(CT_dir, CT_dir, orig_brain, fs_dir, CT_dir)); # remove outliers caused by staples in the most superior portion of the img print "::: Removing outliers from detected electrode coordinates :::"; elecs_dirty_RAS = scipy.loadtxt('dirty_elecsAll_RAS.txt', skiprows=1); clean_elecs_RAS = []; for i in elecs_dirty_RAS: if i[1] > (0.3*np.max(elecs_dirty_RAS[:,2])): clean_elecs_RAS.append(i); clean_elecs_RAS = np.array(clean_elecs_RAS); # save surface RAS coords for cleaned coords # first apply vox2Ras affine for all fs orig volumes print "::: Applying freesurfer vox2RAS transformation :::"; affine = np.array([[ -1., 0., 0., 128.], [ 0., 0., 1., -128.], [ 0., -1., 0., 128.], [ 0., 0., 0., 1.]]); intercept = np.ones(len(clean_elecs_RAS)); vox_elecs = np.column_stack((clean_elecs_RAS,intercept)); vox_elecs = np.transpose(vox_elecs); sRAS_coords = np.matrix.dot(affine,vox_elecs); sRAS_coords = np.transpose(sRAS_coords); sRAS_coords = sRAS_coords[:,0:3]; # apply difference coord (lh_pial.asc - lh.pial) to shift all elecmatrix coords c_RAS = get_cRAS(fs_dir,subj); sRAS_coords = coords - c_RAS; # shifted to correct back to lh.pial coords scipy.io.savemat('elecs_all_cleaned.mat', {'elecmatrix':sRAS_coords}); # run K means to find grid and strip clusters n_clusts = num_gridStrips; # number of cluster to find = number of electrodes iters = 1000; init_clusts = n_clusts; print "::: Performing K-means cluster to find %d grid-strip and noise clusters :::" %(n_clusts); [clust_coords, clust_labels] = clust(sRAS_coords, n_clusts, iters, init_clusts); # save cluster results as individual arrays grid_strip_iter = np.linspace(0,num_gridStrips-1, num_gridStrips); sRAS_coords_list = [list(b) for b in sRAS_coords]; clust_labels_list = list(clust_labels); for i in grid_strip_iter: coords = []; for d in sRAS_coords_list: if clust_labels_list[sRAS_coords_list.index(d)] == int(i): coords.append(d); coords = np.array(coords); scipy.io.savemat('clust%s.mat' %(i), {'elecmatrix':coords});
def preproc(data_dir, sink_dir, subject, task, session, run, masks, motion_thresh, moco): from nipype.interfaces.fsl import MCFLIRT, FLIRT, FNIRT, ExtractROI, ApplyWarp, MotionOutliers, InvWarp, FAST #from nipype.interfaces.afni import AlignEpiAnatPy from nipype.interfaces.utility import Function from nilearn.plotting import plot_anat from nilearn import input_data #WRITE A DARA GRABBER def get_niftis(subject_id, data_dir, task, run, session): from os.path import join, exists t1 = join(data_dir, subject_id, 'session-{0}'.format(session), 'anatomical', 'anatomical-0', 'anatomical.nii.gz') #t1_brain_mask = join(data_dir, subject_id, 'session-1', 'anatomical', 'anatomical-0', 'fsl', 'anatomical-bet.nii.gz') epi = join(data_dir, subject_id, 'session-{0}'.format(session), task, '{0}-{1}'.format(task, run), '{0}.nii.gz'.format(task)) assert exists(t1), "t1 does not exist at {0}".format(t1) assert exists(epi), "epi does not exist at {0}".format(epi) standard = '/home/applications/fsl/5.0.8/data/standard/MNI152_T1_2mm.nii.gz' return t1, epi, standard data = Function( function=get_niftis, input_names=["subject_id", "data_dir", "task", "run", "session"], output_names=["t1", "epi", "standard"]) data.inputs.data_dir = data_dir data.inputs.subject_id = subject data.inputs.run = run data.inputs.session = session data.inputs.task = task grabber = data.run() if session == 0: sesh = 'pre' if session == 1: sesh = 'post' #reg_dir = '/home/data/nbc/physics-learning/data/first-level/{0}/session-1/retr/retr-{1}/retr-5mm.feat/reg'.format(subject, run) #set output paths for quality assurance pngs qa1 = join( sink_dir, 'qa', '{0}-session-{1}_{2}-{3}_t1_flirt.png'.format(subject, session, task, run)) qa2 = join( sink_dir, 'qa', '{0}-session-{1}_{2}-{3}_mni_flirt.png'.format(subject, session, task, run)) qa3 = join( sink_dir, 'qa', '{0}-session-{1}_{2}-{3}_mni_fnirt.png'.format(subject, session, task, run)) confound_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_confounds.txt'.format(subject, session, task, run)) #run motion correction if indicated if moco == True: mcflirt = MCFLIRT(ref_vol=144, save_plots=True, output_type='NIFTI_GZ') mcflirt.inputs.in_file = grabber.outputs.epi #mcflirt.inputs.in_file = join(data_dir, subject, 'session-1', 'retr', 'retr-{0}'.format(run), 'retr.nii.gz') mcflirt.inputs.out_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mcf.nii.gz'.format( subject, session, task, run)) flirty = mcflirt.run() motion = np.genfromtxt(flirty.outputs.par_file) else: print "no moco needed" motion = 0 #calculate motion outliers try: mout = MotionOutliers(metric='fd', threshold=motion_thresh) mout.inputs.in_file = grabber.outputs.epi mout.inputs.out_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_fd-gt-{3}mm'.format( subject, session, task, run, motion_thresh)) mout.inputs.out_metric_plot = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_metrics.png'.format( subject, session, task, run)) mout.inputs.out_metric_values = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_fd.txt'.format(subject, session, task, run)) moutliers = mout.run() outliers = np.genfromtxt(moutliers.outputs.out_file) e = 'no errors in motion outliers, yay' except Exception as e: print(e) outliers = np.genfromtxt(mout.inputs.out_metric_values) #set everything above the threshold to 1 and everything below to 0 outliers[outliers > motion_thresh] = 1 outliers[outliers < motion_thresh] = 0 #concatenate motion parameters and motion outliers to form confounds file #outliers = outliers.reshape((outliers.shape[0],1)) conf = outliers np.savetxt(confound_file, conf, delimiter=',') #extract an example volume for normalization ex_fun = ExtractROI(t_min=144, t_size=1) ex_fun.inputs.in_file = flirty.outputs.out_file ex_fun.inputs.roi_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}-example_func.nii.gz'.format( subject, session, task, run)) fun = ex_fun.run() warp = ApplyWarp(interp="nn", abswarp=True) if not exists( '/home/data/nbc/physics-learning/data/first-level/{0}/session-{1}/{2}/{2}-{3}/{2}-5mm.feat/reg/example_func2standard_warp.nii.gz' .format(subject, session, task, run)): #two-step normalization using flirt and fnirt, outputting qa pix flit = FLIRT(cost_func="corratio", dof=12) reg_func = flit.run( reference=fun.outputs.roi_file, in_file=grabber.outputs.t1, searchr_x=[-180, 180], searchr_y=[-180, 180], out_file=join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_t1-flirt.nii.gz'.format( subject, session, task, run)), out_matrix_file=join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_t1-flirt.mat'.format( subject, session, task, run))) reg_mni = flit.run( reference=grabber.outputs.t1, in_file=grabber.outputs.standard, searchr_y=[-180, 180], searchr_z=[-180, 180], out_file=join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-flirt-t1.nii.gz'.format( subject, session, task, run)), out_matrix_file=join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-flirt-t1.mat'.format( subject, session, task, run))) #plot_stat_map(aligner.outputs.out_file, bg_img=fun.outputs.roi_file, colorbar=True, draw_cross=False, threshold=1000, output_file=qa1a, dim=-2) display = plot_anat(fun.outputs.roi_file, dim=-1) display.add_edges(reg_func.outputs.out_file) display.savefig(qa1, dpi=300) display.close() display = plot_anat(grabber.outputs.t1, dim=-1) display.add_edges(reg_mni.outputs.out_file) display.savefig(qa2, dpi=300) display.close() perf = FNIRT(output_type='NIFTI_GZ') perf.inputs.warped_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-fnirt-t1.nii.gz'.format( subject, session, task, run)) perf.inputs.affine_file = reg_mni.outputs.out_matrix_file perf.inputs.in_file = grabber.outputs.standard perf.inputs.subsampling_scheme = [8, 4, 2, 2] perf.inputs.fieldcoeff_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-fnirt-t1-warpcoeff.nii.gz'.format( subject, session, task, run)) perf.inputs.field_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-fnirt-t1-warp.nii.gz'.format( subject, session, task, run)) perf.inputs.ref_file = grabber.outputs.t1 reg2 = perf.run() warp.inputs.field_file = reg2.outputs.field_file #plot fnirted MNI overlaid on example func display = plot_anat(grabber.outputs.t1, dim=-1) display.add_edges(reg2.outputs.warped_file) display.savefig(qa3, dpi=300) display.close() else: warpspeed = InvWarp(output_type='NIFTI_GZ') warpspeed.inputs.warp = '/home/data/nbc/physics-learning/data/first-level/{0}/session-{1}/{2}/{2}-{3}/{2}-5mm.feat/reg/example_func2standard_warp.nii.gz'.format( subject, session, task, run) warpspeed.inputs.reference = fun.outputs.roi_file warpspeed.inputs.inverse_warp = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_mni-fnirt-t1-warp.nii.gz'.format( subject, session, task, run)) mni2epiwarp = warpspeed.run() warp.inputs.field_file = mni2epiwarp.outputs.inverse_warp for key in masks.keys(): #warp takes us from mni to epi warp.inputs.in_file = masks[key] warp.inputs.ref_file = fun.outputs.roi_file warp.inputs.out_file = join( sink_dir, sesh, subject, '{0}-session-{1}_{2}-{3}_{4}.nii.gz'.format( subject, session, task, run, key)) net_warp = warp.run() qa_file = join( sink_dir, 'qa', '{0}-session-{1}_{2}-{3}_qa_{4}.png'.format( subject, session, task, run, key)) display = plotting.plot_roi(net_warp.outputs.out_file, bg_img=fun.outputs.roi_file, colorbar=True, vmin=0, vmax=18, draw_cross=False) display.savefig(qa_file, dpi=300) display.close() return flirty.outputs.out_file, confound_file, e
# Skull Strip the fmri time series bet_fmri_node = Node(BET(output_type='NIFTI', mask=True), name="bet_fmri") # Bias Correct the fmri time series bias_correction_node = Node(N4BiasFieldCorrection(), name='bias_correction') # Returns the relative concentration of brain iron rcfe_node = Node(Function(input_names=['input_image', 'mask_image'], output_names=['output_image'], function=compute_rcFe), name="rcfe") # coregister (skullstripped) mean of the fmri time series to the skull stripped T1 structural flirt_node = Node( FLIRT(dof=6), name="flirt", cost='mutualinfo') #TODO: do i have to specify out_matrix_file??? # skullstrip the T1 structural image skullstrip_structural_node = Node(SkullStrip(outputtype='NIFTI'), name='skullstrip') # coreg_to_struct_space = Node(FLIRT(apply_xfm=True, reference=struct_image, interp="sinc"), name="coreg") coreg_to_struct_space_node = Node(FLIRT(apply_xfm=True, interp="sinc", cost='mutualinfo'), name="coreg_to_struct_space") # Warp whole head T1 Structural Image to MNI 152 template warp_to_152_node = Node(legacy.GenWarpFields(similarity_metric="CC"), name="warp152")
def _main(subject_list,vols,subid_vol_dict, number_of_skipped_volumes,brain_path,\ mask_path,\ atlas_path,\ tr_path,\ motion_params_path,\ func2std_mat_path,\ MNI3mm_path,\ base_directory,\ fc_datasink_name,\ motion_param_regression,\ band_pass_filtering,\ global_signal_regression,\ smoothing,\ volcorrect,\ num_proc,\ functional_connectivity_directory ): # ## Volume correction # * I have already extracted 4 volumes. # * Now extract 120 - 4 = 116 volumes from each subject # * So define vols = 114 # if number_of_skipped_volumes == None: number_of_skipped_volumes = 4 vols = vols - number_of_skipped_volumes def vol_correct(sub_id, subid_vol_dict, vols, number_of_skipped_volumes): sub_vols = subid_vol_dict[sub_id] - number_of_skipped_volumes if sub_vols > vols: t_min = sub_vols - vols elif sub_vols == vols: t_min = 0 else: raise Exception('Volumes of Sub ',sub_id,' less than desired!') return int(t_min) # In[491]: volCorrect = Node(Function(function=vol_correct, input_names=['sub_id','subid_vol_dict','vols','number_of_skipped_volumes'], output_names=['t_min']), name='volCorrect') volCorrect.inputs.subid_vol_dict = subid_vol_dict volCorrect.inputs.vols = vols volCorrect.inputs.number_of_skipped_volumes = number_of_skipped_volumes # ## Define a function to fetch the filenames of a particular subject ID def get_subject_filenames(subject_id,brain_path,mask_path,atlas_path,tr_path,motion_params_path,func2std_mat_path,MNI3mm_path): import re from itertools import zip_longest for brain,mask,atlas,tr,motion_param,func2std_mat in zip_longest(brain_path,mask_path,atlas_path,tr_path,motion_params_path,func2std_mat_path): #itertools helps to zip unequal save_file_list_in_mask # Source : https://stackoverflow.com/questions/11318977/zipping-unequal-lists-in-python-in-to-a-list-which-does-not-drop-any-element-fro print('*******************',brain,mask,atlas,tr,motion_param,func2std_mat) sub_id_extracted = re.search('.+_subject_id_(\d+)', brain).group(1) if str(subject_id) in brain: # print("Files for subject ",subject_id,brain,mask,atlas,tr,motion_param) return brain,mask,atlas,tr,motion_param,func2std_mat,MNI3mm_path print ('Unable to locate Subject: ',subject_id,'extracted: ',sub_id_extracted) # print ('Unable to locate Subject: ',subject_id) raise Exception('Unable to locate Subject: ',subject_id,'extracted: ',sub_id_extracted) # raise Exception('Unable to locate Subject: ',subject_id) return 0 # Make a node getSubjectFilenames = Node(Function(function=get_subject_filenames, input_names=['subject_id','brain_path','mask_path','atlas_path','tr_path','motion_params_path','func2std_mat_path','MNI3mm_path'], output_names=['brain','mask','atlas','tr','motion_param','func2std_mat', 'MNI3mm_path']), name='getSubjectFilenames') getSubjectFilenames.inputs.brain_path = brain_path getSubjectFilenames.inputs.mask_path = mask_path getSubjectFilenames.inputs.atlas_path = atlas_path getSubjectFilenames.inputs.tr_path = tr_path getSubjectFilenames.inputs.motion_params_path = motion_params_path getSubjectFilenames.inputs.func2std_mat_path = func2std_mat_path getSubjectFilenames.inputs.MNI3mm_path = MNI3mm_path infosource = Node(IdentityInterface(fields=['subject_id']), name="infosource") infosource.iterables = [('subject_id',subject_list)] # ## 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.01, lowpass=0.1, despike=False, no_detrend=True, notrans=True, outputtype='NIFTI_GZ'),name='bandpass') # bandpass = Node(afni.Bandpass(highpass=0.001, lowpass=0.01, # despike=False, no_detrend=True, notrans=True, # tr=2.0,outputtype='NIFTI_GZ'),name='bandpass') # ## Highpass filtering # In[506]: """ Perform temporal highpass filtering on the data """ # https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dBandpass.html # os.chdir('/home1/varunk/Autism-Connectome-Analysis-bids-related/') highpass = Node(afni.Bandpass(highpass=0.009, lowpass=99999, despike=False, no_detrend=True, notrans=True, outputtype='NIFTI_GZ'),name='highpass') # FSL bandpass/Highpass # highpass = Node(interface=ImageMaths(suffix='_tempfilt'), # iterfield=['in_file'], # name='highpass') # # highpass.inputs.op_string = '-bptf 27.77775001525879 -1' # 23.64 # 31.25 # ## Smoothing # ### Using 6mm fwhm # sigma = 6/2.3548 = 2.547987090198743 spatialSmooth = Node(interface=ImageMaths(op_string='-s 2.5479', suffix='_smoothed'), name='spatialSmooth') # ## Performs Gram Schmidt Process # https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process # In[509]: def orthogonalize(in_file, mask_file): import numpy as np import nibabel as nib import os from os.path import join as opj def gram_schmidt(voxel_time_series, mean_vector): numerator = np.dot(voxel_time_series,mean_vector) dinominator = np.dot(mean_vector,mean_vector) voxel_time_series_orthogonalized = voxel_time_series - (numerator/dinominator)*mean_vector # TO CONFIRM IF THE VECTORS ARE ORTHOGONAL # sum_dot_prod = np.sum(np.dot(voxel_time_series_orthogonalized,mean_vector)) # print('Sum of entries of orthogonalized vector = ',sum_dot_prod) return voxel_time_series_orthogonalized mask_data = nib.load(mask_file) mask = mask_data.get_data() brain_data = nib.load(in_file) brain = brain_data.get_data() x_dim, y_dim, z_dim, t_dim = brain_data.shape # Find mean brain mean_vector = np.zeros(t_dim) num_brain_voxels = 0 # Count the number of brain voxels for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): if mask[i,j,k] == 1: mean_vector = mean_vector + brain[i,j,k,:] num_brain_voxels = num_brain_voxels + 1 mean_vector = mean_vector / num_brain_voxels # Orthogonalize for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): if mask[i,j,k] == 1: brain[i,j,k,:] = gram_schmidt(brain[i,j,k,:], mean_vector) sub_id = in_file.split('/')[-1].split('.')[0].split('_')[0].split('-')[1] gsr_file_name = 'sub-' + sub_id + '_task-rest_run-1_bold.nii.gz' # gsr_file_name_nii = gsr_file_name + '.nii.gz' out_file = opj(os.getcwd(),gsr_file_name) # path brain_with_header = nib.Nifti1Image(brain, affine=brain_data.affine,header = brain_data.header) nib.save(brain_with_header,gsr_file_name) return out_file # In[510]: globalSignalRemoval = Node(Function(function=orthogonalize, input_names=['in_file','mask_file'], output_names=['out_file']), name='globalSignalRemoval' ) # globalSignalRemoval.inputs.mask_file = mask_file # globalSignalRemoval.iterables = [('in_file',file_paths)] # ## GLM for regression of motion parameters # In[511]: def calc_residuals(in_file, motion_file): """ Calculates residuals of nuisance regressors -motion parameters for every voxel for a subject using GLM. Parameters ---------- in_file : string Path of a subject's motion corrected nifti file. motion_par_file : string path of a subject's motion parameters Returns ------- out_file : string Path of residual file in nifti format """ import nibabel as nb import numpy as np import os from os.path import join as opj nii = nb.load(in_file) data = nii.get_data().astype(np.float32) global_mask = (data != 0).sum(-1) != 0 # Check and define regressors which are provided from files if motion_file is not None: motion = np.genfromtxt(motion_file) if motion.shape[0] != data.shape[3]: raise ValueError('Motion parameters {0} do not match data ' 'timepoints {1}'.format(motion.shape[0], data.shape[3])) if motion.size == 0: raise ValueError('Motion signal file {0} is ' 'empty'.format(motion_file)) # Calculate regressors regressor_map = {'constant' : np.ones((data.shape[3],1))} regressor_map['motion'] = motion X = np.zeros((data.shape[3], 1)) for rname, rval in regressor_map.items(): X = np.hstack((X, rval.reshape(rval.shape[0],-1))) X = X[:,1:] if np.isnan(X).any() or np.isnan(X).any(): raise ValueError('Regressor file contains NaN') Y = data[global_mask].T try: B = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y) except np.linalg.LinAlgError as e: if "Singular matrix" in e: raise Exception("Error details: {0}\n\nSingular matrix error: " "The nuisance regression configuration you " "selected may have been too stringent, and the " "regression could not be completed. Ensure your " "parameters are not too " "extreme.\n\n".format(e)) else: raise Exception("Error details: {0}\n\nSomething went wrong with " "nuisance regression.\n\n".format(e)) Y_res = Y - X.dot(B) data[global_mask] = Y_res.T img = nb.Nifti1Image(data, header=nii.get_header(), affine=nii.get_affine()) subject_name = in_file.split('/')[-1].split('.')[0] filename = subject_name + '_residual.nii.gz' out_file = os.path.join(os.getcwd(),filename ) img.to_filename(out_file) # alt to nib.save return out_file # In[512]: # Create a Node for above calc_residuals = Node(Function(function=calc_residuals, input_names=['in_file','motion_file'], output_names=['out_file']), name='calc_residuals') # ## Datasink # I needed to define the structure of what files are saved and where. # In[513]: # Create DataSink object dataSink = Node(DataSink(), name='datasink') # Name of the output folder dataSink.inputs.base_directory = opj(base_directory,fc_datasink_name) # To create the substitutions I looked the `datasink` folder where I was redirecting the output. I manually selected the part of file/folder name that I wanted to change and copied below to be substituted. # # In[514]: # Define substitution strings so that the data is similar to BIDS substitutions = [('_subject_id_', 'sub-')] # Feed the substitution strings to the DataSink node dataSink.inputs.substitutions = substitutions # ### Following is a Join Node that collects the preprocessed file paths and saves them in a file # In[516]: def save_file_list_function(in_fc_map_brain_file): # Imports import numpy as np import os from os.path import join as opj file_list = np.asarray(in_fc_map_brain_file) print('######################## File List ######################: \n',file_list) np.save('fc_map_brain_file_list',file_list) file_name = 'fc_map_brain_file_list.npy' out_fc_map_brain_file = opj(os.getcwd(),file_name) # path return out_fc_map_brain_file # In[517]: save_file_list = JoinNode(Function(function=save_file_list_function, input_names=['in_fc_map_brain_file'], output_names=['out_fc_map_brain_file']), joinsource="infosource", joinfield=['in_fc_map_brain_file'], name="save_file_list") # ## Create a FC node # # This node: # 1. Exracts the average time series of the brain ROI's using the atlas and stores # it as a matrix of size [ROIs x Volumes]. # 2. Extracts the Voxel time series and stores it in matrix of size [Voxels x Volumes] # # And save FC matrix files in shape of brains def pear_coff(in_file, atlas_file, mask_file): # code to find how many voxels are in the brain region using the mask # imports import numpy as np import nibabel as nib import os from os.path import join as opj mask_data = nib.load(mask_file) mask = mask_data.get_data() x_dim, y_dim, z_dim = mask_data.shape atlasPath = atlas_file # Read the atlas atlasObject = nib.load(atlasPath) atlas = atlasObject.get_data() num_ROIs = int((np.max(atlas) - np.min(atlas) )) # Read the brain in_file brain_data = nib.load(in_file) brain = brain_data.get_data() x_dim, y_dim, z_dim, num_volumes = brain.shape num_brain_voxels = 0 x_dim, y_dim, z_dim = mask_data.shape for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): if mask[i,j,k] == 1: num_brain_voxels = num_brain_voxels + 1 # Initialize a matrix of ROI time series and voxel time series ROI_matrix = np.zeros((num_ROIs, num_volumes)) voxel_matrix = np.zeros((num_brain_voxels, num_volumes)) # Fill up the voxel_matrix voxel_counter = 0 for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): if mask[i,j,k] == 1: voxel_matrix[voxel_counter,:] = brain[i,j,k,:] voxel_counter = voxel_counter + 1 # Fill up the ROI_matrix # Keep track of number of voxels per ROI as well by using an array - num_voxels_in_ROI[] num_voxels_in_ROI = np.zeros((num_ROIs,1)) # A column arrray containing number of voxels in each ROI for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): label = int(atlas[i,j,k]) - 1 if label != -1: ROI_matrix[label,:] = np.add(ROI_matrix[label,:], brain[i,j,k,:]) num_voxels_in_ROI[label,0] = num_voxels_in_ROI[label,0] + 1 ROI_matrix = np.divide(ROI_matrix,num_voxels_in_ROI) # Check if divide is working correctly X, Y = ROI_matrix, voxel_matrix # Subtract mean from X and Y X = np.subtract(X, np.mean(X, axis=1, keepdims=True)) Y = np.subtract(Y, np.mean(Y, axis=1, keepdims=True)) temp1 = np.dot(X,Y.T) temp2 = np.sqrt(np.sum(np.multiply(X,X), axis=1, keepdims=True)) temp3 = np.sqrt(np.sum(np.multiply(Y,Y), axis=1, keepdims=True)) temp4 = np.dot(temp2,temp3.T) coff_matrix = np.divide(temp1, (temp4 + 1e-7)) # Check if any ROI is missing and replace the NAN values in coff_matrix by 0 if np.argwhere(np.isnan(coff_matrix)).shape[0] != 0: print("Some ROIs are not present. Replacing NAN in coff matrix by 0") np.nan_to_num(coff_matrix, copy=False) # TODO: when I have added 1e-7 in the dinominator, then why did I feel the need to replace NAN by zeros sub_id = in_file.split('/')[-1].split('.')[0].split('_')[0].split('-')[1] fc_file_name = sub_id + '_fc_map' print ("Pear Matrix calculated for subject: ",sub_id) roi_brain_matrix = coff_matrix brain_file = in_file x_dim, y_dim, z_dim, t_dim = brain.shape (brain_data.header).set_data_shape([x_dim,y_dim,z_dim,num_ROIs]) brain_roi_tensor = np.zeros((brain_data.header.get_data_shape())) print("Creating brain for Subject-",sub_id) for roi in range(num_ROIs): brain_voxel_counter = 0 for i in range(x_dim): for j in range(y_dim): for k in range(z_dim): if mask[i,j,k] == 1: brain_roi_tensor[i,j,k,roi] = roi_brain_matrix[roi,brain_voxel_counter] brain_voxel_counter = brain_voxel_counter + 1 assert (brain_voxel_counter == len(roi_brain_matrix[roi,:])) print("Created brain for Subject-",sub_id) path = os.getcwd() fc_file_name = fc_file_name + '.nii.gz' out_file = opj(path,fc_file_name) brain_with_header = nib.Nifti1Image(brain_roi_tensor, affine=brain_data.affine,header = brain_data.header) nib.save(brain_with_header,out_file) fc_map_brain_file = out_file return fc_map_brain_file # In[521]: # Again Create the Node and set default values to paths pearcoff = Node(Function(function=pear_coff, input_names=['in_file','atlas_file','mask_file'], output_names=['fc_map_brain_file']), name='pearcoff') # # IMPORTANT: # * The ROI 255 has been removed due to resampling. Therefore the FC maps will have nan at that row. So don't use that ROI :) # * I came to know coz I keep getting this error: RuntimeWarning: invalid value encountered in true_divide # * To debug it, I read the coff matrix and checked its diagnol to discover the nan value. # # # # ## Extract volumes # ExtractROI - For volCorrect extract = Node(ExtractROI(t_size=-1), output_type='NIFTI', name="extract") # ### Node for applying xformation matrix to functional data # # In[523]: func2std_xform = Node(FLIRT(output_type='NIFTI_GZ', apply_xfm=True), name="func2std_xform") # motion_param_regression = 1 # band_pass_filtering = 0 # global_signal_regression = 0 # smoothing = 1 # volcorrect = 1 if num_proc == None: num_proc = 7 combination = 'motionRegress' + str(int(motion_param_regression)) + \ 'global' + str(int(global_signal_regression)) + 'smoothing' + str(int(smoothing)) +\ 'filt' + str(int(band_pass_filtering)) print("Combination: ",combination) binary_string = str(int(motion_param_regression)) + str(int(global_signal_regression)) + \ str(int(smoothing)) + str(int(band_pass_filtering)) + str(int(volcorrect)) base_dir = opj(base_directory,functional_connectivity_directory) # wf = Workflow(name=functional_connectivity_directory) wf = Workflow(name=combination) wf.base_dir = base_dir # Dir where all the outputs will be stored. wf.connect(infosource ,'subject_id', getSubjectFilenames, 'subject_id') # ------- Dynamic Pipeline ------------------------ nodes = [ calc_residuals, globalSignalRemoval, spatialSmooth, bandpass, volCorrect] # from nipype.interfaces import fsl old_node = getSubjectFilenames old_node_output = 'brain' binary_string = binary_string+'0' # so that the loop runs one more time for idx, include in enumerate(binary_string): # 11111 # motion_param_regression # global_signal_regression # smoothing # band_pass_filtering # volcorrect if old_node == calc_residuals: old_node_output = 'out_file' elif old_node == extract : old_node_output = 'roi_file' elif old_node == globalSignalRemoval: old_node_output = 'out_file' elif old_node == bandpass: old_node_output = 'out_file' elif old_node == highpass: old_node_output = 'out_file' elif old_node == spatialSmooth: old_node_output = 'out_file' elif old_node == volCorrect: old_node_output = 'out_file' if int(include): # if old_node is None: # # wf.add_nodes([nodes[idx]]) # # else: new_node = nodes[idx] if new_node == calc_residuals: wf.connect([(getSubjectFilenames, calc_residuals, [('motion_param', 'motion_file')])]) new_node_input = 'in_file' elif new_node == extract : wf.connect([( volCorrect, extract, [('t_min','t_min')])]) new_node_input = 'in_file' elif new_node == globalSignalRemoval: wf.connect([(getSubjectFilenames, globalSignalRemoval, [('mask','mask_file')])]) new_node_input = 'in_file' elif new_node == bandpass: wf.connect([(getSubjectFilenames, bandpass, [('tr','tr')])]) new_node_input = 'in_file' elif new_node == highpass: wf.connect([(getSubjectFilenames, highpass, [('tr','tr')])]) #Commenting for FSL new_node_input = 'in_file' elif new_node == spatialSmooth: new_node_input = 'in_file' elif new_node == volCorrect: wf.connect([(infosource, volCorrect, [('subject_id','sub_id')])]) wf.connect([( volCorrect, extract, [('t_min','t_min')])]) new_node = extract new_node_input = 'in_file' wf.connect(old_node, old_node_output, new_node, new_node_input) old_node = new_node else: if idx == 3: # bandpas == 0 => Highpass new_node = highpass wf.connect([(getSubjectFilenames, highpass, [('tr','tr')])]) #Commenting for FSL new_node_input = 'in_file' wf.connect(old_node, old_node_output, new_node, new_node_input) old_node = new_node wf.connect(old_node, old_node_output, pearcoff, 'in_file') wf.connect(getSubjectFilenames,'atlas', pearcoff, 'atlas_file') wf.connect(getSubjectFilenames, 'mask', pearcoff, 'mask_file') wf.connect(pearcoff, 'fc_map_brain_file', func2std_xform ,'in_file') wf.connect(getSubjectFilenames,'func2std_mat', func2std_xform, 'in_matrix_file') wf.connect(getSubjectFilenames, 'MNI3mm_path', func2std_xform,'reference') folder_name = combination + '.@fc_map_brain_file' wf.connect(func2std_xform, 'out_file', save_file_list, 'in_fc_map_brain_file') wf.connect(save_file_list, 'out_fc_map_brain_file', dataSink,folder_name) TEMP_DIR_FOR_STORAGE = opj(base_directory,'crash_files') wf.config = {"execution": {"crashdump_dir": TEMP_DIR_FOR_STORAGE}} wf.write_graph(graph2use='flat', format='png') wf.run('MultiProc', plugin_args={'n_procs': num_proc})
write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_t1") normalize_masks = Node(Normalize12( jobtype='estwrite', tpm=template, write_voxel_sizes=[iso_size, iso_size, iso_size], write_bounding_box=[[-90, -126, -72], [90, 90, 108]]), name="normalize_masks") # Threshold - Threshold WM probability image threshold = Node(Threshold(thresh=0.5, args='-bin', output_type='NIFTI_GZ'), name="wm_mask_threshold") # FLIRT - pre-alignment of functional images to anatomical images coreg_pre = Node(FLIRT(dof=6, output_type='NIFTI_GZ'), name="linear_warp_estimation") # FLIRT - coregistration of functional images to anatomical images with BBR coreg_bbr = Node(FLIRT(dof=6, cost='bbr', schedule=opj(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch'), output_type='NIFTI_GZ'), name="nonlinear_warp_estimation") # Apply coregistration warp to functional images applywarp = Node(FLIRT(interp='spline', apply_isoxfm=iso_size, output_type='NIFTI'), name="registration_fmri")
def _fnirt_to_tmpl_pipeline(self, **name_maps): """ Registers a MR scan to a refernce MR scan using FSL's nonlinear FNIRT command Parameters ---------- template : Which template to use, can be one of 'mni_nl6' """ pipeline = self.new_pipeline( name='mag_coreg_to_tmpl', name_maps=name_maps, desc=("Nonlinearly registers a MR scan to a standard space," "e.g. MNI-space"), citations=[fsl_cite]) # Basic reorientation to standard MNI space reorient = pipeline.add( 'reorient', Reorient2Std( output_type='NIFTI_GZ'), inputs={ 'in_file': ('mag_preproc', nifti_gz_format)}, requirements=[fsl_req.v('5.0.8')]) reorient_mask = pipeline.add( 'reorient_mask', Reorient2Std( output_type='NIFTI_GZ'), inputs={ 'in_file': ('brain_mask', nifti_gz_format)}, requirements=[fsl_req.v('5.0.8')]) reorient_brain = pipeline.add( 'reorient_brain', Reorient2Std( output_type='NIFTI_GZ'), inputs={ 'in_file': ('brain', nifti_gz_format)}, requirements=[fsl_req.v('5.0.8')]) # Affine transformation to MNI space flirt = pipeline.add( 'flirt', interface=FLIRT( dof=12, output_type='NIFTI_GZ'), inputs={ 'reference': ('template_brain', nifti_gz_format), 'in_file': (reorient_brain, 'out_file')}, requirements=[fsl_req.v('5.0.8')], wall_time=5) # Apply mask if corresponding subsampling scheme is 1 # (i.e. 1-to-1 resolution) otherwise don't. apply_mask = [int(s == 1) for s in self.parameter('fnirt_subsampling')] # Nonlinear transformation to MNI space pipeline.add( 'fnirt', interface=FNIRT( output_type='NIFTI_GZ', intensity_mapping_model=( self.parameter('fnirt_intensity_model') if self.parameter('fnirt_intensity_model') is not None else 'none'), subsampling_scheme=self.parameter('fnirt_subsampling'), fieldcoeff_file=True, in_fwhm=[8, 6, 5, 4, 3, 2], # [8, 6, 5, 4.5, 3, 2] This threw an error because of float value @IgnorePep8, ref_fwhm=[8, 6, 5, 4, 2, 0], regularization_lambda=[300, 150, 100, 50, 40, 30], apply_intensity_mapping=[1, 1, 1, 1, 1, 0], max_nonlin_iter=[5, 5, 5, 5, 5, 10], apply_inmask=apply_mask, apply_refmask=apply_mask), inputs={ 'ref_file': ('template', nifti_gz_format), 'refmask': ('template_mask', nifti_gz_format), 'in_file': (reorient, 'out_file'), 'inmask_file': (reorient_mask, 'out_file'), 'affine_file': (flirt, 'out_matrix_file')}, outputs={ 'mag_coreg_to_tmpl': ('warped_file', nifti_gz_format), 'coreg_to_tmpl_fsl_coeff': ('fieldcoeff_file', nifti_gz_format)}, requirements=[fsl_req.v('5.0.8')], wall_time=60) # Set registration parameters # TODO: Need to work out which parameters to use return pipeline
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')