source: orange/orange/OrangeWidgets/Visualize/OWPolyvizGraph.py @ 6538:a5f65d7f0b2c

Revision 6538:a5f65d7f0b2c, 24.2 KB checked in by Mitar <Mitar@…>, 4 years ago (diff)

Made XPM version of the icon 32x32.

Line 
1from OWGraph import *
2from copy import copy, deepcopy
3import time, math
4from OWkNNOptimization import *
5from orngScalePolyvizData import *
6import orngVisFuncts
7from OWGraphTools import UnconnectedLinesCurve
8
9# ####################################################################
10# calculate Euclidean distance between two points
11def euclDist(v1, v2):
12    val = 0
13    for i in range(len(v1)):
14        val += (v1[i]-v2[i])**2
15    return math.sqrt(val)
16
17
18# ####################################################################
19# get a list of all different permutations
20def getPermutationList(elements, tempPerm, currList, checkReverse):
21    for i in range(len(elements)):
22        el =  elements[i]
23        elements.remove(el)
24        tempPerm.append(el)
25        getPermutationList(elements, tempPerm, currList, checkReverse)
26
27        elements.insert(i, el)
28        tempPerm.pop()
29
30    if elements == []:
31        temp = copy(tempPerm)
32        # in tempPerm we have a permutation. Check if it already exists in the currList
33        for i in range(len(temp)):
34            el = temp.pop()
35            temp.insert(0, el)
36            if str(temp) in currList: return
37
38
39        if checkReverse == 1:
40            # also try the reverse permutation
41            temp.reverse()
42            for i in range(len(temp)):
43                el = temp.pop()
44                temp.insert(0, el)
45                if str(temp) in currList: return
46        currList[str(tempPerm)] = copy(tempPerm)
47
48def fact(i):
49        ret = 1
50        while i > 1:
51            ret = ret*i
52            i -= 1
53        return ret
54
55# return number of combinations where we select "select" from "total"
56def combinations(select, total):
57    return fact(total)/ (fact(total-select)*fact(select))
58
59
60LINE_TOOLTIPS = 0
61VISIBLE_ATTRIBUTES = 1
62ALL_ATTRIBUTES = 2
63
64TOOLTIPS_SHOW_DATA = 0
65TOOLTIPS_SHOW_SPRINGS = 1
66
67###########################################################################################
68##### CLASS : OWPolyvizGRAPH
69###########################################################################################
70class OWPolyvizGraph(OWGraph, orngScalePolyvizData):
71    def __init__(self, polyvizWidget, parent = None, name = None):
72        "Constructs the graph"
73        OWGraph.__init__(self, parent, name)
74        orngScalePolyvizData.__init__(self)
75        self.enableGridXB(0)
76        self.enableGridYL(0)
77
78        self.lineLength = 2
79        self.totalPossibilities = 0 # a variable used in optimization - tells us the total number of different attribute positions
80        self.triedPossibilities = 0 # how many possibilities did we already try
81        self.startTime = time.time()
82        self.enhancedTooltips = 1
83        self.kNNOptimization = None
84        self.polyvizWidget = polyvizWidget
85        self.useDifferentSymbols = 0
86        self.useDifferentColors = 1
87        self.tooltipKind = 0        # index in ["Show line tooltips", "Show visible attributes", "Show all attributes"]
88        self.tooltipValue = 0       # index in ["Tooltips show data values", "Tooltips show spring values"]
89
90        self.dataMap = {}        # each key is of form: "xVal-yVal", where xVal and yVal are discretized continuous values. Value of each key has form: (x,y, HSVValue, [data vals])
91        self.tooltipCurveKeys = []
92        self.tooltipMarkers   = []
93        self.showLegend = 1
94        self.onlyOnePerSubset = 1
95
96        self.showProbabilities = 0
97        self.squareGranularity = 3
98        self.spaceBetweenCells = 1
99        self.scaleFactor = 1.0
100
101        # init axes
102        self.enableXaxis(0)
103        self.enableYLaxis(0)
104        self.setAxisScale(QwtPlot.xBottom, -1.20, 1.20, 1)
105        self.setAxisScale(QwtPlot.yLeft, -1.20, 1.20, 1)
106
107    def createAnchors(self, anchorNum):
108        anchors = [[],[]]
109        for i in range(anchorNum):
110            x = math.cos(2*math.pi * float(i) / float(anchorNum)); strX = "%.5f" % (x)
111            y = math.sin(2*math.pi * float(i) / float(anchorNum)); strY = "%.5f" % (y)
112            anchors[0].append(float(strX))  # this might look stupid, but this way we get rid of rounding errors
113            anchors[1].append(float(strY))
114        return anchors
115
116    def setData(self, data, subsetData = None, **args):
117        OWGraph.setData(self, data)
118        orngScalePolyvizData.setData(self, data, subsetData, **args)
119
120    #
121    # update shown data. Set labels, coloring by className ....
122    #
123    def updateData(self, labels, foo, **args):
124        #self.removeCurves()
125        self.removeDrawingCurves()  # my function, that doesn't delete selection curves
126        self.removeMarkers()
127
128        # initial var values
129        self.showKNNModel = 0
130        self.showCorrect = 1
131        self.__dict__.update(args)
132
133        length = len(labels)
134        self.dataMap = {}               # dictionary with keys of form "x_i-y_i" with values (x_i, y_i, color, data)
135        self.XAnchor = self.createXAnchors(length)
136        self.YAnchor = self.createYAnchors(length)
137        self.shownAttributes = labels
138        polyvizLineCoordsX = []; polyvizLineCoordsY = []    # if class is discrete we will optimize drawing by storing computed values and adding less data curves to plot
139
140        # we must have at least 3 attributes to be able to show anything
141        if not self.haveData or len(labels) < 3:
142            self.updateLayout()
143            return
144
145        dataSize = len(self.rawData)
146
147        if self.dataHasClass: useDifferentColors = self.useDifferentColors   # don't use colors if we don't have a class
148        else:                 useDifferentColors = 0
149
150        self.setAxisScale(QwtPlot.xBottom, -1.20, 1.20 + 0.05 * self.showLegend, 1)
151
152        # store indices to shown attributes
153        indices = [self.attributeNameIndex[label] for label in labels]
154
155        # will we show different symbols?
156        useDifferentSymbols = self.useDifferentSymbols and self.dataHasDiscreteClass and len(self.dataDomain.classVar.values) < len(self.curveSymbols)
157
158        # ##########
159        # draw text at lines
160        for i in range(length):
161            # print attribute name
162            self.addMarker(labels[i], 0.6*(self.XAnchor[i]+ self.XAnchor[(i+1)%length]), 0.6*(self.YAnchor[i]+ self.YAnchor[(i+1)%length]), Qt.AlignHCenter | Qt.AlignVCenter, bold = 1)
163
164            if self.dataDomain[labels[i]].varType == orange.VarTypes.Discrete:
165                # print all possible attribute values
166                values = getVariableValuesSorted(self.dataDomain[labels[i]])
167                count = len(values)
168                k = 1.08
169                for j in range(count):
170                    pos = (1.0 + 2.0*float(j)) / float(2*count)
171                    self.addMarker(values[j], k*(1-pos)*self.XAnchor[i]+k*pos*self.XAnchor[(i+1)%length], k*(1-pos)*self.YAnchor[i]+k*pos*self.YAnchor[(i+1)%length], Qt.AlignHCenter | Qt.AlignVCenter)
172            else:
173                # min and max value
174                if self.tooltipValue == TOOLTIPS_SHOW_SPRINGS:
175                    names = ["%.1f" % (0.0), "%.1f" % (1.0)]
176                elif self.tooltipValue == TOOLTIPS_SHOW_DATA:
177                    names = ["%%.%df" % (self.dataDomain[labels[i]].numberOfDecimals) % (self.attrValues[labels[i]][0]), "%%.%df" % (self.dataDomain[labels[i]].numberOfDecimals) % (self.attrValues[labels[i]][1])]
178                self.addMarker(names[0],0.95*self.XAnchor[i]+0.15*self.XAnchor[(i+1)%length], 0.95*self.YAnchor[i]+0.15*self.YAnchor[(i+1)%length], Qt.AlignHCenter | Qt.AlignVCenter)
179                self.addMarker(names[1], 0.15*self.XAnchor[i]+0.95*self.XAnchor[(i+1)%length], 0.15*self.YAnchor[i]+0.95*self.YAnchor[(i+1)%length], Qt.AlignHCenter | Qt.AlignVCenter)
180
181        XAnchorPositions = numpy.zeros([length, dataSize], numpy.float)
182        YAnchorPositions = numpy.zeros([length, dataSize], numpy.float)
183        XAnchor = self.createXAnchors(length)
184        YAnchor = self.createYAnchors(length)
185
186        for i in range(length):
187            Xdata = XAnchor[i] * (1-self.noJitteringScaledData[indices[i]]) + XAnchor[(i+1)%length] * self.noJitteringScaledData[indices[i]]
188            Ydata = YAnchor[i] * (1-self.noJitteringScaledData[indices[i]]) + YAnchor[(i+1)%length] * self.noJitteringScaledData[indices[i]]
189            XAnchorPositions[i] = Xdata
190            YAnchorPositions[i] = Ydata
191
192        XAnchorPositions = numpy.swapaxes(XAnchorPositions, 0,1)
193        YAnchorPositions = numpy.swapaxes(YAnchorPositions, 0,1)
194
195        selectedData = numpy.take(self.scaledData, indices, axis = 0)
196        sum_i = numpy.add.reduce(selectedData)
197
198        # test if there are zeros in sum_i
199        if len(numpy.nonzero(sum_i)) < len(sum_i):
200            add = numpy.where(sum_i == 0, 1.0, 0.0)
201            sum_i += add
202
203        x_positions = numpy.sum(numpy.swapaxes(XAnchorPositions * numpy.swapaxes(selectedData, 0,1), 0,1), axis=0) * self.scaleFactor / sum_i
204        y_positions = numpy.sum(numpy.swapaxes(YAnchorPositions * numpy.swapaxes(selectedData, 0,1), 0,1), axis=0) * self.scaleFactor / sum_i
205        validData = self.getValidList(indices)
206
207        xPointsToAdd = {}
208        yPointsToAdd = {}
209        self.xLinesToAdd = {}   # this is filled in addAnchorLine function
210        self.yLinesToAdd = {}
211
212        if self.showKNNModel == 1 and self.dataHasClass:
213            # variables and domain for the table
214            domain = orange.Domain([orange.FloatVariable("xVar"), orange.FloatVariable("yVar"), self.dataDomain.classVar])
215            table = orange.ExampleTable(domain)
216
217            # build an example table
218            for i in range(dataSize):
219                if validData[i]:
220                    table.append(orange.Example(domain, [x_positions[i], y_positions[i], self.rawData[i].getclass()]))
221
222            kNNValues, probabilities = self.kNNOptimization.kNNClassifyData(table)
223            accuracy = copy(kNNValues)
224            measure = self.kNNOptimization.getQualityMeasure()
225            if self.dataDomain.classVar.varType == orange.VarTypes.Discrete:
226                if ((measure == CLASS_ACCURACY or measure == AVERAGE_CORRECT) and self.showCorrect) or (measure == BRIER_SCORE and not self.showCorrect):
227                    kNNValues = [1.0 - val for val in kNNValues]
228            else:
229                if self.showCorrect:
230                    kNNValues = [1.0 - val for val in kNNValues]
231
232            # fill and edge color palettes
233            bwColors = ColorPaletteBW(-1, 55, 255)
234
235            if self.dataHasContinuousClass:
236                preText = 'Mean square error : '
237                classColors = self.contPalette
238            else:
239                classColors = self.discPalette
240                if measure == CLASS_ACCURACY:    preText = "Classification accuracy : "
241                elif measure == AVERAGE_CORRECT: preText = "Average correct classification : "
242                else:                            preText = "Brier score : "
243
244            for i in range(len(table)):
245                fillColor = bwColors.getRGB(kNNValues[i])
246                edgeColor = classColors.getRGB(self.originalData[self.dataClassIndex][i])
247                if not xPointsToAdd.has_key((fillColor, edgeColor, QwtSymbol.Ellipse, 1)):
248                    xPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)] = []
249                    yPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)] = []
250                xPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)].append(table[i][0].value)
251                yPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)].append(table[i][1].value)
252                self.addAnchorLine(x_positions[i], y_positions[i], XAnchorPositions[i], YAnchorPositions[i], fillColor, i, length)
253
254        # CONTINUOUS class
255        elif self.dataHasContinuousClass:
256            for i in range(dataSize):
257                if not validData[i]: continue
258                if useDifferentColors:  newColor = self.contPalette[self.noJitteringScaledData[self.dataClassIndex][i]]
259                else:                   newColor = QColor(0,0,0)
260                self.addCurve(str(i), newColor, newColor, self.pointWidth, xData = [x_positions[i]], yData = [y_positions[i]])
261                self.addTooltipKey(x_positions[i], y_positions[i], XAnchorPositions[i], YAnchorPositions[i], newColor, i)
262                self.addAnchorLine(x_positions[i], y_positions[i], XAnchorPositions[i], YAnchorPositions[i], (newColor.red(), newColor.green(), newColor.blue()), i, length)
263
264        # DISCRETE class or no class at all
265        else:
266            color = (0,0,0)
267            symbol = self.curveSymbols[0]
268            for i in range(dataSize):
269                if not validData[i]: continue
270                if self.dataHasClass:
271                    if self.useDifferentSymbols:
272                        symbol = self.curveSymbols[int(self.originalData[self.dataClassIndex][i])]
273                    if useDifferentColors:
274                        color = self.discPalette.getRGB(self.originalData[self.dataClassIndex][i])
275                if not xPointsToAdd.has_key((color, color, symbol, 1)):
276                    xPointsToAdd[(color, color, symbol, 1)] = []
277                    yPointsToAdd[(color, color, symbol, 1)] = []
278                xPointsToAdd[(color, color, symbol, 1)].append(x_positions[i])
279                yPointsToAdd[(color, color, symbol, 1)].append(y_positions[i])
280
281                self.addAnchorLine(x_positions[i], y_positions[i], XAnchorPositions[i], YAnchorPositions[i], color, i, length)
282                self.addTooltipKey(x_positions[i], y_positions[i], XAnchorPositions[i], YAnchorPositions[i], QColor(*color), i)
283
284        # draw the points
285        for i, (fillColor, edgeColor, symbol, showFilled) in enumerate(xPointsToAdd.keys()):
286            xData = xPointsToAdd[(fillColor, edgeColor, symbol, showFilled)]
287            yData = yPointsToAdd[(fillColor, edgeColor, symbol, showFilled)]
288            self.addCurve(str(i), QColor(*fillColor), QColor(*edgeColor), self.pointWidth, symbol = symbol, xData = xData, yData = yData, showFilledSymbols = showFilled)
289
290        self.showAnchorLines()
291        self.xLinesToAdd = {}
292        self.yLinesToAdd = {}
293
294        # draw polygon
295        self.addCurve("polygon", QColor(0,0,0), QColor(0,0,0), 0, QwtPlotCurve.Lines, symbol = QwtSymbol.NoSymbol, xData = list(self.XAnchor) + [self.XAnchor[0]], yData = list(self.YAnchor) + [self.YAnchor[0]], lineWidth = 2)
296
297        #################
298        # draw the legend
299        if self.showLegend and self.dataHasClass:
300            # show legend for discrete class
301            if self.dataHasDiscreteClass:
302                self.addMarker(self.dataDomain.classVar.name, 0.87, 1.06, Qt.AlignLeft)
303
304                classVariableValues = getVariableValuesSorted(self.dataDomain.classVar)
305                for index in range(len(classVariableValues)):
306                    if useDifferentColors: color = self.discPalette[index]
307                    else:                       color = QColor(0,0,0)
308                    y = 1.0 - index * 0.05
309
310                    if not self.useDifferentSymbols:  curveSymbol = self.curveSymbols[0]
311                    else:                             curveSymbol = self.curveSymbols[index]
312
313                    self.addCurve(str(index), color, color, self.pointWidth, symbol = curveSymbol, xData = [0.95, 0.95], yData = [y, y])
314                    self.addMarker(classVariableValues[index], 0.90, y, Qt.AlignLeft | Qt.AlignVCenter)
315
316            # show legend for continuous class
317            elif self.dataHasContinuousClass:
318                xs = [1.15, 1.20, 1.20, 1.15]
319                count = 200
320                height = 2 / float(count)
321                for i in range(count):
322                    y = -1.0 + i*2.0/float(count)
323                    col = self.contPalette[i/float(count)]
324                    c = PolygonCurve(QPen(col), QBrush(col), xs, [y,y, y+height, y+height])
325                    c.attach(self)
326
327                # add markers for min and max value of color attribute
328                [minVal, maxVal] = self.attrValues[self.dataDomain.classVar.name]
329                self.addMarker("%s = %%.%df" % (self.dataDomain.classVar.name, self.dataDomain.classVar.numberOfDecimals) % (minVal), xs[0] - 0.02, -1.0 + 0.04, Qt.AlignLeft)
330                self.addMarker("%s = %%.%df" % (self.dataDomain.classVar.name, self.dataDomain.classVar.numberOfDecimals) % (maxVal), xs[0] - 0.02, +1.0 - 0.04, Qt.AlignLeft)
331
332        self.replot()
333
334
335    def addAnchorLine(self, x, y, xAnchors, yAnchors, color, index, count):
336        for j in range(count):
337            dist = euclDist([x, y], [xAnchors[j] , yAnchors[j]])
338            if dist == 0: continue
339            kvoc = float(self.lineLength * 0.05) / dist
340            lineX1 = x; lineY1 = y
341
342            # we don't make extrapolation
343            if kvoc > 1: lineX2 = lineX1; lineY2 = lineY1
344            else:
345                lineX2 = (1.0 - kvoc)*xAnchors[j] + kvoc * lineX1
346                lineY2 = (1.0 - kvoc)*yAnchors[j] + kvoc * lineY1
347
348            self.xLinesToAdd[color] = self.xLinesToAdd.get(color, []) + [xAnchors[j], lineX2]
349            self.yLinesToAdd[color] = self.yLinesToAdd.get(color, []) + [yAnchors[j], lineY2]
350
351
352    def showAnchorLines(self):
353        for i, color in enumerate(self.xLinesToAdd.keys()):
354            curve = UnconnectedLinesCurve("", QPen(QColor(*color)), self.xLinesToAdd[color], self.yLinesToAdd[color])
355            curve.attach(self)
356
357    # create a dictionary value for the data point
358    # this will enable to show tooltips faster and to make selection of examples available
359    def addTooltipKey(self, x, y, xAnchors, yAnchors, color, index):
360        dictValue = "%.1f-%.1f"%(x, y)
361        if not self.dataMap.has_key(dictValue):
362            self.dataMap[dictValue] = []
363        self.dataMap[dictValue].append((x, y, xAnchors, yAnchors, color, index))
364
365
366    # ##############
367    # draw tooltips
368    def onMouseMoved(self, e):
369        redraw = 0
370        if self.tooltipCurveKeys != [] or self.tooltipMarkers != []: redraw = 1
371
372        for key in self.tooltipCurveKeys:  self.removeCurve(key)
373        for marker in self.tooltipMarkers: self.removeMarker(marker)
374        self.tooltipCurveKeys = []
375        self.tooltipMarkers = []
376
377        # in case we are drawing a rectangle, we don't draw enhanced tooltips
378        # because it would then fail to draw the rectangle
379        if self.mouseCurrentlyPressed:
380            OWGraph.onMouseMoved(self, e)
381            if redraw: self.replot()
382            return
383
384        xFloat = self.invTransform(QwtPlot.xBottom, e.x())
385        yFloat = self.invTransform(QwtPlot.yLeft, e.y())
386        dictValue = "%.1f-%.1f"%(xFloat, yFloat)
387        if self.dataMap.has_key(dictValue):
388            points = self.dataMap[dictValue]
389            bestDist = 100.0
390            nearestPoint = ()
391            for (x_i, y_i, xAnchors, yAnchors, color, index) in points:
392                currDist = sqrt((xFloat-x_i)*(xFloat-x_i) + (yFloat-y_i)*(yFloat-y_i))
393                if currDist < bestDist:
394                    bestDist = currDist
395                    nearestPoint = (x_i, y_i, xAnchors, yAnchors, color, index)
396
397            (x_i, y_i, xAnchors, yAnchors, color, index) = nearestPoint
398            if self.tooltipKind == LINE_TOOLTIPS and bestDist < 0.05:
399                for i in range(len(self.shownAttributes)):
400
401                    # draw lines
402                    key = self.addCurve("Tooltip curve", color, color, 1, style = QwtPlotCurve.Lines, symbol = QwtSymbol.NoSymbol, xData = [x_i, xAnchors[i]], yData = [y_i, yAnchors[i]])
403                    self.tooltipCurveKeys.append(key)
404
405                    # draw text
406                    marker = None
407                    if self.tooltipValue == TOOLTIPS_SHOW_DATA:
408                        marker = self.addMarker(str(self.rawData[index][self.shownAttributes[i]]), (x_i + xAnchors[i])/2.0, (y_i + yAnchors[i])/2.0, Qt.AlignVCenter | Qt.AlignHCenter, bold = 1)
409                    elif self.tooltipValue == TOOLTIPS_SHOW_SPRINGS:
410                        marker = self.addMarker("%.3f" % (self.scaledData[self.attributeNameIndex[self.shownAttributes[i]]][index]), (x_i + xAnchors[i])/2.0, (y_i + yAnchors[i])/2.0, Qt.AlignVCenter | Qt.AlignHCenter, bold = 1)
411                    font = self.markerFont(marker)
412                    font.setPointSize(12)
413                    self.setMarkerFont(marker, font)
414                    self.tooltipMarkers.append(marker)
415
416            elif self.tooltipKind == VISIBLE_ATTRIBUTES or self.tooltipKind == ALL_ATTRIBUTES:
417                if self.tooltipKind == VISIBLE_ATTRIBUTES: labels = self.shownAttributes
418                else:                                      labels = self.attributeNames
419
420                text = self.getExampleTooltipText(self.rawData[index], labels)
421                self.showTip(self.transform(QwtPlot.xBottom, x_i), self.transform(QwtPlot.yLeft, y_i), text)
422
423        OWGraph.onMouseMoved(self, e)
424        self.update()
425
426
427    def generateAttrReverseLists(self, attrList, fullAttribList, tempList):
428        if attrList == []: return tempList
429        tempList2 = deepcopy(tempList)
430        index = fullAttribList.index(attrList[0])
431        for list in tempList2: list[index] = 1
432        return self.generateAttrReverseLists(attrList[1:], fullAttribList, tempList + tempList2)
433
434
435    # save projection (xAttr, yAttr, classVal) into a filename fileName
436    def saveProjectionAsTabData(self, fileName, attrList):
437        orange.saveTabDelimited(fileName, self.createProjectionAsExampleTable([self.attributeNameIndex[i] for i in attrList]))
438
439
440    # ####################################
441    # send 2 example tables. in first is the data that is inside selected rects (polygons), in the second is unselected data
442    def getSelectionsAsExampleTables(self, attrList, addProjectedPositions = 0):
443        if not self.haveData: return (None, None)
444        if addProjectedPositions == 0 and not self.selectionCurveList: return (None, self.rawData)       # if no selections exist
445
446        xAttr = orange.FloatVariable("X Positions")
447        yAttr = orange.FloatVariable("Y Positions")
448        if addProjectedPositions == 1:
449            domain=orange.Domain([xAttr,yAttr] + [v for v in self.dataDomain.variables])
450        elif addProjectedPositions == 2:
451            domain=orange.Domain(self.dataDomain)
452            domain.addmeta(orange.newmetaid(), xAttr)
453            domain.addmeta(orange.newmetaid(), yAttr)
454        else:
455            domain = orange.Domain(self.dataDomain)
456
457        domain.addmetas(self.dataDomain.getmetas())
458
459        attrIndices = [self.attributeNameIndex[attr] for attr in attrList]
460        validData = self.getValidList(attrIndices)
461
462        array = self.createProjectionAsNumericArray(attrIndices, validData = validData, scaleFactor = self.scaleFactor, removeMissingData = 0)
463        if array == None:       # if all examples have missing values
464            return (None, None)
465
466        #selIndices, unselIndices = self.getSelectionsAsIndices(attrList, validData)
467        selIndices, unselIndices = self.getSelectedPoints(array.T[0], array.T[1], validData)
468
469        if addProjectedPositions:
470            selected = orange.ExampleTable(domain, self.rawData.selectref(selIndices))
471            unselected = orange.ExampleTable(domain, self.rawData.selectref(unselIndices))
472            selIndex = 0; unselIndex = 0
473            for i in range(len(selIndices)):
474                if selIndices[i]:
475                    selected[selIndex][xAttr] = array[i][0]
476                    selected[selIndex][yAttr] = array[i][1]
477                    selIndex += 1
478                else:
479                    unselected[unselIndex][xAttr] = array[i][0]
480                    unselected[unselIndex][yAttr] = array[i][1]
481                    unselIndex += 1
482        else:
483            selected = self.rawData.selectref(selIndices)
484            unselected = self.rawData.selectref(unselIndices)
485
486        if len(selected) == 0: selected = None
487        if len(unselected) == 0: unselected = None
488        return (selected, unselected)
489
490
491    def getSelectionsAsIndices(self, attrList, validData = None):
492        if not self.haveData: return [], []
493
494        attrIndices = [self.attributeNameIndex[attr] for attr in attrList]
495        if validData == None:
496            validData = self.getValidList(attrIndices)
497
498        array = self.createProjectionAsNumericArray(attrIndices, validData = validData, scaleFactor = self.scaleFactor, removeMissingData = 0)
499        if array == None:
500            return [], []
501        array = numpy.transpose(array)
502        return self.getSelectedPoints(array[0], array[1], validData)
503
504
505
506if __name__== "__main__":
507    #Draw a simple graph
508    a = QApplication(sys.argv)
509    c = OWPolyvizGraph()
510
511    a.setMainWidget(c)
512    c.show()
513    a.exec_()
Note: See TracBrowser for help on using the repository browser.