コード例 #1
0
    def __init__(self, parent = None):
    
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.view = vtk.vtkGraphLayoutView()
        self.view.SetInteractor(self.ui.vtkWidget.GetRenderWindow().GetInteractor())
        self.ui.vtkWidget.SetRenderWindow(self.view.GetRenderWindow())

        self.level = 2
        self.basisNum = 0
        self.cutoff = 1.7e-5
        self.basisCutoff = 1.0e-6
        self.ebSumCutoff = 0.1
        self.loadGraph()
        
        self.cutoffValid = QtGui.QDoubleValidator(0.0, 1.0, 12, self.ui.lineEdit_cutoff)
        self.ui.lineEdit_cutoff.setValidator(self.cutoffValid)
        self.basisCutoffValid = QtGui.QDoubleValidator(0.0, 1.0, 12, self.ui.lineEdit_basisCutoff)
        self.ui.lineEdit_basisCutoff.setValidator(self.basisCutoffValid)

        # Connect signals and slots
        # QtCore.QObject.connect(self.ui.actionNew, QtCore.SIGNAL("triggered()"), self.fileOpen)
        QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"), self.fileExit)
        QtCore.QObject.connect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        # QtCore.QObject.connect(self.ui.spinBox_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.connect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        # QtCore.QObject.connect(self.ui.spinBox_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        QtCore.QObject.connect(self.ui.listWidget, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.toggleVisibility)
        QtCore.QObject.connect(self.ui.lineEdit_cutoff, QtCore.SIGNAL("editingFinished()"), self.changeCutoff)
        QtCore.QObject.connect(self.ui.lineEdit_basisCutoff, QtCore.SIGNAL("editingFinished()"), self.changeBasisCutoff)

        self.ui.hSlider_basisIndex.setValue(self.basisNum)
        self.ui.spinBox_basisIndex.setValue(self.basisNum)
        self.ui.hSlider_level.setValue(self.level)
        self.ui.spinBox_level.setValue(self.level)
        
        # TODO: Problem with size of ExtBasis for levels below 2...
        self.ui.hSlider_level.setMinimum(2)
        self.ui.spinBox_level.setMinimum(2)
