Example #1
0
    def _draw_text_inputs(self, layout):
        """
        Generates a GUI that can accept parameter values.
        """
        
        params = [
                  {'name': 'damage :: Saturation Threshold', 'type': 'int', 
                       'value': 10000, 'suffix': 'ADU'},
                  {'name': 'damage :: Area Threshold', 'type': 'int', 
                       'value': 20, 'suffix': '%', 'limits': (0, 100)},
                  
                  {'name': 'xtal :: Saturation Threshold', 'type': 'int',
                      'value': 5000, 'suffix': 'ADU'},
                  {'name': 'xtal :: Area Threshold', 'type': 'int',
                      'value': 1, 'suffix': '%', 'limits': (0, 100)},
                  
                  {'name': 'diffuse :: Saturation Threshold', 'type': 'int',
                       'value': 1000, 'suffix': 'ADU'},
                  {'name': 'diffuse :: Area Threshold', 'type': 'int',
                       'value': 20, 'suffix': '%', 'limits': (0, 100)}
                 ]

        self._params = Parameter.create(name='params', type='group', 
                                        children=params)
        self._params.sigTreeStateChanged.connect(self._enable_apply)

        t = ParameterTree()
        t.setParameters(self._params, showTop=False)
        
        layout.addWidget(t, 0, 1)
        
        return
Example #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)
Example #3
0
class LayerControlTree(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)


        self.basicParam = {'name': 'Layer','expanded':False, 'type': 'group','autoIncrementName':True, 'children': [
            {'name': 'LayerType', 'type': 'list', 'values': {"RGB": 0, "LAB": 1, "ChannelWise": 2}, 'value': 0},
            {'name': 'Channel', 'type': 'int', 'value': 0,'limits':[0,2]},
            {'name': 'Opacity', 'type': 'float', 'value': 0.0, 'step': 0.1,'limits':[0,1]},
            {'name': 'Show', 'type': 'bool', 'value': True, 'tip': "Show / Hide this layer"},
            {'name': 'HideOthers', 'type': 'action','tip':"Hide all other layers"},
            {'name': 'Gradient', 'type': 'colormap'},
            #{'name': 'Subgroup', 'type': 'group', 'children': [
            #    {'name': 'Sub-param 1', 'type': 'int', 'value': 10},
            #    {'name': 'Sub-param 2', 'type': 'float', 'value': 1.2e6},
            #]},
            #{'name': 'Text Parameter', 'type': 'text', 'value': 'Some text...'},
            #{'name': 'Action Parameter', 'type': 'action'},
        ]}



        params = []
            

        self.paramGroup = Parameter.create(name='params', type='group', children=params)
        self.paramGroup.sigTreeStateChanged.connect(self.change)

        self.parameterTree = ParameterTree()
        self.parameterTree.setParameters(self.paramGroup, showTop=False)

        # add view box to graph view layout
        self.hbox = QtGui.QHBoxLayout()
        self.setLayout(self.hbox)
        self.hbox.addWidget(self.parameterTree)

    def addLayerControl(self,layer):
        layerParam = setupLayerParam(layer.layerName(),layer.baseControlTemplate(),
                                     layer.controlTemplate())
        layerParam = self.paramGroup.addChild(layerParam)
        # pass parameter to layer itself
        layer.setLayerParameter(layerParam)

    def removeLayerControl(self,layer):
        paramToRemove = layer.layerParameter
        self.paramGroup.removeChild(paramToRemove)



    ## If anything changes in the tree, print a message
    def change(self,param, changes):
        #print("tree changes:")
        for param, change, data in changes:
            path = self.paramGroup.childPath(param)
            if path is not None:
                childName = '.'.join(path)
            else:
                childName = param.name()
Example #4
0
class FringeRemoveNode(Node):
	"""Node for removing fringes"""

	nodeName = 'FringeRemove'
	nodePaths = [('Analysis',)]

	def __init__(self, name):
		terminals = {
			'sig':{'io':'in'},
			'ref':{'io':'in'},
			'bkg':{'io':'in'},
			'sigMask': {'io':'in'},
			'ref1':{'io':'out', 'bypass': '******'}
		}
		super().__init__(name, terminals=terminals)

		paras_property = [
			{'name': 'rank', 'type': 'int', 'readonly': True},
			{'name': 'rankLimit', 'type': 'int', 'value': 100},
			{'name': 'trunc', 'type': 'float'},
			{'name': 'updateLib', 'type': 'bool'},
			{'name': 'reset', 'type': 'action'}
		]

		self.paras = Parameter.create(name='params', type='group', children=paras_property)
		self.paratree = ParameterTree()
		self.paratree.setParameters(self.paras, showTop=False)
		self.remover = FringeRemove()

		self.paras.param('reset').sigActivated.connect(self.remover.reset)
	
	def onReset(self):
		self.remover.reset()
		self.paras['rank'] = 0

	def ctrlWidget(self):
		return self.paratree

	def process(self, sig, ref, bkg, sigMask, display=True):
		self.remover.setTrunc(self.paras['trunc'])
		ref = ref - bkg
		if self.paras['updateLib'] and self.paras['rank'] <= self.paras['rankLimit']:
			self.remover.updateLibrary(ref)
			self.paras['rank'] = self.remover.rank
		sig = sig - bkg
		coef, ref = self.remover.reconstruct(np.ma.array(sig, mask=sigMask))
		ref = ref.reshape(512, 512) + bkg
		return {'ref1': ref}

	def saveState(self):
		state = super().saveState()
		state['paras'] = self.paras.saveState()
		return state

	def restoreState(self, state):
		super().restoreState(state)
		self.paras.restoreState(state['paras'])
Example #5
0
def setupTree():
  params = [
    {'name':'Update Time (s)', 'type':'float', 'value':1},
    {'name':'Sample Name', 'type':'int', 'value':1},
    {'name':'Counter', 'type':'int', 'value':0}
  ]
  p = Parameter.create(name = 'params', type = 'group', children = params)
  t = ParameterTree()
  t.setParameters(p, showTop = False)
  return t,p
Example #6
0
def setupTree():
  params = [
    {'name':'Update Time (s)', 'type':'float', 'value':1},
    {'name':'std', 'type':'float', 'value':0},
    {'name':'Save Figure', 'type':'action', 'visible':True}
  ]
  p = Parameter.create(name = 'params', type = 'group', children = params)
  t = ParameterTree()
  t.setParameters(p, showTop = False)
  return t,p
class InputCalibrationChannel(SheetForm, SheetBase):
    def __init__(self, config, channel, parent=None):
        SheetBase.__init__(self, parent)
        SheetForm.__init__(self)
        self.config = config
        self.channel = channel
        self.settings = self.config.get("InputCalibration.{0}".format(channel), ChannelSettings())
        self.myCalibration = None
        self.treeWidget = None
    
    def setupUi(self, callback, MainWindow):
        SheetForm.setupUi(self, MainWindow) 
        self.calibrationsCombo.addItems( list(AnalogInputCalibration.AnalogInputCalibrationMap.keys()) )   
        self.calibrationsCombo.currentIndexChanged["QString"].connect( self.onCalibrationChanged )
        self.callback = callback
        if self.settings.calibration:
            self.onCalibrationChanged(self.settings.calibration)
            self.calibrationsCombo.setCurrentIndex(self.calibrationsCombo.findText(self.settings.calibration))
      
    def onCalibrationChanged(self, calibration):  
        calibration = str(calibration)
        if self.myCalibration:
            self.settings.parameters[self.settings.calibration] = self.myCalibration.parameters
        self.myCalibration = AnalogInputCalibration.AnalogInputCalibrationMap[calibration]() 
        if calibration in self.settings.parameters:
            self.myCalibration.parameters = self.settings.parameters[calibration]
        if not self.treeWidget:
            try:
                self.param = Parameter.create(name='params', type='group', children=self.myCalibration.paramDef())
                self.treeWidget = ParameterTree()
                self.treeWidget.setParameters(self.param, showTop=False)
                self.verticalLayout.insertWidget(2, self.treeWidget)
                self.param.sigTreeStateChanged.connect(self.myCalibration.update, QtCore.Qt.UniqueConnection)
            except (TypeError, AttributeError):
                pass
        else:
            self.param = Parameter.create(name='params', type='group', children=self.myCalibration.paramDef())
            self.treeWidget.setParameters(self.param, showTop=False)
            try:
                self.param.sigTreeStateChanged.connect(self.myCalibration.update, QtCore.Qt.UniqueConnection )
            except TypeError:
                pass  # we want the connection to be unique
        self.settings.calibration = calibration
        self.callback( self.channel, self.myCalibration )
            
    def saveConfig(self):
        if self.myCalibration:
            self.settings.parameters[self.settings.calibration] = self.myCalibration.parameters
        self.config["InputCalibration.{0}".format(self.channel)] = self.settings
Example #8
0
class SettingsEditorDialog(QtGui.QDialog):

    def __init__(self,ndViewer, parent):
        super(SettingsEditorDialog, self).__init__(parent)
        
        self.resize(800,600)
        self.ndViewer = ndViewer
        self.layout = QtGui.QVBoxLayout()
        self.setLayout(self.layout) 

  
        self.paramTree = ParameterTree()
        self.paramTree.setParameters(self.ndViewer.options.p, showTop=False)
        self.layout.addWidget(self.paramTree)
    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.hide()
            event.accept()
        else:
            super(QtGui.QDialog, self).keyPressEvent(event)
class InstrumentLoggingSelection( SelectionUi ):
    def __init__(self, config, classdict, instancename="ExternalParameterSelection.ParametersSequence", plotNames=None, parent=None, instrumentLoggingHandler=None ):
        super(InstrumentLoggingSelection, self).__init__(config, dict(), classdict, instancename, parent)
        self.instrumentLoggingHandler = instrumentLoggingHandler
        self.current = None
        
    def setupUi(self, MainWindow):
        super(InstrumentLoggingSelection, self).setupUi(MainWindow)
        self.loggingHandlerTreeWidget = ParameterTree(self.splitter)
        self.loggingHandlerTreeWidget.setObjectName("loggingHandlerTreeWidget")
        self.loggingHandlerTreeWidget.headerItem().setText(0, "1")
        self.loggingHandlerTreeWidget.header().setVisible(False)

    def onActiveInstrumentChanged(self, modelIndex, modelIndex2 ):
        self.current = self.parameters.at(modelIndex.row()).name
        super(InstrumentLoggingSelection, self).onActiveInstrumentChanged( modelIndex, modelIndex2 )          
        self.loggingHandlerTreeWidget.setParameters( self.instrumentLoggingHandler.parameter(self.current) )
        
    def refreshParamTree(self):
        if self.current is not None:
            self.loggingHandlerTreeWidget.setParameters( self.instrumentLoggingHandler.parameter(self.current) )
Example #10
0
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.plotly_pyqt5 = Plotly_PyQt5()

        '''手动调整窗口部件的大小,使之看着更美观'''
        self.widget_parameter_tree.setMaximumWidth(300)
        self.widget_parameter_tree.setMinimumWidth(200)
        self.QWebEngineView_ProductVsHs300.setMinimumHeight(500)
        self.tabWidget.setMinimumHeight(400)


        '''显示parametertree,这里通过布局管理器来把ParameterTree间接地嵌套进Widget窗口里面'''
        from mypyqtgraph import  p
        from pyqtgraph.parametertree import  ParameterTree

        t = ParameterTree()
        t.setParameters(p, showTop=False)
        t.setHeaderLabels(["参数", "数值"])
        # t.setWindowTitle('pyqtgraph example: Parameter Tree')
        layout = QtGui.QGridLayout()
        self.widget_parameter_tree.setLayout(layout)
        layout.addWidget(
            QtGui.QLabel("千石资本-和聚光明1号资产管理计划基本信息"), 0, 0, 1, 1)
        layout.addWidget(t)

        '''显示绘图函数'''
        self.QWebEngineView_ProductVsHs300.load(
            QUrl.fromLocalFile(self.plotly_pyqt5.get_plotly_path_product_vs_hs300()))
        self.QWebEngineView_LagestBack.load(QUrl.fromLocalFile(self.plotly_pyqt5.get_plotly_path_lagest_back()))
        self.QWebEngineView_PeriodReturn.load(QUrl.fromLocalFile(self.plotly_pyqt5.get_plotly_path_period_return()))
        self.QWebEngineview_MonthReturn.load(QUrl.fromLocalFile(self.plotly_pyqt5.get_plotly_path_month_return()))
Example #11
0
def setupTree(startup):
  params = [
    {'name':'ChA', 'type':'int', 'value': startup['ChA']},
    {'name':'BiasV_ChA', 'type':'float', 'value': startup['BiasV_ChA']},
    {'name':'ChA Singles (cps)', 'type':'float', 'value': startup['ChA Singles (cps)']},
    {'name':'ChB', 'type':'int', 'value':startup['ChB']},
    {'name':'BiasV_ChB', 'type':'float', 'value':startup['BiasV_ChB']},
    {'name':'ChB Singles (cps)', 'type':'float', 'value': startup['ChB Singles (cps)']},
    {'name':'Min (s)', 'type':'float', 'value':startup['Min (s)']},
    {'name':'Max (s)', 'type':'float', 'value':startup['Max (s)']},
    {'name':'binSize', 'type':'int', 'value':startup['binSize']},
    {'name':'Update Time (s)', 'type':'float', 'value' :startup['Update Time (s)']},
    {'name':'Counter', 'type':'int', 'value':startup['Counter']},
    {'name':'algorithm', 'type':'str', 'value':startup['algorithm']},
    {'name':'Pause Histogram', 'type':'bool', 'value':startup['Pause Histogram']},
    {'name':'Reset Histogram', 'type':'action', 'visible':startup['Reset Histogram']},
    {'name':'Save Path', 'type':'str', 'value':startup['Save Path']},
    {'name':'Save Figure', 'type':'action', 'visible':startup['Save Figure']},
    {'name':'Save Data', 'type':'action', 'visible':startup['Save Data']}
  ]
  p = Parameter.create(name = 'params', type = 'group', children = params)
  t = ParameterTree()
  t.setParameters(p, showTop = False)
  return t,p
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"
Example #13
0
from PySide import QtGui, QtCore
import os
from pyqtgraph.parametertree import ParameterTree
import widgets
import numpy as np
from pipeline.spacegroups import spacegroupwidget
from pipeline import loader
from xicam import config
import fabio
from pipeline import calibration

from xicam.widgets.calibrationpanel import calibrationpanel

# Globals so Timeline can share the same rightmodes
configtree = ParameterTree()
configtree.setParameters(config.activeExperiment, showTop=False)


def tiltStyleMenuRequested(pos):
    config.activeExperiment.tiltStyleMenu.exec_(configtree.mapToGlobal(pos))


configtree.customContextMenuRequested.connect(tiltStyleMenuRequested)
configtree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

rightmodes = [(configtree,
               QtGui.QFileIconProvider().icon(QtGui.QFileIconProvider.File))]


class ViewerPlugin(base.plugin):
    name = 'Viewer'
Example #14
0
#}}}

qt_mav = QtMav(outdevice, indevice)

# create gui
app = QtGui.QApplication(sys.argv)

f = open("tuner_ui.py.tmp", "w")
uic.compileUi("tuner.ui", f)
tuner = uic.loadUi("tuner.ui")

params = []
parameter = Parameter(name='params', type='group', children=params)
parameter_tree = ParameterTree(parent=tuner.tabTime)
parameter_tree.setParameters(parameter, showTop=False)
parameter_tree.resize(300, 500)


def get_group_index(params, gname):  #{{{
    """
    recursive group refreshing/adding
    params -- parameters structure
    gname -- string representing name
    return:
        index in params structure
        -1 if not found
    """
    i = 0
    for g in params:
        if g['name'] == gname:
Example #15
0
class MaskMaker(object):
    def __init__(self, parent = None):
        self.parent = parent

        self.d12 = Dock("Mask Panel", size=(1, 1))
        ## Dock 12: Mask Panel
        self.w17 = ParameterTree()
        self.d12.addWidget(self.w17)
        self.w18 = pg.LayoutWidget()
        self.maskRectBtn = QtGui.QPushButton('Stamp rectangular mask')
        self.w18.addWidget(self.maskRectBtn, row=0, col=0)#, colspan=2)
        self.maskCircleBtn = QtGui.QPushButton('Stamp circular mask')
        self.w18.addWidget(self.maskCircleBtn, row=0, col=1)#, colspan=2)
        self.maskThreshBtn = QtGui.QPushButton('Mask outside histogram')
        self.w18.addWidget(self.maskThreshBtn, row=1, col=1)#, colspan=2)
        self.maskPolyBtn = QtGui.QPushButton('Stamp polygon mask')
        self.w18.addWidget(self.maskPolyBtn, row=1, col=0)#, colspan=2)
        self.deployMaskBtn = QtGui.QPushButton()
        self.deployMaskBtn.setStyleSheet('QPushButton {background-color: #A3C1DA; color: red;}')
        self.deployMaskBtn.setText('Save static mask')
        self.w18.addWidget(self.deployMaskBtn, row=2, col=0)
        self.loadMaskBtn = QtGui.QPushButton()
        self.loadMaskBtn.setStyleSheet('QPushButton {background-color: #A3C1DA; color: red;}')
        self.loadMaskBtn.setText('Load mask')
        self.w18.addWidget(self.loadMaskBtn, row=2, col=1)
        self.generatePowderBtn = QtGui.QPushButton('Generate Average Image')
        self.w18.addWidget(self.generatePowderBtn, row=3, col=0, colspan=2)
        # Connect listeners to functions
        self.d12.addWidget(self.w18)

        self.mask_grp = 'Mask'
        self.mask_mode_str = 'Masking mode'
        self.do_nothing_str = 'Off'
        self.do_toggle_str = 'Toggle'
        self.do_mask_str = 'Mask'
        self.do_unmask_str = 'Unmask'
        self.streak_mask_str = 'Use jet streak mask'
        self.streak_width_str = 'maximum streak length'
        self.streak_sigma_str = 'sigma'
        self.psana_mask_str = 'Use psana mask'
        self.user_mask_str = 'Use user-defined mask'
        self.mask_calib_str = 'calib pixels'
        self.mask_status_str = 'status pixels'
        self.mask_edges_str = 'edge pixels'
        self.mask_central_str = 'central pixels'
        self.mask_unbond_str = 'unbonded pixels'
        self.mask_unbondnrs_str = 'unbonded pixel neighbors'
        self.powder_grp = 'Generate Average Image'
        self.powder_outDir_str = 'Output directory'
        self.powder_runs_str = 'Run(s)'
        self.powder_queue_str = 'Queue'
        self.powder_cpu_str = 'CPUs'
        self.powder_noe_str = 'Number of events to process'
        self.powder_threshold_str = 'Threshold'
        self.masking_mode_message = "<span style='color: " + color.maskInfo + "; font-size: 24pt;'>Masking mode <br> </span>"

        ######################
        # Mask
        ######################
        self.maskingMode = 0
        self.userMaskOn = False
        self.streakMaskOn = False
        self.streak_sigma = 1
        self.streak_width = 250
        self.psanaMaskOn = False
        self.mask_calibOn = True
        self.mask_statusOn = True
        self.mask_edgesOn = True
        self.mask_centralOn = True
        self.mask_unbondOn = True
        self.mask_unbondnrsOn = True
        self.display_data = None
        self.mask_rect = None
        self.mask_circle = None
        self.mask_poly = None
        self.powder_outDir = self.parent.psocakeDir
        self.powder_runs = ''
        self.powder_queue = self.parent.pk.hitParam_psanaq_str
        self.powder_cpus = 24
        self.powder_noe = -1
        self.powder_threshold = -1

        ###########################
        # Mask variables
        ###########################
        self.psanaMask = None # psana mask
        self.psanaMaskAssem = None
        self.userMask = None # user-defined mask
        self.userMaskAssem = None
        self.streakMask = None # jet streak mask
        self.StreakMask = None # streak mask class
        self.streakMaskAssem = None
        self.combinedMask = None # combined mask

        self.params = [
            {'name': self.mask_grp, 'type': 'group', 'children': [
                {'name': self.user_mask_str, 'type': 'bool', 'value': self.userMaskOn, 'tip': "Mask areas defined by user", 'children':[
                    {'name': self.mask_mode_str, 'type': 'list', 'values': {self.do_toggle_str: 3,
                                                                            self.do_unmask_str: 2,
                                                                            self.do_mask_str: 1,
                                                                            self.do_nothing_str: 0},
                                                                       'value': self.maskingMode,
                                                                       'tip': "Choose masking mode"},
                ]},
                {'name': self.streak_mask_str, 'type': 'bool', 'value': self.streakMaskOn, 'tip': "Mask jet streaks shot-to-shot", 'children':[
                    {'name': self.streak_width_str, 'type': 'float', 'value': self.streak_width, 'tip': "set maximum length of streak"},
                    {'name': self.streak_sigma_str, 'type': 'float', 'value': self.streak_sigma, 'tip': "set number of sigma to threshold"},
                ]},
                {'name': self.psana_mask_str, 'type': 'bool', 'value': self.psanaMaskOn, 'tip': "Mask edges and unbonded pixels etc", 'children': [
                    {'name': self.mask_calib_str, 'type': 'bool', 'value': self.mask_calibOn, 'tip': "use custom mask deployed in calibdir"},
                    {'name': self.mask_status_str, 'type': 'bool', 'value': self.mask_statusOn, 'tip': "mask bad pixel status"},
                    {'name': self.mask_edges_str, 'type': 'bool', 'value': self.mask_edgesOn, 'tip': "mask edge pixels"},
                    {'name': self.mask_central_str, 'type': 'bool', 'value': self.mask_centralOn, 'tip': "mask central edge pixels inside asic2x1"},
                    {'name': self.mask_unbond_str, 'type': 'bool', 'value': self.mask_unbondOn, 'tip': "mask unbonded pixels (cspad only)"},
                    {'name': self.mask_unbondnrs_str, 'type': 'bool', 'value': self.mask_unbondnrsOn, 'tip': "mask unbonded pixel neighbors (cspad only)"},
                ]},
            ]},
            {'name': self.powder_grp, 'type': 'group', 'children': [
                {'name': self.powder_outDir_str, 'type': 'str', 'value': self.powder_outDir},
                {'name': self.powder_runs_str, 'type': 'str', 'value': self.powder_runs,
                 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"},
                {'name': self.powder_queue_str, 'type': 'list', 'values': {self.parent.pk.hitParam_psfehhiprioq_str: 'psfehhiprioq',
                                                                           self.parent.pk.hitParam_psnehhiprioq_str: 'psnehhiprioq',
                                                                           self.parent.pk.hitParam_psfehprioq_str: 'psfehprioq',
                                                                           self.parent.pk.hitParam_psnehprioq_str: 'psnehprioq',
                                                                           self.parent.pk.hitParam_psfehq_str: 'psfehq',
                                                                           self.parent.pk.hitParam_psnehq_str: 'psnehq',
                                                                           self.parent.pk.hitParam_psanaq_str: 'psanaq',
                                                                           self.parent.pk.hitParam_psdebugq_str: 'psdebugq'},
                 'value': self.powder_queue, 'tip': "Choose queue"},
                {'name': self.powder_cpu_str, 'type': 'int', 'value': self.powder_cpus, 'tip': "number of cpus to use per run"},
                {'name': self.powder_threshold_str, 'type': 'float', 'value': self.powder_threshold, 'tip': "ignore pixels below ADU threshold, default=-1 means no threshold"},
                {'name': self.powder_noe_str, 'type': 'int', 'value': self.powder_noe, 'tip': "number of events to process, default=-1 means process all events"},
            ]},
        ]

        self.p6 = Parameter.create(name='paramsMask', type='group', \
                                   children=self.params, expanded=True)
        self.w17.setParameters(self.p6, showTop=False)
        self.p6.sigTreeStateChanged.connect(self.change)

        self.maskRectBtn.clicked.connect(self.makeMaskRect)
        self.maskCircleBtn.clicked.connect(self.makeMaskCircle)
        self.maskThreshBtn.clicked.connect(self.makeMaskThresh)
        self.maskPolyBtn.clicked.connect(self.makeMaskPoly)
        self.deployMaskBtn.clicked.connect(self.deployMask)
        self.loadMaskBtn.clicked.connect(self.loadMask)

        self.generatePowderBtn.clicked.connect(self.makePowder)

    def makePowder(self):
        self.parent.thread.append(LaunchPowderProducer.PowderProducer(self.parent))  # send parent parameters with self
        self.parent.thread[self.parent.threadCounter].computePowder(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo)
        self.parent.threadCounter += 1

    # 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.mask_grp:
            if path[1] == self.user_mask_str and len(path) == 2:
                self.updateUserMask(data)
                self.parent.pk.algInitDone = False
            elif path[1] == self.streak_mask_str and len(path) == 2:
                self.updateStreakMask(data)
                self.parent.pk.algInitDone = False
            elif path[1] == self.psana_mask_str and len(path) == 2:
                self.updatePsanaMask(data)
                self.parent.pk.algInitDone = False
            if len(path) == 3:
                if path[2] == self.mask_mode_str:
                    self.parent.pk.algInitDone = False
                    self.updateMaskingMode(data)
                if path[2] == self.streak_width_str:
                    self.parent.pk.algInitDone = False
                    self.updateStreakWidth(data)
                if path[2] == self.streak_sigma_str:
                    self.parent.pk.algInitDone = False
                    self.updateStreakSigma(data)
                if path[2] == self.mask_calib_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
                elif path[2] == self.mask_status_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
                elif path[2] == self.mask_edges_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
                elif path[2] == self.mask_central_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
                elif path[2] == self.mask_unbond_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
                elif path[2] == self.mask_unbondnrs_str:
                    self.parent.pk.algInitDone = False
                    self.updatePsanaMaskFlag(path[2], data)
        elif path[0] == self.powder_grp:
            if path[1] == self.powder_outDir_str:
                self.powder_outDir = data
            elif path[1] == self.powder_runs_str:
                self.powder_runs = data
            elif path[1] == self.powder_queue_str:
                self.powder_queue = data
            elif path[1] == self.powder_cpu_str:
                self.powder_cpus = data
            elif path[1] == self.powder_noe_str:
                self.powder_noe = data
            elif path[1] == self.powder_threshold_str:
                self.powder_threshold = data

    ##################################
    ############ Masking #############
    ##################################

    def resetMasks(self):
        self.userMask = None
        self.psanaMask = None
        self.streakMask = None
        self.StreakMask = None
        self.userMaskAssem = None
        self.psanaMaskAssem = None
        self.streakMaskAssem = None
        self.combinedMask = None
        self.gapAssemInd = None
        self.gapAssem = None
        self.userMaskOn = False
        self.psanaMaskOn = False
        self.streakMaskOn = False
        self.maskingMode = 0
        self.p6.param(self.mask_grp, self.user_mask_str, self.mask_mode_str).setValue(0)
        self.p6.param(self.mask_grp, self.user_mask_str).setValue(0)
        self.p6.param(self.mask_grp, self.psana_mask_str).setValue(0)
        self.p6.param(self.mask_grp, self.streak_mask_str).setValue(0)

    def updateUserMask(self, data):
        self.userMaskOn = data
        self.parent.pk.algInitDone = False
        self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "Done updateUserMask: ", self.userMaskOn

    def updateStreakMask(self, data):
        self.streakMaskOn = data
        self.parent.pk.algInitDone = False
        self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "Done updateStreakMask: ", self.streakMaskOn

    def updateStreakWidth(self, data):
        self.streak_width = data
        self.streakMask = None
        self.initMask()
        self.parent.pk.algInitDone = False
        self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "Done updateStreakWidth: ", self.streak_width

    def updateStreakSigma(self, data):
        self.streak_sigma = data
        self.streakMask = None
        self.initMask()
        self.parent.pk.algInitDone = False
        self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "Done updateStreakSigma: ", self.streak_sigma

    def updatePsanaMask(self, data):
        self.psanaMaskOn = data
        self.parent.pk.algInitDone = False
        self.updatePsanaMaskOn()
        if self.parent.args.v >= 1: print "Done updatePsanaMask: ", self.psanaMaskOn

    def updateMaskingMode(self, data):
        self.maskingMode = data
        if self.maskingMode == 0:
            # display text
            self.parent.label.setText("")
            # do not display user mask
            self.displayMask()
            # remove ROIs
            self.parent.img.w1.getView().removeItem(self.mask_rect)
            self.parent.img.w1.getView().removeItem(self.mask_circle)
            self.parent.img.w1.getView().removeItem(self.mask_poly)
        else:
            # display text
            self.parent.label.setText(self.masking_mode_message)
            # display user mask
            self.displayMask()
            # init masks
            if self.mask_rect is None:
                # Rect mask
                self.mask_rect = pg.ROI(pos=[-300, 0], size=[200, 200], snapSize=1.0, scaleSnap=True, translateSnap=True,
                                        pen={'color': 'c', 'width': 4})
                self.mask_rect.addScaleHandle([1, 0.5], [0.5, 0.5])
                self.mask_rect.addScaleHandle([0.5, 0], [0.5, 0.5])
                self.mask_rect.addScaleHandle([0.5, 1], [0.5, 0.5])
                self.mask_rect.addScaleHandle([0, 0.5], [0.5, 0.5])
                self.mask_rect.addScaleHandle([0, 0], [1, 1])  # bottom,left handles scaling both vertically and horizontally
                self.mask_rect.addScaleHandle([1, 1], [0, 0])  # top,right handles scaling both vertically and horizontally
                self.mask_rect.addScaleHandle([1, 0], [0, 1])  # bottom,right handles scaling both vertically and horizontally
                self.mask_rect.addScaleHandle([0, 1], [1, 0])
                #self.mask_rect.addRotateHandle([0.5, 0.5], [1, 1])
                # Circular mask
                self.mask_circle = pg.CircleROI([-300, 600], size=[200, 200], snapSize=1.0, scaleSnap=True,
                                                translateSnap=True, pen={'color': 'c', 'width': 4})
                self.mask_circle.addScaleHandle([0.1415, 0.707 * 1.2], [0.5, 0.5])
                self.mask_circle.addScaleHandle([0.707 * 1.2, 0.1415], [0.5, 0.5])
                self.mask_circle.addScaleHandle([0.1415, 0.1415], [0.5, 0.5])
                self.mask_circle.addScaleHandle([0, 0.5], [0.5, 0.5])
                self.mask_circle.addScaleHandle([0.5, 0.0], [0.5, 0.5])
                self.mask_circle.addScaleHandle([0.5, 1.0], [0.5, 0.5])
                self.mask_circle.addScaleHandle([1.0, 0.5], [0.5, 0.5])
                # Polygon mask
                self.mask_poly = pg.PolyLineROI([[-300, 300], [-300,500], [-100,500], [-100,400], [-225,400], [-225,300]], closed=True, snapSize=1.0, scaleSnap=True, translateSnap=True, pen={'color': 'c', 'width': 4})

            # add ROIs
            self.parent.img.w1.getView().addItem(self.mask_rect)
            self.parent.img.w1.getView().addItem(self.mask_circle)
            self.parent.img.w1.getView().addItem(self.mask_poly)
        if self.parent.args.v >= 1: print "Done updateMaskingMode: ", self.maskingMode

    def updatePsanaMaskFlag(self, flag, data):
        if flag == self.mask_calib_str:
            self.mask_calibOn = data
        elif flag == self.mask_status_str:
            self.mask_statusOn = data
        elif flag == self.mask_central_str:
            self.mask_centralOn = data
        elif flag == self.mask_edges_str:
            self.mask_edgesOn = data
        elif flag == self.mask_unbond_str:
            self.mask_unbondOn = data
        elif flag == self.mask_unbondnrs_str:
            self.mask_unbondnrsOn = data
        self.updatePsanaMaskOn()

    def updatePsanaMaskOn(self):
        if self.parent.det is not None:
            self.initMask()
            self.psanaMask = self.parent.det.mask(self.parent.evt, calib=self.mask_calibOn, status=self.mask_statusOn,
                                           edges=self.mask_edgesOn, central=self.mask_centralOn,
                                           unbond=self.mask_unbondOn, unbondnbrs=self.mask_unbondnrsOn)
            if self.psanaMask is not None:
                self.psanaMaskAssem = self.parent.det.image(self.parent.evt, self.psanaMask)
            else:
                self.psanaMaskAssem = None
            self.parent.pk.updateClassification()

    def initMask(self):
        if self.parent.det is not None:
            if self.gapAssemInd is None:
                self.gapAssem = self.parent.det.image(self.parent.evt, np.ones_like(self.parent.exp.detGuaranteed,dtype='int'))
                self.gapAssemInd = np.where(self.gapAssem==0)
            if self.userMask is None and self.parent.data is not None:
                # initialize
                self.userMaskAssem = np.ones_like(self.parent.data,dtype='int')
                self.userMask = self.parent.det.ndarray_from_image(self.parent.evt,self.userMaskAssem, pix_scale_size_um=None, xy0_off_pix=None)
            if self.streakMask is None:
                self.StreakMask = myskbeam.StreakMask(self.parent.det, self.parent.evt, width=self.streak_width, sigma=self.streak_sigma)
            if self.parent.args.v >= 1: print "Done initMask"

    def displayMask(self):
        # convert to RGB
        if self.userMaskOn is False and self.streakMaskOn is False and self.psanaMaskOn is False:
            self.display_data = self.parent.data
        elif self.userMaskAssem is None and self.streakMaskAssem is None and self.psanaMaskAssem is None:
            self.display_data = self.parent.data
        elif self.parent.data is not None:
            self.display_data = np.zeros((self.parent.data.shape[0], self.parent.data.shape[1], 3), dtype = self.parent.data.dtype)
            self.display_data[:,:,0] = self.parent.data
            self.display_data[:,:,1] = self.parent.data
            self.display_data[:,:,2] = self.parent.data
            # update streak mask as red
            if self.streakMaskOn is True and self.streakMaskAssem is not None:
                self.streakMaskAssem[self.gapAssemInd] = 1
                _streakMaskInd = np.where(self.streakMaskAssem==0)
                self.display_data[_streakMaskInd[0], _streakMaskInd[1], 0] = self.parent.data[_streakMaskInd] + (np.max(self.parent.data) - self.parent.data[_streakMaskInd]) * (1-self.streakMaskAssem[_streakMaskInd])
                self.display_data[_streakMaskInd[0], _streakMaskInd[1], 1] = self.parent.data[_streakMaskInd] * self.streakMaskAssem[_streakMaskInd]
                self.display_data[_streakMaskInd[0], _streakMaskInd[1], 2] = self.parent.data[_streakMaskInd] * self.streakMaskAssem[_streakMaskInd]
            # update psana mask as green
            if self.psanaMaskOn is True and self.psanaMaskAssem is not None:
                self.psanaMaskAssem[self.gapAssemInd] = 1
                _psanaMaskInd = np.where(self.psanaMaskAssem==0)
                self.display_data[_psanaMaskInd[0], _psanaMaskInd[1], 0] = self.parent.data[_psanaMaskInd] * self.psanaMaskAssem[_psanaMaskInd]
                self.display_data[_psanaMaskInd[0], _psanaMaskInd[1], 1] = self.parent.data[_psanaMaskInd] + (np.max(self.parent.data) - self.parent.data[_psanaMaskInd]) * (1-self.psanaMaskAssem[_psanaMaskInd])
                self.display_data[_psanaMaskInd[0], _psanaMaskInd[1], 2] = self.parent.data[_psanaMaskInd] * self.psanaMaskAssem[_psanaMaskInd]
            # update user mask as blue
            if self.userMaskOn is True and self.userMaskAssem is not None:
                self.userMaskAssem[self.gapAssemInd] = 1
                _userMaskInd = np.where(self.userMaskAssem==0)
                self.display_data[_userMaskInd[0], _userMaskInd[1], 0] = self.parent.data[_userMaskInd] * self.userMaskAssem[_userMaskInd]
                self.display_data[_userMaskInd[0], _userMaskInd[1], 1] = self.parent.data[_userMaskInd] * self.userMaskAssem[_userMaskInd]
                self.display_data[_userMaskInd[0], _userMaskInd[1], 2] = self.parent.data[_userMaskInd] + (np.max(self.parent.data) - self.parent.data[_userMaskInd]) * (1-self.userMaskAssem[_userMaskInd])
        if self.display_data is not None:
            self.parent.img.w1.setImage(self.display_data, autoRange=False, autoLevels=False, autoHistogramRange=False)
        if self.parent.args.v >= 1: print "Done displayMask"

    # mask
    def makeMaskRect(self):
        self.initMask()
        if self.parent.data is not None and self.maskingMode > 0:
            selected, coord = self.mask_rect.getArrayRegion(self.parent.data, self.parent.img.w1.getImageItem(), returnMappedCoords=True)
            # Remove mask elements outside data
            coord_row = coord[0, (coord[0] >= 0) & (coord[0] < self.parent.data.shape[0]) & (coord[1] >= 0) & (
            coord[1] < self.parent.data.shape[1])].ravel()
            coord_col = coord[1, (coord[0] >= 0) & (coord[0] < self.parent.data.shape[0]) & (coord[1] >= 0) & (
            coord[1] < self.parent.data.shape[1])].ravel()
            _mask = np.ones_like(self.parent.data)
            _mask[coord_row.astype('int'), coord_col.astype('int')] = 0
            if self.maskingMode == 1:  # masking mode
                self.userMaskAssem *= _mask
            elif self.maskingMode == 2:  # unmasking mode
                self.userMaskAssem[coord_row.astype('int'), coord_col.astype('int')] = 1
            elif self.maskingMode == 3:  # toggle mode
                self.userMaskAssem[coord_row.astype('int'), coord_col.astype('int')] = (
                1 - self.userMaskAssem[coord_row.astype('int'), coord_col.astype('int')])

            # update userMask
            self.userMask = self.parent.det.ndarray_from_image(self.parent.evt, self.userMaskAssem, pix_scale_size_um=None,
                                                        xy0_off_pix=None)

            self.displayMask()
            self.parent.pk.algInitDone = False
            self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "done makeMaskRect!!!!!!"

    def makeMaskCircle(self):
        self.initMask()
        if self.parent.data is not None and self.maskingMode > 0:
            (radiusX, radiusY) = self.mask_circle.size()
            (cornerX, cornerY) = self.mask_circle.pos()
            i0, j0 = np.meshgrid(range(int(radiusY)),
                                 range(int(radiusX)), indexing='ij')
            r = np.sqrt(np.square((i0 - radiusY / 2).astype(np.float)) +
                        np.square((j0 - radiusX / 2).astype(np.float)))
            i0 = np.rint(i0[np.where(r < radiusY / 2.)] + cornerY).astype(np.int)
            j0 = np.rint(j0[np.where(r < radiusX / 2.)] + cornerX).astype(np.int)
            i01 = i0[(i0 >= 0) & (i0 < self.parent.data.shape[1]) & (j0 >= 0) & (j0 < self.parent.data.shape[0])]
            j01 = j0[(i0 >= 0) & (i0 < self.parent.data.shape[1]) & (j0 >= 0) & (j0 < self.parent.data.shape[0])]

            _mask = np.ones_like(self.parent.data)
            _mask[j01, i01] = 0
            if self.maskingMode == 1:  # masking mode
                self.userMaskAssem *= _mask
            elif self.maskingMode == 2:  # unmasking mode
                self.userMaskAssem[j01, i01] = 1
            elif self.maskingMode == 3:  # toggle mode
                self.userMaskAssem[j01, i01] = (1 - self.userMaskAssem[j01, i01])

            # update userMask
            self.userMask = self.parent.det.ndarray_from_image(self.parent.evt, self.userMaskAssem, pix_scale_size_um=None,
                                                        xy0_off_pix=None)

            self.displayMask()
            self.parent.pk.algInitDone = False
            self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "done makeMaskCircle!!!!!!"

    def makeMaskThresh(self):
        self.initMask()
        if self.parent.data is not None and self.maskingMode > 0:
            histLevels = self.parent.img.w1.getHistogramWidget().item.getLevels()
            _mask = np.ones_like(self.parent.data)
            _mask[np.where(self.parent.data < histLevels[0])] = 0
            _mask[np.where(self.parent.data > histLevels[1])] = 0
            if self.maskingMode == 1:  # masking mode
                self.userMaskAssem *= _mask
            elif self.maskingMode == 2:  # unmasking mode
                self.userMaskAssem[np.where(_mask == 0)] = 1
            elif self.maskingMode == 3:  # toggle mode
                print "You can only mask/unmask based on threshold "

            # update userMask
            self.userMask = self.parent.det.ndarray_from_image(self.parent.evt, self.userMaskAssem, pix_scale_size_um=None,
                                                        xy0_off_pix=None)

            self.displayMask()
            self.parent.pk.algInitDone = False
            self.parent.pk.updateClassification()
        if self.parent.args.v >= 1: print "done makeMaskThresh!!!!!!"

    def makeMaskPoly(self):
        self.initMask()
        if self.parent.data is not None and self.maskingMode > 0:
            calib = np.ones_like(self.parent.calib)
            img = self.parent.det.image(self.parent.evt, calib)
            # FIXME: pyqtgraph getArrayRegion doesn't work for masks with -x or -y
            self.selected = self.mask_poly.getArrayRegion(img, self.parent.img.w1.getImageItem(), returnMappedCoords=True)

            #import matplotlib.pyplot as plt
            #plt.imshow(self.selected, vmax=1, vmin=0)
            #plt.show()

            self.selected = 1 - self.selected

            x = self.mask_poly.parentBounds().x()
            y = self.mask_poly.parentBounds().y()
            #sx = self.mask_poly.parentBounds().size().height()
            #sy = self.mask_poly.parentBounds().size().width()
            #print "x,y: ", x, y, self.selected.shape#, sx, sy#, self.parent.data.shape[0], self.parent.data.shape[1]

            _mask = np.ones_like(img)
            if x >= 0 and y >= 0:
                _mask[x:x+self.selected.shape[0],y:y+self.selected.shape[1]] = self.selected
            else:
                print "##################################"
                print "Polygon mask has negative indices."
                print "##################################"

            if self.maskingMode >= 1:  # masking mode
                self.userMaskAssem *= _mask

            # update userMask
            self.userMask = self.parent.det.ndarray_from_image(self.parent.evt, self.userMaskAssem, pix_scale_size_um=None,
                                                        xy0_off_pix=None)
            #
            self.displayMask()
            self.parent.pk.algInitDone = False
        if self.parent.args.v >= 1: print "done makeMaskPoly!!!!!!"

    def getCombinedStaticMask(self):
        # update combined mask
        combinedStaticMask = np.ones_like(self.parent.calib)
        if self.userMask is not None and self.userMaskOn is True:
            combinedStaticMask *= self.userMask
        if self.psanaMask is not None and self.psanaMaskOn is True:
            combinedStaticMask *= self.psanaMask
        return combinedStaticMask

    def deployMask(self):
        print "*** deploy user-defined mask as mask.txt and mask.npy as DAQ shape ***"
        print "*** deploy user-defined mask as mask_natural_shape.npy as natural shape ***"

        combinedStaticMask = self.getCombinedStaticMask()

        if self.parent.args.v >= 1: print "natural static mask: ", combinedStaticMask.shape

        if combinedStaticMask.size == 2 * 185 * 388:  # cspad2x2
            # DAQ shape
            asData2x2 = two2x1ToData2x2(combinedStaticMask)
            np.save(self.parent.psocakeRunDir + "/mask.npy", asData2x2)
            np.savetxt(self.parent.psocakeRunDir + "/mask.txt",
                       asData2x2.reshape((-1, asData2x2.shape[-1])), fmt='%0.18e')
            # Natural shape
            np.save(self.parent.psocakeRunDir + "/mask_natural_shape.npy", combinedStaticMask)
        else:
            np.save(self.parent.psocakeRunDir + "/mask.npy", combinedStaticMask)
            np.savetxt(self.parent.psocakeRunDir + "/mask.txt",
                       combinedStaticMask.reshape((-1, combinedStaticMask.shape[-1])), fmt='%0.18e')

    def loadMask(self):
        fname = str(QtGui.QFileDialog.getOpenFileName(self.parent, 'Open file', self.parent.psocakeRunDir, 'ndarray image (*.npy *.npz)'))[0]
        print "fname: ", fname
        self.initMask()
        self.userMask = np.load(fname)
        if self.userMask.shape != self.parent.calib.shape:
            self.userMask = None
        if self.userMask is not None:
            self.userMaskAssem = self.parent.det.image(self.parent.evt, self.userMask)
        else:
            self.userMaskAssem = None
        self.userMaskOn = True
        self.p6.param(self.mask_grp, self.user_mask_str).setValue(self.userMaskOn)
        self.parent.pk.updateClassification()
Example #16
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)
Example #17
0
class RemoteManager(QObject):

    remote_changed = pyqtSignal(dict)

    def __init__(self, actuators=[], detectors=[], msgbox=False):
        super().__init__()
        self.actuators = actuators
        self.detectors = detectors
        if msgbox:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setText("Preset Manager?")
            msgBox.setInformativeText("What do you want to do?")
            cancel_button = msgBox.addButton(QtWidgets.QMessageBox.Cancel)
            new_button = msgBox.addButton("New",
                                          QtWidgets.QMessageBox.ActionRole)
            modify_button = msgBox.addButton('Modify',
                                             QtWidgets.QMessageBox.AcceptRole)
            msgBox.setDefaultButton(QtWidgets.QMessageBox.Cancel)
            ret = msgBox.exec()

            if msgBox.clickedButton() == new_button:
                self.set_new_remote()

            elif msgBox.clickedButton() == modify_button:
                path = select_file(start_path=remote_path,
                                   save=False,
                                   ext='xml')
                if path != '':
                    self.set_file_remote(str(path))
            else:  # cancel
                pass
        params = [{
            'title': 'Activate all',
            'name': 'activate_all',
            'type': 'action'
        }, {
            'title': 'Deactivate all',
            'name': 'deactivate_all',
            'type': 'action'
        }, {
            'title:': 'Actions',
            'name': 'action_group',
            'type': 'group'
        }]

        self.remote_actions = dict(shortcuts=dict([]), joysticks=dict([]))
        self.remote_settings = Parameter.create(title='Remote Settings',
                                                name='remote',
                                                type='group',
                                                children=params)
        self.remote_settings.sigTreeStateChanged.connect(
            self.remote_settings_changed)
        self.remote_settings_tree = ParameterTree()
        self.remote_settings_tree.setParameters(self.remote_settings,
                                                showTop=False)
        self.remote_settings.child(
            ('activate_all'
             )).sigActivated.connect(lambda: self.activate_all(True))
        self.remote_settings.child(
            ('deactivate_all'
             )).sigActivated.connect(lambda: self.activate_all(False))

    def activate_all(self, activate=True):
        for child in self.remote_settings.child(('action_group')).children():
            child.setValue(activate)

    def set_remote_configuration(self):
        #remove existing shorcuts
        while len(self.remote_actions['shortcuts']):
            self.remote_actions['shortcuts'].pop(
                list(self.remote_actions['shortcuts'].keys())[0])

        while len(self.remote_actions['joysticks']):
            self.remote_actions['joysticks'].pop(
                list(self.remote_actions['joysticks'].keys())[0])
        all_actions = []
        for child in self.remote_params.child('act_actions').children():
            module_name = child.opts['title'].split('Actuator ')[1]
            module_type = 'act'
            for action in child.child(('actions')).children():
                all_actions.append((module_name, action, module_type))
        for child in self.remote_params.child('det_actions').children():
            module_name = child.opts['title'].split('Detector ')[1]
            module_type = 'det'
            for action in child.child(('actions')).children():
                all_actions.append((module_name, action, module_type))

        for ind, action_tuple in enumerate(all_actions):
            module, action, module_type = action_tuple
            if action.child('remote_type').value() == 'Keyboard':
                #stc = QtWidgets.QShortcut(QtGui.QKeySequence(action.child(('shortcut')).value()), self.dockarea)
                self.remote_settings.child(('action_group')).addChild({
                    'title':
                    f"{module}: {action.child(('action')).value()} "
                    f"{action.child(('shortcut')).value()}:",
                    'name':
                    f'shortcut{ind:02d}',
                    'type':
                    'led_push',
                    'value':
                    False
                })
                self.remote_actions['shortcuts'][f'shortcut{ind:02d}'] = \
                    dict(shortcut=action.child(('shortcut')).value(), activated=False, name=f'shortcut{ind:02d}',
                         action=action.child(('action')).value(), module_name=module, module_type=module_type)
            else:
                self.remote_settings.child(('action_group')).addChild({
                    'title':
                    f"{module}: {action.child(('action')).value()}=>"
                    f"J{action.child(('joystickID')).value()}/"
                    f"{action.child(('actionner_type')).value()}"
                    f"{action.child(('actionnerID')).value()}:",
                    'name':
                    f'joy{ind:02d}',
                    'type':
                    'led_push',
                    'value':
                    False
                })
                self.remote_actions['joysticks'][f'joy{ind:02d}'] =\
                    dict(joystickID=action.child(('joystickID')).value(),
                         actionner_type=action.child(('actionner_type')).value(),
                         actionnerID=action.child(('actionnerID')).value(),
                         activated=False, name=f'joy{ind:02d}',
                         action=action.child(('action')).value(),
                         module_name=module, module_type=module_type)

        self.activate_all()

    def set_new_remote(self, file=None):
        if file is None:
            file = 'remote_default'
        param = [
            {
                'title': 'Filename:',
                'name': 'filename',
                'type': 'str',
                'value': file
            },
        ]
        params_action = [{
            'title': 'Actuator Actions:',
            'name': 'act_actions',
            'type': 'groupmodules',
            'addList': self.actuators,
            'modtype': 'Actuator'
        }, {
            'title': 'Detector Actions:',
            'name': 'det_actions',
            'type': 'groupmodules',
            'addList': self.detectors,
            'modtype': 'Detector'
        }]  # PresetScalableGroupMove(name="Moves")]
        self.remote_params = Parameter.create(title='Preset',
                                              name='Preset',
                                              type='group',
                                              children=param + params_action)
        self.remote_params.sigTreeStateChanged.connect(
            self.parameter_tree_changed)
        logger.info('Creating a new remote file')
        self.show_remote()

    def parameter_tree_changed(self, param, changes):
        """
            Check for changes in the given (parameter,change,information) tuple list.
            In case of value changed, update the DAQscan_settings tree consequently.

            =============== ============================================ ==============================
            **Parameters**    **Type**                                     **Description**
            *param*           instance of pyqtgraph parameter              the parameter to be checked
            *changes*         (parameter,change,information) tuple list    the current changes state
            =============== ============================================ ==============================
        """
        for param, change, data in changes:
            path = self.remote_params.childPath(param)
            if change == 'childAdded':
                pass

            elif change == 'value':
                if param.name() == 'remote_type':
                    status = data == 'Keyboard'
                    param.parent().child(('set_shortcut')).show(status)
                    param.parent().child(('shortcut')).show(status)
                    param.parent().child(('set_joystick')).show(not status)
                    param.parent().child(('joystickID')).show(not status)
                    param.parent().child(('actionner_type')).show(not status)
                    param.parent().child(('actionnerID')).show(not status)

                elif param.name() == 'set_shortcut':
                    msgBox = ShortcutSelection()
                    ret = msgBox.exec()
                    if ret:
                        param.parent().child(
                            ('shortcut')).setValue(msgBox.label.text())
                elif param.name() == 'set_joystick':
                    msgBox = JoystickButtonsSelection()
                    ret = msgBox.exec()
                    if ret:
                        param.parent().child(
                            ('joystickID')).setValue(msgBox.selection['joy'])
                        """
                        possible cases: ['Axis', 'Button', 'Hat']
                        """
                        if 'axis' in msgBox.selection:
                            param.parent().child(
                                ('actionner_type')).setValue('Axis')
                            param.parent().child(('actionnerID')).setValue(
                                msgBox.selection['axis'])
                        elif 'button' in msgBox.selection:
                            param.parent().child(
                                ('actionner_type')).setValue('Button')
                            param.parent().child(('actionnerID')).setValue(
                                msgBox.selection['button'])
                        elif 'hat' in msgBox.selection:
                            param.parent().child(
                                ('actionner_type')).setValue('Hat')
                            param.parent().child(('actionnerID')).setValue(
                                msgBox.selection['hat'])

            elif change == 'parent':
                pass

    def remote_settings_changed(self, param, changes):
        for param, change, data in changes:
            path = self.remote_params.childPath(param)
            if change == 'childAdded':
                pass

            elif change == 'value':
                if 'shortcut' in param.name():
                    self.remote_actions['shortcuts'][
                        param.name()]['activated'] = data
                    self.remote_changed.emit(
                        dict(action_type='shortcut',
                             action_name=param.name(),
                             action_dict=self.remote_actions['shortcuts'][
                                 param.name()]))
                elif 'joy' in param.name():
                    self.remote_actions['joysticks'][
                        param.name()]['activated'] = data
                    self.remote_changed.emit(
                        dict(action_type='joystick',
                             action_name=param.name(),
                             action_dict=self.remote_actions['joysticks'][
                                 param.name()]))

    def set_file_remote(self, filename, show=True):
        """

        """
        children = custom_tree.XML_file_to_parameter(filename)
        self.remote_params = Parameter.create(title='Shortcuts:',
                                              name='shortcuts',
                                              type='group',
                                              children=children)
        if show:
            self.show_remote()

    def show_remote(self):
        """

        """
        dialog = QtWidgets.QDialog()
        vlayout = QtWidgets.QVBoxLayout()
        tree = ParameterTree()
        # tree.setMinimumWidth(400)
        tree.setMinimumHeight(500)
        tree.setParameters(self.remote_params, showTop=False)

        vlayout.addWidget(tree)
        dialog.setLayout(vlayout)
        buttonBox = QtWidgets.QDialogButtonBox(parent=dialog)

        buttonBox.addButton('Save', buttonBox.AcceptRole)
        buttonBox.accepted.connect(dialog.accept)
        buttonBox.addButton('Cancel', buttonBox.RejectRole)
        buttonBox.rejected.connect(dialog.reject)

        vlayout.addWidget(buttonBox)
        dialog.setWindowTitle(
            'Fill in information about the actions and their shortcuts')
        res = dialog.exec()

        if res == dialog.Accepted:
            # save preset parameters in a xml file
            custom_tree.parameter_to_xml_file(
                self.remote_params,
                os.path.join(remote_path,
                             self.remote_params.child(('filename')).value()))
Example #18
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 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
Example #20
0

qt_mav = QtMav(outdevice, indevice)

# create gui
app = QtGui.QApplication(sys.argv)

f = open("tuner_ui.py.tmp", "w")
uic.compileUi("tuner.ui", f)
tuner = uic.loadUi("tuner.ui")


params = []
parameter = Parameter(name='params', type='group', children=params)
parameter_tree = ParameterTree(parent=tuner.tabTime)
parameter_tree.setParameters(parameter, showTop=False)
parameter_tree.resize(300, 500)

def get_group_index(params, gname):#{{{
    """
    recursive group refreshing/adding
    params -- parameters structure
    gname -- string representing name
    return:
        index in params structure
        -1 if not found
    """
    i = 0
    for g in params:
        if g['name'] == gname:
            return i
Example #21
0
class View(QtGui.QWidget):
    def __init__(self, parent=None, with_config=False, **kargs):
        QtGui.QWidget.__init__(self, parent)

        self.resize(800, 600)

        mainlayout = QtGui.QVBoxLayout()
        self.setLayout(mainlayout)

        self.glview = gl.GLViewWidget()
        mainlayout.addWidget(self.glview)
        self.glview.setCameraPosition(160, 160, 15)

        if with_config:
            h = QtGui.QHBoxLayout()
            mainlayout.addLayout(h)
            but = QtGui.QPushButton('Config',
                                    icon=QtGui.QIcon.fromTheme('configure'))
            h.addWidget(but)
            but.clicked.connect(self.open_params)
            but = QtGui.QPushButton('Save png',
                                    icon=QtGui.QIcon.fromTheme('save'))
            h.addWidget(but)
            but.clicked.connect(self.open_save_dialog)

        _params = [
            {
                'name': 'cortical_mesh',
                'type': 'list',
                'values': cortical_meshes.keys(),
                'value': 'BrainMesh_ICBM152'
            },
            {
                'name': 'cortical_alpha',
                'type': 'float',
                'value': .1,
                'limits': [0., 1.],
                'step': .01
            },
            {
                'name': 'cortical_color',
                'type': 'color',
                'value': 'w'
            },
            {
                'name': 'background_color',
                'type': 'color',
                'value': 'k'
            },
        ]
        self.params = Parameter.create(name='params',
                                       type='group',
                                       children=_params)
        self.tree = ParameterTree(parent=self)
        self.tree.setParameters(self.params)
        self.tree.setWindowFlags(QtCore.Qt.Dialog)

        self.mesh = None
        for k, v in kargs.items():
            self.params[k] = v
        self.change_background_color()
        self.plot_mesh()
        self.change_color_mesh()

        self.params.param('cortical_mesh').sigValueChanged.connect(
            self.plot_mesh)
        self.params.param('cortical_alpha').sigValueChanged.connect(
            self.change_color_mesh)
        self.params.param('cortical_color').sigValueChanged.connect(
            self.change_color_mesh)
        self.params.param('background_color').sigValueChanged.connect(
            self.change_background_color)

        self.glview.resizeGL(self.glview.width(), self.glview.height())

    def open_params(self):
        self.tree.show()

    def change_background_color(self):
        background_color = self.params['background_color']
        try:
            self.glview.setBackgroundColor(background_color)
        except:
            #~ #FIXME this is buggy in pyqtgrap0.9.8
            bgcolor = pg.mkColor(QtGui.QColor(background_color))
            glClearColor(bgcolor.red() / 255.,
                         bgcolor.green() / 255.,
                         bgcolor.blue() / 255., 1.0)
            glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)
            self.glview.paintGL()
            self.glview.update()

    def plot_mesh(self):
        vertexes, faces = cortical_meshes[self.params['cortical_mesh']]
        alpha = self.params['cortical_alpha']
        c = self.params['cortical_color']
        color = (c.red() / 255., c.green() / 255., c.blue() / 255., alpha)

        if self.mesh is None:

            self.mesh = gl.GLMeshItem(
                vertexes=vertexes,
                faces=faces,
                smooth=True,
                drawFaces=True,
                drawEdges=False,
                edgeColor=(1., 1., 1., .2),
                color=color,
                computeNormals=False,
                glOptions='translucent',
                #~ shader='balloon',
                shader='shaded',
            )
            self.glview.addItem(self.mesh)
        else:
            self.mesh.setMeshData(vertexes=vertexes, faces=faces)
            #~ self.mesh.set

    def change_color_mesh(self):
        alpha = self.params['cortical_alpha']
        c = self.params['cortical_color']
        color = (c.red() / 255., c.green() / 255., c.blue() / 255., alpha)
        self.mesh.setColor(color)

    def add_node(self, coords, color=(1, 1, 1, 0), size=5):
        sp1 = gl.GLScatterPlotItem(pos=coords,
                                   size=size,
                                   color=color,
                                   pxMode=False)
        self.glview.addItem(sp1)

    def add_edge(self, node_coords, connection_with, color=(1, 1, 1, 1)):
        for i in range(connection_with.shape[0]):
            for j in range(connection_with.shape[1]):
                if connection_with[i, j] == 0: continue
                plt = gl.GLLinePlotItem(pos=np.vstack(
                    [node_coords[i], node_coords[j]]),
                                        color=color,
                                        width=connection_with[i, j])
                self.glview.addItem(plt)

    def open_save_dialog(self):

        pathname = unicode(
            QtGui.QDesktopServices.storageLocation(
                QtGui.QDesktopServices.DesktopLocation))
        filename = os.path.join(pathname, 'Il est beau le cerveau.png')
        filename = QtGui.QFileDialog.getSaveFileName(self, u'Save png',
                                                     filename, 'PNG (*.png)')
        if filename:
            self.to_file(filename)

    def to_file(self, filename):
        self.glview.readQImage().save(filename)
Example #22
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')          
Example #23
0
class SmallData(object):
    def __init__(self, parent = None):
        self.parent = parent

        ## Dock 8: Quantifier
        self.dSmall = Dock("Small Data", size=(100, 100))
        self.w8 = ParameterTree()
        self.dSmall.addWidget(self.w8)
        self.w11a = pg.LayoutWidget()
        self.refreshBtn = QtGui.QPushButton('Refresh')
        self.w11a.addWidget(self.refreshBtn, row=0, col=0)
        self.dSmall.addWidget(self.w11a)
        # Add plot
        self.w9 = pg.PlotWidget(title="Metric")
        self.dSmall.addWidget(self.w9)

        # Quantifier parameter tree
        self.quantifier_grp = 'Small data'
        self.quantifier_filename_str = 'filename'
        self.quantifier_dataset_str = 'dataset'
        self.quantifier_sort_str = 'sort'

        # Quantifier
        self.quantifier_filename = ''
        self.quantifier_dataset = '/entry_1/result_1/'
        self.quantifier_sort = False
        self.quantifierFileOpen = False
        self.quantifierHasData = False

        self.params = [
            {'name': self.quantifier_grp, 'type': 'group', 'children': [
                {'name': self.quantifier_filename_str, 'type': 'str', 'value': self.quantifier_filename, 'tip': "Full path Hdf5 filename"},
                {'name': self.quantifier_dataset_str, 'type': 'str', 'value': self.quantifier_dataset, 'tip': "Hdf5 dataset metric, nPeaksAll or nHitsAll"},
                {'name': self.quantifier_sort_str, 'type': 'bool', 'value': self.quantifier_sort, 'tip': "Ascending sort metric"},
            ]},
        ]

        self.pSmall = Parameter.create(name='paramsQuantifier', type='group', \
                                       children=self.params, expanded=True)
        self.w8.setParameters(self.pSmall, showTop=False)
        self.pSmall.sigTreeStateChanged.connect(self.change)
        self.refreshBtn.clicked.connect(self.reloadQuantifier)

    # 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.quantifier_grp:
            if path[1] == self.quantifier_filename_str:
                self.updateQuantifierFilename(data)
            elif path[1] == self.quantifier_dataset_str:
                self.updateQuantifierDataset(data)
            elif path[1] == self.quantifier_sort_str:
                self.updateQuantifierSort(data)

    ##################################
    ########### Quantifier ###########
    ##################################

    def reloadQuantifier(self):
        self.updateQuantifierFilename(self.quantifier_filename)
        self.updateQuantifierDataset(self.quantifier_dataset)

    def updateQuantifierFilename(self, data):
        self.quantifier_filename = data
        if self.parent.args.v >= 1: print "Done opening metric"

    def updateQuantifierDataset(self, data):
        self.quantifier_dataset = data
        if os.path.isfile(self.quantifier_filename):
            try:
                self.quantifierFile = h5py.File(self.quantifier_filename, 'r')
                self.quantifierMetric = self.quantifierFile[self.quantifier_dataset].value
                try:
                    if self.quantifier_dataset[0] == '/':  # dataset starts with "/"
                        self.quantifier_eventDataset = self.quantifier_dataset.split("/")[1] + "/event"
                    else:  # dataset does not start with "/"
                        self.quantifier_eventDataset = "/" + self.quantifier_dataset.split("/")[0] + "/event"
                    self.quantifierEvent = self.quantifierFile[self.quantifier_eventDataset].value
                except:
                    if self.parent.args.v >= 1: print "Couldn't find /event dataset"
                    self.quantifierEvent = np.arange(len(self.quantifierMetric))
                self.quantifierFile.close()
                self.quantifierInd = np.arange(len(self.quantifierMetric))
                self.updateQuantifierSort(self.quantifier_sort)
            except:
                print "Couldn't read metric"
            if self.parent.args.v >= 1: print "Done reading metric"

    def updateQuantifierSort(self, data):
        self.quantifier_sort = data
        try:
            if self.quantifier_sort is True:
                self.quantifierIndSorted = np.argsort(self.quantifierMetric)
                self.quantifierMetricSorted = self.quantifierMetric[self.quantifierIndSorted]
                #self.quantifierEventSorted = self.quantifierMetric[self.quantifierInd]
                self.updateQuantifierPlot(self.quantifierMetricSorted)
            else:
                self.updateQuantifierPlot(self.quantifierMetric)
        except:
            print "Couldn't sort data"
            pass

    def updateQuantifierPlot(self, metric):
        self.w9.getPlotItem().clear()
        if len(np.where(metric==-1)[0]) > 0:
            self.curve = self.w9.plot(metric, pen=(200, 200, 200), symbolBrush=(255, 0, 0), symbolPen='k') # red
        else: # Every event was processed
            self.curve = self.w9.plot(metric, pen=(200, 200, 200), symbolBrush=(0, 0, 255), symbolPen='k') # blue
        self.w9.setLabel('left', "Small data")
        if self.quantifier_sort:
            self.w9.setLabel('bottom', "Sorted Event Index")
        else:
            self.w9.setLabel('bottom', "Event Index")
        self.curve.curve.setClickable(True)
        self.curve.sigClicked.connect(self.clicked)

    def clicked(self, points):
        with pg.BusyCursor():
            if self.parent.args.v >= 1:
                print("curve clicked", points)
                from pprint import pprint
                pprint(vars(points.scatter))
            for i in range(len(points.scatter.data)):
                if points.scatter.ptsClicked[0] == points.scatter.data[i][7]:
                    ind = i
                    break
            indX = points.scatter.data[i][0]
            indY = points.scatter.data[i][1]
            if self.parent.args.v >= 1: print "x,y: ", indX, indY
            if self.quantifier_sort:
                ind = self.quantifierIndSorted[ind]

            # temp
            self.parent.eventNumber = self.quantifierEvent[ind]

            self.parent.calib, self.parent.data = self.parent.img.getDetImage(self.parent.eventNumber)
            self.parent.img.w1.setImage(self.parent.data, autoRange=False, autoLevels=False, autoHistogramRange=False)
            self.parent.exp.p.param(self.parent.exp.exp_grp, self.parent.exp.exp_evt_str).setValue(self.parent.eventNumber)
Example #24
0
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))
Example #25
0
# -*- coding: utf-8 -*-
"""
Minimum working example for a bug in pyqtgraph's parametertree. 
Setting a ParameterItem of type int with a float value changes the variable internally to a float?
"""

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
from pyqtgraph.parametertree import Parameter, ParameterTree

app = QtGui.QApplication([])

params = [{'name': 'Dummy', 'type': 'int', 'value': 10}]

p = Parameter.create(name='params', type='group', children=params)
t = ParameterTree()
t.setParameters(p, showTop=False)

p.param('Dummy').setValue(3.14159)
v = p.param('Dummy').value()
print(v, type(v).__name__)

win = QtGui.QMainWindow()
win.setCentralWidget(t)
win.show()

QtGui.QApplication.instance().exec_()        
Example #26
0
class PeakFinding(object):
    def __init__(self, parent = None):
        self.parent = parent

        self.d9 = Dock("Peak Finder", size=(1, 1))
        ## Dock 9: Peak finder
        self.w10 = ParameterTree()
        self.d9.addWidget(self.w10)
        #self.w11 = pg.LayoutWidget()
        #self.generatePowderBtn = QtGui.QPushButton('Generate Powder')
        #self.launchBtn = QtGui.QPushButton('Launch peak finder')
        #self.w11.addWidget(self.launchBtn, row=0,col=0)
        #self.w11.addWidget(self.generatePowderBtn, row=0, col=0)
        #self.d9.addWidget(self.w11)

        self.userUpdate = None
        self.doingUpdate = False

        # Peak finding
        self.hitParam_grp = 'Peak finder'
        self.hitParam_showPeaks_str = 'Show peaks found'
        self.hitParam_algorithm_str = 'Algorithm'
        # algorithm 0
        self.hitParam_algorithm0_str = 'None'
        # algorithm 1
        self.hitParam_alg1_npix_min_str = 'npix_min'
        self.hitParam_alg1_npix_max_str = 'npix_max'
        self.hitParam_alg1_amax_thr_str = 'amax_thr'
        self.hitParam_alg1_atot_thr_str = 'atot_thr'
        self.hitParam_alg1_son_min_str = 'son_min'
        self.hitParam_algorithm1_str = 'Droplet'
        self.hitParam_alg1_thr_low_str = 'thr_low'
        self.hitParam_alg1_thr_high_str = 'thr_high'
        self.hitParam_alg1_rank_str = 'rank'
        self.hitParam_alg1_radius_str = 'radius'
        self.hitParam_alg1_dr_str = 'dr'
        # algorithm 2
        self.hitParam_alg2_npix_min_str = 'npix_min'
        self.hitParam_alg2_npix_max_str = 'npix_max'
        self.hitParam_alg2_amax_thr_str = 'amax_thr'
        self.hitParam_alg2_atot_thr_str = 'atot_thr'
        self.hitParam_alg2_son_min_str = 'son_min'
        self.hitParam_algorithm2_str = 'FloodFill'
        self.hitParam_alg2_thr_str = 'thr'
        self.hitParam_alg2_r0_str = 'r0'
        self.hitParam_alg2_dr_str = 'dr'
        # algorithm 3
        self.hitParam_alg3_npix_min_str = 'npix_min'
        self.hitParam_alg3_npix_max_str = 'npix_max'
        self.hitParam_alg3_amax_thr_str = 'amax_thr'
        self.hitParam_alg3_atot_thr_str = 'atot_thr'
        self.hitParam_alg3_son_min_str = 'son_min'
        self.hitParam_algorithm3_str = 'Ranker'
        self.hitParam_alg3_rank_str = 'rank'
        self.hitParam_alg3_r0_str = 'r0'
        self.hitParam_alg3_dr_str = 'dr'
        # algorithm 4
        self.hitParam_alg4_npix_min_str = 'npix_min'
        self.hitParam_alg4_npix_max_str = 'npix_max'
        self.hitParam_alg4_amax_thr_str = 'amax_thr'
        self.hitParam_alg4_atot_thr_str = 'atot_thr'
        self.hitParam_alg4_son_min_str = 'son_min'
        self.hitParam_algorithm4_str = 'iDroplet'
        self.hitParam_alg4_thr_low_str = 'thr_low'
        self.hitParam_alg4_thr_high_str = 'thr_high'
        self.hitParam_alg4_rank_str = 'rank'
        self.hitParam_alg4_r0_str = 'radius'
        self.hitParam_alg4_dr_str = 'dr'

        self.hitParam_outDir_str = 'Output directory'
        self.hitParam_runs_str = 'Run(s)'
        self.hitParam_queue_str = 'queue'
        self.hitParam_cpu_str = 'CPUs'
        self.hitParam_psanaq_str = 'psanaq'
        self.hitParam_psnehq_str = 'psnehq'
        self.hitParam_psfehq_str = 'psfehq'
        self.hitParam_psnehprioq_str = 'psnehprioq'
        self.hitParam_psfehprioq_str = 'psfehprioq'
        self.hitParam_psnehhiprioq_str = 'psnehhiprioq'
        self.hitParam_psfehhiprioq_str = 'psfehhiprioq'
        self.hitParam_psdebugq_str = 'psdebugq'
        self.hitParam_noe_str = 'Number of events to process'
        self.hitParam_threshold_str = 'Indexable number of peaks'
        self.hitParam_launch_str = 'Launch peak finder'
        self.hitParam_extra_str = 'Extra parameters'

        self.save_minPeaks_str = 'Minimum number of peaks'
        self.save_maxPeaks_str = 'Maximum number of peaks'
        self.save_minRes_str = 'Minimum resolution (pixels)'
        self.save_sample_str = 'Sample name'

        self.showPeaks = True
        self.peaks = None
        self.numPeaksFound = 0
        self.algorithm = 0
        self.algInitDone = False
        self.peaksMaxRes = 0
        self.classify = False

        self.hitParam_alg1_npix_min = 2.
        self.hitParam_alg1_npix_max = 20.
        self.hitParam_alg1_amax_thr = 0.
        self.hitParam_alg1_atot_thr = 1000.
        self.hitParam_alg1_son_min = 7.
        self.hitParam_alg1_thr_low = 250.
        self.hitParam_alg1_thr_high = 600.
        self.hitParam_alg1_rank = 2
        self.hitParam_alg1_radius = 2
        self.hitParam_alg1_dr = 1
        # self.hitParam_alg2_npix_min = 1.
        # self.hitParam_alg2_npix_max = 5000.
        # self.hitParam_alg2_amax_thr = 1.
        # self.hitParam_alg2_atot_thr = 1.
        # self.hitParam_alg2_son_min = 1.
        # self.hitParam_alg2_thr = 10.
        # self.hitParam_alg2_r0 = 1.
        # self.hitParam_alg2_dr = 0.05
        # self.hitParam_alg3_npix_min = 5.
        # self.hitParam_alg3_npix_max = 5000.
        # self.hitParam_alg3_amax_thr = 0.
        # self.hitParam_alg3_atot_thr = 0.
        # self.hitParam_alg3_son_min = 4.
        # self.hitParam_alg3_rank = 3
        # self.hitParam_alg3_r0 = 5.
        # self.hitParam_alg3_dr = 0.05
        # self.hitParam_alg4_npix_min = 1.
        # self.hitParam_alg4_npix_max = 45.
        # self.hitParam_alg4_amax_thr = 800.
        # self.hitParam_alg4_atot_thr = 0
        # self.hitParam_alg4_son_min = 7.
        # self.hitParam_alg4_thr_low = 200.
        # self.hitParam_alg4_thr_high = self.hitParam_alg1_thr_high
        # self.hitParam_alg4_rank = 3
        # self.hitParam_alg4_r0 = 2
        # self.hitParam_alg4_dr = 1
        self.hitParam_outDir = self.parent.psocakeDir
        self.hitParam_outDir_overridden = False
        self.hitParam_runs = ''
        self.hitParam_queue = self.hitParam_psanaq_str
        self.hitParam_cpus = 24
        self.hitParam_noe = -1
        self.hitParam_threshold = 15 # usually crystals with less than 15 peaks are not indexable

        self.minPeaks = 15
        self.maxPeaks = 2048
        self.minRes = -1
        self.sample = 'sample'
        self.profile = 0
        self.hitParam_extra = ''

        self.params = [
            {'name': self.hitParam_grp, 'type': 'group', 'children': [
                {'name': self.hitParam_showPeaks_str, 'type': 'bool', 'value': self.showPeaks,
                 'tip': "Show peaks found shot-to-shot"},
                {'name': self.hitParam_algorithm_str, 'type': 'list', 'values': {self.hitParam_algorithm1_str: 1,
                                                                                 self.hitParam_algorithm0_str: 0},
                 'value': self.algorithm},
                {'name': self.hitParam_algorithm1_str, 'visible': True, 'expanded': False, 'type': 'str', 'value': "",
                 'readonly': True, 'children': [
                    {'name': self.hitParam_alg1_npix_min_str, 'type': 'float', 'value': self.hitParam_alg1_npix_min,
                     'tip': "Only keep the peak if number of pixels above thr_low is above this value"},
                    {'name': self.hitParam_alg1_npix_max_str, 'type': 'float', 'value': self.hitParam_alg1_npix_max,
                     'tip': "Only keep the peak if number of pixels above thr_low is below this value"},
                    {'name': self.hitParam_alg1_amax_thr_str, 'type': 'float', 'value': self.hitParam_alg1_amax_thr,
                     'tip': "Only keep the peak if max value is above this value"},
                    {'name': self.hitParam_alg1_atot_thr_str, 'type': 'float', 'value': self.hitParam_alg1_atot_thr,
                     'tip': "Only keep the peak if integral inside region of interest is above this value"},
                    {'name': self.hitParam_alg1_son_min_str, 'type': 'float', 'value': self.hitParam_alg1_son_min,
                     'tip': "Only keep the peak if signal-over-noise is above this value"},
                    {'name': self.hitParam_alg1_thr_low_str, 'type': 'float', 'value': self.hitParam_alg1_thr_low,
                     'tip': "Grow a seed peak if above this value"},
                    {'name': self.hitParam_alg1_thr_high_str, 'type': 'float', 'value': self.hitParam_alg1_thr_high,
                     'tip': "Start a seed peak if above this value"},
                    {'name': self.hitParam_alg1_rank_str, 'type': 'int', 'value': self.hitParam_alg1_rank,
                     'tip': "region of integration is a square, (2r+1)x(2r+1)"},
                    {'name': self.hitParam_alg1_radius_str, 'type': 'int', 'value': self.hitParam_alg1_radius,
                     'tip': "region inside the region of interest"},
                    {'name': self.hitParam_alg1_dr_str, 'type': 'float', 'value': self.hitParam_alg1_dr,
                     'tip': "background region outside the region of interest"},
                ]},
                {'name': self.save_minPeaks_str, 'type': 'int', 'value': self.minPeaks,
                 'tip': "Index only if there are more Bragg peaks found"},
                {'name': self.save_maxPeaks_str, 'type': 'int', 'value': self.maxPeaks,
                 'tip': "Index only if there are less Bragg peaks found"},
                {'name': self.save_minRes_str, 'type': 'int', 'value': self.minRes,
                 'tip': "Index only if Bragg peak resolution is at least this"},
                {'name': self.save_sample_str, 'type': 'str', 'value': self.sample,
                 'tip': "Sample name saved inside cxi"},
                {'name': self.hitParam_outDir_str, 'type': 'str', 'value': self.hitParam_outDir},
                {'name': self.hitParam_runs_str, 'type': 'str', 'value': self.hitParam_runs},
                {'name': self.hitParam_queue_str, 'type': 'list', 'values': {self.hitParam_psfehhiprioq_str: 'psfehhiprioq',
                                                                             self.hitParam_psnehhiprioq_str: 'psnehhiprioq',
                                                                             self.hitParam_psfehprioq_str: 'psfehprioq',
                                                                             self.hitParam_psnehprioq_str: 'psnehprioq',
                                                                             self.hitParam_psfehq_str: 'psfehq',
                                                                             self.hitParam_psnehq_str: 'psnehq',
                                                                             self.hitParam_psanaq_str: 'psanaq',
                                                                             self.hitParam_psdebugq_str: 'psdebugq'},
                 'value': self.hitParam_queue, 'tip': "Choose queue"},
                {'name': self.hitParam_cpu_str, 'type': 'int', 'value': self.hitParam_cpus},
                {'name': self.hitParam_noe_str, 'type': 'int', 'value': self.hitParam_noe,
                 'tip': "number of events to process, default=-1 means process all events"},
                {'name': self.hitParam_extra_str, 'type': 'str', 'value': self.hitParam_extra, 'tip': "Extra peak finding flags"},
                {'name': self.hitParam_launch_str, 'type': 'action'},
            ]},
        ]

        self.p3 = Parameter.create(name='paramsPeakFinder', type='group', \
                                   children=self.params, expanded=True)
        self.w10.setParameters(self.p3, showTop=False)
        self.p3.sigTreeStateChanged.connect(self.change)
        #self.parent.connect(self.launchBtn, QtCore.SIGNAL("clicked()"), self.findPeaks)

    def digestRunList(self, runList):
        runsToDo = []
        if not runList:
            print "Run(s) is empty. Please type in the run number(s)."
            return runsToDo
        runLists = str(runList).split(",")
        for list in runLists:
            temp = list.split(":")
            if len(temp) == 2:
                for i in np.arange(int(temp[0]),int(temp[1])+1):
                    runsToDo.append(i)
            elif len(temp) == 1:
                runsToDo.append(int(temp[0]))
        return runsToDo

    def updateParam(self):
        if self.userUpdate is None:
            if self.parent.psocakeRunDir is not None:
                peakParamFname = self.parent.psocakeRunDir + '/peakParam.json'
                if os.path.exists(peakParamFname):
                    with open(peakParamFname) as infile:
                        d = json.load(infile)
                        if d[self.hitParam_algorithm_str] == 1:
                            # Update variables
                            try:
                                self.hitParam_alg1_npix_min = d[self.hitParam_alg1_npix_min_str]
                                self.hitParam_alg1_npix_max = d[self.hitParam_alg1_npix_max_str]
                                self.hitParam_alg1_amax_thr = d[self.hitParam_alg1_amax_thr_str]
                                self.hitParam_alg1_atot_thr = d[self.hitParam_alg1_atot_thr_str]
                                self.hitParam_alg1_son_min = d[self.hitParam_alg1_son_min_str]
                                self.hitParam_alg1_thr_low = d[self.hitParam_alg1_thr_low_str]
                                self.hitParam_alg1_thr_high = d[self.hitParam_alg1_thr_high_str]
                                self.hitParam_alg1_rank = int(d[self.hitParam_alg1_rank_str])
                                self.hitParam_alg1_radius = int(d[self.hitParam_alg1_radius_str])
                                self.hitParam_alg1_dr = d[self.hitParam_alg1_dr_str]
                                # Update GUI
                                self.doingUpdate = True
                                #self.p3.param(self.hitParam_grp, self.hitParam_algorithm_str).setValue(self.algorithm)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_npix_min_str).setValue(
                                    self.hitParam_alg1_npix_min)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_npix_max_str).setValue(
                                    self.hitParam_alg1_npix_max)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_amax_thr_str).setValue(
                                    self.hitParam_alg1_amax_thr)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_atot_thr_str).setValue(
                                    self.hitParam_alg1_atot_thr)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_son_min_str).setValue(
                                    self.hitParam_alg1_son_min)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_thr_low_str).setValue(
                                    self.hitParam_alg1_thr_low)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_thr_high_str).setValue(
                                    self.hitParam_alg1_thr_high)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_rank_str).setValue(
                                    self.hitParam_alg1_rank)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_radius_str).setValue(
                                    self.hitParam_alg1_radius)
                                self.doingUpdate = False
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_dr_str).setValue(
                                    self.hitParam_alg1_dr)
                            except:
                                pass

    def writeStatus(self, fname, d):
        json.dump(d, open(fname, 'w'))

    # Launch peak finding
    def findPeaks(self):
        self.parent.thread.append(LaunchPeakFinder.LaunchPeakFinder(self.parent)) # send parent parameters with self
        self.parent.thread[self.parent.threadCounter].launch(self.parent.experimentName, self.parent.detInfo)
        self.parent.threadCounter+=1
        # Save peak finding parameters
        runsToDo = self.digestRunList(self.hitParam_runs)
        for run in runsToDo:
            peakParamFname = self.parent.psocakeDir+'/r'+str(run).zfill(4)+'/peakParam.json'
            d = {self.hitParam_algorithm_str: self.algorithm,
                 self.hitParam_alg1_npix_min_str: self.hitParam_alg1_npix_min,
                 self.hitParam_alg1_npix_max_str: self.hitParam_alg1_npix_max,
                 self.hitParam_alg1_amax_thr_str: self.hitParam_alg1_amax_thr,
                 self.hitParam_alg1_atot_thr_str: self.hitParam_alg1_atot_thr,
                 self.hitParam_alg1_son_min_str: self.hitParam_alg1_son_min,
                 self.hitParam_alg1_thr_low_str: self.hitParam_alg1_thr_low,
                 self.hitParam_alg1_thr_high_str: self.hitParam_alg1_thr_high,
                 self.hitParam_alg1_rank_str: self.hitParam_alg1_rank,
                 self.hitParam_alg1_radius_str: self.hitParam_alg1_radius,
                 self.hitParam_alg1_dr_str: self.hitParam_alg1_dr}
            self.writeStatus(peakParamFname, d)

    # 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.hitParam_grp:
            if path[1] == self.hitParam_algorithm_str:
                self.algInitDone = False
                self.updateAlgorithm(data)
            elif path[1] == self.hitParam_showPeaks_str:
                self.showPeaks = data
                self.drawPeaks()
            elif path[1] == self.hitParam_outDir_str:
                self.hitParam_outDir = data
                self.hitParam_outDir_overridden = True
            elif path[1] == self.hitParam_runs_str:
                self.hitParam_runs = data
            elif path[1] == self.hitParam_queue_str:
                self.hitParam_queue = data
            elif path[1] == self.hitParam_cpu_str:
                self.hitParam_cpus = data
            elif path[1] == self.hitParam_noe_str:
                self.hitParam_noe = data
            elif path[1] == self.hitParam_threshold_str:
                self.hitParam_threshold = data
            elif path[1] == self.hitParam_launch_str:
                self.findPeaks()
            elif path[1] == self.save_minPeaks_str:
                self.minPeaks = data
            elif path[1] == self.save_maxPeaks_str:
                self.maxPeaks = data
            elif path[1] == self.save_minRes_str:
                self.minRes = data
            elif path[1] == self.save_sample_str:
                self.sample = data
            elif path[1] == self.hitParam_extra_str:
                self.hitParam_extra = data
            elif path[2] == self.hitParam_alg1_npix_min_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_npix_min = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_npix_max_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_npix_max = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_amax_thr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_amax_thr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_atot_thr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_atot_thr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_son_min_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_son_min = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_thr_low_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_thr_low = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_thr_high_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_thr_high = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_rank_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_rank = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_radius_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_radius = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_dr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_dr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()

    def updateAlgorithm(self, data):
        self.algorithm = data
        self.algInitDone = False
        self.updateClassification()
        if self.parent.args.v >= 1: print "##### Done updateAlgorithm: ", self.algorithm

    def saveCheetahFormat(self, arg):
        if arg == 'lcls':
            if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                dim0 = 8 * 185
                dim1 = 4 * 388
            elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                dim0 = 1920 #FIXME: rayonix can be binned
                dim1 = 1920
            elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                dim0 = 1920 #FIXME: rayonix can be binned
                dim1 = 1920
            else:
                dim0 = 0
                dim1 = 0

            if dim0 > 0:
                maxNumPeaks = 2048
                if self.parent.index.hiddenCXI is not None:
                    myHdf5 = h5py.File(self.parent.index.hiddenCXI, 'w')
                    grpName = "/entry_1/result_1"
                    dset_nPeaks = "/nPeaks"
                    dset_posX = "/peakXPosRaw"
                    dset_posY = "/peakYPosRaw"
                    dset_atot = "/peakTotalIntensity"
                    if grpName in myHdf5:
                        del myHdf5[grpName]
                    grp = myHdf5.create_group(grpName)
                    myHdf5.create_dataset(grpName + dset_nPeaks, (1,), dtype='int')
                    myHdf5.create_dataset(grpName + dset_posX, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))
                    myHdf5.create_dataset(grpName + dset_posY, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))
                    myHdf5.create_dataset(grpName + dset_atot, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))

                    myHdf5.create_dataset("/LCLS/detector_1/EncoderValue", (1,), dtype=float)
                    myHdf5.create_dataset("/LCLS/photon_energy_eV", (1,), dtype=float)
                    dset = myHdf5.create_dataset("/entry_1/data_1/data", (1, dim0, dim1), dtype=float)

                    # Convert calib image to cheetah image
                    img = np.zeros((dim0, dim1))
                    counter = 0
                    if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                        for quad in range(4):
                            for seg in range(8):
                                img[seg * 185:(seg + 1) * 185, quad * 388:(quad + 1) * 388] = self.parent.calib[counter, :, :]
                                counter += 1
                    elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                        img = self.parent.calib[:, :] # psana format
                    elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                        img = self.parent.calib[:, :]  # psana format
                    else:
                        print "saveCheetahFormat not implemented"

                    peaks = self.peaks.copy()
                    nPeaks = peaks.shape[0]

                    if nPeaks > maxNumPeaks:
                        peaks = peaks[:maxNumPeaks]
                        nPeaks = maxNumPeaks
                    for i, peak in enumerate(peaks):
                        seg, row, col, npix, amax, atot, rcent, ccent, rsigma, csigma, rmin, rmax, cmin, cmax, bkgd, rms, son = peak[0:17]
                        if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                            cheetahRow, cheetahCol = self.convert_peaks_to_cheetah(seg, row, col)
                            myHdf5[grpName + dset_posX][0, i] = cheetahCol
                            myHdf5[grpName + dset_posY][0, i] = cheetahRow
                            myHdf5[grpName + dset_atot][0, i] = atot
                        elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                            myHdf5[grpName + dset_posX][0, i] = col
                            myHdf5[grpName + dset_posY][0, i] = row
                            myHdf5[grpName + dset_atot][0, i] = atot
                        elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                            myHdf5[grpName + dset_posX][0, i] = col
                            myHdf5[grpName + dset_posY][0, i] = row
                            myHdf5[grpName + dset_atot][0, i] = atot
                    myHdf5[grpName + dset_nPeaks][0] = nPeaks

                    if self.parent.args.v >= 1: print "hiddenCXI clen (mm): ", self.parent.clen * 1000.
                    myHdf5["/LCLS/detector_1/EncoderValue"][0] = self.parent.clen * 1000.  # mm
                    myHdf5["/LCLS/photon_energy_eV"][0] = self.parent.photonEnergy
                    dset[0, :, :] = img
                    myHdf5.close()

    def updateClassification(self):
        if self.parent.calib is not None:
            if self.parent.mk.streakMaskOn:
                self.parent.mk.initMask()
                self.parent.mk.streakMask = self.parent.mk.StreakMask.getStreakMaskCalib(self.parent.evt)
                if self.parent.mk.streakMask is None:
                    self.parent.mk.streakMaskAssem = None
                else:
                    self.parent.mk.streakMaskAssem = self.parent.det.image(self.parent.evt, self.parent.mk.streakMask)
                self.algInitDone = False

            self.parent.mk.displayMask()

            # update combined mask
            self.parent.mk.combinedMask = np.ones_like(self.parent.calib)
            if self.parent.mk.streakMask is not None and self.parent.mk.streakMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.streakMask
            if self.parent.mk.userMask is not None and self.parent.mk.userMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.userMask
            if self.parent.mk.psanaMask is not None and self.parent.mk.psanaMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.psanaMask

            # Peak output (0-16):
            # 0 seg
            # 1 row
            # 2 col
            # 3 npix: no. of pixels in the ROI intensities above threshold
            # 4 amp_max: max intensity
            # 5 amp_tot: sum of intensities
            # 6,7: row_cgrav: center of mass
            # 8,9: row_sigma
            # 10,11,12,13: minimum bounding box
            # 14: background
            # 15: noise
            # 16: signal over noise
            if self.algorithm == 0: # No peak algorithm
                self.peaks = None
                self.drawPeaks()
            else:
                # Only initialize the hit finder algorithm once
                if self.algInitDone is False:
                    self.windows = None
                    self.alg = []
                    self.alg = PyAlgos(windows=self.windows, mask=self.parent.mk.combinedMask, pbits=0)

                    # set peak-selector parameters:
                    if self.algorithm == 1:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg1_npix_min, npix_max=self.hitParam_alg1_npix_max, \
                                                amax_thr=self.hitParam_alg1_amax_thr, atot_thr=self.hitParam_alg1_atot_thr, \
                                                son_min=self.hitParam_alg1_son_min)
                    elif self.algorithm == 2:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg2_npix_min, npix_max=self.hitParam_alg2_npix_max, \
                                                amax_thr=self.hitParam_alg2_amax_thr, atot_thr=self.hitParam_alg2_atot_thr, \
                                                son_min=self.hitParam_alg2_son_min)
                    elif self.algorithm == 3:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg3_npix_min, npix_max=self.hitParam_alg3_npix_max, \
                                                amax_thr=self.hitParam_alg3_amax_thr, atot_thr=self.hitParam_alg3_atot_thr, \
                                                son_min=self.hitParam_alg3_son_min)
                    elif self.algorithm == 4:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg4_npix_min, npix_max=self.hitParam_alg4_npix_max, \
                                                amax_thr=self.hitParam_alg4_amax_thr, atot_thr=self.hitParam_alg4_atot_thr, \
                                                son_min=self.hitParam_alg4_son_min)
                    self.algInitDone = True

                self.parent.calib = self.parent.calib * 1.0 # Neccessary when int is returned
                if self.algorithm == 1:
                    # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
                    #                           around pixel with maximal intensity.
                    self.peakRadius = int(self.hitParam_alg1_radius)
                    self.peaks = self.alg.peak_finder_v4r2(self.parent.calib,
                                                           thr_low=self.hitParam_alg1_thr_low,
                                                           thr_high=self.hitParam_alg1_thr_high,
                                                           rank=int(self.hitParam_alg1_rank),
                                                           r0=self.peakRadius,
                                                           dr=self.hitParam_alg1_dr)
                elif self.algorithm == 2:
                    # v2 - define peaks for regions of connected pixels above threshold
                    self.peakRadius = int(self.hitParam_alg2_r0)
                    self.peaks = self.alg.peak_finder_v2(self.parent.calib, thr=self.hitParam_alg2_thr, r0=self.peakRadius, dr=self.hitParam_alg2_dr)
                elif self.algorithm == 3:
                    self.peakRadius = int(self.hitParam_alg3_r0)
                    self.peaks = self.alg.peak_finder_v3(self.parent.calib, rank=self.hitParam_alg3_rank, r0=self.peakRadius, dr=self.hitParam_alg3_dr)
                elif self.algorithm == 4:
                    # v4 - aka Droplet Finder - the same as v1, but uses rank and r0 parameters in stead of common radius.
                    self.peakRadius = int(self.hitParam_alg4_r0)
                    self.peaks = self.alg.peak_finder_v4(self.parent.calib, thr_low=self.hitParam_alg4_thr_low, thr_high=self.hitParam_alg4_thr_high,
                                               rank=self.hitParam_alg4_rank, r0=self.peakRadius,  dr=self.hitParam_alg4_dr)
                self.numPeaksFound = self.peaks.shape[0]

                if self.parent.args.v >= 1: print "Num peaks found: ", self.numPeaksFound, self.peaks.shape

                # update clen
                self.parent.geom.updateClen('lcls')

                self.parent.index.clearIndexedPeaks()

                # Save image and peaks in cheetah cxi file
                self.saveCheetahFormat('lcls')

                if self.parent.index.showIndexedPeaks: self.parent.index.updateIndex()

                self.drawPeaks()
            if self.parent.args.v >= 1: print "Done updateClassification"

    def convert_peaks_to_cheetah(self, s, r, c) :
        """Converts seg, row, col assuming (32,185,388)
           to cheetah 2-d table row and col (8*185, 4*388)
        """
        segs, rows, cols = (32,185,388)
        row2d = (int(s)%8) * rows + int(r) # where s%8 is a segment in quad number [0,7]
        col2d = (int(s)/8) * cols + int(c) # where s/8 is a quad number [0,3]
        return row2d, col2d

    def getMaxRes(self, posX, posY, centerX, centerY):
        maxRes = np.max(np.sqrt((posX-centerX)**2 + (posY-centerY)**2))
        if self.parent.args.v >= 1: print "maxRes: ", maxRes
        return maxRes # in pixels

    def drawPeaks(self):
        self.parent.img.clearPeakMessage()
        if self.showPeaks:
            if self.peaks is not None and self.numPeaksFound > 0:
                self.ix = self.parent.det.indexes_x(self.parent.evt)
                self.iy = self.parent.det.indexes_y(self.parent.evt)
                if self.ix is None:
                    (_, dim0, dim1) = self.parent.calib.shape
                    self.iy = np.tile(np.arange(dim0),[dim1, 1])
                    self.ix = np.transpose(self.iy)
                self.iX = np.array(self.ix, dtype=np.int64)
                self.iY = np.array(self.iy, dtype=np.int64)
                if len(self.iX.shape)==2:
                    self.iX = np.expand_dims(self.iX,axis=0)
                    self.iY = np.expand_dims(self.iY,axis=0)
                cenX = self.iX[np.array(self.peaks[:,0],dtype=np.int64),np.array(self.peaks[:,1],dtype=np.int64),np.array(self.peaks[:,2],dtype=np.int64)] + 0.5
                cenY = self.iY[np.array(self.peaks[:,0],dtype=np.int64),np.array(self.peaks[:,1],dtype=np.int64),np.array(self.peaks[:,2],dtype=np.int64)] + 0.5
                self.peaksMaxRes = self.getMaxRes(cenX, cenY, self.parent.cx, self.parent.cy)
                diameter = self.peakRadius*2+1
                self.parent.img.peak_feature.setData(cenX, cenY, symbol='s', \
                                          size=diameter, brush=(255,255,255,0), \
                                          pen=pg.mkPen({'color': "c", 'width': 4}), pxMode=False) #FF0
                # Write number of peaks found
                xMargin = 5 # pixels
                yMargin = 0  # pixels
                maxX = np.max(self.ix) + xMargin
                maxY = np.max(self.iy) - yMargin
                myMessage = '<div style="text-align: center"><span style="color: cyan; font-size: 12pt;">Peaks=' + \
                            str(self.numPeaksFound) + ' <br>Res=' + str(int(self.peaksMaxRes)) + '<br></span></div>'
                self.parent.img.peak_text = pg.TextItem(html=myMessage, anchor=(0, 0))
                self.parent.img.w1.getView().addItem(self.parent.img.peak_text)
                self.parent.img.peak_text.setPos(maxX, maxY)
            else:
                self.parent.img.peak_feature.setData([], [], pxMode=False)
                self.parent.img.peak_text = pg.TextItem(html='', anchor=(0, 0))
                self.parent.img.w1.getView().addItem(self.parent.img.peak_text)
                self.parent.img.peak_text.setPos(0,0)
        else:
            self.parent.img.peak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print "Done updatePeaks"
Example #27
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())
Example #28
0
class MotorMonitor(QWidget):
    """
    MotorMonitor is a set of widgets to control the movement and readout the
    positions of the motors.
    """
    def __init__(self):
        super(QWidget, self).__init__()
        # self.layout = QVBoxLayout(self)
        self.show()

        with open("config.json") as f:
            self.config = json.load(f)
        # ip_address = self.config["encoder_ip"]
        # username = self.config["encoder_usr"]
        # password = self.config["encoder_pwd"]

        # self.pushButton1 = QPushButton("Initialize Motor Control")
        # self.layout.addWidget(self.pushButton1)
        # self.pushButton1.clicked.connect(self.on_motor_clicked)

        pt_motor = [{
            'name':
            'Motor Positions',
            'type':
            'group',
            'children': [{
                'name': 'Rotary',
                'type': 'float',
                'value': 0
            }, {
                'name': 'Linear',
                'type': 'float',
                'value': 0
            }, {
                'name': 'Source',
                'type': 'float',
                'value': 0
            }]
        }, {
            'name':
            'Limit Switch Check',
            'type':
            'group',
            'children': [{
                'name': 'Rotary',
                'type': 'action'
            }, {
                'name': 'Linear',
                'type': 'action'
            }, {
                'name': 'Source',
                'type': 'action'
            }]
        }, {
            'name':
            'Zero Motors',
            'type':
            'group',
            'children': [{
                'name': 'WARNING',
                'type': 'str',
                'value': 'DO NOT CLICK UNLESS \n ASSEMBLY IS LIFTED'
            }, {
                'name': 'Rotary',
                'type': 'action'
            }, {
                'name': 'Linear',
                'type': 'action'
            }, {
                'name': 'Source',
                'type': 'action'
            }]
        }]

        self.p = Parameter.create(name='params',
                                  type='group',
                                  children=pt_motor)

        self.pt = ParameterTree()
        self.pt.setParameters(self.p, showTop=False)

        self.p.sigTreeStateChanged.connect(self.tree_change)

        # def zero_rotary():
        #     zero_rotary_motor()
        # def zero_linear():
        #     zero_linear_motor()
        # def zero_source():
        #     zero_source_motor()
        # def rotary_switch():
        #     rotary_limit_check()
        # def linear_switch():
        #     linear_limit_check()
        # def source_switch():
        #     source_limit_check()

        # self.p.param('Zero Motors', 'Rotary').sigActivated.connect(zero_rotary)
        # self.p.param('Zero Motors', 'Linear').sigActivated.connect(zero_linear)
        # self.p.param('Zero Motors', 'Source').sigActivated.connect(zero_source)
        # self.p.param('Limit Switch Check', 'Rotary').sigActivated.connect(rotary_switch)
        # self.p.param('Limit Switch Check', 'Linear').sigActivated.connect(linear_switch)
        # self.p.param('Limit Switch Check', 'Source').sigActivated.connect(source_switch)

        # self.layout.addWidget(self.pt)

        text = """
                Run mp.movement() to start a movement program.
                Before any move, make sure the motor assembly is lifted off the cold plate.
                Before a new movement routine, make sure the motors are in their zero positions,
                by either clicking the zero motor button, or running through the terminal
                command in mp.movement().
                """
        # namespace = {'pg': pg, 'np': np, 'mp':mp}
        namespace = {'pg': pg, 'np': np}

        self.c = pyqtgraph.console.ConsoleWidget(namespace=namespace,
                                                 text=text)
        self.c.show()
        self.c.setWindowTitle('Motor Movement Console')

        layout = QGridLayout(self)
        layout.addWidget(self.c, 0, 1)
        layout.setColumnStretch(1, 2)
        layout.addWidget(self.pt, 0, 0)
        # self.pushButton1.clicked.connect(self.on_motor_clicked)

        self.setLayout(layout)

    def tree_change(self, param, changes):
        """
        print a message anytime something in the tree changes.
        """
        for param, change, data in changes:
            path = self.p.childPath(param)
            child_name = '.'.join(path) if path is not None else param.name()
            print(f'  parameter: {child_name}')
            print(f'  change:    {change}')
            print(f'  data:      {str(data)}')

    def on_motor_clicked(self):

        print('Connecting to Motor Controller')
        rotary_limit_check()
        source_limit_check()
        linear_limit_check()
Example #29
0
class ConcatStream():
	def __init__(self, scsynth, arduino, preset, outCh=20):
		print(preset)
		self.outCh = outCh
		self.doneLoading = False
		self.firstFreezeLoop = False
		self.isFreezeEnabled = False
		self.scsynth = scsynth
		self.arduino = arduino
		self.name = preset
		self.presetName = preset
		self.featureSpace = FeatureSpace(data=None)
		self.sndfiles = [f.split('.')[0] for f in os.listdir(sound_file_path) if len(f.split('.')) > 1 and f.split('.')[1] == 'wav']
		self.buffers = [i for i in range(len(self.sndfiles))]
		#self.presets = [f.split('.')[0] for f in os.listdir(preset_path) if len(f.split('.')) > 1 and f.split('.')[1] != 'DS_Store' and f.split('.')[0][-1] != 'P']
		self.presets = [f.split('.')[0] for f in os.listdir(preset_path) if len(f.split('.')) > 1 and f.split('.')[1] == 'npy']
		print(self.presets)
		self.sndfile = self.sndfiles[0]
		self.featureDimension = 3
		self.featureNames = ['centroid', 'skewness', 'hfc', 'crest', 'inharmonicity']		
		self.paramNames = ('Parameters.Feature1', 'Parameters.Feature2', 'Parameters.Feature3', 'Parameters.Feature4', 'Parameters.Feature5', 'Parameters.Pitch', 'Parameters.GrainDur', 'Parameters.GrainFreq', 'Parameters.Amplitude', 'Parameters.Panning', 'Parameters.GrainAtk', 'Parameters.Neighbors')
		self.reversedControl = dict(zip(self.paramNames, [False for i in range(len(self.paramNames))]))
		self.isGUIshown = False
		self.w = QtGui.QMainWindow()
		self.area = DockArea()
		self.w.setCentralWidget(self.area)
		self.w.resize(320,700)
		self.w.setWindowTitle('ConcatStream: '+self.presetName)		
		self.paramDock = Dock("Parameters")
		self.area.addDock(self.paramDock, 'top')

		self.parameters = [
			{'name': 'Parameters', 'type': 'group', 'children': [
				{'name': 'Name', 'type': 'str', 'value': self.presetName},
				{'name': 'Soundfile', 'type': 'list', 'values': self.sndfiles, 'value': self.sndfile},
				{'name': 'Preset', 'type': 'list', 'values': self.presets, 'value': self.presetName},
				{'name': 'Dimensionality', 'type': 'list', 'values': [1, 2, 3, 4, 5], 'value': self.featureDimension},
				{'name': 'Feature1', 'type': 'group', 'children': [
					{'name': 'which', 'type': 'list', 'values': ['centroid', 'crest', 'flatness', 'hfc', 'inharmonicity', 'skewness', 'spread', 'kurtosis'], 'value': self.featureNames[0]},
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 0}
				]},
				{'name': 'Feature2', 'type': 'group', 'children': [
					{'name': 'which', 'type': 'list', 'values': ['centroid', 'crest', 'flatness', 'hfc', 'inharmonicity', 'skewness', 'spread', 'kurtosis'], 'value': self.featureNames[1]},
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 1}
				]},
				{'name': 'Feature3', 'type': 'group', 'children': [
					{'name': 'which', 'type': 'list', 'values': ['centroid', 'crest', 'flatness', 'hfc', 'inharmonicity', 'skewness', 'spread', 'kurtosis'], 'value': self.featureNames[2]},
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 2}
				]},
				{'name': 'Feature4', 'type': 'group', 'children': [
					{'name': 'which', 'type': 'list', 'values': ['centroid', 'crest', 'flatness', 'hfc', 'inharmonicity', 'skewness', 'spread', 'kurtosis'], 'value': self.featureNames[3]},
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'Feature5', 'type': 'group', 'children': [
					{'name': 'which', 'type': 'list', 'values': ['centroid', 'crest', 'flatness', 'hfc', 'inharmonicity', 'skewness', 'spread', 'kurtosis'], 'value': self.featureNames[4]},
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'Pitch', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 0.8},
					{'name': 'max', 'type': 'float', 'value': 4},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'GrainDur', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 0.004},
					{'name': 'max', 'type': 'float', 'value': 0.4},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 3}
				]},
				{'name': 'GrainFreq', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 50},
					{'name': 'max', 'type': 'float', 'value': 400},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'round', 'type': 'float', 'value': 0.0},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 4}
				]},
				{'name': 'Amplitude', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 0.5},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'Panning', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'GrainAtk', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'float', 'value': 0.0},
					{'name': 'max', 'type': 'float', 'value': 1.0},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
				{'name': 'Neighbors', 'type': 'group', 'children': [
					{'name': 'min', 'type': 'int', 'value': 1},
					{'name': 'max', 'type': 'int', 'value': 20},
					{'name': 'reverse', 'type': 'bool', 'value': False},
					{'name': 'hardwareConnection', 'type': 'list', 'values': [999, 0, 1, 2, 3, 4], 'value': 999}
				]},
			]}
		]
		self.p = Parameter.create(name='params', type='group', children=self.parameters)
		self.t = ParameterTree()
		self.t.setParameters(self.p, showTop=False)
		self.p.sigTreeStateChanged.connect(self.change)
		self.paramDock.addWidget(self.t)
		# save preset to file
		self.saveBtn = QtGui.QPushButton('Save')
		self.paramDock.addWidget(self.saveBtn)
		self.saveBtn.clicked.connect(self.save)
		# recall preset from file
		self.recallBtn = QtGui.QPushButton('Recall')
		self.paramDock.addWidget(self.recallBtn)
		self.recallBtn.clicked.connect(self.recall)
		# start/stop freeze
		'''
		self.freezeBtn = QtGui.QPushButton('Freeze')
		self.paramDock.addWidget(self.freezeBtn)
		self.freezeBtn.clicked.connect(self.playFreeze)
		'''
		self.recall()
		self.doneLoading = True
		self.initAudio()

	def save(self):
		np.save(preset_path+self.presetName, self.p.saveState())

	def recall(self):
		print("preset name dio stronzo cane", self.presetName)
		data = dict(np.load(preset_path+self.presetName+'.npy').tolist())
		data['children']['Parameters']['children']['Preset']['values'] = [f.split('.')[0] for f in os.listdir(preset_path) if len(f.split('.')) > 1 and f.split('.')[1] == 'npy']
		data['children']['Parameters']['children']['Preset']['limits'] = data['children']['Parameters']['children']['Preset']['values']
		data['children']['Parameters']['children']['Preset']['value'] = self.presetName
		data['children']['Parameters']['children']['Preset']['default'] = self.presetName
		data['children']['Parameters']['children']['Name']['value'] = self.presetName
		data['children']['Parameters']['children']['Name']['default'] = self.presetName
		data['children']['Parameters']['children']['Soundfile']['values'] = [f.split('.')[0] for f in os.listdir(sound_file_path) if len(f.split('.')) > 1 and f.split('.')[1] == 'wav']
		data['children']['Parameters']['children']['Soundfile']['limits'] = data['children']['Parameters']['children']['Soundfile']['values']
		data['children']['Parameters']['children']['Soundfile']['default'] = data['children']['Parameters']['children']['Soundfile']['value']
		print(data['children']['Parameters']['children']['Soundfile'])
		
		#print(data)
		#np.load(preset_path+self.presetName+'.npy').tolist()
		self.p.restoreState(data)
		np.save(preset_path+self.presetName, self.p.saveState())

	def change(self, param, changes):
		for param, change, data in changes:
			path = self.p.childPath(param)
			if path is not None:
				childName = '.'.join(path)
			else:
				childName = param.name()

			if childName == 'Parameters.Soundfile':
				if not isinstance(data, (list, collections.OrderedDict, np.ndarray)):
					self.sndfile = data
					if self.doneLoading:
						self.initAudioNoReloadCSThread()
						self.reloadFeatureSpace()

			if childName == 'Parameters.Preset':
				self.presetName = str(data)
				print("preset name", self.presetName)
				if self.doneLoading:
					self.recall()
					self.initAudioNoReloadCSThread()
					self.reloadFeatureSpace()
				
			if childName == 'Parameters.Dimensionality':
				self.featureDimension = data
				if self.doneLoading:
					self.initAudioNoReloadCSThread()
					self.reloadFeatureSpace()

			if childName == 'Parameters.Name':
				print('name : ', str(data))
				self.name = str(data)
				self.presetName = str(data)
				self.w.setWindowTitle('ConcatStream: '+self.presetName)

			if len(path) > 2 and path[2] == 'hardwareConnection':
				self.checkHardwareConnections()

			if len(path) > 2 and path[2] == 'which':
				self.featureNames[int(path[1][-1])-1] = data
				if self.doneLoading:
					self.initAudioNoReloadCSThread()
					self.reloadFeatureSpace()

			if len(path) > 2 and (path[2] == 'min' or path[2] == 'max'):
				self.calcParameterMinMaxRanges()

			if childName == 'Parameters.GrainFreq.round':
				print("changing round value to: {}".format(data))
				self.csthread.setRoundGFreq(data)

			if path is not None and len(path) > 2:
				if path[2] == 'reverse':
					if self.reversedControl['.'.join(path[0:2])] == False:
						self.reversedControl['.'.join(path[0:2])] = True
					else:
						self.reversedControl['.'.join(path[0:2])] = False

	def playThread(self):
		if not self.isFreezeEnabled:
			if(self.arduino.port != None):
				self.pots = self.arduino.pots
				self.barycentrum = self.arduino.barycentrum
			else:
				self.pots = np.zeros(5)
				for i in range(len(self.arduino.pots)):
					self.pots[i] = self.arduino.lags[i].getValue()
			for index, param in enumerate(self.paramNames):
				if param.split(".")[1][0:7] == "Feature":
					if self.hardwareConnections[param] != 999:
						self.kdQuery[index] = ((self.pots[self.hardwareConnections[param]] if not self.reversedControl else 1.0 - self.pots[self.hardwareConnections[param]]) * (self.maxValues[param] - self.minValues[param])) + self.minValues[param]
					else:
						self.kdQuery[index] = self.minValues[param]
				else:
					if self.hardwareConnections[param] != 999:
						self.csthread.setParam(param.split(".")[1], ((self.pots[self.hardwareConnections[param]] if not self.reversedControl else 1.0 - self.pots[self.hardwareConnections[param]]) * (self.maxValues[param] - self.minValues[param])) + self.minValues[param])
					else:
						self.csthread.setParam(param.split(".")[1], self.minValues[param])
			if self.hardwareConnections['Parameters.Neighbors'] != 999:
				self.neighbours = int((self.pots[self.hardwareConnections['Parameters.Neighbors']] * (self.maxValues['Parameters.Neighbors'] - self.minValues['Parameters.Neighbors'])) + self.minValues['Parameters.Neighbors'])
			else:
				self.neighbours = int(self.minValues['Parameters.Neighbors'])
			self.featureSpace.setPointerPosition([(self.kdQuery[featurecount] * 20) - 10 for featurecount in range(len(self.kdQuery))])
			sample = queryKDTree(self.kdtree, [self.kdQuery[featurecount] for featurecount in range(self.featureDimension)], self.neighbours)
			if isinstance(sample, list):
				self.csthread.setPos(list(np.multiply(sample, int(fft_hop_size))))
			else:
				self.csthread.setPos(sample * int(fft_hop_size))
		else:
			if self.firstFreezeLoop:
				self.firstFreezeLoop = False
				if(self.arduino.port != None):
					self.pots = self.arduino.pots
				else:
					self.pots = np.zeros(5)
					for i in range(len(self.arduino.pots)):
						self.pots[i] = self.arduino.lags[i].getValue()
				for index, param in enumerate(self.paramNames):
					if param.split(".")[1][0:7] == "Feature":
						if self.hardwareConnections[param] != 999:
							self.kdQuery[index] = ((self.pots[self.hardwareConnections[param]] if not self.reversedControl else 1.0 - self.pots[self.hardwareConnections[param]]) * (self.maxValues[param] - self.minValues[param])) + self.minValues[param]
						else:
							self.kdQuery[index] = self.minValues[param]
					else:
						if self.hardwareConnections[param] != 999:
							self.csthread.setParam(param.split(".")[1], ((self.pots[self.hardwareConnections[param]] if not self.reversedControl else 1.0 - self.pots[self.hardwareConnections[param]]) * (self.maxValues[param] - self.minValues[param])) + self.minValues[param])
						else:
							self.csthread.setParam(param.split(".")[1], self.minValues[param])
				if self.hardwareConnections['Parameters.Neighbors'] != 999:
					self.neighbours = int((self.pots[self.hardwareConnections['Parameters.Neighbors']] * (self.maxValues['Parameters.Neighbors'] - self.minValues['Parameters.Neighbors'])) + self.minValues['Parameters.Neighbors'])
				else:
					self.neighbours = int(self.minValues['Parameters.Neighbors'])
				self.featureSpace.setPointerPosition([(self.kdQuery[featurecount] * 20) - 10 for featurecount in range(len(self.kdQuery))])
				sample = queryKDTree(self.kdtree, [self.kdQuery[featurecount] for featurecount in range(self.featureDimension)], self.neighbours)
				if isinstance(sample, list):
					self.csthread.setPos(list(np.multiply(sample, int(fft_hop_size))))
				else:
					self.csthread.setPos(sample * int(fft_hop_size))

	def play(self):
		self.kdQuery = np.zeros(5)
		self.checkHardwareConnections()
		self.calcParameterMinMaxRanges()
		self.time = time.time()
		self.playTimer = QTimer()
		self.playTimer.setSingleShot(False)
		self.playTimer.timeout.connect(self.playThread)
		self.playTimer.start(10)
		self.isPlaying = True

	def stop(self):
		self.playTimer.stop()
		self.csthread.setAmp(0.0)
		self.isPlaying = False
		self.isFreezeEnabled = False
		self.firstFreezeLoop = False

	def checkHardwareConnections(self):
		self.hardwareConnections = np.array([], dtype="int")
		for param in self.paramNames:
			self.hardwareConnections = np.concatenate((self.hardwareConnections, [int(dict(dict(dict(self.p.getValues())[param.split(".")[0]][1])[param.split(".")[1]][1])['hardwareConnection'][0])]), axis=0)
		self.hardwareConnections = dict(zip(self.paramNames, self.hardwareConnections))
		
	def calcParameterMinMaxRanges(self):
		self.minValues = np.array([])
		self.maxValues = np.array([])
		for param in self.paramNames:
			self.minValues = np.concatenate((self.minValues, [float(dict(dict(dict(self.p.getValues())[param.split(".")[0]][1])[param.split(".")[1]][1])['min'][0])]), axis=0)
			self.maxValues = np.concatenate((self.maxValues, [float(dict(dict(dict(self.p.getValues())[param.split(".")[0]][1])[param.split(".")[1]][1])['max'][0])]), axis=0)
		self.minValues = dict(zip(self.paramNames, self.minValues))
		self.maxValues = dict(zip(self.paramNames, self.maxValues))
		
	def initAudio(self):
		self.featureData = readFeaturesNPY(feature_file_path+self.sndfile, self.featureNames[0:self.featureDimension], normalize=True, interp=0, power=1)
		self.kdtree = buildKDTree(features=self.featureData)
		self.csthread = CSThread(server=self.scsynth, bufnum=0, amp=0, outCh=self.outCh)
		self.csthread.setBufnum(self.sndfiles.index(self.sndfile))
		print("soundfile index", self.sndfiles.index(self.sndfile))
		self.calcParameterMinMaxRanges()
		self.checkHardwareConnections()
		
	def initAudioNoReloadCSThread(self):
		self.featureData = readFeaturesNPY(feature_file_path+self.sndfile, self.featureNames[0:self.featureDimension], normalize=True, interp=0, power=1)
		self.csthread.setBufnum(self.sndfiles.index(self.sndfile))
		self.kdtree = buildKDTree(features=self.featureData)
		self.start_frames = computeStartFrames(features=self.featureData, hopSize=fft_hop_size)
		self.calcParameterMinMaxRanges()
		self.checkHardwareConnections()
		
	def reloadFeatureSpace(self):
		self.featureSpace.reloadData(self.featureData)
		
	def show(self):
		self.w.show()
		self.featureSpace.show()
		self.isGUIshown = True

	def hide(self):
		self.w.hide()
		self.featureSpace.hide()
		self.isGUIshown = False
Example #30
0
class Navigator(QObject):
    log_signal = pyqtSignal(str)
    sig_double_clicked = pyqtSignal(float, float)

    def __init__(self, parent=None, h5file=None):
        super(Navigator, self).__init__(parent)

        if parent is None:
            parent = QtWidgets.QWidget()
        self.parent = parent
        self.title = 'Navigator'
        self.status_time = 1000
        self.x_range = []
        self.y_range = []
        self.filters = tables.Filters(complevel=5)
        self.next_scan_index = 0
        self.viewer = None
        self.overlays = []  #%list of imageItem items displaying 2D scans info
        self.h5file_path = None
        self.h5file = h5file
        if h5file is not None:
            self.h5file_path = h5file.filename
            self.settings.child('settings',
                                'filepath').setValue(h5file.filename)
            self.settings.child('settings', 'Load h5').hide()
            self.show_overlay()

        self.setupUI()

    def create_toolbar(self):
        iconload = QtGui.QIcon()
        iconload.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/OpenLayers.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.loadaction = QtWidgets.QAction(iconload, "Load scan file (.h5)",
                                            None)
        self.toolbar.addAction(self.loadaction)
        self.loadaction.triggered.connect(self.load_data)

        iconloadim = QtGui.QIcon()
        iconloadim.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/Open_File_32.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.loadactionim = QtWidgets.QAction(iconloadim,
                                              "Load image file (.h5)", None)
        self.toolbar.addAction(self.loadactionim)
        self.loadactionim.triggered.connect(self.load_image)

        icon_ratio = QtGui.QIcon()
        icon_ratio.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/Zoom_1_1.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.action_ratio = QtWidgets.QAction(icon_ratio,
                                              "Set viewbox aspect ratio to 1",
                                              None)
        self.action_ratio.setCheckable(True)
        self.toolbar.addAction(self.action_ratio)
        self.action_ratio.triggered.connect(self.set_aspect_ratio)

        icon_moveat = QtGui.QIcon()
        icon_moveat.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/move_contour.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.moveat_action = QtWidgets.QAction(
            icon_moveat,
            "When selected, double clicking on viewbox will move DAQ_Move modules",
            None)
        self.moveat_action.setCheckable(True)
        self.toolbar.addAction(self.moveat_action)

        icon_sel_all = QtGui.QIcon()
        icon_sel_all.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/select_all2.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.sel_all_action = QtWidgets.QAction(
            icon_sel_all, "Select (show) all 2D scans on the viewer", None)
        self.toolbar.addAction(self.sel_all_action)
        self.sel_all_action.triggered.connect(self.show_all)

        icon_sel_none = QtGui.QIcon()
        icon_sel_none.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/select_none.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.sel_none_action = QtWidgets.QAction(
            icon_sel_none, "Unselect (hide) all 2D scans on the viewer", None)
        self.toolbar.addAction(self.sel_none_action)
        self.sel_none_action.triggered.connect(self.show_none)

        icon_histo = QtGui.QIcon()
        icon_histo.addPixmap(
            QtGui.QPixmap(":/icons/Icon_Library/Histogram.png"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.histo_action = QtWidgets.QAction(icon_histo,
                                              "Show (hide) histograms", None)
        self.toolbar.addAction(self.histo_action)
        self.histo_action.setCheckable(True)
        self.histo_action.triggered.connect(self.show_histo)

    @pyqtSlot(float, float)
    def move_at(self, posx, posy):
        if self.moveat_action.isChecked():
            self.sig_double_clicked.emit(posx, posy)

    def show_histo(self):
        show_state = self.histo_action.isChecked()
        self.viewer.histo_widget.setVisible(show_state)

    def show_all(self):
        self.show_scans()

    def show_none(self):
        self.show_scans(False)

    def show_scans(self, show=True):
        for child in self.settings.child('scans'):
            val = child.value()
            val['checked'] = show
            child.setValue(val)
            child.sigValueChanged.emit(child, val)

    def list_2Dscans(self):
        try:
            scans = utils.get_h5file_scans(self.h5file)
            #settings=[dict(scan_name=node._v_name,path=node._v_pathname, pixmap=nparray2Qpixmap(node.read()))),...]
            params = []
            for child in self.settings.child(('scans')).children():
                if 'Scan' in child.name():
                    self.settings.child(('scans')).removeChild(child)
            for scan in scans:
                params.append({
                    'name':
                    scan['scan_name'],
                    'type':
                    'pixmap_check',
                    'value':
                    dict(data=scan['data'], checked=False, path=scan['path'])
                })
            self.settings.child(('scans')).addChildren(params)

            for child in self.settings.child(('scans')).children():
                val = child.value()
                val.update(dict(checked=True))
                child.setValue(val)
                child.sigValueChanged.emit(child, child.value())

        except Exception as e:
            self.update_status(utils.getLineInfo() + str(e),
                               status_time=self.status_time,
                               log_type='log')

    def load_image(self):
        #image_filepath = str(utils.select_file(start_path=None, save=False, ext='h5'))
        data, fname, node_path = browse_data(ret_all=True)
        if data is not None and fname != '':
            self.h5file_image = tables.open_file(fname)
            node = self.h5file_image.get_node(node_path)
            pixmaps = utils.get_h5file_scans(self.h5file_image, node._v_parent)
            self.settings.child('settings', 'imagepath').setValue(fname)
            other_child = [
                child for child in self.settings.child(('scans')).children()
                if 'Scan' not in child.name()
            ]
            if len(other_child) >= 1:
                for child in other_child:
                    self.settings.child(('scans')).removeChild(child)
            params = []
            for pixmap in pixmaps:
                params.append({
                    'name':
                    pixmap['scan_name'],
                    'type':
                    'pixmap_check',
                    'value':
                    dict(data=pixmap['data'],
                         checked=False,
                         path=pixmap['path'])
                })
            self.settings.child(('scans')).addChildren(params)

            val = self.settings.child('scans', pixmaps[0]['scan_name']).value()
            val.update(dict(checked=True))
            self.settings.child('scans', pixmaps[0]['scan_name']).setValue(val)
            self.settings.child(
                'scans', pixmaps[0]['scan_name']).sigValueChanged.emit(
                    self.settings.child('scans', pixmaps[0]['scan_name']),
                    self.settings.child('scans',
                                        pixmaps[0]['scan_name']).value())

    def load_data(self):
        self.h5file_path = str(
            utils.select_file(start_path=None, save=False, ext='h5'))
        if self.h5file_path != '':
            self.settings.child('settings',
                                'filepath').setValue(self.h5file_path)
            if self.h5file is not None:
                self.h5file.close()
            self.h5file = tables.open_file(self.h5file_path, 'a')
            self.list_2Dscans()

    def set_aspect_ratio(self):
        if self.action_ratio.isChecked():
            self.viewer.image_widget.plotitem.vb.setAspectLocked(lock=True,
                                                                 ratio=1)
        else:
            self.viewer.image_widget.plotitem.vb.setAspectLocked(lock=False,
                                                                 ratio=1)

    def settings_changed(self, param, changes):
        """
            Check for changes in the given (parameter,change,information) tuple list.
            In case of value changed, update the DAQscan_settings tree consequently.

            =============== ============================================ ==============================
            **Parameters**    **Type**                                     **Description**
            *param*           instance of pyqtgraph parameter              the parameter to be checked
            *changes*         (parameter,change,information) tuple list    the current changes state
            =============== ============================================ ==============================
        """
        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 == 'childAdded':
                pass

            elif change == 'value':
                if param.parent().name() == 'scans':
                    if data['checked']:
                        try:
                            if 'Scan' in param.name():
                                h5file = self.h5file
                                nodes = list(h5file.walk_nodes(data['path']))
                            else:
                                h5file = self.h5file_image
                                nodes = [h5file.get_node(data['path'])]
                            ind = 0
                            for node in nodes:
                                flag = False
                                if 'type' in node._v_attrs and 'data_dimension' in node._v_attrs:
                                    if 'scan_type' in node._v_attrs:
                                        if node._v_attrs[
                                                'scan_type'] == 'scan2D' and node._v_attrs[
                                                    'data_dimension'] == '0D':  #2d scan of 0D data
                                            flag = True
                                        elif node._v_attrs[
                                                'scan_type'] == '' and node._v_attrs[
                                                    'data_dimension'] == '2D':  #image data (2D) with no scan
                                            flag = True

                                if flag:
                                    im = ImageItem()
                                    im.setOpacity(1)
                                    #im.setOpts(axisOrder='row-major')
                                    self.viewer.image_widget.plotitem.addItem(
                                        im)
                                    im.setCompositionMode(
                                        QtGui.QPainter.CompositionMode_Plus)
                                    im.setImage(node.read().T)

                                    if 'Scan' in param.name():
                                        x_axis = np.unique(
                                            h5file.get_node(data['path']).
                                            _v_parent._f_get_child(
                                                utils.capitalize(
                                                    'scan_x_axis')).read())
                                        y_axis = np.unique(
                                            h5file.get_node(data['path']).
                                            _v_parent._f_get_child(
                                                utils.capitalize(
                                                    'scan_y_axis')).read())
                                    else:
                                        x_axis = np.unique(
                                            h5file.get_node(data['path']).
                                            _v_parent._f_get_child(
                                                utils.capitalize(
                                                    'x_axis')).read())
                                        y_axis = np.unique(
                                            h5file.get_node(data['path']).
                                            _v_parent._f_get_child(
                                                utils.capitalize(
                                                    'y_axis')).read())

                                    dx = x_axis[1] - x_axis[0]
                                    dy = y_axis[1] - y_axis[0]
                                    im.setRect(
                                        QtCore.QRectF(
                                            np.min(x_axis), np.min(y_axis),
                                            np.max(x_axis) - np.min(x_axis) +
                                            dx,
                                            np.max(y_axis) - np.min(y_axis) +
                                            dy))
                                    if ind == 0:
                                        #im.setLookupTable(colors_red)
                                        self.viewer.histogram_red.setImageItem(
                                            im)
                                        if not self.viewer.histogram_red.isVisible(
                                        ):
                                            self.viewer.histogram_red.setVisible(
                                                True)
                                    elif ind == 1:
                                        #im.setLookupTable(colors_green)
                                        self.viewer.histogram_green.setImageItem(
                                            im)
                                        if not self.viewer.histogram_green.isVisible(
                                        ):
                                            self.viewer.histogram_green.setVisible(
                                                True)
                                    else:
                                        #im.setLookupTable(colors_blue)
                                        self.viewer.histogram_blue.setImageItem(
                                            im)
                                        if not self.viewer.histogram_blue.isVisible(
                                        ):
                                            self.viewer.histogram_blue.setVisible(
                                                True)

                                    self.overlays.append(
                                        dict(name='{:s}_{:03d}'.format(
                                            param.name(), ind),
                                             image=im))

                                    ind += 1
                            self.viewer.image_widget.view.autoRange()
                        except Exception as e:
                            self.update_status(utils.getLineInfo() + str(e),
                                               status_time=self.status_time,
                                               log_type='log')

                    else:
                        for overlay in self.overlays[:]:
                            if param.name() in overlay['name']:
                                ind = self.overlays.index(overlay)
                                self.viewer.image_widget.plotitem.removeItem(
                                    overlay['image'])
                                self.overlays.pop(ind)

            elif change == 'parent':
                for overlay in self.overlays[:]:
                    if param.name() in overlay['name']:
                        ind = self.overlays.index(overlay)
                        self.viewer.image_widget.plotitem.removeItem(
                            overlay['image'])
                        self.overlays.pop(ind)

    def setupUI(self):
        self.ui = QObject()
        layout = QtWidgets.QVBoxLayout()

        self.parent.setLayout(layout)
        sett_widget = QtWidgets.QWidget()
        self.sett_layout = QtWidgets.QHBoxLayout()
        sett_widget.setLayout(self.sett_layout)
        # creating a toolbar
        self.toolbar = QtWidgets.QToolBar()
        self.create_toolbar()
        layout.addWidget(self.toolbar)

        splitter = QtWidgets.QSplitter(Qt.Horizontal)
        layout.addWidget(splitter)

        #set viewer area
        widg = QtWidgets.QWidget()
        #self.viewer = Viewer2D(widg)
        self.viewer = Viewer2DBasic(widg)
        self.viewer.histogram_red.setVisible(False)
        self.viewer.histogram_green.setVisible(False)
        self.viewer.histogram_blue.setVisible(False)
        self.viewer.sig_double_clicked.connect(self.move_at)

        #displaying the scan list tree
        self.settings_tree = ParameterTree()
        #self.settings_tree.setMaximumWidth(300)
        self.settings_tree.setMinimumWidth(300)
        #self.settings_tree.setVisible(False)
        params_scan = [
            {
                'title':
                'Settings',
                'name':
                'settings',
                'type':
                'group',
                'children': [
                    {
                        'title': 'Load h5:',
                        'name': 'Load h5',
                        'type': 'action'
                    },
                    {
                        'title': 'h5 path:',
                        'name': 'filepath',
                        'type': 'str',
                        'value': '',
                        'readonly': True
                    },
                    {
                        'title': 'Load Image:',
                        'name': 'Load Image',
                        'type': 'action'
                    },
                    {
                        'title': 'Image path:',
                        'name': 'imagepath',
                        'type': 'str',
                        'value': '',
                        'readonly': True
                    },
                ]
            },
            {
                'title': 'Scans',
                'name': 'scans',
                'type': 'group',
                'children': []
            },
        ]
        self.settings = Parameter.create(name='settings',
                                         type='group',
                                         children=params_scan)
        self.settings_tree.setParameters(self.settings, showTop=False)
        self.settings.sigTreeStateChanged.connect(self.settings_changed)

        self.settings.child('settings',
                            'Load h5').sigActivated.connect(self.load_data)
        self.settings.child('settings',
                            'Load Image').sigActivated.connect(self.load_image)

        self.ui.statusbar = QtWidgets.QStatusBar()
        self.ui.statusbar.setMaximumHeight(25)
        layout.addWidget(self.ui.statusbar)
        self.ui.log_message = QtWidgets.QLabel('Initializing')
        self.ui.statusbar.addPermanentWidget(self.ui.log_message)

        self.sett_layout.addWidget(self.settings_tree)
        splitter.addWidget(sett_widget)
        splitter.addWidget(self.viewer.parent)

    def show_image(self, data):
        """

        Parameters
        ----------
        data: (dict) with keys 'names', 'data', 'x_axis', 'y_axis', 'pixmap2D'
        """

        if self.h5file is None:
            scan_path, current_filename, dataset_path = utils.set_current_scan_path(
                navigator_path,
                base_name='Scan',
                update_h5=True,
                next_scan_index=self.next_scan_index,
                create_scan_folder=False)
            self.h5file = tables.open_file(
                str(dataset_path.joinpath(dataset_path.name + ".h5")), 'w')
            h5group = self.h5file.root
            data2D_group = self.h5file.create_group(h5group, 'Data2D')
            data2D_group._v_attrs.type = 'data2D'
        else:
            scan_path, current_filename, dataset_path = utils.set_current_scan_path(
                navigator_path,
                base_name='Scan',
                update_h5=False,
                next_scan_index=self.next_scan_index,
                create_scan_folder=False)
            if not self.h5file.isopen:
                self.h5file = tables.open_file(
                    str(dataset_path.joinpath(dataset_path.name + ".h5")), 'a')
        self.next_scan_index += 1
        curr_group = self.h5file.create_group('/Data2D', current_filename)
        curr_group._v_attrs['pixmap2D'] = data['pixmap2D']

        xarray = self.h5file.create_array(curr_group,
                                          "scan_x_axis_unique",
                                          obj=data['x_axis'],
                                          title=current_filename)
        xarray.attrs['shape'] = xarray.shape
        xarray.attrs['type'] = 'signal_axis'
        xarray.attrs['data_type'] = '1D'

        yarray = self.h5file.create_array(curr_group,
                                          "scan_y_axis_unique",
                                          obj=data['y_axis'],
                                          title=current_filename)
        yarray.attrs['shape'] = yarray.shape
        yarray.attrs['type'] = 'signal_axis'
        yarray.attrs['data_type'] = '1D'

        for ind_channel, name in enumerate(data['names']):
            try:
                channel_group = self.h5file.create_group(curr_group, name)
                channel_group._v_attrs.Channel_name = name
                array = self.h5file.create_carray(
                    channel_group,
                    current_filename + '_' + name,
                    obj=data['data'][ind_channel],
                    title='data',
                    filters=self.filters)
                array.attrs['type'] = 'data'
                array.attrs['data_type'] = '0D'
                array.attrs['data_name'] = name
                array.attrs['shape'] = data['data'][ind_channel].shape
                array.attrs['scan_type'] = 'Scan2D'
            except Exception as e:
                self.update_status(utils.getLineInfo() + str(e),
                                   status_time=self.status_time,
                                   log_type='log')

        self.update_2Dscans()

    def update_2Dscans(self):
        try:
            if not self.h5file.isopen:
                self.h5file = tables.open_file(self.h5file.filename, 'a')
            scans = utils.get_h5file_scans(self.h5file)
            #settings=[dict(scan_name=node._v_name,path=node._v_pathname, pixmap=nparray2Qpixmap(node.read()))),...]
            params = []
            children = [
                child.name()
                for child in self.settings.child(('scans')).children()
            ]
            for scan in scans:
                if scan['scan_name'] not in children:
                    params.append({
                        'name':
                        scan['scan_name'],
                        'type':
                        'pixmap_check',
                        'value':
                        dict(data=scan['data'],
                             checked=False,
                             path=scan['path'])
                    })
            self.settings.child(('scans')).addChildren(params)

            for child in self.settings.child(('scans')).children():
                if child.name() not in children:
                    val = child.value()
                    val.update(dict(checked=True))
                    child.setValue(val)
                    child.sigValueChanged.emit(child, child.value())

        except Exception as e:
            self.update_status(utils.getLineInfo() + str(e),
                               status_time=self.status_time,
                               log_type='log')

    def update_h5file(self, h5file):
        self.h5file = h5file
        self.update_2Dscans()

    def update_status(self, txt, status_time=0, log_type=None):
        """
            Show the txt message in the status bar with a delay of status_time ms.

            =============== =========== =======================
            **Parameters**    **Type**    **Description**
            *txt*             string      The message to show
            *status_time*       int         the delay of showing
            *log_type*        string      the type of the log
            =============== =========== =======================
        """
        try:
            self.ui.statusbar.showMessage(txt, status_time)
            if log_type is not None:
                self.log_signal.emit(self.title + ': ' + txt)
        except Exception as e:
            pass
Example #31
0
class SmallData(object):
    def __init__(self, parent=None):
        self.parent = parent

        ## Dock: Quantifier
        self.dock = Dock("Small Data", size=(100, 100))
        self.win = ParameterTree()
        self.dock.addWidget(self.win)
        self.winL = pg.LayoutWidget()
        self.refreshBtn = QtGui.QPushButton('Refresh')
        self.winL.addWidget(self.refreshBtn, row=0, col=0)
        self.peakogramBtn = QtGui.QPushButton('Peakogram')
        self.winL.addWidget(self.peakogramBtn, row=0, col=1)
        self.dock.addWidget(self.winL)
        # Add plot
        self.winP = pg.PlotWidget(title="Metric")
        self.dock.addWidget(self.winP)

        # Quantifier parameter tree
        self.quantifier_grp = 'Small data'
        self.quantifier_filename_str = 'filename'
        self.quantifier_dataset_str = 'dataset'
        self.quantifier_sort_str = 'sort'

        # Quantifier
        self.quantifier_filename = ''
        self.quantifier_dataset = '/entry_1/result_1/'
        self.quantifier_sort = False
        self.quantifierFileOpen = False
        self.quantifierHasData = False

        self.params = [
            {
                'name':
                self.quantifier_grp,
                'type':
                'group',
                'children': [
                    {
                        'name': self.quantifier_filename_str,
                        'type': 'str',
                        'value': self.quantifier_filename,
                        'tip': "Full path Hdf5 filename"
                    },
                    {
                        'name': self.quantifier_dataset_str,
                        'type': 'str',
                        'value': self.quantifier_dataset,
                        'tip': "Hdf5 dataset metric, nPeaksAll or nHitsAll"
                    },
                    {
                        'name': self.quantifier_sort_str,
                        'type': 'bool',
                        'value': self.quantifier_sort,
                        'tip': "Descending sort metric"
                    },
                ]
            },
        ]

        self.pSmall = Parameter.create(name='paramsQuantifier', type='group', \
                                       children=self.params, expanded=True)
        self.win.setParameters(self.pSmall, showTop=False)
        self.pSmall.sigTreeStateChanged.connect(self.change)
        if using_pyqt4:
            self.parent.connect(self.refreshBtn, QtCore.SIGNAL("clicked()"),
                                self.reloadQuantifier)
            self.parent.connect(self.peakogramBtn, QtCore.SIGNAL("clicked()"),
                                self.showPeakogram)
        else:
            self.refreshBtn.clicked.connect(self.reloadQuantifier)
            self.peakogramBtn.clicked.connect(self.showPeakogram)

    # 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.quantifier_grp:
            if path[1] == self.quantifier_filename_str:
                self.updateQuantifierFilename(data)
            elif path[1] == self.quantifier_dataset_str:
                self.updateQuantifierDataset(data)
            elif path[1] == self.quantifier_sort_str:
                self.updateQuantifierSort(data)

    ##################################
    ########### Quantifier ###########
    ##################################

    def reloadQuantifier(self):
        self.updateQuantifierFilename(self.quantifier_filename)
        self.updateQuantifierDataset(self.quantifier_dataset)

    def updateQuantifierFilename(self, data):
        self.quantifier_filename = data
        if self.parent.args.v >= 1: print "Done opening metric"

    def updateQuantifierDataset(self, data):
        self.quantifier_dataset = data
        if os.path.isfile(self.quantifier_filename):
            try:
                self.quantifierFile = h5py.File(self.quantifier_filename, 'r')
                self.quantifierMetric = self.quantifierFile[
                    self.quantifier_dataset].value
                try:
                    if self.quantifier_dataset[
                            0] == '/':  # dataset starts with "/"
                        self.quantifier_eventDataset = self.quantifier_dataset.split(
                            "/")[1] + "/event"
                    else:  # dataset does not start with "/"
                        self.quantifier_eventDataset = "/" + self.quantifier_dataset.split(
                            "/")[0] + "/event"
                    self.quantifierEvent = self.quantifierFile[
                        self.quantifier_eventDataset].value
                except:
                    if self.parent.args.v >= 1:
                        print "Couldn't find /event dataset"
                    self.quantifierEvent = np.arange(len(
                        self.quantifierMetric))
                self.quantifierFile.close()
                self.quantifierInd = np.arange(len(self.quantifierMetric))
                self.updateQuantifierSort(self.quantifier_sort)
            except:
                print "Couldn't read metric"
            if self.parent.args.v >= 1: print "Done reading metric"

    def updateQuantifierSort(self, data):
        self.quantifier_sort = data
        try:
            if self.quantifier_sort is True:
                self.quantifierIndSorted = np.argsort(
                    self.quantifierMetric)[::-1]
                self.quantifierMetricSorted = self.quantifierMetric[
                    self.quantifierIndSorted]
                #self.quantifierEventSorted = self.quantifierMetric[self.quantifierInd]
                self.updateQuantifierPlot(self.quantifierMetricSorted)
            else:
                self.updateQuantifierPlot(self.quantifierMetric)
        except:
            print "Couldn't sort data"
            pass

    def updateQuantifierPlot(self, metric):
        self.winP.getPlotItem().clear()
        if len(np.where(metric == -1)[0]) > 0:
            self.curve = self.winP.plot(metric,
                                        pen=(200, 200, 200),
                                        symbolBrush=(255, 0, 0),
                                        symbolPen='k')  # red
        else:  # Every event was processed
            self.curve = self.winP.plot(metric,
                                        pen=(200, 200, 200),
                                        symbolBrush=(0, 0, 255),
                                        symbolPen='k')  # blue
        self.winP.setLabel('left', "Small data")
        if self.quantifier_sort:
            self.winP.setLabel('bottom', "Sorted Event Index")
        else:
            self.winP.setLabel('bottom', "Event Index")
        self.curve.curve.setClickable(True)
        self.curve.sigClicked.connect(self.clicked)

    def clicked(self, points):
        with pg.BusyCursor():
            if self.parent.args.v >= 1:
                print("curve clicked", points)
                from pprint import pprint
                pprint(vars(points.scatter))
            for i in range(len(points.scatter.data)):
                if points.scatter.ptsClicked[0] == points.scatter.data[i][7]:
                    ind = i
                    break
            indX = points.scatter.data[i][0]
            indY = points.scatter.data[i][1]
            if self.parent.args.v >= 1: print "x,y: ", indX, indY
            if self.quantifier_sort:
                ind = self.quantifierIndSorted[ind]

            if self.parent.eventNumber != self.quantifierEvent[ind]:
                self.parent.eventNumber = self.quantifierEvent[ind]
                self.parent.calib, self.parent.data = self.parent.img.getDetImage(
                    self.parent.eventNumber)
                self.parent.img.win.setImage(self.parent.data,
                                             autoRange=False,
                                             autoLevels=False,
                                             autoHistogramRange=False)
                self.parent.exp.p.param(self.parent.exp.exp_grp,
                                        self.parent.exp.exp_evt_str).setValue(
                                            self.parent.eventNumber)

    def showPeakogram(self):
        if os.path.isfile(self.quantifier_filename):
            cmd = "peakogram -i " + self.quantifier_filename
            subprocess.Popen(cmd,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             shell=True)
Example #32
0
    global comboBox
    comboBox.clear()
    szn_lst = sorted(szn.list_commands(str(comboBox4.currentText())))
    for szne in szn_lst:
        comboBox.addItem(szne)    

win = QtGui.QWidget()

t = ParameterTree()
#sz=Szenen_tree("Alles_ein")
inp=InputsTree(isInputs = True, inputsGroup = 'V00')

#t.setParameters(sz.p, showTop=False)
#t.setWindowTitle('Szenen Setup:')
t2 = ParameterTree()
t2.setParameters(inp.p, showTop=False)
t3 = ParameterTree()
cmds=InputsTree(isInputs = False, cmdTable = cmd_lsts[0])
#t3.setParameters(cmds.p, showTop=False)

t4 = ParameterTree()
#seTre = SettingsTree()
#t4.setParameters(seTre.p, showTop=False)


inp.p.sigTreeStateChanged.connect(change)

layout = QtGui.QGridLayout()
win.setLayout(layout)
comboBox = QtGui.QComboBox(win)
comboBox.setMaxVisibleItems(50)    
Example #33
0
class MolViewer(QtGui.QMainWindow):
    '''The application main window.'''

    def __init__(self, parent=None):
        # We're not calling the super method so we can span an new instance in
        # the new function.
        # However, when the first created window is closed, all windoes close
        # super(MolViewer, self).__init__()
        QtGui.QMainWindow.__init__(self, parent)
        self.mol = None
        self.initUI()

    def initToolBar(self):
        '''The main toolbar.'''
        # File actions
        self.newAction = QtGui.QAction(QtGui.QIcon('../icons/new.png'), '&New', self)
        self.newAction.setStatusTip('New molecule viewer')
        self.newAction.setShortcut('Ctrl+N')
        self.newAction.triggered.connect(self.new)

        self.openAction = QtGui.QAction(QtGui.QIcon('../icons/open.png'), '&Open', self)
        self.openAction.setStatusTip('Read molecule from file')
        self.openAction.setShortcut('Ctrl+O')
        self.openAction.triggered.connect(self.open)

        self.saveAction = QtGui.QAction(QtGui.QIcon('../icons/save.png'), '&Save', self)
        self.saveAction.setStatusTip('Write molecule to file')
        self.saveAction.setShortcut('Ctrl+S')
        self.saveAction.triggered.connect(self.save)

        self.saveasAction = QtGui.QAction(QtGui.QIcon.fromTheme('document-save-as'), '&Save as...', self)
        self.saveasAction.setStatusTip('Write molecule to file')
        self.saveasAction.setShortcut('Ctrl+Shift+S')
        self.saveasAction.triggered.connect(self.saveas)

        self.saveimageAction = QtGui.QAction(QtGui.QIcon('../icons/picture-edit.png'), 'Save &image as PNG', self)
        self.saveimageAction.setStatusTip('Save image as PNG')
        self.saveimageAction.setShortcut('Ctrl+I')
        self.saveimageAction.triggered.connect(self.saveimage)

        self.exitAction = QtGui.QAction(QtGui.QIcon('../icons/exit.png'), '&Exit', self)
        self.exitAction.setShortcut('Ctrl+Q')
        self.exitAction.setStatusTip('Exit application')
        self.exitAction.triggered.connect(QtGui.qApp.quit)

        # Edit actions
        self.clearAction = QtGui.QAction(QtGui.QIcon('../icons/clear.png'), 'Clea&r', self)
        self.clearAction.setShortcut('Ctrl+R')
        self.clearAction.setStatusTip('Remove molecule from viewer')
        self.clearAction.triggered.connect(self.clear)

        self.preferencesAction = QtGui.QAction(QtGui.QIcon('../icons/preferences.png'), '&Options', self)
        self.preferencesAction.setStatusTip('Edit Preferences')
        # self.preferencesAction.setShortcut()
        self.preferencesAction.triggered.connect(self.editpreferences)

        # View actions
        self.fullScreenAction = QtGui.QAction(QtGui.QIcon('../icons/fullscreen.png'), '&Full Screen', self)
        self.fullScreenAction.setStatusTip('Toggle full screen')
        self.fullScreenAction.setShortcut('F11')
        self.fullScreenAction.triggered.connect(self.fullscreen)

        self.setwindowsizeAction = QtGui.QAction(QtGui.QIcon('../icons/fullscreen.png'), '&Set Geometry', self)
        self.setwindowsizeAction.setStatusTip('Set height and width of main window')
        self.setwindowsizeAction.setShortcut('F12')
        self.setwindowsizeAction.triggered.connect(self.setwindowsize)

        # Molecule action
        self.getbynameAction = QtGui.QAction(QtGui.QIcon('../icons/find.png'), '&Get molecule by name or CAS number', self)
        self.getbynameAction.setStatusTip('Get a molecule by name or CAS number')
        self.getbynameAction.setShortcut('Ctrl+G')
        self.getbynameAction.triggered.connect(self.getbyname)

        self.distmatAction = QtGui.QAction(QtGui.QIcon('../icons/table.png'), '&Distance matrix', self)
        self.distmatAction.setShortcut('Ctrl+D')
        self.distmatAction.triggered.connect(self.distmatWindow)

        self.infoAction = QtGui.QAction(QtGui.QIcon('../icons/info.png'), '&Information', self)
        self.infoAction.setStatusTip('Show basic information about molecule')
        self.infoAction.setShortcut('Ctrl+I')
        self.infoAction.triggered.connect(self.info)

        # Spectrum action
        self.showspectrumAction = QtGui.QAction(QtGui.QIcon('../icons/spectrum.png'), '&Spectrum', self)
        self.showspectrumAction.setStatusTip('Show spectrum')
        self.showspectrumAction.triggered.connect(self.showspectrum)

        # About action
        self.aboutAction = QtGui.QAction(QtGui.QIcon('../icons/spectrum.png'), '&About', self)
        self.aboutAction.setStatusTip('Show the about dialog')
        self.aboutAction.triggered.connect(self.about)

        # Toolbars
        self.filetoolbar = self.addToolBar('File')
        self.filetoolbar.addAction(self.newAction)
        self.filetoolbar.addAction(self.openAction)
        self.filetoolbar.addAction(self.saveAction)
        # self.filetoolbar.addAction(self.saveasAction)
        self.filetoolbar.addAction(self.saveimageAction)

        self.edittoolbar = self.addToolBar('Edit')
        self.edittoolbar.addAction(self.preferencesAction)
        self.edittoolbar.addAction(self.clearAction)

        self.viewtoolbar = self.addToolBar('View')
        self.viewtoolbar.addAction(self.fullScreenAction)

        self.moleculetoolbar = self.addToolBar('Molecule')
        self.moleculetoolbar.addAction(self.getbynameAction)
        self.moleculetoolbar.addAction(self.distmatAction)
        self.moleculetoolbar.addAction(self.infoAction)

        self.spectrumtoolbar = self.addToolBar('Spectrum')
        self.spectrumtoolbar.addAction(self.showspectrumAction)

    def initMenuBar(self):
        '''The main menubar.'''
        menubar = self.menuBar()
        menubar.setNativeMenuBar(True)

        # Create menus
        file = menubar.addMenu('&File')
        edit = menubar.addMenu('&Edit')
        view = menubar.addMenu('&View')
        molmenu = menubar.addMenu('&Molecule')
        spectrummenu = menubar.addMenu('&Spectrum')
        aboutmenu = menubar.addMenu('&About')

        # File menu
        file.addAction(self.newAction)
        file.addAction(self.openAction)
        file.addAction(self.saveAction)
        file.addAction(self.saveasAction)
        file.addAction(self.saveimageAction)
        file.addSeparator()
        file.addAction(self.exitAction)

        # Edit menu
        edit.addAction(self.clearAction)
        edit.addSeparator()
        edit.addAction(self.preferencesAction)

        # View menu
        view.addAction(self.fullScreenAction)
        view.addAction(self.setwindowsizeAction)

        # Molecule menu
        molmenu.addAction(self.getbynameAction)
        molmenu.addSeparator()
        molmenu.addAction(self.distmatAction)
        molmenu.addAction(self.infoAction)

        # Spectrum menu
        spectrummenu.addAction(self.showspectrumAction)

        # About menu
        aboutmenu.addAction(self.aboutAction)

    def initUI(self):
        '''Initializes the main window widgets.'''
        self.initToolBar()
        self.initMenuBar()

        self.parametertree = ParameterTree()
        self.viewwidget = gl.GLViewWidget()

        widget = QtGui.QWidget()
        hbox = QtGui.QHBoxLayout(widget)
        hbox.addWidget(self.parametertree)
        hbox.addWidget(self.viewwidget, 1)

        self.setCentralWidget(widget)
        self.resize(1200, 600)
        self.setWindowTitle('MolViewer :: Main window')
        self.drawgrid()
        self.show()

    def distmatWindow(self):
        '''Shows the distance matrix window.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information', 'No molecule loaded')
        self.matrixtable = TableWindow(parent=self, mol=self.mol, kind='distance')
        self.matrixtable.show()

    def _open(self, mol):
        '''Draws a new molecule

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        self.mol = mol
        self.clearview()
        self.drawmolecule(mol)
        self.drawgrid()
        self.setWindowTitle('MolViewer :: Main window :: {:s}'.format(self.mol.filename))

    def open(self):
        '''Open a new molecule using the file dialog.'''
        filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', './xyz', '*.*;; *.xyz;; *.mol;; *.sdf')
        if filename:
            mol = read_xyz(filename)
            self._open(mol)

    def new(self):
        '''Spawns a new main window.'''
        spawn = MolViewer(self)
        spawn.show()

    def saveas(self):
        '''Save a molecule to file with a new filename.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information', 'No molecule to saves')
        else:
            filename = QtGui.QFileDialog.getSaveFileName(self, 'Save file as', './molecules/xyz', '*.xyz')
            if filename:
                write_xyz(self.mol, filename)

    def save(self):
        '''Save the molecule to file.'''
        if self.mol and not self.mol.filename:
            self.saveas()
        elif self.mol and self.mol.filename:
            write_xyz(self.mol, self.mol.filename)

    def saveimage(self):
        '''Saves the viewwidget as a png image.'''
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save image as PNG', '', '*.png')
        img = self.viewwidget.readQImage()
        # print('Writing image {:s}'.format(filename), end=' ')
        img.save(filename, 'png', 100)
        print('Done')

    def fullscreen(self):
        '''Toggle full screen window.'''
        if self.windowState() & QtCore.Qt.WindowFullScreen:
            self.showNormal()
        else:
            self.showFullScreen()

    def setwindowsize(self):
        '''Set the window to specified size.'''
        width, ok = QtGui.QInputDialog.getText(self, 'Set width', 'Enter window width in pixels:')
        height, ok = QtGui.QInputDialog.getText(self, 'Set height', 'Enter window height in pixels:')
        self.resize(int(width), int(height))

    def editpreferences(self):
        '''Opens the preferences dialog.'''
        dlg = OptionsDialog(self)
        dlg.exec_()

    def getbyname(self):
        '''Displays the input dialog to find a molecule by its identifier.'''
        text, ok = QtGui.QInputDialog.getText(
            self, 'Get molecule by name or CAS number', 'Enter molecule name or CAS number:')
        if ok:
            if isinstance(text, str) and len(text) > 0:
                mol = get_mol_by_name(text)
                if mol:
                    self._open(mol)
                else:
                    QtGui.QMessageBox.information(self, 'Information', 'Molecule not found')

    def drawmolecule(self, mol):
        '''Creates the polygons to draw the molecule to the viewwidget.

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        self.viewwidget.setCameraPosition(distance=10)
        self.drawatoms(mol)
        self.drawbonds(mol)
        self.setparameter(mol)

    def drawatoms(self, mol):
        '''Draw the atoms.

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        scale = 0.25
        rows = 16
        cols = 16
        shader = 'shaded'
        smooth = True

        for atom in mol.atoms:
            radius = atom.radius() * scale
            pos = atom.r
            md = gl.MeshData.sphere(rows=rows, cols=cols, radius=radius)
            m = gl.GLMeshItem(meshdata=md, smooth=smooth, shader=shader)
            colors = np.ones((md.faceCount(), 4), dtype=float)
            rgb = atom.color()
            colors[:, 0] = rgb[0]  # r
            colors[:, 1] = rgb[1]  # g
            colors[:, 2] = rgb[2]  # b
            colors[:, 3] = 1.0     # a
            md.setFaceColors(colors)
            m.translate(pos[0], pos[1], pos[2])
            self.viewwidget.addItem(m)

    def drawbonds(self, mol):
        '''Draw the bonds.

        :param molecule: The molecule for which to show the bonds.
        :type molecule: molecule.Molecule

        '''
        rows = 16
        cols = 16
        shader = 'shaded'
        smooth = True
        bond_radius = [0.1, 0.1]
        draw_edges = False
        edge_color = (0, 0, 0, 1)
        z = np.asarray([0, 0, 1])
        for bond in mol.bonds():
            vec = bond.p1 - bond.p2
            angle = angle_between_vectors(vec, z) * 180 / np.pi
            axis = np.cross(z, vec)
            md = gl.MeshData.cylinder(rows=rows, cols=cols, radius=bond_radius, length=bond.length())
            m = gl.GLMeshItem(meshdata=md, smooth=smooth, drawEdges=draw_edges, edgeColor=edge_color, shader=shader)
            colors = np.ones((md.faceCount(), 4), dtype=float)
            rgb = bond.atoms[0].color()
            colors[:, 0] = rgb[0]
            colors[:, 1] = rgb[1]
            colors[:, 2] = rgb[2]
            colors[:, 3] = 1.0
            md.setFaceColors(colors)
            m.rotate(angle, axis[0], axis[1], axis[2])
            m.translate(bond.p2[0], bond.p2[1], bond.p2[2])
            self.viewwidget.addItem(m)

    def drawgrid(self):
        '''Show a grid in x,y,z planes.'''
        # gx = gl.GLGridItem()
        # gx.rotate(90, 0, 1, 0)
        # w.addItem(gx)
        # gy = gl.GLGridItem()
        # gy.rotate(90, 1, 0, 0)
        # w.addItem(gy)
        gz = gl.GLGridItem()
        self.viewwidget.addItem(gz)

    def clearview(self):
        '''Removes all items from ViewWidget.'''
        # Not all items are removed in one loop. Why?
        while len(self.viewwidget.items) > 0:
            for i in self.viewwidget.items:
                self.viewwidget.removeItem(i)

    def clear(self):
        '''Clears the viewwidget and deletes the molecule.'''
        self.clearview()
        self.mol = None

    def info(self):
        '''Shows a info box with basic infoemation about the molecule.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information', 'No molecule loaded')
        self.infotree = TreeWindow(parent=self, mol=self.mol)
        self.infotree.show()

    def showspectrum(self):
        win = SpectrumWindow(self)
        win.show()

    def about(self):
        dlg = AboutDialog(self)
        dlg.exec_()

    def setparameter(self, mol):
            params = [
                {'name': mol.name, 'type': 'group', 'children': [
                    {'name': 'File', 'type': 'str', 'value': mol.filename, 'readonly': True},
                    {'name': 'Formula', 'type': 'str', 'value': mol.stoichiometry(), 'readonly': True},
                    {'name': 'Mass', 'type': 'float', 'value': mol.mass(), 'readonly': True},
                    {'name': 'Electrons', 'type': 'int', 'value': mol.nel(), 'readonly': True},
                    {'name': 'Charge', 'type': 'float', 'value': mol.charge, 'readonly': True}]
                }]

            p = Parameter.create(name='Molecule', type='group', children=params)
            self.parametertree.setParameters(p, showTop=True)
Example #34
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)
    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) )
Example #36
0
        #if path is not None:
            #paramName = '.'.join(path)
        #else:
        paramName = param.name()
        print('  parameter: %s'% paramName)
        print('  changeType:    %s'% changeType)
        print('  data:      %s'% str(newVal))
        print('  ----------')
    if changeType=='value':
        sendCommand(paramName, str(newVal)) 
    if changeType=='activated':
        sendCommand(paramName)#, str(newVal)) 

p.sigTreeStateChanged.connect(change)
paramTree = ParameterTree()
paramTree.setParameters(p, showTop=False)
d1a.addWidget(paramTree)

r=re.compile('[: ,]+'); # Regex to match any sequence of colons, 
                #spaces, or commas as seperators in communications from the arduino.

def readAndProcessArd():
    global w2; #Scroll area widget
    lines=[]
    #while ardPort.inWaiting():
        
    while ardPort.inWaiting():
        line=ardPort.readline()
        line=line.strip().strip(',')
        line=line.strip()
        lines.append(line)
Example #37
0
class BiquadDesigner(QtGui.QMainWindow):
    def __init__(self):
        super().__init__()
        self._colors = [
            '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b',
            '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'
        ]
        self._color_index = 0

        self.last_folder = os.getcwd()

        self.filter_parameters = FilterCascadeParameter(
            name='Filter Cascade',
            children=[
                BiquadParameter(name="Biquad 1",
                                removable=True,
                                renamable=True)
            ])

        self.parameter_tree = ParameterTree()
        self.parameter_tree.setParameters(self.filter_parameters, showTop=True)

        self.plot_widget = pyqtgraph.PlotWidget()
        self.plot = self.plot_widget.getPlotItem()
        self.plot.setTitle("Magnitude response")
        self.plot.setLabel("bottom", "Frequency", "Hz")
        self.plot.setXRange(20, SAMPLERATE / 2)
        self.plot.showGrid(x=True, y=True)
        self.plot.addLegend()

        self.normalized_frequencies = np.linspace(1 / NPOINTS, 0.5, NPOINTS)
        magnitude = np.ones(self.normalized_frequencies.shape)
        self.total_response_magnitude = self.plot.plot(
            x=self.normalized_frequencies * SAMPLERATE,
            y=magnitude,
            name="Total",
            pen=self.get_next_pen())

        toolbar = self.get_main_toolbar()

        self.addToolBar(toolbar)

        parameters_dock = QtWidgets.QDockWidget("Parameters", parent=self)
        parameters_dock.setFeatures(
            QtWidgets.QDockWidget.DockWidgetMovable
            | QtWidgets.QDockWidget.DockWidgetFloatable)
        parameters_dock.setWidget(self.parameter_tree)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, parameters_dock)

        curve_widget = DataCurveListWidget(self.plot)
        curve_dock = QtGui.QDockWidget("Curves", parent=self)
        curve_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable
                               | QtWidgets.QDockWidget.DockWidgetFloatable)
        curve_dock.setWidget(curve_widget)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, curve_dock)

        self.setCentralWidget(self.plot_widget)
        self.update_frequency_response()
        self.resize(800, 800)
        self.show()
        self.filter_parameters.coefficients_changed.connect(
            self.update_frequency_response)

    def get_main_toolbar(self):
        toolbar = QtWidgets.QToolBar("Main toolbar")

        open_button = QtWidgets.QAction("Open", self)
        open_button.triggered.connect(self.reload_state)
        toolbar.addAction(open_button)

        save_button = QtWidgets.QAction("Save", self)
        save_button.triggered.connect(self.save_state)
        toolbar.addAction(save_button)

        save_button = QtWidgets.QAction("Save SOS", self)
        save_button.triggered.connect(self.save_sos_coefficients)
        toolbar.addAction(save_button)

        refresh_button = QtWidgets.QAction("Refresh", self)
        refresh_button.triggered.connect(self.update_frequency_response)
        toolbar.addAction(refresh_button)
        return toolbar

    def get_next_pen(self):
        c = self._colors[self._color_index]
        self._color_index = (self._color_index + 1) % len(self._colors)
        return pyqtgraph.mkPen(c)

    def update_frequency_response(self):
        self.sos = self.get_second_order_sections()
        w, h = signal.sosfreqz(self.sos,
                               self.normalized_frequencies * np.pi * 2)
        magnitude = np.abs(h)
        self.total_response_magnitude.setData(x=self.normalized_frequencies *
                                              SAMPLERATE,
                                              y=magnitude)

    def get_second_order_sections(self):
        sos = []
        for f in self.filter_parameters:
            if hasattr(f, "sos"):
                sos.append(f.sos)
        if len(sos) == 0:
            sos = [[1, 0, 0, 1, 0, 0]]
        return np.vstack(sos)

    def update_last_folder(self, filename):
        self.last_folder = os.path.dirname(filename)

    def save_sos_coefficients(self):
        def textproto_sos_save(filename, data):
            if data.shape[1] != 6:
                raise TypeError("All sections should be 6 coefficients")
            with open(filename, "w") as fid:
                for section in data:
                    fid.write(
                        "biquad: {{b0: {0:.6e} b1: {1:.6e} b2: {2:.6e} a1: {4:.6e} a2: {5:.6e} }}\n"
                        .format(*section))

        filters = {
            "Data files (*.txt)":
            lambda filename, data: np.savetxt(
                filename, data, header="# Second order secions coefficients"),
            "Textproto (*.textproto)":
            textproto_sos_save,
        }
        sos_filename, file_type = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save SOS', self.last_folder, ';;'.join(filters.keys()))
        self.update_last_folder(sos_filename)
        if sos_filename == "":
            return
        sos = self.get_second_order_sections()
        save_method = filters[file_type]
        save_method(sos_filename, sos)

    def save_state(self):
        logging.warning('Not yet implemented')

    def reload_state(self):
        logging.warning('Not yet implemented')
Example #38
0
#    cap.set(CV_CAP_PROP_SETTINGS,1)
#    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.param("Camera").sigTreeStateChanged.connect(cchange)

wParams = ParameterTree()
wParams.setParameters(p, showTop=False)

d3.addWidget(wParams)

##############################################################################
## data tree
d = {}
tree = pg.DataTreeWidget(data=d)
dp2.addWidget(tree)

##############################################################################
##image
imv = pg.ImageView()
d1.addWidget(imv)
import scipy
vsize=(1280, 1024)
Example #39
0
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()
Example #40
0
 def widget(self):
     widget = ParameterTree()
     widget.setParameters(self, showTop=False)
     return widget
Example #41
0
class DBMonitor(QWidget):
    """
    DBMonitor is a grid of QWidgets, displayed in a tab of CAGEMonitor.
    Available data streams are "endpoints": mj60_baseline, cage_pressure, etc.
    TODO: add moveable cross hairs, check the crosshair.py example
    TODO: multiple endpoint view.
    since endpoints have different units and y-ranges, let's make it s/t each
    box that's checked in `Endpoint Select' gets its OWN plot, and the
    QGridLayout is automatically re-organized to fit more and more plots in
    column 1, every time the user hits "Query DB".
    """
    def __init__(self):
        super().__init__()

        print("Connecting to DB ...")

        # establish a postgres connection
        with open("config.json") as f:
            self.config = json.load(f)

        self.connection = psycopg2.connect(host=self.config["cage_daq"],
                                           dbname=self.config["db_name"],
                                           user=self.config["db_user"],
                                           password=self.config["password"])
        self.cursor = self.connection.cursor()

        # get a list of all available endpoints in the DB
        self.cursor.execute("SELECT * FROM endpoint_id_map;")

        self.endpt_types = {}
        for rec in self.cursor.fetchall():
            self.endpt_types[rec[1]] = rec[2]
        self.endpt_list = [key for key in self.endpt_types]

        self.endpts_enabled = []
        for endpt in self.endpt_types:
            self.endpts_enabled.append({
                'name': endpt,
                'type': 'bool',
                'value': False
            })

        # set the default endpoints
        # ['cage_pressure', 'cage_coldPlate_temp', 'cage_topHat_temp', 'cage_motor_temp',
        # 'cage_ln_level', 'cage_baseline', 'cage_hv_vmon']
        self.endpts_enabled[10]['value'] = True
        self.endpts_enabled[11]['value'] = True
        self.endpts_enabled[12]['value'] = True
        self.endpts_enabled[13]['value'] = True
        self.endpts_enabled[14]['value'] = True
        self.endpts_enabled[16]['value'] = True
        self.endpts_enabled[17]['value'] = True

        # default time window
        self.t_later = datetime.utcnow()
        self.t_earlier = datetime.utcnow() - timedelta(hours=0.5)

        # create a parameter tree widget from the DB endpoints
        pt_initial = [{
            'name':
            'Run Query',
            'type':
            'group',
            'children': [{
                'name': 'Date (earlier)',
                'type': 'str',
                'value': self.t_earlier.isoformat()
            }, {
                'name': 'Date (later)',
                'type': 'str',
                'value': "now"
            }, {
                'name': 'Query DB',
                'type': 'action'
            }]
        }, {
            'name': 'Endpoint Select',
            'type': 'group',
            'children': self.endpts_enabled
        }]
        self.p = Parameter.create(name='params',
                                  type='group',
                                  children=pt_initial)
        self.pt = ParameterTree()
        self.pt.setParameters(self.p, showTop=False)

        # connect a simple function
        self.p.sigTreeStateChanged.connect(self.tree_change)

        # ---- PLOTTING ----
        # reinitialize the plot when the user clicks the "Query DB" button.
        self.rp = RabbitPlot(self.endpts_enabled, self.t_earlier, self.t_later,
                             self.cursor)
        self.p.param('Run Query',
                     'Query DB').sigActivated.connect(self.update_plot)

        # ---- LAYOUT ----
        # https://doc.qt.io/archives/qt-4.8/qgridlayout.html#public-functions
        # NOTE: addWidget(widget, fromRow, fromColumn, rowSpan, columnSpan)
        self.layout = QGridLayout(self)
        self.setLayout(self.layout)
        self.layout.setColumnStretch(0, 2)  # stretch column 0 by 2
        self.layout.setColumnStretch(1, 5)
        self.layout.addWidget(self.pt, 0, 0)
        self.layout.addWidget(self.rp, 0, 1)
        self.show()

    def tree_change(self, param, changes):
        """
        watch for changes in the ParameterTree and update self variables
        """
        for param, change, data in changes:
            path = self.p.childPath(param)
            child_name = '.'.join(path) if path is not None else param.name()

            print(f'  parameter: {child_name}')
            print(f'  change:    {change}')
            print(f'  data:      {data}')

            if child_name == "Run Query.Date (earlier)":
                self.t_earlier = str(data)

            if child_name == "Run Query.Date (later)":
                self.t_later = str(data)

            if "Endpoint Select" in path:
                for i, ept in enumerate(self.endpt_list):
                    if path[-1] == ept:
                        self.endpts_enabled[i]['value'] = data

    def update_plot(self):
        """
        """
        print('got to here')
        self.layout.removeWidget(self.rp)
        self.rp.deleteLater()
        self.rp = RabbitPlot(self.endpts_enabled, self.t_earlier, self.t_later,
                             self.cursor)
        print('made rabbit plot')
        self.layout.addWidget(self.rp, 0, 1)
        self.show()

    def update_rp(self, *args):
        """
        called by the main thread's listener function
        """
        # print(args)
        self.rp.update_data(*args)
Example #42
0
class H5Saver(QObject):
    """QObject containing all methods in order to save datas in a *hdf5 file* with a hierachy compatible with
    the H5Browser. The saving parameters are contained within a **Parameter** object: self.settings that can be displayed
    on a UI (see :numref:`other_settings`) using the widget self.settings_tree. At the creation of a new file, a node
    group named **Raw_datas** and represented by the attribute ``raw_group`` is created and set with a metadata attribute:

    * 'type' given by the **save_type** class parameter

    The root group of the file is then set with a few metadata:

    * 'pymodaq_version' the current pymodaq version, e.g. 1.6.2
    * 'file' the file name
    * 'date' the current date
    * 'time' the current time

    All datas will then be saved under this node in various groups

    See Also
    --------
    H5Browser

    Parameters
    ----------
    h5_file: pytables hdf5 file
             object used to save all datas and metadas

    h5_file_path: str or Path
                  pyqtSignal signal represented by a float. Is emitted each time the hardware reached the target
                  position within the epsilon precision (see comon_parameters variable)

    save_type: str
               an element of the list module attribute save_types = ['scan', 'detector', 'custom']
               * 'scan' is used for DAQ_Scan module and should be used for similar application
               * 'detector' is used for DAQ_Viewer module and should be used for similar application
               * 'custom' should be used for customized applications

    Attributes
    ----------
    status_sig: pyqtSignal
                emits a signal of type Threadcommand in order to senf log information to a main UI
    new_file_sig: pyqtSignal
                  emits a boolean signal to let the program know when the user pressed the new file button on the UI

    settings: Parameter
               Parameter instance (pyqtgraph) containing all settings (could be represented using the settings_tree widget)

    settings_tree: ParameterTree
                   Widget representing as a Tree structure, all the settings defined in the class preamble variable ``params``

    """
    status_sig = pyqtSignal(utils.ThreadCommand)
    new_file_sig = pyqtSignal(bool)

    params = [
        {
            'title': 'Save type:',
            'name': 'save_type',
            'type': 'list',
            'values': save_types,
            'readonly': True
        },
        {
            'title': 'Save 2D datas:',
            'name': 'save_2D',
            'type': 'bool',
            'value': True
        },
        {
            'title':
            'Save raw datas only:',
            'name':
            'save_raw_only',
            'type':
            'bool',
            'value':
            True,
            'tooltip':
            'if True, will not save extracted ROIs used to do live plotting, only raw datas and the scan \
                        result will be saved'
        },
        {
            'title': 'Do Save:',
            'name': 'do_save',
            'type': 'bool',
            'default': False,
            'value': False
        },
        {
            'title': 'N saved:',
            'name': 'N_saved',
            'type': 'int',
            'default': 0,
            'value': 0,
            'visible': False
        },
        {
            'title': 'custom_name?:',
            'name': 'custom_name',
            'type': 'bool',
            'default': False,
            'value': False
        },
        {
            'title': 'show file content?:',
            'name': 'show_file',
            'type': 'bool',
            'default': False,
            'value': False
        },
        {
            'title': 'Base path:',
            'name': 'base_path',
            'type': 'browsepath',
            'value': 'C:\Data',
            'filetype': False,
            'readonly': True,
        },
        {
            'title': 'Base name:',
            'name': 'base_name',
            'type': 'str',
            'value': 'Scan',
            'readonly': True
        },
        {
            'title': 'Current scan:',
            'name': 'current_scan_name',
            'type': 'str',
            'value': '',
            'readonly': True
        },
        {
            'title': 'Current path:',
            'name': 'current_scan_path',
            'type': 'text',
            'value': 'C:\Data',
            'readonly': True,
            'visible': False
        },
        {
            'title': 'h5file:',
            'name': 'current_h5_file',
            'type': 'text_pb',
            'value': '',
            'readonly': True
        },
        {
            'title':
            'Compression options:',
            'name':
            'compression_options',
            'type':
            'group',
            'children': [
                {
                    'title': 'Compression library:',
                    'name': 'h5comp_library',
                    'type': 'list',
                    'value': 'zlib',
                    'values': ['zlib', 'lzo', 'bzip2', 'blosc']
                },
                {
                    'title': 'Compression level:',
                    'name': 'h5comp_level',
                    'type': 'int',
                    'value': 5,
                    'min': 0,
                    'max': 9
                },
            ]
        },
    ]

    def __init__(self, h5_file_path=None, h5_file=None, save_type='scan'):
        """Initialize the H5Saver object

        Creates the ``setting`` and ``settings_tree`` object



        """
        super(H5Saver, self).__init__()

        if save_type not in save_types:
            raise Exception('Invalid saving type')

        self.h5_file = h5_file
        self.h5_file_path = h5_file_path
        self.h5_file_name = None
        self.logger_array = None

        self.current_group = None
        self.current_scan_group = None
        self.current_scan_name = None
        self.raw_group = None

        self.settings = Parameter.create(title='Saving settings',
                                         name='save_settings',
                                         type='group',
                                         children=self.params)
        self.settings_tree = ParameterTree()
        self.settings_tree.setMinimumHeight(310)
        self.settings_tree.setParameters(self.settings, showTop=False)
        self.settings.child(
            ('current_h5_file'
             )).sigActivated.connect(lambda: self.emit_new_file(True))

        self.settings.child(('save_type')).setValue(save_type)

        self.filters = tables.Filters(
            complevel=self.settings.child('compression_options',
                                          'h5comp_level').value(),
            complib=self.settings.child('compression_options',
                                        'h5comp_library').value())
        # self.settings.child('saving_options', 'save_independent').show(save_type == 'scan')
        # self.settings.child('saving_options', 'do_save').show(not save_type == 'scan')
        # self.settings.child('saving_options', 'current_scan_name').show(save_type == 'scan')

        self.settings.sigTreeStateChanged.connect(
            self.parameter_tree_changed
        )  # any changes on the settings will update accordingly the detector

    def emit_new_file(self, status):
        """Emits the new_file_sig

        Parameters
        ----------
        status: bool
                emits True if a new file has been asked by the user pressing the new file button on the UI
        """
        self.new_file_sig.emit(status)

    def init_file(self,
                  update_h5=False,
                  custom_naming=False,
                  addhoc_file_path=None):
        """Initializes a new h5 file.
        Could set the h5_file attributes as:

        * a file with a name following a template if ``custom_naming`` is ``False`` and ``addhoc_file_path`` is ``None``
        * a file within a name set using a file dialog popup if ``custom_naming`` is ``True``
        * a file with a custom name if ``addhoc_file_path`` is a ``Path`` object or a path string

        Parameters
        ----------
        update_h5: bool
                   create a new h5 file with name specified by other parameters
                   if false try to open an existing file and will append new data to it
        custom_naming: bool
                       if True, a selection file dialog opens to set a new file name
        addhoc_file_path: Path or str
                          supplied name by the user for the new file

        Returns
        -------
        update_h5: bool
                   True if new file has been created, False otherwise
        """
        date = datetime.datetime.now()

        if addhoc_file_path is None:
            if not os.path.isdir(self.settings.child(('base_path')).value()):
                os.mkdir(self.settings.child(('base_path')).value())

            # set the filename and path
            base_name = self.settings.child(('base_name')).value()

            if not custom_naming:
                custom_naming = self.settings.child(('custom_name')).value()

            if not custom_naming:
                scan_type = self.settings.child(
                    ('save_type')).value() == 'scan'
                scan_path, current_scan_name, save_path = self.update_file_paths(
                    update_h5)
                self.current_scan_name = current_scan_name
                self.settings.child(
                    ('current_scan_name')).setValue(current_scan_name)
                self.settings.child(
                    ('current_scan_path')).setValue(str(scan_path))

                if not scan_type:
                    self.h5_file_path = save_path  #will remove the dataset part used for DAQ_scan datas
                    self.h5_file_name = base_name + date.strftime(
                        '_%Y%m%d_%H_%M_%S.h5')
                else:
                    self.h5_file_path = save_path
                    self.h5_file_name = save_path.name + ".h5"
            else:
                self.h5_file_name = utils.select_file(start_path=base_name,
                                                      save=True,
                                                      ext='h5')
                self.h5_file_path = self.h5_file_name.parent

        else:
            if isinstance(addhoc_file_path, str):
                addhoc_file_path = Path(addhoc_file_path)
            self.h5_file_path = addhoc_file_path.parent
            self.h5_file_name = addhoc_file_path.name

        fullpathname = str(self.h5_file_path.joinpath(self.h5_file_name))
        self.settings.child(('current_h5_file')).setValue(fullpathname)

        if update_h5:
            self.current_scan_group = None

        scan_group = None
        if self.current_scan_group is not None:
            scan_group = self.current_scan_group._v_name

        if update_h5:
            self.close_file()
            self.h5_file = tables.open_file(fullpathname,
                                            'w',
                                            title='PyMoDAQ file')
            self.h5_file.root._v_attrs['pymodaq_version'] = get_version()
        else:
            self.close_file()
            self.h5_file = tables.open_file(fullpathname,
                                            'a',
                                            title='PyMoDAQ file')

        self.raw_group = self.get_set_group(self.h5_file.root,
                                            'Raw_datas',
                                            title='Data from PyMoDAQ modules')
        self.get_set_logger(self.raw_group)
        if scan_group is not None:
            self.current_scan_group = self.get_set_group(
                self.raw_group, scan_group)
        else:
            self.current_scan_group = self.get_last_scan()

        self.raw_group._v_attrs['type'] = self.settings.child(
            ('save_type')).value()
        self.h5_file.root._v_attrs['file'] = date.strftime(self.h5_file_name)
        if update_h5:
            self.h5_file.root._v_attrs['date'] = date.strftime('%Y%m%d')
            self.h5_file.root._v_attrs['time'] = date.strftime('%H:%M:%S')

        return update_h5

    def update_file_paths(self, update_h5=False):
        """Apply the template depending on the 'save_type' settings child

        Parameters
        ----------
        update_h5: bool
                   if True, will increment the file name and eventually the current scan index
                   if False, get the current scan index in the h5 file

        Returns
        -------
        scan_path: Path
        current_filename: str
        dataset_path: Path

        See Also
        --------
        :py:meth:`pymodaq.daq_utils.daq_utils.set_current_scan_path`

        """

        try:
            # set the filename and path
            base_path = self.settings.child(('base_path')).value()
            base_name = self.settings.child(('base_name')).value()
            current_scan = self.settings.child(('current_scan_name')).value()
            scan_type = self.settings.child(('save_type')).value() == 'scan'

            if current_scan == '' or update_h5:
                next_scan_index = 0
                update_h5 = True  #just started the main program so one should create a new h5
            else:
                next_scan_index = self.get_scan_index()

            scan_path, current_filename, dataset_path = utils.set_current_scan_path(
                base_path,
                base_name,
                update_h5,
                next_scan_index,
                create_dataset_folder=scan_type)
            self.settings.child(('current_scan_path')).setValue(str(scan_path))

            return scan_path, current_filename, dataset_path

        except Exception as e:
            print(e)

    def get_last_scan(self):
        """Gets the last scan node within the h5_file and under the the **raw_group**

        Returns
        -------
        scan_group: pytables group or None


        """
        groups = [
            group for group in list(self.raw_group._v_groups)
            if 'Scan' in group
        ]
        groups.sort()
        if len(groups) != 0:
            scan_group = self.h5_file.get_node(self.raw_group, groups[-1])
        else:
            scan_group = None
        return scan_group

    def get_scan_index(self):
        """ return the scan group index in the "scan templating": Scan000, Scan001 as an integer
        """
        try:
            if self.current_scan_group is None:
                return 0
            else:

                groups = [
                    group for group in list(self.raw_group._v_groups)
                    if 'Scan' in group
                ]
                groups.sort()
                flag = False
                for child in list(
                        self.h5_file.get_node(self.raw_group,
                                              groups[-1])._v_groups):
                    if 'scan' in child:
                        return len(groups)

                return 0

        except Exception as e:
            return 0

    def load_file(self, base_path=None, file_path=None):
        """Opens a file dialog to select a h5file saved on disk to be used

        Parameters
        ----------
        base_path
        file_path

        See Also
        --------
        :py:meth:`init_file`
        :py:meth:`pymodaq.daq_utils.daq_utils.select_file`

        """
        if base_path is None:
            base_path = self.settings.child('base_path').value()
            if not os.path.isdir(base_path):
                base_path = None

        if file_path is None:
            file_path = utils.select_file(base_path, save=False, ext='h5')

        if not isinstance(file_path, Path):
            file_path = Path(file_path)

        if 'h5' not in file_path.suffix:
            raise IOError('Invalid file type, should be a h5 file')

        self.init_file(addhoc_file_path=file_path)

    def close_file(self):
        """Flush data and close the h5file

        """
        try:
            if self.h5_file is not None:
                self.h5_file.flush()
                if self.h5_file.isopen:
                    self.h5_file.close()
        except Exception as e:
            print(e)  #no big deal

    def is_node_in_group(self, where, name):
        """
        Check if a given node with name is in the group defined by where (comparison on lower case strings)
        Parameters
        ----------
        where: (str or node)
                path or parent node instance
        name: (str)
              group node name

        Returns
        -------
        bool
            True if node exists, False otherwise
        """

        nodes_names = [
            node._v_name.lower() for node in self.h5_file.list_nodes(where)
        ]
        return name.lower() in nodes_names

    def get_set_logger(self, where):
        """ Retrieve or create (if absent) a logger enlargeable array to store logs
        Get attributed to the class attribute ``logger_array``
        Parameters
        ----------
        where: node
               location within the tree where to save or retrieve the array

        Returns
        -------
        logger_array: vlarray
                      enlargeable array accepting strings as elements
        """
        logger = 'Logger'
        if not logger in list(self.h5_file.get_node(where)._v_children.keys()):
            # check if logger node exist
            text_atom = tables.atom.ObjectAtom()
            self.logger_array = self.h5_file.create_vlarray(where,
                                                            logger,
                                                            atom=text_atom)
            self.logger_array._v_attrs['type'] = 'log'
        else:
            self.logger_array = self.h5_file.get_node(where, name=logger)
        return self.logger_array

    def get_set_group(self, where, name, title=''):
        """Retrieve or create (if absent) a node group
        Get attributed to the class attribute ``current_group``

        Parameters
        ----------
        where: str or node
               path or parent node instance
        name: str
              group node name
        title: str
               node title

        Returns
        -------
        group: group node
        """
        if not name in list(self.h5_file.get_node(where)._v_children.keys()):
            self.current_group = self.h5_file.create_group(where, name, title)
        else:
            self.current_group = self.h5_file.get_node(where, name)
        return self.current_group

    def add_data_group(self,
                       where,
                       group_data_type,
                       title='',
                       settings_as_xml='',
                       metadata=dict([])):
        """Creates a group node at given location in the tree

        Parameters
        ----------
        where: group node
               where to create data group
        group_data_type: list of str
                         either ['data0D', 'data1D', 'data2D']
        title: str, optional
               a title for this node, will be saved as metadata
        settings_as_xml: str, optional
                         XML string created from a Parameter object to be saved as metadata
        metadata: dict, optional
                  will be saved as a new metadata attribute with name: key and value: dict value

        Returns
        -------
        group: group node

        See Also
        --------
        :py:meth:`àdd_group`
        """
        if group_data_type not in group_data_types:
            raise Exception('Invalid data group type')
        group = self.add_group(group_data_type, '', where, title,
                               settings_as_xml, metadata)
        return group

    def add_navigation_axis(self,
                            data,
                            parent_group,
                            axis='x_axis',
                            enlargeable=False,
                            title='',
                            metadata=dict([])):
        """
        Create carray for navigation axis within a scan
        Parameters
        ----------
        data: (ndarray) of dimension 1
        parent_group: (str or node) parent node where to save new data
        axis: (str) either x_axis or y_axis
        """
        if axis not in ['x_axis', 'y_axis', 'z_axis']:
            raise Exception('Invalid navigation axis name')
        array = self.add_array(parent_group,
                               'scan_{:s}'.format(axis),
                               'navigation_axis',
                               data_shape=data.shape,
                               data_dimension='1D',
                               array_to_save=data,
                               enlargeable=enlargeable,
                               title=title,
                               metadata=metadata)
        return array

    def add_data_live_scan(self,
                           channel_group,
                           data_dict,
                           scan_type='scan1D',
                           title=''):
        shape, dimension, size = utils.get_data_dimension(
            data_dict['data'], scan_type=scan_type, remove_scan_dimension=True)
        data_array = self.add_array(channel_group,
                                    'Data',
                                    'data',
                                    array_type=np.float,
                                    title=title,
                                    data_shape=shape,
                                    data_dimension=dimension,
                                    scan_type=scan_type,
                                    array_to_save=data_dict['data'])
        if 'x_axis' in data_dict:
            if not isinstance(data_dict['x_axis'], dict):
                array_to_save = data_dict['x_axis']
                tmp_dict = dict(label='', units='')
            else:
                tmp_dict = copy.deepcopy(data_dict['x_axis'])
                array_to_save = tmp_dict.pop('data')
        if 'x_axis' in data_dict:

            array = self.add_array(channel_group,
                                   'x_axis',
                                   'axis',
                                   array_type=np.float,
                                   array_to_save=array_to_save,
                                   enlargeable=False,
                                   data_dimension='1D',
                                   metadata=tmp_dict)
        if 'y_axis' in data_dict:
            if not isinstance(data_dict['y_axis'], dict):
                array_to_save = data_dict['y_axis']
                tmp_dict = dict(label='', units='')
            else:
                tmp_dict = copy.deepcopy(data_dict['y_axis'])
                array_to_save = tmp_dict.pop('data')
        if 'y_axis' in data_dict:
            array = self.add_array(channel_group,
                                   'y_axis',
                                   'axis',
                                   array_type=np.float,
                                   array_to_save=array_to_save,
                                   enlargeable=False,
                                   data_dimension='1D',
                                   metadata=tmp_dict)
        return data_array

    def add_data(self,
                 channel_group,
                 data_dict,
                 scan_type='scan1D',
                 scan_shape=[],
                 title='',
                 enlargeable=False,
                 init=False,
                 add_scan_dim=False):

        shape, dimension, size = utils.get_data_dimension(data_dict['data'])
        data_array = self.add_array(channel_group,
                                    'Data',
                                    'data',
                                    array_type=np.float,
                                    title=title,
                                    data_shape=shape,
                                    enlargeable=enlargeable,
                                    data_dimension=dimension,
                                    scan_type=scan_type,
                                    scan_shape=scan_shape,
                                    array_to_save=data_dict['data'],
                                    init=init,
                                    add_scan_dim=add_scan_dim)

        if 'x_axis' in data_dict:
            if not isinstance(data_dict['x_axis'], dict):
                array_to_save = data_dict['x_axis']
                tmp_dict = dict(label='', units='')
            else:
                tmp_dict = copy.deepcopy(data_dict['x_axis'])
                array_to_save = tmp_dict.pop('data')

            array = self.add_array(channel_group,
                                   'x_axis',
                                   'axis',
                                   array_type=np.float,
                                   array_to_save=array_to_save,
                                   enlargeable=False,
                                   data_dimension='1D',
                                   metadata=tmp_dict)

        if 'y_axis' in data_dict:
            if not isinstance(data_dict['y_axis'], dict):
                array_to_save = data_dict['y_axis']
                tmp_dict = dict(label='', units='')
            else:
                tmp_dict = copy.deepcopy(data_dict['y_axis'])
                array_to_save = tmp_dict.pop('data')

            array = self.add_array(channel_group,
                                   'y_axis',
                                   'axis',
                                   array_type=np.float,
                                   array_to_save=array_to_save,
                                   enlargeable=False,
                                   data_dimension='1D',
                                   metadata=tmp_dict)

        self.h5_file.flush()
        return data_array

    def add_array(self,
                  where,
                  name,
                  data_type,
                  data_shape=(1, ),
                  data_dimension='0D',
                  scan_type='',
                  scan_shape=[],
                  title='',
                  array_to_save=None,
                  array_type=np.float,
                  enlargeable=False,
                  metadata=dict([]),
                  init=False,
                  add_scan_dim=False):

        if data_dimension not in data_dimensions:
            raise Exception('Invalid data dimension')
        if data_type not in data_types:
            raise Exception('Invalid data type')
        if scan_type != '':
            scan_type = utils.uncapitalize(scan_type)
        if scan_type not in scan_types:
            raise Exception('Invalid scan type')
        if enlargeable:
            shape = [0]
            if data_shape != (1, ):
                shape.extend(data_shape)
            shape = tuple(shape)
            array = self.h5_file.create_earray(where,
                                               utils.capitalize(name),
                                               tables.Atom.from_dtype(
                                                   np.dtype(array_type)),
                                               shape=shape,
                                               title=title,
                                               filters=self.filters)
            array._v_attrs['shape'] = shape
        else:
            if add_scan_dim:  #means it is an array initialization to zero
                shape = scan_shape[:]
                shape.extend(data_shape)
                if init or array_to_save is None:
                    array_to_save = np.zeros(shape)

            array = self.h5_file.create_carray(where,
                                               utils.capitalize(name),
                                               obj=array_to_save,
                                               title=title,
                                               filters=self.filters)
            array._v_attrs['shape'] = array_to_save.shape

        array._v_attrs['type'] = data_type
        array._v_attrs['data_dimension'] = data_dimension
        array._v_attrs['scan_type'] = scan_type

        for metadat in metadata:
            array._v_attrs[metadat] = metadata[metadat]
        return array

    def append(self, array, data):
        if not (isinstance(array, tables.vlarray.VLArray)
                or isinstance(array, tables.earray.EArray)):
            raise Exception('This array cannot be appended')
        if isinstance(data, np.ndarray):
            if data.shape != (1, ):
                shape = [1]
                shape.extend(data.shape)
                array.append(data.reshape(shape))
            else:
                array.append(data)
        else:
            array.append(data)
        sh = list(array._v_attrs['shape'])
        sh[0] += 1
        array._v_attrs['shape'] = tuple(sh)

    def add_group(self,
                  group_name,
                  group_type,
                  where,
                  title='',
                  settings_as_xml='',
                  metadata=dict([])):
        """
        Add a node in the h5 file tree of the group type
        Parameters
        ----------
        group_name: (str) a custom name for this group
        group_type: (str) one of the possible values of **group_types**
        where: (str or node) parent node where to create the new group
        settings_as_xml: (str) XML string containing Parameters representation (see custom_Tree)
        metadata: (dict) extra metadata to be saved with this new group node

        Returns
        -------
        (node): newly created group node
        """

        if group_type not in group_types:
            raise Exception('Invalid group type')

        try:
            node = self.h5_file.get_node(where, utils.capitalize(group_name))
        except tables.NoSuchNodeError as e:
            node = None

        if node is None:
            node = self.get_set_group(where, utils.capitalize(group_name),
                                      title)
            node._v_attrs['settings'] = settings_as_xml
            node._v_attrs['type'] = group_type.lower()
            for metadat in metadata:
                node._v_attrs[metadat] = metadata[metadat]

        return node

    def add_incremental_group(self,
                              group_type,
                              where,
                              title='',
                              settings_as_xml='',
                              metadata=dict([])):
        """
        Add a node in the h5 file tree of the group type with an increment in the given name
        Parameters
        ----------
        group_type: (str) one of the possible values of **group_types**
        where: (str or node) parent node where to create the new group
        settings_as_xml: (str) XML string containing Parameters representation (see custom_Tree)
        metadata: (dict) extra metadata to be saved with this new group node

        Returns
        -------
        (node): newly created group node
        """
        if group_type not in group_types:
            raise Exception('Invalid group type')
        nodes = list(self.h5_file.get_node(where)._v_children.keys())
        nodes_tmp = []
        for node in nodes:
            if utils.capitalize(group_type) in node:
                nodes_tmp.append(node)
        nodes_tmp.sort()
        if len(nodes_tmp) == 0:
            ind_group = -1
        else:
            ind_group = int(nodes_tmp[-1][-3:])
        group = self.get_set_group(
            where,
            utils.capitalize(group_type) + '{:03d}'.format(ind_group + 1),
            title)
        group._v_attrs['settings'] = settings_as_xml
        if group_type.lower() != 'ch':
            group._v_attrs['type'] = group_type.lower()
        else:
            group._v_attrs['type'] = ''
        for metadat in metadata:
            group._v_attrs[metadat] = metadata[metadat]
        return group

    def add_det_group(self,
                      where,
                      title='',
                      settings_as_xml='',
                      metadata=dict([])):
        """
        Add a new group of type detector
        See Also
        -------
        add_incremental_group
        """
        group = self.add_incremental_group('detector', where, title,
                                           settings_as_xml, metadata)
        return group

    def add_CH_group(self,
                     where,
                     title='',
                     settings_as_xml='',
                     metadata=dict([])):
        """
        Add a new group of type channel
        See Also
        -------
        add_incremental_group
        """
        group = self.add_incremental_group('ch', where, title, settings_as_xml,
                                           metadata)
        return group

    def add_live_scan_group(self,
                            where,
                            dimensionality,
                            title='',
                            settings_as_xml='',
                            metadata=dict([])):
        """
        Add a new group of type live scan
        See Also
        -------
        add_incremental_group
        """
        group = self.add_group('Live_scan_{:s}'.format(dimensionality),
                               '',
                               where,
                               title=title,
                               settings_as_xml=settings_as_xml,
                               metadata=metadata)
        return group

    def add_scan_group(self, title='', settings_as_xml='', metadata=dict([])):
        """
        Add a new group of type scan
        See Also
        -------
        add_incremental_group
        """

        if self.current_scan_group is not None:
            if list(self.current_scan_group._v_children) == []:
                new_scan = False
            else:
                new_scan = True
        else:
            new_scan = True
        if new_scan:
            self.current_scan_group = self.add_incremental_group(
                'scan', self.raw_group, title, settings_as_xml, metadata)
            self.current_scan_group._v_attrs['description'] = ''
            self.settings.child(('current_scan_name')).setValue(
                self.current_scan_group._v_name)

        return self.current_scan_group

    def add_move_group(self,
                       where,
                       title='',
                       settings_as_xml='',
                       metadata=dict([])):
        """
        Add a new group of type move
        See Also
        -------
        add_incremental_group
        """
        group = self.add_incremental_group('move', where, title,
                                           settings_as_xml, metadata)
        return group

    def parameter_tree_changed(self, param, changes):
        for param, change, data in changes:
            path = self.settings.childPath(param)

            if change == 'childAdded':
                pass

            elif change == 'value':
                if param.name() == 'show_file':
                    param.setValue(False)
                    self.show_file_content()

                elif param.name() == 'base_path':
                    try:
                        if not os.path.isdir(param.value()):
                            os.mkdir(param.value())
                    except:
                        self.update_status(
                            "The base path couldn't be set, please check your options"
                        )

                elif param.name() in custom_tree.iter_children(
                        self.settings.child(('compression_options')), []):
                    self.filters = tables.Filters(
                        complevel=self.settings.child('compression_options',
                                                      'h5comp_level').value(),
                        complib=self.settings.child('compression_options',
                                                    'h5comp_library').value())

            elif change == 'parent':
                pass

    def update_status(self, status):
        self.status_sig.emit(
            utils.ThreadCommand("Update_Status", [status, 'log']))

    def show_file_content(self):
        form = QtWidgets.QWidget()
        if not self.h5_file.isopen:
            if self.h5_file_path.exists():
                self.analysis_prog = H5Browser(form, h5file=self.h5_file_path)
            else:
                raise FileExistsError('no File presents')
        else:
            self.analysis_prog = H5Browser(form, h5file=self.h5_file)
        form.show()
Example #43
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))
Example #44
0
class RosBagWidget(QtGui.QWidget):

    ##
    # @brief
    #
    # @return

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.file_name = ''
        self.bag = None
        self.data = {}
        self.plot_data = {}
        self.gridLayout = None
        self.label1 = None
        self.loadBtn = None
        self.tree = None
        self.addBtn = None
        self.editBtn = None
        self.removeBtn = None
        self.plotBtn = None
        self.plotTree = None
        self.plotData = None
        self.plotwin = None
        self.plot_num = 1
        self.params = [{
            'type':
            'group',
            'name':
            u'plot params',
            'children': [{
                'type': 'str',
                'name': 'x axis name',
                'value': u'time(s)'
            }, {
                'type': 'str',
                'name': 'y axis name',
                'value': u'position(m)'
            }, {
                'type': 'str',
                'name': 'plot name',
                'value': u'plot name'
            }]
        }]
        self.line_mark_list = [
            '+-', '*-', 'o-', '^-', 's-', 'x-', '.-', 'p-', 'h-', 'd-'
        ]
        self.msg_types = []
        self.topics = {}
        self.topics_data = {}
        self.msg_types_blacklist = [
            'sensor_msgs/PointCloud', 'sensor_msgs/Image'
        ]
        self.setup_ui(self)

    ##
    # @brief
    #
    # @param Form
    #
    # @return
    def setup_ui(self, Form):
        self.setObjectName("Form")
        self.resize(217, 499)
        self.gridLayout = QtGui.QGridLayout(self)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setVerticalSpacing(0)
        self.gridLayout.setObjectName("gridLayout")
        self.label1 = QtGui.QLabel("")
        self.label1.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
        self.label1.setStyleSheet("border:1px solid black;")
        self.gridLayout.addWidget(self.label1, 0, 0)
        self.loadBtn = QtGui.QPushButton("...")
        self.loadBtn.setFixedWidth(20)
        self.gridLayout.addWidget(self.loadBtn, 0, 1)
        self.loadBtn.clicked.connect(self.load_file)
        self.tree = DataTreeWidget(data=self.data)
        self.gridLayout.addWidget(self.tree, 1, 0, 1, 2)
        self.addBtn = QtGui.QPushButton("")
        add_icon = QtGui.QIcon()
        add_icon.addPixmap(QtGui.QPixmap("resources/add.png"),
                           QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.addBtn.setIcon(add_icon)
        self.addBtn.clicked.connect(self.add_plot)
        self.gridLayout.addWidget(self.addBtn, 0, 2)
        self.editBtn = QtGui.QPushButton("")
        edit_icon = QtGui.QIcon()
        edit_icon.addPixmap(QtGui.QPixmap("resources/edit.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.editBtn.setIcon(edit_icon)
        self.editBtn.clicked.connect(self.edit_plot)
        self.gridLayout.addWidget(self.editBtn, 0, 3)
        self.removeBtn = QtGui.QPushButton("")
        remove_icon = QtGui.QIcon()
        remove_icon.addPixmap(QtGui.QPixmap("resources/remove.png"),
                              QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.removeBtn.setIcon(remove_icon)
        self.removeBtn.clicked.connect(self.remove_plot)
        self.gridLayout.addWidget(self.removeBtn, 0, 4)
        self.plotBtn = QtGui.QPushButton("plot")
        # plot_icon = QtGui.QIcon()
        # plot_icon.addPixmap(QtGui.QPixmap("resources/plot.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        # self.plotBtn.setIcon(plot_icon)
        self.plotBtn.clicked.connect(self.plot)
        self.gridLayout.addWidget(self.plotBtn, 0, 5)
        self.plotTree = ParameterTree()
        self.plotData = Parameter.create(name='params',
                                         type='group',
                                         children=self.params)
        self.plotTree.setParameters(self.plotData, showTop=False)
        self.gridLayout.addWidget(self.plotTree, 1, 2, 1, 4)
        # self.tree2.setSizePolicity(self.tree1.width()/2, 499)
        # self.tree1.resize(setWidth(150)
        # self.tree2.setWidth(50)
        self.plotData.sigTreeStateChanged.connect(self.change)

    ##
    # @brief
    #
    # @param param
    # @param changes
    #
    # @return
    def change(self, param, changes):  # todo change plot params
        print("tree changes:(to do)")
        for param, change, data in changes:
            path = self.plotData.childPath(param)
            print(path)
            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('  ----------')

    ##
    # @brief
    #
    # @param file_name
    # @param start_dir
    #
    # @return
    def load_file(self, file_name=None, start_dir=None):
        """Load a rosbag (*.bag) file.
        """
        start = time.clock()
        if not file_name:
            if not start_dir:
                start_dir = '.'
            self.file_dialog = FileDialog(None, "Load rosbag ..", start_dir,
                                          "rosbag (*.bag)")
            # file_dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
            self.file_dialog.show()
            self.file_dialog.fileSelected.connect(self.load_file)
            return
        file_name = unicode(file_name)
        self.file_name = file_name
        self.label1.setText(str(file_name))
        self.file_info(file_name)
        end = time.clock()
        print("load file cost %s s" % (end - start))

    ##
    # @brief
    #
    # @param file_name
    #
    # @return
    def file_info(self, file_name=None):
        if not file_name:
            self.data = {}
        else:
            self.bag = rosbag.Bag(file_name)
            self.tree.setData(self.bag.get_type_and_topic_info()[1])
            # print(self.bag.get_type_and_topic_info()[1])
            bag_length = self.get_bag_length(
                self.bag.get_type_and_topic_info()[1]) * 10
            if len(file_name) * 8 > bag_length:
                bag_length = len(file_name) * 8
            self.label1.setFixedWidth(bag_length)
            # clear data
            self.msg_types = []
            self.topics = {}
            self.topics_data = {}
            # print(self.get_bag_length(self.bag.get_type_and_topic_info()[1]))
            for m in self.bag.get_type_and_topic_info()[0]:
                self.msg_types.append(m)
            for t in self.bag.get_type_and_topic_info()[1]:
                if self.bag.get_type_and_topic_info(
                )[1][t][0] not in self.msg_types_blacklist:
                    get_topic_params_cmd = "rostopic echo -b " + file_name + " -n 1 -p " + t
                    topic_parms = os.popen(get_topic_params_cmd).read()
                    topic_parms_list = self.topic_str2list(topic_parms)
                    self.topics[t] = topic_parms_list
                    get_topic_data_cmd = "rostopic echo -b " + self.file_name + " -p " + t
                    topic_data = os.popen(get_topic_data_cmd).read()
                    topic_data_list = self.topic_data_str2list(topic_data[:-1])
                    self.topics_data[t] = topic_data_list
                else:
                    print(t + "is not proper for plot")
                # print("topic_data_list", topic_data_list)
                # break

    @staticmethod
    ##
    # @brief
    #
    # @param data
    #
    # @return
    def get_bag_length(data):
        max_topic_len = 0
        max_topic_type_len = 0
        for topic in data:
            if len(topic) > max_topic_len:
                max_topic_len = len(topic)
            if len(data[topic][0]) > max_topic_type_len:
                max_topic_type_len = len(data[topic][0])
        # print(max_topic_len, max_topic_type_len)
        return max_topic_len + max_topic_type_len

    @staticmethod
    ##
    # @brief
    #
    # @param topic_str
    #
    # @return
    def topic_str2list(topic_str):
        # print(len(topic_str))
        # print(topic_str)
        topic_list = []
        if len(topic_str) > 0:
            # print(topic_str[0])
            out1 = re.split('\n', topic_str)
            params = re.split(',', out1[0])
            values = re.split(',', out1[1])
            # print(len(params), len(values))
            for i in range(len(params)):
                if values[i].strip('-').replace(".", '').isdigit():
                    topic_list.append(params[i])
            # print(topic_list)
            return topic_list

    @staticmethod
    ##
    # @brief
    #
    # @param topic_data_str
    #
    # @return
    def topic_data_str2list(topic_data_str):
        topic_data_list = []
        if len(topic_data_str) > 0:
            out1 = re.split('\n', topic_data_str)
            for o in out1:
                data_list = re.split(',', o)
                topic_data_list.append(data_list)
            return topic_data_list

    ##
    # @brief
    #
    # @return
    def add_plot(self):
        if len(self.file_name):
            #print("add plot")
            self.plotwin = PlotWin(self.topics, self.plot_num)
            self.plotwin.setWindowModality(QtCore.Qt.ApplicationModal)
            self.plotwin.setGeometry(500, 500, 600, 150)
            if self.plotwin.exec_():  # accepted
                #print("ok")
                self.plot_num = self.plot_num + 1
                if len(self.plotwin.plot_name.text()) > 0:
                    self.plotwin.param['name'] = unicode(
                        self.plotwin.plot_name.text()) + " " + unicode(
                            self.plotwin.topic_name.currentText())
                    self.plotwin.param['type'] = 'group'
                    x = {
                        'name': 'x',
                        'type': 'str',
                        'value': unicode(self.plotwin.field1.currentText())
                    }
                    y = {
                        'name': 'y',
                        'type': 'str',
                        'value': unicode(self.plotwin.field2.currentText())
                    }
                    color = self.plotwin.colorBtn.color(mode='byte')
                    color_str = ''
                    for i in color[:-1]:
                        c = str(hex(i)).replace("0x", '')
                        if len(c) < 2:
                            c = '0' + c
                        color_str = color_str + c
                    # print(color, color_str)
                    line_color = {
                        'name': 'line_color',
                        'type': 'color',
                        'value': color_str,
                        'tip': "This is a color button"
                    }
                    line_mark = {
                        'name': 'line_mark',
                        'type': 'list',
                        'values': self.line_mark_list,
                        'value': unicode(self.plotwin.line_mark.currentText())
                    }
                    self.plotwin.param['children'] = [
                        x, y, line_color, line_mark
                    ]
                    self.params.append(self.plotwin.param)
                    self.plotData = Parameter.create(
                        name='params',
                        type='group',
                        children=[self.plotwin.param])
                    self.plotTree.addParameters(self.plotData, showTop=False)
                else:
                    print("Please input the plot name first.")

            else:
                print("cancel")
        else:
            print("Please add bag file first!")

    ##
    # @brief
    #
    # @return
    def edit_plot(self):
        # print("edit plot", self.plotTree.selectedItems(), self.plotTree.currentItem())
        if hasattr(self.plotTree.currentItem(), "param"):
            print("edit plot " + re.split(
                '\'', str(getattr(self.plotTree.currentItem(), "param")))[1] +
                  "(to do)")
            # if hasattr(getattr(self.plotTree.currentItem(), "param"), "name"):
            # print(getattr(getattr(self.plotTree.currentItem(), "param"), "name"))
        # print("%x" % id(self.params[0]))

    ##
    # @brief
    #
    # @return
    def remove_plot(self):
        if hasattr(self.plotTree.currentItem(), "param"):
            print("remove plot " + re.split(
                '\'', str(getattr(self.plotTree.currentItem(), "param")))[1] +
                  "(to do)")

    ##
    # @brief
    #
    # @return
    def plot(self):
        print("plot")
        plots = []
        for p in self.params[1:]:
            topic_name = re.split(' ', p['name'])
            # print(topic_name[1])
            x_name = None
            y_name = None
            line_color = None
            line_mark = None
            for c in p['children']:
                if c['name'] == 'x':
                    x_name = c['value']
                elif c['name'] == 'y':
                    y_name = c['value']
                elif c['name'] == 'line_color':
                    line_color = c['value']
                elif c['name'] == 'line_mark':
                    line_mark = c['value']
            plots.append([
                topic_name[0], topic_name[1], x_name, y_name, line_color,
                line_mark
            ])
        # print(plots)

        # plt.figure(figsize=(12, 10))
        for p in plots:
            x, y = self.get_bag_data(p)
            plt.plot(x, y, p[5], color=("#" + p[4]), label=p[0])
        plt.xlabel(self.params[0]['children'][0]['value'])
        plt.ylabel(self.params[0]['children'][1]['value'])
        plt.title(self.params[0]['children'][2]['value'])
        # plt.ylim(-1.2, 1.2)
        plt.legend(loc='upper right')
        plt.grid(True)
        # plt.savefig(gflags.FLAGS.title + '.svg', format= 'svg')
        plt.show()

    ##
    # @brief
    #
    # @param plot_info
    #
    # @return
    def get_bag_data(self, plot_info):
        x = []
        y = []
        plot_data = self.topics_data[plot_info[1]]
        x_index = plot_data[0].index(plot_info[2])
        y_index = plot_data[0].index(plot_info[3])
        # print(plot_data, x_index, y_index)
        for pd in plot_data[1:]:
            # print('len(pd)', len(pd))
            # print('x_index', x_index)
            # print('y_index', y_index)
            x.append(pd[x_index])
            y.append(pd[y_index])
            # break
        return x, y
Example #45
0
    def test_pyqtgraph(self):
        cfg = collections.OrderedDict({
            "bool": True,
            "int": 5,
            "expected_float": 2,
            'str': 'strdrr',
            'vs': [1.0, 2.5, 7]
            # 'Area Sampling' : dictwidgetpyqtgraph.AreaSamplingParameter(name='Area Sampling')
        })
        captions = {"int": "toto je int"}

        opts = {}
        opts = {
            "children": {
                "vs": {
                    "title": 'voxelsize [mm]',
                    "children": {
                        "0": {
                            "title": "z",
                            'suffix': 'm',
                            'siPrefix': True
                        },
                        "1": {
                            "title": "x",
                            'suffix': 'm',
                            'siPrefix': True
                        },
                        "2": {
                            "title": "y",
                            'suffix': 'm',
                            'siPrefix': True
                        }
                    }
                },
                "expected_float": {
                    "type": "float",
                    "title": "Exp. float"
                }
            }
        }
        import teigen.dictwidgetpg
        params = teigen.dictwidgetpg.to_pyqtgraph_struct('params', cfg, opts=opts)
        params['children'].append(
            teigen.dictwidgetpg.AreaSamplingParameter(name='Area Sampling'))
        # print params

        # params[0]['title'] = "Pokusny title"
        # params[0]['my note'] = "poznamka"


        from PyQt4.QtGui import QApplication, QFileDialog
        app = QApplication(sys.argv)
        p = Parameter.create(**params)
        # p = Parameter.create(name='params', type='group', children=params)
        t = ParameterTree()
        print(p.getValues())
        lst = p.saveState()
        vals = p.getValues()

        name, dict_again = teigen.dictwidgetpg.from_pyqtgraph_struct(lst)
        t.setParameters(p, showTop=False)
        t.show()

        app.exec_()
Example #46
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)
Example #47
0
class MolViewer(QtGui.QMainWindow):
    '''The application main window.'''
    def __init__(self, parent=None):
        # We're not calling the super method so we can span an new instance in
        # the new function.
        # However, when the first created window is closed, all windoes close
        # super(MolViewer, self).__init__()
        QtGui.QMainWindow.__init__(self, parent)
        self.mol = None
        self.initUI()

    def initToolBar(self):
        '''The main toolbar.'''
        # File actions
        self.newAction = QtGui.QAction(QtGui.QIcon('../icons/new.png'), '&New',
                                       self)
        self.newAction.setStatusTip('New molecule viewer')
        self.newAction.setShortcut('Ctrl+N')
        self.newAction.triggered.connect(self.new)

        self.openAction = QtGui.QAction(QtGui.QIcon('../icons/open.png'),
                                        '&Open', self)
        self.openAction.setStatusTip('Read molecule from file')
        self.openAction.setShortcut('Ctrl+O')
        self.openAction.triggered.connect(self.open)

        self.saveAction = QtGui.QAction(QtGui.QIcon('../icons/save.png'),
                                        '&Save', self)
        self.saveAction.setStatusTip('Write molecule to file')
        self.saveAction.setShortcut('Ctrl+S')
        self.saveAction.triggered.connect(self.save)

        self.saveasAction = QtGui.QAction(
            QtGui.QIcon.fromTheme('document-save-as'), '&Save as...', self)
        self.saveasAction.setStatusTip('Write molecule to file')
        self.saveasAction.setShortcut('Ctrl+Shift+S')
        self.saveasAction.triggered.connect(self.saveas)

        self.saveimageAction = QtGui.QAction(
            QtGui.QIcon('../icons/picture-edit.png'), 'Save &image as PNG',
            self)
        self.saveimageAction.setStatusTip('Save image as PNG')
        self.saveimageAction.setShortcut('Ctrl+I')
        self.saveimageAction.triggered.connect(self.saveimage)

        self.exitAction = QtGui.QAction(QtGui.QIcon('../icons/exit.png'),
                                        '&Exit', self)
        self.exitAction.setShortcut('Ctrl+Q')
        self.exitAction.setStatusTip('Exit application')
        self.exitAction.triggered.connect(QtGui.qApp.quit)

        # Edit actions
        self.clearAction = QtGui.QAction(QtGui.QIcon('../icons/clear.png'),
                                         'Clea&r', self)
        self.clearAction.setShortcut('Ctrl+R')
        self.clearAction.setStatusTip('Remove molecule from viewer')
        self.clearAction.triggered.connect(self.clear)

        self.preferencesAction = QtGui.QAction(
            QtGui.QIcon('../icons/preferences.png'), '&Options', self)
        self.preferencesAction.setStatusTip('Edit Preferences')
        # self.preferencesAction.setShortcut()
        self.preferencesAction.triggered.connect(self.editpreferences)

        # View actions
        self.fullScreenAction = QtGui.QAction(
            QtGui.QIcon('../icons/fullscreen.png'), '&Full Screen', self)
        self.fullScreenAction.setStatusTip('Toggle full screen')
        self.fullScreenAction.setShortcut('F11')
        self.fullScreenAction.triggered.connect(self.fullscreen)

        self.setwindowsizeAction = QtGui.QAction(
            QtGui.QIcon('../icons/fullscreen.png'), '&Set Geometry', self)
        self.setwindowsizeAction.setStatusTip(
            'Set height and width of main window')
        self.setwindowsizeAction.setShortcut('F12')
        self.setwindowsizeAction.triggered.connect(self.setwindowsize)

        # Molecule action
        self.getbynameAction = QtGui.QAction(
            QtGui.QIcon('../icons/find.png'),
            '&Get molecule by name or CAS number', self)
        self.getbynameAction.setStatusTip(
            'Get a molecule by name or CAS number')
        self.getbynameAction.setShortcut('Ctrl+G')
        self.getbynameAction.triggered.connect(self.getbyname)

        self.distmatAction = QtGui.QAction(QtGui.QIcon('../icons/table.png'),
                                           '&Distance matrix', self)
        self.distmatAction.setShortcut('Ctrl+D')
        self.distmatAction.triggered.connect(self.distmatWindow)

        self.infoAction = QtGui.QAction(QtGui.QIcon('../icons/info.png'),
                                        '&Information', self)
        self.infoAction.setStatusTip('Show basic information about molecule')
        self.infoAction.setShortcut('Ctrl+I')
        self.infoAction.triggered.connect(self.info)

        # Spectrum action
        self.showspectrumAction = QtGui.QAction(
            QtGui.QIcon('../icons/spectrum.png'), '&Spectrum', self)
        self.showspectrumAction.setStatusTip('Show spectrum')
        self.showspectrumAction.triggered.connect(self.showspectrum)

        # About action
        self.aboutAction = QtGui.QAction(QtGui.QIcon('../icons/spectrum.png'),
                                         '&About', self)
        self.aboutAction.setStatusTip('Show the about dialog')
        self.aboutAction.triggered.connect(self.about)

        # Toolbars
        self.filetoolbar = self.addToolBar('File')
        self.filetoolbar.addAction(self.newAction)
        self.filetoolbar.addAction(self.openAction)
        self.filetoolbar.addAction(self.saveAction)
        # self.filetoolbar.addAction(self.saveasAction)
        self.filetoolbar.addAction(self.saveimageAction)

        self.edittoolbar = self.addToolBar('Edit')
        self.edittoolbar.addAction(self.preferencesAction)
        self.edittoolbar.addAction(self.clearAction)

        self.viewtoolbar = self.addToolBar('View')
        self.viewtoolbar.addAction(self.fullScreenAction)

        self.moleculetoolbar = self.addToolBar('Molecule')
        self.moleculetoolbar.addAction(self.getbynameAction)
        self.moleculetoolbar.addAction(self.distmatAction)
        self.moleculetoolbar.addAction(self.infoAction)

        self.spectrumtoolbar = self.addToolBar('Spectrum')
        self.spectrumtoolbar.addAction(self.showspectrumAction)

    def initMenuBar(self):
        '''The main menubar.'''
        menubar = self.menuBar()
        menubar.setNativeMenuBar(True)

        # Create menus
        file = menubar.addMenu('&File')
        edit = menubar.addMenu('&Edit')
        view = menubar.addMenu('&View')
        molmenu = menubar.addMenu('&Molecule')
        spectrummenu = menubar.addMenu('&Spectrum')
        aboutmenu = menubar.addMenu('&About')

        # File menu
        file.addAction(self.newAction)
        file.addAction(self.openAction)
        file.addAction(self.saveAction)
        file.addAction(self.saveasAction)
        file.addAction(self.saveimageAction)
        file.addSeparator()
        file.addAction(self.exitAction)

        # Edit menu
        edit.addAction(self.clearAction)
        edit.addSeparator()
        edit.addAction(self.preferencesAction)

        # View menu
        view.addAction(self.fullScreenAction)
        view.addAction(self.setwindowsizeAction)

        # Molecule menu
        molmenu.addAction(self.getbynameAction)
        molmenu.addSeparator()
        molmenu.addAction(self.distmatAction)
        molmenu.addAction(self.infoAction)

        # Spectrum menu
        spectrummenu.addAction(self.showspectrumAction)

        # About menu
        aboutmenu.addAction(self.aboutAction)

    def initUI(self):
        '''Initializes the main window widgets.'''
        self.initToolBar()
        self.initMenuBar()

        self.parametertree = ParameterTree()
        self.viewwidget = gl.GLViewWidget()

        widget = QtGui.QWidget()
        hbox = QtGui.QHBoxLayout(widget)
        hbox.addWidget(self.parametertree)
        hbox.addWidget(self.viewwidget, 1)

        self.setCentralWidget(widget)
        self.resize(1200, 600)
        self.setWindowTitle('MolViewer :: Main window')
        self.drawgrid()
        self.show()

    def distmatWindow(self):
        '''Shows the distance matrix window.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information',
                                          'No molecule loaded')
        self.matrixtable = TableWindow(parent=self,
                                       mol=self.mol,
                                       kind='distance')
        self.matrixtable.show()

    def _open(self, mol):
        '''Draws a new molecule

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        self.mol = mol
        self.clearview()
        self.drawmolecule(mol)
        self.drawgrid()
        self.setWindowTitle('MolViewer :: Main window :: {:s}'.format(
            self.mol.filename))

    def open(self):
        '''Open a new molecule using the file dialog.'''
        filename = QtGui.QFileDialog.getOpenFileName(
            self, 'Open File', './xyz', '*.*;; *.xyz;; *.mol;; *.sdf')
        if filename:
            mol = read_xyz(filename)
            self._open(mol)

    def new(self):
        '''Spawns a new main window.'''
        spawn = MolViewer(self)
        spawn.show()

    def saveas(self):
        '''Save a molecule to file with a new filename.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information',
                                          'No molecule to saves')
        else:
            filename = QtGui.QFileDialog.getSaveFileName(
                self, 'Save file as', './molecules/xyz', '*.xyz')
            if filename:
                write_xyz(self.mol, filename)

    def save(self):
        '''Save the molecule to file.'''
        if self.mol and not self.mol.filename:
            self.saveas()
        elif self.mol and self.mol.filename:
            write_xyz(self.mol, self.mol.filename)

    def saveimage(self):
        '''Saves the viewwidget as a png image.'''
        filename = QtGui.QFileDialog.getSaveFileName(self, 'Save image as PNG',
                                                     '', '*.png')
        img = self.viewwidget.readQImage()
        # print('Writing image {:s}'.format(filename), end=' ')
        img.save(filename, 'png', 100)
        print('Done')

    def fullscreen(self):
        '''Toggle full screen window.'''
        if self.windowState() & QtCore.Qt.WindowFullScreen:
            self.showNormal()
        else:
            self.showFullScreen()

    def setwindowsize(self):
        '''Set the window to specified size.'''
        width, ok = QtGui.QInputDialog.getText(
            self, 'Set width', 'Enter window width in pixels:')
        height, ok = QtGui.QInputDialog.getText(
            self, 'Set height', 'Enter window height in pixels:')
        self.resize(int(width), int(height))

    def editpreferences(self):
        '''Opens the preferences dialog.'''
        dlg = OptionsDialog(self)
        dlg.exec_()

    def getbyname(self):
        '''Displays the input dialog to find a molecule by its identifier.'''
        text, ok = QtGui.QInputDialog.getText(
            self, 'Get molecule by name or CAS number',
            'Enter molecule name or CAS number:')
        if ok:
            if isinstance(text, str) and len(text) > 0:
                mol = get_mol_by_name(text)
                if mol:
                    self._open(mol)
                else:
                    QtGui.QMessageBox.information(self, 'Information',
                                                  'Molecule not found')

    def drawmolecule(self, mol):
        '''Creates the polygons to draw the molecule to the viewwidget.

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        self.viewwidget.setCameraPosition(distance=10)
        self.drawatoms(mol)
        self.drawbonds(mol)
        self.setparameter(mol)

    def drawatoms(self, mol):
        '''Draw the atoms.

        :param molecule: The molecule for which to draw the atoms.
        :type molecule: molecule.Molecule

        '''
        scale = 0.25
        rows = 16
        cols = 16
        shader = 'shaded'
        smooth = True

        for atom in mol.atoms:
            radius = atom.radius() * scale
            pos = atom.r
            md = gl.MeshData.sphere(rows=rows, cols=cols, radius=radius)
            m = gl.GLMeshItem(meshdata=md, smooth=smooth, shader=shader)
            colors = np.ones((md.faceCount(), 4), dtype=float)
            rgb = atom.color()
            colors[:, 0] = rgb[0]  # r
            colors[:, 1] = rgb[1]  # g
            colors[:, 2] = rgb[2]  # b
            colors[:, 3] = 1.0  # a
            md.setFaceColors(colors)
            m.translate(pos[0], pos[1], pos[2])
            self.viewwidget.addItem(m)

    def drawbonds(self, mol):
        '''Draw the bonds.

        :param molecule: The molecule for which to show the bonds.
        :type molecule: molecule.Molecule

        '''
        rows = 16
        cols = 16
        shader = 'shaded'
        smooth = True
        bond_radius = [0.1, 0.1]
        draw_edges = False
        edge_color = (0, 0, 0, 1)
        z = np.asarray([0, 0, 1])
        for bond in mol.bonds():
            vec = bond.p1 - bond.p2
            angle = angle_between_vectors(vec, z) * 180 / np.pi
            axis = np.cross(z, vec)
            md = gl.MeshData.cylinder(rows=rows,
                                      cols=cols,
                                      radius=bond_radius,
                                      length=bond.length())
            m = gl.GLMeshItem(meshdata=md,
                              smooth=smooth,
                              drawEdges=draw_edges,
                              edgeColor=edge_color,
                              shader=shader)
            colors = np.ones((md.faceCount(), 4), dtype=float)
            rgb = bond.atoms[0].color()
            colors[:, 0] = rgb[0]
            colors[:, 1] = rgb[1]
            colors[:, 2] = rgb[2]
            colors[:, 3] = 1.0
            md.setFaceColors(colors)
            m.rotate(angle, axis[0], axis[1], axis[2])
            m.translate(bond.p2[0], bond.p2[1], bond.p2[2])
            self.viewwidget.addItem(m)

    def drawgrid(self):
        '''Show a grid in x,y,z planes.'''
        # gx = gl.GLGridItem()
        # gx.rotate(90, 0, 1, 0)
        # w.addItem(gx)
        # gy = gl.GLGridItem()
        # gy.rotate(90, 1, 0, 0)
        # w.addItem(gy)
        gz = gl.GLGridItem()
        self.viewwidget.addItem(gz)

    def clearview(self):
        '''Removes all items from ViewWidget.'''
        # Not all items are removed in one loop. Why?
        while len(self.viewwidget.items) > 0:
            for i in self.viewwidget.items:
                self.viewwidget.removeItem(i)

    def clear(self):
        '''Clears the viewwidget and deletes the molecule.'''
        self.clearview()
        self.mol = None

    def info(self):
        '''Shows a info box with basic infoemation about the molecule.'''
        if self.mol is None:
            QtGui.QMessageBox.information(self, 'Information',
                                          'No molecule loaded')
        self.infotree = TreeWindow(parent=self, mol=self.mol)
        self.infotree.show()

    def showspectrum(self):
        win = SpectrumWindow(self)
        win.show()

    def about(self):
        dlg = AboutDialog(self)
        dlg.exec_()

    def setparameter(self, mol):
        params = [{
            'name':
            mol.name,
            'type':
            'group',
            'children': [{
                'name': 'File',
                'type': 'str',
                'value': mol.filename,
                'readonly': True
            }, {
                'name': 'Formula',
                'type': 'str',
                'value': mol.stoichiometry(),
                'readonly': True
            }, {
                'name': 'Mass',
                'type': 'float',
                'value': mol.mass(),
                'readonly': True
            }, {
                'name': 'Electrons',
                'type': 'int',
                'value': mol.nel(),
                'readonly': True
            }, {
                'name': 'Charge',
                'type': 'float',
                'value': mol.charge,
                'readonly': True
            }]
        }]

        p = Parameter.create(name='Molecule', type='group', children=params)
        self.parametertree.setParameters(p, showTop=True)
Example #48
0
class ExploreDataFile(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.neuron_data = None
        self.setWindowTitle("Experiment Control - Data Analysis & Visualization")
        self.layout = QtGui.QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)
        self.splitter = QtGui.QSplitter()
        self.splitter.setOrientation(QtCore.Qt.Horizontal)
        self.splitter2 = QtGui.QSplitter()
        self.splitter2.setOrientation(QtCore.Qt.Vertical)
        self.layout.addWidget(self.splitter)
        self.splitter.addWidget(self.splitter2)
        self.plot_widget = pg.GraphicsLayoutWidget()
        self.tree = ParameterTree(showHeader=False)
        self.params = Parameter.create(
            name="params",
            type="group",
            children=[
                dict(name="Reanalyze", type="bool", value=False),
                dict(name="Load", type="action"),
                dict(name="GCFR-sigma (ms)", type="float", value=100.0, step=0.1, limits=[1, 5000]),
                dict(name="Save", type="action"),
            ],
        )
        self.tree.setParameters(self.params, showTop=False)
        # self.params.param('Save').sigActivated.connect(self.SavePlot)
        self.params.param("Load").sigActivated.connect(self.OpenDataFile)
        self.splitter2.addWidget(self.tree)
        self.trial_list_tree = pg.TreeWidget(parent=self.splitter2)
        self.splitter.addWidget(self.plot_widget)
        self.trial_list_tree.setColumnCount(1)

    def OpenDataFile(self):
        print("Reanalyze= " + str(self.params["Reanalyze"]))
        file_name = str(getOpenFileName(self, "Neuron Data", "", "HDF5 Files (*.hdf5 *.h5)"))
        if file_name == "":
            return
        self.LoadData(file_name, reanalyze=self.params["Reanalyze"])
        self.setWindowTitle("Experiment Control - Data Analysis & Visualization: " + file_name)

    def LoadData(self, neuron_data_file_name, reanalyze=False):
        if self.neuron_data is not None:
            self.neuron_data.close()
        self.neuron_data = NeuronData(neuron_data_file_name, reanalyze=reanalyze)
        self.trial_list_tree.clear()
        for experiment_name in self.neuron_data.experiment_list:
            experiment_tree_item = QtGui.QTreeWidgetItem([experiment_name])
            self.trial_list_tree.addTopLevelItem(experiment_tree_item)
            experiment = self.neuron_data.experiment[experiment_name]
            if len(experiment.protocol_list) > 0:
                for protocol_name in experiment.protocol_list:
                    protocol_tree_item = QtGui.QTreeWidgetItem([protocol_name])
                    experiment_tree_item.addChild(protocol_tree_item)
                    protocol = experiment.protocol[protocol_name]
                    if len(protocol.trial_list) > 0:
                        for trial_name in protocol.trial_list:
                            trial_tree_item = QtGui.QTreeWidgetItem([trial_name])
                            protocol_tree_item.addChild(trial_tree_item)
                    else:
                        self.trial_list_tree.removeItemWidget(protocol_tree_item, 0)
            else:
                self.trial_list_tree.removeItemWidget(experiment_tree_item, 0)
        self.trial_list_tree.itemClicked.connect(self.UpdatePlot)

    def SavePlotData(self):
        file_name = str(getSaveFileName(self, "Save Plot data", "", "CSV (*.csv)"))
        if file_name == "":
            return
        x_range = self.plot_widget.getItem(0, 0).viewRange()[0]
        t = np.linspace(0, len(arena_out) / 10000.0, num=len(arena_out), endpoint=False)
        """if self.data['type'] == "trial":
            c = pyx.canvas.canvas()
        if self.data['type'] == "protocol":
            c = pyx.canvas.canvas()"""

    def UpdatePlot(self, item, column):
        if str(item.text(0)) in self.neuron_data.experiment_list:
            return
        self.plot_widget.clear()
        if item.childCount() == 0:
            trial_name = str(item.text(0))
            protocol_name = str(item.parent().text(0))
            experiment_name = str(item.parent().parent().text(0))
            protocol = self.neuron_data.experiment[experiment_name].protocol[protocol_name]
            membrane_potential, spike_position_list, antennal_movement = protocol.trial[trial_name].AnalyzeTrial()
            self.data = {
                "type": "trial",
                "trial name": trial_name,
                "membrane potential": membrane_potential,
                "spike position list": spike_position_list,
                "antennal movement": antennal_movement,
                "arena out": protocol.arena_out,
            }
            PlotTrial(
                trial_name,
                membrane_potential,
                spike_position_list,
                antennal_movement,
                protocol.arena_out,
                win=self.plot_widget,
            )
        else:
            protocol_name = str(item.text(0))
            experiment_name = str(item.parent().text(0))
            protocol = self.neuron_data.experiment[experiment_name].protocol[protocol_name]
            antennal_movement_list, mean_antennal_movement, arena_out, raster_data, pre_GCFR = (
                protocol.AnalyzeProtocol()
            )
            gcfr = GCFR(pre_GCFR, self.params["GCFR-sigma (ms)"])
            self.data = {
                "type": "protocol",
                "protocol name": protocol_name,
                "antennal movement list": antennal_movement_list,
                "mean antennal movement": mean_antennal_movement,
                "arena out": arena_out,
                "raster data": raster_data,
                "GCFR": gcfr,
            }
            PlotProtocol(
                protocol_name,
                antennal_movement_list,
                mean_antennal_movement,
                arena_out,
                raster_data,
                gcfr,
                win=self.plot_widget,
            )
class Ui_PropertiesDockWidget(QtCore.QObject):
    def __init__(self):
        self.indexGr = 0
        self.colors = [
            '#B38C41', '#8E3469', '#85A73D', '#334977', '#B345A1', '#B345A1',
            '#B345A1'
        ]
        super(Ui_PropertiesDockWidget, self).__init__()

    def setupUi(self, ControlsBox):
        self.parent = ControlsBox
        ControlsBox.setObjectName('Controls Box')
        self.languageHash = self.parent.controller.languageSupport.languageHash
        self.ui_controls_box_widget = QtGui.QDockWidget(
            self.languageHash.__getitem__("lbl.ModelProperties"), ControlsBox)
        self.ui_controls_box_widget.setAllowedAreas(
            QtCore.Qt.AllDockWidgetAreas)

        self.house_layout = QtGui.QVBoxLayout()

        ## Create ParameterTree for the rest of the parameters
        self.parameter_tree = ParameterTree()
        self.parTr = Parameter.create(name='params',
                                      type='group',
                                      children=self.createParamsRest(),
                                      showHeader=False)
        self.parameter_tree.setParameters(self.parTr, showTop=False)
        #
        self.house_layout.addWidget(self.parameter_tree)

        self.house_widget = QtGui.QWidget()
        self.house_widget.setLayout(self.house_layout)
        self.ui_controls_box_widget.setWidget(self.house_widget)
        self.house_layout.setSizeConstraint(QtGui.QLayout.SetMinAndMaxSize)
        self.house_layout.addSpacing(10)

    def createParamsRest(self):
        # Tree params
        _params = []
        _i = 0
        _listChildAuxEq = []
        for const in self.parent.controller.model._e:
            _childAuxEq = []
            # if const.simulate:
            _childAuxEq = {
                'name':
                const.description + ' (' + "d" + const.name + "/dt" + ')',
                'type':
                'group',
                'expanded':
                True,
                'children': [
                    {
                        'name': "d" + const.name + "/dt" + ' =',
                        'type': 'str',
                        'value': const.equation,
                        'readonly': True
                    },
                    {
                        'name': 'Visible',
                        'type': 'bool',
                        'value': const.simulate,
                        'readonly': False
                    },
                    {
                        'name': 'Color',
                        'type': 'color',
                        'value': self.colors[_i],
                        'readonly': False
                    },
                    #TODO: agregar mas atributos
                    # {'name': 'Line width', 'type': 'int', 'value': self.pen_size[_i], 'readonly': not const.simulate},
                ]
            }
            _listChildAuxEq.append(_childAuxEq)
            _i += 1
            # print(const)self.languageHash.__getitem__("lbl.ModelProperties")
        _paramAux = {
            'name': self.languageHash.__getitem__("lbl.DifferentialEquations"),
            'type': 'group',
            'children': _listChildAuxEq,
            'expanded': True
        }
        _params.append(_paramAux)

        _listChildAuxFunc = []
        for const in self.parent.controller.model._f:
            _childAuxFunc = {
                'name': const.name,
                'type': 'str',
                'value': const.function,
                'siPrefix': False,
                'readonly': True
            }
            _listChildAuxFunc.append(_childAuxFunc)
            # print(const)
        _paramAux = {
            'name': self.languageHash.__getitem__("lbl.Functions"),
            'type': 'group',
            'children': _listChildAuxFunc,
            'expanded': True
        }
        _params.append(_paramAux)

        _listChildAuxConst = []
        for const in self.parent.controller.model._c:
            nomC = const.value1
            # nomC = const.value1 + ' ' + const.operator
            _childAuxConst = {
                'name': nomC,
                'type': 'str',
                'value': const.value2,
                'readonly': True
            }
            _listChildAuxConst.append(_childAuxConst)
        _paramAuxConst = {
            'name': self.languageHash.__getitem__("lbl.Constants"),
            'type': 'group',
            'children': _listChildAuxConst,
            'expanded': True
        }
        _params.append(_paramAuxConst)

        return _params
Example #50
0
class ROIManager(QObject):
    ROI_changed = pyqtSignal()
    ROI_changed_finished = pyqtSignal()
    new_ROI_signal = pyqtSignal(int, str)
    remove_ROI_signal = pyqtSignal(str)
    roi_settings_changed = pyqtSignal(list)

    roi_update_children = pyqtSignal(list)

    color_list = np.array(plot_colors)

    def __init__(self, viewer_widget=None, ROI_type='1D'):
        super().__init__()
        self.ROI_type = ROI_type
        self.roiwidget = QtWidgets.QWidget()
        self.viewer_widget = viewer_widget  # either a PlotWidget or a ImageWidget
        self.ROIs = OrderedDict([])
        self.setupUI()

    def setupUI(self):

        vlayout = QtWidgets.QVBoxLayout()
        self.roiwidget.setLayout(vlayout)

        horwidget = QtWidgets.QWidget()
        horlayout = QtWidgets.QHBoxLayout()
        horwidget.setLayout(horlayout)
        self.save_ROI_pb = QtWidgets.QPushButton('Save ROIs')
        self.load_ROI_pb = QtWidgets.QPushButton('Load ROIs')
        self.clear_ROI_pb = QtWidgets.QPushButton('Clear ROIs')
        horlayout.addWidget(self.save_ROI_pb)
        horlayout.addWidget(self.load_ROI_pb)
        horlayout.addWidget(self.clear_ROI_pb)

        vlayout.addWidget(horwidget)

        self.roitree = ParameterTree()
        vlayout.addWidget(self.roitree)
        self.roiwidget.setMinimumWidth(100)
        self.roiwidget.setMaximumWidth(300)

        params = [{
            'title': 'Measurements:',
            'name': 'measurements',
            'type': 'table',
            'value': OrderedDict([]),
            'Ncol': 2,
            'header': ["LO", "Value"]
        },
                  ROIScalableGroup(roi_type=self.ROI_type, name="ROIs")]
        self.settings = Parameter.create(title='ROIs Settings',
                                         name='rois_settings',
                                         type='group',
                                         children=params)
        self.roitree.setParameters(self.settings, showTop=False)
        self.settings.sigTreeStateChanged.connect(self.roi_tree_changed)

        self.save_ROI_pb.clicked.connect(self.save_ROI)
        self.load_ROI_pb.clicked.connect(lambda: self.load_ROI(None))
        self.clear_ROI_pb.clicked.connect(self.clear_ROI)

    def roi_tree_changed(self, param, changes):

        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 == 'childAdded':  # new roi to create
                par = data[0]
                newindex = int(par.name()[-2:])

                if par.child(('type')).value() == '1D':
                    roi_type = ''

                    pos = self.viewer_widget.plotItem.vb.viewRange()[0]
                    newroi = LinearROI(index=newindex, pos=pos)
                    newroi.setZValue(-10)
                    newroi.setBrush(par.child(('Color')).value())
                    newroi.setOpacity(0.2)

                elif par.child(('type')).value() == '2D':
                    roi_type = par.child(('roi_type')).value()
                    xrange = self.viewer_widget.plotItem.vb.viewRange()[0]
                    yrange = self.viewer_widget.plotItem.vb.viewRange()[1]
                    width = np.max(((xrange[1] - xrange[0]) / 10, 2))
                    height = np.max(((yrange[1] - yrange[0]) / 10, 2))
                    pos = [
                        int(np.mean(xrange) - width / 2),
                        int(np.mean(yrange) - width / 2)
                    ]

                    if roi_type == 'RectROI':
                        newroi = RectROI(index=newindex,
                                         pos=pos,
                                         size=[width, height])
                    else:
                        newroi = EllipseROI(index=newindex,
                                            pos=pos,
                                            size=[width, height])
                    newroi.setPen(par.child(('Color')).value())

                newroi.sigRegionChanged.connect(self.ROI_changed.emit)
                newroi.sigRegionChangeFinished.connect(
                    self.ROI_changed_finished.emit)
                newroi.index_signal[int].connect(self.update_roi_tree)
                try:
                    self.settings.sigTreeStateChanged.disconnect()
                except Exception:
                    pass
                self.settings.sigTreeStateChanged.connect(
                    self.roi_tree_changed)
                self.viewer_widget.plotItem.addItem(newroi)

                self.ROIs["ROI_%02.0d" % newindex] = newroi

                self.new_ROI_signal.emit(newindex, roi_type)
                self.update_roi_tree(newindex)

            elif change == 'value':
                if param.name() in putils.iter_children(
                        self.settings.child(('ROIs')), []):
                    if param.name() == 'Color' or param.name() == 'angle':
                        parent = param.parent().name()
                    else:
                        parent = param.parent().parent().name()
                    self.update_roi(parent, param)

            elif change == 'parent':
                if 'ROI' in param.name():
                    roi = self.ROIs.pop(param.name())
                    self.viewer_widget.plotItem.removeItem(roi)
                    self.remove_ROI_signal.emit(param.name())

            if param.name() != 'measurements':
                self.roi_settings_changed.emit([(param, 'value', param.value())
                                                ])
        self.ROI_changed_finished.emit()

    def update_roi(self, roi_key, param):

        if param.name() == 'Color':
            self.ROIs[roi_key].setPen(param.value())
        elif param.name() == 'left' or param.name() == 'x':
            pos = self.ROIs[roi_key].pos()
            poss = [param.value(), pos[1]]
            poss.sort()
            self.ROIs[roi_key].setPos(poss)

        elif param.name() == 'right' or param.name() == 'y':
            pos = self.ROIs[roi_key].pos()
            poss = [pos[0], param.value()]
            poss.sort()
            self.ROIs[roi_key].setPos(poss)

        elif param.name() == 'angle':
            self.ROIs[roi_key].setAngle(param.value())
        elif param.name() == 'width':
            size = self.ROIs[roi_key].size()
            self.ROIs[roi_key].setSize((param.value(), size[1]))
        elif param.name() == 'height':
            size = self.ROIs[roi_key].size()
            self.ROIs[roi_key].setSize((size[0], param.value()))

    @pyqtSlot(int)
    def update_roi_tree(self, index):
        roi = self.ROIs['ROI_%02.0d' % index]
        par = self.settings.child(*('ROIs', 'ROI_%02.0d' % index))
        if isinstance(roi, LinearROI):
            pos = roi.getRegion()
        else:
            pos = roi.pos()
            size = roi.size()
            angle = roi.angle()

        try:
            self.settings.sigTreeStateChanged.disconnect()
        except Exception:
            pass
        if isinstance(roi, LinearROI):
            par.child(*('position', 'left')).setValue(pos[0])
            par.child(*('position', 'right')).setValue(pos[1])
        if not isinstance(roi, LinearROI):
            par.child(*('position', 'x')).setValue(pos[0])
            par.child(*('position', 'y')).setValue(pos[1])
            par.child(*('size', 'width')).setValue(size[0])
            par.child(*('size', 'height')).setValue(size[1])
            par.child('angle').setValue(angle)

        self.settings.sigTreeStateChanged.connect(self.roi_tree_changed)

    def save_ROI(self):

        try:
            data = ioxml.parameter_to_xml_string(self.settings.child(('ROIs')))
            path = select_file(start_path=Path.home(), ext='xml')

            if path != '':
                with open(path, 'wb') as f:
                    f.write(data)
        except Exception as e:
            print(e)

    def clear_ROI(self):
        indexes = [roi.index for roi in self.ROIs.values()]
        for index in indexes:
            self.settings.child(*('ROIs', 'ROI_%02.0d' % index)).remove()
            # self.settings.sigTreeStateChanged.connect(self.roi_tree_changed)

    def load_ROI(self, path=None, params=None):
        try:
            if params is None:
                if path is None:
                    path = select_file(start_path=Path.home(),
                                       save=False,
                                       ext='xml')
                    if path != '':
                        params = Parameter.create(
                            title='Settings',
                            name='settings',
                            type='group',
                            children=ioxml.XML_file_to_parameter(path))

            if params is not None:
                self.clear_ROI()
                QtWidgets.QApplication.processEvents()

                for param in params:
                    if 'roi_type' in putils.iter_children(param, []):
                        self.settings.child(('ROIs')).addNew(
                            param.child(('roi_type')).value())
                    else:
                        self.settings.child(('ROIs')).addNew()
                # self.settings.child(('ROIs')).addChildren(params)
                QtWidgets.QApplication.processEvents()

                # settings = Parameter.create(title='Settings', name='settings', type='group')
                #
                # for param in params:
                #     settings.addChildren(custom_tree.XML_string_to_parameter(custom_tree.parameter_to_xml_string(param)))

                self.set_roi(self.settings.child(('ROIs')).children(), params)

        except Exception as e:
            pass

    def set_roi(self, roi_params, roi_params_new):
        for child, new_child in zip(roi_params, roi_params_new):
            if 'group' not in child.opts['type']:
                child.setValue(new_child.value())
            else:
                self.set_roi(child.children(), new_child.children())
Example #51
0
class ObjectTree(QWidget, ComponentMixin):

    name = 'Object Tree'
    _stash = []

    preferences = Parameter.create(name='Preferences',
                                   children=[{
                                       'name': 'Preserve properties on reload',
                                       'type': 'bool',
                                       'value': False
                                   }, {
                                       'name': 'Clear all before each run',
                                       'type': 'bool',
                                       'value': True
                                   }, {
                                       'name': 'STL precision',
                                       'type': 'float',
                                       'value': .1
                                   }])

    sigObjectsAdded = pyqtSignal([list], [list, bool])
    sigObjectsRemoved = pyqtSignal(list)
    sigCQObjectSelected = pyqtSignal(object)
    sigAISObjectsSelected = pyqtSignal(list)
    sigItemChanged = pyqtSignal(QTreeWidgetItem, int)
    sigObjectPropertiesChanged = pyqtSignal()

    def __init__(self, parent):

        super(ObjectTree, self).__init__(parent)

        self.tree = tree = QTreeWidget(
            self, selectionMode=QAbstractItemView.ExtendedSelection)
        self.properties_editor = ParameterTree(self)

        tree.setHeaderHidden(True)
        tree.setItemsExpandable(False)
        tree.setRootIsDecorated(False)
        tree.setContextMenuPolicy(Qt.ActionsContextMenu)

        #forward itemChanged singal
        tree.itemChanged.connect(\
            lambda item,col: self.sigItemChanged.emit(item,col))
        #handle visibility changes form tree
        tree.itemChanged.connect(self.handleChecked)

        self.CQ = CQRootItem()
        self.Imports = ImportRootItem()
        self.Helpers = HelpersRootItem()

        root = tree.invisibleRootItem()
        root.addChild(self.CQ)
        root.addChild(self.Imports)
        root.addChild(self.Helpers)

        tree.expandToDepth(1)

        self._export_STL_action = \
            QAction('Export as STL',
                    self,
                    enabled=False,
                    triggered=lambda: \
                        self.export('stl',
                                    self.preferences['STL precision']))

        self._export_STEP_action = \
            QAction('Export as STEP',
                    self,
                    enabled=False,
                    triggered=lambda: \
                        self.export('step'))

        self._clear_current_action = QAction(icon('delete'),
                                             'Clear current',
                                             self,
                                             enabled=False,
                                             triggered=self.removeSelected)

        self._toolbar_actions = \
            [QAction(icon('delete-many'),'Clear all',self,triggered=self.removeObjects),
             self._clear_current_action,]

        self.prepareMenu()

        tree.itemSelectionChanged.connect(self.handleSelection)
        tree.customContextMenuRequested.connect(self.showMenu)

        self.prepareLayout()

    def prepareMenu(self):

        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)

        self._context_menu = QMenu(self)
        self._context_menu.addActions(self._toolbar_actions)
        self._context_menu.addActions(
            (self._export_STL_action, self._export_STEP_action))

    def prepareLayout(self):

        self._splitter = splitter((self.tree, self.properties_editor),
                                  stretch_factors=(2, 1),
                                  orientation=Qt.Vertical)
        layout(self, (self._splitter, ), top_widget=self)

        self._splitter.show()

    def showMenu(self, position):

        self._context_menu.exec_(self.tree.viewport().mapToGlobal(position))

    def menuActions(self):

        return {'Tools': [self._export_STL_action, self._export_STEP_action]}

    def toolbarActions(self):

        return self._toolbar_actions

    def addLines(self):

        origin = (0, 0, 0)
        ais_list = []

        for name, color, direction in zip(('X', 'Y', 'Z'),
                                          ('red', 'lawngreen', 'blue'),
                                          ((1, 0, 0), (0, 1, 0), (0, 0, 1))):
            line_placement = Geom_Line(
                gp_Ax1(gp_Pnt(*origin), gp_Dir(*direction)))
            line = AIS_Line(line_placement)
            line.SetColor(to_occ_color(color))

            self.Helpers.addChild(ObjectTreeItem(name, ais=line))

            ais_list.append(line)

        self.sigObjectsAdded.emit(ais_list)

    def _current_properties(self):

        current_params = {}
        for i in range(self.CQ.childCount()):
            child = self.CQ.child(i)
            current_params[child.properties['Name']] = child.properties

        return current_params

    def _restore_properties(self, obj, properties):

        for p in properties[obj.properties['Name']]:
            obj.properties[p.name()] = p.value()

    @pyqtSlot(dict, bool)
    @pyqtSlot(dict)
    def addObjects(self, objects, clean=False, root=None):

        if root is None:
            root = self.CQ

        request_fit_view = True if root.childCount() == 0 else False
        preserve_props = self.preferences['Preserve properties on reload']

        if preserve_props:
            current_props = self._current_properties()

        if clean or self.preferences['Clear all before each run']:
            self.removeObjects()

        ais_list = []

        #remove empty objects
        objects_f = {
            k: v
            for k, v in objects.items() if not is_obj_empty(v.shape)
        }

        for name, obj in objects_f.items():
            ais, shape_display = make_AIS(obj.shape, obj.options)

            child = ObjectTreeItem(name,
                                   shape=obj.shape,
                                   shape_display=shape_display,
                                   ais=ais,
                                   sig=self.sigObjectPropertiesChanged)

            if preserve_props and name in current_props:
                self._restore_properties(child, current_props)

            if child.properties['Visible']:
                ais_list.append(ais)

            root.addChild(child)

        if request_fit_view:
            self.sigObjectsAdded[list, bool].emit(ais_list, True)
        else:
            self.sigObjectsAdded[list].emit(ais_list)

    @pyqtSlot(object, str, object)
    def addObject(self, obj, name='', options={}):

        root = self.CQ

        ais, shape_display = make_AIS(obj, options)

        root.addChild(
            ObjectTreeItem(name,
                           shape=obj,
                           shape_display=shape_display,
                           ais=ais,
                           sig=self.sigObjectPropertiesChanged))

        self.sigObjectsAdded.emit([ais])

    @pyqtSlot(list)
    @pyqtSlot()
    def removeObjects(self, objects=None):

        if objects:
            removed_items_ais = [self.CQ.takeChild(i).ais for i in objects]
        else:
            removed_items_ais = [ch.ais for ch in self.CQ.takeChildren()]

        self.sigObjectsRemoved.emit(removed_items_ais)

    @pyqtSlot(bool)
    def stashObjects(self, action: bool):

        if action:
            self._stash = self.CQ.takeChildren()
            removed_items_ais = [ch.ais for ch in self._stash]
            self.sigObjectsRemoved.emit(removed_items_ais)
        else:
            self.removeObjects()
            self.CQ.addChildren(self._stash)
            ais_list = [el.ais for el in self._stash]
            self.sigObjectsAdded.emit(ais_list)

    @pyqtSlot()
    def removeSelected(self):

        ixs = self.tree.selectedIndexes()
        rows = [ix.row() for ix in ixs]

        self.removeObjects(rows)

    def export(self, export_type, precision=None):

        items = self.tree.selectedItems()

        # if CQ models is selected get all children
        if [item for item in items if item is self.CQ]:
            CQ = self.CQ
            shapes = [CQ.child(i).shape for i in range(CQ.childCount())]
        # otherwise collect all selected children of CQ
        else:
            shapes = [item.shape for item in items if item.parent() is self.CQ]

        fname = get_save_filename(export_type)
        if fname is not '':
            export(shapes, export_type, fname, precision)

    @pyqtSlot()
    def handleSelection(self):

        items = self.tree.selectedItems()
        if len(items) == 0:
            self._export_STL_action.setEnabled(False)
            self._export_STEP_action.setEnabled(False)
            return

        # emit list of all selected ais objects (might be empty)
        ais_objects = [item.ais for item in items if item.parent() is self.CQ]
        self.sigAISObjectsSelected.emit(ais_objects)

        # handle context menu and emit last selected CQ  object (if present)
        item = items[-1]
        if item.parent() is self.CQ:
            self._export_STL_action.setEnabled(True)
            self._export_STEP_action.setEnabled(True)
            self._clear_current_action.setEnabled(True)
            self.sigCQObjectSelected.emit(item.shape)
            self.properties_editor.setParameters(item.properties,
                                                 showTop=False)
            self.properties_editor.setEnabled(True)
        elif item is self.CQ and item.childCount() > 0:
            self._export_STL_action.setEnabled(True)
            self._export_STEP_action.setEnabled(True)
        else:
            self._export_STL_action.setEnabled(False)
            self._export_STEP_action.setEnabled(False)
            self._clear_current_action.setEnabled(False)
            self.properties_editor.setEnabled(False)
            self.properties_editor.clear()

    @pyqtSlot(list)
    def handleGraphicalSelection(self, shapes):

        self.tree.clearSelection()

        CQ = self.CQ
        for i in range(CQ.childCount()):
            item = CQ.child(i)
            for shape in shapes:
                if item.shape_display.wrapped.IsEqual(shape):
                    item.setSelected(True)

    @pyqtSlot(QTreeWidgetItem, int)
    def handleChecked(self, item, col):

        if type(item) is ObjectTreeItem:
            if item.checkState(0):
                item.properties['Visible'] = True
            else:
                item.properties['Visible'] = False
Example #52
0
class PeakFinding(object):
    def __init__(self, parent = None):
        self.parent = parent

        self.d9 = Dock("Peak Finder", size=(1, 1))
        ## Dock 9: Peak finder
        self.w10 = ParameterTree()
        self.d9.addWidget(self.w10)
        #self.w11 = pg.LayoutWidget()
        #self.generatePowderBtn = QtGui.QPushButton('Generate Powder')
        #self.launchBtn = QtGui.QPushButton('Launch peak finder')
        #self.w11.addWidget(self.launchBtn, row=0,col=0)
        #self.w11.addWidget(self.generatePowderBtn, row=0, col=0)
        #self.d9.addWidget(self.w11)

        self.userUpdate = None
        self.doingUpdate = False

        # Peak finding
        self.hitParam_grp = 'Peak finder'
        self.hitParam_showPeaks_str = 'Show peaks found'
        self.hitParam_algorithm_str = 'Algorithm'
        # algorithm 0
        self.hitParam_algorithm0_str = 'None'
        # algorithm 1
        self.hitParam_alg1_npix_min_str = 'npix_min'
        self.hitParam_alg1_npix_max_str = 'npix_max'
        self.hitParam_alg1_amax_thr_str = 'amax_thr'
        self.hitParam_alg1_atot_thr_str = 'atot_thr'
        self.hitParam_alg1_son_min_str = 'son_min'
        self.hitParam_algorithm1_str = 'Droplet'
        self.hitParam_alg1_thr_low_str = 'thr_low'
        self.hitParam_alg1_thr_high_str = 'thr_high'
        self.hitParam_alg1_rank_str = 'rank'
        self.hitParam_alg1_radius_str = 'radius'
        self.hitParam_alg1_dr_str = 'dr'
        # algorithm 2
        self.hitParam_alg2_npix_min_str = 'npix_min'
        self.hitParam_alg2_npix_max_str = 'npix_max'
        self.hitParam_alg2_amax_thr_str = 'amax_thr'
        self.hitParam_alg2_atot_thr_str = 'atot_thr'
        self.hitParam_alg2_son_min_str = 'son_min'
        self.hitParam_algorithm2_str = 'FloodFill'
        self.hitParam_alg2_thr_str = 'thr'
        self.hitParam_alg2_r0_str = 'r0'
        self.hitParam_alg2_dr_str = 'dr'
        # algorithm 3
        self.hitParam_alg3_npix_min_str = 'npix_min'
        self.hitParam_alg3_npix_max_str = 'npix_max'
        self.hitParam_alg3_amax_thr_str = 'amax_thr'
        self.hitParam_alg3_atot_thr_str = 'atot_thr'
        self.hitParam_alg3_son_min_str = 'son_min'
        self.hitParam_algorithm3_str = 'Ranker'
        self.hitParam_alg3_rank_str = 'rank'
        self.hitParam_alg3_r0_str = 'r0'
        self.hitParam_alg3_dr_str = 'dr'
        # algorithm 4
        self.hitParam_alg4_npix_min_str = 'npix_min'
        self.hitParam_alg4_npix_max_str = 'npix_max'
        self.hitParam_alg4_amax_thr_str = 'amax_thr'
        self.hitParam_alg4_atot_thr_str = 'atot_thr'
        self.hitParam_alg4_son_min_str = 'son_min'
        self.hitParam_algorithm4_str = 'iDroplet'
        self.hitParam_alg4_thr_low_str = 'thr_low'
        self.hitParam_alg4_thr_high_str = 'thr_high'
        self.hitParam_alg4_rank_str = 'rank'
        self.hitParam_alg4_r0_str = 'radius'
        self.hitParam_alg4_dr_str = 'dr'

        self.hitParam_outDir_str = 'Output directory'
        self.hitParam_runs_str = 'Run(s)'
        self.hitParam_queue_str = 'queue'
        self.hitParam_cpu_str = 'CPUs'
        self.hitParam_psanaq_str = 'psanaq'
        self.hitParam_psnehq_str = 'psnehq'
        self.hitParam_psfehq_str = 'psfehq'
        self.hitParam_psnehprioq_str = 'psnehprioq'
        self.hitParam_psfehprioq_str = 'psfehprioq'
        self.hitParam_psnehhiprioq_str = 'psnehhiprioq'
        self.hitParam_psfehhiprioq_str = 'psfehhiprioq'
        self.hitParam_psdebugq_str = 'psdebugq'
        self.hitParam_noe_str = 'Number of events to process'
        self.hitParam_threshold_str = 'Indexable number of peaks'
        self.hitParam_launch_str = 'Launch peak finder'
        self.hitParam_extra_str = 'Extra parameters'

        self.save_minPeaks_str = 'Minimum number of peaks'
        self.save_maxPeaks_str = 'Maximum number of peaks'
        self.save_minRes_str = 'Minimum resolution (pixels)'
        self.save_sample_str = 'Sample name'

        self.showPeaks = True
        self.peaks = None
        self.numPeaksFound = 0
        self.algorithm = 0
        self.algInitDone = False
        self.peaksMaxRes = 0
        self.classify = False

        self.hitParam_alg1_npix_min = 2.
        self.hitParam_alg1_npix_max = 20.
        self.hitParam_alg1_amax_thr = 0.
        self.hitParam_alg1_atot_thr = 1000.
        self.hitParam_alg1_son_min = 7.
        self.hitParam_alg1_thr_low = 250.
        self.hitParam_alg1_thr_high = 600.
        self.hitParam_alg1_rank = 2
        self.hitParam_alg1_radius = 2
        self.hitParam_alg1_dr = 1
        # self.hitParam_alg2_npix_min = 1.
        # self.hitParam_alg2_npix_max = 5000.
        # self.hitParam_alg2_amax_thr = 1.
        # self.hitParam_alg2_atot_thr = 1.
        # self.hitParam_alg2_son_min = 1.
        # self.hitParam_alg2_thr = 10.
        # self.hitParam_alg2_r0 = 1.
        # self.hitParam_alg2_dr = 0.05
        # self.hitParam_alg3_npix_min = 5.
        # self.hitParam_alg3_npix_max = 5000.
        # self.hitParam_alg3_amax_thr = 0.
        # self.hitParam_alg3_atot_thr = 0.
        # self.hitParam_alg3_son_min = 4.
        # self.hitParam_alg3_rank = 3
        # self.hitParam_alg3_r0 = 5.
        # self.hitParam_alg3_dr = 0.05
        # self.hitParam_alg4_npix_min = 1.
        # self.hitParam_alg4_npix_max = 45.
        # self.hitParam_alg4_amax_thr = 800.
        # self.hitParam_alg4_atot_thr = 0
        # self.hitParam_alg4_son_min = 7.
        # self.hitParam_alg4_thr_low = 200.
        # self.hitParam_alg4_thr_high = self.hitParam_alg1_thr_high
        # self.hitParam_alg4_rank = 3
        # self.hitParam_alg4_r0 = 2
        # self.hitParam_alg4_dr = 1
        self.hitParam_outDir = self.parent.psocakeDir
        self.hitParam_outDir_overridden = False
        self.hitParam_runs = ''
        self.hitParam_queue = self.hitParam_psanaq_str
        self.hitParam_cpus = 24
        self.hitParam_noe = -1
        self.hitParam_threshold = 15 # usually crystals with less than 15 peaks are not indexable

        self.minPeaks = 15
        self.maxPeaks = 2048
        self.minRes = -1
        self.sample = 'sample'
        self.profile = 0
        self.hitParam_extra = ''

        self.params = [
            {'name': self.hitParam_grp, 'type': 'group', 'children': [
                {'name': self.hitParam_showPeaks_str, 'type': 'bool', 'value': self.showPeaks,
                 'tip': "Show peaks found shot-to-shot"},
                {'name': self.hitParam_algorithm_str, 'type': 'list', 'values': {self.hitParam_algorithm1_str: 1,
                                                                                 self.hitParam_algorithm0_str: 0},
                 'value': self.algorithm},
                {'name': self.hitParam_algorithm1_str, 'visible': True, 'expanded': False, 'type': 'str', 'value': "",
                 'readonly': True, 'children': [
                    {'name': self.hitParam_alg1_npix_min_str, 'type': 'float', 'value': self.hitParam_alg1_npix_min,
                     'tip': "Only keep the peak if number of pixels above thr_low is above this value"},
                    {'name': self.hitParam_alg1_npix_max_str, 'type': 'float', 'value': self.hitParam_alg1_npix_max,
                     'tip': "Only keep the peak if number of pixels above thr_low is below this value"},
                    {'name': self.hitParam_alg1_amax_thr_str, 'type': 'float', 'value': self.hitParam_alg1_amax_thr,
                     'tip': "Only keep the peak if max value is above this value"},
                    {'name': self.hitParam_alg1_atot_thr_str, 'type': 'float', 'value': self.hitParam_alg1_atot_thr,
                     'tip': "Only keep the peak if integral inside region of interest is above this value"},
                    {'name': self.hitParam_alg1_son_min_str, 'type': 'float', 'value': self.hitParam_alg1_son_min,
                     'tip': "Only keep the peak if signal-over-noise is above this value"},
                    {'name': self.hitParam_alg1_thr_low_str, 'type': 'float', 'value': self.hitParam_alg1_thr_low,
                     'tip': "Grow a seed peak if above this value"},
                    {'name': self.hitParam_alg1_thr_high_str, 'type': 'float', 'value': self.hitParam_alg1_thr_high,
                     'tip': "Start a seed peak if above this value"},
                    {'name': self.hitParam_alg1_rank_str, 'type': 'int', 'value': self.hitParam_alg1_rank,
                     'tip': "region of integration is a square, (2r+1)x(2r+1)"},
                    {'name': self.hitParam_alg1_radius_str, 'type': 'int', 'value': self.hitParam_alg1_radius,
                     'tip': "region inside the region of interest"},
                    {'name': self.hitParam_alg1_dr_str, 'type': 'float', 'value': self.hitParam_alg1_dr,
                     'tip': "background region outside the region of interest"},
                ]},
                {'name': self.save_minPeaks_str, 'type': 'int', 'value': self.minPeaks,
                 'tip': "Index only if there are more Bragg peaks found"},
                {'name': self.save_maxPeaks_str, 'type': 'int', 'value': self.maxPeaks,
                 'tip': "Index only if there are less Bragg peaks found"},
                {'name': self.save_minRes_str, 'type': 'int', 'value': self.minRes,
                 'tip': "Index only if Bragg peak resolution is at least this"},
                {'name': self.save_sample_str, 'type': 'str', 'value': self.sample,
                 'tip': "Sample name saved inside cxi"},
                {'name': self.hitParam_outDir_str, 'type': 'str', 'value': self.hitParam_outDir},
                {'name': self.hitParam_runs_str, 'type': 'str', 'value': self.hitParam_runs},
                {'name': self.hitParam_queue_str, 'type': 'list', 'values': {self.hitParam_psfehhiprioq_str: 'psfehhiprioq',
                                                                             self.hitParam_psnehhiprioq_str: 'psnehhiprioq',
                                                                             self.hitParam_psfehprioq_str: 'psfehprioq',
                                                                             self.hitParam_psnehprioq_str: 'psnehprioq',
                                                                             self.hitParam_psfehq_str: 'psfehq',
                                                                             self.hitParam_psnehq_str: 'psnehq',
                                                                             self.hitParam_psanaq_str: 'psanaq',
                                                                             self.hitParam_psdebugq_str: 'psdebugq'},
                 'value': self.hitParam_queue, 'tip': "Choose queue"},
                {'name': self.hitParam_cpu_str, 'type': 'int', 'value': self.hitParam_cpus},
                {'name': self.hitParam_noe_str, 'type': 'int', 'value': self.hitParam_noe,
                 'tip': "number of events to process, default=-1 means process all events"},
                {'name': self.hitParam_extra_str, 'type': 'str', 'value': self.hitParam_extra, 'tip': "Extra peak finding flags"},
                {'name': self.hitParam_launch_str, 'type': 'action'},
            ]},
        ]

        self.p3 = Parameter.create(name='paramsPeakFinder', type='group', \
                                   children=self.params, expanded=True)
        self.w10.setParameters(self.p3, showTop=False)
        self.p3.sigTreeStateChanged.connect(self.change)
        #self.parent.connect(self.launchBtn, QtCore.SIGNAL("clicked()"), self.findPeaks)

    def digestRunList(self, runList):
        runsToDo = []
        if not runList:
            print "Run(s) is empty. Please type in the run number(s)."
            return runsToDo
        runLists = str(runList).split(",")
        for list in runLists:
            temp = list.split(":")
            if len(temp) == 2:
                for i in np.arange(int(temp[0]),int(temp[1])+1):
                    runsToDo.append(i)
            elif len(temp) == 1:
                runsToDo.append(int(temp[0]))
        return runsToDo

    def updateParam(self):
        if self.userUpdate is None:
            if self.parent.psocakeRunDir is not None:
                peakParamFname = self.parent.psocakeRunDir + '/peakParam.json'
                if os.path.exists(peakParamFname):
                    with open(peakParamFname) as infile:
                        d = json.load(infile)
                        if d[self.hitParam_algorithm_str] == 1:
                            # Update variables
                            try:
                                self.hitParam_alg1_npix_min = d[self.hitParam_alg1_npix_min_str]
                                self.hitParam_alg1_npix_max = d[self.hitParam_alg1_npix_max_str]
                                self.hitParam_alg1_amax_thr = d[self.hitParam_alg1_amax_thr_str]
                                self.hitParam_alg1_atot_thr = d[self.hitParam_alg1_atot_thr_str]
                                self.hitParam_alg1_son_min = d[self.hitParam_alg1_son_min_str]
                                self.hitParam_alg1_thr_low = d[self.hitParam_alg1_thr_low_str]
                                self.hitParam_alg1_thr_high = d[self.hitParam_alg1_thr_high_str]
                                self.hitParam_alg1_rank = int(d[self.hitParam_alg1_rank_str])
                                self.hitParam_alg1_radius = int(d[self.hitParam_alg1_radius_str])
                                self.hitParam_alg1_dr = d[self.hitParam_alg1_dr_str]
                                # Update GUI
                                self.doingUpdate = True
                                #self.p3.param(self.hitParam_grp, self.hitParam_algorithm_str).setValue(self.algorithm)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_npix_min_str).setValue(
                                    self.hitParam_alg1_npix_min)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_npix_max_str).setValue(
                                    self.hitParam_alg1_npix_max)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_amax_thr_str).setValue(
                                    self.hitParam_alg1_amax_thr)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_atot_thr_str).setValue(
                                    self.hitParam_alg1_atot_thr)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_son_min_str).setValue(
                                    self.hitParam_alg1_son_min)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_thr_low_str).setValue(
                                    self.hitParam_alg1_thr_low)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_thr_high_str).setValue(
                                    self.hitParam_alg1_thr_high)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_rank_str).setValue(
                                    self.hitParam_alg1_rank)
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_radius_str).setValue(
                                    self.hitParam_alg1_radius)
                                self.doingUpdate = False
                                self.p3.param(self.hitParam_grp, self.hitParam_algorithm1_str, self.hitParam_alg1_dr_str).setValue(
                                    self.hitParam_alg1_dr)
                            except:
                                pass

    def writeStatus(self, fname, d):
        json.dump(d, open(fname, 'w'))

    # Launch peak finding
    def findPeaks(self):
        self.parent.thread.append(LaunchPeakFinder.LaunchPeakFinder(self.parent)) # send parent parameters with self
        self.parent.thread[self.parent.threadCounter].launch(self.parent.experimentName, self.parent.detInfo)
        self.parent.threadCounter+=1
        # Save peak finding parameters
        runsToDo = self.digestRunList(self.hitParam_runs)
        for run in runsToDo:
            peakParamFname = self.parent.psocakeDir+'/r'+str(run).zfill(4)+'/peakParam.json'
            d = {self.hitParam_algorithm_str: self.algorithm,
                 self.hitParam_alg1_npix_min_str: self.hitParam_alg1_npix_min,
                 self.hitParam_alg1_npix_max_str: self.hitParam_alg1_npix_max,
                 self.hitParam_alg1_amax_thr_str: self.hitParam_alg1_amax_thr,
                 self.hitParam_alg1_atot_thr_str: self.hitParam_alg1_atot_thr,
                 self.hitParam_alg1_son_min_str: self.hitParam_alg1_son_min,
                 self.hitParam_alg1_thr_low_str: self.hitParam_alg1_thr_low,
                 self.hitParam_alg1_thr_high_str: self.hitParam_alg1_thr_high,
                 self.hitParam_alg1_rank_str: self.hitParam_alg1_rank,
                 self.hitParam_alg1_radius_str: self.hitParam_alg1_radius,
                 self.hitParam_alg1_dr_str: self.hitParam_alg1_dr}
            self.writeStatus(peakParamFname, d)

    # 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.hitParam_grp:
            if path[1] == self.hitParam_algorithm_str:
                self.algInitDone = False
                self.updateAlgorithm(data)
            elif path[1] == self.hitParam_showPeaks_str:
                self.showPeaks = data
                self.drawPeaks()
            elif path[1] == self.hitParam_outDir_str:
                self.hitParam_outDir = data
                self.hitParam_outDir_overridden = True
            elif path[1] == self.hitParam_runs_str:
                self.hitParam_runs = data
            elif path[1] == self.hitParam_queue_str:
                self.hitParam_queue = data
            elif path[1] == self.hitParam_cpu_str:
                self.hitParam_cpus = data
            elif path[1] == self.hitParam_noe_str:
                self.hitParam_noe = data
            elif path[1] == self.hitParam_threshold_str:
                self.hitParam_threshold = data
            elif path[1] == self.hitParam_launch_str:
                self.findPeaks()
            elif path[1] == self.save_minPeaks_str:
                self.minPeaks = data
            elif path[1] == self.save_maxPeaks_str:
                self.maxPeaks = data
            elif path[1] == self.save_minRes_str:
                self.minRes = data
            elif path[1] == self.save_sample_str:
                self.sample = data
            elif path[1] == self.hitParam_extra_str:
                self.hitParam_extra = data
            elif path[2] == self.hitParam_alg1_npix_min_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_npix_min = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_npix_max_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_npix_max = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_amax_thr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_amax_thr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_atot_thr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_atot_thr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_son_min_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_son_min = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_thr_low_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_thr_low = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_thr_high_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_thr_high = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_rank_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_rank = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_radius_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_radius = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()
            elif path[2] == self.hitParam_alg1_dr_str and path[1] == self.hitParam_algorithm1_str:
                self.hitParam_alg1_dr = data
                self.algInitDone = False
                self.userUpdate = True
                if self.showPeaks and self.doingUpdate is False:
                    self.updateClassification()

    def updateAlgorithm(self, data):
        self.algorithm = data
        self.algInitDone = False
        self.updateClassification()
        if self.parent.args.v >= 1: print "##### Done updateAlgorithm: ", self.algorithm

    def saveCheetahFormat(self, arg):
        if arg == 'lcls':
            if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                dim0 = 8 * 185
                dim1 = 4 * 388
            elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                dim0 = 1920 #FIXME: rayonix can be binned
                dim1 = 1920
            elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                dim0 = 1920 #FIXME: rayonix can be binned
                dim1 = 1920
            else:
                dim0 = 0
                dim1 = 0

            if dim0 > 0:
                maxNumPeaks = 2048
                if self.parent.index.hiddenCXI is not None:
                    myHdf5 = h5py.File(self.parent.index.hiddenCXI, 'w')
                    grpName = "/entry_1/result_1"
                    dset_nPeaks = "/nPeaks"
                    dset_posX = "/peakXPosRaw"
                    dset_posY = "/peakYPosRaw"
                    dset_atot = "/peakTotalIntensity"
                    if grpName in myHdf5:
                        del myHdf5[grpName]
                    grp = myHdf5.create_group(grpName)
                    myHdf5.create_dataset(grpName + dset_nPeaks, (1,), dtype='int')
                    myHdf5.create_dataset(grpName + dset_posX, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))
                    myHdf5.create_dataset(grpName + dset_posY, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))
                    myHdf5.create_dataset(grpName + dset_atot, (1, maxNumPeaks), dtype='float32', chunks=(1, maxNumPeaks))

                    myHdf5.create_dataset("/LCLS/detector_1/EncoderValue", (1,), dtype=float)
                    myHdf5.create_dataset("/LCLS/photon_energy_eV", (1,), dtype=float)
                    dset = myHdf5.create_dataset("/entry_1/data_1/data", (1, dim0, dim1), dtype=float)

                    # Convert calib image to cheetah image
                    img = np.zeros((dim0, dim1))
                    counter = 0
                    if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                        for quad in range(4):
                            for seg in range(8):
                                img[seg * 185:(seg + 1) * 185, quad * 388:(quad + 1) * 388] = self.parent.calib[counter, :, :]
                                counter += 1
                    elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                        img = self.parent.calib[:, :] # psana format
                    elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                        img = self.parent.calib[:, :]  # psana format
                    else:
                        print "saveCheetahFormat not implemented"

                    peaks = self.peaks.copy()
                    nPeaks = peaks.shape[0]

                    if nPeaks > maxNumPeaks:
                        peaks = peaks[:maxNumPeaks]
                        nPeaks = maxNumPeaks
                    for i, peak in enumerate(peaks):
                        seg, row, col, npix, amax, atot, rcent, ccent, rsigma, csigma, rmin, rmax, cmin, cmax, bkgd, rms, son = peak[0:17]
                        if 'cspad' in self.parent.detInfo.lower() and 'cxi' in self.parent.experimentName:
                            cheetahRow, cheetahCol = self.convert_peaks_to_cheetah(seg, row, col)
                            myHdf5[grpName + dset_posX][0, i] = cheetahCol
                            myHdf5[grpName + dset_posY][0, i] = cheetahRow
                            myHdf5[grpName + dset_atot][0, i] = atot
                        elif 'rayonix' in self.parent.detInfo.lower() and 'mfx' in self.parent.experimentName:
                            myHdf5[grpName + dset_posX][0, i] = col
                            myHdf5[grpName + dset_posY][0, i] = row
                            myHdf5[grpName + dset_atot][0, i] = atot
                        elif 'rayonix' in self.parent.detInfo.lower() and 'xpp' in self.parent.experimentName:
                            myHdf5[grpName + dset_posX][0, i] = col
                            myHdf5[grpName + dset_posY][0, i] = row
                            myHdf5[grpName + dset_atot][0, i] = atot
                    myHdf5[grpName + dset_nPeaks][0] = nPeaks

                    if self.parent.args.v >= 1: print "hiddenCXI clen (mm): ", self.parent.clen * 1000.
                    myHdf5["/LCLS/detector_1/EncoderValue"][0] = self.parent.clen * 1000.  # mm
                    myHdf5["/LCLS/photon_energy_eV"][0] = self.parent.photonEnergy
                    dset[0, :, :] = img
                    myHdf5.close()

    def updateClassification(self):
        if self.parent.calib is not None:
            if self.parent.mk.streakMaskOn:
                self.parent.mk.initMask()
                self.parent.mk.streakMask = self.parent.mk.StreakMask.getStreakMaskCalib(self.parent.evt)
                if self.parent.mk.streakMask is None:
                    self.parent.mk.streakMaskAssem = None
                else:
                    self.parent.mk.streakMaskAssem = self.parent.det.image(self.parent.evt, self.parent.mk.streakMask)
                self.algInitDone = False

            self.parent.mk.displayMask()

            # update combined mask
            self.parent.mk.combinedMask = np.ones_like(self.parent.calib)
            if self.parent.mk.streakMask is not None and self.parent.mk.streakMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.streakMask
            if self.parent.mk.userMask is not None and self.parent.mk.userMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.userMask
            if self.parent.mk.psanaMask is not None and self.parent.mk.psanaMaskOn is True:
                self.parent.mk.combinedMask *= self.parent.mk.psanaMask

            # Peak output (0-16):
            # 0 seg
            # 1 row
            # 2 col
            # 3 npix: no. of pixels in the ROI intensities above threshold
            # 4 amp_max: max intensity
            # 5 amp_tot: sum of intensities
            # 6,7: row_cgrav: center of mass
            # 8,9: row_sigma
            # 10,11,12,13: minimum bounding box
            # 14: background
            # 15: noise
            # 16: signal over noise
            if self.algorithm == 0: # No peak algorithm
                self.peaks = None
                self.drawPeaks()
            else:
                # Only initialize the hit finder algorithm once
                if self.algInitDone is False:
                    self.windows = None
                    self.alg = []
                    self.alg = PyAlgos(windows=self.windows, mask=self.parent.mk.combinedMask, pbits=0)

                    # set peak-selector parameters:
                    if self.algorithm == 1:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg1_npix_min, npix_max=self.hitParam_alg1_npix_max, \
                                                amax_thr=self.hitParam_alg1_amax_thr, atot_thr=self.hitParam_alg1_atot_thr, \
                                                son_min=self.hitParam_alg1_son_min)
                    elif self.algorithm == 2:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg2_npix_min, npix_max=self.hitParam_alg2_npix_max, \
                                                amax_thr=self.hitParam_alg2_amax_thr, atot_thr=self.hitParam_alg2_atot_thr, \
                                                son_min=self.hitParam_alg2_son_min)
                    elif self.algorithm == 3:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg3_npix_min, npix_max=self.hitParam_alg3_npix_max, \
                                                amax_thr=self.hitParam_alg3_amax_thr, atot_thr=self.hitParam_alg3_atot_thr, \
                                                son_min=self.hitParam_alg3_son_min)
                    elif self.algorithm == 4:
                        self.alg.set_peak_selection_pars(npix_min=self.hitParam_alg4_npix_min, npix_max=self.hitParam_alg4_npix_max, \
                                                amax_thr=self.hitParam_alg4_amax_thr, atot_thr=self.hitParam_alg4_atot_thr, \
                                                son_min=self.hitParam_alg4_son_min)
                    self.algInitDone = True

                self.parent.calib = self.parent.calib * 1.0 # Neccessary when int is returned
                if self.algorithm == 1:
                    # v1 - aka Droplet Finder - two-threshold peak-finding algorithm in restricted region
                    #                           around pixel with maximal intensity.
                    self.peakRadius = int(self.hitParam_alg1_radius)
                    self.peaks = self.alg.peak_finder_v4r2(self.parent.calib,
                                                           thr_low=self.hitParam_alg1_thr_low,
                                                           thr_high=self.hitParam_alg1_thr_high,
                                                           rank=int(self.hitParam_alg1_rank),
                                                           r0=self.peakRadius,
                                                           dr=self.hitParam_alg1_dr)
                elif self.algorithm == 2:
                    # v2 - define peaks for regions of connected pixels above threshold
                    self.peakRadius = int(self.hitParam_alg2_r0)
                    self.peaks = self.alg.peak_finder_v2(self.parent.calib, thr=self.hitParam_alg2_thr, r0=self.peakRadius, dr=self.hitParam_alg2_dr)
                elif self.algorithm == 3:
                    self.peakRadius = int(self.hitParam_alg3_r0)
                    self.peaks = self.alg.peak_finder_v3(self.parent.calib, rank=self.hitParam_alg3_rank, r0=self.peakRadius, dr=self.hitParam_alg3_dr)
                elif self.algorithm == 4:
                    # v4 - aka Droplet Finder - the same as v1, but uses rank and r0 parameters in stead of common radius.
                    self.peakRadius = int(self.hitParam_alg4_r0)
                    self.peaks = self.alg.peak_finder_v4(self.parent.calib, thr_low=self.hitParam_alg4_thr_low, thr_high=self.hitParam_alg4_thr_high,
                                               rank=self.hitParam_alg4_rank, r0=self.peakRadius,  dr=self.hitParam_alg4_dr)
                self.numPeaksFound = self.peaks.shape[0]

                if self.parent.args.v >= 1: print "Num peaks found: ", self.numPeaksFound, self.peaks.shape

                # update clen
                self.parent.geom.updateClen('lcls')

                self.parent.index.clearIndexedPeaks()

                # Save image and peaks in cheetah cxi file
                self.saveCheetahFormat('lcls')

                if self.parent.index.showIndexedPeaks: self.parent.index.updateIndex()

                self.drawPeaks()
            if self.parent.args.v >= 1: print "Done updateClassification"

    def convert_peaks_to_cheetah(self, s, r, c) :
        """Converts seg, row, col assuming (32,185,388)
           to cheetah 2-d table row and col (8*185, 4*388)
        """
        segs, rows, cols = (32,185,388)
        row2d = (int(s)%8) * rows + int(r) # where s%8 is a segment in quad number [0,7]
        col2d = (int(s)/8) * cols + int(c) # where s/8 is a quad number [0,3]
        return row2d, col2d

    def getMaxRes(self, posX, posY, centerX, centerY):
        maxRes = np.max(np.sqrt((posX-centerX)**2 + (posY-centerY)**2))
        if self.parent.args.v >= 1: print "maxRes: ", maxRes
        return maxRes # in pixels

    def drawPeaks(self):
        self.parent.img.clearPeakMessage()
        if self.showPeaks:
            if self.peaks is not None and self.numPeaksFound > 0:
                self.ix = self.parent.det.indexes_x(self.parent.evt)
                self.iy = self.parent.det.indexes_y(self.parent.evt)
                if self.ix is None:
                    (_, dim0, dim1) = self.parent.calib.shape
                    self.iy = np.tile(np.arange(dim0),[dim1, 1])
                    self.ix = np.transpose(self.iy)
                self.iX = np.array(self.ix, dtype=np.int64)
                self.iY = np.array(self.iy, dtype=np.int64)
                if len(self.iX.shape)==2:
                    self.iX = np.expand_dims(self.iX,axis=0)
                    self.iY = np.expand_dims(self.iY,axis=0)
                cenX = self.iX[np.array(self.peaks[:,0],dtype=np.int64),np.array(self.peaks[:,1],dtype=np.int64),np.array(self.peaks[:,2],dtype=np.int64)] + 0.5
                cenY = self.iY[np.array(self.peaks[:,0],dtype=np.int64),np.array(self.peaks[:,1],dtype=np.int64),np.array(self.peaks[:,2],dtype=np.int64)] + 0.5
                self.peaksMaxRes = self.getMaxRes(cenX, cenY, self.parent.cx, self.parent.cy)
                diameter = self.peakRadius*2+1
                self.parent.img.peak_feature.setData(cenX, cenY, symbol='s', \
                                          size=diameter, brush=(255,255,255,0), \
                                          pen=pg.mkPen({'color': "c", 'width': 4}), pxMode=False) #FF0
                # Write number of peaks found
                xMargin = 5 # pixels
                yMargin = 0  # pixels
                maxX = np.max(self.ix) + xMargin
                maxY = np.max(self.iy) - yMargin
                myMessage = '<div style="text-align: center"><span style="color: cyan; font-size: 12pt;">Peaks=' + \
                            str(self.numPeaksFound) + ' <br>Res=' + str(int(self.peaksMaxRes)) + '<br></span></div>'
                self.parent.img.peak_text = pg.TextItem(html=myMessage, anchor=(0, 0))
                self.parent.img.w1.getView().addItem(self.parent.img.peak_text)
                self.parent.img.peak_text.setPos(maxX, maxY)
            else:
                self.parent.img.peak_feature.setData([], [], pxMode=False)
                self.parent.img.peak_text = pg.TextItem(html='', anchor=(0, 0))
                self.parent.img.w1.getView().addItem(self.parent.img.peak_text)
                self.parent.img.peak_text.setPos(0,0)
        else:
            self.parent.img.peak_feature.setData([], [], pxMode=False)
        if self.parent.args.v >= 1: print "Done updatePeaks"
Example #53
0
 def addParaTree(self):
     'Add parameter tree for filter and sort'
     self.ptreeItem = pplot.ParaTreeItem(self.opts.filterParameters)
     ptree = ParameterTree()
     ptree.setParameters(self.ptreeItem.paraTree, showTop=False)
     self.addLayoutWidget(ptree, 6, 0, -1, 2 )
Example #54
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"
Example #55
0
class JoystickButtonsSelection(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setupUI()

        self.selection = None

        pygame.init()
        pygame.joystick.init()
        # width, height = 64 * 10, 64 * 8
        # self.screen = pygame.display.set_mode((width, height))
        joystick_count = pygame.joystick.get_count()
        for ind in range(joystick_count):
            joystick = pygame.joystick.Joystick(ind)
            joystick.init()
        self.startTimer(10)

    def timerEvent(self, event):
        for event in pygame.event.get():  # User did something.
            if 'joy' in event.dict:
                self.settings.child(('joystickID')).setValue(event.joy)
                self.selection = dict(joy=event.joy)
            if event.type == pygame.QUIT:  # If user clicked close.
                self.reject()
            elif event.type == pygame.JOYBUTTONDOWN or event.type == pygame.JOYBUTTONUP:
                self.settings.child(('buttonID')).show(True)
                self.settings.child(('axisID')).show(False)
                self.settings.child(('hatID')).show(False)
                self.settings.child(('axis_value')).show(False)
                self.settings.child(('hat_value1')).show(False)
                self.settings.child(('hat_value2')).show(False)
                self.settings.child(('buttonID')).setValue(event.button)
                self.selection.update(dict(button=event.button))
            elif event.type == pygame.JOYAXISMOTION:
                self.settings.child(('buttonID')).show(False)
                self.settings.child(('axisID')).show(True)
                self.settings.child(('hatID')).show(False)
                self.settings.child(('axis_value')).show(True)
                self.settings.child(('axisID')).setValue(event.axis)
                self.settings.child(('axis_value')).setValue(event.value)
                self.settings.child(('hat_value1')).show(False)
                self.settings.child(('hat_value2')).show(False)
                self.selection.update(dict(axis=event.axis, value=event.value))
            elif event.type == pygame.JOYHATMOTION:
                self.settings.child(('buttonID')).show(False)
                self.settings.child(('axisID')).show(False)
                self.settings.child(('hatID')).show(True)
                self.settings.child(('axis_value')).show(True)
                self.settings.child(('hat_value1')).show(True)
                self.settings.child(('hat_value2')).show(True)
                self.settings.child(('hat_value1')).setValue(event.value[0])
                self.settings.child(('hat_value2')).setValue(event.value[1])
                self.selection.update(dict(hat=event.hat, value=event.value))

    def setupUI(self):
        layout = QtWidgets.QVBoxLayout()
        self.setLayout(layout)
        label = QtWidgets.QLabel(
            'Press a button or move an axis on the Joystick:')
        layout.addWidget(label)

        params = [
            {
                'title': 'Joystick ID',
                'name': 'joystickID',
                'type': 'int',
                'value': -1
            },
            {
                'title': 'Button ID',
                'name': 'buttonID',
                'type': 'int',
                'value': -1,
                'visible': False
            },
            {
                'title': 'Axis ID',
                'name': 'axisID',
                'type': 'int',
                'value': -1,
                'visible': False
            },
            {
                'title': 'Value:',
                'name': 'axis_value',
                'type': 'float',
                'value': 0.,
                'visible': False
            },
            {
                'title': 'Hat ID',
                'name': 'hatID',
                'type': 'int',
                'value': -1,
                'visible': False
            },
            {
                'title': 'Value x:',
                'name': 'hat_value1',
                'type': 'int',
                'value': 0,
                'visible': False
            },
            {
                'title': 'Value y:',
                'name': 'hat_value2',
                'type': 'int',
                'value': 0,
                'visible': False
            },
        ]

        self.settings = Parameter.create(name='settings',
                                         type='group',
                                         children=params)
        self.settings_tree = ParameterTree()
        # tree.setMinimumWidth(400)
        #self.settings_tree.setMinimumHeight(500)
        self.settings_tree.setParameters(self.settings, showTop=False)

        layout.addWidget(self.settings_tree)

        buttonBox = QtWidgets.QDialogButtonBox()
        buttonBox.addButton(QtWidgets.QDialogButtonBox.Ok)
        buttonBox.addButton(QtWidgets.QDialogButtonBox.Cancel)
        layout.addWidget(buttonBox)

        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
Example #56
0
class BuildGui():
    def __init__(self, tree):
        """
        Test fixture
        """
        
        self.basename = '/Users/pbmanis/Documents/data/MRK_Pyramidal'        
        self.filename = None
        self.tree = tree
        print('tree: ', tree)
        self.mainwin = pg.Qt.QtGui.QMainWindow()
        self.win = pg.Qt.QtGui.QWidget()
        self.main_layout = pg.Qt.QtGui.QGridLayout()  # top level layout for the window
        self.win.setLayout(self.main_layout)
        self.mainwin.setCentralWidget(self.win)
        self.mainwin.show()
        self.mainwin.setWindowTitle('Data Selection')
        self.mainwin.setGeometry( 100 , 100 , 1400 , 900)

        # build buttons at top of controls
        self.current_DSC = list(self.tree.keys())[0]
        self.btn_read = pg.Qt.QtGui.QPushButton("Read")
        self.btn_find = pg.Qt.QtGui.QPushButton('Find and Read')
        # use a nested grid layout for the buttons
        button_layout = pg.Qt.QtGui.QGridLayout()
        button_layout.addWidget(self.btn_read,    1, 0, 1, 1)  
        # button_layout.addWidget(self.btn_analyze, 0, 1, 1, 1)
        button_layout.addWidget(self.btn_find,    0, 0, 1, 1)

        # build parametertree in left column
        #
        ptreewidth = 320
        self.main_layout.setColumnMinimumWidth(0, ptreewidth)
        
        # analysis   # empty in test rig
        params = [
            {'name': 'Analysis', 'type': 'group', 'children': [],
            }]
                
        self.analysis_ptree = ParameterTree()
        self.analysis_ptreedata = Parameter.create(name='params', type='group', children=params)
        self.analysis_ptree.setParameters(self.analysis_ptreedata)

        self.ptree = ParameterTree()
        self.ptreedata = Parameter.create(name='dataset', type='group', children=self.setParams(0))
        self.ptree.setParameters(self.ptreedata) # add the table with granularity of "cells"
        self.prottree = ParameterTree()
        self.setProtocols()  # add the protocols
        
        # use a grid layout to hold the trees
        self.ptree_widget = pg.Qt.QtGui.QWidget()
        self.ptree_layout = pg.Qt.QtGui.QGridLayout()
        self.ptree_widget.setLayout(self.ptree_layout)
        self.ptree_layout.setSpacing(2)
        # ptree in row 1 col 0, 4 rows, 2 cols
        self.ptree_layout.addWidget(self.analysis_ptree)
        self.ptree_layout.addWidget(self.ptree) # Parameter Tree on left
        self.ptree_layout.addWidget(self.prottree)  # protocol tree just below
#        self.ptree_layout.setColumnStretch(0, 5)
        self.ptree_layout.setRowStretch(0, 5)
        self.ptree_layout.setRowStretch(1, 1)
        self.ptree_layout.setRowStretch(2, 1)

        # build plot window 
        self.plots_widget = pg.Qt.QtGui.QWidget()
        self.plots_layout = pg.Qt.QtGui.QGridLayout()
        self.plots_widget.setLayout(self.plots_layout)
        self.plots_layout.setContentsMargins(4, 4, 4, 4)
        self.plots_layout.setSpacing(2)

        self.plots = {}
        for panel in zip(['Wave', 'Average', 'PSTH'], [0, 14, 18], [1, 5, 5],):
            self.plots[panel[0]] = pg.PlotWidget()
            self.plots_layout.addWidget(self.plots[panel[0]], 
                    panel[1], 0, panel[2], 1)
            self.plots[panel[0]].getAxis('left').setLabel('V', color="#ff0000")
            self.plots[panel[0]].setTitle(panel[0], color="#ff0000")
            self.plots[panel[0]].getAxis('bottom').setLabel('t (sec)', color="#ff0000")
        
        self.main_layout.addWidget(self.plots_widget, 0, 2, 22, 1)
        self.main_layout.addLayout(button_layout, 0, 0, 1, 2)       
        self.main_layout.addWidget(self.ptree_widget, 1, 0, -1, 2)        
        self.retrieveAllParameters()
        
        # connect buttons and ptrees to actions
        self.ptreedata.sigTreeStateChanged.connect(self.update_DSC)
        self.prottreedata.sigTreeStateChanged.connect(self.get_current)
        self.btn_read.clicked.connect(self.read_run)
        # self.btn_analyze.clicked.connect(self.analyze)
        self.btn_find.clicked.connect(self.find_run)
        # print( self.MParams)
    
    def retrieveAllParameters(self):
        pass
    
    def read_run(self):
        pass
    
    def find_run(self):
        pass
    
    def setParams(self, isel):
        self.params = [
            {'name': 'Day', 'type': 'group', 'children': 
                [{'name': 'Slices/Cells', 'type': 'list', 'values': list(self.tree.keys()), 'value': list(self.tree.keys())[isel]}]
            }
        ]
        return self.params

    def setProtocols(self): 
        """
        Update the prototocls to correspond to the current parameters, top protocol selected
        """
        if self.tree == None:
            raise ValueError('setProtocols: Must set up read data before setting up protocols')
        self.protocols = [
            {'name': 'Protos', 'type': 'group', 'children': 
                [{'name': 'Protocols', 'type': 'list',
                'values': self.tree[self.current_DSC][:], 'value': self.tree[self.current_DSC][0]}]
            }
        ]
        self.prottreedata = Parameter.create(name='protocol', type='group', children=self.protocols)
        self.prottree.setParameters(self.prottreedata)
        self.current_protocol = self.tree[self.current_DSC][0]
        self.prottreedata.sigTreeStateChanged.connect(self.get_current)
        return self.protocols
        
    def get_current(self, param, changes):
        for param, change, data in changes:
            # path = self.prottreedata.childPath(param)
            # if path is not None:
            #     childName = '.'.join(path)
            # else:
            #     childName = param.name()
            self.current_protocol = data
            
    def update_DSC(self, param, changes):
        for param, change, data in changes:
            # path = self.ptreedata.childPath(param)
            # if path is not None:
            #     childName = '.'.join(path)
            # else:
            #     childName = param.name()
            self.current_DSC = data
            self.setProtocols()       
Example #57
0
class ConfigManager():
	def __init__(self):
		self.w = QtGui.QMainWindow()
		self.area = DockArea()
		self.w.setCentralWidget(self.area)
		self.w.resize(320,700)
		self.w.setWindowTitle('System Configuration')		
		self.paramDock = Dock("Parameters")
		self.area.addDock(self.paramDock, 'top')

		self.parameters = {
			'SCSYNTH.IP address': '127.0.0.1',
			'SCSYNTH.OSC port': 57110,
			'SCSYNTH.Start channel': 20,
			'SCSYNTH.Spread channels': True,
			'HARDWARE.Type': 'Serial',
			'HARDWARE.Serial Port': '/dev/cu.usbmodem1411',
			'HARDWARE.Number of sensors': 5
		}

		#np.save('./conf/ConfigManager', self.parameters)

		self.parameters = np.load('./conf/ConfigManager.npy').item()

		self.scsynthParameters = [
			{'name': 'SCSYNTH', 'type': 'group', 'children': [
				{'name': 'IP address', 'type': 'str', 'value': self.parameters['SCSYNTH.IP address']},
				{'name': 'OSC port', 'type': 'int', 'value': self.parameters['SCSYNTH.OSC port']},
				{'name': 'Start channel', 'type': 'int', 'value': self.parameters['SCSYNTH.Start channel']},
				{'name': 'Spread channels', 'type': 'bool', 'value': self.parameters['SCSYNTH.Spread channels']}
			]}
		]

		self.hardwareParameters = [
			{'name': 'HARDWARE', 'type': 'group', 'children': [
				{'name': 'Type', 'type': 'list', 'values': ['Serial', 'OSC'], 'value': self.parameters['HARDWARE.Type']},
				{'name': 'Serial Port', 'type': 'str', 'value': self.parameters['HARDWARE.Serial Port']},
				{'name': 'Number of sensors', 'type': 'int', 'value': self.parameters['HARDWARE.Number of sensors']},
			]}
		]




		self.p1 = Parameter.create(name='params', type='group', children=self.scsynthParameters)
		self.t1 = ParameterTree()
		self.t1.setParameters(self.p1, showTop=False)
		self.p1.sigTreeStateChanged.connect(self.change1)
		self.paramDock.addWidget(self.t1)

		self.p2 = Parameter.create(name='params', type='group', children=self.hardwareParameters)
		self.t2 = ParameterTree()
		self.t2.setParameters(self.p2, showTop=False)
		self.p2.sigTreeStateChanged.connect(self.change2)
		self.paramDock.addWidget(self.t2)

		self.analyzeBtn = QtGui.QPushButton('Analyze Datasets')
		self.paramDock.addWidget(self.analyzeBtn)
		self.analyzeBtn.clicked.connect(self.analyze)

		self.w.show()

	def change1(self, param, changes):
		for param, change, data in changes:
			print(param, change, data)
			path = self.p1.childPath(param)
			if path is not None:
				childName = '.'.join(path)
			else:
				childName = param.name()
			self.parameters[childName] = data
			np.save('./conf/ConfigManager', self.parameters)

	def change2(self, param, changes):
		for param, change, data in changes:
			print(param, change, data)
			path = self.p2.childPath(param)
			if path is not None:
				childName = '.'.join(path)
			else:
				childName = param.name()
			self.parameters[childName] = data
			np.save('./conf/ConfigManager', self.parameters)

	def analyze(self):
		for _file in os.listdir(sound_file_path):
			if len(_file.split('.')) > 1:
				if _file.split('.')[1] == 'wav':
					runEssentiaExtractor(feature_extractor_path, sound_file_path+_file, feature_file_path+_file.split('.')[0]+'.txt', str(sample_rate)+" "+str(fft_frame_size)+" "+str(fft_hop_size))
					saveFeatureDataAsNPY(feature_file_path+_file.split('.')[0], all_features)
					os.remove(feature_file_path+_file.split('.')[0]+'.txt')
Example #58
0
class HitFinder(object):
    def __init__(self, parent=None):
        self.parent = parent

        ## Dock: Hit finder
        self.dock = Dock("Hit Finder", size=(1, 1))
        self.win = ParameterTree()
        self.dock.addWidget(self.win)
        self.winL = pg.LayoutWidget()
        self.dock.addWidget(self.winL)

        # Hit finding
        self.spiParam_grp = 'Hit finder'
        self.spiParam_algorithm_str = 'Algorithm'
        # algorithm 0
        self.spiParam_algorithm0_str = 'None'
        # algorithm 1
        self.spiParam_algorithm1_str = 'chiSquared'
        self.spiParam_alg1_pruneInterval_str = 'prune interval'
        # algorithm 2
        self.spiParam_algorithm2_str = 'photonFinder'
        self.spiParam_alg2_threshold_str = 'ADUs per photon'
        self.spiParam_alg2_hitThreshold_str = 'Number of pixels for a hit'

        self.spiParam_outDir_str = 'Output directory'
        self.spiParam_runs_str = 'Run(s)'
        self.spiParam_queue_str = 'queue'
        self.spiParam_cpu_str = 'CPUs'
        self.spiParam_psanaq_str = 'psanaq'
        self.spiParam_psnehq_str = 'psnehq'
        self.spiParam_psfehq_str = 'psfehq'
        self.spiParam_psnehprioq_str = 'psnehprioq'
        self.spiParam_psfehprioq_str = 'psfehprioq'
        self.spiParam_psnehhiprioq_str = 'psnehhiprioq'
        self.spiParam_psfehhiprioq_str = 'psfehhiprioq'
        self.spiParam_psdebugq_str = 'psdebugq'
        self.spiParam_noe_str = 'Number of events to process'
        self.spiParam_launch_str = 'Launch hit finder'

        self.hitParam_grp = 'Find hits'
        self.hitParam_hitThresh_str = 'Hit threshold'
        self.hitParam_backgroundThresh_str = 'Background threshold'
        self.hitParam_sample_str = 'Sample name'
        self.hitParam_save_str = 'Save hits'

        # Init hit finding
        self.nPixels = 0
        self.spiAlgorithm = 2
        self.spiParam_alg1_pruneInterval = -1
        self.spiParam_alg2_threshold = 30
        self.spiParam_outDir = self.parent.psocakeDir
        self.spiParam_outDir_overridden = False
        self.spiParam_runs = ''
        self.spiParam_queue = self.spiParam_psanaq_str
        self.spiParam_cpus = 24
        self.spiParam_noe = -1
        self.hitParam_hitThresh = '-1'
        self.hitParam_backgroundThresh = '-1'
        self.hitParam_sample = "sample"

        self.params = [
            {
                'name':
                self.spiParam_grp,
                'type':
                'group',
                'children': [
                    {
                        'name': self.spiParam_algorithm_str,
                        'type': 'list',
                        'values': {
                            self.spiParam_algorithm2_str: 2,
                            self.spiParam_algorithm0_str: 0
                        },
                        'value': self.spiAlgorithm
                    },
                    #{'name': self.spiParam_algorithm1_str, 'visible': True, 'expanded': False, 'type': 'str', 'value': "",
                    # 'readonly': True, 'children': [
                    #    {'name': self.spiParam_alg1_pruneInterval_str, 'type': 'float', 'value': self.spiParam_alg1_pruneInterval,
                    #     'tip': "update running background"},
                    #]},
                    {
                        'name':
                        self.spiParam_algorithm2_str,
                        'visible':
                        True,
                        'expanded':
                        False,
                        'type':
                        'str',
                        'value':
                        "",
                        'readonly':
                        True,
                        'children': [
                            {
                                'name': self.spiParam_alg2_threshold_str,
                                'type': 'float',
                                'value': self.spiParam_alg2_threshold,
                                'tip': "search for pixels above ADU per photon"
                            },
                        ]
                    },
                    {
                        'name': self.spiParam_outDir_str,
                        'type': 'str',
                        'value': self.spiParam_outDir
                    },
                    {
                        'name':
                        self.spiParam_runs_str,
                        'type':
                        'str',
                        'value':
                        self.spiParam_runs,
                        'tip':
                        "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"
                    },
                    {
                        'name': self.spiParam_queue_str,
                        'type': 'list',
                        'values': {
                            self.spiParam_psfehhiprioq_str: 'psfehhiprioq',
                            self.spiParam_psnehhiprioq_str: 'psnehhiprioq',
                            self.spiParam_psfehprioq_str: 'psfehprioq',
                            self.spiParam_psnehprioq_str: 'psnehprioq',
                            self.spiParam_psfehq_str: 'psfehq',
                            self.spiParam_psnehq_str: 'psnehq',
                            self.spiParam_psanaq_str: 'psanaq',
                            self.spiParam_psdebugq_str: 'psdebugq'
                        },
                        'value': self.spiParam_queue,
                        'tip': "Choose queue"
                    },
                    {
                        'name': self.spiParam_cpu_str,
                        'type': 'int',
                        'value': self.spiParam_cpus
                    },
                    {
                        'name':
                        self.spiParam_noe_str,
                        'type':
                        'int',
                        'value':
                        self.spiParam_noe,
                        'tip':
                        "number of events to process, default=0 means process all events"
                    },
                    {
                        'name': self.spiParam_launch_str,
                        'type': 'action'
                    },
                ]
            },
            {
                'name':
                self.hitParam_grp,
                'type':
                'group',
                'children': [
                    {
                        'name':
                        self.hitParam_hitThresh_str,
                        'type':
                        'str',
                        'value':
                        self.hitParam_hitThresh,
                        'tip':
                        "Set as hit if number of pixels with photons above this value. Or specify a range using a colon, e.g. 100:10000."
                    },
                    {
                        'name':
                        self.hitParam_backgroundThresh_str,
                        'type':
                        'str',
                        'value':
                        self.hitParam_backgroundThresh,
                        'tip':
                        "Use as background if number of pixels with photons below this value. Or specify a range using a colon, e.g. 100:10000."
                    },
                    {
                        'name': self.hitParam_sample_str,
                        'type': 'str',
                        'value': self.hitParam_sample
                    },
                    {
                        'name': self.hitParam_save_str,
                        'type': 'action'
                    },
                ]
            },
        ]
        self.p8 = Parameter.create(name='paramsHitFinder', type='group', \
                                   children=self.params, expanded=True)
        self.win.setParameters(self.p8, showTop=False)
        self.p8.sigTreeStateChanged.connect(self.change)

    # Launch hit finding
    def findHits(self):
        self.parent.thread.append(LaunchHitFinder.HitFinder(
            self.parent))  # send parent parameters with self
        self.parent.thread[self.parent.threadCounter].findHits(
            self.parent.experimentName, self.parent.runNumber,
            self.parent.detInfo)
        self.parent.threadCounter += 1

    def setThreshold(self):
        self.parent.thread.append(
            LaunchHitConverter.LaunchHitConverter(
                self.parent))  # send parent parameters with self
        self.parent.thread[self.parent.threadCounter].launch(
            self.parent.experimentName, self.parent.detInfo)
        self.parent.threadCounter += 1

    # 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.spiParam_grp:
            if path[1] == self.spiParam_algorithm_str:
                self.spiAlgorithm = data
            elif path[1] == self.spiParam_outDir_str:
                self.spiParam_outDir = data
                self.spiParam_outDir_overridden = True
            elif path[1] == self.spiParam_runs_str:
                self.spiParam_runs = data
            elif path[1] == self.spiParam_queue_str:
                self.spiParam_queue = data
            elif path[1] == self.spiParam_cpu_str:
                self.spiParam_cpus = data
            elif path[1] == self.spiParam_noe_str:
                self.spiParam_noe = data
            elif path[1] == self.spiParam_launch_str:
                self.findHits()
            elif path[2] == self.spiParam_alg1_pruneInterval_str and path[
                    1] == self.spiParam_algorithm1_str:
                self.spiParam_alg1_pruneInterval = data
                self.updateHit()
            elif path[2] == self.spiParam_alg2_threshold_str and path[
                    1] == self.spiParam_algorithm2_str:
                self.spiParam_alg2_threshold = data
                self.updateHit()
        elif path[0] == self.hitParam_grp:
            if path[1] == self.hitParam_hitThresh_str:
                self.hitParam_hitThresh = data
            elif path[1] == self.hitParam_backgroundThresh_str:
                self.hitParam_backgroundThresh = data
            elif path[1] == self.hitParam_sample_str:
                self.hitParam_sample = data
            elif path[1] == self.hitParam_save_str:
                self.setThreshold()

    def updateHit(self):
        # Save a temporary mask
        if self.parent.mk.userMask is None:
            userMask = None
        else:
            userMask = self.parent.psocakeDir + "/r" + str(
                self.parent.runNumber).zfill(4) + "/tempUserMask.npy"
            np.save(userMask, self.parent.mk.userMask)

        worker = alg.HitFinder(
            self.parent.experimentName,
            self.parent.runNumber,
            self.parent.detInfo,
            self.parent.evt,
            self.parent.det,
            self.spiParam_alg2_threshold,
            streakMask_on=str(self.parent.mk.streakMaskOn),
            streakMask_sigma=self.parent.mk.streak_sigma,
            streakMask_width=self.parent.mk.streak_width,
            userMask_path=userMask,
            psanaMask_on=str(self.parent.mk.psanaMaskOn),
            psanaMask_calib=str(self.parent.mk.mask_calibOn),
            psanaMask_status=str(self.parent.mk.mask_statusOn),
            psanaMask_edges=str(self.parent.mk.mask_edgesOn),
            psanaMask_central=str(self.parent.mk.mask_centralOn),
            psanaMask_unbond=str(self.parent.mk.mask_unbondOn),
            psanaMask_unbondnrs=str(self.parent.mk.mask_unbondnrsOn))
        worker.findHits(self.parent.calib, self.parent.evt)
        self.nPixels = worker.nPixels
        self.indicatePhotons()
        if self.parent.args.v >= 1: print "self.nPixels: ", self.nPixels

    def indicatePhotons(self):
        self.parent.img.clearPeakMessage()
        self.parent.mk.displayMask()
        # Write number of pixels found containing photons
        xMargin = 5  # pixels
        yMargin = 0  # pixels
        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: cyan; font-size: 12pt;">Pixels=' + \
                    str(self.nPixels) + ' <br></span></div>'
        self.parent.img.peak_text = pg.TextItem(html=myMessage, anchor=(0, 0))
        self.parent.img.w1.getView().addItem(self.parent.img.peak_text)
        self.parent.img.peak_text.setPos(maxX, maxY)
class ChipWhispererAnalyzer(MainChip):
    """ Main ChipWhisperer Analyzer GUI Window Class.

    You can run this class from another Python script if you wish to, which gives you the ability
    to drive the system from another Python script, and not be forced to do everything through
    the GUI. Unfortunutly the GUI window still needs to open, as much of the program flow is
    done through PySide signals/slots.
    """

    MaxRecentFiles = 4
    def __init__(self):
        super(ChipWhispererAnalyzer, self).__init__(name="ChipWhisperer" + u"\u2122" + " Analyzer V2", icon="cwiconA")
        self.console = self.addConsole()

        self.results = ResultsPlotting()
        #self.resultsDialog = ResultsDialog(self)
        #self.addShowStats()

        self.addWaveforms()

        numPreprocessingStep = 4
        self.preprocessingListGUI = [None] * numPreprocessingStep


        self.utilList = []
        self.traceExplorerDialog = TraceExplorerDialog(self)
        self.traceExplorerDialog.scriptsUpdated.connect(self.reloadScripts)
        self.traceExplorerDialog.runScriptFunction.connect(self.runFunc)
        self.utilList.append(self.traceExplorerDialog)

        self.keyScheduleDialog = KeyScheduleDialog(self)

        self.scriptList = []
        self.scriptList.append({'widget':MainScriptEditor(self)})
        self.scriptList[0]['filename'] = self.scriptList[0]['widget'].filename
        self.scriptList[0]['dockname'] = 'Auto-Generated'
        self.defaultEditor = self.scriptList[0]
        autogen = (self.scriptList[0]['dockname'], self.scriptList[0]['filename'])

        self.cwParams = [
                {'name':'Attack Script', 'type':'group', 'children':[
                    {'name':'Filename', 'key':'attackfilelist', 'type':'filelist', 'values':{autogen:0}, 'value':0, 'editor':self.editorControl,},# , 'values':self.attackscripts, 'value':None
                    ]},
                {'name':'Traces', 'type':'group', 'children':[
                    {'name':'Points', 'type':'int', 'value':0, 'readonly':True},
                    {'name':'Traces', 'type':'int', 'value':0, 'readonly':True}
                    ]},

                {'name':'Pre-Processing', 'type':'group', 'children':
                    [{'name':'Module #%d' % step, 'type':'list', 'value':0, 'values':Preprocessing.listAll(self), 'set':partial(self.setPreprocessing, step)} for step in range(0, numPreprocessingStep)]},

                {'name':'Attack', 'type':'group', 'children':[
                    {'name':'Module', 'type':'list', 'values':{'CPA':CPA(self, console=self.console, showScriptParameter=self.showScriptParameter),
                                                               'Profiling':Profiling(self, console=self.console, showScriptParameter=self.showScriptParameter)
                                                               }, 'value':'CPA', 'set':self.setAttack},
                    ]},

                {'name':'Post-Processing', 'type':'group'},

                {'name':'Result Collection', 'type':'group', 'children':[
                    {'name':'Input Trace Plot', 'type':'group', 'children':[
                        {'name':'Enabled', 'type':'bool', 'value':True},
                        {'name':'Redraw after Each (slower)', 'type':'bool', 'value':True, 'set':self.setPlotInputEach},
                        {'name':'Trace Range', 'key':'tracerng', 'type':'range', 'limits':(0, 0)},
                        {'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'limits':(0, 0), 'graphwidget':self.waveformDock.widget()},
                        {'name':'Redraw', 'type':'action', 'action':self.plotInputTrace},
                        ]}
                    ]},
                ]

        self.plotInputEach = False

        self.da = None
        self.numTraces = 100

        self.traceLimits = 0
        self.pointLimits = 0

        self.addToolbars()
        self.addSettingsDocks()

        for d in self.results.dockList():
            self.addDockWidget(Qt.RightDockWidgetArea, d)
            self.addWindowMenuAction(d.toggleViewAction(), "Results")
            self.enforceMenuOrder()

        self.editorDocks()
        self.restoreDockGeometry()

        #Generate correct tab order now that we've restored
        self.tabifyDockWidget(self.settingsNormalDock, self.settingsPreprocessingDock)
        self.tabifyDockWidget(self.settingsNormalDock, self.settingsAttackDock)
        self.tabifyDockWidget(self.settingsNormalDock, self.settingsPostProcessingDock)
        self.tabifyDockWidget(self.settingsNormalDock, self.settingsResultsDock)

        for d in self.results.dockList():
            self.tabifyDockWidget(self.waveformDock, d)

        self.newProject()

        self.newFile.connect(self.newProject)
        self.saveFile.connect(self.saveProject)
        self.openFile.connect(self.openProject)

        self.manageTraces.tracesChanged.connect(self.tracesChanged)
        cpaTemp = CPA(self, console=self.console, showScriptParameter=self.showScriptParameter)
        self.setAttack(cpaTemp)

        self.setupPreprocessorChain()

        # print self.findParam('attackfilelist').items


    def listModules(self):
        """Overload this to test imports"""
        return ListAllModules()

    def editorDocks(self):
        """Ensure we have a script editor window for each referenced analyzer script file"""

        for script in self.scriptList:

            dockname = "Analysis Script: %s" % script['dockname']

            # No previous dock, do setup
            if 'dock' not in script.keys():
                script['widget'].editWindow.runFunction.connect(partial(self.runScriptFunction, filename=script['filename']))
                script['dock'] = self.addDock(script['widget'], name=dockname, area=Qt.RightDockWidgetArea)

            # Dock present, check if name changed
            if script['dock'].windowTitle() != dockname:
                script['dock'].setWindowTitle(dockname)


    def editorControl(self, filename, filedesc, default=False, bringToFront=True):
        """This is the call-back from the script editor file list, which opens editors"""

        # Find filename
        thisEditor = None

        for e in self.scriptList:
            if e['filename'] == filename:
                thisEditor = e
                break

        if thisEditor is None:
            thisEditor = {'widget':MainScriptEditor(parent=self, filename=filename)}
            thisEditor['filename'] = filename
            thisEditor['dockname'] = filedesc
            self.scriptList.append(thisEditor)

        # Update all docks if required
        thisEditor['dockname'] = filedesc
        self.editorDocks()

        if bringToFront:
            thisEditor['dock'].show()
            thisEditor['dock'].raise_()

        if default:
            # Set as default for attacks etc
            self.defaultEditor = thisEditor


    def setPlotInputEach(self, enabled):
        self.plotInputEach = enabled

    def addToolbars(self):
        """Add toolbars and menus to the main window"""

        attack = QAction(QIcon(':/images/attack.png'), 'Start Attack', self)
        attack.triggered.connect(self.doAttack)

        self.AttackToolbar = self.addToolBar('Attack Tools')
        self.AttackToolbar.setObjectName('Attack Tools')
        self.AttackToolbar.addAction(attack)


        # Add utilities

        self.UtilitiesTraceExplorer = QAction('Trace Explorer', self,
                               statusTip='Get information on traces',
                               triggered=self.traceExplorerDialog.show)

        self.UtilitiesAESSchedule = QAction('AES Key Schedule', self,
                               statusTip='Show AES Key Schedule calculator',
                               triggered=self.keyScheduleDialog.show)

        # self.UtilitiesPartition = QAction('Generate Partitions', self,
        #                       statusTip='Generate Partitions for Template Attacks',
        #                       triggered=self.PartitionDialog.exec_)

        self.toolMenu.addSeparator()
        self.toolMenu.addAction(self.UtilitiesTraceExplorer)
        self.toolMenu.addAction(self.UtilitiesAESSchedule)
        # self.toolMenu.addAction(self.UtilitiesPartition)
        self.toolMenu.addSeparator()

    def setPreprocessing(self, num, module):
        """Insert the preprocessing module selected from the GUI into the list of active modules.

        This ensures that the options for that module are then displayed in the GUI, along with
        writing the auto-generated script.
        """
        self.preprocessingListGUI[num] = module
        if module:
            module.paramListUpdated.connect(self.reloadParamListPreprocessing)
            module.scriptsUpdated.connect(self.reloadScripts)
        self.reloadParamListPreprocessing()
        self.reloadScripts()

    def runFunc(self, name):
        # TODO: We should be doing this correctly, this hack is bad ;_;
        # name = "TraceExplorerDialog_PartitionDisplay_" + name
        self.runScriptFunction(name)


    def reloadScripts(self):
        """Rewrite the auto-generated analyzer script, using settings from the GUI"""

        # Auto-Generated is always first
        mse = self.scriptList[0]['widget']

        mse.saveSliderPosition()
        mse.editWindow.clear()

        mse.append("# Date Auto-Generated: %s" % datetime.now().strftime('%Y.%m.%d-%H.%M.%S'), 0)

        mse.append("from chipwhisperer.common.autoscript import AutoScriptBase", 0)

        # Get imports from preprocessing
        mse.append("#Imports from Preprocessing", 0)
        mse.append("import chipwhisperer.analyzer.preprocessing as preprocessing", 0)
        for p in self.preprocessingListGUI:
            if p:
                imports = p.getImportStatements()
                for i in imports: mse.append(i, 0)

        # Get imports from capture
        mse.append("#Imports from Capture", 0)
        for i in self.attack.getImportStatements():
            mse.append(i, 0)

        # Some other imports
        mse.append("#Imports from utilList", 0)
        for index, util in enumerate(self.utilList):
            if hasattr(util, '_smartstatements') and util.isVisible():
                for i in util.getImportStatements(): mse.append(i, 0)

        mse.append("", 0)

        # Add main class
        mse.append("class userScript(AutoScriptBase):", 0)
        mse.append("preProcessingList = []", 1)

        mse.append("def initProject(self):", 1)
        mse.append("pass")


        mse.append("def initPreprocessing(self):", 1)

        # Get init from preprocessing
        instNames = ""
        for i, p in enumerate(self.preprocessingListGUI):
            if p:
                classname = type(p).__name__
                instname = "self.preProcessing%s%d" % (classname, i)
                mse.append("%s = preprocessing.%s.%s(self.parent)" % (instname, classname, classname))
                for s in p.getStatements('init'):
                    mse.append(s.replace("self.", instname + ".").replace("userScript.", "self."))
                instNames += instname + ","

        mse.append("self.preProcessingList = [%s]" % instNames)
        mse.append("return self.preProcessingList")


        mse.append("def initAnalysis(self):", 1)

        # Get init from analysis
        mse.append('self.attack = %s(self.parent, console=self.console, showScriptParameter=self.showScriptParameter)' % type(self.attack).__name__)
        for s in self.attack.getStatements('init'):
            mse.append(s.replace("self.", "self.attack.").replace("userScript.", "self."))

        mse.append('return self.attack')

        # Get init from reporting

        # Get go command from analysis
        mse.append("def initReporting(self, results):", 1)
        # mse.append("results.clear()")
        mse.append("results.setAttack(self.attack)")
        mse.append("results.setTraceManager(self.traceManager())")
        mse.append("self.results = results")

        mse.append("def doAnalysis(self):", 1)
        mse.append("self.attack.doAttack()")

        # Get other commands from attack module
        for k in self.attack._smartstatements:
            if k == 'init' or k == 'go' or k == 'done':
                pass
            else:
                mse.append("def %s(self):" % k, 1)
                for s in self.attack.getStatements(k):
                    mse.append(s.replace("self.", "self.attack.").replace("userScript.", "self."))


        # Get other commands from other utilities
        for index, util in enumerate(self.utilList):
            if hasattr(util, '_smartstatements') and util.isVisible():
                for k in util._smartstatements:
                    util._smartstatements[k].addSelfReplacement("utilList[%d]." % index)
                    util._smartstatements[k].addSelfReplacement("parent.")
                    statements = util.getStatements(k)

                    if len(statements) > 0:
                        mse.append("def %s_%s(self):" % (util.__class__.__name__, k), 1)
                        for s in statements:
                            mse.append(s.replace("userScript.", "self."))

        mse.restoreSliderPosition()

    def reloadParamListPreprocessing(self, list=None):
        """Reload the parameter lists, ensuring GUI is showing correct options to user"""

        plist = []
        for p in self.preprocessingListGUI:
            if p:
                for item in p.paramList():
                    plist.append(item)
        ExtendedParameter.reloadParams(plist, self.preprocessingParamTree)

    def setAttack(self, attack):
        """Set the attack module, reloading GUI and connecting appropriate signals"""

        self.attack = attack
        self.reloadAttackParamList()
        self.results.setAttack(self.attack)
        self.attack.paramListUpdated.connect(self.reloadAttackParamList)
        self.attack.setTraceLimits(self.traceLimits, self.pointLimits)

        # Sometimes required
        if hasattr(self, "traces") and self.traces:
            self.attack.setTraceManager(self.traces)

        self.attack.setProject(self.project())
        self.attack.scriptsUpdated.connect(self.reloadScripts)
        self.attack.runScriptFunction.connect(self.runScriptFunction)
        self.reloadScripts()

    def setupScriptModule(self, filename=None):
        """Loads a given script as a module for dynamic run-time insertion.

        Args:
            filename (str): The full filename to open. If None it opens the
                            auto-generated script instead.

        """

        if filename and filename != self.defaultEditor['filename']:
            QMessageBox.warning(None, "Script Error", "Cannot run script from non-default function")
            return None

        mod = self.defaultEditor['widget'].loadModule()

        # Check if we aborted due to conflitcing edit
        if mod is None:
            return None

        script = mod.userScript(self, self.console, self.showScriptParameter)
        if hasattr(self, "traces") and self.traces:
            script.setTraceManager(self.traces)
        return script

    def runScriptFunction(self, funcname, filename=None):
        """Loads a given script and runs a specific function within it."""

        mod = self.setupScriptModule(filename)

        if mod:
            try:
                eval('mod.%s()' % funcname)
            except AttributeError as e:
                # TODO fix this hack - this function will not exist before the
                # traceexplorer dialog has been opended, but will still be
                # called once
                if funcname == 'TraceExplorerDialog_PartitionDisplay_findPOI':
                    pass
                else:
                    # Continue with exception
                    raise

    def doAttack(self):
        """Called when the 'Do Attack' button is pressed, or can be called via API
        to cause attack to run"""

        #Check if traces enabled
        if self.traces.NumTrace == 0:
            msgBox = QMessageBox(QMessageBox.Warning, "Trace Error", "No traces enabled in project - open Trace Manager?",
                                       QMessageBox.NoButton, self)
            msgBox.addButton("Yes", QMessageBox.AcceptRole)
            msgBox.addButton("No", QMessageBox.RejectRole)
            if msgBox.exec_() == QMessageBox.AcceptRole:
                self.manageTraces.show()
            return

        self.console.append("Loading...")
        mod = self.setupScriptModule()
        # mod.initProject()

        # Setup trace sources etc, this calls the
        # .initPreprocessing itself
        # it also resets the setTraces in the passed 'mod',
        # which is REQUIRED for proper functioning!
        self.setupPreprocessorChain(mod)

        mod.initAnalysis()
        mod.initReporting(self.results)

        mod.doAnalysis()

        mod.doneAnalysis()
        mod.doneReporting()

        # self.console.append("Attack Started")
        # if self.results:
        #    self.results.setTraceManager(self.traces)
        #
        # if self.attack:
        #    self.attack.setTraceManager(self.traces)
        #    self.attack.doAttack()

        # self.console.append("Attack Done")

    def reloadAttackParamList(self, list=None):
        """Reloads parameter tree in GUI when attack changes"""

        ExtendedParameter.reloadParams(self.attack.paramList(), self.attackParamTree)

    def tracesChanged(self):
        """Traces changed due to loading new project or adjustment in trace manager,
        so adjust limits displayed and re-plot the new input trace"""

        self.setTraceLimits(self.manageTraces.iface.NumTrace, self.manageTraces.iface.NumPoint)
        self.plotInputTrace()

    def setupPreprocessorChain(self, mod=None):
        """Setup the preprocessor chain by chaining the first module input to the source
        traces, the next module input to the previous module output, etc."""

        if mod is None:
            mod = self.setupScriptModule()
        self.preprocessingList = mod.initPreprocessing()

        self.lastoutput = self.manageTraces.iface
        for t in self.preprocessingList:
            if t:
                t.setTraceSource(self.lastoutput)
                t.init()
                self.lastoutput = t
        self.traces = self.lastoutput

        for item in self.utilList:
            item.setTraceSource(self.traces)

        mod.setTraceManager(self.traces)

        # self.reloadScripts()

    def plotInputTrace(self):
        """Plot the input trace(s) as given by the GUI settings."""

        #print "Plotting %d-%d for points %d-%d"%(params[0].value(), params[1].value(), params[2].value(), params[3].value())
        self.waveformDock.widget().clearPushed()
        self.setupPreprocessorChain()

        tstart = self.findParam('tracerng').value()[0]
        tend = self.findParam('tracerng').value()[1]
        pstart = self.findParam('pointrng').value()[0]
        pend = self.findParam('pointrng').value()[1]

        ttotal = 0

        if tend - tstart > 1:
            self.waveformDock.widget().setPersistance(True)

        for tnum in range(tstart, tend):
            trace = self.traces.getTrace(tnum)

            if trace is None:
                continue

            ttotal += 1
            self.waveformDock.widget().passTrace(trace[pstart:pend], pstart)

            if self.plotInputEach:
                QCoreApplication.processEvents()

        # print ttotal

    def setTraceLimits(self, traces=None, points=None, deftrace=1, defpoint=-1):
        """When traces is loaded, Tell everything default point/trace range"""

        if defpoint == -1:
            defpoint = points

        #Set parameters for attack
        self.traceLimits = traces
        self.pointLimits = points
        self.attack.setTraceLimits(traces, points)

        # Set local parameters for trace viewer
        if traces is not None:
            self.findParam('tracerng').setLimits((0, traces))
            # TODO: Bug in pyqtgraph maybe - if call with just deftrace &
            #setLimits was called with (0,0), the setValue(1) is ignored which is OK,
            #but then calling setLimits with higher value followed by setValue still
            #has no effect??
            #WORKAROUND: use min(traces,deftrace) to ensure don't set value beyond limit for now
            self.findParam('tracerng').setValue((0, min(traces, deftrace)))


        if points:
            self.findParam('pointrng').setLimits((0, points))
            self.findParam('pointrng').setValue((0, defpoint))

    def addWaveforms(self):
        """Add waveform display dock to main window"""

        self.waveformDock = self.addTraceDock("Waveform Display")        #TODO: FIX THIS HACK
        #Should be something in ScopeInterface class maybe
        self.waveformDock.widget().setDefaultYRange(-0.5, 0.5)
        self.waveformDock.widget().YDefault()

    #def addShowStats(self):
    #    self.statsShowAct = QAction('&Results Monitor', self, statusTip='Plot/Save PGE etc', triggered=self.resultsDialog.show)
    #    self.projectMenu.addAction(self.statsShowAct)

    def addSettingsDocks(self):
        """Add settings dock to main window"""

        self.setupParametersTree()
        self.settingsNormalDock = self.addSettings(self.paramTree, "General")
        self.settingsPreprocessingDock = self.addSettings(self.preprocessingParamTree, "Preprocessing")
        self.settingsAttackDock = self.addSettings(self.attackParamTree, "Attack")
        self.settingsPostProcessingDock = self.addSettings(self.postprocessingParamTree, "Postprocessing")
        self.settingsResultsDock = self.addSettings(self.resultsParamTree, "Results")


    def setupParametersTree(self):
        """Setup all parameter trees so they can be reloaded later with changes"""

        self.params = Parameter.create(name='Generic Settings', type='group', children=self.cwParams)
        ExtendedParameter.setupExtended(self.params, self)
        self.paramTree = ParameterTree()
        self.paramTree.setParameters(self.params, showTop=False)

        self.preprocessingParamTree = ParameterTree()
        self.attackParamTree = ParameterTree()
        self.postprocessingParamTree = ParameterTree()
        self.resultsParamTree = ParameterTree()

        self.results.paramListUpdated.connect(self.reloadParamListResults)
        self.reloadParamListResults()

    def reloadParamListResults(self, lst=None):
        """Reload parameter tree for results settings, ensuring GUI matches loaded modules."""

        ExtendedParameter.reloadParams(self.results.paramList(), self.resultsParamTree)

    def reloadParamList(self, lst=None):
        """Reload parameter trees in a given list, ensuring GUI matches loaded modules."""

        ExtendedParameter.reloadParams(self.paramList(), self.paramTree)

    def paramList(self):
        p = []
        p.append(self.params)
        return p

    def openProject(self, fname):
        """Open a ChipWhisperer project file"""

        self.setProject(ProjectFormat(self))
        self.project().setProgramName("ChipWhisperer-Analyzer")
        self.project().setProgramVersion("2.00")
        self.project().setTraceManager(self.manageTraces)
        self.setCurrentFile(fname)
        self.project().setFilename(fname)
        self.project().load()

        #Open project file & read in everything
        self.project().traceManager.loadProject(fname)

        # Ensure attack knows about this project
        self.attack.setProject(self.project())
        self.traceExplorerDialog.setProject(self.project())

    def newProject(self):
        """Create a new ChipWhisperer project file"""

        #TODO: Move this to MainChip
        self.setProject(ProjectFormat(self))
        self.project().setProgramName("ChipWhisperer-Analyzer")
        self.project().setProgramVersion("2.00")
        self.project().addParamTree(self)
        self.project().setTraceManager(self.manageTraces)
        self.setCurrentFile(None)
        self.projectChanged.connect(self.traceExplorerDialog.setProject)

    def saveProject(self):
        """Save a ChipWhisperer project file"""

        #TODO: Move to MainChip
        if self.project().hasFilename() == False:
            fd = QFileDialog(self, 'Save New File', '.', '*.cwp')
            fd.setDefaultSuffix('cwp')
            fd.setAcceptMode(QFileDialog.AcceptSave)
            fd.setViewMode(QFileDialog.Detail)
            if fd.exec_() == QDialog.Accepted:
                fname = fd.selectedFiles()[0]
            else:
                return

            self.project().setFilename(fname)
            self.setCurrentFile(fname)

        self.project().save()
        self.dirty = False
        self.updateTitleBar()
        self.statusBar().showMessage("Project Saved")
Example #60
0
def show():
    """
    Show epydemic GUI application.
    """
    ## Always start by initializing Qt (only once per application)
    app = QtGui.QApplication([])

    ## Define a top-level widget to hold everything
    w = QtGui.QWidget()
    params = [
            {'name': 'beta', 'type': 'float', 'value': 1.4247},
            {'name': 'gamma', 'type': 'float', 'value': 0.14286, 'step': 0.1},
            {'name': 'TS', 'type': 'float', 'value': 0.1},
            {'name': 'ND', 'type': 'float', 'value': 70},
            {'name': 'S0', 'type': 'float', 'value': 1-1e-6},
            {'name': 'I0', 'type': 'float', 'value': 1e-6},
    ]
    ## Create tree of Parameter objects
    p = Parameter.create(name='params', type='group', children=params)
    t = ParameterTree()
    t.setParameters(p, showTop=False)

    ## Create a grid layout to manage the widgets size and position
    layout = QtGui.QGridLayout()
    w.setLayout(layout)
    w.resize(1000,600)

    ## Create some widgets to be placed inside
    btn = QtGui.QPushButton('&Play')
    btn2 = QtGui.QPushButton('&Stop')
    btn3 = QtGui.QPushButton('E&xit')

    cw = pg.GraphicsLayoutWidget()
    p1 = cw.addPlot(row=0, col=0, title="S")
    p1.setLabel('left', "Ratio")
    p1.setLabel('bottom', "Time", units='day')
    p2 = cw.addPlot(row=1, col=0, title="I")
    p2.setLabel('left', "Ratio")
    p2.setLabel('bottom', "Time", units='day')
    p3 = cw.addPlot(row=2, col=0, title="R")
    p3.setLabel('left', "Ratio")
    p3.setLabel('bottom', "Time", units='day')

    def compute():
        import scipy.integrate as spi
        import numpy as np
        beta=p['beta']
        gamma=p['gamma']
        TS=p['TS']
        ND=p['ND']
        S0=p['S0']
        I0=p['I0']
        INPUT = (S0, I0, 0.0)
        def diff_eqs(INP,t):
            '''The main set of equations'''
            Y=np.zeros((3))
            V = INP
            Y[0] = - beta * V[0] * V[1]
            Y[1] = beta * V[0] * V[1] - gamma * V[1]
            Y[2] = gamma * V[1]
            return Y   # For odeint
        t_start = 0.0; t_end = ND; t_inc = TS
        t_range = np.arange(t_start, t_end+t_inc, t_inc)
        RES = spi.odeint(diff_eqs,INPUT,t_range)
        ## Plot
        p1.clear()
        p2.clear()
        p3.clear()
        p1.plot(t_range, RES[:, 0])
        p2.plot(t_range, RES[:, 1])
        p3.plot(t_range, RES[:, 2])

    btn.clicked.connect(compute)

    ## Add widgets to the layout in their proper positions
    layout.addWidget(t, 0, 0)  # list widget goes in bottom-left
    layout.addWidget(btn, 1, 0)   # button goes in upper-left
    layout.addWidget(btn2, 2, 0)   # button goes in upper-left
    layout.addWidget(btn3, 3, 0)   # button goes in upper-left
    layout.addWidget(cw, 0, 1, 4, 1)  # plot goes on right side, spanning 3 rows

    ## Display the widget as a new window
    w.show()
    ## Start the Qt event loop
    app.exec_()