py-neuromodulation 0.0.2__py3-none-any.whl → 0.0.3__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.
- docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
- docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +233 -0
- docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
- docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
- docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
- docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
- docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
- docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
- docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +239 -0
- docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
- docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
- docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
- docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
- docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
- docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +76 -0
- docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +97 -0
- docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +240 -0
- docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +233 -0
- docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +63 -0
- docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
- docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +210 -0
- docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +192 -0
- docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +219 -0
- docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +121 -0
- docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +68 -0
- docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
- docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +189 -0
- docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
- docs/source/auto_examples/plot_0_first_demo.py +189 -0
- docs/source/auto_examples/plot_1_example_BIDS.py +240 -0
- docs/source/auto_examples/plot_2_example_add_feature.py +76 -0
- docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +219 -0
- docs/source/auto_examples/plot_4_example_gridPointProjection.py +210 -0
- docs/source/auto_examples/plot_5_example_rmap_computing.py +64 -0
- docs/source/auto_examples/plot_6_real_time_demo.py +121 -0
- docs/source/conf.py +105 -0
- examples/plot_0_first_demo.py +189 -0
- examples/plot_1_example_BIDS.py +240 -0
- examples/plot_2_example_add_feature.py +76 -0
- examples/plot_3_example_sharpwave_analysis.py +219 -0
- examples/plot_4_example_gridPointProjection.py +210 -0
- examples/plot_5_example_rmap_computing.py +64 -0
- examples/plot_6_real_time_demo.py +121 -0
- packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +4 -0
- packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +104 -0
- packages/realtime_decoding/build/lib/realtime_decoding/features.py +163 -0
- packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +15 -0
- packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +345 -0
- packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +54 -0
- packages/tmsi/build/lib/TMSiFileFormats/__init__.py +37 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +36 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +200 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +496 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +236 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +977 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +35 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +116 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +294 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +229 -0
- packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +102 -0
- packages/tmsi/build/lib/TMSiPlotters/__init__.py +2 -0
- packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +39 -0
- packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +234 -0
- packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +440 -0
- packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +44 -0
- packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +446 -0
- packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +589 -0
- packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +1326 -0
- packages/tmsi/build/lib/TMSiSDK/__init__.py +54 -0
- packages/tmsi/build/lib/TMSiSDK/device.py +588 -0
- packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +34 -0
- packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +1764 -0
- packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +34 -0
- packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +1366 -0
- packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +520 -0
- packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +165 -0
- packages/tmsi/build/lib/TMSiSDK/error.py +95 -0
- packages/tmsi/build/lib/TMSiSDK/sample_data.py +63 -0
- packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +99 -0
- packages/tmsi/build/lib/TMSiSDK/settings.py +45 -0
- packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +111 -0
- packages/tmsi/build/lib/__init__.py +4 -0
- packages/tmsi/build/lib/apex_sdk/__init__.py +34 -0
- packages/tmsi/build/lib/apex_sdk/device/__init__.py +41 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +1009 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +239 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +668 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +1611 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +38 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +57 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +44 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +150 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +36 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +48 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +108 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +39 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +77 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +150 -0
- packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +129 -0
- packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +59 -0
- packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +57 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +83 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +201 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +103 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +43 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +50 -0
- packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +118 -0
- packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +33 -0
- packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +44 -0
- packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +50 -0
- packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +136 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +126 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +113 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +134 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +60 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +42 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +42 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +72 -0
- packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +98 -0
- py_neuromodulation/{helper.py → _write_example_dataset_helper.py} +1 -1
- py_neuromodulation/nm_EpochStream.py +2 -3
- py_neuromodulation/nm_IO.py +43 -70
- py_neuromodulation/nm_RMAP.py +308 -11
- py_neuromodulation/nm_analysis.py +1 -1
- py_neuromodulation/nm_artifacts.py +25 -0
- py_neuromodulation/nm_bispectra.py +64 -29
- py_neuromodulation/nm_bursts.py +44 -30
- py_neuromodulation/nm_coherence.py +2 -1
- py_neuromodulation/nm_features.py +4 -2
- py_neuromodulation/nm_filter.py +63 -32
- py_neuromodulation/nm_filter_preprocessing.py +91 -0
- py_neuromodulation/nm_fooof.py +47 -29
- py_neuromodulation/nm_mne_connectivity.py +1 -1
- py_neuromodulation/nm_normalization.py +50 -74
- py_neuromodulation/nm_oscillatory.py +151 -31
- py_neuromodulation/nm_plots.py +13 -10
- py_neuromodulation/nm_rereference.py +10 -8
- py_neuromodulation/nm_run_analysis.py +28 -13
- py_neuromodulation/nm_sharpwaves.py +103 -136
- py_neuromodulation/nm_stats.py +44 -30
- py_neuromodulation/nm_stream_abc.py +18 -10
- py_neuromodulation/nm_stream_offline.py +181 -40
- py_neuromodulation/utils/_logging.py +24 -0
- {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/METADATA +182 -142
- py_neuromodulation-0.0.3.dist-info/RECORD +188 -0
- {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/WHEEL +2 -1
- py_neuromodulation-0.0.3.dist-info/top_level.txt +5 -0
- tests/__init__.py +0 -0
- tests/conftest.py +117 -0
- tests/test_all_examples.py +10 -0
- tests/test_all_features.py +63 -0
- tests/test_bispectra.py +70 -0
- tests/test_bursts.py +105 -0
- tests/test_feature_sampling_rates.py +143 -0
- tests/test_fooof.py +16 -0
- tests/test_initalization_offline_stream.py +41 -0
- tests/test_multiprocessing.py +58 -0
- tests/test_nan_values.py +29 -0
- tests/test_nm_filter.py +95 -0
- tests/test_nm_resample.py +63 -0
- tests/test_normalization_settings.py +146 -0
- tests/test_notch_filter.py +31 -0
- tests/test_osc_features.py +424 -0
- tests/test_preprocessing_filter.py +151 -0
- tests/test_rereference.py +171 -0
- tests/test_sampling.py +57 -0
- tests/test_settings_change_after_init.py +76 -0
- tests/test_sharpwave.py +165 -0
- tests/test_target_channel_add.py +100 -0
- tests/test_timing.py +80 -0
- py_neuromodulation/data/README +0 -6
- py_neuromodulation/data/dataset_description.json +0 -8
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/MOV_aligned_features_ch_ECOG_RIGHT_0_all.png +0 -0
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/all_feature_plt.pdf +0 -0
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_FEATURES.csv +0 -182
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_LM_ML_RES.p +0 -0
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SETTINGS.json +0 -273
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SIDECAR.json +0 -6
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_decoding_performance.png +0 -0
- py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_nm_channels.csv +0 -11
- py_neuromodulation/data/participants.json +0 -32
- py_neuromodulation/data/participants.tsv +0 -2
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +0 -5
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +0 -11
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +0 -11
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +0 -18
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +0 -35
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +0 -13
- py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +0 -2
- py_neuromodulation/grid_cortex.tsv +0 -40
- py_neuromodulation/grid_subcortex.tsv +0 -1429
- py_neuromodulation/nm_settings.json +0 -290
- py_neuromodulation/plots/STN_surf.mat +0 -0
- py_neuromodulation/plots/Vertices.mat +0 -0
- py_neuromodulation/plots/faces.mat +0 -0
- py_neuromodulation/plots/grid.mat +0 -0
- py_neuromodulation/py_neuromodulation.egg-info/PKG-INFO +0 -104
- py_neuromodulation/py_neuromodulation.egg-info/dependency_links.txt +0 -1
- py_neuromodulation/py_neuromodulation.egg-info/requires.txt +0 -26
- py_neuromodulation/py_neuromodulation.egg-info/top_level.txt +0 -1
- py_neuromodulation-0.0.2.dist-info/RECORD +0 -73
- /py_neuromodulation/{py_neuromodulation.egg-info/SOURCES.txt → utils/__init__.py} +0 -0
- {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import os
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.testing import assert_allclose
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from py_neuromodulation.nm_rereference import ReReferencer
|
|
9
|
+
from py_neuromodulation import (
|
|
10
|
+
nm_generator,
|
|
11
|
+
nm_settings,
|
|
12
|
+
nm_IO,
|
|
13
|
+
nm_define_nmchannels,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_rereference_not_used_channels_no_reref(setup_databatch):
|
|
18
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
19
|
+
|
|
20
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
21
|
+
ch_names=ch_names,
|
|
22
|
+
ch_types=ch_types,
|
|
23
|
+
reference="default",
|
|
24
|
+
bads=bads,
|
|
25
|
+
new_names="default",
|
|
26
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
27
|
+
target_keywords=("MOV_RIGHT",),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
re_referencer = ReReferencer(1, nm_channels)
|
|
31
|
+
|
|
32
|
+
# select here data that will is selected, this operation takes place in the nm_run_analysis
|
|
33
|
+
data_used = data_batch[nm_channels["used"] == 1]
|
|
34
|
+
|
|
35
|
+
ref_dat = re_referencer.process(data_used)
|
|
36
|
+
|
|
37
|
+
for no_ref_idx in np.where(
|
|
38
|
+
(nm_channels.rereference == "None") & nm_channels.used == 1
|
|
39
|
+
)[0]:
|
|
40
|
+
assert_allclose(ref_dat[no_ref_idx, :], data_batch[no_ref_idx, :])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_rereference_car(setup_databatch):
|
|
44
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
45
|
+
|
|
46
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
47
|
+
ch_names=ch_names,
|
|
48
|
+
ch_types=ch_types,
|
|
49
|
+
reference="default",
|
|
50
|
+
bads=bads,
|
|
51
|
+
new_names="default",
|
|
52
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
53
|
+
target_keywords=("MOV_RIGHT",),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
re_referencer = ReReferencer(1, nm_channels)
|
|
57
|
+
|
|
58
|
+
data_used = data_batch[nm_channels["used"] == 1]
|
|
59
|
+
|
|
60
|
+
ref_dat = re_referencer.process(data_used)
|
|
61
|
+
|
|
62
|
+
for ecog_ch_idx in np.where(
|
|
63
|
+
(nm_channels["type"] == "ecog") & (nm_channels.rereference == "average")
|
|
64
|
+
)[0]:
|
|
65
|
+
assert_allclose(
|
|
66
|
+
ref_dat[ecog_ch_idx, :],
|
|
67
|
+
data_batch[ecog_ch_idx, :]
|
|
68
|
+
- data_batch[
|
|
69
|
+
(nm_channels["type"] == "ecog")
|
|
70
|
+
& (nm_channels.index != ecog_ch_idx)
|
|
71
|
+
].mean(axis=0),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_rereference_bp(setup_databatch):
|
|
76
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
77
|
+
|
|
78
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
79
|
+
ch_names=ch_names,
|
|
80
|
+
ch_types=ch_types,
|
|
81
|
+
reference="default",
|
|
82
|
+
bads=bads,
|
|
83
|
+
new_names="default",
|
|
84
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
85
|
+
target_keywords=("MOV_RIGHT",),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
re_referencer = ReReferencer(1, nm_channels)
|
|
89
|
+
|
|
90
|
+
data_used = data_batch[nm_channels["used"] == 1]
|
|
91
|
+
|
|
92
|
+
ref_dat = re_referencer.process(data_used)
|
|
93
|
+
|
|
94
|
+
for bp_reref_idx in [
|
|
95
|
+
ch_idx
|
|
96
|
+
for ch_idx, ch in enumerate(nm_channels.rereference)
|
|
97
|
+
if ch in list(nm_channels.name)
|
|
98
|
+
]:
|
|
99
|
+
# bp_reref_idx is the channel index of the rereference anode
|
|
100
|
+
# referenced_bp_channel is the channel index which is the rereference cathode
|
|
101
|
+
referenced_bp_channel = np.where(
|
|
102
|
+
nm_channels.iloc[bp_reref_idx]["rereference"] == nm_channels.name
|
|
103
|
+
)[0][0]
|
|
104
|
+
assert_allclose(
|
|
105
|
+
ref_dat[bp_reref_idx, :],
|
|
106
|
+
data_batch[bp_reref_idx, :] - data_batch[referenced_bp_channel, :],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_rereference_wrong_rererference_column_name(setup_databatch):
|
|
111
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
112
|
+
|
|
113
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
114
|
+
ch_names=ch_names,
|
|
115
|
+
ch_types=ch_types,
|
|
116
|
+
reference="default",
|
|
117
|
+
bads=bads,
|
|
118
|
+
new_names="default",
|
|
119
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
120
|
+
target_keywords=("SQUARED_ROTATION",),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
nm_channels.loc[0, "rereference"] = "hallo"
|
|
124
|
+
with pytest.raises(Exception) as e_info:
|
|
125
|
+
re_referencer = ReReferencer(1, nm_channels)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_rereference_muliple_channels(setup_databatch):
|
|
129
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
130
|
+
|
|
131
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
132
|
+
ch_names=ch_names,
|
|
133
|
+
ch_types=ch_types,
|
|
134
|
+
reference="default",
|
|
135
|
+
bads=bads,
|
|
136
|
+
new_names="default",
|
|
137
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
138
|
+
target_keywords=("MOV_RIGHT",),
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
nm_channels.loc[0, "rereference"] = "LFP_RIGHT_1&LFP_RIGHT_2"
|
|
142
|
+
|
|
143
|
+
re_referencer = ReReferencer(1, nm_channels)
|
|
144
|
+
|
|
145
|
+
data_used = data_batch[nm_channels["used"] == 1]
|
|
146
|
+
|
|
147
|
+
ref_dat = re_referencer.process(data_used)
|
|
148
|
+
|
|
149
|
+
assert_allclose(
|
|
150
|
+
ref_dat[0, :],
|
|
151
|
+
data_batch[0, :] - (data_batch[1, :] + data_batch[2, :]) / 2,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_rereference_same_channel(setup_databatch):
|
|
156
|
+
ch_names, ch_types, bads, data_batch = setup_databatch
|
|
157
|
+
|
|
158
|
+
nm_channels = nm_define_nmchannels.set_channels(
|
|
159
|
+
ch_names=ch_names,
|
|
160
|
+
ch_types=ch_types,
|
|
161
|
+
reference="default",
|
|
162
|
+
bads=bads,
|
|
163
|
+
new_names="default",
|
|
164
|
+
used_types=("ecog", "dbs", "seeg"),
|
|
165
|
+
target_keywords=("MOV_RIGHT",),
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
nm_channels.loc[0, "rereference"] = nm_channels.loc[0, "name"]
|
|
169
|
+
|
|
170
|
+
with pytest.raises(Exception):
|
|
171
|
+
re_referencer = ReReferencer(1, nm_channels)
|
tests/test_sampling.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import py_neuromodulation as nm
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_fast_compute_settings():
|
|
6
|
+
settings = nm.nm_settings.get_default_settings()
|
|
7
|
+
settings = nm.nm_settings.reset_settings(settings)
|
|
8
|
+
settings = nm.nm_settings.set_settings_fast_compute(settings)
|
|
9
|
+
settings["preprocessing"] = ["re_referencing", "notch_filter"]
|
|
10
|
+
settings["features"]["fft"] = True
|
|
11
|
+
settings["postprocessing"]["feature_normalization"] = True
|
|
12
|
+
return settings
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_features(time_end_ms: int, segment_length_features_ms: int):
|
|
16
|
+
data = np.random.random([2, time_end_ms])
|
|
17
|
+
settings = get_fast_compute_settings()
|
|
18
|
+
settings["segment_length_features_ms"] = segment_length_features_ms
|
|
19
|
+
settings["fft_settings"]["windowlength_ms"] = segment_length_features_ms
|
|
20
|
+
|
|
21
|
+
settings["frequency_ranges_hz"] = {
|
|
22
|
+
# "high beta" : [20, 35],
|
|
23
|
+
"low gamma": [60, 80],
|
|
24
|
+
"high gamma": [90, 200],
|
|
25
|
+
}
|
|
26
|
+
stream = nm.Stream(
|
|
27
|
+
sfreq=1000,
|
|
28
|
+
data=data,
|
|
29
|
+
sampling_rate_features_hz=10,
|
|
30
|
+
verbose=False,
|
|
31
|
+
settings=settings,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
features = stream.run(data)
|
|
35
|
+
return features
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_feature_timing_5s_start_800ms():
|
|
39
|
+
"""Test if the features timing duration are computed correctly for a 5s signal with 800ms segment length"""
|
|
40
|
+
time_end_ms = 5000
|
|
41
|
+
segment_length_features_ms = 800
|
|
42
|
+
features = get_features(time_end_ms, segment_length_features_ms)
|
|
43
|
+
|
|
44
|
+
assert int(features["time"].iloc[0]) == segment_length_features_ms
|
|
45
|
+
|
|
46
|
+
assert int(features["time"].iloc[-1]) == time_end_ms
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_feature_timing_1s_start_500ms():
|
|
50
|
+
"""Test if the features timing duration are computed correctly for a 1s signal with 500ms segment length"""
|
|
51
|
+
time_end_ms = 1000
|
|
52
|
+
segment_length_features_ms = 500
|
|
53
|
+
features = get_features(time_end_ms, segment_length_features_ms)
|
|
54
|
+
|
|
55
|
+
assert int(features["time"].iloc[0]) == segment_length_features_ms
|
|
56
|
+
|
|
57
|
+
assert int(features["time"].iloc[-1]) == time_end_ms
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import py_neuromodulation as nm
|
|
4
|
+
from py_neuromodulation import nm_settings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_post_init_nm_channels_change():
|
|
8
|
+
"""Test if post initialization of nm_channels will also be ported to the feature computation."""
|
|
9
|
+
|
|
10
|
+
data = np.random.random((10, 1000))
|
|
11
|
+
fs = 1000
|
|
12
|
+
|
|
13
|
+
stream = nm.Stream(fs, data)
|
|
14
|
+
|
|
15
|
+
# default channel names are "ch{i}"
|
|
16
|
+
# every time the name changes, the "new_name" should also changes
|
|
17
|
+
# this is however only done during initialization
|
|
18
|
+
stream.nm_channels["new_name"] = [f"new_ch_name_{i}" for i in range(10)]
|
|
19
|
+
|
|
20
|
+
features = stream.run()
|
|
21
|
+
|
|
22
|
+
assert len([f for f in features.columns if "new_ch_name_0" in f]) != 0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_post_init_nm_channels_used_channels_change_single_channel():
|
|
26
|
+
"""Test if post initialization of nm_settings will also be ported to the feature computation."""
|
|
27
|
+
|
|
28
|
+
np.random.seed(0)
|
|
29
|
+
data = np.random.random((3, 1000))
|
|
30
|
+
sfreq = 1000
|
|
31
|
+
stream = nm.Stream(sfreq=sfreq, data=data, sampling_rate_features_hz=11)
|
|
32
|
+
stream.nm_channels["used"] = 0
|
|
33
|
+
stream.nm_channels.loc[1, "used"] = 1
|
|
34
|
+
|
|
35
|
+
features = stream.run(data)
|
|
36
|
+
|
|
37
|
+
chs_not_used = stream.nm_channels[stream.nm_channels["used"] == 0][
|
|
38
|
+
"new_name"
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
assert (
|
|
42
|
+
np.sum(
|
|
43
|
+
[
|
|
44
|
+
len([c for c in features.columns if c.startswith(ch_not_used)])
|
|
45
|
+
for ch_not_used in chs_not_used
|
|
46
|
+
]
|
|
47
|
+
)
|
|
48
|
+
== 0
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_post_init_nm_channels_used_channels_change_multiple_channel():
|
|
53
|
+
"""Test if post initialization of nm_settings will also be ported to the feature computation."""
|
|
54
|
+
|
|
55
|
+
np.random.seed(0)
|
|
56
|
+
data = np.random.random((3, 1000))
|
|
57
|
+
sfreq = 1000
|
|
58
|
+
stream = nm.Stream(sfreq=sfreq, data=data, sampling_rate_features_hz=11)
|
|
59
|
+
stream.nm_channels["used"] = 0
|
|
60
|
+
stream.nm_channels.loc[[0, 2], "used"] = 1
|
|
61
|
+
|
|
62
|
+
features = stream.run(data)
|
|
63
|
+
|
|
64
|
+
chs_not_used = stream.nm_channels[stream.nm_channels["used"] == 0][
|
|
65
|
+
"new_name"
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
assert (
|
|
69
|
+
np.sum(
|
|
70
|
+
[
|
|
71
|
+
len([c for c in features.columns if c.startswith(ch_not_used)])
|
|
72
|
+
for ch_not_used in chs_not_used
|
|
73
|
+
]
|
|
74
|
+
)
|
|
75
|
+
== 0
|
|
76
|
+
)
|
tests/test_sharpwave.py
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from py_neuromodulation import nm_sharpwaves, nm_settings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def init_sw_settings() -> dict:
|
|
8
|
+
settings = nm_settings.get_default_settings()
|
|
9
|
+
settings["sharpwave_analysis"] = True
|
|
10
|
+
return settings
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_sharpwaveinit_wrong_peak_param():
|
|
14
|
+
|
|
15
|
+
settings = init_sw_settings()
|
|
16
|
+
with pytest.raises(Exception) as e_info:
|
|
17
|
+
|
|
18
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
19
|
+
"peak_left"
|
|
20
|
+
] = 5
|
|
21
|
+
nm_sharpwaves.SharpwaveAnalyzer.test_settings(
|
|
22
|
+
settings, ch_names=[], sfreq=1000
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_sharpwaveinit_wrong_filter_range():
|
|
27
|
+
settings = init_sw_settings()
|
|
28
|
+
with pytest.raises(Exception) as e_info:
|
|
29
|
+
settings["sharpwave_analysis_settings"]["filter_ranges_hz"] = [
|
|
30
|
+
[5, 1200]
|
|
31
|
+
]
|
|
32
|
+
nm_sharpwaves.SharpwaveAnalyzer.test_settings(
|
|
33
|
+
settings, ch_names=[], sfreq=1000
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_sharpwaveinit_missing_estimator():
|
|
38
|
+
settings = init_sw_settings()
|
|
39
|
+
with pytest.raises(Exception) as e_info:
|
|
40
|
+
|
|
41
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
42
|
+
"prominence"
|
|
43
|
+
] = True
|
|
44
|
+
settings["sharpwave_analysis_settings"]["estimator"]["mean"] = []
|
|
45
|
+
settings["sharpwave_analysis_settings"]["estimator"]["median"] = []
|
|
46
|
+
settings["sharpwave_analysis_settings"]["estimator"]["max"] = []
|
|
47
|
+
settings["sharpwave_analysis_settings"]["estimator"]["min"] = []
|
|
48
|
+
settings["sharpwave_analysis_settings"]["estimator"]["var"] = []
|
|
49
|
+
|
|
50
|
+
nm_sharpwaves.SharpwaveAnalyzer.test_settings(
|
|
51
|
+
settings, ch_names=[], sfreq=1000
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_sharpwaveinit_correct_featurelist():
|
|
56
|
+
settings = init_sw_settings()
|
|
57
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
58
|
+
"prominence"
|
|
59
|
+
] = True
|
|
60
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
61
|
+
"interval"
|
|
62
|
+
] = True
|
|
63
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
64
|
+
"sharpness"
|
|
65
|
+
] = True
|
|
66
|
+
settings["sharpwave_analysis_settings"]["estimator"]["mean"] = [
|
|
67
|
+
"prominence",
|
|
68
|
+
"interval",
|
|
69
|
+
]
|
|
70
|
+
settings["sharpwave_analysis_settings"]["estimator"]["median"] = [
|
|
71
|
+
"sharpness"
|
|
72
|
+
]
|
|
73
|
+
settings["sharpwave_analysis_settings"]["estimator"]["max"] = []
|
|
74
|
+
settings["sharpwave_analysis_settings"]["estimator"]["min"] = []
|
|
75
|
+
settings["sharpwave_analysis_settings"]["estimator"]["var"] = []
|
|
76
|
+
|
|
77
|
+
assert (
|
|
78
|
+
nm_sharpwaves.SharpwaveAnalyzer.test_settings(
|
|
79
|
+
settings, ch_names=[], sfreq=1000
|
|
80
|
+
)
|
|
81
|
+
== None
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_prominence_features():
|
|
86
|
+
|
|
87
|
+
settings = init_sw_settings()
|
|
88
|
+
sfreq = 1000
|
|
89
|
+
ch_names = ["ch1", "ch2", "ch3", "ch4"]
|
|
90
|
+
|
|
91
|
+
# Reset feataures
|
|
92
|
+
for f in settings["sharpwave_analysis_settings"][
|
|
93
|
+
"sharpwave_features"
|
|
94
|
+
].keys():
|
|
95
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][f] = False
|
|
96
|
+
for est in settings["sharpwave_analysis_settings"]["estimator"].keys():
|
|
97
|
+
settings["sharpwave_analysis_settings"]["estimator"][est] = []
|
|
98
|
+
|
|
99
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
100
|
+
"prominence"
|
|
101
|
+
] = True
|
|
102
|
+
settings["sharpwave_analysis_settings"]["estimator"]["max"] = ["prominence"]
|
|
103
|
+
|
|
104
|
+
settings["sharpwave_analysis_settings"]["filter_ranges_hz"] = [[5, 80]]
|
|
105
|
+
|
|
106
|
+
sw = nm_sharpwaves.SharpwaveAnalyzer(settings, ch_names, sfreq)
|
|
107
|
+
|
|
108
|
+
data = np.zeros([len(ch_names), sfreq])
|
|
109
|
+
data[0, 500] = 1
|
|
110
|
+
data[1, 500] = 2
|
|
111
|
+
data[2, 500] = 3
|
|
112
|
+
data[3, 500] = 4
|
|
113
|
+
|
|
114
|
+
features = sw.calc_feature(data, {})
|
|
115
|
+
|
|
116
|
+
assert (
|
|
117
|
+
features["ch4_Sharpwave_Max_prominence_range_5_80"]
|
|
118
|
+
> features["ch3_Sharpwave_Max_prominence_range_5_80"]
|
|
119
|
+
> features["ch2_Sharpwave_Max_prominence_range_5_80"]
|
|
120
|
+
> features["ch1_Sharpwave_Max_prominence_range_5_80"]
|
|
121
|
+
), "prominence features were not calculated correctly"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_interval_feature():
|
|
125
|
+
|
|
126
|
+
settings = init_sw_settings()
|
|
127
|
+
sfreq = 1000
|
|
128
|
+
ch_names = ["ch1", "ch2", "ch3", "ch4"]
|
|
129
|
+
|
|
130
|
+
# Reset feataures
|
|
131
|
+
for f in settings["sharpwave_analysis_settings"][
|
|
132
|
+
"sharpwave_features"
|
|
133
|
+
].keys():
|
|
134
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][f] = False
|
|
135
|
+
for est in settings["sharpwave_analysis_settings"]["estimator"].keys():
|
|
136
|
+
settings["sharpwave_analysis_settings"]["estimator"][est] = []
|
|
137
|
+
|
|
138
|
+
settings["sharpwave_analysis_settings"]["sharpwave_features"][
|
|
139
|
+
"interval"
|
|
140
|
+
] = True
|
|
141
|
+
settings["sharpwave_analysis_settings"]["estimator"]["max"] = ["interval"]
|
|
142
|
+
|
|
143
|
+
# the filter cannot be too high, since adjacent ripples will be detected as peaks
|
|
144
|
+
settings["sharpwave_analysis_settings"]["filter_ranges_hz"] = [[5, 200]]
|
|
145
|
+
|
|
146
|
+
sw = nm_sharpwaves.SharpwaveAnalyzer(settings, ch_names, sfreq)
|
|
147
|
+
|
|
148
|
+
data = np.zeros([len(ch_names), sfreq])
|
|
149
|
+
for i in np.arange(0, 1000, 100):
|
|
150
|
+
data[0, i] = 1
|
|
151
|
+
for i in np.arange(0, 1000, 200):
|
|
152
|
+
data[1, i] = 1
|
|
153
|
+
for i in np.arange(0, 1000, 300):
|
|
154
|
+
data[2, i] = 1
|
|
155
|
+
for i in np.arange(0, 1000, 400):
|
|
156
|
+
data[3, i] = 1
|
|
157
|
+
|
|
158
|
+
features = sw.calc_feature(data, {})
|
|
159
|
+
|
|
160
|
+
assert (
|
|
161
|
+
features["ch1_Sharpwave_Max_interval_range_5_200"]
|
|
162
|
+
< features["ch2_Sharpwave_Max_interval_range_5_200"]
|
|
163
|
+
< features["ch3_Sharpwave_Max_interval_range_5_200"]
|
|
164
|
+
< features["ch4_Sharpwave_Max_interval_range_5_200"]
|
|
165
|
+
), "interval features were not calculated correctly"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from py_neuromodulation import (
|
|
6
|
+
nm_settings,
|
|
7
|
+
nm_stream_offline,
|
|
8
|
+
nm_define_nmchannels,
|
|
9
|
+
nm_stream_abc,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_example_settings(test_arr: np.array) -> nm_stream_abc.PNStream:
|
|
14
|
+
settings = nm_settings.set_settings_fast_compute(
|
|
15
|
+
nm_settings.get_default_settings()
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
nm_channels = nm_define_nmchannels.get_default_channels_from_data(test_arr)
|
|
19
|
+
|
|
20
|
+
return settings, nm_channels
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_label_add_single_target():
|
|
24
|
+
sampling_rate_features = 10
|
|
25
|
+
arr_test = np.random.random([2, 5000])
|
|
26
|
+
target_arr = np.arange(0, 5000, 1)
|
|
27
|
+
arr_test[1, :] = target_arr
|
|
28
|
+
|
|
29
|
+
settings, nm_channels = get_example_settings(arr_test)
|
|
30
|
+
|
|
31
|
+
nm_channels["target"] = [0, 1]
|
|
32
|
+
nm_channels["used"] = [1, 0]
|
|
33
|
+
nm_channels.loc[1, "name"] = "target_ch"
|
|
34
|
+
|
|
35
|
+
settings["sampling_rate_features_hz"] = sampling_rate_features
|
|
36
|
+
|
|
37
|
+
stream = nm_stream_offline.Stream(
|
|
38
|
+
sfreq=1000, nm_channels=nm_channels, settings=settings, verbose=True
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
df = stream.run(arr_test)
|
|
42
|
+
|
|
43
|
+
assert df[
|
|
44
|
+
"target_ch"
|
|
45
|
+
].is_monotonic_increasing, "Not all target values are ascending"
|
|
46
|
+
|
|
47
|
+
# check if all "target_ch" values are in the target_arr
|
|
48
|
+
assert all(
|
|
49
|
+
[i in target_arr for i in df["target_ch"]]
|
|
50
|
+
), "Not all target values are were estimated correctly from the simulated target array"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_label_add_multidimensional_target():
|
|
54
|
+
sampling_rate_features = 10
|
|
55
|
+
arr_test = np.random.random([4, 5000])
|
|
56
|
+
target_arr = np.arange(0, 5000, 1)
|
|
57
|
+
target_arr = np.tile(target_arr, (2, 1))
|
|
58
|
+
arr_test[[0, 2], :] = target_arr
|
|
59
|
+
|
|
60
|
+
settings, nm_channels = get_example_settings(arr_test)
|
|
61
|
+
|
|
62
|
+
nm_channels["target"] = [1, 0, 1, 0]
|
|
63
|
+
nm_channels["used"] = [0, 1, 0, 1]
|
|
64
|
+
nm_channels.loc[0, "name"] = "target_ch_0"
|
|
65
|
+
nm_channels.loc[2, "name"] = "target_ch_1"
|
|
66
|
+
|
|
67
|
+
settings["sampling_rate_features_hz"] = sampling_rate_features
|
|
68
|
+
|
|
69
|
+
stream = nm_stream_offline.Stream(
|
|
70
|
+
sfreq=1000, nm_channels=nm_channels, settings=settings, verbose=True
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
df = stream.run(arr_test)
|
|
74
|
+
|
|
75
|
+
for target_ch in ["target_ch_0", "target_ch_1"]:
|
|
76
|
+
assert df[
|
|
77
|
+
target_ch
|
|
78
|
+
].is_monotonic_increasing, "Not all target values are ascending"
|
|
79
|
+
|
|
80
|
+
# check if all "target_ch" values are in the target_arr
|
|
81
|
+
assert all(
|
|
82
|
+
[i in target_arr for i in df[target_ch]]
|
|
83
|
+
), "Not all target values are were estimated correctly from the simulated target array"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_label_add_no_target():
|
|
87
|
+
sampling_rate_features = 10
|
|
88
|
+
arr_test = np.random.random([4, 5000])
|
|
89
|
+
|
|
90
|
+
settings, nm_channels = get_example_settings(arr_test)
|
|
91
|
+
|
|
92
|
+
settings["sampling_rate_features_hz"] = sampling_rate_features
|
|
93
|
+
|
|
94
|
+
stream = nm_stream_offline.Stream(
|
|
95
|
+
sfreq=1000, nm_channels=nm_channels, settings=settings, verbose=True
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
df = stream.run(arr_test)
|
|
99
|
+
|
|
100
|
+
assert all([col.startswith("ch") or col.startswith("time") for col in df])
|
tests/test_timing.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import py_neuromodulation as nm
|
|
2
|
+
from py_neuromodulation import (
|
|
3
|
+
nm_settings,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_setting_computation_time():
|
|
10
|
+
"""Intantiate test for feature computation with fixed time duration.
|
|
11
|
+
The number of output features should match the ratio of the sampling rate of the data and raw signal sampling rate.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
data_duration_s = 5
|
|
15
|
+
sampling_rate_features_hz = 200
|
|
16
|
+
fs = 1000
|
|
17
|
+
data = np.random.random((1, int(data_duration_s * fs)))
|
|
18
|
+
|
|
19
|
+
settings = nm_settings.get_default_settings()
|
|
20
|
+
settings = nm_settings.set_settings_fast_compute(settings)
|
|
21
|
+
settings["segment_length_features_ms"] = 1000 # start afte 1 second
|
|
22
|
+
settings["features"]["fft"] = False
|
|
23
|
+
settings["features"]["raw_hjorth"] = True
|
|
24
|
+
stream = nm.Stream(
|
|
25
|
+
sfreq=fs,
|
|
26
|
+
data=data,
|
|
27
|
+
sampling_rate_features_hz=sampling_rate_features_hz,
|
|
28
|
+
settings=settings,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
features = stream.run()
|
|
32
|
+
|
|
33
|
+
# test if features up till the last sample was computed
|
|
34
|
+
assert (
|
|
35
|
+
data_duration_s * 1000 - features["time"].iloc[-1]
|
|
36
|
+
) < 1000 / sampling_rate_features_hz
|
|
37
|
+
|
|
38
|
+
# test that the time difference between two samples is the feature sampling rate
|
|
39
|
+
assert (
|
|
40
|
+
features["time"].iloc[1] - features["time"].iloc[0]
|
|
41
|
+
) == 1000 / sampling_rate_features_hz
|
|
42
|
+
|
|
43
|
+
assert features["time"].iloc[0] == settings["segment_length_features_ms"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_float_fs():
|
|
47
|
+
"""Change sampling rate here to be float, s.t. rounding issues are not affecting overall number of
|
|
48
|
+
computed features.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
data_duration_s = 5
|
|
52
|
+
sampling_rate_features_hz = 200
|
|
53
|
+
fs = 1111.111
|
|
54
|
+
data = np.random.random((1, int(data_duration_s * fs)))
|
|
55
|
+
|
|
56
|
+
settings = nm_settings.get_default_settings()
|
|
57
|
+
settings = nm_settings.set_settings_fast_compute(settings)
|
|
58
|
+
settings["segment_length_features_ms"] = 333 # start afte 1 second
|
|
59
|
+
|
|
60
|
+
settings["features"]["fft"] = False
|
|
61
|
+
settings["features"]["raw_hjorth"] = True
|
|
62
|
+
stream = nm.Stream(
|
|
63
|
+
sfreq=fs,
|
|
64
|
+
data=data,
|
|
65
|
+
sampling_rate_features_hz=sampling_rate_features_hz,
|
|
66
|
+
settings=settings,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
features = stream.run()
|
|
70
|
+
|
|
71
|
+
# test if features up till the last sample was computed
|
|
72
|
+
assert (
|
|
73
|
+
data_duration_s * 1000 - features["time"].iloc[-1]
|
|
74
|
+
) < 1000 / sampling_rate_features_hz
|
|
75
|
+
|
|
76
|
+
assert (
|
|
77
|
+
features["time"].iloc[1] - features["time"].iloc[0]
|
|
78
|
+
) == 1000 / sampling_rate_features_hz
|
|
79
|
+
|
|
80
|
+
assert features["time"].iloc[0] == settings["segment_length_features_ms"]
|
py_neuromodulation/data/README
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
References
|
|
2
|
-
----------
|
|
3
|
-
Appelhoff, S., Sanderson, M., Brooks, T., Vliet, M., Quentin, R., Holdgraf, C., Chaumon, M., Mikulan, E., Tavabi, K., Höchenberger, R., Welke, D., Brunner, C., Rockhill, A., Larson, E., Gramfort, A. and Jas, M. (2019). MNE-BIDS: Organizing electrophysiological data into the BIDS format and facilitating their analysis. Journal of Open Source Software 4: (1896). https://doi.org/10.21105/joss.01896
|
|
4
|
-
|
|
5
|
-
Holdgraf, C., Appelhoff, S., Bickel, S., Bouchard, K., D'Ambrosio, S., David, O., … Hermes, D. (2019). iEEG-BIDS, extending the Brain Imaging Data Structure specification to human intracranial electrophysiology. Scientific Data, 6, 102. https://doi.org/10.1038/s41597-019-0105-7
|
|
6
|
-
|
|
Binary file
|