Skip to content

Commit c1126ae

Browse files
authored
Merge pull request #336 from mgxd/rf/subworkflows
FIX: Catch nonexistent derivatives, clean up subworkflow logic
2 parents 2bd036d + 9dd371e commit c1126ae

File tree

1 file changed

+36
-20
lines changed

1 file changed

+36
-20
lines changed

nibabies/cli/parser.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
"""Parser."""
4+
from __future__ import annotations
5+
46
import sys
7+
import typing as ty
58

69
from .. import config
710

11+
if ty.TYPE_CHECKING:
12+
from bids.layout import BIDSLayout
13+
814

915
def _build_parser():
1016
"""Build parser object."""
@@ -19,9 +25,20 @@ def _build_parser():
1925

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

2643
def _is_file(path, parser):
2744
"""Ensure a given path exists and it is a file."""
@@ -87,6 +104,7 @@ def _slice_time_ref(value, parser):
87104
formatter_class=ArgumentDefaultsHelpFormatter,
88105
)
89106
PathExists = partial(_path_exists, parser=parser)
107+
DirNotEmpty = partial(_dir_not_empty, parser=parser)
90108
IsFile = partial(_is_file, parser=parser)
91109
PositiveInt = partial(_min_one, parser=parser)
92110
SliceTimeRef = partial(_slice_time_ref, parser=parser)
@@ -635,7 +653,7 @@ def _slice_time_ref(value, parser):
635653
)
636654
g_baby.add_argument(
637655
"--segmentation-atlases-dir",
638-
type=PathExists,
656+
type=DirNotEmpty,
639657
help="Directory containing precalculated segmentations to use for JointLabelFusion.",
640658
)
641659
g_baby.add_argument(
@@ -647,7 +665,7 @@ def _slice_time_ref(value, parser):
647665
g_baby.add_argument(
648666
"-d",
649667
"--derivatives",
650-
type=PathExists,
668+
type=DirNotEmpty,
651669
nargs="+",
652670
help="One or more directory containing pre-computed derivatives.",
653671
)
@@ -822,42 +840,40 @@ def parse_args(args=None, namespace=None):
822840
)
823841

824842
config.execution.participant_label = sorted(participant_label)
843+
844+
config.execution.unique_labels = compute_subworkflows(
845+
layout=config.execution.layout,
846+
participant_ids=config.execution.participant_label,
847+
session_ids=config.execution.session_id,
848+
)
825849
config.workflow.skull_strip_template = config.workflow.skull_strip_template[0]
826-
config.execution.unique_labels = compute_subworkflows()
827850

828851
# finally, write config to file
829852
config_file = config.execution.work_dir / config.execution.run_uuid / "config.toml"
830853
config_file.parent.mkdir(exist_ok=True, parents=True)
831854
config.to_filename(config_file)
832855

833856

834-
def compute_subworkflows() -> list:
857+
def compute_subworkflows(
858+
*,
859+
layout: 'BIDSLayout',
860+
participant_ids: list,
861+
session_ids: list | None = None,
862+
) -> list:
835863
"""
836864
Query all available participants and sessions, and construct the combinations of the
837865
subworkflows needed.
838866
"""
839867
from niworkflows.utils.bids import collect_participants
840868

841-
from nibabies import config
842-
843869
# consists of (subject_id, session_id) tuples
844870
subworkflows = []
845871

846-
subject_list = collect_participants(
847-
config.execution.layout,
848-
participant_label=config.execution.participant_label,
849-
strict=True,
850-
)
851-
872+
subject_list = collect_participants(layout, participant_ids, strict=True)
852873
for subject in subject_list:
853874
# Due to rapidly changing morphometry of the population
854875
# 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
876+
sessions = session_ids or layout.get_sessions(scope='raw', subject=subject) or [None]
861877
for session in sessions:
862878
subworkflows.append((subject, session))
863879
return subworkflows

0 commit comments

Comments
 (0)