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/_version.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
# file generated by
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
2
|
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
__all__ = [
|
|
5
6
|
"__version__",
|
|
@@ -10,25 +11,14 @@ __all__ = [
|
|
|
10
11
|
"commit_id",
|
|
11
12
|
]
|
|
12
13
|
|
|
13
|
-
TYPE_CHECKING = False
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from typing import Tuple
|
|
16
|
-
from typing import Union
|
|
17
|
-
|
|
18
|
-
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
-
COMMIT_ID = Union[str, None]
|
|
20
|
-
else:
|
|
21
|
-
VERSION_TUPLE = object
|
|
22
|
-
COMMIT_ID = object
|
|
23
|
-
|
|
24
14
|
version: str
|
|
25
15
|
__version__: str
|
|
26
|
-
__version_tuple__:
|
|
27
|
-
version_tuple:
|
|
28
|
-
commit_id:
|
|
29
|
-
__commit_id__:
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
30
20
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
21
|
+
__version__ = version = '0.0.8'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 8)
|
|
33
23
|
|
|
34
|
-
__commit_id__ = commit_id =
|
|
24
|
+
__commit_id__ = commit_id = 'g2b4aae01d'
|
junifer/api/__init__.pyi
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
__all__ = [
|
|
1
|
+
__all__ = [
|
|
2
|
+
"decorators",
|
|
3
|
+
"collect",
|
|
4
|
+
"queue",
|
|
5
|
+
"run",
|
|
6
|
+
"reset",
|
|
7
|
+
"list_elements",
|
|
8
|
+
"parse_yaml",
|
|
9
|
+
]
|
|
2
10
|
|
|
3
11
|
from . import decorators
|
|
4
|
-
from .functions import
|
|
12
|
+
from .functions import (
|
|
13
|
+
collect,
|
|
14
|
+
list_elements,
|
|
15
|
+
parse_yaml,
|
|
16
|
+
reset,
|
|
17
|
+
run,
|
|
18
|
+
queue,
|
|
19
|
+
)
|
junifer/api/functions.py
CHANGED
|
@@ -5,10 +5,15 @@
|
|
|
5
5
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
|
6
6
|
# License: AGPL
|
|
7
7
|
|
|
8
|
+
import atexit
|
|
9
|
+
import importlib
|
|
10
|
+
import importlib.util
|
|
8
11
|
import os
|
|
9
12
|
import shutil
|
|
13
|
+
import sys
|
|
10
14
|
from pathlib import Path
|
|
11
|
-
|
|
15
|
+
|
|
16
|
+
import structlog
|
|
12
17
|
|
|
13
18
|
from ..api.queue_context import GnuParallelLocalAdapter, HTCondorAdapter
|
|
14
19
|
from ..datagrabber import BaseDataGrabber
|
|
@@ -27,10 +32,20 @@ from ..typing import (
|
|
|
27
32
|
PreprocessorLike,
|
|
28
33
|
StorageLike,
|
|
29
34
|
)
|
|
30
|
-
from ..utils import
|
|
35
|
+
from ..utils import raise_error, warn_with_log, yaml
|
|
36
|
+
|
|
31
37
|
|
|
38
|
+
__all__ = [
|
|
39
|
+
"collect",
|
|
40
|
+
"list_elements",
|
|
41
|
+
"parse_yaml",
|
|
42
|
+
"queue",
|
|
43
|
+
"reset",
|
|
44
|
+
"run",
|
|
45
|
+
]
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
_log = structlog.get_logger("junifer")
|
|
48
|
+
logger = _log.bind(pkg="api")
|
|
34
49
|
|
|
35
50
|
|
|
36
51
|
def _get_datagrabber(datagrabber_config: dict) -> DataGrabberLike:
|
|
@@ -121,13 +136,52 @@ def _get_storage(storage_config: dict) -> StorageLike:
|
|
|
121
136
|
)
|
|
122
137
|
|
|
123
138
|
|
|
139
|
+
def _get_workdir_params(workdir: str | Path | dict | None) -> dict:
|
|
140
|
+
"""Get the parameters of the working directory manager.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
workdir : str or pathlib.Path or dict or None
|
|
145
|
+
The working directory as a path, or as a dictionary with the keys
|
|
146
|
+
``path`` and ``cleanup`` (default True). If None, the default of
|
|
147
|
+
:class:`.WorkDirManager` is used.
|
|
148
|
+
|
|
149
|
+
Returns
|
|
150
|
+
-------
|
|
151
|
+
dict
|
|
152
|
+
The parameters for :class:`.WorkDirManager`.
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
if isinstance(workdir, dict):
|
|
156
|
+
return {
|
|
157
|
+
"workdir": Path(workdir["path"]),
|
|
158
|
+
"cleanup": workdir.get("cleanup", True),
|
|
159
|
+
}
|
|
160
|
+
if workdir is None:
|
|
161
|
+
return {"workdir": None, "cleanup": True}
|
|
162
|
+
return {"workdir": Path(workdir), "cleanup": True}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _setup_workdir(workdir: str | Path | dict | None) -> None:
|
|
166
|
+
"""Set up the working directory manager.
|
|
167
|
+
|
|
168
|
+
Parameters
|
|
169
|
+
----------
|
|
170
|
+
workdir : str or pathlib.Path or dict or None
|
|
171
|
+
The working directory (see :func:`_get_workdir_params`).
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
WorkDirManager(**_get_workdir_params(workdir))
|
|
175
|
+
atexit.register(WorkDirManager()._cleanup)
|
|
176
|
+
|
|
177
|
+
|
|
124
178
|
def run(
|
|
125
|
-
workdir:
|
|
179
|
+
workdir: str | Path | dict,
|
|
126
180
|
datagrabber: dict,
|
|
127
181
|
markers: list[dict],
|
|
128
182
|
storage: dict,
|
|
129
|
-
preprocessors:
|
|
130
|
-
elements:
|
|
183
|
+
preprocessors: list[dict] | None = None,
|
|
184
|
+
elements: Elements | None = None,
|
|
131
185
|
) -> None:
|
|
132
186
|
"""Run the pipeline on the selected element.
|
|
133
187
|
|
|
@@ -165,24 +219,15 @@ def run(
|
|
|
165
219
|
If invalid element selectors are found.
|
|
166
220
|
|
|
167
221
|
"""
|
|
168
|
-
# Conditional to handle workdir config
|
|
169
|
-
if isinstance(workdir, (str, Path)):
|
|
170
|
-
if isinstance(workdir, str):
|
|
171
|
-
workdir = {"workdir": Path(workdir), "cleanup": True}
|
|
172
|
-
else:
|
|
173
|
-
workdir = {"workdir": workdir, "cleanup": True}
|
|
174
|
-
elif isinstance(workdir, dict):
|
|
175
|
-
workdir["workdir"] = workdir.pop("path")
|
|
176
|
-
|
|
177
222
|
# Initiate working directory manager with correct variation
|
|
178
|
-
if not workdir["cleanup"]:
|
|
223
|
+
if not _get_workdir_params(workdir)["cleanup"]:
|
|
179
224
|
if elements is None or len(elements) > 1:
|
|
180
225
|
raise_error(
|
|
181
226
|
"Cannot disable `workdir.cleanup` as "
|
|
182
227
|
f"{len(elements) if elements is not None else 'all'} "
|
|
183
228
|
"elements will be processed"
|
|
184
229
|
)
|
|
185
|
-
|
|
230
|
+
_setup_workdir(workdir)
|
|
186
231
|
|
|
187
232
|
# Get datagrabber to use
|
|
188
233
|
datagrabber_object = _get_datagrabber(datagrabber.copy())
|
|
@@ -216,28 +261,15 @@ def run(
|
|
|
216
261
|
# Fit elements
|
|
217
262
|
with datagrabber_object:
|
|
218
263
|
if elements is not None:
|
|
219
|
-
#
|
|
220
|
-
|
|
221
|
-
for t_element in datagrabber_object.filter(elements):
|
|
222
|
-
valid_elements.append(t_element)
|
|
223
|
-
mc.fit(datagrabber_object[t_element])
|
|
224
|
-
# Compute invalid selectors
|
|
225
|
-
invalid_elements = set(elements) - set(valid_elements)
|
|
226
|
-
# Report if invalid selectors are found
|
|
227
|
-
if invalid_elements:
|
|
228
|
-
raise_error(
|
|
229
|
-
msg=(
|
|
230
|
-
"The following element selectors are invalid:\n"
|
|
231
|
-
f"{invalid_elements}"
|
|
232
|
-
),
|
|
233
|
-
klass=RuntimeError,
|
|
234
|
-
)
|
|
264
|
+
# Only get the elements of the dataset for partial selectors
|
|
265
|
+
to_fit = datagrabber_object.select_elements(elements)
|
|
235
266
|
else:
|
|
236
|
-
|
|
237
|
-
|
|
267
|
+
to_fit = datagrabber_object.get_elements()
|
|
268
|
+
for t_element in to_fit:
|
|
269
|
+
mc.fit(datagrabber_object[t_element])
|
|
238
270
|
|
|
239
271
|
|
|
240
|
-
def collect(storage: dict) -> None:
|
|
272
|
+
def collect(storage: dict, workdir: str | Path | dict | None = None) -> None:
|
|
241
273
|
"""Collect and store data.
|
|
242
274
|
|
|
243
275
|
Parameters
|
|
@@ -246,8 +278,12 @@ def collect(storage: dict) -> None:
|
|
|
246
278
|
Storage to use. Must have a key ``kind`` with the kind of
|
|
247
279
|
storage to use. All other keys are passed to the storage
|
|
248
280
|
constructor.
|
|
281
|
+
workdir : str or pathlib.Path or dict or None, optional
|
|
282
|
+
The working directory, as in :func:`.run`. If None, the default of
|
|
283
|
+
:class:`.WorkDirManager` is used (default None).
|
|
249
284
|
|
|
250
285
|
"""
|
|
286
|
+
_setup_workdir(workdir)
|
|
251
287
|
logger.info(f"Collecting data using {storage['kind']}")
|
|
252
288
|
logger.debug(f"\tStorage params: {storage}")
|
|
253
289
|
if "single_output" not in storage:
|
|
@@ -263,8 +299,8 @@ def queue(
|
|
|
263
299
|
kind: str,
|
|
264
300
|
jobname: str = "junifer_job",
|
|
265
301
|
overwrite: bool = False,
|
|
266
|
-
elements:
|
|
267
|
-
**kwargs:
|
|
302
|
+
elements: Elements | None = None,
|
|
303
|
+
**kwargs: str | int | bool | dict | tuple | list,
|
|
268
304
|
) -> None:
|
|
269
305
|
"""Queue a job to be executed later.
|
|
270
306
|
|
|
@@ -291,6 +327,7 @@ def queue(
|
|
|
291
327
|
if the ``jobdir`` exists and ``overwrite = False``.
|
|
292
328
|
|
|
293
329
|
"""
|
|
330
|
+
_setup_workdir(config.get("workdir"))
|
|
294
331
|
valid_kind = ["HTCondor", "GNUParallelLocal"]
|
|
295
332
|
if kind not in valid_kind:
|
|
296
333
|
raise_error(
|
|
@@ -394,6 +431,7 @@ def reset(config: dict) -> None:
|
|
|
394
431
|
The configuration to be used for resetting.
|
|
395
432
|
|
|
396
433
|
"""
|
|
434
|
+
_setup_workdir(config.get("workdir"))
|
|
397
435
|
# Fetch storage
|
|
398
436
|
storage = config["storage"]
|
|
399
437
|
storage_uri = Path(storage["uri"])
|
|
@@ -425,7 +463,8 @@ def reset(config: dict) -> None:
|
|
|
425
463
|
|
|
426
464
|
def list_elements(
|
|
427
465
|
datagrabber: dict,
|
|
428
|
-
elements:
|
|
466
|
+
elements: Elements | None = None,
|
|
467
|
+
workdir: str | Path | dict | None = None,
|
|
429
468
|
) -> str:
|
|
430
469
|
"""List elements of the datagrabber filtered using `elements`.
|
|
431
470
|
|
|
@@ -438,8 +477,13 @@ def list_elements(
|
|
|
438
477
|
elements : list or None, optional
|
|
439
478
|
Element(s) to filter using. Will be used to index the DataGrabber
|
|
440
479
|
(default None).
|
|
480
|
+
workdir : str or pathlib.Path or dict or None, optional
|
|
481
|
+
Directory where the DataGrabber will be used, as in :func:`.run`.
|
|
482
|
+
If None, the default of :class:`.WorkDirManager` is used
|
|
483
|
+
(default None).
|
|
441
484
|
|
|
442
485
|
"""
|
|
486
|
+
_setup_workdir(workdir)
|
|
443
487
|
# Get datagrabber to use
|
|
444
488
|
datagrabber_object = _get_datagrabber(datagrabber)
|
|
445
489
|
|
|
@@ -462,3 +506,142 @@ def list_elements(
|
|
|
462
506
|
elements_to_list.append(str_element)
|
|
463
507
|
|
|
464
508
|
return "\n".join(elements_to_list)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def parse_yaml(filepath: str | Path) -> dict: # noqa: C901
|
|
512
|
+
"""Parse YAML.
|
|
513
|
+
|
|
514
|
+
Parameters
|
|
515
|
+
----------
|
|
516
|
+
filepath : str or pathlib.Path
|
|
517
|
+
The filepath to read from.
|
|
518
|
+
|
|
519
|
+
Returns
|
|
520
|
+
-------
|
|
521
|
+
dict
|
|
522
|
+
The contents represented as dictionary.
|
|
523
|
+
|
|
524
|
+
"""
|
|
525
|
+
# Convert str to Path
|
|
526
|
+
if not isinstance(filepath, Path):
|
|
527
|
+
filepath = Path(filepath)
|
|
528
|
+
|
|
529
|
+
logger.info(f"Parsing yaml file: {filepath.absolute()!s}")
|
|
530
|
+
# Filepath existence check
|
|
531
|
+
if not filepath.exists():
|
|
532
|
+
raise_error(f"File does not exist: {filepath.absolute()!s}")
|
|
533
|
+
# Filepath reading
|
|
534
|
+
contents = yaml.load(filepath)
|
|
535
|
+
if "elements" in contents:
|
|
536
|
+
if contents["elements"] is None:
|
|
537
|
+
raise_error(
|
|
538
|
+
"The elements key was defined but its content is empty. "
|
|
539
|
+
"Please define the elements to operate on or remove the key."
|
|
540
|
+
)
|
|
541
|
+
# load modules
|
|
542
|
+
if "with" in contents:
|
|
543
|
+
to_load = contents["with"]
|
|
544
|
+
# Convert load modules to list
|
|
545
|
+
if not isinstance(to_load, list):
|
|
546
|
+
to_load = [to_load]
|
|
547
|
+
# Initialize list to have absolute paths for custom modules
|
|
548
|
+
final_to_load = []
|
|
549
|
+
for t_module in to_load:
|
|
550
|
+
if t_module.endswith(".py"):
|
|
551
|
+
logger.debug(f"Importing file: {t_module}")
|
|
552
|
+
# This resolves both absolute and relative paths
|
|
553
|
+
file_path = filepath.parent / t_module
|
|
554
|
+
if not file_path.exists():
|
|
555
|
+
raise_error(
|
|
556
|
+
f"File in 'with' section does not exist: {file_path}"
|
|
557
|
+
)
|
|
558
|
+
# Add the parent directory to the sys.path so that the
|
|
559
|
+
# any imports from this module work correctly
|
|
560
|
+
t_path = str(file_path.parent)
|
|
561
|
+
if t_path not in sys.path:
|
|
562
|
+
sys.path.append(str(file_path.parent))
|
|
563
|
+
|
|
564
|
+
spec = importlib.util.spec_from_file_location(
|
|
565
|
+
t_module, file_path
|
|
566
|
+
)
|
|
567
|
+
module = importlib.util.module_from_spec(spec) # type: ignore
|
|
568
|
+
sys.modules[t_module] = module
|
|
569
|
+
spec.loader.exec_module(module) # type: ignore
|
|
570
|
+
|
|
571
|
+
# Add absolute path to final list
|
|
572
|
+
final_to_load.append(str(file_path.resolve()))
|
|
573
|
+
|
|
574
|
+
# Check if the module has junifer_module_deps function
|
|
575
|
+
if hasattr(module, "junifer_module_deps"):
|
|
576
|
+
logger.debug(
|
|
577
|
+
f"Module {t_module} has junifer_module_deps function"
|
|
578
|
+
)
|
|
579
|
+
# Get the dependencies
|
|
580
|
+
deps = module.junifer_module_deps()
|
|
581
|
+
# Add the dependencies to the final list
|
|
582
|
+
for dep in deps:
|
|
583
|
+
if dep not in final_to_load:
|
|
584
|
+
final_to_load.append(
|
|
585
|
+
str((file_path.parent / dep).resolve())
|
|
586
|
+
)
|
|
587
|
+
else:
|
|
588
|
+
logger.info(f"Importing module: {t_module}")
|
|
589
|
+
importlib.import_module(t_module)
|
|
590
|
+
# Add module to final list
|
|
591
|
+
final_to_load.append(t_module)
|
|
592
|
+
|
|
593
|
+
# Replace modules to be loaded so that custom modules will take the
|
|
594
|
+
# absolute path. This was not the case as found in #224. Similar thing
|
|
595
|
+
# is done with the storage URI below.
|
|
596
|
+
contents["with"] = final_to_load
|
|
597
|
+
|
|
598
|
+
# Compute path for the URI parameter in storage files that are relative
|
|
599
|
+
# This is a tricky thing that appeared in #127. The problem is that
|
|
600
|
+
# the path in the URI parameter is relative to YAML file, not to the
|
|
601
|
+
# current working directory. If we leave it as is in the contents
|
|
602
|
+
# dict, then it will be used later in the ``build`` function as is,
|
|
603
|
+
# which will be computed relative to the current working directory.
|
|
604
|
+
# The solution is to compute the absolute path and replace the
|
|
605
|
+
# relative path in the contents dict with the absolute path.
|
|
606
|
+
|
|
607
|
+
# Check if the storage file is defined
|
|
608
|
+
if "storage" in contents:
|
|
609
|
+
if "uri" in contents["storage"]:
|
|
610
|
+
# Check if the storage file is relative
|
|
611
|
+
uri_path = Path(contents["storage"]["uri"])
|
|
612
|
+
if not uri_path.is_absolute():
|
|
613
|
+
# Compute the absolute path
|
|
614
|
+
contents["storage"]["uri"] = str(
|
|
615
|
+
(filepath.parent / uri_path).resolve()
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
# Compute the absolute path of the data directory of the datagrabber (and
|
|
619
|
+
# of the datagrabbers of a MultipleDataGrabber) if it is relative; same
|
|
620
|
+
# motivation as above. Otherwise, it would be relative to the current
|
|
621
|
+
# working directory, which is the job directory when queueing.
|
|
622
|
+
if "datagrabber" in contents:
|
|
623
|
+
datagrabbers = [
|
|
624
|
+
contents["datagrabber"],
|
|
625
|
+
*contents["datagrabber"].get("datagrabbers", []),
|
|
626
|
+
]
|
|
627
|
+
for datagrabber in datagrabbers:
|
|
628
|
+
if "datadir" in datagrabber:
|
|
629
|
+
datadir = Path(datagrabber["datadir"])
|
|
630
|
+
if not datadir.is_absolute():
|
|
631
|
+
datagrabber["datadir"] = str(
|
|
632
|
+
(filepath.parent / datadir).resolve()
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
# Allow relative path if queue env kind is venv; same motivation as above
|
|
636
|
+
if "queue" in contents:
|
|
637
|
+
if "env" in contents["queue"]:
|
|
638
|
+
if "venv" == contents["queue"]["env"]["kind"]:
|
|
639
|
+
# Check if the env name is relative
|
|
640
|
+
venv_path = Path(contents["queue"]["env"]["name"])
|
|
641
|
+
if not venv_path.is_absolute():
|
|
642
|
+
# Compute the absolute path
|
|
643
|
+
contents["queue"]["env"]["name"] = str(
|
|
644
|
+
(filepath.parent / venv_path).resolve()
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
return contents
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
__all__ = [
|
|
1
|
+
__all__ = [
|
|
2
|
+
"QueueContextAdapter",
|
|
3
|
+
"EnvKind",
|
|
4
|
+
"EnvShell",
|
|
5
|
+
"QueueContextEnv",
|
|
6
|
+
"HTCondorAdapter",
|
|
7
|
+
"HTCondorCollect",
|
|
8
|
+
"GnuParallelLocalAdapter",
|
|
9
|
+
]
|
|
2
10
|
|
|
3
|
-
from .queue_context_adapter import QueueContextAdapter
|
|
4
|
-
from .htcondor_adapter import HTCondorAdapter
|
|
11
|
+
from .queue_context_adapter import QueueContextAdapter, EnvKind, EnvShell, QueueContextEnv
|
|
12
|
+
from .htcondor_adapter import HTCondorAdapter, HTCondorCollect
|
|
5
13
|
from .gnu_parallel_local_adapter import GnuParallelLocalAdapter
|