Commit 4b177e64 authored by Martin Drechsler's avatar Martin Drechsler

so lot of changes, sorry

parent 160f19a2
......@@ -7,24 +7,29 @@ Created on Thu Apr 4 10:35:32 2019
"""
from PyQt5.QtWidgets import QMainWindow, QPushButton, QLabel
from pyqtgraph.Qt import QtGui, QtCore
from PyQt5 import QtCore, QtGui
from pyqtgraph import dockarea
import pyqtgraph as pg
from pyqtgraph import console
from subclasses.pyqtgraph_subclasses import CustomRectangularROI
from zylaCameraWorker import CameraWorker
from subclasses.cameraParameterTree import CameraParameterTree
from subclasses.controllayouts import LaserControlLayout, LaserScanLayout
#from drivers.andorzyla import AndorZyla
from drivers.dummyAndor import AndorZyla
from measurement import MeasurementGui, MeasurementWorker
from measurement import MeasurementFrame
import sys
import numpy as np
class CameraGuiMainWindow(QMainWindow):
signalWithMeasurementParameters = QtCore.pyqtSignal(object)
def __init__(self):
super().__init__()
......@@ -60,8 +65,10 @@ class CameraGuiMainWindow(QMainWindow):
self.area.addDock(self.dConsole, "bottom", self.dCameraControl)
self.area.addDock(self.dMeasurement, "above", self.dConsole)
#measurement frame
self.measurementFrame = MeasurementFrame()
self.dMeasurement.addWidget(self.measurementFrame)
# button spinbox and label
self.cameraButton = QPushButton("Start Acquisition")
self.isCameraAcquiring = False
......@@ -107,6 +114,9 @@ class CameraGuiMainWindow(QMainWindow):
def make_connections(self, backend):
# backend connections
backend.imageReadySignal.connect(self.updateImage)
backend.measurementStartingSignal.connect(self.measurement_starting)
backend.measurementEndingSignal.connect(self.measurement_ending)
# internal connections
self.frames_checker_timer.timeout.connect(self.frame_counter)
self.cameraButton.clicked.connect(self.camera_button_pressed)
......@@ -115,16 +125,28 @@ class CameraGuiMainWindow(QMainWindow):
namespace = {'np': np, 'cam': backend.cam, 'roi': self.rois[0]}
)
self.dConsole.addWidget(self.console)
self.measurementFrame.startMeasureButton.clicked.connect(self.emit_measurement_parameters)
self.measurementFrame.folderButton.clicked.connect(self.measurementFrame.select_folder)
self.measurementFrame.selectScanSignal.activated[str].connect(self.measurementFrame.configure_spinBoxes)
self.measurementFrame.startValue.valueChanged.connect(self.measurementFrame.update_tree)
self.measurementFrame.endValue.valueChanged.connect(self.measurementFrame.update_tree)
self.measurementFrame.stepsNum.valueChanged.connect(self.measurementFrame.update_tree)
def camera_button_pressed(self):
if self.isCameraAcquiring:
self.frames_checker_timer.stop()
self.cameraButton.setText('Start Acquisition')
self.measurementFrame.startMeasureButton.setEnabled(True)
self.isCameraAcquiring = False
else:
self.repositionRoi()
self.cameraButton.setText('Stop Acquisition')
self.measurementFrame.startMeasureButton.setEnabled(False)
self.frame_index = 0
self.previous_frame_index = 0
self.frames_checker_timer.start(1000)
......@@ -190,9 +212,33 @@ class CameraGuiMainWindow(QMainWindow):
)
self.previous_frame_index = self.frame_index
#@QtCore.pyqtSlot()
def measurement_starting(self):
self.cameraButton.setEnabled(False)
self.measurementFrame.startMeasureButton.setEnabled(False)
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.freeze()
print('gui meas start')
#@QtCore.pyqtSlot()
def measurement_ending(self):
self.cameraButton.setEnabled(True)
self.measurementFrame.startMeasureButton.setEnabled(True)
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.unfreeze()
print('gui meas end')
def __del__(self):
print("chau gui")
def emit_measurement_parameters(self):
measure_params = dict()
measure_params['signal_to_scan'] = self.measurementFrame.selectScanSignal.currentText()
measure_params['start'] = self.measurementFrame.startValue.value()
measure_params['end'] = self.measurementFrame.endValue.value()
measure_params['steps'] = self.measurementFrame.stepsNum.value()
measure_params['directory'] = self.measurementFrame.folderBrowser.toPlainText()
self.signalWithMeasurementParameters.emit(measure_params)
###############################################################################
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 3 10:32:30 2019
@author: martindrech
"""
from drivers.andorzyla import AndorZyla
cam = AndorZyla(0)
cam.Init()
#%%
cam.GetMetaData()
#%%
cam.shutdown()
#%%
def f():
print('hola')
\ No newline at end of file
......@@ -59,7 +59,7 @@ def create_aligned_array(shape, dtype=np.typeDict['singlecomplex'], boundary=16)
class Helper_messager(QtCore.QObject):
imageAquiredSignal = QtCore.pyqtSignal(int)
class AndorBase(SDK3Camera):
......@@ -331,16 +331,16 @@ class AndorBase(SDK3Camera):
def GetSerialNumber(self):
return self.SerialNumber.getValue()
def SetIntegTime(self, iTime):
def SetExposureTime(self, iTime):
self.ExposureTime.setValue(iTime*1e-3)
self.FrameRate.setValue(self.FrameRate.max())
def GetIntegTime(self):
def GetExposureTime(self):
return self.ExposureTime.getValue()
def GetCCDWidth(self):
def GetSensorWidth(self):
return self.SensorHeight.getValue()
def GetCCDHeight(self):
def GetSensorHeight(self):
return self.SensorWidth.getValue()
def SetHorizBin(*args):
......@@ -361,11 +361,12 @@ class AndorBase(SDK3Camera):
def GetElectrTemp(*args):
return 25
def GetCCDTemp(self):
def GetSensorTemp(self):
#for some reason querying the temperature takes a lot of time - do it less often
#return self.SensorTemperature.getValue()
return self._temp
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
......@@ -541,9 +542,9 @@ class AndorBase(SDK3Camera):
def SetBaselineClamp(self, mode):
pass
def GetFPS(self):
#return self.FrameRate.getValue()
return self._frameRate
def GetFrameRate(self):
return self.FrameRate.getValue()
def __del__(self):
self.Shutdown()
......@@ -574,32 +575,32 @@ class AndorBase(SDK3Camera):
return self.BufferOverflowEvent.getValue()
def GetAOIBinning(self):
return self.AOIBinning.getValue()
return self.AOIBinning.getString()
def GetAccumulateCount(self):
self.AccumulateCount.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["ExposureTime"] = self.GetExposureTime()
metadata["SensorWidth"] = self.GetSensorWidth()
metadata["SensorHeight"] = self.GetSensorHeight()
metadata["PicWidth"] = self.GetPicWidth()
metadata["PicHeight"] = self.GetPicHeight()
metadata["AOIBinning"] = self.GetAOIBinning()
metadata["CCDTemp"] = self.GetCCDTemp2()
metadata["NumImsBuffered"] = self.GetNumImsBuffered()
metadata["BufferSize"] = self.GetBufferSize()
metadata["FPS"] = self.GetFPS()
metadata["CCDTempSetPoint"] = self.GetCCDTempSetPoint()
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["TemperatureStatus"] = self.TemperatureStatus.getString()
metadata["ImageSizeBytes"] = self.GetImageSizeBytes()
metadata["Date"] = datetime.now().strftime("%Y-%m-%d")
metadata["Time"] = datetime.now().strftime("%H:%M:%S")
......
......@@ -23,7 +23,14 @@ class AndorZyla:
self.AOIBinning = AndorFeats()
self.ImageArea = AndorFeats()
self.CameraModel = AndorFeats()
self.SensorCooling = AndorFeats()
self.SensorTemperature = AndorFeats()
self.TemperatureStatus = AndorFeats()
self.ReadoutTime = AndorFeats()
self.PixelReadoutRate = AndorFeats()
self.SimplePreAmpGainControl = AndorFeats()
self.SpuriousNoiseFilter = AndorFeats()
self.TriggerMode = AndorFeats()
self.acq_queue = Queue(maxsize=10)
self.helper = Helper_messager()
self.current_image = None
......@@ -51,10 +58,10 @@ class AndorZyla:
while getattr(t, "do_run", True):
self.current_image = self.images_array[self.acq_index_i%10]
time.sleep(self.ExposureTime.getValue())
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):
......@@ -83,7 +90,6 @@ class AndorZyla:
g = np.exp(-((d) ** 2 / (2.0 * sigma ** 2)))
noise = np.random.rand(N, N)
end = time.time()
time.sleep(self.ExposureTime.getValue())
return np.int8(g + noise)
......@@ -108,4 +114,9 @@ class AndorFeats:
return 0
def setString(self, s):
self.value = s
\ No newline at end of file
self.value = s
print(s)
def getString(self):
return ""
\ No newline at end of file
from PyQt5 import QtGui, QtCore
from drivers.andorzyla import AndorZyla
#from drivers.andorzyla import AndorZyla
#from drivers.andorzyla import AndorZyla
from drivers.dummyAndor import AndorZyla
from cameraGui import CameraGuiMainWindow
from zylaCameraWorker import CameraWorker
from measurement import MeasurementWorker, MeasurementGui
#from measurement import MeasurementWorker, MeasurementGui
from MCDAQcontrolsignals import anal_control_signal
from MCDAQcontrolsignals import digital_control_signal
from controlGui import ControlGui
if __name__ == "__main__":
import sys
app = QtGui.QApplication([])
camera = AndorZyla(0)
piezoA397 = anal_control_signal('piezoA397', channel=0, ao_type='cavity_piezo', out_minimum = 0, out_maximum = 4)
piezoB397 = anal_control_signal('piezoB397', channel=1, ao_type='cavity_piezo')
piezoA866 = anal_control_signal('piezoA866', channel=2, ao_type='cavity_piezo', out_minimum = 0, out_maximum = 4)
......@@ -50,7 +55,7 @@ if __name__ == "__main__":
myGuiMainWindow = CameraGuiMainWindow()
cameraWorker = CameraWorker()
cameraWorker = CameraWorker(camera)
cameraWorker.make_connections(myGuiMainWindow)
myGuiMainWindow.make_connections(cameraWorker)
......@@ -58,17 +63,17 @@ if __name__ == "__main__":
cameraThread = QtCore.QThread()
cameraWorker.moveToThread(cameraThread)
measurementGui = MeasurementGui()
measurementWorker = MeasurementWorker(camera)
myGuiMainWindow.dMeasurement.addWidget(measurementGui)
# measurementGui = MeasurementGui()
# measurementWorker = MeasurementWorker()
# myGuiMainWindow.dMeasurement.addWidget(measurementGui)
measurementThread = QtCore.QThread()
measurementWorker.moveToThread(measurementThread)
measurementGui.make_connections(measurementWorker)
measurementWorker.make_connections(measurementGui, camera)
# measurementThread = QtCore.QThread()
# measurementWorker.moveToThread(measurementThread)
# measurementGui.make_connections(measurementWorker)
# measurementWorker.make_connections(measurementGui, camera)
cameraThread.start()
mcDAQthread.start()
measurementThread.start()
# measurementThread.start()
sys.exit(app.exec_())
......@@ -14,9 +14,12 @@ from PyQt5.QtWidgets import QAction, QFileDialog, QInputDialog, QWidget
from measurement_ui import Ui_Frame
from MCDAQcontrolsignals import anal_control_signal
from subclasses.controllayouts import LaserControlLayout, LaserScanLayout
from resources.scanFunctions import create_measurement_array, yield_array
import time
class MeasurementGui(QtWidgets.QFrame, Ui_Frame):
class MeasurementFrame(QtWidgets.QFrame, Ui_Frame):
def __init__(self):
super().__init__()
self.setupUi(self)
......@@ -43,15 +46,6 @@ class MeasurementGui(QtWidgets.QFrame, Ui_Frame):
self.treeModel.setData(self.treeModel.index(0, 1), '?')
def make_connections(self, backend):
# internal
self.folderButton.clicked.connect(self.select_folder)
self.selectScanSignal.activated[str].connect(self.configure_spinBoxes)
self.startValue.valueChanged.connect(self.update_tree)
self.endValue.valueChanged.connect(self.update_tree)
self.stepsNum.valueChanged.connect(self.update_tree)
def select_folder(self):
directory = QFileDialog.getExistingDirectory(self, 'Choose directory')
self.folderBrowser.setText(directory)
......@@ -77,31 +71,45 @@ class MeasurementGui(QtWidgets.QFrame, Ui_Frame):
self.treeModel.setData(self.treeModel.index(0, 1), (self.endValue.value()-self.startValue.value())/self.stepsNum.value() )
except:
self.treeModel.setData(self.treeModel.index(0, 1), '?')
"""
class MeasurementWorker(QtCore.QObject):
"""
Backend for the measurement frame.
Simple scan measurement: for scanning a spinbox.
External scan measurement: scans an external object. For example, the rigol function generator.
"""
def __init__(self):
super().__init__()
def make_connections(self, frontend, camera):
frontend.startMeasureButton.clicked.connect(self.simple_scan_measurement)
def simple_scan_measurement(self):
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.freeze()
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.freeze()
scanSignal = self.get_scan_signal()
scan_array = create_measurement_array() # aca necesito parametros de los spinboxes de la measurementGUi
prepare_camara_to_triggered_acq() #includes stopping acquisition if it is in acq live
create_temporary_data_files
measurement loop:
set_scan_signal
wait_predefined_time
take_and_recibe_image
process_image_to_get_data
save_data
update_camera_gui_with_image_and_data
update_measurement_gui
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.unfreeze()
"""
if __name__ == '__main__':
import sys
from PyQt5 import QtWidgets
......@@ -120,8 +128,8 @@ if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = MeasurementGui()
measurementWorker = MeasurementWorker(None)
measurementWorker.make_connections(gui)
measurementWorker = MeasurementWorker()
measurementWorker.make_connections(gui, 0)
gui.make_connections(measurementWorker)
gui.show()
......
......@@ -27,3 +27,10 @@ Work flow:
- finalizar medicion
- Desbloquear guis
Cosas de andor zyla a pensar y/o consultar:
- Buffer overflow event not implemented!!! Y no hay mucha info sobre la memoria de la camara, que onda?
......@@ -42,7 +42,15 @@ def create_scan_array(scan_start, scan_stop, scan_period, first_value, dt, norma
else:
return scan_array
def _yield_array(arr):
def create_measurement_array(start, stop, steps, back_and_forth=False):
"""
Simply creates the array of a measurement.
"""
pass
def yield_array(arr):
larr = len(arr)
cursor = 0
while cursor < larr:
......@@ -51,8 +59,11 @@ def _yield_array(arr):
def yield_scan_array(arr):
"""
An infinite looping generator
"""
while True:
yield from _yield_array(arr)
yield from yield_array(arr)
......
......@@ -13,7 +13,6 @@ into it. That lies in the dump, and can me made permanent with permanent_save_cu
"""
import numpy as np
import time
import datetime
import os
import shutil
......
......@@ -25,6 +25,14 @@ class BasicAcquisitonParameters(pTypes.GroupParameter):
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})
self.addChild({'name': 'Pixel Readout Rate', 'type': 'list', 'values': ['100 MHz', '270 MHz']})
self.addChild({'name': 'Dynamic Range', 'type': 'list', 'values':
['12-bit (high well capacity)', '12-bit (low noise)', '16-bit (low noise & high well capacity)']}
)
self.addChild({'name': 'Readout Time', 'type': 'float', 'value': 0, 'readonly': True})
self.addChild({'name': 'Spurious Noise Filter', 'type': 'bool', 'value': True})
self.addChild({'name': 'Sensor Temperature', 'type': 'float', 'value': 25, 'readonly': True})
self.addChild({'name': 'Temperature Status', 'type': 'str', 'value': '?', 'readonly': True})
......
......@@ -10,32 +10,42 @@ Created on Thu Apr 4 11:10:20 2019
import numpy as np
from PyQt5 import QtCore
# from drivers.andorzyla import AndorZyla
from drivers.dummyAndor import AndorZyla
import threading
import time
from MCDAQcontrolsignals import anal_control_signal
from resources.messages import show_warning
from resources.storage import Storage
from resources.scanFunctions import create_measurement_array, yield_array
class CameraWorker(QtCore.QObject):
imageReadySignal = QtCore.pyqtSignal(np.ndarray, int)
measurementStartingSignal = QtCore.pyqtSignal()
measurementEndingSignal = QtCore.pyqtSignal()
def __init__(self, andor_camera):
super().__init__()
self.cam = andor_camera
self.cam.Init()
self.cam.SensorCooling.setValue(True)
print("camera worker initialized")
self.ao_to_scan = None
def make_connections(self, frontend):
# frontend connections
params = frontend.param_tree.p
frontend.cameraButton.clicked.connect(lambda: self.run(params))
live_acq_params = frontend.param_tree.p
frontend.cameraButton.clicked.connect(lambda: self.run(live_acq_params))
frontend.signalWithMeasurementParameters.connect(self.simple_scan_measurement)
# 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()
......@@ -67,18 +77,83 @@ class CameraWorker(QtCore.QObject):
for p in params.children()[0].children():
print(p.name(), p.value())
# setting info in parameter tree
params.child('Basic acq parameters').child('Camera name').setValue(
self.cam.CameraModel.getValue())
self.cam.CameraModel.getValue()
)
params.child('Basic acq parameters').child('Sensor Temperature').setValue(
self.cam.SensorTemperature.getValue()
)
params.child('Basic acq parameters').child('Temperature Status').setValue(
self.cam.TemperatureStatus.getString()
)
params.child('Basic acq parameters').child('Readout Time').setValue(
self.cam.ReadoutTime.getValue()
)
# setting camera parameteres according to tree
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.FrameRate.getValue()
)
self.cam.AOIBinning.setString(
params.child('Basic acq parameters').child('Pixel Binning').value()
)
self.cam.PixelReadoutRate.setString(
params.child('Basic acq parameters').child('Pixel Readout Rate').value()
)
self.cam.SimplePreAmpGainControl.setString(
params.child('Basic acq parameters').child('Dynamic Range').value()
)
self.cam.SpuriousNoiseFilter.setValue(
params.child('Basic acq parameters').child('Spurious Noise Filter').value()
)
@QtCore.pyqtSlot(int)
def new_image_acquired(self, acq_index):
self.imageReadySignal.emit(self.cam.acq_queue.get(), acq_index)
def simple_scan_measurement(self, measure_params):
if self.cam.CameraAcquiring.getValue():
show_warning('Can not start measurement if camera is acquiring')
return 0
self.measurementStartingSignal.emit()
signal_to_scan = self.get_scan_signal(measure_params['signal_to_scan'])
start = measure_params['start']
end = measure_params['end']
step_num = measure_params['steps']
directory = measure_params['directory']
scan_array = create_measurement_array(start, end, step_num)
storage = Storage(directory)
self.cam.TriggerMode.setString('Software')
def get_scan_signal():
pass
QtCore.QTimer.singleShot(5000, self.measurementEndingSignal.emit)
print('Ending measurement')
"""
scan_array = create_measurement_array() # aca necesito parametros de los spinboxes de la measurementGUi
prepare_camara_to_triggered_acq() #includes stopping acquisition if it is in acq live
create_temporary_data_files
measurement loop:
set_scan_signal
wait_predefined_time
take_and_recibe_image
process_image_to_get_data
save_data
update_camera_gui_with_image_and_data
update_measurement_gui
"""
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