Commit 5ae7e63b authored by Martin Drechsler's avatar Martin Drechsler

readme deleted

parents 86feb45d b7572d61
# total_control_app
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 11 16:14:02 2016
@author: Admin
"""
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 4 10:35:32 2019
@author: martindrech
"""
from PyQt5.QtWidgets import QMainWindow, QPushButton, QLabel
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph import dockarea
import pyqtgraph as pg
from pyqtgraph import console
from pyqtgraph_subclasses import CustomRectangularROI
from zylaCameraWorker import CameraWorker
from cameraParameterTree import CameraParameterTree
from drivers.andorzyla import AndorZyla
#from dummyAndor import AndorZyla
import sys
import numpy as np
class CameraGuiMainWindow(QMainWindow):
def __init__(self):
super().__init__()
# self.__init__
self.counter = 0
self.frames_checker_timer = QtCore.QTimer()
self.initUI()
def initUI(self):
self.win = QtGui.QMainWindow()
self.win.setWindowTitle("Toy GUI")
self.win.resize(1000, 500)
self.area = dockarea.DockArea()
self.win.setCentralWidget(self.area)
self.cw = QtGui.QWidget()
self.win.show()
self.d1 = dockarea.Dock("Zyla Camera View")
self.d2 = dockarea.Dock("Zyla Camera Analysis")
self.d3 = dockarea.Dock("Zyla Camera Control")
self.d4 = dockarea.Dock("Measurement and saving")
self.area.addDock(self.d1)
self.area.addDock(self.d2, "left", self.d1)
self.area.addDock(self.d3, "right", self.d1)
self.area.addDock(self.d4, "bottom", self.d3)
# button spinbox and label
self.cameraButton = QPushButton("Start Acquisition")
self.isCameraAcquiring = False
self.d3.addWidget(self.cameraButton)
self.label = QLabel("Counter of frames")
self.d1.addWidget(self.label)
self.param_tree = CameraParameterTree()
self.d3.addWidget(self.param_tree.t)
# layouts and viewboxes
self.ImageLayout = pg.GraphicsLayoutWidget()
self.view = self.ImageLayout.addViewBox()
self.AnalysisLayout = pg.GraphicsLayoutWidget()
# image layout
self.img = pg.ImageItem(border="w")
self.imv = pg.ImageView(imageItem=self.img, view=self.view)
self.imv.ui.roiBtn.setText('Useless')
self.d1.addWidget(self.imv)
# analysis layout
self.d2.addWidget(self.AnalysisLayout)
self.p = self.AnalysisLayout.addPlot(row=0, col=0, title="Time plot")
self.p.setRange(QtCore.QRectF(0, 0, 50, 255))
self.p.setAutoPan(y=True)
# self.p.setRange(xRange = (0, 10), yRange = (0, 255))
self.curve = self.p.plot(pen="y")
# rOI
self.rois = []
self.rois.append(CustomRectangularROI([0, 0]))
for r in self.rois:
self.view.addItem(r)
# r.sigRegionChanged.connect(self.updateRoi)
self.ROIdata = np.zeros(1000)
self.iROIdata = 0
self.current_image_size = 2048
self._initialize_image()
def make_connections(self, backend):
# backend connections
backend.imageReadySignal.connect(self.updateImage)
# internal connections
self.frames_checker_timer.timeout.connect(self.frame_counter)
self.cameraButton.clicked.connect(self.camera_button_pressed)
self.console = console.ConsoleWidget(
namespace = {'np': np, 'cam': backend.cam, 'roi': self.rois[0]}
)
self.d4.addWidget(self.console)
def camera_button_pressed(self):
if self.isCameraAcquiring:
self.frames_checker_timer.stop()
self.cameraButton.setText('Start Acquisition')
self.isCameraAcquiring = False
else:
self.repositionRoi()
self.cameraButton.setText('Stop Acquisition')
self.frame_index = 0
self.previous_frame_index = 0
self.frames_checker_timer.start(1000)
self.isCameraAcquiring = True
def _initialize_image(self):
# lock the aspect ratio so pixels are always square
self.view.setAspectLocked(True)
self.view.addItem(self.img)
self.frame_index = 0
self.previous_frame_index = 0
self.frames_checker_timer.start(1000)
def updateRois(self):
for roi in self.rois:
roiSlice = roi.getArrayRegion(self.img.image, img=self.img)
self.newData = roiSlice.sum()
self.ROIdata[self.iROIdata] = self.newData
self.iROIdata = np.mod(self.frame_index + 1, len(self.ROIdata))
self.curve.setData(self.ROIdata)
def repositionRoi(self):
old_size = self.current_image_size
aux_dict = {'1x1': 2048, '2x2': 1024, '4x4': 512, '8x8': 256}
new_size = aux_dict[
self.param_tree.p.child('Basic acq parameters')
.child('Pixel Binning').value()
]
print('sizes:', old_size, new_size)
for roi in self.rois:
x, y, sx, sy = roi.pos()[0], roi.pos()[1], roi.size()[0], roi.size()[1]
new_x, new_y = new_size/old_size * x, new_size/old_size * y
new_sx, new_sy = new_size/old_size * sx, new_size/old_size * sy
roi.setPos([new_x, new_y])
roi.setSize([new_sx, new_sy])
@QtCore.pyqtSlot(np.ndarray, int)
def updateImage(self, image, acq_index):
if self.frame_index is not 0 and not self.frame_index == acq_index:
print(
"Dephasing in camera gui has occured: while frame index is %i, the acq index is %i"
% (self.frame_index, acq_index)
)
# n = 1024
self.img.setImage(image, autoDownsample=True)
self.updateRois()
self.frame_index = self.frame_index + 1
self.current_image_size = image.shape[0]
def frame_counter(self):
self.counter = self.counter + 1
self.label.setText(
"Frames in last second: "
+ str(self.frame_index - self.previous_frame_index)
+ " "
+ "Seconds since start: "
+ str(self.counter)
)
self.previous_frame_index = self.frame_index
def __del__(self):
print("chau gui")
###############################################################################
if __name__ == "__main__":
app = QtGui.QApplication([])
camera = AndorZyla(0)
myGuiMainWindow = CameraGuiMainWindow()
cameraWorker = CameraWorker(andor_camera=camera)
cameraWorker.make_connections(myGuiMainWindow)
myGuiMainWindow.make_connections(cameraWorker)
cameraThread = QtCore.QThread()
cameraWorker.moveToThread(cameraThread)
cameraThread.start()
sys.exit(app.exec_())
# -*- coding: utf-8 -*-
"""
This example demonstrates the use of pyqtgraph's parametertree system. This provides
a simple way to generate user interfaces that control sets of parameters. The example
demonstrates a variety of different parameter types (int, float, list, etc.)
as well as some customized parameter types
"""
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.parametertree.parameterTypes as pTypes
from pyqtgraph.parametertree import Parameter, ParameterTree, ParameterItem, registerParameterType
app = QtGui.QApplication([])
## test subclassing parameters
## This parameter automatically generates two child parameters which are always reciprocals of each other
class BasicAcquisitonParameters(pTypes.GroupParameter):
def __init__(self, **opts):
super().__init__(**opts)
self.addChild({'name': 'Camera name', 'type': 'str', 'value': ' ', 'readonly': True})
self.addChild({'name': 'Acquisition mode', 'type': 'list', 'values': ['acq1', 'acq2']})
self.addChild({'name': 'Pixel Binning', 'type': 'list', 'values': ['1x1', '2x2', '4x4', '8x8']})
self.addChild({'name': 'Image Area', 'type': 'list', 'values': ['2048x2048', '1024x1024', '512x512', '256x256'], 'readonly': True})
self.addChild({'name': 'Exposure Time', 'type': 'float', 'value': .1, 'suffix': 's', 'siPrefix': True, 'step': 0.05})
self.addChild({'name': 'Frame Rate', 'type': 'float', 'value': 0, 'readonly': True})
#exposure time and frame rate connected because they are the inverse of each other
#later, they should be set so that the framerate is the maximum possible value given an exposure time
# self.exposureTimeWidget = self.param('Exposure Time')
# self.frameRateWidget = self.param('Frame Rate')
# self.exposureTimeWidget.sigValueChanged.connect(self.expTimeChanged)
# self.frameRateWidget.sigValueChanged.connect(self.frameRateChanged)
#set image area according to binning
self.param('Pixel Binning').sigValueChanged.connect(self.binningChanged)
# def expTimeChanged(self):
# self.frameRateWidget.setValue(1.0 / self.exposureTimeWidget.value(), blockSignal=self.frameRateChanged)
# def frameRateChanged(self):
# self.exposureTimeWidget.setValue(1.0 / self.frameRateWidget.value(), blockSignal=self.expTimeChanged)
def binningChanged(self):
if self.param('Pixel Binning').value() == '1x1':
self.param('Image Area').setValue('2048x2048')
if self.param('Pixel Binning').value() == '2x2':
self.param('Image Area').setValue('1024x1024')
if self.param('Pixel Binning').value() == '4x4':
self.param('Image Area').setValue('512x512')
if self.param('Pixel Binning').value() == '8x8':
self.param('Image Area').setValue('256x256')
class BasicActionParameters(pTypes.GroupParameter):
def __init__(self, **opts):
super().__init__(**opts)
self.addChild({'name': 'Save State', 'type': 'action'})
self.addChild({'name': 'Restore State', 'type': 'action'})
class CameraParameterTree(ParameterTree):
def __init__(self):
super().__init__()
self.params = [
BasicAcquisitonParameters(name = 'Basic acq parameters'),
BasicActionParameters(name = 'Save/Restore functionality')
]
self.p = Parameter.create(name='params', type='group', children=self.params)
self.p.sigTreeStateChanged.connect(self.change)
self.p.param('Save/Restore functionality', 'Save State').sigActivated.connect(self.save)
self.p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(self.restore)
self.t = ParameterTree()
self.t.setParameters(self.p, showTop=False)
self.t.setWindowTitle('Parameter Tree')
def change(self, param, changes):
print("tree changes:")
for param, change, data in changes:
path = self.p.childPath(param)
if path is not None:
childName = '.'.join(path)
else:
childName = param.name()
print(' parameter: %s'% childName)
print(' change: %s'% change)
print(' data: %s'% str(data))
print(' ----------')
def save(self):
self.state = self.p.saveState()
def restore(self):
self.p.restoreState(self.state)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
param_tree = CameraParameterTree()
win = QtGui.QWidget()
layout = QtGui.QGridLayout()
win.setLayout(layout)
layout.addWidget(QtGui.QLabel("Explanation of parameter tree."), 0, 0, 1, 2)
layout.addWidget(param_tree.t)
win.show()
win.resize(400,800)
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
# -*- 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 SetIntegTime(self, iTime):
self.ExposureTime.setValue(iTime*1e-3)
self.FrameRate.setValue(self.FrameRate.max())
def GetIntegTime(self):
return self.ExposureTime.getValue()
def GetCCDWidth(self):
return self.SensorHeight.getValue()
def GetCCDHeight(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 GetCCDTemp(self):
#for some reason querying the temperature takes a lot of time - do it less often
#return self.SensorTemperature.getValue()
return self._temp
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 GetFPS(self):
#return self.FrameRate.getValue()
return self._frameRate
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 GetMetaData(self):
metadata = dict()
metadata["BufferOverflowEvent"] = self.GetBufferOverflowEvent()
metadata["CameraModel"] = self.GetCameraModel()
metadata["PixelEncoding"] = self.PixelEncoding.getString()
metadata["SerialNumber"] = self.GetSerialNumber()
metadata["IntegTime"] = self.GetIntegTime()
metadata["CCDWidth"] = self.GetCCDWidth()
metadata["CCDHeight"] = self.GetCCDHeight()
metadata["PicWidth"] = self.GetPicWidth()
metadata["PicHeight"] = self.GetPicHeight()
metadata["CCDTemp"] = self.GetCCDTemp2()
metadata["NumImsBuffered"] = self.GetNumImsBuffered()
metadata["BufferSize"] = self.GetBufferSize()
metadata["FPS"] = self.GetFPS()
metadata["CCDTempSetPoint"] = self.GetCCDTempSetPoint()
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["TemperatureStatus"] = self.TemperatureStatus.getString()
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()
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)
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)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 6 22:17:00 2019
@author: martindrech
"""
import numpy as np
from PyQt5 import QtCore
import time
import threading
from queue import Queue
class Helper_messager(QtCore.QObject):
imageAquiredSignal = QtCore.pyqtSignal(int)
class AndorZyla:
def __init__(self, num):
self.ExposureTime = AndorFeats()
self.FrameRate = AndorFeats()
self.CameraAcquiring = AndorFeats()
self.AOIBinning = AndorFeats()
self.ImageArea = AndorFeats()
self.CameraModel = AndorFeats()
self.acq_queue = Queue(maxsize=10)
self.helper = Helper_messager()
self.current_image = None
self.CameraAcquiring.setValue(False)
self.acq_index_i = 0
self.ExposureTime.setValue(0.5)
self.FrameRate.setValue(10)
self.AOIBinning.setValue('1x1')
self.ImageArea.setValue(2048)
self.CameraModel.setValue('dummy')
def Init(self):
print("Dummy camera initialized")
def live_acquisition_loop(self):
t = threading.currentThread()
while getattr(t, "do_run", True):
self.current_image = self._twoD_gaussian()
self.acq_queue.put(self.current_image)
self.helper.imageAquiredSignal.emit(self.acq_index_i)
self.acq_index_i = self.acq_index_i + 1
time.sleep(self.ExposureTime.getValue())
print("stopping acq loop thread")
def live_acquisition_configure(self):
self.acq_index_i = 0
def AcquisitionStart(self):
self.CameraAcquiring.setValue(True)
self._set_image_area()
def AcquisitionStop(self):
self.CameraAcquiring.setValue(False)
def _flush(self):
pass
def _set_image_area(self):
d = {'1x1': 2048, '2x2': 1024, '4x4': 512, '8x8': 256}
self.ImageArea.setValue(d[self.AOIBinning.getValue()])
def _twoD_gaussian(self, lim=10, sigma=1, x0=0, y0=0):
start = time.time()
N = self.ImageArea.getValue()
x, y = np.meshgrid(np.linspace(-lim, lim, N), np.linspace(-lim, lim, N))
d = np.sqrt((x - x0) ** 2 + (y - y0) ** 2)
g = np.exp(-((d) ** 2 / (2.0 * sigma ** 2)))
noise = np.random.rand(N, N)
end = time.time()
time.sleep(self.ExposureTime.getValue())
return noise * 10
class AndorFeats:
def __init__(self):
self.value = None
def getValue(self):
return self.value
def setValue(self, val):
self.value = val
def _twoD_gaussian(self, lim=10, N=100, sigma=1, x0=0, y0=0):
x, y = np.meshgrid(np.linspace(-lim, lim, N), np.linspace(-lim, lim, N))
d = np.sqrt((x - x0) ** 2 + (y - y0) ** 2)
g = np.exp(-((d) ** 2 / (2.0 * sigma ** 2)))
noise = np.random.rand(N, N)
return g + noise
def max(self):
return 0
def setString(self, s):
self.value = s
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Some sub-classes from pyqtgraph.
"""
from pyqtgraph import ROI
class CustomRectangularROI(ROI):
"""
Rectangular ROI subclass with a single scale handle at the top-right corner.
============== =============================================================
**Arguments**
pos (length-2 sequence) The position of the ROI origin.
See ROI().
size (length-2 sequence) The size of the ROI. See ROI().
centered (bool) If True, scale handles affect the ROI relative to its
center, rather than its origin.
sideScalers (bool) If True, extra scale handles are added at the top and
right edges.
**args All extra keyword arguments are passed to ROI()
============== =============================================================
"""
def __init__(self, pos, size = [8, 8], centered=False, sideScalers=False):
#ROI.__init__(self, pos, size, **args)
super().__init__(pos, size, centered, sideScalers)
## handles scaling horizontally around center
self.addScaleHandle([1, 0.5], [0.5, 0.5])
self.addScaleHandle([0, 0.5], [0.5, 0.5])
## handles scaling vertically from opposite edge
self.addScaleHandle([0.5, 0], [0.5, 1])
self.addScaleHandle([0.5, 1], [0.5, 0])
## handles scaling both vertically and horizontally
self.addScaleHandle([1, 1], [0, 0])
self.addScaleHandle([0, 0], [1, 1])
#self.sigRegionChangeFinished.connect(self.correct_scaling)
def correct_scaling(self):
x, y = self.pos()[0], self.pos()[1]
if x%8 != 0 or y%8 != 0:
self.setPos((x//8)*8, (y//8)*8)
sx, sy = self.size()[0], self.size()[1]
if sx%8 != 0 or sy%8 != 0:
self.setSize((sx//8)*8, (sy//8)*8)
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 4 11:10:20 2019
@author: martindrech
"""
import numpy as np
from PyQt5 import QtCore
# from drivers.andorzyla import AndorZyla
from dummyAndor import AndorZyla
import threading
class CameraWorker(QtCore.QObject):
imageReadySignal = QtCore.pyqtSignal(np.ndarray, int)
def __init__(self, andor_camera):
super().__init__()
self.cam = andor_camera
self.cam.Init()
print("camera worker initialized")
def make_connections(self, frontend):
# frontend connections
params = frontend.param_tree.p
frontend.cameraButton.clicked.connect(lambda: self.run(params))
# internal connections
self.cam.helper.imageAquiredSignal.connect(self.new_image_acquired)
def __del__(self):
print("adios camera worker")
# @QtCore.pyqtSlot()
def run(self, params):
if self.cam.CameraAcquiring.getValue():
self._stop_acquisition_loop()
print("acquisition now stopping")
else:
self._configure_acq_parameters(params)
self._start_acquisition_loop()
self.acq_thread = threading.Thread(
target=self.cam.live_acquisition_loop
)
self.acq_thread.start()
print("acquisiting now starting")
def _start_acquisition_loop(self):
self.cam.live_acquisition_configure()
self.cam.AcquisitionStart()
print("frame rate: ", self.cam.FrameRate.getValue())
print("Exp time: ", self.cam.ExposureTime.getValue())
def _stop_acquisition_loop(self):
self.acq_thread.do_run = False
self.acq_thread.join()
self.cam.AcquisitionStop()
self.cam._flush()
def _configure_acq_parameters(self, params):
print('Acq parameters: ')
for p in params.children()[0].children():
print(p.name(), p.value())
params.child('Basic acq parameters').child('Camera name').setValue(
self.cam.CameraModel.getValue())
self.cam.ExposureTime.setValue(
params.child('Basic acq parameters').child('Exposure Time').value()
)
self.cam.FrameRate.setValue(self.cam.FrameRate.max())
params.child('Basic acq parameters').child('Frame Rate').setValue(
self.cam.FrameRate.getValue())
self.cam.AOIBinning.setString(
params.child('Basic acq parameters').child('Pixel Binning').value()
)
@QtCore.pyqtSlot(int)
def new_image_acquired(self, acq_index):
self.imageReadySignal.emit(self.cam.acq_queue.get(), acq_index)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment