Commit 07ac6e35 authored by Martin Drechsler's avatar Martin Drechsler

some changes, queue added but only dto dummy andor

parent 25631830
......@@ -12,160 +12,174 @@ from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph import dockarea
import pyqtgraph as pg
from zylaCameraWorker import CameraWorker
from cameraParameterTree import CameraParameterTree
import sys
import numpy as np
class GuiMainWindow(QMainWindow):
def __init__(self):
super().__init__()
#self.__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.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 Control")
self.d1 = dockarea.Dock("Zyla Camera View")
self.d2 = dockarea.Dock("Zyla Camera Analysis")
self.area.addDock(self.d1)
self.area.addDock(self.d2, 'left', self.d1)
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('Acquisition')
self.d1.addWidget(self.cameraButton)
self.sb = pg.SpinBox(min = 0)
self.d1.addWidget(self.sb)
self.label = QLabel('nada')
self.cameraButton = QPushButton("Start Acquisition")
self.isCameraAcquiring = False
self.d3.addWidget(self.cameraButton)
self.label = QLabel("Counter of frames")
self.d1.addWidget(self.label)
#layouts and viewboxes
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)
# 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
# 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 = 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')
# self.p.setRange(xRange = (0, 10), yRange = (0, 255))
self.curve = self.p.plot(pen="y")
## rOI
self.rois = []
self.rois.append(pg.TestROI([0, 0], [10, 10], pen=(0,9)))
self.rois.append(pg.TestROI([0, 0], [10, 10], pen=(0, 9)))
for r in self.rois:
self.view.addItem(r)
#r.sigRegionChanged.connect(self.updateRoi)
self.ROIdata = np.zeros(100)
# r.sigRegionChanged.connect(self.updateRoi)
self.ROIdata = np.zeros(1000)
self.iROIdata = 0
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(lambda x = backend.isCameraAcquiring: self.camera_button_pressed(x))
def camera_button_pressed(self, isCameraAcquiring):
if isCameraAcquiring:
self.cameraButton.clicked.connect(
self.camera_button_pressed
)
def camera_button_pressed(self):
if self.isCameraAcquiring:
self.frames_checker_timer.stop()
self.cameraButton.setText('Start Acquisition')
self.isCameraAcquiring = False
else:
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.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:
self.lastRoi = roi
roiSlice = roi.getArrayRegion(self.img.image, img=self.img)
self.newData = np.mean(roiSlice)
self.ROIdata[self.iROIdata] = self.newData
self.iROIdata = np.mod(self.frame_index + 1, len(self.ROIdata))
self.curve.setData(self.ROIdata)
@QtCore.pyqtSlot(np.ndarray, int)
@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
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)
self.updateRois()
self.frame_index = self.frame_index + 1
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.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')
print("chau gui")
###############################################################################
if __name__ == '__main__':
if __name__ == "__main__":
app = QtGui.QApplication([])
myGuiMainWIndow = GuiMainWindow()
cameraWorker = CameraWorker()
cameraWorker.make_connections(myGuiMainWIndow)
myGuiMainWIndow.make_connections(cameraWorker)
cameraThread = QtCore.QThread()
cameraThread = QtCore.QThread()
cameraWorker.moveToThread(cameraThread)
cameraThread.start()
sys.exit(app.exec_())
\ No newline at end of file
sys.exit(app.exec_())
......@@ -22,18 +22,19 @@ app = QtGui.QApplication([])
class BasicAcquisitonParameters(pTypes.GroupParameter):
def __init__(self, **opts):
pTypes.GroupParameter.__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': 10})
self.addChild({'name': 'Frame Rate', 'type': 'float', 'value': 10, '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)
......@@ -41,9 +42,7 @@ class BasicAcquisitonParameters(pTypes.GroupParameter):
#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)
......@@ -62,100 +61,61 @@ class BasicAcquisitonParameters(pTypes.GroupParameter):
self.param('Image Area').setValue('256x256')
params = [
BasicAcquisitonParameters(name = 'Basic acq parameters'),
{'name': 'Basic parameter data types', 'type': 'group', 'children': [
{'name': 'Integer', 'type': 'int', 'value': 10},
{'name': 'Float', 'type': 'float', 'value': 10.5, 'step': 0.1},
{'name': 'String', 'type': 'str', 'value': "hi"},
{'name': 'List', 'type': 'list', 'values': [1,2,3], 'value': 2},
{'name': 'Named List', 'type': 'list', 'values': {"one": 1, "two": "twosies", "three": [3,3,3]}, 'value': 2},
{'name': 'Boolean', 'type': 'bool', 'value': True, 'tip': "This is a checkbox"},
{'name': 'Color', 'type': 'color', 'value': "FF0", 'tip': "This is a color button"},
{'name': 'Gradient', 'type': 'colormap'},
{'name': 'Subgroup', 'type': 'group', 'children': [
{'name': 'Sub-param 1', 'type': 'int', 'value': 10},
{'name': 'Sub-param 2', 'type': 'float', 'value': 1.2e6},
]},
{'name': 'Text Parameter', 'type': 'text', 'value': 'Some text...'},
{'name': 'Action Parameter', 'type': 'action'},
]},
{'name': 'Numerical Parameter Options', 'type': 'group', 'children': [
{'name': 'Units + SI prefix', 'type': 'float', 'value': 1.2e-6, 'step': 1e-6, 'siPrefix': True, 'suffix': 'V'},
{'name': 'Limits (min=7;max=15)', 'type': 'int', 'value': 11, 'limits': (7, 15), 'default': -6},
{'name': 'DEC stepping', 'type': 'float', 'value': 1.2e6, 'dec': True, 'step': 1, 'siPrefix': True, 'suffix': 'Hz'},
]},
{'name': 'Save/Restore functionality', 'type': 'group', 'children': [
{'name': 'Save State', 'type': 'action'},
{'name': 'Restore State', 'type': 'action', 'children': [
{'name': 'Add missing items', 'type': 'bool', 'value': True},
{'name': 'Remove extra items', 'type': 'bool', 'value': True},
]},
]},
{'name': 'Extra Parameter Options', 'type': 'group', 'children': [
{'name': 'Read-only', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'readonly': True},
{'name': 'Renamable', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'renamable': True},
{'name': 'Removable', 'type': 'float', 'value': 1.2e6, 'siPrefix': True, 'suffix': 'Hz', 'removable': True},
]}
]
## Create tree of Parameter objects
p = Parameter.create(name='params', type='group', children=params)
## If anything changes in the tree, print a message
def change(param, changes):
print("tree changes:")
for param, change, data in changes:
path = 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(' ----------')
p.sigTreeStateChanged.connect(change)
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)
def save():
global state
state = p.saveState()
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 restore():
global state
add = p['Save/Restore functionality', 'Restore State', 'Add missing items']
rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items']
p.restoreState(state, addChildren=add, removeChildren=rem)
p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save)
p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore)
## Create two ParameterTree widgets, both accessing the same data
t = ParameterTree()
t.setParameters(p, showTop=False)
t.setWindowTitle('Parameter Tree')
win = QtGui.QWidget()
layout = QtGui.QGridLayout()
win.setLayout(layout)
layout.addWidget(QtGui.QLabel("Explanation of parameter tree."), 0, 0, 1, 2)
layout.addWidget(t)
win.show()
win.resize(400,800)
## test save/restore
s = p.saveState()
p.restoreState(s)
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_()
......@@ -9,75 +9,83 @@ 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():
class AndorZyla:
def __init__(self, num):
self.ExposureTime = AndorFeats()
self.FrameRate = AndorFeats()
self.CameraAcquiring = AndorFeats()
self.Binning = AndorFeats()
self.ImageArea = AndorFeats()
self.CameraName = 'Dummy'
self.acq_queue = Queue(maxsize=5)
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.Binning.setValue('1x1')
self.ImageArea.setValue(50)
def Init(self):
print('Dummy camera initialized')
print("Dummy camera initialized")
def live_acquisition_loop(self):
t = threading.currentThread()
while getattr(t, "do_run", True):
time.sleep(self.ExposureTime.getValue())
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
print('stopping acq loop thread')
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)
def AcquisitionStop(self):
self.CameraAcquiring.setValue(False)
def _flush(self):
pass
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 ) ) )
def _twoD_gaussian(self, lim=10, sigma=1, x0=0, y0=0):
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)
return(g+noise)
time.sleep(self.ExposureTime.getValue())
return g + noise
class AndorFeats():
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 ) ) )
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)
\ No newline at end of file
return g + noise
......@@ -10,7 +10,8 @@ Created on Thu Apr 4 11:10:20 2019
import numpy as np
from PyQt5 import QtCore
#from drivers.andorzyla import AndorZyla
# from drivers.andorzyla import AndorZyla
from dummyAndor import AndorZyla
import threading
......@@ -18,55 +19,43 @@ import threading
class CameraWorker(QtCore.QObject):
imageReadySignal = QtCore.pyqtSignal(np.ndarray, int)
def __init__(self):
super().__init__()
def __init__(self):
super(CameraWorker, self).__init__()
self.cam = AndorZyla(0)
self.cam.Init()
self.cam.ExposureTime.setValue(.1)
self.isCameraAcquiring = False
print('camera worker initialized')
#self.cam.ExposureTime.setValue(0.1)
print("camera worker initialized")
def make_connections(self, frontend):
#frontend connections
frontend.cameraButton.clicked.connect(self.run)
frontend.sb.valueChanged.connect(lambda x = frontend.sb.value(): self.cam.ExposureTime.setValue(x))
#internal connections
# 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')
print("adios camera worker")
@QtCore.pyqtSlot()
def run(self):
#@QtCore.pyqtSlot()
def run(self, params):
if self.cam.CameraAcquiring.getValue():
self._stop_acquisition_loop()
self.isCameraAcquiring = False
print('acquisition now stopping')
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 = threading.Thread(target=self.cam.live_acquisition_loop)
self.acq_thread.start()
print('acquisiting now starting')
self.isCameraAcquiring = True
print("acquisiting now starting")
def _start_acquisition_loop(self):
self.cam.live_acquisition_configure()
self.cam.live_acquisition_configure()
self.cam.AcquisitionStart()
print('frame rate: ', self.cam.FrameRate.getValue())
print('Exp time: ', self.cam.ExposureTime.getValue())
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()
......@@ -74,8 +63,19 @@ class CameraWorker(QtCore.QObject):
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.CameraName)
self.cam.ExposureTime.setValue(params.child('Basic acq parameters')
.child('Exposure Time').value()
)
@QtCore.pyqtSlot(int)
def new_image_acquired(self, acq_index):
self.imageReadySignal.emit(self.cam.current_image, 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