[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
|
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,
|
datadir=datadir,
|
||||||
patterns=patterns,
|
patterns=patterns,
|
||||||
replacements=replacements,
|
replacements=replacements,
|
||||||
|
confounds_format="fmriprep",
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_elements(self) -> List:
|
def get_elements(self) -> List:
|
||||||
|
|
|
||||||
|
|
@ -86,4 +86,5 @@ class DataladAOMICID1000(PatternDataladDataGrabber):
|
||||||
uri=uri,
|
uri=uri,
|
||||||
patterns=patterns,
|
patterns=patterns,
|
||||||
replacements=replacements,
|
replacements=replacements,
|
||||||
|
confounds_format="fmriprep",
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ class DataladAOMICPIOP1(PatternDataladDataGrabber):
|
||||||
uri=uri,
|
uri=uri,
|
||||||
patterns=patterns,
|
patterns=patterns,
|
||||||
replacements=replacements,
|
replacements=replacements,
|
||||||
|
confounds_format="fmriprep",
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_item(self, subject: str, task: str) -> Dict:
|
def get_item(self, subject: str, task: str) -> Dict:
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ class DataladAOMICPIOP2(PatternDataladDataGrabber):
|
||||||
uri=uri,
|
uri=uri,
|
||||||
patterns=patterns,
|
patterns=patterns,
|
||||||
replacements=replacements,
|
replacements=replacements,
|
||||||
|
confounds_format="fmriprep",
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_elements(self) -> List:
|
def get_elements(self) -> List:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Tuple, Union
|
from typing import Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
@ -17,6 +17,10 @@ from .base import BaseDataGrabber
|
||||||
from .utils import validate_patterns, validate_replacements
|
from .utils import validate_patterns, validate_replacements
|
||||||
|
|
||||||
|
|
||||||
|
# Accepted formats for confounds specification
|
||||||
|
_CONFOUNDS_FORMATS = ("fmriprep", "adhoc")
|
||||||
|
|
||||||
|
|
||||||
@register_datagrabber
|
@register_datagrabber
|
||||||
class PatternDataGrabber(BaseDataGrabber):
|
class PatternDataGrabber(BaseDataGrabber):
|
||||||
"""Concrete implementation for data grabbing using patterns.
|
"""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.
|
Replacements in the patterns for each item in the "element" tuple.
|
||||||
datadir : str or pathlib.Path
|
datadir : str or pathlib.Path
|
||||||
The directory where the data is / will be stored.
|
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__(
|
def __init__(
|
||||||
|
|
@ -43,6 +50,7 @@ class PatternDataGrabber(BaseDataGrabber):
|
||||||
patterns: Dict[str, str],
|
patterns: Dict[str, str],
|
||||||
replacements: Union[List[str], str],
|
replacements: Union[List[str], str],
|
||||||
datadir: Union[str, Path],
|
datadir: Union[str, Path],
|
||||||
|
confounds_format: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
# Validate patterns
|
# Validate patterns
|
||||||
validate_patterns(types=types, patterns=patterns)
|
validate_patterns(types=types, patterns=patterns)
|
||||||
|
|
@ -52,6 +60,14 @@ class PatternDataGrabber(BaseDataGrabber):
|
||||||
# Validate replacements
|
# Validate replacements
|
||||||
validate_replacements(replacements=replacements, patterns=patterns)
|
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)
|
super().__init__(types=types, datadir=datadir)
|
||||||
logger.debug("Initializing PatternDataGrabber")
|
logger.debug("Initializing PatternDataGrabber")
|
||||||
logger.debug(f"\tpatterns = {patterns}")
|
logger.debug(f"\tpatterns = {patterns}")
|
||||||
|
|
@ -184,7 +200,21 @@ class PatternDataGrabber(BaseDataGrabber):
|
||||||
f"Cannot access {t_type} for {element}: "
|
f"Cannot access {t_type} for {element}: "
|
||||||
f"File {t_out} does not exist"
|
f"File {t_out} does not exist"
|
||||||
)
|
)
|
||||||
|
# Update path for the element
|
||||||
out[t_type] = {"path": t_out}
|
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
|
return out
|
||||||
|
|
||||||
def get_elements(self) -> List:
|
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["func"]["path"] == out2["func"]["path"]
|
||||||
assert out1["anat"]["path"] == out2["anat"]["path"]
|
assert out1["anat"]["path"] == out2["anat"]["path"]
|
||||||
assert out1["vbm"]["path"] != out2["vbm"]["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