py-neuromodulation 0.0.3__py3-none-any.whl → 0.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. py_neuromodulation/ConnectivityDecoding/Automated Anatomical Labeling 3 (Rolls 2020).nii +0 -0
  2. py_neuromodulation/ConnectivityDecoding/_get_grid_hull.m +34 -0
  3. py_neuromodulation/ConnectivityDecoding/_get_grid_whole_brain.py +95 -0
  4. py_neuromodulation/ConnectivityDecoding/_helper_write_connectome.py +107 -0
  5. py_neuromodulation/ConnectivityDecoding/mni_coords_cortical_surface.mat +0 -0
  6. py_neuromodulation/ConnectivityDecoding/mni_coords_whole_brain.mat +0 -0
  7. py_neuromodulation/ConnectivityDecoding/rmap_func_all.nii +0 -0
  8. py_neuromodulation/ConnectivityDecoding/rmap_struc.nii +0 -0
  9. py_neuromodulation/FieldTrip.py +589 -589
  10. py_neuromodulation/__init__.py +74 -13
  11. py_neuromodulation/_write_example_dataset_helper.py +83 -65
  12. py_neuromodulation/data/README +6 -0
  13. py_neuromodulation/data/dataset_description.json +8 -0
  14. py_neuromodulation/data/participants.json +32 -0
  15. py_neuromodulation/data/participants.tsv +2 -0
  16. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +5 -0
  17. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +11 -0
  18. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +11 -0
  19. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
  20. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +18 -0
  21. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +35 -0
  22. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +13 -0
  23. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +2 -0
  24. py_neuromodulation/grid_cortex.tsv +40 -0
  25. py_neuromodulation/grid_subcortex.tsv +1429 -0
  26. py_neuromodulation/liblsl/libpugixml.so.1.12 +0 -0
  27. py_neuromodulation/liblsl/linux/bionic_amd64/liblsl.1.16.2.so +0 -0
  28. py_neuromodulation/liblsl/linux/bookworm_amd64/liblsl.1.16.2.so +0 -0
  29. py_neuromodulation/liblsl/linux/focal_amd46/liblsl.1.16.2.so +0 -0
  30. py_neuromodulation/liblsl/linux/jammy_amd64/liblsl.1.16.2.so +0 -0
  31. py_neuromodulation/liblsl/linux/jammy_x86/liblsl.1.16.2.so +0 -0
  32. py_neuromodulation/liblsl/linux/noble_amd64/liblsl.1.16.2.so +0 -0
  33. py_neuromodulation/liblsl/macos/amd64/liblsl.1.16.2.dylib +0 -0
  34. py_neuromodulation/liblsl/macos/arm64/liblsl.1.16.0.dylib +0 -0
  35. py_neuromodulation/liblsl/windows/amd64/liblsl.1.16.2.dll +0 -0
  36. py_neuromodulation/liblsl/windows/x86/liblsl.1.16.2.dll +0 -0
  37. py_neuromodulation/nm_IO.py +413 -417
  38. py_neuromodulation/nm_RMAP.py +496 -531
  39. py_neuromodulation/nm_analysis.py +993 -1074
  40. py_neuromodulation/nm_artifacts.py +30 -25
  41. py_neuromodulation/nm_bispectra.py +154 -168
  42. py_neuromodulation/nm_bursts.py +292 -198
  43. py_neuromodulation/nm_coherence.py +251 -205
  44. py_neuromodulation/nm_database.py +149 -0
  45. py_neuromodulation/nm_decode.py +918 -992
  46. py_neuromodulation/nm_define_nmchannels.py +300 -302
  47. py_neuromodulation/nm_features.py +144 -116
  48. py_neuromodulation/nm_filter.py +219 -219
  49. py_neuromodulation/nm_filter_preprocessing.py +79 -91
  50. py_neuromodulation/nm_fooof.py +139 -159
  51. py_neuromodulation/nm_generator.py +45 -37
  52. py_neuromodulation/nm_hjorth_raw.py +52 -73
  53. py_neuromodulation/nm_kalmanfilter.py +71 -58
  54. py_neuromodulation/nm_linelength.py +21 -33
  55. py_neuromodulation/nm_logger.py +66 -0
  56. py_neuromodulation/nm_mne_connectivity.py +149 -112
  57. py_neuromodulation/nm_mnelsl_generator.py +90 -0
  58. py_neuromodulation/nm_mnelsl_stream.py +116 -0
  59. py_neuromodulation/nm_nolds.py +96 -93
  60. py_neuromodulation/nm_normalization.py +173 -214
  61. py_neuromodulation/nm_oscillatory.py +423 -448
  62. py_neuromodulation/nm_plots.py +585 -612
  63. py_neuromodulation/nm_preprocessing.py +83 -0
  64. py_neuromodulation/nm_projection.py +370 -394
  65. py_neuromodulation/nm_rereference.py +97 -95
  66. py_neuromodulation/nm_resample.py +59 -50
  67. py_neuromodulation/nm_run_analysis.py +325 -435
  68. py_neuromodulation/nm_settings.py +289 -68
  69. py_neuromodulation/nm_settings.yaml +244 -0
  70. py_neuromodulation/nm_sharpwaves.py +423 -401
  71. py_neuromodulation/nm_stats.py +464 -480
  72. py_neuromodulation/nm_stream.py +398 -0
  73. py_neuromodulation/nm_stream_abc.py +166 -218
  74. py_neuromodulation/nm_types.py +193 -0
  75. py_neuromodulation/plots/STN_surf.mat +0 -0
  76. py_neuromodulation/plots/Vertices.mat +0 -0
  77. py_neuromodulation/plots/faces.mat +0 -0
  78. py_neuromodulation/plots/grid.mat +0 -0
  79. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.5.dist-info}/METADATA +185 -182
  80. py_neuromodulation-0.0.5.dist-info/RECORD +83 -0
  81. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.5.dist-info}/WHEEL +1 -2
  82. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.5.dist-info/licenses}/LICENSE +21 -21
  83. docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
  84. docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -233
  85. docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  86. docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
  87. docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  88. docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
  89. docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  90. docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
  91. docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -239
  92. docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  93. docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
  94. docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  95. docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
  96. docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  97. docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -76
  98. docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +0 -97
  99. docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -240
  100. docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +0 -233
  101. docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +0 -63
  102. docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  103. docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +0 -210
  104. docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +0 -192
  105. docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +0 -219
  106. docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -121
  107. docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +0 -68
  108. docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  109. docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -189
  110. docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  111. docs/source/auto_examples/plot_0_first_demo.py +0 -189
  112. docs/source/auto_examples/plot_1_example_BIDS.py +0 -240
  113. docs/source/auto_examples/plot_2_example_add_feature.py +0 -76
  114. docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +0 -219
  115. docs/source/auto_examples/plot_4_example_gridPointProjection.py +0 -210
  116. docs/source/auto_examples/plot_5_example_rmap_computing.py +0 -64
  117. docs/source/auto_examples/plot_6_real_time_demo.py +0 -121
  118. docs/source/conf.py +0 -105
  119. examples/plot_0_first_demo.py +0 -189
  120. examples/plot_1_example_BIDS.py +0 -240
  121. examples/plot_2_example_add_feature.py +0 -76
  122. examples/plot_3_example_sharpwave_analysis.py +0 -219
  123. examples/plot_4_example_gridPointProjection.py +0 -210
  124. examples/plot_5_example_rmap_computing.py +0 -64
  125. examples/plot_6_real_time_demo.py +0 -121
  126. packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +0 -4
  127. packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +0 -104
  128. packages/realtime_decoding/build/lib/realtime_decoding/features.py +0 -163
  129. packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +0 -15
  130. packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +0 -345
  131. packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +0 -54
  132. packages/tmsi/build/lib/TMSiFileFormats/__init__.py +0 -37
  133. packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +0 -36
  134. packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +0 -200
  135. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +0 -496
  136. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +0 -236
  137. packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +0 -977
  138. packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +0 -35
  139. packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +0 -116
  140. packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +0 -294
  141. packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +0 -229
  142. packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +0 -102
  143. packages/tmsi/build/lib/TMSiPlotters/__init__.py +0 -2
  144. packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +0 -39
  145. packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +0 -234
  146. packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +0 -440
  147. packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +0 -44
  148. packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +0 -446
  149. packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +0 -589
  150. packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +0 -1326
  151. packages/tmsi/build/lib/TMSiSDK/__init__.py +0 -54
  152. packages/tmsi/build/lib/TMSiSDK/device.py +0 -588
  153. packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +0 -34
  154. packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +0 -1764
  155. packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +0 -34
  156. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +0 -1366
  157. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +0 -520
  158. packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +0 -165
  159. packages/tmsi/build/lib/TMSiSDK/error.py +0 -95
  160. packages/tmsi/build/lib/TMSiSDK/sample_data.py +0 -63
  161. packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +0 -99
  162. packages/tmsi/build/lib/TMSiSDK/settings.py +0 -45
  163. packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +0 -111
  164. packages/tmsi/build/lib/__init__.py +0 -4
  165. packages/tmsi/build/lib/apex_sdk/__init__.py +0 -34
  166. packages/tmsi/build/lib/apex_sdk/device/__init__.py +0 -41
  167. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +0 -1009
  168. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +0 -239
  169. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +0 -668
  170. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +0 -1611
  171. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +0 -38
  172. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +0 -57
  173. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +0 -44
  174. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +0 -150
  175. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +0 -36
  176. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +0 -48
  177. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +0 -108
  178. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +0 -39
  179. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +0 -77
  180. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +0 -150
  181. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +0 -129
  182. packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +0 -59
  183. packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +0 -57
  184. packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +0 -83
  185. packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +0 -201
  186. packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +0 -103
  187. packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +0 -43
  188. packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +0 -50
  189. packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +0 -118
  190. packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +0 -33
  191. packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +0 -44
  192. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +0 -50
  193. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +0 -136
  194. packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +0 -126
  195. packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +0 -113
  196. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +0 -134
  197. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +0 -60
  198. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +0 -42
  199. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +0 -42
  200. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +0 -72
  201. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +0 -98
  202. py_neuromodulation/nm_EpochStream.py +0 -92
  203. py_neuromodulation/nm_across_patient_decoding.py +0 -927
  204. py_neuromodulation/nm_cohortwrapper.py +0 -435
  205. py_neuromodulation/nm_eval_timing.py +0 -239
  206. py_neuromodulation/nm_features_abc.py +0 -39
  207. py_neuromodulation/nm_stream_offline.py +0 -358
  208. py_neuromodulation/utils/_logging.py +0 -24
  209. py_neuromodulation-0.0.3.dist-info/RECORD +0 -188
  210. py_neuromodulation-0.0.3.dist-info/top_level.txt +0 -5
  211. tests/__init__.py +0 -0
  212. tests/conftest.py +0 -117
  213. tests/test_all_examples.py +0 -10
  214. tests/test_all_features.py +0 -63
  215. tests/test_bispectra.py +0 -70
  216. tests/test_bursts.py +0 -105
  217. tests/test_feature_sampling_rates.py +0 -143
  218. tests/test_fooof.py +0 -16
  219. tests/test_initalization_offline_stream.py +0 -41
  220. tests/test_multiprocessing.py +0 -58
  221. tests/test_nan_values.py +0 -29
  222. tests/test_nm_filter.py +0 -95
  223. tests/test_nm_resample.py +0 -63
  224. tests/test_normalization_settings.py +0 -146
  225. tests/test_notch_filter.py +0 -31
  226. tests/test_osc_features.py +0 -424
  227. tests/test_preprocessing_filter.py +0 -151
  228. tests/test_rereference.py +0 -171
  229. tests/test_sampling.py +0 -57
  230. tests/test_settings_change_after_init.py +0 -76
  231. tests/test_sharpwave.py +0 -165
  232. tests/test_target_channel_add.py +0 -100
  233. tests/test_timing.py +0 -80
