Skip to content

Commit

Permalink
Make some stylistic changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tsalo committed Jan 23, 2024
1 parent 682c990 commit 8427b67
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
52 changes: 31 additions & 21 deletions bids/ext/reports/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ def _print_message(self, message: str, file: IO[str] | None = None) -> None:
rich.print(message, file=file)


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}>.")

Check warning on line 29 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L28-L29

Added lines #L28 - L29 were not covered by tests

return Path(path).absolute()

Check warning on line 31 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L31

Added line #L31 was not covered by tests


def base_parser() -> MuhParser:
from functools import partial

Check warning on line 35 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L35

Added line #L35 was not covered by tests

parser = MuhParser(
prog="pybids_reports",
description="Report generator for BIDS datasets.",
Expand All @@ -32,31 +42,32 @@ def base_parser() -> MuhParser:
see the online doc https://pybids-reports.readthedocs.io/en/latest/
""",
)
PathExists = partial(_path_exists, parser=parser)

Check warning on line 45 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L45

Added line #L45 was not covered by tests

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-<participant_label> 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-<participant_label> 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",
Expand All @@ -66,21 +77,20 @@ 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


def set_verbosity(verbosity: int | list[int]) -> None:
if isinstance(verbosity, list):
verbosity = verbosity[0]

if verbosity == 0:
LOGGER.setLevel("ERROR")
elif verbosity == 1:
Expand All @@ -95,15 +105,15 @@ def cli(argv: Sequence[str] = sys.argv) -> None:
"""Entry point."""
parser = base_parser()

args, unknowns = parser.parse_known_args(argv[1:])
args, unknowns = parser.parse_args(argv)

Check warning on line 108 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L108

Added line #L108 was not covered by tests

bids_dir = Path(args.bids_dir[0]).resolve()
# output_dir = Path(args.output_dir[0])
bids_dir = args.bids_dir.resolve()

Check warning on line 110 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L110

Added line #L110 was not covered by tests
# output_dir = args.output_dir
participant_label = args.participant_label or None

set_verbosity(args.verbosity)

LOGGER.debug(f"{bids_dir}")
LOGGER.debug(bids_dir)

Check warning on line 116 in bids/ext/reports/cli.py

View check run for this annotation

Codecov / codecov/patch

bids/ext/reports/cli.py#L116

Added line #L116 was not covered by tests

layout = BIDSLayout(bids_dir)

Expand Down
7 changes: 3 additions & 4 deletions bids/ext/reports/parameters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Functions for building strings for individual parameters."""
from __future__ import annotations

import math
Expand All @@ -15,11 +16,11 @@
from bids.layout import BIDSFile
from bids.layout import BIDSLayout

"""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"
Expand Down Expand Up @@ -68,6 +69,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"
Expand All @@ -76,7 +78,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"
Expand Down Expand Up @@ -134,7 +135,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]:
Expand Down Expand Up @@ -193,7 +193,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 ""

Expand Down
8 changes: 7 additions & 1 deletion bids/ext/reports/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,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"]))
Expand Down Expand Up @@ -254,6 +257,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"),
Expand Down Expand Up @@ -355,6 +359,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):
Expand All @@ -363,6 +368,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]
Expand Down
9 changes: 9 additions & 0 deletions bids/ext/reports/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -24,38 +25,46 @@ 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]")
return foo


def footer() -> str:
"""Add footer with PyBIDS information to the report."""
# Imported here to avoid a circular import
from . import __version__

return f"This section was (in part) generated automatically using pybids {__version__}."


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)

0 comments on commit 8427b67

Please sign in to comment.