[BUG]: PatternDataGrabber does not respect the "format" parameter required for BOLD_confounds data type #158
7 changed files with 83 additions and 1 deletions
|
|
@ -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`_).
|
||||
|
|
@ -107,6 +107,7 @@ class JuselessUCLA(PatternDataGrabber):
|
|||
datadir=datadir,
|
||||
patterns=patterns,
|
||||
replacements=replacements,
|
||||
confounds_format="fmriprep",
|
||||
)
|
||||
|
||||
def get_elements(self) -> List:
|
||||
|
|
|
|||
|
|
@ -86,4 +86,5 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
|||
uri=uri,
|
||||
patterns=patterns,
|
||||
replacements=replacements,
|
||||
confounds_format="fmriprep",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
|
|||
uri=uri,
|
||||
patterns=patterns,
|
||||
replacements=replacements,
|
||||
confounds_format="fmriprep",
|
||||
)
|
||||
|
||||
def get_elements(self) -> List:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in a new issue