Skip to content

Commit 9568ccb

Browse files
authored
RF: Load report assembler from nireports (#3177)
This transition is inspired by how MRIQC defines `generate_reports` using _nireports_' Report() mnt: load Report from nireports instead of niworkflows mnt: adapt function arguments accordingly mnt: delete run_reports function mnt: delete Report patch subclass that is no longer necessary
2 parents d85fb53 + 89da33b commit 9568ccb

File tree

3 files changed

+45
-91
lines changed

3 files changed

+45
-91
lines changed

fmriprep/cli/run.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,23 @@ def main():
219219
config.execution.fmriprep_dir,
220220
config.execution.run_uuid,
221221
config=data.load("reports-spec.yml"),
222-
packagename="fmriprep",
223222
)
224223
write_derivative_description(config.execution.bids_dir, config.execution.fmriprep_dir)
225224
write_bidsignore(config.execution.fmriprep_dir)
226225

226+
if failed_reports:
227+
config.loggers.cli.error(
228+
"Report generation was not successful for the following participants : %s.",
229+
", ".join(failed_reports),
230+
)
231+
227232
if sentry_sdk is not None and failed_reports:
228233
sentry_sdk.capture_message(
229-
"Report generation failed for %d subjects" % failed_reports,
234+
"Report generation was not successful for the following participants : %s.",
235+
", ".join(failed_reports),
230236
level="error",
231237
)
232-
sys.exit(int((errno + failed_reports) > 0))
238+
sys.exit(int((errno + len(failed_reports)) > 0))
233239

234240

235241
if __name__ == "__main__":

fmriprep/cli/workflow.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,19 @@ def build_workflow(config_file, retval):
8686
# Called with reports only
8787
if config.execution.reports_only:
8888
build_log.log(25, "Running --reports-only on participants %s", ", ".join(subject_list))
89-
retval["return_code"] = generate_reports(
89+
failed_reports = generate_reports(
9090
config.execution.participant_label,
9191
config.execution.fmriprep_dir,
9292
config.execution.run_uuid,
9393
config=data.load("reports-spec.yml"),
94-
packagename="fmriprep",
9594
)
95+
if failed_reports:
96+
config.loggers.cli.error(
97+
"Report generation was not successful for the following participants : %s.",
98+
", ".join(failed_reports),
99+
)
100+
101+
retval["return_code"] = len(failed_reports)
96102
return retval
97103

98104
# Build main workflow

fmriprep/reports/core.py

Lines changed: 28 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -22,100 +22,42 @@
2222
#
2323
from pathlib import Path
2424

25-
from niworkflows.reports.core import Report as _Report
25+
from nireports.assembler.report import Report
2626

27-
# This patch is intended to permit fMRIPrep 20.2.0 LTS to use the YODA-style
28-
# derivatives directory. Ideally, we will remove this in 20.3.x and use an
29-
# updated niworkflows.
3027

31-
32-
class Report(_Report):
33-
def _load_config(self, config):
34-
from yaml import safe_load as load
35-
36-
settings = load(config.read_text())
37-
self.packagename = self.packagename or settings.get("package", None)
38-
39-
# Removed from here: Appending self.packagename to self.root and self.out_dir
40-
# In this version, pass reportlets_dir and out_dir with fmriprep in the path.
41-
42-
if self.subject_id is not None:
43-
self.root = self.root / f"sub-{self.subject_id}"
44-
45-
if "template_path" in settings:
46-
self.template_path = config.parent / settings["template_path"]
47-
48-
self.index(settings["sections"])
49-
50-
51-
#
52-
# The following are the interface used directly by fMRIPrep
53-
#
54-
55-
56-
def run_reports(
57-
out_dir,
58-
subject_label,
59-
run_uuid,
60-
config=None,
61-
reportlets_dir=None,
62-
packagename=None,
63-
):
64-
"""
65-
Run the reports.
66-
67-
.. testsetup::
68-
69-
>>> copytree_or_skip("data/tests/work", testdir)
70-
>>> (testdir / 'fmriprep').mkdir(parents=True, exist_ok=True)
71-
72-
.. doctest::
73-
74-
>>> run_reports(testdir / 'out', '01', 'madeoutuuid', packagename='fmriprep',
75-
... reportlets_dir=testdir / 'work' / 'reportlets' / 'fmriprep')
76-
0
77-
78-
"""
79-
return Report(
80-
out_dir,
81-
run_uuid,
82-
config=config,
83-
subject_id=subject_label,
84-
packagename=packagename,
85-
reportlets_dir=reportlets_dir,
86-
).generate_report()
87-
88-
89-
def generate_reports(
90-
subject_list, output_dir, run_uuid, config=None, work_dir=None, packagename=None
91-
):
92-
"""Execute run_reports on a list of subjects."""
28+
def generate_reports(subject_list, output_dir, run_uuid, config=None, work_dir=None):
29+
"""Generate reports for a list of subjects."""
9330
reportlets_dir = None
9431
if work_dir is not None:
9532
reportlets_dir = Path(work_dir) / "reportlets"
96-
report_errors = [
97-
run_reports(
33+
34+
errors = []
35+
for subject_label in subject_list:
36+
entities = {}
37+
entities["subject"] = subject_label
38+
39+
robj = Report(
9840
output_dir,
99-
subject_label,
10041
run_uuid,
101-
config=config,
102-
packagename=packagename,
42+
bootstrap_file=config,
10343
reportlets_dir=reportlets_dir,
44+
plugins=None,
45+
plugin_meta=None,
46+
metadata=None,
47+
**entities,
10448
)
105-
for subject_label in subject_list
106-
]
10749

108-
errno = sum(report_errors)
109-
if errno:
110-
import logging
50+
# Count nbr of subject for which report generation failed
51+
try:
52+
robj.generate_report()
53+
except:
54+
import sys
55+
import traceback
11156

112-
logger = logging.getLogger("cli")
113-
error_list = ", ".join(
114-
f"{subid} ({err})" for subid, err in zip(subject_list, report_errors) if err
115-
)
116-
logger.error(
117-
"Preprocessing did not finish successfully. Errors occurred while processing "
118-
"data from participants: %s. Check the HTML reports for details.",
119-
error_list,
120-
)
121-
return errno
57+
errors.append(subject_label)
58+
traceback.print_exception(
59+
*sys.exc_info(),
60+
file=str(Path(output_dir) / "logs" / f"report-{run_uuid}-{subject_label}.err"),
61+
)
62+
63+
return errors

0 commit comments

Comments
 (0)