def add_entity(self, domain, **kwargs): ''' Add a new Entity to tracking. ''' # Set the entity's mapping func if one was specified map_func = kwargs.get('map_func', None) if map_func is not None and not callable(kwargs['map_func']): if self.entity_mapper is None: raise ValueError("Mapping function '%s' specified for Entity " "'%s', but no entity mapper was passed when " "initializing the current Layout. Please make" " sure the 'entity_mapper' argument is set." % (map_func, kwargs['name'])) map_func = getattr(self.entity_mapper, kwargs['map_func']) kwargs['map_func'] = map_func ent = Entity(domain=domain, **kwargs) domain.add_entity(ent) if ent.mandatory: self.mandatory.add(ent.id) if ent.directory is not None: ent.directory = ent.directory.replace('{{root}}', self.root) self.entities[ent.id] = ent for alias in ent.aliases: self.entities[alias] = ent if self.dynamic_getters: func = partial(getattr(self, 'get'), target=ent.name, return_type='id') func_name = inflect.engine().plural(ent.name) setattr(self, 'get_%s' % func_name, func)
def add_entity(self, **kwargs): # Set up the entities we need to track ent = Entity(**kwargs) if ent.mandatory: self.mandatory.add(ent.name) if ent.directory is not None: ent.directory = ent.directory.replace('{{root}}', self.root) self.entities[ent.name] = ent if self.dynamic_getters: func = partial(getattr(self, 'get'), target=ent.name, return_type='id') func_name = inflect.engine().plural(ent.name) setattr(self, 'get_%s' % func_name, func)
def add_derivatives(self, path, **kwargs): ''' Add BIDS-Derivatives datasets to tracking. Args: path (str, list): One or more paths to BIDS-Derivatives datasets. Each path can point to either a derivatives/ directory containing one more more pipeline directories, or to a single pipeline directory (e.g., derivatives/fmriprep). kwargs (dict): Optional keyword arguments to pass on to BIDSLayout() when initializing each of the derivative datasets. ''' paths = listify(path) deriv_dirs = [] # Collect all paths that contain a dataset_description.json def check_for_description(dir): dd = os.path.join(dir, 'dataset_description.json') return os.path.exists(dd) for p in paths: p = os.path.abspath(p) if os.path.exists(p): if check_for_description(p): deriv_dirs.append(p) else: subdirs = [ d for d in os.listdir(p) if os.path.isdir(os.path.join(p, d)) ] for sd in subdirs: sd = os.path.join(p, sd) if check_for_description(sd): deriv_dirs.append(sd) local_entities = set(ent.name for ent in self.entities.values()) for deriv in deriv_dirs: dd = os.path.join(deriv, 'dataset_description.json') with open(dd, 'r', encoding='utf-8') as ddfd: description = json.load(ddfd) pipeline_name = description.get('PipelineDescription', {}).get('Name', None) if pipeline_name is None: raise ValueError("Every valid BIDS-derivatives dataset must " "have a PipelineDescription.Name field set " "inside dataset_description.json.") if pipeline_name in self.derivatives: raise ValueError("Pipeline name '%s' has already been added " "to this BIDSLayout. Every added pipeline " "must have a unique name!") # Default config and sources values kwargs['config'] = kwargs.get('config') or ['bids', 'derivatives'] kwargs['sources'] = kwargs.get('sources') or self self.derivatives[pipeline_name] = BIDSLayout(deriv, **kwargs) # Propagate derivative entities into top-level dynamic getters deriv_entities = set( ent.name for ent in self.derivatives[pipeline_name].entities.values()) for deriv_ent in deriv_entities - local_entities: local_entities.add(deriv_ent) getter = 'get_' + inflect.engine().plural(deriv_ent) if not hasattr(self, getter): func = partial(self.get, target=deriv_ent, return_type='id') setattr(self, getter, func)