| 1 | """ |
|---|
| 2 | <name>Linear Projection</name> |
|---|
| 3 | <description>Create a linear projection.</description> |
|---|
| 4 | <contact>Gregor Leban (gregor.leban@fri.uni-lj.si)</contact> |
|---|
| 5 | <icon>icons/LinearProjection.png</icon> |
|---|
| 6 | <priority>2000</priority> |
|---|
| 7 | """ |
|---|
| 8 | # LinProj.py |
|---|
| 9 | # |
|---|
| 10 | # Show a linear projection of the data |
|---|
| 11 | # |
|---|
| 12 | |
|---|
| 13 | from OWVisWidget import * |
|---|
| 14 | from OWLinProjGraph import * |
|---|
| 15 | from OWkNNOptimization import OWVizRank |
|---|
| 16 | ##from OWClusterOptimization import * |
|---|
| 17 | from OWFreeVizOptimization import * |
|---|
| 18 | import OWToolbars, OWGUI, orngTest |
|---|
| 19 | import orngVisFuncts, OWDlgs |
|---|
| 20 | import orngVizRank |
|---|
| 21 | |
|---|
| 22 | ########################################################################################### |
|---|
| 23 | ##### WIDGET : Linear Projection |
|---|
| 24 | ########################################################################################### |
|---|
| 25 | class OWLinProj(OWVisWidget): |
|---|
| 26 | settingsList = ["graph.pointWidth", "graph.jitterSize", "graph.globalValueScaling", "graph.showFilledSymbols", "graph.scaleFactor", |
|---|
| 27 | "graph.showLegend", "graph.useDifferentSymbols", "autoSendSelection", "graph.useDifferentColors", |
|---|
| 28 | "graph.tooltipKind", "graph.tooltipValue", "toolbarSelection", |
|---|
| 29 | "showProbabilitiesDetails", "graph.showProbabilities", "graph.squareGranularity", "graph.spaceBetweenCells", |
|---|
| 30 | "valueScalingType", "showAllAttributes", "colorSettings", "selectedSchemaIndex", "addProjectedPositions"] |
|---|
| 31 | jitterSizeNums = [0.0, 0.01, 0.1, 0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20] |
|---|
| 32 | jitterSizeList = [str(x) for x in jitterSizeNums] |
|---|
| 33 | |
|---|
| 34 | contextHandlers = {"": DomainContextHandler("", [ContextField("shownAttributes", DomainContextHandler.RequiredList, selected="selectedShown", reservoir="hiddenAttributes")])} |
|---|
| 35 | |
|---|
| 36 | def __init__(self,parent=None, signalManager = None, name = "Linear Projection", graphClass = None): |
|---|
| 37 | OWVisWidget.__init__(self, parent, signalManager, name, TRUE) |
|---|
| 38 | |
|---|
| 39 | self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setShownAttributes), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] |
|---|
| 40 | self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList), ("FreeViz Learner", orange.Learner)] |
|---|
| 41 | |
|---|
| 42 | # local variables |
|---|
| 43 | self.showAllAttributes = 0 |
|---|
| 44 | self.valueScalingType = 0 |
|---|
| 45 | self.autoSendSelection = 1 |
|---|
| 46 | self.data = None |
|---|
| 47 | self.unprocessedSubsetData = None |
|---|
| 48 | self.toolbarSelection = 0 |
|---|
| 49 | self.classificationResults = None |
|---|
| 50 | self.outlierValues = None |
|---|
| 51 | self.attributeSelectionList = None |
|---|
| 52 | self.colorSettings = None |
|---|
| 53 | self.selectedSchemaIndex = 0 |
|---|
| 54 | self.addProjectedPositions = 0 |
|---|
| 55 | self.resetAnchors = 0 |
|---|
| 56 | |
|---|
| 57 | self.showProbabilitiesDetails = 0 |
|---|
| 58 | self.boxGeneral = 1 |
|---|
| 59 | |
|---|
| 60 | #add a graph widget |
|---|
| 61 | self.box = QVBoxLayout(self.mainArea) |
|---|
| 62 | if graphClass: |
|---|
| 63 | self.graph = graphClass(self, self.mainArea, name) |
|---|
| 64 | else: |
|---|
| 65 | self.graph = OWLinProjGraph(self, self.mainArea, name) |
|---|
| 66 | self.box.addWidget(self.graph) |
|---|
| 67 | |
|---|
| 68 | # graph variables |
|---|
| 69 | self.graph.manualPositioning = 0 |
|---|
| 70 | self.graph.hideRadius = 0 |
|---|
| 71 | ## self.graph.showClusters = 0 |
|---|
| 72 | self.graph.showAnchors = 1 |
|---|
| 73 | self.graph.jitterContinuous = 0 |
|---|
| 74 | self.graph.showProbabilities = 0 |
|---|
| 75 | self.graph.useDifferentSymbols = 0 |
|---|
| 76 | self.graph.useDifferentColors = 1 |
|---|
| 77 | self.graph.tooltipKind = 0 |
|---|
| 78 | self.graph.tooltipValue = 0 |
|---|
| 79 | self.graph.scaleFactor = 1.0 |
|---|
| 80 | self.graph.squareGranularity = 3 |
|---|
| 81 | self.graph.spaceBetweenCells = 1 |
|---|
| 82 | self.graph.showAxisScale = 0 |
|---|
| 83 | |
|---|
| 84 | #load settings |
|---|
| 85 | self.loadSettings() |
|---|
| 86 | |
|---|
| 87 | ## # cluster dialog |
|---|
| 88 | ## self.clusterDlg = ClusterOptimization(self, self.signalManager, self.graph, name) |
|---|
| 89 | ## self.graph.clusterOptimization = self.clusterDlg |
|---|
| 90 | |
|---|
| 91 | # freeviz dialog |
|---|
| 92 | self.freeVizDlg = FreeVizOptimization(self, self.signalManager, self.graph, name) |
|---|
| 93 | if name.lower() == "linear projection": |
|---|
| 94 | self.freeVizLearner = FreeVizLearner(self.freeVizDlg) |
|---|
| 95 | self.send("FreeViz Learner", self.freeVizLearner) |
|---|
| 96 | |
|---|
| 97 | # optimization dialog |
|---|
| 98 | if name.lower() == "radviz": |
|---|
| 99 | self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.RADVIZ, name) |
|---|
| 100 | self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFile) |
|---|
| 101 | elif name.lower() == "polyviz": |
|---|
| 102 | self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.POLYVIZ, name) |
|---|
| 103 | self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile) |
|---|
| 104 | else: |
|---|
| 105 | self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.LINEAR_PROJECTION, name) |
|---|
| 106 | self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFile) |
|---|
| 107 | |
|---|
| 108 | self.optimizationDlg = self.vizrank # for backward compatibility |
|---|
| 109 | |
|---|
| 110 | self.graph.normalizeExamples = (name.lower() == "radviz") # ignore settings!! if we have radviz then normalize, otherwise not. |
|---|
| 111 | |
|---|
| 112 | #GUI |
|---|
| 113 | # add a settings dialog and initialize its values |
|---|
| 114 | self.tabs = QTabWidget(self.space, 'tabWidget') |
|---|
| 115 | self.GeneralTab = QVGroupBox(self) |
|---|
| 116 | #self.GeneralTab.setFrameShape(QFrame.NoFrame) |
|---|
| 117 | self.SettingsTab = QVGroupBox(self) |
|---|
| 118 | self.tabs.insertTab(self.GeneralTab, "Main") |
|---|
| 119 | self.tabs.insertTab(self.SettingsTab, "Settings") |
|---|
| 120 | |
|---|
| 121 | #add controls to self.controlArea widget |
|---|
| 122 | self.createShowHiddenLists(self.GeneralTab, callback = self.updateGraphAndAnchors) |
|---|
| 123 | |
|---|
| 124 | self.optimizationButtons = OWGUI.widgetBox(self.GeneralTab, "Optimization Dialogs", orientation = "horizontal") |
|---|
| 125 | self.vizrankButton = OWGUI.button(self.optimizationButtons, self, "VizRank", callback = self.vizrank.reshow, tooltip = "Opens VizRank dialog, where you can search for interesting projections with different subsets of attributes.", debuggingEnabled = 0) |
|---|
| 126 | self.freeVizDlgButton = OWGUI.button(self.optimizationButtons, self, "FreeViz", callback = self.freeVizDlg.reshow, tooltip = "Opens FreeViz dialog, where the position of attribute anchors is optimized so that class separation is improved", debuggingEnabled = 0) |
|---|
| 127 | ## self.clusterDetectionDlgButton = OWGUI.button(self.optimizationButtons, self, "Cluster", callback = self.clusterDlg.reshow, debuggingEnabled = 0) |
|---|
| 128 | ## self.vizrankButton.setMaximumWidth(63) |
|---|
| 129 | ## self.clusterDetectionDlgButton.setMaximumWidth(63) |
|---|
| 130 | ## self.freeVizDlgButton.setMaximumWidth(63) |
|---|
| 131 | ## self.connect(self.clusterDlg.startOptimizationButton , SIGNAL("clicked()"), self.optimizeClusters) |
|---|
| 132 | ## self.connect(self.clusterDlg.resultList, SIGNAL("selectionChanged()"),self.showSelectedCluster) |
|---|
| 133 | |
|---|
| 134 | self.zoomSelectToolbar = OWToolbars.ZoomSelectToolbar(self, self.GeneralTab, self.graph, self.autoSendSelection) |
|---|
| 135 | self.graph.selectionChangedCallback = self.selectionChanged |
|---|
| 136 | self.connect(self.zoomSelectToolbar.buttonSendSelections, SIGNAL("clicked()"), self.sendSelections) |
|---|
| 137 | |
|---|
| 138 | # #################################### |
|---|
| 139 | # SETTINGS TAB |
|---|
| 140 | # ##### |
|---|
| 141 | self.extraTopBox = OWGUI.widgetBox(self.SettingsTab, orientation = "vertical") |
|---|
| 142 | self.extraTopBox.hide() |
|---|
| 143 | OWGUI.hSlider(self.SettingsTab, self, 'graph.pointWidth', box=' Point Size ', minValue=1, maxValue=15, step=1, callback = self.updateGraph) |
|---|
| 144 | |
|---|
| 145 | box = OWGUI.widgetBox(self.SettingsTab, "Jittering Options") |
|---|
| 146 | box2 = OWGUI.widgetBox(self.SettingsTab, "Scaling Options") |
|---|
| 147 | box3 = OWGUI.collapsableWidgetBox(self.SettingsTab, "General Graph Settings", self, "boxGeneral") |
|---|
| 148 | box8 = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal") |
|---|
| 149 | box9 = OWGUI.widgetBox(self.SettingsTab, "Tooltips Settings") |
|---|
| 150 | box10 = OWGUI.widgetBox(self.SettingsTab, "Sending Selection") |
|---|
| 151 | |
|---|
| 152 | OWGUI.comboBox(box9, self, "graph.tooltipKind", items = ["Show line tooltips", "Show visible attributes", "Show all attributes"], callback = self.updateGraph) |
|---|
| 153 | OWGUI.comboBox(box9, self, "graph.tooltipValue", items = ["Tooltips show data values", "Tooltips show spring values"], callback = self.updateGraph, tooltip = "Do you wish that tooltips would show you original values of visualized attributes or the 'spring' values (values between 0 and 1). \nSpring values are scaled values that are used for determining the position of shown points. Observing these values will therefore enable you to \nunderstand why the points are placed where they are.") |
|---|
| 154 | |
|---|
| 155 | OWGUI.checkBox(box10, self, 'autoSendSelection', 'Auto send selected/unselected data', callback = self.selectionChanged, tooltip = "Send signals with selected data whenever the selection changes.") |
|---|
| 156 | OWGUI.comboBox(box10, self, "addProjectedPositions", items = ["Do not modify the domain", "Append projection as attributes", "Append projection as meta attributes"], callback = self.sendSelections) |
|---|
| 157 | self.selectionChanged() |
|---|
| 158 | |
|---|
| 159 | # this is needed so that the tabs are wide enough! |
|---|
| 160 | self.safeProcessEvents() |
|---|
| 161 | self.tabs.updateGeometry() |
|---|
| 162 | |
|---|
| 163 | OWGUI.comboBoxWithCaption(box, self, "graph.jitterSize", 'Jittering size (% of range): ', callback = self.resetGraphData, items = self.jitterSizeNums, sendSelectedValue = 1, valueType = float) |
|---|
| 164 | OWGUI.checkBox(box, self, 'graph.jitterContinuous', 'Jitter continuous attributes', callback = self.resetGraphData, tooltip = "Does jittering apply also on continuous attributes?") |
|---|
| 165 | |
|---|
| 166 | OWGUI.qwtHSlider(box2, self, "graph.scaleFactor", minValue=1.0, maxValue= 10.0, step=0.1, label ='Inflate points by: ', callback = self.updateGraph, tooltip="If points lie too much together you can expand their position to improve perception") |
|---|
| 167 | valueScalingList = ["attribute range", "global range", "attribute variance"] |
|---|
| 168 | if name.lower() in ["radviz", "polyviz"]: |
|---|
| 169 | valueScalingList.pop(); self.valueScalingType = min(self.valueScalingType, 1) |
|---|
| 170 | OWGUI.comboBoxWithCaption(box2, self, "valueScalingType", 'Scale values by: ', callback = self.setValueScaling, items = valueScalingList) |
|---|
| 171 | |
|---|
| 172 | #OWGUI.checkBox(box3, self, 'graph.normalizeExamples', 'Normalize examples', callback = self.updateGraph) |
|---|
| 173 | OWGUI.checkBox(box3, self, 'graph.showLegend', 'Show legend', callback = self.updateGraph) |
|---|
| 174 | OWGUI.checkBox(box3, self, 'graph.useDifferentSymbols', 'Use different symbols', callback = self.updateGraph, tooltip = "Show different class values using different symbols") |
|---|
| 175 | OWGUI.checkBox(box3, self, 'graph.useDifferentColors', 'Use different colors', callback = self.updateGraph, tooltip = "Show different class values using different colors") |
|---|
| 176 | OWGUI.checkBox(box3, self, 'graph.showFilledSymbols', 'Show filled symbols', callback = self.updateGraph) |
|---|
| 177 | ## OWGUI.checkBox(box3, self, 'graph.showClusters', 'Show clusters', callback = self.updateGraph, tooltip = "Show a line boundary around a significant cluster") |
|---|
| 178 | |
|---|
| 179 | box5 = OWGUI.widgetBox(box3, orientation = "horizontal") |
|---|
| 180 | box6 = OWGUI.widgetBox(box3, orientation = "horizontal") |
|---|
| 181 | box7 = OWGUI.widgetBox(box3, orientation = "horizontal") |
|---|
| 182 | |
|---|
| 183 | OWGUI.checkBox(box5, self, 'graph.showProbabilities', 'Show probabilities ', callback = self.updateGraph, tooltip = "Show a background image with class probabilities") |
|---|
| 184 | hider = OWGUI.widgetHider(box5, self, "showProbabilitiesDetails", tooltip = "Show/hide extra settings") |
|---|
| 185 | rubb = OWGUI.rubber(box5) |
|---|
| 186 | rubb.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum)) |
|---|
| 187 | |
|---|
| 188 | OWGUI.separator(box6, width=20) |
|---|
| 189 | OWGUI.label(box6, self, "Granularity: ") |
|---|
| 190 | OWGUI.hSlider(box6, self, 'graph.squareGranularity', minValue=1, maxValue=10, step=1, callback = self.updateGraph) |
|---|
| 191 | |
|---|
| 192 | OWGUI.separator(box7, width=20) |
|---|
| 193 | OWGUI.checkBox(box7, self, 'graph.spaceBetweenCells', 'Show space between cells', callback = self.updateGraph) |
|---|
| 194 | hider.setWidgets([box6, box7]) |
|---|
| 195 | |
|---|
| 196 | OWGUI.button(box8, self, "Set Colors", self.setColors, tooltip = "Set the canvas background color and color palette for coloring continuous variables", debuggingEnabled = 0) |
|---|
| 197 | |
|---|
| 198 | self.icons = self.createAttributeIconDict() |
|---|
| 199 | self.debugSettings = ["hiddenAttributes", "shownAttributes"] |
|---|
| 200 | |
|---|
| 201 | # add a settings dialog and initialize its values |
|---|
| 202 | self.activateLoadedSettings() |
|---|
| 203 | self.setValueScaling() # XXX is there any better way to do this?! |
|---|
| 204 | self.resize(900, 700) |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | def saveToFile(self): |
|---|
| 208 | self.graph.saveToFile([("Save PixTex", self.graph.savePicTeX)]) |
|---|
| 209 | |
|---|
| 210 | def activateLoadedSettings(self): |
|---|
| 211 | dlg = self.createColorDialog() |
|---|
| 212 | self.graph.contPalette = dlg.getContinuousPalette("contPalette") |
|---|
| 213 | self.graph.discPalette = dlg.getDiscretePalette() |
|---|
| 214 | self.graph.setCanvasBackground(dlg.getColor("Canvas")) |
|---|
| 215 | |
|---|
| 216 | apply([self.zoomSelectToolbar.actionZooming, self.zoomSelectToolbar.actionRectangleSelection, self.zoomSelectToolbar.actionPolygonSelection][self.toolbarSelection], []) |
|---|
| 217 | |
|---|
| 218 | self.cbShowAllAttributes() |
|---|
| 219 | self.setValueScaling() |
|---|
| 220 | |
|---|
| 221 | |
|---|
| 222 | # ######################### |
|---|
| 223 | # KNN OPTIMIZATION BUTTON EVENTS |
|---|
| 224 | # ######################### |
|---|
| 225 | def saveCurrentProjection(self): |
|---|
| 226 | qname = QFileDialog.getSaveFileName( os.path.realpath(".") + "/Linear_projection.tab", "Orange Example Table (*.tab)", self, "", "Save File") |
|---|
| 227 | if qname.isEmpty(): return |
|---|
| 228 | name = str(qname) |
|---|
| 229 | if len(name) < 4 or name[-4] != ".": |
|---|
| 230 | name = name + ".tab" |
|---|
| 231 | self.graph.saveProjectionAsTabData(name, self.getShownAttributeList()) |
|---|
| 232 | |
|---|
| 233 | |
|---|
| 234 | ## # ################################################################################################ |
|---|
| 235 | ## # find projections that have tight clusters of points that belong to the same class value |
|---|
| 236 | ## def optimizeClusters(self): |
|---|
| 237 | ## if self.data == None: return |
|---|
| 238 | ## if not self.hasDiscreteClass(self.data): |
|---|
| 239 | ## QMessageBox.critical( None, "Cluster Detection Dialog", 'Clusters can be detected only in data sets with a discrete class value', QMessageBox.Ok) |
|---|
| 240 | ## return |
|---|
| 241 | ## |
|---|
| 242 | ## self.clusterDlg.clearResults() |
|---|
| 243 | ## self.clusterDlg.clusterStabilityButton.setOn(0) |
|---|
| 244 | ## self.clusterDlg.pointStability = None |
|---|
| 245 | ## |
|---|
| 246 | ## try: |
|---|
| 247 | ## listOfAttributes = self.vizrank.getEvaluatedAttributes(self.data) |
|---|
| 248 | ## text = str(self.vizrank.attributeCountCombo.currentText()) |
|---|
| 249 | ## if text == "ALL": maxLen = len(listOfAttributes) |
|---|
| 250 | ## else: maxLen = int(text) |
|---|
| 251 | ## |
|---|
| 252 | ## if self.clusterDlg.getOptimizationType() == self.clusterDlg.EXACT_NUMBER_OF_ATTRS: minLen = maxLen |
|---|
| 253 | ## else: minLen = 3 |
|---|
| 254 | ## |
|---|
| 255 | ## possibilities = 0 |
|---|
| 256 | ## for i in range(minLen, maxLen+1): possibilities += orngVisFuncts.combinationsCount(i, len(listOfAttributes))* orngVisFuncts.fact(i-1)/2 |
|---|
| 257 | ## |
|---|
| 258 | ## self.graph.totalPossibilities = possibilities |
|---|
| 259 | ## self.graph.triedPossibilities = 0 |
|---|
| 260 | ## |
|---|
| 261 | ## if self.graph.totalPossibilities > 20000: |
|---|
| 262 | ## proj = str(self.graph.totalPossibilities) |
|---|
| 263 | ## l = len(proj) |
|---|
| 264 | ## for i in range(len(proj)-2, 0, -1): |
|---|
| 265 | ## if (l-i)%3 == 0: proj = proj[:i] + "," + proj[i:] |
|---|
| 266 | ## self.printEvent("OWLinProj: Warning: There are %s possible projections using currently visualized attributes"% (proj), eventVerbosity = 1) |
|---|
| 267 | ## |
|---|
| 268 | ## self.clusterDlg.disableControls() |
|---|
| 269 | ## |
|---|
| 270 | ## self.graph.getOptimalClusters(listOfAttributes, minLen, maxLen, self.clusterDlg.addResult) |
|---|
| 271 | ## except: |
|---|
| 272 | ## type, val, traceback = sys.exc_info() |
|---|
| 273 | ## sys.excepthook(type, val, traceback) # print the exception |
|---|
| 274 | ## |
|---|
| 275 | ## self.clusterDlg.enableControls() |
|---|
| 276 | ## self.clusterDlg.finishedAddingResults() |
|---|
| 277 | ## self.showSelectedCluster() |
|---|
| 278 | |
|---|
| 279 | |
|---|
| 280 | # send signals with selected and unselected examples as two datasets |
|---|
| 281 | def sendSelections(self): |
|---|
| 282 | if not self.data: return |
|---|
| 283 | (selected, unselected) = self.graph.getSelectionsAsExampleTables(self.getShownAttributeList(), addProjectedPositions = self.addProjectedPositions) |
|---|
| 284 | |
|---|
| 285 | self.send("Selected Examples",selected) |
|---|
| 286 | self.send("Unselected Examples",unselected) |
|---|
| 287 | |
|---|
| 288 | def sendShownAttributes(self): |
|---|
| 289 | self.send("Attribute Selection List", [a[0] for a in self.shownAttributes]) |
|---|
| 290 | |
|---|
| 291 | |
|---|
| 292 | # show selected interesting projection |
|---|
| 293 | def showSelectedAttributes(self): |
|---|
| 294 | val = self.vizrank.getSelectedProjection() |
|---|
| 295 | if val: |
|---|
| 296 | (accuracy, other_results, tableLen, attrList, tryIndex, generalDict) = val |
|---|
| 297 | self.updateGraph(attrList, setAnchors= 1, XAnchors = generalDict.get("XAnchors"), YAnchors = generalDict.get("YAnchors")) |
|---|
| 298 | self.graph.removeAllSelections() |
|---|
| 299 | |
|---|
| 300 | |
|---|
| 301 | ## def showSelectedCluster(self): |
|---|
| 302 | ## val = self.clusterDlg.getSelectedCluster() |
|---|
| 303 | ## if not val: return |
|---|
| 304 | ## (value, closure, vertices, attrList, classValue, enlargedClosure, other, strList) = val |
|---|
| 305 | ## |
|---|
| 306 | ## if self.clusterDlg.clusterStabilityButton.isOn(): |
|---|
| 307 | ## validData = self.graph.getValidList([self.graph.attributeNames.index(attr) for attr in attrList]) |
|---|
| 308 | ## insideColors = (numpy.compress(validData, self.clusterDlg.pointStability), "Point inside a cluster in %.2f%%") |
|---|
| 309 | ## else: insideColors = None |
|---|
| 310 | ## |
|---|
| 311 | ## self.updateGraph(attrList, 1, insideColors, clusterClosure = (closure, enlargedClosure, classValue)) |
|---|
| 312 | ## self.graph.removeAllSelections() |
|---|
| 313 | |
|---|
| 314 | |
|---|
| 315 | def updateGraphAndAnchors(self): |
|---|
| 316 | self.updateGraph(setAnchors = 1) |
|---|
| 317 | |
|---|
| 318 | def updateGraph(self, attrList = None, setAnchors = 0, insideColors = None, clusterClosure = None, **args): |
|---|
| 319 | if not attrList: |
|---|
| 320 | attrList = self.getShownAttributeList() |
|---|
| 321 | else: |
|---|
| 322 | self.setShownAttributeList(self.data, attrList) |
|---|
| 323 | |
|---|
| 324 | self.graph.showKNN = 0 |
|---|
| 325 | if self.hasDiscreteClass(self.data): |
|---|
| 326 | self.graph.showKNN = self.vizrank.showKNNCorrectButton.isOn() and 1 or self.vizrank.showKNNCorrectButton.isOn() and 2 |
|---|
| 327 | |
|---|
| 328 | self.graph.insideColors = insideColors or self.classificationResults or self.outlierValues |
|---|
| 329 | ## self.graph.clusterClosure = clusterClosure |
|---|
| 330 | |
|---|
| 331 | self.graph.updateData(attrList, setAnchors, **args) |
|---|
| 332 | self.graph.repaint() |
|---|
| 333 | |
|---|
| 334 | |
|---|
| 335 | # ############################################################################################################### |
|---|
| 336 | # INPUT SIGNALS |
|---|
| 337 | |
|---|
| 338 | # receive new data and update all fields |
|---|
| 339 | def setData(self, data): |
|---|
| 340 | if data and data.domain.classVar: |
|---|
| 341 | name = getattr(data, "name", "") |
|---|
| 342 | data = data.filterref(orange.Filter_hasClassValue()) |
|---|
| 343 | data.name = name |
|---|
| 344 | if self.data and data and self.data.checksum() == data.checksum(): |
|---|
| 345 | return # check if the new data set is the same as the old one |
|---|
| 346 | |
|---|
| 347 | self.closeContext() |
|---|
| 348 | exData = self.data |
|---|
| 349 | self.data = data |
|---|
| 350 | self.vizrank.setData(data) |
|---|
| 351 | ## self.clusterDlg.setData(data) |
|---|
| 352 | self.freeVizDlg.setData(data) |
|---|
| 353 | self.classificationResults = None |
|---|
| 354 | self.outlierValues = None |
|---|
| 355 | |
|---|
| 356 | sameDomain = self.data and exData and exData.domain.checksum() == self.data.domain.checksum() # preserve attribute choice if the domain is the same |
|---|
| 357 | if not sameDomain: |
|---|
| 358 | self.setShownAttributeList(self.data, self.attributeSelectionList) |
|---|
| 359 | self.resetAnchors += not sameDomain |
|---|
| 360 | |
|---|
| 361 | self.openContext("", data) |
|---|
| 362 | self.resetAttrManipulation() |
|---|
| 363 | |
|---|
| 364 | if data and self.unprocessedSubsetData: # if we first received subset data we now have to call setSubsetData to process it |
|---|
| 365 | self.setSubsetData(self.unprocessedSubsetData) |
|---|
| 366 | self.unprocessedSubsetData = None |
|---|
| 367 | |
|---|
| 368 | |
|---|
| 369 | def setSubsetData(self, data, update = 1): |
|---|
| 370 | if not self.data: |
|---|
| 371 | self.unprocessedSubsetData = data |
|---|
| 372 | self.warning(10) |
|---|
| 373 | return |
|---|
| 374 | |
|---|
| 375 | if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): |
|---|
| 376 | return # check if the new data set is the same as the old one |
|---|
| 377 | |
|---|
| 378 | try: |
|---|
| 379 | subsetData = data.select(self.data.domain) |
|---|
| 380 | self.warning(10) |
|---|
| 381 | except: |
|---|
| 382 | subsetData = None |
|---|
| 383 | self.warning(10, data and "'Examples' and 'Example Subset' data do not have copatible domains. Unable to draw 'Example Subset' data." or "") |
|---|
| 384 | |
|---|
| 385 | self.vizrank.setSubsetData(subsetData) |
|---|
| 386 | # if update: self.updateGraph() |
|---|
| 387 | ## self.clusterDlg.setSubsetData(data) |
|---|
| 388 | # qApp.processEvents() |
|---|
| 389 | |
|---|
| 390 | |
|---|
| 391 | # attribute selection signal - info about which attributes to show |
|---|
| 392 | def setShownAttributes(self, attributeSelectionList): |
|---|
| 393 | self.attributeSelectionList = attributeSelectionList |
|---|
| 394 | if self.data and self.attributeSelectionList: |
|---|
| 395 | for attr in self.attributeSelectionList: |
|---|
| 396 | if not self.graph.attributeNameIndex.has_key(attr): # this attribute list belongs to a new dataset that has not come yet |
|---|
| 397 | return |
|---|
| 398 | |
|---|
| 399 | self.setShownAttributeList(self.data, self.attributeSelectionList) |
|---|
| 400 | self.attributeSelectionList = None |
|---|
| 401 | self.selectionChanged() |
|---|
| 402 | self.resetAnchors += 1 |
|---|
| 403 | |
|---|
| 404 | # visualize the results of the classification |
|---|
| 405 | def setTestResults(self, results): |
|---|
| 406 | self.classificationResults = None |
|---|
| 407 | if isinstance(results, orngTest.ExperimentResults) and len(results.results) > 0 and len(results.results[0].probabilities) > 0: |
|---|
| 408 | self.classificationResults = ([results.results[i].probabilities[0][results.results[i].actualClass] for i in range(len(results.results))], "Probability of correct classificatioin = %.2f%%") |
|---|
| 409 | self.resetAnchors += 1 |
|---|
| 410 | |
|---|
| 411 | |
|---|
| 412 | # set the learning method to be used in VizRank |
|---|
| 413 | def setVizRankLearner(self, learner): |
|---|
| 414 | self.vizrank.externalLearner = learner |
|---|
| 415 | |
|---|
| 416 | # this is called by OWBaseWidget after setData and setSubsetData are called. this way the graph is updated only once |
|---|
| 417 | def handleNewSignals(self): |
|---|
| 418 | self.updateGraph(setAnchors = self.resetAnchors) |
|---|
| 419 | self.sendSelections() |
|---|
| 420 | self.resetAnchors = 0 |
|---|
| 421 | |
|---|
| 422 | # EVENTS |
|---|
| 423 | def resetBmpUpdateValues(self): |
|---|
| 424 | self.graph.potentialsBmp = None |
|---|
| 425 | self.updateGraph() |
|---|
| 426 | |
|---|
| 427 | def resetGraphData(self): |
|---|
| 428 | orngScaleLinProjData.setData(self.graph, self.data) |
|---|
| 429 | #self.graph.setData(self.data) |
|---|
| 430 | self.updateGraph() |
|---|
| 431 | |
|---|
| 432 | def setValueScaling(self): |
|---|
| 433 | self.graph.insideColors = self.graph.clusterClosure = None |
|---|
| 434 | if self.valueScalingType == 0: |
|---|
| 435 | self.graph.globalValueScaling = self.graph.scalingByVariance = 0 |
|---|
| 436 | elif self.valueScalingType == 1: |
|---|
| 437 | self.graph.globalValueScaling = 1 |
|---|
| 438 | self.graph.scalingByVariance = 0 |
|---|
| 439 | else: |
|---|
| 440 | self.graph.globalValueScaling = 0 |
|---|
| 441 | self.graph.scalingByVariance = 1 |
|---|
| 442 | #self.graph.setData(self.data) |
|---|
| 443 | orngScaleLinProjData.setData(self.graph, self.data) |
|---|
| 444 | self.graph.potentialsBmp = None |
|---|
| 445 | self.updateGraph() |
|---|
| 446 | |
|---|
| 447 | |
|---|
| 448 | def selectionChanged(self): |
|---|
| 449 | self.zoomSelectToolbar.buttonSendSelections.setEnabled(not self.autoSendSelection) |
|---|
| 450 | if self.autoSendSelection: |
|---|
| 451 | self.sendSelections() |
|---|
| 452 | |
|---|
| 453 | def setColors(self): |
|---|
| 454 | dlg = self.createColorDialog() |
|---|
| 455 | if dlg.exec_loop(): |
|---|
| 456 | self.colorSettings = dlg.getColorSchemas() |
|---|
| 457 | self.selectedSchemaIndex = dlg.selectedSchemaIndex |
|---|
| 458 | self.graph.contPalette = dlg.getContinuousPalette("contPalette") |
|---|
| 459 | self.graph.discPalette = dlg.getDiscretePalette() |
|---|
| 460 | self.graph.setCanvasBackground(dlg.getColor("Canvas")) |
|---|
| 461 | self.updateGraph() |
|---|
| 462 | |
|---|
| 463 | def createColorDialog(self): |
|---|
| 464 | c = OWDlgs.ColorPalette(self, "Color Palette") |
|---|
| 465 | c.createDiscretePalette(" Discrete Palette ") |
|---|
| 466 | c.createContinuousPalette("contPalette", " Continuous palette ") |
|---|
| 467 | box = c.createBox("otherColors", " Other Colors ") |
|---|
| 468 | c.createColorButton(box, "Canvas", "Canvas color", Qt.white) |
|---|
| 469 | c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) |
|---|
| 470 | box.addSpace(5) |
|---|
| 471 | box.adjustSize() |
|---|
| 472 | return c |
|---|
| 473 | |
|---|
| 474 | def destroy(self, dw = 1, dsw = 1): |
|---|
| 475 | ## self.clusterDlg.hide() |
|---|
| 476 | self.vizrank.hide() |
|---|
| 477 | self.freeVizDlg.hide() |
|---|
| 478 | OWVisWidget.destroy(self, dw, dsw) |
|---|
| 479 | |
|---|
| 480 | |
|---|
| 481 | #test widget appearance |
|---|
| 482 | if __name__=="__main__": |
|---|
| 483 | a=QApplication(sys.argv) |
|---|
| 484 | ow=OWLinProj() |
|---|
| 485 | a.setMainWidget(ow) |
|---|
| 486 | ow.show() |
|---|
| 487 | ow.setData(orange.ExampleTable("..\\..\\doc\\datasets\\zoo")) |
|---|
| 488 | a.exec_loop() |
|---|
| 489 | |
|---|
| 490 | #save settings |
|---|
| 491 | ow.saveSettings() |
|---|