Example #1
0
class SpectrumViewer(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(SpectrumViewer, self).__init__()
            QtGui.QMainWindow.__init__(self, parent)
            self.spectra = []
            self.plots = []
            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.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)

            # 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.toggleSidebarAction = QtGui.QAction('&Toggle sidebar', self)
            self.toggleSidebarAction.setStatusTip('Toggle sidebar')
            self.toggleSidebarAction.triggered.connect(self.togglesidebar)

            # Spectrum actions
            self.addspectrumAction = QtGui.QAction(QtGui.QIcon('../icons/addspectrum.png'), '&Add spectrum', self)
            self.addspectrumAction.setStatusTip('Add a new spectrum')
            self.addspectrumAction.setShortcut('Ctrl + A')
            self.addspectrumAction.triggered.connect(self.open)

            self.removespectrumAction = QtGui.QAction(QtGui.QIcon('../icons/removespectrum.png'), '&Remove spectrum', self)
            self.removespectrumAction.setStatusTip('Remove a spectrum')
            self.removespectrumAction.setShortcut('Ctrl + R')
            self.removespectrumAction.triggered.connect(self.removespectrum)

            # 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.saveimageAction)

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

            self.spectrumtoolbar = self.addToolBar('Spectrum')
            self.spectrumtoolbar.addAction(self.addspectrumAction)
            self.spectrumtoolbar.addAction(self.removespectrumAction)

        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')
            spectrum = menubar.addMenu('&Spectrum')
            about = menubar.addMenu('&About')

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

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

            # Spectrum menu
            spectrum.addAction(self.addspectrumAction)
            spectrum.addAction(self.removespectrumAction)

        def initParameterTree(self):
            '''The sidebar.'''
            self.parametertree = ParameterTree()
            self.params = []

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

            self.plotwidget = pg.PlotWidget()
            self.plot = self.plotwidget.plotItem
            self.plot.setMenuEnabled(False)
            #cross hair
            self.vLine = pg.InfiniteLine(angle=90, movable=False)
            self.hLine = pg.InfiniteLine(angle=0, movable=False)
            self.plotwidget.addItem(self.vLine, ignoreBounds=True)
            self.plotwidget.addItem(self.hLine, ignoreBounds=True)
            self.vb = self.plot.vb
            self.plot.scene().sigMouseMoved.connect(self.mouseMoved)

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

            self.setCentralWidget(widget)
            self.resize(1200, 600)
            self.setWindowTitle('Molviewer :: Spectrum main window')
            self.show()

        def mouseMoved(self, evt):
            '''Detect mouse movement.'''
            pos = evt
            if self.plot.sceneBoundingRect().contains(pos):
                mousePoint = self.vb.mapSceneToView(pos)
                self.vLine.setPos(mousePoint.x())
                self.hLine.setPos(mousePoint.y())

        def new(self):
            '''Spawn new main window.'''
            spawn = SpectrumViewer(self)
            spawn.setWindowTitle('Molviewer :: Spectrum main window (child)')
            spawn.show()

        def open(self):
            '''Open a new spectrum using the file dialog.'''
            filenames = QtGui.QFileDialog.getOpenFileNames(self, 'Open Files', '', '*.dx;; *.jdx')
            if filenames:
                for f in filenames:
                    spectrum = Spectrum(f)
                    self.addspectrum(spectrum)

        def save(self):
            pass

        def saveimage(self):
            pass

        def draw(self, spectrum):
            '''Draw a new spectrum.

            :param spectrum: The spectrum to draw.
            :type spectrum: spectrum.Spectrum
            :param color: The color in which the spectrum is drawn.

            '''
            p = self.plotwidget.plot(spectrum.x, spectrum.y, pen=spectrum.color)
            if p not in self.plots:
                self.plots.append(p)
            if spectrum.datatype.lower() == 'infrared spectrum':
                # Plot higher wavenumbers to the left hand side
                self.plotwidget.invertX(True)
                self.plotwidget.setLabel('bottom', '1/cm')
            else:
                self.plotwidget.setLabel('bottom', spectrum.xunits)

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

        def togglesidebar(self):
            if self.parametertree.isVisible():
                self.parametertree.hide()
            else:
                self.parametertree.show()

        def addspectrum(self, spectrum):
            '''Add a new spectrum.

            :param spectrum: The new spectrum.
            :type spectrum: spectrum.Spectrum

            '''
            self.spectra.append(spectrum)
            ind = self.spectra.index(spectrum)
            spectrum.color = spectrumcolors[ind]
            params = [
                {'name': spectrum.title, 'type': 'group', 'children': [
                    {'name': 'Number', 'type': 'int', 'value': self.spectra.index(spectrum)},
                    {'name': 'Color', 'type': 'color', 'value': spectrum.color},
                    {'name': 'Visible', 'type': 'bool', 'value': True},
                    {'name': 'Action Parameter', 'type': 'action'},
                    {'name': 'Spectrum', 'type': 'str', 'value': spectrum, 'visible': False}]
                }]

            p = Parameter.create(name='Files', type='group', children=params)
            p.sigTreeStateChanged.connect(self.change)
            self.parametertree.addParameters(p, showTop=False)
            self.params.append(p)
            self.draw(spectrum)

        def removespectrum(self):
            '''Remove a spectrum from display.'''
            num, ok = QtGui.QInputDialog.getText(self, 'Remove a spectrum', 'Enter spectrum number:')
            if ok and num:
                num = int(num)
                self.plotwidget.removeItem(self.plots[num])
                self.plots.pop(num)
                self.spectra.pop(num)
                self.params.pop(num)
                self.parametertree.clear()
                for p in self.params:
                    self.parametertree.addParameters(p, showTop=False)

        def change(self, param, changes):
            for param, change, data in changes:
                spec = param.parent().child('Spectrum').value()
                index = self.spectra.index(spec)

                if isinstance(param.value(), QtGui.QColor):
                    self.plots[index].setPen(param.value())
                    self.spectra[index].color = param.value()

                if param.name() == 'Visible':
                    if data is False:
                        self.plots[index].clear()
                    elif data is True:
                        self.plots[index].setData(self.spectra[index].x, self.spectra[index].y)
