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
|
@@ -7,64 +7,50 @@
|
|
|
7
7
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
+
import datalad.api as dl
|
|
10
11
|
import pytest
|
|
12
|
+
from pydantic import AnyUrl
|
|
11
13
|
|
|
12
|
-
from junifer.datagrabber import PatternDataladDataGrabber
|
|
14
|
+
from junifer.datagrabber import DataType, PatternDataladDataGrabber
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
_testing_dataset = {
|
|
16
18
|
"example_bids": {
|
|
17
|
-
"uri":
|
|
19
|
+
"uri": (
|
|
20
|
+
"https://cerebra.fz-juelich.de/junifer/datalad-example-bids.git"
|
|
21
|
+
),
|
|
18
22
|
"commit": "3f288c8725207ae0c9b3616e093e78cda192b570",
|
|
19
23
|
"id": "8fddff30-6993-420a-9d1e-b5b028c59468",
|
|
20
24
|
},
|
|
21
25
|
"example_bids_ses": {
|
|
22
|
-
"uri":
|
|
26
|
+
"uri": (
|
|
27
|
+
"https://cerebra.fz-juelich.de/junifer/datalad-example-bids-ses.git"
|
|
28
|
+
),
|
|
23
29
|
"commit": "6b163aa98af76a9eac0272273c27e14127850181",
|
|
24
30
|
"id": "715c17cf-a1b9-42d6-9af8-9f74c1a4a724",
|
|
25
31
|
},
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
|
|
29
|
-
def test_bids_PatternDataladDataGrabber_missing_uri() -> None:
|
|
30
|
-
"""Test check of missing URI in PatternDataladDataGrabber."""
|
|
31
|
-
with pytest.raises(ValueError, match=r"`uri` must be provided"):
|
|
32
|
-
PatternDataladDataGrabber(
|
|
33
|
-
datadir=None,
|
|
34
|
-
types=[],
|
|
35
|
-
patterns={},
|
|
36
|
-
replacements=[],
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
35
|
def test_bids_PatternDataladDataGrabber() -> None:
|
|
41
36
|
"""Test subject-based BIDS PatternDataladDataGrabber."""
|
|
42
|
-
# Define types
|
|
43
|
-
types = ["T1w", "BOLD"]
|
|
44
|
-
# Define patterns
|
|
45
|
-
patterns = {
|
|
46
|
-
"T1w": {
|
|
47
|
-
"pattern": "{subject}/anat/{subject}_T1w.nii.gz",
|
|
48
|
-
"space": "MNI152NLin6Asym",
|
|
49
|
-
},
|
|
50
|
-
"BOLD": {
|
|
51
|
-
"pattern": "{subject}/func/{subject}_task-rest_bold.nii.gz",
|
|
52
|
-
"space": "MNI152NLin6Asym",
|
|
53
|
-
},
|
|
54
|
-
}
|
|
55
|
-
# Define replacements
|
|
56
|
-
replacements = ["subject"]
|
|
57
|
-
|
|
58
|
-
repo_uri = _testing_dataset["example_bids"]["uri"]
|
|
59
|
-
rootdir = "example_bids"
|
|
60
37
|
repo_commit = _testing_dataset["example_bids"]["commit"]
|
|
61
|
-
|
|
38
|
+
repo_uri = _testing_dataset["example_bids"]["uri"]
|
|
62
39
|
with PatternDataladDataGrabber(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
40
|
+
uri=AnyUrl(repo_uri),
|
|
41
|
+
types=[DataType.T1w, DataType.BOLD],
|
|
42
|
+
patterns={
|
|
43
|
+
"T1w": {
|
|
44
|
+
"pattern": "{subject}/anat/{subject}_T1w.nii.gz",
|
|
45
|
+
"space": "MNI152NLin6Asym",
|
|
46
|
+
},
|
|
47
|
+
"BOLD": {
|
|
48
|
+
"pattern": "{subject}/func/{subject}_task-rest_bold.nii.gz",
|
|
49
|
+
"space": "MNI152NLin6Asym",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
replacements=["subject"],
|
|
53
|
+
rootdir=Path("example_bids"),
|
|
68
54
|
) as dg:
|
|
69
55
|
subs = list(dg)
|
|
70
56
|
expected_subs = [f"sub-{i:02d}" for i in range(1, 10)]
|
|
@@ -74,11 +60,11 @@ def test_bids_PatternDataladDataGrabber() -> None:
|
|
|
74
60
|
t_sub = dg[elem]
|
|
75
61
|
assert "path" in t_sub["T1w"]
|
|
76
62
|
assert t_sub["T1w"]["path"] == (
|
|
77
|
-
dg.
|
|
63
|
+
dg.fulldir / f"{elem}/anat/{elem}_T1w.nii.gz"
|
|
78
64
|
)
|
|
79
65
|
assert "path" in t_sub["BOLD"]
|
|
80
66
|
assert t_sub["BOLD"]["path"] == (
|
|
81
|
-
dg.
|
|
67
|
+
dg.fulldir / f"{elem}/func/{elem}_task-rest_bold.nii.gz"
|
|
82
68
|
)
|
|
83
69
|
|
|
84
70
|
assert "meta" in t_sub["BOLD"]
|
|
@@ -88,7 +74,7 @@ def test_bids_PatternDataladDataGrabber() -> None:
|
|
|
88
74
|
assert "class" in dg_meta
|
|
89
75
|
assert dg_meta["class"] == "PatternDataladDataGrabber"
|
|
90
76
|
assert "uri" in dg_meta
|
|
91
|
-
assert dg_meta["uri"] == repo_uri
|
|
77
|
+
assert str(dg_meta["uri"]) == repo_uri
|
|
92
78
|
assert "datalad_commit_id" in dg_meta
|
|
93
79
|
assert dg_meta["datalad_commit_id"] == repo_commit
|
|
94
80
|
|
|
@@ -98,80 +84,67 @@ def test_bids_PatternDataladDataGrabber() -> None:
|
|
|
98
84
|
|
|
99
85
|
def test_bids_PatternDataladDataGrabber_datadir() -> None:
|
|
100
86
|
"""Test PatternDataladDataGrabber with a datadir set to a relative path."""
|
|
101
|
-
#
|
|
102
|
-
patterns = {
|
|
103
|
-
"T1w": {
|
|
104
|
-
"pattern": "{subject}/anat/{subject}_T*w.nii.gz",
|
|
105
|
-
"space": "MNI152NLin6Asym",
|
|
106
|
-
},
|
|
107
|
-
"BOLD": {
|
|
108
|
-
"pattern": "{subject}/func/{subject}_task-rest_*.nii.gz",
|
|
109
|
-
"space": "MNI152NLin6Asym",
|
|
110
|
-
},
|
|
111
|
-
}
|
|
112
|
-
# Define datadir
|
|
113
|
-
datadir = "dataset" # use string and not absolute path
|
|
87
|
+
datadir = Path("dataset") # use string and not absolute path
|
|
114
88
|
with PatternDataladDataGrabber(
|
|
115
|
-
uri=_testing_dataset["example_bids"]["uri"],
|
|
116
|
-
types=[
|
|
117
|
-
patterns=
|
|
118
|
-
|
|
119
|
-
|
|
89
|
+
uri=AnyUrl(_testing_dataset["example_bids"]["uri"]),
|
|
90
|
+
types=[DataType.T1w, DataType.BOLD],
|
|
91
|
+
patterns={
|
|
92
|
+
"T1w": {
|
|
93
|
+
"pattern": "{subject}/anat/{subject}_T*w.nii.gz",
|
|
94
|
+
"space": "MNI152NLin6Asym",
|
|
95
|
+
},
|
|
96
|
+
"BOLD": {
|
|
97
|
+
"pattern": "{subject}/func/{subject}_task-rest_*bold.nii.gz",
|
|
98
|
+
"space": "MNI152NLin6Asym",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
120
101
|
replacements=["subject"],
|
|
102
|
+
datadir=datadir,
|
|
103
|
+
rootdir=Path("example_bids"),
|
|
121
104
|
) as dg:
|
|
122
|
-
assert dg.
|
|
105
|
+
assert dg.fulldir == Path(datadir) / "example_bids"
|
|
106
|
+
assert len(dg.get_elements()) > 0
|
|
123
107
|
for elem in dg:
|
|
124
108
|
t_sub = dg[elem]
|
|
109
|
+
# The paths are absolute
|
|
125
110
|
assert "path" in t_sub["T1w"]
|
|
126
111
|
assert t_sub["T1w"]["path"] == (
|
|
127
|
-
dg.
|
|
112
|
+
dg.fulldir.absolute() / f"{elem}/anat/{elem}_T1w.nii.gz"
|
|
128
113
|
)
|
|
129
114
|
assert "path" in t_sub["BOLD"]
|
|
130
115
|
assert t_sub["BOLD"]["path"] == (
|
|
131
|
-
dg.
|
|
116
|
+
dg.fulldir.absolute()
|
|
117
|
+
/ f"{elem}/func/{elem}_task-rest_bold.nii.gz"
|
|
132
118
|
)
|
|
133
119
|
|
|
134
120
|
|
|
135
121
|
def test_bids_PatternDataladDataGrabber_session():
|
|
136
122
|
"""Test a subject and session-based BIDS PatternDataladDataGrabber."""
|
|
137
|
-
types = ["T1w", "BOLD"]
|
|
138
|
-
patterns = {
|
|
139
|
-
"T1w": {
|
|
140
|
-
"pattern": (
|
|
141
|
-
"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz"
|
|
142
|
-
),
|
|
143
|
-
"space": "MNI152NLin6Asym",
|
|
144
|
-
},
|
|
145
|
-
"BOLD": {
|
|
146
|
-
"pattern": (
|
|
147
|
-
"{subject}/{session}/func/"
|
|
148
|
-
"{subject}_{session}_task-rest_bold.nii.gz"
|
|
149
|
-
),
|
|
150
|
-
"space": "MNI152NLin6Asym",
|
|
151
|
-
},
|
|
152
|
-
}
|
|
153
|
-
replacements = ["subject", "session"]
|
|
154
|
-
|
|
155
|
-
# Check error
|
|
156
|
-
with pytest.raises(ValueError, match=r"`uri` must be provided"):
|
|
157
|
-
PatternDataladDataGrabber(
|
|
158
|
-
datadir=None,
|
|
159
|
-
types=types,
|
|
160
|
-
patterns=patterns,
|
|
161
|
-
replacements=replacements,
|
|
162
|
-
)
|
|
163
|
-
|
|
164
123
|
# Set parameters
|
|
165
|
-
repo_uri = _testing_dataset["example_bids_ses"]["uri"]
|
|
166
|
-
rootdir = "example_bids_ses"
|
|
167
|
-
|
|
124
|
+
repo_uri = AnyUrl(_testing_dataset["example_bids_ses"]["uri"])
|
|
125
|
+
rootdir = Path("example_bids_ses")
|
|
126
|
+
replacements = ["subject", "session"]
|
|
168
127
|
# With T1W and bold, only 2 sessions are available
|
|
169
128
|
with PatternDataladDataGrabber(
|
|
170
|
-
rootdir=rootdir,
|
|
171
129
|
uri=repo_uri,
|
|
172
|
-
types=
|
|
173
|
-
patterns=
|
|
130
|
+
types=[DataType.T1w, DataType.BOLD],
|
|
131
|
+
patterns={
|
|
132
|
+
"T1w": {
|
|
133
|
+
"pattern": (
|
|
134
|
+
"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz"
|
|
135
|
+
),
|
|
136
|
+
"space": "MNI152NLin6Asym",
|
|
137
|
+
},
|
|
138
|
+
"BOLD": {
|
|
139
|
+
"pattern": (
|
|
140
|
+
"{subject}/{session}/func/"
|
|
141
|
+
"{subject}_{session}_task-rest_bold.nii.gz"
|
|
142
|
+
),
|
|
143
|
+
"space": "MNI152NLin6Asym",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
174
146
|
replacements=replacements,
|
|
147
|
+
rootdir=rootdir,
|
|
175
148
|
) as dg:
|
|
176
149
|
subs = list(dg.get_elements())
|
|
177
150
|
expected_subs = [
|
|
@@ -182,21 +155,19 @@ def test_bids_PatternDataladDataGrabber_session():
|
|
|
182
155
|
assert set(subs) == set(expected_subs)
|
|
183
156
|
|
|
184
157
|
# Test with a different T1w only, it should have 3 sessions
|
|
185
|
-
types = ["T1w"]
|
|
186
|
-
patterns = {
|
|
187
|
-
"T1w": {
|
|
188
|
-
"pattern": (
|
|
189
|
-
"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz"
|
|
190
|
-
),
|
|
191
|
-
"space": "MNI152NLin6Asym",
|
|
192
|
-
},
|
|
193
|
-
}
|
|
194
158
|
with PatternDataladDataGrabber(
|
|
195
|
-
rootdir=rootdir,
|
|
196
159
|
uri=repo_uri,
|
|
197
|
-
types=
|
|
198
|
-
patterns=
|
|
160
|
+
types=DataType.T1w,
|
|
161
|
+
patterns={
|
|
162
|
+
"T1w": {
|
|
163
|
+
"pattern": (
|
|
164
|
+
"{subject}/{session}/anat/{subject}_{session}_T1w.nii.gz"
|
|
165
|
+
),
|
|
166
|
+
"space": "MNI152NLin6Asym",
|
|
167
|
+
},
|
|
168
|
+
},
|
|
199
169
|
replacements=replacements,
|
|
170
|
+
rootdir=rootdir,
|
|
200
171
|
) as dg:
|
|
201
172
|
subs = list(dg)
|
|
202
173
|
expected_subs = [
|
|
@@ -205,3 +176,102 @@ def test_bids_PatternDataladDataGrabber_session():
|
|
|
205
176
|
for i in range(1, 10)
|
|
206
177
|
]
|
|
207
178
|
assert set(subs) == set(expected_subs)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@pytest.fixture
|
|
182
|
+
def subdatasets_uri(tmp_path: Path) -> AnyUrl:
|
|
183
|
+
"""Return the URI of a dataset with a sub-dataset for each subject.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
tmp_path : pathlib.Path
|
|
188
|
+
The path to the test directory.
|
|
189
|
+
|
|
190
|
+
"""
|
|
191
|
+
dataset = dl.create(tmp_path / "origin", result_renderer="disabled")
|
|
192
|
+
for subject in ("sub-01", "sub-02"):
|
|
193
|
+
subdataset = dataset.create(subject, result_renderer="disabled")
|
|
194
|
+
(subdataset.pathobj / "T1w.nii").write_text(subject)
|
|
195
|
+
(dataset.pathobj / f"{subject}_T1w.nii").write_text(subject)
|
|
196
|
+
dataset.save(recursive=True, result_renderer="disabled")
|
|
197
|
+
return AnyUrl(f"file://{dataset.path}")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@pytest.mark.parametrize(
|
|
201
|
+
"pattern",
|
|
202
|
+
["{subject}/T1w.nii", "{subject}/T1*.nii"],
|
|
203
|
+
)
|
|
204
|
+
def test_PatternDataladDataGrabber_subdatasets_search(
|
|
205
|
+
tmp_path: Path, subdatasets_uri: AnyUrl, pattern: str
|
|
206
|
+
) -> None:
|
|
207
|
+
"""Test searching the files of the sub-datasets raises an error.
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
tmp_path : pathlib.Path
|
|
212
|
+
The path to the test directory.
|
|
213
|
+
subdatasets_uri : pydantic.AnyUrl
|
|
214
|
+
The URI of the dataset with a sub-dataset for each subject.
|
|
215
|
+
pattern : str
|
|
216
|
+
The parametrized pattern, which searches the files of the
|
|
217
|
+
sub-datasets.
|
|
218
|
+
|
|
219
|
+
"""
|
|
220
|
+
dg = PatternDataladDataGrabber(
|
|
221
|
+
uri=subdatasets_uri,
|
|
222
|
+
datadir=tmp_path / "clone",
|
|
223
|
+
types=["T1w"],
|
|
224
|
+
patterns={"T1w": {"pattern": pattern, "space": "native"}},
|
|
225
|
+
replacements=["subject"],
|
|
226
|
+
)
|
|
227
|
+
with pytest.raises(RuntimeError, match="searches the files of the"):
|
|
228
|
+
with dg:
|
|
229
|
+
pass
|
|
230
|
+
# The cloned dataset is removed
|
|
231
|
+
assert not (tmp_path / "clone").exists() or not any(
|
|
232
|
+
(tmp_path / "clone").iterdir()
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def test_PatternDataladDataGrabber_subdatasets_files(
|
|
237
|
+
tmp_path: Path, subdatasets_uri: AnyUrl
|
|
238
|
+
) -> None:
|
|
239
|
+
"""Test the patterns of a dataset with sub-datasets.
|
|
240
|
+
|
|
241
|
+
The files of the dataset can be searched, and the patterns without
|
|
242
|
+
wildcards can have files in the sub-datasets.
|
|
243
|
+
|
|
244
|
+
Parameters
|
|
245
|
+
----------
|
|
246
|
+
tmp_path : pathlib.Path
|
|
247
|
+
The path to the test directory.
|
|
248
|
+
subdatasets_uri : pydantic.AnyUrl
|
|
249
|
+
The URI of the dataset with a sub-dataset for each subject.
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
dg = PatternDataladDataGrabber(
|
|
253
|
+
uri=subdatasets_uri,
|
|
254
|
+
datadir=tmp_path / "clone",
|
|
255
|
+
types=["T1w"],
|
|
256
|
+
patterns={"T1w": {"pattern": "{subject}_T1w.nii", "space": "native"}},
|
|
257
|
+
replacements=["subject"],
|
|
258
|
+
)
|
|
259
|
+
with dg:
|
|
260
|
+
assert dg.get_elements() == ["sub-01", "sub-02"]
|
|
261
|
+
assert dg["sub-02"]["T1w"]["path"].read_text() == "sub-02"
|
|
262
|
+
# A pattern without wildcards in a sub-dataset
|
|
263
|
+
dg = PatternDataladDataGrabber(
|
|
264
|
+
uri=subdatasets_uri,
|
|
265
|
+
datadir=tmp_path / "clone",
|
|
266
|
+
types=["T1w"],
|
|
267
|
+
patterns={
|
|
268
|
+
"T1w": {
|
|
269
|
+
"pattern": "{subject}_T1w.nii",
|
|
270
|
+
"space": "native",
|
|
271
|
+
"mask": {"pattern": "sub-01/T1w.nii", "space": "native"},
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
replacements=["subject"],
|
|
275
|
+
)
|
|
276
|
+
with dg:
|
|
277
|
+
assert dg.get_elements() == ["sub-01", "sub-02"]
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
# License: AGPL
|
|
6
6
|
|
|
7
7
|
from contextlib import AbstractContextManager, nullcontext
|
|
8
|
-
from typing import Union
|
|
9
8
|
|
|
10
9
|
import pytest
|
|
11
10
|
|
|
12
|
-
from junifer.datagrabber
|
|
11
|
+
from junifer.datagrabber import (
|
|
12
|
+
DataType,
|
|
13
13
|
DataTypeManager,
|
|
14
14
|
DataTypeSchema,
|
|
15
15
|
PatternValidationMixin,
|
|
@@ -80,7 +80,7 @@ def test_dtype_mgr(dtype: DataTypeSchema) -> None:
|
|
|
80
80
|
|
|
81
81
|
Parameters
|
|
82
82
|
----------
|
|
83
|
-
dtype : DataTypeSchema
|
|
83
|
+
dtype : ``DataTypeSchema``
|
|
84
84
|
The parametrized schema.
|
|
85
85
|
|
|
86
86
|
"""
|
|
@@ -111,33 +111,15 @@ def test_register_data_type() -> None:
|
|
|
111
111
|
)
|
|
112
112
|
|
|
113
113
|
assert "dtype" in DataTypeManager()
|
|
114
|
+
assert "dtype" in list(DataType)
|
|
114
115
|
_ = DataTypeManager().pop("dtype")
|
|
115
|
-
assert "
|
|
116
|
+
assert "dtype" not in DataTypeManager()
|
|
117
|
+
assert "dtype" in list(DataType)
|
|
116
118
|
|
|
117
119
|
|
|
118
120
|
@pytest.mark.parametrize(
|
|
119
121
|
"types, replacements, patterns, expect",
|
|
120
122
|
[
|
|
121
|
-
(
|
|
122
|
-
"wrong",
|
|
123
|
-
[],
|
|
124
|
-
{},
|
|
125
|
-
pytest.raises(TypeError, match="`types` must be a list"),
|
|
126
|
-
),
|
|
127
|
-
(
|
|
128
|
-
[1],
|
|
129
|
-
[],
|
|
130
|
-
{},
|
|
131
|
-
pytest.raises(
|
|
132
|
-
TypeError, match="`types` must be a list of strings"
|
|
133
|
-
),
|
|
134
|
-
),
|
|
135
|
-
(
|
|
136
|
-
["BOLD"],
|
|
137
|
-
[],
|
|
138
|
-
"wrong",
|
|
139
|
-
pytest.raises(TypeError, match="`patterns` must be a dict"),
|
|
140
|
-
),
|
|
141
123
|
(
|
|
142
124
|
["T1w", "BOLD"],
|
|
143
125
|
"",
|
|
@@ -205,30 +187,6 @@ def test_register_data_type() -> None:
|
|
|
205
187
|
},
|
|
206
188
|
pytest.raises(ValueError, match="following a replacement"),
|
|
207
189
|
),
|
|
208
|
-
(
|
|
209
|
-
["T1w"],
|
|
210
|
-
"wrong",
|
|
211
|
-
{
|
|
212
|
-
"T1w": {
|
|
213
|
-
"pattern": "{subject}/anat/{subject}_T1w.nii",
|
|
214
|
-
"space": "native",
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
pytest.raises(TypeError, match="`replacements` must be a list"),
|
|
218
|
-
),
|
|
219
|
-
(
|
|
220
|
-
["T1w"],
|
|
221
|
-
[1],
|
|
222
|
-
{
|
|
223
|
-
"T1w": {
|
|
224
|
-
"pattern": "{subject}/anat/{subject}_T1w.nii",
|
|
225
|
-
"space": "native",
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
pytest.raises(
|
|
229
|
-
TypeError, match="`replacements` must be a list of strings"
|
|
230
|
-
),
|
|
231
|
-
),
|
|
232
190
|
(
|
|
233
191
|
["T1w", "BOLD"],
|
|
234
192
|
["subject", "session"],
|
|
@@ -289,9 +247,9 @@ def test_register_data_type() -> None:
|
|
|
289
247
|
],
|
|
290
248
|
)
|
|
291
249
|
def test_PatternValidationMixin(
|
|
292
|
-
types:
|
|
293
|
-
replacements:
|
|
294
|
-
patterns:
|
|
250
|
+
types: str | list[str] | list[int],
|
|
251
|
+
replacements: str | list[str] | list[int],
|
|
252
|
+
patterns: str | dict[str, dict[str, str]],
|
|
295
253
|
expect: AbstractContextManager,
|
|
296
254
|
) -> None:
|
|
297
255
|
"""Test validation.
|
junifer/datareader/default.py
CHANGED
|
@@ -5,18 +5,21 @@
|
|
|
5
5
|
# License: AGPL
|
|
6
6
|
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Optional, Union
|
|
9
8
|
|
|
10
9
|
import nibabel as nib
|
|
11
10
|
import pandas as pd
|
|
11
|
+
import structlog
|
|
12
|
+
from pydantic import BaseModel
|
|
12
13
|
|
|
13
14
|
from ..api.decorators import register_datareader
|
|
14
15
|
from ..pipeline import PipelineStepMixin, UpdateMetaMixin
|
|
15
|
-
from ..utils.logging import
|
|
16
|
+
from ..utils.logging import warn_with_log
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
__all__ = ["DefaultDataReader"]
|
|
19
20
|
|
|
21
|
+
_log = structlog.get_logger("junifer")
|
|
22
|
+
logger = _log.bind(pkg="datareader", step="datareader")
|
|
20
23
|
|
|
21
24
|
# Map each file extension to a type
|
|
22
25
|
_extensions = {
|
|
@@ -34,7 +37,7 @@ _readers["TSV"] = {"func": pd.read_csv, "params": {"sep": "\t"}}
|
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
@register_datareader
|
|
37
|
-
class DefaultDataReader(PipelineStepMixin, UpdateMetaMixin):
|
|
40
|
+
class DefaultDataReader(BaseModel, PipelineStepMixin, UpdateMetaMixin):
|
|
38
41
|
"""Concrete implementation for common data reading."""
|
|
39
42
|
|
|
40
43
|
def validate_input(self, input: list[str]) -> list[str]:
|
|
@@ -59,7 +62,7 @@ class DefaultDataReader(PipelineStepMixin, UpdateMetaMixin):
|
|
|
59
62
|
def _fit_transform(
|
|
60
63
|
self,
|
|
61
64
|
input: dict[str, dict],
|
|
62
|
-
params:
|
|
65
|
+
params: dict | None = None,
|
|
63
66
|
) -> dict:
|
|
64
67
|
"""Fit and transform.
|
|
65
68
|
|
|
@@ -149,7 +152,7 @@ class DefaultDataReader(PipelineStepMixin, UpdateMetaMixin):
|
|
|
149
152
|
|
|
150
153
|
def _read_data(
|
|
151
154
|
data_type: str, path: Path, read_params: dict
|
|
152
|
-
) ->
|
|
155
|
+
) -> nib.Nifti1Image | pd.DataFrame | None:
|
|
153
156
|
"""Read data for data type.
|
|
154
157
|
|
|
155
158
|
Parameters
|
|
@@ -30,7 +30,7 @@ def test_DefaultDataReader_validation(type_) -> None:
|
|
|
30
30
|
"""
|
|
31
31
|
reader = DefaultDataReader()
|
|
32
32
|
assert reader.validate_input(type_) == type_
|
|
33
|
-
assert reader.
|
|
33
|
+
assert reader.validate_component(type_) == type_
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def test_DefaultDataReader_meta() -> None:
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Create a bug report to help us improve BrainPrint
|
|
4
|
+
title: ''
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Description
|
|
11
|
+
<!-- A clear and concise description of the observed bug and/or error -->
|
|
12
|
+
....
|
|
13
|
+
|
|
14
|
+
## Steps to Reproduce
|
|
15
|
+
<!--
|
|
16
|
+
Steps to reproduce the observed behaviour, in as much detail as possible:
|
|
17
|
+
1. Go to '...'
|
|
18
|
+
2. Checkout version '...'
|
|
19
|
+
3. Run '....'
|
|
20
|
+
4. See error
|
|
21
|
+
-->
|
|
22
|
+
|
|
23
|
+
<!-- If possible, provide error messages, stack traces, and any snippets useful in describing the bug here -->
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
## Expected Behavior
|
|
27
|
+
<!-- A clear and concise description of what you expected to happen. -->
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
## Screenshots
|
|
31
|
+
<!-- If applicable and desired, add screenshots to help illustrate your problem. -->
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
## Environment
|
|
35
|
+
- BrainPrint Version: ...
|
|
36
|
+
- OS: ...
|
|
37
|
+
- CPU: ...
|
|
38
|
+
|
|
39
|
+
<!-- Add any other relevant information on the environment here -->
|
|
40
|
+
|
|
41
|
+
<!-- If possible, include a snapshot of the python software package versions you have (for e.g., using pip freeze or conda list) here -->
|
|
42
|
+
|
|
43
|
+
## Additional Context
|
|
44
|
+
<!-- Add any other context and comments about the problem here. -->
|
|
45
|
+
...
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Documentation
|
|
3
|
+
about: Report an issue or make a suggestion related to BrainPrint documentation
|
|
4
|
+
title: ''
|
|
5
|
+
labels: documentation
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Documentation
|
|
11
|
+
<!-- A clear and concise description of an issue you observed in the documentation, or a suggestion you wish to make. -->
|
|
12
|
+
...
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Submit a proposal/request for a new BrainPrint feature
|
|
4
|
+
title: ''
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Feature Description
|
|
11
|
+
<!-- A clear and concise description of the feature you would like to propose -->
|
|
12
|
+
...
|
|
13
|
+
|
|
14
|
+
## Motivation
|
|
15
|
+
<!-- A clear and concise description of the problem that the proposed feature would address. For e.g., I'm always frustrated when [...]. If this is related to a specific issue, refer to it here -->
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
## Alternatives
|
|
19
|
+
<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->
|
|
20
|
+
...
|
|
21
|
+
|
|
22
|
+
## Additional Context
|
|
23
|
+
<!-- Add any other context or screenshots about the feature request here. -->
|
|
24
|
+
...
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Questions/Help/Support
|
|
3
|
+
about: Submit a request for support or a question
|
|
4
|
+
title: ''
|
|
5
|
+
labels: question
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Question/Support Request
|
|
11
|
+
<!-- A clear and concise description of a question you may have or a problem for which you would like to request support -->
|
|
12
|
+
...
|
|
13
|
+
|
|
14
|
+
## Screenshots
|
|
15
|
+
<!-- If possible, add screenshots to help illustrate your problem. -->
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
<!-- If applicable, provide error messages, stack traces, and any snippets useful in describing your problem here -->
|
|
19
|
+
|
|
20
|
+
## Environment
|
|
21
|
+
- BrainPrint Version: ...
|
|
22
|
+
- OS: ...
|
|
23
|
+
- CPU: ...
|
|
24
|
+
|
|
25
|
+
<!-- Add any other relevant information on the environment here -->
|
|
26
|
+
|
|
27
|
+
<!-- If possible, include a snapshot of the python software package versions you have (for e.g., using pip freeze or conda list) here -->
|
|
28
|
+
|