def is_sourcefile(file: Path) -> str: """ This plugin function supports assessing whether the file is a valid sourcefile :param file: The file that is assessed :return: The valid dataformat of the file for this plugin """ if bids.is_dicomfile(file): return 'DICOM' if bids.is_parfile(file): return 'PAR' return ''
def built_dicommap(dicomfile: Path, bidsmap: dict, template: dict) -> dict: """ All the logic to map dicomfields onto bids labels go into this function :param dicomfile: The full-path name of the source dicom-file :param bidsmap: The bidsmap as we had it :param template: Full BIDS heuristics data structure, with all options, BIDS labels and attributes, etc :return: The bidsmap with new entries in it """ # Get the bidsmodality and dirname (= bidslabel) from the pathname (samples/bidsmodality/[dirname/]dicomfile) suffix = dicomfile.parts[-2] if suffix in bids.bidsmodalities + (bids.unknownmodality, bids.ignoremodality): modality = suffix else: modality = dicomfile.parts[-3] # Input checks if not bids.is_dicomfile(dicomfile) or not template[ 'DICOM'] or not template['DICOM'][modality]: return bidsmap if modality not in bids.bidsmodalities + (bids.unknownmodality, bids.ignoremodality): raise ValueError( "Don't know what to do with this bidsmodality directory name: {}\n{}" .format(modality, dicomfile)) # Get bids-labels from the matching run in the template run = bids.get_run( template, 'DICOM', modality, suffix, dicomfile) # TODO: check if the dicomfile argument is not broken if not run: raise ValueError( f"Oops, this should not happen! BIDS modality '{modality}' or one of the bidslabels is not accounted for in the code\n{dicomfile}" ) # Copy the filled-in run over to the bidsmap if not bids.exist_run(bidsmap, 'DICOM', modality, run): bidsmap = bids.append_run(bidsmap, 'DICOM', modality, run) return bidsmap
def bidstrainer(bidsfolder: str, samplefolder: str, bidsmapfile: str, pattern: str) -> None: """ Main function uses all samples in the samplefolder as training / example data to generate a maximally filled-in bidsmap_sample.yaml file. :param bidsfolder: The name of the BIDS root folder :param samplefolder: The name of the root directory of the tree containing the sample files / training data. If left empty, bidsfolder/code/bidscoin/samples is used or such an empty directory tree is created :param bidsmapfile: The name of the bidsmap YAML-file :param pattern: The regular expression pattern used in re.match(pattern, dicomfile) to select the dicom files', default='.*\\.(IMA|dcm)$') :return: """ bidsfolder = Path(bidsfolder) samplefolder = Path(samplefolder) bidsmapfile = Path(bidsmapfile) # Start logging bids.setup_logging(bidsfolder / 'code' / 'bidscoin' / 'bidstrainer.log') LOGGER.info('------------ START BIDStrainer ------------') # Get the heuristics for creating the bidsmap heuristics, _ = bids.load_bidsmap(bidsmapfile, bidsfolder / 'code' / 'bidscoin') # Input checking if not samplefolder: samplefolder = bidsfolder / 'code' / 'bidscoin' / 'samples' if not samplefolder.is_dir(): LOGGER.info( f"Creating an empty samples directory tree: {samplefolder}") for modality in bids.bidsmodalities + (bids.ignoremodality, bids.unknownmodality): for run in heuristics['DICOM'][modality]: if not run['bids']['suffix']: run['bids']['suffix'] = '' (samplefolder / modality / run['bids']['suffix']).mkdir( parents=True, exist_ok=True) LOGGER.info( 'Fill the directory tree with example DICOM files and re-run bidstrainer.py' ) return # Create a copy / bidsmap skeleton with no modality entries (i.e. bidsmap with empty lists) bidsmap = copy.deepcopy(heuristics) for logic in ('DICOM', 'PAR', 'P7', 'Nifti', 'FileSystem'): for modality in bids.bidsmodalities: if bidsmap[logic] and modality in bidsmap[logic]: bidsmap[logic][modality] = None # Loop over all bidsmodalities and instances and built up the bidsmap entries files = samplefolder.rglob('*') samples = [ Path(dcmfile) for dcmfile in files if re.match(pattern, str(dcmfile)) ] for sample in samples: if not sample.is_file(): continue LOGGER.info(f"Parsing: {sample}") # Try to get a dicom mapping if bids.is_dicomfile(sample) and heuristics['DICOM']: bidsmap = built_dicommap(sample, bidsmap, heuristics) # Try to get a PAR/REC mapping if bids.is_parfile(sample) and heuristics['PAR']: bidsmap = built_parmap(sample, bidsmap, heuristics) # Try to get a P7 mapping if bids.is_p7file(sample) and heuristics['P7']: bidsmap = built_p7map(sample, bidsmap, heuristics) # Try to get a nifti mapping if bids.is_niftifile(sample) and heuristics['Nifti']: bidsmap = built_niftimap(sample, bidsmap, heuristics) # Try to get a file-system mapping if heuristics['FileSystem']: bidsmap = built_filesystemmap(sample, bidsmap, heuristics) # Try to get a plugin mapping if heuristics['PlugIn']: bidsmap = built_pluginmap(sample, bidsmap) # Create the bidsmap_sample YAML-file in bidsfolder/code/bidscoin (bidsfolder / 'code' / 'bidscoin').mkdir(parents=True, exist_ok=True) bidsmapfile = bidsfolder / 'code' / 'bidscoin' / 'bidsmap_sample.yaml' # Save the bidsmap to the bidsmap YAML-file bids.save_bidsmap(bidsmapfile, bidsmap) LOGGER.info('------------ FINISHED! ------------')
def bidstrainer(bidsfolder, samplefolder='', bidsmapfile='bidsmap_template.yaml'): """ Main function uses all samples in the samplefolder as training / example data to generate a maximally filled-in bidsmap_sample.yaml file. :param str bidsfolder: The name of the BIDS root folder :param str samplefolder: The name of the root directory of the tree containing the sample files / training data. If left empty, bidsfolder/code/samples is used or such an empty directory tree is created :param str bidsmapfile: The name of the bidsmap YAML-file :return: The name of the new (trained) bidsmap YAML-file that is save in bidsfolder/code :rtype: str """ # Input checking bidsfolder = os.path.abspath(os.path.expanduser(bidsfolder)) if not samplefolder: samplefolder = os.path.join(bidsfolder,'code','samples') if not os.path.isdir(samplefolder): print('Creating an empty samples directory tree: ' + samplefolder) shutil.copytree(os.path.join(os.path.dirname(bids.__file__),'..','heuristics','samples'), samplefolder) print('Fill the directory tree with example DICOM files and re-run bidstrainer.py') return samplefolder = os.path.abspath(os.path.expanduser(samplefolder)) # Get the heuristics for creating the bidsmap heuristics = bids.get_heuristics(bidsmapfile) # Create a copy / bidsmap skeleton with no modality entries (i.e. bidsmap with empty lists) bidsmap = copy.deepcopy(heuristics) for logic in ('DICOM', 'PAR', 'P7', 'Nifti', 'FileSystem'): for modality in bids.bidsmodalities: if bidsmap[logic] and modality in bidsmap[logic]: bidsmap[logic][modality] = None # Loop over all bidsmodalities and instances and built up the bidsmap entries samples = glob.glob(os.path.join(samplefolder,'**'), recursive=True) for sample in samples: if not os.path.isfile(sample): continue print('Parsing: ' + sample) # Try to get a dicom mapping if bids.is_dicomfile(sample) and heuristics['DICOM']: bidsmap = built_dicommap(sample, bidsmap, heuristics) # Try to get a PAR/REC mapping if bids.is_parfile(sample) and heuristics['PAR']: bidsmap = built_parmap(sample, bidsmap, heuristics) # Try to get a P7 mapping if bids.is_p7file(sample) and heuristics['P7']: bidsmap = built_p7map(sample, bidsmap, heuristics) # Try to get a nifti mapping if bids.is_niftifile(sample) and heuristics['Nifti']: bidsmap = built_niftimap(sample, bidsmap, heuristics) # Try to get a file-system mapping if heuristics['FileSystem']: bidsmap = built_filesystemmap(sample, bidsmap, heuristics) # Try to get a plugin mapping if heuristics['PlugIn']: bidsmap = built_pluginmap(sample, bidsmap) # Create the bidsmap_sample YAML-file in bidsfolder/code os.makedirs(os.path.join(bidsfolder,'code'), exist_ok=True) bidsmapfile = os.path.join(bidsfolder,'code','bidsmap_sample.yaml') # Save the bidsmap to the bidsmap YAML-file print('Writing bidsmap to: ' + bidsmapfile) with open(bidsmapfile, 'w') as stream: yaml.dump(bidsmap, stream) return bidsmapfile