horiba-sdk 0.5.2__py3-none-any.whl → 0.6.0__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.
- horiba_sdk/communication/messages.py +5 -2
- horiba_sdk/communication/websocket_communicator.py +1 -1
- horiba_sdk/core/stitching/__init__.py +6 -0
- horiba_sdk/core/stitching/labspec6_spectra_stitch.py +90 -0
- horiba_sdk/core/stitching/linear_spectra_stitch.py +107 -0
- horiba_sdk/core/stitching/simple_cut_spectra_stitch.py +84 -0
- horiba_sdk/core/stitching/spectra_stitch.py +16 -0
- horiba_sdk/core/stitching/y_displacement_spectra_stitch.py +87 -0
- horiba_sdk/core/trigger_input_polarity.py +6 -0
- horiba_sdk/devices/device_manager.py +19 -1
- horiba_sdk/devices/fake_icl_server.py +7 -0
- horiba_sdk/devices/fake_responses/spectracq3.json +217 -0
- horiba_sdk/devices/single_devices/__init__.py +2 -1
- horiba_sdk/devices/single_devices/ccd.py +4 -2
- horiba_sdk/devices/single_devices/spectracq3.py +392 -0
- horiba_sdk/devices/spectracq3_discovery.py +55 -0
- {horiba_sdk-0.5.2.dist-info → horiba_sdk-0.6.0.dist-info}/METADATA +3 -1
- {horiba_sdk-0.5.2.dist-info → horiba_sdk-0.6.0.dist-info}/RECORD +20 -26
- horiba_sdk/sync/__init__.py +0 -0
- horiba_sdk/sync/communication/__init__.py +0 -7
- horiba_sdk/sync/communication/abstract_communicator.py +0 -47
- horiba_sdk/sync/communication/test_client.py +0 -16
- horiba_sdk/sync/communication/websocket_communicator.py +0 -232
- horiba_sdk/sync/devices/__init__.py +0 -15
- horiba_sdk/sync/devices/abstract_device_discovery.py +0 -17
- horiba_sdk/sync/devices/abstract_device_manager.py +0 -68
- horiba_sdk/sync/devices/device_discovery.py +0 -58
- horiba_sdk/sync/devices/device_manager.py +0 -213
- horiba_sdk/sync/devices/fake_device_manager.py +0 -91
- horiba_sdk/sync/devices/fake_icl_server.py +0 -82
- horiba_sdk/sync/devices/single_devices/__init__.py +0 -5
- horiba_sdk/sync/devices/single_devices/abstract_device.py +0 -87
- horiba_sdk/sync/devices/single_devices/ccd.py +0 -674
- horiba_sdk/sync/devices/single_devices/monochromator.py +0 -413
- {horiba_sdk-0.5.2.dist-info → horiba_sdk-0.6.0.dist-info}/LICENSE +0 -0
- {horiba_sdk-0.5.2.dist-info → horiba_sdk-0.6.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,217 @@
|
|
1
|
+
{
|
2
|
+
"saq3_discover": {
|
3
|
+
"id": 1234,
|
4
|
+
"command": "saq3_discover",
|
5
|
+
"results": {
|
6
|
+
"count": 1
|
7
|
+
},
|
8
|
+
"errors": []
|
9
|
+
},
|
10
|
+
"saq3_list": {
|
11
|
+
"id": 1234,
|
12
|
+
"command": "saq3_list",
|
13
|
+
"results": {
|
14
|
+
"devices": [
|
15
|
+
{
|
16
|
+
"deviceType": "SpectrAcq3",
|
17
|
+
"index": 0,
|
18
|
+
"serialNumber": "SAQ3-2025-001"
|
19
|
+
}
|
20
|
+
]
|
21
|
+
},
|
22
|
+
"errors": []
|
23
|
+
},
|
24
|
+
"saq3_listCount": {
|
25
|
+
"id": 1234,
|
26
|
+
"command": "saq3_listCount",
|
27
|
+
"results": {
|
28
|
+
"count": 1
|
29
|
+
},
|
30
|
+
"errors": []
|
31
|
+
},
|
32
|
+
"saq3_open": {
|
33
|
+
"id": 1234,
|
34
|
+
"command": "saq3_open",
|
35
|
+
"errors": []
|
36
|
+
},
|
37
|
+
"saq3_close": {
|
38
|
+
"id": 1234,
|
39
|
+
"command": "saq3_close",
|
40
|
+
"errors": []
|
41
|
+
},
|
42
|
+
"saq3_isOpen": {
|
43
|
+
"id": 1234,
|
44
|
+
"command": "saq3_isOpen",
|
45
|
+
"results": {
|
46
|
+
"open": true
|
47
|
+
},
|
48
|
+
"errors": []
|
49
|
+
},
|
50
|
+
"saq3_isBusy": {
|
51
|
+
"id": 1234,
|
52
|
+
"command": "saq3_isBusy",
|
53
|
+
"results": {
|
54
|
+
"busy": false
|
55
|
+
},
|
56
|
+
"errors": []
|
57
|
+
},
|
58
|
+
"saq3_getFirmwareVersion": {
|
59
|
+
"id": 1234,
|
60
|
+
"command": "saq3_getFirmwareVersion",
|
61
|
+
"results": {
|
62
|
+
"version": "1.0.0"
|
63
|
+
},
|
64
|
+
"errors": []
|
65
|
+
},
|
66
|
+
"saq3_getFPGAVersion": {
|
67
|
+
"id": 1234,
|
68
|
+
"command": "saq3_getFPGAVersion",
|
69
|
+
"results": {
|
70
|
+
"version": "1.0.0"
|
71
|
+
},
|
72
|
+
"errors": []
|
73
|
+
},
|
74
|
+
"saq3_getBoardRevision": {
|
75
|
+
"id": 1234,
|
76
|
+
"command": "saq3_getBoardRevision",
|
77
|
+
"results": {
|
78
|
+
"revision": "Rev A"
|
79
|
+
},
|
80
|
+
"errors": []
|
81
|
+
},
|
82
|
+
"saq3_getSerialNumber": {
|
83
|
+
"id": 1234,
|
84
|
+
"command": "saq3_getSerialNumber",
|
85
|
+
"results": {
|
86
|
+
"serialNumber": "SAQ3-2025-001"
|
87
|
+
},
|
88
|
+
"errors": []
|
89
|
+
},
|
90
|
+
"saq3_setIntegrationTime": {
|
91
|
+
"id": 1234,
|
92
|
+
"command": "saq3_setIntegrationTime",
|
93
|
+
"errors": []
|
94
|
+
},
|
95
|
+
"saq3_getIntegrationTime": {
|
96
|
+
"id": 1234,
|
97
|
+
"command": "saq3_getIntegrationTime",
|
98
|
+
"results": {
|
99
|
+
"time": 100
|
100
|
+
},
|
101
|
+
"errors": []
|
102
|
+
},
|
103
|
+
"saq3_setHVBiasVoltage": {
|
104
|
+
"id": 1234,
|
105
|
+
"command": "saq3_setHVBiasVoltage",
|
106
|
+
"errors": []
|
107
|
+
},
|
108
|
+
"saq3_getHVBiasVoltage": {
|
109
|
+
"id": 1234,
|
110
|
+
"command": "saq3_getHVBiasVoltage",
|
111
|
+
"results": {
|
112
|
+
"voltage": 5.0
|
113
|
+
},
|
114
|
+
"errors": []
|
115
|
+
},
|
116
|
+
"saq3_getMaxHVVoltageAllowed": {
|
117
|
+
"id": 1234,
|
118
|
+
"command": "saq3_getMaxHVVoltageAllowed",
|
119
|
+
"results": {
|
120
|
+
"maxVoltage": 10.0
|
121
|
+
},
|
122
|
+
"errors": []
|
123
|
+
},
|
124
|
+
"saq3_defineAcqSet": {
|
125
|
+
"id": 1234,
|
126
|
+
"command": "saq3_defineAcqSet",
|
127
|
+
"errors": []
|
128
|
+
},
|
129
|
+
"saq3_acqStart": {
|
130
|
+
"id": 1234,
|
131
|
+
"command": "saq3_acqStart",
|
132
|
+
"errors": []
|
133
|
+
},
|
134
|
+
"saq3_acqStop": {
|
135
|
+
"id": 1234,
|
136
|
+
"command": "saq3_acqStop",
|
137
|
+
"errors": []
|
138
|
+
},
|
139
|
+
"saq3_acqPause": {
|
140
|
+
"id": 1234,
|
141
|
+
"command": "saq3_acqPause",
|
142
|
+
"errors": []
|
143
|
+
},
|
144
|
+
"saq3_acqContinue": {
|
145
|
+
"id": 1234,
|
146
|
+
"command": "saq3_acqContinue",
|
147
|
+
"errors": []
|
148
|
+
},
|
149
|
+
"saq3_getAvailableData": {
|
150
|
+
"id": 1234,
|
151
|
+
"command": "saq3_getAvailableData",
|
152
|
+
"results": {
|
153
|
+
"data": [0, 1, 2, 3, 4]
|
154
|
+
},
|
155
|
+
"errors": []
|
156
|
+
},
|
157
|
+
"saq3_isDataAvailable": {
|
158
|
+
"id": 1234,
|
159
|
+
"command": "saq3_isDataAvailable",
|
160
|
+
"results": {
|
161
|
+
"available": true
|
162
|
+
},
|
163
|
+
"errors": []
|
164
|
+
},
|
165
|
+
"saq3_forceTrigger": {
|
166
|
+
"id": 1234,
|
167
|
+
"command": "saq3_forceTrigger",
|
168
|
+
"errors": []
|
169
|
+
},
|
170
|
+
"saq3_setTriggerInPolarity": {
|
171
|
+
"id": 1234,
|
172
|
+
"command": "saq3_setTriggerInPolarity",
|
173
|
+
"errors": []
|
174
|
+
},
|
175
|
+
"saq3_getTriggerInPolarity": {
|
176
|
+
"id": 1234,
|
177
|
+
"command": "saq3_getTriggerInPolarity",
|
178
|
+
"results": {
|
179
|
+
"polarity": "active_high"
|
180
|
+
},
|
181
|
+
"errors": []
|
182
|
+
},
|
183
|
+
"saq3_setInTriggerMode": {
|
184
|
+
"id": 1234,
|
185
|
+
"command": "saq3_setInTriggerMode",
|
186
|
+
"errors": []
|
187
|
+
},
|
188
|
+
"saq3_getInTriggerMode": {
|
189
|
+
"id": 1234,
|
190
|
+
"command": "saq3_getInTriggerMode",
|
191
|
+
"results": {
|
192
|
+
"mode": "continuous"
|
193
|
+
},
|
194
|
+
"errors": []
|
195
|
+
},
|
196
|
+
"saq3_getLastError": {
|
197
|
+
"id": 1234,
|
198
|
+
"command": "saq3_getLastError",
|
199
|
+
"results": {
|
200
|
+
"error": "No error"
|
201
|
+
},
|
202
|
+
"errors": []
|
203
|
+
},
|
204
|
+
"saq3_getErrorLog": {
|
205
|
+
"id": 1234,
|
206
|
+
"command": "saq3_getErrorLog",
|
207
|
+
"results": {
|
208
|
+
"log": []
|
209
|
+
},
|
210
|
+
"errors": []
|
211
|
+
},
|
212
|
+
"saq3_clearErrorLog": {
|
213
|
+
"id": 1234,
|
214
|
+
"command": "saq3_clearErrorLog",
|
215
|
+
"errors": []
|
216
|
+
}
|
217
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from .abstract_device import AbstractDevice
|
2
2
|
from .ccd import ChargeCoupledDevice
|
3
3
|
from .monochromator import Monochromator
|
4
|
+
from .spectracq3 import SpectrAcq3
|
4
5
|
|
5
|
-
__all__ = ['AbstractDevice', 'Monochromator', 'ChargeCoupledDevice']
|
6
|
+
__all__ = ['AbstractDevice', 'Monochromator', 'ChargeCoupledDevice', 'SpectrAcq3']
|
@@ -618,7 +618,8 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
618
618
|
acquisitions have completed, therefore the same timestamp is used for all acquisitions.
|
619
619
|
"""
|
620
620
|
response: Response = await super()._execute_command('ccd_getAcquisitionData', {'index': self._id})
|
621
|
-
|
621
|
+
results: dict[Any, Any] = response.results
|
622
|
+
return results
|
622
623
|
|
623
624
|
async def set_center_wavelength(self, mono_index: float, center_wavelength: float) -> None:
|
624
625
|
"""Sets the center wavelength value to be used in the grating equation.
|
@@ -668,7 +669,8 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
668
669
|
'overlap': pixel_overlap,
|
669
670
|
},
|
670
671
|
)
|
671
|
-
|
672
|
+
center_wavelengths: list[float] = response.results['centerWavelengths']
|
673
|
+
return center_wavelengths
|
672
674
|
|
673
675
|
@staticmethod
|
674
676
|
async def raman_convert(spectrum: list[float], excitation_wavelength: float) -> list[float]:
|
@@ -0,0 +1,392 @@
|
|
1
|
+
from types import TracebackType
|
2
|
+
from typing import Optional, final
|
3
|
+
|
4
|
+
from loguru import logger
|
5
|
+
from pydantic import BaseModel
|
6
|
+
|
7
|
+
from horiba_sdk.communication import AbstractCommunicator, Response
|
8
|
+
|
9
|
+
from ...core.trigger_input_polarity import TriggerInputPolarity
|
10
|
+
from ...icl_error import AbstractErrorDB
|
11
|
+
from .abstract_device import AbstractDevice
|
12
|
+
|
13
|
+
|
14
|
+
class BaseResults(BaseModel):
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
# Define a model for the saq3_getAvailableData results
|
19
|
+
class Signal(BaseModel):
|
20
|
+
unit: str
|
21
|
+
value: float
|
22
|
+
|
23
|
+
|
24
|
+
class DataPoint(BaseModel):
|
25
|
+
currentSignal: Signal
|
26
|
+
elapsedTime: int
|
27
|
+
eventMarker: bool
|
28
|
+
overscaleCurrentChannel: bool
|
29
|
+
overscaleVoltageChannel: bool
|
30
|
+
pmtSignal: Signal
|
31
|
+
pointNumber: int
|
32
|
+
ppdSignal: Signal
|
33
|
+
voltageSignal: Signal
|
34
|
+
|
35
|
+
|
36
|
+
class AvailableDataResults(BaseModel):
|
37
|
+
data: list[DataPoint]
|
38
|
+
|
39
|
+
|
40
|
+
class AcqSetResults(BaseResults):
|
41
|
+
scanCount: int
|
42
|
+
timeStep: int
|
43
|
+
integrationTime: int
|
44
|
+
externalParam: int
|
45
|
+
|
46
|
+
|
47
|
+
@final
|
48
|
+
class SpectrAcq3(AbstractDevice):
|
49
|
+
"""
|
50
|
+
SpectrAcq3 device class.
|
51
|
+
|
52
|
+
This class represents the SpectrAcq3 - Single Channel Detector Interface. It provides methods to open and close
|
53
|
+
the device connection and retrieve the device's serial number. The focus is on ensuring reliable communication
|
54
|
+
with the device and handling any potential errors gracefully.
|
55
|
+
"""
|
56
|
+
|
57
|
+
def __init__(self, device_id: int, communicator: AbstractCommunicator, error_db: AbstractErrorDB) -> None:
|
58
|
+
super().__init__(device_id, communicator, error_db)
|
59
|
+
|
60
|
+
async def __aenter__(self) -> 'SpectrAcq3':
|
61
|
+
await self.open()
|
62
|
+
return self
|
63
|
+
|
64
|
+
async def __aexit__(
|
65
|
+
self, exc_type: type[BaseException], exc_value: BaseException, traceback: Optional[TracebackType]
|
66
|
+
) -> None:
|
67
|
+
is_open = await self.is_open()
|
68
|
+
if not is_open:
|
69
|
+
logger.debug('SpectrAcq3 is already closed')
|
70
|
+
return
|
71
|
+
|
72
|
+
await self.close()
|
73
|
+
|
74
|
+
async def open(self) -> None:
|
75
|
+
"""
|
76
|
+
Open a connection to the SpectrAcq3 device.
|
77
|
+
|
78
|
+
This method sends a command to the device to establish a connection. It is crucial to ensure that the device
|
79
|
+
is ready for communication before attempting any operations, to prevent errors and data loss.
|
80
|
+
"""
|
81
|
+
await self._execute_command('saq3_open', {'index': self._id})
|
82
|
+
|
83
|
+
async def close(self) -> None:
|
84
|
+
"""
|
85
|
+
Close the connection to the SpectrAcq3 device.
|
86
|
+
|
87
|
+
This method sends a command to safely terminate the connection with the device. Properly closing the connection
|
88
|
+
helps in freeing up resources and maintaining the device's integrity for future operations.
|
89
|
+
"""
|
90
|
+
await self._execute_command('saq3_close', {'index': self._id})
|
91
|
+
|
92
|
+
async def is_open(self) -> bool:
|
93
|
+
"""
|
94
|
+
Check if the connection to the SpectrAcq3 device is open.
|
95
|
+
|
96
|
+
This method checks the status of the device connection to determine if it is open or closed. It is useful for
|
97
|
+
verifying the device's state before performing any operations that require an active connection.
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
bool: True if the connection is open, False otherwise.
|
101
|
+
"""
|
102
|
+
response: Response = await self._execute_command('saq3_isOpen', {'index': self._id})
|
103
|
+
is_open: bool = response.results['open']
|
104
|
+
return is_open
|
105
|
+
|
106
|
+
async def is_busy(self) -> bool:
|
107
|
+
"""
|
108
|
+
Check if the device is busy.
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
bool: True if the device is busy, False otherwise.
|
112
|
+
"""
|
113
|
+
response: Response = await self._execute_command('saq3_isBusy', {'index': self._id})
|
114
|
+
is_busy: bool = response.results['isBusy']
|
115
|
+
return is_busy
|
116
|
+
|
117
|
+
async def get_serial_number(self) -> str:
|
118
|
+
"""
|
119
|
+
Retrieve the serial number of the SpectrAcq3 device.
|
120
|
+
|
121
|
+
This method sends a command to the device to fetch its serial number. Knowing the serial number is essential
|
122
|
+
for device identification and tracking, especially in environments with multiple devices.
|
123
|
+
|
124
|
+
Returns:
|
125
|
+
str: The serial number of the device.
|
126
|
+
"""
|
127
|
+
response: Response = await self._execute_command('saq3_getSerialNumber', {'index': self._id})
|
128
|
+
serial_number: str = response.results['serialNumber']
|
129
|
+
return serial_number
|
130
|
+
|
131
|
+
async def get_firmware_version(self) -> str:
|
132
|
+
"""
|
133
|
+
Get the firmware version of the device.
|
134
|
+
|
135
|
+
This method sends a command to the device to fetch its firmware version.
|
136
|
+
|
137
|
+
Returns:
|
138
|
+
str: The firmware version of the device.
|
139
|
+
"""
|
140
|
+
response: Response = await self._execute_command('saq3_getFirmwareVersion', {'index': self._id})
|
141
|
+
firmware_version: str = response.results['firmwareVersion']
|
142
|
+
return firmware_version
|
143
|
+
|
144
|
+
async def get_fpga_version(self) -> str:
|
145
|
+
"""
|
146
|
+
Get the FPGA version of the device.
|
147
|
+
|
148
|
+
This method sends a command to the device to fetch its FPGA version.
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
str: The FPGA version of the device.
|
152
|
+
"""
|
153
|
+
response: Response = await self._execute_command('saq3_getFPGAVersion', {'index': self._id})
|
154
|
+
fpga_version: str = response.results['FpgaVersion']
|
155
|
+
return fpga_version
|
156
|
+
|
157
|
+
async def get_board_revision(self) -> str:
|
158
|
+
"""
|
159
|
+
Get the board revision of the device.
|
160
|
+
|
161
|
+
This method sends a command to the device to fetch its board revision.
|
162
|
+
|
163
|
+
Returns:
|
164
|
+
str: The board revision of the device.
|
165
|
+
"""
|
166
|
+
response: Response = await self._execute_command('saq3_getBoardRevision', {'index': self._id})
|
167
|
+
board_revision: str = response.results['boardRevision']
|
168
|
+
return board_revision
|
169
|
+
|
170
|
+
async def set_hv_bias_voltage(self, bias_voltage: int) -> None:
|
171
|
+
"""
|
172
|
+
Set the high bias voltage.
|
173
|
+
|
174
|
+
This method sends a command to the device to set the high bias voltage.
|
175
|
+
|
176
|
+
Args:
|
177
|
+
bias_voltage (int): The high bias voltage in volts.
|
178
|
+
"""
|
179
|
+
await self._execute_command('saq3_setHVBiasVoltage', {'index': self._id, 'biasVoltage': bias_voltage})
|
180
|
+
|
181
|
+
async def get_hv_bias_voltage(self) -> int:
|
182
|
+
"""
|
183
|
+
Get the high bias voltage that was previously set.
|
184
|
+
|
185
|
+
This method sends a command to the device to fetch the high bias voltage.
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
int: The high bias voltage in volts.
|
189
|
+
"""
|
190
|
+
response: Response = await self._execute_command('saq3_getHVBiasVoltage', {'index': self._id})
|
191
|
+
hv_bias_voltage: int = response.results['biasVoltage']
|
192
|
+
return hv_bias_voltage
|
193
|
+
|
194
|
+
async def get_max_hv_voltage_allowed(self) -> int:
|
195
|
+
"""
|
196
|
+
Get the maximum high bias voltage allowed.
|
197
|
+
|
198
|
+
This method sends a command to the device to fetch the maximum high bias voltage allowed.
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
int: The maximum high bias voltage in volts.
|
202
|
+
"""
|
203
|
+
response: Response = await self._execute_command('saq3_getMaxHVVoltageAllowed', {'index': self._id})
|
204
|
+
max_hv_voltage: int = response.results['biasVoltage']
|
205
|
+
return max_hv_voltage
|
206
|
+
|
207
|
+
async def set_acq_set(self, scan_count: int, time_step: int, integration_time: int, external_param: int) -> None:
|
208
|
+
"""
|
209
|
+
Define the acquisition set parameters.
|
210
|
+
|
211
|
+
This method sends a command to the device to define the acquisition set parameters.
|
212
|
+
|
213
|
+
Args:
|
214
|
+
scan_count (int): Number of acquisitions to perform.
|
215
|
+
time_step (int): Time interval in seconds between acquisitions.
|
216
|
+
integration_time (int): Integration time in seconds.
|
217
|
+
external_param (int): User defined value.
|
218
|
+
"""
|
219
|
+
await self._execute_command(
|
220
|
+
'saq3_setAcqSet',
|
221
|
+
{
|
222
|
+
'index': self._id,
|
223
|
+
'scanCount': scan_count,
|
224
|
+
'timeStep': time_step,
|
225
|
+
'integrationTime': integration_time,
|
226
|
+
'externalParam': external_param,
|
227
|
+
},
|
228
|
+
)
|
229
|
+
|
230
|
+
async def get_acq_set(self) -> dict:
|
231
|
+
"""
|
232
|
+
Get the acquisition set parameters.
|
233
|
+
|
234
|
+
This method sends a command to the device to fetch the acquisition set parameters.
|
235
|
+
|
236
|
+
Returns:
|
237
|
+
dict: The acquisition set parameters.
|
238
|
+
"""
|
239
|
+
response: Response = await self._execute_command('saq3_getAcqSet', {'index': self._id})
|
240
|
+
acq_set: dict = response.results
|
241
|
+
return acq_set
|
242
|
+
|
243
|
+
async def acq_start(self, trigger: int) -> None:
|
244
|
+
"""
|
245
|
+
Start the acquisition.
|
246
|
+
|
247
|
+
Trigger Modes:
|
248
|
+
>| Mode | description |
|
249
|
+
>|1| 1st data started on Start command, all subsequent data acquired based on interval time|
|
250
|
+
>|2| 1st data started by Trigger after start Command, all subsequent data acquired based on interval time |
|
251
|
+
>|3| Each data acquisition waits for Trigger
|
252
|
+
|
253
|
+
Args:
|
254
|
+
trigger (int): Integer indicating the trigger mode.
|
255
|
+
"""
|
256
|
+
await self._execute_command('saq3_acqStart', {'index': self._id, 'trigger': trigger})
|
257
|
+
|
258
|
+
async def acq_stop(self) -> None:
|
259
|
+
"""
|
260
|
+
Stop the current acquisition.
|
261
|
+
|
262
|
+
This method sends a command to the device to stop the current acquisition.
|
263
|
+
"""
|
264
|
+
await self._execute_command('saq3_acqStop', {'index': self._id})
|
265
|
+
|
266
|
+
async def acq_pause(self) -> None:
|
267
|
+
"""
|
268
|
+
Pause the active acquisition.
|
269
|
+
|
270
|
+
This method sends a command to the device to pause the active acquisition.
|
271
|
+
"""
|
272
|
+
await self._execute_command('saq3_acqPause', {'index': self._id})
|
273
|
+
|
274
|
+
async def acq_continue(self) -> None:
|
275
|
+
"""
|
276
|
+
Continue a paused acquisition.
|
277
|
+
|
278
|
+
This method sends a command to the device to continue a paused acquisition.
|
279
|
+
"""
|
280
|
+
await self._execute_command('saq3_acqContinue', {'index': self._id})
|
281
|
+
|
282
|
+
async def is_data_available(self) -> bool:
|
283
|
+
"""
|
284
|
+
Check whether the acquired data is available.
|
285
|
+
|
286
|
+
This method sends a command to the device to check if the acquired data is available.
|
287
|
+
|
288
|
+
Returns:
|
289
|
+
bool: True if data is available, False otherwise.
|
290
|
+
"""
|
291
|
+
response: Response = await self._execute_command('saq3_isDataAvailable', {'index': self._id})
|
292
|
+
is_data_available: bool = response.results['isDataAvailable']
|
293
|
+
return is_data_available
|
294
|
+
|
295
|
+
async def get_available_data(self) -> AvailableDataResults:
|
296
|
+
"""
|
297
|
+
Retrieve the acquired data that is available so far.
|
298
|
+
|
299
|
+
This method sends a command to the device to retrieve the acquired data.
|
300
|
+
|
301
|
+
Returns:
|
302
|
+
list: The acquired data.
|
303
|
+
"""
|
304
|
+
response: Response = await self._execute_command('saq3_getAvailableData', {'index': self._id})
|
305
|
+
available_data: AvailableDataResults = response.results['data']
|
306
|
+
return available_data
|
307
|
+
|
308
|
+
async def force_trigger(self) -> None:
|
309
|
+
"""
|
310
|
+
Force a software trigger.
|
311
|
+
|
312
|
+
This method sends a command to the device to force a software trigger.
|
313
|
+
"""
|
314
|
+
await self._execute_command('saq3_forceTrigger', {'index': self._id})
|
315
|
+
|
316
|
+
async def set_trigger_in_polarity(self, polarity: TriggerInputPolarity) -> None:
|
317
|
+
"""
|
318
|
+
Set the input trigger polarity.
|
319
|
+
|
320
|
+
Args:
|
321
|
+
polarity (TriggerInputPolarity): Input trigger polarity (ACTIVE_LOW or ACTIVE_HIGH).
|
322
|
+
"""
|
323
|
+
await self._execute_command('saq3_setTriggerInPolarity', {'index': self._id, 'polarity': polarity.value})
|
324
|
+
|
325
|
+
async def get_trigger_in_polarity(self) -> int:
|
326
|
+
"""
|
327
|
+
Get the input trigger polarity.
|
328
|
+
|
329
|
+
Returns:
|
330
|
+
int: Input trigger polarity (0: Active Low, 1: Active High).
|
331
|
+
"""
|
332
|
+
response: Response = await self._execute_command('saq3_getTriggerInPolarity', {'index': self._id})
|
333
|
+
polarity: int = response.results['polarity']
|
334
|
+
return polarity
|
335
|
+
|
336
|
+
async def set_in_trigger_mode(self, mode: int) -> None:
|
337
|
+
"""
|
338
|
+
Set the hardware trigger pin mode.
|
339
|
+
|
340
|
+
This method sends a command to the device to set the hardware trigger pin mode.
|
341
|
+
|
342
|
+
Args:
|
343
|
+
mode (int): Mode of hardware trigger pin.
|
344
|
+
"""
|
345
|
+
await self._execute_command('saq3_setInTriggerMode', {'index': self._id, 'mode': mode})
|
346
|
+
|
347
|
+
async def get_trigger_mode(self) -> dict:
|
348
|
+
"""
|
349
|
+
Get the trigger mode.
|
350
|
+
|
351
|
+
This method sends a command to the device to fetch the trigger mode.
|
352
|
+
|
353
|
+
Returns:
|
354
|
+
dict: The trigger mode settings.
|
355
|
+
"""
|
356
|
+
response: Response = await self._execute_command('saq3_getInTriggerMode', {'index': self._id})
|
357
|
+
trigger_mode: dict = response.results
|
358
|
+
return trigger_mode
|
359
|
+
|
360
|
+
async def get_last_error(self) -> str:
|
361
|
+
"""
|
362
|
+
Get the last error.
|
363
|
+
|
364
|
+
This method sends a command to the device to fetch the last error.
|
365
|
+
|
366
|
+
Returns:
|
367
|
+
str: The last error message.
|
368
|
+
"""
|
369
|
+
response: Response = await self._execute_command('saq3_getLastError', {'index': self._id})
|
370
|
+
last_error: str = response.results['error']
|
371
|
+
return last_error
|
372
|
+
|
373
|
+
async def get_error_log(self) -> list[str]:
|
374
|
+
"""
|
375
|
+
Get the error log.
|
376
|
+
|
377
|
+
This method sends a command to the device to fetch the error log.
|
378
|
+
|
379
|
+
Returns:
|
380
|
+
str: The error log.
|
381
|
+
"""
|
382
|
+
response: Response = await self._execute_command('saq3_getErrorLog', {'index': self._id})
|
383
|
+
error_log: list[str] = response.results['errors']
|
384
|
+
return error_log
|
385
|
+
|
386
|
+
async def clear_error_log(self) -> None:
|
387
|
+
"""
|
388
|
+
Clear all the errors in the log.
|
389
|
+
|
390
|
+
This method sends a command to the device to clear the error log.
|
391
|
+
"""
|
392
|
+
await self._execute_command('saq3_clearErrorLog', {'index': self._id})
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from typing import Any, final
|
2
|
+
|
3
|
+
from loguru import logger
|
4
|
+
from overrides import override
|
5
|
+
|
6
|
+
from horiba_sdk.communication import AbstractCommunicator, Command, Response
|
7
|
+
from horiba_sdk.devices.abstract_device_discovery import AbstractDeviceDiscovery
|
8
|
+
from horiba_sdk.devices.single_devices import SpectrAcq3
|
9
|
+
from horiba_sdk.icl_error import AbstractErrorDB
|
10
|
+
|
11
|
+
|
12
|
+
@final
|
13
|
+
class SpectrAcq3Discovery(AbstractDeviceDiscovery):
|
14
|
+
def __init__(self, communicator: AbstractCommunicator, error_db: AbstractErrorDB):
|
15
|
+
self._communicator: AbstractCommunicator = communicator
|
16
|
+
self._spectracq3_devices: list[SpectrAcq3] = []
|
17
|
+
self._error_db: AbstractErrorDB = error_db
|
18
|
+
|
19
|
+
@override
|
20
|
+
async def execute(self, error_on_no_device: bool = False) -> None:
|
21
|
+
"""
|
22
|
+
Discovers the connected SpectrAcq3 devices and saves them internally.
|
23
|
+
|
24
|
+
Raises:
|
25
|
+
Exception: When no SpectrAcq3 devices are discovered and that `error_on_no_device` is set.
|
26
|
+
Or when there is an issue parsing the SpectrAcq3 devices list
|
27
|
+
"""
|
28
|
+
if not self._communicator.opened():
|
29
|
+
await self._communicator.open()
|
30
|
+
|
31
|
+
response: Response = await self._communicator.request_with_response(Command('saq3_discover', {}))
|
32
|
+
if response.results.get('count', 0) == 0 and error_on_no_device:
|
33
|
+
raise Exception('No SpectrAcq3 devices connected')
|
34
|
+
|
35
|
+
response = await self._communicator.request_with_response(Command('saq3_list', {}))
|
36
|
+
|
37
|
+
raw_device_list = response.results
|
38
|
+
self._spectracq3_devices = self._parse_devices(raw_device_list)
|
39
|
+
logger.info(f'Found {len(self._spectracq3_devices)} SpectrAcq3 devices')
|
40
|
+
|
41
|
+
def _parse_devices(self, raw_device_list: dict[str, Any]) -> list[SpectrAcq3]:
|
42
|
+
detected_devices: list[SpectrAcq3] = []
|
43
|
+
for device in raw_device_list['devices']:
|
44
|
+
try:
|
45
|
+
logger.debug(f'Parsing SpectrAcq3: {device}')
|
46
|
+
spectracq3 = SpectrAcq3(device['index'], self._communicator, self._error_db)
|
47
|
+
logger.info(f'Detected SpectrAcq3: {device["deviceType"]}')
|
48
|
+
detected_devices.append(spectracq3)
|
49
|
+
except Exception as e:
|
50
|
+
logger.error(f'Error while parsing SpectrAcq3: {e}')
|
51
|
+
|
52
|
+
return detected_devices
|
53
|
+
|
54
|
+
def spectracq3_devices(self) -> list[SpectrAcq3]:
|
55
|
+
return self._spectracq3_devices
|