class MaestroUi(QSplitter): connected = Signal() # gets emitted if stage was sucessfully connected newPlotData = Signal(object) updateAvgTxt = Signal(object) def __init__(self, parent): #super(ObjectFT, self).__init__(Qt.Vertical, parent) super().__init__(parent) self.meter = None self.collectData = True # bool for data collection thread self.avgData = Queue() # need data for averaging and set for holding all self.measure = False self.runDataThr = True self.measureData = [] self.startTime = None layoutWidget = QWidget() layout = QGridLayout() layoutWidget.setLayout(layout) ############## # gui elements self.ipEdit = QLineEdit() rx = QRegExp("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$") self.ipEdit.setValidator(QRegExpValidator(rx)) self.ipEdit.setText('127.0.0.1') self.portEdit = QLineEdit() self.portEdit.setValidator(QIntValidator(1, 65535, self)) self.portEdit.setText('5000') self.connectBtn = QPushButton('Connect') self.avgSpin = QSpinBox() self.avgSpin.setValue(1) self.avgSpin.setRange(1, 10000) self.currValDisp = QLabel('0.0') self.startMeasBtn = QPushButton('Start aq') self.stopMeasBtn = QPushButton('Stop aq') ############## # put layout together layout.addWidget(QLabel('IP Address:'), 0, 0) layout.addWidget(self.ipEdit, 1, 0) layout.addWidget(QLabel('Port:'), 0, 1) layout.addWidget(self.portEdit, 1, 1) layout.addWidget(self.connectBtn, 2, 1) layout.addWidget(QLabel('Averages'), 4, 0) layout.addWidget(self.avgSpin, 5, 0) layout.addWidget(self.currValDisp, 5, 1) layout.addWidget(self.startMeasBtn, 6, 0) layout.addWidget(self.stopMeasBtn, 6, 1) layout.setRowStretch(7, 10) self.addWidget(layoutWidget) ############## # Network stuff self.tcpClient = QtNetwork.QTcpSocket() self.tcpClient.readyRead.connect(self.__getSocketData) self.tcpClient.error.connect(lambda x: print(x)) ############## # make button and stuff functional self.connectBtn.released.connect(self.connectMeter) self.avgSpin.valueChanged.connect(self.changeAverage) self.startMeasBtn.released.connect(self._startMeasure) self.stopMeasBtn.released.connect(self._stopMeasure) ############## # thread for getting data from socket self.updateAvgTxt.connect(self.__updateAvgTxt) self.dataAq_Thr = QThread() self.dataAq_Thr.start() self.dataAq_worker = GenericWorker(self.__getData) self.dataAq_worker.moveToThread(self.dataAq_Thr) def connectMeter(self): print('connected') self.tcpClient.connectToHost(self.ipEdit.text(), int(self.portEdit.text())) self.tcpClient.write('start\n'.encode()) self.dataAq_worker.start.emit() def _startMeasure(self): self.measure = True self.measureData = [] # reinitialize measure data array time.sleep(0.1) # time to wait for first data to arrive self.startTime = datetime.now() # datetime object def _stopMeasure(self): self.measure = False #@Slot def __updateAvgTxt(self, text): ''' update current value label ''' self.currValDisp.setText(text) def changeAverage(self): shape = int(self.avgSpin.value()) self.dispData = np.zeros(shape) def __getData(self): ''' Function run in thread ''' while self.runDataThr: tmpData = np.array(int(self.avgSpin.text())*[[datetime.now(), 0]]) for i in range(len(tmpData)): tmpData[i] = self.avgData.get() if self.measure: self.measureData.append( (tmpData[i,0].isoformat().encode(), (tmpData[i,0]-self.startTime).total_seconds(), tmpData[i,1])) #print('mean', tmpData.mean()) self.updateAvgTxt.emit(str(tmpData[:,1].mean())) if self.measure: self.newPlotData.emit(np.float_(np.asarray(self.measureData)[:,1:])) self.avgData.task_done() #@Slot() def __getSocketData(self): ''' to be called if network buffer has more data push data to queue ''' self.avgData.put([datetime.now(), float(self.tcpClient.readLine(1024).decode().rstrip())]) def closeEvent(self, event): if self.tcpClient.isOpen(): self.RunDataThr = False self.tcpClient.write('stop\n'.encode()) time.sleep(0.1) self.tcpClient.close() print(self.tcpClient.isOpen()) #if self.console is not None: # self.console.exit_interpreter() event.accept()
class GreatEyesUi(QSplitter): ''' Handling user interface to manage greateys cameras ''' newPlotData = Signal(object, object) message = Signal(object) def __init__(self, parent): super().__init__(parent) self.camera = None self.cameraSettings = None self.aquireData = False self.directory = 'N:/4all/mpsd_drive/xtsfasta/Data' layoutWidget = QWidget() layout = QGridLayout() layoutWidget.setLayout(layout) ############### # GUI elements self.openCamBtn = QPushButton('Connect camera') self.startAquBtn = QPushButton('Start aquisiton') self.readoutSpeedCombo = QComboBox() # this really should not be hard coded but received from dll self.readoutSpeedCombo.addItems(["1 MHz", "1.8 MHz", "2.3 MHz", "2.8 MHz", "250 kHz", "500 kHz"]) self.exposureTimeSpin = QSpinBox() self.exposureTimeSpin.setRange(1, 1e6) self.exposureTimeSpin.setValue(1e3) # default exposure 1s self.exposureTimeSpin.setSingleStep(100) self.exposureTimeSpin.setSuffix(' ms') #self.exposureTimeSpin.setValidator(QIntValidator(1, 2**31)) # ms self.binningXCombo = QComboBox() self.binningXCombo.addItems(["No binning", "Binning of 2 columns", "Binning of 4 columns", "Binning of 8 columns", "Binning of 16 columns", "Binning of 32 columns", "Binning of 64 columns", "Binning of 128 columns", "Full horizontal binning"]) self.binningYCombo = QComboBox() self.binningYCombo.addItems(["No binning", "Binning of 2 lines", "Binning of 4 lines", "Binning of 8 lines", "Binning of 16 lines", "Binning of 32 lines", "Binning of 64 lines", "Binning of 128 lines", "Binning of 256 lines"]) self.temperatureSpin = QSpinBox() self.temperatureSpin.setRange(-100, 20) self.temperatureSpin.setValue(-10) self.temperatureSpin.setSuffix('°C') self.updateInterSpin = QSpinBox() self.updateInterSpin.setRange(1, 3600) self.updateInterSpin.setValue(5) self.updateInterSpin.setSuffix(' s') #self.updateInterSpin.setText("2") #self.updateInterEdit.setValidator(QIntValidator(1, 3600)) self.loi = QSpinBox() self.loi.setRange(1, 511) # one pixel less as the camera has self.deltaPixels = QSpinBox() self.deltaPixels.setRange(0, 256) self.autoSave = QCheckBox("Auto save") self.getDirectory = QPushButton('Choose Dir') self.dirPath = QLineEdit(self.directory) self.comment = QPlainTextEdit() ############## # put elements in layout layout.addWidget(self.openCamBtn, 0, 0) layout.addWidget(self.startAquBtn, 0, 1) layout.addWidget(QLabel('readout speed'), 1, 0) layout.addWidget(self.readoutSpeedCombo, 1, 1) layout.addWidget(QLabel('exposure time'), 2, 0) layout.addWidget(self.exposureTimeSpin, 2, 1) layout.addWidget(QLabel('binning X'), 3, 0) layout.addWidget(self.binningXCombo, 3, 1) layout.addWidget(QLabel('binning Y'), 4, 0) layout.addWidget(self.binningYCombo, 4, 1) layout.addWidget(QLabel('temperature'), 5, 0) layout.addWidget(self.temperatureSpin, 5, 1) layout.addWidget(QLabel('update every n-seconds'), 6, 0) layout.addWidget(self.updateInterSpin, 6, 1) layout.addWidget(QLabel('Pixel of interest'), 7, 0) layout.addWidget(self.loi, 7, 1) layout.addWidget(QLabel('Δ pixels'), 8, 0) layout.addWidget(self.deltaPixels, 8, 1) layout.addWidget(self.autoSave, 9, 1) layout.addWidget(self.getDirectory, 10, 0) layout.addWidget(self.dirPath, 10, 1) layout.addWidget(QLabel('Comment:'), 11, 0) layout.addWidget(self.comment, 12, 0, 1, 2) layout.setRowStretch(13, 10) self.addWidget(layoutWidget) ################# # connect elements for functionality self.openCamBtn.released.connect(self.__openCam) self.getDirectory.released.connect(self.__chooseDir) self.temperatureSpin.valueChanged.connect(self.__setTemperature) self.exposureTimeSpin.valueChanged.connect(self.__setCamParameter) self.readoutSpeedCombo.currentIndexChanged.connect(self.__setCamParameter) self.startAquBtn.released.connect(self.__startCurrImageThr) ################ # thread for updating position self.currImage_thread = QThread() # create the QThread self.currImage_thread.start() # This causes my_worker.run() to eventually execute in my_thread: self.currImage_worker = GenericWorker(self.__getCurrImage) self.currImage_worker.moveToThread(self.currImage_thread) self.startAquBtn.setEnabled(False) self.readoutSpeedCombo.setEnabled(False) self.exposureTimeSpin.setEnabled(False) self.binningXCombo.setEnabled(False) self.binningYCombo.setEnabled(False) self.temperatureSpin.setEnabled(False) self.updateInterSpin.setEnabled(False) def __openCam(self): self.camera = greatEyes() if not self.camera.connected: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText('Sorry, could not connect to camera :(\n' + self.camera.status) msg.exec_() return self.openCamBtn.setText('Connected') self.message.emit('Camera connected') self.openCamBtn.setStyleSheet('QPushButton {color: green;}') self.readoutSpeedCombo.setEnabled(True) self.exposureTimeSpin.setEnabled(True) self.binningXCombo.setEnabled(False) self.binningYCombo.setEnabled(False) self.temperatureSpin.setEnabled(True) self.updateInterSpin.setEnabled(True) self.openCamBtn.setEnabled(False) self.startAquBtn.setEnabled(True) def __chooseDir(self): self.directory = QFileDialog.getExistingDirectory(self, "Choose directory", self.directory) self.dirPath.setText(self.directory) def __startCurrImageThr(self): if not self.aquireData: self.aquireData = True self.currImage_worker.start.emit() self.startAquBtn.setText('Stop aquisition') self.message.emit('Starting aqusition') else: self.__stopCurrImageThr() self.startAquBtn.setText('Start aquisition') self.message.emit('Stopping aqusition') def __stopCurrImageThr(self): self.aquireData = False #while(self.currPosThr.isRunning()): # time.sleep(0.03) def __getCurrImage(self): #from scipy import mgrid #import numpy as np #X, Y = mgrid[-256:256, -1024:1025] i = self.updateInterSpin.value() while self.aquireData: # seconds over which to record a new image imageIntervall = self.updateInterSpin.value() # sleep for n seconds to check if intervall was changed sleepy = 1 if i >= imageIntervall: # dummy image #z = np.exp(-0.5*(X**2+Y**2)/np.random.uniform(30000, 40000))*np.cos(0.1*X+0.1*Y) z = self.camera.getImage() timeStamp = datetime.datetime.now() self.cameraSettings = { 'temperature': self.camera.getTemperature(), 'exposure_time': self.exposureTimeSpin.value(), 'readout_speed': self.readoutSpeedCombo.currentText() 'time_stamp': timeStamp} self.newPlotData.emit(z, timeStamp) i = 0 # restart counter i += sleepy time.sleep(sleepy) def __setTemperature(self, temp): self.camera.setTemperture(temp) self.message.emit('Temperature set to {:d}°C'.format(temp)) def __setCamParameter(self, param): self.camera.setCameraParameter( self.readoutSpeedCombo.currentIndex(), self.exposureTimeSpin.value(), 0, 0) self.message.emit('Readout: {:s}, Exposure: {:d}, binningX: 0, binningY: 0'.format(self.readoutSpeedCombo.currentText(), self.exposureTimeSpin.value()))