Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] improve log and change verbosity parameter #96

Merged
merged 3 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[codespell]
skip = .git,env,build,outputs,.mypy_cache,moae_fmriprep
ignore-words-list = fo
builtin = clear,rare
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ repos:
rev: 'v0.991'
hooks:
- id: mypy
additional_dependencies: [types-all]
additional_dependencies: [types-all, pydantic]
files: bidsmreye
args: ["--config-file", "setup.cfg"]

Expand Down
59 changes: 31 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,28 +135,29 @@ clean-demo:
rm -fr outputs/moae_fmriprep

demo: clean-demo tests/data/moae_fmriprep ## demo: runs all demo steps on MOAE dataset
bidsmreye --action all \
$$PWD/tests/data/moae_fmriprep \
bidsmreye $$PWD/tests/data/moae_fmriprep \
$$PWD/outputs/moae_fmriprep/derivatives \
participant
participant \
--action all \
-vv \

prepare: tests/data/moae_fmriprep ## demo: prepares the data of MOAE dataset
bidsmreye --action prepare \
--verbosity INFO \
--debug true \
--reset_database true \
$$PWD/tests/data/moae_fmriprep \
bidsmreye $$PWD/tests/data/moae_fmriprep \
$$PWD/outputs/moae_fmriprep/derivatives \
participant
participant \
--action prepare \
-vv \
--debug \
--reset_database

generalize: ## demo: predicts labels of MOAE dataset
bidsmreye --action generalize \
--verbosity WARNING \
--debug true \
--reset_database true \
$$PWD/tests/data/moae_fmriprep \
bidsmreye $$PWD/tests/data/moae_fmriprep \
$$PWD/outputs/moae_fmriprep/derivatives \
participant
participant \
--action generalize \
-vv \
--debug \
--reset_database