Example #2
0
class ObjectTree(QWidget, ComponentMixin):

    name = 'Object Tree'
    _stash = []

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

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

    def __init__(self, parent):

        super(ObjectTree, self).__init__(parent)

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

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

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

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

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

        tree.expandToDepth(1)

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

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

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

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

        self.prepareMenu()

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

        self.prepareLayout()

    def prepareMenu(self):

        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)

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

    def prepareLayout(self):

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

        self._splitter.show()

    def showMenu(self, position):

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

    def menuActions(self):

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

    def toolbarActions(self):

        return self._toolbar_actions

    def addLines(self):

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

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

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

            ais_list.append(line)

        self.sigObjectsAdded.emit(ais_list)

    def _current_properties(self):

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

        return current_params

    def _restore_properties(self, obj, properties):

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

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

        if root is None:
            root = self.CQ

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

        if preserve_props:
            current_props = self._current_properties()

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

        ais_list = []

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

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

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

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

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

            root.addChild(child)

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

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

        root = self.CQ

        ais, shape_display = make_AIS(obj, options)

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

        self.sigObjectsAdded.emit([ais])

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

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

        self.sigObjectsRemoved.emit(removed_items_ais)

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

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

    @pyqtSlot()
    def removeSelected(self):

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

        self.removeObjects(rows)

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

        items = self.tree.selectedItems()

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

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

    @pyqtSlot()
    def handleSelection(self):

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

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

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

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

        self.tree.clearSelection()

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

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

        if type(item) is ObjectTreeItem:
            if item.checkState(0):
                item.properties['Visible'] = True
            else:
                item.properties['Visible'] = False
