source: orange/orange/OrangeWidgets/Prototypes/OWTimeDataVisualizer.py @ 5822:ea533518f12d

Revision 5822:ea533518f12d, 14.5 KB checked in by gregor <gregor@…>, 5 years ago (diff)
Line 
1"""
2<name>Time Data Visualizer</name>
3<description>Visualization of time data.</description>
4<contact>Gregor Leban (gregor.leban@fri.uni-lj.si)</contact>
5<icon>icons/ScatterPlot.png</icon>
6<priority>3300</priority>
7"""
8# Time Data Visualizer.py
9#
10# Show mulitple line visualizations
11#
12from OWWidget import *
13from OWTimeDataVisualizerGraph import *
14import OWGUI, OWToolbars, OWColorPalette
15from orngScaleData import *
16from OWGraph import OWGraph
17
18
19###########################################################################################
20##### WIDGET : Scatterplot visualization
21###########################################################################################
22class OWTimeDataVisualizer(OWWidget):
23    settingsList = ["graph.pointWidth", "graph.showXaxisTitle",
24                    "graph.showLegend", "graph.useAntialiasing", 'graph.drawPoints', 'graph.drawLines',
25                    "graph.alphaValue", "autoSendSelection", "toolbarSelection", "graph.trackExamples"
26                    "colorSettings", "selectedSchemaIndex"]
27    contextHandlers = {"": DomainContextHandler("", ["graph.timeAttr", "graph.attributes", "graph.shownAttributeIndices"], loadImperfect = 0)}
28
29    def __init__(self, parent=None, signalManager = None):
30        OWWidget.__init__(self, parent, signalManager, "Time Data Visualizer", TRUE)
31
32        self.inputs =  [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute selection", AttributeList, self.setShownAttributes)]
33        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)]
34
35        # local variables
36        self.autoSendSelection = 1
37        self.toolbarSelection = 0
38        self.colorSettings = None
39        self.selectedSchemaIndex = 0
40
41        self.graph = OWTimeDataVisualizerGraph(self, self.mainArea, "Time Data Visualizer")
42
43        self.data = None
44        self.subsetData = None
45
46        #load settings
47        self.loadSettings()
48
49        #GUI
50        self.tabs = OWGUI.tabWidget(self.controlArea)
51        self.GeneralTab = OWGUI.createTabPage(self.tabs, "Main")
52        self.SettingsTab = OWGUI.createTabPage(self.tabs, "Settings")
53
54        #add a graph widget
55        self.mainArea.layout().addWidget(self.graph)
56        self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile)
57
58        #x attribute
59        self.attrX = ""
60        box = OWGUI.widgetBox(self.GeneralTab, "Time Attribute")
61        # add an option to use the index of the example as time stamp
62        #OWGUI.checkBox(box, self, 'graph.use', 'X axis title', callback = self.graph.setShowXaxisTitle)
63        self.timeCombo = OWGUI.comboBox(box, self, "graph.timeAttr", callback = self.majorUpdateGraph, sendSelectedValue = 1, valueType = str)
64
65        self.colorCombo = OWGUI.comboBox(self.GeneralTab, self, "graph.colorAttr", "Point Color", callback = self.updateGraph, sendSelectedValue = 1, valueType = str)
66
67        # y attributes
68        box = OWGUI.widgetBox(self.GeneralTab, "Visualized attributes")
69        OWGUI.listBox(box, self, "graph.shownAttributeIndices", "graph.attributes", selectionMode = QListWidget.ExtendedSelection, sizeHint = QSize(150, 250))
70        OWGUI.button(box, self, "Update listbox changes", callback = self.majorUpdateGraph)
71
72
73        # zooming / selection
74        self.zoomSelectToolbar = OWToolbars.ZoomSelectToolbar(self, self.GeneralTab, self.graph, self.autoSendSelection)
75        self.connect(self.zoomSelectToolbar.buttonSendSelections, SIGNAL("clicked()"), self.sendSelections)
76
77        # ####################################
78        # SETTINGS TAB
79        # point width
80        pointBox = OWGUI.widgetBox(self.SettingsTab, "Point properties")
81        OWGUI.hSlider(pointBox, self, 'graph.pointWidth', label = "Symbol size:   ", minValue=1, maxValue=10, step=1, callback = self.pointSizeChange)
82        OWGUI.hSlider(pointBox, self, 'graph.alphaValue', label = "Transparency: ", minValue=0, maxValue=255, step=10, callback = self.alphaChange)
83
84        # general graph settings
85        box4 = OWGUI.widgetBox(self.SettingsTab, "General graph settings")
86        OWGUI.checkBox(box4, self, 'graph.drawLines', 'Draw lines', callback = self.updateGraph)
87        OWGUI.checkBox(box4, self, 'graph.drawPoints', 'Draw points (slower)', callback = self.updateGraph)
88        OWGUI.checkBox(box4, self, 'graph.trackExamples', 'Track examples', callback = self.updateGraph)
89        OWGUI.checkBox(box4, self, 'graph.showGrayRects', 'Show gray rectangles', callback = self.updateGraph)
90        OWGUI.checkBox(box4, self, 'graph.showXaxisTitle', 'Show x axis title', callback = self.graph.setShowXaxisTitle)
91        OWGUI.checkBox(box4, self, 'graph.showLegend', 'Show legend', callback = self.updateGraph)
92        OWGUI.checkBox(box4, self, 'graph.useAntialiasing', 'Use antialiasing', callback = self.antialiasingChange)
93
94        self.colorButtonsBox = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal")
95        OWGUI.button(self.colorButtonsBox, self, "Set Colors", self.setColors, tooltip = "Set the canvas background color, grid color and color palette for coloring continuous variables", debuggingEnabled = 0)
96
97        box5 = OWGUI.widgetBox(self.SettingsTab, "Tooltips settings")
98        OWGUI.comboBox(box5, self, "graph.tooltipKind", items = ["Don't Show Tooltips", "Show Visible Attributes", "Show All Attributes"], callback = self.updateGraph)
99
100        OWGUI.checkBox(self.SettingsTab, self, 'autoSendSelection', 'Auto send selected data', box = "Data selection", callback = self.setAutoSendSelection, tooltip = "Send signals with selected data whenever the selection changes")
101        self.graph.selectionChangedCallback = self.setAutoSendSelection
102
103        OWGUI.rubber(self.GeneralTab)
104        OWGUI.rubber(self.SettingsTab)
105        self.icons = self.createAttributeIconDict()
106
107        self.activateLoadedSettings()
108        self.resize(700, 550)
109
110
111    def activateLoadedSettings(self):
112        dlg = self.createColorDialog()
113        self.graph.contPalette = dlg.getContinuousPalette("contPalette")
114        self.graph.discPalette = dlg.getDiscretePalette("discPalette")
115        self.graph.setCanvasBackground(dlg.getColor("Canvas"))
116
117        apply([self.zoomSelectToolbar.actionZooming, self.zoomSelectToolbar.actionRectangleSelection, self.zoomSelectToolbar.actionPolygonSelection][self.toolbarSelection], [])
118
119    def settingsFromWidgetCallback(self, handler, context):
120        context.selectionPolygons = []
121        for curve in self.graph.selectionCurveList:
122            xs = [curve.x(i) for i in range(curve.dataSize())]
123            ys = [curve.y(i) for i in range(curve.dataSize())]
124            context.selectionPolygons.append((xs, ys))
125
126    def settingsToWidgetCallback(self, handler, context):
127        selections = getattr(context, "selectionPolygons", [])
128        for (xs, ys) in selections:
129            c = SelectionCurve("")
130            c.setData(xs,ys)
131            c.attach(self.graph)
132            self.graph.selectionCurveList.append(c)
133
134    # ##############################################################################################################################################################
135    # SCATTERPLOT SIGNALS
136    # ##############################################################################################################################################################
137
138    def resetGraphData(self):
139        self.graph.rescaleData()
140        self.majorUpdateGraph()
141
142    # receive new data and update all fields
143    def setData(self, data, onlyDataSubset = 0):
144        if data and (len(data) == 0 or len(data.domain) == 0):
145            data = None
146        if self.data != None and data != None and self.data.checksum() == data.checksum():
147            return    # check if the new data set is the same as the old one
148
149        self.closeContext()
150        sameDomain = self.data and data and data.domain.checksum() == self.data.domain.checksum() # preserve attribute choice if the domain is the same
151
152        self.data = data
153        if not sameDomain:
154            self.initAttrValues()
155
156        self.openContext("", data)
157
158
159    # set an example table with a data subset subset of the data. if called by a visual classifier, the update parameter will be 0
160    def setSubsetData(self, data):
161        if self.subsetData != None and data != None and self.subsetData.checksum() == data.checksum():
162            return    # check if the new data set is the same as the old one
163
164        try:
165            subsetData = data.select(self.data.domain)
166            self.warning(10)
167        except:
168            subsetData = None
169            self.warning(10, data and "'Examples' and 'Example Subset' data do not have compatible domains. Unable to draw 'Example Subset' data." or "")
170
171        self.subsetData = subsetData
172
173
174    # this is called by OWBaseWidget after setData and setSubsetData are called. this way the graph is updated only once
175    def handleNewSignals(self):
176        self.graph.clear()
177        self.graph.setData(self.data, self.subsetData)
178        self.majorUpdateGraph()
179        self.sendSelections()
180
181
182    # receive information about which attributes we want to show on x and y axis
183    def setShownAttributes(self, list):
184        if not self.data or not list: return
185        self.graph.shownAttributeIndices = [i for i in range(len(self.data.domain)) if self.data.domain[i].name in list]
186        self.majorUpdateGraph()
187
188
189    # send signals with selected and unselected examples as two datasets
190    def sendSelections(self):
191        pass
192#        (selected, unselected) = self.graph.getSelectionsAsExampleTables([self.attrX, self.attrY])
193#        self.send("Selected Examples",selected)
194#        self.send("Unselected Examples",unselected)
195
196
197    # ##############################################################################################################################################################
198    # ATTRIBUTE SELECTION
199    # ##############################################################################################################################################################
200
201    def initAttrValues(self):
202        self.graph.attributes = []
203        self.graph.shownAttributeIndices = []
204        self.timeCombo.clear()
205        self.colorCombo.clear()
206        self.graph.timeAttr = None
207        self.graph.colorAttr = None
208        self.colorCombo.addItem("(Same color)")
209
210        if self.data == None: return
211
212        domain = self.data.domain
213        for attr in domain:
214            self.timeCombo.addItem(self.icons[attr.varType], attr.name)
215            self.colorCombo.addItem(self.icons[attr.varType], attr.name)
216        self.graph.attributes = [(domain[a].name, domain[a].varType) for a in domain]
217        self.graph.shownAttributeIndices = range(min(10, len(self.graph.attributes)))
218        self.graph.timeAttr = domain[0].name
219        self.graph.colorAttr = "(Same color)"
220
221
222    def majorUpdateGraph(self):
223        self.graph.zoomStack = []
224        self.graph.removeAllSelections()
225        self.updateGraph(setScale = 1)
226
227    def updateGraph(self, **args):
228        if not self.data:
229            return
230
231        self.graph.updateData(**args)
232
233
234    # ##############################################################################################################################################################
235    # SCATTERPLOT SETTINGS
236    # ##############################################################################################################################################################
237
238    def pointSizeChange(self):
239        for curve in self.graph.itemList():
240            if type(curve) == QwtPlotCurve:
241                curve.symbol().setSize(self.graph.pointWidth)
242        self.graph.replot()
243
244    def alphaChange(self):
245        for curve in self.graph.itemList():
246            if type(curve) == QwtPlotCurve:
247                brushColor = curve.symbol().brush().color()
248                penColor = curve.symbol().pen().color()
249                penColor2 = curve.pen().color()
250                brushColor.setAlpha(self.graph.alphaValue)
251                penColor.setAlpha(self.graph.alphaValue)
252                penColor2.setAlpha(self.graph.alphaValue)
253                curve.symbol().setBrush(QBrush(brushColor))
254                curve.symbol().setPen(QPen(penColor))
255                curve.setPen(QPen(penColor2))
256        self.graph.replot()
257
258
259    def antialiasingChange(self):
260        for curve in self.graph.itemList():
261            if type(curve) == QwtPlotCurve:
262                curve.setRenderHint(QwtPlotItem.RenderAntialiased, self.graph.useAntialiasing)
263        self.graph.replot()
264
265    def setAutoSendSelection(self):
266        if self.autoSendSelection:
267            self.zoomSelectToolbar.buttonSendSelections.setEnabled(0)
268            self.sendSelections()
269        else:
270            self.zoomSelectToolbar.buttonSendSelections.setEnabled(1)
271
272    def setColors(self):
273        dlg = self.createColorDialog()
274        if dlg.exec_():
275            self.colorSettings = dlg.getColorSchemas()
276            self.selectedSchemaIndex = dlg.selectedSchemaIndex
277            self.graph.contPalette = dlg.getContinuousPalette("contPalette")
278            self.graph.discPalette = dlg.getDiscretePalette("discPalette")
279            self.graph.setCanvasBackground(dlg.getColor("Canvas"))
280            self.graph.setGridColor(QPen(dlg.getColor("Grid")))
281            self.updateGraph()
282
283    def createColorDialog(self):
284        c = OWColorPalette.ColorPaletteDlg(self, "Color palette")
285        c.createDiscretePalette("discPalette", "Discrete Palette")
286        c.createContinuousPalette("contPalette", "Continuous Palette")
287        box = c.createBox("otherColors", "Other Colors")
288        c.createColorButton(box, "Canvas", "Canvas color", Qt.white)
289        box.layout().addSpacing(5)
290        c.createColorButton(box, "Grid", "Grid color", Qt.black)
291        box.layout().addSpacing(5)
292        #box.adjustSize()
293        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex)
294        return c
295
296    def closeEvent(self, ce):
297        OWWidget.closeEvent(self, ce)
298
299    def sendReport(self):
300        self.reportSettings("",
301                            [("Time attribute", self.graph.timeAttr),
302                             self.graph.colorAttr != "(Same color)" and ("Color", self.graph.colorAttr)])
303        self.reportRaw("<br/>")
304        self.reportImage(self.graph.saveToFileDirect, QSize(400, 400))
305
306#test widget appearance
307if __name__=="__main__":
308    a=QApplication(sys.argv)
309    ow=OWScatterPlot()
310    ow.show()
311    ow.setData(orange.ExampleTable(r"E:\Development\Orange Datasets\UCI\wine.tab"))
312    #ow.setData(orange.ExampleTable("..\\..\\doc\\datasets\\wine.tab"))
313    ow.handleNewSignals()
314    a.exec_()
315    #save settings
316    ow.saveSettings()
Note: See TracBrowser for help on using the repository browser.