Commit f6b374b5 authored by Martin Drechsler's avatar Martin Drechsler
parents d516d036 efc3778c
......@@ -6,6 +6,7 @@ from drivers.ADoutputs import daq_AO, daq_DO
from PyQt5 import QtCore
from subclasses.controllayouts import LaserControlLayout
from subclasses.controllayouts import LaserScanLayout
import numpy as np
AO_TYPES = ['cavity_piezo', 'electrode', 'laser_piezo']
......@@ -52,7 +53,6 @@ class anal_control_signal(QtCore.QObject):
if self.name in layout.spinboxes:
layout.spinboxes[self.name].setMinimum(self.min)
layout.spinboxes[self.name].setMaximum(self.max)
layout.spinboxes[self.name].setValue(self.initial_value)
layout.spinboxes[self.name].sigValueChanging.connect(self.sb_change)
scan_layouts = [l for l in LaserScanLayout._registry if l.name == self.name]
......@@ -85,6 +85,20 @@ class anal_control_signal(QtCore.QObject):
@QtCore.pyqtSlot(object, object)
def sb_change(self, sb, value):
self.AO.set_out(value)
def go_softly_to_value(self, target_value):
start = self.AO.current_value
if start==None:
start = self.initial_value
end = target_value
steps_size = 0.002
array_of_steps= np.arange(min(start, end), max(start, end) + steps_size
, steps_size)
if end<start:
array_of_steps = array_of_steps[::-1]
for i in array_of_steps:
self.AO.set_out(i)
class digital_control_signal(QtCore.QObject):
......
......@@ -76,7 +76,8 @@ class CameraGuiMainWindow(QMainWindow):
self.label = QLabel("Counter of frames")
self.dCameraView.addWidget(self.label)
self.param_tree = CameraParameterTree()
self.param_tree = CameraParameterTree(self.win)
self.param_tree.load()
self.dCameraControl.addWidget(self.param_tree.t)
# layouts and viewboxes
......@@ -134,7 +135,8 @@ class CameraGuiMainWindow(QMainWindow):
self.cameraButton.clicked.connect(self.camera_button_pressed)
self.console = console.ConsoleWidget(
namespace = {'np': np, 'cam': backend.cam, 'roi': self.rois[0], 'storage': backend.storage
namespace = {'np': np, 'cam': backend.cam, 'roi': self.rois[0],
'storage': backend.storage, 'param_tree': self.param_tree
}
)
self.dConsole.addWidget(self.console)
......@@ -148,6 +150,7 @@ class CameraGuiMainWindow(QMainWindow):
self.measurementFrame.saveMeasureButton.clicked.connect(
lambda: self.measurementFrame.saveMeasureButton.setEnabled(False)
)
self.measurementFrame.abortMeasureButton.clicked.connect(backend.abort_measurement)
def camera_button_pressed(self):
......@@ -261,8 +264,15 @@ class CameraGuiMainWindow(QMainWindow):
self.measurementFrame.startMeasureButton.setEnabled(True)
self.measurementFrame.saveMeasureButton.setEnabled(True)
self.isMeasuring = False
scanned_sb_name = self.measurementFrame.selectScanSignal.currentText()
for l in LaserControlLayout._registry + LaserScanLayout._registry :
l.unfreeze()
for sb_name, sb in l.spinboxes.items():
if sb_name == scanned_sb_name:
sb.setValue(self.measurementFrame.endValue.value())
print('gui meas end')
def __del__(self):
......@@ -275,6 +285,14 @@ class CameraGuiMainWindow(QMainWindow):
measure_params['end'] = self.measurementFrame.endValue.value()
measure_params['steps'] = self.measurementFrame.stepsNum.value()
measure_params['directory'] = self.measurementFrame.folderBrowser.toPlainText()
measure_params['comment'] = self.measurementFrame.comments.toPlainText()
measure_params['spinboxes_dict'] = dict()
for l in LaserControlLayout._registry:
for sb_name, sb in l.spinboxes.items():
measure_params['spinboxes_dict'][sb_name] = sb.value()
self.signalWithMeasurementParameters.emit(measure_params)
###############################################################################
......
......@@ -87,7 +87,7 @@ class ControlGui(QtGui.QFrame):
self.electrodes_control_layout.addWidget(self.electrodes_control_layout.spinboxes['compExYb'], 1, 5)
self.toolbar = myToolbarMenu(self)
self.toolbar.load('config.ini')
self.toolbar.load()
self.autosave_timer = QtCore.QTimer()
self.autosave_timer.timeout.connect(lambda: self.toolbar.save('config.ini'))
self.autosave_timer.start(10000)
......@@ -138,5 +138,6 @@ if __name__ == '__main__':
do.moveToThread(mcDAQthread)
mcDAQthread.start()
controlGui.toolbar.load()
sys.exit(app.exec_())
\ No newline at end of file
......@@ -17,20 +17,20 @@ class Helper_messager(QtCore.QObject):
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.SensorCooling = AndorFeats()
self.SensorTemperature = AndorFeats()
self.TemperatureStatus = AndorFeats()
self.ReadoutTime = AndorFeats()
self.PixelReadoutRate = AndorFeats()
self.SimplePreAmpGainControl = AndorFeats()
self.SpuriousNoiseFilter = AndorFeats()
self.TriggerMode = AndorFeats()
self.ExposureTime = AndorFeats('Exposure Time')
self.FrameRate = AndorFeats('Frame Rate')
self.CameraAcquiring = AndorFeats('Camera Acquiring')
self.AOIBinning = AndorFeats('AOIBinning')
self.ImageArea = AndorFeats('Image Area')
self.CameraModel = AndorFeats('Camera Model')
self.SensorCooling = AndorFeats('Sensor Cooling')
self.SensorTemperature = AndorFeats('Sensor Temperature')
self.TemperatureStatus = AndorFeats('Temperature Sensors')
self.ReadoutTime = AndorFeats('Readout Time')
self.PixelReadoutRate = AndorFeats('Pixel Readout Rate')
self.SimplePreAmpGainControl = AndorFeats('SimpleGainControl')
self.SpuriousNoiseFilter = AndorFeats('Filter')
self.TriggerMode = AndorFeats('Trigger Mode')
self.acq_queue = Queue(maxsize=10)
self.helper = Helper_messager()
self.current_image = None
......@@ -107,10 +107,19 @@ class AndorZyla:
self.acq_index_i = self.acq_index_i + 1
self.helper.imageAquiredSignal.emit(self.acq_index_i-1)
def GetMetaData(self):
metadata = dict()
for feat in AndorFeats.registry:
metadata[feat.name] = feat.getValue()
return metadata
class AndorFeats:
def __init__(self):
registry = []
def __init__(self, name):
self.value = None
self.name = name
self.registry.append(self)
def getValue(self):
return self.value
......
......@@ -65,4 +65,5 @@ if __name__ == "__main__":
cameraThread.start()
mcDAQthread.start()
sys.exit(app.exec_())
......@@ -23,10 +23,7 @@ class myToolbarMenu(QWidget):
self.MainGuiWindow = win
self.sbsDicc = dict()
self.first_load()
self.incorporate_toolbar(self.MainGuiWindow)
self.fillSpinBoxesDict()
def fillSpinBoxesDict(self):
......@@ -71,15 +68,15 @@ class myToolbarMenu(QWidget):
viewWebcams.setChecked(False)
viewMenu.addAction(viewWebcams)
saveAct.triggered.connect(lambda: self.save('config.ini'))
loadAct.triggered.connect(lambda: self.load('config.ini'))
saveAct.triggered.connect(lambda: self.save())
loadAct.triggered.connect(lambda: self.load())
loadElectrodesAct.triggered.connect(lambda: self.load_electrodes(win))
saveAsAct.triggered.connect(lambda: self.save_as(win))
openFromAct.triggered.connect(lambda: self.open_from(win))
viewWebcams.toggled.connect(lambda: self.putWebcams(viewWebcams.isChecked()) )
def save(self, location):
def save(self, location='config.ini'):
settings = QSettings(str(location), QSettings.IniFormat)
settings.beginGroup('Ventana')
......@@ -90,11 +87,9 @@ class myToolbarMenu(QWidget):
settings.endGroup()
def load(self, location):
def load(self, location='config.ini'):
settings = QSettings(location, QSettings.IniFormat)
settings.beginGroup('Ventana')
for text, spinb in self.sbsDicc.items():
......@@ -105,23 +100,6 @@ class myToolbarMenu(QWidget):
spinb.setValue( float(spinb.value()) )
settings.endGroup()
def first_load(self):
settings = QSettings('.\config.ini', QSettings.IniFormat)
if not settings:
print('Warning: no config.ini file in control_app folder. Pleace, be kindful and create one')
return 0
settings.beginGroup('Ventana')
for text, spinb in self.sbsDicc.items():
spinbox_saved_value = settings.value(text)
try:
spinb.setValue( float(spinbox_saved_value) )
except TypeError:
spinb.setValue( float(spinb.initial_value) )
settings.endGroup()
def save_as(self, window):
name = QFileDialog.getSaveFileName(window, 'Save File')
if not name[0]:
......@@ -170,6 +148,3 @@ class myToolbarMenu(QWidget):
t_webcams.start()
else:
pass
\ No newline at end of file
......@@ -36,20 +36,37 @@ class Storage(object):
s_num = self.get_saving_number()
# data file
filename = "/".join([saving_directory, 'dump', 's' + str(s_num).zfill(2)]) + '.temp'
header = " ".join([s for s in args]+['\n'])
with open(filename, 'wb') as f:
f.write(header.encode('utf-8'))
#meta data
filename = "/".join([saving_directory, 'dump', 'metadata' + str(s_num).zfill(2)]) + '.txt'
header = 'Meta data file'
with open(filename, 'wb') as f:
f.write(header.encode('utf-8'))
self.delete_temporary()
def append_data_to_current_file(self, row):
with open(self.get_current_filename(), 'ab') as f:
with open(self.get_current_data_filename(), 'ab') as f:
#data = np.column_stack(args)
np.savetxt(f, [row])
f.flush()
def append_metadata_to_current_file(self, *args):
for arg in args:
for key, value in arg.items():
with open(self.get_current_metadata_filename(), 'a') as f:
f.write('\n' + str(key) + ' ' + str(value))
f.flush()
with open(self.get_current_metadata_filename(), 'a') as f:
f.write('\n')
f.flush()
pass
def get_date_string(self):
y = datetime.datetime.now().year
m = datetime.datetime.now().month
......@@ -87,25 +104,43 @@ class Storage(object):
savings_number_list.append(int(s[1:].split('.')[0]))
if len(savings_number_list) > 3: #removes the last of the last 10 files
file_to_remove = "/".join([saving_directory, 's' + str(min(savings_number_list)).zfill(2)])+'.temp'
number_to_remove = min(savings_number_list)
# data file
file_to_remove = "/".join([saving_directory, 's' + str(number_to_remove).zfill(2)])+'.temp'
os.remove(file_to_remove)
def get_current_filename(self):
#meta data
file_to_remove = "/".join([saving_directory, 'metadata' + str(number_to_remove).zfill(2)])+'.txt'
os.remove(file_to_remove)
def get_current_data_filename(self):
s_num = self.get_saving_number()-1
saving_directory = "/".join([self.directory, self.get_date_string()])
filename = "/".join([saving_directory, 'dump', 's' + str(s_num).zfill(2)]) + '.temp'
return filename
def permanent_save_current_data(self):
oldfile = self.get_current_filename()
def get_current_metadata_filename(self):
s_num = self.get_saving_number()-1
saving_directory = "/".join([self.directory, self.get_date_string()])
newfilename = 's' + str(self.get_saving_number(permanent_saving = True) ).zfill(2) + '.dat'
shutil.move(oldfile, "/".join([saving_directory, newfilename]) )
print("/".join([saving_directory, newfilename]))
filename = "/".join([saving_directory, 'dump', 'metadata' + str(s_num).zfill(2)]) + '.txt'
return filename
def permanent_save_current_data(self):
saving_number = self.get_saving_number(permanent_saving = True)
old_datafile = self.get_current_data_filename()
old_metadatafile = self.get_current_metadata_filename()
saving_directory = "/".join([self.directory, self.get_date_string()])
# data file
newfilename = 's' + str(saving_number).zfill(2) + '.dat'
shutil.move(old_datafile, "/".join([saving_directory, newfilename]) )
# metadata file
newfilename = 'metadata' + str(saving_number ).zfill(2) + '.txt'
shutil.move(old_metadatafile, "/".join([saving_directory, newfilename]) )
#%%
import time
if __name__ == '__main__':
storage = Storage()
storage.create_data_file('col1', 'col2')
......@@ -113,5 +148,9 @@ if __name__ == '__main__':
storage.create_data_file('col1', 'col2')
storage.create_data_file('col1', 'col2')
storage.create_data_file('col1', 'col2', 'col3')
storage.append_data_to_current_file([1.0,2.5,time.time()])
storage.permanent_save_current_data()
d1 = {'nombre': 'martin', 'apellido': 'drechsler'}
d2 = {'nombre': 'main', 'edad': 5}
storage.append_metadata_to_current_file(d1, d2)
\ No newline at end of file
# -*- 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
from pyqtgraph.parametertree import Parameter, ParameterTree
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QFileDialog
......@@ -30,28 +28,13 @@ class BasicAcquisitonParameters(pTypes.GroupParameter):
['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': 'Spurious Noise Filter', 'type': 'list', 'values': ['True', 'False']})
self.addChild({'name': 'Sensor Temperature', 'type': 'float', 'value': 25, 'readonly': True})
self.addChild({'name': 'Temperature Status', 'type': 'str', 'value': '?', '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')
......@@ -62,33 +45,36 @@ class BasicAcquisitonParameters(pTypes.GroupParameter):
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': 'Update State', 'type': 'action'})
self.addChild({'name': 'Save State', 'type': 'action'})
self.addChild({'name': 'Restore State', 'type': 'action'})
self.addChild({'name': 'Load State', 'type': 'action'})
self.addChild({'name': 'Load State From', 'type': 'action'})
self.addChild({'name': 'Save State To', 'type': 'action'})
class CameraParameterTree(ParameterTree):
def __init__(self):
def __init__(self, win):
super().__init__()
self.win = win
self.params = [
BasicAcquisitonParameters(name = 'Basic acq parameters'),
BasicActionParameters(name = 'Save/Restore functionality')
BasicActionParameters(name = 'Actions')
]
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.p.sigTreeStateChanged.connect(self.change)
self.t = ParameterTree()
self.t.setParameters(self.p, showTop=False)
self.t.setWindowTitle('Parameter Tree')
self.save()
self.p.param('Actions', 'Save State').sigActivated.connect(lambda: self.save())
self.p.param('Actions', 'Load State').sigActivated.connect(lambda: self.load())
self.p.param('Actions', 'Save State To').sigActivated.connect(lambda: self.save_to())
self.p.param('Actions', 'Load State From').sigActivated.connect(lambda: self.load_from())
self.p.param('Actions', 'Update State').sigActivated.connect(self.print_params)
# self.save()
def change(self, param, changes):
print("tree changes:")
......@@ -103,22 +89,58 @@ class CameraParameterTree(ParameterTree):
print(' data: %s'% str(data))
print(' ----------')
def save(self):
self.state = self.p.saveState()
def print_params(self):
for p in self.p.child('Basic acq parameters').children():
print(p.name(), p.value())
def save(self, location = 'config.ini'):
settings = QSettings(str(location), QSettings.IniFormat)
settings.beginGroup('Camera')
for parameter in self.p.child('Basic acq parameters').children():
settings.setValue(parameter.name(), parameter.value())
settings.endGroup()
def load(self, location = 'config.ini'):
settings = QSettings(str(location), QSettings.IniFormat)
settings.beginGroup('Camera')
for parameter in self.p.child('Basic acq parameters').children():
saved_value = settings.value(parameter.name())
if saved_value:
if not parameter.readonly():
if parameter.type() == 'str' or parameter.type() == 'list':
parameter.setValue(saved_value)
if parameter.type() == 'float':
parameter.setValue(float(saved_value))
settings.endGroup()
def restore(self):
self.p.restoreState(self.state)
def save_to(self):
name = QFileDialog.getSaveFileName(self.win, 'Save File')
if not name[0]:
print('Saving was canceled')
return 0
filename = name[0]+'.ini'
file = open(filename, 'w+')
file.close()
self.save( filename )
def load_from(self):
name = QFileDialog.getOpenFileName(self.win, 'Open File')
if not name[0]:
print('Opening was canceled')
return 0
self.load(name[0])
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
app = QtGui.QApplication([])
import sys
param_tree = CameraParameterTree()
win = QtGui.QWidget()
layout = QtGui.QGridLayout()
win.setLayout(layout)
param_tree = CameraParameterTree(win)
layout.addWidget(QtGui.QLabel("Explanation of parameter tree."), 0, 0, 1, 2)
layout.addWidget(param_tree.t)
win.show()
......
......@@ -34,6 +34,7 @@ class CameraWorker(QtCore.QObject):
self.storage = Storage()
self.ao_to_scan = None
self.scan_array_gen = None
self._lock = threading.Lock()
def make_connections(self, frontend):
# frontend connections
......@@ -135,21 +136,24 @@ class CameraWorker(QtCore.QObject):
end = measure_params['end']
step_num = measure_params['steps']
self.scan_array_gen = yield_array(create_measurement_array(start, end, step_num))
self.ao_to_scan.go_softly_to_value(start)
self.storage.set_directory(measure_params['directory'])
self.storage.create_data_file('Time', measure_params['signal_to_scan'], 'Roi data')
self.storage.append_metadata_to_current_file(measure_params['spinboxes_dict'], self.cam.GetMetaData(), measure_params)
self.cam.TriggerMode.setString('Software')
self.cam.helper.imageAquiredSignal.disconnect(self.new_image_acquired)
self.cam.helper.imageAquiredSignal.connect(self.new_image_acquired_with_trigger)
self._start_acquisition_loop()
self.acq_thread = threading.Thread(
target=self.cam.live_acquisition_loop
)
self.acq_thread.start()
self.simple_scan_measurement_step()
with self._lock:
self.simple_scan_measurement_step()
def simple_scan_measurement_end(self):
......@@ -178,7 +182,9 @@ class CameraWorker(QtCore.QObject):
self.simple_scan_measurement_step()
def abort_measurement(self):
self.scan_array_gen.close()
print('Measurement aborted')
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