pesky-fieldmaps/what-has-fieldmaps.py
Michał Szczepanik e744431151 Add scripts for investigating field maps
The focus is on visual grepping, ie. printing a few lines for each
subject to get an overview of the situation. We require JSON sidecars to
be present (to have been gotten).
2026-04-29 15:58:46 +02:00

63 lines
2.3 KiB
Python

# /// script
# dependencies = ["rich"]
# ///
#
# This script prints (in color) which field maps were matched to which
# acquisition. See arguments (or --help) for details.
import argparse
from collections import defaultdict
import json
from pathlib import Path, PurePosixPath
from rich.console import Console
from rich.theme import Theme
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("modality", help="Modality label, likely func or dwi")
parser.add_argument("ds_path", help="Path to BIDS dataset")
parser.add_argument("--session", default="001", help="Session label")
parser.add_argument("--theme", default="mocha", choices=["mocha", "latte"], help="Color theme ('mocha' - dark, 'latte' - light)")
args = parser.parse_args()
ses_label = args.session
mod_label = args.modality
ds_path = args.ds_path
# a color display for visual grepping
if args.theme == "mocha":
custom_theme = Theme({"info": "#cdd6f4", "warning": "#fab387", "danger": "#f38ba8"})
else:
custom_theme = Theme({"info": "#4c4f69", "warning": "#fe640b", "danger": "#d20f39"})
console = Console(theme=custom_theme)
# loop through subjects
ds_path = Path("q01-bids-dataset")
for sub_label in sorted([p.name[4:] for p in ds_path.glob("sub-*")]):
# print a rule
console.rule(sub_label)
# get a mapping of acquisitions to field maps
fmap_dict = defaultdict(list)
for jpath in (ds_path / f"sub-{sub_label}" / f"ses-{ses_label}" / "fmap").glob("*.json"):
if jpath.is_file():
with jpath.open() as fp:
fm_sidecar = json.load(fp)
for what in fm_sidecar.get("IntendedFor", []):
fmap_dict[PurePosixPath(what).name].append(jpath.name)
else:
console.print(f"Can't read {jpath.name}", style="warning")
# get a list of acquisitions
acq = sorted([p.name for p in (ds_path / f"sub-{sub_label}" / f"ses-{ses_label}" / mod_label).glob("*.nii.gz")])
# for each acquisition, display field maps
for fn in acq:
matching_fieldmaps = sorted(fmap_dict[fn])
if len(matching_fieldmaps) == 2:
style = "info"
elif len(matching_fieldmaps) > 0:
style = "warning"
else:
style = "danger"
console.print(f"{fn}{', '.join(sorted(fmap_dict[fn]))}", style=style)