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
@@ -1,14 +1,15 @@
|
|
1
|
-
from enum import Enum
|
2
1
|
from types import TracebackType
|
3
|
-
from typing import Any, Optional,
|
2
|
+
from typing import Any, Optional, final
|
4
3
|
|
5
|
-
import pint
|
6
4
|
from loguru import logger
|
7
5
|
from overrides import override
|
8
6
|
|
9
|
-
from horiba_sdk import ureg
|
10
7
|
from horiba_sdk.communication import Response
|
8
|
+
from horiba_sdk.core.acquisition_format import AcquisitionFormat
|
9
|
+
from horiba_sdk.core.clean_count_mode import CleanCountMode
|
11
10
|
from horiba_sdk.core.resolution import Resolution
|
11
|
+
from horiba_sdk.core.timer_resolution import TimerResolution
|
12
|
+
from horiba_sdk.core.x_axis_conversion_type import XAxisConversionType
|
12
13
|
from horiba_sdk.icl_error import AbstractErrorDB
|
13
14
|
from horiba_sdk.sync.communication.abstract_communicator import AbstractCommunicator
|
14
15
|
from horiba_sdk.sync.devices.single_devices.abstract_device import AbstractDevice
|
@@ -22,17 +23,12 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
22
23
|
should be used to access the detected CCDs on the system.
|
23
24
|
"""
|
24
25
|
|
25
|
-
@final
|
26
|
-
class XAxisConversionType(Enum):
|
27
|
-
NONE = 0
|
28
|
-
FROM_CCD_FIRMWARE = 1
|
29
|
-
FROM_ICL_SETTINGS_INI = 2
|
30
|
-
|
31
26
|
def __init__(self, device_id: int, communicator: AbstractCommunicator, error_db: AbstractErrorDB) -> None:
|
32
27
|
super().__init__(device_id, communicator, error_db)
|
33
28
|
|
34
29
|
def __enter__(self) -> 'ChargeCoupledDevice':
|
35
30
|
self.open()
|
31
|
+
self._config: dict[str, Any] = self.get_configuration()
|
36
32
|
return self
|
37
33
|
|
38
34
|
def __exit__(
|
@@ -41,8 +37,7 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
41
37
|
exc_value: Optional[BaseException],
|
42
38
|
traceback: Optional[TracebackType],
|
43
39
|
) -> None:
|
44
|
-
|
45
|
-
if not is_open:
|
40
|
+
if not self.is_open():
|
46
41
|
logger.debug('CCD is already closed')
|
47
42
|
return
|
48
43
|
|
@@ -76,88 +71,168 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
76
71
|
response: Response = super()._execute_command('ccd_isOpen', {'index': self._id})
|
77
72
|
return bool(response.results['open'])
|
78
73
|
|
79
|
-
def
|
80
|
-
"""
|
74
|
+
def restart(self) -> None:
|
75
|
+
"""Restarts the charge coupled device.
|
76
|
+
|
77
|
+
This command only works if the camera has been opened before.
|
78
|
+
The connection to the camera stays open after the restart.
|
79
|
+
|
80
|
+
Raises:
|
81
|
+
Exception: When an error occurred on the device side
|
82
|
+
"""
|
83
|
+
super()._execute_command('ccd_restart', {'index': self._id})
|
84
|
+
|
85
|
+
def get_configuration(self) -> dict[str, Any]:
|
86
|
+
"""Returns the configuration of the CCD
|
81
87
|
|
82
88
|
Returns:
|
83
|
-
|
89
|
+
dict[str, Any]: Configuration of the CCD
|
84
90
|
|
85
91
|
Raises:
|
86
92
|
Exception: When an error occurred on the device side
|
87
93
|
"""
|
88
|
-
response: Response = super()._execute_command('
|
89
|
-
return
|
94
|
+
response: Response = super()._execute_command('ccd_getConfig', {'index': self._id})
|
95
|
+
return response.results['configuration']
|
90
96
|
|
91
|
-
def
|
92
|
-
"""
|
97
|
+
def get_gain_token(self) -> int:
|
98
|
+
"""Returns the current gain token.
|
93
99
|
|
94
100
|
Returns:
|
95
|
-
|
101
|
+
int: Gain token of the ccd
|
96
102
|
|
97
103
|
Raises:
|
98
104
|
Exception: When an error occurred on the device side
|
99
105
|
"""
|
100
|
-
response: Response = super()._execute_command('
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
106
|
+
response: Response = super()._execute_command('ccd_getGain', {'index': self._id})
|
107
|
+
gain: int = int(response.results['token'])
|
108
|
+
return gain
|
109
|
+
|
110
|
+
def set_gain(self, gain_token: int) -> None:
|
111
|
+
"""Sets the gain of the CCD
|
112
|
+
|
113
|
+
Args:
|
114
|
+
gain_token (int): Token of the desired gain
|
115
|
+
|
116
|
+
Raises:
|
117
|
+
Exception: When an error occurred on the device side
|
118
|
+
"""
|
119
|
+
super()._execute_command('ccd_setGain', {'index': self._id, 'token': gain_token})
|
105
120
|
|
106
|
-
def
|
107
|
-
"""
|
121
|
+
def get_speed_token(self) -> int:
|
122
|
+
"""Returns the speed token.
|
108
123
|
|
109
124
|
Returns:
|
110
|
-
|
125
|
+
int: Speed token of the CCD.
|
111
126
|
|
112
127
|
Raises:
|
113
128
|
Exception: When an error occurred on the device side
|
114
129
|
"""
|
115
130
|
response: Response = super()._execute_command('ccd_getSpeed', {'index': self._id})
|
116
|
-
|
131
|
+
speed_token: int = int(response.results['token'])
|
132
|
+
return speed_token
|
117
133
|
|
118
|
-
def
|
119
|
-
"""
|
134
|
+
def set_speed(self, speed_token: int) -> None:
|
135
|
+
"""Sets the speed of the CCD
|
136
|
+
|
137
|
+
Args:
|
138
|
+
speed_token (int): Token of the desired speed.
|
139
|
+
|
140
|
+
Raises:
|
141
|
+
Exception: When an error occurred on the device side
|
142
|
+
"""
|
143
|
+
super()._execute_command('ccd_setSpeed', {'index': self._id, 'token': speed_token})
|
144
|
+
|
145
|
+
def get_parallel_speed(self) -> int:
|
146
|
+
"""Gets the current parallel speed token
|
120
147
|
|
121
148
|
Returns:
|
122
|
-
|
149
|
+
int: current parallel speed token
|
150
|
+
|
123
151
|
Raises:
|
124
152
|
Exception: When an error occurred on the device side
|
125
153
|
"""
|
126
|
-
response: Response = super()._execute_command('
|
127
|
-
|
128
|
-
return
|
154
|
+
response: Response = super()._execute_command('ccd_getParallelSpeed', {'index': self._id})
|
155
|
+
parallel_speed_token: int = int(response.results['token'])
|
156
|
+
return parallel_speed_token
|
129
157
|
|
130
|
-
def
|
131
|
-
"""Sets the
|
158
|
+
def set_parallel_speed(self, parallel_speed_token: int) -> None:
|
159
|
+
"""Sets the desired parallel speed token
|
132
160
|
|
133
|
-
Args:
|
134
|
-
exposure_time_ms (int): Exposure time in ms
|
135
161
|
Raises:
|
136
162
|
Exception: When an error occurred on the device side
|
137
163
|
"""
|
164
|
+
super()._execute_command('ccd_setParallelSpeed', {'index': self._id, 'token': parallel_speed_token})
|
138
165
|
|
139
|
-
|
166
|
+
def get_fit_parameters(self) -> list[int]:
|
167
|
+
"""Returns the fit parameters of the CCD
|
140
168
|
|
141
|
-
|
142
|
-
|
169
|
+
Returns:
|
170
|
+
List[int]: Fit parameters
|
171
|
+
|
172
|
+
Raises:
|
173
|
+
Exception: When an error occurred on the device side
|
174
|
+
"""
|
175
|
+
response: Response = super()._execute_command('ccd_getFitParams', {'index': self._id})
|
176
|
+
fit_params: list[int] = response.results['fitParameters']
|
177
|
+
return fit_params
|
178
|
+
|
179
|
+
def set_fit_parameters(self, fit_params: list[int]) -> None:
|
180
|
+
"""Sets the fit parameters of the CCD
|
181
|
+
|
182
|
+
Args:
|
183
|
+
fit_params (List[int]): Fit parameters
|
184
|
+
|
185
|
+
Raises:
|
186
|
+
Exception: When an error occurred on the device side
|
187
|
+
"""
|
188
|
+
fit_params_str: str = ','.join(map(str, fit_params))
|
189
|
+
super()._execute_command('ccd_setFitParams', {'index': self._id, 'params': fit_params_str})
|
190
|
+
|
191
|
+
def get_timer_resolution(self) -> TimerResolution:
|
192
|
+
"""Returns the timer resolution of the CCD in microseconds [μs]
|
143
193
|
|
144
194
|
Returns:
|
145
|
-
|
195
|
+
int: Timer resolution in microseconds [μs]
|
196
|
+
|
146
197
|
Raises:
|
147
198
|
Exception: When an error occurred on the device side
|
148
199
|
"""
|
149
|
-
response: Response = super()._execute_command('
|
150
|
-
|
200
|
+
response: Response = super()._execute_command('ccd_getTimerResolution', {'index': self._id})
|
201
|
+
timer_resolution: int = int(response.results['resolutionToken'])
|
202
|
+
return TimerResolution(timer_resolution)
|
203
|
+
|
204
|
+
def set_timer_resolution(self, timer_resolution: TimerResolution) -> None:
|
205
|
+
"""Sets the timer resolution of the CCD
|
206
|
+
|
207
|
+
.. note:: The timer resolution value of 1 microsecond is not supported by all CCDs.
|
208
|
+
|
209
|
+
Args:
|
210
|
+
timer_resolution (int): Timer resolution
|
211
|
+
|
212
|
+
Raises:
|
213
|
+
Exception: When an error occurred on the device side
|
214
|
+
"""
|
215
|
+
super()._execute_command(
|
216
|
+
'ccd_setTimerResolution', {'index': self._id, 'resolutionToken': timer_resolution.value}
|
217
|
+
)
|
151
218
|
|
152
|
-
def
|
153
|
-
"""
|
219
|
+
def set_acquisition_format(self, number_of_rois: int, acquisition_format: AcquisitionFormat) -> None:
|
220
|
+
"""Sets the acquisition format and the number of ROIs (Regions of Interest) or areas.
|
221
|
+
|
222
|
+
After using this command to set the number of ROIs and format, the set_region_of_interest function
|
223
|
+
should be used to define each ROI. Note: The Crop and Fast Kinetics acquisition formats are not
|
224
|
+
supported by every CCD.
|
154
225
|
|
155
226
|
Args:
|
156
|
-
|
227
|
+
number_of_rois (int): Number of regions of interest
|
228
|
+
acquisition_format (AcquisitionFormat): Acquisition format
|
229
|
+
|
157
230
|
Raises:
|
158
231
|
Exception: When an error occurred on the device side
|
159
232
|
"""
|
160
|
-
super()._execute_command(
|
233
|
+
super()._execute_command(
|
234
|
+
'ccd_setAcqFormat', {'index': self._id, 'format': acquisition_format.value, 'numberOfRois': number_of_rois}
|
235
|
+
)
|
161
236
|
|
162
237
|
def set_region_of_interest(
|
163
238
|
self,
|
@@ -173,7 +248,7 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
173
248
|
an example json command looks like this:
|
174
249
|
|
175
250
|
Args:
|
176
|
-
roi_index (int, optional):
|
251
|
+
roi_index (int, optional): One based index of the region of interest. Defaults to 1.
|
177
252
|
x_origin (int, optional): X origin of the region of interest. Defaults to 0.
|
178
253
|
y_origin (int, optional): Y origin of the region of interest. Defaults to 0.
|
179
254
|
x_size (int, optional): X size of the region of interest. Defaults to 1024.
|
@@ -198,22 +273,402 @@ class ChargeCoupledDevice(AbstractDevice):
|
|
198
273
|
},
|
199
274
|
)
|
200
275
|
|
201
|
-
def
|
202
|
-
"""
|
203
|
-
|
204
|
-
|
205
|
-
|
276
|
+
def set_x_axis_conversion_type(self, conversion_type: XAxisConversionType) -> None:
|
277
|
+
"""Sets the X-axis pixel conversion type to be used when retrieving the acquisition data with the
|
278
|
+
ccd_getAcquisitionData command.
|
279
|
+
0 = None (default)
|
280
|
+
1 = CCD FIT parameters contained in the CCD firmware
|
281
|
+
2 = Mono Wavelength parameters contained in the icl_settings.ini file
|
282
|
+
|
283
|
+
Args:
|
284
|
+
conversion_type (XAxisConversionType): Conversion type Integer. The X-axis pixel conversion type to be used.
|
285
|
+
|
286
|
+
"""
|
287
|
+
super()._execute_command('ccd_setXAxisConversionType', {'index': self._id, 'type': conversion_type.value})
|
288
|
+
|
289
|
+
def get_x_axis_conversion_type(self) -> XAxisConversionType:
|
290
|
+
"""Gets the conversion type of the x axis.
|
291
|
+
0 = None (default)
|
292
|
+
1 = CCD FIT parameters contained in the CCD firmware
|
293
|
+
2 = Mono Wavelength parameters contained in the icl_settings.ini file
|
294
|
+
"""
|
295
|
+
response: Response = super()._execute_command('ccd_getXAxisConversionType', {'index': self._id})
|
296
|
+
return XAxisConversionType(response.results['type'])
|
297
|
+
|
298
|
+
def set_acquisition_count(self, count: int) -> None:
|
299
|
+
"""Sets the number of acquisition measurements to be performed sequentially by the hardware.
|
300
|
+
|
301
|
+
A count > 1 is commonly referred to as "MultiAcq".
|
302
|
+
|
303
|
+
Args:
|
304
|
+
count (int): The number of acquisition measurements.
|
305
|
+
"""
|
306
|
+
super()._execute_command('ccd_setAcqCount', {'index': self._id, 'count': count})
|
307
|
+
|
308
|
+
def get_acquisition_count(self) -> int:
|
309
|
+
"""Gets the number of acquisitions to be performed. The acquisition count is used to perform multiple
|
310
|
+
acquisitions in a row.
|
311
|
+
"""
|
312
|
+
response: Response = super()._execute_command('ccd_getAcqCount', {'index': self._id})
|
313
|
+
return int(response.results['count'])
|
314
|
+
|
315
|
+
def get_clean_count(self) -> tuple[int, CleanCountMode]:
|
316
|
+
"""Gets the number of cleans to be performed prior to measurement.
|
317
|
+
|
318
|
+
Returns:
|
319
|
+
Tuple[int, CleanCountMode]:
|
320
|
+
count: Number of cleans,
|
321
|
+
mode: Specifies how the cleans will be performed.
|
322
|
+
"""
|
323
|
+
response: Response = super()._execute_command('ccd_getCleanCount', {'index': self._id})
|
324
|
+
count: int = int(response.results['count'])
|
325
|
+
mode: CleanCountMode = CleanCountMode(response.results['mode'])
|
326
|
+
return count, mode
|
327
|
+
|
328
|
+
def set_clean_count(self, count: int, mode: CleanCountMode) -> None:
|
329
|
+
"""Sets the clean count mode of the CCD and the according mode
|
330
|
+
Args:
|
331
|
+
count (int): The number of acquisitions to be performed.
|
332
|
+
mode (CleanCountMode): The mode of the clean count
|
333
|
+
"""
|
334
|
+
super()._execute_command('ccd_setCleanCount', {'index': self._id, 'count': count, 'mode': mode.value})
|
335
|
+
|
336
|
+
def get_acquisition_data_size(self) -> int:
|
337
|
+
"""Returns the size of the acquisition data of the CCD
|
338
|
+
|
339
|
+
Returns:
|
340
|
+
int: Size of the data
|
341
|
+
|
342
|
+
Raises:
|
343
|
+
Exception: When an error occurred on the device side
|
344
|
+
"""
|
345
|
+
response: Response = super()._execute_command('ccd_getDataSize', {'index': self._id})
|
346
|
+
return int(response.results['size'])
|
347
|
+
|
348
|
+
def get_chip_temperature(self) -> float:
|
349
|
+
"""Chip temperature of the CCD.
|
350
|
+
|
351
|
+
Returns:
|
352
|
+
float: chip's temperature in degree Celsius
|
353
|
+
|
354
|
+
Raises:
|
355
|
+
Exception: When an error occurred on the device side
|
356
|
+
"""
|
357
|
+
response: Response = super()._execute_command('ccd_getChipTemperature', {'index': self._id})
|
358
|
+
return float(response.results['temperature'])
|
359
|
+
|
360
|
+
def get_chip_size(self) -> Resolution:
|
361
|
+
"""Chip resolution of the CCD.
|
362
|
+
|
363
|
+
Returns:
|
364
|
+
Resolution: chip resolution (width, height)
|
365
|
+
|
366
|
+
Raises:
|
367
|
+
Exception: When an error occurred on the device side
|
368
|
+
"""
|
369
|
+
response: Response = super()._execute_command('ccd_getChipSize', {'index': self._id})
|
370
|
+
width: int = response.results['x']
|
371
|
+
height: int = response.results['y']
|
372
|
+
resolution: Resolution = Resolution(width, height)
|
373
|
+
return resolution
|
374
|
+
|
375
|
+
def get_exposure_time(self) -> int:
|
376
|
+
"""Returns the exposure time in ms
|
377
|
+
|
378
|
+
Returns:
|
379
|
+
pint.Quantity: Exposure time in ms
|
380
|
+
Raises:
|
381
|
+
Exception: When an error occurred on the device side
|
382
|
+
"""
|
383
|
+
response: Response = super()._execute_command('ccd_getExposureTime', {'index': self._id})
|
384
|
+
exposure = int(response.results['time'])
|
385
|
+
return exposure
|
386
|
+
|
387
|
+
def set_exposure_time(self, exposure_time: int) -> None:
|
388
|
+
"""Sets the exposure time in timer resolution units (1us or 1000us)
|
389
|
+
|
390
|
+
Examples:
|
391
|
+
- If exposure_time is set to 50, and the timer resolution value is 1000, the CCD exposure time
|
392
|
+
(integration time) = 50 milliseconds.
|
393
|
+
- If exposure_time is set to 50, and the timer resolution value is 1, the CCD exposure time
|
394
|
+
(integration time) = 50 microseconds.
|
395
|
+
|
396
|
+
Args:
|
397
|
+
exposure_time (int): Exposure time in timer resolution units (1us or 1000us)
|
398
|
+
Raises:
|
399
|
+
Exception: When an error occurred on the device side
|
400
|
+
"""
|
401
|
+
|
402
|
+
super()._execute_command('ccd_setExposureTime', {'index': self._id, 'time': exposure_time})
|
403
|
+
|
404
|
+
def get_trigger_input(self) -> tuple[bool, int, int, int]:
|
405
|
+
"""This command is used to get the current setting of the input trigger.
|
406
|
+
|
407
|
+
The address, event, and signalType parameters are used to define the input trigger based on the
|
408
|
+
supported options of that particular CCD.
|
409
|
+
|
410
|
+
The supported trigger options are retrieved using the get_configuration function, and begin with the
|
411
|
+
“Triggers” string contained in the configuration.
|
412
|
+
|
413
|
+
Returns:
|
414
|
+
Tuple[bool, int, int, int]:
|
415
|
+
enabled: Specifies if the signal is enabled (e.g. False = Disabled),
|
416
|
+
address: used to specify where the trigger is located. (e.g. 0 = Trigger Input).
|
417
|
+
Note: Value of -1 indicates that the input trigger is disabled,
|
418
|
+
event: used to specify when the trigger event should occur. (e.g. 0 = Once - Start All)
|
419
|
+
Note: Value of -1 indicates that the input trigger is disabled,
|
420
|
+
signal type: used to specify how the signal will cause the input trigger. (e.g. 0 = TTL Falling Edge)
|
421
|
+
Note: Value of -1 indicates that the input trigger is disabled,
|
422
|
+
|
423
|
+
Raises:
|
424
|
+
Exception: When an error occurred on the device side
|
425
|
+
"""
|
426
|
+
response: Response = super()._execute_command('ccd_getTriggerIn', {'index': self._id})
|
427
|
+
address = int(response.results['address'])
|
428
|
+
event = int(response.results['event'])
|
429
|
+
signal_type = int(response.results['signalType'])
|
430
|
+
enabled = address > -1 and event > -1 and signal_type > -1
|
431
|
+
return enabled, address, event, signal_type
|
432
|
+
|
433
|
+
def set_trigger_input(self, enabled: bool, address: int, event: int, signal_type: int) -> None:
|
434
|
+
"""This command is used to enable or disable the trigger input.
|
435
|
+
|
436
|
+
When enabling the trigger input, the address, event, and signalType parameters are used to define
|
437
|
+
the input trigger based on the supported options of that particular CCD.
|
438
|
+
|
439
|
+
The supported trigger options are retrieved using the get_configuration function, and begin with the
|
440
|
+
“Triggers” string contained in the configuration.
|
441
|
+
|
442
|
+
Args:
|
443
|
+
enabled (bool): Enable or disable the trigger input. Note: When disabling the input trigger,
|
444
|
+
the address, event, and signalType parameters are ignored.
|
445
|
+
address (int): Used to specify where the trigger is located. (e.g. 0 = Trigger Input)
|
446
|
+
event (int): Used to specify when the trigger event should occur. (e.g. 0 = Once - Start All)
|
447
|
+
signal_type (int): Used to specify how the signal will cause the input trigger. (e.g. 0 = TTL Falling Edge)
|
448
|
+
|
449
|
+
Raises:
|
450
|
+
Exception: When an error occurred on the device side
|
451
|
+
"""
|
452
|
+
if not enabled:
|
453
|
+
address = -1
|
454
|
+
event = -1
|
455
|
+
signal_type = -1
|
456
|
+
|
457
|
+
super()._execute_command(
|
458
|
+
'ccd_setTriggerIn',
|
459
|
+
{'index': self._id, 'enable': enabled, 'address': address, 'event': event, 'signalType': signal_type},
|
460
|
+
)
|
461
|
+
return
|
462
|
+
|
463
|
+
found_triggers = [trigger for trigger in self._config['triggers'] if trigger['token'] == address]
|
464
|
+
if not found_triggers:
|
465
|
+
raise Exception(f'Trigger address {address} not found in the configuration')
|
466
|
+
|
467
|
+
found_events = [
|
468
|
+
trigger_event for trigger_event in found_triggers[0]['events'] if trigger_event['token'] == event
|
469
|
+
]
|
470
|
+
if not found_events:
|
471
|
+
raise Exception(f'Trigger event {event} not found in the configuration')
|
472
|
+
|
473
|
+
found_signal_types = [signal for signal in found_events[0]['types'] if signal['token'] == signal_type]
|
474
|
+
if not found_signal_types:
|
475
|
+
raise Exception(f'Trigger signal type {signal_type} not found in the configuration')
|
476
|
+
|
477
|
+
super()._execute_command(
|
478
|
+
'ccd_setTriggerIn',
|
479
|
+
{'index': self._id, 'enable': enabled, 'address': address, 'event': event, 'signalType': signal_type},
|
480
|
+
)
|
481
|
+
|
482
|
+
def get_signal_output(self) -> tuple[bool, int, int, int]:
|
483
|
+
"""This command is used to get the current setting of the signal output.
|
484
|
+
|
485
|
+
The address, event, and signalType parameters are used to define the signal based on the supported
|
486
|
+
options of that particular CCD.
|
487
|
+
|
488
|
+
The supported signal options are retrieved using the get_configuration command, and begin with the
|
489
|
+
“Signals” string contained in the configuration.
|
490
|
+
|
491
|
+
Returns:
|
492
|
+
Tuple[bool, int, int, int]:
|
493
|
+
enabled: Specifies if the signal is enabled (e.g. False = Disabled),
|
494
|
+
address: Used to specify where the signal is located (e.g. 0 = Signal Output),
|
495
|
+
Note: Value of -1 indicates that the signal output is disabled,
|
496
|
+
event: Used to specify when the signal event should occur. (e.g. 3 = Shutter Open)
|
497
|
+
Note: Value of -1 indicates that the signal output is disabled,
|
498
|
+
signal type: how the signal will cause the event. (e.g. 0 = TTL Active High)
|
499
|
+
Note: Value of -1 indicates that the signal output is disabled,
|
500
|
+
|
501
|
+
Raises:
|
502
|
+
Exception: When an error occurred on the device side
|
503
|
+
"""
|
504
|
+
response: Response = super()._execute_command('ccd_getSignalOut', {'index': self._id})
|
505
|
+
address = int(response.results['address'])
|
506
|
+
event = int(response.results['event'])
|
507
|
+
signal_type = int(response.results['signalType'])
|
508
|
+
enabled = address > -1 and event > -1 and signal_type > -1
|
509
|
+
return enabled, address, event, signal_type
|
510
|
+
|
511
|
+
def set_signal_output(self, enabled: bool, address: int, event: int, signal_type: int) -> None:
|
512
|
+
"""This command is used to enable or disable the signal output.
|
513
|
+
|
514
|
+
When enabling the signal output, the address, event, and signalType parameters are used to
|
515
|
+
define the signal based on the supported options of that particular CCD.
|
516
|
+
|
517
|
+
The supported signal options are retrieved using the ccd_getConfig command, and begin with the
|
518
|
+
“Signals” string contained in the configuration.
|
519
|
+
|
520
|
+
Args:
|
521
|
+
enabled (bool): Enable or disable the signal output. Note: When disabling the signal output,
|
522
|
+
the address, event, and signal_type parameters are ignored.
|
523
|
+
address (int): Used to specify where the signal is located (e.g. 0 = Signal Output)
|
524
|
+
event (int): Used to specify when the signal event should occur. (e.g. 3 = Shutter Open)
|
525
|
+
signal_type (int): How the signal will cause the event. (e.g. 0 = TTL Active High)
|
526
|
+
|
527
|
+
"""
|
528
|
+
if not enabled:
|
529
|
+
address = -1
|
530
|
+
event = -1
|
531
|
+
signal_type = -1
|
532
|
+
|
533
|
+
super()._execute_command(
|
534
|
+
'ccd_setSignalOut',
|
535
|
+
{'index': self._id, 'enable': enabled, 'address': address, 'event': event, 'signalType': signal_type},
|
536
|
+
)
|
537
|
+
return
|
538
|
+
|
539
|
+
found_triggers = [trigger for trigger in self._config['signals'] if trigger['token'] == address]
|
540
|
+
if not found_triggers:
|
541
|
+
raise Exception(f'Signal address {address} not found in the configuration')
|
542
|
+
|
543
|
+
found_events = [
|
544
|
+
trigger_event for trigger_event in found_triggers[0]['events'] if trigger_event['token'] == event
|
545
|
+
]
|
546
|
+
if not found_events:
|
547
|
+
raise Exception(f'Signal event {event} not found in the configuration')
|
548
|
+
|
549
|
+
found_signal_types = [signal for signal in found_events[0]['types'] if signal['token'] == signal_type]
|
550
|
+
if not found_signal_types:
|
551
|
+
raise Exception(f'Signal type {signal_type} not found in the configuration')
|
552
|
+
|
553
|
+
super()._execute_command(
|
554
|
+
'ccd_setSignalOut',
|
555
|
+
{'index': self._id, 'enable': enabled, 'address': address, 'event': event, 'signalType': signal_type},
|
556
|
+
)
|
557
|
+
|
558
|
+
def get_acquisition_ready(self) -> bool:
|
559
|
+
"""Returns true if the CCD is ready to acquire
|
560
|
+
|
561
|
+
Returns:
|
562
|
+
bool: True if the CCD is ready to acquire
|
563
|
+
Raises:
|
564
|
+
Exception: When an error occurred on the device side
|
565
|
+
"""
|
566
|
+
response: Response = super()._execute_command('ccd_getAcquisitionReady', {'index': self._id})
|
567
|
+
return bool(response.results['ready'])
|
568
|
+
|
569
|
+
def acquisition_start(self, open_shutter: bool) -> None:
|
570
|
+
"""Starts an acquisition that has been set up according to the previously defined acquisition parameters.
|
571
|
+
|
572
|
+
Note: To specify the acquisiton parameters please see set_region_of_interest, set_x_axis_conversion_type.
|
573
|
+
If there are no acquisition parameters set at the time of acquisition it may result in no data being generated.
|
574
|
+
|
575
|
+
Args:
|
576
|
+
open_shutter (bool): Whether the shutter of the camera should be open during the acquisition.
|
577
|
+
Raises:
|
578
|
+
Exception: When an error occurred on the device side
|
579
|
+
"""
|
580
|
+
super()._execute_command('ccd_acquisitionStart', {'index': self._id, 'openShutter': open_shutter})
|
206
581
|
|
207
582
|
def get_acquisition_busy(self) -> bool:
|
208
583
|
"""Returns true if the CCD is busy with the acquisition"""
|
209
584
|
response: Response = super()._execute_command('ccd_getAcquisitionBusy', {'index': self._id})
|
210
585
|
return bool(response.results['isBusy'])
|
211
586
|
|
212
|
-
def
|
213
|
-
"""
|
214
|
-
super()._execute_command('
|
587
|
+
def acquisition_abort(self) -> None:
|
588
|
+
"""Stops the acquisition of the CCD"""
|
589
|
+
super()._execute_command('ccd_acquisitionStart', {'index': self._id})
|
215
590
|
|
216
|
-
def
|
217
|
-
"""
|
218
|
-
|
219
|
-
|
591
|
+
def get_acquisition_data(self) -> dict[Any, Any]:
|
592
|
+
"""Retrieves data from the last acquisition.
|
593
|
+
|
594
|
+
The acquisition description string consists of the following information:
|
595
|
+
- acqIndex: Acquisition number
|
596
|
+
- roiIndex: Region of Interest number
|
597
|
+
- xOrigin: ROI’s X Origin
|
598
|
+
- yOrigin: ROI’s Y Origin
|
599
|
+
- xSize: ROI’s X Size
|
600
|
+
- ySize: ROI’s Y Size
|
601
|
+
- xBinning: ROI’s X Bin
|
602
|
+
- yBinning: ROI’s Y Bin
|
603
|
+
- Timestamp: This is a timestamp that relates to the time when the all the programmed acquisitions have
|
604
|
+
completed. The data from all programmed acquisitions are retrieve from the CCD after all
|
605
|
+
acquisitions have completed, therefore the same timestamp is used for all acquisitions.
|
606
|
+
"""
|
607
|
+
response: Response = super()._execute_command('ccd_getAcquisitionData', {'index': self._id})
|
608
|
+
return response.results['acquisition']
|
609
|
+
|
610
|
+
def set_center_wavelength(self, center_wavelength: float) -> None:
|
611
|
+
"""Sets the center wavelength value to be used in the grating equation.
|
612
|
+
|
613
|
+
Used when X axis conversion is XAxisConversionType.FROM_ICL_SETTINGS_INI
|
614
|
+
|
615
|
+
Args:
|
616
|
+
center_wavelength (float): Center wavelength
|
617
|
+
|
618
|
+
Raises:
|
619
|
+
Exception: When an error occurred on the device side
|
620
|
+
"""
|
621
|
+
super()._execute_command(
|
622
|
+
'ccd_setCenterWavelength',
|
623
|
+
{'index': self._id, 'wavelength': center_wavelength},
|
624
|
+
)
|
625
|
+
|
626
|
+
def range_mode_center_wavelengths(
|
627
|
+
self, monochromator_index: int, start_wavelength: float, end_wavelength: float, pixel_overlap: int
|
628
|
+
) -> list[float]:
|
629
|
+
"""Finds the center wavelength positions based on the input range and pixel overlap.
|
630
|
+
|
631
|
+
The following commands are prerequisites and should be called prior to using this command:
|
632
|
+
- :func:`ChargeCoupledDevice.set_x`,
|
633
|
+
- :func:`ChargeCoupledDevice.ccd_setAcqFormat`,
|
634
|
+
- :func:`ChargeCoupledDevice.ccd_setRoi`
|
635
|
+
|
636
|
+
Args:
|
637
|
+
monochromator_index (int): Index of the monochromator that is connected to the setup
|
638
|
+
start_wavelength (float): Start wavelength
|
639
|
+
end_wavelength (float): End wavelength
|
640
|
+
pixel_overlap (int): Overlap size in pixels between the scans.
|
641
|
+
|
642
|
+
Returns:
|
643
|
+
List[float]: List of center wavelength positions to cover the desired range.
|
644
|
+
Raises:
|
645
|
+
Exception: When an error occurred on the device side
|
646
|
+
"""
|
647
|
+
response: Response = super()._execute_command(
|
648
|
+
'ccd_calculateRangeModePositions',
|
649
|
+
{
|
650
|
+
'index': self._id,
|
651
|
+
'monoIndex': monochromator_index,
|
652
|
+
'start': start_wavelength,
|
653
|
+
'end': end_wavelength,
|
654
|
+
'overlap': pixel_overlap,
|
655
|
+
},
|
656
|
+
)
|
657
|
+
return response.results['centerWavelengths']
|
658
|
+
|
659
|
+
@staticmethod
|
660
|
+
def raman_convert(spectrum: list[float], excitation_wavelength: float) -> list[float]:
|
661
|
+
"""Calculates the raman shift for every wavelength in the list relative to the excitation wavelength.
|
662
|
+
|
663
|
+
Args:
|
664
|
+
spectrum (list[float]): Wavelengths
|
665
|
+
excitation_wavelength: Excitation wavelength
|
666
|
+
|
667
|
+
Returns:
|
668
|
+
list[float]: Wavelengths converted to raman shifts
|
669
|
+
"""
|
670
|
+
raman_values = []
|
671
|
+
for wave_length in spectrum:
|
672
|
+
raman_shift = ((1 / excitation_wavelength) - (1 / wave_length)) * (10**7)
|
673
|
+
raman_values.append(raman_shift)
|
674
|
+
return raman_values
|