def get_files(): with open('dset_config.json', 'r') as fo: CONFIG = json.load(fo) DATA_DIR = op.abspath('/home/data/nbc/external-datasets/ds001491/') all_info = {} for dset_name in list(CONFIG.keys())[:3]: layout = BIDSLayout(op.join(DATA_DIR, dset_name)) cfg = CONFIG[dset_name] task = cfg['task'] dset_info = {} for sub in layout.get_subjects(): runs = layout.get_runs(subject=sub, task=task) sub_info = {} for run in runs: run_info = {} run_info['files'] = [] run_info['echo_times'] = [] for echo in sorted( layout.get_echoes(subject=sub, task=task, run=run)): raw_files = layout.get(subject=sub, task=task, run=run, echo=echo, extensions='.nii.gz') preproc_files = layout.get(subject=sub, task=task, run=run, root='afni-step1', echo=echo, extensions='.nii.gz', desc='realign') preproc_files = raw_files[:] if len(preproc_files) != 1: print(preproc_files) raise Exception('BAD') # Replace filename with path when using new version of bids run_info['files'].append(preproc_files[0].filename) metadata = layout.get_metadata(preproc_files[0].filename) run_info['echo_times'].append(metadata['EchoTime']) sub_info[run] = run_info dset_info[sub] = sub_info all_info[dset_name] = dset_info with open('all_files.json', 'w') as fo: json.dump(all_info, fo, indent=4, sort_keys=True)
fmap_args = { "fmapmag": "NONE", "fmapphase": "NONE", "echodiff": "NONE", "t1samplespacing": "NONE", "t2samplespacing": "NONE", "unwarpdir": "NONE", "avgrdcmethod": "NONE", "SEPhaseNeg": "NONE", "SEPhasePos": "NONE", "echospacing": "NONE", "seunwarpdir": "NONE" } if fieldmap_set: t1_spacing = layout.get_metadata(t1ws[0])["DwellTime"] t2_spacing = layout.get_metadata(t2ws[0])["DwellTime"] # use an unwarpdir specified on the command line # this is different from the SE direction unwarpdir = args.anat_unwarpdir fmap_args.update({ "t1samplespacing": "%.8f" % t1_spacing, "t2samplespacing": "%.8f" % t2_spacing, "unwarpdir": unwarpdir }) if fieldmap_set[0]["suffix"] == "phasediff": merged_file = "%s/tmp/%s/magfile.nii.gz" % (args.output_dir, subject_label)
def find_data(self, subject_ids=None, visit_ids=None): """ Return subject and session information for a project in the local repository Parameters ---------- subject_ids : list(str) List of subject IDs with which to filter the tree with. If None all are returned visit_ids : list(str) List of visit IDs with which to filter the tree with. If None all are returned Returns ------- project : arcana.repository.Tree A hierarchical tree of subject, session and fileset information for the repository """ filesets = [] layout = BIDSLayout(self.root_dir) all_subjects = layout.get_subjects() all_visits = layout.get_sessions() if not all_visits: all_visits = [self.DEFAULT_VISIT_ID] self._depth = 1 else: self._depth = 2 for item in layout.get(return_type='object'): if item.path.startswith(self.derivatives_dir): # We handle derivatives using the BasicRepo base # class methods continue if not hasattr(item, 'entities') or not item.entities.get('suffix', False): logger.warning("Skipping unrecognised file '{}' in BIDS tree" .format(op.join(item.dirname, item.filename))) continue # Ignore hidden file try: subject_ids = [item.entities['subject']] except KeyError: # If item exists in top-levels of in the directory structure # it is inferred to exist for all subjects in the tree subject_ids = all_subjects try: visit_ids = [item.entities['session']] except KeyError: # If item exists in top-levels of in the directory structure # it is inferred to exist for all visits in the tree visit_ids = all_visits for subject_id in subject_ids: for visit_id in visit_ids: aux_files = {} metadata = layout.get_metadata(item.path) if metadata and not item.path.endswith('.json'): # Write out the combined JSON side cars to a temporary # file to include in extended NIfTI filesets metadata_path = op.join( self.metadata_dir, 'sub-{}'.format(subject_id), 'ses-{}'.format(visit_id), item.filename + '.json') os.makedirs(op.dirname(metadata_path), exist_ok=True) if not op.exists(metadata_path): with open(metadata_path, 'w') as f: json.dump(metadata, f) aux_files['json'] = metadata_path fileset = BidsFileset( path=op.join(item.dirname, item.filename), type=item.entities['suffix'], subject_id=subject_id, visit_id=visit_id, repository=self, modality=item.entities.get('modality', None), task=item.entities.get('task', None), aux_files=aux_files) filesets.append(fileset) # Get derived filesets, fields and records using the same method using # the method in the BasicRepo base class derived_filesets, fields, records = super().find_data( subject_ids=subject_ids, visit_ids=visit_ids) filesets.extend(derived_filesets) return filesets, fields, records
def main(): parser = makeParser() results = parser.parse_args() if results.boutiques: createDescriptor(parser, results) return 0 verb = results.verbose fsldir = results.fsldir mni152 = op.join(fsldir, "data", "standard", "MNI152_T1_2mm_brain.nii.gz") mni152bn = op.basename(mni152).split(".")[0] outdir = results.output_dir partis = results.participant_label labels = results.parcellation if verb: print("BIDS Dir: {0}".format(results.bids_dir), flush=True) print("Output Dir: {0}".format(results.output_dir), flush=True) print("Analysis level: {0}".format(results.analysis_level), flush=True) # This preprocessing workflow is modified from the FSL recommendations here: # https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FDT/UserGuide # Step 0, 1: Begin interrogation of BIDS dataset # Due to current super-linear slowdown in BIDS Layout, exclude all but # participant of interest. Explored in the following Github issue: # https://github.com/bids-standard/pybids/issues/285 if partis is not None: pattrn = 'sub-(?!{0})(.*)$'.format("|".join(partis)) else: pattrn = '' dset = BIDSLayout(results.bids_dir, exclude=pattrn) subjects = dset.get_subjects() if results.participant_label is not None: subjects = [pl for pl in results.participant_label if pl in subjects] assert (len(subjects) > 0) if verb: print("Participants: {0}".format(", ".join(s for s in subjects)), flush=True) sessions = dset.get_sessions() if results.session_label is not None: sessions = [sl for sl in results.session_label if sl in sessions] assert (len(sessions) > 0) if verb: print("Sessions: {0}".format(", ".join(s for s in sessions)), flush=True) # Step 0, 2: Prune dataset to subjects/sessions that have necessary files ftypes = [".nii", ".bval", ".bvec"] collections = [] for subj in subjects: for sess in sessions: tf_dwi = dset.get(subject=subj, session=sess, datatype="dwi", suffix="dwi", return_type="file") tf_anat = dset.get(subject=subj, session=sess, datatype="anat", suffix="T1w", return_type="file") if (all(any(ftype in fl for fl in tf_dwi) for ftype in ftypes) and any(ftypes[0] in fl for fl in tf_anat)): collections += [{ "subject": subj, "session": sess, "anat": [t for t in tf_anat if ftypes[0] in t][0], "bval": [t for t in tf_dwi if ftypes[1] in t][0], "bvec": [t for t in tf_dwi if ftypes[2] in t][0], "dwi": [t for t in tf_dwi if ftypes[0] in t][0] }] else: if verb: print("Skipping sub-{0}".format(subj) + " / ses-{0} due to missing data.".format(sess), flush=True) complete_collection = [] for col in collections: dwibn = op.basename(col["dwi"]).split('.')[0] anatbn = op.basename(col["anat"]).split('.')[0] subses = op.join('sub-{0}'.format(col['subject']), 'ses-{0}'.format(col['session'])) derivdir_d = op.join(outdir, subses, "dwi") derivdir_a = op.join(outdir, subses, "anat") execute("mkdir -p {0}".format(derivdir_d), verbose=verb, skipif=op.isdir(derivdir_d)) execute("mkdir -p {0}".format(derivdir_a), verbose=verb, skipif=op.isdir(derivdir_a)) # Step 1: Extract B0 volumes # Make even number of spatial voxels? (req'd for eddy for some reason) # TODO : above, if actually needed - docs inconsistent # Get B0 locations with open(col["bval"]) as fhandle: bvals = fhandle.read().split(" ") bvals = [int(b) for b in bvals if b != '' and b != '\n'] b0_loc = [i for i, b in enumerate(bvals) if b == np.min(bvals)] # Get B0 volumes col["b0_scans"] = [] for idx, b0 in enumerate(b0_loc): b0ind = "b0_{0}".format(idx) col["b0_scans"] += [ op.join(derivdir_d, dwibn + "_" + b0ind + ".nii.gz") ] execute(fsl.fslroi(col["dwi"], col["b0_scans"][-1], *[b0, 1]), verbose=verb, skipif=op.isfile(col["b0_scans"][-1])) # Merge B0 volumes col["b0s"] = op.join(derivdir_d, dwibn + "_b0s.nii.gz") execute(fsl.fslmerge(col["b0s"], *col["b0_scans"]), verbose=verb, skipif=op.isfile(col["b0s"])) # Create acquisition parameters file col["acqparams"] = op.join(derivdir_d, dwibn + "_acq.txt") acqs = { "i": "1 0 0", "i-": "-1 0 0", "j": "0 1 0", "j-": "0 -1 0", "k": "0 0 1", "k-": "0 0 -1" } with open(col["acqparams"], 'w') as fhandle: meta = dset.get_metadata(path=col["dwi"]) pedir = meta["PhaseEncodingDirection"] trout = meta["TotalReadoutTime"] line = "{0} {1}".format(acqs[pedir], trout) fhandle.write("\n".join([line] * len(b0_loc))) # Step 1.5: Run Top-up on Diffusion data # TODO: remove; topup only applies with multiple PEs (rare in open data) # col["topup"] = op.join(derivdir_d, dwibn + "_topup") # col["hifi_b0"] = op.join(derivdir_d, dwibn + "_hifi_b0") # execute(fsl.topup(col["b0s"], col["acqparams"], # col["topup"], col["hifi_b0"]), # verbose=verb) # execute(fsl.fslmaths(col["hifi_b0"], "-Tmean", col["hifi_b0"]), # verbose=verb) # Step 2: Brain extraction # ... Diffusion: col["dwi_brain"] = op.join(derivdir_d, dwibn + "_brain.nii.gz") col["dwi_mask"] = op.join(derivdir_d, dwibn + "_brain_mask.nii.gz") execute(fsl.bet(col["dwi"], col["dwi_brain"], "-F", "-m"), verbose=verb, skipif=op.isfile(col["dwi_brain"])) # ... Structural: col["anat_brain"] = op.join(derivdir_a, anatbn + "_brain.nii.gz") col["anat_mask"] = op.join(derivdir_a, anatbn + "_brain.nii.gz") execute(fsl.bet(col["anat"], col["anat_brain"], "-m"), verbose=verb, skipif=op.isfile(col["anat_brain"])) # Step 3: Produce prelimary DTIfit QC figures col["dwi_qc_pre"] = op.join(derivdir_d, dwibn + "_dtifit_pre") execute(fsl.dtifit(col["dwi_brain"], col["dwi_qc_pre"], col["dwi_mask"], col["bvec"], col["bval"]), verbose=verb, skipif=op.isfile(col["dwi_qc_pre"] + "_FA.nii.gz")) # Step 4: Perform eddy correction # ... Create index col["index"] = op.join(derivdir_d, dwibn + "_eddy_index.txt") with open(col["index"], 'w') as fhandle: fhandle.write(" ".join(["1"] * len(bvals))) # ... Run eddy col["eddy_dwi"] = op.join(derivdir_d, dwibn + "_eddy") if results.gpu: eddy_exe = "eddy_cuda8.0" else: eddy_exe = "eddy_openmp" execute(fsl.eddy(col["dwi_brain"], col["dwi_mask"], col["acqparams"], col["index"], col["bvec"], col["bval"], col["eddy_dwi"], exe=eddy_exe), verbose=verb, skipif=op.isfile(col["eddy_dwi"] + ".nii.gz")) # Step 5: Registration to template # ... Compute transforms col["t1w2mni"] = op.join(derivdir_a, anatbn + "_to_mni_xfm.mat") execute(fsl.flirt(col["anat_brain"], omat=col["t1w2mni"], ref=mni152), verbose=verb, skipif=op.isfile(col["t1w2mni"])) col["dwi2t1w"] = op.join(derivdir_d, dwibn + "_to_t1w_xfm.mat") execute(fsl.flirt(col["eddy_dwi"], ref=col["anat_brain"], omat=col["dwi2t1w"]), verbose=verb, skipif=op.isfile(col["dwi2t1w"])) col["dwi2mni"] = op.join(derivdir_d, dwibn + "_to_mni_xfm.mat") execute(fsl.convert_xfm(concat=col["t1w2mni"], inp=col["dwi2t1w"], omat=col["dwi2mni"]), verbose=verb, skipif=op.isfile(col["dwi2mni"])) # ... Invert transforms towards diffusion space col["mni2dwi"] = op.join(derivdir_d, dwibn + "_from_mni_xfm.mat") execute(fsl.convert_xfm(inverse=col["dwi2mni"], omat=col["mni2dwi"]), verbose=verb, skipif=op.isfile(col["mni2dwi"])) col["t1w2dwi"] = op.join(derivdir_a, anatbn + "_dwi_xfm.mat") execute(fsl.convert_xfm(inverse=col["dwi2t1w"], omat=col["t1w2dwi"]), verbose=verb, skipif=op.isfile(col["t1w2dwi"])) # Step 6: Apply registrations to anatomical and template images col["anat_in_dwi"] = op.join(derivdir_a, anatbn + "_brain_dwi.nii.gz") execute(fsl.flirt(col["anat_brain"], applyxfm=True, out=col["anat_in_dwi"], init=col["t1w2dwi"], ref=col["eddy_dwi"]), verbose=verb, skipif=op.isfile(col["anat_in_dwi"])) col["mni_in_dwi"] = op.join( derivdir_d, ("atlas_" + dwibn + "_" + mni152bn + "_dwi.nii.gz")) execute(fsl.flirt(mni152, applyxfm=True, out=col["mni_in_dwi"], init=col["mni2dwi"], ref=col["eddy_dwi"]), verbose=verb, skipif=op.isfile(col["mni_in_dwi"])) # Step 7: Perform tissue segmentation on anatomical images in DWI space col["tissue_masks"] = op.join(derivdir_d, anatbn + "_fast") execute(fsl.fast(col["anat_in_dwi"], col["tissue_masks"], classes=3, imtype=1), verbose=verb, skipif=op.isfile(col["tissue_masks"] + "_seg_2.nii.gz")) # Step 8: Transform parcellations into DWI space col["labels_in_dwi"] = [] for label in labels: lbn = op.basename(label).split('.')[0] col["labels_in_dwi"] += [ op.join(derivdir_d, ("labels_" + dwibn + "_" + lbn + ".nii.gz")) ] execute(fsl.flirt(label, applyxfm=True, out=col["labels_in_dwi"][-1], init=col["mni2dwi"], ref=col["eddy_dwi"], interp="nearestneighbour"), verbose=verb, skipif=op.isfile(col["labels_in_dwi"][-1])) if verb: print("Finished processing sub-{0}".format(subj) + " / ses-{0} !".format(sess), flush=True) complete_collection += [col]
def run_rsHRF(): parser = get_parser() args = parser.parse_args() arg_groups = {} for group in parser._action_groups: group_dict = { a.dest: getattr(args, a.dest, None) for a in group._group_actions } arg_groups[group.title] = group_dict para = arg_groups['Parameters'] nargs = len(sys.argv) temporal_mask = [] if (not args.GUI) and (args.output_dir is None): parser.error( '--output_dir is required when executing in command-line interface' ) if (not args.GUI) and (args.estimation is None): parser.error( '--estimation rule is required when executing in command-line interface' ) if (args.GUI): if (nargs == 2): try: from .rsHRF_GUI import run run.run() except ModuleNotFoundError: parser.error( '--GUI should not be used inside a Docker container') else: parser.error('--no other arguments should be supplied with --GUI') if (args.input_file is not None or args.ts is not None) and args.analysis_level: parser.error( 'analysis_level cannot be used with --input_file or --ts, do not supply it' ) if (args.input_file is not None or args.ts is not None) and args.participant_label: parser.error( 'participant_labels are not to be used with --input_file or --ts, do not supply it' ) if args.input_file is not None and args.brainmask: parser.error( '--brainmask cannot be used with --input_file, use --atlas instead' ) if args.ts is not None and (args.brainmask or args.atlas): parser.error( '--atlas or --brainmask cannot be used with --ts, do not supply it' ) if args.bids_dir is not None and not (args.brainmask or args.atlas): parser.error( '--atlas or --brainmask needs to be supplied with --bids_dir') if args.bids_dir is not None and not args.analysis_level: parser.error( 'analysis_level needs to be supplied with bids_dir, choices=[participant]' ) if args.input_file is not None and (not args.input_file.endswith( ('.nii', '.nii.gz', '.gii', '.gii.gz'))): parser.error( '--input_file should end with .gii, .gii.gz, .nii or .nii.gz') if args.atlas is not None and (not args.atlas.endswith( ('.nii', '.nii.gz', '.gii', '.gii.gz'))): parser.error('--atlas should end with .gii, .gii.gz, .nii or .nii.gz') if args.ts is not None and (not args.ts.endswith(('.txt'))): parser.error('--ts file should end with .txt') if args.temporal_mask is not None and (not args.temporal_mask.endswith( ('.dat'))): parser.error('--temporal_mask ile should end with ".dat"') if args.temporal_mask is not None: f = open(args.temporal_mask, 'r') for line in f: for each in line: if each in ['0', '1']: temporal_mask.append(int(each)) if args.estimation == 'sFIR' or args.estimation == 'FIR': para['T'] = 1 if args.ts is not None: file_type = op.splitext(args.ts) if para['TR'] <= 0: parser.error('Please supply a valid TR using -TR argument') else: TR = para['TR'] para['dt'] = para['TR'] / para['T'] para['lag'] = np.arange(np.fix(para['min_onset_search'] / para['dt']), np.fix(para['max_onset_search'] / para['dt']) + 1, dtype='int') fourD_rsHRF.demo_rsHRF(args.ts, None, args.output_dir, para, args.n_jobs, file_type, mode='time-series', temporal_mask=temporal_mask, wiener=args.wiener) if args.input_file is not None: if args.atlas is not None: if (args.input_file.endswith( ('.nii', '.nii.gz')) and args.atlas.endswith( ('.gii', '.gii.gz'))) or (args.input_file.endswith( ('.gii', '.gii.gz')) and args.atlas.endswith( ('.nii', '.nii.gz'))): parser.error( '--atlas and input_file should be of the same type [NIfTI or GIfTI]' ) # carry analysis with input_file and atlas file_type = op.splitext(args.input_file) if file_type[-1] == ".gz": file_type = op.splitext(file_type[-2])[-1] + file_type[-1] else: file_type = file_type[-1] if ".nii" in file_type: TR = (spm_dep.spm.spm_vol(args.input_file).header.get_zooms())[-1] else: if para['TR'] == -1: parser.error('Please supply a valid TR using -TR argument') else: TR = para['TR'] if TR <= 0: if para['TR'] <= 0: parser.error('Please supply a valid TR using -TR argument') else: if para['TR'] == -1: para['TR'] = TR elif para['TR'] <= 0: print('Invalid TR supplied, using implicit TR: {0}'.format(TR)) para['TR'] = TR para['dt'] = para['TR'] / para['T'] para['lag'] = np.arange(np.fix(para['min_onset_search'] / para['dt']), np.fix(para['max_onset_search'] / para['dt']) + 1, dtype='int') fourD_rsHRF.demo_rsHRF(args.input_file, args.atlas, args.output_dir, para, args.n_jobs, file_type, mode='input', temporal_mask=temporal_mask, wiener=args.wiener) if args.bids_dir is not None: utils.bids.write_derivative_description(args.bids_dir, args.output_dir) bids_dir = Path(args.bids_dir) fname = bids_dir / 'dataset_description.json' if fname.exists(): desc = json.loads(Path(fname).read_text()) if 'DataType' in desc: if desc['DataType'] != 'derivative': parser.error( 'Input data is not a derivative dataset' ' (DataType in dataset_description.json is not equal to "derivative")' ) else: parser.error( 'DataType is not defined in the dataset_description.json file. Please make sure DataType is defined. ' 'Information on the dataset_description.json file can be found online ' '(https://bids-specification.readthedocs.io/en/stable/03-modality-agnostic-files.html' '#derived-dataset-and-pipeline-description)') else: parser.error( 'Could not find dataset_description.json file. Please make sure the BIDS data ' 'structure is present and correct. Datasets can be validated online ' 'using the BIDS Validator (http://incf.github.io/bids-validator/).' ) if args.bids_dir is not None and args.atlas is not None: # carry analysis with bids_dir and 1 atlas layout = BIDSLayout(args.bids_dir, validate=False, config=['bids', 'derivatives']) if args.participant_label: input_subjects = args.participant_label subjects_to_analyze = layout.get_subjects(subject=input_subjects) else: subjects_to_analyze = layout.get_subjects() if not subjects_to_analyze: parser.error( 'Could not find participants. Please make sure the BIDS data ' 'structure is present and correct. Datasets can be validated online ' 'using the BIDS Validator (http://incf.github.io/bids-validator/).' ) if not args.atlas.endswith(('.nii', '.nii.gz')): parser.error('--atlas should end with .nii or .nii.gz') if args.bids_filter_file is not None: filter_list = json.loads(Path(args.bids_filter_file).read_text()) default_input = { 'extension': 'nii.gz', 'datatype': 'func', 'desc': 'preproc', 'task': 'rest', 'suffix': 'bold' } default_input['subject'] = subjects_to_analyze default_input.update(filter_list['bold']) all_inputs = layout.get(return_type='filename', **default_input) else: all_inputs = layout.get(return_type='filename', datatype='func', subject=subjects_to_analyze, task='rest', desc='preproc', suffix='bold', extension=['nii', 'nii.gz']) if not all_inputs != []: parser.error( 'There are no files of type *bold.nii / *bold.nii.gz ' 'Please make sure to have at least one file of the above type ' 'in the BIDS specification') else: num_errors = 0 for file_count in range(len(all_inputs)): try: TR = layout.get_metadata( all_inputs[file_count])['RepetitionTime'] except KeyError as e: TR = spm_dep.spm.spm_vol( all_inputs[file_count]).header.get_zooms()[-1] para['TR'] = TR para['dt'] = para['TR'] / para['T'] para['lag'] = np.arange( np.fix(para['min_onset_search'] / para['dt']), np.fix(para['max_onset_search'] / para['dt']) + 1, dtype='int') num_errors += 1 try: fourD_rsHRF.demo_rsHRF(all_inputs[file_count], args.atlas, args.output_dir, para, args.n_jobs, file_type, mode='bids w/ atlas', temporal_mask=temporal_mask, wiener=args.wiener) num_errors -= 1 except ValueError as err: print(err.args[0]) except: print("Unexpected error:", sys.exc_info()[0]) success = len(all_inputs) - num_errors if success == 0: raise RuntimeError( 'Dimensions were inconsistent for all input-mask pairs; \n' 'No inputs were processed!') if args.bids_dir is not None and args.brainmask: # carry analysis with bids_dir and brainmask layout = BIDSLayout(args.bids_dir, validate=False, config=['bids', 'derivatives']) if args.participant_label: input_subjects = args.participant_label subjects_to_analyze = layout.get_subjects(subject=input_subjects) else: subjects_to_analyze = layout.get_subjects() if not subjects_to_analyze: parser.error( 'Could not find participants. Please make sure the BIDS data ' 'structure is present and correct. Datasets can be validated online ' 'using the BIDS Validator (http://incf.github.io/bids-validator/).' ) if args.bids_filter_file is not None: filter_list = json.loads(Path(args.bids_filter_file).read_text()) default_input = { 'extension': 'nii.gz', 'datatype': 'func', 'desc': 'preproc', 'task': 'rest', 'suffix': 'bold' } default_input['subject'] = subjects_to_analyze default_input.update(filter_list['bold']) all_inputs = layout.get(return_type='filename', **default_input) default_mask = { 'extension': 'nii.gz', 'datatype': 'func', 'desc': 'brain', 'task': 'rest', 'suffix': 'mask' } default_mask['subject'] = subjects_to_analyze default_mask.update(filter_list['mask']) all_masks = layout.get(return_type='filename', **default_mask) else: all_inputs = layout.get(return_type='filename', datatype='func', subject=subjects_to_analyze, task='rest', desc='preproc', suffix='bold', extension=['nii', 'nii.gz']) all_masks = layout.get(return_type='filename', datatype='func', subject=subjects_to_analyze, task='rest', desc='brain', suffix='mask', extension=['nii', 'nii.gz']) if not all_inputs != []: parser.error( 'There are no files of type *bold.nii / *bold.nii.gz ' 'Please make sure to have at least one file of the above type ' 'in the BIDS specification') if not all_masks != []: parser.error( 'There are no files of type *mask.nii / *mask.nii.gz ' 'Please make sure to have at least one file of the above type ' 'in the BIDS specification') if len(all_inputs) != len(all_masks): parser.error( 'The number of *bold.nii / .nii.gz and the number of ' '*mask.nii / .nii.gz are different. Please make sure that ' 'there is one mask for each input_file present') all_inputs.sort() all_masks.sort() all_prefix_match = False prefix_match_count = 0 for i in range(len(all_inputs)): input_prefix = all_inputs[i].split('/')[-1].split('_desc')[0] mask_prefix = all_masks[i].split('/')[-1].split('_desc')[0] if input_prefix == mask_prefix: prefix_match_count += 1 else: all_prefix_match = False break if prefix_match_count == len(all_inputs): all_prefix_match = True if not all_prefix_match: parser.error( 'The mask and input files should have the same prefix for correspondence. ' 'Please consider renaming your files') else: num_errors = 0 for file_count in range(len(all_inputs)): file_type = all_inputs[file_count].split('bold')[1] if file_type == ".nii" or file_type == ".nii.gz": try: TR = layout.get_metadata( all_inputs[file_count])['RepetitionTime'] except KeyError as e: TR = spm_dep.spm.spm_vol( all_inputs[file_count]).header.get_zooms()[-1] para['TR'] = TR else: spm_dep.spm.spm_vol(all_inputs[file_count]) TR = spm_dep.spm.spm_vol( all_inputs[file_count]).get_arrays_from_intent( "NIFTI_INTENT_TIME_SERIES")[0].meta.get_metadata( )["TimeStep"] para['TR'] = float(TR) * 0.001 para['dt'] = para['TR'] / para['T'] para['lag'] = np.arange( np.fix(para['min_onset_search'] / para['dt']), np.fix(para['max_onset_search'] / para['dt']) + 1, dtype='int') num_errors += 1 try: fourD_rsHRF.demo_rsHRF(all_inputs[file_count], all_masks[file_count], args.output_dir, para, args.n_jobs, mode='bids', temporal_mask=temporal_mask, wiener=args.wiener) num_errors -= 1 except ValueError as err: print(err.args[0]) except: print("Unexpected error:", sys.exc_info()[0]) success = len(all_inputs) - num_errors if success == 0: raise RuntimeError( 'Dimensions were inconsistent for all input-mask pairs; \n' 'No inputs were processed!')
return_type='file')[0] subjInfo = pd.read_csv(file_participants, delimiter='\t') # IMAGE META DATA # Images for sub-01 listImages_sub01 = layout.get(subject='01', extension=['nii', 'nii.gz'], return_type='file') # meta data asccoiated with T1 weighted metaT1w = layout.get_metadata(listImages_sub01[0]) # meta data associated with fMRI (run1) metafMRI = layout.get_metadata(listImages_sub01[1]) # locations of meta data files (T1w) metalocT1w = layout.get(suffix='T1w', extension='json', return_type='file') # TASK EVENTS # Task events tsv file for sub-01, run-1
def get_niftis(datapath, subject_id=[]): """ Loads BIDS formatted files. """ from bids.layout import BIDSLayout # Get rid of "sub" from "sub-xx" subject_id = subject_id[-2:] layout = BIDSLayout(datapath) from bids.layout import BIDSLayout # Get rid of "sub" from "sub-xx" subject_id = subject_id[-2:] layout = BIDSLayout(datapath) func = layout.get(subject=subject_id, modality='func', type='bold', task='SPINN', return_type='file', extensions=['nii', 'nii.gz']) # Whole brain EPI wb = layout.get(subject=subject_id, modality='func', type='bold', task='wholehead', return_type='file', extensions=['nii', 'nii.gz'])[0] func_des = layout.get(subject=subject_id, modality='func', type='bold', return_type='file', extensions=['json']) UNI = layout.get(subject=subject_id, modality='anat', type='UNI', return_type='file', extensions=['nii', 'nii.gz']) events = layout.get(subject=subject_id, modality='func', type='events', return_type='file', extensions=['txt', 'tsv']) physio = layout.get(subject=subject_id, modality='func', type='physio', return_type='file', extensions=['txt', 'tsv']) fmaps = layout.get(subject=subject_id, modality='fmap', return_type='file', extensions=['nii', 'nii.gz']) subject_id = 'sub-' + subject_id fmapMag = [f for f in fmaps if layout.get_metadata(f)[ 'ImageType'][2] == 'M'] fmapPh = [f for f in fmaps if layout.get_metadata( f)['ImageType'][2] == 'P'][0] if not fmapMag == []: fmapM1, fmapM2 = fmapMag else: fmapM1, fmapM2 = [], [] return (func, wb, events, physio, UNI, fmapM1, fmapPh, subject_id)
def main(argv=sys.argv): parser = generate_parser() args = parser.parse_args() # Set environment variables for FSL dir based on CLI os.environ['FSL_DIR'] = args.fsl_dir os.environ['FSLDIR'] = args.fsl_dir # for this script's usage of FSL_DIR... fsl_dir = args.fsl_dir + '/bin' # Load the bids layout layout = BIDSLayout(args.bids_dir) subsess = read_bids_layout(layout, subject_list=args.subject_list, collect_on_subject=args.collect) for subject,sessions in subsess: # fmap directory = base dir fmap = layout.get(subject=subject, session=sessions, modality='fmap', extensions='.nii.gz') base_temp_dir = os.path.dirname(fmap[0].filename) # Check if fieldmaps are concatenated if layout.get(subject=subject, session=sessions, modality='fmap', extensions='.nii.gz', acq='func', dir='both'): print("Func fieldmaps are concatenated. Running seperate_concatenate_fm") seperate_concatenated_fm(layout, subject, sessions, fsl_dir) # recreate layout with the additional SEFMS layout = BIDSLayout(args.bids_dir) fmap = layout.get(subject=subject, session=sessions, modality='fmap', extensions='.nii.gz', acq='func') # Check if there are func fieldmaps and return a list of each SEFM pos/neg pair if fmap: print("Running SEFM select") bes_pos, best_neg = sefm_select(layout, subject, sessions, base_temp_dir, fsl_dir, args.mre_dir, args.debug) for sefm in [x.filename for x in fmap]: sefm_json = sefm.replace('.nii.gz', '.json') sefm_metadata = layout.get_metadata(sefm) if 'Philips' in sefm_metadata['Manufacturer']: insert_edit_json(sefm_json, 'EffectiveEchoSpacing', 0.00062771) if 'GE' in sefm_metadata['Manufacturer']: insert_edit_json(sefm_json, 'EffectiveEchoSpacing', 0.000536) if 'Siemens' in sefm_metadata['Manufacturer']: insert_edit_json(sefm_json, 'EffectiveEchoSpacing', 0.000510012) # Check if there are dwi fieldmaps and insert IntendedFor field accordingly if layout.get(subject=subject, session=sessions, modality='fmap', extensions='.nii.gz', acq='dwi'): print("Editing DWI jsons") edit_dwi_jsons(layout, subject, sessions) # Additional edits to the anat json sidecar anat = layout.get(subject=subject, session=sessions, modality='anat', extensions='.nii.gz') if anat: for TX in [x.filename for x in anat]: TX_json = TX.replace('.nii.gz', '.json') TX_metadata = layout.get_metadata(TX) #if 'T1' in TX_metadata['SeriesDescription']: if 'Philips' in TX_metadata['Manufacturer']: insert_edit_json(TX_json, 'DwellTime', 0.00062771) if 'GE' in TX_metadata['Manufacturer']: insert_edit_json(TX_json, 'DwellTime', 0.000536) if 'Siemens' in TX_metadata['Manufacturer']: insert_edit_json(TX_json, 'DwellTime', 0.000510012) # add EffectiveEchoSpacing if it doesn't already exist # PE direction vs axis func = layout.get(subject=subject, session=sessions, modality='func', extensions='.nii.gz') if func: for task in [x.filename for x in func]: task_json = task.replace('.nii.gz', '.json') task_metadata = layout.get_metadata(task) if 'Philips' in task_metadata['Manufacturer']: insert_edit_json(task_json, 'EffectiveEchoSpacing', 0.00062771) if 'GE' in task_metadata['Manufacturer']: if 'DV25' in task_metadata['SoftwareVersions']: insert_edit_json(task_json, 'EffectiveEchoSpacing', 0.000536) if 'DV26' in task_metadata['SoftwareVersions']: insert_edit_json(task_json, 'EffectiveEchoSpacing', 0.000556) if 'Siemens' in task_metadata['Manufacturer']: insert_edit_json(task_json, 'EffectiveEchoSpacing', 0.000510012) if "PhaseEncodingAxis" in task_metadata: insert_edit_json(task_json, 'PhaseEncodingDirection', task_metadata['PhaseEncodingAxis']) elif "PhaseEncodingDirection" in task_metadata: insert_edit_json(task_json, 'PhaseEncodingAxis', task_metadata['PhaseEncodingDirection'].strip('-'))