コード例 #2
0
class SimpleView(QtGui.QMainWindow):
    
    def __init__(self, parent = None):
    
        QtGui.QMainWindow.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.view = vtk.vtkGraphLayoutView()
        self.view.SetInteractor(self.ui.vtkWidget.GetRenderWindow().GetInteractor())
        self.ui.vtkWidget.SetRenderWindow(self.view.GetRenderWindow())

        self.level = 2
        self.basisNum = 0
        self.cutoff = 1.7e-5
        self.basisCutoff = 1.0e-6
        self.ebSumCutoff = 0.1
        self.loadGraph()
        
        self.cutoffValid = QtGui.QDoubleValidator(0.0, 1.0, 12, self.ui.lineEdit_cutoff)
        self.ui.lineEdit_cutoff.setValidator(self.cutoffValid)
        self.basisCutoffValid = QtGui.QDoubleValidator(0.0, 1.0, 12, self.ui.lineEdit_basisCutoff)
        self.ui.lineEdit_basisCutoff.setValidator(self.basisCutoffValid)

        # Connect signals and slots
        # QtCore.QObject.connect(self.ui.actionNew, QtCore.SIGNAL("triggered()"), self.fileOpen)
        QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"), self.fileExit)
        QtCore.QObject.connect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        # QtCore.QObject.connect(self.ui.spinBox_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.connect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        # QtCore.QObject.connect(self.ui.spinBox_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        QtCore.QObject.connect(self.ui.listWidget, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.toggleVisibility)
        QtCore.QObject.connect(self.ui.lineEdit_cutoff, QtCore.SIGNAL("editingFinished()"), self.changeCutoff)
        QtCore.QObject.connect(self.ui.lineEdit_basisCutoff, QtCore.SIGNAL("editingFinished()"), self.changeBasisCutoff)

        self.ui.hSlider_basisIndex.setValue(self.basisNum)
        self.ui.spinBox_basisIndex.setValue(self.basisNum)
        self.ui.hSlider_level.setValue(self.level)
        self.ui.spinBox_level.setValue(self.level)
        
        # TODO: Problem with size of ExtBasis for levels below 2...
        self.ui.hSlider_level.setMinimum(2)
        self.ui.spinBox_level.setMinimum(2)
        
    def loadGraph(self):
        
        subgraph = vtk.vtkRandomGraphSource()

        self.view.SetRepresentationFromInputConnection(subgraph.GetOutputPort())
        self.view.ResetCamera()
        self.view.Render()
        self.view.GetInteractor().Start()


    def changeCutoff(self):
        
        tmpCutoffTxt = self.ui.lineEdit_cutoff.text()
        tmpCutoff = tmpCutoffTxt.toDouble()
        if tmpCutoff[1]:
            self.cutoff = tmpCutoff[0]
            # Update multi-resolution graph
            msGraph = self.buildSubGraph(self.level) 
            self.msMapper.SetInput(msGraph)
            self.msMapper.Modified()
            # self.view.Update()
            self.view.Render()
            
    def changeBasisCutoff(self):
        
        tmpCutoffTxt = self.ui.lineEdit_basisCutoff.text()
        tmpCutoff = tmpCutoffTxt.toDouble()
        if tmpCutoff[1]:
            self.basisCutoff = tmpCutoff[0]
            # Update multi-resolution graph
            self.selection.RemoveAllThresholds()
            self.selection.AddThreshold(self.basisCutoff, 10)
            self.selection.Modified()
            # self.view.Update()
            self.view.Render()
            
    
    def buildSubGraph(self, level):
        
        table = vtk.vtkTable()
        col0 = vtk.vtkIntArray()
        col0.SetName('index1')
        col1 = vtk.vtkIntArray()
        col1.SetName('index2')
        val = vtk.vtkDoubleArray()
        val.SetName('weight')
        
        Tmat = self.G.Tree[level,0].T
        minmax = "(%3.2e, %3.2e)" % (abs(Tmat.data).min(), abs(Tmat.data).max())
        self.ui.label_cutoff_minmax.setText(minmax)
        
        ebSum = self.ExtBasis.sum(0)
        idxs = []
        
        for ii in range(Tmat.nzmax):
            xx = Tmat.rowcol(ii)[0]
            yy = Tmat.rowcol(ii)[1]
            if ((ebSum[0,xx] > self.ebSumCutoff) and (ebSum[0,yy] > self.ebSumCutoff)):
                # print ebSum[0,xx], ebSum[0,yy]
                # Always include diagonal elements (no matter what cutoff) so all vertices are created
                if ((abs(Tmat.getdata(ii)) > self.cutoff) | (Tmat.rowcol(ii)[0]==Tmat.rowcol(ii)[1])):
                    col0.InsertNextValue(xx)
                    col1.InsertNextValue(yy)
                    # But, take out self-loops for edge color scale
                    if (xx == yy):
                        val.InsertNextValue(0.0)        
                        idxs.append(self.G.Tree[level,0].ExtIdxs[xx]-1)
                    else:
                        val.InsertNextValue(abs(Tmat.getdata(ii)))        
        
        table.AddColumn(col0)
        table.AddColumn(col1)
        table.AddColumn(val)
        
        tgraph = vtk.vtkTableToGraph()
        tgraph.SetInput(table)
        tgraph.AddLinkVertex('index2', 'stuff', False)
        tgraph.AddLinkVertex('index1', 'stuff', False)
        tgraph.AddLinkEdge('index2', 'index1')
        
        rawGraph = tgraph.GetOutput()
        rawGraph.Update()
        # print graph
        
        # Grab points from original set with ExtIdxs
        ptsArray = VN.vtk_to_numpy(self.pts.GetData())
        # Remember Matlab uses one-based indices (ExtIdxs-1 for Numpy)
        # print (self.G.Tree[level,0].ExtIdxs-1)
        # print ptsArray[self.G.Tree[level,0].ExtIdxs-1,:]
        ptsMatrix = N.matrix(ptsArray)
        ptsSubMatrix = ptsMatrix[idxs,:]
        ptsSub = VN.numpy_to_vtk(ptsSubMatrix)
        # print VN.vtk_to_numpy(ptsSub)
        pts = vtk.vtkPoints()
        pts.SetData(ptsSub)
        rawGraph.SetPoints(pts)
        # print pts
            
        strategy = vtk.vtkPassThroughLayoutStrategy()
        layout = vtk.vtkGraphLayout()
        layout.SetInput(rawGraph)
        layout.SetLayoutStrategy(strategy)
        
        edgeLayout = vtk.vtkEdgeLayout()
        edgeStrategy = vtk.vtkArcParallelEdgeStrategy()
        edgeStrategy.SetNumberOfSubdivisions(50)
        edgeLayout.SetInputConnection(layout.GetOutputPort())
        edgeLayout.SetLayoutStrategy(edgeStrategy)
        edgeLayout.Update()
        
        return edgeLayout.GetOutput()
         
    def basisUpdate(self, index):
        
        QtCore.QObject.disconnect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.disconnect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        
        self.basisNum = index
        self.ui.spinBox_basisIndex.setValue(index)
        self.ui.hSlider_basisIndex.setValue(index)
        self.selection.RemoveAllIDs()
        
        # Try to directly swap ExtBasis vertex data
        # print 'ExtBasis shape: ' + str(self.ExtBasis[:,self.basisNum].data.shape) + ' (level,basis) (' + str(self.level) + ',' + str(self.basisNum) + ')'
        
        # Indexing of ExtBasis is backwards from graph, so need to reverse with [::-1]
        # and array not "contiguous" if don't do .copy()
        self.Esub[:] = self.ExtBasis[:,self.basisNum].data[::-1].copy()
        self.EsubSq[:] = self.Esub**2
        # self.Esub[:] = N.random.random(self.ExtBasis[:,self.basisNum].data.shape[0])
        # SubIdxs = (self.Esub > 0.001).nonzero()
        # SubIdxs = (self.Esub**2 > 0.8).nonzero()
        self.vertexData.Modified()
        self.degree.Update()
                
        # for ii in SubIdxs[0]:
        #     self.selection.AddID(0,ii)
        vertRange = self.vertMapper.GetInput().GetPointData().GetArray(self.vertMapper.GetArrayName()).GetRange()
        self.vertMapper.SetScalarRange(-1.0*vertRange[1], vertRange[1])
        self.selection.Modified()
        # tmpMin = self.EsubSq.min()
        # tmpMax = self.EsubSq.max()
        # self.map0.SetScalarRange(-100.0*tmpMax, 100.0*tmpMax)
        minmax = "(%3.2e, %3.2e)" % (self.EsubSq.min(), self.EsubSq.max())
        self.ui.label_basisCutoff_minmax.setText(minmax)
        # self.view.Update()
        self.view.Render()
        
        QtCore.QObject.connect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.connect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        
    def levelUpdate(self, index):
        
        QtCore.QObject.disconnect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.disconnect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        
        self.level = index
        self.ui.spinBox_level.setValue(index)
        self.ui.hSlider_level.setValue(index)
        # Start setting up basis function subgraph
        self.ExtBasis = self.G.Tree[self.level,0].ExtBasis
        self.basisMax = self.ExtBasis.shape[1]-1    # zero-based indices
        if self.basisNum > self.basisMax:
            self.basisNum = self.basisMax
            self.ui.hSlider_basisIndex.setValue(self.basisMax)
            self.ui.spinBox_basisIndex.setValue(self.basisMax)
        self.ui.hSlider_basisIndex.setMinimum(0)
        self.ui.hSlider_basisIndex.setMaximum(self.basisMax)
        self.ui.spinBox_basisIndex.setMinimum(0)
        self.ui.spinBox_basisIndex.setMaximum(self.basisMax)

        # self.selection.RemoveAllIDs()
        # print 'ExtBasis shape: ' + str(self.ExtBasis[:,self.basisNum].data.shape) + ' (level,basis) (' + str(self.level) + ',' + str(self.basisNum) + ')'
        
        # Indexing of ExtBasis is backwards from graph, so need to reverse with [::-1]
        # and array not "contiguous" if don't do .copy()
