source: orange/orange/OrangeWidgets/Visualize/OWScatterPlotGraph.py @ 8735:065a34c267f2

Revision 8735:065a34c267f2, 26.9 KB checked in by matejd <matejd@…>, 3 years ago (diff)

Moved over code from qtgraph branch, turned primitives into a module (plot.primitives); added Visualize Qt folder to setup.py packages

Line 
1#
2# OWScatterPlotGraph.py
3#
4from OWGraph import *
5import time
6from orngCI import FeatureByCartesianProduct
7##import OWClusterOptimization
8import orngVisFuncts
9from orngScaleScatterPlotData import *
10import ColorPalette
11
12DONT_SHOW_TOOLTIPS = 0
13VISIBLE_ATTRIBUTES = 1
14ALL_ATTRIBUTES = 2
15
16MIN_SHAPE_SIZE = 6
17
18
19###########################################################################################
20##### CLASS : OWSCATTERPLOTGRAPH
21###########################################################################################
22class OWScatterPlotGraph(OWGraph, orngScaleScatterPlotData):
23    def __init__(self, scatterWidget, parent = None, name = "None"):
24        OWGraph.__init__(self, parent, name)
25        orngScaleScatterPlotData.__init__(self)
26
27        self.pointWidth = 8
28        self.jitterContinuous = 0
29        self.jitterSize = 5
30        self.showAxisScale = 1
31        self.showXaxisTitle = 1
32        self.showYLaxisTitle = 1
33        self.showLegend = 1
34        self.tooltipKind = 1
35        self.showFilledSymbols = 1
36        self.showProbabilities = 0
37
38        self.tooltipData = []
39        self.scatterWidget = scatterWidget
40        self.insideColors = None
41        self.shownAttributeIndices = []
42        self.shownXAttribute = ""
43        self.shownYAttribute = ""
44        self.squareGranularity = 3
45        self.spaceBetweenCells = 1
46        self.oldLegendKeys = {}
47
48        self.enableWheelZoom = 1
49
50
51    def setData(self, data, subsetData = None, **args):
52        OWGraph.setData(self, data)
53        self.oldLegendKeys = {}
54        orngScaleScatterPlotData.setData(self, data, subsetData, **args)
55
56    #########################################################
57    # update shown data. Set labels, coloring by className ....
58    def updateData(self, xAttr, yAttr, colorAttr, shapeAttr = "", sizeShapeAttr = "", labelAttr = None, **args):
59#        if not self.haveData:
60#            self.clear()
61#            self.oldLegendKeys = {}
62#            return
63        self.removeDrawingCurves(removeLegendItems = 0)      # my function, that doesn't delete selection curves
64        self.detachItems(QwtPlotItem.Rtti_PlotMarker)
65        self.tips.removeAll()
66        self.tooltipData = []
67        self.potentialsClassifier = None
68        self.potentialsImage = None
69        self.canvas().invalidatePaintCache()
70        self.shownXAttribute = xAttr
71        self.shownYAttribute = yAttr
72
73        if self.scaledData == None or len(self.scaledData) == 0:
74            self.setAxisScale(QwtPlot.xBottom, 0, 1, 1); self.setAxisScale(QwtPlot.yLeft, 0, 1, 1)
75            self.setXaxisTitle(""); self.setYLaxisTitle("")
76            self.oldLegendKeys = {}
77            return
78
79        self.__dict__.update(args)      # set value from args dictionary
80
81        colorIndex = -1
82        if colorAttr != "" and colorAttr != "(Same color)":
83            colorIndex = self.attributeNameIndex[colorAttr]
84            if self.dataDomain[colorAttr].varType == orange.VarTypes.Discrete:
85                self.discPalette.setNumberOfColors(len(self.dataDomain[colorAttr].values))
86
87        shapeIndex = -1
88        if shapeAttr != "" and shapeAttr != "(Same shape)" and len(self.dataDomain[shapeAttr].values) < 11:
89            shapeIndex = self.attributeNameIndex[shapeAttr]
90
91        sizeIndex = -1
92        if sizeShapeAttr != "" and sizeShapeAttr != "(Same size)":
93            sizeIndex = self.attributeNameIndex[sizeShapeAttr]
94
95        showContinuousColorLegend = self.showLegend and colorIndex != -1 and self.dataDomain[colorIndex].varType == orange.VarTypes.Continuous
96
97        (xVarMin, xVarMax) = self.attrValues[xAttr]
98        (yVarMin, yVarMax) = self.attrValues[yAttr]
99        xVar = max(xVarMax - xVarMin, 1e-10)
100        yVar = max(yVarMax - yVarMin, 1e-10)
101        xAttrIndex = self.attributeNameIndex[xAttr]
102        yAttrIndex = self.attributeNameIndex[yAttr]
103
104        attrIndices = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeIndex]
105        while -1 in attrIndices: attrIndices.remove(-1)
106        self.shownAttributeIndices = attrIndices
107
108        # set axis for x attribute
109        discreteX = self.dataDomain[xAttrIndex].varType == orange.VarTypes.Discrete
110        if discreteX:
111            xVarMax -= 1; xVar -= 1
112            xmin = xVarMin - (self.jitterSize + 10.)/100.
113            xmax = xVarMax + (self.jitterSize + 10.)/100.
114            labels = getVariableValuesSorted(self.dataDomain[xAttrIndex])
115        else:
116            off  = (xVarMax - xVarMin) * (self.jitterSize * self.jitterContinuous + 2) / 100.0
117            xmin = xVarMin - off
118            xmax = xVarMax + off
119            labels = None
120        self.setXlabels(labels)
121        self.setAxisScale(QwtPlot.xBottom, xmin, xmax + showContinuousColorLegend * xVar * 0.07, discreteX)
122
123        # set axis for y attribute
124        discreteY = self.dataDomain[yAttrIndex].varType == orange.VarTypes.Discrete
125        if discreteY:
126            yVarMax -= 1; yVar -= 1
127            ymin = yVarMin - (self.jitterSize + 10.)/100.
128            ymax = yVarMax + (self.jitterSize + 10.)/100.
129            labels = getVariableValuesSorted(self.dataDomain[yAttrIndex])
130        else:
131            off  = (yVarMax - yVarMin) * (self.jitterSize * self.jitterContinuous + 2) / 100.0
132            ymin = yVarMin - off
133            ymax = yVarMax + off
134            labels = None
135        self.setYLlabels(labels)
136        self.setAxisScale(QwtPlot.yLeft, ymin, ymax, discreteY)
137
138        self.setXaxisTitle(xAttr)
139        self.setYLaxisTitle(yAttr)
140
141        # compute x and y positions of the points in the scatterplot
142        xData, yData = self.getXYDataPositions(xAttr, yAttr)
143        validData = self.getValidList(attrIndices)      # get examples that have valid data for each used attribute
144
145        # #######################################################
146        # show probabilities
147        if self.showProbabilities and colorIndex >= 0 and self.dataDomain[colorIndex].varType in [orange.VarTypes.Discrete, orange.VarTypes.Continuous]:
148            if self.dataDomain[colorIndex].varType == orange.VarTypes.Discrete: domain = orange.Domain([self.dataDomain[xAttrIndex], self.dataDomain[yAttrIndex], orange.EnumVariable(self.attributeNames[colorIndex], values = getVariableValuesSorted(self.dataDomain[colorIndex]))])
149            else:                                                               domain = orange.Domain([self.dataDomain[xAttrIndex], self.dataDomain[yAttrIndex], orange.FloatVariable(self.attributeNames[colorIndex])])
150            xdiff = xmax-xmin; ydiff = ymax-ymin
151            scX = xData/xdiff
152            scY = yData/ydiff
153            classData = self.originalData[colorIndex]
154
155            probData = numpy.transpose(numpy.array([scX, scY, classData]))
156            probData= numpy.compress(validData, probData, axis = 0)
157            if probData.any():
158                self.potentialsClassifier = orange.P2NN(domain, probData, None, None, None, None)
159            else:
160                self.potentialsClassifier = None
161            sys.stderr.flush()
162            self.xmin = xmin; self.xmax = xmax
163            self.ymin = ymin; self.ymax = ymax
164
165        # ##############################################################
166        # if we have insideColors defined
167        if self.insideColors and self.dataHasDiscreteClass and self.haveData:
168            # variables and domain for the table
169            classData = self.originalData[self.dataClassIndex]
170            (insideData, stringData) = self.insideColors
171            j = 0
172            equalSize = len(self.rawData) == len(insideData)
173            for i in range(len(self.rawData)):
174                if not validData[i]:
175                    j += equalSize
176                    continue
177
178                fillColor = self.discPalette[classData[i], 255*insideData[j]]
179                edgeColor = self.discPalette[classData[i]]
180
181                key = self.addCurve("", fillColor, edgeColor, self.pointWidth, xData = [xData[i]], yData = [yData[i]])
182
183                # we add a tooltip for this point
184                text = self.getExampleTooltipText(self.rawData[j], attrIndices)
185                text += "<hr>" + stringData % (100*insideData[i])
186                self.addTip(xData[i], yData[i], text = text.decode("unicode_escape"))
187                j+=1
188
189        # ##############################################################
190        # no subset data and discrete color index
191        elif (colorIndex == -1 or self.dataDomain[colorIndex].varType == orange.VarTypes.Discrete) and shapeIndex == -1 and sizeIndex == -1 and self.haveData and not self.haveSubsetData and not labelAttr:
192            if colorIndex != -1:
193                classCount = len(self.dataDomain[colorIndex].values)
194            else: classCount = 1
195
196            pos = [[ [] , [] ] for i in range(classCount)]
197            indices = [colorIndex, xAttrIndex, yAttrIndex]
198            if -1 in indices: indices.remove(-1)
199            validData = self.getValidList(indices)
200            colorData = self.originalData[colorIndex]
201            for i in range(len(self.rawData)):
202                if not validData[i]: continue
203                if colorIndex != -1: index = int(colorData[i])
204                else:                index = 0
205                pos[index][0].append(xData[i])
206                pos[index][1].append(yData[i])
207                self.tips.addToolTip(xData[i], yData[i], i)    # we add a tooltip for this point
208
209            for i in range(classCount):
210                newColor = colorIndex != -1 and QColor(self.discPalette[i]) or QColor(Qt.black)
211                newColor.setAlpha(self.alphaValue)
212                key = self.addCurve("", newColor, newColor, self.pointWidth, symbol = self.curveSymbols[0], xData = pos[i][0], yData = pos[i][1])
213
214
215        # ##############################################################
216        # slower, unoptimized drawing because we use different symbols and/or different sizes of symbols
217        else:
218            attrs = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeIndex]
219            while -1 in attrs: attrs.remove(-1)
220            validData = self.getValidList(attrs)
221            if self.haveSubsetData:
222                subsetIdsToDraw = dict([(example.id, 1) for example in self.rawSubsetData])
223                showFilled = 0
224            else:
225                subsetIdsToDraw ={}
226                showFilled = self.showFilledSymbols
227
228            xPointsToAdd = {}
229            yPointsToAdd = {}
230            for i in range(len(self.rawData)):
231                if not validData[i]: continue
232                if subsetIdsToDraw.has_key(self.rawData[i].id):
233                    continue
234
235                if colorIndex != -1:
236                    if self.dataDomain[colorIndex].varType == orange.VarTypes.Continuous:
237                        newColor = self.contPalette.getRGB(self.noJitteringScaledData[colorIndex][i])
238                    else:
239                        newColor = self.discPalette.getRGB(self.originalData[colorIndex][i])
240                else: newColor = (0,0,0)
241
242                Symbol = self.curveSymbols[0]
243                if shapeIndex != -1: Symbol = self.curveSymbols[int(self.originalData[shapeIndex][i])]
244
245                size = self.pointWidth
246                if sizeIndex != -1: size = MIN_SHAPE_SIZE + round(self.noJitteringScaledData[sizeIndex][i] * self.pointWidth)
247
248                if not xPointsToAdd.has_key((newColor, size, Symbol, showFilled)):
249                    xPointsToAdd[(newColor, size, Symbol, showFilled)] = []
250                    yPointsToAdd[(newColor, size, Symbol, showFilled)] = []
251                xPointsToAdd[(newColor, size, Symbol, showFilled)].append(xData[i])
252                yPointsToAdd[(newColor, size, Symbol, showFilled)].append(yData[i])
253                self.tips.addToolTip(xData[i], yData[i], i)     # we add a tooltip for this point
254
255                # Show a label by each marker
256                if labelAttr:
257                    if labelAttr in [self.rawData.domain.getmeta(mykey).name for mykey in self.rawData.domain.getmetas().keys()] + [var.name for var in self.rawData.domain]:
258                        if self.rawData[i][labelAttr].isSpecial(): continue
259                        if self.rawData[i][labelAttr].varType==orange.VarTypes.Continuous:
260                            lbl = "%4.1f" % orange.Value(self.rawData[i][labelAttr])
261                        else:
262                            lbl = str(self.rawData[i][labelAttr].value)
263                        self.addMarker(lbl, xData[i], yData[i], Qt.AlignCenter | Qt.AlignBottom)
264
265            # if we have a data subset that contains examples that don't exist in the original dataset we show them here
266            if self.haveSubsetData:
267                validSubData = self.getValidSubsetList(attrs)
268                xData, yData = self.getXYSubsetDataPositions(xAttr, yAttr)
269                for i in range(len(self.rawSubsetData)):
270                    if not validSubData[i]: continue
271
272                    if colorIndex != -1 and self.validSubsetDataArray[colorIndex][i]:
273                        if self.rawData.domain[colorIndex].varType == orange.VarTypes.Continuous:
274                            newColor = self.contPalette.getRGB(self.scaledSubsetData[colorIndex][i])
275                        else:
276                            newColor = self.discPalette.getRGB(self.originalSubsetData[colorIndex][i])
277                    else: newColor = (0,0,0)
278
279                    if shapeIndex != -1: Symbol = self.curveSymbols[int(self.originalSubsetData[shapeIndex][i])]
280                    else:                Symbol = self.curveSymbols[0]
281
282                    size = self.pointWidth
283                    if sizeIndex != -1: size = MIN_SHAPE_SIZE + round(self.noJitteringScaledSubsetData[sizeIndex][i] * self.pointWidth)
284
285                    if not xPointsToAdd.has_key((newColor, size, Symbol, 1)):
286                        xPointsToAdd[(newColor, size, Symbol, 1)] = []
287                        yPointsToAdd[(newColor, size, Symbol, 1)] = []
288                    xPointsToAdd[(newColor, size, Symbol, 1)].append(xData[i])
289                    yPointsToAdd[(newColor, size, Symbol, 1)].append(yData[i])
290                    self.tips.addToolTip(xData[i], yData[i], -i-1)     # we add a tooltip for this point
291
292                    # Show a label by each marker
293                    if labelAttr:
294                        if labelAttr in [self.rawSubsetData.domain.getmeta(mykey).name for mykey in self.rawSubsetData.domain.getmetas().keys()] + [var.name for var in self.rawSubsetData.domain]:
295                            if self.rawSubsetData[i][labelAttr].isSpecial(): continue
296                            if self.rawSubsetData[i][labelAttr].varType==orange.VarTypes.Continuous:
297                                lbl = "%4.1f" % orange.Value(self.rawSubsetData[i][labelAttr])
298                            else:
299                                lbl = str(self.rawSubsetData[i][labelAttr].value)
300                            self.addMarker(lbl, xData[i], yData[i], Qt.AlignCenter | Qt.AlignBottom)
301
302            for i, (color, size, symbol, showFilled) in enumerate(xPointsToAdd.keys()):
303                xData = xPointsToAdd[(color, size, symbol, showFilled)]
304                yData = yPointsToAdd[(color, size, symbol, showFilled)]
305                c = QColor(*color)
306                c.setAlpha(self.alphaValue)
307                self.addCurve("", c, c, size, symbol = symbol, xData = xData, yData = yData, showFilledSymbols = showFilled)
308
309        # ##############################################################
310        # show legend if necessary
311        if self.showLegend == 1:
312            legendKeys = {}
313            colorIndex = colorIndex if colorIndex != -1 and self.dataDomain[colorIndex].varType == orange.VarTypes.Discrete else -1
314            shapeIndex = shapeIndex if shapeIndex != -1 and self.dataDomain[shapeIndex].varType == orange.VarTypes.Discrete else -1
315            sizeIndex = sizeIndex if sizeIndex != -1 and self.dataDomain[sizeIndex].varType == orange.VarTypes.Discrete else -1
316           
317            singleLegend = len([index for index in [colorIndex, shapeIndex, sizeIndex] if index != -1]) == 1
318            if singleLegend:
319                #Show only values
320                legendJoin = lambda name, val: val
321            else:
322                legendJoin = lambda name, val: name + "=" + val
323               
324            if colorIndex != -1:
325                num = len(self.dataDomain[colorIndex].values)
326                val = [[], [], [self.pointWidth]*num, [QwtSymbol.Ellipse]*num]
327                varValues = getVariableValuesSorted(self.dataDomain[colorIndex])
328                for ind in range(num):
329                    val[0].append(legendJoin(self.dataDomain[colorIndex].name, varValues[ind]))
330                    val[1].append(self.discPalette[ind])
331                legendKeys[colorIndex] = val
332
333            if shapeIndex != -1:
334                num = len(self.dataDomain[shapeIndex].values)
335                if legendKeys.has_key(shapeIndex):  val = legendKeys[shapeIndex]
336                else:                               val = [[], [Qt.black]*num, [self.pointWidth]*num, []]
337                varValues = getVariableValuesSorted(self.dataDomain[shapeIndex])
338                val[3] = []; val[0] = []
339                for ind in range(num):
340                    val[3].append(self.curveSymbols[ind])
341                    val[0].append(legendJoin(self.dataDomain[shapeIndex].name, varValues[ind]))
342                legendKeys[shapeIndex] = val
343
344            if sizeIndex != -1:
345                num = len(self.dataDomain[sizeIndex].values)
346                if legendKeys.has_key(sizeIndex):  val = legendKeys[sizeIndex]
347                else:                               val = [[], [Qt.black]*num, [], [QwtSymbol.Ellipse]*num]
348                val[2] = []; val[0] = []
349                varValues = getVariableValuesSorted(self.dataDomain[sizeIndex])
350                for ind in range(num):
351                    val[0].append(legendJoin(self.dataDomain[sizeIndex].name, varValues[ind]))
352                    val[2].append(MIN_SHAPE_SIZE + round(ind*self.pointWidth/len(varValues)))
353                legendKeys[sizeIndex] = val
354        else:
355            legendKeys = {}
356
357        if legendKeys != self.oldLegendKeys:
358            self.oldLegendKeys = legendKeys
359            self.legend().clear()
360            for val in legendKeys.values():       # add new curve keys
361                for i in range(len(val[1])):
362                    self.addCurve(val[0][i], val[1][i], val[1][i], val[2][i], symbol = val[3][i], enableLegend = 1)
363
364        # ##############################################################
365        # draw color scale for continuous coloring attribute
366        if colorIndex != -1 and showContinuousColorLegend:
367            x0 = xmax + xVar*1.0/100.0;  x1 = x0 + xVar*2.5/100.0
368            count = 200
369            height = yVar / float(count)
370            xs = [x0, x1, x1, x0]
371
372            for i in range(count):
373                y = yVarMin + i*yVar/float(count)
374                col = self.contPalette[i/float(count)]
375                col.setAlpha(self.alphaValue)
376                curve = PolygonCurve(QPen(col), QBrush(col))
377                curve.setData(xs, [y,y, y+height, y+height])
378                curve.attach(self)
379
380
381            # add markers for min and max value of color attribute
382            (colorVarMin, colorVarMax) = self.attrValues[colorAttr]
383            self.addMarker("%s = %%.%df" % (colorAttr, self.dataDomain[colorAttr].numberOfDecimals) % (colorVarMin), x0 - xVar*1./100.0, yVarMin + yVar*0.04, Qt.AlignLeft)
384            self.addMarker("%s = %%.%df" % (colorAttr, self.dataDomain[colorAttr].numberOfDecimals) % (colorVarMax), x0 - xVar*1./100.0, yVarMin + yVar*0.96, Qt.AlignLeft)
385
386        self.replot()
387
388##    # ##############################################################
389##    # ######  SHOW CLUSTER LINES  ##################################
390##    # ##############################################################
391##    def showClusterLines(self, xAttr, yAttr, width = 1):
392##        classIndices = getVariableValueIndices(self.rawData, self.attributeNameIndex[self.rawData.domain.classVar.name])
393##
394##        shortData = self.rawData.select([self.rawData.domain[xAttr], self.rawData.domain[yAttr], self.rawData.domain.classVar])
395##        shortData = orange.Preprocessor_dropMissing(shortData)
396##
397##        (closure, enlargedClosure, classValue) = self.clusterClosure
398##
399##        (xVarMin, xVarMax) = self.attrValues[xAttr]
400##        (yVarMin, yVarMax) = self.attrValues[yAttr]
401##        xVar = xVarMax - xVarMin
402##        yVar = yVarMax - yVarMin
403##
404##        if type(closure) == dict:
405##            for key in closure.keys():
406##                clusterLines = closure[key]
407##                color = self.discPalette[classIndices[self.rawData.domain.classVar[classValue[key]].value]]
408##                for (p1, p2) in clusterLines:
409##                    self.addCurve("", color, color, 1, QwtPlotCurve.Lines, QwtSymbol.NoSymbol, xData = [float(shortData[p1][0]), float(shortData[p2][0])], yData = [float(shortData[p1][1]), float(shortData[p2][1])], lineWidth = width)
410##        else:
411##            colorIndex = self.discPalette[classIndices[self.rawData.domain.classVar[classValue].value]]
412##            for (p1, p2) in closure:
413##                self.addCurve("", color, color, 1, QwtPlotCurve.Lines, QwtSymbol.NoSymbol, xData = [float(shortData[p1][0]), float(shortData[p2][0])], yData = [float(shortData[p1][1]), float(shortData[p2][1])], lineWidth = width)
414
415    def addTip(self, x, y, attrIndices = None, dataindex = None, text = None):
416        if self.tooltipKind == DONT_SHOW_TOOLTIPS: return
417        if text == None:
418            if self.tooltipKind == VISIBLE_ATTRIBUTES:  text = self.getExampleTooltipText(self.rawData[dataindex], attrIndices)
419            elif self.tooltipKind == ALL_ATTRIBUTES:    text = self.getExampleTooltipText(self.rawData[dataindex], range(len(self.attributeNames)))
420        self.tips.addToolTip(x, y, text)
421
422
423    # override the default buildTooltip function defined in OWGraph
424    def buildTooltip(self, exampleIndex):
425        if exampleIndex < 0:
426            example = self.rawSubsetData[-exampleIndex - 1]
427        else:
428            example = self.rawData[exampleIndex]
429
430        if self.tooltipKind == VISIBLE_ATTRIBUTES:
431            text = self.getExampleTooltipText(example, self.shownAttributeIndices)
432        elif self.tooltipKind == ALL_ATTRIBUTES:
433            text = self.getExampleTooltipText(example)
434        return text
435
436
437    # ##############################################################
438    # send 2 example tables. in first is the data that is inside selected rects (polygons), in the second is unselected data
439    def getSelectionsAsExampleTables(self, attrList):
440        [xAttr, yAttr] = attrList
441        #if not self.rawData: return (None, None, None)
442        if not self.haveData: return (None, None)
443        if not self.selectionCurveList: return (None, self.rawData)       # if no selections exist
444
445        selIndices, unselIndices = self.getSelectionsAsIndices(attrList)
446
447        selected = self.rawData.selectref(selIndices)
448        unselected = self.rawData.selectref(unselIndices)
449
450        if len(selected) == 0: selected = None
451        if len(unselected) == 0: unselected = None
452
453        return (selected, unselected)
454
455
456    def getSelectionsAsIndices(self, attrList, validData = None):
457        [xAttr, yAttr] = attrList
458        if not self.haveData: return [], []
459
460        attrIndices = [self.attributeNameIndex[attr] for attr in attrList]
461        if validData == None:
462            validData = self.getValidList(attrIndices)
463
464        (xArray, yArray) = self.getXYDataPositions(xAttr, yAttr)
465
466        return self.getSelectedPoints(xArray, yArray, validData)
467
468
469    def onMouseReleased(self, e):
470        OWGraph.onMouseReleased(self, e)
471        self.updateLayout()
472
473    def computePotentials(self):
474        import orangeom
475        rx = self.transform(QwtPlot.xBottom, self.xmax) - self.transform(QwtPlot.xBottom, self.xmin)
476        ry = self.transform(QwtPlot.yLeft, self.ymin) - self.transform(QwtPlot.yLeft, self.ymax)
477        rx -= rx % self.squareGranularity
478        ry -= ry % self.squareGranularity
479
480        ox = self.transform(QwtPlot.xBottom, 0) - self.transform(QwtPlot.xBottom, self.xmin)
481        oy = self.transform(QwtPlot.yLeft, self.ymin) - self.transform(QwtPlot.yLeft, 0)
482
483        if not getattr(self, "potentialsImage", None) or getattr(self, "potentialContext", None) != (rx, ry, self.shownXAttribute, self.shownYAttribute, self.squareGranularity, self.jitterSize, self.jitterContinuous, self.spaceBetweenCells):
484            if self.potentialsClassifier.classVar.varType == orange.VarTypes.Continuous:
485                imagebmp = orangeom.potentialsBitmap(self.potentialsClassifier, rx, ry, ox, oy, self.squareGranularity, 1)  # the last argument is self.trueScaleFactor (in LinProjGraph...)
486                palette = [qRgb(255.*i/255., 255.*i/255., 255-(255.*i/255.)) for i in range(255)] + [qRgb(255, 255, 255)]
487            else:
488                imagebmp, nShades = orangeom.potentialsBitmap(self.potentialsClassifier, rx, ry, ox, oy, self.squareGranularity, 1., self.spaceBetweenCells) # the last argument is self.trueScaleFactor (in LinProjGraph...)
489                palette = []
490                sortedClasses = getVariableValuesSorted(self.potentialsClassifier.domain.classVar)
491                for cls in self.potentialsClassifier.classVar.values:
492                    color = self.discPalette.getRGB(sortedClasses.index(cls))
493                    towhite = [255-c for c in color]
494                    for s in range(nShades):
495                        si = 1-float(s)/nShades
496                        palette.append(qRgb(*tuple([color[i]+towhite[i]*si for i in (0, 1, 2)])))
497                palette.extend([qRgb(255, 255, 255) for i in range(256-len(palette))])
498
499            self.potentialsImage = QImage(imagebmp, rx, ry, QImage.Format_Indexed8)
500            self.potentialsImage.setColorTable(ColorPalette.signedPalette(palette) if qVersion() < "4.5" else palette)
501            self.potentialsImage.setNumColors(256)
502            self.potentialContext = (rx, ry, self.shownXAttribute, self.shownYAttribute, self.squareGranularity, self.jitterSize, self.jitterContinuous, self.spaceBetweenCells)
503            self.potentialsImageFromClassifier = self.potentialsClassifier
504
505
506    def drawCanvas(self, painter):
507        if self.showProbabilities and getattr(self, "potentialsClassifier", None):
508            if not (self.potentialsClassifier is getattr(self,"potentialsImageFromClassifier", None)):
509                self.computePotentials()
510            target = QRectF(self.transform(QwtPlot.xBottom, self.xmin), self.transform(QwtPlot.yLeft, self.ymax),
511                            self.transform(QwtPlot.xBottom, self.xmax) - self.transform(QwtPlot.xBottom,self.xmin),
512                            self.transform(QwtPlot.yLeft, self.ymin) - self.transform(QwtPlot.yLeft, self.ymax))
513            source = QRectF(0, 0, self.potentialsImage.size().width(), self.potentialsImage.size().height())
514            painter.drawImage(target, self.potentialsImage, source)
515#            painter.drawImage(self.transform(QwtPlot.xBottom, self.xmin), self.transform(QwtPlot.yLeft, self.ymax), self.potentialsImage)
516        OWGraph.drawCanvas(self, painter)
517
518
519
520
521if __name__== "__main__":
522    #Draw a simple graph
523    a = QApplication(sys.argv)
524    c = OWScatterPlotGraph(None)
525    c.show()
526    a.exec_()
Note: See TracBrowser for help on using the repository browser.