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,520 +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 ${saga_types.py}
26
- * @brief SAGA Device Types.
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- from ...device import (
34
- DeviceInterfaceType,
35
- DeviceState,
36
- DeviceConfig,
37
- ChannelType,
38
- DeviceChannel,
39
- DeviceSensor,
40
- ReferenceMethod,
41
- ReferenceSwitch,
42
- )
43
-
44
- _TMSI_DEVICE_ID_NONE = 0xFFFF
45
-
46
-
47
- class SagaConst:
48
- TMSI_DEVICE_ID_NONE = 0xFFFF
49
-
50
-
51
- class SagaInfo:
52
- """'DeviceInfo' holds the static device information. It has the next properties:
53
-
54
- ds_interface : 'DeviceInterfaceType' Indicates interface-type between the PC
55
- and the docking station.
56
-
57
- dr_interface : 'DeviceInterfaceType' Indicates interface-type between the
58
- PC / docking station and the data recorder.
59
-
60
- ds_serial_number : 'int' The serial number of the docking station.
61
-
62
- dr_serial_number : 'int' The serial number of the data recorder.
63
-
64
- """
65
-
66
- def __init__(
67
- self,
68
- ds_interface=DeviceInterfaceType.none,
69
- dr_interface=DeviceInterfaceType.none,
70
- ):
71
- self.ds_interface = ds_interface
72
- self.dr_interface = dr_interface
73
- self.id = _TMSI_DEVICE_ID_NONE
74
- self.state = DeviceState.disconnected
75
-
76
-
77
- class SagaConfig(DeviceConfig):
78
- """'DeviceConfig' holds the actual device configuration"""
79
-
80
- def __init__(self):
81
- self._parent = None
82
- self._base_sample_rate = 0 # base sample reate in Hz
83
- self._configured_interface = DeviceInterfaceType.none
84
- self._triggers = 0 # 0= Disabled, 1= external triggers enabled
85
- self._reference_method = 0 # 0= Common reference, 1=average reference
86
- self._auto_reference_method = 0 # 0= fixed method, 1= autoswitch to average reference when CREF is out of range
87
- self._dr_sync_out_divider = (
88
- -1
89
- ) # SetBaseSampleRateHz/SyncOutDiv, -1 = marker button
90
- self._dr_sync_out_duty_cycle = 0 # DR Sync dutycycle
91
- self._repair_logging = 0 # 0 = Disabled, 1 = BackupLogging enabled,
92
- self._num_channels = 0
93
- # Total number of channels : active and inactive
94
- self._channels = [] # Total channel list : active and inactive
95
- self._sample_rates = [] # List with sample_rate per channel-type
96
- self._num_sensors = 0 # Number of sensors
97
- self._interface_bandwidth = 0
98
- # Data bandwidth in Mbits/s for current interface.
99
- for chan_type in ChannelType:
100
- self._sample_rates.append(SagaSampleRate(chan_type))
101
-
102
- def get_sample_rate(self, chan_type):
103
- """'int' the sample-rate of the specified channel-type-group.
104
-
105
- Args:
106
- channel_type : 'ChannelType' The channel-type-group.
107
- """
108
- return self._sample_rates[chan_type.value].sample_rate
109
-
110
- def set_sample_rate(self, chan_type, bsr_div):
111
- """Sets the sample-rate of the specified channel-type-group.
112
-
113
- Args:
114
- channel_type : 'ChannelType' The channel-type-group of which the
115
- sample-rate must be updated.
116
- It is possible to set all channels to the same sample-rate within one
117
- call. Then 'ChannelType.all_types' must be used.
118
-
119
- base_sample_rate_divider: 'int' The divider to indicate to what fraction
120
- of the active base-sample-rate the sample-rate of the channel-type-group
121
- must be set. Only the values 1, 2, 4 and 8 are possible.
122
- For example if the base-sample-rate=4000 and base_sample_rate_divider=8,
123
- the sample-rate will become 4000/8 = 500 Hz
124
-
125
- Note:
126
- Upon a change of the sample-rate of a channel-type-group, automatically
127
- the sample-rate of the channels of that channel-type are updated.
128
-
129
- It is advised to "refresh" the applications' local "variables"
130
- after the sample-rate of a channel-type-group has been updated.
131
- """
132
- if (bsr_div == 1) or (bsr_div == 2) or (bsr_div == 4) or (bsr_div == 8):
133
- bsr_shift = 0
134
- while bsr_div > 1:
135
- bsr_shift += 1
136
- bsr_div /= 2
137
- for ch in self._channels:
138
- if (
139
- (ch.type == chan_type)
140
- or (chan_type == ChannelType.all_types)
141
- and (ch.chan_divider != -1)
142
- ):
143
- # Only update the chan_divider of active channels
144
- if ch.chan_divider != -1:
145
- ch.chan_divider = bsr_shift
146
- if self._parent != None:
147
- self._parent._update_config()
148
- else:
149
- print(
150
- "\nProvided base_sample_rate_divider is invalid. Sample rate can not be updated.\n"
151
- )
152
-
153
- @property
154
- def base_sample_rate(self):
155
- """'int' The active base-sample-rate of the device"""
156
- return self._base_sample_rate
157
-
158
- @base_sample_rate.setter
159
- def base_sample_rate(self, var):
160
- """Sets the base-sample-rate of the device.
161
-
162
- Args:
163
- sample_rate : 'int' new base sample rate
164
-
165
- Note:
166
- Upon a change of the base-sample-rate, automatically the sample-rate
167
- of the channel-type-groups (and thus also the sample-rate of every channel)
168
- changes.
169
-
170
- It is advised to "refresh" the applications' local "variables"
171
- after the base-sample-rate has been updated.
172
-
173
- """
174
- if (var == 4000) or (var == 4096):
175
- if self._base_sample_rate != var:
176
- # The device does not support a configuration with different base
177
- # sample rates for sample rate and sync out. Hence sync out config
178
- # has to be update as well
179
- sync_out_freq = (
180
- self._base_sample_rate / self._dr_sync_out_divider
181
- )
182
- self._base_sample_rate = var
183
- self.set_sync_out_config(freq=sync_out_freq)
184
- else:
185
- print(
186
- "\nProvided base_sample_rate is invalid. Sample rate can not be updated.\n"
187
- )
188
-
189
- @property
190
- def sample_rate(self):
191
- """<int> The rate of the current configuration, with which
192
- sample-sets are sent during a measurement. This always
193
- equals the sample-rate of the COUNTER-channel.
194
- """
195
- return self._sample_rates[ChannelType.counter.value].sample_rate
196
-
197
- @property
198
- def configured_interface(self):
199
- return self._configured_interface
200
-
201
- def set_interface_type(self, dr_interface_type):
202
- """Changes the configured interface type of the device.
203
-
204
- Args:
205
- dr_interface_type: 'DeviceInterfaceType' The interface type that needs
206
- to be updated.
207
-
208
- Note:
209
- The interface type switch applies to the DR-DS interface type.
210
- Interface types that can be configured on SAGA are docked,
211
- optical and wifi.
212
- """
213
-
214
- if dr_interface_type.value != self._configured_interface:
215
- print("DR-DS interface is changed to: ")
216
- print(dr_interface_type)
217
- self._configured_interface = dr_interface_type.value
218
-
219
- if self._parent != None:
220
- self._parent._update_config()
221
-
222
- @property
223
- def num_channels(self):
224
- """'int' The total number of channels (enabled and disabled)"""
225
- return self._num_channels
226
-
227
- @property
228
- def channels(self):
229
- """'list DeviceChannel' The total list of channels (enabled and disabled)"""
230
- chan_list = []
231
- for ch in self._channels:
232
- sensor = ch.sensor
233
- if ch.sensor != None:
234
- sensor = DeviceSensor(
235
- ch.sensor.idx_total_channel_list,
236
- ch.sensor.id,
237
- ch.sensor.serial_nr,
238
- ch.sensor.product_id,
239
- ch.sensor.name,
240
- ch.sensor.unit_name,
241
- ch.sensor.exp,
242
- )
243
-
244
- dev_ch = DeviceChannel(
245
- ch.type,
246
- ch.sample_rate,
247
- ch.alt_name,
248
- ch.unit_name,
249
- (ch.chan_divider != -1),
250
- sensor,
251
- )
252
- chan_list.append(dev_ch)
253
- return chan_list
254
-
255
- @channels.setter
256
- def channels(self, var):
257
- """Updates the channel lists in the device.
258
-
259
- Args:
260
- ch_list : 'list DeviceChannel'
261
-
262
- The channel-properties 'enabled' and 'name' can be modified. The other
263
- channel-properties are read-only.
264
-
265
- Note:
266
- 'ch_list' must contain all channels (enabled and disabled), in the
267
- same sequence as retrieved with 'Device.config.channels'
268
-
269
- It is advised to "refresh" the applications' local "variables"
270
- after the channel list has been updated.
271
- """
272
- for idx, channel in enumerate(var):
273
- if self._channels[idx].type.value < ChannelType.status.value:
274
- self._channels[idx].alt_name = channel.name
275
- if channel.enabled == True:
276
- if (
277
- self._sample_rates[
278
- self._channels[idx].type.value
279
- ].sample_rate
280
- != 0
281
- ):
282
- self._channels[idx].sample_rate = self._sample_rates[
283
- self._channels[idx].type.value
284
- ].sample_rate
285
- self._channels[idx].chan_divider = self._sample_rates[
286
- self._channels[idx].type.value
287
- ].chan_divider
288
- else:
289
- self._sample_rates[
290
- self._channels[idx].type.value
291
- ].sample_rate = self._sample_rates[
292
- ChannelType.counter.value
293
- ].sample_rate
294
- self._sample_rates[
295
- self._channels[idx].type.value
296
- ].chan_divider = self._sample_rates[
297
- ChannelType.counter.value
298
- ].chan_divider
299
- self._channels[idx].sample_rate = self._sample_rates[
300
- self._channels[idx].type.value
301
- ].sample_rate
302
- self._channels[idx].chan_divider = self._sample_rates[
303
- self._channels[idx].type.value
304
- ].chan_divider
305
- else:
306
- self._channels[idx].chan_divider = -1
307
- if self._parent != None:
308
- self._parent._update_config()
309
-
310
- @property
311
- def reference_method(self):
312
- """'ReferenceMethod' the reference method applied to the UNI channels,
313
- 'ReferenceSwitch' the switching of reference mode when common reference is disconnected"""
314
- return (
315
- ReferenceMethod(self._reference_method).name,
316
- ReferenceSwitch(self._auto_reference_method).name,
317
- )
318
-
319
- @reference_method.setter
320
- def reference_method(self, reference_type):
321
- """Sets the reference method for the UNI channels
322
-
323
- Args:
324
- reference_type: 'ReferenceMethod' the type of reference method that
325
- should be used for measuring the UNI channels
326
- 'ReferenceSwitch' the switching of reference mode when common reference is disconnected
327
-
328
- """
329
- if not type(reference_type) is tuple:
330
- if isinstance(reference_type, ReferenceMethod):
331
- self._reference_method = reference_type.value
332
- elif isinstance(reference_type, ReferenceSwitch):
333
- self._auto_reference_method = reference_type.value
334
-
335
- else:
336
- for ind in range(len(reference_type)):
337
- if isinstance(reference_type[ind], ReferenceMethod):
338
- self._reference_method = reference_type[ind].value
339
- elif isinstance(reference_type[ind], ReferenceSwitch):
340
- self._auto_reference_method = reference_type[ind].value
341
-
342
- if self._parent != None:
343
- self._parent._update_config()
344
-
345
- @property
346
- def triggers(self):
347
- """'Boolean', true when triggers are enabled or false when disabled"""
348
- return bool(self._triggers)
349
-
350
- @triggers.setter
351
- def triggers(self, enable_triggers):
352
- """Sets the triggers to enabled or disabled"""
353
- self._triggers = enable_triggers
354
- if self._parent != None:
355
- self._parent._update_config()
356
-
357
- @property
358
- def repair_logging(self):
359
- """Boolean, true in case samples are logged on Recorder for repair in case of data loss"""
360
- return self._repair_logging
361
-
362
- @repair_logging.setter
363
- def repair_logging(self, enable_logging):
364
- """Sets repair logging to enabled or disabled"""
365
- self._repair_logging = enable_logging
366
- if self._parent != None:
367
- self._parent._update_config()
368
-
369
- def get_sync_out_config(self):
370
- """Sync out configuration, shows whether sync out is in marker mode or square wave mode with corresponding frequency and duty cycle"""
371
- if self._dr_sync_out_divider == -1:
372
- freq = -1
373
- else:
374
- freq = self._base_sample_rate / self._dr_sync_out_divider
375
- return (
376
- self._dr_sync_out_divider == -1,
377
- freq,
378
- self._dr_sync_out_duty_cycle / 10,
379
- )
380
-
381
- def set_sync_out_config(self, marker=False, freq=None, duty_cycle=None):
382
- """Set sync out to marker mode or square wave mode with corresponding frequency and duty cycle"""
383
- if marker:
384
- self._dr_sync_out_divider = -1
385
- else:
386
- if freq:
387
- self._dr_sync_out_divider = round(self._base_sample_rate / freq)
388
- if duty_cycle:
389
- self._dr_sync_out_duty_cycle = duty_cycle * 10
390
-
391
- if self._parent != None:
392
- self._parent._update_config()
393
-
394
- @property
395
- def interface_bandwidth(self):
396
- return self._interface_bandwidth
397
-
398
- @interface_bandwidth.setter
399
- def interface_bandwidth(self, bandwidth):
400
- """Sets the data bandwidth in Mbits/s for current interface."""
401
- self._interface_bandwidth = bandwidth
402
-
403
-
404
- class SagaSensor:
405
- """<SagaSensor> represents the sensor-data of a channel. It has the next properties:
406
-
407
- offset : <float> Offset for the seonsor-channel.
408
-
409
- gain : <float> Value to convert the sensor value to the correct unit value
410
-
411
- exp : <int> Exponent for the unit, e.g. milli = -3 this gives for a
412
- unit_name V a result mV.
413
-
414
- name : <string> The name of the seonsor-channel.
415
-
416
- unit_name : <string> The name of the unit (e.g. 'μVolt) of the sensor-data.
417
-
418
- """
419
-
420
- def __init__(self):
421
- self.idx_total_channel_list = -1
422
- self.id = -1
423
- self.manufacturer_id = 0
424
- self.serial_nr = 0
425
- self.product_id = 0
426
- self.offset = 0
427
- self.gain = 1
428
- self.exp = 0
429
- self.__name = ""
430
- self.__unit_name = ""
431
-
432
- @property
433
- def name(self):
434
- """'string' The name of the unit (e.g. 'μVolt) of the sample-data of the channel."""
435
- return self.__name
436
-
437
- @name.setter
438
- def name(self, bname):
439
- self.__name = ""
440
- new_name = bytearray()
441
- for i in range(len(bname)):
442
- if bname[i] > 127:
443
- new_name.append(194) # 0xC2
444
- new_name.append(bname[i])
445
- if len(new_name) > 0:
446
- self.__name = new_name.decode("utf8").rstrip("\x00")
447
-
448
- @property
449
- def unit_name(self):
450
- """'string' The name of the unit (e.g. 'μVolt) of the sample-data of the channel."""
451
- return self.__unit_name
452
-
453
- @unit_name.setter
454
- def unit_name(self, bname):
455
- # A unit-name can start with the micro-character (0xB5). In that case must
456
- # the micro-character be converted to it;s utf8-representation : 0xC2B5
457
- self.__unit_name = ""
458
- new_name = bytearray()
459
- for i in range(len(bname)):
460
- if bname[i] > 127:
461
- new_name.append(194) # 0xC2
462
- new_name.append(bname[i])
463
- if len(new_name) > 0:
464
- self.__unit_name = new_name.decode("utf8").rstrip("\x00")
465
-
466
-
467
- class SagaChannel:
468
- """<DeviceChannel> represents a device channel. It has the next properties:
469
-
470
- type : <ChannelType> Indicates the group-type of a channel.
471
-
472
- sample_rate : <int> The curring sampling rate of the channel during a 'normal' measurement.
473
-
474
- name : <string> The name of the channel.
475
-
476
- unit_name : <string> The name of the unit (e.g. 'μVolt) of the sample-data of the channel.
477
-
478
- enabled : <bool> Indicates if a channel is enavled for measuring
479
-
480
- Note: The properties <name> and <anabled> can be modified. The other properties
481
- are read-only.
482
- """
483
-
484
- def __init__(self):
485
- self.type = 0
486
- self.format = 0
487
- self.sample_rate = 0
488
- self.chan_divider = -1
489
- self.imp_divider = -1
490
- self.exp = 1
491
- self.__unit_name = "-"
492
- self.def_name = "-"
493
- self.alt_name = "-"
494
- self.sensor = None
495
-
496
- @property
497
- def unit_name(self):
498
- """'string' The name of the unit (e.g. 'μVolt) of the sample-data of the channel."""
499
- return self.__unit_name
500
-
501
- @unit_name.setter
502
- def unit_name(self, name):
503
- # A unit-name can start with the micro-character (0xB5). In that case must
504
- # the micro-character be converted to it;s utf8-representation : 0xC2B5
505
- self.__unit_name = ""
506
- bname = name.encode("windows-1252")
507
- new_name = bytearray()
508
- for i in range(len(bname)):
509
- if bname[i] > 127:
510
- new_name.append(194) # 0xC2
511
- new_name.append(bname[i])
512
- if len(new_name) > 0:
513
- self.__unit_name = new_name.decode("utf8")
514
-
515
-
516
- class SagaSampleRate:
517
- def __init__(self, type):
518
- self.type = type
519
- self.sample_rate = 0
520
- self.chan_divider = -1
@@ -1,165 +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 ${xml_saga_config.py}
26
- * @brief Reading/Writing SAGA configuration via XML
27
- *
28
- */
29
-
30
-
31
- """
32
-
33
- from xml.dom import minidom
34
- import xml.etree.ElementTree as ET
35
-
36
- from .saga_types import SagaConfig, SagaChannel
37
-
38
-
39
- def __prettify(elem):
40
- """Return a pretty-printed XML string for the Element."""
41
- rough_string = ET.tostring(elem, "utf-8")
42
- reparsed = minidom.parseString(rough_string)
43
- return reparsed.toprettyxml(indent=" ")
44
-
45
-
46
- def xml_write_config(filename, saga_config):
47
- """Writes a device configuration to the specified file.
48
-
49
- Args:
50
- 'filename' Location of the xml-file to write
51
-
52
- 'saga_config' device configuration to write
53
-
54
- Returns:
55
- True if successfull, False otherwise.
56
- """
57
- try:
58
- root = ET.Element("DeviceConfig")
59
-
60
- # 1. Write the device configuration properties
61
- xml_device = ET.SubElement(root, "Device")
62
-
63
- ET.SubElement(xml_device, "BaseSampleRateHz").text = str(
64
- saga_config._base_sample_rate
65
- )
66
- ET.SubElement(xml_device, "ConfiguredInterface").text = str(
67
- saga_config._configured_interface
68
- )
69
- ET.SubElement(xml_device, "Triggers").text = str(saga_config._triggers)
70
- ET.SubElement(xml_device, "ReferenceMethod").text = str(
71
- saga_config._reference_method
72
- )
73
- ET.SubElement(xml_device, "AutoReferenceMethod").text = str(
74
- saga_config._auto_reference_method
75
- )
76
- ET.SubElement(xml_device, "DRSyncOutDiv").text = str(
77
- saga_config._dr_sync_out_divider
78
- )
79
- ET.SubElement(xml_device, "DRSyncOutDutyCycl").text = str(
80
- saga_config._dr_sync_out_duty_cycle
81
- )
82
- ET.SubElement(xml_device, "RepairLogging").text = str(
83
- saga_config._repair_logging
84
- )
85
-
86
- # 2. Write the channel list
87
- xml_channels = ET.SubElement(root, "Channels")
88
- for idx, saga_channel in enumerate(saga_config._channels):
89
-
90
- xml_channel = ET.SubElement(xml_channels, "Channel")
91
-
92
- ET.SubElement(xml_channel, "ChanNr").text = str(idx)
93
- ET.SubElement(xml_channel, "ChanDivider").text = str(
94
- saga_channel.chan_divider
95
- )
96
- ET.SubElement(
97
- xml_channel, "AltChanName"
98
- ).text = saga_channel.alt_name
99
-
100
- xml_data = __prettify(root)
101
-
102
- xml_file = open(filename, "w")
103
- xml_file.write(xml_data)
104
-
105
- return True
106
-
107
- except:
108
- return False
109
-
110
-
111
- def xml_read_config(filename):
112
- """Read a device configuration from the specified file.
113
-
114
- Args:
115
- 'filename' Location of the xml-file to read
116
-
117
- Returns:
118
- if successfull :
119
- True and a 'SagaConfig'-object with the read configuration.
120
- otherwise :
121
- False and a default 'SagaConfig'-object
122
- """
123
- result = True
124
- saga_config = SagaConfig()
125
-
126
- try:
127
- tree = ET.parse(filename)
128
- root = tree.getroot()
129
-
130
- for elem in root:
131
- # print(len(elem))
132
- for subelem in elem:
133
- if elem.tag == "Device":
134
- if subelem.tag == "BaseSampleRateHz":
135
- saga_config._base_sample_rate = int(subelem.text)
136
- if subelem.tag == "ConfiguredInterface":
137
- saga_config._configured_interface = int(subelem.text)
138
- if subelem.tag == "Triggers":
139
- saga_config._triggers = int(subelem.text)
140
- if subelem.tag == "ReferenceMethod":
141
- saga_config._reference_method = int(subelem.text)
142
- if subelem.tag == "AutoReferenceMethod":
143
- saga_config._auto_reference_method = int(subelem.text)
144
- if subelem.tag == "DRSyncOutDiv":
145
- saga_config._dr_sync_out_divider = int(subelem.text)
146
- if subelem.tag == "DRSyncOutDutyCycl":
147
- saga_config._dr_sync_out_duty_cycle = int(subelem.text)
148
- if subelem.tag == "RepairLogging":
149
- saga_config._repair_logging = int(subelem.text)
150
- if elem.tag == "Channels":
151
- if subelem.tag == "Channel":
152
- saga_config._num_channels += 1
153
- channel = SagaChannel()
154
- for subsubelem in subelem:
155
- if subsubelem.tag == "ChanDivider":
156
- channel.chan_divider = int(subsubelem.text)
157
- if subsubelem.tag == "AltChanName":
158
- channel.alt_name = subsubelem.text
159
-
160
- saga_config._channels.append(channel)
161
- except:
162
- result = False
163
- saga_config = None
164
-
165
- return result, saga_config