diff --git a/bids/ext/reports/cli.py b/bids/ext/reports/cli.py index 973bd9e..2cc88c8 100644 --- a/bids/ext/reports/cli.py +++ b/bids/ext/reports/cli.py @@ -3,7 +3,6 @@ from __future__ import annotations import argparse -import sys from pathlib import Path from typing import IO, Sequence @@ -11,20 +10,29 @@ from bids.layout import BIDSLayout from bids.ext.reports import BIDSReport - -from ._version import __version__ -from .logger import pybids_reports_logger +from bids.ext.reports._version import __version__ +from bids.ext.reports.logger import pybids_reports_logger # from bids.reports import BIDSReport LOGGER = pybids_reports_logger() +def _path_exists(path, parser): + """Ensure a given path exists.""" + if path is None or not Path(path).exists(): + raise parser.error(f"Path does not exist: <{path}>.") + + return Path(path).absolute() + + class MuhParser(argparse.ArgumentParser): def _print_message(self, message: str, file: IO[str] | None = None) -> None: rich.print(message, file=file) def base_parser() -> MuhParser: + from functools import partial + parser = MuhParser( prog="pybids_reports", description="Report generator for BIDS datasets.", @@ -32,32 +40,35 @@ def base_parser() -> MuhParser: For a more readable version of this help section, see the online doc https://cohort-creator.readthedocs.io/en/latest/ """, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) + + PathExists = partial(_path_exists, parser=parser) + parser.add_argument( "bids_dir", - help=""" - Path to BIDS dataset. - """, - nargs=1, + action="store", + type=PathExists, + help="Path to BIDS dataset.", ) parser.add_argument( "output_dir", - help=""" - Output path. - """, - nargs=1, + action="store", + type=Path, + help="Output path.", ) parser.add_argument( "--participant_label", - help=""" - The label(s) of the participant(s) that should be used for the report. - The label corresponds to sub- from the BIDS spec - (so it does not include "sub-"). + help="""\ +The label(s) of the participant(s) that should be used for the report. +The label corresponds to sub- from the BIDS spec +(so it does not include "sub-"). - If this parameter is not provided, The first subject will be used. - Multiple participants can be specified with a space separated list. +If this parameter is not provided, The first subject will be used. +Multiple participants can be specified with a space separated list. """, nargs="+", + default=None, ) parser.add_argument( "-v", @@ -67,14 +78,12 @@ def base_parser() -> MuhParser: ) parser.add_argument( "--verbosity", - help=""" - Verbosity level. - """, required=False, choices=[0, 1, 2, 3], default=2, type=int, nargs=1, + help="Verbosity level.", ) return parser @@ -82,6 +91,7 @@ def base_parser() -> MuhParser: def set_verbosity(verbosity: int | list[int]) -> None: if isinstance(verbosity, list): verbosity = verbosity[0] + if verbosity == 0: LOGGER.setLevel("ERROR") elif verbosity == 1: @@ -92,24 +102,30 @@ def set_verbosity(verbosity: int | list[int]) -> None: LOGGER.setLevel("DEBUG") -def cli(argv: Sequence[str] = sys.argv) -> None: +def cli(args: Sequence[str] = None, namespace=None) -> None: """Entry point.""" parser = base_parser() + opts = parser.parse_args(args, namespace) - args, unknowns = parser.parse_known_args(argv[1:]) - - bids_dir = Path(args.bids_dir[0]).resolve() - # output_dir = Path(args.output_dir[0]) - participant_label = args.participant_label or None + bids_dir = opts.bids_dir.absolute() + output_dir = opts.output_dir.absolute() + participant_label = opts.participant_label or None - set_verbosity(args.verbosity) + set_verbosity(opts.verbosity) - LOGGER.debug(f"{bids_dir}") + LOGGER.debug(bids_dir) layout = BIDSLayout(bids_dir) report = BIDSReport(layout) if participant_label: - report.generate(subject=participant_label) + counter = report.generate(subject=participant_label) + else: + counter = report.generate() + + common_patterns = counter.most_common() + if not common_patterns: + LOGGER.warning("No common patterns found.") else: - report.generate() + with open(output_dir / "report.txt", "w") as f: + f.write(str(counter.most_common()[0][0])) diff --git a/bids/ext/reports/parameters.py b/bids/ext/reports/parameters.py index d0fa4d1..c5d6d32 100644 --- a/bids/ext/reports/parameters.py +++ b/bids/ext/reports/parameters.py @@ -1,3 +1,5 @@ +"""Functions for building strings for individual parameters.""" + from __future__ import annotations import math @@ -12,11 +14,11 @@ from .logger import pybids_reports_logger from .utils import list_to_str, num_to_str, remove_duplicates -"""Functions for building strings for individual parameters.""" LOGGER = pybids_reports_logger() def nb_runs(run_list: list[str]) -> str: + """Generate description of number of runs from list of files.""" nb_runs = len(run_list) if nb_runs == 1: return f"{num2words(nb_runs).title()} run" @@ -65,6 +67,7 @@ def get_nb_vols(all_imgs: list[Nifti1Image | None]) -> list[int] | None: def nb_vols(all_imgs: list[Nifti1Image]) -> str: + """Generate description of number of volumes from files.""" nb_vols = get_nb_vols(all_imgs) if nb_vols is None: return "UNKNOWN" @@ -73,7 +76,6 @@ def nb_vols(all_imgs: list[Nifti1Image]) -> str: def duration(all_imgs: list[Nifti1Image], metadata: dict[str, Any]) -> str: """Generate general description of scan length from files.""" - nb_vols = get_nb_vols(all_imgs) if nb_vols is None: return "UNKNOWN" @@ -131,7 +133,6 @@ def multi_echo(files: list[BIDSFile]) -> str: multi_echo : str Whether the data are multi-echo or single-echo. """ - echo_times = [f.get_metadata().get("EchoTime", None) for f in files] echo_times = sorted(list(set(echo_times))) if echo_times == [None]: @@ -190,7 +191,6 @@ def bvals(bval_file: str | Path) -> str: def intendedfor_targets(metadata: dict[str, Any], layout: BIDSLayout) -> str: """Generate description of intended for targets.""" - if "IntendedFor" not in metadata: return "" diff --git a/bids/ext/reports/parsing.py b/bids/ext/reports/parsing.py index 80b036f..e825ee4 100644 --- a/bids/ext/reports/parsing.py +++ b/bids/ext/reports/parsing.py @@ -17,8 +17,11 @@ def common_mri_desc( - img: None | nib.Nifti1Image, metadata: dict[str, Any], config: dict[str, dict[str, str]] + img: None | nib.Nifti1Image, + metadata: dict[str, Any], + config: dict[str, dict[str, str]], ) -> dict[str, Any]: + """Extract common MRI parameters from metadata.""" nb_slices = "UNKNOWN" if "SliceTiming" in metadata: nb_slices = str(len(metadata["SliceTiming"])) @@ -253,6 +256,7 @@ def meg_info(files: list[BIDSFile]) -> str: def device_info(metadata: dict[str, Any]) -> dict[str, Any]: + """Extract device information from metadata.""" return { "manufacturer": metadata.get("Manufacturer", "MANUFACTURER"), "model_name": metadata.get("ManufacturersModelName", "MODEL"), @@ -354,6 +358,7 @@ def parse_files( def try_load_nii(file: BIDSFile) -> None | nib.Nifti1Image: + """Try to load a nifti file, return None if it fails.""" try: img = nib.load(file) except (FileNotFoundError, ImageFileError): @@ -362,6 +367,7 @@ def try_load_nii(file: BIDSFile) -> None | nib.Nifti1Image: def files_not_found_warning(files: list[BIDSFile] | BIDSFile) -> None: + """Warn user that files were not found or empty.""" if not isinstance(files, list): files = [files] files = [str(Path(file)) for file in files] diff --git a/bids/ext/reports/report.py b/bids/ext/reports/report.py index 54897b0..6e3d42a 100644 --- a/bids/ext/reports/report.py +++ b/bids/ext/reports/report.py @@ -29,6 +29,7 @@ class BIDSReport: (str), a dictionary, or None. If None, loads and uses default configuration information. Keys in the dictionary include: + 'dir': a dictionary for converting encoding direction strings (e.g., j-) to descriptions (e.g., anterior to posterior) @@ -72,7 +73,7 @@ def generate_from_files(self, files: list[BIDSFile]) -> Counter[str]: Parameters ---------- - files : list of BIDSImageFile objects + files : list of :obj:`~bids.layout.BIDSImageFile` objects List of files from which to generate methods description. Returns @@ -177,8 +178,6 @@ def generate(self, **kwargs: Any) -> Counter[str]: for sub in subjects: descriptions.append(self._report_subject(subject=sub, **kwargs)) - print(descriptions) - counter = Counter(descriptions) LOGGER.info(f"Number of patterns detected: {len(counter.keys())}") diff --git a/bids/ext/reports/templates.py b/bids/ext/reports/templates.py index d39fabc..6a3c288 100644 --- a/bids/ext/reports/templates.py +++ b/bids/ext/reports/templates.py @@ -7,6 +7,7 @@ def render(template_name: str, data: dict[str, Any] | None = None) -> str: + """Render a mustache template.""" template_file = Path(__file__).resolve().parent / "templates" / "templates" / template_name with open(template_file) as template: @@ -24,6 +25,7 @@ def render(template_name: str, data: dict[str, Any] | None = None) -> str: def highlight_missing_tags(foo: str) -> str: + """Highlight missing tags in a rendered template.""" foo = f"[blue]{foo}[/blue]" foo = foo.replace("{{", "[/blue][red]{{") foo = foo.replace("}}", "}}[/red][blue]") @@ -31,6 +33,7 @@ def highlight_missing_tags(foo: str) -> str: def footer() -> str: + """Add footer with PyBIDS information to the report.""" # Imported here to avoid a circular import from . import __version__ @@ -38,24 +41,30 @@ def footer() -> str: def anat_info(desc_data: dict[str, Any]) -> str: + """Generate anatomical report.""" return render(template_name="anat.mustache", data=desc_data) def func_info(desc_data: dict[str, Any]) -> str: + """Generate functional report.""" return render(template_name="func.mustache", data=desc_data) def dwi_info(desc_data: dict[str, Any]) -> str: + """Generate diffusion report.""" return render(template_name="dwi.mustache", data=desc_data) def fmap_info(desc_data: dict[str, Any]) -> str: + """Generate fieldmap report.""" return render(template_name="fmap.mustache", data=desc_data) def pet_info(desc_data: dict[str, Any]) -> str: + """Generate PET report.""" return render(template_name="pet.mustache", data=desc_data) def meg_info(desc_data: dict[str, Any]) -> str: + """Generate MEG report.""" return render(template_name="meeg.mustache", data=desc_data) diff --git a/bids/ext/reports/tests/conftest.py b/bids/ext/reports/tests/conftest.py index 3fa36cb..229a7c1 100644 --- a/bids/ext/reports/tests/conftest.py +++ b/bids/ext/reports/tests/conftest.py @@ -7,19 +7,24 @@ import nibabel as nib import pytest +from bids.layout import BIDSLayout from bids.tests import get_test_data_path -from bids import BIDSLayout + +@pytest.fixture(scope="module") +def testdataset(): + """Path to a BIDS dataset for testing.""" + data_dir = join(get_test_data_path(), "synthetic") + return data_dir -@pytest.fixture -def testlayout(): +@pytest.fixture(scope="module") +def testlayout(testdataset): """A BIDSLayout for testing.""" - data_dir = join(get_test_data_path(), "synthetic") - return BIDSLayout(data_dir) + return BIDSLayout(testdataset) -@pytest.fixture +@pytest.fixture(scope="module") def testimg(testlayout): """A Nifti1Image for testing.""" func_files = testlayout.get( @@ -32,7 +37,7 @@ def testimg(testlayout): return nib.load(func_files[0].path) -@pytest.fixture +@pytest.fixture(scope="module") def testdiffimg(testlayout): """A Nifti1Image for testing.""" dwi_files = testlayout.get( @@ -44,7 +49,7 @@ def testdiffimg(testlayout): return nib.load(dwi_files[0].path) -@pytest.fixture +@pytest.fixture(scope="module") def testconfig(): """The standard config file for testing.""" config_file = abspath(join(get_test_data_path(), "../../reports/config/converters.json")) @@ -53,7 +58,7 @@ def testconfig(): return config -@pytest.fixture +@pytest.fixture(scope="module") def testmeta(): """A small metadata dictionary for testing.""" return { @@ -66,7 +71,7 @@ def testmeta(): } -@pytest.fixture +@pytest.fixture(scope="module") def testmeta_light(): """An even smaller metadata dictionary for testing.""" return {"RepetitionTime": 2.0} diff --git a/bids/ext/reports/tests/test_cli.py b/bids/ext/reports/tests/test_cli.py new file mode 100644 index 0000000..2e6f435 --- /dev/null +++ b/bids/ext/reports/tests/test_cli.py @@ -0,0 +1,21 @@ +"""Tests for the command-line interface.""" + +from __future__ import annotations + +import os + +from bids.ext.reports import cli + + +def test_cli(testdataset, tmp_path_factory): + """Run cli.cli().""" + tempdir = tmp_path_factory.mktemp("test_cli") + args = [ + testdataset, + str(tempdir), + "--verbosity", + "0", + ] + + cli.cli(args) + assert os.path.isfile(os.path.join(tempdir, "report.txt")), os.listdir(tempdir) diff --git a/bids/ext/reports/tests/test_parsing.py b/bids/ext/reports/tests/test_parsing.py index 73b3b69..b65b39c 100644 --- a/bids/ext/reports/tests/test_parsing.py +++ b/bids/ext/reports/tests/test_parsing.py @@ -4,9 +4,9 @@ from pathlib import Path +from bids.layout import BIDSLayout from bids.tests import get_test_data_path -from bids import BIDSLayout from bids.ext.reports import parsing diff --git a/bids/ext/reports/utils.py b/bids/ext/reports/utils.py index dba135f..2cf2141 100644 --- a/bids/ext/reports/utils.py +++ b/bids/ext/reports/utils.py @@ -22,15 +22,17 @@ def collect_associated_files( Parameters ---------- - layout - - files : list of BIDSFile - - extra_entities + layout : :obj:`bids.layout.BIDSLayout` + Layout object for a BIDS dataset. + files : :obj:`list` of :obj:`bids.layout.BIDSFile` + Files to group. + extra_entities : :obj:`list` of :obj:`str`, optional + Additional entities to use when grouping. + Default is an empty list. Returns ------- - collected_files : list of list of BIDSFile + collected_files : :obj:`list` of :obj:`list` of :obj:`bids.layout.BIDSFile` """ MULTICONTRAST_ENTITIES = ["echo", "part", "ch", "direction"] MULTICONTRAST_SUFFIXES = [ @@ -76,7 +78,7 @@ def remove_duplicates(seq: list[Any]) -> list[Any]: def num_to_str(num: int | float | str) -> str: - """Converts to a nice string. + """Convert number to a nice string. E.g., 21 -> '21' diff --git a/docs/source/cli.rst b/docs/source/cli.rst new file mode 100644 index 0000000..f44b712 --- /dev/null +++ b/docs/source/cli.rst @@ -0,0 +1,7 @@ +********************** +Command-Line Arguments +********************** + +.. argparse:: + :ref: bids.ext.reports.cli.base_parser + :prog: pybids_reports diff --git a/docs/source/conf.py b/docs/source/conf.py index 91d271f..4b3369f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,17 @@ # from bids.ext.reports._version import __version__ from __future__ import annotations -__version__ = "0.1.0" +import os +import sys + +sys.path.insert(0, os.path.abspath(os.path.pardir)) +sys.path.insert(0, os.path.abspath("sphinxext")) + +from github_link import make_linkcode_resolve + +import bids.ext.reports + +__version__ = bids.ext.reports.__version__ # The full version, including alpha/beta/rc tags release = __version__ @@ -30,10 +40,13 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + "myst_parser", + "nbsphinx", "sphinx.ext.autodoc", "sphinx.ext.intersphinx", + "sphinx.ext.viewcode", "sphinx_copybutton", - "myst_parser", + "sphinx_gallery.load_style", "sphinxarg.ext", ] @@ -52,3 +65,30 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] + +# ----------------------------------------------------------------------------- +# linkcode +# ----------------------------------------------------------------------------- +# The following is used by sphinx.ext.linkcode to provide links to github +linkcode_resolve = make_linkcode_resolve( + "bids.ext.reports", + "https://github.com/bids-standard/pybids-reports/blob/{revision}/{package}/{path}#L{lineno}", +) + +# ----------------------------------------------------------------------------- +# intersphinx +# ----------------------------------------------------------------------------- +_python_version_str = f"{sys.version_info.major}.{sys.version_info.minor}" +_python_doc_base = "https://docs.python.org/" + _python_version_str +intersphinx_mapping = { + "python": (_python_doc_base, None), + "numpy": ("https://numpy.org/doc/stable/", (None, "./_intersphinx/numpy-objects.inv")), + "scipy": ( + "https://docs.scipy.org/doc/scipy/reference", + (None, "./_intersphinx/scipy-objects.inv"), + ), + "bids": ( + "https://bids-standard.github.io/pybids", + (None, "./_intersphinx/pybids-objects.inv"), + ), +} diff --git a/docs/source/examples.rst b/docs/source/examples.rst new file mode 100644 index 0000000..3621587 --- /dev/null +++ b/docs/source/examples.rst @@ -0,0 +1,5 @@ +Examples +======== + +.. nbgallery:: + examples/generate_report diff --git a/docs/source/examples/generate_report.ipynb b/docs/source/examples/generate_report.ipynb new file mode 100644 index 0000000..115de08 --- /dev/null +++ b/docs/source/examples/generate_report.ipynb @@ -0,0 +1,523 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "df0b3e95-c3f7-4158-8e90-09cb1d67425b", + "metadata": {}, + "source": [ + "# Generate a dataset report\n", + "\n", + "Here we generate a methods writeup from a synthetic test dataset using `BIDSReport`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "4438f0cb-216a-4cb0-afa1-9991a90eaed1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from os.path import join\n", + "\n", + "import rich\n", + "from bids.layout import BIDSLayout\n", + "from bids.tests import get_test_data_path" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f95fc530-40f2-4596-ade8-a764869f4312", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "layout = BIDSLayout(join(get_test_data_path(), \"synthetic\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "12072a21-bfc6-4b48-a1c5-3d60ee4776dd", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
[10:48:35] WARNING   'sub-01_ses-01_magnitude1.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[10:48:35]\u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-01_ses-01_magnitude1.nii.gz'\u001b[0m not yet supported. \u001b]8;id=435179;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=401211;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-01_ses-01_magnitude2.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-01_ses-01_magnitude2.nii.gz'\u001b[0m not yet supported. \u001b]8;id=67275;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=165938;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/taylor/Documents/tsalo/pybids/bids/layout/models.py:229: UserWarning: Accessing entities as attributes is deprecated as of 0.7. Please use the .entities dictionary instead (i.e., .entities['run'] instead of .run.\n", + " warnings.warn(\"Accessing entities as attributes is deprecated as \"\n" + ] + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-02_ses-01_magnitude1.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-02_ses-01_magnitude1.nii.gz'\u001b[0m not yet supported. \u001b]8;id=815447;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=580686;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-02_ses-01_magnitude2.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-02_ses-01_magnitude2.nii.gz'\u001b[0m not yet supported. \u001b]8;id=175733;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=397757;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[10:48:36] WARNING   'sub-03_ses-01_magnitude1.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[10:48:36]\u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-03_ses-01_magnitude1.nii.gz'\u001b[0m not yet supported. \u001b]8;id=990960;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=459383;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-03_ses-01_magnitude2.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-03_ses-01_magnitude2.nii.gz'\u001b[0m not yet supported. \u001b]8;id=744189;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=239001;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-04_ses-01_magnitude1.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-04_ses-01_magnitude1.nii.gz'\u001b[0m not yet supported. \u001b]8;id=430;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=674534;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-04_ses-01_magnitude2.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-04_ses-01_magnitude2.nii.gz'\u001b[0m not yet supported. \u001b]8;id=140743;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=995779;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-05_ses-01_magnitude1.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-05_ses-01_magnitude1.nii.gz'\u001b[0m not yet supported. \u001b]8;id=520199;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=439096;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           WARNING   'sub-05_ses-01_magnitude2.nii.gz' not yet supported.                            parsing.py:352\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[31mWARNING \u001b[0m \u001b[32m'sub-05_ses-01_magnitude2.nii.gz'\u001b[0m not yet supported. \u001b]8;id=741467;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py\u001b\\\u001b[2mparsing.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=228829;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/parsing.py#352\u001b\\\u001b[2m352\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
[10:48:37] INFO     Number of patterns detected: 1                                                    report.py:182\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m[10:48:37]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Number of patterns detected: \u001b[1;36m1\u001b[0m \u001b]8;id=321550;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/report.py\u001b\\\u001b[2mreport.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=902786;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/report.py#182\u001b\\\u001b[2m182\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
           INFO     Remember to double-check everything and to replace <deg> with a degree symbol.    report.py:184\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[2;36m \u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Remember to double-check everything and to replace \u001b[1m<\u001b[0m\u001b[1;95mdeg\u001b[0m\u001b[1m>\u001b[0m with a degree symbol. \u001b]8;id=366199;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/report.py\u001b\\\u001b[2mreport.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=881493;file:///Users/taylor/Documents/tsalo/pybids-reports/bids/ext/reports/report.py#184\u001b\\\u001b[2m184\u001b[0m\u001b]8;;\u001b\\\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from bids.ext.reports import BIDSReport\n", + "\n", + "report = BIDSReport(layout)\n", + "counter = report.generate(session=\"01\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8b6b5ca9-19e8-4e3e-a53a-9ac1be39d378", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
In session 01, \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .One run of   UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \n",
+       "structural MRI data were collected (repetition time, TR= 2500.0 ms; flip angle, FA= 8°; echo time, TE= 2.9 ms; \n",
+       "field of view FOV= 256x256 mm; matrix size= 256x256; voxel size= 1x1x1 mm; UNKNOWN slices).\n",
+       "\n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .One run of   UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \n",
+       "structural MRI data were collected (repetition time, TR= 2500.0 ms; flip angle, FA= 8°; echo time, TE= 2.9 ms; \n",
+       "field of view FOV= 256x256 mm; matrix size= 256x256; voxel size= 1x1x1 mm; UNKNOWN slices).\n",
+       "\n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .One run of  UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT \n",
+       "diffusion-weighted-imaging () data were collected (68 slices; repetition time, TR= 8400.0 ms; flip angle, FA= 90°; \n",
+       "echo time, TE= 90 ms; field of view FOV= 128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm; b-values of 0 and \n",
+       "1000 acquired; 64 diffusion directions;  ).\n",
+       "\n",
+       "        \n",
+       "        \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .A  UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT field map (repetition \n",
+       "time, TR= 400.0 ms; flip angle, FA= 60.0°; echo time 1 / 2, TE 1/2= 519000.0/519000.0 ms; phase encoding: anterior \n",
+       "to posterior; ; field of view FOV= 256x256 mm; matrix size= 256x256; voxel size= 1x1x1 mm; UNKNOWN slices) was \n",
+       "acquired for the first and second runs of the N-Back BOLD scan.\n",
+       "\n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the N-Back task Two runs of bold  UNKNOwN SEQUENCE UNKNOwN \n",
+       "SEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \n",
+       "a  fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the N-Back task Two runs of bold  UNKNOwN SEQUENCE UNKNOwN \n",
+       "SEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \n",
+       "a  fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the Rest task One run of bold  UNKNOwN SEQUENCE UNKNOwN SEQUENCE\n",
+       "VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a  \n",
+       "fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the Rest task One run of bold  UNKNOwN SEQUENCE UNKNOwN SEQUENCE\n",
+       "VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a  \n",
+       "fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .One run of   UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \n",
+       "structural MRI data were collected (repetition time, TR= 2500.0 ms; flip angle, FA= 8°; echo time, TE= 2.9 ms; \n",
+       "field of view FOV= 256x256 mm; matrix size= 256x256; voxel size= 1x1x1 mm; UNKNOWN slices).\n",
+       "\n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a  system from ,\n",
+       "with serial number . The software version was .One run of   UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \n",
+       "structural MRI data were collected (repetition time, TR= 2500.0 ms; flip angle, FA= 8°; echo time, TE= 2.9 ms; \n",
+       "field of view FOV= 256x256 mm; matrix size= 256x256; voxel size= 1x1x1 mm; UNKNOWN slices).\n",
+       "\n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the N-Back task Two runs of bold  UNKNOwN SEQUENCE UNKNOwN \n",
+       "SEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \n",
+       "a  fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the N-Back task Two runs of bold  UNKNOwN SEQUENCE UNKNOwN \n",
+       "SEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \n",
+       "a  fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the Rest task One run of bold  UNKNOwN SEQUENCE UNKNOwN SEQUENCE\n",
+       "VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a  \n",
+       "fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "        \n",
+       "The data acquisition was performed in the , , .\n",
+       "MRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\n",
+       "with serial number . The software version was .For the Rest task One run of bold  UNKNOwN SEQUENCE UNKNOwN SEQUENCE\n",
+       "VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a  \n",
+       "fashion; repetition time, TR= 2500.0 ms; flip angle, FA= UNKNOWN°; echo time, TE= 30 ms;  ;  field of view FOV= \n",
+       "128x128 mm; matrix size= 64x64; voxel size= 2x2x2 mm;\n",
+       "Each run was 2:40 minutes in length, during which 64 functional volumes were acquired.\n",
+       "\n",
+       "Participants were specifically instructed to: \n",
+       "\n",
+       "Dicoms were converted to NIfTI-1 format.\n",
+       "
\n" + ], + "text/plain": [ + "In session \u001b[1;36m01\u001b[0m, \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .One run of UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \u001b[0m\n", + "\u001b[34mstructural MRI data were collected \u001b[0m\u001b[1;34m(\u001b[0m\u001b[34mrepetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m8\u001b[0m\u001b[34m°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2.9\u001b[0m\u001b[34m ms; \u001b[0m\n", + "\u001b[34mfield of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 256x256 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 256x256; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 1x1x1 mm; UNKNOWN slices\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m.\u001b[0m\n", + "\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .One run of UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \u001b[0m\n", + "\u001b[34mstructural MRI data were collected \u001b[0m\u001b[1;34m(\u001b[0m\u001b[34mrepetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m8\u001b[0m\u001b[34m°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2.9\u001b[0m\u001b[34m ms; \u001b[0m\n", + "\u001b[34mfield of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 256x256 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 256x256; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 1x1x1 mm; UNKNOWN slices\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m.\u001b[0m\n", + "\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .One run of UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT \u001b[0m\n", + "\u001b[34mdiffusion-weighted-imaging \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m data were collected \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m68\u001b[0m\u001b[34m slices; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m8400.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m90\u001b[0m\u001b[34m°; \u001b[0m\n", + "\u001b[34mecho time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m90\u001b[0m\u001b[34m ms; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm; b-values of \u001b[0m\u001b[1;34m0\u001b[0m\u001b[34m and \u001b[0m\n", + "\u001b[1;34m1000\u001b[0m\u001b[34m acquired; \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m diffusion directions; \u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m.\u001b[0m\n", + "\n", + " \n", + " \n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .A UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT field map \u001b[0m\u001b[1;34m(\u001b[0m\u001b[34mrepetition \u001b[0m\n", + "\u001b[34mtime, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m400.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m60.0\u001b[0m\u001b[34m°; echo time \u001b[0m\u001b[1;34m1\u001b[0m\u001b[34m \u001b[0m\u001b[34m/\u001b[0m\u001b[34m \u001b[0m\u001b[1;34m2\u001b[0m\u001b[34m, TE \u001b[0m\u001b[1;34m1\u001b[0m\u001b[34m/\u001b[0m\u001b[1;34m2\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m519000.0\u001b[0m\u001b[34m/\u001b[0m\u001b[1;34m519000.0\u001b[0m\u001b[34m ms; phase encoding: anterior \u001b[0m\n", + "\u001b[34mto posterior; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 256x256 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 256x256; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 1x1x1 mm; UNKNOWN slices\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m was \u001b[0m\n", + "\u001b[34macquired for the first and second runs of the N-Back BOLD scan.\u001b[0m\n", + "\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the N-Back task Two runs of bold UNKNOwN SEQUENCE UNKNOwN \u001b[0m\n", + "\u001b[34mSEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \u001b[0m\n", + "\u001b[34ma fashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the N-Back task Two runs of bold UNKNOwN SEQUENCE UNKNOwN \u001b[0m\n", + "\u001b[34mSEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \u001b[0m\n", + "\u001b[34ma fashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the Rest task One run of bold UNKNOwN SEQUENCE UNKNOwN SEQUENCE\u001b[0m\n", + "\u001b[34mVARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a \u001b[0m\n", + "\u001b[34mfashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the Rest task One run of bold UNKNOwN SEQUENCE UNKNOwN SEQUENCE\u001b[0m\n", + "\u001b[34mVARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a \u001b[0m\n", + "\u001b[34mfashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .One run of UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \u001b[0m\n", + "\u001b[34mstructural MRI data were collected \u001b[0m\u001b[1;34m(\u001b[0m\u001b[34mrepetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m8\u001b[0m\u001b[34m°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2.9\u001b[0m\u001b[34m ms; \u001b[0m\n", + "\u001b[34mfield of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 256x256 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 256x256; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 1x1x1 mm; UNKNOWN slices\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m.\u001b[0m\n", + "\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a system from ,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .One run of UNKNOwN SEQUENCE UNKNOwN SEQUENCE VARIANT single-echo \u001b[0m\n", + "\u001b[34mstructural MRI data were collected \u001b[0m\u001b[1;34m(\u001b[0m\u001b[34mrepetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m8\u001b[0m\u001b[34m°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2.9\u001b[0m\u001b[34m ms; \u001b[0m\n", + "\u001b[34mfield of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= 256x256 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 256x256; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 1x1x1 mm; UNKNOWN slices\u001b[0m\u001b[1;34m)\u001b[0m\u001b[34m.\u001b[0m\n", + "\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the N-Back task Two runs of bold UNKNOwN SEQUENCE UNKNOwN \u001b[0m\n", + "\u001b[34mSEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \u001b[0m\n", + "\u001b[34ma fashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the N-Back task Two runs of bold UNKNOwN SEQUENCE UNKNOwN \u001b[0m\n", + "\u001b[34mSEQUENCE VARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in \u001b[0m\n", + "\u001b[34ma fashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the Rest task One run of bold UNKNOwN SEQUENCE UNKNOwN SEQUENCE\u001b[0m\n", + "\u001b[34mVARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a \u001b[0m\n", + "\u001b[34mfashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + " \n", + "\u001b[34mThe data acquisition was performed in the , , .\u001b[0m\n", + "\u001b[34mMRI data were acquired using a UNKNOWN Tesla using a MODEL system from MANUFACTURER,\u001b[0m\n", + "\u001b[34mwith serial number . The software version was .For the Rest task One run of bold UNKNOwN SEQUENCE UNKNOwN SEQUENCE\u001b[0m\n", + "\u001b[34mVARIANT single-echo fMRI data were collected. The acquisition parameters were: UNKNOWN slices acquired in a \u001b[0m\n", + "\u001b[34mfashion; repetition time, \u001b[0m\u001b[34mTR\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m2500.0\u001b[0m\u001b[34m ms; flip angle, \u001b[0m\u001b[34mFA\u001b[0m\u001b[34m= UNKNOWN°; echo time, \u001b[0m\u001b[34mTE\u001b[0m\u001b[34m= \u001b[0m\u001b[1;34m30\u001b[0m\u001b[34m ms; ; field of view \u001b[0m\u001b[34mFOV\u001b[0m\u001b[34m= \u001b[0m\n", + "\u001b[34m128x128 mm; matrix \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 64x64; voxel \u001b[0m\u001b[34msize\u001b[0m\u001b[34m= 2x2x2 mm;\u001b[0m\n", + "\u001b[34mEach run was \u001b[0m\u001b[1;34m2:40\u001b[0m\u001b[34m minutes in length, during which \u001b[0m\u001b[1;34m64\u001b[0m\u001b[34m functional volumes were acquired.\u001b[0m\n", + "\n", + "\u001b[34mParticipants were specifically instructed to: \u001b[0m\n", + "\n", + "Dicoms were converted to NIfTI-\u001b[1;36m1\u001b[0m format.\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "rich.print(counter.most_common()[0][0])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/index.rst b/docs/source/index.rst index b20aed5..e4aabff 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,6 +10,9 @@ Welcome to pybids-reports's documentation! :maxdepth: 2 :caption: Contents: + reports + cli + examples Indices and tables diff --git a/docs/source/modules.rst b/docs/source/modules.rst deleted file mode 100644 index 9636504..0000000 --- a/docs/source/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -reports -======= - -.. toctree:: - :maxdepth: 4 - - reports diff --git a/docs/source/sphinxext/github_link.py b/docs/source/sphinxext/github_link.py new file mode 100644 index 0000000..214530d --- /dev/null +++ b/docs/source/sphinxext/github_link.py @@ -0,0 +1,92 @@ +""" +This script comes from scikit-learn: +https://github.com/scikit-learn/scikit-learn/blob/master/doc/sphinxext/github_link.py +""" + +from __future__ import annotations + +import inspect +import os +import subprocess +import sys +from functools import partial +from operator import attrgetter + +REVISION_CMD = "git rev-parse --short HEAD" + + +def _get_git_revision(): + try: + revision = subprocess.check_output(REVISION_CMD.split()).strip() + except (subprocess.CalledProcessError, OSError): + print("Failed to execute git to get revision") + return None + return revision.decode("utf-8") + + +def _linkcode_resolve(domain, info, package, url_fmt, revision): + """Determine a link to online source for a class/method/function + + This is called by sphinx.ext.linkcode + + An example with a long-untouched module that everyone has + >>> _linkcode_resolve('py', {'module': 'tty', + ... 'fullname': 'setraw'}, + ... package='tty', + ... url_fmt='http://hg.python.org/cpython/file/' + ... '{revision}/Lib/{package}/{path}#L{lineno}', + ... revision='xxxx') + 'http://hg.python.org/cpython/file/xxxx/Lib/tty/tty.py#L18' + """ + + if revision is None: + return + if domain not in ("py", "pyx"): + return + if not info.get("module") or not info.get("fullname"): + return + + class_name = info["fullname"].split(".")[0] + if not isinstance(class_name, str): + # Python 2 only + class_name = class_name.encode("utf-8") + try: + module = __import__(info["module"], fromlist=[class_name]) + obj = attrgetter(info["fullname"])(module) + except Exception: + fn = None + return + + try: + fn = inspect.getsourcefile(obj) + except Exception: + fn = None + if not fn: + try: + fn = inspect.getsourcefile(sys.modules[obj.__module__]) + except Exception: + fn = None + if not fn: + return + + fn = os.path.relpath(fn, start=os.path.dirname(__import__(package).__file__)) + try: + lineno = inspect.getsourcelines(obj)[1] + except Exception: + lineno = "" + return url_fmt.format(revision=revision, package=package, path=fn, lineno=lineno) + + +def make_linkcode_resolve(package, url_fmt): + """Returns a linkcode_resolve function for the given URL format + + revision is a git commit reference (hash or name) + + package is the name of the root module of the package + + url_fmt is along the lines of ('https://github.com/USER/PROJECT/' + 'blob/{revision}/{package}/' + '{path}#L{lineno}') + """ + revision = _get_git_revision() + return partial(_linkcode_resolve, revision=revision, package=package, url_fmt=url_fmt) diff --git a/pyproject.toml b/pyproject.toml index 9f7bfbb..1c2569d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,17 +48,19 @@ pybids_reports = "bids.ext.reports.cli:cli" [project.urls] Homepage = "http://github.com/bids-standard/pybids-reports" -Documentation = "https://cohort-creator.readthedocs.io/en/latest/" -"Bug trakcer" = "http://github.com/bids-standard/pybids-reports/issues" +Documentation = "https://pybids-reports.readthedocs.io/en/latest/" +"Bug tracker" = "http://github.com/bids-standard/pybids-reports/issues" [project.optional-dependencies] doc = [ + "furo", + "myst-parser", + "nbsphinx", "numpydoc", "sphinx", - "furo", - "myst-parser", "sphinx-argparse", - "sphinx-copybutton" + "sphinx-copybutton", + "sphinx_gallery", ] docs=["pybids_reports[doc]"] test = [