diff --git a/fmriprep/cli/run.py b/fmriprep/cli/run.py index 891284463..551dc014c 100644 --- a/fmriprep/cli/run.py +++ b/fmriprep/cli/run.py @@ -219,17 +219,23 @@ def main(): config.execution.fmriprep_dir, config.execution.run_uuid, config=data.load("reports-spec.yml"), - packagename="fmriprep", ) write_derivative_description(config.execution.bids_dir, config.execution.fmriprep_dir) write_bidsignore(config.execution.fmriprep_dir) + if failed_reports: + config.loggers.cli.error( + "Report generation was not successful for the following participants : %s.", + ", ".join(failed_reports), + ) + if sentry_sdk is not None and failed_reports: sentry_sdk.capture_message( - "Report generation failed for %d subjects" % failed_reports, + "Report generation was not successful for the following participants : %s.", + ", ".join(failed_reports), level="error", ) - sys.exit(int((errno + failed_reports) > 0)) + sys.exit(int((errno + len(failed_reports)) > 0)) if __name__ == "__main__": diff --git a/fmriprep/cli/workflow.py b/fmriprep/cli/workflow.py index 6d754a93d..47db8ec05 100644 --- a/fmriprep/cli/workflow.py +++ b/fmriprep/cli/workflow.py @@ -86,13 +86,19 @@ def build_workflow(config_file, retval): # Called with reports only if config.execution.reports_only: build_log.log(25, "Running --reports-only on participants %s", ", ".join(subject_list)) - retval["return_code"] = generate_reports( + failed_reports = generate_reports( config.execution.participant_label, config.execution.fmriprep_dir, config.execution.run_uuid, config=data.load("reports-spec.yml"), - packagename="fmriprep", ) + if failed_reports: + config.loggers.cli.error( + "Report generation was not successful for the following participants : %s.", + ", ".join(failed_reports), + ) + + retval["return_code"] = len(failed_reports) return retval # Build main workflow diff --git a/fmriprep/reports/core.py b/fmriprep/reports/core.py index 950524e50..55b3be419 100644 --- a/fmriprep/reports/core.py +++ b/fmriprep/reports/core.py @@ -22,100 +22,42 @@ # from pathlib import Path -from niworkflows.reports.core import Report as _Report +from nireports.assembler.report import Report -# This patch is intended to permit fMRIPrep 20.2.0 LTS to use the YODA-style -# derivatives directory. Ideally, we will remove this in 20.3.x and use an -# updated niworkflows. - -class Report(_Report): - def _load_config(self, config): - from yaml import safe_load as load - - settings = load(config.read_text()) - self.packagename = self.packagename or settings.get("package", None) - - # Removed from here: Appending self.packagename to self.root and self.out_dir - # In this version, pass reportlets_dir and out_dir with fmriprep in the path. - - if self.subject_id is not None: - self.root = self.root / f"sub-{self.subject_id}" - - if "template_path" in settings: - self.template_path = config.parent / settings["template_path"] - - self.index(settings["sections"]) - - -# -# The following are the interface used directly by fMRIPrep -# - - -def run_reports( - out_dir, - subject_label, - run_uuid, - config=None, - reportlets_dir=None, - packagename=None, -): - """ - Run the reports. - - .. testsetup:: - - >>> copytree_or_skip("data/tests/work", testdir) - >>> (testdir / 'fmriprep').mkdir(parents=True, exist_ok=True) - - .. doctest:: - - >>> run_reports(testdir / 'out', '01', 'madeoutuuid', packagename='fmriprep', - ... reportlets_dir=testdir / 'work' / 'reportlets' / 'fmriprep') - 0 - - """ - return Report( - out_dir, - run_uuid, - config=config, - subject_id=subject_label, - packagename=packagename, - reportlets_dir=reportlets_dir, - ).generate_report() - - -def generate_reports( - subject_list, output_dir, run_uuid, config=None, work_dir=None, packagename=None -): - """Execute run_reports on a list of subjects.""" +def generate_reports(subject_list, output_dir, run_uuid, config=None, work_dir=None): + """Generate reports for a list of subjects.""" reportlets_dir = None if work_dir is not None: reportlets_dir = Path(work_dir) / "reportlets" - report_errors = [ - run_reports( + + errors = [] + for subject_label in subject_list: + entities = {} + entities["subject"] = subject_label + + robj = Report( output_dir, - subject_label, run_uuid, - config=config, - packagename=packagename, + bootstrap_file=config, reportlets_dir=reportlets_dir, + plugins=None, + plugin_meta=None, + metadata=None, + **entities, ) - for subject_label in subject_list - ] - errno = sum(report_errors) - if errno: - import logging + # Count nbr of subject for which report generation failed + try: + robj.generate_report() + except: + import sys + import traceback - logger = logging.getLogger("cli") - error_list = ", ".join( - f"{subid} ({err})" for subid, err in zip(subject_list, report_errors) if err - ) - logger.error( - "Preprocessing did not finish successfully. Errors occurred while processing " - "data from participants: %s. Check the HTML reports for details.", - error_list, - ) - return errno + errors.append(subject_label) + traceback.print_exception( + *sys.exc_info(), + file=str(Path(output_dir) / "logs" / f"report-{run_uuid}-{subject_label}.err"), + ) + + return errors