## Openneuro data
Expand All @@ -173,35 +174,37 @@ get_ds002799: tests/data/data_ds002799
datalad get sub-30[27]/ses-*/func/*run-*preproc*bold*

ds002799_prepare: get_ds002799
bidsmreye --action prepare \
--debug true \
$$PWD/tests/data/ds002799/derivatives/fmriprep \
bidsmreye $$PWD/tests/data/ds002799/derivatives/fmriprep \
$$PWD/outputs/ds002799/derivatives \
participant \
--action prepare \
--debug \
--participant_label 302 307 \
--space MNI152NLin2009cAsym T1w \
--run 1 2


ds002799_generalize:
bidsmreye --action generalize \
--debug true \
$$PWD/tests/data/ds002799/derivatives/fmriprep \
bidsmreye $$PWD/tests/data/ds002799/derivatives/fmriprep \
$$PWD/outputs/ds002799/derivatives \
participant \
--action generalize \
--debug \
--participant_label 302 307 \
--space MNI152NLin2009cAsym T1w \
--run 1 2


ds002799: clean-ds002799 get_ds002799
bidsmreye --action all \
--debug true \
$$PWD/tests/data/ds002799/derivatives/fmriprep \
bidsmreye $$PWD/tests/data/ds002799/derivatives/fmriprep \
$$PWD/outputs/ds002799/derivatives \
participant \
--action all \
--debug \
--participant_label 302 307 \
--space MNI152NLin2009cAsym T1w \
--run 1 2

--run 1 2 \
-vv

## DOCKER
.PHONY: docker/Dockerfile docker/Dockerfile_dev
Expand Down Expand Up @@ -276,8 +279,8 @@ docker_prepare_data:
/home/neuro/outputs/ \
participant \
--action prepare \
--debug true \
--reset_database true
--debug \
--reset_database

docker_generalize:
docker run --rm -it \
Expand Down
47 changes: 21 additions & 26 deletions bidsmreye/run.py → bidsmreye/bidsmreye.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
from bidsmreye.prepare_data import prepare_data
from bidsmreye.utils import bidsmreye_log
from bidsmreye.utils import Config
from bidsmreye.utils import default_log_level
from bidsmreye.utils import log_levels

__version__ = _version.get_versions()["version"]

log = bidsmreye_log(name="bidsmreye")


def main(argv: Any = sys.argv) -> None:
def cli(argv: Any = sys.argv) -> None:
"""Run the bids app.
:param argv: _description_, defaults to sys.argv
Expand All @@ -46,9 +48,15 @@ def main(argv: Any = sys.argv) -> None:
bids_filter=args.bids_filter_file,
) # type: ignore

log_level = "DEBUG" if cfg.debug else args.verbosity

log.setLevel(log_level)
# TODO integrate as part of base config
# https://stackoverflow.com/a/53293042/14223310
log_level = log_levels().index(default_log_level())
# For each "-v" flag, adjust the logging verbosity accordingly
# making sure to clamp off the value from 0 to 4, inclusive of both
for adjustment in args.log_level or ():
log_level = min(len(log_levels()) - 1, max(log_level + adjustment, 0))
log_level_name = log_levels()[log_level]
log.setLevel(log_level_name)

log.info("Running bidsmreye version %s", __version__)

Expand Down Expand Up @@ -91,7 +99,7 @@ def common_parser() -> MuhParser:
description="BIDS app using deepMReye to decode eye motion for fMRI time series data.",
epilog="""
For a more readable version of this help section,
see the online https://bidsmreye.readthedocs.io/".
see the online https://bidsmreye.readthedocs.io/.
""",
)

Expand Down Expand Up @@ -119,14 +127,7 @@ def common_parser() -> MuhParser:
parser.add_argument(
"--action",
help="""
What action to perform:
- all: run all steps
- prepare: prepare data for analysis coregister to template,
normalize and extract data
- generalize: generalize from data to give predicted labels
What action to perform.
""",
choices=["all", "prepare", "generalize"],
default="all",
Expand Down Expand Up @@ -174,21 +175,19 @@ def common_parser() -> MuhParser:
nargs="+",
)
parser.add_argument(
"--verbosity",
help="ERROR, INFO, WARNING, DEBUG",
choices=["ERROR", "INFO", "WARNING", "DEBUG"],
default="INFO",
)
parser.add_argument(
"--debug", help="true or false.", choices=["true", "false"], default="false"
"-v",
"--verbose",
dest="log_level",
action="append_const",
const=-1,
)
parser.add_argument("--debug", help="Switch to debug mode", action="store_true")
parser.add_argument(
"--reset_database",
help="""
Resets the database of the input dataset.
""",
choices=["true", "false"],
default="false",
action="store_true",
)
parser.add_argument(
"--bids_filter_file",
Expand Down Expand Up @@ -222,7 +221,3 @@ def common_parser() -> MuhParser:
)

return parser


if __name__ == "__main__":
main()
39 changes: 31 additions & 8 deletions bidsmreye/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,37 @@
from __future__ import annotations

import argparse
import sys
from pathlib import Path
from typing import Any
from typing import IO

import pkg_resources
import pooch
import rich

from bidsmreye.utils import bidsmreye_log
from bidsmreye.utils import move_file

log = bidsmreye_log(name="bidsmreye")


def main() -> None:
"""Download the models from OSF.
class MuhParser(argparse.ArgumentParser):
"""Parser for the main script."""

:return: _description_
:rtype: _type_
"""
parser = argparse.ArgumentParser(description="bidsMReye model downloader.")
def _print_message(self, message: str, file: IO[str] | None = None) -> None:
rich.print(message, file=file)


def download_parser() -> MuhParser:
"""Execute the main script."""
parser = MuhParser(
description="Download deepmreye pretrained model from OSF.",
epilog="""
For a more readable version of this help section,
see the online https://bidsmreye.readthedocs.io/.
""",
)
parser.add_argument(
"--model_name",
help="""
Expand All @@ -44,7 +57,17 @@ def main() -> None:
default=Path.cwd().joinpath("models"),
)

args = parser.parse_args()
return parser


def cli(argv: Any = sys.argv) -> None:
"""Download the models from OSF.
:return: _description_
:rtype: _type_
"""
parser = download_parser()
args = parser.parse_args(argv[1:])

download(model_name=args.model_name, output_dir=args.output_dir)

Expand Down Expand Up @@ -77,7 +100,7 @@ def download(
"4_pursuit": "96nyp",
"5_free_viewing": "89nky",
"6_1-to-5": "datasets_1to5.h5",
"7_1-to-6": "datasets_1to5.h5",
"7_1-to-6": "datasets_1to6.h5",
}

if model_name == "all":
Expand Down
5 changes: 4 additions & 1 deletion bidsmreye/generalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ def process_subject(cfg: Config, layout_out: BIDSLayout, subject_label: str) ->
if cfg.run:
this_filter["run"] = return_regex(cfg.run)

log.info(f"Running subject: {subject_label}")

log.debug(f"Looking for files with filter\n{this_filter}")

data = layout_out.get(
Expand All @@ -155,7 +157,8 @@ def process_subject(cfg: Config, layout_out: BIDSLayout, subject_label: str) ->
**this_filter,
)

log.debug(f"Found files\n{data}")
to_print = [str(Path(x).relative_to(layout_out.root)) for x in data]
log.debug(f"Found files\n{to_print}")

for file in data:

Expand Down
5 changes: 3 additions & 2 deletions bidsmreye/prepare_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,12 @@ def process_subject(
**this_filter,
)

log.debug(f"Found files\n{bf}")
to_print = [str(Path(x).relative_to(layout_in.root)) for x in bf]
log.debug(f"Found files\n{to_print}")

for img in bf:

log.info(f"Processing {img}")
log.info(f"Processing file: {Path(img).name}")

coregister_and_extract_data(img)

Expand Down
18 changes: 18 additions & 0 deletions bidsmreye/templates/CITATION.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,22 @@ to decode eye motion for fMRI time series data.

### data extraction

All imaging data underwent co-registration conducted
using Advanced Normalization Tools (ANTs, RRID:SCR_004757) within Python (ANTsPy).
First, each participant's mean EPI was non-linearly co-registered
to an average template.
Second, we co-registered all voxels within a bounding box that included the eyes
to a preselected bounding box in our group template to further improve the fit.

Each voxel within those bounding box underwent two normalization steps.
First, the across-run median signal intensity was subtracted
from each voxel and sample
and was divided by the median absolute deviation over time (temporal normalization).
Second, for each sample, the mean across all voxels
within the eye masks was subtracted and divided by the standard deviation
across voxels (spatial normalization).

### eyemotion decoding

Voxels time series were used as inputs for generalization decoding
using using the the pre-trained model {{model}} from deepMReye ({{model_url}}).
19 changes: 16 additions & 3 deletions bidsmreye/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@
__version__ = _version.get_versions()["version"]


def default_log_level() -> str:
"""Return default log level."""
return "WARNING"


def log_levels() -> list[str]:
"""Return a list of log levels."""
return ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]


def bidsmreye_log(name: str | None = None) -> logging.Logger:
"""Create log.
Expand All @@ -38,7 +48,7 @@ def bidsmreye_log(name: str | None = None) -> logging.Logger:

FORMAT = "bidsMReye - %(asctime)s - %(message)s"

log_level = "INFO"
log_level = default_log_level()

if not name:
name = "rich"
Expand Down Expand Up @@ -187,8 +197,11 @@ def move_file(input: Path, output: Path) -> None:
:param output:
:type output: Path
:param root: Optional. If specified, the printed path will be relative to this path.
:type root: Path
"""
log.info(f"{input.resolve()} --> {output.resolve()}")
log.debug(f"{input.resolve()} --> {output.resolve()}")
create_dir_for_file(output)
shutil.copy(input, output)
input.unlink()
Expand All @@ -203,7 +216,7 @@ def create_dir_if_absent(output_path: str | Path) -> None:
if isinstance(output_path, str):
output_path = Path(output_path)
if not output_path.is_dir():
log.info(f"Creating dir: {output_path}")
log.debug(f"Creating dir: {output_path}")
output_path.mkdir(parents=True, exist_ok=True)


Expand Down
Loading