Exemple #1
0
    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')
Exemple #2
0
def organize_series(conv_dir,
                    first_pass,
                    prot_dict,
                    src_dir,
                    sid,
                    ses,
                    clean_conv_dir,
                    overwrite=False):
    """
    Organize dcm2niix output into BIDS subject/session directory

    :param conv_dir: string
        Working conversion directory
    :param first_pass: boolean
        Flag for first pass conversion
    :param prot_dict: dictionary
        Protocol translation dictionary
    :param src_dir: string
        BIDS source output subj or subj/session directory
    :param sid: string
        subject ID
    :param ses: string
        session name or number
    :param clean_conv_dir: bool
        clean up conversion directory
    :param overwrite: bool
        overwrite flag
    :return:
    """

    # Flag for working conversion directory cleanup
    do_cleanup = clean_conv_dir

    # Proceed if conversion directory exists
    if os.path.isdir(conv_dir):

        # Get Nifti file list ordered by acquisition time
        nii_list, json_list, acq_times = btr.ordered_file_list(conv_dir)

        # Infer run numbers accounting for duplicates.
        # Only used if run-* not present in translator BIDS filename stub
        if not first_pass:
            run_no = btr.auto_run_no(nii_list, prot_dict)

        # Loop over all Nifti files (*.nii, *.nii.gz) for this subject
        for fc, src_nii_fname in enumerate(nii_list):

            # Parse image filename into fields
            info = bio.parse_dcm2niix_fname(src_nii_fname)

            # Check if we're creating new protocol dictionary
            if first_pass:

                print('  Adding protocol %s to dictionary template' %
                      info['SerDesc'])

                # Add current protocol to protocol dictionary
                # Use default EXCLUDE_* values which can be changed (or not) by the user
                prot_dict[info['SerDesc']] = [
                    "EXCLUDE_BIDS_Directory", "EXCLUDE_BIDS_Name", "UNASSIGNED"
                ]

            else:

                # JSON sidecar for this image
                src_json_fname = json_list[fc]

                # Warn if not found and continue
                if not os.path.isfile(src_json_fname):
                    print('* WARNING: JSON sidecar %s not found' %
                          src_json_fname)
                    continue

                if info['SerDesc'] in prot_dict.keys():

                    if prot_dict[info['SerDesc']][0].startswith('EXCLUDE'):

                        # Skip excluded protocols
                        print('* Excluding protocol ' + str(info['SerDesc']))

                    else:

                        print('  Organizing ' + str(info['SerDesc']))

                        # Use protocol dictionary to determine purpose folder, BIDS filename suffix and fmap linking
                        bids_purpose, bids_suffix, bids_intendedfor = prot_dict[
                            info['SerDesc']]

                        # Safely add run-* key to BIDS suffix
                        bids_suffix = btr.add_run_number(
                            bids_suffix, run_no[fc])

                        # Assume the IntendedFor field should aslo have a run- added
                        prot_dict = btr.add_intended_run(
                            prot_dict, info, run_no[fc])

                        # Create BIDS purpose directory
                        bids_purpose_dir = os.path.join(src_dir, bids_purpose)
                        bio.safe_mkdir(bids_purpose_dir)

                        # Complete BIDS filenames for image and sidecar
                        if ses:
                            bids_prefix = 'sub-' + sid + '_ses-' + ses + '_'
                        else:
                            bids_prefix = 'sub-' + sid + '_'

                        # Construct BIDS source Nifti and JSON filenames
                        bids_nii_fname = os.path.join(
                            bids_purpose_dir,
                            bids_prefix + bids_suffix + '.nii.gz')
                        bids_json_fname = bids_nii_fname.replace(
                            '.nii.gz', '.json')

                        # Add prefix and suffix to IntendedFor values
                        if 'UNASSIGNED' not in bids_intendedfor:
                            if isinstance(bids_intendedfor, str):
                                # Single linked image
                                bids_intendedfor = btr.build_intendedfor(
                                    sid, ses, bids_intendedfor)
                            else:
                                # Loop over all linked images
                                for ifc, ifstr in enumerate(bids_intendedfor):
                                    # Avoid multiple substitutions
                                    if '.nii.gz' not in ifstr:
                                        bids_intendedfor[
                                            ifc] = btr.build_intendedfor(
                                                sid, ses, ifstr)

                        # Special handling for specific purposes (anat, func, fmap, etc)
                        # This function populates BIDS structure with the image and adjusted sidecar
                        btr.purpose_handling(bids_purpose, bids_intendedfor,
                                             info['SeqName'], src_nii_fname,
                                             src_json_fname, bids_nii_fname,
                                             bids_json_fname, overwrite)
                else:

                    # Skip protocols not in the dictionary
                    print('* Protocol ' + str(info['SerDesc']) +
                          ' is not in the dictionary, did not convert.')

        if not first_pass:

            # Optional working directory cleanup after Pass 2
            if do_cleanup:
                print('  Cleaning up temporary files')
                shutil.rmtree(conv_dir)
            else:
                print('  Preserving conversion directory')