Example #3
0
    class maintest(QtCore.QObject):
        paramListUpdated = QtCore.Signal(list)

        def __init__(self):
            super(maintest, self).__init__()
            p = [{
                'name':
                'Basic parameter data types',
                'type':
                'group',
                'helpwnd':
                self.printhelp,
                'children': [{
                    'name':
                    'Module 1',
                    'type':
                    'list',
                    'values': {
                        'module 1': module(),
                        'module 2': module(),
                        'module 3': module()
                    },
                    'set':
                    self.setmodule,
                    'help':
                    '%namehdr%Boatload of text is possible here. Can use markup too with external help window.'
                }, {
                    'name': 'Rocks to Skips',
                    'type': 'int',
                    'help': 'Another help example',
                    'helpwnd': None
                }]
            }]
            self.params = Parameter.create(name='Test',
                                           type='group',
                                           children=p)
            ExtendedParameter.setupExtended(self.params)
            self.module = None

            self.t = ParameterTree()
            self.reloadParams()

        def printhelp(self, msg, obj):
            print msg

        def setmodule(self, module):
            print "Changing Module"
            self.module = module
            self.module.paramListUpdated.connect(self.reloadParams)
            self.paramListUpdated.emit(self.paramList())
            self.reloadParams()

        def reloadParams(self):
            ExtendedParameter.reloadParams(self.paramList(), self.t)

        def reloadParamsBad(self):
            """The following is kept as a reminder you must NOT do this, or else objects get deleted"""

            #Notes about my wasted day to report a bug later when I have more time:
            # *Calling the .clear() causes stuff to be deleted
            # *In file parameterTypes.py at line 180 you have the following:
            #    self.widget.sigChanged.disconnect(self.widgetValueChanged)
            #  If self.widget has been deleted, which will happen once the ParameterTree is cleared, the call
            #  to .disconnect causes a bad crash (sometimes). However - you can insert a call to 'self.widget.value()'
            #  before the .disconnect() call. The self.widget.value() actually checks if the object was deleted, and if so
            #  it raises a nice exception with a handy error message.

            lst = self.paramList()
            self.t.clear()
            for p in lst:
                self.t.addParameters(p)

        def paramList(self):
            p = [self.params]
            if self.module is not None:
                for a in self.module.paramList():
                    p.append(a)
            return p
class TraceManagerImport(QtFixes.QDialog):
    def __init__(self, parent=None):        
        super(TraceManagerImport, self).__init__(parent)

        layout = QVBoxLayout()

        # Set dialog layout
        self.setLayout(layout)
        self.setWindowTitle("Add Existing Trace")

        self.openCfg = QPushButton("Load .cfg File")
        self.openCfg.clicked.connect(self.loadCfg)

        layout.addWidget(self.openCfg)
        
        self.modName = QComboBox()
        self.modName.addItem("Select format for manual mode only...")
        self.modName.addItem("ChipWhisperer/Native")
        self.modName.addItem("DPAContestv3")
        if TraceContainerMySQL is not None:        
            self.modName.addItem("MySQL", TraceContainerMySQL)
        self.modName.currentIndexChanged.connect(self.traceTypeChanged)
        
        layout.addWidget(self.modName)

        self.paramTree = ParameterTree()
        layout.addWidget(self.paramTree)

        buts = QHBoxLayout()
        cancel = QPushButton("Close")
        cancel.clicked.connect(self.abort)
        ok = QPushButton("Import")
        ok.clicked.connect(self.accept)
        buts.addWidget(ok)
        buts.addWidget(cancel)
        
        layout.addLayout(buts)
        
        self.tmanager = None
        
    def abort(self):
        self.tmanager = None
        self.reject()        

    def traceTypeChanged(self, newindx):
        self.openCfg.setEnabled(False)
        newTT = self.modName.itemData(newindx)        
        self.tmanagerParams = newTT.getParamsClass(openMode=True)   
        self.tmanager = newTT(self.tmanagerParams)
        self.paramTree.clear()
        self.paramTree.addParameters(self.tmanagerParams.getParams()._PyQtGraphParameter)
        
    def getTrace(self):
        return self.tmanager
    
    def updateConfigData(self):
        if self.tmanager is not None:
            self.tmanager.updateConfigData()

    def loadCfg(self, fname=None):
        if fname is None:
            fname, _ = QFileDialog.getOpenFileName(self, 'Open file', QSettings().value("trace_last_file"), '*.cfg')

        if fname:
            QSettings().setValue("trace_last_file", fname)
            self.modName.setEnabled(False)
            
            #Figure out what format this is in
            tc = TraceContainerConfig(fname)
            fmt = tc.attr("format")
            
            #Generate a temp class for getting parameters from
            fmtclass = chipwhisperer.common.traces.TraceContainerTypes.TraceContainerFormatList[fmt]
            
            #Use temp class to finally initilize our "good" version
            self.tmanager = fmtclass()
            self.tmanager.config.loadTrace(fname)
            self.tmanager.loadAllConfig()
            self.paramTree.clear()
            self.paramTree.addParameters(self.tmanager.getParams()._PyQtGraphParameter)
