class Ui_ChildWindow(object): def setupUi(self, MainWindow, params): #app = QtGui.QApplication([]) #self.win = QtGui.QMainWindow() self.area = DockArea() MainWindow.setCentralWidget(self.area) MainWindow.resize(500, 700) MainWindow.setWindowTitle('Action construct') self.seq_cntr = Dock("Sequence", size=(150, 200)) self.area.addDock(self.seq_cntr, 'left') ## first dock gets save/restore buttons self.t = ParameterTree() if params != None: self.p_child = Parameter.create(name='params', type='group', children=params) self.t.setParameters(self.p_child, showTop=False) self.t.setWindowTitle('pyqtgraph example: Parameter Tree') self.seq_cntr.addWidget(self.t) self.seq = pg.LayoutWidget() self.label = QtGui.QLabel("""Controls""") self.saveBtn = QtGui.QPushButton('Add Action') self.restoreBtn = QtGui.QPushButton('Modify table') self.restoreBtn.setEnabled(False) self.seq.addWidget(self.label, row=0, col=0) self.seq.addWidget(self.saveBtn, row=1, col=0) self.seq.addWidget(self.restoreBtn, row=2, col=0) self.seq_cntr.addWidget(self.seq)
class Ui_ChildWindow(object): def setupUi(self, MainWindow, params): #app = QtGui.QApplication([]) #self.win = QtGui.QMainWindow() self.area = DockArea() MainWindow.setCentralWidget(self.area) MainWindow.resize(500, 700) MainWindow.setWindowTitle('Action construct') self.seq_cntr = Dock("Sequence", size=(150,200)) self.area.addDock(self.seq_cntr, 'left') ## first dock gets save/restore buttons self.t = ParameterTree() if params != None: self.p_child = Parameter.create(name='params', type='group', children=params) self.t.setParameters(self.p_child, showTop=False) self.t.setWindowTitle('pyqtgraph example: Parameter Tree') self.seq_cntr.addWidget(self.t) self.seq = pg.LayoutWidget() self.label = QtGui.QLabel("""Controls""") self.saveBtn = QtGui.QPushButton('Add Action') self.restoreBtn = QtGui.QPushButton('Modify table') self.restoreBtn.setEnabled(False) self.seq.addWidget(self.label, row=0, col=0) self.seq.addWidget(self.saveBtn, row=1, col=0) self.seq.addWidget(self.restoreBtn, row=2, col=0) self.seq_cntr.addWidget(self.seq)
def start_gui(self): from PyQt5 import QtGui from PyQt5 import QtWidgets # import QApplication, QFileDialog app = QtWidgets.QApplication(sys.argv) self.parameters.param('Input', 'Select').sigActivated.connect(self.select_input_dir_gui) self.parameters.param('Make dir with image files').sigActivated.connect(self.make_dir_with_files) self.parameters.param("Make PDF's").sigActivated.connect(self.make_pdfs) self.parameters.param("Make PDF", "Automatic title recognition").sigActivated.connect(self.auto_split_file_names) t = ParameterTree() t.setParameters(self.parameters, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') # t.show() print("run scaffan") win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) # layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) # layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(800, 800) app.exec_()
def main(camera): app = Qt.QApplication([]) t = ParameterTree() t.resize(600, 800) t.show() def value_changed(param, value): try: setattr(camera, param.name(), value) except Exception as err: Qt.QMessageBox.critical(None, "Error setting {}".format(param.name()), repr(err)) def connect(param, slot): param.sigValueChanged.connect(slot) for child in param.children(): connect(child, slot) with camera: t.setWindowTitle(camera.device_info.GetFriendlyName()) data = parameter_dict(camera) # limits are dynamic (ex: max offset-x depends on current value # of width). strip_limits(data) p = Parameter.create(**data) t.setParameters(p, showTop=False) connect(p, value_changed) app.exec_()
class EyeTrackingExperimentWindow(SimpleExperimentWindow): """Window for controlling an experiment where the tail and the eyes of an embedded fish are tracked. Parameters ---------- Returns ------- """ def __init__(self, *args, **kwargs): self.camera_display = CameraEyesSelection( experiment=kwargs["experiment"]) self.camera_splitter = QSplitter(Qt.Horizontal) self.monitoring_widget = QWidget() self.monitoring_layout = QVBoxLayout() self.monitoring_widget.setLayout(self.monitoring_layout) # Stream plot: self.stream_plot = MultiStreamPlot(time_past=30) self.monitoring_layout.addWidget(self.stream_plot) # Tracking params button: self.button_tracking_params = QPushButton("Tracking params") self.button_tracking_params.clicked.connect( self.open_tracking_params_tree) self.monitoring_layout.addWidget(self.button_tracking_params) self.track_params_wnd = None # self.tracking_layout.addWidget(self.camera_display) # self.tracking_layout.addWidget(self.button_tracking_params) super().__init__(*args, **kwargs) def construct_ui(self): """ """ self.stream_plot.add_stream(self.experiment.data_acc, ["th_e0", "th_e1"]) self.experiment.gui_timer.timeout.connect(self.stream_plot.update) previous_widget = super().construct_ui() self.monitoring_layout.addWidget(previous_widget) self.monitoring_layout.setStretch(1, 1) self.monitoring_layout.setStretch(0, 1) self.camera_splitter.addWidget(self.camera_display) self.camera_splitter.addWidget(self.monitoring_widget) return self.camera_splitter def open_tracking_params_tree(self): """ """ self.track_params_wnd = ParameterTree() self.track_params_wnd.setParameters( self.experiment.tracking_method.params, showTop=False) self.track_params_wnd.setWindowTitle("Tracking data") self.track_params_wnd.show()
def do_stuff(self): p = Parameter.create(name='params', type='group', children=self.params) def change(param, changes): print("tree changes:") for param, change, data in changes: path = p.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') p.sigTreeStateChanged.connect(change) # create a parameter tree widget t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') # plot some data plot = pg.PlotWidget() n = 1000 xv = np.arange(n) yv = 1 * pg.gaussianFilter(np.random.random(size=n), 10) plot.plot(xv, yv, pen='r') # make a second plot plot2 = pg.PlotWidget() plot2.plot(xv, yv, pen='g') # set the layout of the widget layout = QtGui.QGridLayout() # layout.columnStretch(5) layout.setColumnStretch(2, 2) # NOTE: (widget, # y_row, x_row, y_span, x_span) # layout.addWidget(QtGui.QLabel("Data monitor thing"), 0, 0, 1, 2) layout.addWidget(t, 0, 0, 2, 1) layout.addWidget(plot, 0, 2) layout.addWidget(plot2, 1, 2) self.setLayout(layout) # test save/restore s = p.saveState() p.restoreState(s)
def valueChanging(param, value): # print("Value changing (not finalized): %s %s" % (param, value)) # Too lazy for recursion: for child in p.children(): child.sigValueChanging.connect(valueChanging) for ch2 in child.children(): ch2.sigValueChanging.connect(valueChanging) def save(): global state state = p.saveState() def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') t2 = ParameterTree() t2.setParameters(p, showTop=False) win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(800,800) ## test save/restore s = p.saveState() p.restoreState(s) ## Start Qt event loop unless running in interactive mode or using pyside. if __name__ == '__main__': import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()
class NetworkInterface(QWidget): def __init__(self, params): super().__init__() self.param = Parameter.create(name='params', type='group', children=params) self.tree = ParameterTree() self.tree.setParameters(self.param, showTop=False) self.tree.setWindowTitle('Network Interface') self.window = QWidget() self.layout = QGridLayout() self.window.setLayout(self.layout) l = QLabel("Network Interface") l.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) self.layout.addWidget(l) self.layout.addWidget(self.tree) self.window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.window.setGeometry(500, 800, 800, 500) def updataParameter(self, params, opt): self.param = Parameter.create(name='params', type='group', children=params) self.tree.setParameters(self.param, showTop=False) self.layout.addWidget(self.tree) if opt == 1: print('Please wait for a moment, I am working in progress') else: print('interface updated') QtWidgets.QApplication.processEvents() def closeEvent(self, closeEvent): reply = QtWidgets.QMessageBox.question( self, 'Warning', 'Are you sure to exit?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: QCloseEvent.accept() else: QCloseEvent.ignore()
class GuiMetadata(HasPyQtGraphParams): """General class for a group of metadata that can be controlled via a GUI. Parameters ---------- Returns ------- """ def __init__(self): super().__init__() self.protocol_params_tree = ParameterTree(showHeader=False) def get_param_dict(self): """ Return values of the parameters. Returns ------- OrderedDict with the params values """ return self.params.getValues() def show_metadata_gui(self): """ Create and return a ParameterTree window (documented `here <http://www.pyqtgraph.org/documentation/parametertree/index.html/>`_ ) Returns ------- ParameterTree object to control the metadata """ self.protocol_params_tree = ParameterTree(showHeader=False) self.protocol_params_tree.setParameters(self.params) self.protocol_params_tree.setWindowTitle("Metadata") self.protocol_params_tree.resize(450, 600) # TODO figure out this window return self.protocol_params_tree
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): # 'Super' is used to initialize the class from which this class # depends, in this case MainWindow depends on Qt.Widget class super(MainWindow, self).__init__() # buscar esto que son cosas de la ventana de la gui self.setFocusPolicy(Qt.Qt.WheelFocus) layout = Qt.QVBoxLayout(self) # Qt.QPushButton is used to generate a button in the GUI self.btnStart = Qt.QPushButton("Start Gen and Adq!") layout.addWidget(self.btnStart) self.btnStartSingleAdq = Qt.QPushButton("Single Adq!") layout.addWidget(self.btnStartSingleAdq) self.ResetGraph = Qt.QPushButton("Reset Graphics") layout.addWidget(self.ResetGraph) #Eliminar######################################## self.btnSaveData = Qt.QPushButton("Save Data") layout.addWidget(self.btnSaveData) ################################################# # Set threads as None self.threadGeneration = None self.threadPlotter = None self.threadPsdPlotter = None self.threadSave = None self.threadCharact = None # #############################Save############################## self.SaveStateParams = FileMod.SaveSateParameters( QTparent=self, name='FileState', title='Save/load config') # With this line, it is initize the group of parameters that are # going to be part of the full GUI self.Parameters = Parameter.create(name='params', type='group', children=(self.SaveStateParams, )) # #############################File############################## self.FileParams = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParams) # #############################Plot Parameters#### REVISARRRR self.PlotParams = TimePltPars(name='TimePlt', title='Time Plot Options') self.Parameters.addChild(self.PlotParams) self.PsdPlotParams = PSDPltPars(name='PSDPlt', title='PSD Plot Options') self.Parameters.addChild(self.PsdPlotParams) # #############################ASIC############################## self.ASICParams = ASICConfig.ASICParameters(QTparent=self, name='ASIC Configuration') self.Parameters.addChild(self.ASICParams) ##ASIC 2 Class if DEBUG == 0: self.ASIC_C = AS(DEBUG=1) self.ParamChange = 1 # #############################Sweep Config############################## self.SwParams = Charact.SweepsConfig(QTparent=self, name='Sweeps Configuration') self.Parameters.addChild(self.SwParams) # ################################EVENTS############################# # Connect event for managing event self.ASICParams.NewConf.connect(self.on_NewASICConf) self.PsdPlotParams.NewConf.connect(self.on_NewPSDConf) self.PlotParams.NewConf.connect(self.on_NewPlotConf) # Event for debug print of changes # self.Parameters.sigTreeStateChanged.connect(self.on_Params_changed) # First call of some events for initializations self.on_NewASICConf() # Event of main button start and stop self.ResetGraph.clicked.connect(self.on_ResetGraph) self.btnStart.clicked.connect(self.on_btnStart) #Boton adicional self.btnStartSingleAdq.clicked.connect(self.on_btnStartSingleAdq) self.btnSaveData.clicked.connect(self.on_btnSaveData) self.SwParams.param('SweepsConfig').param( 'Start/Stop Sweep').sigActivated.connect(self.on_Sweep_start) # self.SwParams.param('SweepsConfig').param('Pause Sweep').sigActivated.connect(self.on_Sweep_paused) self.ASICParams.param('Global_VREFE').param( 'Start/Stop Sweep').sigActivated.connect( self.on_VREF_E_Sweep_start) # ############################GuiConfiguration############################## # Is the same as before functions but for 'Parameters' variable, # which conatins all the trees of all the Gui, so on_Params_changed # will be execute for any change in the Gui self.Parameters.sigTreeStateChanged.connect(self.on_Params_changed) # EXPLICAR ESTO TAMBIEN QUE TIENE QUE VER CON LA GUI self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(550, 10, 500, 700) self.setWindowTitle('MainWindow') # ############################Changes Control############################## def on_Params_changed(self, param, changes): ''' This function is used to print in the consol the changes that have been done. ''' print("tree changes:") for param, change, data in changes: path = self.Parameters.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') #Flag self.ParamChange def on_NewASICConf(self): self.PlotParams.SetChannels(self.ASICParams.GetChannels()) self.PsdPlotParams.ChannelConf = self.PlotParams.ChannelConf nChannels = self.PlotParams.param('nChannels').value() self.PsdPlotParams.param('nChannels').setValue(nChannels) Fs = self.ASICParams.Fs print(Fs) nCols = self.ASICParams.nCols Fs = Fs / 2.0 / 32.0 / nCols self.PlotParams.param('Fs').setValue(Fs) self.PsdPlotParams.param('Fs').setValue(Fs) def on_NewPSDConf(self): if self.threadPsdPlotter is not None: nFFT = self.PsdPlotParams.param('nFFT').value() nAvg = self.PsdPlotParams.param('nAvg').value() self.threadPsdPlotter.InitBuffer(nFFT=nFFT, nAvg=nAvg) def on_NewPlotConf(self): if self.threadPlotter is not None: ViewTime = self.PlotParams.param('ViewTime').value() self.threadPlotter.SetViewTime(ViewTime) RefreshTime = self.PlotParams.param('RefreshTime').value() self.threadPlotter.SetRefreshTime(RefreshTime) def on_ResetGraph(self): if self.threadGeneration is None: return # Plot and PSD threads are stopped if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPsdPlotter is not None: self.threadPsdPlotter.stop() self.threadPsdPlotter = None if self.PlotParams.param('PlotEnable').value(): Pltkw = self.PlotParams.GetParams() self.threadPlotter = TimePlt(**Pltkw) self.threadPlotter.start() if self.PsdPlotParams.param('PlotEnable').value(): PSDKwargs = self.PsdPlotParams.GetParams() self.threadPsdPlotter = PSDPlt(**PSDKwargs) self.threadPsdPlotter.start() # ############################START############################## def on_btnStart(self): ''' This function is executed when the 'start' button is pressed. It is used to initialize the threads, emit signals and data that are necessary durint the execution of the program. Also in this function the different threads starts. ''' if self.threadGeneration is None: print('########## Starting Adquisition ##########') #Actualizacion de los parametros de configuracion DIC_C = self.ASICParams.GetGenParams() DIC_R = self.ASICParams.GetRowsParams() #Solo aplicar cambios si es necesario self.ASIC_C.Dict_To_InstructionSimple(DIC_C) self.ASIC_C.Dict_To_InstructionSimple(DIC_R) #Chapuza # self.threadGeneration = self.ASIC_C self.threadGeneration = AS_Thread( ASP=self.ASIC_C, nChannels=self.ASICParams.nChannels, nCols=self.ASICParams.nCols, DIC_C=DIC_C, DIC_R=DIC_R) #Runs completos self.ASIC_C.Runs_Completos = self.ASICParams.RunsCompletos self.ASIC_C.tInterrupt = 1000 self.threadGeneration.NewGenData.connect(self.on_NewSample) if self.FileParams.param('Enabled').value(): FilekwArgs = { 'FileName': self.FileParams.FilePath(), 'nChannels': self.ASICParams.nChannels, 'Fs': None, 'ChnNames': None, 'MaxSize': self.FileParams.param('MaxSize').value(), 'dtype': 'float', } self.threadSave = FileMod.DataSavingThread(**FilekwArgs) self.threadSave.start() #Reset Plots self.on_ResetGraph() # Start generation self.OldTime = time.time() self.threadGeneration.start() self.btnStart.setText("Stop Gen and Adq!") else: print('########## Stoping Adquisition ##########') #Pone el ASIC en Standby self.ASIC_C.StopRun() # Thread is terminated and set to None self.threadGeneration.NewGenData.disconnect() self.threadGeneration.terminate() self.threadGeneration = None # Plot and PSD threads are stopped if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPsdPlotter is not None: self.threadPsdPlotter.stop() self.threadPsdPlotter = None # Also save thread is stopped if self.threadSave is not None: self.threadSave.stop() self.threadSave = None # Button text is changed again self.btnStart.setText("Start Gen and Adq!") # ############################Single Adquisition Long############################## def on_btnStartSingleAdq(self): ''' This function is executed when the 'start' button is pressed. It is used to initialize the threads, emit signals and data that are necessary durint the execution of the program. Also in this function the different threads starts. ''' print('########## Starting single Adq ##########') if self.threadGeneration is None: #Actualizacion de los parametros de configuracion DIC_C = self.ASICParams.GetGenParams() DIC_R = self.ASICParams.GetRowsParams() #Chapuza self.threadGeneration = self.ASIC_C self.threadGeneration.Dict_To_InstructionSimple(DIC_C) self.threadGeneration.Dict_To_InstructionSimple(DIC_R) # self.ASIC_C.Dict_To_InstructionSimple(DIC_C) # self.ASIC_C.Dict_To_InstructionSimple(DIC_R) # #Short Run Adquisicion self.Error, self.Col, self.Sar_0, self.Sar_1, self.Sar_2, self.Sar_3 = self.ASIC_C.ReadAcqS( ) # self.Error,self.Col,self.Sar_0,self.Sar_1,self.Sar_2,self.Sar_3 = self.ASIC_C.ReadAcqL() Sar_0_I = 2.0 * (self.Sar_0 - (2**(13.0 - 1)) + 0.5) / 2**13.0 Sar_1_I = 2.0 * (self.Sar_1 - (2**(13.0 - 1)) + 0.5) / 2**13.0 Sar_2_I = 2.0 * (self.Sar_2 - (2**(13.0 - 1)) + 0.5) / 2**13.0 Sar_3_I = 2.0 * (self.Sar_3 - (2**(13.0 - 1)) + 0.5) / 2**13.0 # Sar_0_I = Sar_0_I/(4*25e3) # a[0] plt.figure(1001) plt.plot(Sar_0_I) plt.plot(Sar_1_I) plt.plot(Sar_2_I) plt.plot(Sar_3_I) #Pone el ASIC en Standby self.threadGeneration.StopRun() self.threadGeneration = None else: print('########## Stoping single Adq ##########') def on_NewSample(self): """To call when new data ready to read.""" Ts = time.time() - self.OldTime self.OldTime = time.time() # Debug print of interruption time print('Sample time', Ts) # print('Data ', self.threadGeneration.OutData) if self.threadPlotter is not None: self.threadPlotter.AddData(self.threadGeneration.OutData) if self.threadSave is not None: self.threadSave.AddData(self.threadGeneration.OutData) if self.threadPsdPlotter is not None: self.threadPsdPlotter.AddData(self.threadGeneration.OutData) if self.threadCharact is not None: self.threadCharact.AddData(self.threadGeneration.OutData) # #############################VREF_E GLOBAL ############################## def on_VREF_E_Sweep_start(self): Vmin = self.ASICParams.Vmin Vmax = self.ASICParams.Vmax Steps = self.ASICParams.NSweeps nChannels = self.ASICParams.nChannels nCols = self.ASICParams.nCols DIC_C = self.ASICParams.GetGenParams() VREF_E_G = self.ASIC_C.GlobalVREFE(Vmin, Vmax, Steps, nChannels, nCols, DIC_C) self.ASIC_C.StopRun() self.ASICParams.GenConfig.param('DAC E').setValue(VREF_E_G) # #############################START Sweep Acquisition #################### def on_Sweep_start(self): if self.threadGeneration is None: print('Sweep started') self.treepar.setParameters(self.Parameters, showTop=False) self.SweepsKwargs = self.SwParams.GetConfigSweepsParams() self.DcSaveKwargs = self.SwParams.GetSaveSweepsParams() self.VdSweepVals = self.SweepsKwargs['VdSweep'] self.VgSweepVals = self.SweepsKwargs['VgSweep'] self.ASICParams.GenConfig.param('DAC EL').setValue( 0.9 + self.VgSweepVals[0]) ####DESCOMENTAR self.ASICParams.GenConfig.param('DAC COL').setValue( 0.9 + self.VdSweepVals[0]) #Actualizacion de los parametros de configuracion DIC_C = self.ASICParams.GetGenParams() DIC_R = self.ASICParams.GetRowsParams() # print(DIC_C) self.threadGeneration = AS_Thread( ASP=self.ASIC_C, nChannels=self.ASICParams.nChannels, nCols=self.ASICParams.nCols, DIC_C=DIC_C, DIC_R=DIC_R) self.ASIC_C.Dict_To_InstructionSimple(DIC_C) self.ASIC_C.Dict_To_InstructionSimple(DIC_R) #Runs completos self.ASIC_C.Runs_Completos = self.ASICParams.RunsCompletos self.ASIC_C.tInterrupt = 1000 self.threadGeneration.NewGenData.connect(self.on_NewSample) self.threadGeneration.Lista = None #Reset Plots self.on_ResetGraph() self.threadCharact = Charact.StbDetThread( nChannels=self.ASICParams.nChannels, ChnName=self.ASICParams.GetChannels(), PlotterDemodKwargs=self.PsdPlotParams.GetParams(), **self.SweepsKwargs) self.threadCharact.NextVg.connect(self.on_NextVg) self.threadCharact.NextVd.connect(self.on_NextVd) self.threadCharact.CharactEnd.connect(self.on_CharactEnd) self.threadCharact.Timer.start(self.SweepsKwargs['TimeOut'] * 1000) self.threadCharact.start() # Start generation self.threadGeneration.start() self.OldTime = time.time() else: print('########## Stoping Adquisition ##########') #Pone el ASIC en Standby self.ASIC_C.StopRun() # Thread is terminated and set to None self.threadGeneration.NewGenData.disconnect() self.threadGeneration.terminate() self.threadGeneration = None # Plot and PSD threads are stopped if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPsdPlotter is not None: self.threadPsdPlotter.stop() self.threadPsdPlotter = None # Also save thread is stopped if self.threadSave is not None: self.threadSave.stop() self.threadSave = None # Button text is changed again if self.threadCharact is not None: self.threadCharact.NextVg.disconnect() self.threadCharact.NextVd.disconnect() self.threadCharact.CharactEnd.disconnect() self.threadCharact.stop() self.threadCharact = None def on_NextVg(self): print('HUEVO VGS ') while (self.threadGeneration.EndCap == 1): print("Esperando a que acabe de cojer datos...") # self.ASIC_C.StopRun() # # Thread is terminated and set to None # self.threadGeneration.NewGenData.disconnect() # self.threadGeneration.terminate() # self.threadGeneration = None DIC_C = {'DAC EL': 0.9 + self.threadCharact.NextVgs} ####DESCOMENTAR #Actualizacion de los parametros de configuracion # self.ASIC_C.Dict_To_InstructionSimple(DIC_C) ####DESCOMENTAR # self.threadGeneration = AS_Thread(ASP = self.ASIC_C,nChannels = self.ASICParams.nChannels,nCols = self.ASICParams.nCols,Scale = [2,2,2,2]) # self.threadGeneration.NewGenData.connect(self.on_NewSample) # self.threadGeneration.start() self.threadGeneration.Lista = DIC_C print('VG ', self.threadCharact.NextVgs) # self.threadCharact.Timer.start(self.SweepsKwargs['TimeOut']*1000) print('NEXT VGS SWEEP') def on_NextVd(self): while (self.threadGeneration.EndCap == 1): print("Esperando a que acabe de cojer datos...") # self.ASIC_C.StopRun() # Thread is terminated and set to None # self.threadGeneration.NewGenData.disconnect() # self.threadGeneration.terminate() # self.threadGeneration = None DIC_C = {'DAC COL': 0.9 + self.threadCharact.NextVds} #Actualizacion de los parametros de configuracion # self.ASIC_C.Dict_To_InstructionSimple(DIC_C) # self.threadGeneration = AS_Thread(ASP = self.ASIC_C,nChannels = self.ASICParams.nChannels,nCols = self.ASICParams.nCols,Scale = [2,2,2,2]) # self.threadGeneration.NewGenData.connect(self.on_NewSample) # self.threadGeneration.start() self.threadGeneration.Lista = DIC_C print('VD ', self.threadCharact.NextVds) # self.threadCharact.Timer.timeout.connect(self.threadCharact.printTime) # self.threadCharact.Timer.start(self.SweepsKwargs['TimeOut']*1000) def on_CharactEnd(self): while (self.threadGeneration.EndCap == 1): print("Esperando a que acabe de cojer datos...") #Pone el ASIC en Standby self.threadGeneration.EndCap = 2 self.ASIC_C.StopRun() # Thread is terminated and set to None self.threadGeneration.NewGenData.disconnect() self.threadGeneration.terminate() self.threadGeneration = None print('END Charact') self.threadCharact.NextVg.disconnect() self.threadCharact.NextVd.disconnect() self.threadCharact.CharactEnd.disconnect() CharactDCDict = self.threadCharact.DCDict CharactACDict = self.threadCharact.ACDict self.threadCharact.SaveDCAC.SaveDicts(Dcdict=CharactDCDict, Acdict=CharactACDict, **self.DcSaveKwargs) # Plot and PSD threads are stopped if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPsdPlotter is not None: self.threadPsdPlotter.stop() self.threadPsdPlotter = None # Also save thread is stopped if self.threadSave is not None: self.threadSave.stop() self.threadSave = None # Button text is changed again if self.threadCharact is not None: self.threadCharact.stop() self.threadCharact = None ###########ELIMINAR def on_btnSaveData(self): print("SAVING DATA") print("Len Sar 0", len(self.Sar_0)) print("Len Sar 1", len(self.Sar_1)) print("Len Sar 2", len(self.Sar_2)) print("Len Sar 3", len(self.Sar_3)) letra = '2000504_Sar_CDS_999999999' path_f = "/home/jcisneros/Downloads/DAta_rouleta" file_name = "SAR_0_AS2t" + letra + ".txt" self.ASIC_C.Gravar_M_Conversion(path=path_f, filename=file_name, Data=self.Sar_0, Limite=len(self.Sar_0), Conversion=1) file_name = "SAR_1_AS2t" + letra + ".txt" self.ASIC_C.Gravar_M_Conversion(path=path_f, filename=file_name, Data=self.Sar_1, Limite=len(self.Sar_1), Conversion=1) file_name = "SAR_2_AS2t" + letra + ".txt" self.ASIC_C.Gravar_M_Conversion(path=path_f, filename=file_name, Data=self.Sar_2, Limite=len(self.Sar_2), Conversion=1) file_name = "SAR_3_AS2t" + letra + ".txt" self.ASIC_C.Gravar_M_Conversion(path=path_f, filename=file_name, Data=self.Sar_3, Limite=len(self.Sar_3), Conversion=1) print("END SAVING DATA")
'name': 'ADD SINGLE', 'type': 'action' }, { 'name': 'REMOVE SINGLE', 'type': 'action' }, { 'name': 'SAVE OBJECT', 'type': 'action' }] pars_action = Parameter.create(name='params_action', type='group', children=params_action) t_action.setParameters(pars_action, showTop=False) t_action.setWindowTitle('Parameter Action') def reset_button(): global mode mode = "reset" p2.setTitle("mode: %s" % (mode)) #clear the upper right image zeros = np.asarray([[0] * 80 for _ in range(60)]) img2.setImage(make_color_img(zeros), autoLevels=False) draw_contours() pars.param('RESET').sigActivated.connect(reset_button)
class RTSmainView(mainViewBase,mainViewForm): def __init__(self, parent = None): super().__init__() self.params_filename = "params.dat" self.loaded_data = None self.parameters = None self.setupUi() self.setupParameterTree() #self.timetrace_filename = "" settings = QtCore.QSettings("foo","foo") self.timetrace_filename = settings.value('filename', type=str)#.toString() if self.timetrace_filename: self.load_data(self.timetrace_filename) def setupUi(self): super().setupUi(self) self.plot1 = self.ui_plot_area.addPlot(row=1, col=0) self.plot2 = self.ui_plot_area.addPlot(row=2, col=0, colspan =2) self.histogram_plot = self.ui_plot_area.addPlot(row = 1, col = 1) self.label = pg.LabelItem(justify='right') self.region = pg.LinearRegionItem() self.region.setZValue(10) self.region.sigRegionChanged.connect(self.update) ## Add the LinearRegionItem to the ViewBox, but tell the ViewBox to exclude this ## item when doing auto-range calculations. self.plot2.addItem(self.region, ignoreBounds=True) self.plot1.setAutoVisible(y=True) self.general_curve = self.plot2.plot(pen = pg.mkColor("g")) self.general_curve.setVisible(True) self.analysis_curve = self.plot1.plot(pen = pg.mkColor("y")) self.analysis_curve.setVisible(True) self.histogram_curve = self.histogram_plot.plot(pen = pg.mkColor("b"), fillLevel=0, fillBrush=(255,255,255,30)) self.histogram_curve.setVisible(True) self.rts_curve = self.plot1.plot(pen = pg.mkPen("r", width = 3)) #pg.mkColor("r"),width = 3) self.rts_curve.setVisible(True) self.rts_curve.setZValue(100) #self.plot1.addItem(pg.MultiRectROI([[0, 0], [20,0 ], [40, 0]], width = 1e-06)) #roi = pg.MultiRectROI(, width=5, pen=(2,9)) #self.plot1.addItem(roi) print("init") def getDefaultParams(self): return [ {'name': 'Automated RTS recognition', 'type': 'group', 'children': [ {'name': 'Error', 'type': 'float', 'value': 1e-06}, {'name': 'Weights', 'type': 'str', 'value': '2'} #WeightParamGroup(name="Weights", children=[ #]) ]}, {'name':'Window', 'type': 'int', 'value':10}, {'name': 'Filtering', 'type': 'group', 'children':[ {'name':'Filter design', 'type':'list', 'values': {"Butterworth":0, "Chebyshev I":1, "Chebyshev II":2, "Elliptic":3, "Bessel":4 }}, {'name':'Order', 'type': 'int', 'value': 1}, {'name':'Type', 'type':'list', 'values': {"lowpass":0, "highpass":1 }}, {'name':'Frequency','type': 'float', 'value':100.0}, {'name':'Apply', 'type':'action'} ]} ] def save_state(self, filename,state): """Save a tree as a pickle file """ with open(filename, 'wb') as fid: pickle.dump(state,fid) def load_state(self, filename): """Load a tree state to a pickle file """ try: with open(filename, 'rb') as fid: data = pickle.load(fid) return data except FileNotFoundError as e: print("File Not Found") return None def setupParameterTree(self): self.param_tree = ParameterTree() self.param_tree.setWindowTitle('pyqtgraph example: Parameter Tree') #self.param_tree.setFixedWidth(300) self.parameterTreeLayout.addWidget(self.param_tree) self.parameterTreeLayout.setSizes([500,150]) #self.parameterTreeLayour. self.parameters = Parameter.create(name='params', type='group') params = self.getDefaultParams() self.parameters.addChildren(params) state = self.load_state(self.params_filename) if state: self.parameters.restoreState(state) #else: #params = self.getDefaultParams() #self.parameters.addChildren(params) self.parameters.sigTreeStateChanged.connect(self.action_signaled) self.param_tree.setParameters(self.parameters, showTop=False) def action_signaled(self, *args, **kwargs): print(args) print(kwargs) def closeEvent(self,event): print("closing") settings = QtCore.QSettings("foo","foo") if self.timetrace_filename: settings.setValue("filename", self.timetrace_filename) if self.parameters: self.save_state(self.params_filename, self.parameters.saveState()) def update(self): minX, maxX = self.region.getRegion() self.plot1.setXRange(minX, maxX, padding=0) region_data = self.loaded_data.loc[lambda df: (df.time > minX) & (df.time < maxX),:] time = region_data.time data = region_data.data hist, bin_edges = np.histogram(data, bins = 'rice') #bins = 'auto') bin_centers = 0.5*(bin_edges[1:]+bin_edges[:-1]) #0.5*(x[1:] + x[:-1]) self.histogram_curve.setData(bin_centers, hist) print("data points selected: {0}".format(len(time))) #rts_values = self.calc_levels(data) #self.rts_curve.setData(time, rts_values) @QtCore.pyqtSlot() def on_actionConvolve_triggered(self): print("convolution") minX, maxX = self.region.getRegion() region_data = self.loaded_data.loc[lambda df: (df.time > minX) & (df.time < maxX),:] time = region_data.time.values data = region_data.data.values win_size = self.parameters['Window'] win = self.generate_window(win_size) #signal.hann(win_size) pg.plot(win, title = "Window size: {0}".format(win_size)) #filtered = self.fit_using_pearson(data,win) #fit_using_pearson mean_value = np.mean(data) std = np.std(data) signal_to_noise = mean_value / std print("MEAN = {0}".format(mean_value)) print("STD = {0}".format(std)) print("SNR = {0}".format(signal_to_noise)) filtered = signal.convolve(data,win, mode='same')/sum(win) fourier_filter(data, time[1]-time[0]) #pearsonr, p_val = stats.pearsonr(data, filtered) #print("PearsonR = {0}".format(pearsonr)) #optimal_wnd_size, pearsonr = self.fit_data_with_pulses(data, [3,5,10,15,20,25,30,50,100,200]) #print("STD = {0}".format(std)) #print("wnd_size = {0}".format(optimal_wnd_size)) #win = signal.hann(optimal_wnd_size) #filtered = signal.convolve(data,win, mode='same')/sum(win) #filtered = data - filtered self.rts_curve.setData(time,filtered) def generate_window(self, wnd_size, front_size = 3): #wnd = np.hstack((np.zeros(wnd_size),np.ones(wnd_size))) wnd = signal.hann(2*front_size) wnd = np.insert(wnd,front_size,signal.boxcar(wnd_size)) wnd = np.insert(np.zeros(2*front_size),front_size, wnd) return wnd def fit_using_pearson(self, data, wnd): wnd_size = len(wnd) half_wnd_size = wnd_size/2 data_size = len(data) result_size = data_size - wnd_size result = np.zeros(data_size, dtype = np.float) for i in range(result_size): pearsonr,p_val =stats.pearsonr(data[i:i+wnd_size], wnd) result[i+half_wnd_size] = pearsonr * 1e-04 return result def fit_data_with_pulses(self, data, wnd_length_arr:list): #current_std = 0 current_pearsonr_to_one_dist = 1 current_wnd_len = None for i, wnd_size in enumerate(wnd_length_arr): wnd = self.generate_window(wnd_size) #signal.hann(wnd_size) print(wnd) #filtered = data - signal.convolve(data,wnd, mode='same')/sum(wnd) #std = np.std(filtered) pg.plot(wnd, title = "Window size: {0}".format(wnd_size)) filtered = signal.convolve(data,wnd, mode='same')/sum(wnd) pearsonr, p_val = stats.pearsonr(data, filtered) dist = 1 - pearsonr print("PearsonR = {0}".format(pearsonr)) print("wnd_size = {0}".format(wnd_size)) if i == 0: #current_std = std current_pearsonr_to_one_dist = dist current_wnd_len = wnd_size elif dist < current_pearsonr_to_one_dist: current_pearsonr_to_one_dist = dist current_wnd_len = wnd_size return (current_wnd_len, current_pearsonr_to_one_dist) @QtCore.pyqtSlot() def on_actionSelectedArea_triggered(self): minX, maxX = self.region.getRegion() region_data = self.loaded_data.loc[lambda df: (df.time > minX) & (df.time < maxX),:] time = region_data.time.values data = region_data.data.values #weights = self.parameters.va weights = list(map(float, self.parameters["Automated RTS recognition","Weights"].split(';')))#.items() error = self.parameters["Automated RTS recognition","Error"] rts_values = self.calc_levels(data, weights, error) self.rts_curve.setData(time,rts_values) @QtCore.pyqtSlot() def on_actionFull_Set_triggered(self): time = self.loaded_data.time.values data = self.loaded_data.data.values rts_values = self.calc_levels(data) self.rts_curve.setData(time,rts_values) @QtCore.pyqtSlot() def on_actionOpen_triggered(self): print("opening") print("Select folder") self.timetrace_filename = os.path.abspath(QtGui.QFileDialog.getOpenFileName(self,caption="Select File"))#, directory = self._settings.working_directory)) msg = QtGui.QMessageBox() msg.setIcon(QtGui.QMessageBox.Information) msg.setText("This is a message box") msg.setInformativeText("This is additional information") msg.setWindowTitle("MessageBox demo") msg.setDetailedText(self.timetrace_filename) msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) retval = msg.exec_() if retval: self.load_data(self.timetrace_filename) def load_data(self, filename): print("loading file: {0}".format(filename)) try: self.loaded_data = pd.read_csv(filename, delimiter = "\t", names=["time", "data"]) time = self.loaded_data.time #["time"] rts = self.generate_rts(len(self.loaded_data.index), 100, time[1], 5e-05) rts2 = self.generate_rts(len(self.loaded_data.index), 10, time[1], 5e-06) self.loaded_data.data = self.loaded_data.data + rts# + rts2 data = self.loaded_data.data #["data"] #time,data = np.loadtxt(filename).T self.general_curve.setData(time,data) self.analysis_curve.setData(time,data) self.update() except Exception as e: print("failed to load data") def generate_rts(self, nelem, k,dt, amplitude = 1): k = float(k) ra = np.random.rand(nelem) # exponentially distributed jumps: t = np.log(1./ra)/k tr = np.floor(t/dt) x = [] s = amplitude ones = np.ones(len(tr)) ones[::2] = -1 ones = ones * s arr =np.vstack((ones, tr)).T #np.apply_along_axis(generate_arr, 1, arr) result = np.zeros(nelem) current_idx = 0 for val, n in arr: next_idx = current_idx+int(n) result[current_idx: next_idx] = val current_idx = next_idx return result def calc_levels(self,current_arr, weights= [1,0.7,0.4], error = 1e-06): L = len(current_arr) result = np.zeros(L) r_weights = weights #[1,0.7,0.4]#,0.8,0.7] l_weights = r_weights.reverse() N_half_wnd = len(r_weights) sigma = error left_avg = np.average(current_arr[0:N_half_wnd]) right_arv = 0 prev_val = 0 result[:N_half_wnd] = left_avg ## prev_time = 0 ## time_counter = 0 for i in range(N_half_wnd,L-N_half_wnd): left_avg = np.average(current_arr[i-N_half_wnd:i],weights=l_weights) right_avg= np.average(current_arr[i:i+N_half_wnd],weights=r_weights) diff = right_avg - left_avg abs_diff = abs(diff) if abs_diff > sigma or abs(right_avg - prev_val) > sigma: ## if time_counter >1: ## amplitude_time_list.append([prev_val,prev_time]) prev_val = right_avg ## prev_time =0 ## time_counter =0 result[i] = prev_val ## prev_time += dt ## time_counter += 1 ## print(i) result[-N_half_wnd:] = prev_val return result
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): super(MainWindow, self).__init__() self.threadAcq = None self.threadSave = None self.threadPlotter = None self.threadPSDPlotter = None self.threadPlotterRaw = None layout = Qt.QVBoxLayout(self) self.btnAcq = Qt.QPushButton("Start Acq!") layout.addWidget(self.btnAcq) self.ResetGraph = Qt.QPushButton("Reset Graphics") layout.addWidget(self.ResetGraph) self.SamplingPar = AcqMod.SampSetParam(name='SampSettingConf') self.Parameters = Parameter.create(name='App Parameters', type='group', children=(self.SamplingPar, )) self.SamplingPar.NewConf.connect(self.on_NewConf) self.SamplingPar.Fs.sigValueChanged.connect(self.on_FsChanged) self.SamplingPar.FsxCh.sigValueChanged.connect(self.on_FsxChChanged) self.SamplingPar.Vds.sigValueChanged.connect(self.on_BiasChanged) self.SamplingPar.Vgs.sigValueChanged.connect(self.on_BiasChanged) self.PlotParams = TimePltPars(name='TimePlt', title='Time Plot Options') self.PlotParams.NewConf.connect(self.on_NewPlotConf) self.Parameters.addChild(self.PlotParams) self.RawPlotParams = TimePltPars(name='RawPlot') self.Parameters.addChild(self.RawPlotParams) self.PsdPlotParams = PSDPltPars(name='PSDPlt', title='PSD Plot Options') self.Parameters.addChild(self.PsdPlotParams) self.PsdPlotParams.NewConf.connect(self.on_NewPSDConf) self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(650, 20, 400, 800) self.setWindowTitle('MainWindow') self.btnAcq.clicked.connect(self.on_btnStart) self.ResetGraph.clicked.connect(self.on_ResetGraph) self.FileParameters = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParameters) self.ConfigParameters = FileMod.SaveSateParameters( QTparent=self, name='Configuration File') self.Parameters.addChild(self.ConfigParameters) self.on_FsChanged() self.on_FsxChChanged() self.on_NewConf() def on_BiasChanged(self): if self.threadAcq: Vgs = self.SamplingPar.Vgs.value() Vds = self.SamplingPar.Vds.value() Ao2 = None Ao3 = None if self.SamplingPar.Ao2: Ao2 = self.SamplingPar.Ao2.value() if self.SamplingPar.Ao3: Ao3 = self.SamplingPar.Ao3.value() self.threadAcq.DaqInterface.SetBias(Vgs=Vgs, Vds=Vds, ChAo2=Ao2, ChAo3=Ao3) def on_FsChanged(self): self.RawPlotParams.param('Fs').setValue(self.SamplingPar.Fs.value()) def on_FsxChChanged(self): print('FSXCH', self.SamplingPar.FsxCh.value()) self.PlotParams.param('Fs').setValue(self.SamplingPar.FsxCh.value()) self.PsdPlotParams.param('Fs').setValue(self.SamplingPar.FsxCh.value()) def on_NewPSDConf(self): if self.threadPSDPlotter is not None: nFFT = self.PsdPlotParams.param('nFFT').value() nAvg = self.PsdPlotParams.param('nAvg').value() self.threadPSDPlotter.InitBuffer(nFFT=nFFT, nAvg=nAvg) def on_NewConf(self): print('NewConf') self.PlotParams.SetChannels(self.SamplingPar.GetChannelsNames()) self.RawPlotParams.SetChannels(self.SamplingPar.GetRowNames()) self.PsdPlotParams.ChannelConf = self.PlotParams.ChannelConf nChannels = self.PlotParams.param('nChannels').value() self.PsdPlotParams.param('nChannels').setValue(nChannels) if self.SamplingPar.Ao2: self.SamplingPar.Ao2.sigValueChanged.connect(self.on_BiasChanged) if self.SamplingPar.Ao3: self.SamplingPar.Ao3.sigValueChanged.connect(self.on_BiasChanged) def on_NewPlotConf(self): if self.threadPlotter is not None: ViewTime = self.PlotParams.param('ViewTime').value() self.threadPlotter.SetViewTime(ViewTime) RefreshTime = self.PlotParams.param('RefreshTime').value() self.threadPlotter.SetRefreshTime(RefreshTime) def on_ResetGraph(self): if self.threadAcq is None: return # Plot and PSD threads are stopped if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPSDPlotter is not None: self.threadPSDPlotter.stop() self.threadPSDPlotter = None if self.threadPlotterRaw is not None: self.threadPlotterRaw.stop() self.threadPlotterRaw = None if self.PlotParams.param('PlotEnable').value(): Pltkw = self.PlotParams.GetParams() self.threadPlotter = TimePlt(**Pltkw) self.threadPlotter.start() if self.PsdPlotParams.param('PlotEnable').value(): PSDKwargs = self.PsdPlotParams.GetParams() self.threadPSDPlotter = PSDPlt(**PSDKwargs) self.threadPSDPlotter.start() if self.RawPlotParams.param('PlotEnable').value(): RwPltkw = self.RawPlotParams.GetParams() self.threadPlotterRaw = TimePlt(**RwPltkw) self.threadPlotterRaw.start() def on_btnStart(self): if self.threadAcq is None: GenKwargs = self.SamplingPar.GetSampKwargs() GenChanKwargs = self.SamplingPar.GetChannelsConfigKwargs() AvgIndex = self.SamplingPar.SampSet.param('nAvg').value() self.threadAcq = AcqMod.DataAcquisitionThread( ChannelsConfigKW=GenChanKwargs, SampKw=GenKwargs, AvgIndex=AvgIndex, ) self.threadAcq.NewMuxData.connect(self.on_NewSample) self.threadAcq.start() PlotterRawKwargs = self.RawPlotParams.GetParams() print(PlotterRawKwargs['nChannels']) FileName = self.FileParameters.FilePath() print('Filename', FileName) if FileName == '': print('No file') else: if os.path.isfile(FileName): print('Remove File') os.remove(FileName) MaxSize = self.FileParameters.param('MaxSize').value() self.threadSave = FileMod.DataSavingThread( FileName=FileName, nChannels=PlotterRawKwargs['nChannels'], MaxSize=MaxSize) self.threadSave.start() self.on_ResetGraph() self.btnAcq.setText("Stop Gen") self.OldTime = time.time() self.Tss = [] else: self.threadAcq.DaqInterface.Stop() self.threadAcq = None if self.threadSave is not None: self.threadSave.terminate() self.threadSave = None if self.PlotParams.param('PlotEnable').value(): self.threadPlotter.terminate() self.threadPlotter = None if self.threadPSDPlotter is not None: self.threadPSDPlotter.stop() self.threadPSDPlotter = None if self.threadPlotterRaw is not None: self.threadPlotterRaw.stop() self.threadPlotterRaw = None self.btnAcq.setText("Start Gen") def on_NewSample(self): ''' Visualization of streaming data-WorkThread. ''' Ts = time.time() - self.OldTime self.Tss.append(Ts) self.OldTime = time.time() if self.threadSave is not None: self.threadSave.AddData(self.threadAcq.aiData.transpose()) if self.threadPlotter is not None: self.threadPlotter.AddData(self.threadAcq.OutData.transpose()) if self.threadPSDPlotter is not None: self.threadPSDPlotter.AddData(self.threadAcq.OutData.transpose()) if self.threadPlotterRaw is not None: self.threadPlotterRaw.AddData(self.threadAcq.aiData.transpose())
global state state = p.saveState() def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') t2 = ParameterTree() t2.setParameters(p, showTop=False) win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(800,800) ## test save/restore s = p.saveState() p.restoreState(s)
def __init__(self): #========================================== super(GUIMainWindow, self).__init__() # CHANGE HERE ------------------------------------------------- # ------------------------------------------------------------- area = DockArea() self.setCentralWidget(area) self.resize(1280, 800) self.setWindowTitle('Demo: How to use HARP with Python') ## Create docks, place them into the window one at a time. ## Note that size arguments are only a suggestion; docks will still have to ## fill the entire dock area and obey the limits of their internal widgets. d1 = Dock("Control", size=(300,200)) ## give this dock the minimum possible size d2 = Dock("Description", size=(300,800)) d31 = Dock("INTRA frame - Prediction Units", size=(500,300)) d32 = Dock("INTER frame - Prediction Units", size=(500,300)) #d33 = Dock("Dock3 - Transform Units", size=(500,300)) d41 = Dock("Frame Difference ", size=(100,100)) d42 = Dock("Current Frame ", size=(100,100)) d51 = Dock("CU Depths", size=(200,100)) d52 = Dock("MVs X Component", size=(200,100)) d53 = Dock("MVs Y Component", size=(200,100)) area.addDock(d2, 'left') ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) area.addDock(d1, 'bottom', d2) ## place d2 at right edge of dock area area.addDock(d31, 'right') area.addDock(d32, 'bottom', d31) #area.addDock(d33, 'bottom', d32) area.addDock(d41, 'right') area.addDock(d51, 'bottom', d41) area.addDock(d42, 'right', d41) area.addDock(d52, 'right', d51) area.addDock(d53, 'right', d52) #========================================== def dock_ImageItem(self, Dock): #========================================== pgGLWidget = pg.GraphicsLayoutWidget() ViewBox = pgGLWidget.addViewBox(invertY = True) #ViewBox.setBackgroundColor((255,255,255)) ViewBox.setAspectLocked(True) pgImageItem = pg.ImageItem(border='w') ViewBox.addItem(pgImageItem) Dock.addWidget(pgGLWidget) return pgImageItem #========================================== def dock_CurveItem(self, Dock, Title, LabelX, LabelY): #========================================== pgGWindow= pg.GraphicsLayoutWidget() pgPlot = pgGWindow.addPlot(title=Title) x =[0,0,0] y = [0,0] pgCurveItem = pg.PlotCurveItem(x, y, stepMode=True, fillLevel=0, brush=(0, 255, 0, 80)) pgPlot.addItem(pgCurveItem) pgPlot.setLabel('bottom', LabelX) pgPlot.setLabel('left', LabelY) Dock.addWidget(pgGWindow) return pgCurveItem self.ImageItem_d2 = dock_ImageItem(self, d2) self.ImageItem_d31 = dock_ImageItem(self, d31) self.ImageItem_d32 = dock_ImageItem(self, d32) self.ImageItem_d41 = dock_ImageItem(self, d41) self.ImageItem_d42 = dock_ImageItem(self, d42) self.CurveItem_d51 = dock_CurveItem(self, d51, "CU Depths", "CU Depth", "Number of Occurences") self.CurveItem_d52 = dock_CurveItem(self, d52, "MVs X Component", "Magnitude", "Number of Occurences") self.CurveItem_d53 = dock_CurveItem(self, d53, "MVs Y Component", "Magnitude", "Number of Occurences") params = [ {'name': 'Basic settings', 'type': 'group', 'children': [ {'name': 'QP', 'type': 'int', 'value': 30}, {'name': 'x265', 'type': 'bool', 'value': True}, {'name': 'Show CUs', 'type': 'bool', 'value': True}, {'name': 'Show PUs', 'type': 'bool', 'value': True}, {'name': 'Show Modes', 'type': 'bool', 'value': True}, ]}, ] ## Create tree of Parameter objects p = Parameter.create(name='params', type='group', children=params, readonly=False, enabled=True) t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') self.p = p d1.addWidget(t) MyWorkThread = WorkThread(self) MyWorkThread.start() Description = readImg(ProjectDir + "/Various/Resources/Special/LMS_Demo.png") Description = cv2.transpose(cv2.cvtColor(Description, cv2.COLOR_BGR2RGB)) self.ImageItem_d2.setImage(Description, autoDownsample=True, border=(255,255,255) )
class ProjectSettingsDialog(QtGui.QDialog): path2key=dict() def __init__(self, parent = None, savedstate=None): global SETTINGS super(ProjectSettingsDialog, self).__init__(parent) self.setWindowTitle("Application Settings") layout = QtGui.QVBoxLayout(self) self.setLayout(layout) if savedstate: for key,val in savedstate.items(): if flattenned_settings_dict.get(key): flattenned_settings_dict[key]['value'] = val #self._settings.restoreState(savedstate) self.initKeyParamMapping() self._settings = Parameter.create(name='params', type='group', children=settings_params) # Holds settings keys that have changed by the user when the # dialog is closed. Used to update any needed gui values.. self._updated_settings={} self._invalid_settings={} self._settings.sigTreeStateChanged.connect(self.handleSettingChange) self.initSettingsValues() self._settings.param('Default Settings', 'Save As').sigActivated.connect(self.saveToFile) self._settings.param('Default Settings', 'Load').sigActivated.connect(self.loadFromFile) self.ptree = ParameterTree() self.ptree.setParameters(self._settings, showTop=False) self.ptree.setWindowTitle('MarkWrite Application Settings') layout.addWidget(self.ptree) # OK and Cancel buttons self.buttons = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) layout.addWidget(self.buttons) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) wscreen = QtGui.QDesktopWidget().screenGeometry() if savedstate and savedstate.get(SETTINGS_DIALOG_SIZE_SETTING): w, h = savedstate.get(SETTINGS_DIALOG_SIZE_SETTING) self.resize(w, h) SETTINGS[SETTINGS_DIALOG_SIZE_SETTING]=(w, h) if savedstate.get(APP_WIN_SIZE_SETTING): SETTINGS[APP_WIN_SIZE_SETTING]=savedstate.get(APP_WIN_SIZE_SETTING) else: if parent: wscreen = QtGui.QDesktopWidget().screenGeometry(parent) self.resize(min(500,int(wscreen.width()*.66)),min(700,int(wscreen.height()*.66))) # center dialog on same screen as is being used by markwrite app. qr = self.frameGeometry() cp = wscreen.center() qr.moveCenter(cp) self.move(qr.topLeft()) def saveToFile(self): from markwrite.gui.dialogs import fileSaveDlg, ErrorDialog from markwrite import writePickle, current_settings_path save_to_path=fileSaveDlg( initFilePath=current_settings_path, initFileName=u"markwrite_settings.pkl", prompt=u"Save MarkWrite Settings", allowed="Python Pickle file (*.pkl)", parent=self) if save_to_path: import os from markwrite import default_settings_file_name, current_settings_file_name ff, fn = os.path.split(save_to_path) if fn in [default_settings_file_name, current_settings_file_name]: ErrorDialog.info_text = u"%s a is reserved file name." \ u" Save again using a different name."%(fn) ErrorDialog().display() else: writePickle(ff, fn, SETTINGS) def loadFromFile(self): global settings from markwrite.gui.dialogs import fileOpenDlg from markwrite import appdirs as mwappdirs from markwrite import readPickle, writePickle from markwrite import current_settings_file_name, current_settings_path if self.parent: mws_file = fileOpenDlg(current_settings_path, None, "Select MarkWrite Settings File", "Python Pickle file (*.pkl)", False) if mws_file: import os ff, fn = os.path.split(mws_file[0]) mw_setting = readPickle(ff, fn) _ = ProjectSettingsDialog(savedstate=mw_setting) self.parent().updateApplicationFromSettings(mw_setting, mw_setting) writePickle(current_settings_path,current_settings_file_name, SETTINGS) def initKeyParamMapping(self): if len(self.path2key)==0: def replaceGroupKeys(paramlist, parent_path=[]): for i,p in enumerate(paramlist): if isinstance(p,basestring): pdict=flattenned_settings_dict[p] paramlist[i]=pdict self.path2key['.'.join(parent_path+[pdict['name'],])]=p elif isinstance(p,dict): replaceGroupKeys(p.get('children'),parent_path+[p.get('name'),]) replaceGroupKeys(settings_params) def initSettingsValues(self, pgroup=None): global SETTINGS if pgroup is None: pgroup = self._settings for child in pgroup.children(): if child.hasChildren(): self.initSettingsValues(child) else: path = self._settings.childPath(child) if path is not None: childName = '.'.join(path) else: childName = child.name() if self.path2key.has_key(childName): SETTINGS[self.path2key[childName]]=child.value() child.orgvalue = child.value() ## If anything changes in the tree def handleSettingChange(self, param, changes): global SETTINGS for param, change, data in changes: path = self._settings.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() if change == 'value': setting_key = self.path2key[childName] if setting_key.startswith('kbshortcut_'): qks=QtGui.QKeySequence(data) if (len(data)>0 and qks.isEmpty()) or qks.toString() in SETTINGS.values(): self._invalid_settings[setting_key]=param continue else: data = u''+qks.toString() SETTINGS[setting_key]=data self._updated_settings[setting_key] = data param.orgvalue=data def resizeEvent(self, event): global SETTINGS w, h = self.size().width(), self.size().height() SETTINGS[SETTINGS_DIALOG_SIZE_SETTING] = (w, h) self._updated_settings[SETTINGS_DIALOG_SIZE_SETTING] = (w, h) return super(QtGui.QDialog, self).resizeEvent(event) @staticmethod def getProjectSettings(parent = None, usersettings = None): if usersettings is None: usersettings=SETTINGS dialog = ProjectSettingsDialog(parent, usersettings) result = dialog.exec_() for k, v in dialog._invalid_settings.items(): v.setValue(v.orgvalue) dialog._invalid_settings.clear() usersettings=dialog._settings.saveState() return dialog._updated_settings,SETTINGS, usersettings, result == QtGui.QDialog.Accepted
class CrystalIndexing(object): def __init__(self, parent = None): self.parent = parent ## Dock: Indexing self.dock = Dock("Indexing", size=(1, 1)) self.win = ParameterTree() self.win.setWindowTitle('Indexing') self.dock.addWidget(self.win) self.winL = pg.LayoutWidget() self.launchIndexBtn = QtGui.QPushButton('Launch indexing') self.winL.addWidget(self.launchIndexBtn, row=0, col=0) self.synchBtn = QtGui.QPushButton('Deploy CrystFEL geometry') self.winL.addWidget(self.synchBtn, row=1, col=0) self.dock.addWidget(self.winL) self.index_grp = 'Crystal indexing' self.index_on_str = 'Indexing on' self.index_geom_str = 'CrystFEL geometry' self.index_peakMethod_str = 'Peak method' self.index_intRadius_str = 'Integration radii' self.index_pdb_str = 'Unitcell' self.index_method_str = 'Indexing method' self.index_tolerance_str = 'Tolerance' self.index_extra_str = 'Extra CrystFEL parameters' self.index_condition_str = 'Index condition' self.launch_grp = 'Batch' self.outDir_str = 'Output directory' self.runs_str = 'Runs(s)' self.sample_str = 'Sample name' self.tag_str = 'Tag' self.queue_str = 'Queue' self.chunkSize_str = 'Chunk size' self.cpu_str = 'CPUs' self.keepData_str = 'Keep CXI images' self.noe_str = 'Number of events to process' (self.psanaq_str,self.psnehq_str,self.psfehq_str,self.psnehprioq_str,self.psfehprioq_str,self.psnehhiprioq_str,self.psfehhiprioq_str,self.psdebugq_str) = \ ('psanaq','psnehq','psfehq','psnehprioq','psfehprioq','psnehhiprioq','psfehhiprioq','psdebugq') self.noQueue_str = 'N/A' self.outDir = self.parent.psocakeDir self.outDir_overridden = False self.runs = '' self.sample = 'crystal' self.tag = '' self.queue = self.psanaq_str self.chunkSize = 500 self.cpu = 12 self.noe = -1 # Indexing if self.parent.facility == self.parent.facilityLCLS: self.showIndexedPeaks = False self.indexedPeaks = None self.hiddenCXI = '.temp.cxi' self.hiddenCrystfelStream = '.temp.stream' self.hiddenCrystfelList = '.temp.lst' self.indexingOn = False self.numIndexedPeaksFound = 0 self.geom = '.temp.geom' self.peakMethod = 'cxi' self.intRadius = '3,4,5' self.pdb = '' self.indexingMethod = 'mosflm,dirax' self.tolerance = '5,5,5,1.5' self.extra = '' self.condition = '' self.keepData = True elif self.parent.facility == self.parent.facilityPAL: self.showIndexedPeaks = False self.indexedPeaks = None self.hiddenCXI = '.temp.cxi' self.hiddenCrystfelStream = '.temp.stream' self.hiddenCrystfelList = '.temp.lst' self.indexingOn = False self.numIndexedPeaksFound = 0 self.geom = '.temp.geom' self.peakMethod = 'cxi' self.intRadius = '4,5,6' self.pdb = '' self.indexingMethod = 'mosflm,dirax' self.tolerance = '5,5,5,1.5' self.extra = '' self.condition = '' self.keepData = True ####################### # Mandatory parameter # ####################### if self.parent.facility == self.parent.facilityLCLS: self.params = [ {'name': self.index_grp, 'type': 'group', 'children': [ {'name': self.index_on_str, 'type': 'bool', 'value': self.indexingOn, 'tip': "Turn on indexing"}, {'name': self.index_geom_str, 'type': 'str', 'value': self.geom, 'tip': "CrystFEL geometry file"}, #{'name': self.index_peakMethod_str, 'type': 'str', 'value': self.peakMethod, 'tip': "Turn on indexing"}, {'name': self.index_intRadius_str, 'type': 'str', 'value': self.intRadius, 'tip': "Integration radii"}, {'name': self.index_pdb_str, 'type': 'str', 'value': self.pdb, 'tip': "(Optional) CrystFEL unitcell file"}, {'name': self.index_method_str, 'type': 'str', 'value': self.indexingMethod, 'tip': "comma separated indexing methods"}, {'name': self.index_tolerance_str, 'type': 'str', 'value': self.tolerance, 'tip': "Indexing tolerance, default: 5,5,5,1.5"}, {'name': self.index_extra_str, 'type': 'str', 'value': self.extra, 'tip': "Other indexing parameters, comma separated (e.g. --multi,--no-check-peaks)"}, {'name': self.index_condition_str, 'type': 'str', 'value': self.condition, 'tip': "indexing condition e.g. 41 in #evr1# and #eventNumber# > 3"}, ]}, {'name': self.launch_grp, 'type': 'group', 'children': [ {'name': self.outDir_str, 'type': 'str', 'value': self.outDir}, {'name': self.runs_str, 'type': 'str', 'value': self.runs, 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"}, {'name': self.sample_str, 'type': 'str', 'value': self.sample, 'tip': "name of the sample saved in the cxidb file, e.g. lysozyme"}, {'name': self.tag_str, 'type': 'str', 'value': self.tag, 'tip': "attach tag to stream, e.g. cxitut13_0010_tag.stream"}, {'name': self.queue_str, 'type': 'list', 'values': {self.psfehhiprioq_str: self.psfehhiprioq_str, self.psnehhiprioq_str: self.psnehhiprioq_str, self.psfehprioq_str: self.psfehprioq_str, self.psnehprioq_str: self.psnehprioq_str, self.psfehq_str: self.psfehq_str, self.psnehq_str: self.psnehq_str, self.psanaq_str: self.psanaq_str, self.psdebugq_str: self.psdebugq_str}, 'value': self.queue, 'tip': "Choose queue"}, {'name': self.chunkSize_str, 'type': 'int', 'value': self.chunkSize, 'tip': "number of patterns to process per worker"}, {'name': self.keepData_str, 'type': 'bool', 'value': self.keepData, 'tip': "Do not delete cxidb images in cxi file"}, ]}, ] elif self.parent.facility == self.parent.facilityPAL: self.params = [ {'name': self.index_grp, 'type': 'group', 'children': [ {'name': self.index_on_str, 'type': 'bool', 'value': self.indexingOn, 'tip': "Turn on indexing"}, {'name': self.index_geom_str, 'type': 'str', 'value': self.geom, 'tip': "CrystFEL geometry file"}, {'name': self.index_intRadius_str, 'type': 'str', 'value': self.intRadius, 'tip': "Integration radii"}, {'name': self.index_pdb_str, 'type': 'str', 'value': self.pdb, 'tip': "(Optional) CrystFEL unitcell file"}, {'name': self.index_method_str, 'type': 'str', 'value': self.indexingMethod, 'tip': "comma separated indexing methods"}, {'name': self.index_tolerance_str, 'type': 'str', 'value': self.tolerance, 'tip': "Indexing tolerance, default: 5,5,5,1.5"}, {'name': self.index_extra_str, 'type': 'str', 'value': self.extra, 'tip': "Other CrystFEL indexing parameters"}, ]}, {'name': self.launch_grp, 'type': 'group', 'children': [ {'name': self.outDir_str, 'type': 'str', 'value': self.outDir}, {'name': self.runs_str, 'type': 'str', 'value': self.runs, 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"}, {'name': self.sample_str, 'type': 'str', 'value': self.sample, 'tip': "name of the sample saved in the cxidb file, e.g. lysozyme"}, {'name': self.tag_str, 'type': 'str', 'value': self.tag, 'tip': "attach tag to stream, e.g. cxitut13_0010_tag.stream"}, {'name': self.queue_str, 'type': 'list', 'values': {self.noQueue_str: self.noQueue_str}, 'value': self.queue, 'tip': "Choose queue"}, {'name': self.cpu_str, 'type': 'int', 'value': self.cpu, 'tip': "number of cores to use for indexing per run"}, {'name': self.keepData_str, 'type': 'bool', 'value': self.keepData, 'tip': "Do not delete cxidb images in cxi file"}, ]}, ] self.p9 = Parameter.create(name='paramsCrystalIndexing', type='group', \ children=self.params, expanded=True) self.win.setParameters(self.p9, showTop=False) self.p9.sigTreeStateChanged.connect(self.change) if using_pyqt4: self.parent.connect(self.launchIndexBtn, QtCore.SIGNAL("clicked()"), self.indexPeaks) self.parent.connect(self.synchBtn, QtCore.SIGNAL("clicked()"), self.syncGeom) else: self.launchIndexBtn.clicked.connect(self.indexPeaks) self.synchBtn.clicked.connect(self.syncGeom) # Launch indexing def indexPeaks(self): self.parent.thread.append(LaunchIndexer.LaunchIndexer(self.parent)) # send parent parameters with self self.parent.thread[self.parent.threadCounter].launch(self.parent.experimentName, self.parent.detInfo) self.parent.threadCounter += 1 # Update psana geometry def syncGeom(self): if self.parent.facility == self.parent.facilityLCLS: with pg.BusyCursor(): print "#################################################" print "Updating psana geometry with CrystFEL geometry" print "#################################################" self.parent.geom.findPsanaGeometry() psanaGeom = self.parent.psocakeRunDir + "/.temp.data" if self.parent.args.localCalib: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", '.', "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] else: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", self.parent.rootDir, "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] if self.parent.args.v >= 0: print "cmd: ", cmd p = subprocess.Popen(cmd, stdout=subprocess.PIPE) output = p.communicate()[0] p.stdout.close() # Reload new psana geometry cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'converted from crystfel geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = self.parent.dir + self.parent.experimentName[:3] + '/' + self.parent.experimentName + '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=psanaGeom, dcmts=cmts, pbits=0) self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.parent.geom.updateRings() self.parent.index.updateIndex() self.parent.geom.drawCentre() # Show mask self.parent.mk.updatePsanaMaskOn() elif self.parent.facility == self.parent.facilityPAL: print "deploy crystfel geom is not implemented for PAL" # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[1] == self.index_on_str: self.updateIndexStatus(data) elif path[1] == self.index_geom_str: self.updateGeom(data) elif path[1] == self.index_peakMethod_str: self.updatePeakMethod(data) elif path[1] == self.index_intRadius_str: self.updateIntegrationRadius(data) elif path[1] == self.index_pdb_str: self.updatePDB(data) elif path[1] == self.index_method_str: self.updateIndexingMethod(data) elif path[1] == self.index_tolerance_str: self.updateTolerance(data) elif path[1] == self.index_extra_str: self.updateExtra(data) elif path[1] == self.index_condition_str: self.updateCondition(data) # launch grp elif path[1] == self.outDir_str: self.updateOutputDir(data) elif path[1] == self.runs_str: self.updateRuns(data) elif path[1] == self.sample_str: self.updateSample(data) elif path[1] == self.tag_str: self.updateTag(data) elif path[1] == self.queue_str: self.updateQueue(data) elif path[1] == self.chunkSize_str: self.updateChunkSize(data) elif path[1] == self.cpu_str: self.updateCpu(data) elif path[1] == self.noe_str: self.updateNoe(data) elif path[1] == self.keepData_str: self.keepData = data def updateIndexStatus(self, data): self.indexingOn = data self.showIndexedPeaks = data self.updateIndex() def updateGeom(self, data): self.geom = data self.updateIndex() def updatePeakMethod(self, data): self.peakMethod = data if self.indexingOn: self.updateIndex() def updateIntegrationRadius(self, data): self.intRadius = data self.updateIndex() def updatePDB(self, data): self.pdb = data self.updateIndex() def updateIndexingMethod(self, data): self.indexingMethod = data self.updateIndex() def updateTolerance(self, data): self.tolerance = data self.updateIndex() def updateExtra(self, data): self.extra = data.replace(" ","") self.updateIndex() def updateCondition(self, data): self.condition = data self.updateIndex() def updateIndex(self): if self.indexingOn: if self.parent.pk.peaks is None: self.parent.index.clearIndexedPeaks() else: self.indexer = IndexHandler(parent=self.parent) self.indexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, queue=None) else: # do not display predicted spots self.parent.index.clearIndexedPeaks() def updateOutputDir(self, data): self.outDir = data self.outDir_overridden = True def updateRuns(self, data): self.runs = data def updateSample(self, data): self.sample = data def updateTag(self, data): self.tag = data def updateQueue(self, data): self.queue = data def updateChunkSize(self, data): self.chunkSize = data def updateCpu(self, data): self.cpu = data def updateNoe(self, data): self.noe = data def clearIndexedPeaks(self): self.parent.img.win.getView().removeItem(self.parent.img.abc_text) self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) if self.parent.args.v >= 1: print "Done clearIndexedPeaks" def displayWaiting(self): if self.showIndexedPeaks: if self.numIndexedPeaksFound == 0: # indexing proceeding xMargin = 5 # pixels if self.parent.facility == self.parent.facilityLCLS: maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) elif self.parent.facility == self.parent.facilityPAL: yMargin = 0 # pixels (dim0, dim1) = self.parent.calib.shape self.iy = np.tile(np.arange(dim0), [dim1, 1]) self.ix = np.transpose(self.iy) maxX = np.max(self.ix) + xMargin maxY = np.max(self.iy) - yMargin # Draw a big X cenX = np.array((self.parent.cx,)) + 0.5 cenY = np.array((self.parent.cy,)) + 0.5 diameter = 256 # self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='t', \ size=diameter, brush=(255, 255, 255, 0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0, 0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) def drawIndexedPeaks(self, latticeType=None, centering=None, unitCell=None): self.clearIndexedPeaks() if self.showIndexedPeaks: if self.indexedPeaks is not None and self.numIndexedPeaksFound > 0: # indexing succeeded cenX = self.indexedPeaks[:,0]+0.5 cenY = self.indexedPeaks[:,1]+0.5 cenX = np.concatenate((cenX,cenX,cenX)) cenY = np.concatenate((cenY,cenY,cenY)) diameter = np.ones_like(cenX) diameter[0:self.numIndexedPeaksFound] = float(self.intRadius.split(',')[0])*2 diameter[self.numIndexedPeaksFound:2*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[1])*2 diameter[2*self.numIndexedPeaksFound:3*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[2])*2 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='o', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 1.5}), pxMode=False) # Write unit cell parameters if unitCell is not None: xMargin = 5 yMargin = 400 if self.parent.facility == self.parent.facilityLCLS: maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) - yMargin elif self.parent.facility == self.parent.facilityPAL: (dim0, dim1) = self.parent.calib.shape self.iy = np.tile(np.arange(dim0), [dim1, 1]) self.ix = np.transpose(self.iy) maxX = np.max(self.ix) + xMargin maxY = np.max(self.iy) - yMargin #myMessage = '<div style="text-align: center"><span style="color: #FF00FF; font-size: 12pt;">lattice='+\ # str(latticeType) +'<br>centering=' + str(centering) + '<br>a='+\ # str(round(float(unitCell[0])*10,2))+'A <br>b='+str(round(float(unitCell[1])*10,2))+'A <br>c='+\ # str(round(float(unitCell[2])*10,2))+'A <br>α='+str(round(float(unitCell[3]),2))+\ # '° <br>β='+str(round(float(unitCell[4]),2))+'° <br>γ='+\ # str(round(float(unitCell[5]),2))+'° <br></span></div>' myMessage = '<div style="text-align: center"><span style="color: #FF00FF; font-size: 12pt;">lattice='+\ str(latticeType) +'<br>centering=' + str(centering) + '<br></span></div>' self.parent.img.abc_text = pg.TextItem(html=myMessage, anchor=(0,0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) else: # Failed indexing #xMargin = 5 # pixels #if self.parent.facility == self.parent.facilityLCLS: # maxX = np.max(self.parent.det.indexes_x(self.parent.evt))+xMargin # maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) #elif self.parent.facility == self.parent.facilityPAL: # yMargin = 0 # pixels # (dim0, dim1) = self.parent.calib.shape # self.iy = np.tile(np.arange(dim0), [dim1, 1]) # self.ix = np.transpose(self.iy) # maxX = np.max(self.ix) + xMargin # maxY = np.max(self.iy) - yMargin # Draw a big X cenX = np.array((self.parent.cx,))+0.5 cenY = np.array((self.parent.cy,))+0.5 diameter = 256 #self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='x', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0,0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(0,0) else: self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0, 0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(0, 0) if self.parent.args.v >= 1: print "Done drawIndexedPeaks" # This function probably doesn't get called def launchIndexing(self, requestRun=None): self.batchIndexer = IndexHandler(parent=self.parent) if requestRun is None: self.batchIndexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) else: self.batchIndexer.computeIndex(self.parent.experimentName, requestRun, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) if self.parent.args.v >= 1: print "Done updateIndex"
class JsonReader(QWidget): """ """ def __init__(self): super().__init__() self.title = "Json metadata reader" self.left = 100 self.top = 100 self.width = 500 self.height = 500 self.initUI() def initUI(self): """ """ self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.getbtn = QPushButton("Select file") self.getbtn.clicked.connect(self.get_file) self.draglbl = DragDropLabel(self) self.draglbl.setText("... or drop .{} file here".format( DragDropLabel.acceptedFormat.upper())) self.draglbl.setAlignment(QtCore.Qt.AlignCenter) self.draglbl.droppedFile.connect(self.open_file) self.layout = QGridLayout(self) self.layout.addWidget(self.getbtn, 0, 0) self.layout.addWidget(self.draglbl, 1, 0) self.layout.setColumnMinimumWidth(0, 500) self.setLayout(self.layout) self.show() def get_file(self): """ """ self.path, _ = QFileDialog.getOpenFileName( filter="Json files (*.json)") if not self.path: pass else: self.open_file(self.path) def open_file(self, filename): """ Parameters ---------- filename : Returns ------- """ self.filename = filename with open(filename) as json_file: self.metadata_dict = json.load(json_file) self.display_tree_widget(self.metadata_dict) def display_tree_widget(self, metadata): """Display the parameter tree from the experiment metadata. Parameters ---------- metadata : json metadata Returns ------- """ # Close previous tree widget self.close_tree() # Create a variable checking whether changes have been made to the parameter tree values self.has_changed = False # Create list with parameters for the tree self.parameters = self.create_parameters(self.fix_types(metadata)) # Add parameters for Save buttons and Image options self.parameters.append({ "name": "Metadata Image Options", "type": "group", "children": [ { "name": "Append Image", "type": "action" }, { "name": "View Image", "type": "action" }, ], }) self.parameters.append({ "name": "Save/Reset metadata", "type": "group", "children": [ { "name": "Save changes", "type": "action" }, { "name": "Reset changes", "type": "action" }, ], }) # Create tree of Parameter objects self.p = Parameter.create(name="params", type="group", children=self.parameters) # Check if Image parameters already exist. If they don't, # add them and update Parameter object self.children_list = [] for child in self.p.children(): self.children_list.append(str(child).split("'")[1]) # Save original state self.original_state = self.p.saveState() # Connect Save/Reset buttons to respective functions self.p.param("Save/Reset metadata", "Save changes").sigActivated.connect(self.save_treevals) self.p.param("Save/Reset metadata", "Reset changes").sigActivated.connect(self.reset) # Create ParameterTree widget self.tree = ParameterTree() self.tree.setParameters(self.p, showTop=False) self.tree.setWindowTitle("pyqtgraph example: Parameter Tree") # Display tree widget self.layout.addWidget(self.tree, 2, 0) # Send signal when any entry is changed self.p.sigTreeStateChanged.connect(self.change) def append_img(self): """Attach a .png image to the metadata file.""" self.imagefile, _ = QFileDialog.getOpenFileName( filter="png images (*.png)") if not self.imagefile: pass else: with open(self.imagefile, "rb") as f: self.img = f.read() self.encoded_img = base64.b64encode(self.img) self.encoded_img = self.encoded_img.decode("utf8") self.p.param("Metadata Image").setValue(self.encoded_img) self.p.param("Metadata Image").setDefault(self.encoded_img) def display_img(self): """Show image appended to the metadata file""" try: self.layout.removeWidget(self.imglbl) self.imglbl.deleteLater() self.imglbl = None except AttributeError: pass if not self.p.param("Metadata Image").defaultValue(): self.imglbl = QLabel("No image associated to this metadata") self.layout.addWidget(self.imglbl, 2, 1) try: self.layout.removeWidget(self.viewbtn) self.viewbtn.deleteLater() self.viewbtn = None except AttributeError: pass else: self.figstring = self.p.param("Metadata Image").defaultValue() self.figbytes = self.figstring.encode("utf8") self.figbytes = base64.b64decode(self.figbytes) self.viewbtn = QPushButton("Zoom image") self.viewbtn.clicked.connect(self.image_viewer) self.image = QtGui.QPixmap() self.image.loadFromData(self.figbytes) self.image = self.image.scaledToHeight(500) self.imglbl = QLabel() self.imglbl.setPixmap(self.image) self.layout.addWidget(self.imglbl, 0, 1, 3, 1) self.layout.addWidget(self.viewbtn, 3, 1) def image_viewer(self): """Open metadata image in the Image Viewer from PyQtGraph.""" self.win = QtGui.QMainWindow() self.win.resize(800, 800) self.fignp = np.array(Image.open(io.BytesIO(self.figbytes))) self.fignp = np.swapaxes(self.fignp, 0, 1) self.imv = pg.ImageView() self.imv.setImage(self.fignp) self.win.setCentralWidget(self.imv) self.win.setWindowTitle("Metadata Image") self.win.show() def save_treevals(self): """Save current values of the parameter tree into a dictionary.""" # Recover data from tree and store it in a dict self.treevals_dict = self.p.getValues() self.metadata_dict_mod = self.get_mod_dict(self.treevals_dict) # Nasty way to make new dict (with modified metadata) with same structure as the original one self.metadata_dict_mod.pop("Save/Reset metadata") self.metadata_dict_mod.pop("Metadata Image Options") self.metadata_dict_mod["stimulus"]["log"] = self.metadata_dict[ "stimulus"]["log"] self.metadata_dict_mod["stimulus"]["display_params"][ "pos"] = json.loads( self.metadata_dict_mod["stimulus"]["display_params"]["pos"]) self.metadata_dict_mod["stimulus"]["display_params"][ "size"] = json.loads( self.metadata_dict_mod["stimulus"]["display_params"]["size"]) self.show_warning() def show_warning(self): """Upon saving, display a warning message to choose whether to create a new metadata file or replace the existing one. Parameters ---------- Returns ------- """ if self.has_changed: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.setWindowTitle("Saving Warning") self.msg.setText("Some parameters have changed") self.msg.setInformativeText( "Do you want to overwrite the original .json metadata file?") self.msg.addButton("Create new file", QMessageBox.AcceptRole) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) self.ret = self.msg.exec_() if self.ret == QMessageBox.Yes: self.overwrite_metadata_file(self.metadata_dict_mod) elif self.ret == QMessageBox.AcceptRole: self.create_metadata_file(self.metadata_dict_mod) else: pass else: self.msg2 = QMessageBox() self.msg2.setIcon(QMessageBox.Information) self.setWindowTitle("Saving Warning") self.msg2.setText("No changes have been made.") self.msg2.addButton("OK", QMessageBox.AcceptRole) self.ret = self.msg2.exec_() def overwrite_metadata_file(self, metadata_dict_mod): """ Parameters ---------- metadata_dict_mod : Returns ------- """ # Overwritte original metadata file with open(self.filename, "w") as file: json.dump(metadata_dict_mod, file) def create_metadata_file(self, metadata_dict_mod): """ Parameters ---------- metadata_dict_mod : Returns ------- """ # Overwritte original metadata file self.name, self.ext = self.filename.split(".") with open("{}_modified.{}".format(self.name, self.ext), "w") as file: json.dump(metadata_dict_mod, file) def reset(self): """Reset parameter tree values to the original state after loading.""" self.p.restoreState(self.original_state, recursive=True) self.tree.setParameters(self.p, showTop=False) def fix_types(self, datadict): """Modify metadata dict so only accepted types are found. Parameters ---------- datadict : Returns ------- """ param_dict = dict() for key, value in datadict.items(): if isinstance(value, list): param_dict[key] = str(value) elif isinstance(value, dict): param_dict[key] = self.fix_types(value) else: param_dict[key] = value return param_dict def create_parameters(self, datadict): """Create list with parameters and Children to which the tree will be built from. Parameters ---------- datadict : Returns ------- """ parameters = [] for key, value in datadict.items(): if key == "log": pass else: if isinstance(value, dict): parameters.append({ "name": "{}".format(key), "type": "group", "children": self.create_parameters(value), }) else: parameters.append({ "name": "{}".format(key), "type": "{}".format(type(value).__name__), "value": value, }) return parameters def get_mod_dict(self, treevals_dict): """Recursive function to convert into dict output of getValues function. Parameters ---------- treevals_dict : Returns ------- """ metadata_dict_mod = dict() for key, value in treevals_dict.items(): if value[0] is None: metadata_dict_mod[key] = dict(self.get_mod_dict(value[1])) else: metadata_dict_mod[key] = value[0] return metadata_dict_mod def change(self, param, changes): """ Parameters ---------- param : changes : Returns ------- """ print("tree changes:") for param, change, data in changes: path = self.p.childPath(param) if path is not None: childName = ".".join(path) else: childName = param.name() print(" parameter: %s" % childName) print(" change: %s" % change) print(" data: %s" % str(data)) print(" ----------") if change == "activated": pass else: self.has_changed = True def close_tree(self): """ """ try: self.layout.removeWidget(self.tree) self.tree.deleteLater() self.tree = None except AttributeError: pass
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): super(MainWindow, self).__init__() layout = Qt.QVBoxLayout(self) self.btnGen = Qt.QPushButton("Start Gen!") layout.addWidget(self.btnGen) self.SaveStateParams = FileMod.SaveSateParameters(self, name='State') self.Parameters = Parameter.create(name='params', type='group', children=(self.SaveStateParams, )) self.DataGenParams = SampGen.DataGeneratorParameters( name='Data Generator') self.DataGenParams.param('Col0').param('Freq').setValue(75e3) self.DataGenParams.param('Col1').param('Freq').setValue(100e3) self.DataGenParams.param('Col2').param('Freq').setValue(125e3) self.DataGenParams.param('Col3').param('Freq').setValue(150e3) self.DataGenParams.param('Col0').param('Fsig').setValue(1e3) self.DataGenParams.param('Col1').param('Fsig').setValue(800) self.DataGenParams.param('Col2').param('Fsig').setValue(250) self.DataGenParams.param('Col3').param('Fsig').setValue(10) self.Parameters.addChild(self.DataGenParams) self.FileParameters = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParameters) self.PSDParams = PltMod.PSDParameters(name='PSD Options') self.PSDParams.param('Fs').setValue( self.DataGenParams.param('Fs').value()) self.PSDParams.param('Fmin').setValue(50) self.PSDParams.param('nAvg').setValue(50) self.Parameters.addChild(self.PSDParams) self.PlotParams = PltMod.PlotterParameters(name='Plot options') self.PlotParams.SetChannels(self.DataGenParams.GetChannels()) self.PlotParams.param('Fs').setValue( self.DataGenParams.param('Fs').value()) self.Parameters.addChild(self.PlotParams) self.Parameters.sigTreeStateChanged.connect(self.on_pars_changed) self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(550, 10, 300, 700) self.setWindowTitle('MainWindow') self.btnGen.clicked.connect(self.on_btnGen) self.threadGen = None self.threadSave = None self.threadPlotter = None def on_pars_changed(self, param, changes): print("tree changes:") for param, change, data in changes: path = self.Parameters.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') if childName == 'Data Generator.nChannels': self.PlotParams.SetChannels(self.DataGenParams.GetChannels()) if childName == 'Data Generator.Fs': self.PlotParams.param('Fs').setValue(data) self.PSDParams.param('Fs').setValue(data) if childName == 'Plot options.RefreshTime': if self.threadPlotter is not None: self.threadPlotter.SetRefreshTime(data) if childName == 'Plot options.ViewTime': if self.threadPlotter is not None: self.threadPlotter.SetViewTime(data) def on_btnGen(self): if self.threadGen is None: GenKwargs = self.DataGenParams.GetParams() self.threadGen = SampGen.DataSamplingThread(**GenKwargs) self.threadGen.NewSample.connect(self.on_NewSample) self.threadGen.start() FileName = self.FileParameters.param('File Path').value() if FileName == '': print('No file') else: if os.path.isfile(FileName): print('Remove File') os.remove(FileName) MaxSize = self.FileParameters.param('MaxSize').value() self.threadSave = FileMod.DataSavingThread( FileName=FileName, nChannels=GenKwargs['Rows'], MaxSize=MaxSize) self.threadSave.start() PlotterKwargs = self.PlotParams.GetParams() print(PlotterKwargs) self.threadPlotter = PltMod.Plotter(**PlotterKwargs) self.threadPlotter.start() self.threadPSDPlotter = PltMod.PSDPlotter( ChannelConf=PlotterKwargs['ChannelConf'], nChannels=GenKwargs['Rows'], **self.PSDParams.GetParams()) self.threadPSDPlotter.start() self.btnGen.setText("Stop Gen") self.OldTime = time.time() self.Tss = [] else: self.threadGen.NewSample.disconnect() self.threadGen.terminate() self.threadGen = None if self.threadSave is not None: self.threadSave.terminate() self.threadSave = None self.threadPlotter.terminate() self.threadPlotter = None self.btnGen.setText("Start Gen") def on_NewSample(self): ''' Visualization of streaming data-WorkThread. ''' Ts = time.time() - self.OldTime self.Tss.append(Ts) self.OldTime = time.time() if self.threadSave is not None: self.threadSave.AddData(self.threadGen.OutData) self.threadPlotter.AddData(self.threadGen.OutData) self.threadPSDPlotter.AddData(self.threadGen.OutData) print('Sample time', Ts, np.mean(self.Tss))
class GuiManager(QtGui.QMainWindow): def __init__(self): super(GuiManager, self).__init__() self.createLayout() def closeEvent(self, event): print 'User asked to close the app' self.stopAcquisition() Parameters.isAppKilled = True #time.sleep(0.1) #Wait for the worker death event.accept() # let the window close def startAcquisition(self): if Parameters.isConnected == False: return Parameters.isSaving = Parameters.paramObject.child("Saving parameters", "saveResults").value() if Parameters.isSaving == True: theDate = datetime.datetime.today() .strftime('%Y%m%d') theTime = datetime.datetime.today() .strftime('%H%M%S') theName=Parameters.paramObject.child("Saving parameters", "Experiment name").value() #Check counter increment folderParent = 'C:/InterferometryResults/' + theDate counter = 1 folderFound = False theFolder = folderParent + '/' + theName + '_' + str(counter).zfill(3) if not os.path.exists(folderParent): #Make sure parent exist os.makedirs(folderParent) while folderFound == False and counter < 1000: #Loop until folder is found if not os.path.exists(theFolder): #Make sure parent exist os.makedirs(theFolder) folderFound = True else: counter = counter + 1 theFolder = folderParent + '/' + theName + '_' + str(counter).zfill(3) if counter < 1000: Parameters.savingFolder = theFolder if not os.path.exists(theFolder): os.makedirs(theFolder) else: Parameters.isSaving = False; #Should not happen. self.btStart.setEnabled(False) self.btStop.setEnabled(True) self.btOpen.setEnabled(False) #Get the parameter values Parameters.nSamples=Parameters.paramObject.child("Acquisition Parameters", "Number of samples to acquire").value() acqMode=Parameters.paramObject.child("Trigger Options", "Acquisition mode").value() triggerAmplitude=Parameters.paramObject.child("Trigger Options", "Trigger amplitude").value() motorSpeed=Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").value()+28 #28 is calibration nBlocks=int(math.ceil(float(Parameters.nSamples)/512)) #Must be a multiple of 512 Parameters.nSamples = nBlocks*512 Parameters.paramObject.child("Acquisition Parameters", "Number of samples to acquire").setValue(Parameters.nSamples) #Set frequency in free mode. These settings could be optimized depending on the computer. freq=2500000 #10im/s if Parameters.nSamples > 100352: freq=5000000 #5im/s if Parameters.nSamples > 300032: freq=12500000 #2im/s if Parameters.nSamples > 1000000: freq=25000000 #1im/s if Parameters.nSamples > 2000000: freq=50000000 #0.5im/s #Start the acquisition on the FPGA data = [] data = array('i') data.append(1) data.append(freq) data.append(2) data.append(acqMode) data.append(3) data.append(nBlocks) data.append(4) data.append(motorSpeed) data.append(5) data.append(triggerAmplitude) data.append(6) data.append(0) theBytes = struct.pack('i' * len(data), *data) buf = bytearray(theBytes) Parameters.dev.WriteToPipeIn(128, buf) Parameters.dev.SetWireInValue(0, 1+2+8, 1+2+8);Parameters.dev.UpdateWireIns() #Enable DDR2 reading and writing and activate memory. time.sleep(0.1); #Wait to make sure everything is ready. TODO: Reduce this. Parameters.dev.SetWireInValue(0, 4, 4);Parameters.dev.UpdateWireIns() #Start acquisition clock. #self.plotTr.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted Parameters.theQueue = Queue.Queue() #Create the queue #self.DisplayUpdater(0) self.workThread.start(); #Start the display worker def stopAcquisition(self): print 'Stopping...' if hasattr(self,'tDisplay'): self.tDisplay.cancel() self.workThread.exitWorker(); while self.workThread.isRunning == True: time.sleep(0.01) #Wait for the worker death, before resetting the board Parameters.dev.SetWireInValue(0, 0, 1+2+4+8);Parameters.dev.UpdateWireIns() #Reset board. #Save format: Results / YYMMDD / ExperimentName_Counter. Could also use the time. if Parameters.isSaving == True: #global state state = Parameters.paramObject.saveState() file = open(Parameters.savingFolder + '\Parameters.txt', 'w') pickle.dump(state, file) file.close() print 'Stopped.' self.btStart.setEnabled(True) self.btStop.setEnabled(False) self.btOpen.setEnabled(True) ''' def DisplayUpdater(self,dummy): if Parameters.isAppKilled == True: return; if Parameters.theQueue.empty(): print 'no data...' while not Parameters.theQueue.empty(): #Empty the display queue data = Parameters.theQueue.get() #print 'data available!' if 'data' in locals(): #print 'display data' + str(data[2]) self.setDataCurveTr(data) tDisplay = Timer(2, self.DisplayUpdater, [0],{}) tDisplay.start() ''' def motorSpeedChanged(self,value): newSpeed=Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").value() newSpeed=newSpeed+28 #Calibration #Debug #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(enabled=False) #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(visible=False) #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(value=200) data = [] data = array('i') data.append(4) data.append(newSpeed) data.append(0) #Minimum size is 8 'int' data.append(0) data.append(0) data.append(0) data.append(0) data.append(0) theBytes = struct.pack('i' * len(data), *data) Parameters.bufferToDev = bytearray(theBytes) Parameters.bufferToDevReady = True def triggerChanged(self,value): acqMode=Parameters.paramObject.child("Trigger Options", "Acquisition mode").value() triggerAmplitude=Parameters.paramObject.child("Trigger Options", "Trigger amplitude").value() data = [] data = array('i') data.append(2) data.append(acqMode) data.append(5) data.append(triggerAmplitude) data.append(0) data.append(0) data.append(0) data.append(0) theBytes = struct.pack('i' * len(data), *data) print str(theBytes) Parameters.bufferToDev = bytearray(theBytes) Parameters.bufferToDevReady = True def triggerHalfSwitch(self): Parameters.triggerToDev = True def saveParam(self): #global state state = Parameters.paramObject.saveState() file = open('dump.txt', 'w') pickle.dump(state, file) file.close() def restoreParam(self): #lobal state file = open('dump.txt', 'r') state = pickle.load(file) #add = Parameters.paramObject['Save/Restore functionality', 'Restore State', 'Add missing items'] #rem = Parameters.paramObject['Save/Restore functionality', 'Restore State', 'Remove extra items'] Parameters.paramObject.restoreState(state, addChildren=False, removeChildren=False) #Set the status text (system connected or not) def setStatus(self, isConnected, isError = False): def dotChange(item, nDots): #Timer function to display a varying number of dots after "retrying" if Parameters.isConnected == True: return; if Parameters.isAppKilled == True: return; textNotConnected = "System not connected, retrying" item.setText(textNotConnected+".") #Number of dots varies from 1 to 5 if nDots == 1: textDots = "." nDots = 2 elif nDots == 2: textDots = ".." nDots = 3 elif nDots == 3: textDots = "..." nDots = 4 elif nDots == 4: textDots = "...." nDots = 5 else: textDots = "....." nDots = 1 item.setForeground(QtGui.QColor("red")) item.setText(textNotConnected+textDots) self.timerDotChange = Timer(0.25, dotChange, [self.itemStatus, nDots]) self.timerDotChange.start() if (isError == True): #System not connected print "Error" if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() time.sleep(0.5) self.itemStatus.setForeground(QtGui.QColor("red")) self.itemStatus.setText("Error with system. Please restart the application and the system.") elif (isConnected == False): #System not connected nDots = 1 if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() self.timerDotChange = Timer(0.25, dotChange, [self.itemStatus, nDots]) self.timerDotChange.start() else: print "Connected" if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() time.sleep(0.1) self.itemStatus.setForeground(QtGui.QColor("green")) self.itemStatus.setText("System connected.") print "Connected2" #Set the status text (system connected or not) def setCameraStatus(self, isConnected): def dotChange(item, nDots): #Timer function to display a varying number of dots after "retrying" if Parameters.isCameraConnected == True: return; if Parameters.isAppKilled == True: return; textNotConnected = "Camera not connected, retrying" item.setText(textNotConnected+".") #Number of dots varies from 1 to 5 if nDots == 1: textDots = "." nDots = 2 elif nDots == 2: textDots = ".." nDots = 3 elif nDots == 3: textDots = "..." nDots = 4 elif nDots == 4: textDots = "...." nDots = 5 else: textDots = "....." nDots = 1 item.setForeground(QtGui.QColor("red")) item.setText(textNotConnected+textDots) self.timerDotChangeCamera = Timer(0.25, dotChange, [self.itemCameraStatus, nDots]) self.timerDotChangeCamera.start() if (isConnected == False): #System not connected print 'cam oups' nDots = 1 if hasattr(self,'timerDotChangeCamera'): self.timerDotChangeCamera.cancel() self.timerDotChangeCamera = Timer(0.25, dotChange, [self.itemCameraStatus, nDots]) self.timerDotChangeCamera.start() else: print "Camera connected" if hasattr(self,'timerDotChangeCamera'): self.timerDotChangeCamera.cancel() time.sleep(0.1) self.itemCameraStatus.setForeground(QtGui.QColor("green")) self.itemCameraStatus.setText("Camera connected.") print "Camera connected2" #Set the status text (system connected or not) def setInfo(self, text): self.tbInfo.append(text) #Set the status text (system connected or not) def setWire(self, mem1, mem2, mem3, mem4, maxValPos): self.itemMemory.setText("Acquisition board memory usage:\nDDR2: " + str(mem1) + " bytes.\nFIFO in: " + str(mem2) + " bytes.\nFIFO out: " + str(mem3) + " bytes.\nFIFO out (minimum): " + str(mem4) + " bytes.") self.itemMaxValPos.setText("Maximum RF value position: " + str(maxValPos)) def createLayout(self): print 'Creating layout...' self.setWindowTitle('Interferometry Acquisition GUI') #self.widget = QtGui.QWidget() #self.setCentralWidget(self.widget) self.layout = pg.LayoutWidget() #self.widget.setLayout(self.layout) self.setCentralWidget(self.layout) #Create GUI sizePolicyBt = QtGui.QSizePolicy(1, 1) sizePolicyBt.setHorizontalStretch(0) sizePolicyBt.setVerticalStretch(0) self.btOpen = QtGui.QPushButton("Open\nprevious results") sizePolicyBt.setHeightForWidth(self.btOpen.sizePolicy().hasHeightForWidth()) self.btOpen.setSizePolicy(sizePolicyBt); self.btOpen.setStyleSheet("background-color: yellow; font-size: 16px; font: bold") self.btStart = QtGui.QPushButton("Start\nacquisition") sizePolicyBt.setHeightForWidth(self.btStart.sizePolicy().hasHeightForWidth()) self.btStart.setSizePolicy(sizePolicyBt); self.btStart.setStyleSheet("background-color: green; font-size: 16px; font: bold") self.btStart.clicked.connect(self.startAcquisition) self.btStop = QtGui.QPushButton("Stop\nacquisition") sizePolicyBt.setHeightForWidth(self.btStop.sizePolicy().hasHeightForWidth()) self.btStop.setSizePolicy(sizePolicyBt); self.btStop.setStyleSheet("background-color: red; font-size: 16px; font: bold") self.btStop.clicked.connect(self.stopAcquisition) self.btStop.setEnabled(False) self.paramTree = ParameterTree() self.paramTree.setParameters(Parameters.paramObject, showTop=False) self.paramTree.setWindowTitle('pyqtgraph example: Parameter Tree') self.paramTree.setMinimumWidth(350) self.paramTree.setMaximumWidth(350) sizePolicyPt = QtGui.QSizePolicy(1,1) sizePolicyPt.setHorizontalStretch(QtGui.QSizePolicy.Fixed) sizePolicyPt.setVerticalStretch(1) self.paramTree.setSizePolicy(sizePolicyPt); ## Create random 2D data data = np.random.normal(size=(512, 512)) + pg.gaussianFilter(np.random.normal(size=(512, 512)), (5, 5)) * 20 + 100 data = data[:,:,np.newaxis] data = data.repeat(3,2) self.plotTl = pg.GraphicsView() self.plotTlImage = pg.ImageItem(data[:,:,:]) #parent=self.plotTl self.plotTlViewBox = pg.ViewBox() self.plotTl.setCentralWidget(self.plotTlViewBox) self.plotTlViewBox.addItem(self.plotTlImage) self.plotTr = pg.PlotWidget(title="Interferometry", labels={'left': 'Signal amplitude (A.U.)', 'bottom': 'Distance (mm)'}) #self.plotTlViewBox2.addItem(self.plotTr) self.plotTrCurve = self.plotTr.plot(pen=(255,0,0),name='C1') #Red self.plotTrCurve2 = self.plotTr.plot(pen=(0,255,0),name='C2') #Green #self.plotTlViewBox2.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted #self.plotTr.addLegend('Test') self.plotTr.setYRange(-1000, 1000) self.plotBl = pg.PlotWidget(title="Distance", labels={'left': 'Distance (mm)', 'bottom': 'Number of acquisitions'}) self.plotBlCurve = self.plotBl.plot(pen=(255,0,0),name='C1') self.plotBl.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted self.plotBl.setMaximumWidth(3500) self.tbInfo = QtGui.QTextEdit() self.tbInfo.setEnabled(False) palette = self.tbInfo.palette() palette.setColor(QtGui.QPalette.Base, QtGui.QColor("white")) #White background self.tbInfo.setPalette(palette) self.tbInfo.setTextColor(QtGui.QColor("black")) self.tbInfo.insertPlainText("Useful information will appear here.") #Create list view of multiple items self.tbStatus = QtGui.QListView() self.tbStatus.setEnabled(False) palette = self.tbStatus.palette() palette.setColor(QtGui.QPalette.Base, QtGui.QColor("white")) #White background self.tbStatus.setPalette(palette) itemModelStatus = QtGui.QStandardItemModel(self.tbStatus) self.tbStatus.setModel(itemModelStatus) #Add system status self.itemStatus = QtGui.QStandardItem() self.setStatus(False) itemModelStatus.appendRow(self.itemStatus) #Add camera status self.itemCameraStatus = QtGui.QStandardItem() self.setCameraStatus(False) itemModelStatus.appendRow(self.itemCameraStatus) #Add memory usage self.itemMemory = QtGui.QStandardItem("Acquisition board memory usage: N/A") self.itemMemory.setForeground(QtGui.QColor("black")) itemModelStatus.appendRow(self.itemMemory) #Add max value position self.itemMaxValPos = QtGui.QStandardItem("Maximum RF value position: N/A") self.itemMaxValPos.setForeground(QtGui.QColor("black")) itemModelStatus.appendRow(self.itemMaxValPos) #layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) self.layout.addWidget(self.btOpen, 9, 6, 1, 1) self.layout.addWidget(self.btStart, 9, 7, 1, 1) self.layout.addWidget(self.btStop, 9, 8, 1, 1) self.layout.addWidget(self.paramTree, 0, 0, 10, 3) self.layout.addWidget(self.plotTl, 0, 3, 5, 3) self.layout.addWidget(self.plotTr, 0, 6, 5, 3) self.layout.addWidget(self.plotBl, 5, 3, 5, 3) self.layout.addWidget(self.tbInfo, 5, 6, 2, 3) self.layout.addWidget(self.tbStatus, 7, 6, 2, 3) self.layout.layout.setColumnStretch(3,1) self.layout.layout.setColumnStretch(4,1) self.layout.layout.setColumnStretch(5,1) self.layout.layout.setColumnStretch(6,1) self.layout.layout.setColumnStretch(7,1) self.layout.layout.setColumnStretch(8,1) self.show() self.resize(1500,800) self.move(100,100) Parameters.paramObject.param('Save/Restore functionality', 'Save State').sigActivated.connect(self.saveParam) Parameters.paramObject.param('Save/Restore functionality', 'Restore State').sigActivated.connect(self.restoreParam) Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").sigValueChanged.connect(self.motorSpeedChanged) Parameters.paramObject.child("Trigger Options", "Acquisition mode").sigValueChanged.connect(self.triggerChanged) Parameters.paramObject.child("Trigger Options", "Trigger amplitude").sigValueChanged.connect(self.triggerChanged) Parameters.paramObject.child("Trigger Options", "Trigger switch 1/2").sigActivated.connect(self.triggerHalfSwitch) # adding by emitting signal in different thread self.workThread = AcquisitionWorker() self.workThread.updateDataCamera.connect(self.setDataCurveTl) self.workThread.updateDataInterf.connect(self.setDataCurveTr) self.workThread.updateDataDistance.connect(self.setDataCurveBl) self.workThread.updateDataDistance2.connect(self.setDataCurveBl2) self.workThread.updateWire.connect(self.setWire) self.workThread.setStatus.connect(self.setStatus) self.workThread.setInfo.connect(self.setInfo) self.testCount = 0; #Fill the plots with dummy data self.data = np.random.normal(size=(10,1000)) self.plotTrXAxis = np.arange(1000) * (0.01) self.plotBlXAxis = np.arange(1000) * (1) self.plotTrCurve.setData(x=self.plotTrXAxis,y=self.data[2%10],name='C1') self.plotTrCurve2.setData(x=self.plotTrXAxis,y=self.data[3%10],name='C2') self.plotBlCurve.setData(x=self.plotBlXAxis,y=self.data[4%10],name='C1') self.valueTest = 1 def setDataCurveTl(self, data): self.dataImage1 = data self.plotTlImage.setImage(data) self.testCount = self.testCount + 1; def setDataCurveTr(self, dataIn): self.plotTrCurve.setData(dataIn[0:len(dataIn):2],name='C1') self.plotTrCurve2.setData(dataIn[1:len(dataIn):2],name='C2') def setDataCurveBl(self, dataIn): self.plotBlCurve.setData(dataIn,name='C1') def setDataCurveBl2(self, xIn, dataIn): self.plotBlCurve.setData(x=xIn,y=dataIn,name='C1')
class DiffractionGeometry(object): def __init__(self, parent = None): self.parent = parent ############################# ## Dock 3: Diffraction geometry ############################# self.d3 = Dock("Diffraction Geometry", size=(1, 1)) self.w3 = ParameterTree() self.w3.setWindowTitle('Diffraction geometry') self.d3.addWidget(self.w3) self.w3a = pg.LayoutWidget() self.deployGeomBtn = QtGui.QPushButton('Deploy manually centred geometry') self.w3a.addWidget(self.deployGeomBtn, row=0, col=0) self.deployAutoGeomBtn = QtGui.QPushButton('Deploy automatically centred geometry') self.w3a.addWidget(self.deployAutoGeomBtn, row=1, col=0) self.d3.addWidget(self.w3a) self.resolutionRingList = np.array([100.,300.,500.,700.,900.,1100.]) self.resolutionText = [] self.hasUserDefinedResolution = False self.geom_grp = 'Diffraction geometry' self.geom_detectorDistance_str = 'Detector distance' self.geom_clen_str = 'Home to Detector (clen)' self.geom_coffset_str = 'Sample to Home (coffset)' self.geom_photonEnergy_str = 'Photon energy' self.geom_wavelength_str = "Wavelength" self.geom_pixelSize_str = 'Pixel size' self.geom_resolutionRings_str = 'Resolution rings' self.geom_resolution_str = 'Resolution (pixels)' self.geom_resolutionUnits_str = 'Units' self.geom_unitA_crystal_str = 'Crystallography (Angstrom)' self.geom_unitNm_crystal_str = 'Crystallography (Nanometre)' self.geom_unitQ_crystal_str = 'Crystallography Reciprocal Space (q)' self.geom_unitA_physics_str = 'Physics (Angstrom)' self.geom_unitNm_physics_str = 'Physics (Nanometre)' self.geom_unitQ_physics_str = 'Physics Reciprocal Space (q)' self.geom_unitTwoTheta_str = 'Scattering Angle 2Theta' (self.unitA_c,self.unitNm_c,self.unitQ_c,self.unitA_p,self.unitNm_p,self.unitQ_p,self.unitTwoTheta) = (0,1,2,3,4,5,6) ####################### # Mandatory parameter # ####################### self.params = [ {'name': self.geom_grp, 'type': 'group', 'children': [ {'name': self.geom_detectorDistance_str, 'type': 'float', 'value': 0.0, 'precision': 6, 'minVal': 0.0001, 'siFormat': (6,6), 'siPrefix': True, 'suffix': 'mm'}, {'name': self.geom_clen_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_coffset_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_photonEnergy_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'eV'}, {'name': self.geom_wavelength_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_pixelSize_str, 'type': 'float', 'value': 0.0, 'precision': 12, 'minVal': 1e-6, 'siPrefix': True, 'suffix': 'm'}, {'name': self.geom_resolutionRings_str, 'type': 'bool', 'value': False, 'tip': "Display resolution rings", 'children': [ {'name': self.geom_resolution_str, 'type': 'str', 'value': None}, {'name': self.geom_resolutionUnits_str, 'type': 'list', 'values': {self.geom_unitA_crystal_str: self.unitA_c, self.geom_unitNm_crystal_str: self.unitNm_c, self.geom_unitQ_crystal_str: self.unitQ_c, self.geom_unitA_physics_str: self.unitA_p, self.geom_unitNm_physics_str: self.unitNm_p, self.geom_unitQ_physics_str: self.unitQ_p, self.geom_unitTwoTheta_str: self.unitTwoTheta}, 'value': self.unitA_c}, ]}, ]}, ] self.p1 = Parameter.create(name='paramsDiffractionGeometry', type='group', \ children=self.params, expanded=True) self.p1.sigTreeStateChanged.connect(self.change) self.w3.setParameters(self.p1, showTop=False) self.deployGeomBtn.clicked.connect(self.deploy) self.deployAutoGeomBtn.clicked.connect(self.autoDeploy) # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[1] == self.geom_detectorDistance_str: self.updateDetectorDistance(data) elif path[1] == self.geom_clen_str: pass elif path[1] == self.geom_coffset_str: pass elif path[1] == self.geom_photonEnergy_str: self.updatePhotonEnergy(data) elif path[1] == self.geom_pixelSize_str: self.updatePixelSize(data) elif path[1] == self.geom_wavelength_str: pass elif path[1] == self.geom_resolutionRings_str and len(path) == 2: self.updateResolutionRings(data) elif path[2] == self.geom_resolution_str: self.updateResolution(data) elif path[2] == self.geom_resolutionUnits_str: self.updateResolutionUnits(data) def findPsanaGeometry(self): try: self.source = Detector.PyDetector.map_alias_to_source(self.parent.detInfo, self.parent.exp.ds.env()) # 'DetInfo(CxiDs2.0:Cspad.0)' self.calibSource = self.source.split('(')[-1].split(')')[0] # 'CxiDs2.0:Cspad.0' self.detectorType = gu.det_type_from_source(self.source) # 1 self.calibGroup = gu.dic_det_type_to_calib_group[self.detectorType] # 'CsPad::CalibV1' self.detectorName = gu.dic_det_type_to_name[self.detectorType].upper() # 'CSPAD' if self.parent.args.localCalib: self.calibPath = "./calib/" + self.calibGroup + "/" + self.calibSource + "/geometry" else: self.calibPath = "/reg/d/psdm/" + self.parent.experimentName[0:3] + \ "/" + self.parent.experimentName + "/calib/" + \ self.calibGroup + "/" + self.calibSource + "/geometry" if self.parent.args.v >= 1: print "### calibPath: ", self.calibPath # Determine which calib file to use geometryFiles = os.listdir(self.calibPath) if self.parent.args.v >= 1: print "geom: ", geometryFiles self.calibFile = None minDiff = -1e6 for fname in geometryFiles: if fname.endswith('.data'): endValid = False startNum = int(fname.split('-')[0]) endNum = fname.split('-')[-1].split('.data')[0] diff = startNum - self.parent.runNumber # Make sure it's end number is valid too if 'end' in endNum: endValid = True else: try: if self.parent.runNumber <= int(endNum): endValid = True except: continue if diff <= 0 and diff > minDiff and endValid is True: minDiff = diff self.calibFile = fname except: if self.parent.args.v >= 1: print "Couldn't find psana geometry" self.calibFile = None def deployCrystfelGeometry(self, arg): if arg == 'lcls': self.findPsanaGeometry() if self.calibFile is not None and self.parent.writeAccess: # Convert psana geometry to crystfel geom if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName: if '.temp.geom' in self.parent.index.geom: self.parent.index.p9.param(self.parent.index.index_grp, self.parent.index.index_geom_str).setValue( self.parent.psocakeRunDir + '/.temp.geom') cmd = ["psana2crystfel", self.calibPath + '/' + self.calibFile, self.parent.psocakeRunDir + "/.temp.geom", str(self.parent.coffset)] if self.parent.args.v >= 1: print "cmd: ", cmd try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE) p.communicate()[0] p.stdout.close() except: print "Warning! deployCrystfelGeometry() failed." elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName: if '.temp.geom' in self.parent.index.geom: # Set GUI field to .temp.geom self.parent.index.p9.param(self.parent.index.index_grp, self.parent.index.index_geom_str).setValue( self.parent.psocakeRunDir + '/.temp.geom') cmd = ["psana2crystfel", self.calibPath + '/' + self.calibFile, self.parent.psocakeRunDir + "/.temp.geom", str(self.parent.coffset)] if self.parent.args.v >= 1: print "cmd: ", cmd try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE) p.communicate()[0] p.stdout.close() except: print "Warning! deployCrystfelGeometry() failed." elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName: if '.temp.geom' in self.parent.index.geom: # Set GUI field to .temp.geom self.parent.index.p9.param(self.parent.index.index_grp, self.parent.index.index_geom_str).setValue( self.parent.psocakeRunDir + '/.temp.geom') cmd = ["psana2crystfel", self.calibPath + '/' + self.calibFile, self.parent.psocakeRunDir + "/.temp.geom", str(self.parent.coffset)] if self.parent.args.v >= 1: print "cmd: ", cmd try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE) p.communicate()[0] p.stdout.close() except: print "Warning! deployCrystfelGeometry() failed." else: if self.parent.args.v >= 1: print "deployCrystfelGeometry not implemented", self.parent.detInfo.lower(), self.parent.experimentName def updateClen(self, arg): if arg == 'lcls': if ('cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName): self.p1.param(self.geom_grp, self.geom_clen_str).setValue(self.parent.clen) self.parent.coffset = self.parent.detectorDistance - self.parent.clen self.p1.param(self.geom_grp, self.geom_coffset_str).setValue(self.parent.coffset) if self.parent.args.v >= 1: print "Done updateClen: ", self.parent.coffset, self.parent.detectorDistance, self.parent.clen else: if self.parent.args.v >= 1: print "updateClen not implemented" def updateDetectorDistance(self, data): self.parent.detectorDistance = data / 1000. # mm to metres self.updateClen('lcls') if self.parent.args.v >= 1: print "!!!!!!coffset (m), detectorDistance (m), clen (m): ", self.parent.coffset, self.parent.detectorDistance, self.parent.clen self.writeCrystfelGeom('lcls') if self.hasGeometryInfo(): if self.parent.args.v >= 1: print "has geometry info" self.updateGeometry() self.parent.img.updatePolarizationFactor() if self.parent.exp.image_property == self.parent.exp.disp_radialCorrection: self.parent.img.updateImage() if self.parent.pk.showPeaks: self.parent.pk.updateClassification() if self.parent.args.v >= 1: print "Done updateDetectorDistance" def updatePhotonEnergy(self, data): if data > 0: self.parent.photonEnergy = data # E = hc/lambda h = 6.626070e-34 # J.m c = 2.99792458e8 # m/s joulesPerEv = 1.602176621e-19 #J/eV if self.parent.photonEnergy > 0: self.parent.wavelength = (h/joulesPerEv*c)/self.parent.photonEnergy else: self.parent.wavelength = 0 self.p1.param(self.geom_grp,self.geom_wavelength_str).setValue(self.parent.wavelength) if self.hasGeometryInfo(): self.updateGeometry() def updatePixelSize(self, data): self.parent.pixelSize = data if self.hasGeometryInfo(): self.updateGeometry() def hasGeometryInfo(self): if self.parent.detectorDistance is not None \ and self.parent.photonEnergy is not None \ and self.parent.pixelSize is not None: return True else: return False def writeCrystfelGeom(self, arg): if arg == 'lcls': if ('cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName): if self.parent.index.hiddenCXI is not None: if os.path.isfile(self.parent.index.hiddenCXI): f = h5py.File(self.parent.index.hiddenCXI,'r') encoderVal = f['/LCLS/detector_1/EncoderValue'][0] / 1000. # metres f.close() else: encoderVal = self.parent.clen # metres coffset = self.parent.detectorDistance - encoderVal if self.parent.args.v >= 1: print "&&&&&& coffset (m),detectorDistance (m) ,encoderVal (m): ", coffset, self.parent.detectorDistance, encoderVal # Replace coffset value in geometry file if '.temp.geom' in self.parent.index.geom and os.path.exists(self.parent.index.geom): for line in fileinput.input(self.parent.index.geom, inplace=True): if 'coffset' in line and line.strip()[0] is not ';': coffsetStr = line.split('=')[0]+"= "+str(coffset)+"\n" print coffsetStr, # comma is required else: print line, # comma is required else: if self.parent.args.v >= 1: print "writeCrystfelGeom not implemented" def updateGeometry(self): if self.hasUserDefinedResolution: self.myResolutionRingList = self.parent.resolution else: self.myResolutionRingList = self.resolutionRingList self.thetaMax = np.zeros_like(self.myResolutionRingList) self.dMin_crystal = np.zeros_like(self.myResolutionRingList) self.qMax_crystal = np.zeros_like(self.myResolutionRingList) self.dMin_physics = np.zeros_like(self.myResolutionRingList) self.qMax_physics = np.zeros_like(self.myResolutionRingList) for i, pix in enumerate(self.myResolutionRingList): if self.parent.detectorDistance > 0 and self.parent.wavelength is not None: self.thetaMax[i] = np.arctan(pix*self.parent.pixelSize/self.parent.detectorDistance) self.qMax_crystal[i] = 2/self.parent.wavelength*np.sin(self.thetaMax[i]/2) self.dMin_crystal[i] = 1/self.qMax_crystal[i] self.qMax_physics[i] = 4*np.pi/self.parent.wavelength*np.sin(self.thetaMax[i]/2) self.dMin_physics[i] = np.pi/self.qMax_physics[i] if self.parent.args.v >= 1: print "updateGeometry: ", i, self.thetaMax[i], self.dMin_crystal[i], self.dMin_physics[i] if self.parent.resolutionRingsOn: self.updateRings() if self.parent.args.v >= 1: print "Done updateGeometry" def updateDock42(self, data): a = ['a','b','c','d','e','k','m','n','r','s'] myStr = a[5]+a[8]+a[0]+a[5]+a[4]+a[7] if myStr in data: self.d42 = Dock("Console", size=(100,100)) # build an initial namespace for console commands to be executed in (this is optional; # the user can always import these modules manually) namespace = {'pg': pg, 'np': np, 'self': self} # initial text to display in the console text = "You have awoken the "+myStr+"\nWelcome to psocake IPython: dir(self)\n" \ "Here are some commonly used variables:\n" \ "unassembled detector: self.parent.calib\n" \ "assembled detector: self.parent.data\n" \ "user-defined mask: self.parent.mk.userMask\n" \ "streak mask: self.parent.mk.streakMask\n" \ "psana mask: self.parent.mk.psanaMask" self.w42 = pg.console.ConsoleWidget(parent=None,namespace=namespace, text=text) self.d42.addWidget(self.w42) self.parent.area.addDock(self.d42, 'bottom') def updateResolutionRings(self, data): self.parent.resolutionRingsOn = data if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print "Done updateResolutionRings" def updateResolution(self, data): # convert to array of floats _resolution = data.split(',') self.parent.resolution = np.zeros((len(_resolution,))) self.updateDock42(data) if data != '': for i in range(len(_resolution)): self.parent.resolution[i] = float(_resolution[i]) if data != '': self.hasUserDefinedResolution = True else: self.hasUserDefinedResolution = False self.myResolutionRingList = self.parent.resolution self.dMin = np.zeros_like(self.myResolutionRingList) if self.hasGeometryInfo(): self.updateGeometry() if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print "Done updateResolution" def updateResolutionUnits(self, data): # convert to array of floats self.parent.resolutionUnits = data if self.hasGeometryInfo(): self.updateGeometry() if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print "Done updateResolutionUnits" def updateRings(self): if self.parent.resolutionRingsOn: self.clearRings() cenx = np.ones_like(self.myResolutionRingList)*self.parent.cx ceny = np.ones_like(self.myResolutionRingList)*self.parent.cy diameter = 2*self.myResolutionRingList self.parent.img.ring_feature.setData(cenx, ceny, symbol='o', \ size=diameter, brush=(255,255,255,0), \ pen='r', pxMode=False) for i,val in enumerate(self.dMin_crystal): if self.parent.resolutionUnits == self.unitA_c: self.resolutionText.append(pg.TextItem(text='%s A' % float('%.3g' % (val*1e10)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitNm_c: self.resolutionText.append(pg.TextItem(text='%s nm' % float('%.3g' % (val*1e9)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitQ_c: self.resolutionText.append(pg.TextItem(text='%s m^-1' % float('%.3g' % (self.qMax_crystal[i])), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitA_p: self.resolutionText.append(pg.TextItem(text='%s A' % float('%.3g' % (self.dMin_physics[i]*1e10)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitNm_p: self.resolutionText.append(pg.TextItem(text='%s nm' % float('%.3g' % (self.dMin_physics[i]*1e9)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitQ_p: self.resolutionText.append(pg.TextItem(text='%s m^-1' % float('%.3g' % (self.qMax_physics[i])), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitTwoTheta: self.resolutionText.append(pg.TextItem(text='%s degrees' % float('%.3g' % (self.thetaMax[i]*180/np.pi)), border='w', fill=(0, 0, 255, 100))) self.parent.img.w1.getView().addItem(self.resolutionText[i]) self.resolutionText[i].setPos(self.myResolutionRingList[i]+self.parent.cx, self.parent.cy) else: self.clearRings() if self.parent.args.v >= 1: print "Done updateRings" def drawCentre(self): # Always indicate centre of detector try: self.parent.img.centre_feature.setData(np.array([self.parent.cx]), np.array([self.parent.cy]), symbol='o', \ size=6, brush=(255, 255, 255, 0), pen='r', pxMode=False) if self.parent.args.v >= 1: print "Done drawCentre" except: pass def clearRings(self): if self.resolutionText: cen = [0,] self.parent.img.ring_feature.setData(cen, cen, size=0) for i,val in enumerate(self.resolutionText): self.parent.img.w1.getView().removeItem(self.resolutionText[i]) self.resolutionText = [] def deploy(self): with pg.BusyCursor(): # Calculate detector translation in x and y dx = self.parent.pixelSize * 1e6 * (self.parent.cx - self.parent.roi.centreX) # microns dy = self.parent.pixelSize * 1e6 * (self.parent.cy - self.parent.roi.centreY) # microns dz = np.mean(self.parent.det.coords_z(self.parent.evt)) - self.parent.detectorDistance*1e6 # microns geo = self.parent.det.geometry(self.parent.evt) if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName: geo.move_geo('CSPAD:V1', 0, dx=dx, dy=dy, dz=-dz) elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName: top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=dx, dy=dy, dz=-dz) elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName: top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=dx, dy=dy, dz=-dz) else: print "deploy not implemented" fname = self.parent.psocakeRunDir + "/"+str(self.parent.runNumber)+'-end.data' geo.save_pars_in_file(fname) print "#################################################" print "Deploying psana detector geometry: ", fname print "#################################################" cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'recentred geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = '/reg/d/psdm/'+self.parent.experimentName[:3]+'/'+self.parent.experimentName+'/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=fname, dcmts=cmts, pbits=0) # Reload new psana geometry self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.updateRings() self.parent.index.updateIndex() self.drawCentre() def autoDeploy(self): with pg.BusyCursor(): powderHits = np.load(self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '_maxHits.npy') powderMisses = np.load(self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '_maxMisses.npy') powderImg = self.parent.det.image(self.parent.evt, np.maximum(powderHits,powderMisses)) centreRow, centreCol = findDetectorCentre(np.log(abs(powderImg)), self.parent.cx, self.parent.cy, range=200) print("Current centre along row,centre along column: ", self.parent.cx, self.parent.cy) print("Optimum centre along row,centre along column: ", centreRow, centreCol) allowedDeviation = 175 # pixels if abs(self.parent.cx - centreRow) <= allowedDeviation and \ abs(self.parent.cy - centreCol) <= allowedDeviation: deploy = True else: deploy = False print "Too far away from current centre. I will not deploy the auto centred geometry." if deploy: # Calculate detector translation in x and y dx = self.parent.pixelSize * 1e6 * (self.parent.cx - centreRow) # microns dy = self.parent.pixelSize * 1e6 * (self.parent.cy - centreCol) # microns dz = np.mean(self.parent.det.coords_z(self.parent.evt)) - self.parent.detectorDistance * 1e6 # microns geo = self.parent.det.geometry(self.parent.evt) if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName: geo.move_geo('CSPAD:V1', 0, dx=dx, dy=dy, dz=-dz) elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName: top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=dx, dy=dy, dz=-dz) elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName: top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=dx, dy=dy, dz=-dz) else: print "autoDeploy not implemented" fname = self.parent.psocakeRunDir + "/" + str(self.parent.runNumber) + '-end.data' geo.save_pars_in_file(fname) print "#################################################" print "Deploying psana detector geometry: ", fname print "#################################################" cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'auto recentred geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = '/reg/d/psdm/' + self.parent.experimentName[:3] + '/' + self.parent.experimentName + '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=fname, dcmts=cmts, pbits=0) # Reload new psana geometry self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.updateRings() self.parent.index.updateIndex() self.drawCentre()
class TrackingExperimentWindow(SimpleExperimentWindow): """Window for controlling an experiment where the tail of an embedded fish is tracked. Parameters ---------- Returns ------- """ def __init__(self, tracking=True, tail=False, eyes=False, *args, **kwargs): # TODO refactor movement detection self.tracking = tracking self.tail = tail self.eyes = eyes if tail or eyes: self.camera_display = CameraEmbeddedTrackingSelection( experiment=kwargs["experiment"], tail=tail, eyes=eyes) else: self.camera_display = CameraViewWidget( experiment=kwargs["experiment"]) self.camera_splitter = QSplitter(Qt.Horizontal) self.monitoring_widget = QWidget() self.monitoring_layout = QVBoxLayout() self.monitoring_widget.setLayout(self.monitoring_layout) # Stream plot: # if eyes: time_past = 30 # else: # time_past = 5 self.stream_plot = MultiStreamPlot(time_past=time_past) self.monitoring_layout.addWidget(self.stream_plot) # Tracking params button: self.button_tracking_params = QPushButton( "Tracking params" if tracking else "Movement detection params") self.button_tracking_params.clicked.connect( self.open_tracking_params_tree) self.monitoring_layout.addWidget(self.button_tracking_params) self.track_params_wnd = None super().__init__(*args, **kwargs) def construct_ui(self): """ """ self.experiment.gui_timer.timeout.connect(self.stream_plot.update) previous_widget = super().construct_ui() previous_widget.layout().setContentsMargins(0, 0, 0, 0) self.monitoring_layout.addWidget(previous_widget) self.monitoring_layout.setStretch(1, 1) self.monitoring_layout.setStretch(0, 1) self.camera_splitter.addWidget(self.camera_display) self.camera_splitter.addWidget(self.monitoring_widget) return self.camera_splitter def open_tracking_params_tree(self): """ """ self.track_params_wnd = ParameterTree() self.track_params_wnd.addParameters( self.experiment.tracking_method.params) self.track_params_wnd.addParameters( self.experiment.preprocessing_method.params) self.track_params_wnd.setWindowTitle("Tracking parameters") self.track_params_wnd.show()
def _init_extra(self,**kw): self.neuron=kw.get('base_neuron') self.neuron_params=kw.get('neuron_params') for d in self.neuron_params[0]['children']: if 'children' in d.keys(): for dd in d['children']: self.__dict__[dd['name']] = dd['value'] else: pp(d) if 'value' in d.keys(): self.__dict__[d['name']] = d['value'] self.dyn_xticks=[[100*i,i*0.1] for i in range(0,22,4)] self.script_name=kw.get('script_name', __file__.split('/')[-1][0:-3]) self.p.param('store_state', 'save').sigActivated.connect(self.save) self.p.param('stimulate', 'start').sigActivated.connect(self.stimulate) # Comet for recovery current vs time plot w=pg.PlotWidget() w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('Current', units='A') w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current') w.setRange(QtCore.QRectF(0, -200, self.n_history, 400)) w.setLabel('bottom', 'Time', units='s') w.plotItem.layout.setContentsMargins(20, 20, 20, 20) color=self.kw.get('curve_uv_color',(0,0,0)) pen=pg.mkPen(color, width=self.kw.get('curve_uv_width',5)) self.curve_ut = w.plot(pen=pen) self.widgets.append(w) # Comet for voltage recovery current plot w=pg.PlotWidget() w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('Recovery current u', units='A') w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current/voltage') w.setRange(QtCore.QRectF(-100, -50, 100, 200)) w.setLabel('bottom', 'Voltage', units='V') w.plotItem.layout.setContentsMargins(10, 10, 10, 10) self.widgets.append(w) color=self.kw.get('curve_uv_color',(0,0,0)) pen=pg.mkPen(color, width=self.kw.get('curve_uv_width',5) ) self.curve_uv = w.plot(pen=pen) # x,y=self.get_nullcline_extreme_points() # self.curve_uv_extreme_point = w.plot(x,y, pen=pen) color=self.kw.get('curve_uv_color',(0,0,0)) self.curve_uv_nullcline0 = w.plot(pen=pen) self.curve_uv_nullcline1 = w.plot(pen=pen) color=self.kw.get('curve_uv_color',(255,0,0)) brush=pg.mkBrush(color=color) self.curve_uv_comet= w.plot(symbolBrush= brush, symbol='o', symbolSize=15.) # Parameters base_neuron self.p2 = Parameter.create(name='params', type='group', children=self.neuron_params) self.p2.sigTreeStateChanged.connect(self.change) self.p2.param('IV, IF, nullcline, etc', 'run base_neuron').sigActivated.connect(self.run_neuron_thread) self.p2.param('IV, IF, nullcline, etc', 'run GP-ST network').sigActivated.connect(self.run_GP_STN_network_thread) pt = ParameterTree() pt.setParameters(self.p2, showTop=False) pt.setWindowTitle('Parameters') self.widgets.append(pt) # Threshold type w=pg.PlotWidget() # w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('a/g_L') # w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current/voltage') w.setRange(QtCore.QRectF(0, 0, 4, 1)) w.setLabel('bottom', 'tau_m/tau_w') w.plotItem.layout.setContentsMargins(10, 10, 10, 10) self.widgets.append(w) color=self.kw.get('curve_uv_color',(0,0,0)) pen=pg.mkPen(color, width=self.kw.get('curve_uv_width',5) ) c1,c2=self.get_threshold_oscillation_curves() x, y=self.get_threshold_oscilltion_point() color=self.kw.get('curve_uv_color',(255,0,0)) brush=pg.mkBrush(color=color) self.curve_oscillation1 = w.plot(c1[0],c1[1],pen=pen) self.curve_oscillation2 = w.plot(c2[0],c2[1],pen=pen) self.curve_oscillation_points1 = w.plot([x[0]], [y[0]], symbolBrush= brush, symbol='o', symbolSize=25.) color=self.kw.get('curve_uv_color',(0,0,255)) brush=pg.mkBrush(color=color) self.curve_oscillation_points2 = w.plot([x[1]], [y[1]], symbolBrush= brush, symbol='o', symbolSize=15.) self.draw()
def __init__(self, **kw): self.app=kw.pop('app') self.data_label='' self.date_time=dt.datetime.now().strftime('%Y_%m_%d-%H_%M') self.h=kw.pop('h', .1) #integration step size self.n_state_variables=kw.pop('n_state_variables', 2) self.n_history=kw.pop('n_history', 2000) self.kw=kw self.params=kw.get('params') #qt paramters, se tree parameter class self.update_time=kw.pop('update_time', 0) self.widgets=[] self.script_name=kw.pop('script_name',__file__.split('/')[-1][0:-3]) self.start_stim=-10000.0 self.scale_plot=10 for key, value in kw.items(): self.__dict__[key] = value for d in self.params[0]['children']: self.__dict__[d['name']] = d['value'] for d in self.params[1]['children']: if 'value' in d.keys(): self.__dict__[d['name']] = d['value'] self.x=self.n_history self.y=numpy.zeros(self.n_state_variables) self.y[0]=-70 self.dy=numpy.zeros(self.n_state_variables) self.x_history=numpy.arange(0,self.n_history, self.scale_plot*self.h) self.y_history=numpy.random.rand( self.n_state_variables, self.n_history/(self.scale_plot*self.h)) self.y_history[0,:]=-70 # Parameters self.p = Parameter.create(name='params', type='group', children=self.params) self.p.sigTreeStateChanged.connect(self.change) pt = ParameterTree() pt.setParameters(self.p, showTop=False) pt.setWindowTitle('Parameters') self.widgets.append(pt) # Voltage time plot w=pg.PlotWidget() w.setWindowTitle('Voltage/time') w.setRange(QtCore.QRectF(0, -90, self.n_history, 100)) w.setLabel('bottom', 'Time', units='s') w.plotItem.layout.setContentsMargins(20, 20, 20, 20) ax=w.plotItem.getAxis('left') l=[[ (0.0,'0'), (-30, -30), (-60, -60), (-90, -90) ], ] ax.setTicks(l) w.plotItem.getAxis('bottom').setScale(0.001) ax.setLabel('Voltage', units='V') ax.setScale(0.001) # ax.setWidth(w=2) # ax.setRange(500,1500) color=self.kw.get('curve_uv_color',(0,0,0)) pen=pg.mkPen(color, width=self.kw.get('curve_uv_width',5)) self.curve_vt = w.plot(pen=pen) self.curve_vt.setData(self.x_history, self.y_history[0,:]) self.widgets.append(w) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update) self.timer.start(self.update_time) # self.timer.start(1000.) self._init_extra(**kw)
mars_mis = mars1_disable | mars2_disable | mars3_disable | mars_delays print("mars clock %04X" % mars_clock) zc.write(52, mars_clock) print("test pulser %X" % test_pulse) zc.write(32, test_pulse) print("MARS mis %X" % mars_mis) zc.write(56, mars_mis) p2.param('Global actons', 'Set actions').sigActivated.connect(global_set) p2.param('Load MARS', 'Load State').sigActivated.connect(load_MARS) p2.param('Load MARS', 'Global reset').sigActivated.connect(MARS_reset) # Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('MARS settings') t2 = ParameterTree() t2.setParameters(p2, showTop=False) win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget(QtGui.QLabel(" MARS Parameters "), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(800, 800) # test save/restore s = p.saveState() p.restoreState(s)
def setupGUI(self): """Setup GUI""" self.layout = QtGui.QVBoxLayout() self.layout.setContentsMargins(0,0,0,0) self.setLayout(self.layout) self.splitter = QtGui.QSplitter() self.splitter.setOrientation(QtCore.Qt.Vertical) self.splitter.setSizes([int(self.height()*0.5), int(self.height()*0.5)]); self.layout.addWidget(self.splitter) self.splitter2 = QtGui.QSplitter() self.splitter2.setOrientation(QtCore.Qt.Horizontal) #self.splitter2.setSizes([int(self.width()*0.5), int(self.width()*0.5)]); self.splitter.addWidget(self.splitter2); self.splitter3 = QtGui.QSplitter() self.splitter3.setOrientation(QtCore.Qt.Horizontal) #self.splitter2.setSizes([int(self.width()*0.5), int(self.width()*0.5)]); self.splitter.addWidget(self.splitter3); # various matrix like plots: state, goal, weights, p self.nStates = 20; #number of states in the past to remember self.matrixdata = [np.zeros((self.network.nInputs, self.nStates)), np.zeros((self.network.nOutputs, self.nStates)), np.zeros((self.network.nOutputs, self.nStates)), np.zeros((self.network.nNodes, self.nStates)), np.zeros(self.network.weights.shape)]; #np.zeros(self.network.a.shape) #np.zeros(self.network.b.shape)]; self.images = []; for j in range(len(self.matrixdata)): l = pg.GraphicsLayoutWidget() self.splitter2.addWidget(l); v = pg.ViewBox(); l.addItem(v, 0, 1); i = pg.ImageItem(self.matrixdata[j]); v.addItem(i); self.images.append(i); for i in [0,1,2,3]: self.images[i].setLevels([0,1]); #output and error self.plotlayout = pg.GraphicsLayoutWidget(); self.splitter3.addWidget(self.plotlayout); self.plot = []; for i in range(2): self.plot.append(self.plotlayout.addPlot()); self.plot[i].setYRange(0, 1, padding=0); self.plotlength = 10000; self.output = np.zeros((self.network.nOutputs, self.plotlength)); #self.goal = np.zeros((self.network.nOutputs, self.plotlength)); self.errorlength = 10000; self.error = np.zeros(self.errorlength); self.curves = [] for i in range(self.network.nOutputs): c = self.plot[0].plot(self.output[i,:], pen = (i, self.network.nOutputs)); #c.setPos(0,0*i*6); self.curves.append(c); c = self.plot[1].plot(self.error, pen = (2,3)); self.curves.append(c); # parameter controls self.steps = 0; params = [ {'name': 'Controls', 'type': 'group', 'children': [ {'name': 'Simulate', 'type': 'bool', 'value': True, 'tip': "Run the network simulation"}, {'name': 'Plot', 'type': 'bool', 'value': True, 'tip': "Check to plot network evolution"}, {'name': 'Plot Interval', 'type': 'int', 'value': 10, 'tip': "Step between plot updates"}, {'name': 'Timer', 'type': 'int', 'value': 10, 'tip': "Pause between plot is updated"}, ]} , {'name': 'Network Parameter', 'type': 'group', 'children': [ {'name': 'Eta', 'type': 'float', 'value': self.network.eta, 'tip': "Learning rate"}, {'name': 'Gamma', 'type': 'float', 'value': self.network.gamma, 'tip': "Learning rate"}#, ]} , {'name': 'Status', 'type': 'group', 'children': [ {'name': 'Steps', 'type': 'int', 'value': self.steps, 'tip': "Actual iteration step", 'readonly': True} ]} ]; self.parameter = Parameter.create(name = 'Parameter', type = 'group', children = params); print self.parameter print self.parameter.children() self.parameter.sigTreeStateChanged.connect(self.updateParameter); ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree(); t.setParameters(self.parameter, showTop=False) t.setWindowTitle('Parameter'); self.splitter3.addWidget(t); # draw network self.nsteps = 100; self.updateView();
def run_gui(path=None, data=None): """ Loads PCF or CNMF data object from a provided path and loads the CaImAn GUI for component inspection. This GUI was tweaked to not require any storage-intensive mmap files, but can therefore not show individual frames. :param path: optional str, directory of the PCF or CNMF object from which component data should be loaded. If None and data=None, a window prompt will open to select a directory where to look for a CNMF/PCF file. :param data: optional, data in form of an already loaded cnm object can be provided directly :return: """ try: cv2.setNumThreads(1) except: print('Open CV is naturally single threaded') try: if __IPYTHON__: # print(1) # this is used for debugging purposes only. allows to reload classes # when changed get_ipython().magic('load_ext autoreload') get_ipython().magic('autoreload 2') except NameError: print('Not launched under iPython') def make_color_img(img, gain=255, min_max=None, out_type=np.uint8): if min_max is None: min_ = img.min() max_ = img.max() else: min_, max_ = min_max img = (img - min_) / (max_ - min_) * gain img = img.astype(out_type) img = np.dstack([img] * 3) return img ### FIND DATA ### if data is None: # different conditions on file loading (not necessary if data was already provided) if path is None: # if no path has been given, open a window prompt to select a directory F = FileDialog() # load object saved by CNMF path = F.getExistingDirectory( caption='Select folder from which to load a PCF or CNMF file') try: # first try to get CNMF data from a PCF object (should be most up-to-date) cnm_obj = pipe.load_pcf(path).cnmf except FileNotFoundError: try: cnm_obj = pipe.load_cnmf(path) except FileNotFoundError: raise FileNotFoundError( f'Could not find data to load in {path}!') else: cnm_obj = data # movie NOT NEEDED IN VERSION WITHOUT MMAP FILE # if not os.path.exists(cnm_obj.mmap_file): # M = FileDialog() # cnm_obj.mmap_file = M.getOpenFileName(caption='Load memory mapped file', filter='*.mmap')[0] # # if fpath[-3:] == 'nwb': # mov = cm.load(cnm_obj.mmap_file, var_name_hdf5='acquisition/TwoPhotonSeries') # else: # mov = cm.load(cnm_obj.mmap_file) estimates = cnm_obj.estimates params_obj = cnm_obj.params # min_mov = np.min(mov) # max_mov = np.max(mov) if not hasattr(estimates, 'Cn'): if not os.path.exists(cnm_obj.mmap_file): M = FileDialog() cnm_obj.mmap_file = M.getOpenFileName( caption='Load memory mapped file', filter='*.mmap')[0] mov = cm.load(cnm_obj.mmap_file) estimates.Cn = cm.local_correlations(mov, swap_dim=False) Cn = estimates.Cn # min_mov_denoise = np.min(estimates.A)*estimates.C.min() # max_mov_denoise = np.max(estimates.A)*estimates.C.max() background_num = -1 neuron_selected = False nr_index = 0 min_background = np.min(estimates.b, axis=0) * np.min(estimates.f, axis=1) max_background = np.max(estimates.b, axis=0) * np.max(estimates.f, axis=1) if not hasattr(estimates, 'accepted_list'): # if estimates.discarded_components.A.shape[-1] > 0: # estimates.restore_discarded_components() estimates.accepted_list = np.array([], dtype=np.int) estimates.rejected_list = np.array([], dtype=np.int) estimates.img_components = estimates.A.toarray().reshape( (estimates.dims[0], estimates.dims[1], -1), order='F').transpose([2, 0, 1]) estimates.cms = np.array([ scipy.ndimage.measurements.center_of_mass(comp) for comp in estimates.img_components ]) estimates.idx_components = np.arange(estimates.nr) estimates.idx_components_bad = np.array([]) estimates.background_image = make_color_img(estimates.Cn) # Generate image data estimates.img_components /= estimates.img_components.max( axis=(1, 2))[:, None, None] estimates.img_components *= 255 estimates.img_components = estimates.img_components.astype(np.uint8) def draw_contours_overall(md): if md is "reset": draw_contours() elif md is "neurons": if neuron_selected is True: #if a specific neuron has been selected, only one contour should be changed while thrshcomp_line is changing if nr_index is 0: #if user does not start to move through the frames draw_contours_update(estimates.background_image, img) draw_contours_update(comp2_scaled, img2) else: # NEVER CALLED IN THIS VERSION WITHOUT MMAP SINCE NR_INDEX NEVER CHANGES (NO NR_VLINE) draw_contours_update(raw_mov_scaled, img) draw_contours_update(frame_denoise_scaled, img2) else: #if no specific neuron has been selected, all the contours are changing draw_contours() else: #md is "background": return def draw_contours(): global thrshcomp_line, estimates, img bkgr_contours = estimates.background_image.copy() if len(estimates.idx_components) > 0: contours = [ cv2.findContours( cv2.threshold(img, np.int(thrshcomp_line.value()), 255, 0)[1], cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0] for img in estimates.img_components[estimates.idx_components] ] SNRs = np.array(estimates.r_values) iidd = np.array(estimates.idx_components) idx1 = np.where(SNRs[iidd] < 0.1)[0] idx2 = np.where((SNRs[iidd] >= 0.1) & (SNRs[iidd] < 0.25))[0] idx3 = np.where((SNRs[iidd] >= 0.25) & (SNRs[iidd] < 0.5))[0] idx4 = np.where((SNRs[iidd] >= 0.5) & (SNRs[iidd] < 0.75))[0] idx5 = np.where((SNRs[iidd] >= 0.75) & (SNRs[iidd] < 0.9))[0] idx6 = np.where(SNRs[iidd] >= 0.9)[0] cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx1], []), -1, (255, 0, 0), 1) cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx2], []), -1, (0, 255, 0), 1) cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx3], []), -1, (0, 0, 255), 1) cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx4], []), -1, (255, 255, 0), 1) cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx5], []), -1, (255, 0, 255), 1) cv2.drawContours(bkgr_contours, sum([contours[jj] for jj in idx6], []), -1, (0, 255, 255), 1) img.setImage(bkgr_contours, autoLevels=False) # pg.setConfigOptions(imageAxisOrder='row-major') def draw_contours_update(cf, im): global thrshcomp_line, estimates curFrame = cf.copy() if len(estimates.idx_components) > 0: contours = [ cv2.findContours( cv2.threshold(img, np.int(thrshcomp_line.value()), 255, 0)[1], cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0] for img in estimates.img_components[estimates.idx_components] ] SNRs = np.array(estimates.r_values) iidd = np.array(estimates.idx_components) idx1 = np.where(SNRs[iidd] < 0.1)[0] idx2 = np.where((SNRs[iidd] >= 0.1) & (SNRs[iidd] < 0.25))[0] idx3 = np.where((SNRs[iidd] >= 0.25) & (SNRs[iidd] < 0.5))[0] idx4 = np.where((SNRs[iidd] >= 0.5) & (SNRs[iidd] < 0.75))[0] idx5 = np.where((SNRs[iidd] >= 0.75) & (SNRs[iidd] < 0.9))[0] idx6 = np.where(SNRs[iidd] >= 0.9)[0] if min_dist_comp in idx1: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (255, 0, 0), 1) if min_dist_comp in idx2: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (0, 255, 0), 1) if min_dist_comp in idx3: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (0, 0, 255), 1) if min_dist_comp in idx4: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (255, 255, 0), 1) if min_dist_comp in idx5: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (255, 0, 255), 1) if min_dist_comp in idx6: cv2.drawContours(curFrame, contours[min_dist_comp], -1, (0, 255, 255), 1) im.setImage(curFrame, autoLevels=False) #%% START BUILDING THE APPLICATION WINDOW # Always start by initializing Qt (only once per application) app = QtGui.QApplication([]) # Define a top-level widget to hold everything w = QtGui.QWidget() # Create some widgets to be placed inside btn = QtGui.QPushButton('press me') text = QtGui.QLineEdit('enter text') # Histogram controller (win) win = pg.GraphicsLayoutWidget() win.setMaximumWidth(300) win.setMinimumWidth(200) hist = pg.HistogramLUTItem() # Contrast/color control win.addItem(hist) # Plotting windows p1 = pg.PlotWidget( ) # raw movie window (top-mid), all contours are drawn here p2 = pg.PlotWidget( ) # trace window (bottom-mid), calcium trace of the selected component p3 = pg.PlotWidget( ) # denoised movie window (top-right), only selected contour is drawn here # parameter table for online evaluation and mode change t = ParameterTree() # parameter table for neuron selection/sorting t_action = ParameterTree() action_layout = QtGui.QGridLayout() ## Create a grid layout to manage the widgets size and position layout = QtGui.QGridLayout() w.setLayout(layout) # A plot area (ViewBox + axes) for displaying the image #p1 = win.addPlot(title="Image here") # Item for displaying image data img = pg.ImageItem() p1.addItem(img) img2 = pg.ImageItem() p3.addItem(img2) hist.setImageItem(img) # Draggable line for setting isocurve level thrshcomp_line = pg.InfiniteLine(angle=0, movable=True, pen='g') hist.vb.addItem(thrshcomp_line) hist.vb.setMouseEnabled(y=False) # makes user interaction a little easier thrshcomp_line.setValue(100) thrshcomp_line.setZValue(1000) # bring iso line above contrast controls ## Add widgets to the layout in their proper positions layout.addWidget(win, 1, 0) # histogram layout.addWidget(p3, 0, 2) # denoised movie layout.addWidget(t, 0, 0) # upper-right table layout.addWidget(t_action, 1, 2) # bottom-right table layout.addWidget(p1, 0, 1) # raw movie layout.addWidget(p2, 1, 1) # calcium trace window #enable only horizontal zoom for the traces component p2.setMouseEnabled(x=True, y=False) ## Display the widget as a new window w.show() ## Start the Qt event loop app.exec_() draw_contours() hist.setLevels(estimates.background_image.min(), estimates.background_image.max()) # Another plot area for displaying ROI data #win.nextRow() #p2 = win.addPlot(colspan=2) p2.setMaximumHeight(250) #win.resize(800, 800) #win.show() # set position and scale of image img.scale(1, 1) # img.translate(-50, 0) # zoom to fit image p1.autoRange() mode = "reset" p2.setTitle("mode: %s" % (mode)) thrshcomp_line.sigDragged.connect(lambda: draw_contours_overall(mode)) def imageHoverEvent(event): #Show the position, pixel, and value under the mouse cursor. global x, y, i, j, val pos = event.pos() i, j = pos.y(), pos.x() i = int(np.clip(i, 0, estimates.background_image.shape[0] - 1)) j = int(np.clip(j, 0, estimates.background_image.shape[1] - 1)) val = estimates.background_image[i, j, 0] ppos = img.mapToParent(pos) x, y = ppos.x(), ppos.y() # Monkey-patch the image to use our custom hover function. # This is generally discouraged (you should subclass ImageItem instead), # but it works for a very simple use like this. img.hoverEvent = imageHoverEvent def mouseClickEvent(event): global mode global x, y, i, j, val pos = img.mapFromScene(event.pos()) x = int(pos.x()) y = int(pos.y()) if x < 0 or x > mov.shape[1] or y < 0 or y > mov.shape[2]: # if the user click outside of the movie, do nothing and jump out of the function return i, j = pos.y(), pos.x() i = int(np.clip(i, 0, estimates.background_image.shape[0] - 1)) j = int(np.clip(j, 0, estimates.background_image.shape[1] - 1)) val = estimates.background_image[i, j, 0] if mode is "neurons": show_neurons_clicked() p1.mousePressEvent = mouseClickEvent #A general rule in Qt is that if you override one mouse event handler, you must override all of them. def release(event): pass p1.mouseReleaseEvent = release def move(event): pass p1.mouseMoveEvent = move ## PARAMS params = [{ 'name': 'min_cnn_thr', 'type': 'float', 'value': 0.99, 'limits': (0, 1), 'step': 0.01 }, { 'name': 'cnn_lowest', 'type': 'float', 'value': 0.1, 'limits': (0, 1), 'step': 0.01 }, { 'name': 'rval_thr', 'type': 'float', 'value': 0.85, 'limits': (-1, 1), 'step': 0.01 }, { 'name': 'rval_lowest', 'type': 'float', 'value': -1, 'limits': (-1, 1), 'step': 0.01 }, { 'name': 'min_SNR', 'type': 'float', 'value': 2, 'limits': (0, 20), 'step': 0.1 }, { 'name': 'SNR_lowest', 'type': 'float', 'value': 0, 'limits': (0, 20), 'step': 0.1 }, { 'name': 'RESET', 'type': 'action' }, { 'name': 'SHOW BACKGROUND', 'type': 'action' }, { 'name': 'SHOW NEURONS', 'type': 'action' }] ## Create tree of Parameter objects pars = Parameter.create(name='params', type='group', children=params) params_action = [{ 'name': 'Filter components', 'type': 'bool', 'value': True, 'tip': "Filter components" }, { 'name': 'View components', 'type': 'list', 'values': ['All', 'Accepted', 'Rejected', 'Unassigned'], 'value': 'All' }, { 'name': 'ADD GROUP', 'type': 'action' }, { 'name': 'REMOVE GROUP', 'type': 'action' }, { 'name': 'ADD SINGLE', 'type': 'action' }, { 'name': 'REMOVE SINGLE', 'type': 'action' }, { 'name': 'SAVE OBJECT', 'type': 'action' }] pars_action = Parameter.create(name='params_action', type='group', children=params_action) t_action.setParameters(pars_action, showTop=False) t_action.setWindowTitle('Parameter Action') def reset_button(): global mode mode = "reset" p2.setTitle("mode: %s" % (mode)) #clear the upper right image zeros = np.asarray([[0] * 80 for _ in range(60)]) img2.setImage(make_color_img(zeros), autoLevels=False) draw_contours() pars.param('RESET').sigActivated.connect(reset_button) def show_background_button(): global bg_vline, min_background, max_background, background_num global mode, background_first_frame_scaled #clear thhe upper right image zeros = np.asarray([[0] * 80 for _ in range(60)]) img2.setImage(make_color_img(zeros), autoLevels=False) background_num = (background_num + 1) % estimates.f.shape[0] mode = "background" p2.setTitle("mode: %s %d" % (mode, background_num)) # display the first frame of the background background_first_frame = estimates.b[:, background_num].reshape( estimates.dims, order='F') min_background_first_frame = np.min(background_first_frame) max_background_first_frame = np.max(background_first_frame) background_first_frame_scaled = make_color_img( background_first_frame, min_max=(min_background_first_frame, max_background_first_frame)) img.setImage(background_first_frame_scaled, autoLevels=False) # draw the trace and the infinite line trace_background = estimates.f[background_num] p2.plot(trace_background, clear=True) bg_vline = pg.InfiniteLine(angle=90, movable=True) p2.addItem(bg_vline, ignoreBounds=True) bg_vline.setValue(0) bg_vline.sigPositionChanged.connect(show_background_update) def show_background_update(): global bg_index, min_background, max_background, background_scaled bg_index = int(bg_vline.value()) if bg_index > -1 and bg_index < estimates.f.shape[-1]: # upper left component scrolls through the frames of the background background = estimates.b[:, background_num].dot( estimates.f[background_num, bg_index]).reshape(estimates.dims, order='F') background_scaled = make_color_img( background, min_max=(min_background[background_num], max_background[background_num])) img.setImage(background_scaled, autoLevels=False) pars.param('SHOW BACKGROUND').sigActivated.connect(show_background_button) def show_neurons_button(): global mode, neuron_selected mode = "neurons" neuron_selected = False p2.setTitle("mode: %s" % (mode)) #clear the upper right image zeros = np.asarray([[0] * 80 for _ in range(60)]) img2.setImage(make_color_img(zeros), autoLevels=False) def show_neurons_clicked(): global nr_index global x, y, i, j, val, min_dist_comp, contour_single, neuron_selected, comp2_scaled neuron_selected = True distances = np.sum( ((x, y) - estimates.cms[estimates.idx_components])**2, axis=1)**0.5 min_dist_comp = np.argmin(distances) contour_all = [ cv2.threshold(img, np.int(thrshcomp_line.value()), 255, 0)[1] for img in estimates.img_components[estimates.idx_components] ] contour_single = contour_all[min_dist_comp] # draw the traces (lower left component) estimates.components_to_plot = estimates.idx_components[min_dist_comp] p2.plot(estimates.C[estimates.components_to_plot] + estimates.YrA[estimates.components_to_plot], clear=True) # plot img (upper left component) img.setImage(estimates.background_image, autoLevels=False) draw_contours_update(estimates.background_image, img) # plot img2 (upper right component) comp2 = np.multiply(estimates.Cn, contour_single > 0) comp2_scaled = make_color_img(comp2, min_max=(np.min(comp2), np.max(comp2))) img2.setImage(comp2_scaled, autoLevels=False) draw_contours_update(comp2_scaled, img2) # set title for the upper two components p3.setTitle("pos: (%0.1f, %0.1f) component: %d value: %g dist:%f" % (x, y, estimates.components_to_plot, val, distances[min_dist_comp])) p1.setTitle("pos: (%0.1f, %0.1f) component: %d value: %g dist:%f" % (x, y, estimates.components_to_plot, val, distances[min_dist_comp])) # draw the infinite line (INACTIVE IN THIS VERSION WITHOUT MMAP FILES) # nr_vline = pg.InfiniteLine(angle=90, movable=True) # p2.addItem(nr_vline, ignoreBounds=True) # nr_vline.setValue(0) # nr_vline.sigPositionChanged.connect(show_neurons_update) nr_index = 0 def show_neurons_update(): # NOT CALLED IN THIS VERSION global nr_index, frame_denoise_scaled, estimates, raw_mov_scaled global min_mov, max_mov, min_mov_denoise, max_mov_denoise if neuron_selected is False: return nr_index = int(nr_vline.value()) if nr_index > 0 and nr_index < mov[:, 0, 0].shape[0]: # upper left component scrolls through the raw movie raw_mov = mov[nr_index, :, :] raw_mov_scaled = make_color_img(raw_mov, min_max=(min_mov, max_mov)) img.setImage(raw_mov_scaled, autoLevels=False) draw_contours_update(raw_mov_scaled, img) # upper right component scrolls through the denoised movie frame_denoise = estimates.A[:, estimates.idx_components].dot( estimates.C[estimates.idx_components, nr_index]).reshape(estimates.dims, order='F') frame_denoise_scaled = make_color_img(frame_denoise, min_max=(min_mov_denoise, max_mov_denoise)) img2.setImage(frame_denoise_scaled, autoLevels=False) draw_contours_update(frame_denoise_scaled, img2) pars.param('SHOW NEURONS').sigActivated.connect(show_neurons_button) def add_group(): estimates.accepted_list = np.union1d(estimates.accepted_list, estimates.idx_components) estimates.rejected_list = np.setdiff1d(estimates.rejected_list, estimates.idx_components) change(None, None) pars_action.param('ADD GROUP').sigActivated.connect(add_group) def remove_group(): estimates.rejected_list = np.union1d(estimates.rejected_list, estimates.idx_components) estimates.accepted_list = np.setdiff1d(estimates.accepted_list, estimates.idx_components) change(None, None) pars_action.param('REMOVE GROUP').sigActivated.connect(remove_group) def add_single(): estimates.accepted_list = np.union1d(estimates.accepted_list, estimates.components_to_plot) estimates.rejected_list = np.setdiff1d(estimates.rejected_list, estimates.components_to_plot) change(None, None) pars_action.param('ADD SINGLE').sigActivated.connect(add_single) def remove_single(): estimates.rejected_list = np.union1d(estimates.rejected_list, estimates.components_to_plot) estimates.accepted_list = np.setdiff1d(estimates.accepted_list, estimates.components_to_plot) change(None, None) pars_action.param('REMOVE SINGLE').sigActivated.connect(remove_single) def save_object(): print('Saving') ffll = F.getSaveFileName(filter='*.hdf5') print(ffll[0]) cnm_obj.estimates = estimates cnm_obj.save(ffll[0]) pars_action.param('SAVE OBJECT').sigActivated.connect(save_object) def action_pars_activated(param, changes): change(None, None) pars_action.sigTreeStateChanged.connect(action_pars_activated) ## If anything changes in the tree, print a message def change(param, changes): global estimates, pars, pars_action set_par = pars.getValues() if pars_action.param('Filter components').value(): for keyy in set_par.keys(): params_obj.quality.update({keyy: set_par[keyy][0]}) else: params_obj.quality.update({ 'cnn_lowest': .1, 'min_cnn_thr': 0.99, 'rval_thr': 0.85, 'rval_lowest': -1, 'min_SNR': 2, 'SNR_lowest': 0 }) estimates.filter_components( mov, params_obj, dview=None, select_mode=pars_action.param('View components').value()) if mode is "background": return else: draw_contours() pars.sigTreeStateChanged.connect(change) change(None, None) # set params to default t.setParameters(pars, showTop=False) t.setWindowTitle('Parameter Quality') ## END PARAMS ## Display the widget as a new window w.show() ## Start the Qt event loop app.exit(app.exec_())
class ProjectSettingsDialog(QtGui.QDialog): path2key=dict() def __init__(self, parent = None, savedstate=None): super(ProjectSettingsDialog, self).__init__(parent) self.setWindowTitle("Application Settings") layout = QtGui.QVBoxLayout(self) self.initKeyParamMapping() self._settings = Parameter.create(name='params', type='group', children=settings_params) if savedstate: self._settings.restoreState(savedstate) # Holds settings keys that have changed by the user when the # dialog is closed. Used to update any needed gui values.. self._updated_settings={} self._settings.sigTreeStateChanged.connect(self.handleSettingChange) self.initSettingsValues() self.ptree = ParameterTree() self.ptree.setParameters(self._settings, showTop=False) self.ptree.setWindowTitle('MarkWrite Application Settings') layout.addWidget(self.ptree) self.ptree.adjustSize() # OK and Cancel buttons self.buttons = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) layout.addWidget(self.buttons) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) self.resize(500,700) def initKeyParamMapping(self): if len(self.path2key)==0: def replaceGroupKeys(paramlist, parent_path=[]): for i,p in enumerate(paramlist): if isinstance(p,basestring): pdict=flattenned_settings_dict[p] paramlist[i]=pdict self.path2key['.'.join(parent_path+[pdict['name'],])]=p elif isinstance(p,dict): replaceGroupKeys(p.get('children'),parent_path+[p.get('name'),]) replaceGroupKeys(settings_params) def initSettingsValues(self, pgroup=None): global SETTINGS if pgroup is None: pgroup = self._settings for child in pgroup.children(): if child.hasChildren(): self.initSettingsValues(child) else: path = self._settings.childPath(child) if path is not None: childName = '.'.join(path) else: childName = child.name() if self.path2key.has_key(childName): SETTINGS[self.path2key[childName]]=child.value() ## If anything changes in the tree, print a message def handleSettingChange(self, param, changes): global SETTINGS for param, change, data in changes: path = self._settings.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() if change == 'value': setting_key = self.path2key[childName] SETTINGS[setting_key]=data self._updated_settings[setting_key] = data #print 'settings_state:',self.settings_state # static method to create the dialog and return (date, time, accepted) @staticmethod def getProjectSettings(parent = None, usersettings = None): dialog = ProjectSettingsDialog(parent, usersettings) result = dialog.exec_() usersettings=dialog._settings.saveState() return dialog._updated_settings,SETTINGS, usersettings, result == QtGui.QDialog.Accepted
class Labels(object): def __init__(self, parent = None): #print "init!!!!!" self.parent = parent ## Dock: Labels self.dLabels = Dock("Labels", size=(1, 1)) self.wLabels = ParameterTree() self.wLabels.setWindowTitle('Labels') self.dLabels.addWidget(self.wLabels) self.labels_grp = 'Labels' self.labels_A_str = 'Single' self.labels_B_str = 'Multi' self.labels_C_str = 'Dunno' self.labelA = False self.labelB = False self.labelC = False ####################### # Mandatory parameter # ####################### self.params = [ {'name': self.labels_grp, 'type': 'group', 'children': [ {'name': self.labels_A_str, 'type': 'bool', 'value': self.labelA, 'tip': "Single"}, {'name': self.labels_B_str, 'type': 'bool', 'value': self.labelB, 'tip': "Multi"}, {'name': self.labels_C_str, 'type': 'bool', 'value': self.labelC, 'tip': "Dunno"}, ]}, ] self.pLabels = Parameter.create(name='paramsLabel', type='group', \ children=self.params, expanded=True) self.pLabels.sigTreeStateChanged.connect(self.change) self.wLabels.setParameters(self.pLabels, showTop=False) # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, data): global dset if path[1] == self.labels_A_str: self.labelA = data if data: dset[self.parent.eventNumber] = 1 else: dset[self.parent.eventNumber] = 0 elif path[1] == self.labels_B_str: self.labelB = data if data: dset[self.parent.eventNumber] = 2 else: dset[self.parent.eventNumber] = 0 elif path[1] == self.labels_C_str: self.labelC = data if data: dset[self.parent.eventNumber] = 3 else: dset[self.parent.eventNumber] = 0 def refresh(self): fname = self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '_labels.h5' global dset print "##### fname: ", fname if self.parent.runNumber > 0: if os.path.exists(fname): labels = h5py.File(fname, 'r+', dtype = 'i8') else: labels = h5py.File(fname, 'w', dtype = 'i8') try: dset = labels["labels"] except: # corrupt dataset, so create a new one print labels dset = labels.create_dataset("labels", (self.parent.exp.eventTotal, 1)) #print dset.shape self.labelA = False self.labelB = False self.labelC = False if dset[self.parent.eventNumber] == 1: self.labelA = True elif dset[self.parent.eventNumber] == 2: self.labelB = True elif dset[self.parent.eventNumber] == 3: self.labelC = True self.pLabels.param(self.labels_grp, self.labels_A_str).setValue(self.labelA) self.pLabels.param(self.labels_grp, self.labels_B_str).setValue(self.labelB) self.pLabels.param(self.labels_grp, self.labels_C_str).setValue(self.labelC)
def selected(text): global sz, t sz=SzenenTreeInputs(False,text) t.setParameters(sz.p, showTop=False) win = QtGui.QWidget() comboBox = QtGui.QComboBox(win) for cmdLst in cmdLsts: comboBox.addItem(cmdLst) comboBox.activated[str].connect(selected) t = ParameterTree() sz=SzenenTreeInputs(False,cmdLsts[0]) #print sz t.setParameters(sz.p, showTop=False) t.setWindowTitle('Szenen Setup:') #t2 = ParameterTree() #t2.setParameters(p, showTop=False) layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget(QtGui.QLabel(""), 1, 1, 1, 2) layout.addWidget(comboBox, 0, 0, 1, 1) layout.addWidget(t, 20, 0, 1, 1) #layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(800,800)
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): super(MainWindow, self).__init__() layout = Qt.QVBoxLayout(self) self.btnGen = Qt.QPushButton("Start Gen!") layout.addWidget(self.btnGen) self.StateParams = FileMod.SaveSateParameters(QTparent=self, name='State') self.Parameters = Parameter.create(name='params', type='group', children=(self.StateParams, )) self.NifGenParams = FMacq.NifGeneratorParameters(name='NifGenerator') self.Parameters.addChild(self.NifGenParams) self.NiScopeParams = FMacq.NiScopeParameters(name='Scope') self.Parameters.addChild(self.NiScopeParams) # self.FileParameters = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParameters) self.PSDParams = PltMod.PSDParameters(name='PSD Options') self.PSDParams.param('Fs').setValue(self.NifGenParams.Fs.value()) self.PSDParams.param('Fmin').setValue(50) self.PSDParams.param('nAvg').setValue(50) self.PSDEnable = self.PSDParams.param('PSDEnable').value() self.Parameters.addChild(self.PSDParams) self.PlotParams = PltMod.PlotterParameters(name='Plot options') self.PlotParams.SetChannels(self.NiScopeParams.GetChannels()) self.PlotParams.param('Fs').setValue(self.NifGenParams.Fs.value()) self.PltEnable = self.PlotParams.param('PlotEnable').value() self.Parameters.addChild(self.PlotParams) self.Parameters.sigTreeStateChanged.connect(self.on_pars_changed) self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(550, 10, 300, 700) self.setWindowTitle('MainWindow') self.btnGen.clicked.connect(self.on_btnGen) self.threadAqc = None self.threadSave = None self.threadPlotter = None self.threadPSDPlotter = None def on_pars_changed(self, param, changes): print("tree changes:") for param, change, data in changes: path = self.Parameters.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') if childName == 'NifGenerator.SamplingConfig.Fs': self.NiScopeParams.Fs.setValue(data) self.PlotParams.param('Fs').setValue(data) self.PSDParams.param('Fs').setValue(data) if childName == 'Scope.FetchConfig.NRow': self.PlotParams.SetChannels(self.NiScopeParams.GetChannels()) if childName == 'Plot options.RefreshTime': if self.threadPlotter is not None: self.threadPlotter.SetRefreshTime(data) if childName == 'Plot options.ViewTime': if self.threadPlotter is not None: self.threadPlotter.SetViewTime(data) if childName == 'Plot options.PlotEnable': self.PltEnable = data if self.threadAqc is not None: self.UpdatePlots() if childName == 'PSD Options.PSDEnable': self.PSDEnable = data if self.threadAqc is not None: self.UpdatePlots() def on_btnGen(self): print('h') if self.threadAqc is None: self.GenKwargs = self.NifGenParams.GetParams() self.ScopeKwargs = self.NiScopeParams.GetParams() self.threadAqc = FMacq.DataAcquisitionThread( **self.GenKwargs, **self.ScopeKwargs) self.threadAqc.NewData.connect(self.on_NewSample) self.SaveFiles() self.GenPlots() self.threadAqc.start() self.btnGen.setText("Stop Gen") self.OldTime = time.time() else: self.threadAqc.NewData.disconnect() self.threadAqc.stopSessions() self.threadAqc.terminate() self.threadAqc = None if self.threadSave is not None: self.threadSave.stop() self.threadSave = None self.DestroyPlotter() self.DestroyPSD() self.btnGen.setText("Start Gen") def on_NewSample(self): ''' Visualization of streaming data-WorkThread. ''' Ts = time.time() - self.OldTime self.OldTime = time.time() if self.threadSave is not None: self.threadSave.AddData(self.threadAqc.IntData) if self.threadPlotter is not None: self.threadPlotter.AddData(self.threadAqc.OutData) if self.threadPSDPlotter is not None: self.threadPSDPlotter.AddData(self.threadAqc.OutData) print('Sample time', Ts) def GenPlots(self): PlotterKwargs = self.PlotParams.GetParams() ScopeKwargs = self.NiScopeParams.GetParams() if self.threadPlotter is None: if self.PltEnable == True: self.threadPlotter = PltMod.Plotter(**PlotterKwargs) self.threadPlotter.start() if self.threadPSDPlotter is None: if self.PSDEnable == True: self.threadPSDPlotter = PltMod.PSDPlotter( ChannelConf=PlotterKwargs['ChannelConf'], nChannels=ScopeKwargs['NRow'], **self.PSDParams.GetParams()) self.threadPSDPlotter.start() def DestroyPlotter(self): if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None def DestroyPSD(self): if self.threadPSDPlotter is not None: self.threadPSDPlotter.stop() self.threadPSDPlotter = None def UpdatePlots(self): if self.PltEnable == False: self.DestroyPlotter() if self.PSDEnable == False: self.DestroyPSD() else: self.GenPlots() def SaveFiles(self): FileName = self.FileParameters.param('File Path').value() if FileName == '': print('No file') else: if os.path.isfile(FileName): print('Remove File') os.remove(FileName) MaxSize = self.FileParameters.param('MaxSize').value() self.threadSave = FileMod.DataSavingThread( FileName=FileName, nChannels=self.ScopeKwargs['NRow'], MaxSize=MaxSize) self.threadSave.start() GenName = FileName + '_GenConfig.dat' ScopeName = FileName + '_ScopeConfig.dat' if os.path.isfile(GenName): print('Overwriting file') OutGen = input('y/n + press(Enter)') if OutGen == 'y': self.GenArchivo(GenName, self.GenKwargs) else: self.GenArchivo(GenName, self.GenKwargs) if os.path.isfile(ScopeName): print('Overwriting file') OutScope = input('y/n + press(Enter)') if OutScope == 'y': self.GenArchivo(ScopeName, self.ScopeKwargs) else: self.GenArchivo(ScopeName, self.ScopeKwargs) def GenArchivo(self, name, dic2Save): with open(name, "wb") as f: pickle.dump(dic2Save, f)
'name': 'MAX RADIUS', 'type': 'int', 'value': 10 }, { 'name': 'ROUGHNESS', 'type': 'int', 'value': 1 }] }] pars_action = Parameter.create(name='params_action', type='group', children=params_action) neuron_action.setParameters(pars_action, showTop=False) neuron_action.setWindowTitle('Parameter Action') mode = pars_action.getValues()['MODE'][0] def mouseClickEvent(event): global mode, x, y, i, j, pts, roi, cur_image if mode == "POLYGON": pos = img.mapFromScene(event.pos()) x = int(pos.x()) y = int(pos.y()) j, i = pos.y(), pos.x() i = int(np.clip(i, 0, dims[0] - 1)) j = int(np.clip(j, 0, dims[1] - 1)) p1.plot(x=[i], y=[j], symbol='o',
class ProtocolControlWidget(QWidget): """GUI for controlling a ProtocolRunner. This class implements: - selection box of the Protocol to be run; - window for controlling Protocol parameters; - toggle button for starting/stopping the Protocol; - progress bar to display progression of the Protocol. Parameters ---------- protocol_runner: :class:`ProtocolRunner <stytra.stimulation.ProtocolRunner>` object ProtocolRunner that is controlled by the GUI. **Signals** """ sig_start_protocol = pyqtSignal() """ Emitted via the toggle button click, meant to start the protocol """ sig_stop_protocol = pyqtSignal() """ Emitted via the toggle button click, meant to abort the protocol""" def __init__(self, protocol_runner=None, *args): """ """ super().__init__(*args) self.protocol_runner = protocol_runner # Create parametertree for protocol parameter control self.protocol_params_tree = ParameterTree(showHeader=False) # Layout for selecting the protocol: self.lyt_prot_selection = QHBoxLayout() # Dropdown menu with the protocol classes found in the Experiment: self.combo_prot = QComboBox() self.combo_prot.addItems( list(self.protocol_runner.prot_class_dict.keys())) self.combo_prot.currentIndexChanged.connect(self.set_protocol) self.lyt_prot_selection.addWidget(self.combo_prot) # Window with the protocol parameters: self.protocol_params_butt = QPushButton("Protocol parameters") self.protocol_params_butt.clicked.connect(self.show_stim_params_gui) self.lyt_prot_selection.addWidget(self.protocol_params_butt) # Layout for protocol start and progression report: self.lyt_run = QHBoxLayout() # Button for startup: self.button_toggle_prot = QPushButton("▶") self.button_toggle_prot.clicked.connect(self.toggle_protocol_running) self.lyt_run.addWidget(self.button_toggle_prot) # Progress bar for monitoring the protocol: self.progress_bar = QProgressBar() self.progress_bar.setFormat("%p% %v/%m") self.lyt_run.addWidget(self.progress_bar) # Global layout: self.lyt = QVBoxLayout() self.lyt.setContentsMargins(0, 0, 0, 0) self.lyt.addLayout(self.lyt_run) self.lyt.addLayout(self.lyt_prot_selection) self.setLayout(self.lyt) self.timer = None # Connect events and signals from the ProtocolRunner to update the GUI: self.protocol_runner.sig_protocol_updated.connect( self.update_stim_duration) self.protocol_runner.sig_timestep.connect(self.update_progress) self.protocol_runner.sig_protocol_started.connect(self.toggle_icon) self.protocol_runner.sig_protocol_finished.connect(self.toggle_icon) self.protocol_runner.sig_protocol_updated.connect( self.update_stim_duration) # If a previous protocol was already set in the protocol runner # change the GUI values accordingly: if protocol_runner.protocol is not None: self.combo_prot.setCurrentText(protocol_runner.protocol.name) else: self.set_protocol() def show_stim_params_gui(self): """Create and show window to update protocol parameters. """ if self.protocol_runner.protocol.params is not None: self.protocol_params_tree.setParameters( self.protocol_runner.protocol.params) self.protocol_params_tree.show() self.protocol_params_tree.setWindowTitle("Protocol parameters") self.protocol_params_tree.resize(300, 600) def toggle_protocol_running(self): """Emit the start and stop signals. These can be used in the Experiment class or directly connected with the respective ProtocolRunner start() and stop() methods. Parameters ---------- Returns ------- """ # Start/stop the protocol: if not self.protocol_runner.running: self.sig_start_protocol.emit() else: self.sig_stop_protocol.emit() self.toggle_icon() def toggle_icon(self): """Change the play/stop icon of the GUI. """ if self.button_toggle_prot.text() == "■": self.button_toggle_prot.setText("▶") self.progress_bar.setValue(0) else: self.button_toggle_prot.setText("■") def update_stim_duration(self): """ """ self.progress_bar.setMaximum(int(self.protocol_runner.duration)) self.progress_bar.setValue(0) def update_progress(self): """ """ self.progress_bar.setValue(int(self.protocol_runner.t)) def set_protocol(self): """Use value in the dropdown menu to change the protocol. """ protocol_name = self.combo_prot.currentText() self.protocol_runner.set_new_protocol(protocol_name) self.button_toggle_prot.setEnabled(True)
class CrystalIndexing(object): def __init__(self, parent = None): self.parent = parent ## Dock 14: Indexing self.d14 = Dock("Indexing", size=(1, 1)) self.w21 = ParameterTree() self.w21.setWindowTitle('Indexing') self.d14.addWidget(self.w21) self.w22 = pg.LayoutWidget() self.launchIndexBtn = QtGui.QPushButton('Launch indexing') self.w22.addWidget(self.launchIndexBtn, row=0, col=0) self.synchBtn = QtGui.QPushButton('Deploy CrystFEL geometry') self.w22.addWidget(self.synchBtn, row=1, col=0) self.d14.addWidget(self.w22) self.index_grp = 'Crystal indexing' self.index_on_str = 'Indexing on' self.index_geom_str = 'CrystFEL geometry' self.index_peakMethod_str = 'Peak method' self.index_intRadius_str = 'Integration radii' self.index_pdb_str = 'PDB' self.index_method_str = 'Indexing method' #self.index_minPeaks_str = 'Minimum number of peaks' #self.index_maxPeaks_str = 'Maximum number of peaks' #self.index_minRes_str = 'Minimum resolution (pixels)' self.index_tolerance_str = 'Tolerance' self.index_extra_str = 'Extra CrystFEL parameters' self.launch_grp = 'Batch' self.outDir_str = 'Output directory' self.runs_str = 'Runs(s)' self.sample_str = 'Sample name' self.tag_str = 'Tag' self.queue_str = 'Queue' self.chunkSize_str = 'Chunk size' self.keepData_str = 'Keep CXI images' self.noe_str = 'Number of events to process' (self.psanaq_str,self.psnehq_str,self.psfehq_str,self.psnehprioq_str,self.psfehprioq_str,self.psnehhiprioq_str,self.psfehhiprioq_str,self.psdebugq_str) = \ ('psanaq','psnehq','psfehq','psnehprioq','psfehprioq','psnehhiprioq','psfehhiprioq','psdebugq') self.outDir = self.parent.psocakeDir self.outDir_overridden = False self.runs = '' self.sample = 'crystal' self.tag = '' self.queue = self.psanaq_str self.chunkSize = 500 self.noe = -1 # Indexing self.showIndexedPeaks = False self.indexedPeaks = None self.hiddenCXI = '.temp.cxi' self.hiddenCrystfelStream = '.temp.stream' self.hiddenCrystfelList = '.temp.lst' self.indexingOn = False self.numIndexedPeaksFound = 0 self.geom = '.temp.geom' self.peakMethod = 'cxi' self.intRadius = '2,3,4' self.pdb = '' self.indexingMethod = 'mosflm-noretry,dirax' #self.minPeaks = 15 #self.maxPeaks = 2048 #self.minRes = 0 self.tolerance = '5,5,5,1.5' self.extra = '' self.keepData = True ####################### # Mandatory parameter # ####################### self.params = [ {'name': self.index_grp, 'type': 'group', 'children': [ {'name': self.index_on_str, 'type': 'bool', 'value': self.indexingOn, 'tip': "Turn on indexing"}, {'name': self.index_geom_str, 'type': 'str', 'value': self.geom, 'tip': "CrystFEL geometry file"}, #{'name': self.index_peakMethod_str, 'type': 'str', 'value': self.peakMethod, 'tip': "Turn on indexing"}, {'name': self.index_intRadius_str, 'type': 'str', 'value': self.intRadius, 'tip': "Integration radii"}, {'name': self.index_pdb_str, 'type': 'str', 'value': self.pdb, 'tip': "(Optional) CrystFEL unitcell file"}, {'name': self.index_method_str, 'type': 'str', 'value': self.indexingMethod, 'tip': "comma separated indexing methods"}, {'name': self.index_tolerance_str, 'type': 'str', 'value': self.tolerance, 'tip': "Indexing tolerance, default: 5,5,5,1.5"}, {'name': self.index_extra_str, 'type': 'str', 'value': self.extra, 'tip': "Other indexing parameters"}, #{'name': self.index_minPeaks_str, 'type': 'int', 'value': self.minPeaks, # 'tip': "Index only if there are more Bragg peaks found"}, #{'name': self.index_maxPeaks_str, 'type': 'int', 'value': self.maxPeaks, # 'tip': "Index only if there are less Bragg peaks found"}, #{'name': self.index_minRes_str, 'type': 'int', 'value': self.minRes, # 'tip': "Index only if Bragg peak resolution is at least this"}, ]}, {'name': self.launch_grp, 'type': 'group', 'children': [ {'name': self.outDir_str, 'type': 'str', 'value': self.outDir}, {'name': self.runs_str, 'type': 'str', 'value': self.runs, 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"}, {'name': self.sample_str, 'type': 'str', 'value': self.sample, 'tip': "name of the sample saved in the cxidb file, e.g. lysozyme"}, {'name': self.tag_str, 'type': 'str', 'value': self.tag, 'tip': "attach tag to stream, e.g. cxitut13_0010_tag.stream"}, {'name': self.queue_str, 'type': 'list', 'values': {self.psfehhiprioq_str: self.psfehhiprioq_str, self.psnehhiprioq_str: self.psnehhiprioq_str, self.psfehprioq_str: self.psfehprioq_str, self.psnehprioq_str: self.psnehprioq_str, self.psfehq_str: self.psfehq_str, self.psnehq_str: self.psnehq_str, self.psanaq_str: self.psanaq_str, self.psdebugq_str: self.psdebugq_str}, 'value': self.queue, 'tip': "Choose queue"}, {'name': self.chunkSize_str, 'type': 'int', 'value': self.chunkSize, 'tip': "number of patterns to process per worker"}, {'name': self.keepData_str, 'type': 'bool', 'value': self.keepData, 'tip': "Do not delete cxidb images in cxi file"}, ]}, ] self.p9 = Parameter.create(name='paramsCrystalIndexing', type='group', \ children=self.params, expanded=True) self.w21.setParameters(self.p9, showTop=False) self.p9.sigTreeStateChanged.connect(self.change) self.launchIndexBtn.clicked.connect(self.indexPeaks) self.synchBtn.clicked.connect(self.syncGeom) # Launch indexing def indexPeaks(self): self.parent.thread.append(LaunchIndexer.LaunchIndexer(self.parent)) # send parent parameters with self self.parent.thread[self.parent.threadCounter].launch(self.parent.experimentName, self.parent.detInfo) self.parent.threadCounter += 1 # Update psana geometry def syncGeom(self): with pg.BusyCursor(): print "#################################################" print "Updating psana geometry with CrystFEL geometry" print "#################################################" self.parent.geom.findPsanaGeometry() psanaGeom = self.parent.psocakeRunDir + "/.temp.data" if self.parent.args.localCalib: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", '.', "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] else: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", self.parent.rootDir, "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] if self.parent.args.v >= 0: print "cmd: ", cmd p = subprocess.Popen(cmd, stdout=subprocess.PIPE) output = p.communicate()[0] p.stdout.close() # Reload new psana geometry cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'converted from crystfel geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = '/reg/d/psdm/' + self.parent.experimentName[:3] + '/' + self.parent.experimentName + '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=psanaGeom, dcmts=cmts, pbits=0) self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.parent.geom.updateRings() self.parent.index.updateIndex() self.parent.geom.drawCentre() # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[1] == self.index_on_str: self.updateIndexStatus(data) elif path[1] == self.index_geom_str: self.updateGeom(data) elif path[1] == self.index_peakMethod_str: self.updatePeakMethod(data) elif path[1] == self.index_intRadius_str: self.updateIntegrationRadius(data) elif path[1] == self.index_pdb_str: self.updatePDB(data) elif path[1] == self.index_method_str: self.updateIndexingMethod(data) #elif path[1] == self.index_minPeaks_str: # self.updateMinPeaks(data) #elif path[1] == self.index_maxPeaks_str: # self.updateMaxPeaks(data) #elif path[1] == self.index_minRes_str: # self.updateMinRes(data) elif path[1] == self.index_tolerance_str: self.updateTolerance(data) elif path[1] == self.index_extra_str: self.updateExtra(data) # launch grp elif path[1] == self.outDir_str: self.updateOutputDir(data) elif path[1] == self.runs_str: self.updateRuns(data) elif path[1] == self.sample_str: self.updateSample(data) elif path[1] == self.tag_str: self.updateTag(data) elif path[1] == self.queue_str: self.updateQueue(data) elif path[1] == self.chunkSize_str: self.updateChunkSize(data) elif path[1] == self.noe_str: self.updateNoe(data) elif path[1] == self.keepData_str: self.keepData = data def updateIndexStatus(self, data): self.indexingOn = data self.showIndexedPeaks = data self.updateIndex() def updateGeom(self, data): self.geom = data self.updateIndex() def updatePeakMethod(self, data): self.peakMethod = data if self.indexingOn: self.updateIndex() def updateIntegrationRadius(self, data): self.intRadius = data self.updateIndex() def updatePDB(self, data): self.pdb = data self.updateIndex() def updateIndexingMethod(self, data): self.indexingMethod = data self.updateIndex() #def updateMinPeaks(self, data): # self.minPeaks = data # self.updateIndex() #def updateMaxPeaks(self, data): # self.maxPeaks = data # self.updateIndex() #def updateMinRes(self, data): # self.minRes = data # self.updateIndex() def updateTolerance(self, data): self.tolerance = data self.updateIndex() def updateExtra(self, data): self.extra = data self.updateIndex() def updateIndex(self): if self.indexingOn: self.indexer = IndexHandler(parent=self.parent) self.indexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, queue=None) def updateOutputDir(self, data): self.outDir = data self.outDir_overridden = True def updateRuns(self, data): self.runs = data def updateSample(self, data): self.sample = data def updateTag(self, data): self.tag = data def updateQueue(self, data): self.queue = data def updateChunkSize(self, data): self.chunkSize = data def updateNoe(self, data): self.noe = data def clearIndexedPeaks(self): self.parent.img.w1.getView().removeItem(self.parent.img.abc_text) self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) if self.parent.args.v >= 1: print "Done clearIndexedPeaks" def displayWaiting(self): if self.showIndexedPeaks: if self.numIndexedPeaksFound == 0: # indexing proceeding xMargin = 5 # pixels maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) # Draw a big X cenX = np.array((self.parent.cx,)) + 0.5 cenY = np.array((self.parent.cy,)) + 0.5 diameter = 256 # self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='t', \ size=diameter, brush=(255, 255, 255, 0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0, 0)) self.parent.img.w1.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) def drawIndexedPeaks(self, latticeType=None, centering=None, numSaturatedPeaks=None, unitCell=None): self.clearIndexedPeaks() if self.showIndexedPeaks: if self.indexedPeaks is not None and self.numIndexedPeaksFound > 0: # indexing succeeded cenX = self.indexedPeaks[:,0]+0.5 cenY = self.indexedPeaks[:,1]+0.5 cenX = np.concatenate((cenX,cenX,cenX)) cenY = np.concatenate((cenY,cenY,cenY)) diameter = np.ones_like(cenX) diameter[0:self.numIndexedPeaksFound] = float(self.intRadius.split(',')[0])*2 diameter[self.numIndexedPeaksFound:2*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[1])*2 diameter[2*self.numIndexedPeaksFound:3*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[2])*2 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='o', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 1.5}), pxMode=False) # Write unit cell parameters if unitCell is not None: xMargin = 5 yMargin = 400 maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) - yMargin myMessage = '<div style="text-align: center"><span style="color: #FF00FF; font-size: 12pt;">lattice='+\ latticeType +'<br>centering=' + centering + '<br>a='+\ str(round(float(unitCell[0])*10,2))+'A <br>b='+str(round(float(unitCell[1])*10,2))+'A <br>c='+\ str(round(float(unitCell[2])*10,2))+'A <br>α='+str(round(float(unitCell[3]),2))+\ '° <br>β='+str(round(float(unitCell[4]),2))+'° <br>γ='+\ str(round(float(unitCell[5]),2))+'° <br></span></div>' self.parent.img.abc_text = pg.TextItem(html=myMessage, anchor=(0,0)) self.parent.img.w1.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) else: # Failed indexing xMargin = 5 # pixels maxX = np.max(self.parent.det.indexes_x(self.parent.evt))+xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) # Draw a big X cenX = np.array((self.parent.cx,))+0.5 cenY = np.array((self.parent.cy,))+0.5 diameter = 256 #self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='x', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0,0)) self.parent.img.w1.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX,maxY) else: self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) if self.parent.args.v >= 1: print "Done updatePeaks" # This function probably doesn't get called def launchIndexing(self, requestRun=None): self.batchIndexer = IndexHandler(parent=self.parent) if requestRun is None: self.batchIndexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) else: self.batchIndexer.computeIndex(self.parent.experimentName, requestRun, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) if self.parent.args.v >= 1: print "Done updateIndex"
def start_gui(self, skip_exec=False, qapp=None): from PyQt5 import QtWidgets # import scaffan.qtexceptionhook # import QApplication, QFileDialog if not skip_exec and qapp == None: qapp = QtWidgets.QApplication(sys.argv) self.parameters.param("Input", "Select").sigActivated.connect( self.select_file_gui) # self.parameters.param("Output", "Select").sigActivated.connect( # self.select_output_dir_gui # ) self.parameters.param( "Output", "Select Common Spreadsheet File").sigActivated.connect( self.select_output_spreadsheet_gui) self.parameters.param("Run").sigActivated.connect(self.run) self.parameters.param("Input", "X-Axis").sigValueChanged.connect( self._on_param_change) self.parameters.param("Input", "Y-Axis").sigValueChanged.connect( self._on_param_change) self.parameters.param("Input", "Time Axis").sigValueChanged.connect( self._on_param_change) self.parameters.param("Input", "C-Axis").sigValueChanged.connect( self._on_param_change) self.parameters.param("Input", "Tracked Channel").sigValueChanged.connect( self._on_param_change) self.parameters.param("Input", "Preview Time").sigValueChanged.connect( self._on_param_change) # self.parameters.param("Processing", "Open output dir").setValue(True) t = ParameterTree() t.setParameters(self.parameters, showTop=False) t.setWindowTitle("pyqtgraph example: Parameter Tree") t.show() # print("run scaffan") win = QtGui.QWidget() win.setWindowTitle("CellTrack {}".format(celltrack.__version__)) logo_fn = op.join(op.dirname(__file__), "celltrack_icon512.png") logo_fav_fn = op.join(op.dirname(__file__), "logo_fav.png") logo_prifuk = op.join(op.dirname(__file__), "logo_prifuk.png") app_icon = QtGui.QIcon() # app_icon.addFile(logo_fn, QtCore.QSize(16, 16)) app_icon.addFile(logo_fn) win.setWindowIcon(app_icon) # qapp.setWindowIcon(app_icon) layout = QtGui.QGridLayout() layout.setColumnStretch(0, 2) layout.setColumnStretch(1, 3) win.setLayout(layout) # layout.setColumnStretch(2, 3) logolink = QGroupBox("Created by") logolink_layout = QtGui.QGridLayout() logolink.setLayout(logolink_layout) pic = QtGui.QLabel() urlLink = "<a href=\"http://www.google.com\">'Click this link to go to Google'</a>" pic.setText(urlLink) pic.setPixmap(QtGui.QPixmap(logo_fav_fn).scaled(50, 50)) pic.setOpenExternalLinks(True) pic.show() urlLink = "<a href=\"http://www.google.com\">'Click this link to go to Google'</a>" pic2 = QtGui.QLabel() pic2.setText(urlLink) pic2.setPixmap(QtGui.QPixmap(logo_prifuk).scaled(50, 50)) pic2.setOpenExternalLinks(True) pic2.show() # self.image1 = PlotCanvas() # self.image1.axes.set_axis_off() # self.image1.imshow(plt.imread(logo_fn)) # self.image1.plot() self.image2 = PlotCanvas() self.image2.axes.text(0.1, 0.6, "Load Tiff file") self.image2.axes.text(0.1, 0.5, "Check pixelsize") self.image2.axes.text(0.1, 0.4, "Run") # self.image2.axes.text(0.1, 0.3, "Use Comparative Annotation (optimal in further iterations)") self.image2.axes.set_axis_off() self.image2.draw() # self.image2.plot() # self.addToolBar(NavigationToolbar(self.image1, self)) # self.image1.setPixmap(QtGui.QPixmap(logo_fn).scaled(100, 100)) # self.image1.show() # self.image2 = QtGui.QLabel() # self.image2.setPixmap(QtGui.QPixmap(logo_fn).scaled(100, 100)) # self.image2.show() # layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) logolink_layout.addWidget(pic, 1, 0, 1, 1) logolink_layout.addWidget(pic2, 1, 1, 1, 1) layout.addWidget(logolink, 1, 0, 1, 1) layout.addWidget(t, 2, 0, 1, 1) # layout.addWidget(NavigationToolbar(self.image2, win),1, 2, 1, 1) layout.addWidget(NavigationToolbar(self.image2, win), 1, 1, 1, 1) layout.addWidget(self.image2, 2, 1, 1, 1) # layout.addWidget(self.image2, 2, 2, 1, 1) # layout.addWidget(t2, 1, 1, 1, 1) win.show() win.resize(1200, 800) self.win = win # win. self.qapp = qapp if not skip_exec: qapp.exec_()
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): # 'Super' is used to initialize the class from which this class # depends, in this case MainWindow depends on Qt.Widget class super(MainWindow, self).__init__() # buscar esto que son cosas de la ventana de la gui self.setFocusPolicy(Qt.Qt.WheelFocus) layout = Qt.QVBoxLayout(self) # Qt.QPushButton is used to generate a button in the GUI self.btnStart = Qt.QPushButton("Start Gen and Adq!") layout.addWidget(self.btnStart) # #############################Save############################## self.SaveStateParams = FileMod.SaveTreeSateParameters(QTparent=self, name='State') # With this line, it is initize the group of parameters that are # going to be part of the full GUI self.Parameters = Parameter.create(name='params', type='group', children=(self.SaveStateParams,)) # #############################File############################## self.FileParams = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParams) # ############################SignalConfig############################## # QTparent indicades that is going to be added a tree in the actual # GUI that has already been created. # Name is the name that you want as title of your tree in the GUI self.SigParams = SigConfig.SignalConfig(QTparent=self, name='Signal SetUp') self.Parameters.addChild(self.SigParams) # You can create variables of the main class with the values of # an specific tree you have created in a concret GroupParameter class self.GenParams = self.SigParams.param('GeneralConfig') self.CarrParams = self.SigParams.param('CarrierConfig') self.ModParams = self.SigParams.param('ModConfig') # ############################LockInConfig############################## # It is added the tree of LockIn_Config to the actual GUI self.LockInParams = LockInConfig.LockIn_Config(QTparent=self, name='LockIn SetUp') # And its parameters are added to Parameters variable self.Parameters.addChild(self.LockInParams) # A variable with LockInConfig parameters is created self.LockInConf = self.LockInParams.param('LockInConfig') # ############################LPFConfig############################## # It is added the tree of LPFilterConfig to the actual GUI self.LPFParams = LPFilter.LPFilterConfig(QTparent=self, name='LPF SetUp') # And its parameters are added to Parameters variable self.Parameters.addChild(self.LPFParams) # A variable with LPFConfig parameters is created self.LPFConf = self.LPFParams.param('LPFConfig') # #############################Plots############################## self.PsdPlotParams = PSDPlt.PSDParameters(name='PSD Plot Options') self.PsdPlotParams.param('Fmin').setValue(50) self.PsdPlotParams.param('nAvg').setValue(50) self.Parameters.addChild(self.PsdPlotParams) self.PlotParams = TimePlt.PlotterParameters(name='Plot options') self.PlotParams.SetChannels({'Row1': 0,}) self.Parameters.addChild(self.PlotParams) # ############################Shared Configs############################## # It can be seen that some parameters of different trees are # the same, so they need to have the same value. # To force a value in a parameter it is used the statement setValue # With the form XX.param('param') you access to a concrete param value # With the form self.XX.param.value() you acced to the value of a # SELF variable created in the XX class self.LockInConf.param('Fs').setValue(self.SigParams.Fs.value()) self.LPFConf.param('Fs').setValue(self.SigParams.Fs.value()) self.PlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.PsdPlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.LockInConf.param( 'CarrFrequency').setValue( self.SigParams.CarrFreq.value()) self.LPFConf.param( 'CuttOffFreq').setValue( self.LockInParams.OutFs.value()) self.LockInConf.param( 'nSamples').setValue( self.SigParams.nSamples.value()) # ############################Instancias for Changes###################### # Statement sigValueChanged.connect is used to execute a function # if the indicated value (param('param')) changes # Statement sigTreeStateChanged.connect is used to execute a function # if any parameter of the indicated tree changes self.CarrParams.param('CarrFrequency').sigValueChanged.connect(self.on_Fc_changed) self.GenParams.sigTreeStateChanged.connect(self.on_GenConfig_changed) self.CarrParams.sigTreeStateChanged.connect(self.on_CarrierConfig_changed) self.ModParams.sigTreeStateChanged.connect(self.on_ModConfig_changed) self.LockInConf.param('OutFs').sigValueChanged.connect(self.on_OutFs_changed) self.PlotParams.param('PlotEnable').sigValueChanged.connect(self.on_PlotEnable_changed) self.PlotParams.param('RefreshTime').sigValueChanged.connect(self.on_RefreshTimePlt_changed) self.PlotParams.param('ViewTime').sigValueChanged.connect(self.on_SetViewTimePlt_changed) self.PsdPlotParams.param('PSDEnable').sigValueChanged.connect(self.on_PSDEnable_changed) # ############################GuiConfiguration############################## # Is the same as before functions but for 'Parameters' variable, # which conatins all the trees of all the Gui, so on_Params_changed # will be execute for any change in the Gui self.Parameters.sigTreeStateChanged.connect(self.on_Params_changed) # EXPLICAR ESTO TAMBIEN QUE TIENE QUE VER CON LA GUI self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(550, 10, 300, 700) self.setWindowTitle('MainWindow') # It is connected the action of click a button with a function self.btnStart.clicked.connect(self.on_btnStart) # Threads are startes as None self.threadGeneration = None self.threadLockIn = None self.threadPlotter = None self.threadPsdPlotter = None self.threadDemodSave = None # ############################Changes Control############################## def on_Params_changed(self, param, changes): ''' This function is used to print in the consol the changes that have been done. ''' print("tree changes:") for param, change, data in changes: path = self.Parameters.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') # ############################Changes Emits############################## def on_Fc_changed(self): ''' This function is used to change the Carrier Frequency value of Lock In tree to the same value specified in Signal Configuration tree ''' self.LockInConf.param( 'CarrFrequency').setValue( self.SigParams.CarrFreq.value()) if self.threadLockIn is not None: self.threadLockIn.LockIn.GenerateVcoiSignal( self.SigParams.CarrFreq.value()) def on_OutFs_changed(self): ''' This function is used to change the Cutoff Frequency value of Low pass filter tree to the same value specified in Lock In Configuration tree ''' self.LPFConf.param( 'CuttOffFreq').setValue( self.LockInParams.OutFs.value()) self.PlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.PsdPlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.PlotParams.param('ViewBuffer').setValue( self.SigParams.nSamples.value()/self.LockInParams.OutFs.value()) def on_GenConfig_changed(self): ''' This function is used to change the Sampling frequency value and nSamples value of Lock In and Low pass Filter trees to the ones specified in the signal configuration ''' self.LockInConf.param('Fs').setValue(self.SigParams.Fs.value()) self.LPFConf.param('Fs').setValue(self.SigParams.Fs.value()) self.PlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.PsdPlotParams.param('Fs').setValue(self.LockInParams.OutFs.value()) self.LockInConf.param( 'nSamples').setValue( self.SigParams.nSamples.value()) self.PlotParams.param('ViewBuffer').setValue( self.SigParams.nSamples.value()/self.LockInParams.OutFs.value()) def on_CarrierConfig_changed(self): ''' This function is used to change the Carrier parameters while the program is running ''' # It is checked if the Thread of generation is active if self.threadGeneration is not None: # Gen Carrier function is called and appropiate parameters are # sent to generate the new waveform SigGen.GenAMSignal(**self.SigParams.Get_SignalConf_Params()) def on_ModConfig_changed(self): ''' This function is used to change the Modulation parameters while the program is running ''' # It is checked if the Thread of generation is active if self.threadGeneration is not None: if self.ModParams.param('ModType').value() == 'sinusoidal': # GenModulation for a sinusoidal waveform function is called # and appropiate parameters are sent to generate the new # waveform SigGen.GenAMSignal(**self.SigParams.Get_SignalConf_Params()) if self.ModParams.param('ModType').value() == 'square': # GenModulation for an square waveform function is called # and appropiate parameters are sent to generate the new # waveform SigGen.GenAMSignal(**self.SigParams.Get_SignalConf_Params()) def on_PSDEnable_changed(self): ''' This function is used to Generate or destroy the PSD plot ''' if self.threadGeneration is not None: self.Gen_Destroy_PsdPlotter() def on_PlotEnable_changed(self): ''' This function is used to Generate or destroy the Time plot ''' if self.threadGeneration is not None: self.Gen_Destroy_Plotters() def on_RefreshTimePlt_changed(self): ''' This function is used to change the refresh time of Time Plot ''' if self.threadPlotter is not None: self.threadPlotter.SetRefreshTime(self.PlotParams.param('RefreshTime').value()) def on_SetViewTimePlt_changed(self): ''' This function is used to change the View time of Time Plot ''' if self.threadPlotter is not None: self.threadPlotter.SetViewTime(self.PlotParams.param('ViewTime').value()) # ############################START############################## def on_btnStart(self): ''' This function is executed when the 'start' button is pressed. It is used to initialize the threads, emit signals and data that are necessary durint the execution of the program. Also in this function the different threads starts. ''' # It is checked if the thread of generation is running if self.threadGeneration is None: # If it is not running # A dictionary created by the function Get_SignalConf_Params, with # all the parameters and values of Signal configuration class is # saved in a class variable. This dictionary can be used as kwargs self.SignalConfigKwargs = self.SigParams.Get_SignalConf_Params() # The function Get_LockInConf_Params generates a dictioanry that # is saved to pass to other functions as dictionary or kwargs self.LockInConfigKwargs = self.LockInParams.Get_LockInConf_Params() # The function Get_LPF_Params generates a dictioanry that # is saved to pass to other functions as dictionary or kwargs self.LPFConfigKwargs = self.LPFParams.Get_LPF_Params() # The dictionary is passed to the genration thread self.threadGeneration = SigGen.GenerationThread(**self.SignalConfigKwargs) # As LPF is used in Lock In process, both dictionaries are passed # to the LockIn Thread self.threadLockIn = LockIn.LockInThread(self.LockInConfigKwargs, self.LPFConfigKwargs, tWait=self.SigParams.tInterrput.value() ) # the Qt signal of the generation thread is connected to a # function (on_NewSample) so, when the thread emits this signal # the specified function will be executed self.threadGeneration.NewGenData.connect(self.on_NewSample) self.threadLockIn.NewDemodData.connect(self.on_NewDemodSample) # Time and PSD Plots threads are initialized and started self.Gen_Destroy_PsdPlotter() self.Gen_Destroy_Plotters() # Also save thread is initialize and started self.SaveFiles() # The thread is started, so run function is executed in loop self.threadGeneration.start() self.threadLockIn.start() # Falta iniciar plot y PSD cuando javi los haga para 1 # Text of the button is changed to 'stop' self.btnStart.setText("Stop Gen") # The exact time the thread starts is saved self.OldTime = time.time() else: # stopped is printed in the console print('Stopped') # Thread is terminated and set to None self.threadGeneration.NewGenData.disconnect() self.threadLockIn.NewDemodData.disconnect() self.threadGeneration.terminate() self.threadGeneration = None self.threadLockIn = None if self.threadPlotter is not None: self.threadPlotter.stop() self.threadPlotter = None if self.threadPsdPlotter is not None: self.threadPsdPlotter.stop() self.threadPsdPlotter = None # Also save thread is stopped if self.threadDemodSave is not None: self.threadDemodSave.stop() self.threadDemodSave = None # Button text is changed again self.btnStart.setText("Start Gen and Adq!") def on_NewSample(self): ''' This function is executed when a new amount of values of the signal generated are ready so they can be read and processed ''' # It is calculated the period of Generation Thread with the actual # time and the one saved in the last iteration Ts = time.time() - self.OldTime # Time is saved again to calculate the next periot of the thread self.OldTime = time.time() # period is printed in the console print('Sample time', Ts) # to read clean signal self.threadLockIn.AddData(NewData=self.threadGeneration.OutData) # to read noisy signal # self.threadLockIn.AddData(NewData=self.threadGeneration.OutNoiseData) def on_NewDemodSample(self): print('demodDone') if self.threadDemodSave is not None: self.threadDemodSave.AddData(self.threadLockIn.OutDemodDataReShape) if self.LockInConf.param('OutType').value() == 'Abs': OutDemodData = np.abs(self.threadLockIn.OutDemodDataReShape) elif self.LockInConf.param('OutType').value() == 'Real': OutDemodData = np.real(self.threadLockIn.OutDemodDataReShape) elif self.LockInConf.param('OutType').value() == 'Imag': OutDemodData = np.imag(self.threadLockIn.OutDemodDataReShape) elif self.LockInConf.param('OutType').value() == 'Angle': OutDemodData = np.angle(self.threadLockIn.OutDemodDataReShape, deg=True) if self.threadPlotter is not None: self.threadPlotter.AddData(OutDemodData) if self.threadPsdPlotter is not None: self.threadPsdPlotter.AddData(OutDemodData) # #############################Plots############################## def Gen_Destroy_Plotters(self): ''' This function is executed to initialize and start or destroy time plot ''' # If Time plot thread does not exist if self.threadPlotter is None: # And the plot enable checkbox is selected if self.PlotParams.param('PlotEnable').value() is True: # A dictionary obtained with Get Params function is saved PlotterKwargs = self.PlotParams.GetParams() # And is sent to Plotter thread to initialize it self.threadPlotter = TimePlt.Plotter(**PlotterKwargs) # Then thread is started self.threadPlotter.start() # If time plot thread exists if self.threadPlotter is not None: # And plot enable checkbox is not selected if self.PlotParams.param('PlotEnable').value() is False: # The thread is stopped and set to None self.threadPlotter.stop() self.threadPlotter = None def Gen_Destroy_PsdPlotter(self): ''' This function is executed to initialize and start or destroy PSD plot ''' # If PSD plot thread does not exist if self.threadPsdPlotter is None: # And the plot enable checkbox is selected if self.PsdPlotParams.param('PSDEnable').value() is True: # A dictionary obtained with Get Params function is saved PlotterKwargs = self.PlotParams.GetParams() # And is sent to PSDPlotter thread to initialize it self.threadPsdPlotter = PSDPlt.PSDPlotter(ChannelConf=PlotterKwargs['ChannelConf'], nChannels=1, **self.PsdPlotParams.GetParams()) # Then thread is started self.threadPsdPlotter.start() # If PSD plot thread exists if self.threadPsdPlotter is not None: # And plot enable checkbox is not selected if self.PsdPlotParams.param('PSDEnable').value() is False: # The thread is stopped and set to None self.threadPsdPlotter.stop() self.threadPsdPlotter = None # #############################Saving Files############################## def SaveFiles(self): ''' This function is executed to initialize and start save thread ''' # The File Name is obtained from the GUI File Path FileName = self.FileParams.param('File Path').value() # If the is no file name, No file is printed if FileName == '': print('No file') # If there is file name else: # It is checked if the file exists, if it exists is removed if os.path.isfile(FileName): print('Remove File') os.remove(FileName) # Maximum size alowed for the new file is obtained from the GUI MaxSize = self.FileParams.param('MaxSize').value() # The threas is initialized self.threadDemodSave = FileMod.DataSavingThread(FileName=FileName, nChannels=1, MaxSize=MaxSize, Fs = self.SigParams.Fs.value(), tWait=self.SigParams.tInterrput.value(), dtype='float') # And then started self.threadDemodSave.start()
class ProjectSettingsDialog(QtGui.QDialog): path2key = dict() def __init__(self, parent=None, savedstate=None): global SETTINGS super(ProjectSettingsDialog, self).__init__(parent) self.setWindowTitle("Application Settings") layout = QtGui.QVBoxLayout(self) self.setLayout(layout) if savedstate: for key, val in savedstate.items(): if flattenned_settings_dict.get(key): flattenned_settings_dict[key]['value'] = val #self._settings.restoreState(savedstate) self.initKeyParamMapping() self._settings = Parameter.create(name='params', type='group', children=settings_params) # Holds settings keys that have changed by the user when the # dialog is closed. Used to update any needed gui values.. self._updated_settings = {} self._invalid_settings = {} self._settings.sigTreeStateChanged.connect(self.handleSettingChange) self.initSettingsValues() self._settings.param('Default Settings', 'Save As').sigActivated.connect(self.saveToFile) self._settings.param('Default Settings', 'Load').sigActivated.connect(self.loadFromFile) self.ptree = ParameterTree() self.ptree.setParameters(self._settings, showTop=False) self.ptree.setWindowTitle('MarkWrite Application Settings') layout.addWidget(self.ptree) # OK and Cancel buttons self.buttons = QtGui.QDialogButtonBox( QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) layout.addWidget(self.buttons) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) wscreen = QtGui.QDesktopWidget().screenGeometry() if savedstate and savedstate.get(SETTINGS_DIALOG_SIZE_SETTING): w, h = savedstate.get(SETTINGS_DIALOG_SIZE_SETTING) self.resize(w, h) SETTINGS[SETTINGS_DIALOG_SIZE_SETTING] = (w, h) if savedstate.get(APP_WIN_SIZE_SETTING): SETTINGS[APP_WIN_SIZE_SETTING] = savedstate.get( APP_WIN_SIZE_SETTING) else: if parent: wscreen = QtGui.QDesktopWidget().screenGeometry(parent) self.resize(min(500, int(wscreen.width() * .66)), min(700, int(wscreen.height() * .66))) # center dialog on same screen as is being used by markwrite app. qr = self.frameGeometry() cp = wscreen.center() qr.moveCenter(cp) self.move(qr.topLeft()) def saveToFile(self): from markwrite.gui.dialogs import fileSaveDlg, ErrorDialog from markwrite import writePickle, current_settings_path save_to_path = fileSaveDlg(initFilePath=current_settings_path, initFileName=u"markwrite_settings.pkl", prompt=u"Save MarkWrite Settings", allowed="Python Pickle file (*.pkl)", parent=self) if save_to_path: import os from markwrite import default_settings_file_name, current_settings_file_name ff, fn = os.path.split(save_to_path) if fn in [default_settings_file_name, current_settings_file_name]: ErrorDialog.info_text = u"%s a is reserved file name." \ u" Save again using a different name."%(fn) ErrorDialog().display() else: writePickle(ff, fn, SETTINGS) def loadFromFile(self): global settings from markwrite.gui.dialogs import fileOpenDlg from markwrite import appdirs as mwappdirs from markwrite import readPickle, writePickle from markwrite import current_settings_file_name, current_settings_path if self.parent: mws_file = fileOpenDlg(current_settings_path, None, "Select MarkWrite Settings File", "Python Pickle file (*.pkl)", False) if mws_file: import os ff, fn = os.path.split(mws_file[0]) mw_setting = readPickle(ff, fn) _ = ProjectSettingsDialog(savedstate=mw_setting) self.parent().updateApplicationFromSettings( mw_setting, mw_setting) writePickle(current_settings_path, current_settings_file_name, SETTINGS) def initKeyParamMapping(self): if len(self.path2key) == 0: def replaceGroupKeys(paramlist, parent_path=[]): for i, p in enumerate(paramlist): if isinstance(p, basestring): pdict = flattenned_settings_dict[p] paramlist[i] = pdict self.path2key['.'.join(parent_path + [ pdict['name'], ])] = p elif isinstance(p, dict): replaceGroupKeys(p.get('children'), parent_path + [ p.get('name'), ]) replaceGroupKeys(settings_params) def initSettingsValues(self, pgroup=None): global SETTINGS if pgroup is None: pgroup = self._settings for child in pgroup.children(): if child.hasChildren(): self.initSettingsValues(child) else: path = self._settings.childPath(child) if path is not None: childName = '.'.join(path) else: childName = child.name() if self.path2key.has_key(childName): SETTINGS[self.path2key[childName]] = child.value() child.orgvalue = child.value() ## If anything changes in the tree def handleSettingChange(self, param, changes): global SETTINGS for param, change, data in changes: path = self._settings.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() if change == 'value': setting_key = self.path2key[childName] if setting_key.startswith('kbshortcut_'): qks = QtGui.QKeySequence(data) if (len(data) > 0 and qks.isEmpty() ) or qks.toString() in SETTINGS.values(): self._invalid_settings[setting_key] = param continue else: data = u'' + qks.toString() SETTINGS[setting_key] = data self._updated_settings[setting_key] = data param.orgvalue = data def resizeEvent(self, event): global SETTINGS w, h = self.size().width(), self.size().height() SETTINGS[SETTINGS_DIALOG_SIZE_SETTING] = (w, h) self._updated_settings[SETTINGS_DIALOG_SIZE_SETTING] = (w, h) return super(QtGui.QDialog, self).resizeEvent(event) @staticmethod def getProjectSettings(parent=None, usersettings=None): if usersettings is None: usersettings = SETTINGS dialog = ProjectSettingsDialog(parent, usersettings) result = dialog.exec_() for k, v in dialog._invalid_settings.items(): v.setValue(v.orgvalue) dialog._invalid_settings.clear() usersettings = dialog._settings.saveState() return dialog._updated_settings, SETTINGS, usersettings, result == QtGui.QDialog.Accepted
def __init__(self, **kw): self.app = kw.pop('app') self.data_label = '' self.date_time = dt.datetime.now().strftime('%Y_%m_%d-%H_%M') self.h = kw.pop('h', .1) #integration step size self.n_state_variables = kw.pop('n_state_variables', 2) self.n_history = kw.pop('n_history', 2000) self.kw = kw self.params = kw.get('params') #qt paramters, se tree parameter class self.update_time = kw.pop('update_time', 0) self.widgets = [] self.script_name = kw.pop('script_name', __file__.split('/')[-1][0:-3]) self.start_stim = -10000.0 self.scale_plot = 10 for key, value in kw.items(): self.__dict__[key] = value for d in self.params[0]['children']: self.__dict__[d['name']] = d['value'] for d in self.params[1]['children']: if 'value' in d.keys(): self.__dict__[d['name']] = d['value'] self.x = self.n_history self.y = numpy.zeros(self.n_state_variables) self.y[0] = -70 self.dy = numpy.zeros(self.n_state_variables) self.x_history = numpy.arange(0, self.n_history, self.scale_plot * self.h) self.y_history = numpy.random.rand( self.n_state_variables, self.n_history / (self.scale_plot * self.h)) self.y_history[0, :] = -70 # Parameters self.p = Parameter.create(name='params', type='group', children=self.params) self.p.sigTreeStateChanged.connect(self.change) pt = ParameterTree() pt.setParameters(self.p, showTop=False) pt.setWindowTitle('Parameters') self.widgets.append(pt) # Voltage time plot w = pg.PlotWidget() w.setWindowTitle('Voltage/time') w.setRange(QtCore.QRectF(0, -90, self.n_history, 100)) w.setLabel('bottom', 'Time', units='s') w.plotItem.layout.setContentsMargins(20, 20, 20, 20) ax = w.plotItem.getAxis('left') l = [ [(0.0, '0'), (-30, -30), (-60, -60), (-90, -90)], ] ax.setTicks(l) w.plotItem.getAxis('bottom').setScale(0.001) ax.setLabel('Voltage', units='V') ax.setScale(0.001) # ax.setWidth(w=2) # ax.setRange(500,1500) color = self.kw.get('curve_uv_color', (0, 0, 0)) pen = pg.mkPen(color, width=self.kw.get('curve_uv_width', 5)) self.curve_vt = w.plot(pen=pen) self.curve_vt.setData(self.x_history, self.y_history[0, :]) self.widgets.append(w) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update) self.timer.start(self.update_time) # self.timer.start(1000.) self._init_extra(**kw)
class MainWindow(Qt.QWidget): ''' Main Window ''' def __init__(self): super(MainWindow, self).__init__() layout = Qt.QVBoxLayout(self) self.btnAcq = Qt.QPushButton("Start Acq!") layout.addWidget(self.btnAcq) self.SamplingPar = AcqMod.SampSetParam(name='SampSettingConf') self.Parameters = Parameter.create(name='App Parameters', type='group', children=(self.SamplingPar, )) self.SamplingPar.NewConf.connect(self.on_NewConf) self.PlotParams = PltMod.PlotterParameters(name='Plot options') self.PlotParams.SetChannels(self.SamplingPar.GetChannelsNames()) self.PlotParams.param('Fs').setValue(self.SamplingPar.Fs.value()) self.Parameters.addChild(self.PlotParams) self.PSDParams = PltMod.PSDParameters(name='PSD Options') self.PSDParams.param('Fs').setValue(self.SamplingPar.Fs.value()) self.Parameters.addChild(self.PSDParams) self.Parameters.sigTreeStateChanged.connect(self.on_pars_changed) self.treepar = ParameterTree() self.treepar.setParameters(self.Parameters, showTop=False) self.treepar.setWindowTitle('pyqtgraph example: Parameter Tree') layout.addWidget(self.treepar) self.setGeometry(650, 20, 400, 800) self.setWindowTitle('MainWindow') self.btnAcq.clicked.connect(self.on_btnStart) self.threadAcq = None self.threadSave = None self.threadPlotter = None self.FileParameters = FileMod.SaveFileParameters(QTparent=self, name='Record File') self.Parameters.addChild(self.FileParameters) self.ConfigParameters = FileMod.SaveSateParameters( QTparent=self, name='Configuration File') self.Parameters.addChild(self.ConfigParameters) def on_pars_changed(self, param, changes): print("tree changes:") for param, change, data in changes: path = self.Parameters.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') if childName == 'SampSettingConf.Sampling Settings.Fs': self.PlotParams.param('Fs').setValue(data) self.PSDParams.param('Fs').setValue(data) if childName == 'SampSettingConf.Sampling Settings.Vgs': if self.threadAcq: Vds = self.threadAcq.DaqInterface.Vds self.threadAcq.DaqInterface.SetBias(Vgs=data, Vds=Vds) if childName == 'SampSettingConf.Sampling Settings.Vds': if self.threadAcq: Vgs = self.threadAcq.DaqInterface.Vgs self.threadAcq.DaqInterface.SetBias(Vgs=Vgs, Vds=data) if childName == 'Plot options.RefreshTime': if self.threadPlotter is not None: self.threadPlotter.SetRefreshTime(data) if childName == 'Plot options.ViewTime': if self.threadPlotter is not None: self.threadPlotter.SetViewTime(data) if childName == 'Raw Plot.ViewTime': if self.threadPlotterRaw is not None: self.threadPlotterRaw.SetViewTime(data) if childName == 'Raw Plot.RefreshTime': if self.threadPlotterRaw is not None: self.threadPlotterRaw.SetRefreshTime(data) def on_NewConf(self): self.Parameters.sigTreeStateChanged.disconnect() self.PlotParams.SetChannels(self.SamplingPar.GetChannelsNames()) self.Parameters.sigTreeStateChanged.connect(self.on_pars_changed) def on_btnStart(self): if self.threadAcq is None: GenKwargs = self.SamplingPar.GetSampKwargs() GenChanKwargs = self.SamplingPar.GetChannelsConfigKwargs() self.threadAcq = AcqMod.DataAcquisitionThread( ChannelsConfigKW=GenChanKwargs, SampKw=GenKwargs) self.threadAcq.NewTimeData.connect(self.on_NewSample) self.threadAcq.start() PlotterKwargs = self.PlotParams.GetParams() # FileName = self.Parameters.param('File Path').value() FileName = self.FileParameters.FilePath() print('Filename', FileName) if FileName == '': print('No file') else: if os.path.isfile(FileName): print('Remove File') os.remove(FileName) MaxSize = self.FileParameters.param('MaxSize').value() self.threadSave = FileMod.DataSavingThread( FileName=FileName, nChannels=PlotterKwargs['nChannels'], MaxSize=MaxSize) self.threadSave.start() self.threadPlotter = PltMod.Plotter(**PlotterKwargs) self.threadPlotter.start() self.threadPSDPlotter = PltMod.PSDPlotter( ChannelConf=PlotterKwargs['ChannelConf'], nChannels=PlotterKwargs['nChannels'], **self.PSDParams.GetParams()) self.threadPSDPlotter.start() self.btnAcq.setText("Stop Gen") self.OldTime = time.time() self.Tss = [] else: self.threadAcq.DaqInterface.Stop() self.threadAcq = None if self.threadSave is not None: self.threadSave.terminate() self.threadSave = None self.threadPlotter.terminate() self.threadPlotter = None self.btnAcq.setText("Start Gen") def on_NewSample(self): ''' Visualization of streaming data-WorkThread. ''' Ts = time.time() - self.OldTime self.Tss.append(Ts) self.OldTime = time.time() if self.threadSave is not None: self.threadSave.AddData(self.threadAcq.aiData) self.threadPlotter.AddData(self.threadAcq.aiData) self.threadPSDPlotter.AddData(self.threadAcq.aiData) print('Sample time', Ts, np.mean(self.Tss))
def _init_extra(self, **kw): self.neuron = kw.get('base_neuron') self.neuron_params = kw.get('neuron_params') for d in self.neuron_params[0]['children']: if 'children' in d.keys(): for dd in d['children']: self.__dict__[dd['name']] = dd['value'] else: pp(d) if 'value' in d.keys(): self.__dict__[d['name']] = d['value'] self.dyn_xticks = [[100 * i, i * 0.1] for i in range(0, 22, 4)] self.script_name = kw.get('script_name', __file__.split('/')[-1][0:-3]) self.p.param('store_state', 'save').sigActivated.connect(self.save) self.p.param('stimulate', 'start').sigActivated.connect(self.stimulate) # Comet for recovery current vs time plot w = pg.PlotWidget() w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('Current', units='A') w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current') w.setRange(QtCore.QRectF(0, -200, self.n_history, 400)) w.setLabel('bottom', 'Time', units='s') w.plotItem.layout.setContentsMargins(20, 20, 20, 20) color = self.kw.get('curve_uv_color', (0, 0, 0)) pen = pg.mkPen(color, width=self.kw.get('curve_uv_width', 5)) self.curve_ut = w.plot(pen=pen) self.widgets.append(w) # Comet for voltage recovery current plot w = pg.PlotWidget() w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('Recovery current u', units='A') w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current/voltage') w.setRange(QtCore.QRectF(-100, -50, 100, 200)) w.setLabel('bottom', 'Voltage', units='V') w.plotItem.layout.setContentsMargins(10, 10, 10, 10) self.widgets.append(w) color = self.kw.get('curve_uv_color', (0, 0, 0)) pen = pg.mkPen(color, width=self.kw.get('curve_uv_width', 5)) self.curve_uv = w.plot(pen=pen) # x,y=self.get_nullcline_extreme_points() # self.curve_uv_extreme_point = w.plot(x,y, pen=pen) color = self.kw.get('curve_uv_color', (0, 0, 0)) self.curve_uv_nullcline0 = w.plot(pen=pen) self.curve_uv_nullcline1 = w.plot(pen=pen) color = self.kw.get('curve_uv_color', (255, 0, 0)) brush = pg.mkBrush(color=color) self.curve_uv_comet = w.plot(symbolBrush=brush, symbol='o', symbolSize=15.) # Parameters base_neuron self.p2 = Parameter.create(name='params', type='group', children=self.neuron_params) self.p2.sigTreeStateChanged.connect(self.change) self.p2.param('IV, IF, nullcline, etc', 'run base_neuron').sigActivated.connect( self.run_neuron_thread) self.p2.param('IV, IF, nullcline, etc', 'run GP-ST network').sigActivated.connect( self.run_GP_STN_network_thread) pt = ParameterTree() pt.setParameters(self.p2, showTop=False) pt.setWindowTitle('Parameters') self.widgets.append(pt) # Threshold type w = pg.PlotWidget() # w.plotItem.getAxis('bottom').setScale(0.001) w.plotItem.getAxis('left').setLabel('a/g_L') # w.plotItem.getAxis('left').setScale(0.000000000001) w.setWindowTitle('Recovery current/voltage') w.setRange(QtCore.QRectF(0, 0, 4, 1)) w.setLabel('bottom', 'tau_m/tau_w') w.plotItem.layout.setContentsMargins(10, 10, 10, 10) self.widgets.append(w) color = self.kw.get('curve_uv_color', (0, 0, 0)) pen = pg.mkPen(color, width=self.kw.get('curve_uv_width', 5)) c1, c2 = self.get_threshold_oscillation_curves() x, y = self.get_threshold_oscilltion_point() color = self.kw.get('curve_uv_color', (255, 0, 0)) brush = pg.mkBrush(color=color) self.curve_oscillation1 = w.plot(c1[0], c1[1], pen=pen) self.curve_oscillation2 = w.plot(c2[0], c2[1], pen=pen) self.curve_oscillation_points1 = w.plot([x[0]], [y[0]], symbolBrush=brush, symbol='o', symbolSize=25.) color = self.kw.get('curve_uv_color', (0, 0, 255)) brush = pg.mkBrush(color=color) self.curve_oscillation_points2 = w.plot([x[1]], [y[1]], symbolBrush=brush, symbol='o', symbolSize=15.) self.draw()
def restore(): global state add = p['Save/Restore functionality', 'Restore State', 'Add missing items'] rem = p['Save/Restore functionality', 'Restore State', 'Remove extra items'] p.restoreState(state, addChildren=add, removeChildren=rem) p.param('Save/Restore functionality', 'Save State').sigActivated.connect(save) p.param('Save/Restore functionality', 'Restore State').sigActivated.connect(restore) ## Create two ParameterTree widgets, both accessing the same data t = ParameterTree() t.setParameters(p, showTop=False) t.setWindowTitle('pyqtgraph example: Parameter Tree') t2 = ParameterTree() t2.setParameters(p, showTop=False) win = QtGui.QWidget() layout = QtGui.QGridLayout() win.setLayout(layout) layout.addWidget( QtGui.QLabel( "These are two views of the same data. They should always display the same values." ), 0, 0, 1, 2) layout.addWidget(t, 1, 0, 1, 1) layout.addWidget(t2, 1, 1, 1, 1) win.show() ## test save/restore
class ParameterWidget(QtGui.QWidget): """Settings Widget takes a list of dictionaries and provides a widget to edit the values (and key names) Each dict object must include these keys: key: The string used to get/set the value, shown to left of value if 'name' not given value: The value to show next to name, matches 'type' if given else use type of this value accepts QColor, lambda, list, generic types Optional keys are: name: the name which is shown to the left of the value for user readability type: Specify the type if it is not obvious by the value provided, as a string suffix: (for float/int values only) added for user readability children: a list of dicts under a 'group' parameter removable: bool specifying if this can be removed (set to False) renamable: bool specifying if this can be renamed (set to False) appendable: bool specifying if user can add to this group To pass in a parent parameter with children, pass 'group' to the 'value' key and the list of dicts to a new 'children' parameter """ done = QtCore.Signal(dict) valueChanged = QtCore.Signal(str, object) def __init__(self, title, paramlist, about="", doneButton=False, appendable=False): super(ParameterWidget, self).__init__() self.ParamGroup = ScalableGroup if appendable else pTypes.GroupParameter self.hasDone = doneButton self.parameters = self.ParamGroup(name="Parameters", children=ParameterWidget.build_parameter_list(paramlist)) self.parameters.sigTreeStateChanged.connect(self.paramsChanged) self.info = about self.tree = ParameterTree() self.tree.setParameters(self.parameters, showTop=False) self.tree.setWindowTitle(title) self.makeLayout() self.resize(800, 600) @staticmethod def type_as_str(var): if type(var) == tuple and len(var) != 3: var = list(var) elif isinstance(var, np.string_): return "str" elif isinstance(var, np.generic): var = float(var) elif isinstance(var, QtGui.QColor) or (type(var) == tuple and len(var) == 3): return "color" elif isinstance(var, dict) or (isinstance(var, list) and all([type(i) == dict for i in var])): return "group" elif isinstance(var, (int, float, bool, list, str)): return type(var).__name__ elif isinstance(var, FunctionType): return "action" return "text" def paramsChanged(self, params, change): obj, change, val = change[0] if change == "value": self.valueChanged.emit(obj.opts["key"], val) else: pass def makeLayout(self): layout = QtGui.QGridLayout() self.setLayout(layout) if len(self.info) > 0: self.scrollArea = QtGui.QScrollArea(self) self.scrollArea.setWidgetResizable(True) self.scrollArea.setWidget(QtGui.QLabel(self.info)) layout.addWidget(self.scrollArea, 0, 0, 1, 2) layout.addWidget(self.tree, 1, 0, 1, 2) if self.hasDone: cancelButton = QtGui.QPushButton("Cancel") cancelButton.clicked.connect(self.close) okButton = QtGui.QPushButton("Ok") okButton.clicked.connect(lambda: self.close(emit=True)) layout.addWidget(cancelButton, 2, 0) layout.addWidget(okButton, 2, 1) layout.setRowStretch(1, 4) @staticmethod def get_group_dict(groupParam): d = {} for c in groupParam.childs: if isinstance(c, pTypes.GroupParameter): d[c.opts["name"]] = ParameterWidget.get_group_dict(c) else: d[c.opts["key"]] = c.opts["value"] return d @staticmethod def build_parameter_list(params): return_params = [] for param_dict in params: assert "key" in param_dict, "Must provide a key for each item" assert "value" in param_dict, ( "Must provide a value for each item; %s does not have a value" % param_dict["key"] ) if param_dict["value"] == None: continue if "name" not in param_dict: param_dict["name"] = param_dict["key"] if param_dict["value"] == "group": return_params.append( pTypes.GroupParameter( name=param_dict["name"], children=ParameterWidget.build_parameter_list(param_dict["children"]) ) ) continue if "type" not in param_dict: param_dict["type"] = ParameterWidget.type_as_str(param_dict["value"]) if param_dict["type"] == "list": param_dict["values"] = param_dict.pop("value") return_params.append(param_dict) return return_params def close(self, emit=False): super(ParameterWidget, self).close() if emit == True: self.done.emit(ParameterWidget.get_group_dict(self.parameters))
class DiffractionGeometry(object): def __init__(self, parent = None): self.parent = parent ############################# ## Dock: Diffraction geometry ############################# self.dock = Dock("Diffraction Geometry", size=(1, 1)) self.win = ParameterTree() self.win.setWindowTitle('Diffraction geometry') self.dock.addWidget(self.win) self.winL = pg.LayoutWidget() self.deployGeomBtn = QtGui.QPushButton('Deploy manually centred geometry') self.winL.addWidget(self.deployGeomBtn, row=0, col=0) self.deployAutoGeomBtn = QtGui.QPushButton('Deploy automatically centred geometry') self.winL.addWidget(self.deployAutoGeomBtn, row=1, col=0) self.dock.addWidget(self.winL) self.resolutionRingList = np.array([100.,300.,500.,700.,900.,1100.]) self.resolutionText = [] self.hasUserDefinedResolution = False self.geom_grp = 'Diffraction geometry' self.geom_detectorDistance_str = 'Detector distance' self.geom_clen_str = 'Home to Detector (clen)' self.geom_coffset_str = 'Sample to Home (coffset)' self.geom_photonEnergy_str = 'Photon energy' self.geom_wavelength_str = "Wavelength" self.geom_pixelSize_str = 'Pixel size' self.geom_resolutionRings_str = 'Resolution rings' self.geom_resolution_str = 'Resolution (pixels)' self.geom_resolutionUnits_str = 'Units' self.geom_unitA_crystal_str = 'Crystallography (Angstrom)' self.geom_unitNm_crystal_str = 'Crystallography (Nanometre)' self.geom_unitQ_crystal_str = 'Crystallography Reciprocal Space (q)' self.geom_unitA_physics_str = 'Physics (Angstrom)' self.geom_unitNm_physics_str = 'Physics (Nanometre)' self.geom_unitQ_physics_str = 'Physics Reciprocal Space (q)' self.geom_unitTwoTheta_str = 'Scattering Angle 2Theta' (self.unitA_c,self.unitNm_c,self.unitQ_c,self.unitA_p,self.unitNm_p,self.unitQ_p,self.unitTwoTheta) = (0,1,2,3,4,5,6) ####################### # Mandatory parameter # ####################### self.params = [ {'name': self.geom_grp, 'type': 'group', 'children': [ {'name': self.geom_detectorDistance_str, 'type': 'float', 'value': 0.0, 'precision': 6, 'minVal': 0.0001, 'siFormat': (6,6), 'siPrefix': True, 'suffix': 'mm'}, {'name': self.geom_clen_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_coffset_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_photonEnergy_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'eV'}, {'name': self.geom_wavelength_str, 'type': 'float', 'value': 0.0, 'step': 1e-6, 'siPrefix': True, 'suffix': 'm', 'readonly': True}, {'name': self.geom_pixelSize_str, 'type': 'float', 'value': 0.0, 'precision': 12, 'minVal': 1e-6, 'siPrefix': True, 'suffix': 'm'}, {'name': self.geom_resolutionRings_str, 'type': 'bool', 'value': False, 'tip': "Display resolution rings", 'children': [ {'name': self.geom_resolution_str, 'type': 'str', 'value': None}, {'name': self.geom_resolutionUnits_str, 'type': 'list', 'values': {self.geom_unitA_crystal_str: self.unitA_c, self.geom_unitNm_crystal_str: self.unitNm_c, self.geom_unitQ_crystal_str: self.unitQ_c, self.geom_unitA_physics_str: self.unitA_p, self.geom_unitNm_physics_str: self.unitNm_p, self.geom_unitQ_physics_str: self.unitQ_p, self.geom_unitTwoTheta_str: self.unitTwoTheta}, 'value': self.unitA_c}, ]}, ]}, ] self.p1 = Parameter.create(name='paramsDiffractionGeometry', type='group', \ children=self.params, expanded=True) self.p1.sigTreeStateChanged.connect(self.change) self.win.setParameters(self.p1, showTop=False) if using_pyqt4: self.parent.connect(self.deployGeomBtn, QtCore.SIGNAL("clicked()"), self.deploy) self.parent.connect(self.deployAutoGeomBtn, QtCore.SIGNAL("clicked()"), self.autoDeploy) else: self.deployGeomBtn.clicked.connect(self.deploy) self.deployAutoGeomBtn.clicked.connect(self.autoDeploy) # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[1] == self.geom_detectorDistance_str: self.updateDetectorDistance(data) elif path[1] == self.geom_clen_str: pass elif path[1] == self.geom_coffset_str: pass elif path[1] == self.geom_photonEnergy_str: self.updatePhotonEnergy(data) elif path[1] == self.geom_pixelSize_str: self.updatePixelSize(data) elif path[1] == self.geom_wavelength_str: pass elif path[1] == self.geom_resolutionRings_str and len(path) == 2: self.updateResolutionRings(data) elif path[2] == self.geom_resolution_str: self.updateResolution(data) elif path[2] == self.geom_resolutionUnits_str: self.updateResolutionUnits(data) def findPsanaGeometry(self): try: self.source = Detector.PyDetector.map_alias_to_source(self.parent.detInfo, self.parent.exp.ds.env()) # 'DetInfo(CxiDs2.0:Cspad.0)' self.calibSource = self.source.split('(')[-1].split(')')[0] # 'CxiDs2.0:Cspad.0' self.detectorType = gu.det_type_from_source(self.source) # 1 self.calibGroup = gu.dic_det_type_to_calib_group[self.detectorType] # 'CsPad::CalibV1' self.detectorName = gu.dic_det_type_to_name[self.detectorType].upper() # 'CSPAD' if self.parent.args.localCalib: self.calibPath = "./calib/" + self.calibGroup + "/" + self.calibSource + "/geometry" else: self.calibPath = self.parent.dir + '/' + self.parent.experimentName[:3] + '/' + \ self.parent.experimentName + "/calib/" + self.calibGroup + '/' + \ self.calibSource + "/geometry" if self.parent.args.v >= 1: print("### calibPath: ", self.calibPath) # Determine which calib file to use geometryFiles = os.listdir(self.calibPath) if self.parent.args.v >= 1: print("geom: ", geometryFiles) self.calibFile = None minDiff = -1e6 for fname in geometryFiles: if fname.endswith('.data'): endValid = False try: startNum = int(fname.split('-')[0]) except: continue endNum = fname.split('-')[-1].split('.data')[0] diff = startNum - self.parent.runNumber # Make sure it's end number is valid too if 'end' in endNum: endValid = True else: try: if self.parent.runNumber <= int(endNum): endValid = True except: continue if diff <= 0 and diff > minDiff and endValid is True: minDiff = diff self.calibFile = fname except: if self.parent.args.v >= 1: print("Couldn't find psana geometry") self.calibFile = None def deployCrystfelGeometry(self, arg): self.findPsanaGeometry() if self.calibFile is not None and self.parent.writeAccess: # Convert psana geometry to crystfel geom if '.temp.geom' in self.parent.index.geom: self.parent.index.p9.param(self.parent.index.index_grp, self.parent.index.index_geom_str).setValue( self.parent.psocakeRunDir + '/.temp.geom') cmd = ["psana2crystfel", self.calibPath + '/' + self.calibFile, self.parent.psocakeRunDir + "/.temp.geom", str(self.parent.coffset)] if self.parent.args.v >= 1: print("cmd: ", cmd) try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE) p.communicate()[0] p.stdout.close() except: print(highlight("Warning! deployCrystfelGeometry() failed.", 'r', 1)) # FIXME: Configure crystfel geom file to read in a mask (crystfel 'mask_file=' broken?) with open(self.parent.psocakeRunDir + '/.temp.geom', 'r') as f: lines = f.readlines() newGeom = [] for line in lines: # remove commented out lines if '; mask =' in line: newGeom.append(line.split('; ')[-1]) elif '; mask_good =' in line: newGeom.append(line.split('; ')[-1]) elif '; mask_bad =' in line: newGeom.append(line.split('; ')[-1]) elif '; clen =' in line: newGeom.append(line.split('; ')[-1]) elif '; photon_energy =' in line: newGeom.append(line.split('; ')[-1]) elif '; adu_per_eV =' in line: if 'epix10k' in self.parent.detInfo.lower() or \ 'jungfrau4m' in self.parent.detInfo.lower(): newGeom.append(line.split('; ')[-1].split('0.1')[0]+"0.001") # override else: newGeom.append(line.split('; ')[-1]) else: newGeom.append(line) with open(self.parent.psocakeRunDir + '/.temp.geom', 'w') as f: f.writelines(newGeom) if self.parent.args.v >= 1: print("Done deployCrystfelGeometry") def updateClen(self, arg): self.p1.param(self.geom_grp, self.geom_clen_str).setValue(self.parent.clen) self.parent.coffset = self.parent.detectorDistance - self.parent.clen self.p1.param(self.geom_grp, self.geom_coffset_str).setValue(self.parent.coffset) if self.parent.args.v >= 1: print("Done updateClen: ", self.parent.coffset, self.parent.detectorDistance, self.parent.clen) def updateDetectorDistance(self, data): self.parent.detectorDistance = data / 1000. # mm to metres self.updateClen(self.parent.facility) if self.parent.args.v >= 1: print("coffset (m), detectorDistance (m), clen (m): ", self.parent.coffset, self.parent.detectorDistance, self.parent.clen) self.writeCrystfelGeom(self.parent.facility) if self.hasGeometryInfo(): if self.parent.args.v >= 1: print("has geometry info") self.updateGeometry() self.parent.img.updatePolarizationFactor() if self.parent.exp.image_property == self.parent.exp.disp_radialCorrection: self.parent.img.updateImage() if self.parent.pk.showPeaks: self.parent.pk.updateClassification() if self.parent.args.v >= 1: print("Done updateDetectorDistance") def updatePhotonEnergy(self, data): if data > 0: self.parent.photonEnergy = data # E = hc/lambda h = 6.626070e-34 # J.m c = 2.99792458e8 # m/s joulesPerEv = 1.602176621e-19 #J/eV if self.parent.photonEnergy > 0: self.parent.wavelength = (h/joulesPerEv*c)/self.parent.photonEnergy else: self.parent.wavelength = 0 self.p1.param(self.geom_grp,self.geom_wavelength_str).setValue(self.parent.wavelength) if self.hasGeometryInfo(): self.updateGeometry() def updatePixelSize(self, data): self.parent.pixelSize = data if self.hasGeometryInfo(): self.updateGeometry() def hasGeometryInfo(self): if self.parent.detectorDistance is not None \ and self.parent.photonEnergy is not None \ and self.parent.pixelSize is not None: return True else: return False def writeCrystfelGeom(self, arg): if self.parent.index.hiddenCXI is not None: if os.path.isfile(self.parent.index.hiddenCXI): f = h5py.File(self.parent.index.hiddenCXI,'r') encoderVal = f['/LCLS/detector_1/EncoderValue'][0] / 1000. # metres f.close() else: encoderVal = self.parent.clen # metres coffset = self.parent.detectorDistance - encoderVal if self.parent.args.v >= 1: print("coffset (m),detectorDistance (m) ,encoderVal (m): ", coffset, self.parent.detectorDistance, encoderVal) # Replace coffset value in geometry file if '.temp.geom' in self.parent.index.geom and os.path.exists(self.parent.index.geom): for line in fileinput.FileInput(self.parent.index.geom, inplace=True): if 'coffset' in line and line.strip()[0] is not ';': coffsetStr = line.split('=')[0]+"= "+str(coffset)+"\n" print(coffsetStr.rstrip()) # FIXME: check whether comma is required elif 'clen' in line and line.strip()[0] is ';': #FIXME: hack for mfxc00318 _c = line.split('; ')[-1] print(_c.rstrip()) # comma is required elif 'photon_energy' in line and line.strip()[0] is ';': #FIXME: hack for mfxc00318 _c = line.split('; ')[-1] print(_c.rstrip()) # comma is required elif 'adu_per_eV' in line and line.strip()[0] is ';': #FIXME: hack for mfxc00318 _c = line.split('; ')[-1] print(_c.rstrip()) # comma is required else: print(line.rstrip()) # comma is required if self.parent.args.v >= 1: print("Done writeCrystfelGeom") def getClosestGeom(self): # Search for the correct geom file to use calibDir = self.parent.rootDir + '/calib/' + self.parent.detInfo + '/geometry' _geomFiles = glob.glob(calibDir + '/*.geom') _runWithGeom = np.array([int(a.split('/')[-1].split('-')[0]) for a in _geomFiles]) diff = _runWithGeom - self.parent.runNumber geomFile = _geomFiles[ int(np.where(diff == np.max(diff[np.where(diff <= 0)[0]]))[0]) ] if self.parent.args.v >= 1: print("getClosestGeom::Choosing this geom file: ", geomFile) return geomFile def updateGeometry(self): if self.hasUserDefinedResolution: self.myResolutionRingList = self.parent.resolution else: self.myResolutionRingList = self.resolutionRingList self.thetaMax = np.zeros_like(self.myResolutionRingList) self.dMin_crystal = np.zeros_like(self.myResolutionRingList) self.qMax_crystal = np.zeros_like(self.myResolutionRingList) self.dMin_physics = np.zeros_like(self.myResolutionRingList) self.qMax_physics = np.zeros_like(self.myResolutionRingList) for i, pix in enumerate(self.myResolutionRingList): if self.parent.detectorDistance > 0 and self.parent.wavelength is not None: self.thetaMax[i] = np.arctan(pix*self.parent.pixelSize/self.parent.detectorDistance) self.qMax_crystal[i] = 2/self.parent.wavelength*np.sin(self.thetaMax[i]/2) self.dMin_crystal[i] = 1/self.qMax_crystal[i] self.qMax_physics[i] = 4*np.pi/self.parent.wavelength*np.sin(self.thetaMax[i]/2) self.dMin_physics[i] = np.pi/self.qMax_physics[i] if self.parent.args.v >= 1: print("updateGeometry: ", i, self.thetaMax[i], self.dMin_crystal[i], self.dMin_physics[i]) if self.parent.resolutionRingsOn: self.updateRings() if self.parent.args.v >= 1: print("Done updateGeometry") def updateDock42(self, data): a = ['a','b','c','d','e','k','m','n','r','s'] myStr = a[5]+a[8]+a[0]+a[5]+a[4]+a[7] if myStr in data: self.d42 = Dock("Console", size=(100,100)) # build an initial namespace for console commands to be executed in (this is optional; # the user can always import these modules manually) namespace = {'pg': pg, 'np': np, 'self': self} # initial text to display in the console text = "You have awoken the "+myStr+"\nWelcome to psocake IPython: dir(self)\n" \ "Here are some commonly used variables:\n" \ "unassembled detector: self.parent.calib\n" \ "assembled detector: self.parent.data\n" \ "user-defined mask: self.parent.mk.userMask\n" \ "streak mask: self.parent.mk.streakMask\n" \ "psana mask: self.parent.mk.psanaMask" self.w42 = console.ConsoleWidget(parent=None,namespace=namespace, text=text) self.d42.addWidget(self.w42) self.parent.area.addDock(self.d42, 'bottom') def updateResolutionRings(self, data): self.parent.resolutionRingsOn = data if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print("Done updateResolutionRings") def updateResolution(self, data): # convert to array of floats _resolution = data.split(',') self.parent.resolution = np.zeros((len(_resolution,))) self.updateDock42(data) if data != '': for i in range(len(_resolution)): self.parent.resolution[i] = float(_resolution[i]) if data != '': self.hasUserDefinedResolution = True else: self.hasUserDefinedResolution = False self.myResolutionRingList = self.parent.resolution self.dMin = np.zeros_like(self.myResolutionRingList) if self.hasGeometryInfo(): self.updateGeometry() if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print("Done updateResolution") def updateResolutionUnits(self, data): # convert to array of floats self.parent.resolutionUnits = data if self.hasGeometryInfo(): self.updateGeometry() if self.parent.exp.hasExpRunDetInfo(): self.updateRings() if self.parent.args.v >= 1: print("Done updateResolutionUnits") def updateRings(self): if self.parent.resolutionRingsOn: self.clearRings() cenx = np.ones_like(self.myResolutionRingList)*self.parent.cx ceny = np.ones_like(self.myResolutionRingList)*self.parent.cy diameter = 2*self.myResolutionRingList self.parent.img.ring_feature.setData(cenx, ceny, symbol='o', \ size=diameter, brush=(255,255,255,0), \ pen='r', pxMode=False) for i,val in enumerate(self.dMin_crystal): if self.parent.resolutionUnits == self.unitA_c: self.resolutionText.append(pg.TextItem(text='%s A' % float('%.3g' % (val*1e10)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitNm_c: self.resolutionText.append(pg.TextItem(text='%s nm' % float('%.3g' % (val*1e9)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitQ_c: self.resolutionText.append(pg.TextItem(text='%s m^-1' % float('%.3g' % (self.qMax_crystal[i])), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitA_p: self.resolutionText.append(pg.TextItem(text='%s A' % float('%.3g' % (self.dMin_physics[i]*1e10)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitNm_p: self.resolutionText.append(pg.TextItem(text='%s nm' % float('%.3g' % (self.dMin_physics[i]*1e9)), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitQ_p: self.resolutionText.append(pg.TextItem(text='%s m^-1' % float('%.3g' % (self.qMax_physics[i])), border='w', fill=(0, 0, 255, 100))) elif self.parent.resolutionUnits == self.unitTwoTheta: self.resolutionText.append(pg.TextItem(text='%s degrees' % float('%.3g' % (self.thetaMax[i]*180/np.pi)), border='w', fill=(0, 0, 255, 100))) self.parent.img.win.getView().addItem(self.resolutionText[i]) self.resolutionText[i].setPos(self.myResolutionRingList[i]+self.parent.cx, self.parent.cy) else: self.clearRings() if self.parent.args.v >= 1: print("Done updateRings") def drawCentre(self): # Always indicate centre of detector try: self.parent.img.centre_feature.setData(np.array([self.parent.cx]), np.array([self.parent.cy]), symbol='o', \ size=6, brush=(255, 255, 255, 0), pen='r', pxMode=False) if self.parent.args.v >= 1: print("Done drawCentre") except: pass def clearRings(self): if self.resolutionText: cen = [0,] self.parent.img.ring_feature.setData(cen, cen, size=0) for i,val in enumerate(self.resolutionText): self.parent.img.win.getView().removeItem(self.resolutionText[i]) self.resolutionText = [] def deploy(self): with pg.BusyCursor(): # Calculate detector translation required in x and y dx = self.parent.pixelSize * 1e6 * (self.parent.roi.centreX - self.parent.cx) # microns dy = self.parent.pixelSize * 1e6 * (self.parent.roi.centreY - self.parent.cy) # microns dz = np.mean(-self.parent.det.coords_z(self.parent.evt)) - self.parent.detectorDistance * 1e6 # microns geo = self.parent.det.geometry(self.parent.evt) top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=-dy, dy=-dx, dz=dz) fname = self.parent.psocakeRunDir + "/"+str(self.parent.runNumber)+'-end.data' geo.save_pars_in_file(fname) print("#################################################") print("Deploying psana detector geometry: ", fname) print("#################################################") cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'recentred geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = self.parent.dir + '/' + self.parent.experimentName[:3] + '/' + \ self.parent.experimentName + '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=fname, dcmts=cmts, pbits=0) # Reload new psana geometry self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.updateRings() self.parent.index.updateIndex() self.drawCentre() # Show mask self.parent.mk.updatePsanaMaskOn() def autoDeploy(self): #FIXME: yet to verify this works correctly on new lab coordinate with pg.BusyCursor(): powderHits = np.load(self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '_maxHits.npy') powderMisses = np.load(self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '_maxMisses.npy') powderImg = self.parent.det.image(self.parent.evt, np.maximum(powderHits,powderMisses)) centreRow, centreCol = findDetectorCentre(np.log(abs(powderImg)), self.parent.cx, self.parent.cy, range=200) print("Current centre along row,centre along column: ", self.parent.cx, self.parent.cy) print("Optimum centre along row,centre along column: ", centreRow, centreCol) allowedDeviation = 175 # pixels if abs(self.parent.cx - centreRow) <= allowedDeviation and \ abs(self.parent.cy - centreCol) <= allowedDeviation: deploy = True else: deploy = False print("Too far away from current centre. I will not deploy the auto centred geometry.") if deploy: # Calculate detector translation in x and y dx = self.parent.pixelSize * 1e6 * (self.parent.cx - centreRow) # microns dy = self.parent.pixelSize * 1e6 * (self.parent.cy - centreCol) # microns dz = np.mean(-self.parent.det.coords_z(self.parent.evt)) - self.parent.detectorDistance * 1e6 # microns dx = self.parent.pixelSize * 1e6 * (self.parent.roi.centreX - self.parent.cx) # microns dy = self.parent.pixelSize * 1e6 * (self.parent.roi.centreY - self.parent.cy) # microns dz = np.mean(-self.parent.det.coords_z(self.parent.evt)) - self.parent.detectorDistance * 1e6 # microns geo = self.parent.det.geometry(self.parent.evt) top = geo.get_top_geo() children = top.get_list_of_children()[0] geo.move_geo(children.oname, 0, dx=-dy, dy=-dx, dz=dz) fname = self.parent.psocakeRunDir + "/" + str(self.parent.runNumber) + '-end.data' geo.save_pars_in_file(fname) print("#################################################") print("Deploying psana detector geometry: ", fname) print("#################################################") cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'auto recentred geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = self.parent.dir + '/' + self.parent.experimentName[:3] + '/' + self.parent.experimentName + \ '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=fname, dcmts=cmts, pbits=0) # Reload new psana geometry self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.updateRings() self.parent.index.updateIndex() self.drawCentre() # Show mask self.parent.mk.updatePsanaMaskOn()
class Ui_MainWindow(object): def setupUi(self, MainWindow, params): #app = QtGui.QApplication([]) #self.win = QtGui.QMainWindow() self.area = DockArea() MainWindow.setCentralWidget(self.area) MainWindow.resize(1200,600) MainWindow.setWindowTitle('SASE optimization') ## Create docks, place them into the window one at a time. ## Note that size arguments are only a suggestion; docks will still have to ## fill the entire dock area and obey the limits of their internal widgets. #self.orb_fig = Dock("Orbit", size=(400, 300)) ## give this dock the minimum possible size #self.orb_fig.float() #self.sase_fig = Dock("SASE", size=(400,300), closable=True) self.sase_fig = Dock("SASE", size=(400,300)) self.blm_fig = Dock("BLM", size=(400,200)) self.seq_cntr = Dock("Sequence", size=(150,200)) self.sase_cntr = Dock("Controls", size=(150,200)) #self.orb_cntr = Dock("orb contr.", size=(400,100)) self.cur_fig = Dock("Settings", size=(400,300)) self.logger = Dock("Logger", size=(100,300)) self.area.addDock(self.cur_fig, 'left') #self.area.addDock(self.orb_fig, 'above', self.cur_fig) ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) self.area.addDock(self.sase_fig, 'bottom', self.cur_fig) ## place d2 at right edge of dock area self.area.addDock(self.blm_fig, 'top', self.sase_fig)## place d3 at bottom edge of d1 self.area.addDock(self.sase_cntr, 'right') ## place d5 at left edge of d1 self.area.addDock(self.seq_cntr, 'left', self.sase_cntr) ## place d4 at right edge of dock area #self.area.addDock(self.orb_cntr, 'bottom', self.orb_fig) ## Test ability to move docks programatically after they have been placed #self.area.moveDock(self.sase_fig, 'bottom', self.orb_fig) ## move d4 to top edge of d2 #self.area.moveDock(self.blm_fig, 'bottom', self.sase_fig) ## move d6 to stack on top of d4 self.area.addDock(self.logger, 'bottom', self.sase_fig) self.area.moveDock(self.blm_fig, 'above', self.logger) ## Add widgets into each dock #add Logger self.log_lab = QtGui.QTextBrowser() #self.log_lab.verticalScrollBar().setValue(self.log_lab.verticalScrollBar().maximum()) self.logger.addWidget(self.log_lab) ## first dock gets save/restore buttons self.t = ParameterTree() if params != None: self.p = Parameter.create(name='params', type='group', children=params) self.t.setParameters(self.p, showTop=False) self.t.setWindowTitle('SASE optimization') self.seq_cntr.addWidget(self.t) self.seq = pg.LayoutWidget() self.label = QtGui.QLabel("""sequence control""") self.add_seq_btn = QtGui.QPushButton('Add Action') self.save_seq_btn = QtGui.QPushButton('Save seqs') self.load_seq_btn = QtGui.QPushButton('Load seqs') #self.restoreBtn.setEnabled(False) self.seq.addWidget(self.label, row=0, col=0) self.seq.addWidget(self.add_seq_btn, row=1, col=0) self.seq.addWidget(self.save_seq_btn, row=2, col=0) self.seq.addWidget(self.load_seq_btn, row=3, col=0) self.seq_cntr.addWidget(self.seq) #Currents graphics self.t_cur_cntr = ParameterTree() #param = [{'name': 'Devices', 'type': 'list', 'values': {}, 'value': 0}] param = [] self.p_cur_cntr = Parameter.create(name='control', type='group', children=param) self.t_cur_cntr.setParameters(self.p_cur_cntr, showTop=False) self.current = pg.PlotWidget(title="Settings") self.cur_fig.addWidget(self.current, row=0, col=0) self.cur_fig.addWidget(self.t_cur_cntr, row=0, col=1) #BLM graphics ## Hide title bar on dock 3 #d3.hideTitleBar() self.blm = pg.PlotWidget(title="BLM") self.blm_fig.addWidget(self.blm) #SASE graphics self.sase = pg.PlotWidget(title="SASE") self.sase_fig.addWidget(self.sase) #controls self.w5 = pg.LayoutWidget() self.start_opt_btm = QtGui.QPushButton('start') params = [ {'name': 'Basic opt. parameters', 'type': 'group', 'children': [ {'name': 'debug', 'type': 'bool', 'value': False}, {'name': 'logging', 'type': 'bool', 'value': True}, {'name': 'log file', 'type': 'str', 'value': 'test.log'}, {'name': 'timeout', 'type': 'float', 'value': 0.5, 'step': 0.1, 'limits': (0, 10)}, #{'name': 'SASE det.', 'type': 'list', 'values': {'mcp': 'mcp', 'gmd slow':'gmd_fl1_slow', 'bkr':'bkr', 'default':'gmd_default'}, 'value': "default"}, {'name': 'detector', 'type': 'list', 'values': ['gmd_default', 'mcp', 'gmd_fl1_slow', 'bkr'], 'value': "gmd_default"} ]} ] self.t_cntr = ParameterTree() self.p_cntr = Parameter.create(name='control', type='group', children=params) self.t_cntr.setParameters(self.p_cntr, showTop=False) self.restore_cur_btn = QtGui.QPushButton('Restore') #self.restore_cur_btn.setEnabled(False) self.setmax_opt_btn = QtGui.QPushButton('Set currents for max SASE') #self.setmax_opt_btn.setEnabled(False) self.stop_opt_btn = QtGui.QPushButton('Stop') self.clear_disp_btn = QtGui.QPushButton('Clear display') self.save_machine_btn = QtGui.QPushButton('Save new tuning') #self.save_machine_btn.setEnabled(False) #self.stop_btn = QtGui.QPushButton('stop') #self.w5.addWidget(self.start_opt_btm, row=0, col=0) self.w5.addWidget(self.stop_opt_btn, row=0, col=0) self.w5.addWidget(self.restore_cur_btn, row=1, col=0) #self.w5.addWidget(self.setmax_opt_btn, row=2, col=0) self.w5.addWidget(self.clear_disp_btn, row=4, col=0) #self.w5.addWidget(self.debug_opt_chk, row=3, col=0) #self.w5.addWidget(self.log_opt_chk, row=4, col=0) self.w5.addWidget(self.t_cntr, row=5, col=0) #self.w5.addWidget(QtGui.QLabel("""machine settings"""), row=6, col=0) #self.w5.addWidget(self.save_machine_btn, row=7, col=0) self.sase_cntr.addWidget(self.w5)
class JsonReader(QWidget): def __init__(self): super().__init__() self.title = 'Json metadata reader' self.initUI() def initUI(self): self.setWindowTitle(self.title) self.getbtn = QPushButton("Select file") self.getbtn.clicked.connect(self.get_file) self.draglbl = DragDropLabel(self) self.draglbl.setText("... or drop .{} file here".format( DragDropLabel.acceptedFormat.upper())) self.draglbl.setAlignment(QtCore.Qt.AlignCenter) self.draglbl.droppedFile.connect(self.open_file) self.layout = QGridLayout(self) self.layout.addWidget(self.getbtn, 0, 0, 1, 2) self.layout.addWidget(self.draglbl, 1, 0, 1, 2) self.setLayout(self.layout) self.show() def get_file(self): self.path, _ = QFileDialog.getOpenFileName( filter="Json files (*.json)") if not self.path: pass else: self.open_file(self.path) def open_file(self, filename): self.filename = filename with open(filename) as json_file: self.metadata_dict = json.load(json_file) self.display_tree_widget(self.metadata_dict) def display_tree_widget(self, metadata): """Display the parameter tree from the experiment metadata. :param metadata: .json metadata """ # Close previous tree widget self.close_tree() # Create a variable checking whether changes have been made to the parameter tree values self.has_changed = False # Create list with parameters for the tree self.parameters = self.create_parameters(self.fix_types(metadata)) # Create tree of Parameter objects self.p = Parameter.create(name='params', type='group', children=self.parameters) # Save original state self.original_state = self.p.saveState() # Create ParameterTree widget self.tree = ParameterTree() self.tree.setParameters(self.p, showTop=False) self.tree.setWindowTitle('pyqtgraph example: Parameter Tree') # Display tree widget self.layout.addWidget(self.tree, 2, 0, 1, 2) # And buttons self.savebtn = QPushButton("Save changes") self.resetbtn = QPushButton("Reset changes") self.layout.addWidget(self.savebtn, 3, 0) self.layout.addWidget(self.resetbtn, 3, 1) self.savebtn.clicked.connect(self.save_treevals) self.resetbtn.clicked.connect(self.reset) # Send signal when any entry is changed self.p.sigTreeStateChanged.connect(self.change) def save_treevals(self): """Save current values of the parameter tree into a dictionary. """ # Recover data from tree and store it in a dict self.treevals_dict = self.p.getValues() self.metadata_dict_mod = self.get_mod_dict(self.treevals_dict) # Nasty way to make new dict (with modified metadata) with same structure as the original one self.metadata_dict_mod['stimulus']['log'] = self.metadata_dict[ 'stimulus']['log'] self.metadata_dict_mod['stimulus']['display_params']['pos'] = \ json.loads(self.metadata_dict_mod['stimulus']['display_params']['pos']) self.metadata_dict_mod['stimulus']['display_params']['size'] = \ json.loads(self.metadata_dict_mod['stimulus']['display_params']['size']) self.show_warning() def show_warning(self): """Upon saving, display a warning message to choose whether to create a new metadata file or replace the existing one. """ if self.has_changed: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.setWindowTitle("Saving Warning") self.msg.setText("Some parameters have changed") self.msg.setInformativeText( "Do you want to overwrite the original .json metadata file?") self.msg.addButton('Create new file', QMessageBox.AcceptRole) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) self.ret = self.msg.exec_() if self.ret == QMessageBox.Yes: self.overwrite_metadata_file(self.metadata_dict_mod) elif self.ret == QMessageBox.AcceptRole: self.create_metadata_file(self.metadata_dict_mod) else: pass else: self.msg2 = QMessageBox() self.msg2.setIcon(QMessageBox.Information) self.setWindowTitle("Saving Warning") self.msg2.setText("No changes have been made.") self.msg2.addButton('OK', QMessageBox.AcceptRole) self.ret = self.msg2.exec_() def overwrite_metadata_file(self, metadata_dict_mod): # Overwritte original metadata file with open(self.filename, 'w') as file: json.dump(metadata_dict_mod, file) def create_metadata_file(self, metadata_dict_mod): # Overwritte original metadata file self.name, self.ext = self.filename.split('.') with open('{}_modified.{}'.format(self.name, self.ext), 'w') as file: json.dump(metadata_dict_mod, file) def reset(self): """Reset parameter tree values to the original state after loading. """ self.p.restoreState(self.original_state, recursive=True) #self.tree.setParameters(self.p, showTop=False) def fix_types(self, datadict): """Modify metadata dict so only accepted types are found. """ param_dict = dict() for key, value in datadict.items(): if isinstance(value, list): param_dict[key] = str(value) elif isinstance(value, dict): param_dict[key] = self.fix_types(value) else: param_dict[key] = value return param_dict def create_parameters(self, datadict): """Create list with parameters and Children to which the tree will be built from. """ parameters = [] for key, value in datadict.items(): if key == 'log': pass else: if isinstance(value, dict): parameters.append({ 'name': '{}'.format(key), 'type': 'group', 'children': self.create_parameters(value) }) else: parameters.append({ 'name': '{}'.format(key), 'type': '{}'.format(type(value).__name__), 'value': value }) return parameters def get_mod_dict(self, treevals_dict): """Recursive function to convert into dict output of getValues function. """ metadata_dict_mod = dict() for key, value in treevals_dict.items(): if value[0] is None: metadata_dict_mod[key] = dict(self.get_mod_dict(value[1])) else: metadata_dict_mod[key] = value[0] return metadata_dict_mod def change(self, param, changes): print("tree changes:") for param, change, data in changes: path = self.p.childPath(param) if path is not None: childName = '.'.join(path) else: childName = param.name() print(' parameter: %s' % childName) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') if change == 'activated': pass else: self.has_changed = True def close_tree(self): try: self.layout.removeWidget(self.tree) self.tree.deleteLater() self.tree = None except AttributeError: pass
class ExperimentInfo(object): def __init__(self, parent = None): self.parent = parent ############################# ## Dock 2: parameter ############################# self.d2 = Dock("Experiment Parameters", size=(1, 1)) self.w2 = ParameterTree() self.w2.setWindowTitle('Parameters') self.d2.addWidget(self.w2) self.exp_grp = 'Experiment information' self.exp_name_str = 'Experiment Name' self.exp_run_str = 'Run Number' self.exp_det_str = 'DetInfo' self.exp_evt_str = 'Event Number' self.exp_eventID_str = 'EventID' self.exp_second_str = 'Seconds' self.exp_nanosecond_str = 'Nanoseconds' self.exp_fiducial_str = 'Fiducial' self.exp_numEvents_str = 'Total Events' self.exp_detInfo_str = 'Detector ID' self.eventSeconds = 0 self.eventNanoseconds = 0 self.eventFiducial = 0 self.eventTotal = 0 self.run = None self.times = None self.disp_grp = 'Display' self.disp_log_str = 'Logscale' self.disp_aduPerPhoton_str = 'ADUs per Photon' self.disp_image_str = 'Image properties' self.disp_adu_str = 'gain corrected ADU' self.disp_gain_str = 'gain' self.disp_gainMask_str = 'gain_mask' self.disp_coordx_str = 'coord_x' self.disp_coordy_str = 'coord_y' self.disp_quad_str = 'quad number' self.disp_seg_str = 'seg number' self.disp_row_str = 'row number' self.disp_col_str = 'col number' self.disp_raw_str = 'raw ADU' self.disp_pedestalCorrected_str = 'pedestal corrected ADU' self.disp_commonModeCorrected_str = 'common mode corrected ADU' self.disp_photons_str = 'photon counts' self.disp_rms_str = 'pixel rms' self.disp_status_str = 'pixel status' self.disp_pedestal_str = 'pedestal' self.disp_commonMode_str = 'common mode' self.disp_friedel_str = 'Apply Friedel symmetry' self.disp_commonModeOverride_str = 'Common mode (override)' self.disp_overrideCommonMode_str = 'Apply common mode (override)' self.disp_commonModeParam0_str = 'parameters 0' self.disp_commonModeParam1_str = 'parameters 1' self.disp_commonModeParam2_str = 'parameters 2' self.disp_commonModeParam3_str = 'parameters 3' self.disp_medianCorrection_str = 'median background corrected ADU' self.disp_radialCorrection_str = 'radial background corrected ADU' self.disp_medianFilterRank_str = 'median filter rank' self.logscaleOn = False self.aduPerPhoton = 1. self.medianFilterRank = 5 # image properties self.disp_medianCorrection = 19 self.disp_radialCorrection = 18 self.disp_gainMask = 17 self.disp_coordy= 16 self.disp_coordx= 15 self.disp_col= 14 self.disp_row= 13 self.disp_seg= 12 self.disp_quad= 11 self.disp_gain= 10 self.disp_commonMode= 9 self.disp_rms= 8 self.disp_status= 7 self.disp_pedestal= 6 self.disp_photons= 5 self.disp_raw= 4 self.disp_pedestalCorrected= 3 self.disp_commonModeCorrected= 2 self.disp_adu= 1 self.image_property = self.disp_adu self.applyFriedel = False self.applyCommonMode = False self.commonModeParams = np.array([0,0,0,0]) self.commonMode = np.array([0, 0, 0, 0]) self.firstSetupExperiment = True # e-log self.logger = False self.loggerFile = None self.crawlerRunning = False self.username = None self.rt = None self.table = None self.params = [ {'name': self.exp_grp, 'type': 'group', 'children': [ {'name': self.exp_name_str, 'type': 'str', 'value': self.parent.experimentName, 'tip': "Experiment name, .e.g. cxic0415"}, {'name': self.exp_run_str, 'type': 'int', 'value': self.parent.runNumber, 'tip': "Run number, e.g. 15"}, {'name': self.exp_detInfo_str, 'type': 'str', 'value': self.parent.detInfo, 'tip': "Detector ID. Look at the terminal for available area detectors, e.g. DscCsPad"}, {'name': self.exp_evt_str, 'type': 'int', 'value': self.parent.eventNumber, 'tip': "Event number, first event is 0", 'children': [ # {'name': exp_eventID_str, 'type': 'str', 'value': self.eventID},#, 'readonly': False}, {'name': self.exp_second_str, 'type': 'str', 'value': self.eventSeconds, 'readonly': True}, {'name': self.exp_nanosecond_str, 'type': 'str', 'value': self.eventNanoseconds, 'readonly': True}, {'name': self.exp_fiducial_str, 'type': 'str', 'value': self.eventFiducial, 'readonly': True}, {'name': self.exp_numEvents_str, 'type': 'str', 'value': self.eventTotal, 'readonly': True}, ]}, ]}, {'name': self.disp_grp, 'type': 'group', 'children': [ {'name': self.disp_log_str, 'type': 'bool', 'value': self.logscaleOn, 'tip': "Display in log10"}, {'name': self.disp_aduPerPhoton_str, 'type': 'float', 'value': self.aduPerPhoton, 'tip': "ADUs per photon is used for photon conversion"}, {'name': self.disp_medianFilterRank_str, 'type': 'int', 'value': self.medianFilterRank, 'tip': "Window size for median filter"}, {'name': self.disp_image_str, 'type': 'list', 'values': {self.disp_medianCorrection_str: self.disp_medianCorrection, self.disp_radialCorrection_str: self.disp_radialCorrection, self.disp_gainMask_str: self.disp_gainMask, self.disp_coordy_str: self.disp_coordy, self.disp_coordx_str: self.disp_coordx, self.disp_col_str: self.disp_col, self.disp_row_str: self.disp_row, self.disp_seg_str: self.disp_seg, self.disp_quad_str: self.disp_quad, self.disp_gain_str: self.disp_gain, self.disp_commonMode_str: self.disp_commonMode, self.disp_rms_str: self.disp_rms, self.disp_status_str: self.disp_status, self.disp_pedestal_str: self.disp_pedestal, self.disp_photons_str: self.disp_photons, self.disp_raw_str: self.disp_raw, self.disp_pedestalCorrected_str: self.disp_pedestalCorrected, self.disp_commonModeCorrected_str: self.disp_commonModeCorrected, self.disp_adu_str: self.disp_adu}, 'value': self.image_property, 'tip': "Choose image property to display"}, {'name': self.disp_friedel_str, 'type': 'bool', 'value': self.applyFriedel, 'tip': "Click to apply Friedel symmetry to the detector image."}, {'name': self.disp_commonModeOverride_str, 'visible': True, 'expanded': False, 'type': 'str', 'value': "", 'readonly': True, 'children': [ {'name': self.disp_overrideCommonMode_str, 'type': 'bool', 'value': self.applyCommonMode, 'tip': "Click to play around with common mode settings.\n This does not change your deployed calib file."}, {'name': self.disp_commonModeParam0_str, 'type': 'int', 'value': self.commonModeParams[0]}, {'name': self.disp_commonModeParam1_str, 'type': 'int', 'value': self.commonModeParams[1]}, {'name': self.disp_commonModeParam2_str, 'type': 'int', 'value': self.commonModeParams[2]}, {'name': self.disp_commonModeParam3_str, 'type': 'int', 'value': self.commonModeParams[3]}, ]}, ]}, ] self.p = Parameter.create(name='params', type='group', children=self.params, expanded=True) self.w2.setParameters(self.p, showTop=False) self.p.sigTreeStateChanged.connect(self.change) # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[0] == self.exp_grp: if path[1] == self.exp_name_str: self.updateExpName(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.exp_run_str: self.updateRunNumber(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.exp_detInfo_str: self.updateDetInfo(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.exp_evt_str and len(path) == 2 and change is 'value': self.updateEventNumber(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[0] == self.disp_grp: if path[1] == self.disp_log_str: self.updateLogscale(data) elif path[1] == self.disp_aduPerPhoton_str: self.updateAduPerPhoton(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.disp_medianFilterRank_str: self.updateMedianFilter(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.disp_image_str: self.updateImageProperty(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() elif path[1] == self.disp_friedel_str: self.updateFriedel(data) elif path[2] == self.disp_commonModeParam0_str: self.updateCommonModeParam(data, 0) elif path[2] == self.disp_commonModeParam1_str: self.updateCommonModeParam(data, 1) elif path[2] == self.disp_commonModeParam2_str: self.updateCommonModeParam(data, 2) elif path[2] == self.disp_commonModeParam3_str: self.updateCommonModeParam(data, 3) elif path[2] == self.disp_overrideCommonMode_str: self.updateCommonMode(data) if self.parent.pk.showPeaks: self.parent.pk.updateClassification() ################################### ###### Experiment Parameters ###### ################################### def resetVariables(self): self.secList = None self.nsecList = None self.fidList = None def updateExpName(self, data): self.parent.experimentName = data self.parent.hasExperimentName = True self.parent.detInfoList = None self.resetVariables() # Setup elog if logbook_present: self.rt = RunTables(**{'web-service-url': 'https://pswww.slac.stanford.edu/ws-kerb'}) try: self.table = self.rt.findUserTable(exper_name=self.parent.experimentName, table_name='Run summary') except: self.table = None #print "Your experiment may not exist" #print "Or you need a kerberos ticket. Type: kinit" #exit() #exit() self.setupExperiment() self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateExperimentName:", self.parent.experimentName def updateRunNumber(self, data): if data == 0: self.parent.runNumber = data self.parent.hasRunNumber = False else: self.parent.runNumber = data self.parent.hasRunNumber = True self.parent.detInfoList = None self.setupExperiment() self.parent.mk.resetMasks() self.resetVariables() self.parent.pk.userUpdate = None self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateRunNumber: ", self.parent.runNumber def updateDetInfo(self, data): if self.parent.hasDetInfo is False or self.parent.detInfo is not data: self.parent.mk.resetMasks() self.parent.calib = None self.parent.data = None self.parent.firstUpdate = True self.parent.detInfo = data if data == 'DscCsPad' or data == 'DsdCsPad' or data == 'DsaCsPad': self.parent.isCspad = True self.parent.hasDetInfo = True self.setupExperiment() self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateDetInfo: ", self.parent.detInfo def findEventFromTimestamp(self, secList, nsecList, fidList, sec, nsec, fid): eventNumber = (np.where(secList == sec)[0] & np.where(nsecList == nsec)[0] & np.where(fidList == fid)[0])[0] return eventNumber def convertTimestamp64(self, t): _sec = int(t) >> 32 _nsec = int(t) & 0xFFFFFFFF return _sec, _nsec def convertSecNanosec(self, sec, nsec): _timestamp64 = int(sec << 32 | nsec) return _timestamp64 def getEvt(self, evtNumber): if self.parent.hasRunNumber: _evt = self.run.event(self.times[evtNumber]) return _evt else: return None def getEventID(self, evt): if evt is not None: _evtid = evt.get(psana.EventId) _seconds = _evtid.time()[0] _nanoseconds = _evtid.time()[1] _fiducials = _evtid.fiducials() return _seconds, _nanoseconds, _fiducials def updateEventNumber(self, data): self.parent.eventNumber = data if self.parent.eventNumber >= self.eventTotal: self.parent.eventNumber = self.eventTotal - 1 # update timestamps and fiducial self.parent.evt = self.getEvt(self.parent.eventNumber) if self.parent.evt is not None: sec, nanosec, fid = self.getEventID(self.parent.evt) self.eventSeconds = str(sec) self.eventNanoseconds = str(nanosec) self.eventFiducial = str(fid) self.updateEventID(self.eventSeconds, self.eventNanoseconds, self.eventFiducial) self.p.param(self.exp_grp, self.exp_evt_str).setValue(self.parent.eventNumber) self.parent.img.updateImage() # update labels if self.parent.args.mode == "all": if self.parent.evtLabels is not None: self.parent.evtLabels.refresh() if self.parent.args.v >= 1: print "Done updateEventNumber: ", self.parent.eventNumber def hasExpRunInfo(self): if self.parent.hasExperimentName and self.parent.hasRunNumber: # Check such a run exists import glob xtcs = glob.glob('/reg/d/psdm/' + self.parent.experimentName[0:3] + '/' + self.parent.experimentName + '/xtc/*-r' + str( self.parent.runNumber).zfill(4) + '-*.xtc') if len(xtcs) > 0: return True else: # reset run number if self.parent.runNumber > 0: print "No such run exists in: ", self.parent.experimentName self.parent.runNumber = 0 self.updateRunNumber(self.parent.runNumber) self.p.param(self.exp_grp, self.exp_run_str).setValue(self.parent.runNumber) return False return False def hasExpRunDetInfo(self): if self.parent.args.v >= 1: print "exp,run,det: ", self.parent.hasExperimentName, self.parent.hasRunNumber, self.parent.hasDetInfo if self.parent.hasExperimentName and self.parent.hasRunNumber and self.parent.hasDetInfo: if self.parent.args.v >= 1: print "hasExpRunDetInfo: True ", self.parent.runNumber return True else: if self.parent.args.v >= 1: print "hasExpRunDetInfo: False ", self.parent.runNumber return False def getUsername(self): process = subprocess.Popen('whoami', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = process.communicate() self.username = out.strip() def setupPsocake(self): self.loggerFile = self.parent.elogDir + '/logger.data' if os.path.exists(self.parent.elogDir) is False: try: os.makedirs(self.parent.elogDir, 0774) # setup permissions process = subprocess.Popen('chgrp -R ' + self.parent.experimentName + ' ' + self.parent.elogDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = process.communicate() process = subprocess.Popen('chmod -R u+rwx,g+rws,o+rx ' + self.parent.elogDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = process.communicate() # create logger with open(self.loggerFile, "w") as myfile: if self.parent.args.outDir is None: myfile.write(self.username) else: myfile.write("NOONE") except: print "No write access: ", self.parent.elogDir else: # check if I'm a logger with open(self.loggerFile, "r") as myfile: content = myfile.readlines() if content[0].strip() == self.username: if logbook_present and self.table is not None: self.logger = True else: print "WARNING: logbook not present" if logbook_present and self.parent.args.v >= 1: print "I'm an elogger" else: self.logger = False if self.parent.args.v >= 1: print "I'm not an elogger" # Make run folder try: if os.path.exists(self.parent.psocakeRunDir) is False: if self.parent.args.outDir is None: os.makedirs(self.parent.psocakeRunDir, 0774) else: # don't let groups and others access to this folder os.makedirs(self.parent.psocakeRunDir, 0700) process = subprocess.Popen('chmod -R ' + self.parent.psocakeRunDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = process.communicate() self.parent.writeAccess = True except: print "No write access: ", self.parent.psocakeRunDir self.parent.writeAccess = False # Launch crawler crawlerThread = [] crawlerThreadCounter = 0 def launchCrawler(self): self.crawlerThread.append(LogbookCrawler.LogbookCrawler(self.parent)) # send parent parameters with self self.crawlerThread[self.crawlerThreadCounter].updateLogbook(self.parent.experimentName, self.parent.psocakeDir) self.crawlerThreadCounter += 1 def getDetectorAlias(self, srcOrAlias): for i in self.parent.detInfoList: src, alias, _ = i if srcOrAlias.lower() == src.lower() or srcOrAlias.lower() == alias.lower(): return alias def updateHiddenCrystfelFiles(self, arg): if arg == 'lcls': if ('cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName) or \ ('rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName): self.parent.index.hiddenCXI = self.parent.psocakeRunDir + '/.temp.cxi' self.parent.index.hiddenCrystfelStream = self.parent.psocakeRunDir + '/.temp.stream' self.parent.index.hiddenCrystfelList = self.parent.psocakeRunDir + '/.temp.lst' else: if self.parent.args.v >= 1: print "updateHiddenCrystfelFiles not implemented" self.parent.index.hiddenCXI = None def updateDetectorDistance(self, arg): if arg == 'lcls': if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName: if self.parent.detectorDistance < 0.01: self.parent.detectorDistance = np.mean(self.parent.det.coords_z(self.parent.evt)) * 1e-6 # metres self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_detectorDistance_str).setValue(self.parent.detectorDistance*1e3) # mm self.parent.coffset = self.parent.detectorDistance - self.parent.clen self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_clen_str).setValue(self.parent.clen) elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName: if self.parent.detectorDistance < 0.01: self.parent.detectorDistance = np.mean(self.parent.det.coords_z(self.parent.evt)) * 1e-6 # metres self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_detectorDistance_str).setValue(self.parent.detectorDistance*1e3) # mm self.parent.coffset = self.parent.detectorDistance - self.parent.clen self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_clen_str).setValue(self.parent.clen) elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName: if self.parent.detectorDistance < 0.01: self.parent.detectorDistance = np.mean(self.parent.det.coords_z(self.parent.evt)) * 1e-6 # metres self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_detectorDistance_str).setValue(self.parent.detectorDistance*1e3) # mm self.parent.coffset = self.parent.detectorDistance - self.parent.clen self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_clen_str).setValue( self.parent.clen) else: if self.parent.args.v >= 1: print "updateDetectorDistance: not implemented for this detector yet" if self.parent.args.v >= 1: print "detectorDistance (m), self.clen (m), self.coffset (m): ", self.parent.detectorDistance, self.parent.clen, self.parent.coffset def updatePixelSize(self, arg): if arg == 'lcls': if 'cspad' in self.parent.detInfo.lower(): # TODO: increase pixel size list: epix, rayonix self.parent.pixelSize = 110e-6 # metres elif 'pnccd' in self.parent.detInfo.lower(): self.parent.pixelSize = 75e-6 # metres elif 'rayonix' in self.parent.detInfo.lower(): self.parent.pixelSize = 89e-6 # metres # Update geometry panel self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_pixelSize_str).setValue( self.parent.pixelSize) # pixel size def updatePhotonEnergy(self, arg): if arg == 'lcls': self.parent.ebeam = self.parent.evt.get(psana.Bld.BldDataEBeamV7, psana.Source('BldInfo(EBeam)')) if self.parent.ebeam: self.parent.photonEnergy = self.parent.ebeam.ebeamPhotonEnergy() else: try: wavelength = self.parent.epics.value('SIOC:SYS0:ML00:AO192') # nanometre h = 6.626070e-34 # J.m c = 2.99792458e8 # m/s joulesPerEv = 1.602176621e-19 # J/eV self.parent.photonEnergy = (h / joulesPerEv * c) / (wavelength * 1e-9) except: self.parent.photonEnergy = 0.0 self.parent.geom.p1.param(self.parent.geom.geom_grp, self.parent.geom.geom_photonEnergy_str).setValue(self.parent.photonEnergy) def setClen(self): if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName: try: self.parent.clenEpics = str(self.parent.detAlias) + '_z' self.readEpicsClen() except: if 'ds1' in self.parent.detInfo.lower(): self.parent.clenEpics = str('CXI:DS1:MMS:06.RBV') self.readEpicsClen() elif 'ds2' in self.parent.detInfo.lower(): self.parent.clenEpics = str('CXI:DS2:MMS:06.RBV') self.readEpicsClen() else: print "Couldn't handle detector clen. Try using the full detector name." exit() elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName: print "setClen: Not implemented yet" self.parent.clenEpics = 'MFX:DET:MMS:04' #'Rayonix_z' try: self.readEpicsClen() except: print "ERROR: No such epics variable, ", self.parent.clenEpics print "ERROR: setting clen to 0.0 metre" self.parent.clen = 0.0 # metres elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName: self.parent.clenEpics = 'XPP:ROB:POS:Z' try: self.readEpicsClen() except: print "ERROR: No such epics variable, ", self.parent.clenEpics print "ERROR: setting clen to 0.0 metre" self.parent.clen = 0.0 # metres else: if self.parent.args.v >= 1: print "Not implemented yet clen: ", self.parent.detInfo def readEpicsClen(self): for i in range(120): # assume at least 1 second run time evt = self.run.event(self.times[i]) self.parent.clen = self.parent.epics.value(self.parent.clenEpics) / 1000. # metres if i == 0: _temp = self.parent.clen if i > 0: if abs(_temp - self.parent.clen) >= 0.01: break _temp = self.parent.clen if self.parent.args.v >= 1: print "Best guess at clen: ", self.parent.clen def setupExperiment(self): if self.parent.args.v >= 1: print "Doing setupExperiment" if self.hasExpRunInfo(): self.getUsername() # Set up psocake directory in scratch if self.parent.args.outDir is None: self.parent.rootDir = '/reg/d/psdm/' + self.parent.experimentName[:3] + '/' + self.parent.experimentName self.parent.elogDir = self.parent.rootDir + '/scratch/psocake' self.parent.psocakeDir = self.parent.rootDir + '/scratch/' + self.username + '/psocake' else: self.parent.rootDir = self.parent.args.outDir self.parent.elogDir = self.parent.rootDir + '/psocake' self.parent.psocakeDir = self.parent.rootDir + '/' + self.username + '/psocake' self.parent.psocakeRunDir = self.parent.psocakeDir + '/r' + str(self.parent.runNumber).zfill(4) if self.parent.args.v >= 1: print "psocakeDir: ", self.parent.psocakeDir # Update peak finder outdir and run number self.parent.pk.p3.param(self.parent.pk.hitParam_grp, self.parent.pk.hitParam_outDir_str).setValue(self.parent.psocakeDir) self.parent.pk.p3.param(self.parent.pk.hitParam_grp, self.parent.pk.hitParam_runs_str).setValue(self.parent.runNumber) # Update powder outdir and run number self.parent.mk.p6.param(self.parent.mk.powder_grp, self.parent.mk.powder_outDir_str).setValue(self.parent.psocakeDir) self.parent.mk.p6.param(self.parent.mk.powder_grp, self.parent.mk.powder_runs_str).setValue(self.parent.runNumber) # Update hit finding outdir, run number self.parent.hf.p8.param(self.parent.hf.spiParam_grp, self.parent.hf.spiParam_outDir_str).setValue(self.parent.psocakeDir) self.parent.hf.p8.param(self.parent.hf.spiParam_grp, self.parent.hf.spiParam_runs_str).setValue(self.parent.runNumber) # Update indexing outdir, run number self.parent.index.p9.param(self.parent.index.launch_grp, self.parent.index.outDir_str).setValue(self.parent.psocakeDir) self.parent.index.p9.param(self.parent.index.launch_grp, self.parent.index.runs_str).setValue(self.parent.runNumber) # Update quantifier filename fname = self.parent.psocakeRunDir + '/' + self.parent.experimentName + '_' + str(self.parent.runNumber).zfill(4) + '.cxi' if self.parent.args.mode == 'sfx': dsetname = '/entry_1/result_1/nPeaksAll' elif self.parent.args.mode == 'spi': dsetname = '/entry_1/result_1/nHitsAll' else: dsetname = '/entry_1/result_1/' self.parent.small.pSmall.param(self.parent.small.quantifier_grp, self.parent.small.quantifier_filename_str).setValue(fname) self.parent.small.pSmall.param(self.parent.small.quantifier_grp, self.parent.small.quantifier_dataset_str).setValue(dsetname) self.setupPsocake() # Update hidden CrystFEL files self.updateHiddenCrystfelFiles('lcls') if self.parent.args.localCalib: if self.parent.args.v >= 1: print "Using local calib directory" psana.setOption('psana.calib-dir', './calib') try: self.ds = psana.DataSource('exp=' + str(self.parent.experimentName) + ':run=' + str( self.parent.runNumber) + ':idx') except: print "############# No such datasource exists ###############" self.run = self.ds.runs().next() self.times = self.run.times() self.eventTotal = len(self.times) self.parent.stack.spinBox.setMaximum(self.eventTotal - self.parent.stack.stackSize) self.p.param(self.exp_grp, self.exp_evt_str).setLimits((0, self.eventTotal - 1)) self.p.param(self.exp_grp, self.exp_evt_str, self.exp_numEvents_str).setValue(self.eventTotal) self.env = self.ds.env() if self.parent.detInfoList is None: self.parent.evt = self.run.event(self.times[-1]) myAreaDetectors = [] self.parent.detnames = psana.DetNames() for k in self.parent.detnames: try: if Detector.PyDetector.dettype(str(k[0]), self.env) == Detector.AreaDetector.AreaDetector: myAreaDetectors.append(k) except ValueError: continue self.parent.detInfoList = list(set(myAreaDetectors)) print "#######################################" print "# Available area detectors: " for k in self.parent.detInfoList: print "#", k print "#######################################" # Launch e-log crawler if self.logger and self.crawlerRunning == False: if self.parent.args.v >= 1: print "Launching crawler" self.launchCrawler() self.crawlerRunning = True if self.hasExpRunDetInfo(): self.parent.det = psana.Detector(str(self.parent.detInfo), self.env) self.parent.det.do_reshape_2d_to_3d(flag=True) self.parent.detAlias = self.getDetectorAlias(str(self.parent.detInfo)) self.parent.epics = self.ds.env().epicsStore() self.setClen() # detector distance self.updateDetectorDistance('lcls') # pixel size self.updatePixelSize('lcls') # photon energy self.updatePhotonEnergy('lcls') # Some detectors do not read out at 120 Hz. So need to loop over events to guarantee a valid detector image. if self.parent.evt is None: self.parent.evt = self.run.event(self.times[0]) self.detGuaranteed = self.parent.det.calib(self.parent.evt) if self.detGuaranteed is None: # image isn't present for this event print "No image in this event. Searching for an event..." for i in np.arange(len(self.times)): evt = self.run.event(self.times[i]) self.detGuaranteed = self.parent.det.calib(evt) if self.detGuaranteed is not None: print "Found an event with image: ", i break # Setup pixel indices if self.detGuaranteed is not None: self.parent.pixelInd = np.reshape(np.arange(self.detGuaranteed.size) + 1, self.detGuaranteed.shape) self.parent.pixelIndAssem = self.parent.img.getAssembledImage('lcls', self.parent.pixelInd) self.parent.pixelIndAssem -= 1 # First pixel is 0 # Get detector shape self.detGuaranteedData = self.parent.det.image(self.parent.evt, self.detGuaranteed) # Write a temporary geom file self.parent.geom.deployCrystfelGeometry('lcls') self.parent.geom.writeCrystfelGeom('lcls') self.parent.img.setupRadialBackground() self.parent.img.updatePolarizationFactor() if self.parent.args.v >= 1: print "Done setupExperiment" def updateLogscale(self, data): self.logscaleOn = data if self.hasExpRunDetInfo(): self.parent.firstUpdate = True # clicking logscale resets plot colorscale self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateLogscale: ", self.logscaleOn def updateAduPerPhoton(self, data): self.aduPerPhoton = data if self.hasExpRunDetInfo() is True and self.image_property == self.disp_photons: #self.parent.firstUpdate = True # clicking logscale resets plot colorscale self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateAduPerPhoton: ", self.aduPerPhoton def updateMedianFilter(self, data): self.medianFilterRank = data if self.hasExpRunDetInfo() is True and self.image_property == self.disp_medianCorrection: # self.parent.firstUpdate = True # clicking logscale resets plot colorscale self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateMedianFilter: ", self.medianFilterRank def updateImageProperty(self, data): self.image_property = data self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateImageProperty: ", self.image_property def updateFriedel(self, data): self.applyFriedel = data self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateFriedel: ", self.applyFriedel def updateCommonModeParam(self, data, ind): self.commonModeParams[ind] = data self.updateCommonMode(self.applyCommonMode) if self.parent.args.v >= 1: print "Done updateCommonModeParam: ", self.commonModeParams def updateCommonMode(self, data): self.applyCommonMode = data if self.applyCommonMode: self.commonMode = self.checkCommonMode(self.commonModeParams) if self.hasExpRunDetInfo(): if self.parent.args.v >= 1: print "%%% Redraw image with new common mode: ", self.commonMode self.setupExperiment() self.parent.img.updateImage() if self.parent.args.v >= 1: print "Done updateCommonMode: ", self.commonMode def checkCommonMode(self, _commonMode): # TODO: cspad2x2 can only use algorithms 1 and 5 _alg = int(_commonMode[0]) if _alg >= 1 and _alg <= 4: _param1 = int(_commonMode[1]) _param2 = int(_commonMode[2]) _param3 = int(_commonMode[3]) return (_alg,_param1,_param2,_param3) elif _alg == 5: _param1 = int(_commonMode[1]) return (_alg,_param1) else: print "Undefined common mode algorithm" return None def updateEventID(self, sec, nanosec, fid): if self.parent.args.v >= 1: print "eventID: ", sec, nanosec, fid self.p.param(self.exp_grp, self.exp_evt_str, self.exp_second_str).setValue(self.eventSeconds) self.p.param(self.exp_grp, self.exp_evt_str, self.exp_nanosecond_str).setValue(self.eventNanoseconds) self.p.param(self.exp_grp, self.exp_evt_str, self.exp_fiducial_str).setValue(self.eventFiducial)