@@ -1,35 +0,0 @@
1
- """
2
- (c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
-
16
- ####### # # ##### #
17
- # ## ## #
18
- # # # # # # #
19
- # # # # ##### #
20
- # # # # #
21
- # # # # #
22
- # # # ##### #
23
-
24
- /**
25
- * @file ${__init__.py}
26
- * @brief Initialisation of the file_readers directory classes.
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- from .poly5reader import Poly5Reader
34
- from .xdf_reader import Xdf_Reader
35
- from .edf_reader import Edf_Reader
@@ -1,116 +0,0 @@
1
- """
2
- (c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
-
16
- ####### # # ##### #
17
- # ## ## #
18
- # # # # # # #
19
- # # # # ##### #
20
- # # # # #
21
- # # # # #
22
- # # # ##### #
23
-
24
- /**
25
- * @file ${xdf_reader.py}
26
- * @brief EDF to MNE Converter.
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- import tkinter as tk
34
- from tkinter import filedialog
35
- import mne
36
- import pandas as pd
37
-
38
- from os.path import join, dirname, realpath
39
-
40
- Reader_dir = dirname(realpath(__file__)) # directory of this file
41
- modules_dir = join(Reader_dir, "../../") # directory with all modules
42
-
43
-
44
- class Edf_Reader:
45
- def __init__(self, filename=None, add_ch_locs=False):
46
- if filename == None:
47
- root = tk.Tk()
48
- filename = filedialog.askopenfilename(
49
- title="Select edf-file",
50
- filetypes=(("edf-files", "*.edf"), ("All files", "*.*")),
51
- )
52
- root.withdraw()
53
-
54
- # read raw edf-file
55
- # change channel type of COUNTER channel to misc
56
- mne_object = mne.io.read_raw_edf(filename, misc=[-2], preload=True)
57
-
58
- if add_ch_locs:
59
- # add channel locations from txt file
60
- chLocs = pd.read_csv(
61
- join(modules_dir, "TMSiSDK/_resources/EEGchannelsTMSi3D.txt"),
62
- sep="\t",
63
- header=None,
64
- )
65
- chLocs.columns = ["default_name", "eeg_name", "X", "Y", "Z"]
66
- # add locations and convert to head size of 95 mm
67
- for idx, ch in enumerate(mne_object.info["chs"]):
68
- try:
69
- a = [
70
- i
71
- for i, e in (
72
- enumerate(chLocs["eeg_name"].values)
73
- or enumerate(chLocs["default_name"].values)
74
- )
75
- if e == ch["ch_name"]
76
- ]
77
- mne_object.info["chs"][idx]["loc"][0] = (
78
- 95 * 1e-3 * chLocs["X"].values[a]
79
- )
80
- mne_object.info["chs"][idx]["loc"][1] = (
81
- 95 * 1e-3 * chLocs["Y"].values[a]
82
- )
83
- mne_object.info["chs"][idx]["loc"][2] = (
84
- 95 * 1e-3 * chLocs["Z"].values[a]
85
- )
86
- except:
87
- pass
88
-
89
- # unit conversion of eeg channels
90
- mne_object.apply_function(lambda x: x * 1e-6, picks="eeg")
91
-
92
- self.mne_object = mne_object
93
-
94
- def add_impedances(self, imp_filename=None):
95
- """Add impedances from .txt-file"""
96
- if imp_filename == None:
97
- root = tk.Tk()
98
- imp_filename = filedialog.askopenfilename(
99
- title="Select impedance file",
100
- filetypes=(("text files", "*.txt"), ("All files", "*.*")),
101
- )
102
- root.withdraw()
103
- impedances = []
104
-
105
- imp_df = pd.read_csv(imp_filename, delimiter="\t", header=None)
106
- imp_df.columns = ["ch_name", "impedance", "unit"]
107
-
108
- for ch in range(len(self.mne_object.info["chs"])):
109
- for i_ch in range(len(imp_df)):
110
- if (
111
- self.mne_object.info["chs"][ch]["ch_name"]
112
- == imp_df["ch_name"][i_ch]
113
- ):
114
- impedances.append(imp_df["impedance"][i_ch])
115
-
116
- self.mne_object.impedances = impedances
@@ -1,294 +0,0 @@
1
- """
2
- (c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
-
16
- ####### # # ##### #
17
- # ## ## #
18
- # # # # # # #
19
- # # # # ##### #
20
- # # # # #
21
- # # # # #
22
- # # # ##### #
23
-
24
- /**
25
- * @file ${poly5reader.py}
26
- * @brief Poly5 File Reader.
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- import numpy as np
34
- import struct
35
- import datetime
36
- import mne
37
- import tkinter as tk
38
- from tkinter import filedialog
39
-
40
-
41
- class Poly5Reader:
42
- def __init__(self, filename=None, readAll=True):
43
- if filename == None:
44
- root = tk.Tk()
45
-
46
- filename = filedialog.askopenfilename(
47
- title="Select poly5-file",
48
- filetypes=(("poly5-files", "*.poly5"), ("All files", "*.*")),
49
- )
50
- root.withdraw()
51
-
52
- self.filename = filename
53
- self.readAll = readAll
54
- print("Reading file ", filename)
55
- self._readFile(filename)
56
-
57
- def read_data_MNE(
58
- self,
59
- ) -> mne.io.RawArray:
60
- """Return MNE RawArray given internal channel names and types
61
-
62
- Returns
63
- -------
64
- mne.io.RawArray
65
- """
66
-
67
- streams = self.channels
68
- fs = self.sample_rate
69
- labels = [s._Channel__name for s in streams]
70
- units = [s._Channel__unit_name for s in streams]
71
-
72
- type_options = [
73
- "ecg",
74
- "bio",
75
- "stim",
76
- "eog",
77
- "misc",
78
- "seeg",
79
- "dbs",
80
- "ecog",
81
- "mag",
82
- "eeg",
83
- "ref_meg",
84
- "grad",
85
- "emg",
86
- "hbr",
87
- "hbo",
88
- ]
89
- types_clean = []
90
- for t in labels:
91
- for t_option in type_options:
92
- if t_option in t.lower():
93
- types_clean.append(t_option)
94
- break
95
- else:
96
- types_clean.append("misc")
97
-
98
- info = mne.create_info(ch_names=labels, sfreq=fs, ch_types=types_clean)
99
-
100
- # convert from microvolts to volts if necessary
101
- scale = np.array([1e-6 if u == "µVolt" else 1 for u in units])
102
-
103
- raw = mne.io.RawArray(
104
- self.samples * np.expand_dims(scale, axis=1), info
105
- )
106
- return raw
107
-
108
- def _readFile(self, filename):
109
- try:
110
- self.file_obj = open(filename, "rb")
111
- file_obj = self.file_obj
112
- try:
113
- self._readHeader(file_obj)
114
- self.channels = self._readSignalDescription(file_obj)
115
- self._myfmt = (
116
- "f" * self.num_channels * self.num_samples_per_block
117
- )
118
- self._buffer_size = (
119
- self.num_channels * self.num_samples_per_block
120
- )
121
-
122
- if self.readAll:
123
- sample_buffer = np.zeros(
124
- self.num_channels * self.num_samples
125
- )
126
-
127
- for i in range(self.num_data_blocks):
128
- print(
129
- "\rProgress: % 0.1f %%"
130
- % (100 * i / self.num_data_blocks),
131
- end="\r",
132
- )
133
-
134
- # Check whether final data block is filled completely or not
135
- if i == self.num_data_blocks - 1:
136
- _final_block_size = (
137
- self.num_samples / self.num_data_blocks
138
- )
139
- if (
140
- _final_block_size % self.num_samples_per_block
141
- != 0
142
- ):
143
- data_block = self._readSignalBlock(
144
- file_obj,
145
- buffer_size=(
146
- self.num_samples
147
- % self.num_samples_per_block
148
- )
149
- * self.num_channels,
150
- myfmt="f"
151
- * (
152
- self.num_samples
153
- % self.num_samples_per_block
154
- )
155
- * self.num_channels,
156
- )
157
- else:
158
- data_block = self._readSignalBlock(
159
- file_obj, self._buffer_size, self._myfmt
160
- )
161
- else:
162
- data_block = self._readSignalBlock(
163
- file_obj, self._buffer_size, self._myfmt
164
- )
165
-
166
- # Get indices that need to be filled in the samples array
167
- i1 = i * self.num_samples_per_block * self.num_channels
168
- i2 = (
169
- (i + 1)
170
- * self.num_samples_per_block
171
- * self.num_channels
172
- )
173
-
174
- # Correct for final data block if this is not fully filled
175
- if i2 >= self.num_samples * self.num_channels:
176
- i2 = self.num_samples * self.num_channels
177
-
178
- # Insert the read data_block into the sample_buffer array
179
- sample_buffer[i1:i2] = data_block
180
-
181
- samples = np.transpose(
182
- np.reshape(
183
- sample_buffer, [self.num_samples, self.num_channels]
184
- )
185
- )
186
-
187
- self.ch_names = [s._Channel__name for s in self.channels]
188
- self.ch_unit_names = [
189
- s._Channel__unit_name for s in self.channels
190
- ]
191
-
192
- self.samples = samples
193
- print("Done reading data.")
194
- self.file_obj.close()
195
-
196
- except Exception as e:
197
- print("Reading data failed, because of the following error:\n")
198
- raise
199
- except OSError:
200
- print("Could not open file. ")
201
-
202
- def readSamples(self, n_blocks=None):
203
- "Function to read a subset of sample blocks from a file"
204
- if n_blocks == None:
205
- n_blocks = self.num_data_blocks
206
-
207
- sample_buffer = np.zeros(
208
- self.num_channels * n_blocks * self.num_samples_per_block
209
- )
210
-
211
- for i in range(n_blocks):
212
- data_block = self._readSignalBlock(
213
- self.file_obj, self._buffer_size, self._myfmt
214
- )
215
- i1 = i * self.num_samples_per_block * self.num_channels
216
- i2 = (i + 1) * self.num_samples_per_block * self.num_channels
217
- sample_buffer[i1:i2] = data_block
218
-
219
- samples = np.transpose(
220
- np.reshape(
221
- sample_buffer,
222
- [self.num_samples_per_block * (i + 1), self.num_channels],
223
- )
224
- )
225
- return samples
226
-
227
- def _readHeader(self, f):
228
- header_data = struct.unpack(
229
- "=31sH81phhBHi4xHHHHHHHiHHH64x", f.read(217)
230
- )
231
- magic_number = str(header_data[0])
232
- version_number = header_data[1]
233
- self.sample_rate = header_data[3]
234
- # self.storage_rate=header_data[4]
235
- self.num_channels = header_data[6] // 2
236
- self.num_samples = header_data[7]
237
- self.start_time = datetime.datetime(
238
- header_data[8],
239
- header_data[9],
240
- header_data[10],
241
- header_data[12],
242
- header_data[13],
243
- header_data[14],
244
- )
245
- self.num_data_blocks = header_data[15]
246
- self.num_samples_per_block = header_data[16]
247
- if magic_number != "b'POLY SAMPLE FILEversion 2.03\\r\\n\\x1a'":
248
- print("This is not a Poly5 file.")
249
- elif version_number != 203:
250
- print("Version number of file is invalid.")
251
- else:
252
- print("\t Number of samples: %s " % self.num_samples)
253
- print("\t Number of channels: %s " % self.num_channels)
254
- print("\t Sample rate: %s Hz" % self.sample_rate)
255
-
256
- def _readSignalDescription(self, f):
257
- chan_list = []
258
- for ch in range(self.num_channels):
259
- channel_description = struct.unpack(
260
- "=41p4x11pffffH62x", f.read(136)
261
- )
262
- name = channel_description[0][5:].decode("ascii")
263
- unit_name = channel_description[1].decode("utf-8")
264
- ch = Channel(name, unit_name)
265
- chan_list.append(ch)
266
- f.read(136)
267
- return chan_list
268
-
269
- def _readSignalBlock(self, f, buffer_size, myfmt):
270
- f.read(86)
271
- sampleData = f.read(buffer_size * 4)
272
- DataBlock = struct.unpack(myfmt, sampleData)
273
- SignalBlock = np.asarray(DataBlock)
274
- return SignalBlock
275
-
276
- def close(self):
277
- self.file_obj.close()
278
-
279
-
280
- class Channel:
281
- """'Channel' represents a device channel. It has the next properties:
282
-
283
- name : 'string' The name of the channel.
284
-
285
- unit_name : 'string' The name of the unit (e.g. 'μVolt) of the sample-data of the channel.
286
- """
287
-
288
- def __init__(self, name, unit_name):
289
- self.__unit_name = unit_name
290
- self.__name = name
291
-
292
-
293
- if __name__ == "__main__":
294
- data = Poly5Reader()
@@ -1,229 +0,0 @@
1
- """
2
- (c) 2022 Twente Medical Systems International B.V., Oldenzaal The Netherlands
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
-
16
- ####### # # ##### #
17
- # ## ## #
18
- # # # # # # #
19
- # # # # ##### #
20
- # # # # #
21
- # # # # #
22
- # # # ##### #
23
-
24
- /**
25
- * @file ${xdf_reader.py}
26
- * @brief XDF File Reader.
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- from pyxdf import load_xdf
34
- import mne
35
- import tkinter as tk
36
- from tkinter import filedialog
37
- import numpy as np
38
- import pandas as pd
39
- import copy
40
-
41
- from os.path import join, dirname, realpath
42
-
43
- Reader_dir = dirname(realpath(__file__)) # directory of this file
44
- modules_dir = join(Reader_dir, "../../") # directory with all modules
45
-
46
-
47
- class Xdf_Reader:
48
- def __init__(self, filename=None, add_ch_locs=False):
49
- if filename == None:
50
- root = tk.Tk()
51
-
52
- filename = filedialog.askopenfilename(
53
- title="Select xdf-file",
54
- filetypes=(("xdf-files", "*.xdf"), ("All files", "*.*")),
55
- )
56
- root.withdraw()
57
-
58
- self.filename = filename
59
- self.add_ch_locs = add_ch_locs
60
- print("Reading file ", filename)
61
- self.data, self.time_stamps = self._readFile(filename)
62
-
63
- def _readFile(self, fname):
64
- try:
65
- streams, header = load_xdf(fname)
66
- num_streams = len(streams)
67
- self.stream_info = {}
68
-
69
- print("Number of streams in file: " + str(num_streams))
70
- for i in range(num_streams):
71
- stream = streams[i]
72
- self.stream_info[i] = stream["info"]
73
- if stream is not None:
74
- fs = float(stream["info"]["nominal_srate"][0])
75
-
76
- labels, types, units, impedances = self._get_ch_info(stream)
77
-
78
- type_options = [
79
- "ecg",
80
- "bio",
81
- "stim",
82
- "eog",
83
- "misc",
84
- "seeg",
85
- "dbs",
86
- "ecog",
87
- "mag",
88
- "eeg",
89
- "ref_meg",
90
- "grad",
91
- "emg",
92
- "hbr",
93
- "hbo",
94
- ]
95
- for ind, t in enumerate(types):
96
- if t == "EEG":
97
- types[ind] = "eeg"
98
- elif not t in type_options:
99
- types[ind] = "misc"
100
- info = mne.create_info(
101
- ch_names=labels, sfreq=fs, ch_types=types
102
- )
103
- info = self._get_ch_locations(stream, info)
104
- if self.add_ch_locs:
105
- info = self._add_ch_locations(info)
106
-
107
- # convert from microvolts to volts if necessary
108
- scale = np.array(
109
- [1e-6 if u == "µVolt" else 1 for u in units]
110
- )
111
- raw = mne.io.RawArray(
112
- (stream["time_series"] * scale).T, info
113
- )
114
- raw.impedances = impedances
115
-
116
- if raw is not None:
117
- print(raw, end="\n\n")
118
- print(raw.info)
119
-
120
- if num_streams == 1:
121
- return (raw,), (stream["time_stamps"],)
122
- else:
123
- if i == 0:
124
- output_data = (copy.copy(raw),)
125
- output_timestamps = (
126
- copy.copy(stream["time_stamps"]),
127
- )
128
- elif i == num_streams - 1:
129
- output_data = output_data + (copy.copy(raw),)
130
- output_timestamps = output_timestamps + (
131
- copy.copy(stream["time_stamps"]),
132
- )
133
- return output_data, output_timestamps
134
- else:
135
- output_data = output_data + (copy.copy(raw),)
136
- output_timestamps = output_timestamps + (
137
- copy.copy(stream["time_stamps"]),
138
- )
139
- except Exception as e:
140
- print("Reading data failed because of the following error:\n")
141
- raise
142
-
143
- def add_impedances(self, imp_filename=None):
144
- """Add impedances from .txt-file"""
145
- if imp_filename == None:
146
- root = tk.Tk()
147
- imp_filename = filedialog.askopenfilename(
148
- title="Select impedance file",
149
- filetypes=(("text files", "*.txt"), ("All files", "*.*")),
150
- )
151
- root.withdraw()
152
- impedances = []
153
-
154
- imp_df = pd.read_csv(imp_filename, delimiter="\t", header=None)
155
- imp_df.columns = ["ch_name", "impedance", "unit"]
156
-
157
- for ch in range(len(self.data[0].info["chs"])):
158
- for i_ch in range(len(imp_df)):
159
- if (
160
- self.data[0].info["chs"][ch]["ch_name"]
161
- == imp_df["ch_name"][i_ch]
162
- ):
163
- impedances.append(imp_df["impedance"][i_ch])
164
-
165
- self.data[0].impedances = impedances
166
-
167
- def _get_ch_info(self, stream):
168
- # read channel labels, types, units and impedances
169
- labels, types, units, impedances = [], [], [], []
170
-
171
- for ch in stream["info"]["desc"][0]["channels"][0]["channel"]:
172
- labels.append(str(ch["label"][0]))
173
- types.append(ch["type"][0])
174
- units.append(ch["unit"][0])
175
- if ch["impedance"]:
176
- impedances.append(str(ch["impedance"][0]))
177
- return labels, types, units, impedances
178
-
179
- def _get_ch_locations(self, stream, info):
180
- # read channel locations and convert unit from mm to m
181
- for i, ch in enumerate(
182
- stream["info"]["desc"][0]["channels"][0]["channel"]
183
- ):
184
- if ch["location"]:
185
- info["chs"][i]["loc"][0] = (
186
- float(ch["location"][0]["X"][0]) * 1e-3
187
- )
188
- info["chs"][i]["loc"][1] = (
189
- float(ch["location"][0]["Y"][0]) * 1e-3
190
- )
191
- info["chs"][i]["loc"][2] = (
192
- float(ch["location"][0]["Z"][0]) * 1e-3
193
- )
194
- self.add_ch_locs = False
195
- return info
196
-
197
- def _add_ch_locations(self, info):
198
- # add channel locations from txt file
199
- chLocs = pd.read_csv(
200
- join(modules_dir, "TMSiSDK/_resources/EEGchannelsTMSi3D.txt"),
201
- sep="\t",
202
- header=None,
203
- )
204
- chLocs.columns = ["default_name", "eeg_name", "X", "Y", "Z"]
205
-
206
- # add locations and convert to head size of 95 mm
207
- for idx, ch in enumerate(info["chs"]):
208
- try:
209
- a = [
210
- i
211
- for i, e in (
212
- enumerate(chLocs["eeg_name"].values)
213
- or enumerate(chLocs["default_name"].values)
214
- )
215
- if e == ch["ch_name"]
216
- ]
217
- info["chs"][idx]["loc"][0] = 95 * 1e-3 * chLocs["X"].values[a]
218
- info["chs"][idx]["loc"][1] = 95 * 1e-3 * chLocs["Y"].values[a]
219
- info["chs"][idx]["loc"][2] = 95 * 1e-3 * chLocs["Z"].values[a]
220
- except:
221
- pass
222
- return info
223
-
224
- def get_stream_info(self):
225
- # Retrieve the information from the streams in the data.
226
- if hasattr(self, "stream_info"):
227
- return self.stream_info
228
- else:
229
- return None