py-neuromodulation 0.0.2__py3-none-any.whl → 0.0.3__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 (204) hide show
  1. docs/build/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
  2. docs/build/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +233 -0
  3. docs/build/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  4. docs/build/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
  5. docs/build/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  6. docs/build/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
  7. docs/build/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  8. docs/build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +68 -0
  9. docs/build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +239 -0
  10. docs/build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  11. docs/build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +97 -0
  12. docs/build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  13. docs/build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +192 -0
  14. docs/build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  15. docs/source/_build/html/_downloads/09df217f95985497f45d69e2d4bdc5b1/plot_2_example_add_feature.py +76 -0
  16. docs/source/_build/html/_downloads/0d0d0a76e8f648d5d3cbc47da6351932/plot_real_time_demo.py +97 -0
  17. docs/source/_build/html/_downloads/3b4900a2b2818ff30362215b76f7d5eb/plot_1_example_BIDS.py +240 -0
  18. docs/source/_build/html/_downloads/5d73cadc59a8805c47e3b84063afc157/plot_example_BIDS.py +233 -0
  19. docs/source/_build/html/_downloads/7660317fa5a6bfbd12fcca9961457fc4/plot_example_rmap_computing.py +63 -0
  20. docs/source/_build/html/_downloads/7e92dd2e6cc86b239d14cafad972ae4f/plot_3_example_sharpwave_analysis.py +219 -0
  21. docs/source/_build/html/_downloads/839e5b319379f7fd9e867deb00fd797f/plot_example_gridPointProjection.py +210 -0
  22. docs/source/_build/html/_downloads/ae8be19afe5e559f011fc9b138968ba0/plot_first_demo.py +192 -0
  23. docs/source/_build/html/_downloads/b8b06cacc17969d3725a0b6f1d7741c5/plot_example_sharpwave_analysis.py +219 -0
  24. docs/source/_build/html/_downloads/c2db0bf2b334d541b00662b991682256/plot_6_real_time_demo.py +121 -0
  25. docs/source/_build/html/_downloads/c31a86c0b68cb4167d968091ace8080d/plot_example_add_feature.py +68 -0
  26. docs/source/_build/html/_downloads/ce3914826f782cbd1ea8fd024eaf0ac3/plot_5_example_rmap_computing.py +64 -0
  27. docs/source/_build/html/_downloads/da36848a41e6a3235d91fb7cfb6d59b4/plot_0_first_demo.py +189 -0
  28. docs/source/_build/html/_downloads/eaa4305c75b19a1e2eea941f742a6331/plot_4_example_gridPointProjection.py +210 -0
  29. docs/source/auto_examples/plot_0_first_demo.py +189 -0
  30. docs/source/auto_examples/plot_1_example_BIDS.py +240 -0
  31. docs/source/auto_examples/plot_2_example_add_feature.py +76 -0
  32. docs/source/auto_examples/plot_3_example_sharpwave_analysis.py +219 -0
  33. docs/source/auto_examples/plot_4_example_gridPointProjection.py +210 -0
  34. docs/source/auto_examples/plot_5_example_rmap_computing.py +64 -0
  35. docs/source/auto_examples/plot_6_real_time_demo.py +121 -0
  36. docs/source/conf.py +105 -0
  37. examples/plot_0_first_demo.py +189 -0
  38. examples/plot_1_example_BIDS.py +240 -0
  39. examples/plot_2_example_add_feature.py +76 -0
  40. examples/plot_3_example_sharpwave_analysis.py +219 -0
  41. examples/plot_4_example_gridPointProjection.py +210 -0
  42. examples/plot_5_example_rmap_computing.py +64 -0
  43. examples/plot_6_real_time_demo.py +121 -0
  44. packages/realtime_decoding/build/lib/realtime_decoding/__init__.py +4 -0
  45. packages/realtime_decoding/build/lib/realtime_decoding/decoder.py +104 -0
  46. packages/realtime_decoding/build/lib/realtime_decoding/features.py +163 -0
  47. packages/realtime_decoding/build/lib/realtime_decoding/helpers.py +15 -0
  48. packages/realtime_decoding/build/lib/realtime_decoding/run_decoding.py +345 -0
  49. packages/realtime_decoding/build/lib/realtime_decoding/trainer.py +54 -0
  50. packages/tmsi/build/lib/TMSiFileFormats/__init__.py +37 -0
  51. packages/tmsi/build/lib/TMSiFileFormats/file_formats/__init__.py +36 -0
  52. packages/tmsi/build/lib/TMSiFileFormats/file_formats/lsl_stream_writer.py +200 -0
  53. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_file_writer.py +496 -0
  54. packages/tmsi/build/lib/TMSiFileFormats/file_formats/poly5_to_edf_converter.py +236 -0
  55. packages/tmsi/build/lib/TMSiFileFormats/file_formats/xdf_file_writer.py +977 -0
  56. packages/tmsi/build/lib/TMSiFileFormats/file_readers/__init__.py +35 -0
  57. packages/tmsi/build/lib/TMSiFileFormats/file_readers/edf_reader.py +116 -0
  58. packages/tmsi/build/lib/TMSiFileFormats/file_readers/poly5reader.py +294 -0
  59. packages/tmsi/build/lib/TMSiFileFormats/file_readers/xdf_reader.py +229 -0
  60. packages/tmsi/build/lib/TMSiFileFormats/file_writer.py +102 -0
  61. packages/tmsi/build/lib/TMSiPlotters/__init__.py +2 -0
  62. packages/tmsi/build/lib/TMSiPlotters/gui/__init__.py +39 -0
  63. packages/tmsi/build/lib/TMSiPlotters/gui/_plotter_gui.py +234 -0
  64. packages/tmsi/build/lib/TMSiPlotters/gui/plotting_gui.py +440 -0
  65. packages/tmsi/build/lib/TMSiPlotters/plotters/__init__.py +44 -0
  66. packages/tmsi/build/lib/TMSiPlotters/plotters/hd_emg_plotter.py +446 -0
  67. packages/tmsi/build/lib/TMSiPlotters/plotters/impedance_plotter.py +589 -0
  68. packages/tmsi/build/lib/TMSiPlotters/plotters/signal_plotter.py +1326 -0
  69. packages/tmsi/build/lib/TMSiSDK/__init__.py +54 -0
  70. packages/tmsi/build/lib/TMSiSDK/device.py +588 -0
  71. packages/tmsi/build/lib/TMSiSDK/devices/__init__.py +34 -0
  72. packages/tmsi/build/lib/TMSiSDK/devices/saga/TMSi_Device_API.py +1764 -0
  73. packages/tmsi/build/lib/TMSiSDK/devices/saga/__init__.py +34 -0
  74. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_device.py +1366 -0
  75. packages/tmsi/build/lib/TMSiSDK/devices/saga/saga_types.py +520 -0
  76. packages/tmsi/build/lib/TMSiSDK/devices/saga/xml_saga_config.py +165 -0
  77. packages/tmsi/build/lib/TMSiSDK/error.py +95 -0
  78. packages/tmsi/build/lib/TMSiSDK/sample_data.py +63 -0
  79. packages/tmsi/build/lib/TMSiSDK/sample_data_server.py +99 -0
  80. packages/tmsi/build/lib/TMSiSDK/settings.py +45 -0
  81. packages/tmsi/build/lib/TMSiSDK/tmsi_device.py +111 -0
  82. packages/tmsi/build/lib/__init__.py +4 -0
  83. packages/tmsi/build/lib/apex_sdk/__init__.py +34 -0
  84. packages/tmsi/build/lib/apex_sdk/device/__init__.py +41 -0
  85. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API.py +1009 -0
  86. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_enums.py +239 -0
  87. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_API_structures.py +668 -0
  88. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_device.py +1611 -0
  89. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_dongle.py +38 -0
  90. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_event_reader.py +57 -0
  91. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_channel.py +44 -0
  92. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_config.py +150 -0
  93. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_const.py +36 -0
  94. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_impedance_channel.py +48 -0
  95. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/apex_info.py +108 -0
  96. packages/tmsi/build/lib/apex_sdk/device/devices/apex/apex_structures/dongle_info.py +39 -0
  97. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/download_measurement.py +77 -0
  98. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/eeg_measurement.py +150 -0
  99. packages/tmsi/build/lib/apex_sdk/device/devices/apex/measurements/impedance_measurement.py +129 -0
  100. packages/tmsi/build/lib/apex_sdk/device/threads/conversion_thread.py +59 -0
  101. packages/tmsi/build/lib/apex_sdk/device/threads/sampling_thread.py +57 -0
  102. packages/tmsi/build/lib/apex_sdk/device/tmsi_channel.py +83 -0
  103. packages/tmsi/build/lib/apex_sdk/device/tmsi_device.py +201 -0
  104. packages/tmsi/build/lib/apex_sdk/device/tmsi_device_enums.py +103 -0
  105. packages/tmsi/build/lib/apex_sdk/device/tmsi_dongle.py +43 -0
  106. packages/tmsi/build/lib/apex_sdk/device/tmsi_event_reader.py +50 -0
  107. packages/tmsi/build/lib/apex_sdk/device/tmsi_measurement.py +118 -0
  108. packages/tmsi/build/lib/apex_sdk/sample_data_server/__init__.py +33 -0
  109. packages/tmsi/build/lib/apex_sdk/sample_data_server/event_data.py +44 -0
  110. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data.py +50 -0
  111. packages/tmsi/build/lib/apex_sdk/sample_data_server/sample_data_server.py +136 -0
  112. packages/tmsi/build/lib/apex_sdk/tmsi_errors/error.py +126 -0
  113. packages/tmsi/build/lib/apex_sdk/tmsi_sdk.py +113 -0
  114. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/apex/apex_structure_generator.py +134 -0
  115. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/decorators.py +60 -0
  116. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/logger_filter.py +42 -0
  117. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/singleton.py +42 -0
  118. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/support_functions.py +72 -0
  119. packages/tmsi/build/lib/apex_sdk/tmsi_utilities/tmsi_logger.py +98 -0
  120. py_neuromodulation/{helper.py → _write_example_dataset_helper.py} +1 -1
  121. py_neuromodulation/nm_EpochStream.py +2 -3
  122. py_neuromodulation/nm_IO.py +43 -70
  123. py_neuromodulation/nm_RMAP.py +308 -11
  124. py_neuromodulation/nm_analysis.py +1 -1
  125. py_neuromodulation/nm_artifacts.py +25 -0
  126. py_neuromodulation/nm_bispectra.py +64 -29
  127. py_neuromodulation/nm_bursts.py +44 -30
  128. py_neuromodulation/nm_coherence.py +2 -1
  129. py_neuromodulation/nm_features.py +4 -2
  130. py_neuromodulation/nm_filter.py +63 -32
  131. py_neuromodulation/nm_filter_preprocessing.py +91 -0
  132. py_neuromodulation/nm_fooof.py +47 -29
  133. py_neuromodulation/nm_mne_connectivity.py +1 -1
  134. py_neuromodulation/nm_normalization.py +50 -74
  135. py_neuromodulation/nm_oscillatory.py +151 -31
  136. py_neuromodulation/nm_plots.py +13 -10
  137. py_neuromodulation/nm_rereference.py +10 -8
  138. py_neuromodulation/nm_run_analysis.py +28 -13
  139. py_neuromodulation/nm_sharpwaves.py +103 -136
  140. py_neuromodulation/nm_stats.py +44 -30
  141. py_neuromodulation/nm_stream_abc.py +18 -10
  142. py_neuromodulation/nm_stream_offline.py +181 -40
  143. py_neuromodulation/utils/_logging.py +24 -0
  144. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/METADATA +182 -142
  145. py_neuromodulation-0.0.3.dist-info/RECORD +188 -0
  146. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/WHEEL +2 -1
  147. py_neuromodulation-0.0.3.dist-info/top_level.txt +5 -0
  148. tests/__init__.py +0 -0
  149. tests/conftest.py +117 -0
  150. tests/test_all_examples.py +10 -0
  151. tests/test_all_features.py +63 -0
  152. tests/test_bispectra.py +70 -0
  153. tests/test_bursts.py +105 -0
  154. tests/test_feature_sampling_rates.py +143 -0
  155. tests/test_fooof.py +16 -0
  156. tests/test_initalization_offline_stream.py +41 -0
  157. tests/test_multiprocessing.py +58 -0
  158. tests/test_nan_values.py +29 -0
  159. tests/test_nm_filter.py +95 -0
  160. tests/test_nm_resample.py +63 -0
  161. tests/test_normalization_settings.py +146 -0
  162. tests/test_notch_filter.py +31 -0
  163. tests/test_osc_features.py +424 -0
  164. tests/test_preprocessing_filter.py +151 -0
  165. tests/test_rereference.py +171 -0
  166. tests/test_sampling.py +57 -0
  167. tests/test_settings_change_after_init.py +76 -0
  168. tests/test_sharpwave.py +165 -0
  169. tests/test_target_channel_add.py +100 -0
  170. tests/test_timing.py +80 -0
  171. py_neuromodulation/data/README +0 -6
  172. py_neuromodulation/data/dataset_description.json +0 -8
  173. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/MOV_aligned_features_ch_ECOG_RIGHT_0_all.png +0 -0
  174. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/all_feature_plt.pdf +0 -0
  175. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_FEATURES.csv +0 -182
  176. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_LM_ML_RES.p +0 -0
  177. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SETTINGS.json +0 -273
  178. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SIDECAR.json +0 -6
  179. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_decoding_performance.png +0 -0
  180. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_nm_channels.csv +0 -11
  181. py_neuromodulation/data/participants.json +0 -32
  182. py_neuromodulation/data/participants.tsv +0 -2
  183. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +0 -5
  184. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +0 -11
  185. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +0 -11
  186. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.eeg +0 -0
  187. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +0 -18
  188. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +0 -35
  189. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +0 -13
  190. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +0 -2
  191. py_neuromodulation/grid_cortex.tsv +0 -40
  192. py_neuromodulation/grid_subcortex.tsv +0 -1429
  193. py_neuromodulation/nm_settings.json +0 -290
  194. py_neuromodulation/plots/STN_surf.mat +0 -0
  195. py_neuromodulation/plots/Vertices.mat +0 -0
  196. py_neuromodulation/plots/faces.mat +0 -0
  197. py_neuromodulation/plots/grid.mat +0 -0
  198. py_neuromodulation/py_neuromodulation.egg-info/PKG-INFO +0 -104
  199. py_neuromodulation/py_neuromodulation.egg-info/dependency_links.txt +0 -1
  200. py_neuromodulation/py_neuromodulation.egg-info/requires.txt +0 -26
  201. py_neuromodulation/py_neuromodulation.egg-info/top_level.txt +0 -1
  202. py_neuromodulation-0.0.2.dist-info/RECORD +0 -73
  203. /py_neuromodulation/{py_neuromodulation.egg-info/SOURCES.txt → utils/__init__.py} +0 -0
  204. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.3.dist-info}/LICENSE +0 -0
