# -*- coding: utf-8 -*-
"""
lantz.drivers.andor.andor
~~~~~~~~~~~~~~~~~~~~~~~~~
Low level driver wrapping atcore andor library.
Sources::
- Andor Manual
:copyright: 2015 by Lantz Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
import ctypes as ct
from lantz import Driver, Feat, Action
from lantz.errors import InstrumentError
from lantz.foreign import LibraryDriver
_ERRORS = {
0: 'SUCCESS',
1: 'AT_ERR_NOTINITIALISED',
#1: 'AT_HANDLE_SYSTEM', # TODO: Check twice the same key!
2: 'AT_ERR_NOTIMPLEMENTED',
3: 'AT_ERR_READONLY',
4: 'AT_ERR_NOTREADABLE',
5: 'AT_ERR_NOTWRITABLE',
6: 'AT_ERR_OUTOFRANGE',
7: 'AT_ERR_INDEXNOTAVAILABLE',
8: 'AT_ERR_INDEXNOTIMPLEMENTED',
9: 'AT_ERR_EXCEEDEDMAXSTRINGLENGTH',
10: 'AT_ERR_CONNECTION',
11: 'AT_ERR_NODATA',
12: 'AT_ERR_INVALIDHANDLE',
13: 'AT_ERR_TIMEDOUT',
14: 'AT_ERR_BUFFERFULL',
15: 'AT_ERR_INVALIDSIZE',
16: 'AT_ERR_INVALIDALIGNMENT',
17: 'AT_ERR_COMM',
18: 'AT_ERR_STRINGNOTAVAILABLE',
19: 'AT_ERR_STRINGNOTIMPLEMENTED',
20: 'AT_ERR_NULL_FEATURE',
21: 'AT_ERR_NULL_HANDLE',
22: 'AT_ERR_NULL_IMPLEMENTED_VAR',
23: 'AT_ERR_NULL_READABLE_VAR',
24: 'AT_ERR_NULL_READONLY_VAR',
25: 'AT_ERR_NULL_WRITABLE_VAR',
26: 'AT_ERR_NULL_MINVALUE',
27: 'AT_ERR_NULL_MAXVALUE',
28: 'AT_ERR_NULL_VALUE',
29: 'AT_ERR_NULL_STRING',
30: 'AT_ERR_NULL_COUNT_VAR',
31: 'AT_ERR_NULL_ISAVAILABLE_VAR',
32: 'AT_ERR_NULL_MAXSTRINGLENGTH',
33: 'AT_ERR_NULL_EVCALLBACK',
34: 'AT_ERR_NULL_QUEUE_PTR',
35: 'AT_ERR_NULL_WAIT_PTR',
36: 'AT_ERR_NULL_PTRSIZE',
37: 'AT_ERR_NOMEMORY',
100: 'AT_ERR_HARDWARE_OVERFLOW',
-1: 'AT_HANDLE_UNINITIALISED'
}
[docs]class Andor(LibraryDriver):
LIBRARY_NAME = 'atcore.dll'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.AT_H = ct.c_int()
self.AT_U8 = ct.c_ubyte()
self.cameraIndex = ct.c_int(0)
def _patch_functions(self):
internal = self.lib.internal
internal.AT_Command.argtypes = [ct.c_int, ct.c_wchar_p, ]
internal.AT_GetInt.argtypes = [ct.c_int, ct.c_wchar_p, ct.addressof(ct.c_longlong)]
internal.AT_SetInt.argtypes = [ct.c_int, ct.c_wchar_p, ct.c_longlong]
internal.AT_GetFloat.argtypes = [ct.c_int, ct.c_wchar_p, ct.addressof(ct.c_double)]
internal.AT_SetFloat.argtypes = [ct.c_int, ct.c_wchar_p, ct.c_double]
internal.AT_GetBool.argtypes = [ct.c_int, ct.c_wchar_p, ct.addressof(ct.c_bool)]
internal.AT_SetBool.argtypes = [ct.c_int, ct.c_wchar_p, ct.c_bool]
internal.AT_GetEnumerated.argtypes = [ct.c_int, ct.c_wchar_p, ct.addressof(ct.c_int)]
internal.AT_SetEnumerated.argtypes = [ct.c_int, ct.c_wchar_p, ct.c_int]
internal.AT_SetEnumString.argtypes = [ct.c_int, ct.c_wchar_p, ct.c_wchar_p]
def _return_handler(self, func_name, ret_value):
if ret_value != 0:
raise InstrumentError('{} ({})'.format(ret_value, _ERRORS[ret_value]))
return ret_value
[docs] def initialize(self):
"""Initialize Library.
"""
self.lib.AT_InitialiseLibrary()
self.open()
[docs] def finalize(self):
"""Finalize Library. Concluding function.
"""
self.close()
self.lib.AT_FinaliseLibrary()
@Action()
def open(self):
"""Open camera self.AT_H.
"""
camidx = ct.c_int(0)
self.lib.AT_Open(camidx, ct.addressof(self.AT_H))
return self.AT_H
@Action()
def close(self):
"""Close camera self.AT_H.
"""
self.lib.AT_Close(self.AT_H)
[docs] def is_implemented(self, strcommand):
"""Checks if command is implemented.
"""
result = ct.c_bool()
command = ct.c_wchar_p(strcommand)
self.lib.AT_IsImplemented(self.AT_H, command, ct.addressof(result))
return result.value
[docs] def is_writable(self, strcommand):
"""Checks if command is writable.
"""
result = ct.c_bool()
command = ct.c_wchar_p(strcommand)
self.lib.AT_IsWritable(self.AT_H, command, ct.addressof(result))
return result.value
[docs] def queuebuffer(self, bufptr, value):
"""Put buffer in queue.
"""
value = ct.c_int(value)
self.lib.AT_QueueBuffer(self.AT_H, ct.byref(bufptr), value)
[docs] def waitbuffer(self, ptr, bufsize):
"""Wait for next buffer ready.
"""
timeout = ct.c_int(20000)
self.lib.AT_WaitBuffer(self.AT_H, ct.byref(ptr), ct.byref(bufsize), timeout)
[docs] def command(self, strcommand):
"""Run command.
"""
command = ct.c_wchar_p(strcommand)
self.lib.AT_Command(self.AT_H, command)
[docs] def getint(self, strcommand):
"""Run command and get Int return value.
"""
result = ct.c_longlong()
command = ct.c_wchar_p(strcommand)
self.lib.AT_GetInt(self.AT_H, command, ct.addressof(result))
return result.value
[docs] def setint(self, strcommand, value):
"""SetInt function.
"""
command = ct.c_wchar_p(strcommand)
value = ct.c_longlong(value)
self.lib.AT_SetInt(self.AT_H, command, value)
[docs] def getfloat(self, strcommand):
"""Run command and get Int return value.
"""
result = ct.c_double()
command = ct.c_wchar_p(strcommand)
self.lib.AT_GetFloat(self.AT_H, command, ct.addressof(result))
return result.value
[docs] def setfloat(self, strcommand, value):
"""Set command with Float value parameter.
"""
command = ct.c_wchar_p(strcommand)
value = ct.c_double(value)
self.lib.AT_SetFloat(self.AT_H, command, value)
[docs] def getbool(self, strcommand):
"""Run command and get Bool return value.
"""
result = ct.c_bool()
command = ct.c_wchar_p(strcommand)
self.lib.AT_GetBool(self.AT_H, command, ct.addressof(result))
return result.value
[docs] def setbool(self, strcommand, value):
"""Set command with Bool value parameter.
"""
command = ct.c_wchar_p(strcommand)
value = ct.c_bool(value)
self.lib.AT_SetBool(self.AT_H, command, value)
[docs] def getenumerated(self, strcommand):
"""Run command and set Enumerated return value.
"""
result = ct.c_int()
command = ct.c_wchar_p(strcommand)
self.lib.AT_GetEnumerated(self.AT_H, command, ct.addressof(result))
[docs] def setenumerated(self, strcommand, value):
"""Set command with Enumerated value parameter.
"""
command = ct.c_wchar_p(strcommand)
value = ct.c_bool(value)
self.lib.AT_SetEnumerated(self.AT_H, command, value) #TODO: IS THIS CORRECT
[docs] def setenumstring(self, strcommand, item):
"""Set command with EnumeratedString value parameter.
"""
command = ct.c_wchar_p(strcommand)
item = ct.c_wchar_p(item)
self.lib.AT_SetEnumString(self.AT_H, command, item)
[docs] def flush(self):
self.lib.AT_Flush(self.AT_H)
if __name__ == '__main__':
import numpy as np
import ctypes as ct
from andor import Andor
from matplotlib import pyplot as plt
with Andor() as andor:
andor.flush()
width = andor.getint("SensorWidth")
height = andor.getint("SensorHeight")
length = width * height
#andor.setenumerated("FanSpeed", 2)
andor.getfloat("SensorTemperature")
andor.setfloat("ExposureTime", 0.001)
andor.setenumstring("PixelReadoutRate", "100 MHz")
andor.setenumstring("PixelEncoding", "Mono32")
#andor.setenumstring("PixelEncoding", "Mono16")
imagesizebytes = andor.getint("ImageSizeBytes")
userbuffer = ct.create_string_buffer(' ' * imagesizebytes)
andor.queuebuffer(userbuffer, imagesizebytes)
imsize = ct.c_int(1)
ubuffer = ct.create_string_buffer(" " * 1)
andor.command("AcquisitionStart")
andor.waitbuffer(ubuffer, imsize)
andor.command("AcquisitionStop")
andor.flush()
image = np.fromstring(userbuffer, dtype=np.uint32, count=length)
#image = np.fromstring(userbuffer, dtype=np.uint16, count=length)
image.shape = (height, width)
im = plt.imshow(image, cmap = 'gray')
plt.show()
print(image.min(), image.max(), image.mean())