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,192 +0,0 @@
1
- """
2
- First Demo
3
- ==========
4
-
5
- This Demo will showcase the feature estimation and
6
- exemplar analysis using simulated data.
7
- """
8
-
9
- import numpy as np
10
- from matplotlib import pyplot as plt
11
-
12
- import py_neuromodulation as py_nm
13
-
14
- from py_neuromodulation import (
15
- nm_analysis,
16
- nm_define_nmchannels,
17
- nm_plots
18
-
19
- )
20
-
21
- # %%
22
- # Data Simulation
23
- # ---------------
24
- # We will now generate some exemplar data with 10 second duration for 6 channels with a sample rate of 1 kHz.
25
-
26
- def generate_random_walk(NUM_CHANNELS, TIME_DATA_SAMPLES):
27
- # from https://towardsdatascience.com/random-walks-with-python-8420981bc4bc
28
- dims = NUM_CHANNELS
29
- step_n = TIME_DATA_SAMPLES-1
30
- step_set = [-1, 0, 1]
31
- origin = (np.random.random([1,dims])-0.5)*1 # Simulate steps in 1D
32
- step_shape = (step_n,dims)
33
- steps = np.random.choice(a=step_set, size=step_shape)
34
- path = np.concatenate([origin, steps]).cumsum(0)
35
- return path.T
36
-
37
- NUM_CHANNELS = 6
38
- sfreq = 1000
39
- TIME_DATA_SAMPLES = 10 * sfreq
40
- data = generate_random_walk(NUM_CHANNELS, TIME_DATA_SAMPLES)
41
- time = np.arange(0, TIME_DATA_SAMPLES/sfreq, 1/sfreq)
42
-
43
- plt.figure(figsize=(8,4), dpi=100)
44
- for ch_idx in range(data.shape[0]):
45
- plt.plot(time, data[ch_idx, :])
46
- plt.xlabel("Time [s]")
47
- plt.ylabel("Amplitude")
48
- plt.title("Example random walk data")
49
-
50
- # %%
51
- # Now let’s define the necessary setup files we will be using for data
52
- # preprocessing and feature estimation. Py_neuromodualtion is based on two
53
- # parametrization files: the *nm_channels.tsv* and the *nm_setting.json*.
54
- #
55
- # nm_channels
56
- # ~~~~~~~~~~~
57
- #
58
- # The *nm_channel* dataframe. This dataframe contains the columns
59
- #
60
- # +-----------------------------------+-----------------------------------+
61
- # | Column name | Description |
62
- # +===================================+===================================+
63
- # | **name** | name of the channel |
64
- # +-----------------------------------+-----------------------------------+
65
- # | **rereference** | different channel name for |
66
- # | | bipolar re-referencing, or |
67
- # | | average for common average |
68
- # | | re-referencing |
69
- # +-----------------------------------+-----------------------------------+
70
- # | **used** | 0 or 1, channel selection |
71
- # +-----------------------------------+-----------------------------------+
72
- # | **target** | 0 or 1, for some decoding |
73
- # | | applications we can define target |
74
- # | | channels, e.g. EMG channels |
75
- # +-----------------------------------+-----------------------------------+
76
- # | **type** | channel type according to the |
77
- # | | `mne-python`_ toolbox |
78
- # | | |
79
- # | | |
80
- # | | |
81
- # | | |
82
- # | | e.g. ecog, eeg, ecg, emg, dbs, |
83
- # | | seeg etc. |
84
- # +-----------------------------------+-----------------------------------+
85
- # | **status** | good or bad, used for channel |
86
- # | | quality indication |
87
- # +-----------------------------------+-----------------------------------+
88
- # | **new_name** | this keyword can be specified to |
89
- # | | indicate for example the used |
90
- # | | rereferncing scheme |
91
- # +-----------------------------------+-----------------------------------+
92
- #
93
- # .. _mne-python: https://mne.tools/stable/auto_tutorials/raw/10_raw_overview.html#sphx-glr-auto-tutorials-raw-10-raw-overview-py
94
- #
95
- # The :class:`~nm_stream_abc` can either be created as a *.tsv* text file, or as a pandas
96
- # DataFrame. There are some helper functions that let you create the
97
- # nm_channels without much effort:
98
-
99
- nm_channels = nm_define_nmchannels.get_default_channels_from_data(data, car_rereferencing=True)
100
-
101
- nm_channels
102
-
103
- # %%
104
- # Using this function default channel names and a common average re-referencing scheme is specified.
105
- # Alternatively the *nm_define_nmchannels.set_channels* function can be used to pass each column values.
106
- #
107
- # nm_settings
108
- # -----------
109
- # Next, we will initialize the nm_settings dictionary and use the default settings, reset them, and enable a subset of features:
110
-
111
- settings = py_nm.nm_settings.get_default_settings()
112
- settings = py_nm.nm_settings.reset_settings(settings)
113
-
114
-
115
- # %%
116
- # The setting itself is a .json file which contains the parametrization for preprocessing, feature estimation, postprocessing and
117
- # definition with which sampling rate features are being calculated.
118
- # In this example `sampling_rate_features_hz` is specified to be 10 Hz, so every 100ms a new set of features is calculated.
119
- #
120
- # For many features the `segment_length_features_ms` specifies the time dimension of the raw signal being used for feature calculation. Here it is specified to be 1000 ms.
121
- #
122
- # We will now enable the features:
123
- #
124
- # * fft
125
- # * bursts
126
- # * sharpwave
127
- #
128
- # and stay with the default preprcessing methods:
129
- #
130
- # * notch_filter
131
- # * re_referencing
132
- #
133
- # and use *z-score* postprocessing normalization.
134
-
135
- settings["features"]["fft"] = True
136
- settings["features"]["bursts"] = True
137
- settings["features"]["sharpwave_analysis"] = True
138
-
139
- # %%
140
- # We are now ready to go to instantiate the *Stream* and call the *run* method for feature estimation:
141
-
142
- stream = py_nm.Stream(
143
- settings=settings,
144
- nm_channels=nm_channels,
145
- verbose=True,
146
- sfreq=sfreq,
147
- line_noise=50
148
- )
149
-
150
- features = stream.run(data)
151
-
152
- # %%
153
- # Feature Analysis
154
- # ----------------
155
- #
156
- # There is a lot of output, which we could omit by verbose being False, but let's have a look what was being computed.
157
- # We will therefore use the :class:`~nm_analysis` class to showcase some functions. For multi-run -or subject analysis we will pass here the feature_file "sub" as default directory:
158
-
159
- analyzer = nm_analysis.Feature_Reader(
160
- feature_dir=stream.PATH_OUT,
161
- feature_file=stream.PATH_OUT_folder_name
162
- )
163
-
164
- # %%
165
- # Let's have a look at the resulting "feature_arr" DataFrame:
166
-
167
- analyzer.feature_arr.iloc[:10, :7]
168
-
169
- # %%
170
- # Seems like a lot of features were calculated. The `time` column tells us about each row time index.
171
- # For the 6 specified channels, it is each 31 features.
172
- # We can now use some in-built plotting functions for visualization.
173
- #
174
- # .. note::
175
- #
176
- # Due to the nature of simulated data, some of the features have constant values, which are not displayed through the image normalization.
177
- #
178
- #
179
-
180
- analyzer.plot_all_features(ch_used="ch1")
181
-
182
- # %%
183
- nm_plots.plot_corr_matrix(
184
- figsize=(25,25),
185
- show_plot=True,
186
- feature=analyzer.feature_arr,
187
- )
188
-
189
- # %%
190
- # The upper correlation matrix shows the correlation of every feature of every channel to every other.
191
- # This notebook demonstrated a first demo how features can quickly be generated. For further feature modalities and decoding applications check out the next notebooks.
192
-
@@ -1,210 +0,0 @@
1
- """
2
- Grid Point Projection
3
- =====================
4
-
5
- """
6
-
7
- # %%
8
- # In ECoG datasets the electrode locations are usually different. For this reason, we established a grid
9
- # with a set of points defined in a standardized MNI brain.
10
- # Data is then interpolated to this grid, such that they are common across patients, which allows across patient decoding use cases.
11
- #
12
- # In this notebook, we will plot these grid points and see how the features extracted from our data can be projected into this grid space.
13
- #
14
- # In order to do so, we'll read saved features that were computed in the ECoG movement notebook.
15
- # Please note that in order to do so, when running the feature estimation, the settings
16
- #
17
- # .. note::
18
- #
19
- # .. code-block:: python
20
- #
21
- # stream.settings['postprocessing']['project_cortex'] = True
22
- # stream.settings['postprocessing']['project_subcortex'] = True
23
- #
24
- # need to be set to `True` for a cortical and/or subcortical projection.
25
- #
26
-
27
- # %%
28
- import numpy as np
29
- import matplotlib.pyplot as plt
30
-
31
- import py_neuromodulation as nm
32
- from py_neuromodulation import (
33
- nm_analysis,
34
- nm_plots,
35
- nm_IO,
36
- nm_settings,
37
- nm_define_nmchannels
38
- )
39
-
40
-
41
- # %%
42
- # Read features from BIDS data
43
- # ----------------------------
44
- #
45
- # We first estimate features, with the `grid_point` projection settings enabled for cortex.
46
-
47
-
48
- # %%
49
- RUN_NAME, PATH_RUN, PATH_BIDS, PATH_OUT, datatype = nm_IO.get_paths_example_data()
50
-
51
- (
52
- raw,
53
- data,
54
- sfreq,
55
- line_noise,
56
- coord_list,
57
- coord_names,
58
- ) = nm_IO.read_BIDS_data(
59
- PATH_RUN=PATH_RUN,
60
- BIDS_PATH=PATH_BIDS, datatype=datatype
61
- )
62
-
63
- settings = nm_settings.get_default_settings()
64
- settings = nm_settings.set_settings_fast_compute(settings)
65
-
66
- settings["postprocessing"]["project_cortex"] = True
67
-
68
- nm_channels = nm_define_nmchannels.set_channels(
69
- ch_names=raw.ch_names,
70
- ch_types=raw.get_channel_types(),
71
- reference="default",
72
- bads=raw.info["bads"],
73
- new_names="default",
74
- used_types=("ecog", "dbs", "seeg"),
75
- target_keywords=["MOV_RIGHT_CLEAN","MOV_LEFT_CLEAN"]
76
- )
77
-
78
- stream = nm.Stream(
79
- sfreq=sfreq,
80
- nm_channels=nm_channels,
81
- settings=settings,
82
- line_noise=line_noise,
83
- coord_list=coord_list,
84
- coord_names=coord_names,
85
- verbose=True,
86
- )
87
-
88
- features = stream.run(
89
- data=data[:, :int(sfreq*5)],
90
- out_path_root=PATH_OUT,
91
- folder_name=RUN_NAME,
92
- )
93
-
94
- # %%
95
- # From nm_analysis.py, we use the :class:~`nm_analysis.FeatureReader` class to load the data.
96
-
97
- # init analyzer
98
- feature_reader = nm_analysis.Feature_Reader(
99
- feature_dir=PATH_OUT, feature_file=RUN_NAME
100
- )
101
-
102
- # %%
103
- # To perform the grid projection, for all computed features we check for every grid point if there is any electrode channel within the spatial range ```max_dist_mm```, and weight
104
- # this electrode contact by the inverse distance and normalize across all electrode distances within the maximum distance range.
105
- # This gives us a projection matrix that we can apply to streamed data, to transform the feature-channel matrix *(n_features, n_channels)* into the grid point matrix *(n_features, n_gridpoints)*.
106
- #
107
- # To save computation time, this projection matrix is precomputed before the real time run computation.
108
- # The cortical grid is stored in *py_neuromodulation/grid_cortex.tsv* and the electrodes coordinates are stored in *_space-mni_electrodes.tsv* in a BIDS dataset.
109
- #
110
- # .. note::
111
- #
112
- # One remark is that our cortical and subcortical grids are defined for the **left** hemisphere of the brain and, therefore, electrode contacts are mapped to the left hemisphere.
113
- #
114
- # From the analyzer, the user can plot the cortical projection with the function below, display the grid points and ECoG electrodes are crosses.
115
- # The yellow grid points are the ones that are active for that specific ECoG electrode location. The inactive grid points are shown in purple.
116
-
117
- feature_reader.plot_cort_projection()
118
-
119
- # %%
120
- # We can also plot only the ECoG electrodes or the grid points, with the help of the data saved in feature_reader.sidecar. BIDS sidecar files are json files where you store additional information, here it is used to save the ECoG strip positions and the grid coordinates, which are not part of the settings and nm_channels.csv. We can check what is stored in the file and then use the nmplotter.plot_cortex function:
121
-
122
- grid_plotter = nm_plots.NM_Plot(
123
- ecog_strip=np.array(feature_reader.sidecar["coords"]["cortex_right"]["positions"]),
124
- grid_cortex=np.array(feature_reader.sidecar["grid_cortex"]),
125
- # grid_subcortex=np.array(feature_reader.sidecar["grid_subcortex"]),
126
- sess_right=feature_reader.sidecar["sess_right"],
127
- proj_matrix_cortex=np.array(feature_reader.sidecar["proj_matrix_cortex"])
128
- )
129
-
130
- # %%
131
- grid_plotter.plot_cortex(
132
- grid_color=np.sum(np.array(feature_reader.sidecar["proj_matrix_cortex"]),axis=1),
133
- lower_clim=0.,
134
- upper_clim=1.0,
135
- cbar_label="Used Grid Points",
136
- title = "ECoG electrodes projected onto cortical grid"
137
- )
138
-
139
- # %%
140
- feature_reader.sidecar["coords"]["cortex_right"]["positions"]
141
-
142
- # %%
143
- feature_reader.nmplotter.plot_cortex(
144
- ecog_strip=np.array(
145
- feature_reader.sidecar["coords"]["cortex_right"]["positions"],
146
- ),
147
- lower_clim=0.,
148
- upper_clim=1.0,
149
- cbar_label="Used ECoG Electrodes",
150
- title = "Plot of ECoG electrodes"
151
- )
152
-
153
- # %%
154
- feature_reader.nmplotter.plot_cortex(
155
- np.array(
156
- feature_reader.sidecar["grid_cortex"]
157
- ),
158
- lower_clim=0.,
159
- upper_clim=1.0,
160
- cbar_label="All Grid Points",
161
- title = "All grid points"
162
- )
163
-
164
- # %%
165
- # The Projection Matrix
166
- # ---------------------
167
- # To go from the feature-channel matrix *(n_features, n_channels)* to the grid point matrix *(n_features, n_gridpoints)*
168
- # we need a projection matrix that has the shape *(n_channels, n_gridpoints)*.
169
- # It maps the strengths of the signals in each ECoG channel to the correspondent ones in the cortical grid.
170
- # In the cell below we plot this matrix, that has the property that the column sum over channels for each grid point is either 1 or 0.
171
-
172
- plt.figure(figsize=(8,5))
173
- plt.imshow(np.array(feature_reader.sidecar['proj_matrix_cortex']), aspect = 'auto')
174
- plt.colorbar(label = "Strength of ECoG signal in each grid point")
175
- plt.xlabel("ECoG channels")
176
- plt.ylabel("Grid points")
177
- plt.title("Matrix mapping from ECoG to grid")
178
-
179
- # %%
180
- # Feature Plot in the Grid: An Example of Post-processing
181
- # -------------------------------------------------------
182
- # First we take the dataframe with all the features in all time points.
183
-
184
- df = feature_reader.feature_arr
185
-
186
- # %%
187
- df.iloc[:5, :5]
188
-
189
- # %%
190
- # Then we filter for only 'avgref_fft_theta', which gives us the value for fft_theta in all 6 ECoG channels over all time points. Then we take only the 6th time point - as an arbitrary choice.
191
-
192
- fft_theta_oneTimePoint = np.asarray(df[df.columns[df.columns.str.contains(pat = 'avgref_fft_theta')]].iloc[5])
193
- fft_theta_oneTimePoint
194
-
195
- # %%
196
- # Then the projection of the features into the grid is gonna be the color of the grid points in the *plot_cortex* function.
197
- # That is the matrix multiplication of the projection matrix of the cortex and 6 values for the *fft_theta* feature above.
198
-
199
- grid_fft_Theta = np.array(feature_reader.sidecar["proj_matrix_cortex"]) @ fft_theta_oneTimePoint
200
-
201
- feature_reader.nmplotter.plot_cortex(np.array(
202
- feature_reader.sidecar["grid_cortex"]),grid_color = grid_fft_Theta, set_clim = True, lower_clim=min(grid_fft_Theta[grid_fft_Theta>0]), upper_clim=max(grid_fft_Theta), cbar_label="FFT Theta Projection to Grid", title = "FFT Theta Projection to Grid")
203
-
204
- # %%
205
- # Lower and upper boundaries for clim were chosen to be the max and min values of the projection of the features (minimum value excluding zero). This can be checked in the cell below:
206
-
207
- grid_fft_Theta
208
-
209
- # %%
210
- # In the plot above we can see how the intensity of the fast fourier transform in the theta band varies for each grid point in the cortex, for one specific time point.
@@ -1,68 +0,0 @@
1
- """
2
- ===================
3
- Adding New Features
4
- ===================
5
-
6
- """
7
-
8
- import py_neuromodulation as pn
9
- from py_neuromodulation import nm_features_abc
10
- import numpy as np
11
- from typing import Iterable
12
-
13
- # %%
14
- # In this example we will demonstrate how a new feature can be added to the existing feature pipeline.
15
- # This can be done simply by adding an object of the inherited :class:`~nm_features_abc.Feature`
16
- # class to the stream `stream.run_analysis.features.features` list.
17
-
18
- data = np.random.random([1, 1000])
19
-
20
- stream = pn.Stream(sfreq=1000, data=data, sampling_rate_features_hz=10, verbose=False,)
21
-
22
- class NewFeature(nm_features_abc.Feature):
23
-
24
- def __init__(
25
- self, settings: dict, ch_names: Iterable[str], sfreq: float
26
- ) -> None:
27
- self.s = settings
28
- self.ch_names = ch_names
29
-
30
- def calc_feature(self, data: np.array, features_compute: dict) -> dict:
31
- for ch_idx, ch in enumerate(self.ch_names):
32
- features_compute[f"new_feature_{ch}"] = np.mean(data[ch_idx, :])
33
-
34
- return features_compute
35
-
36
- def test_settings():
37
- pass
38
-
39
- newFeature = NewFeature(stream.settings, list(stream.nm_channels["name"]), stream.sfreq)
40
- stream.run_analysis.features.features.append(newFeature)
41
-
42
- features = stream.run_analysis.process(data)
43
- feature_name = f"new_feature_{stream.nm_channels['name'][0]}"
44
-
45
- print(f"{feature_name}: {features[feature_name]}")
46
-
47
- # %%
48
- # This example shows a simple newly instantiated feature class called `NewFeature`.
49
- # The instantiated `newFeature` object could then be added to the existing feature list by calling
50
- # `stream.run_analysis.features.features.append(newFeature)`.
51
- #
52
- # To permanently add a novel feature, the new feature class needs to be added to
53
- # the :class:`~nm_features` class. This can be done by inserting the feature_name in
54
- # in the :class:`~nm_features.Feature` init function:
55
- #
56
- # .. code-block:: python
57
- #
58
- # for feature in s["features"]:
59
- # if s["features"][feature] is False:
60
- # continue
61
- # match feature:
62
- # case "new_feature":
63
- # FeatureClass = nm_new_feature.NewFeature
64
- # ...
65
- #
66
- # The new feature class can then be used by setting the `settings["feature"]["new_feature"]` value in the
67
- # settings to true.
68
- #