⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 owinteractiongraph.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 2 页
字号:
"""
<name>Interaction Graph</name>
<description>Interaction graph construction and viewer.</description>
<icon>icons/InteractionGraph.png</icon>
<contact>Aleks Jakulin</contact> 
<priority>4000</priority>
"""
# InteractionGraph.py
#
# 

from OWWidget import *
from qt import *
from qtcanvas import *
import orngInteract
import statc
import os
from re import *
from math import floor, ceil
from orngCI import FeatureByCartesianProduct

class IntGraphView(QCanvasView):
    def __init__(self, parent, name, *args):
        apply(QCanvasView.__init__,(self,) + args)
        self.parent = parent
        self.name = name
        self.connect(self, SIGNAL("contentsMoving(int,int)"), self.contentsMoving)

    # mouse button was pressed
    def contentsMousePressEvent(self, ev):
        self.parent.mousePressed(self.name, ev)

    def contentsMoving(self, x,y):
        self.parent.contentsMoving(x,y)        


###########################################################################################
##### WIDGET : Interaction graph
###########################################################################################
class OWInteractionGraph(OWWidget):
    settingsList = ["onlyImportantInteractions"]
    
    def __init__(self, parent=None, signalManager = None):
        OWWidget.__init__(self, parent, signalManager, "Interaction graph")

        self.inputs = [("Examples", ExampleTable, self.cdata)]
        self.outputs = [("Examples", ExampleTable), ("Attribute Pair", list), ("Selected Attributes List", list)]
    

        #set default settings
        self.originalData = None
        self.data = None
        self.dataSize = 1
        self.rest = None
        self.interactionMatrix = None
        self.rectIndices = {}   # QRect rectangles
        self.rectNames   = {}   # info about rectangle names (attributes)
        self.lines = []         # dict of form (rectName1, rectName2):(labelQPoint, [p1QPoint, p2QPoint, ...])
        self.interactionRects = []
        self.rectItems = []
        self.viewXPos = 0       # next two variables are used at setting tooltip position
        self.viewYPos = 0       # inside canvasView

        self.onlyImportantInteractions = 1
        self.mergeAttributes = 0

        #load settings
        self.loadSettings()

        # add a settings dialog and initialize its values
        self.splitCanvas = QSplitter(self.mainArea)
        
        self.canvasL = QCanvas(2000, 2000)
        self.canvasViewL = IntGraphView(self, "interactions", self.canvasL, self.splitCanvas)
        self.canvasViewL.show()
        
        self.canvasR = QCanvas(2000,2000)
        self.canvasViewR = IntGraphView(self, "graph", self.canvasR, self.splitCanvas)
        self.canvasViewR.show()


        #GUI
        #add controls to self.controlArea widget
        self.shownAttribsGroup = QVGroupBox(self.space)
        self.addRemoveGroup = QHButtonGroup(self.space)
        self.hiddenAttribsGroup = QVGroupBox(self.space)
        self.shownAttribsGroup.setTitle("Selected attributes")
        self.hiddenAttribsGroup.setTitle("Unselected attributes")

        self.shownAttribsLB = QListBox(self.shownAttribsGroup)
        self.shownAttribsLB.setSelectionMode(QListBox.Extended)

        self.hiddenAttribsLB = QListBox(self.hiddenAttribsGroup)
        self.hiddenAttribsLB.setSelectionMode(QListBox.Extended)
        
        self.attrAddButton = QPushButton("Add attr.", self.addRemoveGroup)
        self.attrRemoveButton = QPushButton("Remove attr.", self.addRemoveGroup)

        self.mergeAttributesCB = QCheckBox('Merge attributes', self.space)
        self.importantInteractionsCB = QCheckBox('Show only important interactions', self.space)
        
        self.selectionButton = QPushButton("Show selection", self.space)

        QToolTip.add(self.selectionButton, "Sends 'selection' signal to any successor visualization widgets.\nThis signal contains a list of selected attributes to visualize.")
        QToolTip.add(self.mergeAttributesCB, "Enable or disable attribute merging. If enabled, you can merge \ntwo attributes with right mouse click inside attribute rectangle.\nMerged attribute is then built as cartesian product of corresponding attribute pair\nand added to the list of possible attributes")


        self.saveLCanvas = QPushButton("Save left canvas", self.space)
        self.saveRCanvas = QPushButton("Save right canvas", self.space)
        self.connect(self.saveLCanvas, SIGNAL("clicked()"), self.saveToFileLCanvas)
        self.connect(self.saveRCanvas, SIGNAL("clicked()"), self.saveToFileRCanvas)

        #connect controls to appropriate functions
        self.connect(self.attrAddButton, SIGNAL("clicked()"), self.addAttributeClick)
        self.connect(self.attrRemoveButton, SIGNAL("clicked()"), self.removeAttributeClick)
        self.connect(self.selectionButton, SIGNAL("clicked()"), self.selectionClick)
        self.connect(self.mergeAttributesCB, SIGNAL("toggled(bool)"), self.mergeAttributesEvent)
        self.connect(self.importantInteractionsCB, SIGNAL("toggled(bool)"), self.showImportantInteractions)

        #self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile)
        #self.connect(self.settingsButton, SIGNAL("clicked()"), self.options.show)
        self.activateLoadedSettings()

    def mergeAttributesEvent(self, b):
        self.mergeAttributes = b
        if b == 0:
            self.updateNewData(self.originalData)
        

    def showImportantInteractions(self, b):
        self.onlyImportantInteractions = b
        self.showInteractionRects(self.data)

    def activateLoadedSettings(self):
        self.importantInteractionsCB.setChecked(self.onlyImportantInteractions)

    # did we click inside the rect rectangle
    def clickInside(self, rect, point):
        x = point.x()
        y = point.y()
        
        if rect.left() > x: return 0
        if rect.right() < x: return 0
        if rect.top() > y: return 0
        if rect.bottom() < y: return 0

        return 1
        
    # if we clicked on edge label send "wiew" signal, if clicked inside rectangle select/unselect attribute
    def mousePressed(self, name, ev):
        if ev.button() == QMouseEvent.LeftButton and name == "graph":
            for name in self.rectNames:
                clicked = self.clickInside(self.rectNames[name].rect(), ev.pos())
                if clicked == 1:
                    self._setAttrVisible(name, not self.getAttrVisible(name))
                    self.showInteractionRects(self.data)
                    self.canvasR.update()
                    return
            for (attr1, attr2, rect) in self.lines:
                clicked = self.clickInside(rect.rect(), ev.pos())
                if clicked == 1:
                    self.send("Attribute Pair", [attr1, attr2])
                    return
        elif ev.button() == QMouseEvent.LeftButton and name == "interactions":
            self.rest = None
            for (rect1, rect2, rect3, nbrect, text1, text2, tooltipRect, tooltipText) in self.interactionRects:
                if self.clickInside(tooltipRect, ev.pos()) == 1:
                    self.send("Attribute Pair", [str(text1.text()), str(text2.text())])

        elif ev.button() == QMouseEvent.RightButton and name == "interactions":
            if not self.mergeAttributes == 1: return

            found = 0; i = 0
            while not found and i < len(self.interactionRects):
                (rect1, rect2, rect3, nbrect, text1, text2, tooltipRect, tooltipText) = self.interactionRects[i]
                if self.clickInside(tooltipRect, ev.pos()) == 1:
                    attr1 = str(text1.text()); attr2 = str(text2.text())
                    found = 1
                i+=1
            if not found: return

            data = self.interactionMatrix.discData
            (cart, profit) = FeatureByCartesianProduct(data, [data.domain[attr1], data.domain[attr2]])
            if cart in data.domain: return  # if this attribute already in domain return

            for attr in data.domain:
                if cart.name == attr.name:
                    print "Attribute pair already in the domain"
                    return
        
            tempData = data.select(list(data.domain) + [cart])
            dd = orange.DomainDistributions(tempData)
            vals = []
            for i in range(len(cart.values)):
                if dd[cart][i] != 0.0:
                    vals.append(cart.values[i])

            newVar = orange.EnumVariable(cart.name, values = vals)
            newData = data.select(list(data.domain) + [newVar])
            for i in range(len(newData)):
                newData[i][newVar] = tempData[i][cart]

            #rest = newData.select({cart.name:todoList})
            
            #print "intervals = %d, non clear values = %d" % (len(cart.values), len(todoList))
            #print "entropy left = %f" % (float(len(rest)) / float(self.dataSize))
            self.updateNewData(newData)


    # we catch mouse release event so that we can send the "view" signal
    def onMouseReleased(self, e):
        for i in range(len(self.graphs)):
            if self.graphs[i].blankClick == 1:
                (attr1, attr2, className, string) = self.graphParameters[i]
                self.send("Attribute Pair", [attr1, attr2])
                self.graphs[i].blankClick = 0

    # click on selection button   
    def selectionClick(self):
        if self.data == None: return
        l = []
        for i in range(self.shownAttribsLB.count()):
            l.append(str(self.shownAttribsLB.text(i)))
        self.send("Selected Attributes List", l)

    def resizeEvent(self, e):
        if hasattr(self, "splitCanvas"):
            self.splitCanvas.resize(self.mainArea.size())


    ####### CDATA ################################
    # receive new data and update all fields
    def cdata(self, data):
        if not data:
            return
        self.originalData = orange.Preprocessor_dropMissing(data)
        self.dataSize = len(self.originalData)

        self.updateNewData(self.originalData)
        
    def updateNewData(self, data):
        self.data = data
        self.interactionMatrix = orngInteract.InteractionMatrix(data, dependencies_too=1)

        # save discretized data and repair invalid names
        
        for attr in self.interactionMatrix.discData.domain.attributes:
            attr.name = attr.name.replace("ED_","")
            attr.name = attr.name.replace("D_","")
            attr.name = attr.name.replace("M_","")

        self.interactionList = []
        entropy = self.interactionMatrix.entropy
        if entropy == 0.0: return

        ################################
        # create a sorted list of total information
        for ((val,(val2, attrIndex1, attrIndex2))) in self.interactionMatrix.list:
            gain1 = self.interactionMatrix.gains[attrIndex1] / entropy
            gain2 = self.interactionMatrix.gains[attrIndex2] / entropy
            total = (val/entropy) + gain1 + gain2
            self.interactionList.append((total, (gain1, gain2, attrIndex1, attrIndex2)))
        self.interactionList.sort()
        self.interactionList.reverse()
       
        f = open('interaction.dot','w')
        self.interactionMatrix.exportGraph(f, significant_digits=3,positive_int=8,negative_int=8,absolute_int=0,url=1)
        f.flush()
        f.close()

        # execute dot and save otuput to pipes
        (pipePngOut, pipePngIn) = os.popen2("dot interaction.dot -Tpng", "b")
        (pipePlainOut, pipePlainIn) = os.popen2("dot interaction.dot -Tismap", "t")
        
        textPng = pipePngIn.read()
        textPlainList = pipePlainIn.readlines()
        pipePngIn.close()
        pipePlainIn.close()
        pipePngOut.close()
        pipePlainOut.close()
        os.remove('interaction.dot')

        # if the output from the pipe was empty, then the software isn't installed correctly
        if len(textPng) == 0:
            print "-----------------------------"
            print "Error. This widget needs graphviz software package installed. You can find it on the internet."
            print "-----------------------------"
            return
        
        # create a picture
        pixmap = QPixmap()
        pixmap.loadFromData(textPng)
        canvasPixmap = QCanvasPixmap(pixmap, QPoint(0,0))
        width = canvasPixmap.width()
        height = canvasPixmap.height()

        # hide all rects
        for rectInd in self.rectIndices.keys():
            self.rectIndices[rectInd].hide()

        self.canvasR.setTiles(pixmap, 1, 1, width, height)
        self.canvasR.resize(width, height)
        
        self.rectIndices = {}       # QRect rectangles
        self.rectNames   = {}       # info about rectangle names (attributes)
        self.lines = []             # dict of form (rectName1, rectName2):(labelQPoint, [p1QPoint, p2QPoint, ...])

        
        self.parseGraphData(data, textPlainList, width, height)
        self.initLists(data)   # add all attributes found in .dot file to shown list
        self.showInteractionRects(data) # use interaction matrix to fill the left canvas with rectangles
        
        self.canvasL.update()
        self.canvasR.update()

        self.send("Examples", data)


    #########################################
    # do we want to show interactions between attrIndex1 and attrIndex2
    def showInteractionPair(self, attrIndex1, attrIndex2):
        attrName1 = self.data.domain[attrIndex1].name
        attrName2 = self.data.domain[attrIndex2].name

        if self.mergeAttributes == 1:
            if self.getAttrVisible(attrName1) == 0 or self.getAttrVisible(attrName2) == 0: return 0
            list1 = attrName1.split("-")
            list2 = attrName2.split("-")

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -