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,424 @@
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from py_neuromodulation import nm_oscillatory, nm_settings
5
+
6
+
7
+ def setup_osc_settings(
8
+ osc_feature_name: str,
9
+ osc_feature_setting: str,
10
+ windowlength_ms: int,
11
+ log_transform: bool,
12
+ ):
13
+ settings = nm_settings.get_default_settings()
14
+ settings = nm_settings.reset_settings(settings)
15
+ settings[osc_feature_name] = True
16
+ settings[osc_feature_setting]["windowlength_ms"] = windowlength_ms
17
+ settings[osc_feature_setting]["log_transform"] = log_transform
18
+
19
+ return settings
20
+
21
+
22
+ def test_fft_wrong_logtransform_param_init():
23
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
24
+ sfreq = 1000
25
+
26
+ settings = setup_osc_settings(
27
+ osc_feature_name="fft",
28
+ osc_feature_setting="fft_settings",
29
+ windowlength_ms=1000,
30
+ log_transform="123",
31
+ )
32
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
33
+
34
+ with pytest.raises(Exception) as e_info:
35
+ nm_oscillatory.FFT.test_settings(settings, ch_names, sfreq)
36
+
37
+
38
+ def test_fft_wrong_frequencyband_range_init():
39
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
40
+ sfreq = 1000
41
+
42
+ settings = setup_osc_settings(
43
+ osc_feature_name="fft",
44
+ osc_feature_setting="fft_settings",
45
+ windowlength_ms=1000,
46
+ log_transform="123",
47
+ )
48
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "broadband": [10, 600]}
49
+
50
+ with pytest.raises(Exception):
51
+ nm_oscillatory.FFT.test_settings(settings, ch_names, sfreq)
52
+
53
+
54
+ def test_fft_zero_data():
55
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
56
+ sfreq = 1000
57
+
58
+ settings = setup_osc_settings(
59
+ osc_feature_name="fft",
60
+ osc_feature_setting="fft_settings",
61
+ windowlength_ms=1000,
62
+ log_transform=False,
63
+ )
64
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
65
+ fft_obj = nm_oscillatory.FFT(settings, ch_names, sfreq)
66
+ fft_obj.test_settings(settings, ch_names, sfreq)
67
+
68
+ data = np.ones([len(ch_names), sfreq])
69
+ features_out = fft_obj.calc_feature(data, {})
70
+
71
+ for f in features_out.keys():
72
+ if "psd_0" not in f:
73
+ assert np.isclose(features_out[f], 0, atol=1e-6)
74
+
75
+
76
+ def test_fft_random_data():
77
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
78
+ sfreq = 1000
79
+
80
+ settings = setup_osc_settings(
81
+ osc_feature_name="fft",
82
+ osc_feature_setting="fft_settings",
83
+ windowlength_ms=1000,
84
+ log_transform=False,
85
+ )
86
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
87
+ fft_obj = nm_oscillatory.FFT(settings, ch_names, sfreq)
88
+ fft_obj.test_settings(settings, ch_names, sfreq)
89
+
90
+ data = np.random.random([len(ch_names), sfreq])
91
+ features_out = fft_obj.calc_feature(data, {})
92
+
93
+ for f in features_out.keys():
94
+ assert features_out[f] != 0
95
+
96
+
97
+ def test_fft_beta_osc():
98
+ ch_names = [
99
+ "ch1",
100
+ ]
101
+ sfreq = 1000
102
+
103
+ settings = setup_osc_settings(
104
+ osc_feature_name="fft",
105
+ osc_feature_setting="fft_settings",
106
+ windowlength_ms=1000,
107
+ log_transform=False,
108
+ )
109
+
110
+ settings["frequency_ranges_hz"] = {
111
+ "theta": [4, 8],
112
+ "beta": [10, 28],
113
+ "gamma": [50, 60],
114
+ }
115
+
116
+ fft_obj = nm_oscillatory.FFT(settings, ch_names, sfreq)
117
+ fft_obj.test_settings(settings, ch_names, sfreq)
118
+
119
+ time_duration = 1
120
+
121
+ time_points = np.arange(0, time_duration, 1 / sfreq)
122
+ beta_freq = 20
123
+
124
+ beta_wave = np.sin(2 * np.pi * beta_freq * time_points)
125
+
126
+ np.random.seed(0)
127
+ data = np.random.random([len(ch_names), sfreq]) + beta_wave
128
+
129
+ features_out = fft_obj.calc_feature(data, {})
130
+
131
+ assert (
132
+ features_out["ch1_fft_beta_mean"] > features_out["ch1_fft_theta_mean"]
133
+ and features_out["ch1_fft_beta_mean"]
134
+ > features_out["ch1_fft_gamma_mean"]
135
+ )
136
+
137
+
138
+ def test_stft_wrong_logtransform_param_init():
139
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
140
+ sfreq = 1000
141
+
142
+ settings = setup_osc_settings(
143
+ osc_feature_name="stft",
144
+ osc_feature_setting="stft_settings",
145
+ windowlength_ms=1000,
146
+ log_transform="123",
147
+ )
148
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
149
+
150
+ with pytest.raises(Exception) as e_info:
151
+ nm_oscillatory.STFT.test_settings(settings, ch_names, sfreq)
152
+
153
+
154
+ def test_stft_wrong_frequencyband_range_init():
155
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
156
+ sfreq = 1000
157
+
158
+ settings = setup_osc_settings(
159
+ osc_feature_name="stft",
160
+ osc_feature_setting="stft_settings",
161
+ windowlength_ms=1000,
162
+ log_transform="123",
163
+ )
164
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "broadband": [10, 600]}
165
+
166
+ with pytest.raises(Exception):
167
+ nm_oscillatory.STFT.test_settings(settings, ch_names, sfreq)
168
+
169
+
170
+ def test_stft_beta_osc():
171
+ ch_names = [
172
+ "ch1",
173
+ ]
174
+ sfreq = 1000
175
+
176
+ settings = setup_osc_settings(
177
+ osc_feature_name="stft",
178
+ osc_feature_setting="stft_settings",
179
+ windowlength_ms=1000,
180
+ log_transform=True,
181
+ )
182
+
183
+ settings["frequency_ranges_hz"] = {
184
+ "theta": [4, 8],
185
+ "beta": [10, 28],
186
+ "gamma": [50, 60],
187
+ }
188
+
189
+ stft_obj = nm_oscillatory.STFT(settings, ch_names, sfreq)
190
+ stft_obj.test_settings(settings, ch_names, sfreq)
191
+
192
+ time_duration = 1
193
+
194
+ time_points = np.arange(0, time_duration, 1 / sfreq)
195
+ beta_freq = 20
196
+
197
+ beta_wave = np.sin(2 * np.pi * beta_freq * time_points)
198
+
199
+ np.random.seed(0)
200
+ data = np.random.random([len(ch_names), sfreq]) + beta_wave
201
+
202
+ features_out = stft_obj.calc_feature(data, {})
203
+
204
+ assert (
205
+ features_out["ch1_stft_beta_mean"] > features_out["ch1_stft_theta_mean"]
206
+ and features_out["ch1_stft_beta_mean"]
207
+ > features_out["ch1_stft_gamma_mean"]
208
+ )
209
+
210
+
211
+ def test_welch_beta_osc():
212
+ ch_names = [
213
+ "ch1",
214
+ ]
215
+ sfreq = 1000
216
+
217
+ settings = setup_osc_settings(
218
+ osc_feature_name="welch",
219
+ osc_feature_setting="welch_settings",
220
+ windowlength_ms=1000,
221
+ log_transform=True,
222
+ )
223
+
224
+ settings["frequency_ranges_hz"] = {
225
+ "theta": [4, 8],
226
+ "beta": [10, 28],
227
+ "gamma": [50, 60],
228
+ }
229
+
230
+ stft_obj = nm_oscillatory.Welch(settings, ch_names, sfreq)
231
+ stft_obj.test_settings(settings, ch_names, sfreq)
232
+
233
+ time_duration = 1
234
+
235
+ time_points = np.arange(0, time_duration, 1 / sfreq)
236
+ beta_freq = 20
237
+
238
+ beta_wave = np.sin(2 * np.pi * beta_freq * time_points)
239
+
240
+ np.random.seed(0)
241
+ data = np.random.random([len(ch_names), sfreq]) + beta_wave
242
+
243
+ features_out = stft_obj.calc_feature(data, {})
244
+
245
+ assert (
246
+ features_out["ch1_welch_beta_mean"]
247
+ > features_out["ch1_welch_theta_mean"]
248
+ and features_out["ch1_welch_beta_mean"]
249
+ > features_out["ch1_welch_gamma_mean"]
250
+ )
251
+
252
+
253
+ def test_bp_wrong_logtransform_param_init():
254
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
255
+ sfreq = 1000
256
+
257
+ settings = setup_osc_settings(
258
+ osc_feature_name="bandpass_filter",
259
+ osc_feature_setting="bandpass_filter_settings",
260
+ windowlength_ms=1000,
261
+ log_transform="123",
262
+ )
263
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
264
+
265
+ with pytest.raises(Exception) as e_info:
266
+ nm_oscillatory.BandPower.test_settings(settings, ch_names, sfreq)
267
+
268
+
269
+ def test_bp_wrong_frequencyband_range_init():
270
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
271
+ sfreq = 1000
272
+
273
+ settings = setup_osc_settings(
274
+ osc_feature_name="bandpass_filter",
275
+ osc_feature_setting="bandpass_filter_settings",
276
+ windowlength_ms=1000,
277
+ log_transform="123",
278
+ )
279
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "broadband": [10, 600]}
280
+
281
+ with pytest.raises(Exception):
282
+ nm_oscillatory.BandPower.test_settings(settings, ch_names, sfreq)
283
+
284
+
285
+ def test_bp_non_defined_fband():
286
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
287
+ sfreq = 1000
288
+
289
+ settings = setup_osc_settings(
290
+ osc_feature_name="bandpass_filter",
291
+ osc_feature_setting="bandpass_filter_settings",
292
+ windowlength_ms=1000,
293
+ log_transform=True,
294
+ )
295
+
296
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "broadband": [10, 600]}
297
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["theta"] = 1000
298
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["beta"] = 300
299
+
300
+ with pytest.raises(Exception):
301
+ nm_oscillatory.BandPower.test_settings(settings, ch_names, sfreq)
302
+
303
+
304
+ def test_bp_segment_length_fb_exceeds_segment_length_features():
305
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
306
+ sfreq = 1000
307
+
308
+ settings = setup_osc_settings(
309
+ osc_feature_name="bandpass_filter",
310
+ osc_feature_setting="bandpass_filter_settings",
311
+ windowlength_ms=1000,
312
+ log_transform=True,
313
+ )
314
+
315
+ settings["segment_length_features_ms"] = 500
316
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "broadband": [10, 600]}
317
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["theta"] = 1000
318
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["beta"] = 300
319
+
320
+ with pytest.raises(Exception):
321
+ nm_oscillatory.BandPower.test_settings(settings, ch_names, sfreq)
322
+
323
+
324
+ def test_bp_zero_data():
325
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
326
+ sfreq = 1000
327
+
328
+ settings = nm_settings.get_default_settings()
329
+ settings = nm_settings.reset_settings(settings)
330
+ settings["features"]["bandpass_filter"] = True
331
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["theta"] = 1000
332
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["beta"] = 300
333
+
334
+ settings["bandpass_filter_settings"]["log_transform"] = False
335
+ settings["bandpass_filter_settings"]["kalman_filter"] = False
336
+ settings["bandpass_filter_settings"]["bandpower_features"][
337
+ "activity"
338
+ ] = True
339
+
340
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 20]}
341
+ stft_obj = nm_oscillatory.BandPower(settings, ch_names, sfreq)
342
+ stft_obj.test_settings(settings, ch_names, sfreq)
343
+
344
+ data = np.zeros([len(ch_names), sfreq])
345
+ features_out = stft_obj.calc_feature(data, {})
346
+
347
+ for f in features_out.keys():
348
+ assert pytest.approx(0, 0.01) == features_out[f]
349
+
350
+
351
+ def test_bp_random_data():
352
+ ch_names = ["ch1", "ch2", "ch3", "ch4"]
353
+ sfreq = 1000
354
+
355
+ settings = nm_settings.get_default_settings()
356
+ settings = nm_settings.reset_settings(settings)
357
+ settings["frequency_ranges_hz"] = {"theta": [4, 8], "beta": [10, 30]}
358
+ settings["features"]["bandpass_filter"] = True
359
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["theta"] = 1000
360
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["beta"] = 300
361
+
362
+ settings["bandpass_filter_settings"]["log_transform"] = False
363
+ settings["bandpass_filter_settings"]["kalman_filter"] = False
364
+ settings["bandpass_filter_settings"]["bandpower_features"][
365
+ "activity"
366
+ ] = True
367
+
368
+ stft_obj = nm_oscillatory.BandPower(settings, ch_names, sfreq)
369
+ stft_obj.test_settings(settings, ch_names, sfreq)
370
+
371
+ np.random.seed(0)
372
+ data = np.random.random([len(ch_names), sfreq])
373
+ features_out = stft_obj.calc_feature(data, {})
374
+
375
+ for f in features_out.keys():
376
+ assert pytest.approx(0, 0.01) != features_out[f]
377
+
378
+
379
+ def test_bp_beta_osc():
380
+ ch_names = [
381
+ "ch1",
382
+ ]
383
+ sfreq = 1000
384
+
385
+ settings = nm_settings.get_default_settings()
386
+ settings = nm_settings.reset_settings(settings)
387
+ settings["frequency_ranges_hz"] = {
388
+ "theta": [4, 8],
389
+ "beta": [10, 30],
390
+ "gamma": [50, 60],
391
+ }
392
+
393
+ settings["features"]["bandpass_filter"] = True
394
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["theta"] = 1000
395
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["beta"] = 300
396
+ settings["bandpass_filter_settings"]["segment_lengths_ms"]["gamma"] = 100
397
+
398
+ settings["bandpass_filter_settings"]["log_transform"] = False
399
+ settings["bandpass_filter_settings"]["kalman_filter"] = False
400
+ settings["bandpass_filter_settings"]["bandpower_features"][
401
+ "activity"
402
+ ] = True
403
+
404
+ bp_obj = nm_oscillatory.BandPower(settings, ch_names, sfreq)
405
+ bp_obj.test_settings(settings, ch_names, sfreq)
406
+
407
+ time_duration = 1
408
+
409
+ time_points = np.arange(0, time_duration, 1 / sfreq)
410
+ beta_freq = 20
411
+
412
+ beta_wave = np.sin(2 * np.pi * beta_freq * time_points)
413
+
414
+ np.random.seed(0)
415
+ data = np.random.random([len(ch_names), sfreq]) + beta_wave
416
+
417
+ features_out = bp_obj.calc_feature(data, {})
418
+
419
+ assert (
420
+ features_out["ch1_bandpass_activity_beta"]
421
+ > features_out["ch1_bandpass_activity_theta"]
422
+ and features_out["ch1_bandpass_activity_beta"]
423
+ > features_out["ch1_bandpass_activity_gamma"]
424
+ )
@@ -0,0 +1,151 @@
1
+ import numpy as np
2
+ from scipy import signal
3
+
4
+ from py_neuromodulation import nm_settings
5
+ from py_neuromodulation.nm_filter_preprocessing import PreprocessingFilter
6
+
7
+
8
+ def test_preprocessing_within_pipeline(setup_default_stream_fast_compute):
9
+
10
+ data, stream = setup_default_stream_fast_compute
11
+
12
+ stream.settings["preprocessing"].append("preprocessing_filter")
13
+
14
+ stream.settings["preprocessing_filter"]["bandstop_filter"] = True
15
+ stream.settings["preprocessing_filter"]["bandpass_filter"] = True
16
+ stream.settings["preprocessing_filter"]["lowpass_filter"] = True
17
+ stream.settings["preprocessing_filter"]["highpass_filter"] = True
18
+
19
+ stream.sfreq
20
+
21
+ try:
22
+ _ = stream.run(data[:, : int(stream.sfreq * 2)])
23
+ except Exception as e:
24
+ assert False, f"Error in pipeline including preprocess filtering : {e}"
25
+
26
+
27
+ def test_preprocessing_filter_lowpass():
28
+
29
+ data_batch = np.random.random([1, 1000])
30
+
31
+ settings = nm_settings.get_default_settings()
32
+ settings["preprocessing"] = settings["preprocessing"].append(
33
+ "preprocessing_filter"
34
+ )
35
+ settings["preprocessing_filter"]["lowpass_filter"] = True
36
+ settings["preprocessing_filter"]["highpass_filter"] = False
37
+ settings["preprocessing_filter"]["bandpass_filter"] = False
38
+ settings["preprocessing_filter"]["bandstop_filter"] = False
39
+
40
+ settings["preprocessing_filter"]["lowpass_filter_settings"][
41
+ "frequency_cutoff_hz"
42
+ ] = 100
43
+
44
+ sfreq = 1000
45
+
46
+ preprocessing_filter = PreprocessingFilter(settings, sfreq)
47
+ data_filtered = preprocessing_filter.process(data_batch)
48
+
49
+ # compute a scipy signal welch to check if the filter worked
50
+ f, Pxx = signal.welch(data_batch, fs=sfreq, nperseg=1000)
51
+ f, Pxx_f = signal.welch(data_filtered, fs=sfreq, nperseg=1000)
52
+
53
+ # check if the power in the frequency range of the lowpass filter is reduced
54
+ assert np.mean(Pxx_f[0, 100:500]) < np.mean(Pxx[0, 100:500])
55
+
56
+
57
+ def test_preprocessing_filter_highpass():
58
+
59
+ data_batch = np.random.random([1, 1000])
60
+
61
+ settings = nm_settings.get_default_settings()
62
+ settings["preprocessing"] = settings["preprocessing"].append(
63
+ "preprocessing_filter"
64
+ )
65
+ settings["preprocessing_filter"]["highpass_filter"] = True
66
+ settings["preprocessing_filter"]["lowpass_filter"] = False
67
+ settings["preprocessing_filter"]["bandpass_filter"] = False
68
+ settings["preprocessing_filter"]["bandstop_filter"] = False
69
+
70
+ settings["preprocessing_filter"]["highpass_filter_settings"][
71
+ "frequency_cutoff_hz"
72
+ ] = 100
73
+
74
+ sfreq = 1000
75
+
76
+ preprocessing_filter = PreprocessingFilter(settings, sfreq)
77
+ data_filtered = preprocessing_filter.process(data_batch)
78
+
79
+ # compute a scipy signal welch to check if the filter worked
80
+ f, Pxx = signal.welch(data_batch, fs=sfreq, nperseg=1000)
81
+ f, Pxx_f = signal.welch(data_filtered, fs=sfreq, nperseg=1000)
82
+
83
+ # check if the power in the frequency range of the highpass filter is reduced
84
+ assert np.mean(Pxx_f[0, 0:100]) < np.mean(Pxx[0, 0:100])
85
+
86
+
87
+ def test_preprocessing_filter_bandstop():
88
+
89
+ data_batch = np.random.random([1, 1000])
90
+
91
+ settings = nm_settings.get_default_settings()
92
+ settings["preprocessing"] = settings["preprocessing"].append(
93
+ "preprocessing_filter"
94
+ )
95
+ settings["preprocessing_filter"]["bandstop_filter"] = True
96
+ settings["preprocessing_filter"]["bandpass_filter"] = False
97
+ settings["preprocessing_filter"]["lowpass_filter"] = False
98
+ settings["preprocessing_filter"]["highpass_filter"] = False
99
+
100
+ settings["preprocessing_filter"]["bandstop_filter_settings"][
101
+ "frequency_low_hz"
102
+ ] = 100
103
+ settings["preprocessing_filter"]["bandstop_filter_settings"][
104
+ "frequency_high_hz"
105
+ ] = 160
106
+
107
+ sfreq = 1000
108
+
109
+ preprocessing_filter = PreprocessingFilter(settings, sfreq)
110
+ data_filtered = preprocessing_filter.process(data_batch)
111
+
112
+ # compute a scipy signal welch to check if the filter worked
113
+ f, Pxx = signal.welch(data_batch, fs=sfreq, nperseg=1000)
114
+ f, Pxx_f = signal.welch(data_filtered, fs=sfreq, nperseg=1000)
115
+
116
+ # check if the power in the frequency range of the bandstop filter is reduced
117
+ assert np.mean(Pxx_f[0, 100:160]) < np.mean(Pxx[0, 100:160])
118
+
119
+
120
+ def test_preprocessing_filter_bandpass():
121
+
122
+ data_batch = np.random.random([1, 1000])
123
+
124
+ settings = nm_settings.get_default_settings()
125
+ settings["preprocessing"] = settings["preprocessing"].append(
126
+ "preprocessing_filter"
127
+ )
128
+ settings["preprocessing_filter"]["bandstop_filter"] = False
129
+ settings["preprocessing_filter"]["bandpass_filter"] = True
130
+ settings["preprocessing_filter"]["lowpass_filter"] = False
131
+ settings["preprocessing_filter"]["highpass_filter"] = False
132
+
133
+ settings["preprocessing_filter"]["bandpass_filter_settings"][
134
+ "frequency_low_hz"
135
+ ] = 100
136
+ settings["preprocessing_filter"]["bandpass_filter_settings"][
137
+ "frequency_high_hz"
138
+ ] = 160
139
+
140
+ sfreq = 1000
141
+
142
+ preprocessing_filter = PreprocessingFilter(settings, sfreq)
143
+ data_filtered = preprocessing_filter.process(data_batch)
144
+
145
+ # compute a scipy signal welch to check if the filter worked
146
+ f, Pxx = signal.welch(data_batch, fs=sfreq, nperseg=1000)
147
+ f, Pxx_f = signal.welch(data_filtered, fs=sfreq, nperseg=1000)
148
+
149
+ # check if the power in the frequency range of the bandpass filter is reduced
150
+ assert np.mean(Pxx_f[0, 0:100]) < np.mean(Pxx[0, 0:100])
151
+ assert np.mean(Pxx_f[0, 160:500]) < np.mean(Pxx[0, 160:500])