def __init__(self, parent): super(FileUi, self).__init__(Qt.Vertical, parent) layoutWidget = QWidget() layout = QVBoxLayout() layoutWidget.setLayout(layout) self.comment = QPlainTextEdit() self.fileName = None self.saveTxtCheck = QCheckBox('Save Txt') self.saveHdfCheck = QCheckBox('Save HDF5') self.saveTxtBtn = QPushButton('Save Txt') self.saveHdfBtn = QPushButton('Save HDF5') ############# # stream group streamGroup = QGroupBox('Stream data to file:') streamGroup.setFlat(True) streamGroupLayout = QHBoxLayout() streamGroupLayout.addWidget(self.saveTxtCheck) streamGroupLayout.addWidget(self.saveHdfCheck) streamGroup.setLayout(streamGroupLayout) ############## # save static file saveGroup = QGroupBox('Save now to file:') saveGroup.setFlat(True) saveGroupLayout = QHBoxLayout() saveGroupLayout.addWidget(self.saveTxtBtn) saveGroupLayout.addWidget(self.saveHdfBtn) saveGroup.setLayout(saveGroupLayout) ############## # put layout together layout.addWidget(QLabel('Comment:')) layout.addWidget(self.comment) layout.addWidget(streamGroup) layout.addWidget(saveGroup) self.addWidget(layoutWidget) ############## # connnect stuff for functionality self.saveTxtCheck.stateChanged.connect(self.__makeFileName) self.saveHdfCheck.stateChanged.connect(self.__makeFileName) ############## # thread for streaming data to file #self.updateCurrPos.connect(self.__updateCurrPos) self.stream_thread = QThread() # create the QThread self.stream_thread.start() self.stream_worker = GenericWorker(self.__streamFile) self.stream_worker.moveToThread(self.stream_thread)
def __init__(self): QMainWindow.__init__(self) self.stage = None self.stopOsci = False self.stopMeasure = False self.setWindowTitle(APP_NAME) ############### # Osci live curveplot_toolbar = self.addToolBar(_("Curve Plotting Toolbar")) self.osciCurveWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.osciCurveWidget.calcFun.addFun('s', lambda x: x, lambda x: x) self.osciCurveWidget.calcFun.addFun('ms', lambda x: x*1e3, lambda x: x*1e-3) self.osciCurveWidget.calcFun.addFun('µs', lambda x: x*1e6, lambda x: x*1e-6) osciPlot = self.osciCurveWidget.get_plot() #osciPlot.set_axis_title('bottom', 'Time (s)') #osciplot.add_item(make.legend("TR")) self.osciSignal = SignalFT(self, plot=osciPlot) self.osciSignal.addHCursor(0) self.osciSignal.addBounds() ############## # Time domain plot self.tdWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.tdWidget.calcFun.addFun('fs', lambda x: x, lambda x: x) self.tdWidget.calcFun.addFun('µm', lambda x: x*fsDelay*1e3, lambda x: x/fsDelay*1e-3) self.tdWidget.calcFun.addFun('mm', lambda x: x*fsDelay, lambda x: x/fsDelay) tdPlot = self.tdWidget.get_plot() #tdPlot.add_item(make.legend("TR")) self.tdSignal = SignalFT(self, plot=tdPlot) self.tdSignal.addVCursor(0) ################## # Frequency domain plot self.fdWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.fdWidget.calcFun.addFun('PHz', lambda x: x, lambda x: x) self.fdWidget.calcFun.addFun('THz', lambda x: x*1e3, lambda x: x*1e-3) # x = PHz -> 1e15, µm = 1e-6 self.fdWidget.calcFun.addFun('µm', lambda x: c0/x*1e-9, lambda x: c0/x*1e-9) self.fdWidget.calcFun.addFun('eV', lambda x: x, lambda x: x) fdplot = self.fdWidget.get_plot() #fqdplot.add_item(make.legend("TR")) self.fdSignal = SignalFT(self, plot=fdplot) ############## # Main window widgets self.tabwidget = DockableTabWidget(self) #self.tabwidget.setMaximumWidth(500) self.tiepieUi = TiePieUi(self) self.piUi = PiStageUi(self) #self.stage = self.piUi.stage self.tabwidget.addTab(self.tiepieUi, QIcon('icons/Handyscope_HS4.png'), _("Osci")) self.tabwidget.addTab(self.piUi, QIcon('icons/piController.png'), _("Stage")) self.add_dockwidget(self.tabwidget, _("Inst. sett.")) # self.setCentralWidget(self.tabwidget) self.osci_dock = self.add_dockwidget(self.osciCurveWidget, title=_("Osciloscope")) self.td_dock = self.add_dockwidget(self.tdWidget, title=_("Time Domain")) self.fd_dock = self.add_dockwidget(self.fdWidget, title=_("Frequency Domain")) ################ # connect signals self.piUi.startScanBtn.released.connect(self.startMeasureThr) self.piUi.stopScanBtn.released.connect(self.stopMeasureThr) self.piUi.xAxeChanged.connect(self.tdSignal.updateXAxe) self.piUi.xAxeChanged.connect(self.fdSignal.updateXAxe) self.piUi.niceBtn.released.connect(self.showMakeNicerWidget) self.tiepieUi.scpConnected.connect(self.startOsciThr) self.tiepieUi.xAxeChanged.connect(self.osciSignal.updateXAxe) self.tiepieUi.yAxeChanged.connect(self.osciSignal.updateYAxe) self.tiepieUi.triggLevelChanged.connect(self.osciSignal.setHCursor) #self.piUi.centerBtn.released.connect( # lambda x=None: self.piUi.setCenter(self.tdSignal.getVCursor())) self.tdSignal.plot.SIG_MARKER_CHANGED.connect( lambda x=None: self.piUi.newOffset(self.tdSignal.getVCursor())) self.osciCurveWidget.calcFun.idxChanged.connect(self.osciSignal.funChanged) self.tdWidget.calcFun.idxChanged.connect(self.tdSignal.funChanged) self.fdWidget.calcFun.idxChanged.connect(self.fdSignal.funChanged) self.updateOsciPlot.connect(self.osciSignal.updatePlot) self.updateTdPlot.connect(self.tdSignal.updatePlot) self.updateFdPlot.connect(lambda data: self.fdSignal.updatePlot(self.fdSignal.computeFFT(data))) ################ # create threads #self.osciThr = GenericThread(self.getOsciData) self.osciThr = QThread() self.osciThr.start() self.osciWorker = GenericWorker(self.getOsciData) self.osciWorker.moveToThread(self.osciThr) #self.measureThr = GenericThread(self.getMeasureData) self.measureThr = QThread() self.measureThr.start() self.measureWorker = GenericWorker(self.getMeasureData) self.measureWorker.moveToThread(self.measureThr) ################ # File menu file_menu = self.menuBar().addMenu(_("File")) self.quit_action = create_action(self, _("Quit"), shortcut="Ctrl+Q", icon=get_std_icon("DialogCloseButton"), tip=_("Quit application"), triggered=self.close) saveData = create_action(self, _("Save"), shortcut="Ctrl+S", icon=get_std_icon("DialogSaveButton"), tip=_("Save data"), triggered=self.saveData) triggerTest_action = create_action(self, _("Stop Osci"), shortcut="Ctrl+O", icon=get_icon('fileopen.png'), tip=_("Open an image"), triggered=self.stopOsciThr) add_actions(file_menu, (triggerTest_action, saveData, None, self.quit_action)) ############## # Eventually add an internal console (requires 'spyderlib') self.sift_proxy = SiftProxy(self) if DockableConsole is None: self.console = None else: import time, scipy.signal as sps, scipy.ndimage as spi ns = {'ftir': self.sift_proxy, 'np': np, 'sps': sps, 'spi': spi, 'os': os, 'sys': sys, 'osp': osp, 'time': time} msg = "Example: ftir.s[0] returns signal object #0\n"\ "Modules imported at startup: "\ "os, sys, os.path as osp, time, "\ "numpy as np, scipy.signal as sps, scipy.ndimage as spi" self.console = DockableConsole(self, namespace=ns, message=msg) self.add_dockwidget(self.console, _("Console")) ''' try: self.console.interpreter.widget_proxy.sig_new_prompt.connect( lambda txt: self.refresh_lists()) except AttributeError: print('sift: spyderlib is outdated', file=sys.stderr) ''' # Show main window and raise the signal plot panel self.show()
class MainWindow(QMainWindow): updateOsciPlot = Signal(object) updateTdPlot = Signal(object) updateFdPlot = Signal(object) def __init__(self): QMainWindow.__init__(self) self.stage = None self.stopOsci = False self.stopMeasure = False self.setWindowTitle(APP_NAME) ############### # Osci live curveplot_toolbar = self.addToolBar(_("Curve Plotting Toolbar")) self.osciCurveWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.osciCurveWidget.calcFun.addFun('s', lambda x: x, lambda x: x) self.osciCurveWidget.calcFun.addFun('ms', lambda x: x*1e3, lambda x: x*1e-3) self.osciCurveWidget.calcFun.addFun('µs', lambda x: x*1e6, lambda x: x*1e-6) osciPlot = self.osciCurveWidget.get_plot() #osciPlot.set_axis_title('bottom', 'Time (s)') #osciplot.add_item(make.legend("TR")) self.osciSignal = SignalFT(self, plot=osciPlot) self.osciSignal.addHCursor(0) self.osciSignal.addBounds() ############## # Time domain plot self.tdWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.tdWidget.calcFun.addFun('fs', lambda x: x, lambda x: x) self.tdWidget.calcFun.addFun('µm', lambda x: x*fsDelay*1e3, lambda x: x/fsDelay*1e-3) self.tdWidget.calcFun.addFun('mm', lambda x: x*fsDelay, lambda x: x/fsDelay) tdPlot = self.tdWidget.get_plot() #tdPlot.add_item(make.legend("TR")) self.tdSignal = SignalFT(self, plot=tdPlot) self.tdSignal.addVCursor(0) ################## # Frequency domain plot self.fdWidget = DockablePlotWidget(self, CurveWidget, curveplot_toolbar) self.fdWidget.calcFun.addFun('PHz', lambda x: x, lambda x: x) self.fdWidget.calcFun.addFun('THz', lambda x: x*1e3, lambda x: x*1e-3) # x = PHz -> 1e15, µm = 1e-6 self.fdWidget.calcFun.addFun('µm', lambda x: c0/x*1e-9, lambda x: c0/x*1e-9) self.fdWidget.calcFun.addFun('eV', lambda x: x, lambda x: x) fdplot = self.fdWidget.get_plot() #fqdplot.add_item(make.legend("TR")) self.fdSignal = SignalFT(self, plot=fdplot) ############## # Main window widgets self.tabwidget = DockableTabWidget(self) #self.tabwidget.setMaximumWidth(500) self.tiepieUi = TiePieUi(self) self.piUi = PiStageUi(self) #self.stage = self.piUi.stage self.tabwidget.addTab(self.tiepieUi, QIcon('icons/Handyscope_HS4.png'), _("Osci")) self.tabwidget.addTab(self.piUi, QIcon('icons/piController.png'), _("Stage")) self.add_dockwidget(self.tabwidget, _("Inst. sett.")) # self.setCentralWidget(self.tabwidget) self.osci_dock = self.add_dockwidget(self.osciCurveWidget, title=_("Osciloscope")) self.td_dock = self.add_dockwidget(self.tdWidget, title=_("Time Domain")) self.fd_dock = self.add_dockwidget(self.fdWidget, title=_("Frequency Domain")) ################ # connect signals self.piUi.startScanBtn.released.connect(self.startMeasureThr) self.piUi.stopScanBtn.released.connect(self.stopMeasureThr) self.piUi.xAxeChanged.connect(self.tdSignal.updateXAxe) self.piUi.xAxeChanged.connect(self.fdSignal.updateXAxe) self.piUi.niceBtn.released.connect(self.showMakeNicerWidget) self.tiepieUi.scpConnected.connect(self.startOsciThr) self.tiepieUi.xAxeChanged.connect(self.osciSignal.updateXAxe) self.tiepieUi.yAxeChanged.connect(self.osciSignal.updateYAxe) self.tiepieUi.triggLevelChanged.connect(self.osciSignal.setHCursor) #self.piUi.centerBtn.released.connect( # lambda x=None: self.piUi.setCenter(self.tdSignal.getVCursor())) self.tdSignal.plot.SIG_MARKER_CHANGED.connect( lambda x=None: self.piUi.newOffset(self.tdSignal.getVCursor())) self.osciCurveWidget.calcFun.idxChanged.connect(self.osciSignal.funChanged) self.tdWidget.calcFun.idxChanged.connect(self.tdSignal.funChanged) self.fdWidget.calcFun.idxChanged.connect(self.fdSignal.funChanged) self.updateOsciPlot.connect(self.osciSignal.updatePlot) self.updateTdPlot.connect(self.tdSignal.updatePlot) self.updateFdPlot.connect(lambda data: self.fdSignal.updatePlot(self.fdSignal.computeFFT(data))) ################ # create threads #self.osciThr = GenericThread(self.getOsciData) self.osciThr = QThread() self.osciThr.start() self.osciWorker = GenericWorker(self.getOsciData) self.osciWorker.moveToThread(self.osciThr) #self.measureThr = GenericThread(self.getMeasureData) self.measureThr = QThread() self.measureThr.start() self.measureWorker = GenericWorker(self.getMeasureData) self.measureWorker.moveToThread(self.measureThr) ################ # File menu file_menu = self.menuBar().addMenu(_("File")) self.quit_action = create_action(self, _("Quit"), shortcut="Ctrl+Q", icon=get_std_icon("DialogCloseButton"), tip=_("Quit application"), triggered=self.close) saveData = create_action(self, _("Save"), shortcut="Ctrl+S", icon=get_std_icon("DialogSaveButton"), tip=_("Save data"), triggered=self.saveData) triggerTest_action = create_action(self, _("Stop Osci"), shortcut="Ctrl+O", icon=get_icon('fileopen.png'), tip=_("Open an image"), triggered=self.stopOsciThr) add_actions(file_menu, (triggerTest_action, saveData, None, self.quit_action)) ############## # Eventually add an internal console (requires 'spyderlib') self.sift_proxy = SiftProxy(self) if DockableConsole is None: self.console = None else: import time, scipy.signal as sps, scipy.ndimage as spi ns = {'ftir': self.sift_proxy, 'np': np, 'sps': sps, 'spi': spi, 'os': os, 'sys': sys, 'osp': osp, 'time': time} msg = "Example: ftir.s[0] returns signal object #0\n"\ "Modules imported at startup: "\ "os, sys, os.path as osp, time, "\ "numpy as np, scipy.signal as sps, scipy.ndimage as spi" self.console = DockableConsole(self, namespace=ns, message=msg) self.add_dockwidget(self.console, _("Console")) ''' try: self.console.interpreter.widget_proxy.sig_new_prompt.connect( lambda txt: self.refresh_lists()) except AttributeError: print('sift: spyderlib is outdated', file=sys.stderr) ''' # Show main window and raise the signal plot panel self.show() #------GUI refresh/setup def add_dockwidget(self, child, title): """Add QDockWidget and toggleViewAction""" dockwidget, location = child.create_dockwidget(title) self.addDockWidget(location, dockwidget) return dockwidget def showMakeNicerWidget(self): self.makeNicerWidget = MakeNicerWidget(self) self.makeNicerDock = self.add_dockwidget(self.makeNicerWidget, 'Make FFT nicer') #self.makeNicerDock.setFloating(True) #self.fsBrowser = QDockWidget("4D Fermi Surface Browser", self) #self.fsWidget = FermiSurface_Widget(self) #self.fsBrowser.setWidget(self.fsWidget) #self.fsBrowser.setFloating(True) #self.addDockWidget(Qt.RightDockWidgetArea, self.fsBrowser) def closeEvent(self, event): if self.stage is not None: self.stage.CloseConnection() if self.console is not None: self.console.exit_interpreter() event.accept() def saveData(self): import datetime now = datetime.datetime.now().strftime('%Y%m%d-%H%M%S') # save time domain foo = self.tdWidget.calcFun.functions texts = [self.tdWidget.calcFun.itemText(i) for i in range(len(foo))] tmp = ['td_x_{:s},td_y_{:s}'.format(i, i) for i in texts] header = ','.join(tmp) dataTd = np.zeros((self.tdSignal.getData(foo[0][0])[0].shape[0], 2*len(foo))) for i, fun in enumerate(foo): x, y = self.tdSignal.getData(fun[0])# [0]: fun, [1]: inverse fun dataTd[:,2*i] = x dataTd[:,2*i+1] = y np.savetxt('data/{:s}_TD.txt'.format(now), dataTd, header=header) self.tdSignal.plot.save_widget('data/{:s}_TD.png'.format(now)) # save frequency domain foo = self.fdWidget.calcFun.functions texts = [self.fdWidget.calcFun.itemText(i) for i in range(len(foo))] tmp = ['fd_x_{:s},fd_y_{:s}'.format(i, i) for i in texts] header += ','.join(tmp) dataFd = np.zeros((self.fdSignal.getData(foo[0][0])[0].shape[0], 2*len(foo))) for fun in foo: x, y = self.fdSignal.getData(fun[0]) dataFd[:,2*i] = x dataFd[:,2*i+1] = y np.savetxt('data/{:s}_FD.txt'.format(now), dataFd, header=header) self.fdSignal.plot.save_widget('data/{:s}_FD.png'.format(now)) # TODO: maybe put this in status bar msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText('Data saved') msg.exec_() #def getStage(self, gcs): # self.stage = gcs # print(dir(self.stage)) # print(self.stage.qPOS()) def startOsciThr(self): self.stopOsci = False #self.osciThr.start() self.osciWorker.start.emit() def stopOsciThr(self): self.stopOsci = True # TODO: not quite shure how to do this with the worker solution. # finished signal is emitted but this function should wait for worker to finish?!? while(self.osciWorker.isRunning()): time.sleep(0.03) def getOsciData(self): while not self.stopOsci: data = self.tiepieUi.getData() self.updateOsciPlot.emit(data) time.sleep(0.5) def startMeasureThr(self): # stop osci thread and start measure thread self.stopOsciThr() # rescale tdPlot (updateXAxe) self.piUi._xAxeChanged() # set vCursor to 0 self.tdSignal.setVCursor(0) self.piUi.setCenter() # init x axe frequency domain plot to a min and max delays = self.piUi.getDelays_fs() data = np.column_stack((delays, np.zeros(len(delays)))) fdAxe = self.fdSignal.computeFFT(data) self.fdSignal.updateXAxe(fdAxe[0,0], fdAxe[-1,0]) self.stopMeasure = False #self.measureThr.start() self.measureWorker.start.emit() def stopMeasureThr(self): self.stopMeasure = True while(self.measureWorker.isRunning()): time.sleep(0.03) self.startOsciThr() def getMeasureData(self): delays = self.piUi.getDelays_fs() data = np.column_stack((delays, np.zeros(len(delays)))) for i, delay in enumerate(delays): if not self.stopMeasure: self.piUi.gotoPos_fs(delay) tmp = self.tiepieUi.getData() self.updateOsciPlot.emit(tmp) #print('measuring at', delay) #y = dummyPulse(delay) #data[i,1] = y #data[i,1] = tmp[:,1].mean() data[i,1] = self.osciSignal.computeSum() #time.sleep(0.05) self.updateTdPlot.emit(data) self.updateFdPlot.emit(data) else: break self.startOsciThr() """
def __init__(self, parent): #super(ObjectFT, self).__init__(Qt.Vertical, parent) super().__init__(parent) self.stage = None self.offset = 0. # offset from 0 where t0 is (mm) self.newOff = 0. self.stageRange = (0, 0) layoutWidget = QWidget() layout = QGridLayout() layoutWidget.setLayout(layout) # put layout together self.openStageBtn = QPushButton("Open stage") self.initStageBtn = QPushButton("Init stage") #absolute move #current position self.currentPos = QLabel('') #self.currentPos.setValidator(QDoubleValidator()) #relative move (mm) self.deltaMove_mm = QLineEdit() self.deltaMove_mm.setText('0') self.deltaMove_mm.setValidator(QDoubleValidator()) self.deltaMovePlus_mm = QPushButton('+') self.deltaMoveMinus_mm = QPushButton('-') #relative move (fs) self.deltaMove_fs = QLineEdit() self.deltaMovePlus_fs = QPushButton('+') self.deltaMoveMinus_fs = QPushButton('-') #velocity self.velocityLabel = QLabel('Velocity:') self.velocity = QSlider(Qt.Horizontal) self.velocity.setMinimum(0) self.velocity.setMaximum( 2000) # unit in µm; TODO: try to get max vel. from controller # scan from (fs) self.scanFrom = QLineEdit() self.scanFrom.setText('-100') self.scanFrom.setValidator(QIntValidator()) # scan to (fs) self.scanTo = QLineEdit() self.scanTo.setText('100') self.scanTo.setValidator(QIntValidator()) # scan stepsize (fs) self.scanStep = QLineEdit() self.scanStep.setText('10') self.scanStep.setValidator(QDoubleValidator()) # center here button self.centerBtn = QPushButton('Center here') self.centerBtn.setToolTip('Center scan at current stage position') self.startScanBtn = QPushButton("Start scan") self.stopScanBtn = QPushButton("Stop scan") self.niceBtn = QPushButton('Make it nice') # spacer line hLine = QFrame() hLine.setFrameStyle(QFrame.HLine) hLine.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) # put layout together layout.addWidget(self.openStageBtn, 0, 0) layout.addWidget(self.initStageBtn, 0, 1) layout.addWidget(QLabel("Current pos (mm):"), 1, 0) layout.addWidget(self.currentPos, 1, 1) layout.addWidget(self.velocityLabel, 2, 0) layout.addWidget(self.velocity, 3, 0, 1, 2) layout.addWidget(QLabel('Move relative (mm)'), 4, 0) layout.addWidget(self.deltaMove_mm, 5, 0, 1, 2) layout.addWidget(self.deltaMoveMinus_mm, 6, 0) layout.addWidget(self.deltaMovePlus_mm, 6, 1) layout.addWidget(QLabel('Move relative (fs)'), 7, 0) layout.addWidget(self.deltaMove_fs, 8, 0, 1, 2) layout.addWidget(self.deltaMoveMinus_fs, 9, 0) layout.addWidget(self.deltaMovePlus_fs, 9, 1) layout.addWidget(hLine, 10, 0, 1, 2) layout.addWidget(QLabel('Scan from (fs)'), 11, 0) layout.addWidget(self.scanFrom, 11, 1) layout.addWidget(QLabel('Scan to (fs)'), 12, 0) layout.addWidget(self.scanTo, 12, 1) layout.addWidget(QLabel('Stepsize (fs)'), 13, 0) layout.addWidget(self.scanStep, 13, 1) layout.addWidget(self.startScanBtn, 14, 0) layout.addWidget(self.stopScanBtn, 14, 1) layout.addWidget(self.centerBtn, 15, 1) layout.addWidget(self.niceBtn, 16, 1) layout.setRowStretch(17, 10) layout.setColumnStretch(2, 10) self.addWidget(layoutWidget) # make button and stuff functional self.openStageBtn.released.connect(self.connectStage) self.initStageBtn.released.connect(self.initStage) self.scanFrom.returnPressed.connect(self._xAxeChanged) self.scanTo.returnPressed.connect(self._xAxeChanged) self.centerBtn.released.connect(self._centerHere) self.deltaMovePlus_mm.released.connect( lambda x=1: self.moveRel_mm(float(self.deltaMove_mm.text()))) self.deltaMoveMinus_mm.released.connect( lambda x=-1: self.moveRel_mm(float(self.deltaMove_mm.text()), x)) ################ # thread for updating position #self.currPosThr = GenericThread(self.__getCurrPos) self.updateCurrPos.connect(self.__updateCurrPos) self.currPos_thread = QThread() # create the QThread self.currPos_thread.start() # This causes my_worker.run() to eventually execute in my_thread: self.currPos_worker = GenericWorker(self.__getCurrPos) self.currPos_worker.moveToThread(self.currPos_thread)
class FileUi(QSplitter): def __init__(self, parent): super(FileUi, self).__init__(Qt.Vertical, parent) layoutWidget = QWidget() layout = QVBoxLayout() layoutWidget.setLayout(layout) self.comment = QPlainTextEdit() self.fileName = None self.saveTxtCheck = QCheckBox('Save Txt') self.saveHdfCheck = QCheckBox('Save HDF5') self.saveTxtBtn = QPushButton('Save Txt') self.saveHdfBtn = QPushButton('Save HDF5') ############# # stream group streamGroup = QGroupBox('Stream data to file:') streamGroup.setFlat(True) streamGroupLayout = QHBoxLayout() streamGroupLayout.addWidget(self.saveTxtCheck) streamGroupLayout.addWidget(self.saveHdfCheck) streamGroup.setLayout(streamGroupLayout) ############## # save static file saveGroup = QGroupBox('Save now to file:') saveGroup.setFlat(True) saveGroupLayout = QHBoxLayout() saveGroupLayout.addWidget(self.saveTxtBtn) saveGroupLayout.addWidget(self.saveHdfBtn) saveGroup.setLayout(saveGroupLayout) ############## # put layout together layout.addWidget(QLabel('Comment:')) layout.addWidget(self.comment) layout.addWidget(streamGroup) layout.addWidget(saveGroup) self.addWidget(layoutWidget) ############## # connnect stuff for functionality self.saveTxtCheck.stateChanged.connect(self.__makeFileName) self.saveHdfCheck.stateChanged.connect(self.__makeFileName) ############## # thread for streaming data to file #self.updateCurrPos.connect(self.__updateCurrPos) self.stream_thread = QThread() # create the QThread self.stream_thread.start() self.stream_worker = GenericWorker(self.__streamFile) self.stream_worker.moveToThread(self.stream_thread) def __makeFileName(self, state): if state == 2: self.fileName = datetime.now().strftime('%Y%m%d-%H%M%S') self.stream_worker.start.emit() else: self.fileName = None def __streamFile(self): while self.saveHdfCheck.isChecked(): self.saveHdfBtn.released.emit() time.sleep(10)
class PiStageUi(QSplitter): stageConnected = Signal( ) # gets emitted if stage was sucessfully connected stopScan = Signal() xAxeChanged = Signal(object, object) updateCurrPos = Signal(object) def __init__(self, parent): #super(ObjectFT, self).__init__(Qt.Vertical, parent) super().__init__(parent) self.stage = None self.offset = 0. # offset from 0 where t0 is (mm) self.newOff = 0. self.stageRange = (0, 0) layoutWidget = QWidget() layout = QGridLayout() layoutWidget.setLayout(layout) # put layout together self.openStageBtn = QPushButton("Open stage") self.initStageBtn = QPushButton("Init stage") #absolute move #current position self.currentPos = QLabel('') #self.currentPos.setValidator(QDoubleValidator()) #relative move (mm) self.deltaMove_mm = QLineEdit() self.deltaMove_mm.setText('0') self.deltaMove_mm.setValidator(QDoubleValidator()) self.deltaMovePlus_mm = QPushButton('+') self.deltaMoveMinus_mm = QPushButton('-') #relative move (fs) self.deltaMove_fs = QLineEdit() self.deltaMovePlus_fs = QPushButton('+') self.deltaMoveMinus_fs = QPushButton('-') #velocity self.velocityLabel = QLabel('Velocity:') self.velocity = QSlider(Qt.Horizontal) self.velocity.setMinimum(0) self.velocity.setMaximum( 2000) # unit in µm; TODO: try to get max vel. from controller # scan from (fs) self.scanFrom = QLineEdit() self.scanFrom.setText('-100') self.scanFrom.setValidator(QIntValidator()) # scan to (fs) self.scanTo = QLineEdit() self.scanTo.setText('100') self.scanTo.setValidator(QIntValidator()) # scan stepsize (fs) self.scanStep = QLineEdit() self.scanStep.setText('10') self.scanStep.setValidator(QDoubleValidator()) # center here button self.centerBtn = QPushButton('Center here') self.centerBtn.setToolTip('Center scan at current stage position') self.startScanBtn = QPushButton("Start scan") self.stopScanBtn = QPushButton("Stop scan") self.niceBtn = QPushButton('Make it nice') # spacer line hLine = QFrame() hLine.setFrameStyle(QFrame.HLine) hLine.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) # put layout together layout.addWidget(self.openStageBtn, 0, 0) layout.addWidget(self.initStageBtn, 0, 1) layout.addWidget(QLabel("Current pos (mm):"), 1, 0) layout.addWidget(self.currentPos, 1, 1) layout.addWidget(self.velocityLabel, 2, 0) layout.addWidget(self.velocity, 3, 0, 1, 2) layout.addWidget(QLabel('Move relative (mm)'), 4, 0) layout.addWidget(self.deltaMove_mm, 5, 0, 1, 2) layout.addWidget(self.deltaMoveMinus_mm, 6, 0) layout.addWidget(self.deltaMovePlus_mm, 6, 1) layout.addWidget(QLabel('Move relative (fs)'), 7, 0) layout.addWidget(self.deltaMove_fs, 8, 0, 1, 2) layout.addWidget(self.deltaMoveMinus_fs, 9, 0) layout.addWidget(self.deltaMovePlus_fs, 9, 1) layout.addWidget(hLine, 10, 0, 1, 2) layout.addWidget(QLabel('Scan from (fs)'), 11, 0) layout.addWidget(self.scanFrom, 11, 1) layout.addWidget(QLabel('Scan to (fs)'), 12, 0) layout.addWidget(self.scanTo, 12, 1) layout.addWidget(QLabel('Stepsize (fs)'), 13, 0) layout.addWidget(self.scanStep, 13, 1) layout.addWidget(self.startScanBtn, 14, 0) layout.addWidget(self.stopScanBtn, 14, 1) layout.addWidget(self.centerBtn, 15, 1) layout.addWidget(self.niceBtn, 16, 1) layout.setRowStretch(17, 10) layout.setColumnStretch(2, 10) self.addWidget(layoutWidget) # make button and stuff functional self.openStageBtn.released.connect(self.connectStage) self.initStageBtn.released.connect(self.initStage) self.scanFrom.returnPressed.connect(self._xAxeChanged) self.scanTo.returnPressed.connect(self._xAxeChanged) self.centerBtn.released.connect(self._centerHere) self.deltaMovePlus_mm.released.connect( lambda x=1: self.moveRel_mm(float(self.deltaMove_mm.text()))) self.deltaMoveMinus_mm.released.connect( lambda x=-1: self.moveRel_mm(float(self.deltaMove_mm.text()), x)) ################ # thread for updating position #self.currPosThr = GenericThread(self.__getCurrPos) self.updateCurrPos.connect(self.__updateCurrPos) self.currPos_thread = QThread() # create the QThread self.currPos_thread.start() # This causes my_worker.run() to eventually execute in my_thread: self.currPos_worker = GenericWorker(self.__getCurrPos) self.currPos_worker.moveToThread(self.currPos_thread) # my_worker.finished.connect(self.xxx) #self.threadPool.append(my_thread) #self.my_worker = my_worker def connectStage(self): gcs = GCSDevice() try: gcs.InterfaceSetupDlg() msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText(gcs.qIDN()) msg.exec_() self.stage = gcs self.openStageBtn.setEnabled(False) except: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText('Could not connect stage') msg.exec_() def initStage(self): # TODO put this in thread and show egg clock if self.stage is not None: ## Create and display the splash screen #splash_pix = QPixmap('icons/piController.png') #splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) #splash.setMask(splash_pix.mask()) #splash.show() # TODO: give choice to select stage pitools.startup(self.stage, stages='M-112.1DG-NEW', refmode='FNL') #splash.close() # TODO: show dialog for waiting self.velocityLabel.setText('Velocity: {:f}mm/s'.format( self.stage.qVEL()['1'])) self.velocity.setValue(int(1000 * self.stage.qVEL()['1'])) self.stageConnected.emit() self._xAxeChanged() self.currentPos.setText('{:.7f}'.format(self.stage.qPOS()['1'])) self.__startCurrPosThr() self.stageRange = (self.stage.qTMN()['1'], self.stage.qTMX()['1']) self.scanStep.validator().setBottom(0) self.initStageBtn.setEnabled(False) else: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText('No stage connected') msg.exec_() def gotoPos_mm(self, x): '''Move stage to absolute position in mm''' if self.stageRange[0] <= x <= self.stageRange[1]: self.stage.MOV(self.stage.axes, x) while not pitools.ontarget(self.stage, '1')['1']: time.sleep(0.05) else: print('Requested postition', x, 'outside of range', self.stageRange) def gotoPos_fs(self, x): '''Move stage to absolute position in mm''' self.gotoPos_mm(self._calcAbsPos(x)) def moveRel_mm(self, x=0, sign=1): '''Moves stage relative to current position''' # TODO raise message if outside of range currPos = float(self.currentPos.text()) if self.stageRange[0] <= sign * x + currPos <= self.stageRange[1]: self.stage.MVR(self.stage.axes, sign * x) else: print('Requested postition', x, 'outside of range', self.stageRange) def moveRel_fs(self, x=0, sign=1): '''Moves stage relative to current position; expexts fs''' # TODO raise message if outside of range self.moveRel_mm(self._calcAbsPos(x), sign) def _calcAbsPos(self, x): '''Calculate absolute position on stage from given femtosecond value gets x in fs and returns position mm''' return (x * fsDelay) + self.offset def getDelays_mm(self): '''expects fs and returns mm''' von = self._calcAbsPos(float(self.scanFrom.text())) bis = self._calcAbsPos(float(self.scanTo.text())) #stepSize = int(self.scanStep.text()) stepSize = float(self.scanStep.text()) * fsDelay return np.linspace(von, bis, (np.abs(von) + bis) / stepSize) def getDelays_fs(self): '''expects fs and returns mm''' von = float(self.scanFrom.text()) bis = float(self.scanTo.text()) #stepSize = int(self.scanStep.text()) stepSize = float(self.scanStep.text()) return np.linspace(von, bis, (np.abs(von) + bis) / stepSize) def _xAxeChanged(self): self.xAxeChanged.emit(int(self.scanFrom.text()), int(self.scanTo.text())) def setCenter(self): '''Slot which recieves the new center position in fs and sets offset in mm ''' if self.newOff != 0: self.offset += (self.newOff * fsDelay) print('offset', self.offset, self.newOff) self.newOff = 0. def newOffset(self, newOffset): self.newOff = newOffset def _centerHere(self): self.offset = self.stage.qPOS()['1'] def __startCurrPosThr(self): self.stopCurrPosThr = False #self.currPosThr.start() self.currPos_worker.start.emit() def __stopCurrPosThr(self): self.stopCurrPosThr = True while (self.currPosThr.isRunning()): time.sleep(0.03) def __getCurrPos(self): oldPos = self.stage.qPOS()['1'] while not self.stopCurrPosThr: newPos = self.stage.qPOS()['1'] if oldPos != newPos: oldPos = newPos self.updateCurrPos.emit(newPos) time.sleep(0.5) def __updateCurrPos(self, newPos): self.currentPos.setText('{:.7f}'.format(newPos))
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)
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()
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)
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()))