#         self.Esub[:] = self.ExtBasis[:,self.basisNum].data[::-1].copy()
#         self.EsubSq[:] = self.Esub**2
#         # self.Esub[:] = N.random.random(self.ExtBasis[:,self.basisNum].data.shape[0])
#         # SubIdxs = (self.Esub > 0.001).nonzero()
#         # SubIdxs = (self.Esub**2 > 0.8).nonzero()
#         self.vertexData.Modified()
#         self.degree.Update()
        
        # Update multi-resolution graph
        msGraph = self.buildSubGraph(index) 
        self.msMapper.SetInput(msGraph)
        self.msMapper.Modified()

        # for ii in SubIdxs[0]:
        #     self.selection.AddID(0,ii)
        self.selection.Modified()
        # tmpMin = self.Esub.min()
        # tmpMax = self.Esub.max()
        # self.map0.SetScalarRange(-100.0*tmpMax, 100.0*tmpMax)
        self.basisUpdate(self.ui.hSlider_basisIndex.value())
        
        QtCore.QObject.connect(self.ui.hSlider_basisIndex, QtCore.SIGNAL("valueChanged(int)"), self.basisUpdate)
        QtCore.QObject.connect(self.ui.hSlider_level, QtCore.SIGNAL("valueChanged(int)"), self.levelUpdate)
        
    def toggleVisibility(self, item):
        
        tmpQtActor = item.data(QtCore.Qt.UserRole)
        tmpActor = tmpQtActor.toPyObject()
        if tmpActor.GetClassName() == 'vtkActorCollection':
            # Loop through actor collection
            tmpActor.InitTraversal()
            singleActor = tmpActor.GetNextActor()
            while singleActor is not None:
                self.toggleActorVisibility(item,singleActor)
                singleActor = tmpActor.GetNextActor()
        else:
            # Single actor
            self.toggleActorVisibility(item,tmpActor)
            
    def toggleActorVisibility(self, item, tmpActor):
        actorVis = tmpActor.GetVisibility()
        itemCheck = item.checkState()   # QtCore.Qt.Checked = 2, QtCore.Qt.Unchecked = 0
        if (actorVis == 0) and (itemCheck == QtCore.Qt.Checked):
            tmpActor.SetVisibility(1)
            # self.view.Update()
            self.view.Render()
        elif (actorVis == 1) and (itemCheck == QtCore.Qt.Unchecked):
            tmpActor.SetVisibility(0)
            # self.view.Update()
            self.view.Render()
        
        
    def fileExit(self):
        
        # Usually would use the qApp global variable qApp.quit(), but wasn't working...
        QtGui.QApplication.instance().quit()