Skip to content

Commit 0742d96

Browse files
committed
FIX: Catch nonexistent derivatives, clean up subworkflow logic
1 parent 2bd036d commit 0742d96

File tree

1 file changed

+34
-20
lines changed

1 file changed

+34
-20
lines changed

nibabies/cli/parser.py

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
"""Parser."""
44
import sys
5+
import typing as ty
56

67
from .. import config
78

9+
if ty.TYPE_CHECKING:
10+
from bids.layout import BIDSLayout
11+
812

913
def _build_parser():
1014
"""Build parser object."""
@@ -19,9 +23,20 @@ def _build_parser():
1923

2024
def _path_exists(path, parser):
2125
"""Ensure a given path exists."""
22-
if path is None or not Path(path).exists():
26+
if path is None:
27+
raise parser.error("No value provided!")
28+
path = Path(path).absolute()
29+
if not path.exists():
2330
raise parser.error(f"Path does not exist: <{path}>.")
24-
return Path(path).absolute()
31+
return path
32+
33+
def _dir_not_empty(path, parser):
34+
path = _path_exists(path, parser)
35+
if not path.is_dir():
36+
raise parser.error(f"Path is not a directory <{path}>.")
37+
for f in path.iterdir():
38+
return path
39+
raise parser.error(f"Directory found with no contents <{path}>.")
2540

2641
def _is_file(path, parser):
2742
"""Ensure a given path exists and it is a file."""
@@ -87,6 +102,7 @@ def _slice_time_ref(value, parser):
87102
formatter_class=ArgumentDefaultsHelpFormatter,
88103
)
89104
PathExists = partial(_path_exists, parser=parser)
105+
DirNotEmpty = partial(_dir_not_empty, parser=parser)
90106
IsFile = partial(_is_file, parser=parser)
91107
PositiveInt = partial(_min_one, parser=parser)
92108
SliceTimeRef = partial(_slice_time_ref, parser=parser)
@@ -635,7 +651,7 @@ def _slice_time_ref(value, parser):
635651
)
636652
g_baby.add_argument(
637653
"--segmentation-atlases-dir",
638-
type=PathExists,
654+
type=DirNotEmpty,
639655
help="Directory containing precalculated segmentations to use for JointLabelFusion.",
640656
)
641657
g_baby.add_argument(
@@ -647,7 +663,7 @@ def _slice_time_ref(value, parser):
647663
g_baby.add_argument(
648664
"-d",
649665
"--derivatives",
650-
type=PathExists,
666+
type=DirNotEmpty,
651667
nargs="+",
652668
help="One or more directory containing pre-computed derivatives.",
653669
)
@@ -822,42 +838,40 @@ def parse_args(args=None, namespace=None):
822838
)
823839

824840
config.execution.participant_label = sorted(participant_label)
841+
842+
config.execution.unique_labels = compute_subworkflows(
843+
layout=config.execution.layout,
844+
participant_ids=config.execution.participant_label,
845+
session_ids=config.execution.session_id,
846+
)
825847
config.workflow.skull_strip_template = config.workflow.skull_strip_template[0]
826-
config.execution.unique_labels = compute_subworkflows()
827848

828849
# finally, write config to file
829850
config_file = config.execution.work_dir / config.execution.run_uuid / "config.toml"
830851
config_file.parent.mkdir(exist_ok=True, parents=True)
831852
config.to_filename(config_file)
832853

833854

834-
def compute_subworkflows() -> list:
855+
def compute_subworkflows(
856+
*,
857+
layout: 'BIDSLayout',
858+
participant_ids: list,
859+
session_ids: list | None = None,
860+
) -> list:
835861
"""
836862
Query all available participants and sessions, and construct the combinations of the
837863
subworkflows needed.
838864
"""
839865
from niworkflows.utils.bids import collect_participants
840866

841-
from nibabies import config
842-
843867
# consists of (subject_id, session_id) tuples
844868
subworkflows = []
845869

846-
subject_list = collect_participants(
847-
config.execution.layout,
848-
participant_label=config.execution.participant_label,
849-
strict=True,
850-
)
851-
870+
subject_list = collect_participants(layout, participant_ids, strict=True)
852871
for subject in subject_list:
853872
# Due to rapidly changing morphometry of the population
854873
# Ensure each subject session is processed individually
855-
sessions = (
856-
config.execution.session_id
857-
or config.execution.layout.get_sessions(scope='raw', subject=subject)
858-
or [None]
859-
)
860-
# grab participant age per session
874+
sessions = session_ids or layout.get_sessions(scope='raw', subject=subject) or [None]
861875
for session in sessions:
862876
subworkflows.append((subject, session))
863877
return subworkflows

0 commit comments

Comments
 (0)