biosignal-device-interface 0.2.1a1__py3-none-any.whl → 0.2.2__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.
- biosignal_device_interface/constants/devices/__init__.py +3 -3
- biosignal_device_interface/constants/devices/core/base_device_constants.py +61 -61
- biosignal_device_interface/constants/devices/otb/otb_muovi_constants.py +129 -129
- biosignal_device_interface/constants/devices/otb/otb_quattrocento_constants.py +313 -313
- biosignal_device_interface/constants/devices/otb/otb_quattrocento_light_constants.py +59 -59
- biosignal_device_interface/constants/devices/otb/otb_syncstation_constants.py +233 -233
- biosignal_device_interface/constants/plots/color_palette.py +59 -59
- biosignal_device_interface/devices/__init__.py +17 -17
- biosignal_device_interface/devices/core/base_device.py +424 -412
- biosignal_device_interface/devices/otb/__init__.py +29 -29
- biosignal_device_interface/devices/otb/otb_muovi.py +290 -290
- biosignal_device_interface/devices/otb/otb_quattrocento.py +332 -332
- biosignal_device_interface/devices/otb/otb_quattrocento_light.py +210 -210
- biosignal_device_interface/devices/otb/otb_syncstation.py +407 -407
- biosignal_device_interface/gui/device_template_widgets/all_devices_widget.py +51 -51
- biosignal_device_interface/gui/device_template_widgets/core/base_device_widget.py +130 -130
- biosignal_device_interface/gui/device_template_widgets/core/base_multiple_devices_widget.py +108 -108
- biosignal_device_interface/gui/device_template_widgets/otb/otb_devices_widget.py +44 -44
- biosignal_device_interface/gui/device_template_widgets/otb/otb_muovi_plus_widget.py +158 -158
- biosignal_device_interface/gui/device_template_widgets/otb/otb_muovi_widget.py +158 -158
- biosignal_device_interface/gui/device_template_widgets/otb/otb_quattrocento_light_widget.py +174 -174
- biosignal_device_interface/gui/device_template_widgets/otb/otb_quattrocento_widget.py +260 -260
- biosignal_device_interface/gui/device_template_widgets/otb/otb_syncstation_widget.py +262 -262
- biosignal_device_interface/gui/plot_widgets/biosignal_plot_widget.py +500 -501
- biosignal_device_interface/gui/ui/devices_template_widget.ui +38 -38
- biosignal_device_interface/gui/ui/otb_muovi_plus_template_widget.ui +171 -171
- biosignal_device_interface/gui/ui/otb_muovi_template_widget.ui +171 -171
- biosignal_device_interface/gui/ui/otb_quattrocento_light_template_widget.ui +266 -266
- biosignal_device_interface/gui/ui/otb_quattrocento_template_widget.ui +415 -415
- biosignal_device_interface/gui/ui/otb_syncstation_template_widget.ui +732 -732
- biosignal_device_interface/gui/ui_compiled/devices_template_widget.py +56 -56
- biosignal_device_interface/gui/ui_compiled/otb_muovi_plus_template_widget.py +153 -153
- biosignal_device_interface/gui/ui_compiled/otb_muovi_template_widget.py +153 -153
- biosignal_device_interface/gui/ui_compiled/otb_quattrocento_light_template_widget.py +217 -217
- biosignal_device_interface/gui/ui_compiled/otb_quattrocento_template_widget.py +318 -318
- biosignal_device_interface/gui/ui_compiled/otb_syncstation_template_widget.py +495 -495
- {biosignal_device_interface-0.2.1a1.dist-info → biosignal_device_interface-0.2.2.dist-info}/METADATA +3 -2
- biosignal_device_interface-0.2.2.dist-info/RECORD +46 -0
- {biosignal_device_interface-0.2.1a1.dist-info → biosignal_device_interface-0.2.2.dist-info}/WHEEL +1 -1
- {biosignal_device_interface-0.2.1a1.dist-info → biosignal_device_interface-0.2.2.dist-info/licenses}/LICENSE +675 -675
- biosignal_device_interface-0.2.1a1.dist-info/RECORD +0 -46
|
@@ -1,210 +1,210 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Quattrocento Light class for real-time interface to
|
|
3
|
-
Quattrocento using OT Biolab Light.
|
|
4
|
-
|
|
5
|
-
Developer: Dominik I. Braun
|
|
6
|
-
Contact: dome.braun@fau.de
|
|
7
|
-
Last Update: 2023-06-05
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
# Python Libraries
|
|
11
|
-
from __future__ import annotations
|
|
12
|
-
from typing import TYPE_CHECKING, Union, Dict
|
|
13
|
-
from PySide6.QtNetwork import QTcpSocket, QHostAddress
|
|
14
|
-
from PySide6.QtCore import QIODevice
|
|
15
|
-
import numpy as np
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
from biosignal_device_interface.devices.core.base_device import BaseDevice
|
|
19
|
-
from biosignal_device_interface.constants.devices.core.base_device_constants import (
|
|
20
|
-
DeviceType,
|
|
21
|
-
)
|
|
22
|
-
from biosignal_device_interface.constants.devices.otb.otb_quattrocento_light_constants import (
|
|
23
|
-
COMMAND_START_STREAMING,
|
|
24
|
-
COMMAND_STOP_STREAMING,
|
|
25
|
-
CONNECTION_RESPONSE,
|
|
26
|
-
QUATTROCENTO_LIGHT_STREAMING_FREQUENCY_DICT,
|
|
27
|
-
QUATTROCENTO_SAMPLING_FREQUENCY_DICT,
|
|
28
|
-
QuattrocentoLightSamplingFrequency,
|
|
29
|
-
QuattrocentoLightStreamingFrequency,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if TYPE_CHECKING:
|
|
34
|
-
# Python Libraries
|
|
35
|
-
from PySide6.QtWidgets import QMainWindow, QWidget
|
|
36
|
-
from aenum import Enum
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class OTBQuattrocentoLight(BaseDevice):
|
|
40
|
-
"""
|
|
41
|
-
QuattrocentoLight device class derived from BaseDevice class.
|
|
42
|
-
The QuattrocentoLight is using a TCP/IP protocol to communicate with the device.
|
|
43
|
-
|
|
44
|
-
This class directly interfaces with the OT Biolab Light software from
|
|
45
|
-
OT Bioelettronica. The configured settings of the device have to
|
|
46
|
-
match the settings from the OT Biolab Light software!
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
def __init__(
|
|
50
|
-
self,
|
|
51
|
-
parent: Union[QMainWindow, QWidget] = None,
|
|
52
|
-
) -> None:
|
|
53
|
-
super().__init__(parent)
|
|
54
|
-
|
|
55
|
-
# Device Parameters
|
|
56
|
-
self._device_type: DeviceType = DeviceType.OTB_QUATTROCENTO_LIGHT
|
|
57
|
-
|
|
58
|
-
# Device Information
|
|
59
|
-
self._number_of_channels: int = 408 # Fix value
|
|
60
|
-
self._auxiliary_channel_start_index: int = 384 # Fix value
|
|
61
|
-
self._number_of_auxiliary_channels: int = 16 # Fix value
|
|
62
|
-
self._conversion_factor_biosignal: float = 5 / (2**16) / 150 * 1000 # in mV
|
|
63
|
-
self._conversion_factor_auxiliary: float = 5 / (2**16) / 0.5 # in mV
|
|
64
|
-
self._bytes_per_sample: int = 2 # Fix value
|
|
65
|
-
# Quattrocento unique parameters
|
|
66
|
-
self._streaming_frequency: int | None = None
|
|
67
|
-
|
|
68
|
-
# Connection Parameters
|
|
69
|
-
self._interface: QTcpSocket = QTcpSocket()
|
|
70
|
-
|
|
71
|
-
# Configuration Parameters
|
|
72
|
-
self._grids: list[int] | None = None
|
|
73
|
-
self._grid_size: int = 64 # TODO: This is only valid for the big electrodes
|
|
74
|
-
self._streaming_frequency_mode: QuattrocentoLightStreamingFrequency | None = (
|
|
75
|
-
None
|
|
76
|
-
)
|
|
77
|
-
self._sampling_frequency_mode: QuattrocentoLightSamplingFrequency | None = None
|
|
78
|
-
|
|
79
|
-
def _connect_to_device(self) -> bool:
|
|
80
|
-
super()._connect_to_device()
|
|
81
|
-
|
|
82
|
-
self._received_bytes: bytearray = bytearray()
|
|
83
|
-
return self._make_request()
|
|
84
|
-
|
|
85
|
-
def _make_request(self) -> bool:
|
|
86
|
-
super()._make_request()
|
|
87
|
-
# Signal self.connect_toggled is emitted in _read_data
|
|
88
|
-
self._interface.connectToHost(
|
|
89
|
-
QHostAddress(self._connection_settings[0]),
|
|
90
|
-
self._connection_settings[1],
|
|
91
|
-
QIODevice.ReadWrite,
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
if not self._interface.waitForConnected(1000):
|
|
95
|
-
self._disconnect_from_device()
|
|
96
|
-
return False
|
|
97
|
-
|
|
98
|
-
self._interface.readyRead.connect(self._read_data)
|
|
99
|
-
|
|
100
|
-
return True
|
|
101
|
-
|
|
102
|
-
def _disconnect_from_device(self) -> None:
|
|
103
|
-
super()._disconnect_from_device()
|
|
104
|
-
|
|
105
|
-
self._interface.disconnectFromHost()
|
|
106
|
-
self._interface.readyRead.disconnect(self._read_data)
|
|
107
|
-
self._interface.close()
|
|
108
|
-
|
|
109
|
-
def configure_device(
|
|
110
|
-
self, params: Dict[str, Union[Enum, Dict[str, Enum]]] # type: ignore
|
|
111
|
-
) -> None:
|
|
112
|
-
super().configure_device(params)
|
|
113
|
-
|
|
114
|
-
# Configure the device
|
|
115
|
-
self._number_of_biosignal_channels = len(self._grids) * self._grid_size
|
|
116
|
-
self._biosignal_channel_indices = np.array(
|
|
117
|
-
[
|
|
118
|
-
i * self._grid_size + j
|
|
119
|
-
for i in self._grids
|
|
120
|
-
for j in range(self._grid_size)
|
|
121
|
-
]
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
self._auxiliary_channel_indices = np.array(
|
|
125
|
-
[
|
|
126
|
-
i + self._auxiliary_channel_start_index
|
|
127
|
-
for i in range(self._number_of_auxiliary_channels)
|
|
128
|
-
]
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
self._streaming_frequency = QUATTROCENTO_LIGHT_STREAMING_FREQUENCY_DICT[
|
|
132
|
-
self._streaming_frequency_mode
|
|
133
|
-
]
|
|
134
|
-
self._sampling_frequency = QUATTROCENTO_SAMPLING_FREQUENCY_DICT[
|
|
135
|
-
self._sampling_frequency_mode
|
|
136
|
-
]
|
|
137
|
-
|
|
138
|
-
self._samples_per_frame = self._sampling_frequency // self._streaming_frequency
|
|
139
|
-
|
|
140
|
-
self._buffer_size = (
|
|
141
|
-
self._bytes_per_sample * self._number_of_channels * self._samples_per_frame
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
self._is_configured = True
|
|
145
|
-
self.configure_toggled.emit(True)
|
|
146
|
-
|
|
147
|
-
def _start_streaming(self) -> None:
|
|
148
|
-
super()._start_streaming()
|
|
149
|
-
|
|
150
|
-
self._interface.write(COMMAND_START_STREAMING)
|
|
151
|
-
|
|
152
|
-
def _stop_streaming(self) -> None:
|
|
153
|
-
super()._stop_streaming()
|
|
154
|
-
|
|
155
|
-
self._interface.write(COMMAND_STOP_STREAMING)
|
|
156
|
-
self._interface.waitForBytesWritten(1000)
|
|
157
|
-
|
|
158
|
-
def clear_socket(self) -> None:
|
|
159
|
-
super().clear_socket()
|
|
160
|
-
|
|
161
|
-
self._interface.readAll()
|
|
162
|
-
|
|
163
|
-
def _read_data(self) -> None:
|
|
164
|
-
super()._read_data()
|
|
165
|
-
|
|
166
|
-
# Wait for connection response
|
|
167
|
-
if not self.is_connected and (
|
|
168
|
-
self._interface.bytesAvailable() == len(CONNECTION_RESPONSE)
|
|
169
|
-
and self._interface.readAll() == CONNECTION_RESPONSE
|
|
170
|
-
):
|
|
171
|
-
self.is_connected = True
|
|
172
|
-
self.connect_toggled.emit(True)
|
|
173
|
-
return
|
|
174
|
-
if not self._is_streaming:
|
|
175
|
-
self.clear_socket()
|
|
176
|
-
return
|
|
177
|
-
|
|
178
|
-
while self._interface.bytesAvailable() > self._buffer_size:
|
|
179
|
-
packet = self._interface.read(self._buffer_size)
|
|
180
|
-
if not packet:
|
|
181
|
-
continue
|
|
182
|
-
|
|
183
|
-
self._received_bytes.extend(packet)
|
|
184
|
-
|
|
185
|
-
while len(self._received_bytes) >= self._buffer_size:
|
|
186
|
-
data_to_process = self._received_bytes[: self._buffer_size]
|
|
187
|
-
self._process_data(data_to_process)
|
|
188
|
-
self._received_bytes = self._received_bytes[self._buffer_size :]
|
|
189
|
-
|
|
190
|
-
def _process_data(self, input: bytearray) -> None:
|
|
191
|
-
super()._process_data(input)
|
|
192
|
-
|
|
193
|
-
# Decode the data
|
|
194
|
-
decoded_data = np.frombuffer(input, dtype=np.int16)
|
|
195
|
-
|
|
196
|
-
# Reshape it to the correct format
|
|
197
|
-
processed_data = decoded_data.reshape(
|
|
198
|
-
self._number_of_channels, -1, order="F"
|
|
199
|
-
).astype(np.float32)
|
|
200
|
-
|
|
201
|
-
# Emit the data
|
|
202
|
-
self.data_available.emit(processed_data)
|
|
203
|
-
|
|
204
|
-
biosignal_data = self._extract_biosignal_data(processed_data)
|
|
205
|
-
self.biosignal_data_available.emit(biosignal_data)
|
|
206
|
-
auxiliary_data = self._extract_auxiliary_data(processed_data)
|
|
207
|
-
self.auxiliary_data_available.emit(auxiliary_data)
|
|
208
|
-
|
|
209
|
-
def get_device_information(self) -> Dict[str, Enum | int | float | str]: # type: ignore
|
|
210
|
-
return super().get_device_information()
|
|
1
|
+
"""
|
|
2
|
+
Quattrocento Light class for real-time interface to
|
|
3
|
+
Quattrocento using OT Biolab Light.
|
|
4
|
+
|
|
5
|
+
Developer: Dominik I. Braun
|
|
6
|
+
Contact: dome.braun@fau.de
|
|
7
|
+
Last Update: 2023-06-05
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Python Libraries
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
from typing import TYPE_CHECKING, Union, Dict
|
|
13
|
+
from PySide6.QtNetwork import QTcpSocket, QHostAddress
|
|
14
|
+
from PySide6.QtCore import QIODevice
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from biosignal_device_interface.devices.core.base_device import BaseDevice
|
|
19
|
+
from biosignal_device_interface.constants.devices.core.base_device_constants import (
|
|
20
|
+
DeviceType,
|
|
21
|
+
)
|
|
22
|
+
from biosignal_device_interface.constants.devices.otb.otb_quattrocento_light_constants import (
|
|
23
|
+
COMMAND_START_STREAMING,
|
|
24
|
+
COMMAND_STOP_STREAMING,
|
|
25
|
+
CONNECTION_RESPONSE,
|
|
26
|
+
QUATTROCENTO_LIGHT_STREAMING_FREQUENCY_DICT,
|
|
27
|
+
QUATTROCENTO_SAMPLING_FREQUENCY_DICT,
|
|
28
|
+
QuattrocentoLightSamplingFrequency,
|
|
29
|
+
QuattrocentoLightStreamingFrequency,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
# Python Libraries
|
|
35
|
+
from PySide6.QtWidgets import QMainWindow, QWidget
|
|
36
|
+
from aenum import Enum
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class OTBQuattrocentoLight(BaseDevice):
|
|
40
|
+
"""
|
|
41
|
+
QuattrocentoLight device class derived from BaseDevice class.
|
|
42
|
+
The QuattrocentoLight is using a TCP/IP protocol to communicate with the device.
|
|
43
|
+
|
|
44
|
+
This class directly interfaces with the OT Biolab Light software from
|
|
45
|
+
OT Bioelettronica. The configured settings of the device have to
|
|
46
|
+
match the settings from the OT Biolab Light software!
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
parent: Union[QMainWindow, QWidget] = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
super().__init__(parent)
|
|
54
|
+
|
|
55
|
+
# Device Parameters
|
|
56
|
+
self._device_type: DeviceType = DeviceType.OTB_QUATTROCENTO_LIGHT
|
|
57
|
+
|
|
58
|
+
# Device Information
|
|
59
|
+
self._number_of_channels: int = 408 # Fix value
|
|
60
|
+
self._auxiliary_channel_start_index: int = 384 # Fix value
|
|
61
|
+
self._number_of_auxiliary_channels: int = 16 # Fix value
|
|
62
|
+
self._conversion_factor_biosignal: float = 5 / (2**16) / 150 * 1000 # in mV
|
|
63
|
+
self._conversion_factor_auxiliary: float = 5 / (2**16) / 0.5 # in mV
|
|
64
|
+
self._bytes_per_sample: int = 2 # Fix value
|
|
65
|
+
# Quattrocento unique parameters
|
|
66
|
+
self._streaming_frequency: int | None = None
|
|
67
|
+
|
|
68
|
+
# Connection Parameters
|
|
69
|
+
self._interface: QTcpSocket = QTcpSocket()
|
|
70
|
+
|
|
71
|
+
# Configuration Parameters
|
|
72
|
+
self._grids: list[int] | None = None
|
|
73
|
+
self._grid_size: int = 64 # TODO: This is only valid for the big electrodes
|
|
74
|
+
self._streaming_frequency_mode: QuattrocentoLightStreamingFrequency | None = (
|
|
75
|
+
None
|
|
76
|
+
)
|
|
77
|
+
self._sampling_frequency_mode: QuattrocentoLightSamplingFrequency | None = None
|
|
78
|
+
|
|
79
|
+
def _connect_to_device(self) -> bool:
|
|
80
|
+
super()._connect_to_device()
|
|
81
|
+
|
|
82
|
+
self._received_bytes: bytearray = bytearray()
|
|
83
|
+
return self._make_request()
|
|
84
|
+
|
|
85
|
+
def _make_request(self) -> bool:
|
|
86
|
+
super()._make_request()
|
|
87
|
+
# Signal self.connect_toggled is emitted in _read_data
|
|
88
|
+
self._interface.connectToHost(
|
|
89
|
+
QHostAddress(self._connection_settings[0]),
|
|
90
|
+
self._connection_settings[1],
|
|
91
|
+
QIODevice.ReadWrite,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if not self._interface.waitForConnected(1000):
|
|
95
|
+
self._disconnect_from_device()
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
self._interface.readyRead.connect(self._read_data)
|
|
99
|
+
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
def _disconnect_from_device(self) -> None:
|
|
103
|
+
super()._disconnect_from_device()
|
|
104
|
+
|
|
105
|
+
self._interface.disconnectFromHost()
|
|
106
|
+
self._interface.readyRead.disconnect(self._read_data)
|
|
107
|
+
self._interface.close()
|
|
108
|
+
|
|
109
|
+
def configure_device(
|
|
110
|
+
self, params: Dict[str, Union[Enum, Dict[str, Enum]]] # type: ignore
|
|
111
|
+
) -> None:
|
|
112
|
+
super().configure_device(params)
|
|
113
|
+
|
|
114
|
+
# Configure the device
|
|
115
|
+
self._number_of_biosignal_channels = len(self._grids) * self._grid_size
|
|
116
|
+
self._biosignal_channel_indices = np.array(
|
|
117
|
+
[
|
|
118
|
+
i * self._grid_size + j
|
|
119
|
+
for i in self._grids
|
|
120
|
+
for j in range(self._grid_size)
|
|
121
|
+
]
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
self._auxiliary_channel_indices = np.array(
|
|
125
|
+
[
|
|
126
|
+
i + self._auxiliary_channel_start_index
|
|
127
|
+
for i in range(self._number_of_auxiliary_channels)
|
|
128
|
+
]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
self._streaming_frequency = QUATTROCENTO_LIGHT_STREAMING_FREQUENCY_DICT[
|
|
132
|
+
self._streaming_frequency_mode
|
|
133
|
+
]
|
|
134
|
+
self._sampling_frequency = QUATTROCENTO_SAMPLING_FREQUENCY_DICT[
|
|
135
|
+
self._sampling_frequency_mode
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
self._samples_per_frame = self._sampling_frequency // self._streaming_frequency
|
|
139
|
+
|
|
140
|
+
self._buffer_size = (
|
|
141
|
+
self._bytes_per_sample * self._number_of_channels * self._samples_per_frame
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
self._is_configured = True
|
|
145
|
+
self.configure_toggled.emit(True)
|
|
146
|
+
|
|
147
|
+
def _start_streaming(self) -> None:
|
|
148
|
+
super()._start_streaming()
|
|
149
|
+
|
|
150
|
+
self._interface.write(COMMAND_START_STREAMING)
|
|
151
|
+
|
|
152
|
+
def _stop_streaming(self) -> None:
|
|
153
|
+
super()._stop_streaming()
|
|
154
|
+
|
|
155
|
+
self._interface.write(COMMAND_STOP_STREAMING)
|
|
156
|
+
self._interface.waitForBytesWritten(1000)
|
|
157
|
+
|
|
158
|
+
def clear_socket(self) -> None:
|
|
159
|
+
super().clear_socket()
|
|
160
|
+
|
|
161
|
+
self._interface.readAll()
|
|
162
|
+
|
|
163
|
+
def _read_data(self) -> None:
|
|
164
|
+
super()._read_data()
|
|
165
|
+
|
|
166
|
+
# Wait for connection response
|
|
167
|
+
if not self.is_connected and (
|
|
168
|
+
self._interface.bytesAvailable() == len(CONNECTION_RESPONSE)
|
|
169
|
+
and self._interface.readAll() == CONNECTION_RESPONSE
|
|
170
|
+
):
|
|
171
|
+
self.is_connected = True
|
|
172
|
+
self.connect_toggled.emit(True)
|
|
173
|
+
return
|
|
174
|
+
if not self._is_streaming:
|
|
175
|
+
self.clear_socket()
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
while self._interface.bytesAvailable() > self._buffer_size:
|
|
179
|
+
packet = self._interface.read(self._buffer_size)
|
|
180
|
+
if not packet:
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
self._received_bytes.extend(packet)
|
|
184
|
+
|
|
185
|
+
while len(self._received_bytes) >= self._buffer_size:
|
|
186
|
+
data_to_process = self._received_bytes[: self._buffer_size]
|
|
187
|
+
self._process_data(data_to_process)
|
|
188
|
+
self._received_bytes = self._received_bytes[self._buffer_size :]
|
|
189
|
+
|
|
190
|
+
def _process_data(self, input: bytearray) -> None:
|
|
191
|
+
super()._process_data(input)
|
|
192
|
+
|
|
193
|
+
# Decode the data
|
|
194
|
+
decoded_data = np.frombuffer(input, dtype=np.int16)
|
|
195
|
+
|
|
196
|
+
# Reshape it to the correct format
|
|
197
|
+
processed_data = decoded_data.reshape(
|
|
198
|
+
self._number_of_channels, -1, order="F"
|
|
199
|
+
).astype(np.float32)
|
|
200
|
+
|
|
201
|
+
# Emit the data
|
|
202
|
+
self.data_available.emit(processed_data)
|
|
203
|
+
|
|
204
|
+
biosignal_data = self._extract_biosignal_data(processed_data)
|
|
205
|
+
self.biosignal_data_available.emit(biosignal_data)
|
|
206
|
+
auxiliary_data = self._extract_auxiliary_data(processed_data)
|
|
207
|
+
self.auxiliary_data_available.emit(auxiliary_data)
|
|
208
|
+
|
|
209
|
+
def get_device_information(self) -> Dict[str, Enum | int | float | str]: # type: ignore
|
|
210
|
+
return super().get_device_information()
|