@@ -0,0 +1,1611 @@
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 apex_device.py
26
+ * @brief
27
+ * APEX Device object.
28
+ */
29
+
30
+
31
+ """
32
+
33
+ import datetime
34
+ import os
35
+ import time
36
+
37
+ from ....tmsi_errors.error import TMSiError, TMSiErrorCode
38
+ from ....tmsi_utilities.decorators import LogPerformances
39
+
40
+ from ...tmsi_device import TMSiDevice
41
+ from ...tmsi_device_enums import *
42
+
43
+ from .apex_structures.apex_const import ApexConst
44
+ from .apex_structures.apex_info import ApexInfo
45
+ from .apex_structures.apex_config import ApexConfig
46
+ from .apex_structures.dongle_info import DongleInfo
47
+ from .apex_structures.apex_channel import ApexChannel
48
+ from .apex_structures.apex_impedance_channel import ApexImpedanceChannel
49
+ from .apex_API_structures import *
50
+ from .apex_API_enums import *
51
+ from .apex_dongle import ApexDongle
52
+
53
+ if "TMSi_ENV" in os.environ and os.environ["TMSi_ENV"] == "MOCKED":
54
+ from .apex_API_mock import *
55
+ elif "TMSi_ENV" in os.environ and os.environ["TMSi_ENV"] == "MOCKED24":
56
+ from .apex_API_mock_24 import *
57
+ else:
58
+ from .apex_API import *
59
+
60
+
61
+ class ApexDevice(TMSiDevice):
62
+ """A class to represent and handle the Apex"""
63
+
64
+ __apex_sdk = None
65
+ __MAX_NUM_DEVICES = 10
66
+ __MAX_NUM_DONGLES = 2
67
+ __device_info_list = []
68
+ __dongle_info_list = []
69
+ __DEVICE_TYPE = "APEX"
70
+
71
+ @LogPerformances
72
+ def __init__(
73
+ self,
74
+ serial_number,
75
+ dr_interface: DeviceInterfaceType,
76
+ pairing_status=PairingStatus.no_pairing_needed,
77
+ dongle_serial_number=0,
78
+ idx=-1,
79
+ ):
80
+ """Initialize the Device.
81
+
82
+ :param dr_serial_number: Serial number of the device.
83
+ :type dr_serial_number: int
84
+ :param dr_interface: Interface to use to communicate with the device.
85
+ :type dr_interface: DeviceInterfaceType
86
+ :param dongle_serial_number: Serial number of the dongle, default to 0.
87
+ :type dongle_serial_number: int
88
+ :param idx: Device index, defaults to -1.
89
+ :type idx: int, optional
90
+ """
91
+ self.__device_handle = DeviceHandle(0)
92
+ self.__info = ApexInfo(
93
+ id=idx,
94
+ serial_number=serial_number,
95
+ dr_interface=dr_interface,
96
+ dongle_serial_number=dongle_serial_number,
97
+ pairing_status=pairing_status,
98
+ )
99
+ self.__config = ApexConfig()
100
+
101
+ @LogPerformances
102
+ def close(self):
103
+ """Closes the connection to the device.
104
+
105
+ :raises TMSiError: TMSiErrorCode.device_error if impossible to close.
106
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
107
+ """
108
+ if self.__info.get_state() != DeviceState.disconnected:
109
+ self.__last_error_code = TMSiCloseInterface(self.__device_handle)
110
+ self.__info.set_state(DeviceState.disconnected)
111
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
112
+ return
113
+ else:
114
+ raise TMSiError(
115
+ TMSiErrorCode.device_error, self.__last_error_code
116
+ )
117
+ else:
118
+ raise TMSiError(TMSiErrorCode.device_not_connected)
119
+
120
+ @LogPerformances
121
+ def discover(dr_interface: DeviceInterfaceType, num_retries: int = 3):
122
+ """Discovers available devices.
123
+
124
+ :param dr_interface: Device interface to be searched.
125
+ :type dr_interface: DeviceInterfaceType
126
+ :param num_retries: Number of retries, optional
127
+ :type num_reties: int
128
+ """
129
+ if not ApexDllAvailable:
130
+ TMSiLogger().warning("APEX DLL not available.")
131
+ raise TMSiError(error_code=TMSiErrorCode.missing_dll)
132
+ if ApexDllLocked:
133
+ TMSiLogger().warning("APEX DLL already in use.")
134
+ raise TMSiError(error_code=TMSiErrorCode.already_in_use_dll)
135
+ ApexDevice.get_sdk() # if sdk already available, nothing happens, otherwise initialize
136
+ for i in range(ApexDevice.__MAX_NUM_DEVICES):
137
+ if (
138
+ ApexDevice.__device_info_list[i].get_dr_interface()
139
+ == dr_interface
140
+ ):
141
+ ApexDevice.__device_info_list[i] = ApexInfo()
142
+
143
+ for i in range(ApexDevice.__MAX_NUM_DONGLES):
144
+ ApexDevice.__dongle_info_list[i] = DongleInfo()
145
+
146
+ device_list = (TMSiDevList * ApexDevice.__MAX_NUM_DEVICES)()
147
+ dongle_list = (TMSiDongleList * ApexDevice.__MAX_NUM_DONGLES)()
148
+ num_found_devices = (c_uint)(0)
149
+ num_found_dongles = (c_uint)(0)
150
+
151
+ ret = TMSiGetDongleList(
152
+ pointer(dongle_list),
153
+ ApexDevice.__MAX_NUM_DONGLES,
154
+ pointer(num_found_dongles),
155
+ )
156
+ if ret == TMSiDeviceRetVal.TMSiStatusOK:
157
+ for i in range(ApexDevice.__MAX_NUM_DONGLES):
158
+ if i < num_found_dongles.value:
159
+ ApexDevice.__dongle_info_list[i].TMSiDongleID = dongle_list[
160
+ i
161
+ ].TMSiDongleID
162
+ ApexDevice.__dongle_info_list[i].SerialNumber = dongle_list[
163
+ i
164
+ ].SerialNumber
165
+ else:
166
+ break
167
+
168
+ for i in range(ApexDevice.__MAX_NUM_DEVICES):
169
+ device_list[i].TMSiDeviceID = ApexConst.TMSI_DEVICE_ID_NONE
170
+
171
+ while num_retries > 0:
172
+ ret = TMSiGetDeviceList(
173
+ pointer(device_list),
174
+ ApexDevice.__MAX_NUM_DEVICES,
175
+ dr_interface.value,
176
+ pointer(num_found_devices),
177
+ )
178
+
179
+ if ret == TMSiDeviceRetVal.TMSiStatusOK:
180
+ # Devices are found, update the local device list with the found result
181
+ for i in range(ApexDevice.__MAX_NUM_DEVICES):
182
+ if (
183
+ device_list[i].TMSiDeviceID
184
+ != ApexConst.TMSI_DEVICE_ID_NONE
185
+ ):
186
+ for ii in range(ApexDevice.__MAX_NUM_DEVICES):
187
+ if (
188
+ ApexDevice.__device_info_list[ii].get_id()
189
+ == ApexConst.TMSI_DEVICE_ID_NONE
190
+ ):
191
+ ApexDevice.__device_info_list[ii].set_id(
192
+ device_list[i].TMSiDeviceID
193
+ )
194
+ ApexDevice.__device_info_list[
195
+ ii
196
+ ].set_dr_interface(dr_interface)
197
+ ApexDevice.__device_info_list[
198
+ ii
199
+ ].set_dr_serial_number(
200
+ device_list[i].SerialNumberDataRecorder
201
+ )
202
+ ApexDevice.__device_info_list[
203
+ ii
204
+ ].set_dongle_serial_number(
205
+ device_list[i].SerialNumberDongle
206
+ )
207
+ ApexDevice.__device_info_list[
208
+ ii
209
+ ].set_pairing_status(
210
+ device_list[i].PairingStatus
211
+ )
212
+ ApexDevice.__device_info_list[ii].set_state(
213
+ DeviceState.disconnected
214
+ )
215
+
216
+ num_retries = 0
217
+ break
218
+ num_retries -= 1
219
+ else:
220
+ num_retries -= 1
221
+ TMSiLogger().warning(
222
+ "Trying to open connection to device. Number of retries left: "
223
+ + str(num_retries)
224
+ )
225
+
226
+ @LogPerformances
227
+ def download_file_from_device(self, file_id: int, filename: str = None):
228
+ """Creates a data stream to download the file from the device.
229
+
230
+ :param file_id: id of the file to download.
231
+ :type file_id: int
232
+ :param verbosity: if True, writes information about the download stream, defaults to True.
233
+ :type verbosity: bool, optional
234
+ :param filename: filename where to write the impedance report (if available), defaults to None
235
+ :type filename: str, optional
236
+ :raises TMSiError: TMSiErrorCode.file_writer_error if impedance report download fails.
237
+ :raises TMSiError: TMSiErrorCode.device_error if the file download fails.
238
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if already sampling.
239
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
240
+ """
241
+ header, metadata = self.get_device_card_file_info(file_id)
242
+ n_of_samples = metadata.NumberOfSamples
243
+ self.start_download_file(file_id, filename, n_of_samples)
244
+
245
+ while True:
246
+ percentage = self.__measurement.get_download_percentage()
247
+ if percentage >= 100:
248
+ break
249
+ if self.__measurement.is_timeout():
250
+ break
251
+ time.sleep(0.1)
252
+
253
+ self.stop_download_file()
254
+
255
+ @LogPerformances
256
+ def export_configuration(self, filename: str):
257
+ """Exports the current configuration to an xml file.
258
+
259
+ :param filename: name of the file where to export configuration.
260
+ :type filename: str
261
+ :raises TMSiError: TMSiErrorCode.file_writer_error if export configuration fails.
262
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
263
+ """
264
+ if self.__info.get_state() == DeviceState.connected:
265
+ if self.__config.export_to_xml(filename):
266
+ return
267
+ else:
268
+ raise TMSiError(error_code=TMSiErrorCode.file_writer_error)
269
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
270
+
271
+ @LogPerformances
272
+ def import_configuration(self, filename: str):
273
+ """Imports the file configuration to the device.
274
+
275
+ :param filename: name of the file where to export configuration.
276
+ :type filename: str
277
+ :raises TMSiError: TMSiErrorCode.general_error if import configuration fails.
278
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
279
+ """
280
+ if self.__info.get_state() == DeviceState.connected:
281
+ if self.__config.import_from_xml(filename):
282
+ self.__set_device_channel_config(
283
+ [
284
+ ch.get_channel_name()
285
+ for ch in self.__config.get_channels()
286
+ ],
287
+ [i for i in range(len(self.__config.get_channels()))],
288
+ )
289
+ self.__set_device_reference_config(
290
+ [ch.is_reference() for ch in self.__config.get_channels()],
291
+ [i for i in range(len(self.__config.get_channels()))],
292
+ )
293
+ self.__set_device_sampling_config(
294
+ frequency=TMSiBaseSampleRate(
295
+ self.__config.get_sample_rate()
296
+ ),
297
+ impedance_limit=self.__config.get_impedance_limit(),
298
+ live_impedance=TMSiLiveImpedance(
299
+ self.__config.get_live_impedance()
300
+ ),
301
+ )
302
+ self.__load_config_from_device()
303
+ return
304
+ else:
305
+ raise TMSiError(error_code=TMSiErrorCode.general_error)
306
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
307
+
308
+ @LogPerformances
309
+ def get_card_recording_config(self) -> TMSiDevCardRecCfg:
310
+ """Gets configuration for card recording.
311
+
312
+ :raises TMSiError: TMSiErrorCode.device_error if get configuration fails.
313
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
314
+ :return: Configuration of the card recording.
315
+ :rtype: TMSiDevCardRecCfg
316
+ """
317
+ if self.__info.get_state() == DeviceState.connected:
318
+ return self.__get_device_card_recording_config()
319
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
320
+
321
+ @LogPerformances
322
+ def get_card_status(self) -> TMSiDevCardStatus:
323
+ """Gets card status.
324
+
325
+ :raises TMSiError: TMSiErrorCode.device_error if get card status fails.
326
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
327
+ :return: Configuration of the card recording.
328
+ :rtype: TMSiDevCardStatus
329
+ """
330
+ if self.__info.get_state() == DeviceState.connected:
331
+ return self.__get_device_card_status()
332
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
333
+
334
+ @LogPerformances
335
+ def get_device_active_channels(self):
336
+ """Gets the list of active channels.
337
+
338
+ :raises TMSiError: TMSiErrorCode.device_error if get channels from the device fails.
339
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
340
+ :return: The list of channels
341
+ :rtype: list[ApexChannel]
342
+ """
343
+ return self.get_device_channels()
344
+
345
+ @LogPerformances
346
+ def get_device_card_file_info(
347
+ self, file_id: int
348
+ ) -> tuple[TMSiFileMetadataHeader, TMSiDevCardFileDetails]:
349
+ """Gets the information of the file on the device's card.
350
+
351
+ :param file_id: Id of the file to be investigated.
352
+ :type file_id: int
353
+ :raises TMSiError: TMSiErrorCode.device_error if get card info fails.
354
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
355
+ :return: A tuple with file metadata and file details.
356
+ :rtype: tuple[TMSiFileMetadataHeader, TMSiDevCardFileDetails]
357
+ """
358
+ if self.__info.get_state() == DeviceState.connected:
359
+ metadata, _ = self.__get_device_card_file_metadata(file_id)
360
+ header = self.__get_device_card_file_metadata_header(file_id)
361
+ return (header, metadata)
362
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
363
+
364
+ @LogPerformances
365
+ def get_device_card_file_list(self) -> list[TMSiDevCardFileInfo]:
366
+ """Gets the list of files available on the device's card.
367
+
368
+ :raises TMSiError: TMSiErrorCode.device_error if get card file list fails.
369
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
370
+ :return: A list of file info.
371
+ :rtype: list[TMSiDevCardFileInfo]
372
+ """
373
+ if self.__info.get_state() == DeviceState.connected:
374
+ return self.__get_device_card_file_list()
375
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
376
+
377
+ @LogPerformances
378
+ def get_device_channels(self) -> list[ApexChannel]:
379
+ """Gets the list of channels.
380
+
381
+ :raises TMSiError: TMSiErrorCode.device_error if get channels from the device fails.
382
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
383
+ :return: The list of channels
384
+ :rtype: list[ApexChannel]
385
+ """
386
+ if self.__info.get_state() == DeviceState.sampling:
387
+ return self.__config.get_channels()
388
+ if self.__info.get_state() != DeviceState.connected:
389
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
390
+ (
391
+ device_channel_metadata,
392
+ device_cycling_state_metadata,
393
+ ) = self.__get_device_sample_metadata()
394
+ (
395
+ device_channel_name_list,
396
+ device_channel_alt_name_list,
397
+ ) = self.__get_device_channel_config()
398
+ device_reference_config = self.__get_device_reference_config()
399
+ channels = []
400
+ for i in range(self.get_num_channels()):
401
+ channel = ApexChannel()
402
+ channel.set_device_channel_information(device_channel_metadata[i])
403
+ channel.set_device_channel_names(
404
+ device_channel_name_list[i].ChanName.decode("windows-1252"),
405
+ device_channel_alt_name_list[i].AltChanName.decode(
406
+ "windows-1252"
407
+ ),
408
+ )
409
+ if i < len(device_reference_config):
410
+ channel.set_device_reference(
411
+ device_reference_config[i].ChanRefStatus
412
+ )
413
+ else:
414
+ channel.set_device_reference(None)
415
+ channels.append(channel)
416
+ self.__config.set_channels(channels)
417
+ self.__get_device_impedance_metadata()
418
+ return self.__config.get_channels()
419
+
420
+ @LogPerformances
421
+ def get_device_data(
422
+ self,
423
+ POINTER_received_data_array: pointer,
424
+ buffer_size: int,
425
+ POINTER_num_of_sets: pointer,
426
+ POINTER_data_type: pointer,
427
+ ) -> TMSiDeviceRetVal:
428
+ """Gets data from the device during sampling.
429
+
430
+ :param POINTER_received_data_array: array that will contain the received data.
431
+ :type POINTER_received_data_array: pointer(array[c_float])
432
+ :param buffer_size: maximum size of the buffer.
433
+ :type buffer_size: int
434
+ :param POINTER_num_of_sets: number of sets of data received.
435
+ :type POINTER_num_of_sets: pointer(c_uint)
436
+ :param POINTER_data_type: type of data received.
437
+ :type POINTER_data_type: pointer(c_int)
438
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is notin samplin modeg
439
+ :return: return value of the call
440
+ :rtype: TMSiDeviceRetVal
441
+ """
442
+ if self.__info.get_state() != DeviceState.sampling:
443
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
444
+ return TMSiGetDeviceData(
445
+ self.__device_handle,
446
+ POINTER_received_data_array,
447
+ buffer_size,
448
+ POINTER_num_of_sets,
449
+ POINTER_data_type,
450
+ )
451
+
452
+ @LogPerformances
453
+ def get_device_handle_value(self) -> int:
454
+ """Returns the value of the device handle.
455
+
456
+ :return: Device handle.
457
+ :rtype: int
458
+ """
459
+ return self.__device_handle.value
460
+
461
+ @LogPerformances
462
+ def get_device_impedance_channels(self) -> list[ApexImpedanceChannel]:
463
+ """Gets the list of impedance channels.
464
+
465
+ :raises TMSiError: TMSiErrorCode.device_error if get channels from the device fails.
466
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
467
+ :return: The list of channels
468
+ :rtype: list[ApexChannel]
469
+ """
470
+ self.get_device_channels()
471
+ return self.__config.get_impedance_channels()
472
+
473
+ @LogPerformances
474
+ def get_device_impedance_data(
475
+ self,
476
+ POINTER_received_data_array: pointer,
477
+ buffer_size: int,
478
+ POINTER_num_of_sets: pointer,
479
+ ) -> TMSiDeviceRetVal:
480
+ """Gets impedance data from the device during sampling.
481
+
482
+ :param POINTER_received_data_array: array that will contain the received data.
483
+ :type POINTER_received_data_array: pointer(array[TMSiImpedanceSample])
484
+ :param buffer_size: maximum size of the buffer.
485
+ :type buffer_size: int
486
+ :param POINTER_num_of_sets: number of sets of data received.
487
+ :type POINTER_num_of_sets: pointer
488
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is notin samplin modeg
489
+ :return: return value of the call
490
+ :rtype: TMSiDeviceRetVal
491
+ """
492
+ if self.__info.get_state() != DeviceState.sampling:
493
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
494
+ return TMSiGetDeviceImpedanceData(
495
+ self.__device_handle,
496
+ POINTER_received_data_array,
497
+ buffer_size,
498
+ POINTER_num_of_sets,
499
+ )
500
+
501
+ @LogPerformances
502
+ def get_device_info_report(self) -> TMSiDevInfoReport:
503
+ """Gets the report with device information.
504
+
505
+ :raises TMSiError: TMSiErrorCode.device_error if get device info from the device fails.
506
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
507
+ :return: the device info report.
508
+ :rtype: TMSiDevInfoReport
509
+ """
510
+ if self.__info.get_state() == DeviceState.connected:
511
+ device_info_report = self.__get_device_info_report()
512
+ self.__info.set_device_info_report(device_info_report)
513
+ return device_info_report
514
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
515
+
516
+ @LogPerformances
517
+ def get_device_interface_status(
518
+ self, interface=DeviceInterfaceType.bluetooth
519
+ ) -> TMSiInterfaceStatus:
520
+ """Gets the device interface status.
521
+
522
+ :param interface: interface to check, defaults to DeviceInterfaceType.bluetooth
523
+ :type interface: DeviceInterfaceType, optional
524
+ :raises TMSiError: TMSiErrorCode.device_error if get device interface status from the device fails.
525
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
526
+ :return: interface status of the device.
527
+ :rtype: TMSiInterfaceStatus
528
+ """
529
+ if self.__info.get_state() == DeviceState.connected:
530
+ device_interface_status = self.__get_device_interface_status(
531
+ interface
532
+ )
533
+ return device_interface_status
534
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
535
+
536
+ @LogPerformances
537
+ def get_device_list(
538
+ dr_interface: DeviceInterfaceType,
539
+ ) -> list["ApexDevice"]:
540
+ """Gets the list of available devices.
541
+
542
+ :param dr_interface: interface to check.
543
+ :type dr_interface: DeviceInterfaceType
544
+ :return: a list of available devices on the requested interface.
545
+ :rtype: list[ApexDevice]
546
+ """
547
+ device_list = []
548
+ for idx in range(ApexDevice.__MAX_NUM_DEVICES):
549
+ if (
550
+ ApexDevice.__device_info_list[idx].get_id()
551
+ != ApexConst.TMSI_DEVICE_ID_NONE
552
+ and ApexDevice.__device_info_list[idx].get_dr_interface()
553
+ == dr_interface
554
+ ):
555
+ device_list.append(
556
+ ApexDevice(
557
+ dongle_serial_number=ApexDevice.__device_info_list[
558
+ idx
559
+ ].get_dongle_serial_number(),
560
+ serial_number=ApexDevice.__device_info_list[
561
+ idx
562
+ ].get_dr_serial_number(),
563
+ dr_interface=dr_interface,
564
+ idx=ApexDevice.__device_info_list[idx].get_id(),
565
+ pairing_status=ApexDevice.__device_info_list[
566
+ idx
567
+ ].get_pairing_status(),
568
+ )
569
+ )
570
+ return device_list
571
+
572
+ @LogPerformances
573
+ def get_device_power_status(self) -> TMSiDevPowerStatus:
574
+ """Returns the power status of the device
575
+
576
+ :raises TMSiError: TMSiErrorCode.device_error if get device power status from the device fails.
577
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
578
+ :return: device power status.
579
+ :rtype: TMSiDevPowerStatus
580
+ """
581
+ if self.__info.get_state() == DeviceState.connected:
582
+ return self.__get_device_power_status()
583
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
584
+
585
+ @LogPerformances
586
+ def get_device_sampling_config(self) -> TMSiDevSamplingCfg:
587
+ """Gets the sampling configuration of the device.
588
+
589
+ :raises TMSiError: TMSiErrorCode.device_error if get device sampling configuration from the device fails.
590
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
591
+ :return: device sampling configuration
592
+ :rtype: TMSiDevSamplingCfg
593
+ """
594
+ if self.__info.get_state() == DeviceState.connected:
595
+ device_sampling_config = self.__get_device_sampling_config()
596
+ self.__config.set_device_sampling_config(device_sampling_config)
597
+ return device_sampling_config
598
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
599
+
600
+ @LogPerformances
601
+ def get_device_sampling_frequency(self):
602
+ """Gets the sampling frequency."""
603
+ return self.__config.get_sampling_frequency()
604
+
605
+ @LogPerformances
606
+ def get_device_serial_number(self) -> int:
607
+ """Gets the serial number of the device.
608
+
609
+ :return: serial number of the device.
610
+ :rtype: int
611
+ """
612
+ return self.__info.get_dr_serial_number()
613
+
614
+ @LogPerformances
615
+ def get_device_state(self) -> DeviceState:
616
+ """Gets the state of the device.
617
+
618
+ :return: the device state.
619
+ :rtype: DeviceState
620
+ """
621
+ return self.__info.get_state()
622
+
623
+ @LogPerformances
624
+ def get_device_time(self) -> datetime.datetime:
625
+ """Gets the time on the device.
626
+
627
+ :raises TMSiError: TMSiErrorCode.device_error if get time from the device fails.
628
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
629
+ :return: returns the datetime on the device.
630
+ :rtype: datetime.datetime
631
+ """
632
+ if self.__info.get_state() != DeviceState.connected:
633
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
634
+ return self.__get_device_rtc()
635
+
636
+ @LogPerformances
637
+ def get_device_type(self) -> str:
638
+ """Returns the device type.
639
+
640
+ :return: the device type.
641
+ :rtype: str
642
+ """
643
+ return ApexDevice.__DEVICE_TYPE
644
+
645
+ @LogPerformances
646
+ def get_dongle_list() -> list[ApexDongle]:
647
+ """Returns the list of available dongles.
648
+
649
+ :return: list of available dongles.
650
+ :rtype: list[ApexDongle]
651
+ """
652
+ dongle_list = []
653
+ for idx in range(ApexDevice.__MAX_NUM_DONGLES):
654
+ if (
655
+ ApexDevice.__dongle_info_list[idx].TMSiDongleID
656
+ != ApexConst.TMSI_DONGLE_ID_NONE
657
+ ):
658
+ dongle_list.append(
659
+ ApexDongle(
660
+ ApexDevice.__dongle_info_list[idx].TMSiDongleID,
661
+ ApexDevice.__dongle_info_list[idx].SerialNumber,
662
+ )
663
+ )
664
+ return dongle_list
665
+
666
+ @LogPerformances
667
+ def get_dongle_serial_number(self) -> int:
668
+ """Gets the serial number of the dongle.
669
+
670
+ :return: serial number of the device.
671
+ :rtype: int
672
+ """
673
+ return self.__info.get_dongle_serial_number()
674
+
675
+ @LogPerformances
676
+ def get_downloaded_percentage(self) -> int:
677
+ """Gets the percentage of file downloaded.
678
+
679
+ :return: percentage of file downloaded.
680
+ :rtype: int
681
+ """
682
+ return self.__measurement.get_download_percentage()
683
+
684
+ @LogPerformances
685
+ def get_driver_version() -> tuple[str, str]:
686
+ """Gets the version of the DLL and USB drivers.
687
+
688
+ :raises TMSiError: TMSiErrorCode.device_error if it fails.
689
+ :return: tuple(dll_version, usb_version)
690
+ :rtype: tuple(str, str)
691
+ """
692
+ version = TMSiDeviceDriverVersionInfo()
693
+ __last_error = TMSiGetDeviceDriverVersionInfo(pointer(version))
694
+ if __last_error != TMSiDeviceRetVal.TMSiStatusOK:
695
+ raise TMSiError(
696
+ error_code=TMSiErrorCode.device_error,
697
+ dll_error_code=__last_error,
698
+ )
699
+ return version
700
+
701
+ @LogPerformances
702
+ def get_dr_interface(self) -> DeviceInterfaceType:
703
+ """Returns the interface of the device.
704
+
705
+ :return: the interface of the device.
706
+ :rtype: DeviceInterfaceType
707
+ """
708
+ return self.__info.get_dr_interface()
709
+
710
+ @LogPerformances
711
+ def get_event(POINTER_event):
712
+ """Gets the last event available
713
+
714
+ :param POINTER_event: _description_
715
+ :type POINTER_event: _type_
716
+ :return: _description_
717
+ :rtype: _type_
718
+ """
719
+ __last_error = TMSiGetEvent(POINTER_event)
720
+ if __last_error != TMSiDeviceRetVal.TMSiStatusOK:
721
+ raise TMSiError(
722
+ error_code=TMSiErrorCode.device_error,
723
+ dll_error_code=__last_error,
724
+ )
725
+
726
+ @LogPerformances
727
+ def get_event_buffer(POINTER_num_found_events):
728
+ """Gets the available events in the buffer
729
+
730
+ :return: TMSiDeviceRetVal.TMSiStatusOK
731
+ :rtype: TMSiDeviceRetVal
732
+ """
733
+ return TMSiGetEventBuffered(POINTER_num_found_events)
734
+
735
+ @LogPerformances
736
+ def get_id(self) -> int:
737
+ """Gets the device id.
738
+
739
+ :return: the device id.
740
+ :rtype: int
741
+ """
742
+ return self.__info.get_id()
743
+
744
+ @LogPerformances
745
+ def get_live_impedance(self) -> bool:
746
+ """Returns if live impedance is enabled.
747
+
748
+ :return: True if enabled, False if disabled.
749
+ :rtype: bool
750
+ """
751
+ return self.__config.get_live_impedance()
752
+
753
+ @LogPerformances
754
+ def get_num_channels(self) -> int:
755
+ """Returns the number of channels of the device.
756
+
757
+ :return: number of channels of the device.
758
+ :rtype: int
759
+ """
760
+ return self.__info.get_num_channels()
761
+
762
+ @LogPerformances
763
+ def get_num_impedance_channels(self) -> int:
764
+ """Returns the number of impedance channels of the device.
765
+
766
+ :return: number of impedance channels of the device.
767
+ :rtype: int
768
+ """
769
+ return self.__info.get_num_impedance_channels()
770
+
771
+ @LogPerformances
772
+ def get_sdk() -> CDLL:
773
+ """Gets the handle of the communication library
774
+
775
+ :return: the handle of the communication library.
776
+ :rtype: CDLL
777
+ """
778
+ if ApexDevice.__apex_sdk is None:
779
+ ApexDevice.__initialize()
780
+ return ApexDevice.__apex_sdk
781
+
782
+ @LogPerformances
783
+ def open(self, dongle_id=ApexConst.TMSI_DONGLE_ID_NONE):
784
+ """Opens the connection with the device.
785
+
786
+ :param dongle_id: Id of the dongle to use for the connection. Defaults to ApexConst.TMSI_DONGLE_ID_NONE
787
+ :type dongle_id: int, optional
788
+ :raises TMSiError: TMSiErrorCode.device_error if get time from the device fails.
789
+ :raises TMSiError: TMSiErrorCode.no_devices_found if device not found.
790
+ """
791
+ self.__info.set_dongle_id(dongle_id)
792
+ if self.__info.get_id() != ApexConst.TMSI_DEVICE_ID_NONE:
793
+ self.__last_error_code = TMSiOpenInterface(
794
+ pointer(self.__device_handle),
795
+ dongle_id,
796
+ self.__info.get_id(),
797
+ self.__info.get_dr_interface().value,
798
+ )
799
+ if (
800
+ self.__last_error_code
801
+ == TMSiDeviceRetVal.TMSiStatusDrInterfaceAlreadyOpen
802
+ ):
803
+ # The found device is available but in it's open-state: Close and re-open the connection
804
+ self.__last_error_code = TMSiCloseInterface(
805
+ self.__device_handle, self.__info.get_dr_interface().value
806
+ )
807
+ self.__last_error_code = TMSiOpenInterface(
808
+ pointer(self.__device_handle),
809
+ dongle_id,
810
+ self.__info.get_id(),
811
+ self.__info.get_dr_interface().value,
812
+ )
813
+
814
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
815
+ # The device is opened succesfully. Update the device information.
816
+ self.__info.set_state(DeviceState.connected)
817
+
818
+ # Read the device's configuration
819
+ self.__load_config_from_device()
820
+
821
+ else:
822
+ raise TMSiError(
823
+ error_code=TMSiErrorCode.device_error,
824
+ dll_error_code=self.__last_error_code,
825
+ )
826
+ else:
827
+ raise TMSiError(error_code=TMSiErrorCode.no_devices_found)
828
+
829
+ @LogPerformances
830
+ def pair_device(dongle_id: int, device_id: int) -> TMSiDeviceRetVal:
831
+ """Pairs the device with the dongle
832
+
833
+ :param dongle_id: Id of the dongle
834
+ :type dongle_id: int
835
+ :param device_id: Id of the device
836
+ :type device_id: int
837
+ :return: return value of the call
838
+ :rtype: TMSiDeviceRetVal
839
+ """
840
+ ret = TMSiPairDevice(dongle_id, device_id)
841
+ if ret == TMSiDeviceRetVal.TMSiStatusDllCommandInProgress:
842
+ TMSiLogger().info("Pairing ongoing")
843
+ elif ret == TMSiDeviceRetVal.TMSiStatusDllDeviceAlreadyPaired:
844
+ TMSiLogger().warning("Device already paired")
845
+ else:
846
+ TMSiLogger().warning("Pairing process failed")
847
+ return ret
848
+
849
+ @LogPerformances
850
+ def reset_device_card(self):
851
+ """Resets the memory card of the device.
852
+
853
+ :raises TMSiError: TMSiErrorCode.device_error if reset card fails.
854
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
855
+ """
856
+ if self.__info.get_state() != DeviceState.connected:
857
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
858
+ self.__reset_device_card()
859
+
860
+ @LogPerformances
861
+ def reset_device_data_buffer(self):
862
+ """Resets the incoming buffer.
863
+
864
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is notin samplin modeg
865
+ :raises TMSiError: TMSiErrorCode.device_error if reset fails
866
+ """
867
+ if self.__info.get_state() != DeviceState.sampling:
868
+ raise TMSiError(TMSiErrorCode.api_invalid_command)
869
+ self.__last_error_code = TMSiResetDeviceDataBuffer(self.__device_handle)
870
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
871
+ return
872
+ else:
873
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
874
+
875
+ @LogPerformances
876
+ def reset_device_event_buffer():
877
+ """Resets the incoming event buffer.
878
+
879
+ :raises TMSiError: TMSiErrorCode.device_error if reset fails
880
+ """
881
+ __last_error_code = TMSiResetEventBuffer()
882
+ if __last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
883
+ return
884
+ else:
885
+ raise TMSiError(TMSiErrorCode.device_error, __last_error_code)
886
+
887
+ @LogPerformances
888
+ def reset_to_factory_default(self):
889
+ """Resets the device to default configuration.
890
+
891
+ :raises TMSiError: TMSiErrorCode.device_error if reset fails.
892
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
893
+ """
894
+ if self.__info.get_state() != DeviceState.connected:
895
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
896
+ self.__set_device_factory_default()
897
+ self.__load_config_from_device()
898
+
899
+ @LogPerformances
900
+ def set_card_recording_config(
901
+ self, config: TMSiDevCardRecCfg
902
+ ) -> TMSiDevCardRecCfg:
903
+ """Sets the configuration for recording on card.
904
+
905
+ :param config: configuration to be set.
906
+ :type config: TMSiDevCardRecCfg
907
+ :raises TMSiError: TMSiErrorCode.device_error if set configuration fails.
908
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
909
+ :return: the new available configuration for recording on card.
910
+ :rtype: TMSiDevCardRecCfg
911
+ """
912
+ if self.__info.get_state() != DeviceState.connected:
913
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
914
+ self.__set_device_card_recording_config(config)
915
+ return self.__get_device_card_recording_config()
916
+
917
+ @LogPerformances
918
+ def set_device_channel_names(
919
+ self, names: list[str], indices: list[int]
920
+ ) -> list[ApexChannel]:
921
+ """Sets the device channel names
922
+
923
+ :param names: names to be set.
924
+ :type names: list[str]
925
+ :param indices: index of the channels to edit.
926
+ :type indices: list[int]
927
+ :raises TMSiError: TMSiErrorCode.device_error if set names fails.
928
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
929
+ :raises TypeError: if names is not only strings
930
+ :raises TypeError: if indices is not only integers.
931
+ :return: list of new channels.
932
+ :rtype: list[ApexChannel]
933
+ """
934
+ if self.__info.get_state() != DeviceState.connected:
935
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
936
+ for name in names:
937
+ if not isinstance(name, str):
938
+ raise TypeError("names must be strings")
939
+ for index in indices:
940
+ if not isinstance(index, int):
941
+ raise TypeError("indices must be integers")
942
+ self.__set_device_channel_config(names, indices)
943
+ return self.get_device_channels()
944
+
945
+ @LogPerformances
946
+ def set_device_download_file_request(
947
+ self, file_request: TMSiDevSetCardFileReq
948
+ ):
949
+ """Sets the download file request to start or stop the download stream.
950
+
951
+ :param file_request: file request to start or stop.
952
+ :type file_request: TMSiDevSetCardFileReq
953
+ :raises TMSiError: TMSiErrorCode.device_error if set impedance request fails.
954
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is not in sampling mode.
955
+ """
956
+ if self.__info.get_state() != DeviceState.sampling:
957
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
958
+ self.__last_error_code = TMSiSetDeviceCardFileRequest(
959
+ self.__device_handle, pointer(file_request)
960
+ )
961
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
962
+ return
963
+ else:
964
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
965
+
966
+ @LogPerformances
967
+ def set_device_impedance_request(
968
+ self, measurement_request: TMSiDevImpedanceRequest
969
+ ):
970
+ """Sets the impedance request to start or stop the acquisition.
971
+
972
+ :param measurement_request: measurement request to start or stop.
973
+ :type measurement_request: TMSiSetDeviceImpedanceRequest
974
+ :raises TMSiError: TMSiErrorCode.device_error if set impedance request fails.
975
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is not in sampling mode.
976
+ """
977
+ if self.__info.get_state() != DeviceState.sampling:
978
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
979
+ self.__last_error_code = TMSiSetDeviceImpedanceRequest(
980
+ self.__device_handle, pointer(measurement_request)
981
+ )
982
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
983
+ return
984
+ else:
985
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
986
+
987
+ @LogPerformances
988
+ def set_device_interface(
989
+ self,
990
+ device_interface=DeviceInterfaceType.bluetooth,
991
+ control=TMSiControl.ControlEnabled,
992
+ ) -> TMSiDevCardStatus:
993
+ """Set the device interface.
994
+
995
+ :param device_interface: the interface to set, defaults to DeviceInterfaceType.bluetooth
996
+ :type device_interface: DeviceInterfaceType, optional
997
+ :param control: enable or disable interface, defaults to TMSiControl.ControlEnabled
998
+ :type control: TMSiControl, optional
999
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1000
+ :return: the new status of the device interface.
1001
+ :rtype: TMSiDevCardStatus
1002
+ """
1003
+ if self.__info.get_state() != DeviceState.connected:
1004
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
1005
+ self.__set_device_interface_config(
1006
+ device_interface=device_interface, control=control
1007
+ )
1008
+ return self.get_device_interface_status(device_interface)
1009
+
1010
+ @LogPerformances
1011
+ def set_device_references(
1012
+ self, list_references: list[int], list_indices: list[int]
1013
+ ):
1014
+ """Sets the channels to be used as reference.
1015
+
1016
+ :param list_references: list of reference values.
1017
+ :type list_references: list[int]
1018
+ :param list_indices: list of indices to be edited.
1019
+ :type list_indices: list[int]
1020
+ :raises TMSiError: TMSiErrorCode.device_error if set references fails.
1021
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1022
+ :raises TypeError: if references is not only integers
1023
+ :raises TypeError: if indices is not only integers.
1024
+ :return: list of new channels.
1025
+ :rtype: list[ApexChannel]
1026
+ """
1027
+ if self.__info.get_state() != DeviceState.connected:
1028
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
1029
+ for index in list_indices:
1030
+ if not isinstance(index, int):
1031
+ raise TypeError("indices must be integers")
1032
+ for reference in list_references:
1033
+ if not isinstance(reference, int):
1034
+ raise TypeError("references must be integers")
1035
+ self.__set_device_reference_config(
1036
+ list_references=list_references, list_indices=list_indices
1037
+ )
1038
+ return self.get_device_channels()
1039
+
1040
+ @LogPerformances
1041
+ def set_device_sampling_config(
1042
+ self,
1043
+ sampling_frequency=TMSiBaseSampleRate.Decimal,
1044
+ live_impedance=TMSiLiveImpedance.On,
1045
+ impedance_limit=0,
1046
+ ) -> TMSiDevSamplingCfg:
1047
+ """Sets the sampling configuration of the device.
1048
+
1049
+ :param sampling_frequency: sample rate to set, defaults to TMSiBaseSampleRate.Decimal
1050
+ :type sampling_frequency: TMSiBaseSampleRate, optional
1051
+ :param live_impedance: enable or disable live impedance, defaults to TMSiLiveImpedance.On
1052
+ :type live_impedance: TMSiLiveImpedance, optional
1053
+ :param impedance_limit: kOhms value of the impedance limit, defaults to 0
1054
+ :type impedance_limit: int, optional
1055
+ :raises TMSiError: TMSiErrorCode.device_error if set sampling configuration fails.
1056
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1057
+ :return: the new sampling configuration
1058
+ :rtype: TMSiDevSamplingCfg
1059
+ """
1060
+ if self.__info.get_state() != DeviceState.connected:
1061
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
1062
+ self.__set_device_sampling_config(
1063
+ frequency=sampling_frequency,
1064
+ live_impedance=live_impedance,
1065
+ impedance_limit=impedance_limit,
1066
+ )
1067
+ return self.get_device_sampling_config()
1068
+
1069
+ @LogPerformances
1070
+ def set_device_sampling_request(
1071
+ self, measurement_request: TMSiDevSampleRequest
1072
+ ):
1073
+ """Sets the sampling request to start or stop the acquisition.
1074
+
1075
+ :param measurement_request: measurement request to configure the acquisition.
1076
+ :type measurement_request: TMSiDevSampleRequest
1077
+ :raises TMSiError: TMSiErrorCode.device_error if set sampling request fails.
1078
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if device is not in sampling mode.
1079
+ """
1080
+ if self.__info.get_state() != DeviceState.sampling:
1081
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
1082
+ self.__last_error_code = TMSiSetDeviceSamplingRequest(
1083
+ self.__device_handle, pointer(measurement_request)
1084
+ )
1085
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1086
+ return
1087
+ else:
1088
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1089
+
1090
+ @LogPerformances
1091
+ def set_device_time(self, datetime: datetime.datetime):
1092
+ """Sets the datetime of the device.
1093
+
1094
+ :param datetime: datetime to set on the device.
1095
+ :type datetime: datetime.datetime
1096
+ :raises TMSiError: TMSiErrorCode.device_error if set time fails.
1097
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1098
+ """
1099
+ if self.__info.get_state() != DeviceState.connected:
1100
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
1101
+ self.__set_device_rtc(datetime)
1102
+
1103
+ @LogPerformances
1104
+ def start_download_file(
1105
+ self, file_id: int, filename: str = None, n_of_samples: int = None
1106
+ ):
1107
+ """Starts the download of the file requested.
1108
+
1109
+ :param file_id: id of the file to download.
1110
+ :type file_id: int
1111
+ :param filename: filename where to write the impedance report (if available), defaults to None
1112
+ :type filename: str, optional
1113
+ :raises TMSiError: TMSiErrorCode.file_writer_error if impedance report download fails.
1114
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if already sampling.
1115
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1116
+ """
1117
+ if self.__info.get_state() == DeviceState.sampling:
1118
+ raise TMSiError(TMSiErrorCode.api_invalid_command)
1119
+ if self.__info.get_state() != DeviceState.connected:
1120
+ raise TMSiError(TMSiErrorCode.device_not_connected)
1121
+ if filename is not None:
1122
+ self.__download_impedance_report(file_id, filename)
1123
+ self.__measurement = MeasurementType.APEX_DOWNLOAD(
1124
+ self, file_id, n_of_samples
1125
+ )
1126
+ self.__info.set_state(DeviceState.sampling)
1127
+ self.__measurement.start()
1128
+
1129
+ @LogPerformances
1130
+ def start_measurement(
1131
+ self, measurement_type: MeasurementType, thread_refresh=None
1132
+ ):
1133
+ """Starts the measurement requested.
1134
+
1135
+ :param measurement_type: measurement to start
1136
+ :type measurement_type: MeasurementType
1137
+ :param thread_refresh: refresh time for sampling and conversion threads, defaults to None.
1138
+ :type thread_refresh: float, optional.
1139
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if already sampling.
1140
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1141
+ """
1142
+ if self.__info.get_state() == DeviceState.sampling:
1143
+ raise TMSiError(TMSiErrorCode.api_invalid_command)
1144
+ if self.__info.get_state() != DeviceState.connected:
1145
+ raise TMSiError(error_code=TMSiErrorCode.device_not_connected)
1146
+ self.__measurement = measurement_type(self)
1147
+ if thread_refresh is not None:
1148
+ self.__measurement.set_sampling_pause(thread_refresh)
1149
+ self.__measurement.set_conversion_pause(thread_refresh)
1150
+ self.__info.set_state(DeviceState.sampling)
1151
+ self.__measurement.start()
1152
+
1153
+ @LogPerformances
1154
+ def stop_download_file(self):
1155
+ """Stops the download of the file.
1156
+
1157
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if not sampling.
1158
+ """
1159
+ if self.__info.get_state() != DeviceState.sampling:
1160
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
1161
+ self.__measurement.stop()
1162
+ self.__info.set_state(DeviceState.connected)
1163
+
1164
+ @LogPerformances
1165
+ def stop_measurement(self):
1166
+ """Stops the measurement requested.
1167
+
1168
+ :param file_id: id of the file to download.
1169
+ :type file_id: int
1170
+ :raises TMSiError: TMSiErrorCode.api_invalid_command if already sampling.
1171
+ :raises TMSiError: TMSiErrorCode.device_not_connected if not connected.
1172
+ """
1173
+ if self.__info.get_state() != DeviceState.sampling:
1174
+ raise TMSiError(error_code=TMSiErrorCode.api_invalid_command)
1175
+ self.__measurement.stop()
1176
+ self.__info.set_state(DeviceState.connected)
1177
+
1178
+ @LogPerformances
1179
+ def __initialize():
1180
+ try:
1181
+ ApexDevice.__apex_sdk = ApexSDK
1182
+ for i in range(ApexDevice.__MAX_NUM_DEVICES):
1183
+ ApexDevice.__device_info_list.append(ApexInfo())
1184
+ for i in range(ApexDevice.__MAX_NUM_DONGLES):
1185
+ ApexDevice.__dongle_info_list.append(DongleInfo())
1186
+ except:
1187
+ ApexDevice.__apex_sdk = None
1188
+ raise TMSiError(error_code=TMSiErrorCode.api_no_driver)
1189
+
1190
+ @LogPerformances
1191
+ def __download_impedance_report(self, file_id, filename):
1192
+ (
1193
+ card_file_details,
1194
+ impedance_report_list,
1195
+ ) = self.__get_device_card_file_metadata(file_id)
1196
+ try:
1197
+ with open("{}.txt".format(filename), "w") as f:
1198
+ f.write("{}\n\n".format(card_file_details.RecFileName.decode()))
1199
+ f.write("Idx\t\tName\t\tRe\t\t\tIm\n")
1200
+ f.write(
1201
+ "\n".join(
1202
+ [
1203
+ "{}\t\t{}\t\t{} kOhm\t\t{} nF".format(
1204
+ i.ChanIdx,
1205
+ i.ChanName.decode(),
1206
+ i.ImpedanceRe,
1207
+ i.ImpedanceIm,
1208
+ )
1209
+ for i in impedance_report_list
1210
+ ]
1211
+ )
1212
+ )
1213
+ except Exception as e:
1214
+ raise TMSiError(TMSiErrorCode.file_writer_error)
1215
+
1216
+ @LogPerformances
1217
+ def __get_device_card_file_list(self):
1218
+ file_list = (2000 * TMSiDevCardFileInfo)()
1219
+ file_number = (c_uint)(0)
1220
+ self.__last_error_code = TMSiGetDeviceCardFileList(
1221
+ self.__device_handle,
1222
+ pointer(file_list),
1223
+ len(file_list),
1224
+ pointer(file_number),
1225
+ )
1226
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1227
+ return_list = []
1228
+ for i in range(file_number.value):
1229
+ return_list.append(file_list[i])
1230
+ return return_list
1231
+ else:
1232
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1233
+
1234
+ @LogPerformances
1235
+ def __get_device_card_file_metadata(self, file_id):
1236
+ RecFileID = file_id
1237
+ DevCardFileDetails = TMSiDevCardFileDetails()
1238
+ ChannelMetadataList = (self.get_num_channels() * TMSiChannelMetadata)()
1239
+ ChannelMetadataListLen = self.get_num_channels()
1240
+ RetChannelMetadataListLen = (c_uint)(0)
1241
+ CyclingStateMetadataList = (
1242
+ self.get_num_channels() * TMSiCyclingStateMetadata
1243
+ )()
1244
+ CyclingStateMetadataListLen = self.get_num_channels()
1245
+ RetCyclingStatMetadataListLen = (c_uint)(0)
1246
+ ImpReportMetadata = TMSiDevImpReportMetadata()
1247
+ ImpedanceReportList = (self.get_num_channels() * TMSiDevImpReport)()
1248
+ ImpedanceReportListLen = self.get_num_channels()
1249
+ RetImpedanceReportListLen = (c_uint)(0)
1250
+ self.__last_error_code = TMSiGetDeviceCardFileMetadata(
1251
+ self.__device_handle,
1252
+ RecFileID,
1253
+ pointer(DevCardFileDetails),
1254
+ pointer(ChannelMetadataList),
1255
+ ChannelMetadataListLen,
1256
+ pointer(RetChannelMetadataListLen),
1257
+ pointer(CyclingStateMetadataList),
1258
+ CyclingStateMetadataListLen,
1259
+ pointer(RetCyclingStatMetadataListLen),
1260
+ pointer(ImpReportMetadata),
1261
+ pointer(ImpedanceReportList),
1262
+ ImpedanceReportListLen,
1263
+ pointer(RetImpedanceReportListLen),
1264
+ )
1265
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1266
+ return (
1267
+ DevCardFileDetails,
1268
+ ImpedanceReportList[0 : RetImpedanceReportListLen.value],
1269
+ )
1270
+ else:
1271
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1272
+
1273
+ @LogPerformances
1274
+ def __get_device_card_file_metadata_header(self, file_id):
1275
+ metadata = TMSiFileMetadataHeader()
1276
+ self.__last_error_code = TMSiGetDeviceCardFileMetadataHeader(
1277
+ self.__device_handle, file_id, pointer(metadata)
1278
+ )
1279
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1280
+ return metadata
1281
+ else:
1282
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1283
+
1284
+ @LogPerformances
1285
+ def __get_device_card_recording_config(self):
1286
+ config = TMSiDevCardRecCfg()
1287
+ self.__last_error_code = TMSiGetDeviceCardRecordingConfig(
1288
+ self.__device_handle, pointer(config)
1289
+ )
1290
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1291
+ return config
1292
+ else:
1293
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1294
+
1295
+ @LogPerformances
1296
+ def __get_device_card_status(self):
1297
+ card_status = TMSiDevCardStatus()
1298
+ self.__last_error_code = TMSiGetDeviceCardStatus(
1299
+ self.__device_handle, pointer(card_status)
1300
+ )
1301
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1302
+ return card_status
1303
+ else:
1304
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1305
+
1306
+ @LogPerformances
1307
+ def __get_device_channel_config(self):
1308
+ device_channel_alt_name_list = (
1309
+ TMSiDevAltChName * self.get_num_channels()
1310
+ )()
1311
+ device_channel_name_list = (TMSiDevChName * self.get_num_channels())()
1312
+ num_returned_items = (c_uint)(0)
1313
+ self.__last_error_code = TMSiGetDeviceChannelConfig(
1314
+ self.__device_handle,
1315
+ pointer(device_channel_name_list),
1316
+ pointer(device_channel_alt_name_list),
1317
+ self.get_num_channels(),
1318
+ pointer(num_returned_items),
1319
+ )
1320
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1321
+ return device_channel_name_list, device_channel_alt_name_list
1322
+ else:
1323
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1324
+
1325
+ @LogPerformances
1326
+ def __get_device_impedance_metadata(self):
1327
+ num_returned_items = (c_uint)(0)
1328
+ device_impedance_metadata_list = (
1329
+ TMSiImpedanceMetadata * self.get_num_impedance_channels()
1330
+ )()
1331
+ TMSiGetDeviceImpedanceMetadata(
1332
+ self.__device_handle,
1333
+ pointer(device_impedance_metadata_list),
1334
+ self.get_num_impedance_channels(),
1335
+ pointer(num_returned_items),
1336
+ )
1337
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1338
+ impedance_metadata_list = []
1339
+ impedance_channels = []
1340
+ for i in range(num_returned_items.value):
1341
+ impedance_metadata_list.append(
1342
+ device_impedance_metadata_list[i]
1343
+ )
1344
+ impedance_channels.append(
1345
+ ApexImpedanceChannel(device_impedance_metadata_list[i])
1346
+ )
1347
+ self.__config.set_impedance_channels(impedance_channels)
1348
+ return impedance_metadata_list
1349
+ else:
1350
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1351
+
1352
+ @LogPerformances
1353
+ def __get_device_info_report(self):
1354
+ device_info_report = TMSiDevInfoReport()
1355
+ self.__last_error_code = TMSiGetDeviceInfo(
1356
+ self.__device_handle, pointer(device_info_report)
1357
+ )
1358
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1359
+ return device_info_report
1360
+ else:
1361
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1362
+
1363
+ @LogPerformances
1364
+ def __get_device_interface_status(self, interface):
1365
+ interface_status = TMSiInterfaceStatus()
1366
+ self.__last_error_code = TMSiGetDeviceInterfaceStatus(
1367
+ self.__device_handle, interface.value, pointer(interface_status)
1368
+ )
1369
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1370
+ return interface_status
1371
+ else:
1372
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1373
+
1374
+ @LogPerformances
1375
+ def __get_device_power_status(self):
1376
+ power_status = TMSiDevPowerStatus()
1377
+ self.__last_error_code = TMSiGetDevicePowerStatus(
1378
+ self.__device_handle, pointer(power_status)
1379
+ )
1380
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1381
+ return power_status
1382
+ else:
1383
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1384
+
1385
+ @LogPerformances
1386
+ def __get_device_reference_config(self):
1387
+ device_channel_reference_list = (
1388
+ TMSiDevChanRef * self.get_num_channels()
1389
+ )()
1390
+ len_channel_reference_list = (c_uint)(0)
1391
+ self.__last_error_code = TMSiGetDeviceReferenceConfig(
1392
+ self.__device_handle,
1393
+ pointer(device_channel_reference_list),
1394
+ self.get_num_channels(),
1395
+ pointer(len_channel_reference_list),
1396
+ )
1397
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1398
+ device_channel_reference_list_to_return = (
1399
+ TMSiDevChanRef * len_channel_reference_list.value
1400
+ )()
1401
+ for i in range(len_channel_reference_list.value):
1402
+ device_channel_reference_list_to_return[
1403
+ i
1404
+ ] = device_channel_reference_list[i]
1405
+ return device_channel_reference_list_to_return
1406
+ else:
1407
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1408
+
1409
+ @LogPerformances
1410
+ def __get_device_rtc(self):
1411
+ dev_time = TMSiTime()
1412
+ self.__last_error_code = TMSiGetDeviceRTC(
1413
+ self.__device_handle, pointer(dev_time)
1414
+ )
1415
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1416
+ return datetime.datetime(
1417
+ dev_time.Year + 1900,
1418
+ dev_time.Month + 1,
1419
+ dev_time.DayOfMonth,
1420
+ dev_time.Hours,
1421
+ dev_time.Minutes,
1422
+ dev_time.Seconds,
1423
+ )
1424
+ else:
1425
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1426
+
1427
+ @LogPerformances
1428
+ def __get_device_sample_metadata_header(self):
1429
+ device_sampling_metadata_header = TMSiSampleMetadataHeader()
1430
+ self.__last_error_code = TMSiGetDeviceSampleMetadataHeader(
1431
+ self.__device_handle,
1432
+ self.__info.get_dr_interface().value,
1433
+ pointer(device_sampling_metadata_header),
1434
+ )
1435
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1436
+ return device_sampling_metadata_header
1437
+ else:
1438
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1439
+
1440
+ @LogPerformances
1441
+ def __get_device_sample_metadata(self):
1442
+ device_channel_metadata = (
1443
+ TMSiChannelMetadata * self.get_num_channels()
1444
+ )()
1445
+ device_cycling_state_metadata = (
1446
+ TMSiCyclingStateMetadata * self.get_num_channels()
1447
+ )()
1448
+ num_returned_channels = (c_uint)(0)
1449
+ num_returned_cycling_states = (c_uint)(0)
1450
+ TMSiGetDeviceSampleMetadata(
1451
+ self.__device_handle,
1452
+ self.__info.get_dr_interface().value,
1453
+ pointer(device_channel_metadata),
1454
+ self.get_num_channels(),
1455
+ pointer(num_returned_channels),
1456
+ pointer(device_cycling_state_metadata),
1457
+ self.get_num_channels(),
1458
+ pointer(num_returned_cycling_states),
1459
+ )
1460
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1461
+ return_channels = []
1462
+ return_cycling_states = []
1463
+ for i in range(num_returned_channels.value):
1464
+ return_channels.append(device_channel_metadata[i])
1465
+ for i in range(num_returned_cycling_states.value):
1466
+ return_cycling_states.append(device_cycling_state_metadata[i])
1467
+ return return_channels, return_cycling_states
1468
+ else:
1469
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1470
+
1471
+ @LogPerformances
1472
+ def __get_device_sampling_config(self):
1473
+ device_sampling_config = TMSiDevSamplingCfg()
1474
+ self.__last_error_code = TMSiGetDeviceSamplingConfig(
1475
+ self.__device_handle, pointer(device_sampling_config)
1476
+ )
1477
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1478
+ return device_sampling_config
1479
+ else:
1480
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1481
+
1482
+ @LogPerformances
1483
+ def __load_config_from_device(self):
1484
+ self.get_device_info_report()
1485
+ self.get_device_sampling_config()
1486
+ device_sampling_metadata_header = (
1487
+ self.__get_device_sample_metadata_header()
1488
+ )
1489
+ self.__config.set_sampling_frequency(
1490
+ device_sampling_metadata_header.BaseFS
1491
+ )
1492
+ self.get_device_channels()
1493
+
1494
+ @LogPerformances
1495
+ def __reset_device_card(self):
1496
+ self.__last_error_code = TMSiResetDeviceCard(self.__device_handle)
1497
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1498
+ return
1499
+ else:
1500
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1501
+
1502
+ @LogPerformances
1503
+ def __set_device_factory_default(self):
1504
+ self.__last_error_code = TMSiSetDeviceFactoryDefaults(
1505
+ self.__device_handle
1506
+ )
1507
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1508
+ return
1509
+ else:
1510
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1511
+
1512
+ @LogPerformances
1513
+ def __set_device_card_recording_config(self, config):
1514
+ self.__last_error_code = TMSiSetDeviceCardRecordingConfig(
1515
+ self.__device_handle, pointer(config)
1516
+ )
1517
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1518
+ return
1519
+ else:
1520
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1521
+
1522
+ @LogPerformances
1523
+ def __set_device_channel_config(self, list_names, list_indices):
1524
+ _, device_channel_alt_name_list = self.__get_device_channel_config()
1525
+ num_channels = len(list_indices)
1526
+ if len(list_indices) > 0:
1527
+ for i in range(num_channels):
1528
+ converted_str = bytearray(ApexStringLengths.AltChanName.value)
1529
+ for character in range(len(list_names[i])):
1530
+ converted_str[character] = ord(list_names[i][character])
1531
+ device_channel_alt_name_list[
1532
+ list_indices[i]
1533
+ ].AltChanName = bytes(converted_str)
1534
+ self.__last_error_code = TMSiSetDeviceChannelConfig(
1535
+ self.__device_handle,
1536
+ device_channel_alt_name_list,
1537
+ len(device_channel_alt_name_list),
1538
+ )
1539
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1540
+ return
1541
+ else:
1542
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1543
+
1544
+ @LogPerformances
1545
+ def __set_device_interface_config(
1546
+ self,
1547
+ device_interface=DeviceInterfaceType.bluetooth,
1548
+ control=TMSiControl.ControlEnabled,
1549
+ ):
1550
+ self.__last_error_code = TMSiSetDeviceInterfaceConfig(
1551
+ self.__device_handle, device_interface.value, control.value
1552
+ )
1553
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1554
+ return
1555
+ else:
1556
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1557
+
1558
+ @LogPerformances
1559
+ def __set_device_reference_config(self, list_references, list_indices):
1560
+ device_channel_reference_list = self.__get_device_reference_config()
1561
+ if len(list_indices) > 0:
1562
+ for i in range(len(list_indices)):
1563
+ if list_indices[i] < len(device_channel_reference_list):
1564
+ device_channel_reference_list[
1565
+ list_indices[i]
1566
+ ].ChanRefStatus = list_references[i]
1567
+ self.__last_error_code = TMSiSetDeviceReferenceConfig(
1568
+ self.__device_handle,
1569
+ pointer(device_channel_reference_list),
1570
+ len(device_channel_reference_list),
1571
+ )
1572
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1573
+ return
1574
+ else:
1575
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1576
+
1577
+ @LogPerformances
1578
+ def __set_device_rtc(self, dt):
1579
+ dev_time = TMSiTime()
1580
+ dev_time.Year = dt.year - 1900
1581
+ dev_time.Month = dt.month - 1
1582
+ dev_time.DayOfMonth = dt.day
1583
+ dev_time.Hours = dt.hour
1584
+ dev_time.Minutes = dt.minute
1585
+ dev_time.Seconds = dt.second
1586
+ self.__last_error_code = TMSiSetDeviceRTC(
1587
+ self.__device_handle, pointer(dev_time)
1588
+ )
1589
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1590
+ return
1591
+ else:
1592
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)
1593
+
1594
+ @LogPerformances
1595
+ def __set_device_sampling_config(
1596
+ self,
1597
+ frequency=TMSiBaseSampleRate.Binary,
1598
+ live_impedance=TMSiLiveImpedance.On,
1599
+ impedance_limit=0,
1600
+ ):
1601
+ device_sampling_config = TMSiDevSamplingCfg()
1602
+ device_sampling_config.BaseSampleRate = frequency.value
1603
+ device_sampling_config.ImpedanceLimit = impedance_limit
1604
+ device_sampling_config.LiveImpedance = live_impedance.value
1605
+ self.__last_error_code = TMSiSetDeviceSamplingConfig(
1606
+ self.__device_handle, pointer(device_sampling_config)
1607
+ )
1608
+ if self.__last_error_code == TMSiDeviceRetVal.TMSiStatusOK:
1609
+ return
1610
+ else:
1611
+ raise TMSiError(TMSiErrorCode.device_error, self.__last_error_code)