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/stats.py
CHANGED
|
@@ -4,37 +4,63 @@
|
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
5
5
|
# License: AGPL
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Callable
|
|
8
|
+
from enum import StrEnum
|
|
9
|
+
from typing import Any
|
|
8
10
|
|
|
9
11
|
import numpy as np
|
|
12
|
+
import structlog
|
|
13
|
+
from pydantic import validate_call
|
|
10
14
|
from scipy.stats import mode, trim_mean
|
|
11
15
|
from scipy.stats.mstats import winsorize
|
|
12
16
|
|
|
13
|
-
from .utils import
|
|
17
|
+
from .utils import raise_error
|
|
14
18
|
|
|
15
19
|
|
|
16
|
-
__all__ = [
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AggFunc",
|
|
22
|
+
"count",
|
|
23
|
+
"get_aggfunc_by_name",
|
|
24
|
+
"select",
|
|
25
|
+
"winsorized_mean",
|
|
26
|
+
]
|
|
17
27
|
|
|
28
|
+
_log = structlog.get_logger("junifer")
|
|
29
|
+
logger = _log.bind(pkg="stats")
|
|
18
30
|
|
|
31
|
+
|
|
32
|
+
class AggFunc(StrEnum):
|
|
33
|
+
"""Accepted aggregation function names.
|
|
34
|
+
|
|
35
|
+
* ``mean`` -> :func:`numpy.mean`
|
|
36
|
+
* ``winsorized_mean`` -> :func:`scipy.stats.mstats.winsorize`
|
|
37
|
+
* ``trim_mean`` -> :func:`scipy.stats.trim_mean`
|
|
38
|
+
* ``mode`` -> :func:`scipy.stats.mode`
|
|
39
|
+
* ``std`` -> :func:`numpy.std`
|
|
40
|
+
* ``count`` -> :func:`.count`
|
|
41
|
+
* ``select`` -> :func:`.select`
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
Mean = "mean"
|
|
46
|
+
WinsorizedMean = "winsorized_mean"
|
|
47
|
+
TrimMean = "trim_mean"
|
|
48
|
+
Mode = "mode"
|
|
49
|
+
Std = "std"
|
|
50
|
+
Count = "count"
|
|
51
|
+
Select = "select"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@validate_call
|
|
19
55
|
def get_aggfunc_by_name(
|
|
20
|
-
name:
|
|
56
|
+
name: AggFunc, func_params: dict[str, Any] | None = None
|
|
21
57
|
) -> Callable:
|
|
22
58
|
"""Get an aggregation function by its name.
|
|
23
59
|
|
|
24
60
|
Parameters
|
|
25
61
|
----------
|
|
26
|
-
name :
|
|
27
|
-
|
|
28
|
-
corresponding functions are:
|
|
29
|
-
|
|
30
|
-
* ``mean`` -> :func:`numpy.mean`
|
|
31
|
-
* ``winsorized_mean`` -> :func:`scipy.stats.mstats.winsorize`
|
|
32
|
-
* ``trim_mean`` -> :func:`scipy.stats.trim_mean`
|
|
33
|
-
* ``mode`` -> :func:`scipy.stats.mode`
|
|
34
|
-
* ``std`` -> :func:`numpy.std`
|
|
35
|
-
* ``count`` -> :func:`.count`
|
|
36
|
-
* ``select`` -> :func:`.select`
|
|
37
|
-
|
|
62
|
+
name : :enum:`.AggFunc`
|
|
63
|
+
Aggregation function name.
|
|
38
64
|
func_params : dict, optional
|
|
39
65
|
Parameters to pass to the function.
|
|
40
66
|
E.g. for ``winsorized_mean``: ``func_params = {'limits': [0.1, 0.1]}``
|
|
@@ -48,16 +74,6 @@ def get_aggfunc_by_name(
|
|
|
48
74
|
"""
|
|
49
75
|
from functools import partial # local import to avoid sphinx error
|
|
50
76
|
|
|
51
|
-
# check validity of names
|
|
52
|
-
_valid_func_names = {
|
|
53
|
-
"winsorized_mean",
|
|
54
|
-
"mean",
|
|
55
|
-
"std",
|
|
56
|
-
"trim_mean",
|
|
57
|
-
"count",
|
|
58
|
-
"select",
|
|
59
|
-
"mode",
|
|
60
|
-
}
|
|
61
77
|
if func_params is None:
|
|
62
78
|
func_params = {}
|
|
63
79
|
# apply functions
|
|
@@ -101,11 +117,7 @@ def get_aggfunc_by_name(
|
|
|
101
117
|
func = partial(select, **func_params)
|
|
102
118
|
elif name == "mode":
|
|
103
119
|
func = partial(mode, **func_params)
|
|
104
|
-
|
|
105
|
-
raise_error(
|
|
106
|
-
f"Function {name} unknown. Please provide any of "
|
|
107
|
-
f"{_valid_func_names}"
|
|
108
|
-
)
|
|
120
|
+
|
|
109
121
|
return func
|
|
110
122
|
|
|
111
123
|
|
|
@@ -134,7 +146,7 @@ def count(data: np.ndarray, axis: int = 0) -> np.ndarray:
|
|
|
134
146
|
|
|
135
147
|
|
|
136
148
|
def winsorized_mean(
|
|
137
|
-
data: np.ndarray, axis:
|
|
149
|
+
data: np.ndarray, axis: int | None = None, **win_params
|
|
138
150
|
) -> np.ndarray:
|
|
139
151
|
"""Compute a winsorized mean by chaining winsorization and mean.
|
|
140
152
|
|
|
@@ -169,8 +181,8 @@ def winsorized_mean(
|
|
|
169
181
|
def select(
|
|
170
182
|
data: np.ndarray,
|
|
171
183
|
axis: int = 0,
|
|
172
|
-
pick:
|
|
173
|
-
drop:
|
|
184
|
+
pick: list[int] | None = None,
|
|
185
|
+
drop: list[int] | None = None,
|
|
174
186
|
) -> np.ndarray:
|
|
175
187
|
"""Select a subset of the data.
|
|
176
188
|
|
junifer/storage/__init__.pyi
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
__all__ = [
|
|
2
2
|
"BaseFeatureStorage",
|
|
3
|
+
"MatrixKind",
|
|
4
|
+
"StorageType",
|
|
5
|
+
"HDF5FeatureStorage",
|
|
3
6
|
"PandasBaseFeatureStorage",
|
|
4
7
|
"SQLiteFeatureStorage",
|
|
5
|
-
"
|
|
8
|
+
"Upsert",
|
|
9
|
+
"logger",
|
|
6
10
|
]
|
|
7
11
|
|
|
8
|
-
from .base import BaseFeatureStorage
|
|
9
|
-
from .pandas_base import PandasBaseFeatureStorage
|
|
10
|
-
from .sqlite import SQLiteFeatureStorage
|
|
12
|
+
from .base import BaseFeatureStorage, MatrixKind, StorageType, logger
|
|
11
13
|
from .hdf5 import HDF5FeatureStorage
|
|
14
|
+
from .pandas_base import PandasBaseFeatureStorage
|
|
15
|
+
from .sqlite import SQLiteFeatureStorage, Upsert
|
junifer/storage/base.py
CHANGED
|
@@ -6,20 +6,44 @@
|
|
|
6
6
|
|
|
7
7
|
from abc import ABC, abstractmethod
|
|
8
8
|
from collections.abc import Sequence
|
|
9
|
+
from enum import StrEnum
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import Any, ClassVar
|
|
11
|
+
from typing import Any, ClassVar
|
|
11
12
|
|
|
12
13
|
import numpy as np
|
|
13
14
|
import pandas as pd
|
|
15
|
+
import structlog
|
|
16
|
+
from pydantic import BaseModel, ConfigDict
|
|
14
17
|
|
|
15
|
-
from ..utils import
|
|
16
|
-
from .utils import process_meta
|
|
18
|
+
from ..utils import raise_error
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
__all__ = ["BaseFeatureStorage"]
|
|
21
|
+
__all__ = ["BaseFeatureStorage", "MatrixKind", "StorageType"]
|
|
20
22
|
|
|
21
23
|
|
|
22
|
-
class
|
|
24
|
+
class MatrixKind(StrEnum):
|
|
25
|
+
"""Accepted matrix kind value."""
|
|
26
|
+
|
|
27
|
+
UpperTriangle = "triu"
|
|
28
|
+
LowerTriangle = "tril"
|
|
29
|
+
Full = "full"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
_log = structlog.get_logger("junifer")
|
|
33
|
+
logger = _log.bind(pkg="storage", step="storage")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class StorageType(StrEnum):
|
|
37
|
+
"""Accepted storage type."""
|
|
38
|
+
|
|
39
|
+
Vector = "vector"
|
|
40
|
+
Matrix = "matrix"
|
|
41
|
+
Timeseries = "timeseries"
|
|
42
|
+
Timeseries2D = "timeseries_2d"
|
|
43
|
+
ScalarTable = "scalar_table"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class BaseFeatureStorage(BaseModel, ABC):
|
|
23
47
|
"""Abstract base class for feature storage.
|
|
24
48
|
|
|
25
49
|
For every storage, one needs to provide a concrete
|
|
@@ -27,7 +51,7 @@ class BaseFeatureStorage(ABC):
|
|
|
27
51
|
|
|
28
52
|
Parameters
|
|
29
53
|
----------
|
|
30
|
-
uri :
|
|
54
|
+
uri : pathlib.Path
|
|
31
55
|
The path to the storage.
|
|
32
56
|
single_output : bool, optional
|
|
33
57
|
Whether to have single output (default True).
|
|
@@ -35,27 +59,26 @@ class BaseFeatureStorage(ABC):
|
|
|
35
59
|
Raises
|
|
36
60
|
------
|
|
37
61
|
AttributeError
|
|
38
|
-
If the storage does not have
|
|
62
|
+
If the storage does not have ``_STORAGE_TYPES`` attribute.
|
|
39
63
|
|
|
40
64
|
"""
|
|
41
65
|
|
|
42
|
-
_STORAGE_TYPES: ClassVar[Sequence[
|
|
66
|
+
_STORAGE_TYPES: ClassVar[Sequence[StorageType]]
|
|
43
67
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
model_config = ConfigDict(
|
|
69
|
+
extra="forbid", frozen=True, use_enum_values=True
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
uri: Path
|
|
73
|
+
single_output: bool = True
|
|
74
|
+
|
|
75
|
+
def model_post_init(self, context: Any): # noqa: D102
|
|
49
76
|
# Check for missing storage types attribute
|
|
50
77
|
if not hasattr(self, "_STORAGE_TYPES"):
|
|
51
78
|
raise_error(
|
|
52
79
|
msg="Missing `_STORAGE_TYPES` for the storage",
|
|
53
80
|
klass=AttributeError,
|
|
54
81
|
)
|
|
55
|
-
# Convert str to Path
|
|
56
|
-
if not isinstance(uri, Path):
|
|
57
|
-
uri = Path(uri)
|
|
58
|
-
self.uri = uri
|
|
59
82
|
# Create parent directories if not present
|
|
60
83
|
if not self.uri.parent.exists():
|
|
61
84
|
logger.info(
|
|
@@ -63,21 +86,12 @@ class BaseFeatureStorage(ABC):
|
|
|
63
86
|
"does not exist, creating now"
|
|
64
87
|
)
|
|
65
88
|
self.uri.parent.mkdir(parents=True, exist_ok=True)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Returns
|
|
72
|
-
-------
|
|
73
|
-
list of str
|
|
74
|
-
The list of storage types that can be used as input for this
|
|
75
|
-
storage.
|
|
76
|
-
|
|
77
|
-
"""
|
|
78
|
-
return list(self._STORAGE_TYPES)
|
|
89
|
+
logger.info(
|
|
90
|
+
f"Parameters: {self.model_dump(mode='json')}",
|
|
91
|
+
component=self.__class__.__name__,
|
|
92
|
+
)
|
|
79
93
|
|
|
80
|
-
def
|
|
94
|
+
def validate_input(self, input_: list[str]) -> None:
|
|
81
95
|
"""Validate the input to the pipeline step.
|
|
82
96
|
|
|
83
97
|
Parameters
|
|
@@ -119,11 +133,9 @@ class BaseFeatureStorage(ABC):
|
|
|
119
133
|
@abstractmethod
|
|
120
134
|
def read(
|
|
121
135
|
self,
|
|
122
|
-
feature_name:
|
|
123
|
-
feature_md5:
|
|
124
|
-
) -> dict[
|
|
125
|
-
str, Union[str, list[Union[int, str, dict[str, str]]], np.ndarray]
|
|
126
|
-
]:
|
|
136
|
+
feature_name: str | None = None,
|
|
137
|
+
feature_md5: str | None = None,
|
|
138
|
+
) -> dict[str, str | list[int | str | dict[str, str]] | np.ndarray]:
|
|
127
139
|
"""Read stored feature.
|
|
128
140
|
|
|
129
141
|
Parameters
|
|
@@ -147,8 +159,8 @@ class BaseFeatureStorage(ABC):
|
|
|
147
159
|
@abstractmethod
|
|
148
160
|
def read_df(
|
|
149
161
|
self,
|
|
150
|
-
feature_name:
|
|
151
|
-
feature_md5:
|
|
162
|
+
feature_name: str | None = None,
|
|
163
|
+
feature_md5: str | None = None,
|
|
152
164
|
) -> pd.DataFrame:
|
|
153
165
|
"""Read feature into a pandas DataFrame.
|
|
154
166
|
|
|
@@ -171,7 +183,13 @@ class BaseFeatureStorage(ABC):
|
|
|
171
183
|
) # pragma: no cover
|
|
172
184
|
|
|
173
185
|
@abstractmethod
|
|
174
|
-
def store_metadata(
|
|
186
|
+
def store_metadata(
|
|
187
|
+
self,
|
|
188
|
+
meta_md5: str,
|
|
189
|
+
element: dict,
|
|
190
|
+
meta: dict,
|
|
191
|
+
processed_element: dict | None = None,
|
|
192
|
+
) -> None:
|
|
175
193
|
"""Store metadata.
|
|
176
194
|
|
|
177
195
|
Parameters
|
|
@@ -182,6 +200,11 @@ class BaseFeatureStorage(ABC):
|
|
|
182
200
|
The element as a dictionary.
|
|
183
201
|
meta : dict
|
|
184
202
|
The metadata as a dictionary.
|
|
203
|
+
processed_element : dict or None, optional
|
|
204
|
+
The element being processed when the data was computed, with all
|
|
205
|
+
the keys of the element, which can be used to choose where to
|
|
206
|
+
store the data (e.g., the file of each element being processed).
|
|
207
|
+
If None, ``element`` is used (default None).
|
|
185
208
|
|
|
186
209
|
"""
|
|
187
210
|
raise_error(
|
|
@@ -189,12 +212,12 @@ class BaseFeatureStorage(ABC):
|
|
|
189
212
|
klass=NotImplementedError,
|
|
190
213
|
) # pragma: no cover
|
|
191
214
|
|
|
192
|
-
def store(self, kind:
|
|
215
|
+
def store(self, kind: StorageType, **kwargs) -> None:
|
|
193
216
|
"""Store extracted features data.
|
|
194
217
|
|
|
195
218
|
Parameters
|
|
196
219
|
----------
|
|
197
|
-
kind :
|
|
220
|
+
kind : :enum:`.StorageType`
|
|
198
221
|
The storage kind.
|
|
199
222
|
**kwargs
|
|
200
223
|
The keyword arguments.
|
|
@@ -212,11 +235,24 @@ class BaseFeatureStorage(ABC):
|
|
|
212
235
|
msg=f"I don't know how to store {kind}.",
|
|
213
236
|
klass=ValueError,
|
|
214
237
|
)
|
|
215
|
-
#
|
|
238
|
+
# Imported here to avoid circular import
|
|
239
|
+
from .utils import process_meta
|
|
240
|
+
|
|
241
|
+
# Process and store metadata: the data is stored for the element with
|
|
242
|
+
# the keys that it depends on, and the element being processed is
|
|
243
|
+
# passed as ``processed_element`` (e.g., to choose the file to store
|
|
244
|
+
# the data of each element being processed)
|
|
216
245
|
t_meta = kwargs.pop("meta")
|
|
246
|
+
processed_element = t_meta.get("element")
|
|
217
247
|
meta_md5, t_meta, t_element = process_meta(t_meta)
|
|
218
|
-
self.store_metadata(
|
|
248
|
+
self.store_metadata(
|
|
249
|
+
meta_md5=meta_md5,
|
|
250
|
+
element=t_element,
|
|
251
|
+
meta=t_meta,
|
|
252
|
+
processed_element=processed_element,
|
|
253
|
+
)
|
|
219
254
|
# Store data
|
|
255
|
+
kwargs["processed_element"] = processed_element
|
|
220
256
|
if kind == "matrix":
|
|
221
257
|
self.store_matrix(meta_md5=meta_md5, element=t_element, **kwargs)
|
|
222
258
|
elif kind == "timeseries":
|
|
@@ -239,10 +275,11 @@ class BaseFeatureStorage(ABC):
|
|
|
239
275
|
meta_md5: str,
|
|
240
276
|
element: dict,
|
|
241
277
|
data: np.ndarray,
|
|
242
|
-
col_names:
|
|
243
|
-
row_names:
|
|
244
|
-
matrix_kind:
|
|
278
|
+
col_names: Sequence[str] | None = None,
|
|
279
|
+
row_names: Sequence[str] | None = None,
|
|
280
|
+
matrix_kind: MatrixKind = MatrixKind.Full,
|
|
245
281
|
diagonal: bool = True,
|
|
282
|
+
processed_element: dict | None = None,
|
|
246
283
|
) -> None:
|
|
247
284
|
"""Store matrix.
|
|
248
285
|
|
|
@@ -258,17 +295,17 @@ class BaseFeatureStorage(ABC):
|
|
|
258
295
|
The column labels (default None).
|
|
259
296
|
row_names : list-like of str, optional
|
|
260
297
|
The row labels (default None).
|
|
261
|
-
matrix_kind :
|
|
262
|
-
The kind
|
|
263
|
-
|
|
264
|
-
* ``triu`` : store upper triangular only
|
|
265
|
-
* ``tril`` : store lower triangular
|
|
266
|
-
* ``full`` : full matrix
|
|
267
|
-
|
|
268
|
-
(default "full").
|
|
298
|
+
matrix_kind : :enum:`.MatrixKind`, optional
|
|
299
|
+
The matrix kind (default ``MatrixKind.Full``).
|
|
269
300
|
diagonal : bool, optional
|
|
270
|
-
Whether to store the diagonal. If ``matrix_kind
|
|
271
|
-
this to False will raise an error (default True).
|
|
301
|
+
Whether to store the diagonal. If ``matrix_kind=MatrixKind.Full``,
|
|
302
|
+
setting this to False will raise an error (default True).
|
|
303
|
+
|
|
304
|
+
processed_element : dict or None, optional
|
|
305
|
+
The element being processed when the data was computed, with all
|
|
306
|
+
the keys of the element, which can be used to choose where to
|
|
307
|
+
store the data (e.g., the file of each element being processed).
|
|
308
|
+
If None, ``element`` is used (default None).
|
|
272
309
|
|
|
273
310
|
"""
|
|
274
311
|
raise_error(
|
|
@@ -280,8 +317,9 @@ class BaseFeatureStorage(ABC):
|
|
|
280
317
|
self,
|
|
281
318
|
meta_md5: str,
|
|
282
319
|
element: dict,
|
|
283
|
-
data:
|
|
284
|
-
col_names:
|
|
320
|
+
data: np.ndarray | list,
|
|
321
|
+
col_names: Sequence[str] | None = None,
|
|
322
|
+
processed_element: dict | None = None,
|
|
285
323
|
) -> None:
|
|
286
324
|
"""Store vector.
|
|
287
325
|
|
|
@@ -296,6 +334,12 @@ class BaseFeatureStorage(ABC):
|
|
|
296
334
|
col_names : list-like of str, optional
|
|
297
335
|
The column labels (default None).
|
|
298
336
|
|
|
337
|
+
processed_element : dict or None, optional
|
|
338
|
+
The element being processed when the data was computed, with all
|
|
339
|
+
the keys of the element, which can be used to choose where to
|
|
340
|
+
store the data (e.g., the file of each element being processed).
|
|
341
|
+
If None, ``element`` is used (default None).
|
|
342
|
+
|
|
299
343
|
"""
|
|
300
344
|
raise_error(
|
|
301
345
|
msg="Concrete classes need to implement store_vector().",
|
|
@@ -307,7 +351,8 @@ class BaseFeatureStorage(ABC):
|
|
|
307
351
|
meta_md5: str,
|
|
308
352
|
element: dict,
|
|
309
353
|
data: np.ndarray,
|
|
310
|
-
col_names:
|
|
354
|
+
col_names: Sequence[str] | None = None,
|
|
355
|
+
processed_element: dict | None = None,
|
|
311
356
|
) -> None:
|
|
312
357
|
"""Store timeseries.
|
|
313
358
|
|
|
@@ -322,6 +367,12 @@ class BaseFeatureStorage(ABC):
|
|
|
322
367
|
col_names : list-like of str, optional
|
|
323
368
|
The column labels (default None).
|
|
324
369
|
|
|
370
|
+
processed_element : dict or None, optional
|
|
371
|
+
The element being processed when the data was computed, with all
|
|
372
|
+
the keys of the element, which can be used to choose where to
|
|
373
|
+
store the data (e.g., the file of each element being processed).
|
|
374
|
+
If None, ``element`` is used (default None).
|
|
375
|
+
|
|
325
376
|
"""
|
|
326
377
|
raise_error(
|
|
327
378
|
msg="Concrete classes need to implement store_timeseries().",
|
|
@@ -333,8 +384,9 @@ class BaseFeatureStorage(ABC):
|
|
|
333
384
|
meta_md5: str,
|
|
334
385
|
element: dict,
|
|
335
386
|
data: np.ndarray,
|
|
336
|
-
col_names:
|
|
337
|
-
row_names:
|
|
387
|
+
col_names: Sequence[str] | None = None,
|
|
388
|
+
row_names: Sequence[str] | None = None,
|
|
389
|
+
processed_element: dict | None = None,
|
|
338
390
|
) -> None:
|
|
339
391
|
"""Store 2D timeseries.
|
|
340
392
|
|
|
@@ -351,6 +403,12 @@ class BaseFeatureStorage(ABC):
|
|
|
351
403
|
row_names : list-like of str, optional
|
|
352
404
|
The row labels (default None).
|
|
353
405
|
|
|
406
|
+
processed_element : dict or None, optional
|
|
407
|
+
The element being processed when the data was computed, with all
|
|
408
|
+
the keys of the element, which can be used to choose where to
|
|
409
|
+
store the data (e.g., the file of each element being processed).
|
|
410
|
+
If None, ``element`` is used (default None).
|
|
411
|
+
|
|
354
412
|
"""
|
|
355
413
|
raise_error(
|
|
356
414
|
msg="Concrete classes need to implement store_timeseries_2d().",
|
|
@@ -362,9 +420,10 @@ class BaseFeatureStorage(ABC):
|
|
|
362
420
|
meta_md5: str,
|
|
363
421
|
element: dict,
|
|
364
422
|
data: np.ndarray,
|
|
365
|
-
col_names:
|
|
366
|
-
row_names:
|
|
367
|
-
row_header_col_name:
|
|
423
|
+
col_names: Sequence[str] | None = None,
|
|
424
|
+
row_names: Sequence[str] | None = None,
|
|
425
|
+
row_header_col_name: str | None = "feature",
|
|
426
|
+
processed_element: dict | None = None,
|
|
368
427
|
) -> None:
|
|
369
428
|
"""Store table with scalar values.
|
|
370
429
|
|
|
@@ -383,6 +442,12 @@ class BaseFeatureStorage(ABC):
|
|
|
383
442
|
row_header_col_name : str, optional
|
|
384
443
|
The column name for the row header column (default "feature").
|
|
385
444
|
|
|
445
|
+
processed_element : dict or None, optional
|
|
446
|
+
The element being processed when the data was computed, with all
|
|
447
|
+
the keys of the element, which can be used to choose where to
|
|
448
|
+
store the data (e.g., the file of each element being processed).
|
|
449
|
+
If None, ``element`` is used (default None).
|
|
450
|
+
|
|
386
451
|
"""
|
|
387
452
|
raise_error(
|
|
388
453
|
msg="Concrete classes need to implement store_scalar_table().",
|