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
class Ui_ChildWindow(object): def setupUi(self, MainWindow, params): #app = QtGui.QApplication([]) #self.win = QtGui.QMainWindow() self.area = DockArea() MainWindow.setCentralWidget(self.area) MainWindow.resize(500, 700) MainWindow.setWindowTitle('Action construct') self.seq_cntr = Dock("Sequence", size=(150,200)) self.area.addDock(self.seq_cntr, 'left') ## first dock gets save/restore buttons self.t = ParameterTree() if params != None: self.p_child = Parameter.create(name='params', type='group', children=params) self.t.setParameters(self.p_child, showTop=False) self.t.setWindowTitle('pyqtgraph example: Parameter Tree') self.seq_cntr.addWidget(self.t) self.seq = pg.LayoutWidget() self.label = QtGui.QLabel("""Controls""") self.saveBtn = QtGui.QPushButton('Add Action') self.restoreBtn = QtGui.QPushButton('Modify table') self.restoreBtn.setEnabled(False) self.seq.addWidget(self.label, row=0, col=0) self.seq.addWidget(self.saveBtn, row=1, col=0) self.seq.addWidget(self.restoreBtn, row=2, col=0) self.seq_cntr.addWidget(self.seq)
class 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()
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'])
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
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
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) )
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()))
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>α='+str(round(float(unitCell[3]),2))+\ '° <br>β='+str(round(float(unitCell[4]),2))+'° <br>γ='+\ str(round(float(unitCell[5]),2))+'° <br></span></div>' self.parent.img.abc_text = pg.TextItem(html=myMessage, anchor=(0,0)) self.parent.img.w1.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) else: # Failed indexing xMargin = 5 # pixels maxX = np.max(self.parent.det.indexes_x(self.parent.evt))+xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) # Draw a big X cenX = np.array((self.parent.cx,))+0.5 cenY = np.array((self.parent.cy,))+0.5 diameter = 256 #self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='x', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0,0)) self.parent.img.w1.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX,maxY) else: self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) if self.parent.args.v >= 1: print "Done updatePeaks" # This function probably doesn't get called def launchIndexing(self, requestRun=None): self.batchIndexer = IndexHandler(parent=self.parent) if requestRun is None: self.batchIndexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) else: self.batchIndexer.computeIndex(self.parent.experimentName, requestRun, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) if self.parent.args.v >= 1: print "Done updateIndex"
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'
#}}} 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:
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()
class Ui_MainWindow(object): def setupUi(self, MainWindow, params): #app = QtGui.QApplication([]) #self.win = QtGui.QMainWindow() self.area = DockArea() MainWindow.setCentralWidget(self.area) MainWindow.resize(1200,600) MainWindow.setWindowTitle('SASE optimization') ## Create docks, place them into the window one at a time. ## Note that size arguments are only a suggestion; docks will still have to ## fill the entire dock area and obey the limits of their internal widgets. #self.orb_fig = Dock("Orbit", size=(400, 300)) ## give this dock the minimum possible size #self.orb_fig.float() #self.sase_fig = Dock("SASE", size=(400,300), closable=True) self.sase_fig = Dock("SASE", size=(400,300)) self.blm_fig = Dock("BLM", size=(400,200)) self.seq_cntr = Dock("Sequence", size=(150,200)) self.sase_cntr = Dock("Controls", size=(150,200)) #self.orb_cntr = Dock("orb contr.", size=(400,100)) self.cur_fig = Dock("Settings", size=(400,300)) self.logger = Dock("Logger", size=(100,300)) self.area.addDock(self.cur_fig, 'left') #self.area.addDock(self.orb_fig, 'above', self.cur_fig) ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) self.area.addDock(self.sase_fig, 'bottom', self.cur_fig) ## place d2 at right edge of dock area self.area.addDock(self.blm_fig, 'top', self.sase_fig)## place d3 at bottom edge of d1 self.area.addDock(self.sase_cntr, 'right') ## place d5 at left edge of d1 self.area.addDock(self.seq_cntr, 'left', self.sase_cntr) ## place d4 at right edge of dock area #self.area.addDock(self.orb_cntr, 'bottom', self.orb_fig) ## Test ability to move docks programatically after they have been placed #self.area.moveDock(self.sase_fig, 'bottom', self.orb_fig) ## move d4 to top edge of d2 #self.area.moveDock(self.blm_fig, 'bottom', self.sase_fig) ## move d6 to stack on top of d4 self.area.addDock(self.logger, 'bottom', self.sase_fig) self.area.moveDock(self.blm_fig, 'above', self.logger) ## Add widgets into each dock #add Logger self.log_lab = QtGui.QTextBrowser() #self.log_lab.verticalScrollBar().setValue(self.log_lab.verticalScrollBar().maximum()) self.logger.addWidget(self.log_lab) ## first dock gets save/restore buttons self.t = ParameterTree() if params != None: self.p = Parameter.create(name='params', type='group', children=params) self.t.setParameters(self.p, showTop=False) self.t.setWindowTitle('SASE optimization') self.seq_cntr.addWidget(self.t) self.seq = pg.LayoutWidget() self.label = QtGui.QLabel("""sequence control""") self.add_seq_btn = QtGui.QPushButton('Add Action') self.save_seq_btn = QtGui.QPushButton('Save seqs') self.load_seq_btn = QtGui.QPushButton('Load seqs') #self.restoreBtn.setEnabled(False) self.seq.addWidget(self.label, row=0, col=0) self.seq.addWidget(self.add_seq_btn, row=1, col=0) self.seq.addWidget(self.save_seq_btn, row=2, col=0) self.seq.addWidget(self.load_seq_btn, row=3, col=0) self.seq_cntr.addWidget(self.seq) #Currents graphics self.t_cur_cntr = ParameterTree() #param = [{'name': 'Devices', 'type': 'list', 'values': {}, 'value': 0}] param = [] self.p_cur_cntr = Parameter.create(name='control', type='group', children=param) self.t_cur_cntr.setParameters(self.p_cur_cntr, showTop=False) self.current = pg.PlotWidget(title="Settings") self.cur_fig.addWidget(self.current, row=0, col=0) self.cur_fig.addWidget(self.t_cur_cntr, row=0, col=1) #BLM graphics ## Hide title bar on dock 3 #d3.hideTitleBar() self.blm = pg.PlotWidget(title="BLM") self.blm_fig.addWidget(self.blm) #SASE graphics self.sase = pg.PlotWidget(title="SASE") self.sase_fig.addWidget(self.sase) #controls self.w5 = pg.LayoutWidget() self.start_opt_btm = QtGui.QPushButton('start') params = [ {'name': 'Basic opt. parameters', 'type': 'group', 'children': [ {'name': 'debug', 'type': 'bool', 'value': False}, {'name': 'logging', 'type': 'bool', 'value': True}, {'name': 'log file', 'type': 'str', 'value': 'test.log'}, {'name': 'timeout', 'type': 'float', 'value': 0.5, 'step': 0.1, 'limits': (0, 10)}, #{'name': 'SASE det.', 'type': 'list', 'values': {'mcp': 'mcp', 'gmd slow':'gmd_fl1_slow', 'bkr':'bkr', 'default':'gmd_default'}, 'value': "default"}, {'name': 'detector', 'type': 'list', 'values': ['gmd_default', 'mcp', 'gmd_fl1_slow', 'bkr'], 'value': "gmd_default"} ]} ] self.t_cntr = ParameterTree() self.p_cntr = Parameter.create(name='control', type='group', children=params) self.t_cntr.setParameters(self.p_cntr, showTop=False) self.restore_cur_btn = QtGui.QPushButton('Restore') #self.restore_cur_btn.setEnabled(False) self.setmax_opt_btn = QtGui.QPushButton('Set currents for max SASE') #self.setmax_opt_btn.setEnabled(False) self.stop_opt_btn = QtGui.QPushButton('Stop') self.clear_disp_btn = QtGui.QPushButton('Clear display') self.save_machine_btn = QtGui.QPushButton('Save new tuning') #self.save_machine_btn.setEnabled(False) #self.stop_btn = QtGui.QPushButton('stop') #self.w5.addWidget(self.start_opt_btm, row=0, col=0) self.w5.addWidget(self.stop_opt_btn, row=0, col=0) self.w5.addWidget(self.restore_cur_btn, row=1, col=0) #self.w5.addWidget(self.setmax_opt_btn, row=2, col=0) self.w5.addWidget(self.clear_disp_btn, row=4, col=0) #self.w5.addWidget(self.debug_opt_chk, row=3, col=0) #self.w5.addWidget(self.log_opt_chk, row=4, col=0) self.w5.addWidget(self.t_cntr, row=5, col=0) #self.w5.addWidget(QtGui.QLabel("""machine settings"""), row=6, col=0) #self.w5.addWidget(self.save_machine_btn, row=7, col=0) self.sase_cntr.addWidget(self.w5)
class 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()))
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
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
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)
class GuiManager(QtGui.QMainWindow): def __init__(self): super(GuiManager, self).__init__() self.createLayout() def closeEvent(self, event): print 'User asked to close the app' self.stopAcquisition() Parameters.isAppKilled = True #time.sleep(0.1) #Wait for the worker death event.accept() # let the window close def startAcquisition(self): if Parameters.isConnected == False: return Parameters.isSaving = Parameters.paramObject.child("Saving parameters", "saveResults").value() if Parameters.isSaving == True: theDate = datetime.datetime.today() .strftime('%Y%m%d') theTime = datetime.datetime.today() .strftime('%H%M%S') theName=Parameters.paramObject.child("Saving parameters", "Experiment name").value() #Check counter increment folderParent = 'C:/InterferometryResults/' + theDate counter = 1 folderFound = False theFolder = folderParent + '/' + theName + '_' + str(counter).zfill(3) if not os.path.exists(folderParent): #Make sure parent exist os.makedirs(folderParent) while folderFound == False and counter < 1000: #Loop until folder is found if not os.path.exists(theFolder): #Make sure parent exist os.makedirs(theFolder) folderFound = True else: counter = counter + 1 theFolder = folderParent + '/' + theName + '_' + str(counter).zfill(3) if counter < 1000: Parameters.savingFolder = theFolder if not os.path.exists(theFolder): os.makedirs(theFolder) else: Parameters.isSaving = False; #Should not happen. self.btStart.setEnabled(False) self.btStop.setEnabled(True) self.btOpen.setEnabled(False) #Get the parameter values Parameters.nSamples=Parameters.paramObject.child("Acquisition Parameters", "Number of samples to acquire").value() acqMode=Parameters.paramObject.child("Trigger Options", "Acquisition mode").value() triggerAmplitude=Parameters.paramObject.child("Trigger Options", "Trigger amplitude").value() motorSpeed=Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").value()+28 #28 is calibration nBlocks=int(math.ceil(float(Parameters.nSamples)/512)) #Must be a multiple of 512 Parameters.nSamples = nBlocks*512 Parameters.paramObject.child("Acquisition Parameters", "Number of samples to acquire").setValue(Parameters.nSamples) #Set frequency in free mode. These settings could be optimized depending on the computer. freq=2500000 #10im/s if Parameters.nSamples > 100352: freq=5000000 #5im/s if Parameters.nSamples > 300032: freq=12500000 #2im/s if Parameters.nSamples > 1000000: freq=25000000 #1im/s if Parameters.nSamples > 2000000: freq=50000000 #0.5im/s #Start the acquisition on the FPGA data = [] data = array('i') data.append(1) data.append(freq) data.append(2) data.append(acqMode) data.append(3) data.append(nBlocks) data.append(4) data.append(motorSpeed) data.append(5) data.append(triggerAmplitude) data.append(6) data.append(0) theBytes = struct.pack('i' * len(data), *data) buf = bytearray(theBytes) Parameters.dev.WriteToPipeIn(128, buf) Parameters.dev.SetWireInValue(0, 1+2+8, 1+2+8);Parameters.dev.UpdateWireIns() #Enable DDR2 reading and writing and activate memory. time.sleep(0.1); #Wait to make sure everything is ready. TODO: Reduce this. Parameters.dev.SetWireInValue(0, 4, 4);Parameters.dev.UpdateWireIns() #Start acquisition clock. #self.plotTr.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted Parameters.theQueue = Queue.Queue() #Create the queue #self.DisplayUpdater(0) self.workThread.start(); #Start the display worker def stopAcquisition(self): print 'Stopping...' if hasattr(self,'tDisplay'): self.tDisplay.cancel() self.workThread.exitWorker(); while self.workThread.isRunning == True: time.sleep(0.01) #Wait for the worker death, before resetting the board Parameters.dev.SetWireInValue(0, 0, 1+2+4+8);Parameters.dev.UpdateWireIns() #Reset board. #Save format: Results / YYMMDD / ExperimentName_Counter. Could also use the time. if Parameters.isSaving == True: #global state state = Parameters.paramObject.saveState() file = open(Parameters.savingFolder + '\Parameters.txt', 'w') pickle.dump(state, file) file.close() print 'Stopped.' self.btStart.setEnabled(True) self.btStop.setEnabled(False) self.btOpen.setEnabled(True) ''' def DisplayUpdater(self,dummy): if Parameters.isAppKilled == True: return; if Parameters.theQueue.empty(): print 'no data...' while not Parameters.theQueue.empty(): #Empty the display queue data = Parameters.theQueue.get() #print 'data available!' if 'data' in locals(): #print 'display data' + str(data[2]) self.setDataCurveTr(data) tDisplay = Timer(2, self.DisplayUpdater, [0],{}) tDisplay.start() ''' def motorSpeedChanged(self,value): newSpeed=Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").value() newSpeed=newSpeed+28 #Calibration #Debug #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(enabled=False) #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(visible=False) #Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").setOpts(value=200) data = [] data = array('i') data.append(4) data.append(newSpeed) data.append(0) #Minimum size is 8 'int' data.append(0) data.append(0) data.append(0) data.append(0) data.append(0) theBytes = struct.pack('i' * len(data), *data) Parameters.bufferToDev = bytearray(theBytes) Parameters.bufferToDevReady = True def triggerChanged(self,value): acqMode=Parameters.paramObject.child("Trigger Options", "Acquisition mode").value() triggerAmplitude=Parameters.paramObject.child("Trigger Options", "Trigger amplitude").value() data = [] data = array('i') data.append(2) data.append(acqMode) data.append(5) data.append(triggerAmplitude) data.append(0) data.append(0) data.append(0) data.append(0) theBytes = struct.pack('i' * len(data), *data) print str(theBytes) Parameters.bufferToDev = bytearray(theBytes) Parameters.bufferToDevReady = True def triggerHalfSwitch(self): Parameters.triggerToDev = True def saveParam(self): #global state state = Parameters.paramObject.saveState() file = open('dump.txt', 'w') pickle.dump(state, file) file.close() def restoreParam(self): #lobal state file = open('dump.txt', 'r') state = pickle.load(file) #add = Parameters.paramObject['Save/Restore functionality', 'Restore State', 'Add missing items'] #rem = Parameters.paramObject['Save/Restore functionality', 'Restore State', 'Remove extra items'] Parameters.paramObject.restoreState(state, addChildren=False, removeChildren=False) #Set the status text (system connected or not) def setStatus(self, isConnected, isError = False): def dotChange(item, nDots): #Timer function to display a varying number of dots after "retrying" if Parameters.isConnected == True: return; if Parameters.isAppKilled == True: return; textNotConnected = "System not connected, retrying" item.setText(textNotConnected+".") #Number of dots varies from 1 to 5 if nDots == 1: textDots = "." nDots = 2 elif nDots == 2: textDots = ".." nDots = 3 elif nDots == 3: textDots = "..." nDots = 4 elif nDots == 4: textDots = "...." nDots = 5 else: textDots = "....." nDots = 1 item.setForeground(QtGui.QColor("red")) item.setText(textNotConnected+textDots) self.timerDotChange = Timer(0.25, dotChange, [self.itemStatus, nDots]) self.timerDotChange.start() if (isError == True): #System not connected print "Error" if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() time.sleep(0.5) self.itemStatus.setForeground(QtGui.QColor("red")) self.itemStatus.setText("Error with system. Please restart the application and the system.") elif (isConnected == False): #System not connected nDots = 1 if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() self.timerDotChange = Timer(0.25, dotChange, [self.itemStatus, nDots]) self.timerDotChange.start() else: print "Connected" if hasattr(self,'timerDotChange'): self.timerDotChange.cancel() time.sleep(0.1) self.itemStatus.setForeground(QtGui.QColor("green")) self.itemStatus.setText("System connected.") print "Connected2" #Set the status text (system connected or not) def setCameraStatus(self, isConnected): def dotChange(item, nDots): #Timer function to display a varying number of dots after "retrying" if Parameters.isCameraConnected == True: return; if Parameters.isAppKilled == True: return; textNotConnected = "Camera not connected, retrying" item.setText(textNotConnected+".") #Number of dots varies from 1 to 5 if nDots == 1: textDots = "." nDots = 2 elif nDots == 2: textDots = ".." nDots = 3 elif nDots == 3: textDots = "..." nDots = 4 elif nDots == 4: textDots = "...." nDots = 5 else: textDots = "....." nDots = 1 item.setForeground(QtGui.QColor("red")) item.setText(textNotConnected+textDots) self.timerDotChangeCamera = Timer(0.25, dotChange, [self.itemCameraStatus, nDots]) self.timerDotChangeCamera.start() if (isConnected == False): #System not connected print 'cam oups' nDots = 1 if hasattr(self,'timerDotChangeCamera'): self.timerDotChangeCamera.cancel() self.timerDotChangeCamera = Timer(0.25, dotChange, [self.itemCameraStatus, nDots]) self.timerDotChangeCamera.start() else: print "Camera connected" if hasattr(self,'timerDotChangeCamera'): self.timerDotChangeCamera.cancel() time.sleep(0.1) self.itemCameraStatus.setForeground(QtGui.QColor("green")) self.itemCameraStatus.setText("Camera connected.") print "Camera connected2" #Set the status text (system connected or not) def setInfo(self, text): self.tbInfo.append(text) #Set the status text (system connected or not) def setWire(self, mem1, mem2, mem3, mem4, maxValPos): self.itemMemory.setText("Acquisition board memory usage:\nDDR2: " + str(mem1) + " bytes.\nFIFO in: " + str(mem2) + " bytes.\nFIFO out: " + str(mem3) + " bytes.\nFIFO out (minimum): " + str(mem4) + " bytes.") self.itemMaxValPos.setText("Maximum RF value position: " + str(maxValPos)) def createLayout(self): print 'Creating layout...' self.setWindowTitle('Interferometry Acquisition GUI') #self.widget = QtGui.QWidget() #self.setCentralWidget(self.widget) self.layout = pg.LayoutWidget() #self.widget.setLayout(self.layout) self.setCentralWidget(self.layout) #Create GUI sizePolicyBt = QtGui.QSizePolicy(1, 1) sizePolicyBt.setHorizontalStretch(0) sizePolicyBt.setVerticalStretch(0) self.btOpen = QtGui.QPushButton("Open\nprevious results") sizePolicyBt.setHeightForWidth(self.btOpen.sizePolicy().hasHeightForWidth()) self.btOpen.setSizePolicy(sizePolicyBt); self.btOpen.setStyleSheet("background-color: yellow; font-size: 16px; font: bold") self.btStart = QtGui.QPushButton("Start\nacquisition") sizePolicyBt.setHeightForWidth(self.btStart.sizePolicy().hasHeightForWidth()) self.btStart.setSizePolicy(sizePolicyBt); self.btStart.setStyleSheet("background-color: green; font-size: 16px; font: bold") self.btStart.clicked.connect(self.startAcquisition) self.btStop = QtGui.QPushButton("Stop\nacquisition") sizePolicyBt.setHeightForWidth(self.btStop.sizePolicy().hasHeightForWidth()) self.btStop.setSizePolicy(sizePolicyBt); self.btStop.setStyleSheet("background-color: red; font-size: 16px; font: bold") self.btStop.clicked.connect(self.stopAcquisition) self.btStop.setEnabled(False) self.paramTree = ParameterTree() self.paramTree.setParameters(Parameters.paramObject, showTop=False) self.paramTree.setWindowTitle('pyqtgraph example: Parameter Tree') self.paramTree.setMinimumWidth(350) self.paramTree.setMaximumWidth(350) sizePolicyPt = QtGui.QSizePolicy(1,1) sizePolicyPt.setHorizontalStretch(QtGui.QSizePolicy.Fixed) sizePolicyPt.setVerticalStretch(1) self.paramTree.setSizePolicy(sizePolicyPt); ## Create random 2D data data = np.random.normal(size=(512, 512)) + pg.gaussianFilter(np.random.normal(size=(512, 512)), (5, 5)) * 20 + 100 data = data[:,:,np.newaxis] data = data.repeat(3,2) self.plotTl = pg.GraphicsView() self.plotTlImage = pg.ImageItem(data[:,:,:]) #parent=self.plotTl self.plotTlViewBox = pg.ViewBox() self.plotTl.setCentralWidget(self.plotTlViewBox) self.plotTlViewBox.addItem(self.plotTlImage) self.plotTr = pg.PlotWidget(title="Interferometry", labels={'left': 'Signal amplitude (A.U.)', 'bottom': 'Distance (mm)'}) #self.plotTlViewBox2.addItem(self.plotTr) self.plotTrCurve = self.plotTr.plot(pen=(255,0,0),name='C1') #Red self.plotTrCurve2 = self.plotTr.plot(pen=(0,255,0),name='C2') #Green #self.plotTlViewBox2.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted #self.plotTr.addLegend('Test') self.plotTr.setYRange(-1000, 1000) self.plotBl = pg.PlotWidget(title="Distance", labels={'left': 'Distance (mm)', 'bottom': 'Number of acquisitions'}) self.plotBlCurve = self.plotBl.plot(pen=(255,0,0),name='C1') self.plotBl.enableAutoRange('xy', True) ## stop auto-scaling after the first data set is plotted self.plotBl.setMaximumWidth(3500) self.tbInfo = QtGui.QTextEdit() self.tbInfo.setEnabled(False) palette = self.tbInfo.palette() palette.setColor(QtGui.QPalette.Base, QtGui.QColor("white")) #White background self.tbInfo.setPalette(palette) self.tbInfo.setTextColor(QtGui.QColor("black")) self.tbInfo.insertPlainText("Useful information will appear here.") #Create list view of multiple items self.tbStatus = QtGui.QListView() self.tbStatus.setEnabled(False) palette = self.tbStatus.palette() palette.setColor(QtGui.QPalette.Base, QtGui.QColor("white")) #White background self.tbStatus.setPalette(palette) itemModelStatus = QtGui.QStandardItemModel(self.tbStatus) self.tbStatus.setModel(itemModelStatus) #Add system status self.itemStatus = QtGui.QStandardItem() self.setStatus(False) itemModelStatus.appendRow(self.itemStatus) #Add camera status self.itemCameraStatus = QtGui.QStandardItem() self.setCameraStatus(False) itemModelStatus.appendRow(self.itemCameraStatus) #Add memory usage self.itemMemory = QtGui.QStandardItem("Acquisition board memory usage: N/A") self.itemMemory.setForeground(QtGui.QColor("black")) itemModelStatus.appendRow(self.itemMemory) #Add max value position self.itemMaxValPos = QtGui.QStandardItem("Maximum RF value position: N/A") self.itemMaxValPos.setForeground(QtGui.QColor("black")) itemModelStatus.appendRow(self.itemMaxValPos) #layout.addWidget(QtGui.QLabel("These are two views of the same data. They should always display the same values."), 0, 0, 1, 2) self.layout.addWidget(self.btOpen, 9, 6, 1, 1) self.layout.addWidget(self.btStart, 9, 7, 1, 1) self.layout.addWidget(self.btStop, 9, 8, 1, 1) self.layout.addWidget(self.paramTree, 0, 0, 10, 3) self.layout.addWidget(self.plotTl, 0, 3, 5, 3) self.layout.addWidget(self.plotTr, 0, 6, 5, 3) self.layout.addWidget(self.plotBl, 5, 3, 5, 3) self.layout.addWidget(self.tbInfo, 5, 6, 2, 3) self.layout.addWidget(self.tbStatus, 7, 6, 2, 3) self.layout.layout.setColumnStretch(3,1) self.layout.layout.setColumnStretch(4,1) self.layout.layout.setColumnStretch(5,1) self.layout.layout.setColumnStretch(6,1) self.layout.layout.setColumnStretch(7,1) self.layout.layout.setColumnStretch(8,1) self.show() self.resize(1500,800) self.move(100,100) Parameters.paramObject.param('Save/Restore functionality', 'Save State').sigActivated.connect(self.saveParam) Parameters.paramObject.param('Save/Restore functionality', 'Restore State').sigActivated.connect(self.restoreParam) Parameters.paramObject.child("Acquisition Parameters", "Rotation speed (%)").sigValueChanged.connect(self.motorSpeedChanged) Parameters.paramObject.child("Trigger Options", "Acquisition mode").sigValueChanged.connect(self.triggerChanged) Parameters.paramObject.child("Trigger Options", "Trigger amplitude").sigValueChanged.connect(self.triggerChanged) Parameters.paramObject.child("Trigger Options", "Trigger switch 1/2").sigActivated.connect(self.triggerHalfSwitch) # adding by emitting signal in different thread self.workThread = AcquisitionWorker() self.workThread.updateDataCamera.connect(self.setDataCurveTl) self.workThread.updateDataInterf.connect(self.setDataCurveTr) self.workThread.updateDataDistance.connect(self.setDataCurveBl) self.workThread.updateDataDistance2.connect(self.setDataCurveBl2) self.workThread.updateWire.connect(self.setWire) self.workThread.setStatus.connect(self.setStatus) self.workThread.setInfo.connect(self.setInfo) self.testCount = 0; #Fill the plots with dummy data self.data = np.random.normal(size=(10,1000)) self.plotTrXAxis = np.arange(1000) * (0.01) self.plotBlXAxis = np.arange(1000) * (1) self.plotTrCurve.setData(x=self.plotTrXAxis,y=self.data[2%10],name='C1') self.plotTrCurve2.setData(x=self.plotTrXAxis,y=self.data[3%10],name='C2') self.plotBlCurve.setData(x=self.plotBlXAxis,y=self.data[4%10],name='C1') self.valueTest = 1 def setDataCurveTl(self, data): self.dataImage1 = data self.plotTlImage.setImage(data) self.testCount = self.testCount + 1; def setDataCurveTr(self, dataIn): self.plotTrCurve.setData(dataIn[0:len(dataIn):2],name='C1') self.plotTrCurve2.setData(dataIn[1:len(dataIn):2],name='C2') def setDataCurveBl(self, dataIn): self.plotBlCurve.setData(dataIn,name='C1') def setDataCurveBl2(self, xIn, dataIn): self.plotBlCurve.setData(x=xIn,y=dataIn,name='C1')
class 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)
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))
# -*- 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_()
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"
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())
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()
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
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
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)
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)
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)
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) )
#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)
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')
# 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)
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()
def widget(self): widget = ParameterTree() widget.setParameters(self, showTop=False) return widget
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)
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()
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))
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
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_()
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)
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)
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
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())
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
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"
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 )
class CrystalIndexing(object): def __init__(self, parent = None): self.parent = parent ## Dock: Indexing self.dock = Dock("Indexing", size=(1, 1)) self.win = ParameterTree() self.win.setWindowTitle('Indexing') self.dock.addWidget(self.win) self.winL = pg.LayoutWidget() self.launchIndexBtn = QtGui.QPushButton('Launch indexing') self.winL.addWidget(self.launchIndexBtn, row=0, col=0) self.synchBtn = QtGui.QPushButton('Deploy CrystFEL geometry') self.winL.addWidget(self.synchBtn, row=1, col=0) self.dock.addWidget(self.winL) self.index_grp = 'Crystal indexing' self.index_on_str = 'Indexing on' self.index_geom_str = 'CrystFEL geometry' self.index_peakMethod_str = 'Peak method' self.index_intRadius_str = 'Integration radii' self.index_pdb_str = 'Unitcell' self.index_method_str = 'Indexing method' self.index_tolerance_str = 'Tolerance' self.index_extra_str = 'Extra CrystFEL parameters' self.index_condition_str = 'Index condition' self.launch_grp = 'Batch' self.outDir_str = 'Output directory' self.runs_str = 'Runs(s)' self.sample_str = 'Sample name' self.tag_str = 'Tag' self.queue_str = 'Queue' self.chunkSize_str = 'Chunk size' self.cpu_str = 'CPUs' self.keepData_str = 'Keep CXI images' self.noe_str = 'Number of events to process' (self.psanaq_str,self.psnehq_str,self.psfehq_str,self.psnehprioq_str,self.psfehprioq_str,self.psnehhiprioq_str,self.psfehhiprioq_str,self.psdebugq_str) = \ ('psanaq','psnehq','psfehq','psnehprioq','psfehprioq','psnehhiprioq','psfehhiprioq','psdebugq') self.noQueue_str = 'N/A' self.outDir = self.parent.psocakeDir self.outDir_overridden = False self.runs = '' self.sample = 'crystal' self.tag = '' self.queue = self.psanaq_str self.chunkSize = 500 self.cpu = 12 self.noe = -1 # Indexing if self.parent.facility == self.parent.facilityLCLS: self.showIndexedPeaks = False self.indexedPeaks = None self.hiddenCXI = '.temp.cxi' self.hiddenCrystfelStream = '.temp.stream' self.hiddenCrystfelList = '.temp.lst' self.indexingOn = False self.numIndexedPeaksFound = 0 self.geom = '.temp.geom' self.peakMethod = 'cxi' self.intRadius = '3,4,5' self.pdb = '' self.indexingMethod = 'mosflm,dirax' self.tolerance = '5,5,5,1.5' self.extra = '' self.condition = '' self.keepData = True elif self.parent.facility == self.parent.facilityPAL: self.showIndexedPeaks = False self.indexedPeaks = None self.hiddenCXI = '.temp.cxi' self.hiddenCrystfelStream = '.temp.stream' self.hiddenCrystfelList = '.temp.lst' self.indexingOn = False self.numIndexedPeaksFound = 0 self.geom = '.temp.geom' self.peakMethod = 'cxi' self.intRadius = '4,5,6' self.pdb = '' self.indexingMethod = 'mosflm,dirax' self.tolerance = '5,5,5,1.5' self.extra = '' self.condition = '' self.keepData = True ####################### # Mandatory parameter # ####################### if self.parent.facility == self.parent.facilityLCLS: self.params = [ {'name': self.index_grp, 'type': 'group', 'children': [ {'name': self.index_on_str, 'type': 'bool', 'value': self.indexingOn, 'tip': "Turn on indexing"}, {'name': self.index_geom_str, 'type': 'str', 'value': self.geom, 'tip': "CrystFEL geometry file"}, #{'name': self.index_peakMethod_str, 'type': 'str', 'value': self.peakMethod, 'tip': "Turn on indexing"}, {'name': self.index_intRadius_str, 'type': 'str', 'value': self.intRadius, 'tip': "Integration radii"}, {'name': self.index_pdb_str, 'type': 'str', 'value': self.pdb, 'tip': "(Optional) CrystFEL unitcell file"}, {'name': self.index_method_str, 'type': 'str', 'value': self.indexingMethod, 'tip': "comma separated indexing methods"}, {'name': self.index_tolerance_str, 'type': 'str', 'value': self.tolerance, 'tip': "Indexing tolerance, default: 5,5,5,1.5"}, {'name': self.index_extra_str, 'type': 'str', 'value': self.extra, 'tip': "Other indexing parameters, comma separated (e.g. --multi,--no-check-peaks)"}, {'name': self.index_condition_str, 'type': 'str', 'value': self.condition, 'tip': "indexing condition e.g. 41 in #evr1# and #eventNumber# > 3"}, ]}, {'name': self.launch_grp, 'type': 'group', 'children': [ {'name': self.outDir_str, 'type': 'str', 'value': self.outDir}, {'name': self.runs_str, 'type': 'str', 'value': self.runs, 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"}, {'name': self.sample_str, 'type': 'str', 'value': self.sample, 'tip': "name of the sample saved in the cxidb file, e.g. lysozyme"}, {'name': self.tag_str, 'type': 'str', 'value': self.tag, 'tip': "attach tag to stream, e.g. cxitut13_0010_tag.stream"}, {'name': self.queue_str, 'type': 'list', 'values': {self.psfehhiprioq_str: self.psfehhiprioq_str, self.psnehhiprioq_str: self.psnehhiprioq_str, self.psfehprioq_str: self.psfehprioq_str, self.psnehprioq_str: self.psnehprioq_str, self.psfehq_str: self.psfehq_str, self.psnehq_str: self.psnehq_str, self.psanaq_str: self.psanaq_str, self.psdebugq_str: self.psdebugq_str}, 'value': self.queue, 'tip': "Choose queue"}, {'name': self.chunkSize_str, 'type': 'int', 'value': self.chunkSize, 'tip': "number of patterns to process per worker"}, {'name': self.keepData_str, 'type': 'bool', 'value': self.keepData, 'tip': "Do not delete cxidb images in cxi file"}, ]}, ] elif self.parent.facility == self.parent.facilityPAL: self.params = [ {'name': self.index_grp, 'type': 'group', 'children': [ {'name': self.index_on_str, 'type': 'bool', 'value': self.indexingOn, 'tip': "Turn on indexing"}, {'name': self.index_geom_str, 'type': 'str', 'value': self.geom, 'tip': "CrystFEL geometry file"}, {'name': self.index_intRadius_str, 'type': 'str', 'value': self.intRadius, 'tip': "Integration radii"}, {'name': self.index_pdb_str, 'type': 'str', 'value': self.pdb, 'tip': "(Optional) CrystFEL unitcell file"}, {'name': self.index_method_str, 'type': 'str', 'value': self.indexingMethod, 'tip': "comma separated indexing methods"}, {'name': self.index_tolerance_str, 'type': 'str', 'value': self.tolerance, 'tip': "Indexing tolerance, default: 5,5,5,1.5"}, {'name': self.index_extra_str, 'type': 'str', 'value': self.extra, 'tip': "Other CrystFEL indexing parameters"}, ]}, {'name': self.launch_grp, 'type': 'group', 'children': [ {'name': self.outDir_str, 'type': 'str', 'value': self.outDir}, {'name': self.runs_str, 'type': 'str', 'value': self.runs, 'tip': "comma separated or use colon for a range, e.g. 1,3,5:7 = runs 1,3,5,6,7"}, {'name': self.sample_str, 'type': 'str', 'value': self.sample, 'tip': "name of the sample saved in the cxidb file, e.g. lysozyme"}, {'name': self.tag_str, 'type': 'str', 'value': self.tag, 'tip': "attach tag to stream, e.g. cxitut13_0010_tag.stream"}, {'name': self.queue_str, 'type': 'list', 'values': {self.noQueue_str: self.noQueue_str}, 'value': self.queue, 'tip': "Choose queue"}, {'name': self.cpu_str, 'type': 'int', 'value': self.cpu, 'tip': "number of cores to use for indexing per run"}, {'name': self.keepData_str, 'type': 'bool', 'value': self.keepData, 'tip': "Do not delete cxidb images in cxi file"}, ]}, ] self.p9 = Parameter.create(name='paramsCrystalIndexing', type='group', \ children=self.params, expanded=True) self.win.setParameters(self.p9, showTop=False) self.p9.sigTreeStateChanged.connect(self.change) if using_pyqt4: self.parent.connect(self.launchIndexBtn, QtCore.SIGNAL("clicked()"), self.indexPeaks) self.parent.connect(self.synchBtn, QtCore.SIGNAL("clicked()"), self.syncGeom) else: self.launchIndexBtn.clicked.connect(self.indexPeaks) self.synchBtn.clicked.connect(self.syncGeom) # Launch indexing def indexPeaks(self): self.parent.thread.append(LaunchIndexer.LaunchIndexer(self.parent)) # send parent parameters with self self.parent.thread[self.parent.threadCounter].launch(self.parent.experimentName, self.parent.detInfo) self.parent.threadCounter += 1 # Update psana geometry def syncGeom(self): if self.parent.facility == self.parent.facilityLCLS: with pg.BusyCursor(): print "#################################################" print "Updating psana geometry with CrystFEL geometry" print "#################################################" self.parent.geom.findPsanaGeometry() psanaGeom = self.parent.psocakeRunDir + "/.temp.data" if self.parent.args.localCalib: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", '.', "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] else: cmd = ["crystfel2psana", "-e", self.parent.experimentName, "-r", str(self.parent.runNumber), "-d", str(self.parent.det.name), "--rootDir", self.parent.rootDir, "-c", self.geom, "-p", psanaGeom, "-z", str(self.parent.clen)] if self.parent.args.v >= 0: print "cmd: ", cmd p = subprocess.Popen(cmd, stdout=subprocess.PIPE) output = p.communicate()[0] p.stdout.close() # Reload new psana geometry cmts = {'exp': self.parent.experimentName, 'app': 'psocake', 'comment': 'converted from crystfel geometry'} if self.parent.args.localCalib: calibDir = './calib' elif self.parent.args.outDir is None: calibDir = self.parent.rootDir + '/calib' else: calibDir = self.parent.dir + self.parent.experimentName[:3] + '/' + self.parent.experimentName + '/calib' deploy_calib_file(cdir=calibDir, src=str(self.parent.det.name), type='geometry', run_start=self.parent.runNumber, run_end=None, ifname=psanaGeom, dcmts=cmts, pbits=0) self.parent.exp.setupExperiment() self.parent.img.getDetImage(self.parent.eventNumber) self.parent.geom.updateRings() self.parent.index.updateIndex() self.parent.geom.drawCentre() # Show mask self.parent.mk.updatePsanaMaskOn() elif self.parent.facility == self.parent.facilityPAL: print "deploy crystfel geom is not implemented for PAL" # If anything changes in the parameter tree, print a message def change(self, panel, changes): for param, change, data in changes: path = panel.childPath(param) if self.parent.args.v >= 1: print(' path: %s' % path) print(' change: %s' % change) print(' data: %s' % str(data)) print(' ----------') self.paramUpdate(path, change, data) ############################## # Mandatory parameter update # ############################## def paramUpdate(self, path, change, data): if path[1] == self.index_on_str: self.updateIndexStatus(data) elif path[1] == self.index_geom_str: self.updateGeom(data) elif path[1] == self.index_peakMethod_str: self.updatePeakMethod(data) elif path[1] == self.index_intRadius_str: self.updateIntegrationRadius(data) elif path[1] == self.index_pdb_str: self.updatePDB(data) elif path[1] == self.index_method_str: self.updateIndexingMethod(data) elif path[1] == self.index_tolerance_str: self.updateTolerance(data) elif path[1] == self.index_extra_str: self.updateExtra(data) elif path[1] == self.index_condition_str: self.updateCondition(data) # launch grp elif path[1] == self.outDir_str: self.updateOutputDir(data) elif path[1] == self.runs_str: self.updateRuns(data) elif path[1] == self.sample_str: self.updateSample(data) elif path[1] == self.tag_str: self.updateTag(data) elif path[1] == self.queue_str: self.updateQueue(data) elif path[1] == self.chunkSize_str: self.updateChunkSize(data) elif path[1] == self.cpu_str: self.updateCpu(data) elif path[1] == self.noe_str: self.updateNoe(data) elif path[1] == self.keepData_str: self.keepData = data def updateIndexStatus(self, data): self.indexingOn = data self.showIndexedPeaks = data self.updateIndex() def updateGeom(self, data): self.geom = data self.updateIndex() def updatePeakMethod(self, data): self.peakMethod = data if self.indexingOn: self.updateIndex() def updateIntegrationRadius(self, data): self.intRadius = data self.updateIndex() def updatePDB(self, data): self.pdb = data self.updateIndex() def updateIndexingMethod(self, data): self.indexingMethod = data self.updateIndex() def updateTolerance(self, data): self.tolerance = data self.updateIndex() def updateExtra(self, data): self.extra = data.replace(" ","") self.updateIndex() def updateCondition(self, data): self.condition = data self.updateIndex() def updateIndex(self): if self.indexingOn: if self.parent.pk.peaks is None: self.parent.index.clearIndexedPeaks() else: self.indexer = IndexHandler(parent=self.parent) self.indexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, queue=None) else: # do not display predicted spots self.parent.index.clearIndexedPeaks() def updateOutputDir(self, data): self.outDir = data self.outDir_overridden = True def updateRuns(self, data): self.runs = data def updateSample(self, data): self.sample = data def updateTag(self, data): self.tag = data def updateQueue(self, data): self.queue = data def updateChunkSize(self, data): self.chunkSize = data def updateCpu(self, data): self.cpu = data def updateNoe(self, data): self.noe = data def clearIndexedPeaks(self): self.parent.img.win.getView().removeItem(self.parent.img.abc_text) self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) if self.parent.args.v >= 1: print "Done clearIndexedPeaks" def displayWaiting(self): if self.showIndexedPeaks: if self.numIndexedPeaksFound == 0: # indexing proceeding xMargin = 5 # pixels if self.parent.facility == self.parent.facilityLCLS: maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) elif self.parent.facility == self.parent.facilityPAL: yMargin = 0 # pixels (dim0, dim1) = self.parent.calib.shape self.iy = np.tile(np.arange(dim0), [dim1, 1]) self.ix = np.transpose(self.iy) maxX = np.max(self.ix) + xMargin maxY = np.max(self.iy) - yMargin # Draw a big X cenX = np.array((self.parent.cx,)) + 0.5 cenY = np.array((self.parent.cy,)) + 0.5 diameter = 256 # self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='t', \ size=diameter, brush=(255, 255, 255, 0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0, 0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) def drawIndexedPeaks(self, latticeType=None, centering=None, unitCell=None): self.clearIndexedPeaks() if self.showIndexedPeaks: if self.indexedPeaks is not None and self.numIndexedPeaksFound > 0: # indexing succeeded cenX = self.indexedPeaks[:,0]+0.5 cenY = self.indexedPeaks[:,1]+0.5 cenX = np.concatenate((cenX,cenX,cenX)) cenY = np.concatenate((cenY,cenY,cenY)) diameter = np.ones_like(cenX) diameter[0:self.numIndexedPeaksFound] = float(self.intRadius.split(',')[0])*2 diameter[self.numIndexedPeaksFound:2*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[1])*2 diameter[2*self.numIndexedPeaksFound:3*self.numIndexedPeaksFound] = float(self.intRadius.split(',')[2])*2 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='o', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 1.5}), pxMode=False) # Write unit cell parameters if unitCell is not None: xMargin = 5 yMargin = 400 if self.parent.facility == self.parent.facilityLCLS: maxX = np.max(self.parent.det.indexes_x(self.parent.evt)) + xMargin maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) - yMargin elif self.parent.facility == self.parent.facilityPAL: (dim0, dim1) = self.parent.calib.shape self.iy = np.tile(np.arange(dim0), [dim1, 1]) self.ix = np.transpose(self.iy) maxX = np.max(self.ix) + xMargin maxY = np.max(self.iy) - yMargin #myMessage = '<div style="text-align: center"><span style="color: #FF00FF; font-size: 12pt;">lattice='+\ # str(latticeType) +'<br>centering=' + str(centering) + '<br>a='+\ # str(round(float(unitCell[0])*10,2))+'A <br>b='+str(round(float(unitCell[1])*10,2))+'A <br>c='+\ # str(round(float(unitCell[2])*10,2))+'A <br>α='+str(round(float(unitCell[3]),2))+\ # '° <br>β='+str(round(float(unitCell[4]),2))+'° <br>γ='+\ # str(round(float(unitCell[5]),2))+'° <br></span></div>' myMessage = '<div style="text-align: center"><span style="color: #FF00FF; font-size: 12pt;">lattice='+\ str(latticeType) +'<br>centering=' + str(centering) + '<br></span></div>' self.parent.img.abc_text = pg.TextItem(html=myMessage, anchor=(0,0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(maxX, maxY) else: # Failed indexing #xMargin = 5 # pixels #if self.parent.facility == self.parent.facilityLCLS: # maxX = np.max(self.parent.det.indexes_x(self.parent.evt))+xMargin # maxY = np.max(self.parent.det.indexes_y(self.parent.evt)) #elif self.parent.facility == self.parent.facilityPAL: # yMargin = 0 # pixels # (dim0, dim1) = self.parent.calib.shape # self.iy = np.tile(np.arange(dim0), [dim1, 1]) # self.ix = np.transpose(self.iy) # maxX = np.max(self.ix) + xMargin # maxY = np.max(self.iy) - yMargin # Draw a big X cenX = np.array((self.parent.cx,))+0.5 cenY = np.array((self.parent.cy,))+0.5 diameter = 256 #self.peakRadius*2+1 self.parent.img.indexedPeak_feature.setData(cenX, cenY, symbol='x', \ size=diameter, brush=(255,255,255,0), \ pen=pg.mkPen({'color': "#FF00FF", 'width': 3}), pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0,0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(0,0) else: self.parent.img.indexedPeak_feature.setData([], [], pxMode=False) self.parent.img.abc_text = pg.TextItem(html='', anchor=(0, 0)) self.parent.img.win.getView().addItem(self.parent.img.abc_text) self.parent.img.abc_text.setPos(0, 0) if self.parent.args.v >= 1: print "Done drawIndexedPeaks" # This function probably doesn't get called def launchIndexing(self, requestRun=None): self.batchIndexer = IndexHandler(parent=self.parent) if requestRun is None: self.batchIndexer.computeIndex(self.parent.experimentName, self.parent.runNumber, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) else: self.batchIndexer.computeIndex(self.parent.experimentName, requestRun, self.parent.detInfo, self.parent.eventNumber, self.geom, self.peakMethod, self.intRadius, self.pdb, self.indexingMethod, self.parent.pk.minPeaks, self.parent.pk.maxPeaks, self.parent.pk.minRes, self.tolerance, self.extra, self.outDir, self.runs, self.sample, self.tag, self.queue, self.chunkSize, self.noe) if self.parent.args.v >= 1: print "Done updateIndex"
class 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)
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()
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')
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")
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_()