BioImager  3.9.1
A .NET microscopy imaging library. Supports various microscopes by using imported libraries & GUI automation. Supported libraries include PriorĀ® & ZeissĀ® & all devices supported by Micromanager 2.0 and python-microscope.
Loading...
Searching...
No Matches
atmcd.py
1#!/usr/bin/env python3
2
3## Copyright (C) 2009 David Baddeley <d.baddeley@auckland.ac.nz>
4## Copyright (C) 2020 Mick Phillips <mick.phillips@gmail.com>
5##
6## This file is part of Microscope.
7##
8## Microscope is free software: you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation, either version 3 of the License, or
11## (at your option) any later version.
12##
13## Microscope is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with Microscope. If not, see <http://www.gnu.org/licenses/>.
20
21## The implementation of dllFunc is based on the implementation in
22## PYME, hence copyright to David Baddeley.
23
24"""This module wraps Andor's SDK for (EM)CCD cameras.
25
26Example deviceserver entry::
27
28 from microscope.cameras import atmcd
29 DEVICES = [ ...
30 device(atmcd.AndorAtmcd, "127.0.0.1", 8000, uid="VSC-01234")
31 ]
32
33Tested against Ixon Ultra with atmcd64d.dll ver 2.97.30007.0.
34
35"""
36
37import ctypes
38import functools
39import logging
40import os
41import platform
42import sys
43import time
44from ctypes import (
45 POINTER,
46 Structure,
47 c_char,
48 c_char_p,
49 c_double,
50 c_float,
51 c_int,
52 c_long,
53 c_longlong,
54 c_short,
55 c_ubyte,
56 c_uint,
57 c_ulong,
58 c_ulonglong,
59)
60from enum import Enum, IntEnum
61from threading import Lock
62
63import numpy as np
64from numpy.ctypeslib import ndpointer
65
66import microscope
67import microscope.abc
68
69
70_logger = logging.getLogger(__name__)
71
72
73# Andor docs use Windows datatypes in call signatures. These may not be available on
74# other platforms.
75try:
76 from ctypes.wintypes import BYTE, DWORD, HANDLE, WORD
77except:
78 # Docs give no clues. These need testing against a non-Windows library.
79 BYTE = ctypes.c_byte
80 WORD = ctypes.c_ushort
81 DWORD = ctypes.c_ulong
82 HANDLE = ctypes.c_void_p
83
84_stdcall_libraries = {}
85arch, plat = platform.architecture()
86if arch == "32bit":
87 _dllName = "atmcd32d"
88else:
89 _dllName = "atmcd64d"
90if os.name in ("nt", "ce"):
91 _dll = ctypes.WinDLL(_dllName)
92else:
93 _dll = ctypes.CDLL(_dllName + ".so")
94
95# Andor's types
96at_32 = c_long
97at_u32 = c_ulong
98at_64 = c_longlong
99at_u64 = c_ulonglong
100
101"""Version Information Definitions"""
102# Version information enumeration
103class AT_VersionInfoId(c_int):
104 pass
105
106
107AT_SDKVersion = AT_VersionInfoId(0x40000000)
108AT_DeviceDriverVersion = AT_VersionInfoId(0x40000001)
109# No. of elements in version info.
110AT_NoOfVersionInfoIds = 2
111# Minimum recommended length of the Version Info buffer parameter
112AT_VERSION_INFO_LEN = 80
113# Minimum recommended length of the Controller Card Model buffer parameter
114AT_CONTROLLER_CARD_MODEL_LEN = 80
115
116"""DDG Lite Definitions"""
117# Channel enumeration
119 pass
120
121
122AT_DDGLite_ChannelA = AT_DDGLiteChannelId(0x40000000)
123AT_DDGLite_ChannelB = AT_DDGLiteChannelId(0x40000001)
124AT_DDGLite_ChannelC = AT_DDGLiteChannelId(0x40000002)
125# Control byte flags
126AT_DDGLite_ControlBit_GlobalEnable = 0x01
127AT_DDGLite_ControlBit_ChannelEnable = 0x01
128AT_DDGLite_ControlBit_FreeRun = 0x02
129AT_DDGLite_ControlBit_DisableOnFrame = 0x04
130AT_DDGLite_ControlBit_RestartOnFire = 0x08
131AT_DDGLite_ControlBit_Invert = 0x10
132AT_DDGLite_ControlBit_EnableOnFire = 0x20
133
134"""USB iStar Definitions"""
135# Electrical
136AT_DDG_POLARITY_POSITIVE = 0
137AT_DDG_POLARITY_NEGATIVE = 1
138AT_DDG_TERMINATION_50OHMS = 0
139AT_DDG_TERMINATION_HIGHZ = 1
140# Stepmode
141AT_STEPMODE_CONSTANT = 0
142AT_STEPMODE_EXPONENTIAL = 1
143AT_STEPMODE_LOGARITHMIC = 2
144AT_STEPMODE_LINEAR = 3
145AT_STEPMODE_OFF = 100
146# Gatemode
147AT_GATEMODE_FIRE_AND_GATE = 0
148AT_GATEMODE_FIRE_ONLY = 1
149AT_GATEMODE_GATE_ONLY = 2
150AT_GATEMODE_CW_ON = 3
151AT_GATEMODE_CW_OFF = 4
152AT_GATEMODE_DDG = 5
153
154
155"""typedef structs"""
156
157
158class ANDORCAPS(Structure):
159 _fields_ = [
160 ("ulSize", c_ulong),
161 ("ulAcqModes", c_ulong),
162 ("ulReadModes", c_ulong),
163 ("ulTriggerModes", c_ulong),
164 ("ulCameraType", c_ulong),
165 ("ulPixelMode", c_ulong),
166 ("ulSetFunctions", c_ulong),
167 ("ulGetFunctions", c_ulong),
168 ("ulFeatures", c_ulong),
169 ("ulPCICard", c_ulong),
170 ("ulEMGainCapability", c_ulong),
171 ("ulFTReadModes", c_ulong),
172 ]
173
174 def __init__(self):
175 # The function that uses this strcut requires that ulSize contains
176 # the size of the structure.
177 self.ulSize = ctypes.sizeof(self)
178
179
180AndorCapabilities = ANDORCAPS
181
182
183class COLORDEMOSAICINFO(Structure):
184 _fields_ = [
185 ("iX", c_int),
186 ("iY", c_int),
187 ("iAlgorithm", c_int),
188 ("iXPhase", c_int),
189 ("iYPhase", c_int),
190 ("iBackground", c_int),
191 ]
192
193
194ColorDemosaicInfo = COLORDEMOSAICINFO
195
196
197class SYSTEMTIME(Structure):
198 _fields_ = [
199 ("wYear", WORD),
200 ("wMonth", WORD),
201 ("wDayOfWeek", WORD),
202 ("wDay", WORD),
203 ("wHour", WORD),
204 ("wMinute", WORD),
205 ("wSecond", WORD),
206 ("wMilliseconds", WORD),
207 ]
208
209
210class WHITEBALANCEINFO(Structure):
211 _fields_ = [
212 ("iSize", c_int),
213 ("iX", c_int),
214 ("iY", c_int),
215 ("iAlgorithm", c_int),
216 ("iROI_left", c_int),
217 ("iROI_right", c_int),
218 ("iROI_top", c_int),
219 ("iROI_bottom", c_int),
220 ("iOperation", c_int),
221 ]
222
223
224WhiteBalanceInfo = WHITEBALANCEINFO
225
226
227"""Enums"""
228# Status codes
229DRV_ERROR_CODES = 20001
230DRV_SUCCESS = 20002
231DRV_VXDNOTINSTALLED = 20003
232DRV_ERROR_SCAN = 20004
233DRV_ERROR_CHECK_SUM = 20005
234DRV_ERROR_FILELOAD = 20006
235DRV_UNKNOWN_FUNCTION = 20007
236DRV_ERROR_VXD_INIT = 20008
237DRV_ERROR_ADDRESS = 20009
238DRV_ERROR_PAGELOCK = 20010
239DRV_ERROR_PAGEUNLOCK = 20011
240DRV_ERROR_BOARDTEST = 20012
241DRV_ERROR_ACK = 20013
242DRV_ERROR_UP_FIFO = 20014
243DRV_ERROR_PATTERN = 20015
244DRV_ACQUISITION_ERRORS = 20017
245DRV_ACQ_BUFFER = 20018
246DRV_ACQ_DOWNFIFO_FULL = 20019
247DRV_PROC_UNKONWN_INSTRUCTION = 20020
248DRV_ILLEGAL_OP_CODE = 20021
249DRV_KINETIC_TIME_NOT_MET = 20022
250DRV_ACCUM_TIME_NOT_MET = 20023
251DRV_NO_NEW_DATA = 20024
252DRV_PCI_DMA_FAIL = 20025
253DRV_SPOOLERROR = 20026
254DRV_SPOOLSETUPERROR = 20027
255DRV_FILESIZELIMITERROR = 20028
256DRV_ERROR_FILESAVE = 20029
257DRV_TEMPERATURE_CODES = 20033
258DRV_TEMPERATURE_OFF = 20034
259DRV_TEMPERATURE_NOT_STABILIZED = 20035
260DRV_TEMPERATURE_STABILIZED = 20036
261DRV_TEMPERATURE_NOT_REACHED = 20037
262DRV_TEMPERATURE_OUT_RANGE = 20038
263DRV_TEMPERATURE_NOT_SUPPORTED = 20039
264DRV_TEMPERATURE_DRIFT = 20040
265DRV_TEMP_CODES = 20033
266DRV_TEMP_OFF = 20034
267DRV_TEMP_NOT_STABILIZED = 20035
268DRV_TEMP_STABILIZED = 20036
269DRV_TEMP_NOT_REACHED = 20037
270DRV_TEMP_OUT_RANGE = 20038
271DRV_TEMP_NOT_SUPPORTED = 20039
272DRV_TEMP_DRIFT = 20040
273DRV_GENERAL_ERRORS = 20049
274DRV_INVALID_AUX = 20050
275DRV_COF_NOTLOADED = 20051
276DRV_FPGAPROG = 20052
277DRV_FLEXERROR = 20053
278DRV_GPIBERROR = 20054
279DRV_EEPROMVERSIONERROR = 20055
280DRV_DATATYPE = 20064
281DRV_DRIVER_ERRORS = 20065
282DRV_P1INVALID = 20066
283DRV_P2INVALID = 20067
284DRV_P3INVALID = 20068
285DRV_P4INVALID = 20069
286DRV_INIERROR = 20070
287DRV_COFERROR = 20071
288DRV_ACQUIRING = 20072
289DRV_IDLE = 20073
290DRV_TEMPCYCLE = 20074
291DRV_NOT_INITIALIZED = 20075
292DRV_P5INVALID = 20076
293DRV_P6INVALID = 20077
294DRV_INVALID_MODE = 20078
295DRV_INVALID_FILTER = 20079
296DRV_I2CERRORS = 20080
297DRV_I2CDEVNOTFOUND = 20081
298DRV_I2CTIMEOUT = 20082
299DRV_P7INVALID = 20083
300DRV_P8INVALID = 20084
301DRV_P9INVALID = 20085
302DRV_P10INVALID = 20086
303DRV_P11INVALID = 20087
304DRV_USBERROR = 20089
305DRV_IOCERROR = 20090
306DRV_VRMVERSIONERROR = 20091
307DRV_GATESTEPERROR = 20092
308DRV_USB_INTERRUPT_ENDPOINT_ERROR = 20093
309DRV_RANDOM_TRACK_ERROR = 20094
310DRV_INVALID_TRIGGER_MODE = 20095
311DRV_LOAD_FIRMWARE_ERROR = 20096
312DRV_DIVIDE_BY_ZERO_ERROR = 20097
313DRV_INVALID_RINGEXPOSURES = 20098
314DRV_BINNING_ERROR = 20099
315DRV_INVALID_AMPLIFIER = 20100
316DRV_INVALID_COUNTCONVERT_MODE = 20101
317DRV_ERROR_NOCAMERA = 20990
318DRV_NOT_SUPPORTED = 20991
319DRV_NOT_AVAILABLE = 20992
320DRV_ERROR_MAP = 20115
321DRV_ERROR_UNMAP = 20116
322DRV_ERROR_MDL = 20117
323DRV_ERROR_UNMDL = 20118
324DRV_ERROR_BUFFSIZE = 20119
325DRV_ERROR_NOHANDLE = 20121
326DRV_GATING_NOT_AVAILABLE = 20130
327DRV_FPGA_VOLTAGE_ERROR = 20131
328DRV_OW_CMD_FAIL = 20150
329DRV_OWMEMORY_BAD_ADDR = 20151
330DRV_OWCMD_NOT_AVAILABLE = 20152
331DRV_OW_NO_SLAVES = 20153
332DRV_OW_NOT_INITIALIZED = 20154
333DRV_OW_ERROR_SLAVE_NUM = 20155
334DRV_MSTIMINGS_ERROR = 20156
335DRV_OA_NULL_ERROR = 20173
336DRV_OA_PARSE_DTD_ERROR = 20174
337DRV_OA_DTD_VALIDATE_ERROR = 20175
338DRV_OA_FILE_ACCESS_ERROR = 20176
339DRV_OA_FILE_DOES_NOT_EXIST = 20177
340DRV_OA_XML_INVALID_OR_NOT_FOUND_ERROR = 20178
341DRV_OA_PRESET_FILE_NOT_LOADED = 20179
342DRV_OA_USER_FILE_NOT_LOADED = 20180
343DRV_OA_PRESET_AND_USER_FILE_NOT_LOADED = 20181
344DRV_OA_INVALID_FILE = 20182
345DRV_OA_FILE_HAS_BEEN_MODIFIED = 20183
346DRV_OA_BUFFER_FULL = 20184
347DRV_OA_INVALID_STRING_LENGTH = 20185
348DRV_OA_INVALID_CHARS_IN_NAME = 20186
349DRV_OA_INVALID_NAMING = 20187
350DRV_OA_GET_CAMERA_ERROR = 20188
351DRV_OA_MODE_ALREADY_EXISTS = 20189
352DRV_OA_STRINGS_NOT_EQUAL = 20190
353DRV_OA_NO_USER_DATA = 20191
354DRV_OA_VALUE_NOT_SUPPORTED = 20192
355DRV_OA_MODE_DOES_NOT_EXIST = 20193
356DRV_OA_CAMERA_NOT_SUPPORTED = 20194
357DRV_OA_FAILED_TO_GET_MODE = 20195
358DRV_PROCESSING_FAILED = 20211
359# Andor capabilities AC_...
360# Acquisition modes
361AC_ACQMODE_SINGLE = 1
362AC_ACQMODE_VIDEO = 2
363AC_ACQMODE_ACCUMULATE = 4
364AC_ACQMODE_KINETIC = 8
365AC_ACQMODE_FRAMETRANSFER = 16
366AC_ACQMODE_FASTKINETICS = 32
367AC_ACQMODE_OVERLAP = 64
368AC_READMODE_FULLIMAGE = 1
369AC_READMODE_SUBIMAGE = 2
370AC_READMODE_SINGLETRACK = 4
371AC_READMODE_FVB = 8
372AC_READMODE_MULTITRACK = 16
373AC_READMODE_RANDOMTRACK = 32
374AC_READMODE_MULTITRACKSCAN = 64
375AC_TRIGGERMODE_INTERNAL = 1
376AC_TRIGGERMODE_EXTERNAL = 2
377AC_TRIGGERMODE_EXTERNAL_FVB_EM = 4
378AC_TRIGGERMODE_CONTINUOUS = 8
379AC_TRIGGERMODE_EXTERNALSTART = 16
380AC_TRIGGERMODE_EXTERNALEXPOSURE = 32
381AC_TRIGGERMODE_INVERTED = 64
382AC_TRIGGERMODE_EXTERNAL_CHARGESHIFTING = 128
383AC_TRIGGERMODE_BULB = 32
384AC_CAMERATYPE_PDA = 0
385AC_CAMERATYPE_IXON = 1
386AC_CAMERATYPE_ICCD = 2
387AC_CAMERATYPE_EMCCD = 3
388AC_CAMERATYPE_CCD = 4
389AC_CAMERATYPE_ISTAR = 5
390AC_CAMERATYPE_VIDEO = 6
391AC_CAMERATYPE_IDUS = 7
392AC_CAMERATYPE_NEWTON = 8
393AC_CAMERATYPE_SURCAM = 9
394AC_CAMERATYPE_USBICCD = 10
395AC_CAMERATYPE_LUCA = 11
396AC_CAMERATYPE_RESERVED = 12
397AC_CAMERATYPE_IKON = 13
398AC_CAMERATYPE_INGAAS = 14
399AC_CAMERATYPE_IVAC = 15
400AC_CAMERATYPE_UNPROGRAMMED = 16
401AC_CAMERATYPE_CLARA = 17
402AC_CAMERATYPE_USBISTAR = 18
403AC_CAMERATYPE_SIMCAM = 19
404AC_CAMERATYPE_NEO = 20
405AC_CAMERATYPE_IXONULTRA = 21
406AC_CAMERATYPE_VOLMOS = 22
407AC_PIXELMODE_8BIT = 1
408AC_PIXELMODE_14BIT = 2
409AC_PIXELMODE_16BIT = 4
410AC_PIXELMODE_32BIT = 8
411AC_PIXELMODE_MONO = 0x000000
412AC_PIXELMODE_RGB = 0x010000
413AC_PIXELMODE_CMY = 0x020000
414# Set functions
415AC_SETFUNCTION_VREADOUT = 0x01
416AC_SETFUNCTION_HREADOUT = 0x02
417AC_SETFUNCTION_TEMPERATURE = 0x04
418AC_SETFUNCTION_MCPGAIN = 0x08
419AC_SETFUNCTION_EMCCDGAIN = 0x10
420AC_SETFUNCTION_BASELINECLAMP = 0x20
421AC_SETFUNCTION_VSAMPLITUDE = 0x40
422AC_SETFUNCTION_HIGHCAPACITY = 0x80
423AC_SETFUNCTION_BASELINEOFFSET = 0x0100
424AC_SETFUNCTION_PREAMPGAIN = 0x0200
425AC_SETFUNCTION_CROPMODE = 0x0400
426AC_SETFUNCTION_DMAPARAMETERS = 0x0800
427AC_SETFUNCTION_HORIZONTALBIN = 0x1000
428AC_SETFUNCTION_MULTITRACKHRANGE = 0x2000
429AC_SETFUNCTION_RANDOMTRACKNOGAPS = 0x4000
430AC_SETFUNCTION_EMADVANCED = 0x8000
431AC_SETFUNCTION_GATEMODE = 0x010000
432AC_SETFUNCTION_DDGTIMES = 0x020000
433AC_SETFUNCTION_IOC = 0x040000
434AC_SETFUNCTION_INTELLIGATE = 0x080000
435AC_SETFUNCTION_INSERTION_DELAY = 0x100000
436AC_SETFUNCTION_GATESTEP = 0x200000
437AC_SETFUNCTION_TRIGGERTERMINATION = 0x400000
438AC_SETFUNCTION_EXTENDEDNIR = 0x800000
439AC_SETFUNCTION_SPOOLTHREADCOUNT = 0x1000000
440# AC_SETFUNCTION_MCPGAIN deprecated
441AC_SETFUNCTION_GAIN = 8
442AC_SETFUNCTION_ICCDGAIN = 8
443# Get functions
444AC_GETFUNCTION_TEMPERATURE = 0x01
445AC_GETFUNCTION_TARGETTEMPERATURE = 0x02
446AC_GETFUNCTION_TEMPERATURERANGE = 0x04
447AC_GETFUNCTION_DETECTORSIZE = 0x08
448AC_GETFUNCTION_MCPGAIN = 0x10
449AC_GETFUNCTION_EMCCDGAIN = 0x20
450AC_GETFUNCTION_HVFLAG = 0x40
451AC_GETFUNCTION_GATEMODE = 0x80
452AC_GETFUNCTION_DDGTIMES = 0x0100
453AC_GETFUNCTION_IOC = 0x0200
454AC_GETFUNCTION_INTELLIGATE = 0x0400
455AC_GETFUNCTION_INSERTION_DELAY = 0x0800
456AC_GETFUNCTION_GATESTEP = 0x1000
457AC_GETFUNCTION_PHOSPHORSTATUS = 0x2000
458AC_GETFUNCTION_MCPGAINTABLE = 0x4000
459AC_GETFUNCTION_BASELINECLAMP = 0x8000
460# AC_GETFUNCTION_MCPGAIN deprecated
461AC_GETFUNCTION_GAIN = 0x10
462AC_GETFUNCTION_ICCDGAIN = 0x10
463# Features
464AC_FEATURES_POLLING = 1
465AC_FEATURES_EVENTS = 2
466AC_FEATURES_SPOOLING = 4
467AC_FEATURES_SHUTTER = 8
468AC_FEATURES_SHUTTEREX = 16
469AC_FEATURES_EXTERNAL_I2C = 32
470AC_FEATURES_SATURATIONEVENT = 64
471AC_FEATURES_FANCONTROL = 128
472AC_FEATURES_MIDFANCONTROL = 256
473AC_FEATURES_TEMPERATUREDURINGACQUISITION = 512
474AC_FEATURES_KEEPCLEANCONTROL = 1024
475AC_FEATURES_DDGLITE = 0x0800
476AC_FEATURES_FTEXTERNALEXPOSURE = 0x1000
477AC_FEATURES_KINETICEXTERNALEXPOSURE = 0x2000
478AC_FEATURES_DACCONTROL = 0x4000
479AC_FEATURES_METADATA = 0x8000
480AC_FEATURES_IOCONTROL = 0x10000
481AC_FEATURES_PHOTONCOUNTING = 0x20000
482AC_FEATURES_COUNTCONVERT = 0x40000
483AC_FEATURES_DUALMODE = 0x80000
484AC_FEATURES_OPTACQUIRE = 0x100000
485AC_FEATURES_REALTIMESPURIOUSNOISEFILTER = 0x200000
486AC_FEATURES_POSTPROCESSSPURIOUSNOISEFILTER = 0x400000
487AC_FEATURES_DUALPREAMPGAIN = 0x800000
488AC_FEATURES_DEFECT_CORRECTION = 0x1000000
489AC_FEATURES_STARTOFEXPOSURE_EVENT = 0x2000000
490AC_FEATURES_ENDOFEXPOSURE_EVENT = 0x4000000
491AC_FEATURES_CAMERALINK = 0x80000007108864
492# Gain types
493AC_EMGAIN_8BIT = 1
494AC_EMGAIN_12BIT = 2
495AC_EMGAIN_LINEAR12 = 4
496AC_EMGAIN_REAL12 = 8
497
498# We need a mapping to enable lookup of status codes to meaning.
499status_codes = {}
500for attrib_name in dir(sys.modules[__name__]):
501 if attrib_name.startswith("DRV_"):
502 status_codes.update({eval(attrib_name): attrib_name})
503
504# The lookup function.
505def lookup_status(code):
506 key = code[0] if type(code) is list else code
507 if key in status_codes:
508 return status_codes[key]
509 else:
510 return "Unknown status code %s." % key
511
512
513# The following DLL-wrapping classes are largely lifted from David Baddeley's
514# SDK3 wrapper, with some modifications and additions.
515
516# Classes used to handle outputs and parameters that need buffers.
517class _meta:
518 pass
519
520
521STRING = c_char_p
522
523
525 """Used to indicated output from a DLL call"""
526
527 def __init__(self, val):
528 self.type = val
529 self.val = POINTER(val)
530
531 def getVar(self, bufLen=0):
532 v = self.type()
533 return v, ctypes.byref(v)
534
535
537 """A special type of OUTPUT that creates an output buffer."""
538
539 def __init__(self):
540 self.valval = STRING
541
542 def getVar(self, bufLen):
543 v = ctypes.create_string_buffer(bufLen)
544 return v, v
545
546
547OUTSTRING = _OUTSTRING()
548
549
551 """Used to mark call parameters that define a string buffer size."""
552
553 def __init__(self):
554 self.val = c_int
555
556
557OUTSTRLEN = _OUTSTRLEN()
558
559
561 """Used for DLL call parameters that return an array."""
562
563 def __init__(self, val):
564 self.typetype = val
565 # self.val = POINTER(val)
566 self.valval = ndpointer(val, flags="C_CONTIGUOUS")
567
568 def getVar(self, size):
569 # self.val = (size * self.type)()
570 self.valval = np.zeros(int(size), dtype=self.typetype)
571 return self.valval, self.valval
572
573
575 """Used to mark DLL call parameters that define array sizes."""
576
577 def __init__(self):
578 self.val = c_ulong
579
580
581OUTARRSIZE = _OUTARRSIZE()
582
583
584def stripMeta(val):
585 """Strips the outer metaclass to give the underlying data object."""
586 if isinstance(val, _meta):
587 return val.val
588 else:
589 return val
590
591
592def extract_value(val):
593 """Calls .value on simple ctypes."""
594 if type(val) in [
595 c_int,
596 c_uint,
597 c_long,
598 c_ulong,
599 c_longlong,
600 c_ulonglong,
601 c_ubyte,
602 c_short,
603 c_float,
604 c_double,
605 c_char,
606 c_char_p,
607 ]:
608 return val.value
609 elif isinstance(val, ctypes.Array) and val._type_ is c_char:
610 return val.value.decode()
611 else:
612 return val
613
614
615class AtmcdException(Exception):
616 """An exception arising from a DLL call."""
617
618 def __init__(self, status):
619 self.message = "%s %s" % (status, lookup_status(status))
620 super().__init__(self.message)
621 self.status = status
622
623
625 """A wrapper class for DLL functions to make them available in python."""
626
627 def __init__(self, name, args=[], argnames=[], rstatus=False, lib=_dll):
628 # the library function
629 self.f = getattr(lib, name)
630 # dll call return type
631 self.f.restype = c_uint
632 # dll call parameter types
633 self.f.argtypes = [stripMeta(a) for a in args]
634 # dll call parameters, with their meta wrappers
635 self.fargs = args
636 # dll call parameter names, used to generate helpstrings
637 self.fargnames = argnames
638 # the function name
639 self.name = name
640 # input arguments
641 self.in_args = [a for a in args if not isinstance(a, OUTPUT)]
642 # output arguments
643 self.out_args = [a for a in args if isinstance(a, OUTPUT)]
644 # Indicates that this function should return the status code it generates.
645 self.rstatus = rstatus
646 # Find any arguments that set string buffer or array sizes.
647 self.buf_size_arg_pos = -1
648 self.arr_size_arg_pos = -1
649 for i in range(len(self.in_args)):
650 if isinstance(self.in_args[i], _OUTSTRLEN):
651 self.buf_size_arg_pos = i
652 if isinstance(self.in_args[i], _OUTARRSIZE):
653 self.arr_size_pos = i
654 # Generate a docstring.
655 ds = name + "\n\nArguments:\n===========\n"
656 for i in range(len(args)):
657 an = ""
658 if i < len(argnames):
659 an = argnames[i]
660 ds += "\t%s\t%s\n" % (args[i], an)
661 self.f.__doc__ = ds
662
663 def __call__(self, *args):
664 """Parse arguments, allocate any required storage, and execute the call."""
665 # The C function arguments
666 c_args = []
667 i = 0
668 ret = []
669
670 if self.buf_size_arg_pos >= 0:
671 try:
672 bs = args[self.buf_size_arg_pos]
673 except:
674 bs = 255
675 else:
676 bs = 255
677 # Sort input and output arguments, allocating output storage as required.
678 i = 0
679 for farg in self.fargs:
680 if isinstance(farg, OUTPUT):
681 if isinstance(farg, OUTARR):
682 size = args[self.arr_size_arg_pos]
683 else:
684 size = bs
685 r, c_arg = farg.getVar(size)
686 c_args.append(c_arg)
687 ret.append(r)
688 elif isinstance(farg, _OUTSTRLEN):
689 c_args.append(bs)
690 elif isinstance(args[i], Enum):
691 c_args.append(args[i].value)
692 i += 1
693 else:
694 c_args.append(args[i])
695 i += 1
696
697 # Make the library call, tolerating a few DRV_ERROR_ACKs
698 status = DRV_ERROR_ACK
699 ack_err_count = -1
700 while status == DRV_ERROR_ACK and ack_err_count < 3:
701 ack_err_count += 1
702 status = self.f(*c_args)
703 ret = [extract_value(r) for r in ret]
704 if len(ret) == 1:
705 ret = ret[0]
706 elif len(ret) == 0:
707 ret = None
708 # A few functions indicate state using the returned status code instead
709 # of filling a variable passed by reference pointer.
710 if self.rstatus:
711 if status == DRV_SUCCESS:
712 return True
713 elif status in [
714 DRV_INVALID_AMPLIFIER,
715 DRV_INVALID_MODE,
716 DRV_INVALID_COUNTCONVERT_MODE,
717 DRV_INVALID_FILTER,
718 ]:
719 return False
720 elif status in [
721 DRV_TEMP_OFF,
722 DRV_TEMP_STABILIZED,
723 DRV_TEMP_NOT_REACHED,
724 DRV_TEMP_DRIFT,
725 DRV_TEMP_NOT_STABILIZED,
726 ]:
727 return (status, ret)
728 else:
729 raise AtmcdException(status)
730 # Most functions return values via pointers, or have no return.
731 if not status == DRV_SUCCESS:
732 raise AtmcdException(status)
733 return ret
734
735
736def dllFunc(name, args=[], argnames=[], rstatus=False, lib=_dll):
737 """Wrap library calls and add them to this module's namespace."""
738 try:
739 f = dllFunction(name, args, argnames, rstatus, lib)
740 except Exception as e:
742 "Error wrapping dll function '%s'" % name
743 ) from e
744 globals()[name] = f
745
746
747# We now add selected DLL functions to this library's namespace.
748# These may be used directly: while this may work well when there is a
749# single camera, care must be taken when there are multiple cameras
750# on a system to ensure calls act on the expected camera. The AntorAtmcd
751# class defined below does much of this work.
752dllFunc("AbortAcquisition", [], [])
753dllFunc("CancelWait", [], [])
754dllFunc("CoolerOFF", [], [])
755dllFunc("CoolerON", [], [])
756dllFunc(
757 "DemosaicImage",
758 [
759 POINTER(WORD),
760 POINTER(WORD),
761 POINTER(WORD),
762 POINTER(WORD),
763 POINTER(ColorDemosaicInfo),
764 ],
765 ["grey", "red", "green", "blue", "info"],
766)
767dllFunc("EnableKeepCleans", [c_int], ["iMode"])
768dllFunc("FreeInternalMemory", [], [])
769# Note - documentation states that the next two functions return the data
770# "from the last acquisition". That appears to mean the data resulting from
771# the last trigger, rather than all the available data between the last
772# StartAcquisition and Abort calls.
773dllFunc("GetAcquiredData", [OUTARR(at_32), OUTARRSIZE], ["arr", "size"])
774dllFunc("GetAcquiredData16", [OUTARR(WORD), OUTARRSIZE], ["arr", "size"])
775# GetAcquiredFloatData(float * arr, unsigned long size)
776dllFunc(
777 "GetAcquisitionProgress",
778 [OUTPUT(c_long), OUTPUT(c_long)],
779 ["acc", "series"],
780)
781dllFunc(
782 "GetAcquisitionTimings",
783 [OUTPUT(c_float), OUTPUT(c_float), OUTPUT(c_float)],
784 ["exposure", "accumulate", "kinetic"],
785)
786dllFunc(
787 "GetAdjustedRingExposureTimes",
788 [c_int, POINTER(c_float)],
789 ["iNumTimes", "fptimes"],
790)
791# GetAllDMAData(at_32 * arr, unsigned long size)
792dllFunc(
793 "GetAmpDesc", [c_int, OUTSTRING, OUTSTRLEN], ["index", "name", "length"]
794)
795dllFunc("GetAmpMaxSpeed", [c_int, OUTPUT(c_float)], ["index", "speed"])
796dllFunc("GetAvailableCameras", [OUTPUT(c_long)], ["totalCameras"])
797# # GetBackground(at_32 * arr, unsigned long size)
798dllFunc("GetBaselineClamp", [OUTPUT(c_int)], ["state"])
799dllFunc("GetBitDepth", [c_int, OUTPUT(c_int)], ["channel", "depth"])
800dllFunc("GetCameraEventStatus", [OUTPUT(DWORD)], ["camStatus"])
801dllFunc(
802 "GetCameraHandle",
803 [c_long, OUTPUT(c_long)],
804 ["cameraIndex", "cameraHandle"],
805)
806dllFunc(
807 "GetCameraInformation", [c_int, OUTPUT(c_long)], ["index", "information"]
808)
809dllFunc("GetCameraSerialNumber", [OUTPUT(c_int)], ["number"])
810dllFunc("GetCapabilities", [OUTPUT(AndorCapabilities)], ["caps"])
811dllFunc("GetControllerCardModel", [OUTSTRING], ["controllerCardModel"])
812dllFunc(
813 "GetCountConvertWavelengthRange",
814 [OUTPUT(c_float), OUTPUT(c_float)],
815 ["minVal", "maxVal"],
816)
817dllFunc("GetCurrentCamera", [OUTPUT(c_long)], ["cameraHandle"])
818# # GetCYMGShift(int * iXshift, int * iYShift)
819# GetDDGExternalOutputEnabled(at_u32 uiIndex, at_u32 * puiEnabled)
820# GetDDGExternalOutputPolarity(at_u32 uiIndex, at_u32 * puiPolarity)
821# GetDDGExternalOutputStepEnabled(at_u32 uiIndex, at_u32 * puiEnabled)
822# GetDDGExternalOutputTime(at_u32 uiIndex, at_u64 * puiDelay, at_u64 * puiWidth)
823# GetDDGTTLGateWidth(at_u64 opticalWidth, at_u64 * ttlWidth)
824# GetDDGGateTime(at_u64 * puiDelay, at_u64 * puiWidth)
825# GetDDGInsertionDelay(int * piState)
826# GetDDGIntelligate(int * piState)
827# GetDDGIOC(int * state)
828# GetDDGIOCFrequency(double * frequency)
829# GetDDGIOCNumber(unsigned long * numberPulses)
830# GetDDGIOCNumberRequested(at_u32 * pulses)
831# GetDDGIOCPeriod(at_u64 * period)
832# GetDDGIOCPulses(int * pulses)
833# GetDDGIOCTrigger(at_u32 * trigger)
834# GetDDGOpticalWidthEnabled(at_u32 * puiEnabled)
835# # GetDDGLiteGlobalControlByte(unsigned char * control)
836# # GetDDGLiteControlByte(AT_DDGLiteChannelId channel, unsigned char * control)
837# # GetDDGLiteInitialDelay(AT_DDGLiteChannelId channel, float * fDelay)
838# # GetDDGLitePulseWidth(AT_DDGLiteChannelId channel, float * fWidth)
839# # GetDDGLiteInterPulseDelay(AT_DDGLiteChannelId channel, float * fDelay)
840# # GetDDGLitePulsesPerExposure(AT_DDGLiteChannelId channel, at_u32 * ui32Pulses)
841# GetDDGPulse(double wid, double resolution, double * Delay, double * Width)
842# GetDDGStepCoefficients(at_u32 mode, double * p1, double * p2)
843# GetDDGStepMode(at_u32 * mode)
844dllFunc("GetDetector", [OUTPUT(c_int), OUTPUT(c_int)], ["xpixels", "ypixels"])
845# # GetDICameraInfo(void * info)
846dllFunc("GetEMAdvanced", [OUTPUT(c_int)], ["state"])
847dllFunc("GetEMCCDGain", [OUTPUT(c_int)], [" gain"])
848dllFunc("GetEMGainRange", [OUTPUT(c_int), OUTPUT(c_int)], ["low", "high"])
849dllFunc("GetExternalTriggerTermination", [OUTPUT(at_u32)], ["puiTermination"])
850dllFunc(
851 "GetFastestRecommendedVSSpeed",
852 [OUTPUT(c_int), OUTPUT(c_float)],
853 ["index", "speed"],
854)
855# # GetFIFOUsage(int * FIFOusage)
856dllFunc("GetFilterMode", [OUTPUT(c_int)], ["mode"])
857dllFunc("GetFKExposureTime", [OUTPUT(c_float)], ["time"])
858# # GetFKVShiftSpeed(int index, int * speed)
859dllFunc("GetFKVShiftSpeedF", [c_int, OUTPUT(c_float)], ["index", "speed"])
860dllFunc("GetFrontEndStatus", [OUTPUT(c_int)], ["piFlag"])
861dllFunc("GetGateMode", [OUTPUT(c_int)], ["piGatemode"])
862dllFunc(
863 "GetHardwareVersion",
864 [OUTPUT(c_uint) for i in range(6)],
865 [
866 "PCB",
867 "Decode",
868 "dummy1",
869 "dummy2",
870 "CameraFirmwareVersion",
871 "CameraFirmwareBuild",
872 ],
873)
874dllFunc("GetHeadModel", [OUTSTRING], ["name"])
875# # GetHorizontalSpeed(int index, int * speed)
876dllFunc(
877 "GetHSSpeed",
878 [c_int, c_int, c_int, OUTPUT(c_float)],
879 ["channel", "typ", "index", "speed"],
880)
881dllFunc("GetHVflag", [OUTPUT(c_int)], ["bFlag"])
882# # GetID(int devNum, int * id)
883dllFunc("GetImageFlip", [OUTPUT(c_int), OUTPUT(c_int)], ["iHFlip", "iVFlip"])
884dllFunc("GetImageRotate", [OUTPUT(c_int)], ["Rotate"])
885dllFunc(
886 "GetImages",
887 [
888 c_long,
889 c_long,
890 OUTARR(at_32),
891 OUTARRSIZE,
892 OUTPUT(c_long),
893 OUTPUT(c_long),
894 ],
895 ["first", "last", "arr", "size", "validfirst", "validlast"],
896)
897dllFunc(
898 "GetImages16",
899 [c_long, c_long, OUTARR(WORD), OUTARRSIZE, OUTPUT(c_long), OUTPUT(c_long)],
900 ["first", "last", "arr", "size", "validfirst", "validlast"],
901)
902dllFunc("GetImagesPerDMA", [OUTPUT(c_ulong)], ["images"])
903# # GetIRQ(int * IRQ)
904dllFunc("GetKeepCleanTime", [OUTPUT(c_float)], ["KeepCleanTime"])
905dllFunc(
906 "GetMaximumBinning",
907 [c_int, c_int, OUTPUT(c_int)],
908 ["ReadMode", "HorzVert", "MaxBinning"],
909)
910dllFunc("GetMaximumExposure", [OUTPUT(c_float)], ["MaxExp"])
911dllFunc("GetMCPGain", [OUTPUT(c_int)], ["piGain"])
912dllFunc("GetMCPGainRange", [OUTPUT(c_int), OUTPUT(c_int)], ["iLow", "iHigh"])
913# # GetMCPGainTable(int iNum, int * piGain, float * pfPhotoepc)
914dllFunc("GetMCPVoltage", [OUTPUT(c_int)], ["iVoltage"])
915dllFunc("GetMinimumImageLength", [OUTPUT(c_int)], ["MinImageLength"])
916# # GetMinimumNumberInSeries(int * number)
917dllFunc(
918 "GetMostRecentColorImage16",
919 [OUTARRSIZE, c_int, OUTARR(WORD), OUTARR(WORD), OUTARR(WORD)],
920 ["size", "algorithm", "red", "green", "blue"],
921)
922dllFunc("GetMostRecentImage", [OUTARR(at_32), OUTARRSIZE], ["arr", "size"])
923dllFunc("GetMostRecentImage16", [OUTARR(WORD), OUTARRSIZE], ["arr", "size"])
924# # GetMSTimingsData(SYSTEMTIME * TimeOfStart, float * pfDifferences, int inoOfImages)
925dllFunc(
926 "GetMetaDataInfo",
927 [OUTPUT(SYSTEMTIME), OUTPUT(c_float), c_uint],
928 ["TimeOfStart", "TimeFromStart", "index"],
929)
930# # GetMSTimingsEnabled(void)
931# # GetNewData(at_32 * arr, unsigned long size)
932# # GetNewData16(WORD * arr, unsigned long size)
933# # GetNewData8(unsigned char * arr, unsigned long size)
934# # GetNewFloatData(float * arr, unsigned long size)
935dllFunc("GetNumberADChannels", [OUTPUT(c_int)], ["channels"])
936dllFunc("GetNumberAmp", [OUTPUT(c_int)], ["amp"])
937dllFunc(
938 "GetNumberAvailableImages",
939 [OUTPUT(at_32), OUTPUT(at_32)],
940 ["first", "last"],
941)
942dllFunc("GetNumberDDGExternalOutputs", [OUTPUT(at_u32)], ["puiCount"])
943# # GetNumberDevices(int * numDevs)
944dllFunc("GetNumberFKVShiftSpeeds", [OUTPUT(c_int)], ["number"])
945# # GetNumberHorizontalSpeeds(int * number)
946dllFunc(
947 "GetNumberHSSpeeds",
948 [c_int, c_int, OUTPUT(c_int)],
949 ["channel", "typ", "speeds"],
950)
951dllFunc(
952 "GetNumberNewImages", [OUTPUT(c_long), OUTPUT(c_long)], ["first", "last"]
953)
954dllFunc(
955 "GetNumberPhotonCountingDivisions", [OUTPUT(at_u32)], ["noOfDivisions"]
956)
957dllFunc("GetNumberPreAmpGains", [OUTPUT(c_int)], ["noGains"])
958dllFunc("GetNumberRingExposureTimes", [OUTPUT(c_int)], ["ipnumTimes"])
959dllFunc("GetNumberIO", [OUTPUT(c_int)], ["iNumber"])
960# # GetNumberVerticalSpeeds(int * number)
961dllFunc("GetNumberVSAmplitudes", [OUTPUT(c_int)], ["number"])
962dllFunc("GetNumberVSSpeeds", [OUTPUT(c_int)], ["speeds"])
963dllFunc("GetOldestImage", [OUTARR(at_32), OUTARRSIZE], ["arr", "size"])
964dllFunc("GetOldestImage16", [OUTARR(WORD), OUTARRSIZE], ["arr", "size"])
965dllFunc("GetPhosphorStatus", [OUTPUT(c_int)], ["piFlag"])
966# # GetPhysicalDMAAddress(unsigned long * Address1, unsigned long * Address2)
967dllFunc("GetPixelSize", [OUTPUT(c_float), OUTPUT(c_float)], ["xSize", "ySize"])
968dllFunc("GetPreAmpGain", [c_int, OUTPUT(c_float)], ["index", "gain"])
969dllFunc(
970 "GetPreAmpGainText",
971 [c_int, OUTSTRING, OUTSTRLEN],
972 ["index", "name", "length"],
973)
974dllFunc(
975 "GetDualExposureTimes",
976 [OUTPUT(c_float), OUTPUT(c_float)],
977 ["exposure1", "exposure2"],
978)
979dllFunc(
980 "GetQE",
981 [STRING, c_float, c_uint, OUTPUT(c_float)],
982 ["sensor", "wavelength", "mode", "QE"],
983)
984dllFunc("GetReadOutTime", [OUTPUT(c_float)], ["ReadOutTime"])
985# # GetRegisterDump(int * mode)
986dllFunc(
987 "GetRingExposureRange", [OUTPUT(c_float), OUTPUT(c_float)], ["Min", "Max"]
988)
989# # GetSDK3Handle(int * Handle)
990dllFunc(
991 "GetSensitivity",
992 [c_int, c_int, c_int, c_int, OUTPUT(c_float)],
993 ["channel", "horzShift", "amplifier", "pa", "sensitivity"],
994)
995dllFunc(
996 "GetShutterMinTimes",
997 [OUTPUT(c_int), OUTPUT(c_int)],
998 ["minclosingtime", "minopeningtime"],
999)
1000dllFunc("GetSizeOfCircularBuffer", [OUTPUT(c_long)], ["index"])
1001# # GetSlotBusDeviceFunction(DWORD * dwslot, DWORD * dwBus, DWORD * dwDevice, DWORD * dwFunction)
1002dllFunc(
1003 "GetSoftwareVersion",
1004 [OUTPUT(c_uint) for i in range(6)],
1005 ["eprom", "coffile", "vxdrev", "vxdver", "dllrev", "dllver"],
1006)
1007# # GetSpoolProgress(long * index)
1008# # GetStartUpTime(float * time)
1009dllFunc("GetStatus", [OUTPUT(c_int)], ["status"])
1010dllFunc("GetTECStatus", [OUTPUT(c_int)], ["piFlag"])
1011dllFunc("GetTemperature", [OUTPUT(c_int)], ["temperature"], True)
1012dllFunc("GetTemperatureF", [OUTPUT(c_float)], ["temperature"], True)
1013dllFunc(
1014 "GetTemperatureRange",
1015 [OUTPUT(c_int), OUTPUT(c_int)],
1016 ["mintemp", "maxtemp"],
1017)
1018# Reserved function seems to be incomplete - only populates first parameter with Ixon Ultra.
1019# dllFunc('GetTemperatureStatus', [OUTPUT(c_float) for i in range(4)],
1020# ['SensorTemp', 'TargetTemp', 'AmbientTemp', 'CoolerVolts'], True)
1021dllFunc("GetTotalNumberImagesAcquired", [OUTPUT(c_long)], ["index"])
1022dllFunc("GetIODirection", [c_int, OUTPUT(c_int)], ["index", "iDirection"])
1023dllFunc("GetIOLevel", [c_int, OUTPUT(c_int)], ["index", "iLevel"])
1024dllFunc(
1025 "GetVersionInfo",
1026 [AT_VersionInfoId, OUTSTRING, OUTSTRLEN],
1027 ["arr", "szVersionInfo", "ui32BufferLen"],
1028)
1029# # GetVerticalSpeed(int index, int * speed)
1030# # GetVirtualDMAAddress(void ** Address1, void ** Address2)
1031dllFunc("GetVSAmplitudeString", [c_int, OUTSTRING], ["index", "text"])
1032dllFunc("GetVSAmplitudeFromString", [STRING, OUTPUT(c_int)], ["text", "index"])
1033dllFunc("GetVSAmplitudeValue", [c_int, OUTPUT(c_int)], ["index", "value"])
1034dllFunc("GetVSSpeed", [c_int, OUTPUT(c_float)], ["index", "speed"])
1035# GPIBReceive(int id, short address, char * text, int size)
1036# GPIBSend(int id, short address, char * text)
1037# I2CBurstRead(BYTE i2cAddress, long nBytes, BYTE * data)
1038# I2CBurstWrite(BYTE i2cAddress, long nBytes, BYTE * data)
1039# I2CRead(BYTE deviceID, BYTE intAddress, BYTE * pdata)
1040# I2CReset(void)
1041# I2CWrite(BYTE deviceID, BYTE intAddress, BYTE data)
1042# #'IdAndorDll(void)
1043# InAuxPort(int port, int * state)
1044dllFunc("Initialize", [STRING], ["dir"])
1045# #'InitializeDevice(char * dir)
1046dllFunc("IsAmplifierAvailable", [c_int], ["iamp"], True)
1047dllFunc("IsCoolerOn", [OUTPUT(c_int)], ["iCoolerStatus"])
1048dllFunc("IsCountConvertModeAvailable", [c_int], ["mode"], True)
1049dllFunc("IsInternalMechanicalShutter", [OUTPUT(c_int)], ["InternalShutter"])
1050dllFunc(
1051 "IsPreAmpGainAvailable",
1052 [c_int, c_int, c_int, c_int, OUTPUT(c_int)],
1053 ["channel", "amplifier", "index", "pa", "status"],
1054)
1055dllFunc("IsTriggerModeAvailable", [c_int], ["iTriggerMode"], True)
1056# #'Merge(const at_32 * arr, long nOrder, long nPoint, long nPixel, float * coeff, long fit, long hbin, at_32 * output, float * start, float * step_Renamed)
1057# OutAuxPort(int port, int state)
1058dllFunc("PrepareAcquisition", [], [])
1059# SaveAsBmp(char * path, char * palette, long ymin, long ymax)
1060# SaveAsCommentedSif(char * path, char * comment)
1061# SaveAsEDF(char * szPath, int iMode)
1062# SaveAsFITS(char * szFileTitle, int typ)
1063# SaveAsRaw(char * szFileTitle, int typ)
1064# SaveAsSif(char * path)
1065# SaveAsSPC(char * path)
1066# SaveAsTiff(char * path, char * palette, int position, int typ)
1067# SaveAsTiffEx(char * path, char * palette, int position, int typ, int mode)
1068# #'SaveEEPROMToFile(char * cFileName)
1069# #'SaveToClipBoard(char * palette)
1070# #'SelectDevice(int devNum)
1071dllFunc("SendSoftwareTrigger", [], [])
1072dllFunc("SetAccumulationCycleTime", [c_float], ["time"])
1073# SetAcqStatusEvent(HANDLE statusEvent)
1074dllFunc("SetAcquisitionMode", [c_int], ["mode"])
1075# #'SetAcquisitionType(int typ)
1076dllFunc("SetADChannel", [c_int], ["channel"])
1077dllFunc("SetAdvancedTriggerModeState", [c_int], ["iState"])
1078# #'SetBackground(at_32 * arr, unsigned long size)
1079dllFunc("SetBaselineClamp", [c_int], ["state"])
1080dllFunc("SetBaselineOffset", [c_int], ["offset"])
1081dllFunc("SetCameraLinkMode", [c_int], ["mode"])
1082dllFunc("SetCameraStatusEnable", [DWORD], ["Enable"])
1083dllFunc("SetChargeShifting", [c_uint, c_uint], ["NumberRows", "NumberRepeats"])
1084dllFunc("SetComplexImage", [c_uint, POINTER(c_int)], ["numAreas", "areas"])
1085dllFunc("SetCoolerMode", [c_int], ["mode"])
1086dllFunc("SetCountConvertMode", [c_int], ["Mode"])
1087dllFunc("SetCountConvertWavelength", [c_float], ["wavelength"])
1088dllFunc(
1089 "SetCropMode", [c_int, c_int, c_int], ["active", "cropHeight", "reserved"]
1090)
1091dllFunc("SetCurrentCamera", [c_long], ["cameraHandle"])
1092dllFunc("SetCustomTrackHBin", [c_int], ["bin"])
1093# #'SetDataType(int typ)
1094dllFunc(
1095 "SetDACOutput", [c_int, c_int, c_int], ["iOption", "iResolution", "iValue"]
1096)
1097dllFunc("SetDACOutputScale", [c_int], ["iScale"])
1098# #'SetDDGAddress(BYTE t0, BYTE t1, BYTE t2, BYTE t3, BYTE address)
1099# SetDDGExternalOutputEnabled(at_u32 uiIndex, at_u32 uiEnabled)
1100# SetDDGExternalOutputPolarity(at_u32 uiIndex, at_u32 uiPolarity)
1101# SetDDGExternalOutputStepEnabled(at_u32 uiIndex, at_u32 uiEnabled)
1102# SetDDGExternalOutputTime(at_u32 uiIndex, at_u64 uiDelay, at_u64 uiWidth)
1103# #'SetDDGGain(int gain)
1104# SetDDGGateStep(double step_Renamed)
1105# SetDDGGateTime(at_u64 uiDelay, at_u64 uiWidth)
1106# SetDDGInsertionDelay(int state)
1107# SetDDGIntelligate(int state)
1108# SetDDGIOC(int state)
1109# SetDDGIOCFrequency(double frequency)
1110# SetDDGIOCNumber(unsigned long numberPulses)
1111# SetDDGIOCPeriod(at_u64 period)
1112# SetDDGIOCTrigger(at_u32 trigger)
1113# SetDDGOpticalWidthEnabled(at_u32 uiEnabled)
1114# #'SetDDGLiteGlobalControlByte(unsigned char control)
1115# #'SetDDGLiteControlByte(AT_DDGLiteChannelId channel, unsigned char control)
1116# #'SetDDGLiteInitialDelay(AT_DDGLiteChannelId channel, float fDelay)
1117# #'SetDDGLitePulseWidth(AT_DDGLiteChannelId channel, float fWidth)
1118# #'SetDDGLiteInterPulseDelay(AT_DDGLiteChannelId channel, float fDelay)
1119# #'SetDDGLitePulsesPerExposure(AT_DDGLiteChannelId channel, at_u32 ui32Pulses)
1120# SetDDGStepCoefficients(at_u32 mode, double p1, double p2)
1121# SetDDGStepMode(at_u32 mode)
1122# SetDDGTimes(double t0, double t1, double t2)
1123# SetDDGTriggerMode(int mode)
1124# SetDDGVariableGateStep(int mode, double p1, double p2)
1125# SetDelayGenerator(int board, short address, int typ)
1126# SetDMAParameters(int MaxImagesPerDMA, float SecondsPerDMA)
1127# SetDriverEvent(HANDLE driverEvent)
1128dllFunc("SetEMAdvanced", [c_int], ["state"])
1129dllFunc("SetEMCCDGain", [c_int], ["gain"])
1130# #'SetEMClockCompensation(int EMClockCompensationFlag)
1131dllFunc("SetEMGainMode", [c_int], ["mode"])
1132dllFunc("SetExposureTime", [c_float], ["time"])
1133dllFunc("SetExternalTriggerTermination", [at_u32], ["uiTermination"])
1134dllFunc("SetFanMode", [c_int], ["mode"])
1135dllFunc("SetFastExtTrigger", [c_int], ["mode"])
1136dllFunc(
1137 "SetFastKinetics",
1138 [c_int, c_int, c_float, c_int, c_int, c_int],
1139 ["exposedRows", "seriesLength", "time", "mode", "hbin", "vbin"],
1140)
1141dllFunc(
1142 "SetFastKineticsEx",
1143 [c_int, c_int, c_float, c_int, c_int, c_int, c_int],
1144 ["exposedRows", "seriesLength", "time", "mode", "hbin", "vbin", "offset"],
1145)
1146dllFunc("SetFilterMode", [c_int], ["mode"])
1147# #'SetFilterParameters(int width, float sensitivity, int range, float accept, int smooth, int noise)
1148dllFunc("SetFKVShiftSpeed", [c_int], ["index"])
1149# #'SetFPDP(int state)
1150dllFunc("SetFrameTransferMode", [c_int], ["mode"])
1151# SetFrontEndEvent(HANDLE driverEvent)
1152# #'SetFullImage(int hbin, int vbin)
1153dllFunc("SetFVBHBin", [c_int], ["bin"])
1154# #'SetGain(int gain)
1155dllFunc(
1156 "SetGate", [c_float, c_float, c_float], ["delay", "width", "stepRenamed"]
1157)
1158dllFunc("SetGateMode", [c_int], ["gatemode"])
1159dllFunc("SetHighCapacity", [c_int], ["state"])
1160# #'SetHorizontalSpeed(int index)
1161dllFunc("SetHSSpeed", [c_int, c_int], ["typ", "index"])
1162dllFunc(
1163 "SetImage",
1164 [c_int, c_int, c_int, c_int, c_int, c_int],
1165 ["bnin", "vbin", "hstar", "hend", "vstart", "vend"],
1166)
1167dllFunc("SetImageFlip", [c_int, c_int], ["iHFlip", "iVFlip"])
1168dllFunc("SetImageRotate", [c_int], ["iRotate"])
1169dllFunc(
1170 "SetIsolatedCropMode",
1171 [c_int, c_int, c_int, c_int, c_int],
1172 ["active", "cropheight", "cropwidth", "vbin", "hbin"],
1173)
1174dllFunc("SetKineticCycleTime", [c_float], ["time"])
1175dllFunc("SetMCPGain", [c_int], ["gain"])
1176dllFunc("SetMCPGating", [c_int], ["gating"])
1177# #'SetMessageWindow(HWND wnd)' # reser)
1178dllFunc("SetMetaData", [c_int], ["state"])
1179# SetMultiTrack(int number, int height, int offset, int * bottom, int * gap)
1180# SetMultiTrackHBin(int bin)
1181# SetMultiTrackHRange(int iStart, int iEnd)
1182# #'SetMultiTrackScan(int trackHeight, int numberTracks, int iSIHStart, int iSIHEnd, int trackHBinning, int trackVBinning, int trackGap, int trackOffset, int trackSkip, int numberSubFrames)
1183# #'SetNextAddress(at_32 * data, long lowAdd, long highAdd, long length, long physical)
1184# #'SetNextAddress16(at_32 * data, long lowAdd, long highAdd, long length, long physical)
1185dllFunc("SetNumberAccumulations", [c_int], ["number"])
1186dllFunc("SetNumberKinetics", [c_int], ["number"])
1187dllFunc("SetNumberPrescans", [c_int], ["iNumber"])
1188dllFunc("SetOutputAmplifier", [c_int], ["typ"])
1189dllFunc("SetOverlapMode", [c_int], ["mode"])
1190dllFunc("SetPCIMode", [c_int, c_int], ["mode", "value"])
1191dllFunc("SetPhotonCounting", [c_int], ["state"])
1192dllFunc("SetPhotonCountingThreshold", [c_long, c_long], ["min", "max"])
1193# SetPhosphorEvent(HANDLE driverEvent)
1194dllFunc(
1195 "SetPhotonCountingDivisions",
1196 [at_u32, at_32],
1197 ["noOfDivisions", "divisions"],
1198)
1199# #'SetPixelMode(int bitdepth, int colormode)
1200dllFunc("SetPreAmpGain", [c_int], ["index"])
1201dllFunc("SetDualExposureTimes", [c_float, c_float], ["expTime1", "expTime2"])
1202dllFunc("SetDualExposureMode", [c_int], ["mode"])
1203dllFunc("SetRandomTracks", [c_int, c_int], ["numTracks", "areas"])
1204dllFunc("SetReadMode", [c_int], ["mode"])
1205# #'SetRegisterDump(int mode)
1206dllFunc("SetRingExposureTimes", [c_int, c_float], ["numTimes", "times"])
1207# SetSaturationEvent(HANDLE saturationEvent)
1208dllFunc(
1209 "SetShutter",
1210 [c_int, c_int, c_int, c_int],
1211 ["typ", "mode", "closingtime", "openingtime"],
1212)
1213dllFunc(
1214 "SetShutterEx",
1215 [c_int, c_int, c_int, c_int, c_int],
1216 ["typ", "mode", "closingtime", "openingtime", "extmode"],
1217)
1218# #'SetShutters(int typ, int mode, int closingtime, int openingtime, int exttype, int extmode, int dummy1, int dummy2)
1219dllFunc("SetSifComment", [STRING], ["comment"])
1220dllFunc("SetSingleTrack", [c_int, c_int], ["centre", "height"])
1221dllFunc("SetSingleTrackHBin", [c_int], ["bin"])
1222dllFunc(
1223 "SetSpool",
1224 [c_int, c_int, STRING, c_int],
1225 ["active", "method", "path", "framebuffersize"],
1226)
1227dllFunc("SetSpoolThreadCount", [c_int], ["count"])
1228# #'SetStorageMode(long mode)
1229# SetTECEvent(HANDLE driverEvent)
1230dllFunc("SetTemperature", [c_int], ["temperature"])
1231# #'SetTemperatureEvent(HANDLE temperatureEvent)
1232dllFunc("SetTriggerMode", [c_int], ["mode"])
1233dllFunc("SetTriggerInvert", [c_int], ["mode"])
1234dllFunc(
1235 "GetTriggerLevelRange",
1236 [OUTPUT(c_float), OUTPUT(c_float)],
1237 ["minimum", "maximum"],
1238)
1239dllFunc("SetTriggerLevel", [c_float], ["f_level"])
1240dllFunc("SetIODirection", [c_int, c_int], ["index", "iDirection"])
1241dllFunc("SetIOLevel", [c_int, c_int], ["index", "iLevel"])
1242# #'SetUserEvent(HANDLE userEvent)
1243# #'SetUSGenomics(long width, long height)
1244# #'SetVerticalRowBuffer(int rows)
1245# #'SetVerticalSpeed(int index)
1246# #'SetVirtualChip(int state)
1247dllFunc("SetVSAmplitude", [c_int], ["index"])
1248dllFunc("SetVSSpeed", [c_int], ["index"])
1249dllFunc("ShutDown", [], [])
1250dllFunc("StartAcquisition", [], [])
1251# #'UnMapPhysicalAddress(void)
1252dllFunc("WaitForAcquisition", [], [])
1253dllFunc("WaitForAcquisitionByHandle", [c_long], ["cameraHandle"])
1254dllFunc(
1255 "WaitForAcquisitionByHandleTimeOut",
1256 [c_long, c_int],
1257 ["cameraHandle", "iTimeOutMs"],
1258)
1259dllFunc("WaitForAcquisitionTimeOut", [c_int], ["iTimeOutMs"])
1260# WhiteBalance(WORD * wRed, WORD * wGreen, WORD * wBlue, float * fRelR, float * fRelB, WhiteBalanceInfo * info)
1261# OA_Initialize(const char * const pcFilename, unsigned int uiFileNameLen)
1262# OA_EnableMode(const char * const pcModeName)
1263# OA_GetModeAcqParams(const char * const pcModeName, char * const pcListOfParams)
1264# OA_GetUserModeNames(char * pcListOfModes)
1265# OA_GetPreSetModeNames(char * pcListOfModes)
1266# OA_GetNumberOfUserModes(unsigned int * const puiNumberOfModes)
1267# OA_GetNumberOfPreSetModes(unsigned int * const puiNumberOfModes)
1268# OA_GetNumberOfAcqParams(const char * const pcModeName, unsigned int * const puiNumberOfParams)
1269# OA_AddMode(char * pcModeName, unsigned int uiModeNameLen, char * pcModeDescription, unsigned int uiModeDescriptionLen)
1270# OA_WriteToFile(const char * const pcFileName, unsigned int uiFileNameLen)
1271# OA_DeleteMode(const char * const pcModeName, unsigned int uiModeNameLen)
1272# OA_SetInt(const char * const pcModeName, const char * pcModeParam, const int iIntValue)
1273# OA_SetFloat(const char * const pcModeName, const char * pcModeParam, const float fFloatValue)
1274# OA_SetString(const char * const pcModeName, const char * pcModeParam, char * pcStringValue, const unsigned int uiStringLen)
1275# OA_GetInt(const char * const pcModeName, const char * const pcModeParam, int * iIntValue)
1276# OA_GetFloat(const char * const pcModeName, const char * const pcModeParam, float * fFloatValue)
1277# OA_GetString(const char * const pcModeName, const char * const pcModeParam, char * pcStringValue, const unsigned int uiStringLen)
1278# Filter_SetMode(unsigned int mode)
1279# Filter_GetMode(unsigned int * mode)
1280# Filter_SetThreshold(float threshold)
1281# Filter_GetThreshold(float * threshold)
1282# Filter_SetDataAveragingMode(int mode)
1283# Filter_GetDataAveragingMode(int * mode)
1284# Filter_SetAveragingFrameCount(int frames)
1285# Filter_GetAveragingFrameCount(int * frames)
1286# Filter_SetAveragingFactor(int averagingFactor)
1287# Filter_GetAveragingFactor(int * averagingFactor)
1288# PostProcessNoiseFilter(at_32 * pInputImage, at_32 * pOutputImage, int iOutputBufferSize, int iBaseline, int iMode, float fThreshold, int iHeight, int iWidth)
1289# PostProcessCountConvert(at_32 * pInputImage, at_32 * pOutputImage, int iOutputBufferSize, int iNumImages, int iBaseline, int iMode, int iEmGain, float fQE, float fSensitivity, int iHeight, int iWidth)
1290# PostProcessPhotonCounting(at_32 * pInputImage, at_32 * pOutputImage, int iOutputBufferSize, int iNumImages, int iNumframes, int iNumberOfThresholds, float * pfThreshold, int iHeight, int iWidth)
1291# #'PostProcessDataAveraging(at_32 * pInputImage, at_32 * pOutputImage, int iOutputBufferSize, int iNumImages, int iAveragingFilterMode, int iHeight, int iWidth, int iFrameCount, int iAveragingFactor)
1292
1293
1294class TriggerMode(IntEnum):
1295 """Camera trigger modes"""
1296
1297 INTERNAL = 0
1298 EXTERNAL = 1
1299 EXT_START = 6
1300 BULB = 7
1301 EXT_FVB = 9
1302 SOFTWARE = 10
1303
1304
1305class AcquisitionMode(IntEnum):
1306 """Acquisition modes."""
1307
1308 SINGLE = 1
1309 ACCUMULATE = 2
1310 KINETICS = 3
1311 FASTKINETICS = 4
1312 RUNTILLABORT = 5
1313
1314
1315class ReadMode(IntEnum):
1316 """Chip readout modes. Currently, only IMAGE is supported."""
1317
1318 FULLVERTICALBINNING = 0
1319 MULTITRACK = 1
1320 RANDOMTRACK = 2
1321 SINGLETRACK = 3
1322 IMAGE = 4
1323
1324
1326 """A combination of channel, amplifier and speed settings."""
1327
1328 def __init__(self, channel, amplifier, hs_index, speed):
1329 self.channel = channel # Channel index
1330 self.amp = amplifier # Amplifier enum
1331 self.hsindex = hs_index # HS speed index
1332 self.speed = speed # Shift frequency in MHz
1333
1334 def __str__(self):
1335 if self.speed < 1:
1336 speedstr = "{:.0f} kHz".format(self.speed * 1000)
1337 else:
1338 speedstr = "{:.0f} MHz".format(self.speed)
1339 return "{} {} CH{:.0f}".format(self.amp.name, speedstr, self.channel)
1340
1341
1342# A lock on the DLL used to ensure DLL calls act on the correct device.
1343_dll_lock = Lock()
1344
1345
1346ATMCD_MODE_TO_TRIGGER = {
1347 TriggerMode.EXTERNAL: (
1348 microscope.TriggerType.RISING_EDGE,
1349 microscope.TriggerMode.ONCE,
1350 ),
1351 TriggerMode.BULB: (
1352 microscope.TriggerType.RISING_EDGE,
1353 microscope.TriggerMode.BULB,
1354 ),
1355 TriggerMode.SOFTWARE: (
1356 microscope.TriggerType.SOFTWARE,
1357 microscope.TriggerMode.ONCE,
1358 ),
1359}
1360
1361TRIGGER_TO_ATMCD_MODE = {v: k for k, v in ATMCD_MODE_TO_TRIGGER.items()}
1362
1363
1367):
1368 """Implements CameraDevice interface for Andor ATMCD library."""
1369
1370 def __init__(self, index=0, **kwargs):
1371 super().__init__(index=index, **kwargs)
1372 # Recursion depth for context manager behaviour.
1373 self._rdepth = 0
1374 # The handle used by the DLL to identify this camera.
1375 self._handle = None
1376 # The following parameters will be populated after hardware init.
1377 self._roi = None
1378 self._binning = None
1380
1381 def _bind(self, fn):
1382 """Binds unbound SDK functions to this camera."""
1383
1384 @functools.wraps(fn)
1385 def wrapper(*args, **kwargs):
1386 with self:
1387 return fn(*args, **kwargs)
1388
1389 return wrapper
1390
1391 def __enter__(self):
1392 """Context manager entry code.
1393
1394 The camera class is also a context manager that ensures DLL calls act
1395 on this camera by obtaining the _dll_lock.
1396
1397 We could use RLock to give re-entrant behaviour, but we track recursion
1398 ourselves so that we know when we must call SetCurrentCamera.
1399 """
1400 if self._rdepth == 0:
1401 _dll_lock.acquire()
1402 SetCurrentCamera(self._handle)
1403 self._rdepth += 1
1404
1405 def __exit__(self, exc_type, exc_value, traceback):
1406 """Context manager exit code."""
1407 self._rdepth -= 1
1408 if self._rdepth == 0:
1409 _dll_lock.release()
1410
1411 @property
1412 def _acquiring(self):
1413 """Indicate whether or not camera is acquiring data."""
1414 with self:
1415 return GetStatus() == DRV_ACQUIRING
1416
1417 @_acquiring.setter
1418 def _acquiring(self, value):
1419 # Here to prevent an error when super.__init__ intializes
1420 # self._acquiring. Doesn't do anything, because the DLL keeps
1421 # track of acquisition state.
1422 pass
1423
1424 def abort(self):
1425 """Abort acquisition."""
1426 _logger.debug("Disabling acquisition.")
1427 try:
1428 with self:
1429 AbortAcquisition()
1430 except AtmcdException as e:
1431 if e.status != DRV_IDLE:
1432 raise
1433
1434 def _set_cooler_state(self, state):
1435 """Turn the sensor cooler on (True) or off (False)"""
1436 with self:
1437 if state:
1438 CoolerON()
1439 else:
1440 CoolerOFF()
1441
1442 def initialize(self):
1443 """Initialize the library and hardware and create Setting objects."""
1444 _logger.info("Initializing ...")
1445 num_cams = GetAvailableCameras()
1446 if self._index >= num_cams:
1447 msg = "Requested camera %d, but only found %d cameras" % (
1448 self._index,
1449 num_cams,
1450 )
1452 self._handle = GetCameraHandle(self._index)
1453
1454 with self:
1455 # Initialize the library and connect to camera.
1456 Initialize(b"")
1457 # Initialise ROI to full sensor area and binning to single-pixel.
1458 self._set_roi_set_roi(microscope.ROI(0, 0, 0, 0))
1460 # Check info bits to see if initialization successful.
1461 info = GetCameraInformation(self._index)
1462 if not info & 1 << 2:
1463 raise microscope.InitialiseError("... initialization failed.")
1464 self._caps = GetCapabilities()
1465 model = GetHeadModel()
1466 serial = self.get_idget_id()
1467 # Populate amplifiers
1468 if GetNumberAmp() > 1:
1469 if self._caps.ulCameraType == AC_CAMERATYPE_CLARA:
1470 self.amplifiers = IntEnum(
1471 "Amplifiers",
1472 (("CONVENTIONAL", 0), ("EXTENDED_NIR", 1)),
1473 )
1474 else:
1475 self.amplifiers = IntEnum(
1476 "Amplifiers", (("EMCCD", 0), ("CONVENTIONAL", 1))
1477 )
1478 # Populate readout modes
1480 for ch in range(GetNumberADChannels()):
1481 for amp in self.amplifiers:
1482 for s in range(GetNumberHSSpeeds(ch, amp.value)):
1483 speed = GetHSSpeed(ch, amp.value, s)
1484 self._readout_modes_readout_modes.append(
1485 ReadoutMode(ch, amp, s, speed)
1486 )
1487 _logger.info("... initilized %s s/n %s", model, serial)
1488 # Add settings. Some are write-only, so we set defaults here.
1489 # Mode
1490 name = "readout mode"
1492 self.add_setting(
1493 name,
1494 "enum",
1495 None,
1496 self._set_readout_mode,
1497 lambda: [str(mode) for mode in self._readout_modes_readout_modes],
1498 )
1499 self.set_settingset_setting(name, 0)
1500 # TriggerMode
1501 name = "TriggerMode"
1502 self.add_setting(
1503 name, "enum", None, self._bind(SetTriggerMode), TriggerMode
1504 )
1505 if self._caps.ulTriggerModes & AC_TRIGGERMODE_EXTERNAL:
1506 self.set_settingset_setting(name, TriggerMode.EXTERNAL)
1507 elif self._caps.ulTriggerModes & AC_TRIGGERMODE_CONTINUOUS:
1508 self.set_settingset_setting(name, TriggerMode.SOFTWARE)
1509 # Gain - device will use either EMGain or MCPGain
1510 name = "gain"
1511 getter, setter, vrange = None, None, None
1512 if self._caps.ulGetFunctions & AC_GETFUNCTION_EMCCDGAIN:
1513 getter = self._bind(GetEMCCDGain)
1514 elif self._caps.ulGetFunctions & AC_GETFUNCTION_MCPGAIN:
1515 getter = self._bind(GetMCPGain)
1516 if self._caps.ulSetFunctions & AC_SETFUNCTION_EMCCDGAIN:
1517 setter = self._bind(SetEMCCDGain)
1518 vrange = self._bind(GetEMGainRange)
1519 elif self._caps.ulSetFunctions & AC_SETFUNCTION_MCPGAIN:
1520 setter = self._bind(SetMCPGain)
1521 vrange = self._bind(GetMCPGainRange)
1522 if getter or setter:
1523 self.add_setting(name, "int", getter, setter, vrange)
1524 # Temperature
1525 name = "TemperatureSetPoint"
1526 getter, setter, vrange = None, None, None
1527 if self._caps.ulSetFunctions & AC_SETFUNCTION_TEMPERATURE:
1528 setter = self._bind(SetTemperature)
1529 if self._caps.ulGetFunctions & AC_GETFUNCTION_TEMPERATURERANGE:
1530 vrange = self._bind(GetTemperatureRange)
1531 if setter:
1532 self.add_setting(name, "int", None, setter, vrange)
1533 # Set a conservative default temperature set-point.
1534 self.set_settingset_setting(name, -20)
1535 # Fan control
1536 name = "Temperature"
1537 self.add_setting(
1538 name, "int", self._get_sensor_temperature, None, (None, None)
1539 )
1540 name = "Fan mode"
1541 self.add_setting(
1542 name,
1543 "enum",
1544 None, # Can't query fan mode
1545 self._bind(SetFanMode),
1546 {0: "full", 1: "low", 2: "off"},
1547 )
1548 # Cooler control
1549 name = "Cooler Enabled"
1550 self.add_setting(name, "bool", None, self._set_cooler_state, None)
1551 self.set_settingset_setting(name, True)
1552 # Binning
1553 name = "Binning"
1554 self.add_setting(
1555 name, "tuple", self.get_binning, self.set_binning, None
1556 )
1557 # Roi
1558 name = "Roi"
1559 self.add_setting(
1560 name, "tuple", self.get_roi, lambda roi: self.set_roi(*roi), None
1561 )
1562 # BaselineClamp
1563 name = "BaselineClamp"
1564 if self._caps.ulSetFunctions & AC_SETFUNCTION_BASELINECLAMP:
1565 self.add_setting(
1566 name, "bool", None, self._bind(SetBaselineClamp), None
1567 )
1568 self.set_settingset_setting(name, False)
1569 # BaselineOffset
1570 name = "BaselineOffset"
1571 if self._caps.ulSetFunctions & AC_SETFUNCTION_BASELINEOFFSET:
1572 self.add_setting(
1573 name, "int", None, self._bind(SetBaselineOffset), (-1000, 1000)
1574 )
1575 self.set_settingset_setting(name, 0)
1576 # EMAdvanced
1577 name = "EMAdvanced"
1578 if self._caps.ulSetFunctions & AC_SETFUNCTION_EMADVANCED:
1579 self.add_setting(
1580 name, "bool", None, self._bind(SetEMAdvanced), None
1581 )
1582 self.set_settingset_setting(name, False)
1583 # GateMode
1584 name = "GateMode"
1585 if self._caps.ulSetFunctions & AC_SETFUNCTION_GATEMODE:
1586 vrange = range(
1587 0, [5, 6][self._caps.ulCameraType & AC_CAMERATYPE_ISTAR]
1588 )
1589 self.add_setting(
1590 name, "int", None, self._bind(SetGateMode), vrange
1591 )
1592 # HighCapacity
1593 name = "HighCapacity"
1594 if self._caps.ulSetFunctions & AC_SETFUNCTION_HIGHCAPACITY:
1595 self.add_setting(
1596 name, "bool", None, self._bind(SetHighCapacity), None
1597 )
1598
1599 def _fetch_data(self):
1600 """Poll for data and return it, with minimal processing.
1601
1602 Returns the data, or None if no data is available.
1603 """
1604 binning = self._binning
1605 roi = self._roi
1606 width = roi.width // binning.h
1607 height = roi.height // binning.v
1608 try:
1609 with self:
1610 data = GetOldestImage16(width * height).reshape(height, width)
1611 except AtmcdException as e:
1612 if e.status == DRV_NO_NEW_DATA:
1613 return None
1614 else:
1615 raise e
1616 return data
1617
1618 def get_id(self):
1619 """Return the device's unique identifier."""
1620 with self:
1621 return GetCameraSerialNumber()
1622
1623 def _do_shutdown(self) -> None:
1624 """Warm up the sensor then shut down the camera.
1625
1626 This may take some time, so we should ensure that the _dll_lock is
1627 released when we don't need it."""
1628 # Switch off cooler then release lock.
1629 with self:
1630 CoolerOFF()
1631
1632 _logger.info(
1633 "Waiting for temperature to rise above -20C" " before shutdown ..."
1634 )
1635
1636 while True:
1637 # Check temperature then release lock.
1638 with self:
1639 t = GetTemperature()[1]
1640 _logger.info("... T = %dC", t)
1641 if t > -20:
1642 break
1643 time.sleep(10)
1644
1645 _logger.info("Temperature is %dC: shutting down camera.", t)
1646
1647 with self:
1648 ShutDown()
1649
1650 def _do_disable(self):
1651 """Call abort to stop acquisition."""
1652 self.abortabort()
1653
1654 def _do_enable(self):
1655 """Enter data acquisition state."""
1657 self.abortabort()
1658 with self:
1659 SetAcquisitionMode(AcquisitionMode.RUNTILLABORT)
1660 SetShutter(1, 1, 1, 1)
1661 SetReadMode(ReadMode.IMAGE)
1662 x, y = GetDetector()
1663 self._set_image()
1664 if not IsTriggerModeAvailable(self.get_setting("TriggerMode")):
1666 "Trigger mode is not valid."
1667 )
1668 StartAcquisition()
1669 return True
1670
1671 def _set_image(self):
1672 """Set ROI and binning prior to acquisition."""
1673 binning = (
1674 self._binning
1675 ) # Binning is mode-dependent, so not validated yet.
1676 roi = self._roi # ROI validated in _set_roi, so should be OK
1677 with self:
1678 try:
1679 SetImage(
1680 binning.h,
1681 binning.v,
1682 roi.left,
1683 roi.left + roi.width - 1,
1684 roi.top,
1685 roi.top + roi.height - 1,
1686 )
1687 except AtmcdException as e:
1688 if e.status == DRV_P1INVALID:
1689 out_e = ValueError("Horizontal binning invalid.")
1690 elif e.status == DRV_P2INVALID:
1691 e = ValueError("Vertical binning invalid.")
1692 elif e.status == DRV_P3INVALID:
1693 out_e = ValueError("roi.left invalid.")
1694 elif e.status == DRV_P4INVALID:
1695 out_e = ValueError("roi.width invalid.")
1696 elif e.status == DRV_P5INVALID:
1697 out_e = ValueError("roi.top invalid.")
1698 elif e.status == DRV_P6INVALID:
1699 out_e = ValueError("roi.height invalid.")
1700 else:
1701 out_e = e
1702 # Just raise the descriptive exception, not the chain.
1703 raise out_e from None
1704
1705 @microscope.abc.keep_acquiring
1706 def set_exposure_time(self, value):
1707 """Set exposure time."""
1708 with self:
1709 SetExposureTime(value)
1710
1712 """Query the actual exposure time."""
1713 with self:
1714 exposure, accumulate, kinetic = GetAcquisitionTimings()
1715 return exposure
1716
1718 """Determine the minimum time between exposures."""
1719 with self:
1720 exposure, accumulate, kinetic = GetAcquisitionTimings()
1721 readout = GetReadOutTime()
1722 # IMD 20210422 DeepSIM timing is wrong as the keepclear cycles are
1723 # not accounted for.
1724 # return exposure + readout
1725 # This appears to allow the correct time between trigger pulses.
1726 return kinetic
1727
1728 def _set_readout_mode(self, mode_index):
1729 """Configure channel, amplifier and VS-speed."""
1730 mode = self._readout_modes_readout_modes[mode_index]
1731 _logger.info("Setting readout mode to %s", mode)
1732 with self:
1733 SetADChannel(mode.channel)
1734 SetOutputAmplifier(mode.amp)
1735 # On (at least) the Ixon Ultra, the two amplifiers read from
1736 # opposite edges from the chip. We set the horizontal flip
1737 # so that the returned image orientation is independent of
1738 # amplifier selection
1739 SetImageFlip(not mode.amp, 0)
1740 SetHSSpeed(mode.amp, mode.hsindex)
1741
1742 def _get_sensor_shape(self):
1743 """Return the sensor geometry."""
1744 with self:
1745 return GetDetector()
1746
1747 def _get_sensor_temperature(self):
1748 """Return the sensor temperature."""
1749 with self:
1750 return GetTemperature()[1]
1751
1752 def soft_trigger(self):
1753 """Send a software trigger signal.
1754
1755 Deprecated, use trigger().
1756 """
1757 with self:
1758 SendSoftwareTrigger()
1759
1760 @property
1761 def trigger_mode(self) -> microscope.TriggerMode:
1762 return ATMCD_MODE_TO_TRIGGER[self.get_setting("TriggerMode")][1]
1763
1764 @property
1765 def trigger_type(self) -> microscope.TriggerType:
1766 return ATMCD_MODE_TO_TRIGGER[self.get_setting("TriggerMode")][0]
1767
1769 self, ttype: microscope.TriggerType, tmode: microscope.TriggerMode
1770 ) -> None:
1771 try:
1772 atmcd_mode = TRIGGER_TO_ATMCD_MODE[(ttype, tmode)]
1773 except KeyError:
1775 "no ATMCD mode for %s and %s" % (ttype, tmode)
1776 )
1777 self.set_settingset_setting("TriggerMode", atmcd_mode)
1778
1779 def _do_trigger(self) -> None:
1780 with self:
1781 SendSoftwareTrigger()
1782
1783 def _get_binning(self):
1784 """Return the binning setting."""
1785 return self._binning
1786
1787 @microscope.abc.keep_acquiring
1788 def _set_binning(self, binning):
1789 """Set horizontal and vertical binning. Default to single pixel."""
1790 self._binning = binning
1791 return True
1792
1793 def _get_roi(self):
1794 """Return the current ROI setting."""
1795 return self._roi
1796
1797 @microscope.abc.keep_acquiring
1798 def _set_roi(self, roi):
1799 """Set the ROI, defaulting to full sensor area."""
1800 with self:
1801 x, y = GetDetector()
1802 left = roi.left or 1
1803 top = roi.top or 1
1804 width = roi.width or x
1805 height = roi.height or y
1806 if any(
1807 [left < 1, top < 1, left + width - 1 > x, top + height - 1 > y]
1808 ):
1809 return False
1810 self._roi = microscope.ROI(left, top, width, height)
1811 return True
None set_binning(self, microscope.Binning binning)
Definition: abc.py:946
microscope.ROI get_roi(self)
Definition: abc.py:961
def _set_roi(self, microscope.ROI roi)
Definition: abc.py:970
None set_roi(self, microscope.ROI roi)
Definition: abc.py:974
def _set_binning(self, microscope.Binning binning)
Definition: abc.py:942
microscope.Binning get_binning(self)
Definition: abc.py:933
None abort(self)
Definition: abc.py:588
None add_setting(self, name, dtype, get_func, set_func, values, typing.Optional[typing.Callable[[], bool]] readonly=None)
Definition: abc.py:407
def get_setting(self, str name)
Definition: abc.py:447
None initialize(self)
Definition: abc.py:339
None set_setting(self, str name, value)
Definition: abc.py:468
def _set_readout_mode(self, mode_index)
Definition: atmcd.py:1728
def set_exposure_time(self, value)
Definition: atmcd.py:1706
def __exit__(self, exc_type, exc_value, traceback)
Definition: atmcd.py:1405
def _set_binning(self, binning)
Definition: atmcd.py:1788
None set_trigger(self, microscope.TriggerType ttype, microscope.TriggerMode tmode)
Definition: atmcd.py:1770
def _set_cooler_state(self, state)
Definition: atmcd.py:1434