diff --git a/niworkflows/interfaces/plotting.py b/niworkflows/interfaces/plotting.py
index c37aa9b1d3b..874ced26cf5 100644
--- a/niworkflows/interfaces/plotting.py
+++ b/niworkflows/interfaces/plotting.py
@@ -21,229 +21,17 @@
# https://www.nipreps.org/community/licensing/
#
"""Visualization tools."""
-import numpy as np
-import nibabel as nb
-
-from nipype.utils.filemanip import fname_presuffix
-from nipype.interfaces.base import (
- File,
- BaseInterfaceInputSpec,
- TraitedSpec,
- SimpleInterface,
- traits,
- isdefined,
-)
-from niworkflows.utils.timeseries import _cifti_timeseries, _nifti_timeseries
-from niworkflows.viz.plots import (
- fMRIPlot,
- compcor_variance_plot,
- confounds_correlation_plot,
+import warnings
+from nireports.interfaces import (
+ CompCorVariancePlot,
+ ConfoundsCorrelationPlot,
+ FMRISummary,
)
+__all__ = (
+ "CompCorVariancePlot",
+ "ConfoundsCorrelationPlot",
+ "FMRISummary",
+)
-class _FMRISummaryInputSpec(BaseInterfaceInputSpec):
- in_func = File(exists=True, mandatory=True, desc="")
- in_spikes_bg = File(exists=True, desc="")
- fd = File(exists=True, desc="")
- dvars = File(exists=True, desc="")
- outliers = File(exists=True, desc="")
- in_segm = File(exists=True, desc="")
- tr = traits.Either(None, traits.Float, usedefault=True, desc="the TR")
- fd_thres = traits.Float(0.2, usedefault=True, desc="")
- drop_trs = traits.Int(0, usedefault=True, desc="dummy scans")
-
-
-class _FMRISummaryOutputSpec(TraitedSpec):
- out_file = File(exists=True, desc="written file path")
-
-
-class FMRISummary(SimpleInterface):
- """Prepare an fMRI summary plot for the report."""
-
- input_spec = _FMRISummaryInputSpec
- output_spec = _FMRISummaryOutputSpec
-
- def _run_interface(self, runtime):
- import pandas as pd
-
- self._results["out_file"] = fname_presuffix(
- self.inputs.in_func,
- suffix="_fmriplot.svg",
- use_ext=False,
- newpath=runtime.cwd,
- )
-
- dataframe = pd.DataFrame({
- "outliers": np.loadtxt(self.inputs.outliers, usecols=[0]).tolist(),
- # Pick non-standardize dvars (col 1)
- # First timepoint is NaN (difference)
- "DVARS": [np.nan]
- + np.loadtxt(self.inputs.dvars, skiprows=1, usecols=[1]).tolist(),
- # First timepoint is zero (reference volume)
- "FD": [0.0]
- + np.loadtxt(self.inputs.fd, skiprows=1, usecols=[0]).tolist(),
- }) if (
- isdefined(self.inputs.outliers)
- and isdefined(self.inputs.dvars)
- and isdefined(self.inputs.fd)
- ) else None
-
- input_data = nb.load(self.inputs.in_func)
- seg_file = self.inputs.in_segm if isdefined(self.inputs.in_segm) else None
- dataset, segments = (
- _cifti_timeseries(input_data)
- if isinstance(input_data, nb.Cifti2Image) else
- _nifti_timeseries(input_data, seg_file)
- )
-
- fig = fMRIPlot(
- dataset,
- segments=segments,
- spikes_files=(
- [self.inputs.in_spikes_bg]
- if isdefined(self.inputs.in_spikes_bg) else None
- ),
- tr=(
- self.inputs.tr if isdefined(self.inputs.tr) else
- _get_tr(input_data)
- ),
- confounds=dataframe,
- units={"outliers": "%", "FD": "mm"},
- vlines={"FD": [self.inputs.fd_thres]},
- nskip=self.inputs.drop_trs,
- ).plot()
- fig.savefig(self._results["out_file"], bbox_inches="tight")
- return runtime
-
-
-class _CompCorVariancePlotInputSpec(BaseInterfaceInputSpec):
- metadata_files = traits.List(
- File(exists=True),
- mandatory=True,
- desc="List of files containing component " "metadata",
- )
- metadata_sources = traits.List(
- traits.Str,
- desc="List of names of decompositions "
- "(e.g., aCompCor, tCompCor) yielding "
- "the arguments in `metadata_files`",
- )
- variance_thresholds = traits.Tuple(
- traits.Float(0.5),
- traits.Float(0.7),
- traits.Float(0.9),
- usedefault=True,
- desc="Levels of explained variance to include in " "plot",
- )
- out_file = traits.Either(
- None, File, value=None, usedefault=True, desc="Path to save plot"
- )
-
-
-class _CompCorVariancePlotOutputSpec(TraitedSpec):
- out_file = File(exists=True, desc="Path to saved plot")
-
-
-class CompCorVariancePlot(SimpleInterface):
- """Plot the number of components necessary to explain the specified levels of variance."""
-
- input_spec = _CompCorVariancePlotInputSpec
- output_spec = _CompCorVariancePlotOutputSpec
-
- def _run_interface(self, runtime):
- if self.inputs.out_file is None:
- self._results["out_file"] = fname_presuffix(
- self.inputs.metadata_files[0],
- suffix="_compcor.svg",
- use_ext=False,
- newpath=runtime.cwd,
- )
- else:
- self._results["out_file"] = self.inputs.out_file
- compcor_variance_plot(
- metadata_files=self.inputs.metadata_files,
- metadata_sources=self.inputs.metadata_sources,
- output_file=self._results["out_file"],
- varexp_thresh=self.inputs.variance_thresholds,
- )
- return runtime
-
-
-class _ConfoundsCorrelationPlotInputSpec(BaseInterfaceInputSpec):
- confounds_file = File(
- exists=True, mandatory=True, desc="File containing confound regressors"
- )
- out_file = traits.Either(
- None, File, value=None, usedefault=True, desc="Path to save plot"
- )
- reference_column = traits.Str(
- "global_signal",
- usedefault=True,
- desc="Column in the confound file for "
- "which all correlation magnitudes "
- "should be ranked and plotted",
- )
- columns = traits.List(
- traits.Str,
- desc="Filter out all regressors not found in this list."
- )
- max_dim = traits.Int(
- 20,
- usedefault=True,
- desc="Maximum number of regressors to include in "
- "plot. Regressors with highest magnitude of "
- "correlation with `reference_column` will be "
- "selected.",
- )
-
-
-class _ConfoundsCorrelationPlotOutputSpec(TraitedSpec):
- out_file = File(exists=True, desc="Path to saved plot")
-
-
-class ConfoundsCorrelationPlot(SimpleInterface):
- """Plot the correlation among confound regressors."""
-
- input_spec = _ConfoundsCorrelationPlotInputSpec
- output_spec = _ConfoundsCorrelationPlotOutputSpec
-
- def _run_interface(self, runtime):
- if self.inputs.out_file is None:
- self._results["out_file"] = fname_presuffix(
- self.inputs.confounds_file,
- suffix="_confoundCorrelation.svg",
- use_ext=False,
- newpath=runtime.cwd,
- )
- else:
- self._results["out_file"] = self.inputs.out_file
- confounds_correlation_plot(
- confounds_file=self.inputs.confounds_file,
- columns=self.inputs.columns if isdefined(self.inputs.columns) else None,
- max_dim=self.inputs.max_dim,
- output_file=self._results["out_file"],
- reference=self.inputs.reference_column,
- )
- return runtime
-
-
-def _get_tr(img):
- """
- Attempt to extract repetition time from NIfTI/CIFTI header
-
- Examples
- --------
- >>> _get_tr(nb.load(Path(test_data) /
- ... 'sub-ds205s03_task-functionallocalizer_run-01_bold_volreg.nii.gz'))
- 2.2
- >>> _get_tr(nb.load(Path(test_data) /
- ... 'sub-01_task-mixedgamblestask_run-02_space-fsLR_den-91k_bold.dtseries.nii'))
- 2.0
-
- """
-
- try:
- return img.header.matrix.get_index_map(0).series_step
- except AttributeError:
- return img.header.get_zooms()[-1]
- raise RuntimeError("Could not extract TR - unknown data structure type")
+warnings.warn("Please use nireports.interfaces", DeprecationWarning)
diff --git a/niworkflows/reports/core.py b/niworkflows/reports/core.py
index d7a460fc01a..701171e28c8 100644
--- a/niworkflows/reports/core.py
+++ b/niworkflows/reports/core.py
@@ -20,572 +20,21 @@
#
# https://www.nipreps.org/community/licensing/
#
-"""
-Reports builder for BIDS-Apps.
-
-Generalizes report generation across BIDS-Apps
-
-"""
-from pathlib import Path
-import re
-from itertools import compress
-from collections import defaultdict
-from pkg_resources import resource_filename as pkgrf
-from bids.layout import BIDSLayout, add_config_paths
-import jinja2
-from nipype.utils.filemanip import copyfile
-
-# Add a new figures spec
-try:
- add_config_paths(figures=pkgrf("niworkflows", "data/nipreps.json"))
-except ValueError as e:
- if "Configuration 'figures' already exists" != str(e):
- raise
-
-PLURAL_SUFFIX = defaultdict(str("s").format, [("echo", "es")])
-SVG_SNIPPET = [
- """\
-
-
-
-""",
- """\
-
-
-
-""",
-]
-
-
-class Smallest:
- """An object that always evaluates smaller than anything else, for sorting
-
- >>> Smallest() < 1
- True
- >>> Smallest() < "epsilon"
- True
- >>> sorted([1, None, 2], key=lambda x: x if x is not None else Smallest())
- [None, 1, 2]
- """
- def __lt__(self, other):
- return not isinstance(other, Smallest)
-
- def __eq__(self, other):
- return isinstance(other, Smallest)
-
- def __gt__(self, other):
- return False
-
-
-class Element(object):
- """Just a basic component of a report"""
-
- def __init__(self, name, title=None):
- self.name = name
- self.title = title
-
-
-class Reportlet(Element):
- """
- A reportlet has title, description and a list of components with either an
- HTML fragment or a path to an SVG file, and possibly a caption. This is a
- factory class to generate Reportlets reusing the layout from a ``Report``
- object.
-
- .. testsetup::
-
- >>> cwd = os.getcwd()
- >>> os.chdir(tmpdir)
-
- >>> from pkg_resources import resource_filename
- >>> from shutil import copytree
- >>> from bids.layout import BIDSLayout
- >>> test_data_path = resource_filename('niworkflows', 'data/tests/work')
- >>> testdir = Path(tmpdir)
- >>> data_dir = copytree(test_data_path, str(testdir / 'work'))
- >>> out_figs = testdir / 'out' / 'fmriprep'
- >>> bl = BIDSLayout(str(testdir / 'work' / 'reportlets'),
- ... config='figures', validate=False)
-
- .. doctest::
-
- >>> bl.get(subject='01', desc='reconall') # doctest: +ELLIPSIS
- []
-
- >>> len(bl.get(subject='01', space='.*', regex_search=True))
- 2
-
- >>> r = Reportlet(bl, out_figs, config={
- ... 'title': 'Some Title', 'bids': {'datatype': 'figures', 'desc': 'reconall'},
- ... 'description': 'Some description'})
- >>> r.name
- 'datatype-figures_desc-reconall'
-
- >>> r.components[0][0].startswith('>> r = Reportlet(bl, out_figs, config={
- ... 'title': 'Some Title', 'bids': {'datatype': 'figures', 'desc': 'reconall'},
- ... 'description': 'Some description', 'static': False})
- >>> r.name
- 'datatype-figures_desc-reconall'
-
- >>> r.components[0][0].startswith('