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.
Files changed (204) hide show
  1. docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
  2. docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +233 -0
  3. docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  4. docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
  5. docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  6. docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
  7. docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  8. docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
  9. docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +239 -0
  10. docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  11. docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
  12. docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  13. docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
  14. docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  15. docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +76 -0
  16. docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +97 -0
  17. docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +240 -0
  18. docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +233 -0
  19. docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +63 -0
  20. docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  21. docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +210 -0
  22. docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +192 -0
  23. docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +219 -0
  24. docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +121 -0
  25. docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +68 -0
  26. docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  27. docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +189 -0
  28. docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  29. docs/source/auto_examples/plot_0_first_demo.py +189 -0
  30. docs/source/auto_examples/plot_1_example_BIDS.py +240 -0
  31. docs/source/auto_examples/plot_2_example_add_feature.py +76 -0
  32. docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +219 -0
  33. docs/source/auto_examples/plot_4_example_gridPointProjection.py +210 -0
  34. docs/source/auto_examples/plot_5_example_rmap_computing.py +64 -0
  35. docs/source/auto_examples/plot_6_real_time_demo.py +121 -0
  36. docs/source/conf.py +105 -0
  37. examples/plot_0_first_demo.py +189 -0
  38. examples/plot_1_example_BIDS.py +240 -0
  39. examples/plot_2_example_add_feature.py +76 -0
  40. examples/plot_3_example_sharpwave_analysis.py +219 -0
  41. examples/plot_4_example_gridPointProjection.py +210 -0
  42. examples/plot_5_example_rmap_computing.py +64 -0
  43. examples/plot_6_real_time_demo.py +121 -0
  44. packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +4 -0
  45. packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +104 -0
  46. packages/realtime_decoding/build/lib/realtime_decoding/features.py +163 -0
  47. packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +15 -0
  48. packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +345 -0
  49. packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +54 -0
  50. packages/tmsi/build/lib/TMSiFileFormats/__init__.py +37 -0
  51. packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +36 -0
  52. packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +200 -0
  53. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +496 -0
  54. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +236 -0
  55. packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +977 -0
  56. packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +35 -0
  57. packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +116 -0
  58. packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +294 -0
  59. packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +229 -0
  60. packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +102 -0
  61. packages/tmsi/build/lib/TMSiPlotters/__init__.py +2 -0
  62. packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +39 -0
  63. packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +234 -0
  64. packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +440 -0
  65. packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +44 -0
  66. packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +446 -0
  67. packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +589 -0
  68. packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +1326 -0
  69. packages/tmsi/build/lib/TMSiSDK/__init__.py +54 -0
  70. packages/tmsi/build/lib/TMSiSDK/device.py +588 -0
  71. packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +34 -0
  72. packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +1764 -0
  73. packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +34 -0
  74. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +1366 -0
  75. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +520 -0
  76. packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +165 -0
  77. packages/tmsi/build/lib/TMSiSDK/error.py +95 -0
  78. packages/tmsi/build/lib/TMSiSDK/sample_data.py +63 -0
  79. packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +99 -0
  80. packages/tmsi/build/lib/TMSiSDK/settings.py +45 -0
  81. packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +111 -0
  82. packages/tmsi/build/lib/__init__.py +4 -0
  83. packages/tmsi/build/lib/apex_sdk/__init__.py +34 -0
  84. packages/tmsi/build/lib/apex_sdk/device/__init__.py +41 -0
  85. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +1009 -0
  86. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +239 -0
  87. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +668 -0
  88. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +1611 -0
  89. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +38 -0
  90. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +57 -0
  91. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +44 -0
  92. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +150 -0
  93. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +36 -0
  94. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +48 -0
  95. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +108 -0
  96. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +39 -0
  97. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +77 -0
  98. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +150 -0
  99. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +129 -0
  100. packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +59 -0
  101. packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +57 -0
  102. packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +83 -0
  103. packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +201 -0
  104. packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +103 -0
  105. packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +43 -0
  106. packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +50 -0
  107. packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +118 -0
  108. packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +33 -0
  109. packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +44 -0
  110. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +50 -0
  111. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +136 -0
  112. packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +126 -0
  113. packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +113 -0
  114. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +134 -0
  115. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +60 -0
  116. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +42 -0
  117. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +42 -0
  118. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +72 -0
  119. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +98 -0
  120. py_neuromodulation/{helper.py → _write_example_dataset_helper.py} +1 -1
  121. py_neuromodulation/nm_EpochStream.py +2 -3
  122. py_neuromodulation/nm_IO.py +43 -70
  123. py_neuromodulation/nm_RMAP.py +308 -11
  124. py_neuromodulation/nm_analysis.py +1 -1
  125. py_neuromodulation/nm_artifacts.py +25 -0
  126. py_neuromodulation/nm_bispectra.py +64 -29
  127. py_neuromodulation/nm_bursts.py +44 -30
  128. py_neuromodulation/nm_coherence.py +2 -1
  129. py_neuromodulation/nm_features.py +4 -2
  130. py_neuromodulation/nm_filter.py +63 -32
  131. py_neuromodulation/nm_filter_preprocessing.py +91 -0
  132. py_neuromodulation/nm_fooof.py +47 -29
  133. py_neuromodulation/nm_mne_connectivity.py +1 -1
  134. py_neuromodulation/nm_normalization.py +50 -74
  135. py_neuromodulation/nm_oscillatory.py +151 -31
  136. py_neuromodulation/nm_plots.py +13 -10
  137. py_neuromodulation/nm_rereference.py +10 -8
  138. py_neuromodulation/nm_run_analysis.py +28 -13
  139. py_neuromodulation/nm_sharpwaves.py +103 -136
  140. py_neuromodulation/nm_stats.py +44 -30
  141. py_neuromodulation/nm_stream_abc.py +18 -10
  142. py_neuromodulation/nm_stream_offline.py +181 -40
  143. py_neuromodulation/utils/_logging.py +24 -0
  144. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/METADATA +182 -142
  145. py_neuromodulation-0.0.3.dist-info/RECORD +188 -0
  146. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/WHEEL +2 -1
  147. py_neuromodulation-0.0.3.dist-info/top_level.txt +5 -0
  148. tests/__init__.py +0 -0
  149. tests/conftest.py +117 -0
  150. tests/test_all_examples.py +10 -0
  151. tests/test_all_features.py +63 -0
  152. tests/test_bispectra.py +70 -0
  153. tests/test_bursts.py +105 -0
  154. tests/test_feature_sampling_rates.py +143 -0
  155. tests/test_fooof.py +16 -0
  156. tests/test_initalization_offline_stream.py +41 -0
  157. tests/test_multiprocessing.py +58 -0
  158. tests/test_nan_values.py +29 -0
  159. tests/test_nm_filter.py +95 -0
  160. tests/test_nm_resample.py +63 -0
  161. tests/test_normalization_settings.py +146 -0
  162. tests/test_notch_filter.py +31 -0
  163. tests/test_osc_features.py +424 -0
  164. tests/test_preprocessing_filter.py +151 -0
  165. tests/test_rereference.py +171 -0
  166. tests/test_sampling.py +57 -0
  167. tests/test_settings_change_after_init.py +76 -0
  168. tests/test_sharpwave.py +165 -0
  169. tests/test_target_channel_add.py +100 -0
  170. tests/test_timing.py +80 -0
  171. py_neuromodulation/data/README +0 -6
  172. py_neuromodulation/data/dataset_description.json +0 -8
  173. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/MOV_aligned_features_ch_ECOG_RIGHT_0_all.png +0 -0
  174. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/all_feature_plt.pdf +0 -0
  175. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_FEATURES.csv +0 -182
  176. 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
  177. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SETTINGS.json +0 -273
  178. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SIDECAR.json +0 -6
  179. 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
  180. 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
  181. py_neuromodulation/data/participants.json +0 -32
  182. py_neuromodulation/data/participants.tsv +0 -2
  183. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +0 -5
  184. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +0 -11
  185. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +0 -11
  186. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
  187. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +0 -18
  188. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +0 -35
  189. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +0 -13
  190. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +0 -2
  191. py_neuromodulation/grid_cortex.tsv +0 -40
  192. py_neuromodulation/grid_subcortex.tsv +0 -1429
  193. py_neuromodulation/nm_settings.json +0 -290
  194. py_neuromodulation/plots/STN_surf.mat +0 -0
  195. py_neuromodulation/plots/Vertices.mat +0 -0
  196. py_neuromodulation/plots/faces.mat +0 -0
  197. py_neuromodulation/plots/grid.mat +0 -0
  198. py_neuromodulation/py_neuromodulation.egg-info/PKG-INFO +0 -104
  199. py_neuromodulation/py_neuromodulation.egg-info/dependency_links.txt +0 -1
  200. py_neuromodulation/py_neuromodulation.egg-info/requires.txt +0 -26
  201. py_neuromodulation/py_neuromodulation.egg-info/top_level.txt +0 -1
  202. py_neuromodulation-0.0.2.dist-info/RECORD +0 -73
  203. /py_neuromodulation/{py_neuromodulation.egg-info/SOURCES.txt → utils/__init__.py} +0 -0
  204. {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
+ )
@@ -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"]
@@ -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
-
@@ -1,8 +0,0 @@
1
- {
2
- "Name": " ",
3
- "BIDSVersion": "1.7.0",
4
- "DatasetType": "raw",
5
- "Authors": [
6
- "[Unspecified]"
7
- ]
8
- }