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
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Provide tests for markers on regions lost in resampling."""
|
|
2
|
+
|
|
3
|
+
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
|
4
|
+
# License: AGPL
|
|
5
|
+
|
|
6
|
+
from collections.abc import Iterator
|
|
7
|
+
from importlib.util import find_spec
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import nibabel as nib
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
from junifer import markers
|
|
15
|
+
from junifer.data import deregister_data, register_data
|
|
16
|
+
from junifer.datareader import DefaultDataReader
|
|
17
|
+
from junifer.pipeline import WorkDirManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
COMPLEXITY_MARKERS = (
|
|
21
|
+
"HurstExponent",
|
|
22
|
+
"RangeEntropy",
|
|
23
|
+
"RangeEntropyAUC",
|
|
24
|
+
"MultiscaleEntropyAUC",
|
|
25
|
+
"PermEntropy",
|
|
26
|
+
"WeightedPermEntropy",
|
|
27
|
+
"SampleEntropy",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
skip_no_neurokit2 = pytest.mark.skipif(
|
|
31
|
+
find_spec("neurokit2") is None, reason="requires neurokit2"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.fixture(scope="module")
|
|
36
|
+
def element(tmp_path_factory: pytest.TempPathFactory) -> Iterator[dict]:
|
|
37
|
+
"""Provide BOLD data where regions of the parcellations are lost.
|
|
38
|
+
|
|
39
|
+
The parcellations are on a 1mm grid and the BOLD data on a 3mm grid,
|
|
40
|
+
which does not sample their single-voxel regions:
|
|
41
|
+
|
|
42
|
+
* ``LostRegion`` (and ``LostRegion2``, the same): regions ``a``, ``b``,
|
|
43
|
+
``lost``, ``c`` and ``d``.
|
|
44
|
+
* ``OneRegionLeft``: regions ``kept``, ``lost`` and ``lost_too``.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
tmp_path_factory : pytest.TempPathFactory
|
|
49
|
+
The pytest factory for temporary directories.
|
|
50
|
+
|
|
51
|
+
Yields
|
|
52
|
+
------
|
|
53
|
+
dict
|
|
54
|
+
The element data.
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
tmp_path = tmp_path_factory.mktemp("lost_regions")
|
|
58
|
+
# Voxels 0, 3, 6, ... are sampled by the 3mm grid, 7 and 13 are not
|
|
59
|
+
lost_region = np.zeros((24, 24, 24), dtype=np.int16)
|
|
60
|
+
lost_region[0:12, 0:12] = 1
|
|
61
|
+
lost_region[12:24, 0:12] = 2
|
|
62
|
+
lost_region[7, 13, 7] = 3
|
|
63
|
+
lost_region[0:12, 15:24] = 4
|
|
64
|
+
lost_region[12:24, 15:24] = 5
|
|
65
|
+
one_region_left = np.zeros((24, 24, 24), dtype=np.int16)
|
|
66
|
+
one_region_left[0:12, 0:12] = 1
|
|
67
|
+
one_region_left[7, 13, 7] = 2
|
|
68
|
+
one_region_left[13, 7, 7] = 3
|
|
69
|
+
for name, data, labels in (
|
|
70
|
+
("LostRegion", lost_region, ["a", "b", "lost", "c", "d"]),
|
|
71
|
+
("LostRegion2", lost_region, ["a", "b", "lost", "c", "d"]),
|
|
72
|
+
("OneRegionLeft", one_region_left, ["kept", "lost", "lost_too"]),
|
|
73
|
+
):
|
|
74
|
+
path = tmp_path / f"{name}.nii.gz"
|
|
75
|
+
nib.save(nib.Nifti1Image(data, np.eye(4)), path)
|
|
76
|
+
register_data(
|
|
77
|
+
kind="parcellation",
|
|
78
|
+
name=name,
|
|
79
|
+
parcellation_path=path,
|
|
80
|
+
parcels_labels=labels,
|
|
81
|
+
space="MNI152NLin6Asym",
|
|
82
|
+
)
|
|
83
|
+
# Random walks, so all the measures are defined
|
|
84
|
+
rng = np.random.default_rng(0)
|
|
85
|
+
bold = rng.normal(size=(8, 8, 8, 120)).cumsum(axis=-1) + 1000
|
|
86
|
+
bold_img = nib.Nifti1Image(
|
|
87
|
+
bold.astype(np.float32), np.diag([3.0, 3.0, 3.0, 1.0])
|
|
88
|
+
)
|
|
89
|
+
bold_img.header.set_xyzt_units("mm", "sec")
|
|
90
|
+
bold_path = tmp_path / "bold.nii.gz"
|
|
91
|
+
nib.save(bold_img, bold_path)
|
|
92
|
+
yield DefaultDataReader().fit_transform(
|
|
93
|
+
{"BOLD": {"path": bold_path, "space": "MNI152NLin6Asym"}}
|
|
94
|
+
)
|
|
95
|
+
for name in ("LostRegion", "LostRegion2", "OneRegionLeft"):
|
|
96
|
+
deregister_data(kind="parcellation", name=name)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _case(name: str, params: dict, feature: str, nan: list) -> object:
|
|
100
|
+
"""Get a test case.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
name : str
|
|
105
|
+
The name of the marker class.
|
|
106
|
+
params : dict
|
|
107
|
+
The parameters of the marker.
|
|
108
|
+
feature : str
|
|
109
|
+
The name of the feature to check.
|
|
110
|
+
nan : list
|
|
111
|
+
The values that are NaN.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
object
|
|
116
|
+
The test case, named after the parcellation, marker and feature.
|
|
117
|
+
Complexity markers are skipped if neurokit2 is not installed.
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
parcellation = params.get("parcellation", params.get("parcellation_one"))
|
|
121
|
+
return pytest.param(
|
|
122
|
+
name,
|
|
123
|
+
params,
|
|
124
|
+
feature,
|
|
125
|
+
nan,
|
|
126
|
+
marks=skip_no_neurokit2 if name in COMPLEXITY_MARKERS else (),
|
|
127
|
+
id=f"{parcellation}-{name}-{feature}",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Whether the values are NaN for LostRegion, whose 3rd region is lost
|
|
132
|
+
REGIONS = [False, False, True, False, False]
|
|
133
|
+
# For connectivity, a region pair is NaN if one of the regions is lost
|
|
134
|
+
PAIRS = [[r or c for c in REGIONS] for r in REGIONS]
|
|
135
|
+
# For edge-centric FC, the edges are the region pairs (lower triangle)
|
|
136
|
+
EDGES = [r or c for i, r in enumerate(REGIONS) for c in REGIONS[:i]]
|
|
137
|
+
EDGE_PAIRS = [[r or c for c in EDGES] for r in EDGES]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@pytest.mark.parametrize(
|
|
141
|
+
"name, params, feature, nan",
|
|
142
|
+
[
|
|
143
|
+
_case(
|
|
144
|
+
"ParcelAggregation",
|
|
145
|
+
{"parcellation": "LostRegion", "method": "mean", "on": "BOLD"},
|
|
146
|
+
"aggregation",
|
|
147
|
+
[REGIONS] * 120,
|
|
148
|
+
),
|
|
149
|
+
_case(
|
|
150
|
+
"FunctionalConnectivityParcels",
|
|
151
|
+
{"parcellation": "LostRegion"},
|
|
152
|
+
"functional_connectivity",
|
|
153
|
+
PAIRS,
|
|
154
|
+
),
|
|
155
|
+
_case(
|
|
156
|
+
"EdgeCentricFCParcels",
|
|
157
|
+
{"parcellation": "LostRegion"},
|
|
158
|
+
"functional_connectivity",
|
|
159
|
+
EDGE_PAIRS,
|
|
160
|
+
),
|
|
161
|
+
_case(
|
|
162
|
+
"CrossParcellationFC",
|
|
163
|
+
{
|
|
164
|
+
"parcellation_one": "LostRegion",
|
|
165
|
+
"parcellation_two": "LostRegion2",
|
|
166
|
+
},
|
|
167
|
+
"functional_connectivity",
|
|
168
|
+
PAIRS,
|
|
169
|
+
),
|
|
170
|
+
_case(
|
|
171
|
+
"ReHoParcels",
|
|
172
|
+
{"parcellation": "LostRegion", "using": "junifer"},
|
|
173
|
+
"reho",
|
|
174
|
+
[REGIONS],
|
|
175
|
+
),
|
|
176
|
+
_case(
|
|
177
|
+
"ALFFParcels",
|
|
178
|
+
{"parcellation": "LostRegion", "using": "junifer"},
|
|
179
|
+
"alff",
|
|
180
|
+
[REGIONS],
|
|
181
|
+
),
|
|
182
|
+
_case(
|
|
183
|
+
"ALFFParcels",
|
|
184
|
+
{"parcellation": "LostRegion", "using": "junifer"},
|
|
185
|
+
"falff",
|
|
186
|
+
[REGIONS],
|
|
187
|
+
),
|
|
188
|
+
_case(
|
|
189
|
+
"TemporalSNRParcels",
|
|
190
|
+
{"parcellation": "LostRegion"},
|
|
191
|
+
"tsnr",
|
|
192
|
+
[REGIONS],
|
|
193
|
+
),
|
|
194
|
+
# Computed with the edges with data
|
|
195
|
+
_case(
|
|
196
|
+
"RSSETSMarker",
|
|
197
|
+
{"parcellation": "LostRegion"},
|
|
198
|
+
"rss_ets",
|
|
199
|
+
[[False]] * 120,
|
|
200
|
+
),
|
|
201
|
+
*[
|
|
202
|
+
_case(
|
|
203
|
+
name, {"parcellation": "LostRegion"}, "complexity", [REGIONS]
|
|
204
|
+
)
|
|
205
|
+
for name in COMPLEXITY_MARKERS
|
|
206
|
+
],
|
|
207
|
+
# Only the kept region with itself
|
|
208
|
+
_case(
|
|
209
|
+
"FunctionalConnectivityParcels",
|
|
210
|
+
{"parcellation": "OneRegionLeft"},
|
|
211
|
+
"functional_connectivity",
|
|
212
|
+
[[False, True, True], [True, True, True], [True, True, True]],
|
|
213
|
+
),
|
|
214
|
+
# All the edges have a lost region
|
|
215
|
+
_case(
|
|
216
|
+
"EdgeCentricFCParcels",
|
|
217
|
+
{"parcellation": "OneRegionLeft"},
|
|
218
|
+
"functional_connectivity",
|
|
219
|
+
[[True] * 3] * 3,
|
|
220
|
+
),
|
|
221
|
+
# No edges with data
|
|
222
|
+
_case(
|
|
223
|
+
"RSSETSMarker",
|
|
224
|
+
{"parcellation": "OneRegionLeft"},
|
|
225
|
+
"rss_ets",
|
|
226
|
+
[[True]] * 120,
|
|
227
|
+
),
|
|
228
|
+
*[
|
|
229
|
+
_case(
|
|
230
|
+
name,
|
|
231
|
+
{"parcellation": "OneRegionLeft"},
|
|
232
|
+
"complexity",
|
|
233
|
+
[[False, True, True]],
|
|
234
|
+
)
|
|
235
|
+
for name in COMPLEXITY_MARKERS
|
|
236
|
+
],
|
|
237
|
+
],
|
|
238
|
+
)
|
|
239
|
+
def test_lost_regions(
|
|
240
|
+
tmp_path: Path,
|
|
241
|
+
element: dict,
|
|
242
|
+
name: str,
|
|
243
|
+
params: dict,
|
|
244
|
+
feature: str,
|
|
245
|
+
nan: list,
|
|
246
|
+
) -> None:
|
|
247
|
+
"""Test markers on regions lost in resampling.
|
|
248
|
+
|
|
249
|
+
The lost regions have no data (NaN), and the other regions are not
|
|
250
|
+
affected.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
tmp_path : pathlib.Path
|
|
255
|
+
The path to the test directory.
|
|
256
|
+
element : dict
|
|
257
|
+
The element data.
|
|
258
|
+
name : str
|
|
259
|
+
The parametrized name of the marker class.
|
|
260
|
+
params : dict
|
|
261
|
+
The parametrized parameters of the marker.
|
|
262
|
+
feature : str
|
|
263
|
+
The parametrized name of the feature to check.
|
|
264
|
+
nan : list
|
|
265
|
+
The parametrized values that are NaN.
|
|
266
|
+
|
|
267
|
+
"""
|
|
268
|
+
if name in COMPLEXITY_MARKERS:
|
|
269
|
+
from junifer.markers import complexity
|
|
270
|
+
|
|
271
|
+
marker = getattr(complexity, name)(**params)
|
|
272
|
+
else:
|
|
273
|
+
marker = getattr(markers, name)(**params)
|
|
274
|
+
WorkDirManager().workdir = tmp_path
|
|
275
|
+
with pytest.warns(RuntimeWarning, match=r"region\(s\) .* have no voxels"):
|
|
276
|
+
# Copy the data, as some markers change their input
|
|
277
|
+
out = marker.fit_transform({"BOLD": dict(element["BOLD"])})
|
|
278
|
+
data = np.asarray(out["BOLD"][feature]["data"], dtype=float)
|
|
279
|
+
assert np.array_equal(np.isnan(data), nan)
|
|
@@ -12,63 +12,67 @@ from numpy.testing import assert_array_almost_equal, assert_array_equal
|
|
|
12
12
|
|
|
13
13
|
from junifer.data import MapsRegistry, MaskRegistry
|
|
14
14
|
from junifer.data.masks import compute_brain_mask
|
|
15
|
-
from junifer.datagrabber import
|
|
15
|
+
from junifer.datagrabber import DataType
|
|
16
16
|
from junifer.datareader import DefaultDataReader
|
|
17
17
|
from junifer.markers import MapsAggregation
|
|
18
|
-
from junifer.storage import HDF5FeatureStorage
|
|
18
|
+
from junifer.storage import HDF5FeatureStorage, StorageType
|
|
19
|
+
from junifer.testing.datagrabbers import ADHDTestingDataGrabber
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
pytestmark = pytest.mark.external
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
@pytest.mark.parametrize(
|
|
22
26
|
"input_type, storage_type",
|
|
23
27
|
[
|
|
24
28
|
(
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
DataType.T1w,
|
|
30
|
+
StorageType.Vector,
|
|
27
31
|
),
|
|
28
32
|
(
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
DataType.T2w,
|
|
34
|
+
StorageType.Vector,
|
|
31
35
|
),
|
|
32
36
|
(
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
DataType.BOLD,
|
|
38
|
+
StorageType.Timeseries,
|
|
35
39
|
),
|
|
36
40
|
(
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
DataType.VBM_GM,
|
|
42
|
+
StorageType.Vector,
|
|
39
43
|
),
|
|
40
44
|
(
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
DataType.VBM_WM,
|
|
46
|
+
StorageType.Vector,
|
|
43
47
|
),
|
|
44
48
|
(
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
DataType.VBM_CSF,
|
|
50
|
+
StorageType.Vector,
|
|
47
51
|
),
|
|
48
52
|
(
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
DataType.FALFF,
|
|
54
|
+
StorageType.Vector,
|
|
51
55
|
),
|
|
52
56
|
(
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
DataType.GCOR,
|
|
58
|
+
StorageType.Vector,
|
|
55
59
|
),
|
|
56
60
|
(
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
DataType.LCOR,
|
|
62
|
+
StorageType.Vector,
|
|
59
63
|
),
|
|
60
64
|
],
|
|
61
65
|
)
|
|
62
66
|
def test_MapsAggregation_input_output(
|
|
63
|
-
input_type:
|
|
67
|
+
input_type: DataType, storage_type: StorageType
|
|
64
68
|
) -> None:
|
|
65
69
|
"""Test MapsAggregation input and output types.
|
|
66
70
|
|
|
67
71
|
Parameters
|
|
68
72
|
----------
|
|
69
|
-
input_type :
|
|
73
|
+
input_type : DataType
|
|
70
74
|
The parametrized input type.
|
|
71
|
-
storage_type :
|
|
75
|
+
storage_type : StorageType
|
|
72
76
|
The parametrized storage type.
|
|
73
77
|
|
|
74
78
|
"""
|
|
@@ -77,19 +81,10 @@ def test_MapsAggregation_input_output(
|
|
|
77
81
|
).storage_type(input_type=input_type, output_feature="aggregation")
|
|
78
82
|
|
|
79
83
|
|
|
80
|
-
def test_MapsAggregation_3D(
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
Parameters
|
|
86
|
-
----------
|
|
87
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
88
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
89
|
-
|
|
90
|
-
"""
|
|
91
|
-
with maps_datagrabber as dg:
|
|
92
|
-
element = dg[("sub-01", "sub-001", "rest", "1")]
|
|
84
|
+
def test_MapsAggregation_3D() -> None:
|
|
85
|
+
"""Test MapsAggregation on 3D data."""
|
|
86
|
+
with ADHDTestingDataGrabber() as dg:
|
|
87
|
+
element = dg["sub-01"]
|
|
93
88
|
element_data = DefaultDataReader().fit_transform(element)
|
|
94
89
|
# Deepcopy data for later use
|
|
95
90
|
input_data = deepcopy(element_data)
|
|
@@ -122,19 +117,10 @@ def test_MapsAggregation_3D(
|
|
|
122
117
|
assert_array_equal(nifti_maps_masked_bold, maps_agg_bold_data)
|
|
123
118
|
|
|
124
119
|
|
|
125
|
-
def test_MapsAggregation_4D(
|
|
126
|
-
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Parameters
|
|
131
|
-
----------
|
|
132
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
133
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
134
|
-
|
|
135
|
-
"""
|
|
136
|
-
with maps_datagrabber as dg:
|
|
137
|
-
element = dg[("sub-01", "sub-001", "rest", "1")]
|
|
120
|
+
def test_MapsAggregation_4D() -> None:
|
|
121
|
+
"""Test MapsAggregation on 4D data."""
|
|
122
|
+
with ADHDTestingDataGrabber() as dg:
|
|
123
|
+
element = dg["sub-01"]
|
|
138
124
|
element_data = DefaultDataReader().fit_transform(element)
|
|
139
125
|
# Deepcopy data for later use
|
|
140
126
|
input_data = deepcopy(element_data)
|
|
@@ -162,29 +148,25 @@ def test_MapsAggregation_4D(
|
|
|
162
148
|
assert_array_equal(nifti_maps_masked_bold, maps_agg_bold_data)
|
|
163
149
|
|
|
164
150
|
|
|
165
|
-
def test_MapsAggregation_storage(
|
|
166
|
-
maps_datagrabber: PatternDataladDataGrabber, tmp_path: Path
|
|
167
|
-
) -> None:
|
|
151
|
+
def test_MapsAggregation_storage(tmp_path: Path) -> None:
|
|
168
152
|
"""Test MapsAggregation storage.
|
|
169
153
|
|
|
170
154
|
Parameters
|
|
171
155
|
----------
|
|
172
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
173
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
174
156
|
tmp_path : pathlib.Path
|
|
175
157
|
The path to the test directory.
|
|
176
158
|
|
|
177
159
|
"""
|
|
178
160
|
# Store 3D
|
|
179
|
-
with
|
|
180
|
-
element = dg[
|
|
161
|
+
with ADHDTestingDataGrabber() as dg:
|
|
162
|
+
element = dg["sub-01"]
|
|
181
163
|
element_data = DefaultDataReader().fit_transform(element)
|
|
182
164
|
storage = HDF5FeatureStorage(
|
|
183
165
|
uri=tmp_path / "test_maps_storage_3D.hdf5"
|
|
184
166
|
)
|
|
185
167
|
marker = MapsAggregation(
|
|
186
168
|
maps="Smith_rsn_10",
|
|
187
|
-
on=
|
|
169
|
+
on=DataType.BOLD,
|
|
188
170
|
)
|
|
189
171
|
element_data["BOLD"]["data"] = element_data["BOLD"]["data"].slicer[
|
|
190
172
|
..., 0:1
|
|
@@ -197,15 +179,15 @@ def test_MapsAggregation_storage(
|
|
|
197
179
|
)
|
|
198
180
|
|
|
199
181
|
# Store 4D
|
|
200
|
-
with
|
|
201
|
-
element = dg[
|
|
182
|
+
with ADHDTestingDataGrabber() as dg:
|
|
183
|
+
element = dg["sub-01"]
|
|
202
184
|
element_data = DefaultDataReader().fit_transform(element)
|
|
203
185
|
storage = HDF5FeatureStorage(
|
|
204
|
-
uri=tmp_path / "test_maps_storage_4D.
|
|
186
|
+
uri=tmp_path / "test_maps_storage_4D.hdf5"
|
|
205
187
|
)
|
|
206
188
|
marker = MapsAggregation(
|
|
207
189
|
maps="Smith_rsn_10",
|
|
208
|
-
on=
|
|
190
|
+
on=DataType.BOLD,
|
|
209
191
|
)
|
|
210
192
|
marker.fit_transform(input=element_data, storage=storage)
|
|
211
193
|
features = storage.list_features()
|
|
@@ -215,19 +197,10 @@ def test_MapsAggregation_storage(
|
|
|
215
197
|
)
|
|
216
198
|
|
|
217
199
|
|
|
218
|
-
def test_MapsAggregation_3D_mask(
|
|
219
|
-
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
Parameters
|
|
224
|
-
----------
|
|
225
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
226
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
227
|
-
|
|
228
|
-
"""
|
|
229
|
-
with maps_datagrabber as dg:
|
|
230
|
-
element = dg[("sub-01", "sub-001", "rest", "1")]
|
|
200
|
+
def test_MapsAggregation_3D_mask() -> None:
|
|
201
|
+
"""Test MapsAggregation on 3D data with mask."""
|
|
202
|
+
with ADHDTestingDataGrabber() as dg:
|
|
203
|
+
element = dg["sub-01"]
|
|
231
204
|
element_data = DefaultDataReader().fit_transform(element)
|
|
232
205
|
# Deepcopy data for later use
|
|
233
206
|
input_data = deepcopy(element_data)
|
|
@@ -238,8 +211,8 @@ def test_MapsAggregation_3D_mask(
|
|
|
238
211
|
]
|
|
239
212
|
marker = MapsAggregation(
|
|
240
213
|
maps="Smith_rsn_10",
|
|
241
|
-
on=
|
|
242
|
-
masks="compute_brain_mask",
|
|
214
|
+
on=DataType.BOLD,
|
|
215
|
+
masks=["compute_brain_mask"],
|
|
243
216
|
)
|
|
244
217
|
maps_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
|
|
245
218
|
"aggregation"
|
|
@@ -268,19 +241,10 @@ def test_MapsAggregation_3D_mask(
|
|
|
268
241
|
assert_array_equal(nifti_maps_masked_bold, maps_agg_bold_data)
|
|
269
242
|
|
|
270
243
|
|
|
271
|
-
def test_MapsAggregation_3D_mask_computed(
|
|
272
|
-
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
Parameters
|
|
277
|
-
----------
|
|
278
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
279
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
280
|
-
|
|
281
|
-
"""
|
|
282
|
-
with maps_datagrabber as dg:
|
|
283
|
-
element = dg[("sub-01", "sub-001", "rest", "1")]
|
|
244
|
+
def test_MapsAggregation_3D_mask_computed() -> None:
|
|
245
|
+
"""Test MapsAggregation on 3D data with computed masks."""
|
|
246
|
+
with ADHDTestingDataGrabber() as dg:
|
|
247
|
+
element = dg["sub-01"]
|
|
284
248
|
element_data = DefaultDataReader().fit_transform(element)
|
|
285
249
|
|
|
286
250
|
# Compare with nilearn
|
|
@@ -306,8 +270,8 @@ def test_MapsAggregation_3D_mask_computed(
|
|
|
306
270
|
# Use the MapsAggregation object
|
|
307
271
|
marker = MapsAggregation(
|
|
308
272
|
maps="Smith_rsn_10",
|
|
309
|
-
masks={"compute_brain_mask": {"threshold": 0.2}},
|
|
310
|
-
on=
|
|
273
|
+
masks=[{"compute_brain_mask": {"threshold": 0.2}}],
|
|
274
|
+
on=DataType.BOLD,
|
|
311
275
|
)
|
|
312
276
|
maps_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
|
|
313
277
|
"aggregation"
|
|
@@ -324,25 +288,16 @@ def test_MapsAggregation_3D_mask_computed(
|
|
|
324
288
|
)
|
|
325
289
|
|
|
326
290
|
|
|
327
|
-
def test_MapsAggregation_4D_agg_time(
|
|
328
|
-
|
|
329
|
-
):
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
Parameters
|
|
333
|
-
----------
|
|
334
|
-
maps_datagrabber : PatternDataladDataGrabber
|
|
335
|
-
The testing PatternDataladDataGrabber, as fixture.
|
|
336
|
-
|
|
337
|
-
"""
|
|
338
|
-
with maps_datagrabber as dg:
|
|
339
|
-
element = dg[("sub-01", "sub-001", "rest", "1")]
|
|
291
|
+
def test_MapsAggregation_4D_agg_time() -> None:
|
|
292
|
+
"""Test MapsAggregation on 4D data, aggregating time."""
|
|
293
|
+
with ADHDTestingDataGrabber() as dg:
|
|
294
|
+
element = dg["sub-01"]
|
|
340
295
|
element_data = DefaultDataReader().fit_transform(element)
|
|
341
296
|
# Create MapsAggregation object
|
|
342
297
|
marker = MapsAggregation(
|
|
343
298
|
maps="Smith_rsn_10",
|
|
344
299
|
time_method="mean",
|
|
345
|
-
on=
|
|
300
|
+
on=DataType.BOLD,
|
|
346
301
|
)
|
|
347
302
|
maps_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
|
|
348
303
|
"aggregation"
|
|
@@ -375,7 +330,7 @@ def test_MapsAggregation_4D_agg_time(
|
|
|
375
330
|
maps="Smith_rsn_10",
|
|
376
331
|
time_method="select",
|
|
377
332
|
time_method_params={"pick": [0]},
|
|
378
|
-
on=
|
|
333
|
+
on=DataType.BOLD,
|
|
379
334
|
)
|
|
380
335
|
maps_agg_bold_data = marker.fit_transform(element_data)["BOLD"][
|
|
381
336
|
"aggregation"
|
|
@@ -395,7 +350,7 @@ def test_MapsAggregation_errors() -> None:
|
|
|
395
350
|
maps="Smith_rsn_10",
|
|
396
351
|
time_method="select",
|
|
397
352
|
time_method_params={"pick": [0]},
|
|
398
|
-
on=
|
|
353
|
+
on=[DataType.VBM_GM],
|
|
399
354
|
)
|
|
400
355
|
|
|
401
356
|
with pytest.raises(
|
|
@@ -404,16 +359,14 @@ def test_MapsAggregation_errors() -> None:
|
|
|
404
359
|
MapsAggregation(
|
|
405
360
|
maps="Smith_rsn_10",
|
|
406
361
|
time_method_params={"pick": [0]},
|
|
407
|
-
on=
|
|
362
|
+
on=[DataType.VBM_GM],
|
|
408
363
|
)
|
|
409
364
|
|
|
410
365
|
|
|
411
|
-
def test_MapsAggregation_warning(
|
|
412
|
-
maps_datagrabber: PatternDataladDataGrabber,
|
|
413
|
-
) -> None:
|
|
366
|
+
def test_MapsAggregation_warning() -> None:
|
|
414
367
|
"""Test warning for MapsAggregation."""
|
|
415
|
-
with
|
|
416
|
-
element = dg[
|
|
368
|
+
with ADHDTestingDataGrabber() as dg:
|
|
369
|
+
element = dg["sub-01"]
|
|
417
370
|
element_data = DefaultDataReader().fit_transform(element)
|
|
418
371
|
with pytest.warns(
|
|
419
372
|
RuntimeWarning, match="No time dimension to aggregate"
|
|
@@ -422,7 +375,7 @@ def test_MapsAggregation_warning(
|
|
|
422
375
|
maps="Smith_rsn_10",
|
|
423
376
|
time_method="select",
|
|
424
377
|
time_method_params={"pick": [0]},
|
|
425
|
-
on=
|
|
378
|
+
on=DataType.BOLD,
|
|
426
379
|
)
|
|
427
380
|
element_data["BOLD"]["data"] = element_data["BOLD"]["data"].slicer[
|
|
428
381
|
..., 0:1
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
7
7
|
# License: AGPL
|
|
8
8
|
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import nibabel as nib
|
|
9
12
|
import numpy as np
|
|
10
13
|
import pytest
|
|
11
14
|
|
|
12
|
-
from junifer.markers.utils import _ets
|
|
15
|
+
from junifer.markers.utils import _ets, _save_mask
|
|
16
|
+
from junifer.pipeline import WorkDirManager
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
def test_ets() -> None:
|
|
@@ -48,3 +52,38 @@ def test_ets_incorrect_label_list() -> None:
|
|
|
48
52
|
ValueError, match="List of roi names does not correspond"
|
|
49
53
|
):
|
|
50
54
|
_ets(bold_ts, roi_labels)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_save_mask(tmp_path: Path) -> None:
|
|
58
|
+
"""Test saving masks in the element directory, named by their content.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
tmp_path : pathlib.Path
|
|
63
|
+
The path to the test directory.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
workdir_mgr = WorkDirManager()
|
|
67
|
+
workdir_mgr.workdir = tmp_path
|
|
68
|
+
data = np.zeros((3, 4, 5), dtype=np.int8)
|
|
69
|
+
data[1, 1:3, 2:4] = 1
|
|
70
|
+
mask = nib.Nifti1Image(data, np.eye(4))
|
|
71
|
+
path = _save_mask(mask, prefix="test_mask")
|
|
72
|
+
# In the element directory, with the voxels in the mask
|
|
73
|
+
assert path.parent == workdir_mgr.elementdir
|
|
74
|
+
assert path.name.startswith("test_mask_")
|
|
75
|
+
assert np.array_equal(np.asarray(nib.load(path).dataobj), data)
|
|
76
|
+
# The same mask (another image) has the same path, a different one not
|
|
77
|
+
assert (
|
|
78
|
+
_save_mask(nib.Nifti1Image(data.copy(), np.eye(4)), prefix="test_mask")
|
|
79
|
+
== path
|
|
80
|
+
)
|
|
81
|
+
other = data.copy()
|
|
82
|
+
other[0, 0, 0] = 1
|
|
83
|
+
assert (
|
|
84
|
+
_save_mask(nib.Nifti1Image(other, np.eye(4)), prefix="test_mask")
|
|
85
|
+
!= path
|
|
86
|
+
)
|
|
87
|
+
# Deleted with the element directory
|
|
88
|
+
workdir_mgr.cleanup_elementdir()
|
|
89
|
+
assert not path.exists()
|