horiba-sdk 0.3.3__py3-none-any.whl → 0.5.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.
- horiba_sdk/__init__.py +5 -3
- horiba_sdk/communication/websocket_communicator.py +2 -2
- horiba_sdk/core/__init__.py +0 -0
- horiba_sdk/core/acquisition_format.py +20 -0
- horiba_sdk/core/clean_count_mode.py +13 -0
- horiba_sdk/core/timer_resolution.py +14 -0
- horiba_sdk/core/x_axis_conversion_type.py +18 -0
- horiba_sdk/devices/ccd_discovery.py +10 -12
- horiba_sdk/devices/device_manager.py +24 -10
- horiba_sdk/devices/fake_responses/ccd.json +261 -12
- horiba_sdk/devices/fake_responses/monochromator.json +38 -10
- horiba_sdk/devices/monochromator_discovery.py +16 -9
- horiba_sdk/devices/single_devices/abstract_device.py +46 -1
- horiba_sdk/devices/single_devices/ccd.py +388 -143
- horiba_sdk/devices/single_devices/monochromator.py +87 -71
- horiba_sdk/sync/communication/abstract_communicator.py +2 -3
- horiba_sdk/sync/communication/websocket_communicator.py +38 -18
- horiba_sdk/sync/devices/device_discovery.py +13 -37
- horiba_sdk/sync/devices/device_manager.py +14 -10
- horiba_sdk/sync/devices/fake_icl_server.py +9 -6
- horiba_sdk/sync/devices/single_devices/abstract_device.py +11 -7
- horiba_sdk/sync/devices/single_devices/ccd.py +517 -62
- horiba_sdk/sync/devices/single_devices/monochromator.py +288 -25
- {horiba_sdk-0.3.3.dist-info → horiba_sdk-0.5.2.dist-info}/METADATA +166 -92
- {horiba_sdk-0.3.3.dist-info → horiba_sdk-0.5.2.dist-info}/RECORD +27 -22
- {horiba_sdk-0.3.3.dist-info → horiba_sdk-0.5.2.dist-info}/LICENSE +0 -0
- {horiba_sdk-0.3.3.dist-info → horiba_sdk-0.5.2.dist-info}/WHEEL +0 -0
horiba_sdk/__init__.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# mypy: disable-error-code="attr-defined"
|
2
2
|
"""'horiba-sdk' is a package that provides source code for the development with Horiba devices"""
|
3
3
|
|
4
|
+
from loguru import logger
|
5
|
+
|
4
6
|
__version__ = '0.2.0' # It MUST match the version in pyproject.toml file
|
5
7
|
from importlib import metadata as importlib_metadata
|
6
8
|
|
7
|
-
from pint import UnitRegistry
|
8
|
-
|
9
9
|
|
10
10
|
def get_version() -> str:
|
11
11
|
try:
|
@@ -16,4 +16,6 @@ def get_version() -> str:
|
|
16
16
|
|
17
17
|
version: str = get_version()
|
18
18
|
|
19
|
-
|
19
|
+
# it is good practice to disable the logging for a library, this is done here.
|
20
|
+
# on initialization of a device manager, this can be enabled.
|
21
|
+
logger.disable(__name__)
|
@@ -166,13 +166,13 @@ class WebsocketCommunicator(AbstractCommunicator):
|
|
166
166
|
|
167
167
|
def register_binary_message_callback(self, callback: Callable[[bytes], Any]) -> None:
|
168
168
|
"""Registers a callback to be called with every incoming binary message."""
|
169
|
-
logger.
|
169
|
+
logger.debug('Binary message callback registered.')
|
170
170
|
self.binary_message_callback = callback
|
171
171
|
|
172
172
|
async def _receive_data(self) -> None:
|
173
173
|
try:
|
174
174
|
async for message in self.websocket: # type: ignore
|
175
|
-
logger.
|
175
|
+
logger.debug(f'Received message: {message!r}')
|
176
176
|
if isinstance(message, str):
|
177
177
|
await self.json_message_queue.put(message)
|
178
178
|
elif isinstance(message, bytes):
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import final
|
3
|
+
|
4
|
+
|
5
|
+
@final
|
6
|
+
class AcquisitionFormat(Enum):
|
7
|
+
"""Formats for the acquisition.
|
8
|
+
|
9
|
+
Attributes:
|
10
|
+
SPECTRA: X axis in nm, Y axis in counts
|
11
|
+
IMAGE: X axis in pixels, Y axis in counts
|
12
|
+
CROP: TBD
|
13
|
+
FAST_KINETICS: TBD
|
14
|
+
|
15
|
+
"""
|
16
|
+
|
17
|
+
SPECTRA = 0
|
18
|
+
IMAGE = 1
|
19
|
+
CROP = 2
|
20
|
+
FAST_KINETICS = 3
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import final
|
3
|
+
|
4
|
+
|
5
|
+
@final
|
6
|
+
class TimerResolution(Enum):
|
7
|
+
"""Resolution for the timer for the acquisition time.
|
8
|
+
|
9
|
+
.. note:: The timer resolution value MICROSECONDS is not supported by all CCDs.
|
10
|
+
"""
|
11
|
+
|
12
|
+
MILLISECONDS = 0
|
13
|
+
MICROSECONDS = 1
|
14
|
+
NOTHING_EVAL = 2
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import final
|
3
|
+
|
4
|
+
|
5
|
+
@final
|
6
|
+
class XAxisConversionType(Enum):
|
7
|
+
"""
|
8
|
+
Conversion types for the x axis of acquired data.
|
9
|
+
|
10
|
+
Attributes:
|
11
|
+
NONE: No conversion.
|
12
|
+
FROM_CCD_FIRMWARE: CCD FIT parameters contained in the CCD firmware.
|
13
|
+
FROM_ICL_SETTINGS_INI: Mono Wavelength parameters contained in the icl_settings.ini file
|
14
|
+
"""
|
15
|
+
|
16
|
+
NONE = 0
|
17
|
+
FROM_CCD_FIRMWARE = 1
|
18
|
+
FROM_ICL_SETTINGS_INI = 2
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import re
|
2
1
|
from typing import Any, final
|
3
2
|
|
4
3
|
from loguru import logger
|
@@ -32,24 +31,23 @@ class ChargeCoupledDevicesDiscovery(AbstractDeviceDiscovery):
|
|
32
31
|
response: Response = await self._communicator.request_with_response(Command('ccd_discover', {}))
|
33
32
|
if response.results.get('count', 0) == 0 and error_on_no_device:
|
34
33
|
raise Exception('No CCDs connected')
|
34
|
+
|
35
35
|
response = await self._communicator.request_with_response(Command('ccd_list', {}))
|
36
36
|
|
37
37
|
raw_device_list = response.results
|
38
38
|
self._charge_coupled_devices = self._parse_ccds(raw_device_list)
|
39
|
-
logger.info(f'Found {len(self._charge_coupled_devices)} CCD devices
|
39
|
+
logger.info(f'Found {len(self._charge_coupled_devices)} CCD devices')
|
40
40
|
|
41
41
|
def _parse_ccds(self, raw_device_list: dict[str, Any]) -> list[ChargeCoupledDevice]:
|
42
42
|
detected_ccds: list[ChargeCoupledDevice] = []
|
43
|
-
for
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
logger.info(f'Detected CCD: {ccd_type}')
|
52
|
-
detected_ccds.append(ChargeCoupledDevice(ccd_index, self._communicator, self._error_db))
|
43
|
+
for device in raw_device_list['devices']:
|
44
|
+
try:
|
45
|
+
logger.debug(f'Parsing CCD: {device}')
|
46
|
+
ccd = ChargeCoupledDevice(device['index'], self._communicator, self._error_db)
|
47
|
+
logger.info(f'Detected CCD: {device["deviceType"]}')
|
48
|
+
detected_ccds.append(ccd)
|
49
|
+
except Exception as e:
|
50
|
+
logger.error(f'Error while parsing ChargeCoupledDevice: {e}')
|
53
51
|
|
54
52
|
return detected_ccds
|
55
53
|
|
@@ -63,27 +63,34 @@ class DeviceManager(AbstractDeviceManager):
|
|
63
63
|
def __init__(
|
64
64
|
self,
|
65
65
|
start_icl: bool = True,
|
66
|
-
|
67
|
-
|
66
|
+
icl_ip: str = '127.0.0.1',
|
67
|
+
icl_port: str = '25010',
|
68
68
|
enable_binary_messages: bool = True,
|
69
|
+
enable_logging: bool = False
|
69
70
|
):
|
70
71
|
"""
|
71
72
|
Initializes the DeviceManager with the specified communicator class.
|
72
73
|
|
73
74
|
Args:
|
74
75
|
start_icl (bool) = True: If True, the ICL software is started and communication is established.
|
75
|
-
|
76
|
-
|
76
|
+
icl_ip (str) = '127.0.0.1': websocket IP
|
77
|
+
icl_port (str) = '25010': websocket port
|
77
78
|
enable_binary_messages (bool) = True: If True, binary messages are enabled.
|
79
|
+
enable_logging (bool) = True: If True, logging with the loguru library is enabled.
|
78
80
|
"""
|
81
|
+
# By default, logging is disabled for a library, so if desired it can be enabled
|
82
|
+
root_name_space: str = __name__.split('.')[0]
|
83
|
+
if enable_logging:
|
84
|
+
logger.info(f"Initializing logger for namespace: {root_name_space}")
|
85
|
+
logger.enable(root_name_space)
|
86
|
+
else:
|
87
|
+
logger.disable(root_name_space)
|
79
88
|
super().__init__()
|
80
89
|
self._start_icl = start_icl
|
81
|
-
self._icl_communicator: WebsocketCommunicator = WebsocketCommunicator(
|
82
|
-
'ws://' + websocket_ip + ':' + str(websocket_port)
|
83
|
-
)
|
90
|
+
self._icl_communicator: WebsocketCommunicator = WebsocketCommunicator('ws://' + icl_ip + ':' + str(icl_port))
|
84
91
|
self._icl_communicator.register_binary_message_callback(self._binary_message_callback)
|
85
|
-
self._icl_websocket_ip: str =
|
86
|
-
self._icl_websocket_port: str =
|
92
|
+
self._icl_websocket_ip: str = icl_ip
|
93
|
+
self._icl_websocket_port: str = icl_port
|
87
94
|
self._icl_process: Optional[asyncio.subprocess.Process] = None
|
88
95
|
self._binary_messages: bool = enable_binary_messages
|
89
96
|
self._charge_coupled_devices: list[ChargeCoupledDevice] = []
|
@@ -109,7 +116,12 @@ class DeviceManager(AbstractDeviceManager):
|
|
109
116
|
|
110
117
|
@override
|
111
118
|
async def stop(self) -> None:
|
112
|
-
|
119
|
+
if self._start_icl:
|
120
|
+
await self.stop_icl()
|
121
|
+
return
|
122
|
+
|
123
|
+
if self._icl_communicator.opened():
|
124
|
+
await self._icl_communicator.close()
|
113
125
|
|
114
126
|
async def start_icl(self) -> None:
|
115
127
|
"""
|
@@ -126,6 +138,8 @@ class DeviceManager(AbstractDeviceManager):
|
|
126
138
|
logger.info('icl not running, starting it...')
|
127
139
|
# subprocess.Popen([r'C:\Program Files\HORIBA Scientific\SDK\icl.exe'])
|
128
140
|
self._icl_process = await asyncio.create_subprocess_exec(r'C:\Program Files\HORIBA Scientific\SDK\icl.exe')
|
141
|
+
await asyncio.sleep(4)
|
142
|
+
|
129
143
|
# except subprocess.CalledProcessError:
|
130
144
|
# logger.error('Failed to start ICL software.')
|
131
145
|
# TODO: [saga] is this the best way handle exceptions?
|
@@ -8,12 +8,19 @@
|
|
8
8
|
"errors": []
|
9
9
|
},
|
10
10
|
"ccd_list": {
|
11
|
-
"id": 1234,
|
12
11
|
"command": "ccd_list",
|
12
|
+
"errors": [],
|
13
|
+
"id": 1234,
|
13
14
|
"results": {
|
14
|
-
"
|
15
|
-
|
16
|
-
|
15
|
+
"devices": [
|
16
|
+
{
|
17
|
+
"deviceType": "HORIBA Scientific Syncerity",
|
18
|
+
"index":0,
|
19
|
+
"productId":13,
|
20
|
+
"serialNumber": "Camera SN: 2244"
|
21
|
+
}
|
22
|
+
]
|
23
|
+
}
|
17
24
|
},
|
18
25
|
"ccd_listCount": {
|
19
26
|
"id": 1234,
|
@@ -45,7 +52,190 @@
|
|
45
52
|
]
|
46
53
|
},
|
47
54
|
"ccd_restart": {},
|
48
|
-
"ccd_getConfig": {
|
55
|
+
"ccd_getConfig": {
|
56
|
+
"command": "ccd_getConfig",
|
57
|
+
"errors": [],
|
58
|
+
"id": 1234,
|
59
|
+
"results": {
|
60
|
+
"configuration": {
|
61
|
+
"centerWavelength": 0,
|
62
|
+
"chipHSpacing": 260,
|
63
|
+
"chipHeight": 256,
|
64
|
+
"chipName": "CCD30-11-1-275",
|
65
|
+
"chipSerialNumber": "20091-22-21",
|
66
|
+
"chipVSpacing": 260,
|
67
|
+
"chipWidth": 1024,
|
68
|
+
"deviceType": "HORIBA Scientific Syncerity",
|
69
|
+
"fitParameters": [
|
70
|
+
0,
|
71
|
+
1,
|
72
|
+
0,
|
73
|
+
0,
|
74
|
+
0
|
75
|
+
],
|
76
|
+
"gains": [
|
77
|
+
{
|
78
|
+
"info": "High Sensitivity",
|
79
|
+
"token": 2
|
80
|
+
},
|
81
|
+
{
|
82
|
+
"info": "High Light",
|
83
|
+
"token": 0
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"info": "Best Dynamic Range",
|
87
|
+
"token": 1
|
88
|
+
}
|
89
|
+
],
|
90
|
+
"hardwareAvgAvailable": "false",
|
91
|
+
"lineScan": "false",
|
92
|
+
"productId": "13",
|
93
|
+
"serialNumber": "Camera SN: 2244",
|
94
|
+
"signals": [
|
95
|
+
{
|
96
|
+
"events": [
|
97
|
+
{
|
98
|
+
"name": "Reserved-DO NOT USE",
|
99
|
+
"token": 2,
|
100
|
+
"types": [
|
101
|
+
{
|
102
|
+
"name": "TTL Active High",
|
103
|
+
"token": 0
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"name": "TTL Active Low",
|
107
|
+
"token": 1
|
108
|
+
}
|
109
|
+
]
|
110
|
+
},
|
111
|
+
{
|
112
|
+
"name": "Shutter Open",
|
113
|
+
"token": 3,
|
114
|
+
"types": [
|
115
|
+
{
|
116
|
+
"name": "TTL Active High",
|
117
|
+
"token": 0
|
118
|
+
},
|
119
|
+
{
|
120
|
+
"name": "TTL Active Low",
|
121
|
+
"token": 1
|
122
|
+
}
|
123
|
+
]
|
124
|
+
},
|
125
|
+
{
|
126
|
+
"name": "Start Experiment",
|
127
|
+
"token": 0,
|
128
|
+
"types": [
|
129
|
+
{
|
130
|
+
"name": "TTL Active High",
|
131
|
+
"token": 0
|
132
|
+
},
|
133
|
+
{
|
134
|
+
"name": "TTL Active Low",
|
135
|
+
"token": 1
|
136
|
+
}
|
137
|
+
]
|
138
|
+
},
|
139
|
+
{
|
140
|
+
"name": "Ready For Trigger",
|
141
|
+
"token": 1,
|
142
|
+
"types": [
|
143
|
+
{
|
144
|
+
"name": "TTL Active High",
|
145
|
+
"token": 0
|
146
|
+
},
|
147
|
+
{
|
148
|
+
"name": "TTL Active Low",
|
149
|
+
"token": 1
|
150
|
+
}
|
151
|
+
]
|
152
|
+
}
|
153
|
+
],
|
154
|
+
"name": "Signal Output",
|
155
|
+
"token": 0
|
156
|
+
}
|
157
|
+
],
|
158
|
+
"speeds": [
|
159
|
+
{
|
160
|
+
"info": " 1 MHz Ultra ",
|
161
|
+
"token": 2
|
162
|
+
},
|
163
|
+
{
|
164
|
+
"info": "500 kHz Wrap",
|
165
|
+
"token": 127
|
166
|
+
},
|
167
|
+
{
|
168
|
+
"info": "45 kHz ",
|
169
|
+
"token": 0
|
170
|
+
},
|
171
|
+
{
|
172
|
+
"info": " 1 MHz ",
|
173
|
+
"token": 1
|
174
|
+
}
|
175
|
+
],
|
176
|
+
"supportedFeatures": {
|
177
|
+
"cf_3PositionSlit": "false",
|
178
|
+
"cf_CMOSOffsetCorrection": "false",
|
179
|
+
"cf_Cleaning": "true",
|
180
|
+
"cf_DSP": "false",
|
181
|
+
"cf_DSPBin2X": "false",
|
182
|
+
"cf_DelayAfterTrigger": "false",
|
183
|
+
"cf_Delays": "false",
|
184
|
+
"cf_EMCCD": "false",
|
185
|
+
"cf_EShutter": "false",
|
186
|
+
"cf_HDR": "false",
|
187
|
+
"cf_Image": "true",
|
188
|
+
"cf_MemorySlots": "true",
|
189
|
+
"cf_Metadata": "false",
|
190
|
+
"cf_MultipleExposeTimes": "false",
|
191
|
+
"cf_MultipleSensors": "false",
|
192
|
+
"cf_PulseSummation": "false",
|
193
|
+
"cf_ROIs": "true",
|
194
|
+
"cf_Signals": "true",
|
195
|
+
"cf_Spectra": "true",
|
196
|
+
"cf_TriggerQualifier": "false",
|
197
|
+
"cf_Triggers": "true"
|
198
|
+
},
|
199
|
+
"triggers": [
|
200
|
+
{
|
201
|
+
"events": [
|
202
|
+
{
|
203
|
+
"name": "Once - Start All",
|
204
|
+
"token": 0,
|
205
|
+
"types": [
|
206
|
+
{
|
207
|
+
"name": "TTL Falling Edge",
|
208
|
+
"token": 0
|
209
|
+
},
|
210
|
+
{
|
211
|
+
"name": "TTL Rising Edge",
|
212
|
+
"token": 1
|
213
|
+
}
|
214
|
+
]
|
215
|
+
},
|
216
|
+
{
|
217
|
+
"name": "Each - For Each Acq",
|
218
|
+
"token": 1,
|
219
|
+
"types": [
|
220
|
+
{
|
221
|
+
"name": "TTL Falling Edge",
|
222
|
+
"token": 0
|
223
|
+
},
|
224
|
+
{
|
225
|
+
"name": "TTL Rising Edge",
|
226
|
+
"token": 1
|
227
|
+
}
|
228
|
+
]
|
229
|
+
}
|
230
|
+
],
|
231
|
+
"name": "Trigger Input",
|
232
|
+
"token": 0
|
233
|
+
}
|
234
|
+
],
|
235
|
+
"version": "Syncerity Ver 1.001.7.1"
|
236
|
+
}
|
237
|
+
}
|
238
|
+
},
|
49
239
|
"ccd_getChipSize": {
|
50
240
|
"id": 1234,
|
51
241
|
"command": "ccd_getChipSize",
|
@@ -90,7 +280,7 @@
|
|
90
280
|
"command": "ccd_getFitParams",
|
91
281
|
"errors": [],
|
92
282
|
"results": {
|
93
|
-
"
|
283
|
+
"fitParameters": [0,1,0,0,0]
|
94
284
|
}
|
95
285
|
},
|
96
286
|
"ccd_setFitParams": {},
|
@@ -108,7 +298,7 @@
|
|
108
298
|
"command": "ccd_getTimerResolution",
|
109
299
|
"errors": [],
|
110
300
|
"results": {
|
111
|
-
"
|
301
|
+
"resolutionToken": 0
|
112
302
|
}
|
113
303
|
},
|
114
304
|
"ccd_setTimerResolution": {},
|
@@ -133,6 +323,40 @@
|
|
133
323
|
"count": 1
|
134
324
|
}
|
135
325
|
},
|
326
|
+
"ccd_getAcquisitionData": {
|
327
|
+
"command":"ccd_getAcquisitionData",
|
328
|
+
"errors":[],
|
329
|
+
"id":0,
|
330
|
+
"results": {
|
331
|
+
"acquisition":
|
332
|
+
[
|
333
|
+
{
|
334
|
+
"acqIndex":1,
|
335
|
+
"roi":
|
336
|
+
[
|
337
|
+
{
|
338
|
+
"roiIndex":1,
|
339
|
+
"xBinning":1,
|
340
|
+
"xData":
|
341
|
+
[
|
342
|
+
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999]
|
343
|
+
|
344
|
+
],
|
345
|
+
"xOrigin":0,
|
346
|
+
"xSize":1000,
|
347
|
+
"yBinning":200,
|
348
|
+
"yData": [
|
349
|
+
[607,605,609,608,605,604,606,607,608,607,606,604,604,606,608,605,606,608,608,606,605,608,607,608,606,607,607,605,608,607,607,607,605,608,608,605,607,606,610,605,605,605,604,606,605,604,604,604,607,606,607,606,605,609,603,607,604,605,603,607,603,606,606,606,606,606,606,604,603,606,606,607,604,607,604,606,605,605,604,607,608,606,605,606,605,603,606,606,607,605,607,608,605,604,607,604,606,607,606,604,606,604,604,606,604,608,603,606,605,606,608,603,604,606,605,607,607,605,606,604,606,606,606,606,606,608,605,606,605,607,607,606,607,607,606,604,604,607,602,605,604,606,606,607,606,605,606,606,608,608,607,605,604,607,606,606,605,605,606,604,606,605,603,606,606,608,607,603,606,605,606,604,605,606,603,607,602,604,606,606,605,606,606,604,606,607,603,603,609,605,605,605,606,606,606,605,605,607,605,608,608,606,606,607,607,608,604,608,604,606,607,605,608,604,605,607,603,607,607,607,606,607,606,605,609,606,603,607,605,605,605,606,604,608,608,607,608,608,606,606,605,611,609,605,604,605,606,608,607,604,607,605,607,604,606,604,609,608,606,606,606,607,605,608,605,606,606,605,607,604,606,606,608,606,606,607,605,604,606,606,606,606,607,608,607,605,604,604,605,606,607,608,604,605,607,606,608,607,606,604,606,605,609,605,608,607,608,608,606,608,608,607,606,607,608,607,606,605,607,607,609,606,605,607,607,606,606,607,607,607,606,607,605,607,608,607,606,609,609,607,607,605,607,609,603,608,607,605,608,605,608,607,607,607,608,607,607,606,609,607,609,608,607,608,605,605,606,607,608,607,608,607,605,606,609,608,606,607,607,606,608,606,606,608,606,607,608,607,606,606,606,606,605,609,607,608,608,610,605,608,609,607,606,605,609,607,608,606,606,609,606,607,609,606,608,607,606,604,608,606,605,606,608,609,604,604,605,607,607,608,607,610,605,606,606,608,606,607,606,605,606,607,606,606,609,607,606,606,607,607,607,606,606,609,609,607,606,607,607,607,605,606,607,606,605,605,607,608,607,605,608,608,603,606,606,607,607,607,608,607,607,607,606,605,608,608,607,604,606,607,608,607,609,605,608,605,606,607,606,607,607,606,607,606,605,604,607,605,608,605,607,606,605,608,605,607,606,607,607,605,606,608,606,607,606,609,605,607,608,606,606,608,604,606,606,608,605,604,605,607,607,609,604,605,607,603,608,604,605,608,607,609,603,609,606,607,606,608,605,606,605,608,606,606,605,606,605,606,605,606,605,607,608,609,607,606,606,609,607,606,604,606,607,607,606,606,608,607,608,605,606,609,610,606,609,606,606,606,607,610,606,607,607,604,605,606,607,606,612,606,605,606,607,608,604,606,608,608,607,607,609,609,605,607,605,607,606,607,606,607,607,607,605,606,605,605,605,607,605,608,606,608,607,607,608,605,607,607,605,608,609,606,604,606,608,606,607,604,605,606,607,607,607,607,605,606,605,606,606,608,607,604,607,609,606,608,606,606,608,606,608,605,604,606,606,604,607,607,605,606,605,605,607,607,606,604,607,608,604,608,605,607,606,605,607,608,603,606,607,606,609,606,609,606,607,607,607,606,605,605,606,606,608,605,605,606,606,607,608,606,606,605,604,603,604,608,606,609,608,606,606,609,607,606,604,606,607,607,605,606,605,609,605,606,606,606,609,608,607,606,608,607,607,608,609,609,604,603,606,607,607,606,605,606,608,607,605,605,602,606,609,607,605,607,604,606,606,607,607,606,606,608,606,607,608,606,607,607,608,607,607,606,607,608,606,606,608,607,606,607,608,607,605,608,606,606,605,605,606,606,606,604,607,608,604,605,606,604,605,605,608,608,605,604,607,606,604,606,608,609,606,605,606,605,606,606,608,608,607,608,608,607,607,609,606,606,607,608,604,605,607,606,606,607,606,605,606,606,607,607,607,608,604,606,605,604,608,606,607,608,606,606,607,608,608,604,606,607,607,608,605,605,604,605,603,607,605,606,607,608,606,604,606,606,608,605,607,609,606,606,606,607,609,606,606,607,605,605,608,606,607,603,605,607,604,606,606,605,607,609,607,608,607,606,606,603,605,605,606,605,608,606,606,607,609,609,604,606,604,608,605,605,607,607,606,605,606,605,605,605,607,606,606,603,606,605,608,607,607,604,605,606,608,605,607,606,608,606,614,608,605,608,604,606,608,607,606,607,607,608,605,610,607,607,607,609,605,609,607,607]
|
350
|
+
],
|
351
|
+
"yOrigin":0,
|
352
|
+
"ySize":200
|
353
|
+
}
|
354
|
+
]
|
355
|
+
}
|
356
|
+
],
|
357
|
+
"timestamp":"2024.04.22 15:07:50.096"
|
358
|
+
}
|
359
|
+
},
|
136
360
|
"ccd_setAcqCount": {},
|
137
361
|
"ccd_getCleanCount": {
|
138
362
|
"command": "ccd_getCleanCount",
|
@@ -157,12 +381,37 @@
|
|
157
381
|
"errors": [],
|
158
382
|
"id": 0,
|
159
383
|
"results": {
|
160
|
-
"
|
161
|
-
"
|
162
|
-
"
|
384
|
+
"address": -1,
|
385
|
+
"event": -1,
|
386
|
+
"signalType": -1
|
163
387
|
}
|
164
388
|
},
|
165
389
|
"ccd_setTriggerIn": {},
|
166
|
-
"ccd_getSignalOut": {
|
167
|
-
|
390
|
+
"ccd_getSignalOut": {
|
391
|
+
"command": "ccd_getSignalOut",
|
392
|
+
"errors": [],
|
393
|
+
"id": 1234,
|
394
|
+
"results": {
|
395
|
+
"address": 0,
|
396
|
+
"event": 0,
|
397
|
+
"signalType":0
|
398
|
+
}
|
399
|
+
},
|
400
|
+
"ccd_setSignalOut": {},
|
401
|
+
"ccd_getAcquisitionReady": {
|
402
|
+
"command": "ccd_getAcquisitionReady",
|
403
|
+
"errors": [],
|
404
|
+
"id": 1234,
|
405
|
+
"results": {
|
406
|
+
"ready": true
|
407
|
+
}
|
408
|
+
},
|
409
|
+
"ccd_getAcquisitionBusy": {
|
410
|
+
"command": "ccd_getAcquisitionBusy",
|
411
|
+
"errors": [],
|
412
|
+
"id": 1234,
|
413
|
+
"results": {
|
414
|
+
"isBusy": false
|
415
|
+
}
|
416
|
+
}
|
168
417
|
}
|
@@ -9,15 +9,19 @@
|
|
9
9
|
"errors": []
|
10
10
|
},
|
11
11
|
"mono_list": {
|
12
|
-
"id": 1234,
|
13
12
|
"command": "mono_list",
|
14
|
-
"
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
"errors": [],
|
14
|
+
"id": 0,
|
15
|
+
"results":
|
16
|
+
{
|
17
|
+
"devices": [
|
18
|
+
{
|
19
|
+
"deviceType": "HORIBA Scientific iHR",
|
20
|
+
"index": 0,
|
21
|
+
"serialNumber":"1745B-2017-iHR320 "
|
22
|
+
}
|
18
23
|
]
|
19
|
-
}
|
20
|
-
"errors": []
|
24
|
+
}
|
21
25
|
},
|
22
26
|
"mono_listCount": {
|
23
27
|
"id": 1234,
|
@@ -61,10 +65,33 @@
|
|
61
65
|
"mono_getConfig": {
|
62
66
|
"id": 1234,
|
63
67
|
"command": "mono_getConfig",
|
64
|
-
"results":{
|
68
|
+
"results": {
|
69
|
+
"configuration": {
|
70
|
+
"filterWheels": [
|
71
|
+
{"location":1},
|
72
|
+
{"location":2}
|
73
|
+
],
|
74
|
+
"gratings": [
|
75
|
+
{"blaze":0,"grooveDensity":1800,"positionIndex":0},
|
76
|
+
{"blaze":0,"grooveDensity":1200,"positionIndex":1},
|
77
|
+
{"blaze":0,"grooveDensity":300,"positionIndex":2}
|
78
|
+
],
|
79
|
+
"mirrors": [
|
80
|
+
{"blaze":0,"grooveDensity":1800,"positionIndex":0},
|
81
|
+
{"blaze":0,"grooveDensity":1200,"positionIndex":1},
|
82
|
+
{"blaze":0,"grooveDensity":300,"positionIndex":2}
|
83
|
+
],
|
84
|
+
"monoModel":"iHR320",
|
85
|
+
"ports": [
|
86
|
+
{"monoPortLocation":1,"slitType":2},
|
87
|
+
{"monoPortLocation":2,"slitType":2},
|
88
|
+
{"monoPortLocation":4,"slitType":2}
|
89
|
+
],
|
90
|
+
"procuctId":"257",
|
91
|
+
"serialNumber":""
|
92
|
+
}
|
65
93
|
},
|
66
94
|
"errors": []
|
67
|
-
|
68
95
|
},
|
69
96
|
"mono_setConfig": {},
|
70
97
|
"mono_getPosition": {
|
@@ -160,7 +187,8 @@
|
|
160
187
|
"id": 1234,
|
161
188
|
"command": "mono_getShutterStatus",
|
162
189
|
"results": {
|
163
|
-
"
|
190
|
+
"shutter 1": 0,
|
191
|
+
"shutter 2": 1
|
164
192
|
},
|
165
193
|
"errors": []
|
166
194
|
},
|
@@ -20,6 +20,10 @@ class MonochromatorsDiscovery(AbstractDeviceDiscovery):
|
|
20
20
|
async def execute(self, error_on_no_device: bool = False) -> None:
|
21
21
|
"""
|
22
22
|
Discovers the connected Monochromators and saves them internally.
|
23
|
+
|
24
|
+
Raises:
|
25
|
+
Exception: When no Monochromators are discovered and that `error_on_no_device` is set. Or when there is an
|
26
|
+
issue parsing the Monochromators list
|
23
27
|
"""
|
24
28
|
if not self._communicator.opened():
|
25
29
|
await self._communicator.open()
|
@@ -29,18 +33,21 @@ class MonochromatorsDiscovery(AbstractDeviceDiscovery):
|
|
29
33
|
raise Exception('No Monochromators connected')
|
30
34
|
|
31
35
|
response = await self._communicator.request_with_response(Command('mono_list', {}))
|
32
|
-
|
36
|
+
|
37
|
+
raw_device_list = response.results
|
33
38
|
self._monochromators = self._parse_monos(raw_device_list)
|
34
|
-
logger.info(f'Found {len(self._monochromators)} Monochromator devices
|
39
|
+
logger.info(f'Found {len(self._monochromators)} Monochromator devices')
|
35
40
|
|
36
41
|
def _parse_monos(self, raw_device_list: dict[str, Any]) -> list[Monochromator]:
|
37
|
-
detected_monos = []
|
38
|
-
for
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
detected_monos: list[Monochromator] = []
|
43
|
+
for device in raw_device_list['devices']:
|
44
|
+
try:
|
45
|
+
logger.debug(f'Parsing Monochromator: {device}')
|
46
|
+
mono = Monochromator(device['index'], self._communicator, self._error_db)
|
47
|
+
logger.info(f'Detected Monochromator: {device["deviceType"]}')
|
48
|
+
detected_monos.append(mono)
|
49
|
+
except Exception as e:
|
50
|
+
logger.error(f'Error while parsing Monochromator: {e}')
|
44
51
|
|
45
52
|
return detected_monos
|
46
53
|
|