Example #5
0
class TraceManagerImport(QtFixes.QDialog):
    def __init__(self, parent=None):
        super(TraceManagerImport, self).__init__(parent)

        layout = QVBoxLayout()

        # Set dialog layout
        self.setLayout(layout)
        self.setWindowTitle("Add Existing Trace")

        self.openCfg = QPushButton("Load .cfg File")
        self.openCfg.clicked.connect(self.loadCfg)

        layout.addWidget(self.openCfg)

        self.modName = QComboBox()
        self.modName.addItem("Select format for manual mode only...")
        self.modName.addItem("ChipWhisperer/Native")
        self.modName.addItem("DPAContestv3")
        if TraceContainerMySQL is not None:
            self.modName.addItem("MySQL", TraceContainerMySQL)
        self.modName.currentIndexChanged.connect(self.traceTypeChanged)

        layout.addWidget(self.modName)

        self.paramTree = ParameterTree()
        layout.addWidget(self.paramTree)

        buts = QHBoxLayout()
        cancel = QPushButton("Close")
        cancel.clicked.connect(self.abort)
        ok = QPushButton("Import")
        ok.clicked.connect(self.accept)
        buts.addWidget(ok)
        buts.addWidget(cancel)

        layout.addLayout(buts)

        self.tmanager = None

    def abort(self):
        self.tmanager = None
        self.reject()

    def traceTypeChanged(self, newindx):
        self.openCfg.setEnabled(False)
        newTT = self.modName.itemData(newindx)
        self.tmanagerParams = newTT.getParamsClass(openMode=True)
        self.tmanager = newTT(self.tmanagerParams)
        self.paramTree.clear()
        self.paramTree.addParameters(
            self.tmanagerParams.getParams()._PyQtGraphParameter)

    def getTrace(self):
        return self.tmanager

    def updateConfigData(self):
        if self.tmanager is not None:
            self.tmanager.updateConfigData()

    def loadCfg(self, fname=None):
        if fname is None:
            fname, _ = QFileDialog.getOpenFileName(
                self, 'Open file',
                QSettings().value("trace_last_file"), '*.cfg')

        if fname:
            QSettings().setValue("trace_last_file", fname)
            self.modName.setEnabled(False)

            #Figure out what format this is in
            tc = TraceContainerConfig(fname)
            fmt = tc.attr("format")

            #Generate a temp class for getting parameters from
            fmtclass = chipwhisperer.common.traces.TraceContainerTypes.TraceContainerFormatList[
                fmt]

            #Use temp class to finally initilize our "good" version
            self.tmanager = fmtclass()
            self.tmanager.config.loadTrace(fname)
            self.tmanager.loadAllConfig()
            self.paramTree.clear()
            self.paramTree.addParameters(
                self.tmanager.getParams()._PyQtGraphParameter)
