Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Associate "is_metadata" with Tag, not Entity; and only return non-metadata entries for core Entities in get(return_type='id') #749

Merged
merged 7 commits into from
Jul 26, 2021
Merged
4 changes: 2 additions & 2 deletions bids/layout/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,9 @@ def create_association_pair(src, dst, kind, kind2=None):
md_val))
continue
if md_key not in all_entities:
all_entities[md_key] = Entity(md_key, is_metadata=True)
all_entities[md_key] = Entity(md_key)
self.session.add(all_entities[md_key])
tag = Tag(bf, all_entities[md_key], md_val)
tag = Tag(bf, all_entities[md_key], md_val, is_metadata=True)
self.session.add(tag)

if len(self.session.new) >= 1000:
Expand Down
20 changes: 10 additions & 10 deletions bids/layout/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ def files(self):

@classmethod
def load(cls, database_path):
""" Load index from database path. Initialization parameters are set to
""" Load index from database path. Initiget_entitiesalization parameters are set to
adelavega marked this conversation as resolved.
Show resolved Hide resolved
those found in database_path JSON sidecar.

Parameters
Expand All @@ -313,7 +313,7 @@ def save(self, database_path, replace_connection=True):

Note: This is only necessary if a database_path was not specified
at initialization, and the user now wants to save the index.
If a database_path was specified originally, there is no need to
If a database_path was specified originaquery = l.session.query(Entity)lly, there is no need to
adelavega marked this conversation as resolved.
Show resolved Hide resolved
re-save using this method.

Parameters
Expand Down Expand Up @@ -369,7 +369,7 @@ def get_entities(self, scope='all', metadata=None):
for l in layouts:
query = l.session.query(Entity)
if metadata is not None:
query = query.filter_by(is_metadata=metadata)
query = query.join(Tag).filter_by(is_metadata=metadata)
results = query.all()
entities.update({e.name: e for e in results})
return entities
Expand Down Expand Up @@ -513,7 +513,7 @@ def to_df(self, metadata=False, **filters):
query = self.session.query(Tag).filter(Tag.file_path.in_(file_paths))

if not metadata:
query = query.join(Entity).filter(Entity.is_metadata == False)
query = query.join(Entity).filter(Tag.is_metadata == False)

tags = query.all()

Expand Down Expand Up @@ -675,13 +675,13 @@ def get(self, return_type='object', target=None, scope='all',
raise TargetError('If return_type is "id" or "dir", a valid '
'target entity must also be specified.')

results = [x for x in results if target in x.entities]
metadata = target not in self.get_entities(metadata=False)

if return_type == 'id':
results = list(set(
[x.entities[target] for x in results
if type(x.entities[target]) is not dict]))
results = natural_sort(results)
ent_iter = (x.get_entities(metadata=metadata) for x in results)
results = list({
ents[target] for ents in ent_iter if target in ents
})

elif return_type == 'dir':
template = entities[target].directory
Expand Down Expand Up @@ -879,7 +879,7 @@ def get_metadata(self, path, include_entities=False, scope='all'):
.filter(BIDSFile.path == path))

if not include_entities:
query = query.join(Entity).filter(Entity.is_metadata == True)
query = query.join(Entity).filter(Tag.is_metadata == True)

results = query.all()
if results:
Expand Down
20 changes: 11 additions & 9 deletions bids/layout/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,9 @@ def get_entities(self, metadata=False, values='tags'):
query = (session.query(Tag)
.filter_by(file_path=self.path)
.join(Entity))

if metadata not in (None, 'all'):
query = query.filter(Entity.is_metadata == metadata)
query = query.filter(Tag.is_metadata == metadata)

results = query.all()
if values.startswith('obj'):
Expand Down Expand Up @@ -517,28 +518,22 @@ class Entity(Base):
one of 'int', 'float', 'bool', or 'str'. If None, no type
enforcement will be attempted, which means the dtype of the
value may be unpredictable.
is_metadata : bool
Indicates whether or not the Entity is derived
from JSON sidecars (True) or is a predefined Entity from a
config (False).
"""
__tablename__ = 'entities'

name = Column(String, primary_key=True)
mandatory = Column(Boolean, default=False)
pattern = Column(String)
directory = Column(String, nullable=True)
is_metadata = Column(Boolean, default=False)
_dtype = Column(String, default='str')
files = association_proxy("tags", "value")

def __init__(self, name, pattern=None, mandatory=False, directory=None,
dtype='str', is_metadata=False):
dtype='str'):
self.name = name
self.pattern = pattern
self.mandatory = mandatory
self.directory = directory
self.is_metadata = is_metadata

if not isinstance(dtype, str):
dtype = dtype.__name__
Expand Down Expand Up @@ -640,25 +635,32 @@ class Tag(Base):
value. If passed, must be one of str, int, float, bool, or json.
Any other value will be treated as json (and will fail if the
value can't be serialized to json).
is_metadata : bool
Indicates whether or not the Entity is derived
from JSON sidecars (True) or is a predefined Entity from a
config (False).
"""
__tablename__ = 'tags'

file_path = Column(String, ForeignKey('files.path'), primary_key=True)
entity_name = Column(String, ForeignKey('entities.name'), primary_key=True)
_value = Column(String, nullable=False)
_dtype = Column(String, default='str')
is_metadata = Column(Boolean, default=False)


file = relationship('BIDSFile', backref=backref(
"tags", collection_class=attribute_mapped_collection("entity_name")))
entity = relationship('Entity', backref=backref(
"tags", collection_class=attribute_mapped_collection("file_path")))

def __init__(self, file, entity, value, dtype=None):
def __init__(self, file, entity, value, dtype=None, is_metadata=False):

if dtype is None:
dtype = type(value)

self.value = value
self.is_metadata = is_metadata

if not isinstance(dtype, str):
dtype = dtype.__name__
Expand Down