# -*- coding: utf-8 -*- """ Andor Zyla 5.5 Camera Driver. Adapted from the PYME driver. """ import sys sys.path.append(r'C:\Users\Usuario\Anaconda3\Lib\site-packages') import time import numpy as np import threading import ctypes from datetime import datetime import pylab as plt from PyQt5 import QtCore def _add_path_to_os_path(): # This makes sure that SDK3 finds the DLLs import os p = os.environ['PATH'].split(';') from drivers.PYME.Acquire.Hardware import AndorNeo loc, _ = os.path.split(AndorNeo.__file__) if loc in p: return p.append(loc) os.environ['path'] = ';'.join(p) _add_path_to_os_path() #%% from drivers.PYME.Acquire.Hardware.AndorNeo import SDK3 from drivers.PYME.Acquire.Hardware.AndorNeo.SDK3Cam import SDK3Camera from drivers.PYME.Acquire.Hardware.AndorNeo.SDK3Cam import ATBool, ATCommand, ATEnum, ATInt, ATString, ATFloat, camReg try: import Queue except ImportError: import queue as Queue from drivers.PYME.Acquire import MetaDataHandler def create_aligned_array(shape, dtype=np.typeDict['singlecomplex'], boundary=16): array = np.zeros(shape, dtype=dtype) if (array.ctypes.data % boundary) == 0: return array extra = boundary / array.itemsize buf = np.empty(array.size + extra, dtype=array.dtype) ofs = (-buf.ctypes.data % boundary) / array.itemsize aligned_array = buf[ofs:ofs+array.size].reshape(array.shape) np.copyto(aligned_array, array) assert (aligned_array.ctypes.data % boundary) == 0 return aligned_array class Helper_messager(QtCore.QObject): imageAquiredSignal = QtCore.pyqtSignal(int) class AndorBase(SDK3Camera): numpy_frames=1 MODE_CONTINUOUS = 1 MODE_SINGLE_SHOT = 0 # validROIS = [(2592, 2160,1, 1), # (2544,2160,1,25), # (2064,2048,57,265), # (1776,1760,201,409), # (1920,1080,537,337), # (1392,1040,561,601), # (528,512,825,1033), # (240,256,953,1177), # (144,128,1017,1225)] def __init__(self, camNum): #some helper attributes (Martin) self.helper = Helper_messager() self.acq_queue = Queue.Queue(maxsize=10) self.current_image = None #define properties self.CameraAcquiring = ATBool() self.SensorCooling = ATBool() self.AcquisitionStart = ATCommand() self.AcquisitionStop = ATCommand() self.CycleMode = ATEnum() self.ElectronicShutteringMode = ATEnum() self.FanSpeed = ATEnum() self.PreAmpGainChannel = ATEnum() self.PixelEncoding = ATEnum() self.PixelReadoutRate = ATEnum() self.PreAmpGain = ATEnum() self.PreAmpGainSelector = ATEnum() self.TriggerMode = ATEnum() self.AOIBinning = ATEnum() self.AOIHeight = ATInt() self.AOILeft = ATInt() self.AOITop = ATInt() self.AOIWidth = ATInt() self.AOIStride = ATInt() self.FrameCount = ATInt() self.ImageSizeBytes = ATInt() self.SensorHeight = ATInt() self.SensorWidth = ATInt() self.BufferOverflowEvent = ATInt() self.Baseline = ATInt() self.CameraModel = ATString() self.SerialNumber = ATString() self.CameraName = ATString() self.ExposureTime = ATFloat() self.FrameRate = ATFloat() self.SensorTemperature = ATFloat() self.TargetSensorTemperature = ATFloat() SDK3Camera.__init__(self,camNum) #end auto properties self.camLock = threading.Lock() self.buffersToQueue = Queue.Queue() self.queuedBuffers = Queue.Queue() self.fullBuffers = Queue.Queue() self.nQueued = 0 self.nFull = 0 self.nBuffers = 100 self.defBuffers = 100 self.contMode = True self.burstMode = False self._temp = 0 self._frameRate = 0 self.active = True #register as a provider of metadata MetaDataHandler.provideStartMetadata.append(self.GenStartMetadata) # def Init(self): # SDK3Camera.Init(self) # # #set some intial parameters # #self.FrameCount.setValue(1) # self.CycleMode.setString(u'Continuous') # px_encoding = self.PixelEncoding.getString() # print(px_encoding) # self.PixelEncoding.setString(px_encoding) # self.SensorCooling.setValue(True) # #self.TemperatureControl.setString('-30.00') # #self.PixelReadoutRate.setIndex(1) # # #set up polling thread # self.doPoll = False # self.pollLoopActive = True # self.pollThread = threading.Thread(target = self._pollLoop) # self.pollThread.start() # # # def Init2(self): # SDK3Camera.Init(self) # # #set some intial parameters # self.CycleMode.setString(u'Fixed') # self.FrameCount.setValue(1) # px_encoding = self.PixelEncoding.getString() # print(px_encoding) # self.SensorCooling.setValue(True) # #self.TemperatureControl.setString('-30.00') # #self.PixelReadoutRate.setIndex(1) # # #set up polling thread # self.doPoll = False # self.pollLoopActive = True # self.pollThread = threading.Thread(target = self._pollLoop) # self.pollThread.start() #Neo buffer helper functions def InitBuffers(self): self._flush() bufSize = self.ImageSizeBytes.getValue() vRed = int(self.SensorHeight.getValue()/self.AOIHeight.getValue()) self.nBuffers = vRed*self.defBuffers #print bufSize for i in range(self.nBuffers): #buf = np.empty(bufSize, 'uint8') buf = create_aligned_array(bufSize, 'uint8') self._queueBuffer(buf) self.doPoll = True def _flush(self): self.doPoll = False #purge camera buffers SDK3.Flush(self.handle) #purge our local queues while not self.queuedBuffers.empty(): self.queuedBuffers.get() while not self.buffersToQueue.empty(): self.buffersToQueue.get() self.nQueued = 0 while not self.fullBuffers.empty(): self.fullBuffers.get() self.nFull = 0 #purge camera buffers SDK3.Flush(self.handle) def _queueBuffer(self, buf): #self.queuedBuffers.put(buf) #print np.base_repr(buf.ctypes.data, 16) #SDK3.QueueBuffer(self.handle, buf.ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), buf.nbytes) #self.nQueued += 1 self.buffersToQueue.put(buf) def _queueBuffers(self): #self.camLock.acquire() while not self.buffersToQueue.empty(): buf = self.buffersToQueue.get(block=False) self.queuedBuffers.put(buf) #print np.base_repr(buf.ctypes.data, 16) SDK3.QueueBuffer(self.handle, buf.ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), buf.nbytes) #self.fLog.write('%f\tq\n' % time.time()) self.nQueued += 1 #self.camLock.release() def _pollBuffer(self): try: #self.fLog.write('%f\tp\n' % time.time()) pData, lData = SDK3.WaitBuffer(self.handle, 100) #self.fLog.write('%f\tb\n' % time.time()) except SDK3.TimeoutError as e: #Both AT_ERR_TIMEDOUT and AT_ERR_NODATA #get caught as TimeoutErrors #if e.errNo == SDK3.AT_ERR_TIMEDOUT: # self.fLog.write('%f\tt\n' % time.time()) #else: # self.fLog.write('%f\tn\n' % time.time()) return #except SDK3.CameraError as e: # if not e.errNo == SDK3.AT_ERR_NODATA: # traceback.print_exc() # return #self.camLock.acquire() buf = self.queuedBuffers.get() self.nQueued -= 1 if not buf.ctypes.data == ctypes.addressof(pData.contents): print((ctypes.addressof(pData.contents), buf.ctypes.data)) #self.camLock.release() raise RuntimeError('Returned buffer not equal to expected buffer') #print 'Returned buffer not equal to expected buffer' self.fullBuffers.put(buf) self.nFull += 1 #self.camLock.release() def _pollLoop(self): #self.fLog = open('poll.txt', 'w') while self.pollLoopActive: self._queueBuffers() if self.doPoll: #only poll if an acquisition is running self._pollBuffer() else: #print 'w', time.sleep(.05) time.sleep(.0005) #self.fLog.flush() #self.fLog.close() #PYME Camera interface functions - make this look like the other cameras def ExpReady(self): #self._pollBuffer() return not self.fullBuffers.empty() def ExtractColor(self, chSlice, mode): #grab our buffer from the full buffers list buf = self.fullBuffers.get() self.nFull -= 1 #copy to the current 'active frame' #print chSlice.shape, buf.view(chSlice.dtype).shape #bv = buf.view(chSlice.dtype).reshape(chSlice.shape) xs, ys = chSlice.shape[:2] a_s = self.AOIStride.getValue() #print buf.nbytes #bv = buf.view(chSlice.dtype).reshape([-1, ys], order='F') # bv = np.ndarray(shape=[xs,ys], dtype='uint16', strides=[2, a_s], buffer=buf) # chSlice[:] = bv #chSlice[:,:] = bv #ctypes.cdll.msvcrt.memcpy(chSlice.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), chSlice.nbytes) #ctypes.cdll.msvcrt.memcpy(chSlice.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), chSlice.nbytes) #print 'f' dt = self.PixelEncoding.getString() SDK3.ConvertBuffer(buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), chSlice.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, dt, 'Mono16') #SDK3.ConvertBuffer(buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), chSlice.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, dt, dt) #recycle buffer self._queueBuffer(buf) def GetSerialNumber(self): return self.SerialNumber.getValue() def SetExposureTime(self, iTime): self.ExposureTime.setValue(iTime*1e-3) self.FrameRate.setValue(self.FrameRate.max()) def GetExposureTime(self): return self.ExposureTime.getValue() def GetSensorWidth(self): return self.SensorHeight.getValue() def GetSensorHeight(self): return self.SensorWidth.getValue() def SetHorizBin(*args): raise Exception('Not implemented yet!!') def GetHorizBin(*args): return 0 #raise Exception, 'Not implemented yet!!' def GetHorzBinValue(*args): raise Exception('Not implemented yet!!') def SetVertBin(*args): raise Exception('Not implemented yet!!') def GetVertBin(*args): return 0 #raise Exception, 'Not implemented yet!!' def GetNumberChannels(*args): raise Exception('Not implemented yet!!') def GetElectrTemp(*args): return 25 def GetSensorTemp(self): #for some reason querying the temperature takes a lot of time - do it less often return self.SensorTemperature.getValue() def GetTemperatureStatus(self): return self.TemperatureStatus.getString() def GetCCDTemp2(self): #for some reason querying the temperature takes a lot of time - do it less often return self.SensorTemperature.getValue() #return self._temp def CamReady(*args): return True def GetPicWidth(self): return self.AOIWidth.getValue() def GetPicHeight(self): return self.AOIHeight.getValue() def SetROIIndex(self, index): width, height, top, left = self.validROIS[index] self.AOIWidth.setValue(width) self.AOILeft.setValue(left) self.AOIHeight.setValue(height) self.AOITop.setValue(top) def SetROI(self, x1, y1, x2, y2): #shouldn't do GUI stuff here, but quick way of making it work #print('Setting ROI') #import wx #dlg = wx.SingleChoiceDialog(None, 'Please select the ROI size', 'Camera ROI', ['%dx%d at (%d, %d)' % roi for roi in self.validROIS]) #dlg.ShowModal() #self.SetROIIndex(dlg.GetSelection()) #dlg.Destroy() print(x1, y1, x2-x1, y2-y1) #pass #silently fail #have to set width before x, height before y self.AOIWidth.setValue(x2-x1) self.AOIHeight.setValue(y2 - y1) self.AOILeft.setValue(x1+1) self.AOITop.setValue(y1+1) def GetROIX1(self): return self.AOILeft.getValue() def GetROIX2(self): return self.AOILeft.getValue() + self.AOIWidth.getValue() def GetROIY1(self): return self.AOITop.getValue() def GetROIY2(self): return self.AOITop.getValue() + self.AOIHeight.getValue() def DisplayError(*args): pass #def Init(*args): # pass def Shutdown(self): print('Shutting down sCMOS camera') self.pollLoopActive = False self.shutdown() #pass def GetStatus(*args): pass def SetCOC(*args): pass def StartExposure(self): #make sure no acquisiton is running self.StopAq() self._temp = self.SensorTemperature.getValue() self._frameRate = self.FrameRate.getValue() self._flush() self.InitBuffers() self.AcquisitionStart() return 0 def StopAq(self): if self.CameraAcquiring.getValue(): self.AcquisitionStop() def StartLifePreview(*args): raise Exception('Not implemented yet!!') def StopLifePreview(*args): raise Exception('Not implemented yet!!') def GetBWPicture(*args): raise Exception('Not implemented yet!!') def CheckCoordinates(*args): raise Exception('Not implemented yet!!') #new fcns for Andor compatibility def GetNumImsBuffered(self): return self.nFull def GetBufferSize(self): return self.nBuffers def SetActive(self, active=True): '''flag the camera as active (or inactive) to dictate whether it writes it's metadata or not''' self.active = active def GenStartMetadata(self, mdh): if self.active: self.GetStatus() mdh.setEntry('Camera.Name', 'Andor Zyla') mdh.setEntry('Camera.IntegrationTime', self.GetIntegTime()) mdh.setEntry('Camera.CycleTime', self.GetIntegTime()) mdh.setEntry('Camera.EMGain', 1) mdh.setEntry('Camera.ROIPosX', self.GetROIX1()) mdh.setEntry('Camera.ROIPosY', self.GetROIY1()) mdh.setEntry('Camera.ROIWidth', self.GetROIX2() - self.GetROIX1()) mdh.setEntry('Camera.ROIHeight', self.GetROIY2() - self.GetROIY1()) #mdh.setEntry('Camera.StartCCDTemp', self.GetCCDTemp()) mdh.setEntry('Camera.ReadNoise', 1) mdh.setEntry('Camera.NoiseFactor', 1) mdh.setEntry('Camera.ElectronsPerCount', .28) mdh.setEntry('Camera.ADOffset', self.Baseline.getValue()) #mdh.setEntry('Simulation.Fluorophores', self.fluors.fl) #mdh.setEntry('Simulation.LaserPowers', self.laserPowers) #realEMGain = ccdCalibrator.CalibratedCCDGain(self.GetEMGain(), self.GetCCDTempSetPoint()) #if not realEMGain == None: mdh.setEntry('Camera.TrueEMGain', 1) #functions to make us look more like andor camera def GetEMGain(self): return 1 def GetCCDTempSetPoint(self): return self.TargetSensorTemperature.getValue() def SetCCDTemp(self, temp): self.TargetSensorTemperature.setValue(temp) #pass def SetEMGain(self, gain): pass def SetAcquisitionMode(self, aqMode): self.CycleMode.setIndex(aqMode) self.contMode = aqMode == self.MODE_CONTINUOUS def SetBurst(self, burstSize): if burstSize > 1: self.SetAcquisitionMode(self.MODE_SINGLE_SHOT) self.FrameCount.setValue(burstSize) self.contMode = True self.burstMode = True else: self.FrameCount.setValue(1) self.SetAcquisitionMode(self.MODE_CONTINUOUS) self.burstMode = False def SetShutter(self, mode): pass def SetBaselineClamp(self, mode): pass def GetFrameRate(self): return self.FrameRate.getValue() def __del__(self): self.Shutdown() #self.compT.kill = True def GetCameraModel(self): return self.CameraModel.getValue() def GetShutteringMode(self): return self.ElectronicShutteringMode.getString() def GetFanSpeed(self): return self.FanSpeed.getString() def GetCycleMode(self): return self.CycleMode.getString() def GetPixelReadoutRate(self): return self.PixelReadoutRate.getString() def GetSimplePreAmpGainControl(self): return self.SimplePreAmpGainControl.getString() def GetImageSizeBytes(self): return self.ImageSizeBytes.getValue() def GetBufferOverflowEvent(self): return self.BufferOverflowEvent.getValue() def GetAOIBinning(self): return self.AOIBinning.getString() def GetAccumulateCount(self): self.AccumulateCount.getValue() def GetMetaData(self): metadata = dict() metadata["CameraModel"] = self.GetCameraModel() metadata["PixelEncoding"] = self.PixelEncoding.getString() metadata["SerialNumber"] = self.GetSerialNumber() metadata["ExposureTime"] = self.GetExposureTime() metadata["SensorWidth"] = self.GetSensorWidth() metadata["SensorHeight"] = self.GetSensorHeight() metadata["PicWidth"] = self.GetPicWidth() metadata["PicHeight"] = self.GetPicHeight() metadata["AOIBinning"] = self.GetAOIBinning() metadata["SensorTemp"] = self.GetSensorTemp() metadata["TemperatureStatus"] = self.GetTemperatureStatus() metadata["FrameRate"] = self.GetFrameRate() metadata["AccumulateCount"] = self.GetAccumulateCount() metadata["ShutteringMode"] = self.GetShutteringMode() metadata["FanSpeed"] = self.GetFanSpeed() metadata["CycleMode"] = self.GetCycleMode() metadata["PixelReadoutRate"] = self.GetPixelReadoutRate() metadata["SimplePreAmpGainControl"] = self.GetSimplePreAmpGainControl() metadata["SpuriousNoiseFilter"] = self.SpuriousNoiseFilter.getValue() metadata["ImageSizeBytes"] = self.GetImageSizeBytes() metadata["Date"] = datetime.now().strftime("%Y-%m-%d") metadata["Time"] = datetime.now().strftime("%H:%M:%S") metadata["TimeAbsolute"] = time.time() return metadata def GetInt(self, name): return SDK3.GetInt(self.handle, name).value def acquireOne(self): image_size = self.ImageSizeBytes.getValue() buf = create_aligned_array(image_size, 'uint8') SDK3.QueueBuffer(self.handle, buf.ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), buf.nbytes) self.AcquisitionStart() pData, lData = SDK3.WaitBuffer(self.handle, SDK3.AT_INFINITE) self.AcquisitionStop() xs, ys = self.GetPicWidth(), self.GetPicHeight() img = create_aligned_array(xs*ys, 'uint16') a_s = self.AOIStride.getValue() px_encoding = self.PixelEncoding.getString() SDK3.ConvertBuffer(buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, px_encoding, 'Mono16') self._flush() img.shape = (ys, xs) return img def live_preview_plot(self): fig, ax = plt.subplots(1, 1 ) ax.set_title(str(0)) myPlot = plt.imshow(self.acquireOne()) image_size = self.ImageSizeBytes.getValue() buf = create_aligned_array(image_size, 'uint8') self.CycleMode.setString('Continuous') a_s = self.AOIStride.getValue() px_encoding = self.PixelEncoding.getString() self.AcquisitionStart() xs, ys = self.GetPicWidth(), self.GetPicHeight() i = 1 while plt.fignum_exists(fig.number): SDK3.QueueBuffer(self.handle, buf.ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), buf.nbytes) pData, lData = SDK3.WaitBuffer(self.handle, 1000) img = create_aligned_array(xs*ys, 'uint16') SDK3.ConvertBuffer(buf.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, px_encoding, 'Mono16') img.shape = (ys, xs) myPlot.set_data(img) fig.canvas.draw() fig.canvas.flush_events() ax.set_title(str(i)) plt.pause(0.01) i = i + 1 self.AcquisitionStop() self._flush() def live_preview_plot_circular(self): image_size = self.ImageSizeBytes.getValue() bufs = [create_aligned_array(image_size, 'uint8') for i in range(1)] n_of_bufs = len(bufs) for i in range(n_of_bufs): SDK3.QueueBuffer(self.handle, bufs[i].ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), bufs[i].nbytes) self.CycleMode.setString('Continuous') a_s = self.AOIStride.getValue() px_encoding = self.PixelEncoding.getString() self.AcquisitionStart() xs, ys = self.GetPicWidth(), self.GetPicHeight() #start_t = time.time() i = 0 while True: pData, lData = SDK3.WaitBuffer(self.handle, 1000) img = create_aligned_array(xs*ys, 'uint16') SDK3.ConvertBuffer(bufs[i%n_of_bufs].ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, px_encoding, 'Mono16') img.shape = (ys, xs) self.current_image = img self.helper.imageAquiredSignal.emit() #if i%self.FrameRate.getValue() == 0: # print(i, 'time = : ', '%.2f' % (time.time()-start_t)) SDK3.QueueBuffer(self.handle, bufs[i%n_of_bufs].ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), bufs[i%n_of_bufs].nbytes) i = i + 1 self.AcquisitionStop() self._flush() def live_acquisition_configure(self): image_size = self.ImageSizeBytes.getValue() bufs = [create_aligned_array(image_size, 'uint8') for i in range(10)] n_of_bufs = len(bufs) for ind in range(n_of_bufs): SDK3.QueueBuffer(self.handle, bufs[ind].ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), bufs[ind].nbytes) self.CycleMode.setString('Continuous') a_s = self.AOIStride.getValue() px_encoding = self.PixelEncoding.getString() xs, ys = self.GetPicWidth(), self.GetPicHeight() self.acq_index_i = 0 self._live_acq_auxs = a_s, px_encoding, xs, ys, bufs def live_acquisition_loop(self): t = threading.currentThread() timeout = self.ExposureTime.getValue() * 5000 while getattr(t, "do_run", True): a_s, px_encoding, xs, ys, bufs = self._live_acq_auxs try: pData, lData = SDK3.WaitBuffer(self.handle, int(timeout)) except: return img = create_aligned_array(xs*ys, 'uint16') SDK3.ConvertBuffer(bufs[self.acq_index_i%len(bufs)].ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, px_encoding, 'Mono16') img.shape = (ys, xs) self.current_image = img self.acq_queue.put(self.current_image) SDK3.QueueBuffer(self.handle, bufs[self.acq_index_i%len(bufs)].ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), bufs[self.acq_index_i%len(bufs)].nbytes) self.helper.imageAquiredSignal.emit(self.acq_index_i) self.acq_index_i = self.acq_index_i + 1 print('stopping acq loop thread') def live_acquisition_loop_triggered(self): t = threading.currentThread() while getattr(t, "do_run", True): a_s, px_encoding, xs, ys, bufs = self._live_acq_auxs try: pData, lData = SDK3.WaitBuffer(self.handle, 10000) except: return img = create_aligned_array(xs*ys, 'uint16') SDK3.ConvertBuffer(bufs[self.acq_index_i%len(bufs)].ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), img.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)), xs, ys, a_s, px_encoding, 'Mono16') img.shape = (ys, xs) self.current_image = img self.acq_queue.put(self.current_image) SDK3.QueueBuffer(self.handle, bufs[self.acq_index_i%len(bufs)].ctypes.data_as(SDK3.POINTER(SDK3.AT_U8)), bufs[self.acq_index_i%len(bufs)].nbytes) self.helper.imageAquiredSignal.emit(self.acq_index_i) self.acq_index_i = self.acq_index_i + 1 print('stopping acq loop thread') def _convert_buffer_12(self, buf): import itertools xs, ys = self.GetPicWidth(), self.GetPicHeight() a_s = self.AOIStride.getValue() img = np.empty((xs, ys), 'uint16') for m, n in itertools.product(range(xs), range(ys)): try: img[m, n] = buf[n*a_s + 2 * m + 1] *256 + buf[n*a_s + 2 * m] except: print('!!',xs, ys, a_s, buf.size, buf.shape) print(m, n,n*a_s + 2 * m + 1, n*a_s + 2 * m) break return img class AndorZyla(AndorBase): def __init__(self, camNum): #define properties self.Overlap = ATBool() self.SpuriousNoiseFilter = ATBool() self.StaticBlemishCorrection = ATBool() self.VerticallyCentreAOI = ATBool() self.CameraDump = ATCommand() self.SoftwareTrigger = ATCommand() self.TemperatureControl = ATEnum() self.TemperatureStatus = ATEnum() self.SimplePreAmpGainControl = ATEnum() self.BitDepth = ATEnum() self.ActualExposureTime = ATFloat() self.BurstRate = ATFloat() self.ReadoutTime = ATFloat() self.TimestampClock = ATInt() self.TimestampClockFrequency = ATInt() self.AccumulateCount = ATInt() self.BaselineLevel = ATInt() self.BurstCount = ATInt() self.LUTIndex = ATInt() self.LUTValue = ATInt() self.ControllerID = ATString() self.FirmwareVersion = ATString() AndorBase.__init__(self,camNum) def trigger(self): self.SoftwareTrigger() class AndorSim(AndorBase): def __init__(self, camNum): #define properties self.SynchronousTriggering = ATBool() self.PixelCorrection = ATEnum() self.TriggerSelector = ATEnum() self.TriggerSource = ATEnum() self.PixelHeight = ATFloat() self.PixelWidth = ATFloat() self.AOIHBin = ATInt() self.AOIVbin = ATInt() AndorBase.__init__(self,camNum)