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

📄 owparallelcoordinates.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 3 页
字号:
"""
<name>Parallel coordinates</name>
<description>Parallel coordinates (multiattribute) visualization.</description>
<contact>Gregor Leban (gregor.leban@fri.uni-lj.si)</contact>
<icon>icons/ParallelCoordinates.png</icon>
<priority>3200</priority>
"""
# ParallelCoordinates.py
#
# Show data using parallel coordinates visualization method
# 

from OWVisWidget import *
from OWParallelGraph import *
import OWToolbars, OWGUI, OWDlgs, orngVisFuncts 
from sys import getrecursionlimit, setrecursionlimit

###########################################################################################
##### WIDGET : Parallel coordinates visualization
###########################################################################################
class OWParallelCoordinates(OWVisWidget):
    settingsList = ["attrContOrder", "attrDiscOrder", "graph.jitterSize", "graph.showDistributions",
                    "graph.showAttrValues", "graph.hidePureExamples", "graph.globalValueScaling", "linesDistance",
                    "graph.useSplines", "graph.lineTracking", "graph.enabledLegend", "autoSendSelection",
                    "toolbarSelection", "graph.showStatistics", "colorSettings", "showAllAttributes"]
    attributeContOrder = ["None", "ReliefF", "Fisher discriminant", "Signal to Noise", "Signal to Noise For Each Class"]
    attributeDiscOrder = ["None", "ReliefF", "GainRatio"]
    jitterSizeNums = [0, 2,  5,  10, 15, 20, 30]
    linesDistanceNums = [10, 20, 30, 40, 50, 60, 70, 80, 100, 120, 150]

    def __init__(self,parent=None, signalManager = None):
        OWWidget.__init__(self, parent, signalManager, "Parallel Coordinates", TRUE)

        #add a graph widget
        self.box = QVBoxLayout(self.mainArea)
        self.graph = OWParallelGraph(self, self.mainArea)
        self.slider = QSlider(QSlider.Horizontal, self.mainArea)
        self.sliderRange = 0
        self.slider.setRange(0, 0)
        self.slider.setTickmarks(QSlider.Below)
        self.isResizing = 0
        self.showAllAttributes = 0
        
        self.box.addWidget(self.graph)
        self.box.addWidget(self.slider)

        self.inputs = [("Examples", ExampleTable, self.cdata), ("Example Subset", ExampleTable, self.subsetdata), ("Attribute Selection List", AttributeList, self.attributeSelection)]
        self.outputs = [("Selected Examples", ExampleTableWithClass), ("Unselected Examples", ExampleTableWithClass), ("Attribute Selection List", AttributeList)]
    
        #set default settings
        self.data = None
        self.linesDistance = 60
        self.autoSendSelection = 1
        self.attrDiscOrder = "None"
        self.attrContOrder = "None"
        self.projections = None
        self.correlationDict = {}
        self.middleLabels = "Correlations"
        self.attributeSelectionList = None  
        self.toolbarSelection = 0
        self.colorSettings = None
        
        self.graph.jitterSize = 10
        self.graph.showDistributions = 1
        self.graph.showStatistics = 0
        self.graph.showAttrValues = 1
        self.graph.hidePureExamples = 1
        self.graph.globalValueScaling = 0
        self.graph.useSplines = 0
        self.graph.lineTracking = 0
        self.graph.enabledLegend = 1
        self.setSliderIndex = -1

        #load settings
        self.loadSettings()

        #GUI
        self.tabs = QTabWidget(self.space, 'tabWidget')
        self.GeneralTab = QVGroupBox(self)
        self.SettingsTab = QVGroupBox(self, "Settings")
        self.tabs.insertTab(self.GeneralTab, "General")
        self.tabs.insertTab(self.SettingsTab, "Settings")

        #add controls to self.controlArea widget
        self.targetValueCombo = OWGUI.comboBox(self.GeneralTab, self, "targetValue", box = " Target Class Value ", sendSelectedValue = 1, valueType = str, callback = self.updateGraph)

        self.createShowHiddenLists(self.GeneralTab, callback = self.updateGraph)
        self.connect(self.shownAttribsLB, SIGNAL('doubleClicked(QListBoxItem *)'), self.flipAttribute)

        self.optimizationDlg = ParallelOptimization(self, signalManager = self.signalManager)
        self.optimizationDlgButton = OWGUI.button(self.GeneralTab, self, "Optimization dialog", callback = self.optimizationDlg.reshow, debuggingEnabled = 0)

        self.zoomSelectToolbar = OWToolbars.ZoomSelectToolbar(self, self.GeneralTab, self.graph, self.autoSendSelection)
        self.connect(self.zoomSelectToolbar.buttonSendSelections, SIGNAL("clicked()"), self.sendSelections)

        #connect controls to appropriate functions
        self.connect(self.slider, SIGNAL("valueChanged(int)"), self.updateGraphSlider)
        self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile)

        # ####################################
        # SETTINGS functionality

        boxX = OWGUI.widgetBox(self.SettingsTab, " Graph settings ")
        OWGUI.comboBox(boxX, self, "graph.jitterSize", label = 'Jittering size (% of size):  ', orientation='horizontal', callback = self.setJitteringSize, items = self.jitterSizeNums, sendSelectedValue = 1, valueType = float)
        OWGUI.comboBox(boxX, self, "linesDistance", label = 'Minimum axis distance:  ', orientation='horizontal', callback = self.updateGraph, items = self.linesDistanceNums, tooltip = "What is the minimum distance between two adjecent attribute axis", sendSelectedValue = 1, valueType = int)
        
        # visual settings
        box = OWGUI.widgetBox(self.SettingsTab, " Visual settings ")
        OWGUI.checkBox(box, self, 'graph.showAttrValues', 'Show attribute values', callback = self.updateValues)
        OWGUI.checkBox(box, self, 'graph.hidePureExamples', 'Hide pure examples', callback = self.updateValues, tooltip = "When one value of a discrete attribute has only examples from one class, \nstop drawing lines for this example. Figure must be interpreted from left to right.")
        OWGUI.checkBox(box, self, 'graph.useSplines', 'Show splines', callback = self.updateValues, tooltip  = "Show lines using splines")
        OWGUI.checkBox(box, self, 'graph.lineTracking', 'Line tracking', callback = self.updateValues, tooltip = "Show nearest example with a wider line. The rest of the lines \nwill be shown in lighter colors.")
        OWGUI.checkBox(box, self, 'graph.enabledLegend', 'Show legend', callback = self.updateValues)
        OWGUI.checkBox(box, self, 'graph.globalValueScaling', 'Global Value Scaling', callback = self.setGlobalValueScaling)

        box3 = OWGUI.widgetBox(self.SettingsTab, " Statistics ")
        OWGUI.comboBox(box3, self, "graph.showStatistics", items = ["No statistics", "Means, deviations", "Median, quartiles"], callback = self.updateValues, sendSelectedValue = 0, valueType = int)
        OWGUI.checkBox(box3, self, 'graph.showDistributions', 'Show distributions', callback = self.updateValues, tooltip = "Show bars with distribution of class values (only for discrete attributes)")

        OWGUI.comboBox(self.SettingsTab, self, "middleLabels", box = " Middle labels ", items = ["Off", "Correlations", "VizRank"], callback = self.updateGraph, tooltip = "What information do you wish to view on top in the middle of coordinate axes?", sendSelectedValue = 1, valueType = str)
        
        hbox4 = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal")
        OWGUI.button(hbox4, self, "Set Colors", self.setColors, tooltip = "Set the canvas background color and color palette for coloring continuous variables", debuggingEnabled = 0)

        box2 = OWGUI.widgetBox(self.SettingsTab, " Sending selection ")
        OWGUI.checkBox(box2, self, 'autoSendSelection', 'Auto send selected data', callback = self.setAutoSendSelection, tooltip = "Send signals with selected data whenever the selection changes.")

        # continuous attribute ordering
        OWGUI.comboBox(self.SettingsTab, self, "attrContOrder", box = " Continuous attribute ordering ", items = self.attributeContOrder, callback = self.updateShownAttributeList, sendSelectedValue = 1, valueType = str)
        OWGUI.comboBox(self.SettingsTab, self, "attrDiscOrder", box = " Discrete attribute ordering ", items = self.attributeDiscOrder, callback = self.updateShownAttributeList, sendSelectedValue = 1, valueType = str)

        self.graph.autoSendSelectionCallback = self.setAutoSendSelection
        self.icons = self.createAttributeIconDict()
        
        # add a settings dialog and initialize its values        
        self.activateLoadedSettings()
        self.resize(900, 700)
        

    # #########################
    # OPTIONS
    # #########################
    def activateLoadedSettings(self):
        dlg = self.createColorDialog()
        self.graph.contPalette = dlg.getContinuousPalette("contPalette")
        self.graph.discPalette = dlg.getDiscretePalette()
        self.graph.setCanvasBackground(dlg.getColor("Canvas"))
        apply([self.zoomSelectToolbar.actionZooming, self.zoomSelectToolbar.actionRectangleSelection, self.zoomSelectToolbar.actionPolygonSelection][self.toolbarSelection], [])
        self.cbShowAllAttributes()

    def flipAttribute(self, item):
        if self.graph.flipAttribute(str(item.text())):
            self.updateGraph()
        else:
            self.information("Didn't flip the attribute. To flip a continuous attribute uncheck 'Global value scaling' checkbox.")
        
    def updateGraph(self, *args):
        attrs = self.getShownAttributeList()
        maxAttrs = self.mainArea.width() / self.linesDistance
        if len(attrs) > maxAttrs:
            rest = len(attrs) - maxAttrs
            if self.sliderRange != rest:
                self.slider.setRange(0, rest)
                self.sliderRange = rest
            elif self.isResizing:
                self.isResizing = 0
                return  # if we resized widget and it doesn't change the number of attributes that are shown then we return
            start = min(self.slider.value(), len(attrs)-maxAttrs)
            if self.setSliderIndex != -1:
                if self.setSliderIndex == 0: start = 0
                else:                        start = min(len(attrs)-maxAttrs, self.setSliderIndex - (maxAttrs+1)/2)
                start = max(start, 0)
                self.setSliderIndex = -1
                self.slider.setValue(start)
        else:
            self.slider.setRange(0,0)
            self.sliderRange = 0
            maxAttrs = len(attrs)
            start = 0

        targetVal = str(self.targetValueCombo.currentText())
        if targetVal == "(None)": targetVal = None
        #self.graph.updateData(attrs[start:start+maxAttrs], targetVal, self.buildMidLabels(attrs[start:start+maxAttrs]))
        self.graph.updateData(attrs, targetVal, self.buildMidLabels(attrs), start, start + maxAttrs)
        self.slider.repaint()
        self.graph.update()
        #self.graph.repaint()

    def updateGraphSlider(self, *args):
        attrs = self.getShownAttributeList()
        maxAttrs = self.mainArea.width() / self.linesDistance
        start = min(self.slider.value(), len(attrs)-maxAttrs)
        self.graph.setAxisScale(QwtPlot.xBottom, start, start + maxAttrs - 1, 1)
        self.graph.update()

    # build a list of strings that will be shown in the middle of the parallel axis
    def buildMidLabels(self, attrs):
        labels = []
        if self.middleLabels == "Off" or self.data == None or len(self.data) == 0: return None
        elif self.middleLabels == "Correlations":
            for i in range(len(attrs)-1):
                corr = None
                if (attrs[i], attrs[i+1]) in self.correlationDict.keys():   corr = self.correlationDict[(attrs[i], attrs[i+1])]
                elif (attrs[i+1], attrs[i]) in self.correlationDict.keys(): corr = self.correlationDict[(attrs[i+1], attrs[i])]
                else:
                    corr = orngVisFuncts.computeCorrelation(self.data, attrs[i], attrs[i+1])
                    self.correlationDict[(attrs[i], attrs[i+1])] = corr
                if corr and len(self.graph.attributeFlipInfo.keys()) > 0 and (self.graph.attributeFlipInfo[attrs[i]] != self.graph.attributeFlipInfo[attrs[i+1]]): corr = -corr
                if corr: labels.append("%2.3f" % (corr))
                else: labels.append("")
        elif self.middleLabels == "VizRank":
            for i in range(len(attrs)-1):
                val = self.optimizationDlg.getVizRankVal(attrs[i], attrs[i+1])
                if val: labels.append("%2.2f%%" % (val))
                else: labels.append("")
        return labels
                

    # ###### SHOWN ATTRIBUTE LIST ##############
    # set attribute list
    def setShownAttributeList(self, data, shownAttributes = None):
        shown = []
        hidden = []
        if not data: return

        if shownAttributes:
            if type(shownAttributes[0]) == tuple:
                shown = shownAttributes
            else:
                domain = data.domain
                shown = [(domain[a].name, domain[a].varType) for a in shownAttributes]
            hidden = filter(lambda x:x not in shown, [(a.name, a.varType) for a in data.domain.attributes])
        else:
            shown, hidden, maxIndex = orngVisFuncts.selectAttributes(data, self.attrContOrder, self.attrDiscOrder)
            shown = [(attr, data.domain[attr].varType) for attr in shown]
            hidden = [(attr, data.domain[attr].varType) for attr in hidden]
            if self.showAllAttributes:
                shown += hidden
                hidden = []
            else:
                hidden = shown[10:] + hidden
                shown = shown[:10]
                
        if data.domain.classVar and (data.domain.classVar.name, data.domain.classVar.varType) not in shown + hidden:
            hidden += [(data.domain.classVar.name, data.domain.classVar.varType)]

        self.shownAttributes = shown
        self.hiddenAttributes = hidden
        self.selectedHidden = []
        self.selectedShown = []
        self.resetAttrManipulation()
        self.sendShownAttributes()
                       
       
    def sendShownAttributes(self):
        self.send("Attribute Selection List", self.getShownAttributeList())

    # #############################################

    # had to override standart show to call updateGraph. otherwise self.mainArea.width() gives incorrect value    
    def show(self):
        OWWidget.show(self)
        self.updateGraph()

⌨️ 快捷键说明

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