📄 owparallelgraph.py
字号:
#
# OWParallelGraph.py
#
from OWGraph import *
from OWDistributions import *
from orngScaleData import *
from statc import pearsonr
from MLab import mean, std
NO_STATISTICS = 0
MEANS = 1
MEDIAN = 2
class OWParallelGraph(OWGraph, orngScaleData):
def __init__(self, parallelDlg, parent = None, name = None):
OWGraph.__init__(self, parent, name)
orngScaleData.__init__(self)
self.parallelDlg = parallelDlg
self.showDistributions = 0
self.hidePureExamples = 1
self.toolInfo = []
self.toolRects = []
self.useSplines = 0
self.showStatistics = 0
self.lastSelectedKey = 0
self.enabledLegend = 0
self.curvePoints = [] # save curve points in form [(y1, y2, ..., yi), (y1, y2, ... yi), ...] - used for sending selected and unselected points
self.lineTracking = 0
self.nonDataKeys = []
def setData(self, data):
OWGraph.setData(self, data)
orngScaleData.setData(self, data)
# update shown data. Set attributes, coloring by className ....
def updateData(self, attributes, targetValue, midLabels = None, startIndex = 0, stopIndex = 0):
self.removeDrawingCurves() # my function, that doesn't delete selection curves
self.removeTooltips()
self.removeMarkers()
self.curvePoints = []
self.nonDataKeys = []
blackColor = QColor(0, 0, 0)
if self.scaledData == None: return
if len(attributes) == 0: return
if (self.showDistributions == 1 or self.showAttrValues == 1) and self.rawdata.domain[attributes[-1]].varType == orange.VarTypes.Discrete:
#self.setAxisScale(QwtPlot.xBottom, 0, len(attributes)-0.5, 1)
#self.setAxisScale(QwtPlot.xBottom, 0, len(attributes)-1, 1) # changed because of qwtplot's bug. only every second attribute label was shown if -0.5 was used
self.setAxisScale(QwtPlot.xBottom, startIndex, stopIndex-1, 1) # changed because of qwtplot's bug. only every second attribute label was shown if -0.5 was used
else:
#self.setAxisScale(QwtPlot.xBottom, 0, len(attributes)-1.0, 1)
self.setAxisScale(QwtPlot.xBottom, startIndex, stopIndex-1, 1)
if self.showAttrValues: self.setAxisScale(QwtPlot.yLeft, -0.04, 1.04, 1)
elif midLabels: self.setAxisScale(QwtPlot.yLeft, 0, 1.04, 1)
else: self.setAxisScale(QwtPlot.yLeft, 0, 1, 1)
## if (self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Continuous and self.enabledLegend) or (len(attributes) and self.rawdata.domain[attributes[-1]].varType == orange.VarTypes.Discrete and (self.showDistributionValues or self.showAttrValues)):
## self.addCurve("edge", self.canvasBackground(), self.canvasBackground(), 1, QwtCurve.Lines, QwtSymbol.None, xData = [len(attributes),len(attributes)], yData = [1,1])
self.setAxisScaleDraw(QwtPlot.xBottom, DiscreteAxisScaleDraw([self.getAttributeLabel(attr) for attr in attributes]))
self.setAxisScaleDraw(QwtPlot.yLeft, HiddenScaleDraw())
self.axisScaleDraw(QwtPlot.xBottom).setTickLength(0, 0, 0) # hide ticks
self.axisScaleDraw(QwtPlot.xBottom).setOptions(0) # hide horizontal line representing x axis
self.axisScaleDraw(QwtPlot.yLeft).setTickLength(0, 0, 0)
self.axisScaleDraw(QwtPlot.yLeft).setOptions(0)
self.setAxisMaxMajor(QwtPlot.xBottom, len(attributes))
self.setAxisMaxMinor(QwtPlot.xBottom, 0)
classNameIndex = -1
continuousClass = 0
if self.rawdata.domain.classVar:
classNameIndex = self.attributeNameIndex[self.rawdata.domain.classVar.name]
continuousClass = self.rawdata.domain.classVar.varType == orange.VarTypes.Continuous
haveSubsetData = 0
if self.subsetData and self.rawdata and self.subsetData.domain == self.rawdata.domain:
haveSubsetData = 1
length = len(attributes)
indices = [self.attributeNameIndex[label] for label in attributes]
xs = range(length)
dataSize = len(self.scaledData[0])
if self.rawdata.domain.classVar and not continuousClass:
classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name)
# ############################################
# if self.hidePureExamples == 1 we have to calculate where to stop drawing lines
# we do this by adding a integer meta attribute, that for each example stores attribute index, where we stop drawing lines
# ############################################
lastIndex = indices[-1]
dataStop = None
if self.hidePureExamples == 1 and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete:
# add a meta attribute if it doesn't exist yet
dataStop = dataSize * [lastIndex] # array where we store index value for each data value where to stop drawing
metaid = orange.newmetaid()
self.rawdata.domain.addmeta(metaid, orange.IntVariable("ItemIndex"))
for i in range(dataSize): self.rawdata[i].setmeta(metaid, i)
for i in range(length):
if self.rawdata.domain[indices[i]].varType != orange.VarTypes.Discrete or attributes[i] == self.rawdata.domain.classVar.name: continue
attr = self.rawdata.domain[indices[i]]
for attrVal in attr.values:
tempData = self.rawdata.select({attr.name:attrVal})
ind = 0
while ind < len(tempData):
if dataStop[int(tempData[ind].getmeta(metaid))] == lastIndex:
val = tempData[ind][classNameIndex]
break
ind += 1
# do all instances belong to the same class?
while ind < len(tempData):
if dataStop[int(tempData[ind].getmeta(metaid))] != lastIndex: ind += 1; continue
if val != tempData[ind][classNameIndex]: break
ind += 1
# if all examples belong to one class we repair the meta variable values
if ind >= len(tempData):
for item in tempData:
index = int(item.getmeta(metaid))
if dataStop[index] == lastIndex:
dataStop[index] = indices[i]
self.rawdata.domain.removemeta(metaid)
# first create all curves
curves = [[],[]]
# ############################################
# draw the data
# ############################################
if not haveSubsetData: subsetReferencesToDraw = []
else: subsetReferencesToDraw = [example.reference() for example in self.subsetData]
validData = self.getValidList(indices)
for i in range(dataSize):
if not validData[i]:
self.curvePoints.append([]) # add an empty list
continue
curve = QwtPlotCurve(self)
if targetValue != None:
if self.rawdata[i].getclass().value == targetValue:
newColor = self.colorTargetValue
curves[1].append(curve)
else:
newColor = self.colorNonTargetValue
curves[0].append(curve)
else:
if not self.rawdata.domain.classVar: newColor = blackColor
elif continuousClass:
newColor = self.contPalette[self.noJitteringScaledData[classNameIndex][i]]
else:
newColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]]
if haveSubsetData and self.rawdata[i].reference() not in subsetReferencesToDraw:
newColor.setHsv(newColor.hsv()[0], 50, newColor.hsv()[2])
curves[0].append(curve)
else:
curves[1].append(curve)
if subsetReferencesToDraw:
subsetReferencesToDraw.remove(self.rawdata[i].reference())
curve.setPen(QPen(newColor, 1))
if not dataStop:
ys = [self.scaledData[index][i] for index in indices]
else:
ys = []
for index in indices:
ys.append(self.scaledData[index][i])
if index == dataStop[i]: break
curve.setData(xs, ys)
self.curvePoints.append(ys) # save curve points
if self.useSplines:
curve.setStyle(QwtCurve.Spline)
# if we have a data subset that contains examples that don't exist in the original dataset we show them here
if subsetReferencesToDraw != []:
for i in range(len(self.subsetData)):
if not self.subsetData[i].reference() in subsetReferencesToDraw: continue
subsetReferencesToDraw.remove(self.subsetData[i].reference())
# check if has missing values
if 1 in [self.subsetData[i][ind].isSpecial() for ind in indices]: continue
curve = QwtPlotCurve(self)
if targetValue != None:
if self.subsetData[i].getclass().value == targetValue:
newColor = self.colorTargetValue
curves[1].append(curve)
else:
newColor = self.colorNonTargetValue
curves[0].append(curve)
else:
if not self.subsetData.domain.classVar or self.subsetData[i].getclass().isSpecial():
newColor = blackColor
elif continuousClass:
newColor = self.contPalette[self.scaleExampleValue(self.subsetData[i], classNameIndex)]
else:
newColor = self.discPalette[classValueIndices[self.subsetData[i].getclass().value]]
curves[1].append(curve)
curve.setPen(QPen(newColor, 1))
ys = [self.scaledData[index][i] for index in indices]
curve.setData(xs, ys)
if self.useSplines:
curve.setStyle(QwtCurve.Spline)
# now add all curves. First add the gray curves (they will be shown in the back) and then the blue (target value) curves (shown in front)
for curve in curves[0]: self.insertCurve(curve)
for curve in curves[1]: self.insertCurve(curve)
# ############################################
# do we want to show distributions with discrete attributes
if self.showDistributions and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete:
self.showDistributionValues(targetValue, validData, indices, dataStop)
# ############################################
# draw vertical lines that represent attributes
for i in range(len(attributes)):
newCurveKey = self.insertCurve(attributes[i])
self.nonDataKeys.append(newCurveKey)
self.setCurveData(newCurveKey, [i,i], [0,1])
pen = self.curve(newCurveKey).pen(); pen.setWidth(2); self.curve(newCurveKey).setPen(pen)
if self.showAttrValues == 1:
attr = self.rawdata.domain[attributes[i]]
if attr.varType == orange.VarTypes.Continuous:
strVal = "%%.%df" % (attr.numberOfDecimals) % (self.attrValues[attr.name][0])
mkey1 = self.insertMarker(strVal)
self.marker(mkey1).setXValue(i)
self.marker(mkey1).setYValue(0.0-0.01)
strVal = "%%.%df" % (attr.numberOfDecimals) % (self.attrValues[attr.name][1])
mkey2 = self.insertMarker(strVal)
self.marker(mkey2).setXValue(i)
self.marker(mkey2).setYValue(1.0+0.01)
if i == 0:
self.marker(mkey1).setLabelAlignment(Qt.AlignRight + Qt.AlignBottom)
self.marker(mkey2).setLabelAlignment(Qt.AlignRight + Qt.AlignTop)
elif i == len(attributes)-1:
self.marker(mkey1).setLabelAlignment(Qt.AlignLeft + Qt.AlignBottom)
self.marker(mkey2).setLabelAlignment(Qt.AlignLeft + Qt.AlignTop)
else:
self.marker(mkey1).setLabelAlignment(Qt.AlignHCenter + Qt.AlignBottom)
self.marker(mkey2).setLabelAlignment(Qt.AlignHCenter + Qt.AlignTop)
elif attr.varType == orange.VarTypes.Discrete:
attrVals = getVariableValuesSorted(self.rawdata, attributes[i])
valsLen = len(attrVals)
for pos in range(len(attrVals)):
# show a rectangle behind the marker
mkey = self.insertMarker(nonTransparentMarker(QColor(255,255,255), self))
self.marker(mkey).setLabel(attrVals[pos])
font = self.marker(mkey).font(); font.setBold(1); self.marker(mkey).setFont(font)
self.marker(mkey).setXValue(i+0.01)
self.marker(mkey).setYValue(float(1+2*pos)/float(2*valsLen))
self.marker(mkey).setLabelAlignment(Qt.AlignRight + Qt.AlignVCenter)
# ##############################################
# show lines that represent standard deviation or quartiles
# ##############################################
if self.showStatistics:
data = []
for i in range(length):
if self.rawdata.domain[indices[i]].varType != orange.VarTypes.Continuous:
data.append([()])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -