def test_force_index(layout_ds005): data_dir = join(get_test_data_path(), 'ds005') target = join(data_dir, 'models', 'ds-005_type-test_model.json') indexer = BIDSLayoutIndexer(force_index=['models']) model_layout = BIDSLayout(data_dir, validate=True, indexer=indexer) assert target not in layout_ds005.files assert target in model_layout.files assert 'all' not in model_layout.get_subjects() for f in model_layout.files.values(): assert 'derivatives' not in f.path
def test_index_metadata(index_metadata, query, result): data_dir = join(get_test_data_path(), '7t_trt') layout = BIDSLayout(data_dir, index_metadata=index_metadata) if not index_metadata and query is not None: indexer = BIDSLayoutIndexer(layout) indexer.index_metadata(**query) sample_file = layout.get(task='rest', extension='nii.gz', acq='fullbrain')[0] metadata = sample_file.get_metadata() assert metadata.get('RepetitionTime') == result
def init(cls): """Create a new BIDS Layout accessible with :attr:`~execution.layout`.""" if cls._layout is None: import re from bids.layout.index import BIDSLayoutIndexer from bids.layout import BIDSLayout _db_path = cls.bids_database_dir or ( cls.work_dir / cls.run_uuid / "bids_db" ) _db_path.mkdir(exist_ok=True, parents=True) # Recommended after PyBIDS 12.1 _indexer = BIDSLayoutIndexer( validate=False, ignore=( "code", "stimuli", "sourcedata", "models", "derivatives", "scripts", re.compile(r"^\."), # Exclude modalities and contrasts ignored by MRIQC (doesn't know how to QC) re.compile( r"sub-[a-zA-Z0-9]+(/ses-[a-zA-Z0-9]+)?/(dwi|fmap|perf)/" ), re.compile( r"sub-[a-zA-Z0-9]+(/ses-[a-zA-Z0-9]+)?/anat/.*_" r"(PDw|T2starw|FLAIR|inplaneT1|inplaneT2|PDT2|angio|T2star" r"|FLASH|PD|T1map|T2map|T2starmap|R1map|R2map|R2starmap|PDmap" r"|MTRmap|MTsat|UNIT1|T1rho|MWFmap|MTVmap|PDT2map|Chimap" r"|S0map|M0map|defacemask|MESE|MEGRE|VFA|IRT1|MP2RAGE|MPM|MTS|MTR)\." ), re.compile( r"sub-[a-zA-Z0-9]+(/ses-[a-zA-Z0-9]+)?/func/.*" r"_(cbv|sbref|phase|events|physio|stim)\." ), ), ) cls._layout = BIDSLayout( str(cls.bids_dir), database_path=_db_path, reset_database=cls.bids_database_dir is None, indexer=_indexer, ) cls.bids_database_dir = _db_path cls.layout = cls._layout
def test_ignore_files(layout_ds005): data_dir = join(get_test_data_path(), 'ds005') target1 = join(data_dir, 'models', 'ds-005_type-test_model.json') target2 = join(data_dir, 'models', 'extras', 'ds-005_type-test_model.json') layout1 = BIDSLayout(data_dir, validate=False) assert target1 not in layout_ds005.files assert target1 not in layout1.files assert target2 not in layout1.files # now the models/ dir should show up, because passing ignore explicitly # overrides the default - but 'model/extras/' should still be ignored # because of the regex. ignore = [re.compile('xtra'), 'dummy'] indexer = BIDSLayoutIndexer(validate=False, ignore=ignore) layout2 = BIDSLayout(data_dir, indexer=indexer) assert target1 in layout2.files assert target2 not in layout2.files
def init_layout(): from .bids import Layout from bids.layout.index import BIDSLayoutIndexer global TF_LAYOUT TF_LAYOUT = Layout( TF_HOME, validate=False, config="templateflow", indexer=BIDSLayoutIndexer( validate=False, ignore=( ".git", ".datalad", ".gitannex", ".gitattributes", ".github", "scripts", ), ), )
def _resolve_bids(self, fileobj: File) -> list[File]: # load using pybids validate = False # save time layout = BIDSLayout( root=fileobj.path, reset_database=True, # force reindex in case files have changed absolute_paths=True, validate=validate, indexer=BIDSLayoutIndexer( validate=validate, index_metadata=False, # save time ), ) # load override metadata basemetadata = dict() if hasattr(fileobj, "metadata"): metadata = getattr(fileobj, "metadata", None) if isinstance(metadata, dict): basemetadata.update(metadata) resolved_files: list[File] = [] for obj in layout.get_files().values(): file: File | None = to_fileobj(obj, basemetadata) if file is None: continue self.fileobj_by_filepaths[file.path] = file self.specfileobj_by_filepaths[file.path] = file resolved_files.append(file) intended_for: dict[str, frozenset[tuple[str, str]]] = dict() for file in resolved_files: if file.datatype != "fmap": continue metadata = SidecarMetadataLoader.load(file.path) if metadata is None: continue intended_for_paths = metadata.get("intended_for") if intended_for_paths is None: continue linked_fmap_tags = frozenset(file.tags.items()) for intended_for_path in intended_for_paths: intended_for[intended_for_path] = linked_fmap_tags informed_by: dict[frozenset[tuple[str, str]], list[frozenset[tuple[str, str]]]] = defaultdict(list) for file in resolved_files: file_tags = frozenset(file.tags.items()) for file_path, linked_fmap_tags in intended_for.items(): if file.path.endswith(file_path): # slow performance informed_by[file_tags].append(linked_fmap_tags) mappings: set[tuple[tuple[str, str], tuple[str, str]]] = set() for func_tags, linked_fmap_tags_list in informed_by.items(): for linked_fmap_tags in linked_fmap_tags_list: for func_tag, linked_fmap_tag in product( func_tags, linked_fmap_tags): if func_tag[0] == "sub" or linked_fmap_tag[0] == "sub": continue if (func_tag[0] == linked_fmap_tag[0] ): # only map between different entities continue mappings.add((func_tag, linked_fmap_tag)) intended_for_rules = defaultdict(list) for functag, fmaptag in mappings: entity, val = functag funcstr = f"{entity}.{val}" entity, val = fmaptag fmapstr = f"{entity}.{val}" intended_for_rules[fmapstr].append(funcstr) if len(intended_for) > 0: logger.info( "Inferred mapping between func and fmap files to be %s", pformat(intended_for_rules), ) for file in resolved_files: if file.datatype != "fmap": continue file.intended_for = intended_for_rules return resolved_files