📄 owclassificationtreegraph.py
字号:
"""
<name>Classification Tree Graph</name>
<description>Classification tree viewer (graph view).</description>
<icon>icons/ClassificationTreeGraph.png</icon>
<contact>Blaz Zupan (blaz.zupan(@at@)fri.uni-lj.si)</contact>
<priority>2110</priority>
"""
from OWTreeViewer2D import *
import OWGraphTools
class ClassificationNode(CanvasNode):
def __init__(self,attrVal,*args):
CanvasNode.__init__(self,*args)
self.dist=self.tree.distribution
self.attrVal=attrVal
maxInst=max(self.dist)
#self.majClass=ind=list(self.dist).index(maxProb)
self.majClass = filter(lambda i, m=maxInst: self.dist[i]==m, range(len(self.dist)))
ind=self.majClass[0]
self.majClassName=self.dist.items()[ind][0]
self.majClassProb=maxInst/self.dist.cases
self.tarClassProb=self.dist.items()[0][1]/self.dist.cases
self.numInst=self.dist.cases
self.title=QCanvasText(attrVal,self.canvas())
self.texts=[self.majClassName, "%.3f" % self.majClassProb, "%.3f" % self.tarClassProb, "%.1f" % self.numInst]
self.name = (self.tree.branches and self.tree.branchSelector.classVar.name) or self.majClassName
self.textAdvance=12
self.addTextLine(attrVal, fitSquare=False)
self.addTextLine("", fitSquare=False)
self.addTextLine("", fitSquare=False)
self.addTextLine(fitSquare=False)
self.addTextLine(self.name, fitSquare=False)
self.rule=(isinstance(self.parent, QCanvasRectangle) and self.parent.rule+[(self.parent.tree.branchSelector.classVar, attrVal)]) or []
#print self.rule
#self.textObj.extend([self.title, self.name]+self.textList)
self.textInd=[]
self.pieObj=[]
distSum=sum(self.dist)
color=OWGraphTools.ColorPaletteHSV(len(self.dist))
startAngle=0
for i in range(len(self.dist)):
angle=360/distSum*self.dist[i]*16
e=QCanvasEllipse(self.height()*0.8,self.height()*0.8,startAngle,angle,self.canvas())
e.setBrush(QBrush(color[i]))
e.move(self.height()/2,self.width())
e.setZ(0)
startAngle+=angle
self.pieObj.append(e)
e=QCanvasEllipse(self.height()*0.8+4,self.height()*0.8+4,0,360*16,self.canvas())
e.setBrush(QBrush(Qt.black))
e.move(self.height(), self.width())
e.setZ(-1)
self.pieObj.append(e)
self.canvasObj.extend(self.pieObj)
self.isPieShown=True
def setSize(self,w,h):
CanvasNode.setSize(self,w,h)
self.updateText()
for e in self.pieObj:
e.setSize(h*0.8,h*0.8)
e.move(self.x()+self.width(),self.y()+self.height()/2)
self.pieObj[-1].setSize(h*0.8+2,h*0.8+2)
def setBrush(self, brush):
CanvasTextContainer.setBrush(self, brush)
if self.textObj:
self.textObj[0].setColor(Qt.black)
def show(self):
CanvasNode.show(self)
if not self.isPieShown:
for e in self.pieObj:
e.hide()
def setPieVisible(self, b=True):
self.isPieShown=b
if self.isShown and b:
for e in self.pieObj:
e.show()
else:
for e in self.pieObj:
e.hide()
def setText(self, textInd=[]):
self.textInd=textInd
j=1
for i in textInd:
CanvasNode.setText(self, j, self.texts[i], fitSquare=False)
j+=1
for i in range(len(textInd),2):
CanvasNode.setText(self, i+1, "", fitSquare=False)
def updateText(self):
self.textAdvance=float(self.height())/3
self.lineSpacing=0
self.setFont(QFont("",self.textAdvance*0.7), False)
self.reArangeText(False, -self.textAdvance-self.lineSpacing)
def reArangeText(self, fitSquare=True, startOffset=0):
self.textOffset=startOffset
x,y=self.x(),self.y()
for i in range(4):
self.textObj[i].move(x+1, y+(i-1)*self.textAdvance)
self.spliterObj[0].move(x, y+self.height()-self.textAdvance)
import re
import sets
def parseRules(rules):
def joinCont(rule1, rule2):
int1, int2=["(",-1e1000,1e1000,")"], ["(",-1e1000,1e1000,")"]
rule=[rule1, rule2]
interval=[int1, int2]
for i in [0,1]:
if rule[i][1].startswith("in"):
r=rule[i][1][2:]
interval[i]=[r.strip(" ")[0]]+map(lambda a: float(a), r.strip("()[] ").split(","))+[r.strip(" ")[-1]]
else:
if "<" in rule[i][1]:
interval[i][3]=("=" in rule[i][1] and "]") or ")"
interval[i][2]=float(rule[i][1].strip("<>= "))
else:
interval[i][0]=("=" in rule[i][1] and "[") or "("
interval[i][1]=float(rule[i][1].strip("<>= "))
inter=[None]*4
if interval[0][1]<interval[1][1] or (interval[0][1]==interval[1][1] and interval[0][0]=="["):
interval.reverse()
inter[:2]=interval[0][:2]
if interval[0][2]>interval[1][2] or (interval[0][2]==interval[1][2] and interval[0][3]=="]"):
interval.reverse()
inter[2:]=interval[0][2:]
if 1e1000 in inter or -1e1000 in inter:
rule=((-1e1000==inter[1] and "<") or ">")
rule+=(("[" in inter or "]" in inter) and "=") or ""
rule+=(-1e1000==inter[1] and str(inter[2])) or str(inter[1])
else:
rule="in "+inter[0]+str(inter[1])+","+str(inter[2])+inter[3]
return (rule1[0], rule)
def joinDisc(rule1, rule2):
r1,r2=rule1[1],rule2[1]
r1=re.sub("^in ","",r1)
r2=re.sub("^in ","",r2)
r1=r1.strip("[]=")
r2=r2.strip("[]=")
s1=sets.Set([s.strip(" ") for s in r1.split(",")])
s2=sets.Set([s.strip(" ") for s in r2.split(",")])
s=s1 & s2
if len(s)==1:
return (rule1[0], "= "+str(list(s)[0]))
else:
return (rule1[0], "in ["+",".join([str(st) for st in s])+"]")
rules.sort(lambda a,b: (a[0].name<b[0].name and -1) or 1 )
newRules=[rules[0]]
for r in rules[1:]:
if r[0].name==newRules[-1][0].name:
if re.search("(a-zA-Z\"')+",r[1].lstrip("in")):
newRules[-1]=joinDisc(r,newRules[-1])
else:
newRules[-1]=joinCont(r,newRules[-1])
else:
newRules.append(r)
return newRules
BodyColor_Default = QColor(255, 225, 10)
BodyCasesColor_Default = QColor(0, 0, 128)
class OWClassificationTreeGraph(OWTreeViewer2D):
def __init__(self, parent=None, signalManager = None, name='ClassificationTreeViewer2D'):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -