diff --git a/sdcflows/fieldmaps.py b/sdcflows/fieldmaps.py index fb28cb5e96..197a4d3a2f 100644 --- a/sdcflows/fieldmaps.py +++ b/sdcflows/fieldmaps.py @@ -404,27 +404,31 @@ def __attrs_post_init__(self): # Register this estimation method if not self.bids_id: # If not manually set, try to get it from BIDS metadata - bids_ids = set( - [ - f.metadata.get("B0FieldIdentifier") - for f in self.sources - if f.metadata.get("B0FieldIdentifier") - ] - ) - if len(bids_ids) > 1: - raise ValueError( - f"Multiple ``B0FieldIdentifier`` set: <{', '.join(bids_ids)}>" - ) - elif bids_ids: + b0_ids = [ + listify(f.metadata.get("B0FieldIdentifier")) + for f in self.sources + if f.metadata.get("B0FieldIdentifier") + ] + + if b0_ids: + # Find common IDs + bids_ids = set(b0_ids[0]).intersection(*b0_ids[1:]) + if not bids_ids: + raise ValueError( + f"No common ``B0FieldIdentifier`` found: <{', '.join(map(str, b0_ids))}>" + ) + elif len(bids_ids) > 1: + raise ValueError( + f"Multiple common ``B0FieldIdentifier``s found: <{', '.join(bids_ids)}>" + ) object.__setattr__(self, "bids_id", bids_ids.pop()) - else: - bids_id = _estimators.add(self.paths()) - object.__setattr__(self, "bids_id", bids_id) - for intent_file in intents_meta: - _intents[intent_file].add(bids_id) - return - - _estimators[self.bids_id] = self.paths() + + if self.bids_id: + _estimators[self.bids_id] = self.paths() + else: + bids_id = _estimators.add(self.paths()) + object.__setattr__(self, "bids_id", bids_id) + for intent_file in intents_meta: _intents[intent_file].add(self.bids_id) diff --git a/sdcflows/utils/wrangler.py b/sdcflows/utils/wrangler.py index 361c85aef1..7f3f312279 100644 --- a/sdcflows/utils/wrangler.py +++ b/sdcflows/utils/wrangler.py @@ -22,6 +22,7 @@ # """Find fieldmaps on the BIDS inputs for :abbr:`SDC (susceptibility distortion correction)`.""" import logging +from functools import reduce from itertools import product from contextlib import suppress from pathlib import Path @@ -293,7 +294,12 @@ def find_estimators( # Step 1. Use B0FieldIdentifier metadata b0_ids = tuple() with suppress(BIDSEntityError): - b0_ids = layout.get_B0FieldIdentifiers(**base_entities) + # flatten lists from json (tupled in pybids for hashing), then unique + b0_ids = reduce( + set.union, + (listify(ids) for ids in layout.get_B0FieldIdentifiers(**base_entities)), + set() + ) if b0_ids: logger.debug( @@ -305,9 +311,15 @@ def find_estimators( b0_entities = base_entities.copy() b0_entities["B0FieldIdentifier"] = b0_id + bare_ids = layout.get(**base_entities, B0FieldIdentifier=b0_id) + listed_ids = layout.get( + **base_entities, + B0FieldIdentifier=f'"{b0_id}"', # Double quotes to match JSON, not Python repr + regex_search=True, + ) e = fm.FieldmapEstimation([ fm.FieldmapFile(fmap.path, metadata=fmap.get_metadata()) - for fmap in layout.get(**b0_entities) + for fmap in bare_ids + listed_ids ]) _log_debug_estimation(logger, e, layout.root) estimators.append(e)