junifer 0.0.7.dev332__py3-none-any.whl → 0.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- junifer/_version.py +9 -19
- junifer/api/__init__.pyi +17 -2
- junifer/api/functions.py +222 -39
- junifer/api/queue_context/__init__.pyi +11 -3
- junifer/api/queue_context/gnu_parallel_local_adapter.py +81 -120
- junifer/api/queue_context/htcondor_adapter.py +118 -181
- junifer/api/queue_context/queue_context_adapter.py +51 -7
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +10 -35
- junifer/api/queue_context/tests/test_htcondor_adapter.py +13 -50
- junifer/api/res/fsl/run_fsl_docker.sh +4 -0
- junifer/api/tests/test_functions.py +863 -36
- junifer/cli/__init__.py +1 -7
- junifer/cli/cli.py +41 -22
- junifer/cli/parser.py +23 -147
- junifer/cli/tests/data/gmd_mean.yaml +6 -6
- junifer/cli/tests/data/gmd_mean_htcondor.yaml +6 -5
- junifer/cli/tests/data/partly_cloudy_agg_mean_tian.yml +1 -0
- junifer/cli/tests/test_cli.py +120 -4
- junifer/cli/tests/test_cli_utils.py +23 -6
- junifer/cli/utils.py +14 -9
- junifer/configs/__init__.py +5 -0
- junifer/configs/__init__.pyi +0 -0
- junifer/configs/juseless/datagrabbers/__init__.pyi +4 -2
- junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +18 -24
- junifer/configs/juseless/datagrabbers/camcan_vbm.py +20 -27
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +44 -52
- junifer/configs/juseless/datagrabbers/tests/test_ixi_vbm.py +0 -7
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +2 -19
- junifer/configs/juseless/datagrabbers/ucla.py +111 -104
- junifer/configs/juseless/datagrabbers/ukb_vbm.py +19 -25
- junifer/configs/py.typed +0 -0
- junifer/conftest.py +63 -24
- junifer/data/_dispatch.py +9 -19
- junifer/data/coordinates/_ants_coordinates_warper.py +4 -1
- junifer/data/coordinates/_coordinates.py +51 -6
- junifer/data/coordinates/_fsl_coordinates_warper.py +4 -1
- junifer/data/coordinates/tests/test_coordinates.py +15 -3
- junifer/data/coordinates/tests/test_coordinates_names.py +37 -0
- junifer/data/maps/_ants_maps_warper.py +18 -12
- junifer/data/maps/_fsl_maps_warper.py +7 -3
- junifer/data/maps/_maps.py +12 -8
- junifer/data/maps/tests/test_maps.py +13 -21
- junifer/data/masks/_ants_mask_warper.py +18 -12
- junifer/data/masks/_fsl_mask_warper.py +7 -3
- junifer/data/masks/_masks.py +15 -12
- junifer/data/masks/tests/test_masks.py +20 -17
- junifer/data/parcellations/_ants_parcellation_warper.py +18 -12
- junifer/data/parcellations/_fsl_parcellation_warper.py +7 -5
- junifer/data/parcellations/_parcellations.py +125 -91
- junifer/data/parcellations/tests/test_parcellations.py +122 -1
- junifer/data/template_spaces.py +117 -50
- junifer/data/tests/test_template_spaces.py +10 -7
- junifer/data/utils.py +10 -8
- junifer/datagrabber/__init__.pyi +38 -5
- junifer/datagrabber/aomic/__init__.pyi +8 -1
- junifer/datagrabber/aomic/_types.py +22 -0
- junifer/datagrabber/aomic/id1000.py +193 -183
- junifer/datagrabber/aomic/piop1.py +215 -259
- junifer/datagrabber/aomic/piop2.py +211 -244
- junifer/datagrabber/aomic/tests/test_id1000.py +70 -53
- junifer/datagrabber/aomic/tests/test_piop1.py +98 -102
- junifer/datagrabber/aomic/tests/test_piop2.py +88 -85
- junifer/datagrabber/base.py +253 -79
- junifer/datagrabber/datalad_base.py +127 -76
- junifer/datagrabber/dmcc13_benchmark.py +204 -289
- junifer/datagrabber/hcp1200/__init__.pyi +7 -2
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +61 -40
- junifer/datagrabber/hcp1200/hcp1200.py +151 -164
- junifer/datagrabber/hcp1200/tests/test_hcp1200.py +116 -128
- junifer/datagrabber/multiple.py +183 -63
- junifer/datagrabber/pattern.py +358 -227
- junifer/datagrabber/pattern_datalad.py +84 -124
- junifer/datagrabber/pattern_validation_mixin.py +22 -50
- junifer/datagrabber/tests/test_base.py +17 -4
- junifer/datagrabber/tests/test_datalad_base.py +20 -27
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +110 -122
- junifer/datagrabber/tests/test_multiple.py +293 -31
- junifer/datagrabber/tests/test_pattern.py +577 -18
- junifer/datagrabber/tests/test_pattern_datalad.py +177 -107
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +9 -51
- junifer/datareader/default.py +8 -5
- junifer/datareader/tests/test_default_reader.py +1 -1
- junifer/external/BrainPrint/.codecov.yml +2 -0
- junifer/external/BrainPrint/.codespellignore +2 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/bug-report.md +45 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/documentation.md +12 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/feature-request.md +24 -0
- junifer/external/BrainPrint/.github/ISSUE_TEMPLATE/questions-help-support.md +28 -0
- junifer/external/BrainPrint/.github/dependabot.yml +6 -0
- junifer/external/BrainPrint/.github/workflows/build.yml +53 -0
- junifer/external/BrainPrint/.github/workflows/code-style.yml +44 -0
- junifer/external/BrainPrint/.github/workflows/doc.yml +65 -0
- junifer/external/BrainPrint/.github/workflows/publish.yml +31 -0
- junifer/external/BrainPrint/.github/workflows/pytest.yml +54 -0
- junifer/external/BrainPrint/.gitignore +123 -0
- junifer/external/BrainPrint/LICENSE +21 -0
- junifer/external/BrainPrint/README.md +108 -0
- junifer/external/BrainPrint/brainprint/cli/__init__.py +11 -0
- junifer/external/BrainPrint/brainprint/cli/help_text.py +169 -0
- junifer/external/BrainPrint/brainprint/cli/parser.py +150 -0
- junifer/external/BrainPrint/brainprint/cli/utils.py +14 -0
- junifer/external/BrainPrint/brainprint/commands/__init__.py +0 -0
- junifer/external/BrainPrint/brainprint/commands/sys_info.py +18 -0
- junifer/external/BrainPrint/brainprint/utils/tests/__init__.py +0 -0
- junifer/external/BrainPrint/brainprint/utils/tests/test_config.py +33 -0
- junifer/external/BrainPrint/doc/Makefile +20 -0
- junifer/external/BrainPrint/doc/_static/.gitkeep +0 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/class.rst +10 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/function.rst +8 -0
- junifer/external/BrainPrint/doc/_templates/autosummary/module.rst +6 -0
- junifer/external/BrainPrint/doc/api/index.rst +11 -0
- junifer/external/BrainPrint/doc/conf.py +272 -0
- junifer/external/BrainPrint/doc/index.rst +140 -0
- junifer/external/BrainPrint/doc/links.inc +36 -0
- junifer/external/BrainPrint/doc/make.bat +35 -0
- junifer/external/BrainPrint/doc/references.bib +23 -0
- junifer/external/BrainPrint/pyproject.toml +170 -0
- junifer/external/BrainPrint/setup.py +3 -0
- junifer/external/__init__.py +5 -0
- junifer/external/__init__.pyi +0 -0
- junifer/external/nilearn/junifer_connectivity_measure.py +95 -39
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +226 -67
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +39 -27
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +231 -21
- junifer/external/py.typed +0 -0
- junifer/markers/__init__.pyi +6 -3
- junifer/markers/base.py +126 -76
- junifer/markers/brainprint.py +30 -39
- junifer/markers/complexity/__init__.py +20 -3
- junifer/markers/complexity/complexity_base.py +40 -41
- junifer/markers/complexity/hurst_exponent.py +22 -35
- junifer/markers/complexity/multiscale_entropy_auc.py +53 -41
- junifer/markers/complexity/perm_entropy.py +22 -36
- junifer/markers/complexity/range_entropy.py +22 -35
- junifer/markers/complexity/range_entropy_auc.py +27 -36
- junifer/markers/complexity/sample_entropy.py +22 -36
- junifer/markers/complexity/tests/test_complexity_registry.py +48 -0
- junifer/markers/complexity/tests/test_hurst_exponent.py +47 -36
- junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +50 -36
- junifer/markers/complexity/tests/test_perm_entropy.py +48 -36
- junifer/markers/complexity/tests/test_range_entropy.py +47 -36
- junifer/markers/complexity/tests/test_range_entropy_auc.py +47 -36
- junifer/markers/complexity/tests/test_sample_entropy.py +48 -36
- junifer/markers/complexity/tests/test_weighted_perm_entropy.py +50 -36
- junifer/markers/complexity/weighted_perm_entropy.py +22 -36
- junifer/markers/ets_rss.py +35 -31
- junifer/markers/falff/__init__.pyi +7 -1
- junifer/markers/falff/_afni_falff.py +22 -9
- junifer/markers/falff/_junifer_falff.py +47 -31
- junifer/markers/falff/falff_base.py +80 -60
- junifer/markers/falff/falff_maps.py +17 -41
- junifer/markers/falff/falff_parcels.py +26 -51
- junifer/markers/falff/falff_spheres.py +34 -61
- junifer/markers/falff/tests/test_falff_maps.py +20 -23
- junifer/markers/falff/tests/test_falff_mask.py +99 -0
- junifer/markers/falff/tests/test_falff_parcels.py +14 -10
- junifer/markers/falff/tests/test_falff_spheres.py +14 -10
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +32 -34
- junifer/markers/functional_connectivity/edge_functional_connectivity_maps.py +12 -25
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +19 -34
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +24 -44
- junifer/markers/functional_connectivity/functional_connectivity_base.py +50 -40
- junifer/markers/functional_connectivity/functional_connectivity_maps.py +12 -25
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +19 -34
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +24 -45
- junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +21 -22
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_maps.py +8 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +8 -4
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +8 -4
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_maps.py +8 -7
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +9 -5
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +8 -12
- junifer/markers/maps_aggregation.py +77 -55
- junifer/markers/parcel_aggregation.py +91 -70
- junifer/markers/reho/__init__.pyi +7 -1
- junifer/markers/reho/_afni_reho.py +23 -14
- junifer/markers/reho/_junifer_reho.py +112 -123
- junifer/markers/reho/reho_base.py +115 -37
- junifer/markers/reho/reho_maps.py +18 -32
- junifer/markers/reho/reho_parcels.py +26 -41
- junifer/markers/reho/reho_spheres.py +33 -54
- junifer/markers/reho/tests/test_junifer_reho.py +178 -0
- junifer/markers/reho/tests/test_reho_maps.py +27 -25
- junifer/markers/reho/tests/test_reho_parcels.py +28 -22
- junifer/markers/reho/tests/test_reho_spheres.py +16 -12
- junifer/markers/sphere_aggregation.py +88 -72
- junifer/markers/temporal_snr/temporal_snr_base.py +32 -30
- junifer/markers/temporal_snr/temporal_snr_maps.py +9 -18
- junifer/markers/temporal_snr/temporal_snr_parcels.py +19 -27
- junifer/markers/temporal_snr/temporal_snr_spheres.py +27 -41
- junifer/markers/temporal_snr/tests/test_temporal_snr_base.py +2 -2
- junifer/markers/temporal_snr/tests/test_temporal_snr_maps.py +17 -22
- junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +11 -3
- junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +9 -9
- junifer/markers/tests/test_brainprint.py +10 -9
- junifer/markers/tests/test_ets_rss.py +7 -3
- junifer/markers/tests/test_lost_regions.py +279 -0
- junifer/markers/tests/test_maps_aggregation.py +67 -114
- junifer/markers/tests/test_marker_utils.py +40 -1
- junifer/markers/tests/test_markers_base.py +275 -6
- junifer/markers/tests/test_parcel_aggregation.py +91 -53
- junifer/markers/tests/test_sphere_aggregation.py +53 -47
- junifer/markers/utils.py +267 -5
- junifer/onthefly/__init__.py +2 -3
- junifer/onthefly/__init__.pyi +4 -0
- junifer/onthefly/_brainprint.py +3 -5
- junifer/onthefly/py.typed +0 -0
- junifer/onthefly/read_transform.py +11 -9
- junifer/onthefly/tests/test_read_transform.py +7 -7
- junifer/pipeline/__init__.pyi +4 -2
- junifer/pipeline/marker_collection.py +14 -10
- junifer/pipeline/pipeline_component_registry.py +25 -6
- junifer/pipeline/pipeline_step_mixin.py +5 -12
- junifer/pipeline/tests/test_data_object_dumper.py +10 -10
- junifer/pipeline/tests/test_marker_collection.py +145 -168
- junifer/pipeline/tests/test_pipeline_component_registry.py +52 -8
- junifer/pipeline/tests/test_pipeline_step_mixin.py +12 -26
- junifer/pipeline/tests/test_update_meta_mixin.py +4 -5
- junifer/pipeline/tests/test_workdir_manager.py +39 -0
- junifer/pipeline/update_meta_mixin.py +13 -10
- junifer/pipeline/utils.py +22 -17
- junifer/pipeline/workdir_manager.py +41 -32
- junifer/preprocess/__init__.pyi +9 -4
- junifer/preprocess/_temporal_filter.py +34 -33
- junifer/preprocess/_temporal_slicer.py +17 -30
- junifer/preprocess/base.py +99 -55
- junifer/preprocess/confounds/__init__.pyi +10 -2
- junifer/preprocess/confounds/fmriprep_confound_remover.py +87 -109
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +64 -45
- junifer/preprocess/smoothing/__init__.pyi +2 -2
- junifer/preprocess/smoothing/_afni_smoothing.py +8 -7
- junifer/preprocess/smoothing/_fsl_smoothing.py +6 -4
- junifer/preprocess/smoothing/_nilearn_smoothing.py +7 -5
- junifer/preprocess/smoothing/smoothing.py +59 -40
- junifer/preprocess/smoothing/tests/test_smoothing.py +28 -8
- junifer/preprocess/tests/test_preprocess_base.py +17 -9
- junifer/preprocess/tests/test_temporal_filter.py +37 -16
- junifer/preprocess/tests/test_temporal_slicer.py +12 -12
- junifer/preprocess/warping/__init__.pyi +2 -2
- junifer/preprocess/warping/_ants_warper.py +56 -40
- junifer/preprocess/warping/_fsl_warper.py +49 -36
- junifer/preprocess/warping/_utils.py +106 -0
- junifer/preprocess/warping/space_warper.py +99 -98
- junifer/preprocess/warping/tests/test_space_warper.py +46 -41
- junifer/preprocess/warping/tests/test_warping_utils.py +163 -0
- junifer/stats.py +46 -34
- junifer/storage/__init__.pyi +8 -4
- junifer/storage/base.py +129 -64
- junifer/storage/hdf5.py +307 -199
- junifer/storage/pandas_base.py +46 -24
- junifer/storage/sqlite.py +99 -62
- junifer/storage/tests/data/collected_h5io_fork.hdf5 +0 -0
- junifer/storage/tests/test_hdf5.py +147 -12
- junifer/storage/tests/test_repeated_storage.py +293 -0
- junifer/storage/tests/test_sqlite.py +9 -20
- junifer/storage/tests/test_storage_base.py +18 -21
- junifer/storage/tests/test_utils.py +83 -22
- junifer/storage/utils.py +58 -38
- junifer/testing/__init__.pyi +2 -2
- junifer/testing/datagrabbers.py +480 -44
- junifer/testing/registry.py +12 -0
- junifer/testing/tests/test_adhdtesting_datagrabber.py +24 -0
- junifer/testing/tests/test_oasisvmbtesting_datagrabber.py +5 -0
- junifer/testing/tests/test_partlycloudytesting_datagrabber.py +52 -0
- junifer/testing/tests/test_spmauditory_datagrabber.py +16 -0
- junifer/testing/tests/test_testing_registry.py +31 -0
- junifer/testing/tests/test_testing_utils.py +35 -0
- junifer/testing/tests/test_uclacnpvbmtesting_datagrabber.py +81 -0
- junifer/testing/utils.py +33 -1
- junifer/tests/test_stats.py +1 -5
- junifer/typing/__init__.pyi +2 -0
- junifer/typing/_typing.py +34 -19
- junifer/typing/py.typed +0 -0
- junifer/utils/__init__.pyi +10 -1
- junifer/utils/_config.py +1 -2
- junifer/utils/helpers.py +68 -2
- junifer/utils/logging.py +31 -7
- junifer/utils/tests/test_helpers.py +36 -1
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/METADATA +43 -35
- junifer-0.0.8.dist-info/RECORD +402 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/WHEEL +1 -1
- junifer/cli/tests/test_parser.py +0 -280
- junifer/external/h5io/h5io/__init__.py +0 -15
- junifer/external/h5io/h5io/_h5io.py +0 -767
- junifer/external/h5io/h5io/_version.py +0 -1
- junifer/external/h5io/h5io/chunked_array.py +0 -94
- junifer/external/h5io/h5io/chunked_list.py +0 -65
- junifer/markers/complexity/__init__.pyi +0 -17
- junifer-0.0.7.dev332.dist-info/RECORD +0 -353
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/AUTHORS.rst +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/licenses/LICENSE.md +0 -0
- {junifer-0.0.7.dev332.dist-info → junifer-0.0.8.dist-info}/top_level.txt +0 -0
|
@@ -7,7 +7,6 @@ from typing import (
|
|
|
7
7
|
Any,
|
|
8
8
|
ClassVar,
|
|
9
9
|
Literal,
|
|
10
|
-
Union,
|
|
11
10
|
)
|
|
12
11
|
|
|
13
12
|
import nibabel as nib
|
|
@@ -16,7 +15,7 @@ from numpy.typing import ArrayLike
|
|
|
16
15
|
|
|
17
16
|
from ...pipeline import WorkDirManager
|
|
18
17
|
from ...typing import Dependencies
|
|
19
|
-
from
|
|
18
|
+
from ..base import logger
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
__all__ = ["NilearnSmoothing"]
|
|
@@ -34,7 +33,7 @@ class NilearnSmoothing:
|
|
|
34
33
|
def preprocess(
|
|
35
34
|
self,
|
|
36
35
|
input: dict[str, Any],
|
|
37
|
-
fwhm:
|
|
36
|
+
fwhm: int | float | ArrayLike | Literal["fast"] | None,
|
|
38
37
|
) -> dict[str, Any]:
|
|
39
38
|
"""Preprocess using nilearn.
|
|
40
39
|
|
|
@@ -75,7 +74,7 @@ class NilearnSmoothing:
|
|
|
75
74
|
smoothed_img = nimg.smooth_img(imgs=input["data"], fwhm=fwhm)
|
|
76
75
|
|
|
77
76
|
# Save smoothed output
|
|
78
|
-
smoothed_img_path = element_tempdir / "smoothed_data.nii
|
|
77
|
+
smoothed_img_path = element_tempdir / "smoothed_data.nii"
|
|
79
78
|
nib.save(smoothed_img, smoothed_img_path)
|
|
80
79
|
|
|
81
80
|
logger.debug("Updating smoothed data")
|
|
@@ -83,7 +82,10 @@ class NilearnSmoothing:
|
|
|
83
82
|
{
|
|
84
83
|
# Update path to sync with "data"
|
|
85
84
|
"path": smoothed_img_path,
|
|
86
|
-
|
|
85
|
+
# Update data, loaded from the file to not keep the
|
|
86
|
+
# in-memory image (memory-mapped, as the file is not
|
|
87
|
+
# compressed)
|
|
88
|
+
"data": nib.load(smoothed_img_path),
|
|
87
89
|
}
|
|
88
90
|
)
|
|
89
91
|
|
|
@@ -4,18 +4,44 @@
|
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
6
|
from collections.abc import Sequence
|
|
7
|
-
from
|
|
7
|
+
from enum import StrEnum
|
|
8
|
+
from typing import (
|
|
9
|
+
Annotated,
|
|
10
|
+
Any,
|
|
11
|
+
ClassVar,
|
|
12
|
+
Literal,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from pydantic import BeforeValidator
|
|
8
16
|
|
|
9
17
|
from ...api.decorators import register_preprocessor
|
|
18
|
+
from ...datagrabber import DataType
|
|
10
19
|
from ...typing import ConditionalDependencies
|
|
11
|
-
from ...utils import
|
|
12
|
-
from ..base import BasePreprocessor
|
|
20
|
+
from ...utils import ensure_list_or_none
|
|
21
|
+
from ..base import BasePreprocessor, logger
|
|
13
22
|
from ._afni_smoothing import AFNISmoothing
|
|
14
23
|
from ._fsl_smoothing import FSLSmoothing
|
|
15
24
|
from ._nilearn_smoothing import NilearnSmoothing
|
|
16
25
|
|
|
17
26
|
|
|
18
|
-
__all__ = ["Smoothing"]
|
|
27
|
+
__all__ = ["Smoothing", "SmoothingImpl"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SmoothingImpl(StrEnum):
|
|
31
|
+
"""Accepted smoothing implementations.
|
|
32
|
+
|
|
33
|
+
* ``nilearn`` : :func:`nilearn.image.smooth_img`
|
|
34
|
+
* ``afni`` : AFNI's ``3dBlurToFWHM``
|
|
35
|
+
* ``fsl`` : FSL SUSAN's ``susan``
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
nilearn = "nilearn"
|
|
40
|
+
afni = "afni"
|
|
41
|
+
fsl = "fsl"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_on = Literal[DataType.T1w, DataType.T2w, DataType.BOLD]
|
|
19
45
|
|
|
20
46
|
|
|
21
47
|
@register_preprocessor
|
|
@@ -24,18 +50,13 @@ class Smoothing(BasePreprocessor):
|
|
|
24
50
|
|
|
25
51
|
Parameters
|
|
26
52
|
----------
|
|
27
|
-
using :
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* "afni" : Use AFNI's ``3dBlurToFWHM``
|
|
32
|
-
* "fsl" : Use FSL SUSAN's ``susan``
|
|
33
|
-
|
|
34
|
-
on : {"T1w", "T2w", "BOLD"} or list of the options
|
|
35
|
-
The data type to apply smoothing to.
|
|
53
|
+
using : :enum:`.SmoothingImpl`
|
|
54
|
+
on : {``DataType.T1w``, ``DataType.T2w``, ``DataType.BOLD``} or \
|
|
55
|
+
list of them
|
|
56
|
+
The data type(s) to apply smoothing to.
|
|
36
57
|
smoothing_params : dict, optional
|
|
37
58
|
Extra parameters for smoothing as a dictionary (default None).
|
|
38
|
-
If ``using=
|
|
59
|
+
If ``using=SmoothingImpl.nilearn``, then the valid keys are:
|
|
39
60
|
|
|
40
61
|
* ``fmhw`` : scalar, ``numpy.ndarray``, tuple or list of scalar, \
|
|
41
62
|
"fast" or None
|
|
@@ -52,13 +73,13 @@ class Smoothing(BasePreprocessor):
|
|
|
52
73
|
- If None, no filtering is performed (useful when just removal of
|
|
53
74
|
non-finite values is needed).
|
|
54
75
|
|
|
55
|
-
else if ``using=
|
|
76
|
+
else if ``using=SmoothingImpl.afni``, then the valid keys are:
|
|
56
77
|
|
|
57
78
|
* ``fwhm`` : int or float
|
|
58
79
|
Smooth until the value. AFNI estimates the smoothing and then
|
|
59
80
|
applies smoothing to reach ``fwhm``.
|
|
60
81
|
|
|
61
|
-
else if ``using=
|
|
82
|
+
else if ``using=SmoothingImpl.fsl``, then the valid keys are:
|
|
62
83
|
|
|
63
84
|
* ``brightness_threshold`` : float
|
|
64
85
|
Threshold to discriminate between noise and the underlying image.
|
|
@@ -71,43 +92,41 @@ class Smoothing(BasePreprocessor):
|
|
|
71
92
|
|
|
72
93
|
_CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
|
|
73
94
|
{
|
|
74
|
-
"using":
|
|
75
|
-
"depends_on": NilearnSmoothing,
|
|
95
|
+
"using": SmoothingImpl.nilearn,
|
|
96
|
+
"depends_on": [NilearnSmoothing],
|
|
76
97
|
},
|
|
77
98
|
{
|
|
78
|
-
"using":
|
|
79
|
-
"depends_on": AFNISmoothing,
|
|
99
|
+
"using": SmoothingImpl.afni,
|
|
100
|
+
"depends_on": [AFNISmoothing],
|
|
80
101
|
},
|
|
81
102
|
{
|
|
82
|
-
"using":
|
|
83
|
-
"depends_on": FSLSmoothing,
|
|
103
|
+
"using": SmoothingImpl.fsl,
|
|
104
|
+
"depends_on": [FSLSmoothing],
|
|
84
105
|
},
|
|
85
106
|
]
|
|
86
|
-
_VALID_DATA_TYPES: ClassVar[Sequence[
|
|
107
|
+
_VALID_DATA_TYPES: ClassVar[Sequence[DataType]] = [
|
|
108
|
+
DataType.T1w,
|
|
109
|
+
DataType.T2w,
|
|
110
|
+
DataType.BOLD,
|
|
111
|
+
]
|
|
87
112
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if using not in valid_using:
|
|
98
|
-
raise_error(
|
|
99
|
-
f"Invalid value for `using`, should be one of: {valid_using}"
|
|
100
|
-
)
|
|
101
|
-
self.using = using
|
|
113
|
+
using: SmoothingImpl
|
|
114
|
+
on: Annotated[
|
|
115
|
+
_on | list[_on],
|
|
116
|
+
BeforeValidator(ensure_list_or_none),
|
|
117
|
+
]
|
|
118
|
+
smoothing_params: dict | None = None
|
|
119
|
+
|
|
120
|
+
def validate_preprocessor_params(self) -> None:
|
|
121
|
+
"""Run extra logical validation for preprocessor."""
|
|
102
122
|
self.smoothing_params = (
|
|
103
|
-
smoothing_params if smoothing_params is not None else {}
|
|
123
|
+
self.smoothing_params if self.smoothing_params is not None else {}
|
|
104
124
|
)
|
|
105
|
-
super().__init__(on=on)
|
|
106
125
|
|
|
107
126
|
def preprocess(
|
|
108
127
|
self,
|
|
109
128
|
input: dict[str, Any],
|
|
110
|
-
extra_input:
|
|
129
|
+
extra_input: dict[str, Any] | None = None,
|
|
111
130
|
) -> dict[str, Any]:
|
|
112
131
|
"""Preprocess.
|
|
113
132
|
|
|
@@ -3,14 +3,20 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import nibabel as nib
|
|
6
9
|
import pytest
|
|
7
10
|
|
|
8
11
|
from junifer.datareader import DefaultDataReader
|
|
9
12
|
from junifer.pipeline.utils import _check_afni, _check_fsl
|
|
10
|
-
from junifer.preprocess import Smoothing
|
|
13
|
+
from junifer.preprocess import Smoothing, SmoothingImpl
|
|
11
14
|
from junifer.testing.datagrabbers import SPMAuditoryTestingDataGrabber
|
|
12
15
|
|
|
13
16
|
|
|
17
|
+
pytestmark = pytest.mark.external
|
|
18
|
+
|
|
19
|
+
|
|
14
20
|
@pytest.mark.parametrize(
|
|
15
21
|
"data_type",
|
|
16
22
|
["T1w", "BOLD"],
|
|
@@ -24,17 +30,22 @@ def test_Smoothing_nilearn(data_type: str) -> None:
|
|
|
24
30
|
The parametrized data type.
|
|
25
31
|
|
|
26
32
|
"""
|
|
27
|
-
with SPMAuditoryTestingDataGrabber() as dg:
|
|
33
|
+
with SPMAuditoryTestingDataGrabber(n_timepoints=10) as dg:
|
|
28
34
|
# Read data
|
|
29
35
|
element_data = DefaultDataReader().fit_transform(dg["sub001"])
|
|
30
36
|
# Preprocess data
|
|
31
37
|
output = Smoothing(
|
|
32
|
-
using=
|
|
38
|
+
using=SmoothingImpl.nilearn,
|
|
33
39
|
on=data_type,
|
|
34
40
|
smoothing_params={"fwhm": "fast"},
|
|
35
41
|
).fit_transform(element_data)
|
|
36
42
|
|
|
37
43
|
assert isinstance(output, dict)
|
|
44
|
+
# The data is loaded from the saved file, not kept in memory
|
|
45
|
+
assert nib.is_proxy(output[data_type]["data"].dataobj)
|
|
46
|
+
assert output[data_type]["data"].get_filename() == str(
|
|
47
|
+
output[data_type]["path"]
|
|
48
|
+
)
|
|
38
49
|
|
|
39
50
|
|
|
40
51
|
@pytest.mark.parametrize(
|
|
@@ -44,26 +55,35 @@ def test_Smoothing_nilearn(data_type: str) -> None:
|
|
|
44
55
|
@pytest.mark.skipif(
|
|
45
56
|
_check_afni() is False, reason="requires AFNI to be in PATH"
|
|
46
57
|
)
|
|
47
|
-
def test_Smoothing_afni(
|
|
58
|
+
def test_Smoothing_afni(
|
|
59
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, data_type: str
|
|
60
|
+
) -> None:
|
|
48
61
|
"""Test Smoothing using AFNI.
|
|
49
62
|
|
|
50
63
|
Parameters
|
|
51
64
|
----------
|
|
65
|
+
tmp_path : pathlib.Path
|
|
66
|
+
The path to the test directory.
|
|
67
|
+
monkeypatch : pytest.MonkeyPatch
|
|
68
|
+
The pytest.MonkeyPatch object.
|
|
52
69
|
data_type : str
|
|
53
70
|
The parametrized data type.
|
|
54
71
|
|
|
55
72
|
"""
|
|
56
|
-
|
|
73
|
+
# Run in an empty directory, to check that no files are written in it
|
|
74
|
+
monkeypatch.chdir(tmp_path)
|
|
75
|
+
with SPMAuditoryTestingDataGrabber(n_timepoints=10) as dg:
|
|
57
76
|
# Read data
|
|
58
77
|
element_data = DefaultDataReader().fit_transform(dg["sub001"])
|
|
59
78
|
# Preprocess data
|
|
60
79
|
output = Smoothing(
|
|
61
|
-
using=
|
|
80
|
+
using=SmoothingImpl.afni,
|
|
62
81
|
on=data_type,
|
|
63
82
|
smoothing_params={"fwhm": 3},
|
|
64
83
|
).fit_transform(element_data)
|
|
65
84
|
|
|
66
85
|
assert isinstance(output, dict)
|
|
86
|
+
assert list(tmp_path.iterdir()) == []
|
|
67
87
|
|
|
68
88
|
|
|
69
89
|
@pytest.mark.parametrize(
|
|
@@ -80,12 +100,12 @@ def test_Smoothing_fsl(data_type: str) -> None:
|
|
|
80
100
|
The parametrized data type.
|
|
81
101
|
|
|
82
102
|
"""
|
|
83
|
-
with SPMAuditoryTestingDataGrabber() as dg:
|
|
103
|
+
with SPMAuditoryTestingDataGrabber(n_timepoints=10) as dg:
|
|
84
104
|
# Read data
|
|
85
105
|
element_data = DefaultDataReader().fit_transform(dg["sub001"])
|
|
86
106
|
# Preprocess data
|
|
87
107
|
output = Smoothing(
|
|
88
|
-
using=
|
|
108
|
+
using=SmoothingImpl.fsl,
|
|
89
109
|
on=data_type,
|
|
90
110
|
smoothing_params={"brightness_threshold": 10.0, "fwhm": 3.0},
|
|
91
111
|
).fit_transform(element_data)
|
|
@@ -15,7 +15,7 @@ from junifer.preprocess.base import BasePreprocessor
|
|
|
15
15
|
def test_base_preprocessor_abstractness() -> None:
|
|
16
16
|
"""Test BasePreprocessor is abstract base class."""
|
|
17
17
|
with pytest.raises(TypeError, match=r"abstract"):
|
|
18
|
-
BasePreprocessor(on=
|
|
18
|
+
BasePreprocessor(on="BOLD")
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def test_base_preprocessor_subclassing() -> None:
|
|
@@ -25,9 +25,7 @@ def test_base_preprocessor_subclassing() -> None:
|
|
|
25
25
|
class MyBasePreprocessor(BasePreprocessor):
|
|
26
26
|
_VALID_DATA_TYPES: ClassVar[Sequence[str]] = ["BOLD", "T1w"]
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
self.parameter = 1
|
|
30
|
-
super().__init__(on=on)
|
|
28
|
+
parameter: int = 1
|
|
31
29
|
|
|
32
30
|
def preprocess(self, input, extra_input=None):
|
|
33
31
|
input["data"] = f"modified_{input['data']}"
|
|
@@ -60,7 +58,7 @@ def test_base_preprocessor_subclassing() -> None:
|
|
|
60
58
|
},
|
|
61
59
|
},
|
|
62
60
|
}
|
|
63
|
-
prep = MyBasePreprocessor(on=
|
|
61
|
+
prep = MyBasePreprocessor(on="BOLD")
|
|
64
62
|
|
|
65
63
|
with pytest.raises(ValueError, match="not have the required data"):
|
|
66
64
|
prep.validate_input(["T1w"])
|
|
@@ -75,10 +73,20 @@ def test_base_preprocessor_subclassing() -> None:
|
|
|
75
73
|
|
|
76
74
|
meta = output["BOLD"]["meta"]
|
|
77
75
|
assert "preprocess" in meta
|
|
78
|
-
assert
|
|
79
|
-
assert "
|
|
80
|
-
assert "
|
|
81
|
-
assert
|
|
76
|
+
assert len(meta["preprocess"]) == 1
|
|
77
|
+
assert "class" in meta["preprocess"][0]
|
|
78
|
+
assert "MyBasePreprocessor" == meta["preprocess"][0]["class"]
|
|
79
|
+
assert "parameter" in meta["preprocess"][0]
|
|
80
|
+
assert 1 == meta["preprocess"][0]["parameter"]
|
|
81
|
+
|
|
82
|
+
# A second preprocessor is recorded after the first one
|
|
83
|
+
output = MyBasePreprocessor(on="BOLD", parameter=2).fit_transform(
|
|
84
|
+
input=output
|
|
85
|
+
)
|
|
86
|
+
assert [x["parameter"] for x in output["BOLD"]["meta"]["preprocess"]] == [
|
|
87
|
+
1,
|
|
88
|
+
2,
|
|
89
|
+
]
|
|
82
90
|
|
|
83
91
|
assert "T1w" in output
|
|
84
92
|
assert "data" in output["T1w"]
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import nibabel as nib
|
|
8
7
|
import pytest
|
|
9
8
|
|
|
10
9
|
from junifer.datareader import DefaultDataReader
|
|
@@ -12,12 +11,15 @@ from junifer.preprocess import TemporalFilter
|
|
|
12
11
|
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
13
12
|
|
|
14
13
|
|
|
14
|
+
pytestmark = pytest.mark.external
|
|
15
|
+
|
|
16
|
+
|
|
15
17
|
@pytest.mark.parametrize(
|
|
16
18
|
"detrend, standardize, low_pass, high_pass, t_r, masks",
|
|
17
19
|
(
|
|
18
20
|
[
|
|
19
21
|
True,
|
|
20
|
-
|
|
22
|
+
"zscore_sample",
|
|
21
23
|
None,
|
|
22
24
|
None,
|
|
23
25
|
None,
|
|
@@ -25,7 +27,7 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
25
27
|
],
|
|
26
28
|
[
|
|
27
29
|
False,
|
|
28
|
-
|
|
30
|
+
"zscore_sample",
|
|
29
31
|
0.1,
|
|
30
32
|
None,
|
|
31
33
|
None,
|
|
@@ -33,15 +35,15 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
33
35
|
],
|
|
34
36
|
[
|
|
35
37
|
True,
|
|
36
|
-
|
|
38
|
+
None,
|
|
37
39
|
None,
|
|
38
40
|
0.08,
|
|
39
41
|
None,
|
|
40
|
-
"compute_background_mask",
|
|
42
|
+
["compute_background_mask"],
|
|
41
43
|
],
|
|
42
44
|
[
|
|
43
45
|
False,
|
|
44
|
-
|
|
46
|
+
"psc",
|
|
45
47
|
None,
|
|
46
48
|
None,
|
|
47
49
|
2,
|
|
@@ -49,7 +51,7 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
49
51
|
],
|
|
50
52
|
[
|
|
51
53
|
True,
|
|
52
|
-
|
|
54
|
+
"zscore_sample",
|
|
53
55
|
0.1,
|
|
54
56
|
0.08,
|
|
55
57
|
2,
|
|
@@ -59,11 +61,11 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
59
61
|
)
|
|
60
62
|
def test_TemporalFilter(
|
|
61
63
|
detrend: bool,
|
|
62
|
-
standardize:
|
|
63
|
-
low_pass:
|
|
64
|
-
high_pass:
|
|
65
|
-
t_r:
|
|
66
|
-
masks:
|
|
64
|
+
standardize: str | None,
|
|
65
|
+
low_pass: float | None,
|
|
66
|
+
high_pass: float | None,
|
|
67
|
+
t_r: float | None,
|
|
68
|
+
masks: str | list[str] | None,
|
|
67
69
|
) -> None:
|
|
68
70
|
"""Test TemporalFilter.
|
|
69
71
|
|
|
@@ -71,15 +73,15 @@ def test_TemporalFilter(
|
|
|
71
73
|
----------
|
|
72
74
|
detrend : bool
|
|
73
75
|
The parametrized detrending flag.
|
|
74
|
-
standardize :
|
|
75
|
-
The parametrized standardization
|
|
76
|
+
standardize : str or None
|
|
77
|
+
The parametrized standardization strategy.
|
|
76
78
|
low_pass : float or None
|
|
77
79
|
The parametrized low pass value.
|
|
78
80
|
high_pass : float or None
|
|
79
81
|
The parametrized high pass value.
|
|
80
82
|
t_r : float or None
|
|
81
83
|
The parametrized repetition time.
|
|
82
|
-
masks : str or None
|
|
84
|
+
masks : str, list of str or None
|
|
83
85
|
The parametrized mask.
|
|
84
86
|
|
|
85
87
|
"""
|
|
@@ -97,3 +99,22 @@ def test_TemporalFilter(
|
|
|
97
99
|
).fit_transform(element_data)
|
|
98
100
|
|
|
99
101
|
assert isinstance(output, dict)
|
|
102
|
+
# The data is loaded from the saved file, not kept in memory
|
|
103
|
+
assert nib.is_proxy(output["BOLD"]["data"].dataobj)
|
|
104
|
+
assert output["BOLD"]["data"].get_filename() == str(
|
|
105
|
+
output["BOLD"]["path"]
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.parametrize("standardize", [True, False])
|
|
110
|
+
def test_TemporalFilter_standardize_bool(standardize: bool) -> None:
|
|
111
|
+
"""Test TemporalFilter error for boolean standardize.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
standardize : bool
|
|
116
|
+
The parametrized standardization flag.
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
with pytest.raises(ValueError, match="does not accept booleans"):
|
|
120
|
+
TemporalFilter(standardize=standardize)
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
6
|
from contextlib import AbstractContextManager, nullcontext
|
|
7
|
-
from typing import Optional
|
|
8
7
|
|
|
8
|
+
import nibabel as nib
|
|
9
9
|
import pytest
|
|
10
10
|
|
|
11
11
|
from junifer.datareader import DefaultDataReader
|
|
@@ -13,6 +13,9 @@ from junifer.preprocess import TemporalSlicer
|
|
|
13
13
|
from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
pytestmark = pytest.mark.external
|
|
17
|
+
|
|
18
|
+
|
|
16
19
|
@pytest.mark.parametrize(
|
|
17
20
|
"start, stop, duration, t_r, expected_dim, expect",
|
|
18
21
|
(
|
|
@@ -75,14 +78,6 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
75
78
|
pytest.raises(RuntimeError, match="`stop` should be None"),
|
|
76
79
|
],
|
|
77
80
|
[10.0, None, 30.0, None, 30, nullcontext()],
|
|
78
|
-
[
|
|
79
|
-
-1.0,
|
|
80
|
-
None,
|
|
81
|
-
None,
|
|
82
|
-
None,
|
|
83
|
-
84,
|
|
84
|
-
pytest.raises(ValueError, match="`start` cannot be negative"),
|
|
85
|
-
],
|
|
86
81
|
[
|
|
87
82
|
0.0,
|
|
88
83
|
500.0,
|
|
@@ -95,9 +90,9 @@ from junifer.testing.datagrabbers import PartlyCloudyTestingDataGrabber
|
|
|
95
90
|
)
|
|
96
91
|
def test_TemporalSlicer(
|
|
97
92
|
start: float,
|
|
98
|
-
stop:
|
|
99
|
-
duration:
|
|
100
|
-
t_r:
|
|
93
|
+
stop: float | None,
|
|
94
|
+
duration: float | None,
|
|
95
|
+
t_r: float | None,
|
|
101
96
|
expected_dim: int,
|
|
102
97
|
expect: AbstractContextManager,
|
|
103
98
|
) -> None:
|
|
@@ -134,5 +129,10 @@ def test_TemporalSlicer(
|
|
|
134
129
|
|
|
135
130
|
# Check image data dim
|
|
136
131
|
assert output["BOLD"]["data"].shape[3] == expected_dim
|
|
132
|
+
# The data is loaded from the saved file, not kept in memory
|
|
133
|
+
assert nib.is_proxy(output["BOLD"]["data"].dataobj)
|
|
134
|
+
assert output["BOLD"]["data"].get_filename() == str(
|
|
135
|
+
output["BOLD"]["path"]
|
|
136
|
+
)
|
|
137
137
|
# Check confounds dim
|
|
138
138
|
assert output["BOLD"]["confounds"]["data"].shape[0] == expected_dim
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
__all__ = ["SpaceWarper"]
|
|
1
|
+
__all__ = ["SpaceWarper", "SpaceWarpingImpl"]
|
|
2
2
|
|
|
3
|
-
from .space_warper import SpaceWarper
|
|
3
|
+
from .space_warper import SpaceWarper, SpaceWarpingImpl
|