def __init__(self, dataset_dir, overwrite=False): print('Initializing BIDS dataset directory tree in %s' % dataset_dir) self.bids_dir = dataset_dir self.derivatives_dir = os.path.join(dataset_dir, 'derivatives') self.sourcedata_dir = os.path.join(dataset_dir, 'sourcedata') self.code_dir = os.path.join(dataset_dir, 'code') self.work_dir = os.path.join(dataset_dir, 'work') bio.safe_mkdir(self.derivatives_dir) bio.safe_mkdir(self.sourcedata_dir) bio.safe_mkdir(self.code_dir) bio.safe_mkdir(self.work_dir) self.translator_file = os.path.join(self.code_dir, 'Protocol_Translator.json') print('Creating required file templates') # README file self.readme_file = os.path.join(dataset_dir, 'README') with open(self.readme_file, 'w') as fd: fd.writelines('Useful information about this dataset\n') # CHANGES changelog file self.changes_file = os.path.join(dataset_dir, 'CHANGES') with open(self.changes_file, 'w') as fd: fd.writelines(['1.0.0 YYYY-MM-DD\n', ' - Initial release\n']) # Create template JSON dataset description (must comply with BIDS 1.2 spec) self.datadesc_json = os.path.join(self.bids_dir, 'dataset_description.json') meta_dict = dict({ 'Name': 'Descriptive name for this dataset', 'BIDSVersion': '1.2', 'License': 'This data is made available under the Creative Commons BY-SA 4.0 International License.', 'Authors': ['First Author', 'Second Author'], 'Acknowledgments': 'Thanks to everyone for all your help', 'HowToAcknowledge': 'Please cite: Author AB, Seminal Paper Title, High Impact Journal, 2019', 'Funding': ['First Grant', 'Second Grant'], 'ReferencesAndLinks': ['A Reference', 'Another Reference', 'A Link'], 'DatasetDOI': '10.0.1.2/abcd.10' }) bio.write_json(self.datadesc_json, meta_dict, overwrite) # Create participants JSON file defining columns in participants.tsv # See self.participants_json = os.path.join(self.bids_dir, 'participants.json') meta_dict = dict({ 'age': { 'Description': 'Age of participant', 'Units': 'years' }, 'sex': { 'Description': 'Sex of participant', 'Levels': { 'M': 'male', 'F': 'female', 'T': 'transgender' } }, 'group': { 'Description': 'participant group assignment' }, }) bio.write_json(self.participants_json, meta_dict, overwrite) # Create .bidsignore file to skip work/ during validation self.ignore_file = os.path.join(dataset_dir, '.bidsignore') with open(self.ignore_file, 'w') as fd: fd.writelines('work/\n')
def purpose_handling(bids_purpose, bids_intendedfor, seq_name, work_nii_fname, work_json_fname, bids_nii_fname, bids_json_fname, overwrite=False): """ Special handling for each image purpose (func, anat, fmap, dwi, etc) :param bids_purpose: str :param bids_intendedfor: str :param seq_name: str :param work_nii_fname: str :param work_json_fname: str :param bids_nii_fname: str :param bids_json_fname: str :param overwrite: bool :return: """ # Init DWI sidecars work_bval_fname = [] work_bvec_fname = [] bids_bval_fname = [] bids_bvec_fname = [] # Load the JSON sidecar bids_info = bio.read_json(work_json_fname) if bids_purpose == 'func': if seq_name == 'EP': print(' EPI detected') create_events_template(bids_nii_fname, overwrite) # Add taskname to BIDS JSON sidecar bids_keys = bio.parse_bids_fname(bids_nii_fname) if 'task' in bids_keys: bids_info['TaskName'] = bids_keys['task'] else: bids_info['TaskName'] = 'unknown' elif bids_purpose == 'fmap': # Add IntendedFor field if requested through protocol translator if 'UNASSIGNED' not in bids_intendedfor: bids_info['IntendedFor'] = bids_intendedfor # Check for MEGE vs SE-EPI fieldmap images # MEGE will have a 'GR' sequence, SE-EPI will have 'EP' print(' Identifying fieldmap image type') if seq_name == 'GR': print(' GRE detected') print(' Identifying magnitude and phase images') # Siemens: Dual gradient echo fieldmaps reconstruct to three series # (Requires dcm2nixx v1.0.20180404 or later for echo number suffix) # *--GR--<serno>_e1.<ext> : magnitude image from echo 1 # *--GR--<serno>_e2.<ext> : magnitude image from echo 2 # *--GR--<serno+1>_ph.<ext> : inter-echo phase difference # Pull dcm2niix filename info work_info = bio.parse_dcm2niix_fname(work_nii_fname) if 'e1' in work_info['Suffix']: print(' Echo 1 magnitude detected') # Replace existing contrast suffix (if any) with '_magnitude1' bids_nii_fname = replace_contrast(bids_nii_fname, 'magnitude1') bids_json_fname = [] # Do not copy sidecar elif 'e2' in work_info['Suffix']: print(' Echo 2 magnitude detected') # Replace existing contrast suffix (if any) with '_magnitude1' bids_nii_fname = replace_contrast(bids_nii_fname, 'magnitude2') bids_json_fname = [] # Do not copy sidecar elif 'ph' in work_info['Suffix']: print(' Interecho phase difference detected') # Replace existing contrast suffix (if any) with '_phasediff' bids_nii_fname = replace_contrast(bids_nii_fname, 'phasediff') bids_json_fname = replace_contrast(bids_json_fname, 'phasediff') # Extract TE1 and TE2 from mag and phase JSON sidecars te1, te2 = fmap_echotimes(work_json_fname) bids_info['EchoTime1'] = te1 bids_info['EchoTime2'] = te2 else: print('* Magnitude or phase image not found - skipping') bids_nii_fname = [] bids_json_fname = [] elif seq_name == 'EP': print(' EPI detected') else: print(' Unrecognized fieldmap detected') print(' Simply copying image and sidecar to fmap directory') elif bids_purpose == 'anat': if seq_name == 'GR_IR': print( ' IR-prepared GRE detected - likely T1w MP-RAGE or equivalent' ) elif seq_name == 'SE': print(' Spin echo detected - likely T1w or T2w anatomic image') elif seq_name == 'GR': print(' Gradient echo detected') elif bids_purpose == 'dwi': # Fill DWI bval and bvec working and source filenames # Non-empty filenames trigger the copy below work_bval_fname = str(work_json_fname.replace('.json', '.bval')) bids_bval_fname = str(bids_json_fname.replace('dwi.json', 'dwi.bval')) work_bvec_fname = str(work_json_fname.replace('.json', '.bvec')) bids_bvec_fname = str(bids_json_fname.replace('dwi.json', 'dwi.bvec')) # Populate BIDS source directory with Nifti images, JSON and DWI sidecars print(' Populating BIDS source directory') if bids_nii_fname: bio.safe_copy(work_nii_fname, str(bids_nii_fname), overwrite) if bids_json_fname: bio.write_json(bids_json_fname, bids_info, overwrite) if bids_bval_fname: bio.safe_copy(work_bval_fname, bids_bval_fname, overwrite) if bids_bvec_fname: bio.safe_copy(work_bvec_fname, bids_bvec_fname, overwrite)
def purpose_handling(bids_purpose, bids_intendedfor, seq_name, work_nii_fname, work_json_fname, bids_nii_fname, bids_json_fname, overwrite=False): """ Special handling for each image purpose (func, anat, fmap, dwi, etc) :param bids_purpose: str :param bids_intendedfor: str :param seq_name: str :param work_nii_fname: str :param work_json_fname: str :param bids_nii_fname: str :param bids_json_fname: str :param overwrite: bool :return: """ # Init DWI sidecars work_bval_fname = [] work_bvec_fname = [] bids_bval_fname = [] bids_bvec_fname = [] # Load the JSON sidecar bids_info = bio.read_json(work_json_fname) if bids_purpose == 'func': if seq_name == 'EP': print(' EPI detected') create_events_template(bids_nii_fname, overwrite) # Add taskname to BIDS JSON sidecar bids_keys = bio.parse_bids_fname(bids_nii_fname) if 'task' in bids_keys: bids_info['TaskName'] = bids_keys['task'] else: bids_info['TaskName'] = 'unknown' elif bids_purpose == 'fmap': # Add IntendedFor field if requested through protocol translator if 'UNASSIGNED' not in bids_intendedfor: bids_info['IntendedFor'] = bids_intendedfor # Check for MEGE vs SE-EPI fieldmap images # MEGE will have a 'GR' sequence, SE-EPI will have 'EP' print(' Identifying fieldmap image type') if seq_name == 'GR': print(' GRE detected') print(' Identifying magnitude and phase images') # Siemens: Dual gradient echo fieldmaps reconstruct to three series # (Requires dcm2nixx v1.0.20180404 or later for echo number suffix) # *--GR--<serno>_e1.<ext> : magnitude image from echo 1 # *--GR--<serno>_e2.<ext> : magnitude image from echo 2 # *--GR--<serno+1>_ph.<ext> : inter-echo phase difference # Pull dcm2niix filename info work_info = bio.parse_dcm2niix_fname(work_nii_fname) if 'e1' in work_info['Suffix']: print(' Echo 1 magnitude detected') # Replace existing contrast suffix (if any) with '_magnitude1' bids_nii_fname = replace_contrast(bids_nii_fname, 'magnitude1') bids_json_fname = [] # Do not copy sidecar elif 'e2' in work_info['Suffix']: print(' Echo 2 magnitude detected') # Replace existing contrast suffix (if any) with '_magnitude1' bids_nii_fname = replace_contrast(bids_nii_fname, 'magnitude2') bids_json_fname = [] # Do not copy sidecar elif 'ph' in work_info['Suffix']: print(' Interecho phase difference detected') # Replace existing contrast suffix (if any) with '_phasediff' bids_nii_fname = replace_contrast(bids_nii_fname, 'phasediff') bids_json_fname = replace_contrast(bids_json_fname, 'phasediff') # Extract TE1 and TE2 from mag and phase JSON sidecars te1, te2 = fmap_echotimes(work_json_fname) bids_info['EchoTime1'] = te1 bids_info['EchoTime2'] = te2 else: print('* Magnitude or phase image not found - skipping') bids_nii_fname = [] bids_json_fname = [] elif seq_name == 'EP': print(' EPI detected') else: print(' Unrecognized fieldmap detected') print(' Simply copying image and sidecar to fmap directory') elif bids_purpose == 'anat': if seq_name == 'GR_IR': print(' IR-prepared GRE detected - likely T1w MP-RAGE or equivalent') elif seq_name == 'SE': print(' Spin echo detected - likely T1w or T2w anatomic image') elif seq_name == 'GR': print(' Gradient echo detected') elif bids_purpose == 'dwi': # Fill DWI bval and bvec working and source filenames # Non-empty filenames trigger the copy below work_bval_fname = str(work_json_fname.replace('.json', '.bval')) bids_bval_fname = str(bids_json_fname.replace('dwi.json', 'dwi.bval')) work_bvec_fname = str(work_json_fname.replace('.json', '.bvec')) bids_bvec_fname = str(bids_json_fname.replace('dwi.json', 'dwi.bvec')) # Populate BIDS source directory with Nifti images, JSON and DWI sidecars print(' Populating BIDS source directory') if bids_nii_fname: bio.safe_copy(work_nii_fname, str(bids_nii_fname), overwrite) if bids_json_fname: bio.write_json(bids_json_fname, bids_info, overwrite) if bids_bval_fname: bio.safe_copy(work_bval_fname, bids_bval_fname, overwrite) if bids_bvec_fname: bio.safe_copy(work_bvec_fname, bids_bvec_fname, overwrite)