def test_Similarity_outputs(): output_map = dict(similarity=dict(), ) outputs = Similarity.output_spec() for key, metadata in output_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(outputs.traits()[key], metakey), value
def similarity_measure(file1, file2, threshold): """ Function that compares 2 Nifti inputs using a correlation metric. Nifti are equals if correlation gives Args: (string) file1: path to first nifti input (string) file2: path to second nifti to compare (float) threshold Returns: (bool) True if file1 and file2 can be considered similar enough. (superior than threshold) """ import nipype.pipeline.engine as npe import numpy as np from nipype.algorithms.metrics import Similarity # Node similarity (nipy required) img_similarity = npe.Node(name="img_similarity", interface=Similarity()) img_similarity.inputs.metric = "cc" # stands for correlation coefficient img_similarity.inputs.volume1 = file1 img_similarity.inputs.volume2 = file2 res = img_similarity.run() return np.mean(res.outputs.similarity) > threshold
def test_Similarity_inputs(): input_map = dict( ignore_exception=dict( nohash=True, usedefault=True, ), mask1=dict(), mask2=dict(), metric=dict(usedefault=True, ), volume1=dict(mandatory=True, ), volume2=dict(mandatory=True, ), ) inputs = Similarity.input_spec() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(inputs.traits()[key], metakey), value
def test_Similarity_inputs(): input_map = dict(ignore_exception=dict(nohash=True, usedefault=True, ), mask1=dict(), mask2=dict(), metric=dict(usedefault=True, ), volume1=dict(mandatory=True, ), volume2=dict(mandatory=True, ), ) inputs = Similarity.input_spec() for key, metadata in input_map.items(): for metakey, value in metadata.items(): yield assert_equal, getattr(inputs.traits()[key], metakey), value
def quality_check_image_similarity(caps_directory, tsv, ref_template, working_directory=None): """ This is a function to do a raw quality check for the preprocessed image. To mention, the preprocessing pipeline of DL includes: 1) N4 bias correction (Ants) 2) linear registration to MNI (MNI icbm152 nlinear sym template) (ANTS) 3) cropping the background to save the computational power To note, we use mutual information to quantify the similarity between the target and template MRI. Args: Returns: A tsv with an order based on the intensity differences between each individual and the template. """ import nipype.interfaces.utility as nutil import nipype.pipeline.engine as npe import tempfile from nipype.algorithms.metrics import Similarity from nipype.interfaces.fsl.preprocess import BET from T1_preprocessing_utils import get_caps_list, rank_mean if working_directory is None: working_directory = tempfile.mkdtemp() inputnode = npe.Node(nutil.IdentityInterface( fields=['caps_directory', 'tsv', 'ref_template']), name='inputnode') inputnode.inputs.caps_directory = caps_directory inputnode.inputs.tsv = tsv inputnode.inputs.ref_template = ref_template get_caps_list = npe.Node(name='get_caps_list', interface=nutil.Function( function=get_caps_list, input_names=['caps_directory', 'tsv'], output_names=['caps_intensity_nor_list'])) # get the mask of the template bet_ref_img = npe.Node(name='bet_ref_img', interface=BET()) bet_ref_img.inputs.frac = 0.5 bet_ref_img.inputs.mask = True bet_ref_img.inputs.robust = True img_similarity = npe.MapNode(name='img_similarity', iterfield=['volume1'], interface=Similarity()) img_similarity.inputs.metric = 'cc' # rand the mean intensity rank_mean = npe.Node(name='rank_mean', interface=nutil.Function(function=rank_mean, input_names=[ 'similarity', 'tsv', 'caps_directory' ], output_names=['result_tsv'])) wf = npe.Workflow(name='quality_check_dl') wf.base_dir = working_directory wf.connect([(inputnode, get_caps_list, [('caps_directory', 'caps_directory')]), (inputnode, get_caps_list, [('tsv', 'tsv')]), (inputnode, bet_ref_img, [('ref_template', 'in_file')]), (get_caps_list, img_similarity, [('caps_intensity_nor_list', 'volume1')]), (inputnode, img_similarity, [('ref_template', 'volume2')]), (bet_ref_img, img_similarity, [('mask_file', 'mask1')]), (bet_ref_img, img_similarity, [('mask_file', 'mask2')]), (inputnode, rank_mean, [('tsv', 'tsv')]), (inputnode, rank_mean, [('caps_directory', 'caps_directory')]), (img_similarity, rank_mean, [('similarity', 'similarity')])]) return wf
def create_qc_pipeline(working_dir, ds_dir, name='qc'): # initiate workflow qc_wf = Workflow(name=name) qc_wf.base_dir = os.path.join(working_dir, 'LeiCA_resting', 'rsfMRI_preprocessing') # set fsl output fsl.FSLCommand.set_default_output_type('NIFTI_GZ') # I/O NODES inputnode = Node(util.IdentityInterface(fields=[ 'subject_id', 'par_moco', 'outlier_files', 'epi_deskulled', 't1w_brain', 'mean_epi_structSpace', 'mean_epi_MNIspace', 'struct_MNIspace', 'struct_brain_mask', 'brain_mask_epiSpace', 'struct_2_MNI_warp', 'rs_preprocessed' ]), name='inputnode') outputnode = Node(util.IdentityInterface(fields=['']), name='outputnode') ds = Node(nio.DataSink(base_directory=ds_dir), name='ds') ds.inputs.substitutions = [('_TR_id_', 'TR_')] # CALCULATED POWER FD FD_power = Node(util.Function(input_names=['in_file'], output_names=['out_file'], function=calculate_FD_P), name='FD_power') qc_wf.connect(inputnode, 'par_moco', FD_power, 'in_file') qc_wf.connect(FD_power, 'out_file', ds, 'QC.FD.FD_ts') mean_FD_power = Node(util.Function( input_names=['in_file'], output_names=['mean_FD_power', 'out_file'], function=calculate_mean_FD_fct), name='mean_FD_power') qc_wf.connect(FD_power, 'out_file', mean_FD_power, 'in_file') qc_wf.connect(mean_FD_power, 'out_file', ds, 'QC.FD.FD_mean') # EXTRACT NUMBER OF SPIKES (OUTLIERS) def get_n_spikes_fct(outliers_file): import numpy as np try: spikes = np.atleast_1d(np.genfromtxt(outliers_file)) except IOError: spikes = np.empty((0)) n_spikes = len(spikes) return n_spikes get_n_spikes = Node(util.Function(input_names=['outliers_file'], output_names=['n_spikes'], function=get_n_spikes_fct), name='get_n_spikes') qc_wf.connect(inputnode, 'outlier_files', get_n_spikes, 'outliers_file') # CALCULATE TSNR tsnr_uglyname = Node(misc.TSNR(), name='tsnr_uglyname') qc_wf.connect(inputnode, 'epi_deskulled', tsnr_uglyname, 'in_file') tsnr = Node(niu.Rename(format_string='tsnr', keep_ext=True), name='tsnr') qc_wf.connect(tsnr_uglyname, 'tsnr_file', tsnr, 'in_file') qc_wf.connect(tsnr, 'out_file', ds, 'QC.tsnr') # GET MEAN TSNR IN BRAIN_MASK def get_values_inside_a_mask(main_file, mask_file, out_file): import nibabel as nb import numpy as np import os out_file = os.path.join(os.getcwd(), out_file + '.npy') main_nii = nb.load(main_file) main_data = main_nii.get_data() nan_mask = np.logical_not(np.isnan(main_data)) mask = nb.load(mask_file).get_data() > 0 data = main_data[np.logical_and(nan_mask, mask)] np.save(out_file, data) median_data = np.median(data) return (out_file, median_data) get_tsnr = Node(util.Function( input_names=['main_file', 'mask_file', 'out_file'], output_names=['out_file', 'median_data'], function=get_values_inside_a_mask), name='get_tsnr') get_tsnr.inputs.out_file = 'tsnr' qc_wf.connect(tsnr, 'out_file', get_tsnr, 'main_file') qc_wf.connect(inputnode, 'brain_mask_epiSpace', get_tsnr, 'mask_file') qc_wf.connect(get_tsnr, 'out_file', ds, 'QC.tsnr.@out_file') ## CREATE SLICES OVERLAY slices_epi_structSpace = Node(util.Function( input_names=['in_file', 'in_file2'], output_names=['out_file'], function=fsl_slices_fct), name='slices_epi_structSpace') qc_wf.connect(inputnode, 'mean_epi_structSpace', slices_epi_structSpace, 'in_file') qc_wf.connect(inputnode, 't1w_brain', slices_epi_structSpace, 'in_file2') qc_wf.connect(slices_epi_structSpace, 'out_file', ds, 'QC.slices.epi_structSpace') slices_epi_MNIspace = Node(util.Function( input_names=['in_file', 'in_file2'], output_names=['out_file'], function=fsl_slices_fct), name='slices_epi_MNIspace') slices_epi_MNIspace.inputs.in_file2 = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') qc_wf.connect(inputnode, 'mean_epi_MNIspace', slices_epi_MNIspace, 'in_file') qc_wf.connect(slices_epi_MNIspace, 'out_file', ds, 'QC.slices.epi_MNIspace') slices_struct_MNIspace = Node(util.Function( input_names=['in_file', 'in_file2'], output_names=['out_file'], function=fsl_slices_fct), name='slices_struct_MNIspace') qc_wf.connect(inputnode, 'struct_MNIspace', slices_struct_MNIspace, 'in_file') slices_struct_MNIspace.inputs.in_file2 = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') qc_wf.connect(slices_struct_MNIspace, 'out_file', ds, 'QC.slices.struct_MNIspace') # CREATE BRAIN MASK IN MNI SPACE struct_brain_mask_MNIspace = Node(fsl.ApplyWarp(), name='struct_brain_mask_MNIspace', interp='nn') struct_brain_mask_MNIspace.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') struct_brain_mask_MNIspace.inputs.out_file = 'struct_brain_mask_MNIspace.nii.gz' qc_wf.connect(inputnode, 'struct_brain_mask', struct_brain_mask_MNIspace, 'in_file') qc_wf.connect(inputnode, 'struct_2_MNI_warp', struct_brain_mask_MNIspace, 'field_file') # CREATE STRUCT_BRAIN IN MNI SPACE struct_brain_MNIspace = Node(fsl.ApplyWarp(), name='struct_brain_MNIspace') struct_brain_MNIspace.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') struct_brain_MNIspace.inputs.out_file = 'struct_MNIspace.nii.gz' qc_wf.connect(inputnode, 't1w_brain', struct_brain_MNIspace, 'in_file') qc_wf.connect(inputnode, 'struct_2_MNI_warp', struct_brain_MNIspace, 'field_file') def similarity_to_file_fct(similarity): import os import numpy as np out_file = os.path.join(os.getcwd(), 'similarity.txt') np.savetxt(out_file, np.array(similarity)) return out_file # CALCULATE SIMILARITY FOR QC similarity_epi_struct = Node(interface=Similarity(metric='nmi'), name='similarity_epi_struct') qc_wf.connect(inputnode, 'mean_epi_structSpace', similarity_epi_struct, 'volume1') qc_wf.connect(inputnode, 't1w_brain', similarity_epi_struct, 'volume2') qc_wf.connect(inputnode, 'struct_brain_mask', similarity_epi_struct, 'mask1') qc_wf.connect(inputnode, 'struct_brain_mask', similarity_epi_struct, 'mask2') similarity_epi_struct_txt = Node(util.Function( input_names=['similarity'], output_names=['out_file'], function=similarity_to_file_fct), name='similarity_epi_struct_txt') qc_wf.connect(similarity_epi_struct, 'similarity', similarity_epi_struct_txt, 'similarity') qc_wf.connect(similarity_epi_struct_txt, 'out_file', ds, 'QC.similarity.epi_struct') similarity_struct_MNI = Node(interface=Similarity(metric='nmi'), name='similarity_struct_MNI') qc_wf.connect(struct_brain_MNIspace, 'out_file', similarity_struct_MNI, 'volume1') similarity_struct_MNI.inputs.volume2 = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') qc_wf.connect(struct_brain_mask_MNIspace, 'out_file', similarity_struct_MNI, 'mask1') qc_wf.connect(struct_brain_mask_MNIspace, 'out_file', similarity_struct_MNI, 'mask2') similarity_struct_MNI_txt = Node(util.Function( input_names=['similarity'], output_names=['out_file'], function=similarity_to_file_fct), name='similarity_struct_MNI_txt') qc_wf.connect(similarity_struct_MNI, 'similarity', similarity_struct_MNI_txt, 'similarity') qc_wf.connect(similarity_struct_MNI_txt, 'out_file', ds, 'QC.similarity.struct_MNI') def list_to_num(lst): return lst[0] def create_qc_df_fct(subject_id, similarity_epi_struct, similarity_struct_MNI, mean_FD_Power, n_spikes, median_tsnr): import pandas as pd import os out_file_df = os.path.join(os.getcwd(), 'qc_values.pkl') out_file_txt = os.path.join(os.getcwd(), 'qc_values.txt') data = [ subject_id, similarity_epi_struct, similarity_struct_MNI, mean_FD_Power, n_spikes, median_tsnr ] header = [ 'subject_id', 'similarity_epi_struct', 'similarity_struct_MNI', 'mean_FD_Power', 'n_spikes', 'median_tsnr' ] df = pd.DataFrame([data], columns=header) df = df.set_index(df.subject_id) df.to_pickle(out_file_df) df.to_csv(out_file_txt, sep='\t') return (out_file_df, out_file_txt) create_qc_df = Node(util.Function( input_names=[ 'subject_id', 'similarity_epi_struct', 'similarity_struct_MNI', 'mean_FD_Power', 'n_spikes', 'median_tsnr' ], output_names=['out_file_df', 'out_file_txt'], function=create_qc_df_fct), name='create_qc_df') qc_wf.connect(inputnode, 'subject_id', create_qc_df, 'subject_id') qc_wf.connect(similarity_epi_struct, ('similarity', list_to_num), create_qc_df, 'similarity_epi_struct') qc_wf.connect(similarity_struct_MNI, ('similarity', list_to_num), create_qc_df, 'similarity_struct_MNI') qc_wf.connect(mean_FD_power, 'mean_FD_power', create_qc_df, 'mean_FD_Power') qc_wf.connect(get_n_spikes, 'n_spikes', create_qc_df, 'n_spikes') qc_wf.connect(get_tsnr, 'median_data', create_qc_df, 'median_tsnr') qc_wf.connect(create_qc_df, 'out_file_df', ds, 'QC.df.@df') qc_wf.connect(create_qc_df, 'out_file_txt', ds, 'QC.df.@txt') qc_wf.write_graph(dotfilename=qc_wf.name, graph2use='flat', format='pdf') return qc_wf