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

📄 ownomogramgraph.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 5 页
字号:
# Nomogram visualization widget. It is used together with OWNomogram

from OWWidget import *
#from Numeric import *
import Numeric
import math
from qtcanvas import *
import time, statc

# constants
SE_Z = -100
HISTOGRAM_Z = -200
aproxZero = 0.0001

def norm_factor(p):
    max = 10.
    min = -10.
    z = 0.
    eps = 0.001
    while ((max-min)>eps):
        pval = statc.zprob(z)
        if pval>p:
            max = z
        if pval<p:
            min = z
        z = (max + min)/2.
    return z

def unique(lst):
    d = {}
    for item in lst:
        d[item] = None
    return d.keys()

# returns difference between continuous label values
def getDiff(d):
    if d < 1 and d>0:
        mnum = d/pow(10, math.floor(math.log10(d)))
    else:
        mnum = d
        
    if d==0:
        return 0
    if str(mnum)[0]>'4':
        return math.pow(10,math.floor(math.log10(d))+1)
    elif str(mnum)[0]<'2':
        return 2*math.pow(10,math.floor(math.log10(d)))
    else:
        return 5*math.pow(10,math.floor(math.log10(d)))


# Detailed description of selected value in attribute:
#     - shows its value on the upper scale (points, log odds, ...)
#     - its real value (example: age = 45) or in case of discrete attribute:
#     - shows proportional value between two (real,possible) values of attribute
class Descriptor(QCanvasRectangle):
    def __init__(self, canvas, attribute, z=60):
        apply(QCanvasRectangle.__init__,(self, canvas))
        self.canvas = canvas
        self.attribute = attribute
        self.setPen(QPen(Qt.black, 2))
        self.setBrush(QBrush(QColor(135,206,250)))
        
        self.splitLine = QCanvasLine(canvas)
        self.header = QCanvasText(canvas)
        self.header.setTextFlags(Qt.AlignLeft+Qt.AlignTop)
        self.headerValue = QCanvasText(canvas)
        self.headerValue.setTextFlags(Qt.AlignRight + Qt.AlignTop)
        self.valName = QCanvasText(canvas)
        self.valName.setTextFlags(Qt.AlignLeft+Qt.AlignTop)
        self.value = QCanvasText(canvas)
        self.value.setTextFlags(Qt.AlignRight + Qt.AlignTop)
        self.supportingValName = QCanvasText(canvas)
        self.supportingValName.setTextFlags(Qt.AlignLeft+Qt.AlignTop)
        self.supportingValue = QCanvasText(canvas)
        self.supportingValue.setTextFlags(Qt.AlignRight + Qt.AlignTop)
        self.setZAll(z)
       

    def drawAll(self, x, y):
        def getNearestAtt(selectedBeta):
            if isinstance(self.attribute, AttrLineCont):
                for i in range(len(self.attribute.attValues)):
                    if self.attribute.attValues[i].betaValue==selectedBeta:
                        nearestRight = self.attribute.attValues[i]
                        nearestLeft = self.attribute.attValues[i]
                        break
                    elif i>0 and self.attribute.attValues[i].betaValue>selectedBeta and selectedBeta>self.attribute.attValues[i-1].betaValue:
                        nearestRight = self.attribute.attValues[i]
                        nearestLeft = self.attribute.attValues[i-1]
                        break
                    elif i>0 and self.attribute.attValues[i].betaValue<selectedBeta and selectedBeta<self.attribute.attValues[i-1].betaValue:
                        nearestRight = self.attribute.attValues[i-1]
                        nearestLeft = self.attribute.attValues[i]
                        break
                    elif i == len(self.attribute.attValues)-1:
                        nearestRight = self.attribute.attValues[i]
                        nearestLeft = self.attribute.attValues[i-1]
                        break
                        
            else:
                nearestLeft = filter(lambda x: x.betaValue == max([at.betaValue for at in filter(lambda x: x.betaValue <= selectedBeta, self.attribute.attValues)]) ,self.attribute.attValues)[0]
                nearestRight = filter(lambda x: x.betaValue == min([at.betaValue for at in filter(lambda x: x.betaValue >= selectedBeta, self.attribute.attValues)]) ,self.attribute.attValues)[0]
            return (nearestLeft, nearestRight)
        
        # I need mapper to calculate various quantities (said in chemistry way) from the attribute and its selected value
        # happens at the time of drawing header and footer canvases
        # x and y should be on canvas!
        
        if ((not isinstance(self.canvas, BasicNomogram) or not self.canvas.onCanvas(x,y)) and
            (not isinstance(self.canvas, BasicNomogramFooter) or not self.canvas.onCanvas(x,y))):
            return True

        if isinstance(self.canvas, BasicNomogramFooter) and self.canvas.onCanvas(x,y):
            self.header.setText(self.attribute.name)
            self.headerValue.setText("")
            self.valName.setText("Value:")
            if self.attribute.selectedValue:
                self.value.setText(str(round(self.attribute.selectedValue[2],2)))
            else:
                self.value.setText("None")
            self.supportingValName.setText("")
            self.supportingValue.setText("")
            points = 1
        else:
            # get points
            selectedBeta = self.attribute.selectedValue[2]
            proportionalBeta = self.canvas.mapper.propBeta(selectedBeta, self.attribute)
            maxValue = self.canvas.mapper.getMaxMapperValue()
            minValue = self.canvas.mapper.getMinMapperValue()
            points = minValue+(maxValue-minValue)*proportionalBeta

            self.header.setText(self.canvas.parent.pointsName[self.canvas.parent.yAxis]+":")
            self.headerValue.setText(str(round(points,2)))
            

            # continuous? --> get attribute value
            if isinstance(self.attribute, AttrLineCont):
                self.valName.setText("Value:")
                if len(self.attribute.selectedValue)==4:
                    self.value.setText(str(round(self.attribute.selectedValue[3],2)))
                else:
                    (nleft, nright) = getNearestAtt(selectedBeta)
                    if nright.betaValue>nleft.betaValue:
                        prop = (selectedBeta-nleft.betaValue)/(nright.betaValue-nleft.betaValue)
                    else:
                        prop = 0
                    if prop == 0:
                        avgValue = (float(nleft.name)+float(nright.name))/2.
                    else:
                        avgValue = float(nleft.name)+prop*(float(nright.name)-float(nleft.name))
                    self.value.setText(str(round(avgValue,2)))
                self.supportingValName.setText("")
                self.supportingValue.setText("")            
            # discrete? --> get left and right value, proportional select values
            else:
                (nleft, nright) = getNearestAtt(selectedBeta)
                if nright.betaValue>nleft.betaValue:
                    prop = (selectedBeta-nleft.betaValue)/(nright.betaValue-nleft.betaValue)
                else:
                    prop = 0
                if prop == 0 or prop == 1:
                    self.valName.setText("Value:")
                    self.supportingValName.setText("")
                    self.supportingValue.setText("")            
                    if prop == 0:
                        self.value.setText(nleft.name)
                    else:
                        self.value.setText(nright.name)
                else:
                    self.valName.setText(nleft.name + ":")
                    self.supportingValName.setText(nright.name + ":")
                    self.value.setText(str(round(1-prop,4)*100)+"%")
                    self.supportingValue.setText(str(round(prop,4)*100)+"%")

        # set height
        height = 15+ self.valName.boundingRect().height() + self.header.boundingRect().height()
        if self.supportingValName.text() != "":
            height+= self.supportingValName.boundingRect().height()

        # set width
        width = 20+max([self.header.boundingRect().width()+2+self.headerValue.boundingRect().width(),
                  self.valName.boundingRect().width()+2+self.value.boundingRect().width(), 
                  self.supportingValName.boundingRect().width()+2+self.supportingValue.boundingRect().width()])

        # if bubble wants to jump of the canvas, better catch it !
        selOffset = 20
        xTemp, yTemp = x+selOffset, y-selOffset-height
        while not self.canvas.onCanvas(xTemp,yTemp) or not self.canvas.onCanvas(xTemp,yTemp+height) or not self.canvas.onCanvas(xTemp+width,yTemp) or not self.canvas.onCanvas(xTemp+width,yTemp+height):
            if yTemp == y-selOffset-height and not xTemp <= x-selOffset-width:
                xTemp-=1
            elif xTemp <= x-selOffset-width and not yTemp >= y+selOffset:
                yTemp+=1
            elif yTemp >= y+selOffset and not xTemp >= x+selOffset:
                xTemp+=1
            elif xTemp>= x+selOffset and not yTemp<y-selOffset-height+2:
                yTemp-=1
            else:
                break

        x,y = xTemp, yTemp
        
        # set coordinates
        self.setX(x)
        self.setY(y)
        self.setSize(width+2, height+2)
        
        # header
        self.header.setX(x+2)
        self.header.setY(y+2)
        self.headerValue.setX(x+width-4)
        self.headerValue.setY(y+2)

        #line
        self.splitLine.setPoints(x, y+4+self.header.boundingRect().height(), x+width, y+4+self.header.boundingRect().height())

        # values        
        self.valName.setX(x+3)
        self.valName.setY(y+7+self.header.boundingRect().height())
        self.value.setX(x+width-4)
        self.value.setY(y+7+self.header.boundingRect().height())
        self.supportingValName.setX(x+3)
        self.supportingValName.setY(y+10+self.header.boundingRect().height()+self.valName.boundingRect().height())
        self.supportingValue.setX(x+width-4)
        self.supportingValue.setY(y+10+self.header.boundingRect().height()+self.valName.boundingRect().height())

        #return false if position is at zero and alignment is centered
        if round(points,3) == 0.0 and self.canvas.parent.alignType == 1:
            return False
        return True
        
                

    def setZAll(self, z):
        self.setZ(z)
        self.header.setZ(z+1)
        self.splitLine.setZ(z+1)
        self.headerValue.setZ(z+1)
        self.valName.setZ(z+1)
        self.value.setZ(z+1)
        self.supportingValName.setZ(z+1)
        self.supportingValue.setZ(z+1)
        
    def showAll(self):
        self.show()
        self.splitLine.show()
        self.header.show()
        self.headerValue.show()
        self.valName.show()
        self.value.show()
        if self.supportingValName.text != "":
            self.supportingValName.show()
            self.supportingValue.show()
        
    def hideAll(self):
        self.hide()
        self.header.hide()
        self.splitLine.hide()
        self.headerValue.hide()
        self.valName.hide()
        self.value.hide()
        self.supportingValName.hide()
        self.supportingValue.hide()


# Attribute value selector -- a small circle
class AttValueMarker(QCanvasEllipse):
    def __init__(self, attribute, canvas, z=50):
        apply(QCanvasEllipse.__init__,(self,10,10,canvas))
        self.attribute = attribute
        #self.canvas = canvas
        self.setZ(z)
        self.setBrush(QBrush(Qt.blue))
        self.name=""
        #self.borderCircle = QCanvasEllipse(15,15,canvas)
        #self.borderCircle.setBrush(QBrush(Qt.red))
        #self.borderCircle.setZ(z-1)
        self.descriptor = Descriptor(canvas, attribute, z+1)

    def setPos(self, x, y):
        self.setX(x)
        self.setY(y)
        #self.borderCircle.setX(x)
        #self.borderCircle.setY(y)
        if not self.descriptor.drawAll(x,y):
            brush = QBrush(self.brush().color(), Qt.Dense4Pattern)

⌨️ 快捷键说明

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