py-neuromodulation 0.0.3__py3-none-any.whl → 0.0.4__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 (176) 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 +106 -0
  4. py_neuromodulation/ConnectivityDecoding/_helper_write_connectome.py +119 -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/data/README +6 -0
  10. py_neuromodulation/data/dataset_description.json +8 -0
  11. py_neuromodulation/data/participants.json +32 -0
  12. py_neuromodulation/data/participants.tsv +2 -0
  13. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +5 -0
  14. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +11 -0
  15. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +11 -0
  16. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
  17. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +18 -0
  18. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +35 -0
  19. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +13 -0
  20. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +2 -0
  21. py_neuromodulation/grid_cortex.tsv +40 -0
  22. py_neuromodulation/grid_subcortex.tsv +1429 -0
  23. py_neuromodulation/nm_settings.json +338 -0
  24. py_neuromodulation/nm_stream_offline.py +7 -6
  25. py_neuromodulation/plots/STN_surf.mat +0 -0
  26. py_neuromodulation/plots/Vertices.mat +0 -0
  27. py_neuromodulation/plots/faces.mat +0 -0
  28. py_neuromodulation/plots/grid.mat +0 -0
  29. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info}/METADATA +182 -182
  30. py_neuromodulation-0.0.4.dist-info/RECORD +72 -0
  31. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info}/WHEEL +1 -2
  32. docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
  33. docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -233
  34. docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  35. docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
  36. docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  37. docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
  38. docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  39. docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -68
  40. docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -239
  41. docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  42. docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -97
  43. docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  44. docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -192
  45. docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  46. docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +0 -76
  47. docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +0 -97
  48. docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +0 -240
  49. docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +0 -233
  50. docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +0 -63
  51. docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +0 -219
  52. docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +0 -210
  53. docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +0 -192
  54. docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +0 -219
  55. docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +0 -121
  56. docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +0 -68
  57. docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +0 -64
  58. docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +0 -189
  59. docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +0 -210
  60. docs/source/auto_examples/plot_0_first_demo.py +0 -189
  61. docs/source/auto_examples/plot_1_example_BIDS.py +0 -240
  62. docs/source/auto_examples/plot_2_example_add_feature.py +0 -76
  63. docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +0 -219
  64. docs/source/auto_examples/plot_4_example_gridPointProjection.py +0 -210
  65. docs/source/auto_examples/plot_5_example_rmap_computing.py +0 -64
  66. docs/source/auto_examples/plot_6_real_time_demo.py +0 -121
  67. docs/source/conf.py +0 -105
  68. examples/plot_0_first_demo.py +0 -189
  69. examples/plot_1_example_BIDS.py +0 -240
  70. examples/plot_2_example_add_feature.py +0 -76
  71. examples/plot_3_example_sharpwave_analysis.py +0 -219
  72. examples/plot_4_example_gridPointProjection.py +0 -210
  73. examples/plot_5_example_rmap_computing.py +0 -64
  74. examples/plot_6_real_time_demo.py +0 -121
  75. packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +0 -4
  76. packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +0 -104
  77. packages/realtime_decoding/build/lib/realtime_decoding/features.py +0 -163
  78. packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +0 -15
  79. packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +0 -345
  80. packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +0 -54
  81. packages/tmsi/build/lib/TMSiFileFormats/__init__.py +0 -37
  82. packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +0 -36
  83. packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +0 -200
  84. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +0 -496
  85. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +0 -236
  86. packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +0 -977
  87. packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +0 -35
  88. packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +0 -116
  89. packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +0 -294
  90. packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +0 -229
  91. packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +0 -102
  92. packages/tmsi/build/lib/TMSiPlotters/__init__.py +0 -2
  93. packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +0 -39
  94. packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +0 -234
  95. packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +0 -440
  96. packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +0 -44
  97. packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +0 -446
  98. packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +0 -589
  99. packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +0 -1326
  100. packages/tmsi/build/lib/TMSiSDK/__init__.py +0 -54
  101. packages/tmsi/build/lib/TMSiSDK/device.py +0 -588
  102. packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +0 -34
  103. packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +0 -1764
  104. packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +0 -34
  105. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +0 -1366
  106. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +0 -520
  107. packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +0 -165
  108. packages/tmsi/build/lib/TMSiSDK/error.py +0 -95
  109. packages/tmsi/build/lib/TMSiSDK/sample_data.py +0 -63
  110. packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +0 -99
  111. packages/tmsi/build/lib/TMSiSDK/settings.py +0 -45
  112. packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +0 -111
  113. packages/tmsi/build/lib/__init__.py +0 -4
  114. packages/tmsi/build/lib/apex_sdk/__init__.py +0 -34
  115. packages/tmsi/build/lib/apex_sdk/device/__init__.py +0 -41
  116. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +0 -1009
  117. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +0 -239
  118. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +0 -668
  119. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +0 -1611
  120. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +0 -38
  121. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +0 -57
  122. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +0 -44
  123. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +0 -150
  124. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +0 -36
  125. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +0 -48
  126. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +0 -108
  127. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +0 -39
  128. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +0 -77
  129. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +0 -150
  130. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +0 -129
  131. packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +0 -59
  132. packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +0 -57
  133. packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +0 -83
  134. packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +0 -201
  135. packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +0 -103
  136. packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +0 -43
  137. packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +0 -50
  138. packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +0 -118
  139. packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +0 -33
  140. packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +0 -44
  141. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +0 -50
  142. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +0 -136
  143. packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +0 -126
  144. packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +0 -113
  145. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +0 -134
  146. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +0 -60
  147. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +0 -42
  148. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +0 -42
  149. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +0 -72
  150. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +0 -98
  151. py_neuromodulation-0.0.3.dist-info/RECORD +0 -188
  152. py_neuromodulation-0.0.3.dist-info/top_level.txt +0 -5
  153. tests/__init__.py +0 -0
  154. tests/conftest.py +0 -117
  155. tests/test_all_examples.py +0 -10
  156. tests/test_all_features.py +0 -63
  157. tests/test_bispectra.py +0 -70
  158. tests/test_bursts.py +0 -105
  159. tests/test_feature_sampling_rates.py +0 -143
  160. tests/test_fooof.py +0 -16
  161. tests/test_initalization_offline_stream.py +0 -41
  162. tests/test_multiprocessing.py +0 -58
  163. tests/test_nan_values.py +0 -29
  164. tests/test_nm_filter.py +0 -95
  165. tests/test_nm_resample.py +0 -63
  166. tests/test_normalization_settings.py +0 -146
  167. tests/test_notch_filter.py +0 -31
  168. tests/test_osc_features.py +0 -424
  169. tests/test_preprocessing_filter.py +0 -151
  170. tests/test_rereference.py +0 -171
  171. tests/test_sampling.py +0 -57
  172. tests/test_settings_change_after_init.py +0 -76
  173. tests/test_sharpwave.py +0 -165
  174. tests/test_target_channel_add.py +0 -100
  175. tests/test_timing.py +0 -80
  176. {py_neuromodulation-0.0.3.dist-info → py_neuromodulation-0.0.4.dist-info/licenses}/LICENSE +0 -0
@@ -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