Skip to content

Commit

Permalink
Merge pull request #328 from mgxd/new/reports
Browse files Browse the repository at this point in the history
ENH: Use nireports report generation
  • Loading branch information
mgxd authored Dec 20, 2023
2 parents f6ad255 + 07eece0 commit 7c8f110
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 84 deletions.
2 changes: 0 additions & 2 deletions nibabies/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ def main():
config.execution.unique_labels,
config.execution.nibabies_dir,
config.execution.run_uuid,
config=pkgrf("nibabies", "data/reports-spec.yml"),
packagename="nibabies",
)
write_derivative_description(config.execution.bids_dir, config.execution.nibabies_dir)
write_bidsignore(config.execution.nibabies_dir)
Expand Down
2 changes: 0 additions & 2 deletions nibabies/cli/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ def build_workflow(config_file):
config.execution.unique_labels,
nibabies_dir,
config.execution.run_uuid,
config=pkgrf("nibabies", "data/reports-spec.yml"),
packagename="nibabies",
)
return retval

Expand Down
8 changes: 8 additions & 0 deletions nibabies/data/reports-spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@ sections:
static: false
subtitle: Spatial normalization of the anatomical T1w reference
- bids: {datatype: figures, desc: reconall, suffix: T1w}
caption: Surfaces (white and pial) reconstructed with FreeSurfer (<code>recon-all</code>)
overlaid on the participant's T1w template.
subtitle: Surface reconstruction
- bids: {datatype: figures, desc: infantfs, suffix: T1w}
caption: Surfaces (white and pial) reconstructed with FreeSurfer (<code>infant_recon_all</code>)
overlaid on the participant's T1w template.
subtitle: Surface reconstruction
- bids: {datatype: figures, desc: mcribs, suffix: T2w}
caption: Surfaces (white and pial) reconstructed with M-CRIB-S (<code>MCRIBReconAll</code>)
overlaid on the participant's T2w template.
subtitle: Surface reconstruction

- name: <em>B<sub>0</sub></em> field mapping
ordering: session,acquisition,run,fmapid
Expand Down
86 changes: 11 additions & 75 deletions nibabies/reports/core.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,16 @@
from itertools import product
from pathlib import Path

from niworkflows.reports.core import Report as _Report
from pkg_resources import resource_filename as pkgrf
from nireports.assembler.report import Report


class Report(_Report):
# niworkflows patch to preserve `out_filename` even if subject_id is present
def __init__(
self,
out_dir,
run_uuid,
config=None,
out_filename=None,
packagename=None,
reportlets_dir=None,
subject_id=None,
):
self.root = Path(reportlets_dir or out_dir)

# Initialize structuring elements
self.sections = []
self.errors = []
self.out_dir = Path(out_dir)
self.run_uuid = run_uuid
self.packagename = packagename
self.subject_id = subject_id
if subject_id is not None:
self.subject_id = subject_id[4:] if subject_id.startswith("sub-") else subject_id
# ensure set output filename is preserved
if not out_filename:
out_filename = f"sub-{self.subject_id}.html"

self.out_filename = out_filename or "report.html"

# Default template from niworkflows
self.template_path = Path(pkgrf("niworkflows", "reports/report.tpl"))
self._load_config(Path(config or pkgrf("niworkflows", "reports/default.yml")))
assert self.template_path.exists()

# TODO: Upstream ``Report._load_config`` to niworkflows
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 nibabies in the path.

if self.subject_id is not None:
self.root = self.root / "sub-{}".format(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 NiBabies
#
from nibabies.data import load_resource


def run_reports(
out_dir,
subject_label,
subject,
run_uuid,
config=None,
out_filename='report.html',
session=None,
out_filename=None,
reportlets_dir=None,
packagename=None,
):
Expand All @@ -78,10 +20,9 @@ def run_reports(
return Report(
out_dir,
run_uuid,
config=config,
out_filename=out_filename,
subject_id=subject_label,
packagename=packagename,
subject=subject,
session=session,
bootstrap_file=load_resource('reports-spec.yml'),
reportlets_dir=reportlets_dir,
).generate_report()

Expand All @@ -90,7 +31,6 @@ def generate_reports(
sub_ses_list,
output_dir,
run_uuid,
config=None,
work_dir=None,
packagename=None,
):
Expand All @@ -100,17 +40,13 @@ def generate_reports(
reportlets_dir = Path(work_dir) / "reportlets"

report_errors = []
for subject_label, session in sub_ses_list:
html_report = ''.join(
[f"sub-{subject_label}", f"_ses-{session}" if session else "", ".html"]
)
for subject, session in sub_ses_list:
report_errors.append(
run_reports(
output_dir,
subject_label,
subject,
run_uuid,
config=config,
out_filename=html_report,
session=session,
packagename=packagename,
reportlets_dir=reportlets_dir,
)
Expand Down
14 changes: 9 additions & 5 deletions nibabies/workflows/anatomical/outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,25 +233,29 @@ def init_anat_reports_wf(
if not surface_recon:
return workflow

# TODO: Separate report for MCRIBS?
from smriprep.interfaces.reports import FSSurfaceReport

recon_report = pe.Node(FSSurfaceReport(), name="recon_report")
recon_report.interface._always_run = True

if surface_recon == "freesurfer":
recon_desc = "reconall"
elif surface_recon == "infantfs":
recon_desc = "infantfs"
elif surface_recon == "mcribs":
recon_desc = "mcribs"

ds_recon_report = pe.Node(
DerivativesDataSink(base_directory=output_dir, desc="reconall", datatype="figures"),
DerivativesDataSink(base_directory=output_dir, desc=recon_desc, datatype="figures"),
name="ds_recon_report",
run_without_submitting=True,
)
# fmt: off
workflow.connect([
(inputnode, recon_report, [('subjects_dir', 'subjects_dir'),
('subject_id', 'subject_id')]),
(recon_report, ds_recon_report, [('out_report', 'in_file')]),
(inputnode, ds_recon_report, [('source_file', 'source_file')])
])
# fmt: on
]) # fmt: skip

return workflow

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies = [
'importlib_resources; python_version < "3.9"',
"nibabel >= 5.0.0",
"nipype >= 1.8.5",
"nireports >= 23.2.0",
"nitime",
"nitransforms >= 23.0.1",
"niworkflows >= 1.9.0",
Expand Down

0 comments on commit 7c8f110

Please sign in to comment.