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