Example #6
0
class MeasuringApp(CamObject, QtGui.QMainWindow):
    def __init__(self, *args, **kwargs):
        CamObject.__init__(self)
        QtGui.QMainWindow.__init__(self)
        self.resize(700, 150)
        self.setWindowTitle('Workpiece Dimensional Control')
        self.area = DockArea()
        self.setCentralWidget(self.area)

        # Window Docks
        self.camMenuDock = Dock('Camera Menu', size=(1, 1))
        self.procMenuDock = Dock('Analysis Menu', size=(1, 1))
        self.paramDock = Dock('Parameter Tree', size=(250, 150))
        self.area.addDock(self.camMenuDock, 'right')
        self.area.addDock(self.procMenuDock, 'right')
        self.area.addDock(self.paramDock, 'left')

        # Parameter Tree
        self._parameter_tree = ParameterTree()
        self._parameter_tree.setWindowTitle('Parameter Tree')
        self.paramDock.addWidget(self._parameter_tree)

        # Camera Menu
        self._cam_menu = pg.LayoutWidget(parent=self.camMenuDock)
        self._cam_buttons = self.cam_buttons()
        [btn.resize(btn.minimumSizeHint()) for btn in self._cam_buttons]
        [self._cam_menu.addWidget(btn, row=i, col=0) for btn, i in zip(
            self._cam_buttons, range(len(self._cam_buttons)))]
        self.camMenuDock.addWidget(self._cam_menu)

        # Analysis menu
        self._proc_menu = pg.LayoutWidget(parent=self.procMenuDock)
        self._proc_buttons = self.process_buttons()
        [btn.resize(btn.minimumSizeHint()) for btn in self._proc_buttons]
        [self._proc_menu.addWidget(btn, row=i, col=1) for btn, i in zip(
            self._proc_buttons, range(len(self._proc_buttons)))]
        self.procMenuDock.addWidget(self._proc_menu)

        # Original frames window
        self._orig_frame = FrameWindow("Original")

        # Flowchart input preparation window
        self._prep_flow = FlowchartPrepWindow('Flowchart Input preparation')

        # Calibrate system window
        self._calib_window = FlowchartCalibrateWindow()
        # Calibration Parameters
        self._calib_params = None

        # Measurement preparation window
        self._measure_prep_window = FlowchartMeasureWindow()

        # Realtime measurement window
        self._realtime_measure_window = MeasureRealtimeWindow()

        # Show Main Window
        self.show()

        # Result Queue init
        self.preproc_queue = queue.Queue()

        # FPS display count
        self.fps_display_count = 0

    def cam_buttons(self):
        """
        Menu buttons as list
        """
        # Camera create button
        cam_create = QtGui.QPushButton('Find Camera', parent=self._cam_menu)
        cam_create.clicked.connect(self.create)
        # Camera open button
        cam_open = QtGui.QPushButton('Open Camera', parent=self._cam_menu)
        cam_open.clicked.connect(self.open)
        # Camera print info
        cam_print_info = QtGui.QPushButton('Print Info', parent=self._cam_menu)
        cam_print_info.clicked.connect(self.print_info)
        # Camera start grabbing
        cam_start_grab = QtGui.QPushButton(
            'Start Grabbing', parent=self._cam_menu)
        cam_start_grab.clicked.connect(self.start_grabbing)
        # Camera stop grabbing
        cam_stop_grab = QtGui.QPushButton(
            'Stop Grabbing', parent=self._cam_menu)
        cam_stop_grab.clicked.connect(self.stop_grabbing)
        # Camera close
        cam_close = QtGui.QPushButton('Close Camera', parent=self._cam_menu)
        cam_close.clicked.connect(self.close)
        return [
            cam_create, cam_open, cam_print_info, cam_start_grab,
            cam_stop_grab, cam_close
        ]

    def process_buttons(self):
        """
        Process buttons as list
        """
        # Grab single frame button
        proc_grab_frame = QtGui.QPushButton(
            'Grab Frame', parent=self._proc_menu)
        proc_grab_frame.clicked.connect(self.grab_single_frame)
        proc_discard_frame = QtGui.QPushButton(
            'Discard Frame', parent=self._proc_menu)
        proc_discard_frame.clicked.connect(self.discard_frame)
        proc_calib_sys = QtGui.QPushButton(
            'Calibrate System', parent=self._proc_menu)
        proc_calib_sys.clicked.connect(self.calibrate_system)
        proc_set_calib_const = QtGui.QPushButton(
            'Set Calibration Constants', parent=self._proc_menu)
        proc_set_calib_const.clicked.connect(self.set_calib_const)
        proc_measure_prep = QtGui.QPushButton(
            'Measurement Preparation', parent=self._proc_menu)
        proc_measure_prep.clicked.connect(self.measurement_preparation)
        proc_realtime_start = QtGui.QPushButton(
            'Start Measurement', parent=self._proc_menu)
        proc_realtime_start.clicked.connect(self.start_realtime_measurement)
        proc_realtime_stop = QtGui.QPushButton(
            'Stop Measurement', parent=self._proc_menu)
        proc_realtime_stop.clicked.connect(self.stop_realtime_measurement)
        return [
            proc_grab_frame, proc_discard_frame, proc_calib_sys,
            proc_set_calib_const, proc_measure_prep, proc_realtime_start,
            proc_realtime_stop
        ]

    def open(self):
        """
        Reimplementation of open function to update GUI numbers and sliders
        """
        super().open()
        self._parameter_tree.clear()
        self._parameter_tree.addParameters(
            CameraParams(name='Camera Parameters', cam_obj=self), showTop=True)

    def close(self):
        """
        Reimplementation of close function to update GUI numbers and sliders
        """
        super().close()
        self._parameter_tree.clear()

    def set_default_params(self):
        """
        Reimplementation of set_default_params function to update GUI
        """
        super().set_default_params()
        self._cam_gain.value = self.cam.Gain()
        self._cam_exposure.value = self.cam.ExposureTime()
        self._cam_width.value = self.cam.Width.GetValue()
        self._cam_height.value = self.cam.Height.GetValue()
        self._cam_offsetx.value = self.cam.OffsetX.GetValue()
        self._cam_offsety.value = self.cam.OffsetY.GetValue()

    def start_grabbing(self, strategy=pylon.GrabStrategy_LatestImageOnly):
        """
        Reimplementation of start_grabbing to show new window
        """
        if not self.cam.IsGrabbing():
            self._orig_frame.show()
            self.frame_queue = queue.Queue()
            fg_hndl = FrameGrabEventHandler(self.frame_queue)
            # Frame grab event registering
            self.cam.RegisterImageEventHandler(
                fg_hndl,
                pylon.RegistrationMode_ReplaceAll,
                pylon.Cleanup_Delete
            )
            super().start_grabbing(strategy)
            self.frame_burst(graphicsObject=self._orig_frame)

    def stop_grabbing(self):
        """
        Reimplementation of stop_grabbing to close new window
        """
        if self.cam.IsGrabbing():
            super().stop_grabbing()
            self._orig_frame.close()

    def frame_burst(self, graphicsObject, updateFrame=True, updateFPS=True,
                    updateMeasurementResult=False, numProc=1, fps_display=5):
        """
        Grab frames from camera using software trigger, scheduling and event
        handler.
        frame_burst reimplementation for FPS, frame and measurement result
        update.

        :param graphicsObject: object which methods are called and graphics updated
        :param updateFrame: bool
        :param updateFPS: bool
        :param updateMeasurementResult: bool
        :param numProc: 1
        :param fps_display: int
        """
        if self.fps_count == 0:
            if updateFPS:
                # Update graphicsObject FPS label
                graphicsObject.update_fps(self.fps)
            self.fps_start = pg.ptime.time()
        if self.cam.IsGrabbing():
            for _ in range(numProc):
                if self.cam.WaitForFrameTriggerReady(
                        300, pylon.TimeoutHandling_ThrowException):
                    self.cam.ExecuteSoftwareTrigger()
            frames = [self.frame_queue.get() for _ in range(numProc)]
            self.fps_display_count += 1
            # print('FPS_display_count: {}'.format(self.fps_display_count))
            if updateFrame and not (self.fps_display_count % fps_display):
                self.fps_display_count = 0
                # Update graphicsObject ImageItem
                [graphicsObject.update_frame(frame) for frame in frames]
                self.fps_count += numProc
            if updateMeasurementResult:
                while not self.preproc_queue.empty():
                    graphicsObject.update_measurement_result(
                        self._measure_prep_window.fc_process(
                            dip.Image(self.preproc_queue.get())
                        ))
            # Average FPS on number of frames
            if self.fps_count >= 10:
                fps_time = pg.ptime.time() - self.fps_start
                self.fps = self.fps_count / fps_time
                print("Camera FPS: {:.2f}".format(
                    self.cam.ResultingFrameRate.GetValue()))
                print("FPS: {:.2f}".format(self.fps))
                self.fps_count = 0
            QtCore.QTimer.singleShot(
                1, lambda : self.frame_burst(graphicsObject,
                                             updateFrame,
                                             updateFPS,
                                             numProc,
                                             ))

    def grab_single_frame(self):
        self._prep_flow.set_frame(self._orig_frame.grab_single_frame())
        self._prep_flow.show()

    def discard_frame(self):
        self._prep_flow.close()

    def calibrate_system(self):
        """
        Show Calibration flowchart and set input frame
        """
        self._calib_window.setInput(self._prep_flow.get_dip_slice())
        self._calib_window.show()

    def set_calib_const(self):
        """
        Set and show calibration parameters in parameterTree
        """
        standard_dict = self._calib_window.output()
        self._calib_params = CalibrationParams(
            name='Calibration Parameters', standard_dict=standard_dict)
        self._parameter_tree.clear()
        self._parameter_tree.addParameters(self._calib_params, showTop=True)

    def measurement_preparation(self):
        """
        Show Measurement preparation flowchart and set input frame
        """
        self._measure_prep_window.setInput(
            self._prep_flow.get_dip_slice(),
            self._calib_params.obj_mm_px.value()
        )
        self._measure_prep_window.show()

    def start_realtime_measurement(
            self, strategy=pylon.GrabStrategy_LatestImageOnly):
        """
        Show window for realtime measurement and start grabbing frames from cam
        """
        if not self.cam.IsGrabbing():
            self._realtime_measure_window.show()
            procParallel = ProcessParallel(
                self._measure_prep_window, numberProc=3
            )
            # Queue for storing frames
            self.frame_queue = queue.Queue()
            # Queue for storing measurement result list
            self.preproc_queue = queue.Queue()
            self.fm_hndl = FrameMeasureEventHandler(
                self.frame_queue, self.preproc_queue, procParallel
            )
            # Frame grab event registering
            self.cam.RegisterImageEventHandler(
                self.fm_hndl,
                pylon.RegistrationMode_ReplaceAll,
                pylon.Cleanup_Delete
            )
            super().start_grabbing(strategy)
            self.frame_burst(
                graphicsObject=self._realtime_measure_window,
                updateFPS=False, updateMeasurementResult=True,
                fps_display=10,
                # numProc=procParallel.getNumProc()
            )

    def stop_realtime_measurement(self):
        """
        Close window for realtime measurement and stop grabbing frames from cam
        """
        if self.cam.IsGrabbing():
            super().stop_grabbing()
            self._realtime_measure_window.close()
            self.cam.DeregisterImageEventHandler(self.fm_hndl)