Exemple #3
0
    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')
Exemple #4
0
def organize_series(conv_dir, first_pass, prot_dict, src_dir, sid, ses, clean_conv_dir, overwrite=False):
    """
    Organize dcm2niix output into BIDS subject/session directory

    :param conv_dir: string
        Working conversion directory
    :param first_pass: boolean
        Flag for first pass conversion
    :param prot_dict: dictionary
        Protocol translation dictionary
    :param src_dir: string
        BIDS source output subj or subj/session directory
    :param sid: string
        subject ID
    :param ses: string
        session name or number
    :param clean_conv_dir: bool
        clean up conversion directory
    :param overwrite: bool
        overwrite flag
    :return:
    """

    # Flag for working conversion directory cleanup
    do_cleanup = clean_conv_dir

    # Proceed if conversion directory exists
    if os.path.isdir(conv_dir):

        # Get Nifti file list ordered by acquisition time
        nii_list, json_list, acq_times = btr.ordered_file_list(conv_dir)

        # Infer run numbers accounting for duplicates.
        # Only used if run-* not present in translator BIDS filename stub
        if not first_pass:
            run_no = btr.auto_run_no(nii_list, prot_dict)

        # Loop over all Nifti files (*.nii, *.nii.gz) for this subject
        for fc, src_nii_fname in enumerate(nii_list):

            # Parse image filename into fields
            info = bio.parse_dcm2niix_fname(src_nii_fname)

            # Check if we're creating new protocol dictionary
            if first_pass:

                print('  Adding protocol %s to dictionary template' % info['SerDesc'])

                # Add current protocol to protocol dictionary
                # Use default EXCLUDE_* values which can be changed (or not) by the user
                prot_dict[info['SerDesc']] = ["EXCLUDE_BIDS_Directory", "EXCLUDE_BIDS_Name", "UNASSIGNED"]

            else:

                # JSON sidecar for this image
                src_json_fname = json_list[fc]

                # Warn if not found and continue
                if not os.path.isfile(src_json_fname):
                    print('* WARNING: JSON sidecar %s not found' % src_json_fname)
                    continue

                if info['SerDesc'] in prot_dict.keys():

                    if prot_dict[info['SerDesc']][0].startswith('EXCLUDE'):

                        # Skip excluded protocols
                        print('* Excluding protocol ' + str(info['SerDesc']))

                    else:

                        print('  Organizing ' + str(info['SerDesc']))

                        # Use protocol dictionary to determine purpose folder, BIDS filename suffix and fmap linking
                        bids_purpose, bids_suffix, bids_intendedfor = prot_dict[info['SerDesc']]

                        # Safely add run-* key to BIDS suffix
                        bids_suffix = btr.add_run_number(bids_suffix, run_no[fc])

                        # Assume the IntendedFor field should aslo have a run- added
                        prot_dict = btr.add_intended_run(prot_dict, info, run_no[fc])

                        # Create BIDS purpose directory
                        bids_purpose_dir = os.path.join(src_dir, bids_purpose)
                        bio.safe_mkdir(bids_purpose_dir)

                        # Complete BIDS filenames for image and sidecar
                        if ses:
                            bids_prefix = 'sub-' + sid + '_ses-' + ses + '_'
                        else:
                            bids_prefix = 'sub-' + sid + '_'

                        # Construct BIDS source Nifti and JSON filenames
                        bids_nii_fname = os.path.join(bids_purpose_dir, bids_prefix + bids_suffix + '.nii.gz')
                        bids_json_fname = bids_nii_fname.replace('.nii.gz', '.json')

                        # Add prefix and suffix to IntendedFor values
                        if 'UNASSIGNED' not in bids_intendedfor:
                            if isinstance(bids_intendedfor, str):
                                # Single linked image
                                bids_intendedfor = btr.build_intendedfor(sid, ses, bids_intendedfor)
                            else:
                                # Loop over all linked images
                                for ifc, ifstr in enumerate(bids_intendedfor):
                                    # Avoid multiple substitutions
                                    if '.nii.gz' not in ifstr:
                                        bids_intendedfor[ifc] = btr.build_intendedfor(sid, ses, ifstr)

                        # Special handling for specific purposes (anat, func, fmap, etc)
                        # This function populates BIDS structure with the image and adjusted sidecar
                        btr.purpose_handling(bids_purpose, bids_intendedfor, info['SeqName'],
                                             src_nii_fname, src_json_fname,
                                             bids_nii_fname, bids_json_fname,
                                             overwrite)
                else:

                    # Skip protocols not in the dictionary
                    print('* Protocol ' + str(info['SerDesc']) + ' is not in the dictionary, did not convert.')

        if not first_pass:

            # Optional working directory cleanup after Pass 2
            if do_cleanup:
                print('  Cleaning up temporary files')
                shutil.rmtree(conv_dir)
            else:
                print('  Preserving conversion directory')