📄 owinteractiongraph.py
字号:
for item in list1:
if item in list2: return 0
for item in list2:
if item in list1: return 0
#return 1
if self.getAttrVisible(attrName1) == 0 or self.getAttrVisible(attrName2) == 0: return 0
if self.onlyImportantInteractions == 1:
for (attr1, attr2, rect) in self.lines:
if (attr1 == attrName1 and attr2 == attrName2) or (attr1 == attrName2 and attr2 == attrName1): return 1
return 0
return 1
#########################################
# show interactions between attributes in left canvas
def showInteractionRects(self, data):
if self.interactionMatrix == None: return
if self.data == None : return
################################
# hide all interaction rectangles
for (rect1, rect2, rect3, nbrect, text1, text2, tooltipRect, tooltipText) in self.interactionRects:
rect1.hide()
rect2.hide()
rect3.hide()
nbrect.hide()
text1.hide()
text2.hide()
QToolTip.remove(self.canvasViewL, tooltipRect)
self.interactionRects = []
for item in self.rectItems:
item.hide()
self.rectItems = []
################################
# get max width of the attribute text
xOff = 0
for ((total, (gain1, gain2, attrIndex1, attrIndex2))) in self.interactionList:
if not self.showInteractionPair(attrIndex1, attrIndex2): continue
if gain1 > gain2: text = QCanvasText(data.domain[attrIndex1].name, self.canvasL)
else: text = QCanvasText(data.domain[attrIndex2].name, self.canvasL)
rect = text.boundingRect()
if xOff < rect.width():
xOff = rect.width()
xOff += 10; yOff = 40
index = 0
xscale = 300; yscale = 200
maxWidth = xOff + xscale + 10; maxHeight = 0
rectHeight = yscale * 0.1 # height of the rectangle will be 1/10 of max width
################################
# print scale
line = QCanvasRectangle(xOff, yOff - 4, xscale, 1, self.canvasL)
line.show()
tick1 = QCanvasRectangle(xOff, yOff-10, 1, 6, self.canvasL); tick1.show()
tick2 = QCanvasRectangle(xOff + (xscale/2), yOff-10, 1, 6, self.canvasL); tick2.show()
tick3 = QCanvasRectangle(xOff + xscale-1, yOff-10, 1, 6, self.canvasL); tick3.show()
self.rectItems = [line, tick1, tick2, tick3]
for i in range(10):
tick = QCanvasRectangle(xOff + xscale * (float(i)/10.0), yOff-8, 1, 5, self.canvasL);
tick.show()
self.rectItems.append(tick)
text1 = QCanvasText("0%", self.canvasL); text1.setTextFlags(Qt.AlignHCenter); text1.move(xOff, yOff - 23); text1.show()
text2 = QCanvasText("50%", self.canvasL); text2.setTextFlags(Qt.AlignHCenter); text2.move(xOff + xscale/2, yOff - 23); text2.show()
text3 = QCanvasText("100%", self.canvasL); text3.setTextFlags(Qt.AlignHCenter); text3.move(xOff + xscale, yOff - 23); text3.show()
text4 = QCanvasText("Class entropy removed", self.canvasL); text4.setTextFlags(Qt.AlignHCenter); text4.move(xOff + xscale/2, yOff - 36); text4.show()
self.rectItems.append(text1); self.rectItems.append(text2); self.rectItems.append(text3); self.rectItems.append(text4)
################################
#create rectangles
for ((total, (gain1, gain2, attrIndex1, attrIndex2))) in self.interactionList:
if not self.showInteractionPair(attrIndex1, attrIndex2): continue
interaction = (total - gain1 - gain2)
atts = (max(attrIndex1, attrIndex2), min(attrIndex1, attrIndex2))
#nbgain = self.interactionMatrix.ig[atts[0]][atts[1]] + self.interactionMatrix.gains[atts[0]] + self.interactionMatrix.gains[atts[1]]
nbgain = self.interactionMatrix.gains[atts[0]] + self.interactionMatrix.gains[atts[1]]
nbgain -= self.interactionMatrix.corr[(atts[1],atts[0])]
rectsYOff = yOff + 3 + index * yscale * 0.15
# swap if gain1 < gain2
if gain1 < gain2:
ind = attrIndex1; attrIndex1 = attrIndex2; attrIndex2 = ind
ga = gain1; gain1 = gain2; gain2 = ga
x1 = round(xOff)
if interaction < 0:
x2 = floor(xOff + xscale*(gain1+interaction))
x3 = ceil(xOff + xscale*gain1)
else:
x2 = floor(xOff + xscale*gain1)
x3 = ceil(xOff + xscale*(total-gain2))
x4 = ceil(xOff + xscale*total)
# compute nbgain position
nb_x1 = min(xOff, floor(xOff + 0.5*xscale*nbgain))
nb_x2 = max(xOff, floor(xOff + 0.5*xscale*nbgain))
nbrect = QCanvasRectangle(nb_x1, rectsYOff-3, nb_x2-nb_x1+1, 2, self.canvasL)
rect2 = QCanvasRectangle(x2, rectsYOff, x3-x2+1, rectHeight, self.canvasL)
rect1 = QCanvasRectangle(x1, rectsYOff, x2-x1+1, rectHeight, self.canvasL)
rect3 = QCanvasRectangle(x3, rectsYOff, x4-x3, rectHeight, self.canvasL)
if interaction < 0.0:
#color = QColor(255, 128, 128)
color = QColor(200, 0, 0)
style = Qt.DiagCrossPattern
else:
color = QColor(Qt.green)
style = Qt.Dense5Pattern
brush1 = QBrush(Qt.blue); brush1.setStyle(Qt.BDiagPattern)
brush2 = QBrush(color); brush2.setStyle(style)
brush3 = QBrush(Qt.blue); brush3.setStyle(Qt.FDiagPattern)
rect1.setBrush(brush1); rect1.setPen(QPen(QColor(Qt.blue)))
rect2.setBrush(brush2); rect2.setPen(QPen(color))
rect3.setBrush(brush3); rect3.setPen(QPen(QColor(Qt.blue)))
rect1.show(); rect2.show(); rect3.show(); nbrect.show()
# create text labels
text1 = QCanvasText(data.domain[attrIndex1].name, self.canvasL)
text2 = QCanvasText(data.domain[attrIndex2].name, self.canvasL)
text1.setTextFlags(Qt.AlignRight)
text2.setTextFlags(Qt.AlignLeft)
text1.move(xOff - 5, rectsYOff + 3)
text2.move(xOff + xscale*total + 5, rectsYOff + 3)
text1.show()
text2.show()
tooltipRect = QRect(x1-self.viewXPos, rectsYOff-self.viewYPos, x4-x1, rectHeight)
tooltipText = "%s : <b>%.1f%%</b><br>%s : <b>%.1f%%</b><br>Interaction : <b>%.1f%%</b><br>Total entropy removed: <b>%.1f%%</b>" %(data.domain[attrIndex1].name, gain1*100, data.domain[attrIndex2].name, gain2*100, interaction*100, total*100)
QToolTip.add(self.canvasViewL, tooltipRect, tooltipText)
# compute line width
rect = text2.boundingRect()
lineWidth = xOff + xscale*total + 5 + rect.width() + 10
if lineWidth > maxWidth:
maxWidth = lineWidth
if rectsYOff + rectHeight + 10 > maxHeight:
maxHeight = rectsYOff + rectHeight + 10
self.interactionRects.append((rect1, rect2, rect3, nbrect, text1, text2, QRect(x1, rectsYOff, x4-x1, rectHeight), tooltipText))
index += 1
# resizing of the left canvas to update width
self.canvasViewL.setMaximumSize(QSize(maxWidth + 30, max(2000, maxHeight)))
self.canvasViewL.setMinimumWidth(maxWidth + 10)
self.canvasL.resize(maxWidth + 10, maxHeight)
self.canvasViewL.setMinimumWidth(0)
self.canvasL.update()
#########################################
# if we scrolled in the left canvas then we have to update tooltip positions
def contentsMoving(self, x,y):
for (rect1, rect2, rect3, nbrect, text1, text2, rect, tooltipText) in self.interactionRects:
oldrect = QRect(rect.left()-self.viewXPos, rect.top()-self.viewYPos, rect.width(), rect.height())
QToolTip.remove(self.canvasViewL, oldrect)
newrect = QRect(rect.left()-x, rect.top()-y, rect.width(), rect.height())
QToolTip.add(self.canvasViewL, newrect, tooltipText)
self.viewXPos = x
self.viewYPos = y
#########################################
# parse info from plain file. picWidth and picHeight are sizes in pixels
def parseGraphData(self, data, textPlainList, picWidth, picHeight):
scale = 0
w = 1; h = 1
for line in textPlainList:
if line[:9] == "rectangle":
list = line.split()
topLeftRectStr = list[1]
bottomRightRectStr = list[2]
attrIndex = list[3]
isAttribute = 0 # does rectangle represent attribute
if attrIndex.find("-") < 0:
isAttribute = 1
topLeftRectStr = topLeftRectStr.replace("(","")
bottomRightRectStr = bottomRightRectStr.replace("(","")
topLeftRectStr = topLeftRectStr.replace(")","")
bottomRightRectStr = bottomRightRectStr.replace(")","")
topLeftRectList = topLeftRectStr.split(",")
bottomRightRectList = bottomRightRectStr.split(",")
xLeft = int(topLeftRectList[0])
yTop = int(topLeftRectList[1])
width = int(bottomRightRectList[0]) - xLeft
height = int(bottomRightRectList[1]) - yTop
rect = QCanvasRectangle(xLeft+2, yTop+2, width, height, self.canvasR)
pen = QPen(Qt.blue)
pen.setWidth(4)
rect.setPen(pen)
rect.hide()
if isAttribute == 1:
name = data.domain[int(attrIndex)].name
self.rectIndices[int(attrIndex)] = rect
self.rectNames[name] = rect
else:
attrs = attrIndex.split("-")
attr1 = data.domain[int(attrs[0])].name
attr2 = data.domain[int(attrs[1])].name
pen.setStyle(Qt.NoPen)
rect.setPen(pen)
self.lines.append((attr1, attr2, rect))
##################################################
# initialize lists for shown and hidden attributes
def initLists(self, data):
self.shownAttribsLB.clear()
self.hiddenAttribsLB.clear()
if data == None: return
for key in self.rectNames.keys():
self._setAttrVisible(key, 1)
#################################################
### showing and hiding attributes
#################################################
def _showAttribute(self, name):
self.shownAttribsLB.insertItem(name) # add to shown
count = self.hiddenAttribsLB.count()
for i in range(count-1, -1, -1): # remove from hidden
if str(self.hiddenAttribsLB.text(i)) == name:
self.hiddenAttribsLB.removeItem(i)
def _hideAttribute(self, name):
self.hiddenAttribsLB.insertItem(name) # add to hidden
count = self.shownAttribsLB.count()
for i in range(count-1, -1, -1): # remove from shown
if str(self.shownAttribsLB.text(i)) == name:
self.shownAttribsLB.removeItem(i)
##########
# add attribute to showList or hideList and show or hide its rectangle
def _setAttrVisible(self, name, visible = 1):
if visible == 1:
if name in self.rectNames.keys(): self.rectNames[name].show();
self._showAttribute(name)
else:
if name in self.rectNames.keys(): self.rectNames[name].hide();
self._hideAttribute(name)
def getAttrVisible(self, name):
for i in range(self.hiddenAttribsLB.count()):
if str(self.hiddenAttribsLB.text(i)) == name: return 0
if self.mergeAttributes == 1:
names = name.split("-")
for i in range(self.hiddenAttribsLB.count()):
if str(self.hiddenAttribsLB.text(i)) in names: return 0
return 1
#################################################
# event processing
#################################################
def addAttributeClick(self):
count = self.hiddenAttribsLB.count()
for i in range(count-1, -1, -1):
if self.hiddenAttribsLB.isSelected(i):
name = str(self.hiddenAttribsLB.text(i))
self._setAttrVisible(name, 1)
self.showInteractionRects(self.data)
self.canvasL.update()
self.canvasR.update()
def removeAttributeClick(self):
count = self.shownAttribsLB.count()
for i in range(count-1, -1, -1):
if self.shownAttribsLB.isSelected(i):
name = str(self.shownAttribsLB.text(i))
self._setAttrVisible(name, 0)
self.showInteractionRects(self.data)
self.canvasL.update()
self.canvasR.update()
##################################################
# SAVING GRAPHS
##################################################
def saveToFileLCanvas(self):
self.saveCanvasToFile(self.canvasViewL, self.canvasL.size())
def saveToFileRCanvas(self):
self.saveCanvasToFile(self.canvasViewR, self.canvasR.size())
def saveCanvasToFile(self, canvas, size):
qfileName = QFileDialog.getSaveFileName("graph.png","Portable Network Graphics (.PNG)\nWindows Bitmap (.BMP)\nGraphics Interchange Format (.GIF)", None, "Save to..")
fileName = str(qfileName)
if fileName == "": return
(fil,ext) = os.path.splitext(fileName)
ext = ext.replace(".","")
ext = ext.upper()
buffer = QPixmap(size) # any size can do, now using the window size
painter = QPainter(buffer)
painter.fillRect(buffer.rect(), QBrush(QColor(255, 255, 255))) # make background same color as the widget's background
canvas.drawContents(painter, 0,0, size.width(), size.height())
painter.end()
buffer.save(fileName, ext)
#test widget appearance
if __name__=="__main__":
a=QApplication(sys.argv)
ow=OWInteractionGraph()
a.setMainWidget(ow)
ow.show()
a.exec_loop()
#save settings
ow.saveSettings()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -