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

📄 owdistancemap.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 2 页
字号:
"""
<name>Distance Map</name>
<description>Displays distance matrix as a heat map.</description>
<icon>icons/DistanceMap.png</icon>
<contact>Blaz Zupan (blaz.zupan(@at@)fri.uni-lj.si)</contact> 
<priority>1500</priority>
"""

import orange, math
import OWGUI, OWToolbars
from qt import *
from qtcanvas import *
from OWWidget import *

from ColorPalette import *
import OWToolbars

##############################################################################
# parameters that determine the canvas layout

c_offsetX = 10; c_offsetY = 10  # top and left border
c_spaceX = 10; c_spaceY = 10    # space btw graphical elements
c_legendHeight = 15             # height of the legend
c_averageStripeWidth = 12       # width of the stripe with averages

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

class EventfulCanvasView(QCanvasView):
    def __init__(self, canvas, parent, master):
        QCanvasView.__init__(self, canvas,parent)
        self.master = master
        self.viewport().setMouseTracking(True)

    def contentsMousePressEvent (self, event):
        self.master.mousePress(event.pos().x(), event.pos().y())

    def contentsMouseReleaseEvent (self, event):
        self.master.mouseRelease(event.pos().x(), event.pos().y())

    def contentsMouseMoveEvent (self, event):
        self.master.mouseMove(event.pos().x(), event.pos().y())

# main class
v_sel_width = 2
v_legend_width = 104
v_legend_height = 18
v_legend_offsetX = 5
v_legend_offsetY = 15