Example #7
0
class ObjectTree(QWidget, ComponentMixin):

    name = 'Object Tree'
    _stash = []

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

    sigObjectsAdded = pyqtSignal(list)
    sigObjectsRemoved = pyqtSignal(list)
    sigCQObjectSelected = pyqtSignal(object)
    sigItemChanged = pyqtSignal(QTreeWidgetItem, int)
    sigObjectPropertiesChanged = pyqtSignal()

    def __init__(self, parent):

        super(ObjectTree, self).__init__(parent)

        self.tree = tree = QTreeWidget(self)
        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)

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

        self._export_STEP_action = \
            QAction('Export as SETP',
                    self,
                    enabled=False,
                    triggered=lambda: \
                        self.export('*step','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):

        item = self.tree.selectedItems()[-1]
        if item.parent() is self.CQ:
            self._export_STL_action.setEnabled(True)
        else:
            self._export_STL_action.setEnabled(False)

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

    def menuActions(self):

        return {'Tools': [self._export_STL_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, GREEN, 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.GetHandle())
            line.SetColor(color)

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

            ais_list.append(line)

        self.sigObjectsAdded.emit(ais_list)
        self.tree.expandToDepth(1)

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

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

        ais_list = []

        #if root is None:
        root = self.CQ

        #remove Vector objects
        objects_f = \
        {k:v for k,v in objects.items() if type(v.val()) not in (Vector,)}

        for name, shape in objects_f.items():
            ais = make_AIS(shape)
            ais.SetTransparency(alpha)
            ais_list.append(ais)
            root.addChild(
                ObjectTreeItem(name,
                               shape=shape,
                               ais=ais,
                               sig=self.sigObjectPropertiesChanged))

        self.sigObjectsAdded.emit(ais_list)

    @pyqtSlot(object, str, float)
    def addObject(
        self,
        obj,
        name='',
        alpha=.0,
    ):

        root = self.CQ

        ais = make_AIS(obj)
        ais.SetTransparency(alpha)

        root.addChild(
            ObjectTreeItem(name,
                           shape=obj,
                           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, file_wildcard, export_type, precision=None):

        item = self.tree.selectedItems()[-1]
        if item.parent() is self.CQ:
            shape = item.shape
        else:
            return

        fname, _ = QFileDialog.getSaveFileName(self, filter=file_wildcard)
        if fname is not '':
            export(shape, export_type, fname, precision)

    @pyqtSlot()
    def handleSelection(self):

        item = self.tree.selectedItems()[-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)
        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(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