Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
    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_()
Exemple #4
0
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_()
Exemple #5
0
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()
Exemple #6
0
    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)
Exemple #7
0
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_()
Exemple #8
0
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()
Exemple #9
0
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
Exemple #10
0
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)

Exemple #12
0
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
Exemple #13
0
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())
Exemple #14
0
    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
Exemple #17
0
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>&alpha;='+str(round(float(unitCell[3]),2))+\
                    #           '&deg; <br>&beta;='+str(round(float(unitCell[4]),2))+'&deg; <br>&gamma;='+\
                    #           str(round(float(unitCell[5]),2))+'&deg; <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"
Exemple #18
0
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
Exemple #19
0
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))
Exemple #20
0
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()
Exemple #22
0
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()
Exemple #23
0
    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()
Exemple #24
0
    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)        
Exemple #25
0
    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();
Exemple #27
0
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
Exemple #29
0
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)
Exemple #30
0
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)
Exemple #31
0
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)
Exemple #32
0
        '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',
Exemple #33
0
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>&alpha;='+str(round(float(unitCell[3]),2))+\
                                '&deg; <br>&beta;='+str(round(float(unitCell[4]),2))+'&deg; <br>&gamma;='+\
                                str(round(float(unitCell[5]),2))+'&deg; <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"
Exemple #35
0
    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
Exemple #38
0
    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)
Exemple #39
0
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))
Exemple #40
0
    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()
Exemple #44
0
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)