junifer 0.0.4.dev829__py3-none-any.whl → 0.0.5__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/__init__.py +17 -0
- junifer/_version.py +2 -2
- junifer/api/__init__.py +4 -1
- junifer/api/cli.py +91 -1
- junifer/api/decorators.py +9 -0
- junifer/api/functions.py +56 -10
- junifer/api/parser.py +3 -0
- junifer/api/queue_context/__init__.py +4 -1
- junifer/api/queue_context/gnu_parallel_local_adapter.py +16 -6
- junifer/api/queue_context/htcondor_adapter.py +16 -5
- junifer/api/queue_context/tests/test_gnu_parallel_local_adapter.py +41 -12
- junifer/api/queue_context/tests/test_htcondor_adapter.py +48 -15
- junifer/api/res/afni/run_afni_docker.sh +1 -1
- junifer/api/res/ants/run_ants_docker.sh +1 -1
- junifer/api/res/freesurfer/mri_binarize +3 -0
- junifer/api/res/freesurfer/mri_mc +3 -0
- junifer/api/res/freesurfer/mri_pretess +3 -0
- junifer/api/res/freesurfer/mris_convert +3 -0
- junifer/api/res/freesurfer/run_freesurfer_docker.sh +61 -0
- junifer/api/res/fsl/run_fsl_docker.sh +1 -1
- junifer/api/res/{run_conda.sh → run_conda.bash} +1 -1
- junifer/api/res/run_conda.zsh +23 -0
- junifer/api/res/run_venv.bash +22 -0
- junifer/api/res/{run_venv.sh → run_venv.zsh} +1 -1
- junifer/api/tests/test_api_utils.py +4 -2
- junifer/api/tests/test_cli.py +83 -0
- junifer/api/tests/test_functions.py +27 -2
- junifer/configs/__init__.py +1 -1
- junifer/configs/juseless/__init__.py +4 -1
- junifer/configs/juseless/datagrabbers/__init__.py +10 -1
- junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +4 -3
- junifer/configs/juseless/datagrabbers/camcan_vbm.py +3 -0
- junifer/configs/juseless/datagrabbers/ixi_vbm.py +4 -3
- junifer/configs/juseless/datagrabbers/tests/test_ucla.py +1 -3
- junifer/configs/juseless/datagrabbers/ucla.py +12 -9
- junifer/configs/juseless/datagrabbers/ukb_vbm.py +3 -0
- junifer/data/__init__.py +21 -1
- junifer/data/coordinates.py +10 -19
- junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
- junifer/data/masks.py +58 -87
- junifer/data/parcellations.py +14 -3
- junifer/data/template_spaces.py +4 -1
- junifer/data/tests/test_masks.py +26 -37
- junifer/data/utils.py +3 -0
- junifer/datagrabber/__init__.py +18 -1
- junifer/datagrabber/aomic/__init__.py +3 -0
- junifer/datagrabber/aomic/id1000.py +70 -37
- junifer/datagrabber/aomic/piop1.py +69 -36
- junifer/datagrabber/aomic/piop2.py +71 -38
- junifer/datagrabber/aomic/tests/test_id1000.py +44 -100
- junifer/datagrabber/aomic/tests/test_piop1.py +65 -108
- junifer/datagrabber/aomic/tests/test_piop2.py +45 -102
- junifer/datagrabber/base.py +13 -6
- junifer/datagrabber/datalad_base.py +13 -1
- junifer/datagrabber/dmcc13_benchmark.py +36 -53
- junifer/datagrabber/hcp1200/__init__.py +3 -0
- junifer/datagrabber/hcp1200/datalad_hcp1200.py +3 -0
- junifer/datagrabber/hcp1200/hcp1200.py +4 -1
- junifer/datagrabber/multiple.py +45 -6
- junifer/datagrabber/pattern.py +170 -62
- junifer/datagrabber/pattern_datalad.py +25 -12
- junifer/datagrabber/pattern_validation_mixin.py +388 -0
- junifer/datagrabber/tests/test_datalad_base.py +4 -4
- junifer/datagrabber/tests/test_dmcc13_benchmark.py +46 -19
- junifer/datagrabber/tests/test_multiple.py +161 -84
- junifer/datagrabber/tests/test_pattern.py +45 -0
- junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
- junifer/datagrabber/tests/test_pattern_validation_mixin.py +249 -0
- junifer/datareader/__init__.py +4 -1
- junifer/datareader/default.py +95 -43
- junifer/external/BrainPrint/brainprint/__init__.py +4 -0
- junifer/external/BrainPrint/brainprint/_version.py +3 -0
- junifer/external/BrainPrint/brainprint/asymmetry.py +91 -0
- junifer/external/BrainPrint/brainprint/brainprint.py +441 -0
- junifer/external/BrainPrint/brainprint/surfaces.py +258 -0
- junifer/external/BrainPrint/brainprint/utils/__init__.py +1 -0
- junifer/external/BrainPrint/brainprint/utils/_config.py +112 -0
- junifer/external/BrainPrint/brainprint/utils/utils.py +188 -0
- junifer/external/__init__.py +1 -1
- junifer/external/nilearn/__init__.py +5 -1
- junifer/external/nilearn/junifer_connectivity_measure.py +483 -0
- junifer/external/nilearn/junifer_nifti_spheres_masker.py +23 -9
- junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +1089 -0
- junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +76 -1
- junifer/markers/__init__.py +23 -1
- junifer/markers/base.py +68 -28
- junifer/markers/brainprint.py +459 -0
- junifer/markers/collection.py +10 -2
- junifer/markers/complexity/__init__.py +10 -0
- junifer/markers/complexity/complexity_base.py +26 -43
- junifer/markers/complexity/hurst_exponent.py +3 -0
- junifer/markers/complexity/multiscale_entropy_auc.py +3 -0
- junifer/markers/complexity/perm_entropy.py +3 -0
- junifer/markers/complexity/range_entropy.py +3 -0
- junifer/markers/complexity/range_entropy_auc.py +3 -0
- junifer/markers/complexity/sample_entropy.py +3 -0
- junifer/markers/complexity/tests/test_hurst_exponent.py +11 -3
- junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +11 -3
- junifer/markers/complexity/tests/test_perm_entropy.py +11 -3
- junifer/markers/complexity/tests/test_range_entropy.py +11 -3
- junifer/markers/complexity/tests/test_range_entropy_auc.py +11 -3
- junifer/markers/complexity/tests/test_sample_entropy.py +11 -3
- junifer/markers/complexity/tests/test_weighted_perm_entropy.py +11 -3
- junifer/markers/complexity/weighted_perm_entropy.py +3 -0
- junifer/markers/ets_rss.py +27 -42
- junifer/markers/falff/__init__.py +3 -0
- junifer/markers/falff/_afni_falff.py +5 -2
- junifer/markers/falff/_junifer_falff.py +3 -0
- junifer/markers/falff/falff_base.py +20 -46
- junifer/markers/falff/falff_parcels.py +56 -27
- junifer/markers/falff/falff_spheres.py +60 -29
- junifer/markers/falff/tests/test_falff_parcels.py +39 -23
- junifer/markers/falff/tests/test_falff_spheres.py +39 -23
- junifer/markers/functional_connectivity/__init__.py +9 -0
- junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +63 -60
- junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +45 -32
- junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +49 -36
- junifer/markers/functional_connectivity/functional_connectivity_base.py +71 -70
- junifer/markers/functional_connectivity/functional_connectivity_parcels.py +34 -25
- junifer/markers/functional_connectivity/functional_connectivity_spheres.py +40 -30
- junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +11 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +27 -7
- junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +28 -12
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +35 -11
- junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +36 -62
- junifer/markers/parcel_aggregation.py +47 -61
- junifer/markers/reho/__init__.py +3 -0
- junifer/markers/reho/_afni_reho.py +5 -2
- junifer/markers/reho/_junifer_reho.py +4 -1
- junifer/markers/reho/reho_base.py +8 -27
- junifer/markers/reho/reho_parcels.py +28 -17
- junifer/markers/reho/reho_spheres.py +27 -18
- junifer/markers/reho/tests/test_reho_parcels.py +8 -3
- junifer/markers/reho/tests/test_reho_spheres.py +8 -3
- junifer/markers/sphere_aggregation.py +43 -59
- junifer/markers/temporal_snr/__init__.py +3 -0
- junifer/markers/temporal_snr/temporal_snr_base.py +23 -32
- junifer/markers/temporal_snr/temporal_snr_parcels.py +9 -6
- junifer/markers/temporal_snr/temporal_snr_spheres.py +9 -6
- junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +6 -3
- junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +6 -3
- junifer/markers/tests/test_brainprint.py +58 -0
- junifer/markers/tests/test_collection.py +9 -8
- junifer/markers/tests/test_ets_rss.py +15 -9
- junifer/markers/tests/test_markers_base.py +17 -18
- junifer/markers/tests/test_parcel_aggregation.py +93 -32
- junifer/markers/tests/test_sphere_aggregation.py +72 -19
- junifer/onthefly/__init__.py +4 -1
- junifer/onthefly/read_transform.py +3 -0
- junifer/pipeline/__init__.py +9 -1
- junifer/pipeline/pipeline_step_mixin.py +21 -4
- junifer/pipeline/registry.py +3 -0
- junifer/pipeline/singleton.py +3 -0
- junifer/pipeline/tests/test_registry.py +1 -1
- junifer/pipeline/update_meta_mixin.py +3 -0
- junifer/pipeline/utils.py +67 -1
- junifer/pipeline/workdir_manager.py +3 -0
- junifer/preprocess/__init__.py +10 -2
- junifer/preprocess/base.py +6 -3
- junifer/preprocess/confounds/__init__.py +3 -0
- junifer/preprocess/confounds/fmriprep_confound_remover.py +47 -60
- junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +72 -113
- junifer/preprocess/smoothing/__init__.py +9 -0
- junifer/preprocess/smoothing/_afni_smoothing.py +119 -0
- junifer/preprocess/smoothing/_fsl_smoothing.py +116 -0
- junifer/preprocess/smoothing/_nilearn_smoothing.py +69 -0
- junifer/preprocess/smoothing/smoothing.py +174 -0
- junifer/preprocess/smoothing/tests/test_smoothing.py +94 -0
- junifer/preprocess/warping/__init__.py +3 -0
- junifer/preprocess/warping/_ants_warper.py +3 -0
- junifer/preprocess/warping/_fsl_warper.py +3 -0
- junifer/stats.py +4 -1
- junifer/storage/__init__.py +9 -1
- junifer/storage/base.py +40 -1
- junifer/storage/hdf5.py +71 -9
- junifer/storage/pandas_base.py +3 -0
- junifer/storage/sqlite.py +3 -0
- junifer/storage/tests/test_hdf5.py +82 -10
- junifer/storage/utils.py +9 -0
- junifer/testing/__init__.py +4 -1
- junifer/testing/datagrabbers.py +13 -6
- junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
- junifer/testing/utils.py +3 -0
- junifer/utils/__init__.py +13 -2
- junifer/utils/fs.py +3 -0
- junifer/utils/helpers.py +32 -1
- junifer/utils/logging.py +33 -4
- junifer/utils/tests/test_logging.py +8 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/METADATA +17 -16
- junifer-0.0.5.dist-info/RECORD +275 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/WHEEL +1 -1
- junifer/datagrabber/tests/test_datagrabber_utils.py +0 -218
- junifer/datagrabber/utils.py +0 -230
- junifer/preprocess/ants/__init__.py +0 -4
- junifer/preprocess/ants/ants_apply_transforms_warper.py +0 -185
- junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +0 -56
- junifer/preprocess/bold_warper.py +0 -265
- junifer/preprocess/fsl/__init__.py +0 -4
- junifer/preprocess/fsl/apply_warper.py +0 -179
- junifer/preprocess/fsl/tests/test_apply_warper.py +0 -45
- junifer/preprocess/tests/test_bold_warper.py +0 -159
- junifer-0.0.4.dev829.dist-info/RECORD +0 -257
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.4.dev829.dist-info → junifer-0.0.5.dist-info}/top_level.txt +0 -0
@@ -25,7 +25,12 @@ from junifer.storage.utils import (
|
|
25
25
|
def test_get_valid_inputs() -> None:
|
26
26
|
"""Test valid inputs."""
|
27
27
|
storage = HDF5FeatureStorage(uri="/tmp")
|
28
|
-
assert storage.get_valid_inputs() == [
|
28
|
+
assert storage.get_valid_inputs() == [
|
29
|
+
"matrix",
|
30
|
+
"vector",
|
31
|
+
"timeseries",
|
32
|
+
"scalar_table",
|
33
|
+
]
|
29
34
|
|
30
35
|
|
31
36
|
def test_single_output(tmp_path: Path) -> None:
|
@@ -808,7 +813,7 @@ def test_store_timeseries(tmp_path: Path) -> None:
|
|
808
813
|
data = np.array([[10], [20], [30], [40], [50]])
|
809
814
|
col_names = ["signal"]
|
810
815
|
|
811
|
-
# Store
|
816
|
+
# Store timeseries
|
812
817
|
storage.store_timeseries(
|
813
818
|
meta_md5=meta_md5,
|
814
819
|
element=element_to_store,
|
@@ -822,6 +827,53 @@ def test_store_timeseries(tmp_path: Path) -> None:
|
|
822
827
|
assert_array_equal(read_df.values, data)
|
823
828
|
|
824
829
|
|
830
|
+
def test_store_scalar_table(tmp_path: Path) -> None:
|
831
|
+
"""Test scalar table store.
|
832
|
+
|
833
|
+
Parameters
|
834
|
+
----------
|
835
|
+
tmp_path : pathlib.Path
|
836
|
+
The path to the test directory.
|
837
|
+
|
838
|
+
"""
|
839
|
+
uri = tmp_path / "test_store_scalar_table.hdf5"
|
840
|
+
storage = HDF5FeatureStorage(uri=uri)
|
841
|
+
# Metadata to store
|
842
|
+
element = {"subject": "test"}
|
843
|
+
meta = {
|
844
|
+
"element": element,
|
845
|
+
"dependencies": ["numpy"],
|
846
|
+
"marker": {"name": "brainprint"},
|
847
|
+
"type": "FreeSurfer",
|
848
|
+
}
|
849
|
+
# Process the metadata
|
850
|
+
meta_md5, meta_to_store, element_to_store = process_meta(meta)
|
851
|
+
# Store metadata
|
852
|
+
storage.store_metadata(
|
853
|
+
meta_md5=meta_md5, element=element_to_store, meta=meta_to_store
|
854
|
+
)
|
855
|
+
|
856
|
+
# Data to store
|
857
|
+
data = np.array([[10, 20], [30, 40], [50, 60]])
|
858
|
+
col_names = ["roi1", "roi2"]
|
859
|
+
row_names = ["ev1", "ev2", "ev3"]
|
860
|
+
|
861
|
+
# Store timeseries
|
862
|
+
storage.store_scalar_table(
|
863
|
+
meta_md5=meta_md5,
|
864
|
+
element=element_to_store,
|
865
|
+
data=data,
|
866
|
+
col_names=col_names,
|
867
|
+
row_names=row_names,
|
868
|
+
row_header_col_name="eigenvalue",
|
869
|
+
)
|
870
|
+
|
871
|
+
# Read into dataframe
|
872
|
+
read_df = storage.read_df(feature_md5=meta_md5)
|
873
|
+
# Check if data are equal
|
874
|
+
assert_array_equal(read_df.values, data)
|
875
|
+
|
876
|
+
|
825
877
|
def _create_data_to_store(n_elements: int, kind: str) -> Tuple[str, Dict]:
|
826
878
|
"""Create data to store.
|
827
879
|
|
@@ -854,13 +906,19 @@ def _create_data_to_store(n_elements: int, kind: str) -> Tuple[str, Dict]:
|
|
854
906
|
"col_names": [f"col-{i}" for i in range(10)],
|
855
907
|
"matrix_kind": "full",
|
856
908
|
}
|
857
|
-
elif kind
|
909
|
+
elif kind in "timeseries":
|
858
910
|
data_to_store = {
|
859
911
|
"data": np.arange(20).reshape(2, 10),
|
860
912
|
"col_names": [f"col-{i}" for i in range(10)],
|
861
913
|
}
|
862
|
-
|
863
|
-
|
914
|
+
elif kind in "scalar_table":
|
915
|
+
data_to_store = {
|
916
|
+
"data": np.arange(50).reshape(5, 10),
|
917
|
+
"row_names": [f"row-{i}" for i in range(5)],
|
918
|
+
"col_names": [f"col-{i}" for i in range(10)],
|
919
|
+
"row_header_col_name": "row",
|
920
|
+
}
|
921
|
+
|
864
922
|
for i in range(n_elements):
|
865
923
|
element = {"subject": f"sub-{i // 2}", "session": f"ses-{i % 2}"}
|
866
924
|
meta = {
|
@@ -903,6 +961,7 @@ def _create_data_to_store(n_elements: int, kind: str) -> Tuple[str, Dict]:
|
|
903
961
|
(10, 3, "matrix"),
|
904
962
|
(10, 5, "matrix"),
|
905
963
|
(10, 5, "timeseries"),
|
964
|
+
(10, 5, "scalar_table"),
|
906
965
|
],
|
907
966
|
)
|
908
967
|
def test_multi_output_store_and_collect(
|
@@ -930,21 +989,20 @@ def test_multi_output_store_and_collect(
|
|
930
989
|
meta_md5, all_data = _create_data_to_store(n_elements, kind)
|
931
990
|
|
932
991
|
for t_data in all_data:
|
933
|
-
# Store metadata
|
992
|
+
# Store metadata
|
934
993
|
storage.store_metadata(
|
935
994
|
meta_md5=meta_md5,
|
936
995
|
element=t_data["element"],
|
937
996
|
meta=t_data["meta"],
|
938
997
|
)
|
998
|
+
# Store data
|
939
999
|
if kind == "vector":
|
940
|
-
# Store tables
|
941
1000
|
storage.store_vector(
|
942
1001
|
meta_md5=meta_md5,
|
943
1002
|
element=t_data["element"],
|
944
1003
|
**t_data["data"],
|
945
1004
|
)
|
946
1005
|
elif kind == "matrix":
|
947
|
-
# Store tables
|
948
1006
|
storage.store_matrix(
|
949
1007
|
meta_md5=meta_md5,
|
950
1008
|
element=t_data["element"],
|
@@ -956,11 +1014,17 @@ def test_multi_output_store_and_collect(
|
|
956
1014
|
element=t_data["element"],
|
957
1015
|
**t_data["data"],
|
958
1016
|
)
|
1017
|
+
elif kind == "scalar_table":
|
1018
|
+
storage.store_scalar_table(
|
1019
|
+
meta_md5=meta_md5,
|
1020
|
+
element=t_data["element"],
|
1021
|
+
**t_data["data"],
|
1022
|
+
)
|
959
1023
|
# Check that base URI does not exist yet
|
960
1024
|
assert not uri.exists()
|
961
1025
|
|
962
1026
|
for t_data in all_data:
|
963
|
-
# Convert element to
|
1027
|
+
# Convert element to prefix
|
964
1028
|
prefix = element_to_prefix(t_data["element"])
|
965
1029
|
# URIs for data storage
|
966
1030
|
elem_uri = uri.parent / f"{prefix}{uri.name}"
|
@@ -977,7 +1041,7 @@ def test_multi_output_store_and_collect(
|
|
977
1041
|
# Check that base URI exists now
|
978
1042
|
assert uri.exists()
|
979
1043
|
|
980
|
-
#
|
1044
|
+
# Read unified metadata
|
981
1045
|
read_unified_meta = storage.list_features()
|
982
1046
|
assert meta_md5 in read_unified_meta
|
983
1047
|
|
@@ -989,6 +1053,10 @@ def test_multi_output_store_and_collect(
|
|
989
1053
|
data_size = np.sum([x["data"]["data"].shape[0] for x in all_data])
|
990
1054
|
assert len(all_df) == data_size
|
991
1055
|
idx_names = [x for x in all_df.index.names if x != "timepoint"]
|
1056
|
+
elif kind == "scalar_table":
|
1057
|
+
data_size = np.sum([x["data"]["data"].shape[0] for x in all_data])
|
1058
|
+
assert len(all_df) == data_size
|
1059
|
+
idx_names = [x for x in all_df.index.names if x != "row"]
|
992
1060
|
else:
|
993
1061
|
assert len(all_df) == len(all_data)
|
994
1062
|
idx_names = all_df.index.names
|
@@ -1013,6 +1081,10 @@ def test_multi_output_store_and_collect(
|
|
1013
1081
|
assert_array_equal(t_series.values, t_data["data"]["data"])
|
1014
1082
|
series_names = t_series.columns.values.tolist()
|
1015
1083
|
assert series_names == t_data["data"]["col_names"]
|
1084
|
+
elif kind == "scalar_table":
|
1085
|
+
assert_array_equal(t_series.values, t_data["data"]["data"])
|
1086
|
+
series_names = t_series.columns.values.tolist()
|
1087
|
+
assert series_names == t_data["data"]["col_names"]
|
1016
1088
|
|
1017
1089
|
|
1018
1090
|
def test_collect_error_single_output() -> None:
|
junifer/storage/utils.py
CHANGED
@@ -14,6 +14,15 @@ import numpy as np
|
|
14
14
|
from ..utils.logging import logger, raise_error
|
15
15
|
|
16
16
|
|
17
|
+
__all__ = [
|
18
|
+
"get_dependency_version",
|
19
|
+
"process_meta",
|
20
|
+
"element_to_prefix",
|
21
|
+
"store_matrix_checks",
|
22
|
+
"matrix_to_vector",
|
23
|
+
]
|
24
|
+
|
25
|
+
|
17
26
|
def get_dependency_version(dependency: str) -> str:
|
18
27
|
"""Get dependency version.
|
19
28
|
|
junifer/testing/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Testing components."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -6,3 +6,6 @@
|
|
6
6
|
|
7
7
|
from . import datagrabbers
|
8
8
|
from .utils import get_testing_data
|
9
|
+
|
10
|
+
|
11
|
+
__all__ = ["datagrabbers", "get_testing_data"]
|
junifer/testing/datagrabbers.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Testing DataGrabbers."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -14,6 +14,13 @@ from nilearn import datasets, image
|
|
14
14
|
from ..datagrabber.base import BaseDataGrabber
|
15
15
|
|
16
16
|
|
17
|
+
__all__ = [
|
18
|
+
"OasisVBMTestingDataGrabber",
|
19
|
+
"SPMAuditoryTestingDataGrabber",
|
20
|
+
"PartlyCloudyTestingDataGrabber",
|
21
|
+
]
|
22
|
+
|
23
|
+
|
17
24
|
class OasisVBMTestingDataGrabber(BaseDataGrabber):
|
18
25
|
"""DataGrabber for Oasis VBM testing data.
|
19
26
|
|
@@ -181,7 +188,7 @@ class PartlyCloudyTestingDataGrabber(BaseDataGrabber):
|
|
181
188
|
"""Initialize the class."""
|
182
189
|
datadir = tempfile.mkdtemp()
|
183
190
|
# Define types
|
184
|
-
types = ["BOLD"
|
191
|
+
types = ["BOLD"]
|
185
192
|
self.reduce_confounds = reduce_confounds
|
186
193
|
self.age_group = age_group
|
187
194
|
super().__init__(types=types, datadir=datadir)
|
@@ -242,10 +249,10 @@ class PartlyCloudyTestingDataGrabber(BaseDataGrabber):
|
|
242
249
|
out["BOLD"] = {
|
243
250
|
"path": Path(self._dataset["func"][i_sub]),
|
244
251
|
"space": "MNI152NLin2009cAsym",
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
252
|
+
"confounds": {
|
253
|
+
"path": Path(self._dataset["confounds"][i_sub]),
|
254
|
+
"format": "fmriprep",
|
255
|
+
},
|
249
256
|
}
|
250
257
|
|
251
258
|
return out
|
@@ -28,13 +28,13 @@ def test_PartlyCloudyTestingDataGrabber() -> None:
|
|
28
28
|
assert out["BOLD"]["path"].exists()
|
29
29
|
assert out["BOLD"]["path"].is_file()
|
30
30
|
|
31
|
-
assert "
|
32
|
-
assert out["
|
33
|
-
assert out["
|
34
|
-
assert "format" in out["
|
35
|
-
assert "fmriprep" == out["
|
31
|
+
assert "confounds" in out["BOLD"]
|
32
|
+
assert out["BOLD"]["confounds"]["path"].exists()
|
33
|
+
assert out["BOLD"]["confounds"]["path"].is_file()
|
34
|
+
assert "format" in out["BOLD"]["confounds"]
|
35
|
+
assert "fmriprep" == out["BOLD"]["confounds"]["format"]
|
36
36
|
|
37
37
|
with PartlyCloudyTestingDataGrabber(reduce_confounds=False) as dg:
|
38
38
|
out = dg["sub-01"]
|
39
|
-
assert "format" in out["
|
40
|
-
assert "fmriprep" == out["
|
39
|
+
assert "format" in out["BOLD"]["confounds"]
|
40
|
+
assert "fmriprep" == out["BOLD"]["confounds"]["format"]
|
junifer/testing/utils.py
CHANGED
junifer/utils/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""General utilities and helpers."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -6,4 +6,15 @@
|
|
6
6
|
|
7
7
|
from .fs import make_executable
|
8
8
|
from .logging import configure_logging, logger, raise_error, warn_with_log
|
9
|
-
from .helpers import run_ext_cmd
|
9
|
+
from .helpers import run_ext_cmd, deep_update
|
10
|
+
|
11
|
+
|
12
|
+
__all__ = [
|
13
|
+
"make_executable",
|
14
|
+
"configure_logging",
|
15
|
+
"logger",
|
16
|
+
"raise_error",
|
17
|
+
"warn_with_log",
|
18
|
+
"run_ext_cmd",
|
19
|
+
"deep_update",
|
20
|
+
]
|
junifer/utils/fs.py
CHANGED
junifer/utils/helpers.py
CHANGED
@@ -3,12 +3,16 @@
|
|
3
3
|
# Authors: Synchon Mandal <s.mandal@fz-juelich.de>
|
4
4
|
# License: AGPL
|
5
5
|
|
6
|
+
import collections.abc
|
6
7
|
import subprocess
|
7
|
-
from typing import List
|
8
|
+
from typing import Dict, List
|
8
9
|
|
9
10
|
from .logging import logger, raise_error
|
10
11
|
|
11
12
|
|
13
|
+
__all__ = ["run_ext_cmd", "deep_update"]
|
14
|
+
|
15
|
+
|
12
16
|
def run_ext_cmd(name: str, cmd: List[str]) -> None:
|
13
17
|
"""Run external command via subprocess.
|
14
18
|
|
@@ -51,3 +55,30 @@ def run_ext_cmd(name: str, cmd: List[str]) -> None:
|
|
51
55
|
),
|
52
56
|
klass=RuntimeError,
|
53
57
|
)
|
58
|
+
|
59
|
+
|
60
|
+
def deep_update(d: Dict, u: Dict) -> Dict:
|
61
|
+
"""Deep update `d` with `u`.
|
62
|
+
|
63
|
+
From: "https://stackoverflow.com/questions/3232943/update-value-of-a-nested
|
64
|
+
-dictionary-of-varying-depth"
|
65
|
+
|
66
|
+
Parameters
|
67
|
+
----------
|
68
|
+
d : dict
|
69
|
+
The dictionary to deep-update.
|
70
|
+
u : dict
|
71
|
+
The dictionary to deep-update `d` with.
|
72
|
+
|
73
|
+
Returns
|
74
|
+
-------
|
75
|
+
dict
|
76
|
+
The updated dictionary.
|
77
|
+
|
78
|
+
"""
|
79
|
+
for k, v in u.items():
|
80
|
+
if isinstance(v, collections.abc.Mapping):
|
81
|
+
d[k] = deep_update(d.get(k, {}), v)
|
82
|
+
else:
|
83
|
+
d[k] = v
|
84
|
+
return d
|
junifer/utils/logging.py
CHANGED
@@ -4,13 +4,16 @@
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
|
7
|
+
import sys
|
8
|
+
|
9
|
+
|
10
|
+
if sys.version_info < (3, 12):
|
8
11
|
from distutils.version import LooseVersion
|
9
|
-
|
12
|
+
else: # pragma: no cover
|
10
13
|
from looseversion import LooseVersion
|
11
14
|
|
12
15
|
import logging
|
13
|
-
import
|
16
|
+
import warnings
|
14
17
|
from pathlib import Path
|
15
18
|
from subprocess import PIPE, Popen, TimeoutExpired
|
16
19
|
from typing import Dict, NoReturn, Optional, Type, Union
|
@@ -19,6 +22,16 @@ from warnings import warn
|
|
19
22
|
import datalad
|
20
23
|
|
21
24
|
|
25
|
+
__all__ = [
|
26
|
+
"WrapStdOut",
|
27
|
+
"get_versions",
|
28
|
+
"log_versions",
|
29
|
+
"configure_logging",
|
30
|
+
"raise_error",
|
31
|
+
"warn_with_log",
|
32
|
+
]
|
33
|
+
|
34
|
+
|
22
35
|
logger = logging.getLogger("JUNIFER")
|
23
36
|
|
24
37
|
# Set up datalad logger level to warning by default
|
@@ -32,6 +45,23 @@ _logging_types = {
|
|
32
45
|
}
|
33
46
|
|
34
47
|
|
48
|
+
# Copied over from stdlib and tweaked to our use-case.
|
49
|
+
def _showwarning(message, category, filename, lineno, file=None, line=None):
|
50
|
+
s = warnings.formatwarning(message, category, filename, lineno, line)
|
51
|
+
logger.warning(str(s))
|
52
|
+
|
53
|
+
|
54
|
+
# Overwrite warnings display to integrate with logging
|
55
|
+
|
56
|
+
|
57
|
+
def capture_warnings():
|
58
|
+
"""Capture warnings and log them."""
|
59
|
+
warnings.showwarning = _showwarning
|
60
|
+
|
61
|
+
|
62
|
+
capture_warnings()
|
63
|
+
|
64
|
+
|
35
65
|
class WrapStdOut(logging.StreamHandler):
|
36
66
|
"""Dynamically wrap to sys.stdout.
|
37
67
|
|
@@ -313,5 +343,4 @@ def warn_with_log(
|
|
313
343
|
The warning subclass (default RuntimeWarning).
|
314
344
|
|
315
345
|
"""
|
316
|
-
logger.warning(msg)
|
317
346
|
warn(msg, category=category, stacklevel=2)
|
@@ -145,8 +145,16 @@ def test_log_file(tmp_path: Path) -> None:
|
|
145
145
|
assert any("Warn3 message" in line for line in lines)
|
146
146
|
assert any("Error3 message" in line for line in lines)
|
147
147
|
|
148
|
+
# This should raise a warning (test that it was raised)
|
148
149
|
with pytest.warns(RuntimeWarning, match=r"Warn raised"):
|
149
150
|
warn_with_log("Warn raised")
|
151
|
+
|
152
|
+
# This should log the warning (workaround for pytest messing with logging)
|
153
|
+
from junifer.utils.logging import capture_warnings
|
154
|
+
|
155
|
+
capture_warnings()
|
156
|
+
|
157
|
+
warn_with_log("Warn raised 2")
|
150
158
|
with pytest.raises(ValueError, match=r"Error raised"):
|
151
159
|
raise_error("Error raised")
|
152
160
|
with open(tmp_path / "test4.log") as f:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: junifer
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.5
|
4
4
|
Summary: JUelich NeuroImaging FEature extractoR
|
5
5
|
Author-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
6
6
|
Maintainer-email: Fede Raimondo <f.raimondo@fz-juelich.de>, Synchon Mandal <s.mandal@fz-juelich.de>
|
@@ -29,19 +29,20 @@ Description-Content-Type: text/markdown
|
|
29
29
|
License-File: LICENSE.md
|
30
30
|
License-File: AUTHORS.rst
|
31
31
|
Requires-Dist: click <8.2,>=8.1.3
|
32
|
-
Requires-Dist: numpy <
|
33
|
-
Requires-Dist: scipy <=1.
|
34
|
-
Requires-Dist: datalad <0.
|
35
|
-
Requires-Dist: pandas <2.2
|
36
|
-
Requires-Dist: nibabel <5.
|
37
|
-
Requires-Dist: nilearn <=0.10.
|
38
|
-
Requires-Dist: sqlalchemy <=2.1.0,>=
|
32
|
+
Requires-Dist: numpy <2.0.0,>=1.24.0
|
33
|
+
Requires-Dist: scipy <=1.14.0,>=1.10.0
|
34
|
+
Requires-Dist: datalad <1.2.0,>=1.0.0
|
35
|
+
Requires-Dist: pandas <2.3.0,>=2.0.0
|
36
|
+
Requires-Dist: nibabel <5.3.0,>=5.2.0
|
37
|
+
Requires-Dist: nilearn <=0.10.4,>=0.10.3
|
38
|
+
Requires-Dist: sqlalchemy <=2.1.0,>=2.0.25
|
39
39
|
Requires-Dist: ruamel.yaml <0.18,>=0.17
|
40
40
|
Requires-Dist: h5py >=3.10
|
41
41
|
Requires-Dist: httpx[http2] ==0.26.0
|
42
42
|
Requires-Dist: tqdm ==4.66.1
|
43
43
|
Requires-Dist: templateflow >=23.0.0
|
44
|
-
Requires-Dist:
|
44
|
+
Requires-Dist: lapy <2.0.0,>=1.0.0
|
45
|
+
Requires-Dist: importlib-metadata ; python_version < "3.9"
|
45
46
|
Requires-Dist: looseversion ==1.3.0 ; python_version >= "3.12"
|
46
47
|
Provides-Extra: all
|
47
48
|
Requires-Dist: bctpy ==0.6.0 ; extra == 'all'
|
@@ -52,14 +53,14 @@ Provides-Extra: dev
|
|
52
53
|
Requires-Dist: tox ; extra == 'dev'
|
53
54
|
Requires-Dist: pre-commit ; extra == 'dev'
|
54
55
|
Provides-Extra: docs
|
55
|
-
Requires-Dist: seaborn <0.
|
56
|
-
Requires-Dist: sphinx <7.
|
57
|
-
Requires-Dist: sphinx-gallery <0.
|
58
|
-
Requires-Dist: furo <
|
59
|
-
Requires-Dist: numpydoc <1.
|
60
|
-
Requires-Dist: julearn
|
56
|
+
Requires-Dist: seaborn <0.14.0,>=0.13.0 ; extra == 'docs'
|
57
|
+
Requires-Dist: sphinx <7.4.0,>=7.3.0 ; extra == 'docs'
|
58
|
+
Requires-Dist: sphinx-gallery <0.17.0,>=0.15.0 ; extra == 'docs'
|
59
|
+
Requires-Dist: furo <2024.6.0,>=2024.4.27 ; extra == 'docs'
|
60
|
+
Requires-Dist: numpydoc <1.8.0,>=1.6.0 ; extra == 'docs'
|
61
|
+
Requires-Dist: julearn ==0.3.3 ; extra == 'docs'
|
61
62
|
Requires-Dist: sphinx-copybutton <0.5.3,>=0.5.1 ; extra == 'docs'
|
62
|
-
Requires-Dist: towncrier <23.
|
63
|
+
Requires-Dist: towncrier <23.12.0,>=23.10.0 ; extra == 'docs'
|
63
64
|
Requires-Dist: sphinxcontrib-mermaid <0.10,>=0.8.1 ; extra == 'docs'
|
64
65
|
Provides-Extra: neurokit2
|
65
66
|
Requires-Dist: neurokit2 >=0.1.7 ; extra == 'neurokit2'
|