[BUG]: PatternDataGrabber does not respect the "format" parameter required for BOLD_confounds data type #158

Merged
synchon merged 8 commits from fix/confounds-format-pattern-dg into main 2022-12-22 13:47:19 +00:00
7 changed files with 83 additions and 1 deletions

View file

@ -30,3 +30,6 @@ Bugs
API changes
~~~~~~~~~~~
- Add ``confounds_format`` parameter to :class:`junifer.datagrabber.PatternDataGrabber` constructor for
improved handling of confounds specified via ``BOLD_confounds`` data type (:gh:`158` by `Synchon Mandal`_).

View file

@ -107,6 +107,7 @@ class JuselessUCLA(PatternDataGrabber):
datadir=datadir,
patterns=patterns,
replacements=replacements,
confounds_format="fmriprep",
)
def get_elements(self) -> List:

View file

@ -86,4 +86,5 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
uri=uri,
patterns=patterns,
replacements=replacements,
confounds_format="fmriprep",
)

View file

@ -116,6 +116,7 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
uri=uri,
patterns=patterns,
replacements=replacements,
confounds_format="fmriprep",
)
def get_item(self, subject: str, task: str) -> Dict:

View file

@ -113,6 +113,7 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
uri=uri,
patterns=patterns,
replacements=replacements,
confounds_format="fmriprep",
)
def get_elements(self) -> List:

View file

@ -7,7 +7,7 @@
import re
from pathlib import Path
from typing import Dict, List, Tuple, Union
from typing import Dict, List, Optional, Tuple, Union
import numpy as np
@ -17,6 +17,10 @@ from .base import BaseDataGrabber
from .utils import validate_patterns, validate_replacements
# Accepted formats for confounds specification
_CONFOUNDS_FORMATS = ("fmriprep", "adhoc")
@register_datagrabber
class PatternDataGrabber(BaseDataGrabber):
"""Concrete implementation for data grabbing using patterns.
@ -35,6 +39,9 @@ class PatternDataGrabber(BaseDataGrabber):
Replacements in the patterns for each item in the "element" tuple.
datadir : str or pathlib.Path
The directory where the data is / will be stored.
confounds_format : {"fmriprep", "adhoc"}, optional
The format of the confounds for the dataset (default None).
"""
def __init__(
@ -43,6 +50,7 @@ class PatternDataGrabber(BaseDataGrabber):
patterns: Dict[str, str],
replacements: Union[List[str], str],
datadir: Union[str, Path],
confounds_format: Optional[str] = None,
) -> None:
# Validate patterns
validate_patterns(types=types, patterns=patterns)
@ -52,6 +60,14 @@ class PatternDataGrabber(BaseDataGrabber):
# Validate replacements
validate_replacements(replacements=replacements, patterns=patterns)
# Validate confounds format
if confounds_format and confounds_format not in _CONFOUNDS_FORMATS:
raise_error(
"Invalid value for `confounds_format`, should be one of "
f"{_CONFOUNDS_FORMATS}."
)
self.confounds_format = confounds_format
super().__init__(types=types, datadir=datadir)
logger.debug("Initializing PatternDataGrabber")
logger.debug(f"\tpatterns = {patterns}")
@ -184,7 +200,21 @@ class PatternDataGrabber(BaseDataGrabber):
f"Cannot access {t_type} for {element}: "
f"File {t_out} does not exist"
)
# Update path for the element
out[t_type] = {"path": t_out}
# Update confounds format for BOLD_confounds
# (if found in the datagrabber)
if t_type == "BOLD_confounds":
if not self.confounds_format:
raise_error(
"`confounds_format` needs to be one of "
f"{_CONFOUNDS_FORMATS}, None provided. "
"As the datagrabber used specifies "
"'BOLD_confounds', None is invalid."
)
# Set the format
out[t_type].update({"format": self.confounds_format})
return out
def get_elements(self) -> List:

View file

@ -259,3 +259,48 @@ def test_PatternDataGrabber(tmp_path: Path) -> None:
assert out1["func"]["path"] == out2["func"]["path"]
assert out1["anat"]["path"] == out2["anat"]["path"]
assert out1["vbm"]["path"] != out2["vbm"]["path"]
def test_pattern_data_grabber_confounds_format_error_on_init() -> None:
"""Test PatterDataGrabber confounds format error on initialisation."""
with pytest.raises(
ValueError, match="Invalid value for `confounds_format`"
):
PatternDataGrabber(
types=["func"],
patterns={"func": "func/{subject}.nii"},
replacements=["subject"],
datadir="/tmp",
confounds_format="foobar",
)
def test_pattern_data_grabber_confounds_format_error_on_fetch(
tmp_path: Path,
) -> None:
"""Test PatterDataGrabber confounds format error on fetching.
Parameters
----------
tmp_path : pathlib.Path
The path to the test directory.
"""
# Create test directory path
tmpdir = tmp_path / "pattern_dg_test"
# Create final test directory
(tmpdir / "func" / "confounds").mkdir(exist_ok=True, parents=True)
# Create test confound file
(tmpdir / "func" / "confounds" / "sub-001.nii").touch()
# Initialise datagrabber
datagrabber = PatternDataGrabber(
types=["BOLD_confounds"],
patterns={"BOLD_confounds": "func/confounds/{subject}.nii"},
replacements=["subject"],
datadir=tmpdir,
)
# Check error on fetch
with pytest.raises(
ValueError, match="As the datagrabber used specifies 'BOLD_confounds'"
):
datagrabber.get_item(subject="sub-001")