-
Notifications
You must be signed in to change notification settings - Fork 124
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
Conversation
Unfortunately, my knowledge about pybids falls short to make a good assessment of this PR (without spending a whole day to catch up with code). But I would say this will help with the API errors from the user perspective. I don't think it will address the DB problems though (see conversation triggered by #682 (comment)). I believe that in addition to test the type of metadata being retrieved (i.e., whether it is an entity value or not), it would be beneficial and more robust to filter out values that do not match the corresponding regexp. |
Ah, sorry I missed that PR. I think Chris summarized it nicely here: #682 (comment) This PR is in the spirit of tal's suggestion to "finesse" the logic of The alternative is to catch this on ingestion of entities. That is, not read in TSV sidecars at all, like Tal suggested, and enforce type and regex incoming entities prior to adding to the The one issue I have with this (aside from this fix being easier), is that then if you call @effigies WDYT? |
bids/layout/layout.py
Outdated
base_entities = self.get_entities(metadata=False) | ||
metadata = False if target in base_entities else True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ternary is just if not
. And we don't reuse base entities. Maybe just a comment?
base_entities = self.get_entities(metadata=False) | |
metadata = False if target in base_entities else True | |
# Fetch metadata if target is not a filename entity | |
metadata = target not in self.get_entities(metadata=False) |
bids/layout/layout.py
Outdated
results = [x for x in results if target in x.entities] | ||
base_entities = self.get_entities(metadata=False) | ||
metadata = False if target in base_entities else True | ||
results = [x for x in results if target in x.get_entities(metadata=metadata)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of times we're calling get_entities
feels high, and I think it's a DB query. What if we dropped this and did:
if return_type == "id":
ent_iter = (x.get_entities(metadata=metadata) for x in results)
results = list({
ents[target] for ents in ent_iter
if isinstance(ents.get(target, {}), Hashable) # from collections.abc
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from collection.abc import Hashable
Check that return_type == 'dir', still works.
@oesteban: @effigies and I discussed this, and we think this PR should take care of the issue. All entities being read in from file names are validated, and thus no invalid values should sneak in. Here, we limit it so that only real entities are queried when The alternative would be to do this upon ingestion of meta-data, and filter out meta-data that looks like an entity (but isn't) from being ingested. However, this causes two problems. 1) it's not illegal in BIDS (yet) and 2) if you I prefer this solution because it keep |
Summary of how this should behave: if |
Turns out to make this change possible, I had to change where Previously, This means that an For me, this meant that the "Task" Entitity said To fix this, I moved In an example where the "task"
That is,
Going back to the original problem, the
This value does not include the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like some stray middle-clicks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good otherwise. Only question: Do we have a way of invalidating old database files?
Co-authored-by: Chris Markiewicz <[email protected]>
Co-authored-by: Chris Markiewicz <[email protected]>
Thanks. No, and it looks like it doesn't crash on initialization, but until you try to access a property that doesn't exist in the old db (i.e. Only way I can see us handling this proactively is adding BIDS versions to the db dirs, and throwing a warning if you load a saved layout from a previous version. Would be good for different PR. |
Tests passing, merging but opening a new issue for what you mentioned @effigies |
If return_type = 'id' ("shorthand queries") or 'dir' and "target" is a core BIDS entity (i.e. one that is derived from filenames, not from meta-data), then only look at results that are not from meta-data.
If you ask for
layout.get_runs()
, it will only look at values that came from files, not meta-data.This should prevent collisions from similarly named meta-data values.
However, if you ask for a meta-data target, then it will attempt to take a
set
across all values it finds:Related #694