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,68 +1,289 @@
1
- """Module for handling settings."""
2
- import pathlib
3
-
4
- import pandas as pd
5
-
6
- from py_neuromodulation import nm_IO
7
-
8
-
9
- def get_default_settings() -> dict:
10
- """Read default settings from nm_settings.json"""
11
- settings_path = str(
12
- pathlib.Path(__file__).parent.resolve() / "nm_settings.json"
13
- )
14
- return nm_IO.read_settings(settings_path)
15
-
16
-
17
- def reset_settings(
18
- settings: dict,
19
- ) -> dict:
20
- for f in settings["features"]:
21
- settings["features"][f] = False
22
- settings["preprocessing"] = []
23
- for f in settings["postprocessing"]:
24
- settings["postprocessing"][f] = False
25
- return settings
26
-
27
-
28
- def set_settings_fast_compute(
29
- settings: dict,
30
- ) -> dict:
31
- settings = reset_settings(settings)
32
- settings["features"]["fft"] = True
33
- settings["preprocessing"] = [
34
- "raw_resampling",
35
- "notch_filter",
36
- "re_referencing",
37
- ]
38
- settings["postprocessing"]["feature_normalization"] = True
39
- settings["postprocessing"]["project_cortex"] = False
40
- settings["postprocessing"]["project_subcortex"] = False
41
- return settings
42
-
43
-
44
- def test_settings(
45
- settings: dict,
46
- ) -> None:
47
- """Test if settings are specified correctly in nm_settings.json
48
- Parameters
49
- ----------
50
- settings: dict
51
- settings to tests
52
- verbose: boolean
53
- set to True if feedback is desired.
54
- Returns
55
- -------
56
- None
57
- """
58
- s = settings
59
-
60
- assert isinstance(s["sampling_rate_features_hz"], (float, int))
61
-
62
- assert (
63
- isinstance(value, bool) for value in s["features"].values()
64
- ), "features must be a boolean value."
65
-
66
- assert any(
67
- value is True for value in s["features"].values()
68
- ), "Set at least one feature to True."
1
+ """Module for handling settings."""
2
+
3
+ from pathlib import Path
4
+ from typing import ClassVar
5
+ from pydantic import Field, model_validator
6
+
7
+ from py_neuromodulation import PYNM_DIR, logger, user_features
8
+ from py_neuromodulation.nm_types import (
9
+ BoolSelector,
10
+ FrequencyRange,
11
+ PreprocessorName,
12
+ _PathLike,
13
+ )
14
+
15
+ from py_neuromodulation.nm_types import NMBaseModel
16
+ from py_neuromodulation.nm_filter_preprocessing import FilterSettings
17
+ from py_neuromodulation.nm_kalmanfilter import KalmanSettings
18
+ from py_neuromodulation.nm_projection import ProjectionSettings
19
+ from py_neuromodulation.nm_bispectra import BispectraSettings
20
+ from py_neuromodulation.nm_nolds import NoldsSettings
21
+ from py_neuromodulation.nm_mne_connectivity import MNEConnectivitySettings
22
+ from py_neuromodulation.nm_fooof import FooofSettings
23
+ from py_neuromodulation.nm_coherence import CoherenceSettings
24
+ from py_neuromodulation.nm_sharpwaves import SharpwaveSettings
25
+ from py_neuromodulation.nm_oscillatory import OscillatorySettings, BandpassSettings
26
+ from py_neuromodulation.nm_bursts import BurstSettings
27
+ from py_neuromodulation.nm_normalization import NormMethod, NormalizationSettings
28
+ from py_neuromodulation.nm_resample import ResamplerSettings
29
+
30
+
31
+ class FeatureSelection(BoolSelector):
32
+ raw_hjorth: bool = True
33
+ return_raw: bool = True
34
+ bandpass_filter: bool = False
35
+ stft: bool = False
36
+ fft: bool = True
37
+ welch: bool = True
38
+ sharpwave_analysis: bool = True
39
+ fooof: bool = False
40
+ nolds: bool = False
41
+ coherence: bool = False
42
+ bursts: bool = True
43
+ linelength: bool = True
44
+ mne_connectivity: bool = False
45
+ bispectrum: bool = False
46
+
47
+
48
+ class PostprocessingSettings(BoolSelector):
49
+ feature_normalization: bool = True
50
+ project_cortex: bool = False
51
+ project_subcortex: bool = False
52
+
53
+
54
+ class NMSettings(NMBaseModel):
55
+ # Class variable to store instances
56
+ _instances: ClassVar[list["NMSettings"]] = []
57
+
58
+ # General settings
59
+ sampling_rate_features_hz: float = Field(default=10, gt=0)
60
+ segment_length_features_ms: float = Field(default=1000, gt=0)
61
+ frequency_ranges_hz: dict[str, FrequencyRange] = {
62
+ "theta": FrequencyRange(4, 8),
63
+ "alpha": FrequencyRange(8, 12),
64
+ "low_beta": FrequencyRange(13, 20),
65
+ "high_beta": FrequencyRange(20, 35),
66
+ "low_gamma": FrequencyRange(60, 80),
67
+ "high_gamma": FrequencyRange(90, 200),
68
+ "HFA": FrequencyRange(200, 400),
69
+ }
70
+
71
+ # Preproceessing settings
72
+ preprocessing: list[PreprocessorName] = [
73
+ "raw_resampling",
74
+ "notch_filter",
75
+ "re_referencing",
76
+ ]
77
+ raw_resampling_settings: ResamplerSettings = ResamplerSettings()
78
+ preprocessing_filter: FilterSettings = FilterSettings()
79
+ raw_normalization_settings: NormalizationSettings = NormalizationSettings()
80
+
81
+ # Postprocessing settings
82
+ postprocessing: PostprocessingSettings = PostprocessingSettings()
83
+ feature_normalization_settings: NormalizationSettings = NormalizationSettings()
84
+ project_cortex_settings: ProjectionSettings = ProjectionSettings(max_dist_mm=20)
85
+ project_subcortex_settings: ProjectionSettings = ProjectionSettings(max_dist_mm=5)
86
+
87
+ # Feature settings
88
+ features: FeatureSelection = FeatureSelection()
89
+
90
+ fft_settings: OscillatorySettings = OscillatorySettings()
91
+ welch_settings: OscillatorySettings = OscillatorySettings()
92
+ stft_settings: OscillatorySettings = OscillatorySettings()
93
+ bandpass_filter_settings: BandpassSettings = BandpassSettings()
94
+ kalman_filter_settings: KalmanSettings = KalmanSettings()
95
+ burst_settings: BurstSettings = BurstSettings()
96
+ sharpwave_analysis_settings: SharpwaveSettings = SharpwaveSettings()
97
+ mne_connectivity: MNEConnectivitySettings = MNEConnectivitySettings()
98
+ coherence: CoherenceSettings = CoherenceSettings()
99
+ fooof: FooofSettings = FooofSettings()
100
+ nolds_features: NoldsSettings = NoldsSettings()
101
+ bispectrum: BispectraSettings = BispectraSettings()
102
+
103
+ def __init__(self, *args, **kwargs) -> None:
104
+ super().__init__(*args, **kwargs)
105
+
106
+ for feat_name in user_features.keys():
107
+ setattr(self.features, feat_name, True)
108
+
109
+ NMSettings._add_instance(self)
110
+
111
+ @classmethod
112
+ def _add_instance(cls, instance: "NMSettings") -> None:
113
+ """Keep track of all instances created in class variable"""
114
+ cls._instances.append(instance)
115
+
116
+ @classmethod
117
+ def _add_feature(cls, feature: str) -> None:
118
+ for instance in cls._instances:
119
+ setattr(instance.features, feature, True)
120
+
121
+ @classmethod
122
+ def _remove_feature(cls, feature: str) -> None:
123
+ for instance in cls._instances:
124
+ delattr(instance.features, feature)
125
+
126
+ @model_validator(mode="after")
127
+ def validate_settings(self):
128
+ if len(self.features.get_enabled()) == 0:
129
+ raise ValueError("At least one feature must be selected.")
130
+
131
+ # Replace spaces with underscores in frequency band names
132
+ self.frequency_ranges_hz = {
133
+ k.replace(" ", "_"): v for k, v in self.frequency_ranges_hz.items()
134
+ }
135
+
136
+ if self.features.bandpass_filter:
137
+ # Check BandPass settings frequency bands
138
+ self.bandpass_filter_settings.validate_fbands(self)
139
+
140
+ # Check Kalman filter frequency bands
141
+ if self.bandpass_filter_settings.kalman_filter:
142
+ self.kalman_filter_settings.validate_fbands(self)
143
+
144
+ for k, v in self.frequency_ranges_hz.items():
145
+ if not isinstance(v, FrequencyRange):
146
+ self.frequency_ranges_hz[k] = FrequencyRange.create_from(v)
147
+
148
+ return self
149
+
150
+ def reset(self) -> "NMSettings":
151
+ self.features.disable_all()
152
+ self.preprocessing = []
153
+ self.postprocessing.disable_all()
154
+ return self
155
+
156
+ def set_fast_compute(self) -> "NMSettings":
157
+ self.reset()
158
+ self.features.fft = True
159
+ self.preprocessing = [
160
+ "raw_resampling",
161
+ "notch_filter",
162
+ "re_referencing",
163
+ ]
164
+ self.postprocessing.feature_normalization = True
165
+ self.postprocessing.project_cortex = False
166
+ self.postprocessing.project_subcortex = False
167
+
168
+ return self
169
+
170
+ def enable_all_features(self):
171
+ self.features.enable_all()
172
+ return self
173
+
174
+ def disable_all_features(self):
175
+ self.features.disable_all()
176
+ return self
177
+
178
+ @staticmethod
179
+ def get_fast_compute() -> "NMSettings":
180
+ return NMSettings.get_default().set_fast_compute()
181
+
182
+ @classmethod
183
+ def load(cls, settings: "NMSettings | _PathLike | None") -> "NMSettings":
184
+ if isinstance(settings, cls):
185
+ return settings.validate()
186
+ if settings is None:
187
+ return cls.get_default()
188
+ return cls.from_file(str(settings))
189
+
190
+ @staticmethod
191
+ def from_file(PATH: _PathLike) -> "NMSettings":
192
+ """Load settings from file or a directory.
193
+
194
+ Args:
195
+ PATH (_PathLike): Path to settings file or to directory containing settings file,
196
+ or path to experiment including experiment prefix
197
+ (e.g. /path/to/exp/exp_prefix[_SETTINGS.json]).
198
+ Supported file types are .json and .yaml
199
+
200
+ Raises:
201
+ ValueError: when file format is not supported.
202
+
203
+ Returns:
204
+ NMSettings: PyNM settings object
205
+ """
206
+ path = Path(PATH)
207
+
208
+ # If directory is passed, look for settings file inside
209
+ if path.is_dir():
210
+ for child in path.iterdir():
211
+ if child.is_file() and child.suffix in [".json", ".yaml"]:
212
+ path = child
213
+ break
214
+
215
+ # If prefix is passed, look for settings file matching prefix
216
+ if not path.is_dir() and not path.is_file():
217
+ for child in path.parent.iterdir():
218
+ ext = child.suffix.lower()
219
+ if (
220
+ child.is_file()
221
+ and ext in [".json", ".yaml"]
222
+ and child.name == path.stem + "_SETTINGS" + ext
223
+ ):
224
+ path = child
225
+ break
226
+
227
+ match path.suffix:
228
+ case ".json":
229
+ import json
230
+
231
+ with open(path) as f:
232
+ model_dict = json.load(f)
233
+ case ".yaml":
234
+ import yaml
235
+
236
+ # with open(path) as f:
237
+ # model_dict = yaml.safe_load(f)
238
+
239
+ # Timon: this is potentially dangerous since python code is directly executed
240
+ with open(path) as f:
241
+ model_dict = yaml.load(f, Loader=yaml.Loader)
242
+
243
+ case _:
244
+ raise ValueError("File format not supported.")
245
+
246
+ return NMSettings(**model_dict)
247
+
248
+ @staticmethod
249
+ def get_default() -> "NMSettings":
250
+ return NMSettings.from_file(PYNM_DIR / "nm_settings.yaml")
251
+
252
+ @staticmethod
253
+ def list_normalization_methods() -> list[NormMethod]:
254
+ return NormalizationSettings.list_normalization_methods()
255
+
256
+ def save(
257
+ self, out_dir: _PathLike = ".", prefix: str = "", format: str = "yaml"
258
+ ) -> None:
259
+ filename = f"{prefix}_SETTINGS.{format}" if prefix else f"SETTINGS.{format}"
260
+
261
+ path_out = Path(out_dir) / filename
262
+
263
+ with open(path_out, "w") as f:
264
+ match format:
265
+ case "json":
266
+ f.write(self.model_dump_json(indent=4))
267
+ case "yaml":
268
+ import yaml
269
+
270
+ yaml.dump(self.model_dump(), f, default_flow_style=None)
271
+
272
+ logger.info(f"Settings saved to {path_out.resolve()}")
273
+
274
+
275
+ # For retrocompatibility with previous versions of PyNM
276
+ def get_default_settings() -> NMSettings:
277
+ return NMSettings.get_default()
278
+
279
+
280
+ def reset_settings(settings: NMSettings) -> NMSettings:
281
+ return settings.reset()
282
+
283
+
284
+ def set_settings_fast_compute() -> NMSettings:
285
+ return NMSettings.get_fast_compute()
286
+
287
+
288
+ def test_settings(settings: NMSettings) -> NMSettings:
289
+ return settings.validate()
@@ -0,0 +1,244 @@
1
+ ---
2
+
3
+ ########################
4
+ ### General settings ###
5
+ ########################
6
+ sampling_rate_features_hz: 10
7
+ segment_length_features_ms: 1000
8
+
9
+ frequency_ranges_hz: # frequency band ranges can be added, removed and altered
10
+ theta: [4, 8]
11
+ alpha: [8, 12]
12
+ low_beta: [13, 20]
13
+ high_beta: [20, 35]
14
+ low_gamma: [60, 80]
15
+ high_gamma: [90, 200]
16
+ HFA: [200, 400]
17
+
18
+
19
+ # Enabled features
20
+ features:
21
+ raw_hjorth: true
22
+ return_raw: true
23
+ bandpass_filter: false
24
+ stft: false
25
+ fft: true
26
+ welch: true
27
+ sharpwave_analysis: true
28
+ fooof: false
29
+ bursts: true
30
+ linelength: true
31
+ coherence: false
32
+ nolds: false
33
+ mne_connectivity: false
34
+ bispectrum: false
35
+
36
+ ##############################
37
+ ### Preprocessing settings ###
38
+ ##############################
39
+ # preprocessing options: raw_resampling, notch_filter, re_referencing, preprocessing_filter, raw_normalization
40
+ # note: the list order specifies also the order of execution
41
+ preprocessing: [raw_resampling, notch_filter, re_referencing]
42
+
43
+ raw_resampling_settings:
44
+ resample_freq_hz: 1000
45
+
46
+ raw_normalization_settings:
47
+ normalization_time_s: 30
48
+ normalization_method: zscore # supported methods: mean, median, zscore, zscore-median, quantile, power, robust, minmax
49
+ clip: 3
50
+
51
+ preprocessing_filter:
52
+ bandstop_filter: true
53
+ lowpass_filter: true
54
+ highpass_filter: true
55
+ bandpass_filter: true
56
+ bandstop_filter_settings:
57
+ frequency_low_hz: 100
58
+ frequency_high_hz: 160
59
+ bandpass_filter_settings:
60
+ frequency_low_hz: 3
61
+ frequency_high_hz: 200
62
+ lowpass_filter_cutoff_hz: 200
63
+ highpass_filter_cutoff_hz: 3
64
+
65
+
66
+ ################################
67
+ ### Postprocessing settings ####
68
+ ################################
69
+ postprocessing:
70
+ feature_normalization: true
71
+ project_cortex: false
72
+ project_subcortex: false
73
+
74
+ feature_normalization_settings:
75
+ normalization_time_s: 30
76
+ normalization_method: zscore # supported methods: mean, median, zscore, zscore-median, quantile, power, robust, minmax
77
+ clip: 3
78
+
79
+ project_cortex_settings:
80
+ max_dist_mm: 20
81
+
82
+ project_subcortex_settings:
83
+ max_dist_mm: 5
84
+
85
+
86
+ #################################
87
+ ### Feature specific settings ###
88
+ #################################
89
+
90
+ fft_settings:
91
+ windowlength_ms: 1000
92
+ log_transform: true
93
+ features:
94
+ mean: true
95
+ median: false
96
+ std: false
97
+ max: false
98
+ return_spectrum: false
99
+
100
+ welch_settings:
101
+ windowlength_ms: 1000
102
+ log_transform: true
103
+ features:
104
+ mean: true
105
+ median: false
106
+ std: false
107
+ max: false
108
+ return_spectrum: false
109
+
110
+ stft_settings:
111
+ windowlength_ms: 500
112
+ log_transform: true
113
+ features:
114
+ mean: true
115
+ median: false
116
+ std: false
117
+ max: false
118
+ return_spectrum: false
119
+
120
+ bandpass_filter_settings:
121
+ segment_lengths_ms:
122
+ theta: 1000
123
+ alpha: 500
124
+ low_beta: 333
125
+ high_beta: 333
126
+ low_gamma: 100
127
+ high_gamma: 100
128
+ HFA: 100
129
+ bandpower_features:
130
+ activity: true
131
+ mobility: false
132
+ complexity: false
133
+ log_transform: true
134
+ kalman_filter: false
135
+
136
+ kalman_filter_settings:
137
+ Tp: 0.1
138
+ sigma_w: 0.7
139
+ sigma_v: 1
140
+ frequency_bands:
141
+ [theta, alpha, low_beta, high_beta, low_gamma, high_gamma, HFA]
142
+
143
+ burst_settings:
144
+ threshold: 75
145
+ time_duration_s: 30
146
+ frequency_bands: [low_beta, high_beta, low_gamma]
147
+ burst_features:
148
+ duration: true
149
+ amplitude: true
150
+ burst_rate_per_s: true
151
+ in_burst: true
152
+
153
+ sharpwave_analysis_settings:
154
+ sharpwave_features:
155
+ peak_left: false
156
+ peak_right: false
157
+ trough: false
158
+ width: false
159
+ prominence: true
160
+ interval: true
161
+ decay_time: false
162
+ rise_time: false
163
+ sharpness: true
164
+ rise_steepness: false
165
+ decay_steepness: false
166
+ slope_ratio: false
167
+ filter_ranges_hz:
168
+ - frequency_low_hz: 5
169
+ frequency_high_hz: 80
170
+ - frequency_low_hz: 5
171
+ frequency_high_hz: 30
172
+ detect_troughs:
173
+ estimate: true
174
+ distance_troughs_ms: 10
175
+ distance_peaks_ms: 5
176
+ detect_peaks:
177
+ estimate: true
178
+ distance_troughs_ms: 5
179
+ distance_peaks_ms: 10
180
+ estimator:
181
+ mean: [interval]
182
+ median: []
183
+ max: [prominence, sharpness]
184
+ min: []
185
+ var: []
186
+ apply_estimator_between_peaks_and_troughs: true
187
+
188
+ coherence:
189
+ channels: [] # List of channel pairs, empty by default. Each pair is a list of two channels.
190
+ # Example channels: [[STN_RIGHT_0, ECOG_RIGHT_0], [STN_RIGHT_1, ECOG_RIGHT_1]]
191
+ frequency_bands: [high_beta]
192
+ features:
193
+ mean_fband: true
194
+ max_fband: true
195
+ max_allfbands: true
196
+ method:
197
+ coh: true
198
+ icoh: true
199
+
200
+ fooof:
201
+ aperiodic:
202
+ exponent: true
203
+ offset: true
204
+ knee: true
205
+ periodic:
206
+ center_frequency: false
207
+ band_width: false
208
+ height_over_ap: false
209
+ windowlength_ms: 800
210
+ peak_width_limits: [0.5, 12]
211
+ max_n_peaks: 3
212
+ min_peak_height: 0
213
+ peak_threshold: 2
214
+ freq_range_hz: [2, 40]
215
+ knee: true
216
+
217
+ nolds_features:
218
+ sample_entropy: false
219
+ correlation_dimension: false
220
+ lyapunov_exponent: true
221
+ hurst_exponent: false
222
+ detrended_fluctutaion_analysis: false
223
+ data:
224
+ raw: true
225
+ frequency_bands: [low_beta]
226
+
227
+ mne_connectiviy:
228
+ method: plv
229
+ mode: multitaper
230
+
231
+ bispectrum:
232
+ f1s: [5, 35]
233
+ f2s: [5, 35]
234
+ compute_features_for_whole_fband_range: true
235
+ frequency_bands: [theta, alpha, low_beta, high_beta]
236
+ components:
237
+ absolute: true
238
+ real: true
239
+ imag: true
240
+ phase: true
241
+ bispectrum_features:
242
+ mean: true
243
+ sum: true
244
+ var: true