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
junifer/markers/ets_rss.py
CHANGED
|
@@ -6,16 +6,19 @@
|
|
|
6
6
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
7
7
|
# License: AGPL
|
|
8
8
|
|
|
9
|
-
from typing import Any, ClassVar
|
|
9
|
+
from typing import Annotated, Any, ClassVar
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
|
+
from pydantic import BeforeValidator
|
|
12
13
|
|
|
13
14
|
from ..api.decorators import register_marker
|
|
15
|
+
from ..datagrabber import DataType
|
|
16
|
+
from ..storage import StorageType
|
|
14
17
|
from ..typing import Dependencies, MarkerInOutMappings
|
|
15
|
-
from ..utils import
|
|
16
|
-
from .base import BaseMarker
|
|
18
|
+
from ..utils import ensure_list, ensure_list_or_none
|
|
19
|
+
from .base import BaseMarker, logger
|
|
17
20
|
from .parcel_aggregation import ParcelAggregation
|
|
18
|
-
from .utils import _ets
|
|
21
|
+
from .utils import _ets, _has_data
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
__all__ = ["RSSETSMarker"]
|
|
@@ -31,47 +34,42 @@ class RSSETSMarker(BaseMarker):
|
|
|
31
34
|
The name(s) of the parcellation(s) to use.
|
|
32
35
|
See :func:`.list_data` for options.
|
|
33
36
|
agg_method : str, optional
|
|
34
|
-
The
|
|
35
|
-
:func:`.get_aggfunc_by_name`
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
The aggregation function to use.
|
|
38
|
+
See :func:`.get_aggfunc_by_name` for options
|
|
39
|
+
(default "mean").
|
|
40
|
+
agg_method_params : dict or None, optional
|
|
41
|
+
The parameters to pass to the aggregation function.
|
|
42
|
+
See :func:`.get_aggfunc_by_name` for options (default None).
|
|
43
|
+
masks : str, dict, list of them or None, optional
|
|
40
44
|
The specification of the masks to apply to regions before extracting
|
|
41
45
|
signals. Check :ref:`Using Masks <using_masks>` for more details.
|
|
42
46
|
If None, will not apply any mask (default None).
|
|
43
|
-
name : str, optional
|
|
44
|
-
The name of the marker.
|
|
45
|
-
None).
|
|
47
|
+
name : str or None, optional
|
|
48
|
+
The name of the marker.
|
|
49
|
+
If None, will use the class name (default None).
|
|
46
50
|
|
|
47
51
|
"""
|
|
48
52
|
|
|
49
53
|
_DEPENDENCIES: ClassVar[Dependencies] = {"nilearn"}
|
|
50
54
|
|
|
51
55
|
_MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
|
|
52
|
-
|
|
53
|
-
"rss_ets":
|
|
56
|
+
DataType.BOLD: {
|
|
57
|
+
"rss_ets": StorageType.Timeseries,
|
|
54
58
|
},
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
) -> None:
|
|
65
|
-
self.parcellation = parcellation
|
|
66
|
-
self.agg_method = agg_method
|
|
67
|
-
self.agg_method_params = agg_method_params
|
|
68
|
-
self.masks = masks
|
|
69
|
-
super().__init__(name=name)
|
|
61
|
+
parcellation: Annotated[str | list[str], BeforeValidator(ensure_list)]
|
|
62
|
+
agg_method: str = "mean"
|
|
63
|
+
agg_method_params: dict | None = None
|
|
64
|
+
masks: Annotated[
|
|
65
|
+
dict | str | list[dict | str] | None,
|
|
66
|
+
BeforeValidator(ensure_list_or_none),
|
|
67
|
+
] = None
|
|
70
68
|
|
|
71
69
|
def compute(
|
|
72
70
|
self,
|
|
73
71
|
input: dict[str, Any],
|
|
74
|
-
extra_input:
|
|
72
|
+
extra_input: dict | None = None,
|
|
75
73
|
) -> dict:
|
|
76
74
|
"""Compute.
|
|
77
75
|
|
|
@@ -110,12 +108,18 @@ class RSSETSMarker(BaseMarker):
|
|
|
110
108
|
parcellation=self.parcellation,
|
|
111
109
|
method=self.agg_method,
|
|
112
110
|
method_params=self.agg_method_params,
|
|
111
|
+
on=DataType.BOLD,
|
|
113
112
|
masks=self.masks,
|
|
114
113
|
).compute(input=input, extra_input=extra_input)
|
|
115
114
|
# Compute edgewise timeseries
|
|
116
115
|
edge_ts, _ = _ets(aggregation["aggregation"]["data"])
|
|
117
|
-
# Compute the RSS of edgewise timeseries
|
|
118
|
-
|
|
116
|
+
# Compute the RSS of edgewise timeseries, only using the edges with
|
|
117
|
+
# data (e.g. regions lost in resampling have none)
|
|
118
|
+
edge_ts = edge_ts[:, _has_data(edge_ts)]
|
|
119
|
+
if edge_ts.shape[1] > 0:
|
|
120
|
+
rss = np.sum(edge_ts**2, 1) ** 0.5
|
|
121
|
+
else:
|
|
122
|
+
rss = np.full(edge_ts.shape[0], np.nan)
|
|
119
123
|
|
|
120
124
|
return {
|
|
121
125
|
"rss_ets": {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
__all__ = [
|
|
1
|
+
__all__ = [
|
|
2
|
+
"ALFFImpl",
|
|
3
|
+
"ALFFMaps",
|
|
4
|
+
"ALFFParcels",
|
|
5
|
+
"ALFFSpheres",
|
|
6
|
+
]
|
|
2
7
|
|
|
8
|
+
from .falff_base import ALFFImpl
|
|
3
9
|
from .falff_maps import ALFFMaps
|
|
4
10
|
from .falff_parcels import ALFFParcels
|
|
5
11
|
from .falff_spheres import ALFFSpheres
|
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
+
import atexit
|
|
6
7
|
from functools import lru_cache
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from typing import (
|
|
9
10
|
TYPE_CHECKING,
|
|
10
11
|
ClassVar,
|
|
11
|
-
Optional,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
import nibabel as nib
|
|
15
15
|
|
|
16
|
-
from ...pipeline import WorkDirManager
|
|
16
|
+
from ...pipeline import ExtDep, WorkDirManager
|
|
17
17
|
from ...typing import ExternalDependencies
|
|
18
|
-
from ...utils import
|
|
18
|
+
from ...utils import run_ext_cmd
|
|
19
19
|
from ...utils.singleton import Singleton
|
|
20
|
+
from ..base import logger
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
if TYPE_CHECKING:
|
|
@@ -36,13 +37,15 @@ class AFNIALFF(metaclass=Singleton):
|
|
|
36
37
|
|
|
37
38
|
_EXT_DEPENDENCIES: ClassVar[ExternalDependencies] = [
|
|
38
39
|
{
|
|
39
|
-
"name":
|
|
40
|
+
"name": ExtDep.AFNI,
|
|
40
41
|
"commands": ["3dRSFC", "3dAFNItoNIFTI"],
|
|
41
42
|
},
|
|
42
43
|
]
|
|
43
44
|
|
|
44
|
-
def
|
|
45
|
-
|
|
45
|
+
def __init__(self) -> None:
|
|
46
|
+
atexit.register(self._del)
|
|
47
|
+
|
|
48
|
+
def _del(self) -> None:
|
|
46
49
|
# Clear the computation cache
|
|
47
50
|
logger.debug("Clearing cache for ALFF computation via AFNI")
|
|
48
51
|
self.compute.cache_clear()
|
|
@@ -53,7 +56,8 @@ class AFNIALFF(metaclass=Singleton):
|
|
|
53
56
|
input_path: Path,
|
|
54
57
|
highpass: float,
|
|
55
58
|
lowpass: float,
|
|
56
|
-
tr:
|
|
59
|
+
tr: float | None,
|
|
60
|
+
mask_path: Path | None = None,
|
|
57
61
|
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
|
58
62
|
"""Compute ALFF + fALFF map.
|
|
59
63
|
|
|
@@ -67,6 +71,10 @@ class AFNIALFF(metaclass=Singleton):
|
|
|
67
71
|
Lowpass cutoff frequency.
|
|
68
72
|
tr : positive float, optional
|
|
69
73
|
The Repetition Time of the BOLD data.
|
|
74
|
+
mask_path : pathlib.Path, optional
|
|
75
|
+
Path to the mask to restrict the computation to. The voxels
|
|
76
|
+
outside the mask are set to 0. If None, all the voxels are used
|
|
77
|
+
(default None).
|
|
70
78
|
|
|
71
79
|
Returns
|
|
72
80
|
-------
|
|
@@ -87,18 +95,23 @@ class AFNIALFF(metaclass=Singleton):
|
|
|
87
95
|
prefix="afni_lff"
|
|
88
96
|
)
|
|
89
97
|
|
|
90
|
-
# Set 3dRSFC command
|
|
98
|
+
# Set 3dRSFC command; only the parameters are needed, not the
|
|
99
|
+
# bandpassed time series (-no_rs_out)
|
|
91
100
|
lff_out_path_prefix = element_tempdir / "output"
|
|
92
101
|
bp_cmd = [
|
|
93
102
|
"3dRSFC",
|
|
94
103
|
f"-prefix {lff_out_path_prefix.resolve()}",
|
|
95
104
|
f"-input {input_path.resolve()}",
|
|
96
105
|
f"-band {highpass} {lowpass}",
|
|
97
|
-
"-no_rsfa -nosat -nodetrend",
|
|
106
|
+
"-no_rsfa -nosat -nodetrend -no_rs_out",
|
|
98
107
|
]
|
|
99
108
|
# Check tr
|
|
100
109
|
if tr is not None:
|
|
101
110
|
bp_cmd.append(f"-dt {tr}")
|
|
111
|
+
# Restrict the computation to the mask, which reduces the memory and
|
|
112
|
+
# time used by 3dRSFC
|
|
113
|
+
if mask_path is not None:
|
|
114
|
+
bp_cmd.append(f"-mask {mask_path.resolve()}")
|
|
102
115
|
# Call 3dRSFC
|
|
103
116
|
run_ext_cmd(name="3dRSFC", cmd=bp_cmd)
|
|
104
117
|
|
|
@@ -8,7 +8,6 @@ from pathlib import Path
|
|
|
8
8
|
from typing import (
|
|
9
9
|
TYPE_CHECKING,
|
|
10
10
|
ClassVar,
|
|
11
|
-
Optional,
|
|
12
11
|
)
|
|
13
12
|
|
|
14
13
|
import nibabel as nib
|
|
@@ -18,8 +17,8 @@ from nilearn import image as nimg
|
|
|
18
17
|
|
|
19
18
|
from ...pipeline import WorkDirManager
|
|
20
19
|
from ...typing import Dependencies
|
|
21
|
-
from ...utils import logger
|
|
22
20
|
from ...utils.singleton import Singleton
|
|
21
|
+
from ..base import logger
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
@@ -50,7 +49,8 @@ class JuniferALFF(metaclass=Singleton):
|
|
|
50
49
|
input_path: Path,
|
|
51
50
|
highpass: float,
|
|
52
51
|
lowpass: float,
|
|
53
|
-
tr:
|
|
52
|
+
tr: float | None,
|
|
53
|
+
mask_path: Path | None = None,
|
|
54
54
|
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
|
55
55
|
"""Compute ALFF + fALFF map.
|
|
56
56
|
|
|
@@ -64,6 +64,10 @@ class JuniferALFF(metaclass=Singleton):
|
|
|
64
64
|
Lowpass cutoff frequency.
|
|
65
65
|
tr : positive float, optional
|
|
66
66
|
The Repetition Time of the BOLD data.
|
|
67
|
+
mask_path : pathlib.Path, optional
|
|
68
|
+
Path to the mask to restrict the computation to. The voxels
|
|
69
|
+
outside the mask are set to 0. If None, all the voxels are used
|
|
70
|
+
(default None).
|
|
67
71
|
|
|
68
72
|
Returns
|
|
69
73
|
-------
|
|
@@ -79,47 +83,59 @@ class JuniferALFF(metaclass=Singleton):
|
|
|
79
83
|
"""
|
|
80
84
|
logger.debug("Creating cache for ALFF computation via junifer")
|
|
81
85
|
|
|
82
|
-
# Get scan data
|
|
86
|
+
# Get scan data (no extra copy, don't keep nibabel's cached copy)
|
|
83
87
|
niimg = nib.load(input_path)
|
|
84
|
-
niimg_data = niimg.get_fdata()
|
|
88
|
+
niimg_data = niimg.get_fdata(caching="unchanged")
|
|
85
89
|
if tr is None:
|
|
86
90
|
tr = float(niimg.header["pixdim"][4]) # type: ignore
|
|
87
91
|
logger.info(f"`tr` not provided, using `tr` from header: {tr}")
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
n_timepoints = niimg_data.shape[-1]
|
|
94
|
+
# One-sided spectrum of a real signal; weights reproduce the
|
|
95
|
+
# two-sided sums (each non-zero bin appears twice, Nyquist once)
|
|
96
|
+
fft_freqs = sp.fft.rfftfreq(n_timepoints, tr)
|
|
97
|
+
weights = np.full(fft_freqs.shape, 2.0)
|
|
98
|
+
weights[0] = 0.0 # exclude DC
|
|
99
|
+
if n_timepoints % 2 == 0:
|
|
100
|
+
weights[-1] = 1.0 # Nyquist bin appears only once
|
|
101
|
+
band_weights = np.where(
|
|
102
|
+
(fft_freqs > highpass) & (fft_freqs < lowpass), weights, 0.0
|
|
103
|
+
)
|
|
98
104
|
logger.info(
|
|
99
|
-
f"FFT: nfft = {
|
|
100
|
-
f"
|
|
105
|
+
f"FFT: nfft = {n_timepoints}, "
|
|
106
|
+
f"dFreq = {fft_freqs[1] - fft_freqs[0]}, "
|
|
107
|
+
f"nyquist = {fft_freqs[-1]}"
|
|
101
108
|
)
|
|
102
109
|
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
numerator = np.
|
|
110
|
+
# Process voxels (only the ones in the mask, if any) in chunks to
|
|
111
|
+
# bound FFT memory
|
|
112
|
+
flat = niimg_data.reshape(-1, n_timepoints)
|
|
113
|
+
if mask_path is not None:
|
|
114
|
+
mask_data = np.squeeze(np.asarray(nib.load(mask_path).dataobj))
|
|
115
|
+
voxels = np.flatnonzero(mask_data.reshape(-1) != 0)
|
|
116
|
+
else:
|
|
117
|
+
voxels = np.arange(flat.shape[0])
|
|
118
|
+
numerator = np.zeros(flat.shape[0])
|
|
119
|
+
denominator = np.zeros(flat.shape[0])
|
|
120
|
+
chunk = 20_000
|
|
121
|
+
for start in range(0, len(voxels), chunk):
|
|
122
|
+
t_voxels = voxels[start : start + chunk]
|
|
123
|
+
amp = np.abs(sp.fft.rfft(flat[t_voxels], axis=-1))
|
|
124
|
+
denominator[t_voxels] = amp @ weights
|
|
125
|
+
numerator[t_voxels] = amp @ band_weights
|
|
126
|
+
spatial_shape = niimg_data.shape[:-1]
|
|
127
|
+
numerator = numerator.reshape(spatial_shape)
|
|
128
|
+
denominator = denominator.reshape(spatial_shape)
|
|
129
|
+
del niimg_data, flat
|
|
112
130
|
|
|
113
131
|
# Compute fALFF, but avoid division by zero
|
|
114
132
|
denom_mask = denominator <= 0.000001
|
|
115
|
-
denominator[denom_mask] = 1
|
|
116
|
-
# Calculate fALFF
|
|
133
|
+
denominator[denom_mask] = 1
|
|
117
134
|
falff = np.divide(numerator, denominator)
|
|
118
|
-
# Set the values where denominator is zero to zero
|
|
119
135
|
falff[denom_mask] = 0
|
|
120
136
|
|
|
121
137
|
# Calculate ALFF
|
|
122
|
-
alff = numerator / np.sqrt(
|
|
138
|
+
alff = numerator / np.sqrt(n_timepoints)
|
|
123
139
|
alff_data = nimg.new_img_like(
|
|
124
140
|
ref_niimg=niimg,
|
|
125
141
|
data=alff,
|
|
@@ -133,8 +149,8 @@ class JuniferALFF(metaclass=Singleton):
|
|
|
133
149
|
element_tempdir = WorkDirManager().get_element_tempdir(
|
|
134
150
|
prefix="junifer_lff"
|
|
135
151
|
)
|
|
136
|
-
output_alff_path = element_tempdir / "output_alff.nii
|
|
137
|
-
output_falff_path = element_tempdir / "output_falff.nii
|
|
152
|
+
output_alff_path = element_tempdir / "output_alff.nii"
|
|
153
|
+
output_falff_path = element_tempdir / "output_falff.nii"
|
|
138
154
|
# Save computed data to file
|
|
139
155
|
nib.save(alff_data, output_alff_path)
|
|
140
156
|
nib.save(falff_data, output_falff_path)
|
|
@@ -6,17 +6,24 @@
|
|
|
6
6
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
7
7
|
# License: AGPL
|
|
8
8
|
|
|
9
|
+
from enum import StrEnum
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import (
|
|
11
12
|
TYPE_CHECKING,
|
|
13
|
+
Annotated,
|
|
12
14
|
Any,
|
|
13
15
|
ClassVar,
|
|
14
|
-
Optional,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
from pydantic import BeforeValidator, PositiveFloat
|
|
19
|
+
|
|
20
|
+
from ...data import get_data
|
|
21
|
+
from ...datagrabber import DataType
|
|
22
|
+
from ...storage import StorageType
|
|
17
23
|
from ...typing import ConditionalDependencies, MarkerInOutMappings
|
|
18
|
-
from ...utils
|
|
19
|
-
from ..base import BaseMarker
|
|
24
|
+
from ...utils import ensure_list_or_none
|
|
25
|
+
from ..base import BaseMarker, logger
|
|
26
|
+
from ..utils import _save_mask
|
|
20
27
|
from ._afni_falff import AFNIALFF
|
|
21
28
|
from ._junifer_falff import JuniferALFF
|
|
22
29
|
|
|
@@ -25,7 +32,19 @@ if TYPE_CHECKING:
|
|
|
25
32
|
from nibabel.nifti1 import Nifti1Image
|
|
26
33
|
|
|
27
34
|
|
|
28
|
-
__all__ = ["ALFFBase"]
|
|
35
|
+
__all__ = ["ALFFBase", "ALFFImpl"]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ALFFImpl(StrEnum):
|
|
39
|
+
"""Accepted ALFF implementations.
|
|
40
|
+
|
|
41
|
+
* ``junifer`` : ``junifer``'s ALFF
|
|
42
|
+
* ``afni`` : AFNI's ``3dRSFC``
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
junifer = "junifer"
|
|
47
|
+
afni = "afni"
|
|
29
48
|
|
|
30
49
|
|
|
31
50
|
class ALFFBase(BaseMarker):
|
|
@@ -33,22 +52,30 @@ class ALFFBase(BaseMarker):
|
|
|
33
52
|
|
|
34
53
|
Parameters
|
|
35
54
|
----------
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Implementation to use for computing ALFF:
|
|
42
|
-
|
|
43
|
-
* "junifer" : Use ``junifer``'s own ALFF implementation
|
|
44
|
-
* "afni" : Use AFNI's ``3dRSFC``
|
|
45
|
-
|
|
55
|
+
using : :enum:`.ALFFImpl`
|
|
56
|
+
highpass : positive float, optional
|
|
57
|
+
Highpass cutoff frequency (default 0.01).
|
|
58
|
+
lowpass : positive float, optional
|
|
59
|
+
Lowpass cutoff frequency (default 0.1).
|
|
46
60
|
tr : positive float, optional
|
|
47
|
-
The
|
|
48
|
-
the TR from NIfTI header (default None).
|
|
49
|
-
|
|
50
|
-
The
|
|
51
|
-
|
|
61
|
+
The repetition time of the BOLD data.
|
|
62
|
+
If None, will extract the TR from NIfTI header (default None).
|
|
63
|
+
agg_method : str, optional
|
|
64
|
+
The aggregation function to use.
|
|
65
|
+
See :func:`.get_aggfunc_by_name` for options
|
|
66
|
+
(default "mean").
|
|
67
|
+
agg_method_params : dict or None, optional
|
|
68
|
+
The parameters to pass to the aggregation function.
|
|
69
|
+
See :func:`.get_aggfunc_by_name` for options (default None).
|
|
70
|
+
masks : str, dict, list of them or None, optional
|
|
71
|
+
The specification of the masks to apply. The ALFF and fALFF
|
|
72
|
+
computation is restricted to the voxels in the mask, and the mask is
|
|
73
|
+
also applied to regions before extracting signals. Check
|
|
74
|
+
:ref:`Using Masks <using_masks>` for more details.
|
|
75
|
+
If None, will not apply any mask (default None).
|
|
76
|
+
name : str or None, optional
|
|
77
|
+
The name of the marker.
|
|
78
|
+
If None, it will use the class name (default None).
|
|
52
79
|
|
|
53
80
|
Notes
|
|
54
81
|
-----
|
|
@@ -58,63 +85,41 @@ class ALFFBase(BaseMarker):
|
|
|
58
85
|
reported that some preprocessed data might not have the correct ``tr`` in
|
|
59
86
|
the NIfTI header.
|
|
60
87
|
|
|
61
|
-
Raises
|
|
62
|
-
------
|
|
63
|
-
ValueError
|
|
64
|
-
If ``highpass`` is not positive or zero or
|
|
65
|
-
if ``lowpass`` is not positive or
|
|
66
|
-
if ``highpass`` is higher than ``lowpass`` or
|
|
67
|
-
if ``using`` is invalid.
|
|
68
|
-
|
|
69
88
|
"""
|
|
70
89
|
|
|
71
90
|
_CONDITIONAL_DEPENDENCIES: ClassVar[ConditionalDependencies] = [
|
|
72
91
|
{
|
|
73
|
-
"using":
|
|
74
|
-
"depends_on": AFNIALFF,
|
|
92
|
+
"using": ALFFImpl.afni,
|
|
93
|
+
"depends_on": [AFNIALFF],
|
|
75
94
|
},
|
|
76
95
|
{
|
|
77
|
-
"using":
|
|
78
|
-
"depends_on": JuniferALFF,
|
|
96
|
+
"using": ALFFImpl.junifer,
|
|
97
|
+
"depends_on": [JuniferALFF],
|
|
79
98
|
},
|
|
80
99
|
]
|
|
81
100
|
|
|
82
101
|
_MARKER_INOUT_MAPPINGS: ClassVar[MarkerInOutMappings] = {
|
|
83
|
-
|
|
84
|
-
"alff":
|
|
85
|
-
"falff":
|
|
102
|
+
DataType.BOLD: {
|
|
103
|
+
"alff": StorageType.Vector,
|
|
104
|
+
"falff": StorageType.Vector,
|
|
86
105
|
},
|
|
87
106
|
}
|
|
88
107
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if lowpass <= 0:
|
|
100
|
-
raise_error("Lowpass must be positive")
|
|
101
|
-
if highpass >= lowpass:
|
|
102
|
-
raise_error("Highpass must be lower than lowpass")
|
|
103
|
-
self.highpass = highpass
|
|
104
|
-
self.lowpass = lowpass
|
|
105
|
-
# Validate `using` parameter
|
|
106
|
-
valid_using = [dep["using"] for dep in self._CONDITIONAL_DEPENDENCIES]
|
|
107
|
-
if using not in valid_using:
|
|
108
|
-
raise_error(
|
|
109
|
-
f"Invalid value for `using`, should be one of: {valid_using}"
|
|
110
|
-
)
|
|
111
|
-
self.using = using
|
|
112
|
-
self.tr = tr
|
|
113
|
-
super().__init__(on="BOLD", name=name)
|
|
108
|
+
using: ALFFImpl
|
|
109
|
+
highpass: PositiveFloat = 0.01
|
|
110
|
+
lowpass: PositiveFloat = 0.1
|
|
111
|
+
tr: PositiveFloat | None = None
|
|
112
|
+
agg_method: str = "mean"
|
|
113
|
+
agg_method_params: dict | None = None
|
|
114
|
+
masks: Annotated[
|
|
115
|
+
dict | str | list[dict | str] | None,
|
|
116
|
+
BeforeValidator(ensure_list_or_none),
|
|
117
|
+
] = None
|
|
114
118
|
|
|
115
119
|
def _compute(
|
|
116
120
|
self,
|
|
117
121
|
input_data: dict[str, Any],
|
|
122
|
+
extra_input: dict[str, Any] | None = None,
|
|
118
123
|
) -> tuple["Nifti1Image", "Nifti1Image", Path, Path]:
|
|
119
124
|
"""Compute ALFF and fALFF.
|
|
120
125
|
|
|
@@ -123,7 +128,8 @@ class ALFFBase(BaseMarker):
|
|
|
123
128
|
input_data : dict
|
|
124
129
|
The input to the marker.
|
|
125
130
|
extra_input : dict, optional
|
|
126
|
-
The other fields in the pipeline data object
|
|
131
|
+
The other fields in the pipeline data object. Used to compute
|
|
132
|
+
the mask in the space of ``input_data`` (default None).
|
|
127
133
|
|
|
128
134
|
Returns
|
|
129
135
|
-------
|
|
@@ -144,12 +150,26 @@ class ALFFBase(BaseMarker):
|
|
|
144
150
|
estimator = AFNIALFF()
|
|
145
151
|
elif self.using == "junifer":
|
|
146
152
|
estimator = JuniferALFF()
|
|
153
|
+
# Get mask in the space of the input data
|
|
154
|
+
mask_path = None
|
|
155
|
+
if self.masks is not None:
|
|
156
|
+
logger.debug(f"Masking with {self.masks}")
|
|
157
|
+
mask_path = _save_mask(
|
|
158
|
+
get_data(
|
|
159
|
+
kind="mask",
|
|
160
|
+
names=self.masks,
|
|
161
|
+
target_data=input_data,
|
|
162
|
+
extra_input=extra_input,
|
|
163
|
+
),
|
|
164
|
+
prefix="alff_mask",
|
|
165
|
+
)
|
|
147
166
|
# Compute ALFF + fALFF
|
|
148
167
|
alff, falff, alff_path, falff_path = estimator.compute( # type: ignore
|
|
149
168
|
input_path=input_data["path"],
|
|
150
169
|
highpass=self.highpass,
|
|
151
170
|
lowpass=self.lowpass,
|
|
152
171
|
tr=self.tr,
|
|
172
|
+
mask_path=mask_path,
|
|
153
173
|
)
|
|
154
174
|
|
|
155
175
|
# If the input data space is native already, the original path should
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
|
4
4
|
# License: AGPL
|
|
5
5
|
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from ...api.decorators import register_marker
|
|
9
|
-
from ...
|
|
9
|
+
from ...datagrabber import DataType
|
|
10
|
+
from ..base import logger
|
|
10
11
|
from ..maps_aggregation import MapsAggregation
|
|
11
12
|
from .falff_base import ALFFBase
|
|
12
13
|
|
|
@@ -23,27 +24,21 @@ class ALFFMaps(ALFFBase):
|
|
|
23
24
|
maps : str
|
|
24
25
|
The name of the map(s) to use.
|
|
25
26
|
See :func:`.list_data` for options.
|
|
26
|
-
using :
|
|
27
|
-
Implementation to use for computing ALFF:
|
|
28
|
-
|
|
29
|
-
* "junifer" : Use ``junifer``'s own ALFF implementation
|
|
30
|
-
* "afni" : Use AFNI's ``3dRSFC``
|
|
31
|
-
|
|
27
|
+
using : :enum:`.ALFFImpl`
|
|
32
28
|
highpass : positive float, optional
|
|
33
|
-
|
|
34
|
-
it will not apply a highpass filter (default 0.01).
|
|
29
|
+
Highpass cutoff frequency (default 0.01).
|
|
35
30
|
lowpass : positive float, optional
|
|
36
|
-
|
|
31
|
+
Lowpass cutoff frequency (default 0.1).
|
|
37
32
|
tr : positive float, optional
|
|
38
|
-
The
|
|
39
|
-
the TR from NIfTI header (default None).
|
|
40
|
-
masks : str, dict
|
|
33
|
+
The repetition time of the BOLD data.
|
|
34
|
+
If None, will extract the TR from NIfTI header (default None).
|
|
35
|
+
masks : str, dict, list of them or None, optional
|
|
41
36
|
The specification of the masks to apply to regions before extracting
|
|
42
37
|
signals. Check :ref:`Using Masks <using_masks>` for more details.
|
|
43
38
|
If None, will not apply any mask (default None).
|
|
44
|
-
name : str, optional
|
|
45
|
-
The name of the marker.
|
|
46
|
-
None).
|
|
39
|
+
name : str or None, optional
|
|
40
|
+
The name of the marker.
|
|
41
|
+
If None, will use the class name (default None).
|
|
47
42
|
|
|
48
43
|
Notes
|
|
49
44
|
-----
|
|
@@ -59,31 +54,12 @@ class ALFFMaps(ALFFBase):
|
|
|
59
54
|
|
|
60
55
|
"""
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
self,
|
|
64
|
-
maps: str,
|
|
65
|
-
using: str,
|
|
66
|
-
highpass: float = 0.01,
|
|
67
|
-
lowpass: float = 0.1,
|
|
68
|
-
tr: Optional[float] = None,
|
|
69
|
-
masks: Union[str, dict, list[Union[dict, str]], None] = None,
|
|
70
|
-
name: Optional[str] = None,
|
|
71
|
-
) -> None:
|
|
72
|
-
# Superclass init first to validate `using` parameter
|
|
73
|
-
super().__init__(
|
|
74
|
-
highpass=highpass,
|
|
75
|
-
lowpass=lowpass,
|
|
76
|
-
using=using,
|
|
77
|
-
tr=tr,
|
|
78
|
-
name=name,
|
|
79
|
-
)
|
|
80
|
-
self.maps = maps
|
|
81
|
-
self.masks = masks
|
|
57
|
+
maps: str
|
|
82
58
|
|
|
83
59
|
def compute(
|
|
84
60
|
self,
|
|
85
61
|
input: dict[str, Any],
|
|
86
|
-
extra_input:
|
|
62
|
+
extra_input: dict[str, Any] | None = None,
|
|
87
63
|
) -> dict[str, Any]:
|
|
88
64
|
"""Compute.
|
|
89
65
|
|
|
@@ -116,7 +92,7 @@ class ALFFMaps(ALFFBase):
|
|
|
116
92
|
|
|
117
93
|
# Compute ALFF + fALFF
|
|
118
94
|
alff_output, falff_output, alff_output_path, falff_output_path = (
|
|
119
|
-
self._compute(input_data=input)
|
|
95
|
+
self._compute(input_data=input, extra_input=extra_input)
|
|
120
96
|
)
|
|
121
97
|
|
|
122
98
|
# Perform aggregation on ALFF + fALFF
|
|
@@ -132,7 +108,7 @@ class ALFFMaps(ALFFBase):
|
|
|
132
108
|
**MapsAggregation(
|
|
133
109
|
maps=self.maps,
|
|
134
110
|
masks=self.masks,
|
|
135
|
-
on=
|
|
111
|
+
on=DataType.BOLD,
|
|
136
112
|
).compute(
|
|
137
113
|
input=aggregation_alff_input,
|
|
138
114
|
extra_input=extra_input,
|
|
@@ -142,7 +118,7 @@ class ALFFMaps(ALFFBase):
|
|
|
142
118
|
**MapsAggregation(
|
|
143
119
|
maps=self.maps,
|
|
144
120
|
masks=self.masks,
|
|
145
|
-
on=
|
|
121
|
+
on=DataType.BOLD,
|
|
146
122
|
).compute(
|
|
147
123
|
input=aggregation_falff_input,
|
|
148
124
|
extra_input=extra_input,
|