class OWDistanceMap(OWWidget):	
    settingsList = ["CellWidth", "CellHeight", "Merge", "Gamma", "CutLow", "CutHigh", "CutEnabled", "Sort",
                    "ShowLegend", "ShowAnnotations", "ShowBalloon", "ShowItemsInBalloon", "SendOnRelease", "ColorSchemas"]

    def __init__(self, parent=None, signalManager = None):
        self.callbackDeposit = [] # deposit for OWGUI callback function
        OWWidget.__init__(self, parent, signalManager, 'Distance Map') 

        self.inputs = [("Distance Matrix", orange.SymMatrix, self.setMatrix)]
        self.outputs = [("Examples", ExampleTable), ("Classified Examples", ExampleTableWithClass),("Attribute List", orange.VarList)]

        self.clicked = False
        self.offsetX = 5
        self.offsetY = 5
        self.imageWidth = 0
        self.imageHeight = 0
        self.distanceImage = None
        self.legendImage = None
        self.ColorSchemas = None

        self.shiftPressed = False        

        #set default settings
        self.CellWidth = 15; self.CellHeight = 15
        self.Merge = 1;
        self.savedMerge = self.Merge
        self.Gamma = 1
        self.Grid = 1
        self.CutLow = 0; self.CutHigh = 0; self.CutEnabled = 0
        self.Sort = 0
        self.SquareCells = 0
        self.ShowLegend = 1;
        self.ShowAnnotations = 1;
        self.ShowBalloon = 1;
        self.ShowItemsInBalloon = 1
        self.SendOnRelease = 1
        
        self.loadSettings()
        
        self.maxHSize = 30; self.maxVSize = 30
        self.sorting = [("None", self.sortNone), ("Adjacent distance", self.sortAdjDist), ("Random", self.sortRandom)]

        self.matrix = self.order = None
        
        # GUI definition
        self.tabs = QTabWidget(self.controlArea, 'tabWidget')

        # SETTINGS TAB
        tab = QVGroupBox(self)
        box = QVButtonGroup("Cell Size (Pixels)", tab)
        OWGUI.qwtHSlider(box, self, "CellWidth", label='Width: ', labelWidth=38, minValue=1, maxValue=self.maxHSize, step=1, precision=0, callback=self.drawDistanceMap)
        self.sliderVSize = OWGUI.qwtHSlider(box, self, "CellHeight", label='Height: ', labelWidth=38, minValue=1, maxValue=self.maxVSize, step=1, precision=0, callback=self.createDistanceMap)
        OWGUI.checkBox(box, self, "SquareCells", "Cells as squares", callback = self.drawDistanceMap)
        OWGUI.checkBox(box, self, "Grid", "Show grid", callback = self.createDistanceMap)
        
        OWGUI.qwtHSlider(tab, self, "Gamma", box="Gamma", minValue=0.1, maxValue=1, step=0.1, callback=self.drawDistanceMap)

        self.colorPalette = ColorPalette(tab, self, "", additionalColors =["Cell outline", "Selected cells"], callback = self.setColor)
        self.tabs.insertTab(tab, "Settings")

        # FILTER TAB
        tab = QVGroupBox(self)
        box = QVButtonGroup("Threshold Values", tab)
        OWGUI.checkBox(box, self, 'CutEnabled', "Enabled", callback=self.setCutEnabled)
        self.sliderCutLow = OWGUI.qwtHSlider(box, self, 'CutLow', label='Low:', labelWidth=33, minValue=-100, maxValue=0, step=0.1, precision=1, ticks=0, maxWidth=80, callback=self.drawDistanceMap)
        self.sliderCutHigh = OWGUI.qwtHSlider(box, self, 'CutHigh', label='High:', labelWidth=33, minValue=0, maxValue=100, step=0.1, precision=1, ticks=0, maxWidth=80, callback=self.drawDistanceMap)
        if not self.CutEnabled:
            self.sliderCutLow.box.setDisabled(1)
            self.sliderCutHigh.box.setDisabled(1)

        box = QVButtonGroup("Merge", tab)
        OWGUI.qwtHSlider(box, self, "Merge", label='Elements:', labelWidth=50, minValue=1, maxValue=100, step=1, callback=self.createDistanceMap, ticks=0)
        self.labelCombo = OWGUI.comboBox(tab, self, "Sort", box="Sort", items=[x[0] for x in self.sorting],
                                         tooltip="Choose method to sort items in distance matrix.", callback=self.sortItems)
        self.tabs.insertTab(tab, "Filter")

        # INFO TAB
        tab = QVGroupBox(self)
        box = QVButtonGroup("Annotation && Legends", tab)
        OWGUI.checkBox(box, self, 'ShowLegend', 'Show legend', callback=self.drawDistanceMap)
        OWGUI.checkBox(box, self, 'ShowAnnotations', 'Show annotations', callback=self.drawDistanceMap)
        
        box = QVButtonGroup("Balloon", tab)
        OWGUI.checkBox(box, self, 'ShowBalloon', "Show balloon", callback=None)
        OWGUI.checkBox(box, self, 'ShowItemsInBalloon', "Display item names", callback=None)

        box = QVButtonGroup("Select", tab)
        box2 = QHBox(box)
        self.box2 = box2
        self.buttonUndo = OWToolbars.createButton(box2, 'Undo', self.actionUndo, QPixmap(OWToolbars.dlg_undo), toggle = 0)
        self.buttonRemoveAllSelections = OWToolbars.createButton(box2, 'Remove all selections', self.actionRemoveAllSelections, QPixmap(OWToolbars.dlg_clear), toggle = 0)

        self.buttonSendSelections = OWToolbars.createButton(box2, 'Send selections', self.sendOutput, QPixmap(OWToolbars.dlg_send), toggle = 0)
        OWGUI.checkBox(box, self, 'SendOnRelease', "Send after mouse release", callback=None)

        self.tabs.insertTab(tab, "Info")
        
        self.resize(700,400)

        self.layout = QVBoxLayout(self.mainArea)
        self.canvas = QCanvas()
        self.canvasView = EventfulCanvasView(self.canvas, self.mainArea, self)

        self.layout.add(self.canvasView)
        

        #construct selector
        self.selector = QCanvasRectangle(0, 0, self.CellWidth, self.getCellHeight(), self.canvas)
        color = self.colorPalette.getCurrentColorSchema().getAdditionalColors()["Cell outline"]
        self.selector.setPen(QPen(self.qrgbToQColor(color),v_sel_width))
        self.selector.setZ(20)

        self.bubble = BubbleInfo(self.canvas)
        self.selection = SelectionManager()

        self.selectionLines = []
        self.annotationText = []

        self.legendText1 = QCanvasText(self.canvas)
        self.legendText1.move(0,0)
        self.legendText2 = QCanvasText(self.canvas)
        self.legendText2.move(v_legend_width,0)

        self.errorText = QCanvasText("Bitmap is too large.", self.canvas)
        self.errorText.move(10,10)

        #restore color schemas from settings
        if self.ColorSchemas:
            self.colorPalette.setColorSchemas(self.ColorSchemas)
        
    def createColorStripe(self, palette):
        dx = v_legend_width
        dy = v_legend_height
        bmp = chr(252)*dx*2 + reduce(lambda x,y:x+y, [chr(i*250/dx) for i in range(dx)] * (dy-4)) + chr(252)*dx*2

        image = ImageItem(bmp, self.canvas, dx, dy, palette, x=v_legend_offsetX, y=v_legend_offsetY, z=0)
        return image

    def colFromMousePos(self, x, y):
        if (x <= self.offsetX or x >= self.offsetX + self.imageWidth):
            return -1
        else:
            return int((x - self.offsetX)/self.CellWidth)

    def rowFromMousePos(self, x,y):
        if (y <= self.offsetY or y >= self.offsetY + self.imageHeight):
            return -1
        else:
            return int((y - self.offsetY)/self.getCellHeight())


    def qrgbToQColor(self, color):
        return QColor(qRed(color), qGreen(color), qBlue(color))

    def getItemFromPos(self, i):
        if (len(self.distanceMap.elementIndices)==0):
            j = i
        else:
            j = self.distanceMap.elementIndices[i]

        if self.distanceMapConstructor.order:
           j = self.distanceMapConstructor.order[j]

        return j

    def getCellHeight(self):
        if self.SquareCells:
            return self.CellWidth
        else:
            return self.CellHeight
        
    def sendOutput(self):
        if len(self.matrix.items)<1:
            return

        selectedIndices = []
        tmp = []

        if len(self.selection.getSelection())==0:
            self.send("Attribute List", None)
            self.send("Examples", None)
            self.send("Classified Examples", None)
        else:
            selection = self.selection.getSelection()
            for sel in selection:
                if (len(self.distanceMap.elementIndices)==0):
                    tmp += range(sel[0].x(), sel[1].x()+1)
                    tmp +=range(sel[0].y(), sel[1].y()+1)
                else:
                    tmp += range(self.distanceMap.elementIndices[sel[0].x()], self.distanceMap.elementIndices[sel[1].x()+1])
                    tmp +=range(self.distanceMap.elementIndices[sel[0].y()], self.distanceMap.elementIndices[sel[1].y()+1])

            for i in tmp:
                if self.distanceMapConstructor.order:
                    if not (self.distanceMapConstructor.order[i] in selectedIndices):
                        selectedIndices += [self.distanceMapConstructor.order[i]]

                if not (i in selectedIndices):
                    selectedIndices += [i]

            items = self.matrix.items
            if issubclass(orange.EnumVariable, type(items[0])):
                selected = orange.VarList()
                for i in selectedIndices:
                    selected.append(items[i])
                self.send("Attribute List", selected)

                
            if isinstance(items[0], orange.Example):
                ex = [items[x] for x in selectedIndices]
                selected = orange.ExampleTable(items[0].domain, ex)
                self.send("Examples", selected)
                if selected.domain.classVar:
                    self.send("Classified Examples", selected)
                
    # callbacks (rutines called after some GUI event, like click on a button)

    def setColor(self):
        color = self.colorPalette.getCurrentColorSchema().getAdditionalColors()["Cell outline"]
        self.selector.setPen(QPen(self.qrgbToQColor(color),v_sel_width))

        self.ColorSchemas = self.colorPalette.getColorSchemas()
        self.drawDistanceMap()

    def setCutEnabled(self):
        self.sliderCutLow.box.setDisabled(not self.CutEnabled)
        self.sliderCutHigh.box.setDisabled(not self.CutEnabled)
        self.drawDistanceMap()

    def constructDistanceMap(self):
        if self.matrix:
            self.distanceMapConstructor = orange.DistanceMapConstructor(distanceMatrix = self.matrix)
            self.createDistanceMap()

    def createDistanceMap(self):
        merge = min(self.Merge, float(self.matrix.dim))
        squeeze = 1. / merge

        self.distanceMapConstructor.order = self.order
        self.distanceMap, self.lowerBound, self.upperBound = self.distanceMapConstructor(squeeze)

        self.sliderCutLow.setRange(self.lowerBound, self.upperBound, 0.1)
        self.sliderCutHigh.setRange(self.lowerBound, self.upperBound, 0.1)
        self.CutLow = max(self.CutLow, self.lowerBound)
        self.CutHigh = min(self.CutHigh, self.upperBound)
        self.sliderCutLow.setValue(self.CutLow)
        self.sliderCutHigh.setValue(self.CutHigh)

        self.selection.clear()
        self.drawDistanceMap()

    def drawDistanceMap(self):
        if not self.matrix:
            return

        if self.matrix.dim * max(int(self.CellWidth), int(self.getCellHeight())) > 32767:
            self.errorText.show()
            return

        self.errorText.hide()
            
        lo = self.CutEnabled and self.CutLow   or self.lowerBound
        hi = round(self.CutEnabled and self.CutHigh  or self.upperBound, 1)

        self.offsetX = 5
        
        if self.distanceImage:
            self.distanceImage.setCanvas(None)

        if self.legendImage:
            self.legendImage.setCanvas(None)

        if self.ShowLegend==1:
            self.legendImage = self.createColorStripe(self.colorPalette.getCurrentColorSchema().getPalette())
            self.offsetY = v_legend_height + 30
            self.legendText1.setText(str(lo))
            self.legendText2.setText(str(hi))
            self.legendText1.show()
            self.legendText2.show()
        else:
            self.legendText1.hide()
            self.legendText2.hide()
            self.offsetY = 5

        palette = self.colorPalette.getCurrentColorSchema().getPalette()
        bitmap, width, height = self.distanceMap.getBitmap(int(self.CellWidth), int(self.getCellHeight()), lo, hi, self.Gamma, self.Grid)

        self.canvas.resize(2000, 2000) # this needs adjustment

        for tmpText in self.annotationText:
            tmpText.setCanvas(None)

        self.annotationText = []

        if self.ShowAnnotations==1 and self.Merge==1:
            items = self.matrix.items
            if len(self.distanceMap.elementIndices)==0:
                tmp = [i for i in range(0, len(items))]
            else:
                tmp = [self.distanceMap.elementIndices[i] for i in range(0, len(items))]                

            if self.distanceMapConstructor.order:
                indices = [self.distanceMapConstructor.order[i] for i in tmp]
            else:
                indices = tmp

            maxHeight = 0
            maxWidth = 0
            for i in range(0, len(indices)):
#                text = str(i)
                text = items[indices[i]]
                if type(text) not in [str, unicode]:
                    text = text.name
                if text<>"":
                    tmpText = QCustomCanvasText(text, self.canvas, -90.0)
                    tmpText.show()
                    if tmpText.height() > maxHeight:
                        maxHeight = tmpText.height()
                    self.annotationText += [tmpText]

                    tmpText = QCanvasText(text, self.canvas)
                    tmpText.show()
                    if tmpText.boundingRect().width() > maxWidth:
                        maxWidth = tmpText.boundingRect().width()
                    self.annotationText += [tmpText]

            for i in range(0, len(self.annotationText)/2):
                self.annotationText[i*2].setX(self.offsetX + maxWidth + 10 + i*self.CellWidth)
                self.annotationText[i*2].setY(self.offsetY)

⌨️ 快捷键说明

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