Skip to content

Commit

Permalink
enh: add support for BIDS filters file a la *fMRIPrep*
Browse files Browse the repository at this point in the history
Resolves: #760.

Co-authored-by: Chris Markiewicz <effigies@gmail.com>
  • Loading branch information
oesteban and effigies committed Nov 15, 2023
1 parent 741d1a3 commit 0aec011
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
32 changes: 20 additions & 12 deletions mriqc/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ def _bids_filter(value):
help="A space delimited list of participant identifiers or a single "
"identifier (the sub- prefix can be removed).",
)
g_bids.add_argument(
'--bids-filter-file', action='store', type=Path, metavar='PATH',
help='a JSON file describing custom BIDS input filter using pybids '
'{<suffix>:{<entity>:<filter>,...},...} '
'(https://github.com/bids-standard/pybids/blob/master/bids/layout/config/bids.json)'
)
g_bids.add_argument(
"--session-id",
action="store",
Expand All @@ -184,7 +190,7 @@ def _bids_filter(value):
action="store",
type=int,
nargs="*",
help="Filter input dataset by run ID (only integer run IDs are valid).",
help="DEPRECATED - This argument will be disabled. Use ``--bids-filter-file`` instead.",
)
g_bids.add_argument(
"--task-id",
Expand Down Expand Up @@ -447,6 +453,8 @@ def parse_args(args=None, namespace=None):
"""Parse args and run further checks on the command line."""
from logging import DEBUG
from contextlib import suppress
from json import loads
from pprint import pformat

from niworkflows.utils.bids import collect_data, DEFAULT_BIDS_QUERIES

Expand All @@ -469,6 +477,10 @@ def parse_args(args=None, namespace=None):
"nprocs", config.nipype.nprocs
)

# Load BIDS filters
if opts.bids_filter_file:
config.execution.bids_filters = loads(opts.bids_filter_file.read_text())

bids_dir = config.execution.bids_dir
output_dir = config.execution.output_dir
work_dir = config.execution.work_dir
Expand Down Expand Up @@ -521,20 +533,13 @@ def parse_args(args=None, namespace=None):

# List of files to be run
lc_modalities = [mod.lower() for mod in config.execution.modalities]

bids_filters = (
{mod: {"run": config.execution.run_id} for mod in lc_modalities}
if config.execution.run_id
else {}
)

bids_dataset, _ = collect_data(
config.execution.layout,
config.execution.participant_label,
session_id=config.execution.session_id,
task=config.execution.task_id,
group_echos=False,
bids_filters=bids_filters,
bids_filters=config.execution.bids_filters,
queries={mod: DEFAULT_BIDS_QUERIES[mod] for mod in lc_modalities}
)

Expand All @@ -546,12 +551,15 @@ def parse_args(args=None, namespace=None):

# Check the query is not empty
if not list(config.workflow.inputs.values()):
_j = "\n *"
ffile = (
"(--bids-filter-file was not set)" if not opts.bids_filter_file
else f"(with '--bids-filter-file {opts.bids_filter_file}')"
)
parser.error(
f"""\
Querying BIDS dataset at <{config.execution.bids_dir}> got an empty result.
Please, check out your currently set filters:
{_j.join([''] + [': '.join((k, str(v))) for k, v in bids_filters.items()])}"""
Please, check out your currently set filters {ffile}:
{pformat(config.execution.bids_filters, indent=2, width=99)}"""
)

# Check no DWI or others are sneaked into MRIQC
Expand Down
11 changes: 11 additions & 0 deletions mriqc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ class execution(_Config):
"""Wipe out previously existing BIDS indexing caches, forcing re-indexing."""
bids_description_hash = None
"""Checksum (SHA256) of the ``dataset_description.json`` of the BIDS dataset."""
bids_filters = None
"""A dictionary describing custom BIDS input filter using PyBIDS."""
cwd = os.getcwd()
"""Current working directory."""
debug = False
Expand Down Expand Up @@ -436,6 +438,15 @@ class execution(_Config):
@classmethod
def init(cls):
"""Create a new BIDS Layout accessible with :attr:`~execution.layout`."""

if cls.bids_filters is None:
cls.bids_filters = {}

# Process --run-id if the argument was provided
if cls.run_id:
for mod in cls.modalities:
cls.bids_filters.setdefault(mod.lower(), {})["run"] = cls.run_id

if cls._layout is None:
import re
from bids.layout.index import BIDSLayoutIndexer
Expand Down

0 comments on commit 0aec011

Please sign in to comment.