biosignal-device-interface 0.2.4__py3-none-any.whl → 0.2.6__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.
@@ -22,6 +22,9 @@ from biosignal_device_interface.gui.device_template_widgets.otb.otb_quattrocento
22
22
  from biosignal_device_interface.gui.device_template_widgets.otb.otb_syncstation_widget import (
23
23
  OTBSyncStationWidget,
24
24
  )
25
+ from biosignal_device_interface.gui.device_template_widgets.otb.otb_sessantaquattro_widget import (
26
+ OTBSessantaquattroWidget,
27
+ )
25
28
 
26
29
  if TYPE_CHECKING:
27
30
  from PySide6.QtWidgets import QWidget, QMainWindow
@@ -40,5 +43,6 @@ class OTBDevicesWidget(BaseMultipleDevicesWidget):
40
43
  DeviceType.OTB_MUOVI: OTBMuoviWidget(self),
41
44
  DeviceType.OTB_MUOVI_PLUS: OTBMuoviPlusWidget(self),
42
45
  DeviceType.OTB_SYNCSTATION: OTBSyncStationWidget(self),
46
+ DeviceType.OTB_SESSANTAQUATTRO: OTBSessantaquattroWidget(self),
43
47
  }
44
48
  self._set_devices(self._device_selection)
@@ -0,0 +1,265 @@
1
+ """
2
+ Sessantaquattro Widget class for GUI configuration
3
+ of the Sessantaquattro from OT Bioelettronica.
4
+
5
+ Developer: Dominik I. Braun
6
+ Contact: dome.braun@fau.de
7
+ Last Update: 2026-02-01
8
+ """
9
+
10
+ from __future__ import annotations
11
+ from functools import partial
12
+ from typing import TYPE_CHECKING
13
+
14
+ from biosignal_device_interface.gui.device_template_widgets.core.base_device_widget import (
15
+ BaseDeviceWidget,
16
+ )
17
+ from biosignal_device_interface.gui.ui_compiled.otb_sessantaquattro_template_widget import (
18
+ Ui_SessantaquattroForm,
19
+ )
20
+ from biosignal_device_interface.devices.otb.otb_sessantaquattro import (
21
+ OTBSessantaquattro,
22
+ )
23
+
24
+ # Constants
25
+ from biosignal_device_interface.constants.devices.otb.otb_sessantaquattro_constants import (
26
+ SessantaquattroChannelMode,
27
+ SessantaquattroDetectionMode,
28
+ SessantaquattroGainMode,
29
+ SessantaquattroRecordingMode,
30
+ SessantaquattroResolutionMode,
31
+ SessantaquattroSamplingFrequencyMode,
32
+ SessantaquattroTriggerMode,
33
+ )
34
+
35
+ if TYPE_CHECKING:
36
+ from PySide6.QtWidgets import (
37
+ QWidget,
38
+ QMainWindow,
39
+ QGroupBox,
40
+ QPushButton,
41
+ QComboBox,
42
+ QRadioButton,
43
+ QLineEdit,
44
+ )
45
+
46
+
47
+ class OTBSessantaquattroWidget(BaseDeviceWidget):
48
+ def __init__(self, parent: QWidget | QMainWindow | None = None):
49
+ super().__init__(parent)
50
+
51
+ self._set_device(OTBSessantaquattro(parent=self))
52
+
53
+ def _toggle_connection(self) -> None:
54
+ if not self._device.is_connected:
55
+ self._connect_push_button.setEnabled(False)
56
+
57
+ self._device.toggle_connection(
58
+ (
59
+ self._connection_ip_line_edit.text(),
60
+ int(self._connection_port_line_edit.text()),
61
+ )
62
+ )
63
+
64
+ def _connection_toggled(self, is_connected: bool) -> None:
65
+ self._connect_push_button.setEnabled(True)
66
+ if is_connected:
67
+ self._connect_push_button.setText("Disconnect")
68
+ self._connect_push_button.setChecked(True)
69
+ self._configure_push_button.setEnabled(True)
70
+ self._configure_push_button.setToolTip("Step 2: Configure device settings")
71
+ self._connection_group_box.setEnabled(False)
72
+ else:
73
+ self._connect_push_button.setText("Connect")
74
+ self._connect_push_button.setChecked(False)
75
+ self._configure_push_button.setEnabled(False)
76
+ self._configure_push_button.setToolTip(
77
+ "Step 2: Configure device settings (connect first)"
78
+ )
79
+ self._stream_push_button.setEnabled(False)
80
+ self._stream_push_button.setToolTip(
81
+ "Step 3: Start data streaming (configure first)"
82
+ )
83
+ self._connection_group_box.setEnabled(True)
84
+
85
+ self.connect_toggled.emit(is_connected)
86
+
87
+ def _toggle_configuration(self) -> None:
88
+ self._update_device_params()
89
+
90
+ self._device.configure_device(self._device_params)
91
+
92
+ def _configuration_toggled(self, is_configured: bool) -> None:
93
+ if is_configured:
94
+ self._stream_push_button.setEnabled(True)
95
+ self._stream_push_button.setToolTip("Step 3: Start data streaming")
96
+
97
+ self.configure_toggled.emit(is_configured)
98
+
99
+ def _toggle_configuration_group_boxes(self) -> None:
100
+ for group_box in self._configuration_group_boxes:
101
+ group_box.setEnabled(not group_box.isEnabled())
102
+
103
+ def _toggle_stream(self) -> None:
104
+ self._stream_push_button.setEnabled(False)
105
+ self._device.toggle_streaming()
106
+
107
+ def _stream_toggled(self, is_streaming: bool) -> None:
108
+ self._stream_push_button.setEnabled(True)
109
+ if is_streaming:
110
+ self._stream_push_button.setText("Stop Streaming")
111
+ self._stream_push_button.setChecked(True)
112
+ self._configure_push_button.setEnabled(False)
113
+ self._toggle_configuration_group_boxes()
114
+ else:
115
+ self._stream_push_button.setText("Stream")
116
+ self._stream_push_button.setChecked(False)
117
+ self._configure_push_button.setEnabled(True)
118
+ self._toggle_configuration_group_boxes()
119
+
120
+ self.stream_toggled.emit(is_streaming)
121
+
122
+ def _update_device_params(self) -> None:
123
+ self._device_params = {
124
+ "sampling_frequency_mode": SessantaquattroSamplingFrequencyMode(
125
+ self._get_enum_value(
126
+ self._acquisition_sampling_frequency_mode_combo_box
127
+ )
128
+ ),
129
+ "channel_mode": SessantaquattroChannelMode(
130
+ self._get_enum_value(self._acquisition_channel_mode_combo_box)
131
+ ),
132
+ "detection_mode": SessantaquattroDetectionMode(
133
+ self._get_enum_value(self._input_detection_mode_combo_box)
134
+ ),
135
+ "resolution_mode": SessantaquattroResolutionMode(
136
+ self._get_resolution_mode()
137
+ ),
138
+ "gain_mode": SessantaquattroGainMode(
139
+ self._get_enum_value(self._input_gain_mode_combo_box)
140
+ ),
141
+ "trigger_mode": SessantaquattroTriggerMode.DEFAULT,
142
+ "recording_mode": SessantaquattroRecordingMode.STOP,
143
+ }
144
+
145
+ def _initialize_device_params(self) -> None:
146
+ self._device_params = {
147
+ "sampling_frequency_mode": SessantaquattroSamplingFrequencyMode.NONE,
148
+ "channel_mode": SessantaquattroChannelMode.NONE,
149
+ "detection_mode": SessantaquattroDetectionMode.NONE,
150
+ "resolution_mode": SessantaquattroResolutionMode.NONE,
151
+ "gain_mode": SessantaquattroGainMode.NONE,
152
+ "trigger_mode": SessantaquattroTriggerMode.NONE,
153
+ "recording_mode": SessantaquattroRecordingMode.NONE,
154
+ }
155
+
156
+ def _get_enum_value(self, combo_box: QComboBox) -> int | None:
157
+ index = combo_box.currentIndex()
158
+ return index + 1
159
+
160
+ def _get_resolution_mode(self) -> SessantaquattroResolutionMode:
161
+ if self._input_high_resolution_mode_combo_box.isChecked():
162
+ return SessantaquattroResolutionMode.HIGH
163
+ else:
164
+ return SessantaquattroResolutionMode.LOW
165
+
166
+ def _initialize_ui(self) -> None:
167
+ self.ui = Ui_SessantaquattroForm()
168
+ self.ui.setupUi(self)
169
+
170
+ # Command Push Buttons
171
+ self._connect_push_button: QPushButton = self.ui.commandConnectionPushButton
172
+ self._connect_push_button.clicked.connect(self._toggle_connection)
173
+ self._connect_push_button.setToolTip(
174
+ "Step 1: Connect to the Sessantaquattro device"
175
+ )
176
+ self._device.connect_toggled.connect(self._connection_toggled)
177
+
178
+ self._configure_push_button: QPushButton = (
179
+ self.ui.commandConfigurationPushButton
180
+ )
181
+ self._configure_push_button.clicked.connect(self._toggle_configuration)
182
+ self._configure_push_button.setEnabled(False)
183
+ self._configure_push_button.setToolTip(
184
+ "Step 2: Configure device settings (connect first)"
185
+ )
186
+ self._device.configure_toggled.connect(self._configuration_toggled)
187
+
188
+ self._stream_push_button: QPushButton = self.ui.commandStreamPushButton
189
+ self._stream_push_button.clicked.connect(self._toggle_stream)
190
+ self._stream_push_button.setEnabled(False)
191
+ self._stream_push_button.setToolTip(
192
+ "Step 3: Start data streaming (configure first)"
193
+ )
194
+ self._device.stream_toggled.connect(self._stream_toggled)
195
+
196
+ # Connection parameters
197
+ self._connection_group_box: QGroupBox = self.ui.connectionGroupBox
198
+ self._connection_ip_line_edit: QLineEdit = self.ui.connectionIPLineEdit
199
+ self._default_connection_ip: str = self._connection_ip_line_edit.text()
200
+ self._connection_ip_line_edit.editingFinished.connect(
201
+ partial(
202
+ self._check_ip_input,
203
+ self._connection_ip_line_edit,
204
+ self._default_connection_ip,
205
+ )
206
+ )
207
+ self._connection_port_line_edit: QLineEdit = self.ui.connectionPortLineEdit
208
+ self._default_connection_port: str = self._connection_port_line_edit.text()
209
+ self._connection_port_line_edit.editingFinished.connect(
210
+ partial(
211
+ self._check_port_input,
212
+ self._connection_port_line_edit,
213
+ self._default_connection_port,
214
+ )
215
+ )
216
+
217
+ # Acquisition parameters
218
+ self._acquisition_group_box: QGroupBox = self.ui.acquisitionGroupBox
219
+ self._acquisition_sampling_frequency_mode_combo_box: QComboBox = (
220
+ self.ui.acquisitionSamplingFrequencyModeComboBox
221
+ )
222
+ self._acquisition_sampling_frequency_mode_combo_box.setToolTip(
223
+ "Higher frequencies capture more detail but generate more data"
224
+ )
225
+ self._acquisition_channel_mode_combo_box: QComboBox = (
226
+ self.ui.acquisitionChannelModeComboBox
227
+ )
228
+ self._acquisition_channel_mode_combo_box.setToolTip(
229
+ "Number of channels to acquire from the device"
230
+ )
231
+
232
+ # Input parameters
233
+ self._input_parameters_group_box: QGroupBox = self.ui.inputParametersGroupBox
234
+ self._input_low_resolution_mode_combo_box: QRadioButton = (
235
+ self.ui.inputLowResolutionRadioButton
236
+ )
237
+ self._input_low_resolution_mode_combo_box.setToolTip(
238
+ "Low resolution: Lower data rate"
239
+ )
240
+ self._input_high_resolution_mode_combo_box: QRadioButton = (
241
+ self.ui.inputHighResolutionRadioButton
242
+ )
243
+ self._input_high_resolution_mode_combo_box.setToolTip(
244
+ "High resolution: Better signal quality"
245
+ )
246
+ self._input_detection_mode_combo_box: QComboBox = (
247
+ self.ui.inputDetectionModeComboBox
248
+ )
249
+ self._input_detection_mode_combo_box.setToolTip(
250
+ "Monopolar: Each electrode vs reference\n"
251
+ "Differential: Difference between adjacent electrodes"
252
+ )
253
+ self._input_gain_mode_combo_box: QComboBox = self.ui.inputGainModeComboBox
254
+ self._input_gain_mode_combo_box.setToolTip(
255
+ "Amplification factor for the input signal"
256
+ )
257
+ self._input_detection_mode_combo_box: QComboBox = (
258
+ self.ui.inputDetectionModeComboBox
259
+ )
260
+
261
+ # Configuration parameters
262
+ self._configuration_group_boxes: list[QGroupBox] = [
263
+ self._input_parameters_group_box,
264
+ self._acquisition_group_box,
265
+ ]
@@ -0,0 +1,317 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>SessantaquattroForm</class>
4
+ <widget class="QWidget" name="SessantaquattroForm">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>340</width>
10
+ <height>486</height>
11
+ </rect>
12
+ </property>
13
+ <property name="minimumSize">
14
+ <size>
15
+ <width>0</width>
16
+ <height>400</height>
17
+ </size>
18
+ </property>
19
+ <property name="maximumSize">
20
+ <size>
21
+ <width>340</width>
22
+ <height>16777215</height>
23
+ </size>
24
+ </property>
25
+ <property name="windowTitle">
26
+ <string>Form</string>
27
+ </property>
28
+ <layout class="QGridLayout" name="gridLayout_2">
29
+ <item row="0" column="0">
30
+ <widget class="QWidget" name="widget" native="true">
31
+ <layout class="QGridLayout" name="gridLayout_5">
32
+ <item row="2" column="0">
33
+ <widget class="QGroupBox" name="inputParametersGroupBox">
34
+ <property name="title">
35
+ <string>Input Parameters</string>
36
+ </property>
37
+ <layout class="QGridLayout" name="gridLayout_4">
38
+ <item row="2" column="0">
39
+ <widget class="QLabel" name="label_10">
40
+ <property name="text">
41
+ <string>Mode</string>
42
+ </property>
43
+ </widget>
44
+ </item>
45
+ <item row="2" column="1">
46
+ <widget class="QComboBox" name="inputDetectionModeComboBox">
47
+ <item>
48
+ <property name="text">
49
+ <string>Monopolar</string>
50
+ </property>
51
+ </item>
52
+ <item>
53
+ <property name="text">
54
+ <string>Bipolar</string>
55
+ </property>
56
+ </item>
57
+ <item>
58
+ <property name="text">
59
+ <string>Differential</string>
60
+ </property>
61
+ </item>
62
+ <item>
63
+ <property name="text">
64
+ <string>Accelerometer</string>
65
+ </property>
66
+ </item>
67
+ <item>
68
+ <property name="text">
69
+ <string>Undefined</string>
70
+ </property>
71
+ </item>
72
+ <item>
73
+ <property name="text">
74
+ <string>Impedance (Advanced)</string>
75
+ </property>
76
+ </item>
77
+ <item>
78
+ <property name="text">
79
+ <string>Impedance</string>
80
+ </property>
81
+ </item>
82
+ <item>
83
+ <property name="text">
84
+ <string>Test</string>
85
+ </property>
86
+ </item>
87
+ </widget>
88
+ </item>
89
+ <item row="1" column="0">
90
+ <widget class="QRadioButton" name="inputLowResolutionRadioButton">
91
+ <property name="text">
92
+ <string>16 Bit</string>
93
+ </property>
94
+ <property name="checked">
95
+ <bool>true</bool>
96
+ </property>
97
+ </widget>
98
+ </item>
99
+ <item row="0" column="0" colspan="2">
100
+ <widget class="QLabel" name="label_4">
101
+ <property name="sizePolicy">
102
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
103
+ <horstretch>0</horstretch>
104
+ <verstretch>0</verstretch>
105
+ </sizepolicy>
106
+ </property>
107
+ <property name="text">
108
+ <string>Resolution</string>
109
+ </property>
110
+ </widget>
111
+ </item>
112
+ <item row="1" column="1">
113
+ <widget class="QRadioButton" name="inputHighResolutionRadioButton">
114
+ <property name="text">
115
+ <string>24 Bit</string>
116
+ </property>
117
+ </widget>
118
+ </item>
119
+ <item row="3" column="0">
120
+ <widget class="QLabel" name="label_5">
121
+ <property name="text">
122
+ <string>Gain</string>
123
+ </property>
124
+ </widget>
125
+ </item>
126
+ <item row="3" column="1">
127
+ <widget class="QComboBox" name="inputGainModeComboBox">
128
+ <item>
129
+ <property name="text">
130
+ <string>Default</string>
131
+ </property>
132
+ </item>
133
+ <item>
134
+ <property name="text">
135
+ <string>Gain 4</string>
136
+ </property>
137
+ </item>
138
+ <item>
139
+ <property name="text">
140
+ <string>Gain 6</string>
141
+ </property>
142
+ </item>
143
+ <item>
144
+ <property name="text">
145
+ <string>Gain 8</string>
146
+ </property>
147
+ </item>
148
+ </widget>
149
+ </item>
150
+ </layout>
151
+ </widget>
152
+ </item>
153
+ <item row="3" column="0">
154
+ <widget class="QGroupBox" name="commandsGroupBox">
155
+ <property name="title">
156
+ <string>Commands</string>
157
+ </property>
158
+ <layout class="QGridLayout" name="gridLayout_3">
159
+ <item row="0" column="0">
160
+ <widget class="QPushButton" name="commandConnectionPushButton">
161
+ <property name="text">
162
+ <string>Connect</string>
163
+ </property>
164
+ </widget>
165
+ </item>
166
+ <item row="1" column="0">
167
+ <widget class="QPushButton" name="commandConfigurationPushButton">
168
+ <property name="text">
169
+ <string>Configure</string>
170
+ </property>
171
+ </widget>
172
+ </item>
173
+ <item row="2" column="0">
174
+ <widget class="QPushButton" name="commandStreamPushButton">
175
+ <property name="text">
176
+ <string>Stream</string>
177
+ </property>
178
+ </widget>
179
+ </item>
180
+ </layout>
181
+ </widget>
182
+ </item>
183
+ <item row="1" column="0">
184
+ <widget class="QGroupBox" name="acquisitionGroupBox">
185
+ <property name="title">
186
+ <string>Acquisiton Parameters</string>
187
+ </property>
188
+ <layout class="QGridLayout" name="gridLayout">
189
+ <item row="1" column="0">
190
+ <widget class="QLabel" name="label_2">
191
+ <property name="text">
192
+ <string>Number of Channels</string>
193
+ </property>
194
+ </widget>
195
+ </item>
196
+ <item row="0" column="1">
197
+ <widget class="QComboBox" name="acquisitionSamplingFrequencyModeComboBox">
198
+ <property name="currentIndex">
199
+ <number>2</number>
200
+ </property>
201
+ <item>
202
+ <property name="text">
203
+ <string>500</string>
204
+ </property>
205
+ </item>
206
+ <item>
207
+ <property name="text">
208
+ <string>1000</string>
209
+ </property>
210
+ </item>
211
+ <item>
212
+ <property name="text">
213
+ <string>2000</string>
214
+ </property>
215
+ </item>
216
+ <item>
217
+ <property name="text">
218
+ <string>4000</string>
219
+ </property>
220
+ </item>
221
+ </widget>
222
+ </item>
223
+ <item row="1" column="1">
224
+ <widget class="QComboBox" name="acquisitionChannelModeComboBox">
225
+ <property name="currentIndex">
226
+ <number>3</number>
227
+ </property>
228
+ <item>
229
+ <property name="text">
230
+ <string>8 Bio + 2 AUX + 2 ACC</string>
231
+ </property>
232
+ </item>
233
+ <item>
234
+ <property name="text">
235
+ <string>16 Bio + 2 AUX + 2 ACC</string>
236
+ </property>
237
+ </item>
238
+ <item>
239
+ <property name="text">
240
+ <string>32 Bio + 2 AUX + 2 ACC</string>
241
+ </property>
242
+ </item>
243
+ <item>
244
+ <property name="text">
245
+ <string>64 Bio + 2 AUX + 2 ACC</string>
246
+ </property>
247
+ </item>
248
+ </widget>
249
+ </item>
250
+ <item row="0" column="0">
251
+ <widget class="QLabel" name="label">
252
+ <property name="text">
253
+ <string>Sampling Frequency</string>
254
+ </property>
255
+ </widget>
256
+ </item>
257
+ </layout>
258
+ </widget>
259
+ </item>
260
+ <item row="0" column="0">
261
+ <widget class="QGroupBox" name="connectionGroupBox">
262
+ <property name="title">
263
+ <string>Connection parameters</string>
264
+ </property>
265
+ <layout class="QGridLayout" name="gridLayout_7">
266
+ <item row="0" column="0">
267
+ <widget class="QLabel" name="label_6">
268
+ <property name="text">
269
+ <string>IP</string>
270
+ </property>
271
+ </widget>
272
+ </item>
273
+ <item row="0" column="1">
274
+ <widget class="QLineEdit" name="connectionIPLineEdit">
275
+ <property name="text">
276
+ <string>0.0.0.0</string>
277
+ </property>
278
+ </widget>
279
+ </item>
280
+ <item row="1" column="0">
281
+ <widget class="QLabel" name="label_7">
282
+ <property name="text">
283
+ <string>Port</string>
284
+ </property>
285
+ </widget>
286
+ </item>
287
+ <item row="1" column="1">
288
+ <widget class="QLineEdit" name="connectionPortLineEdit">
289
+ <property name="text">
290
+ <string>45454</string>
291
+ </property>
292
+ </widget>
293
+ </item>
294
+ </layout>
295
+ </widget>
296
+ </item>
297
+ </layout>
298
+ </widget>
299
+ </item>
300
+ <item row="1" column="0">
301
+ <spacer name="verticalSpacer">
302
+ <property name="orientation">
303
+ <enum>Qt::Vertical</enum>
304
+ </property>
305
+ <property name="sizeHint" stdset="0">
306
+ <size>
307
+ <width>20</width>
308
+ <height>40</height>
309
+ </size>
310
+ </property>
311
+ </spacer>
312
+ </item>
313
+ </layout>
314
+ </widget>
315
+ <resources/>
316
+ <connections/>
317
+ </ui>