Changeset 3483:c628d1e304b8 in orange


Ignore:
Timestamp:
04/04/07 13:26:55 (7 years ago)
Author:
Gregor <Gregor@…>
Branch:
default
Convert:
a36737a1a66fcbde77113519e76e7a19482b2d19
Message:
  • faster drawing with less curves
  • modified tab names
  • changed signal names and their handler functions
Location:
orange/OrangeWidgets/Visualize
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Visualize/OWDistributions.py

    r3415 r3483  
    404404        self.tabs = QTabWidget(self.space, 'tabWidget') 
    405405        self.GeneralTab = QVGroupBox(self) 
    406         self.SettingsTab = QVGroupBox(self, "Settings") 
    407         self.tabs.insertTab(self.GeneralTab, "General") 
     406        self.SettingsTab = QVGroupBox(self) 
     407        self.tabs.insertTab(self.GeneralTab, "Main") 
    408408        self.tabs.insertTab(self.SettingsTab, "Settings") 
    409409         
  • orange/OrangeWidgets/Visualize/OWLinProj.py

    r3415 r3483  
    99# 
    1010# Show a linear projection of the data 
    11 #  
     11# 
    1212 
    1313from OWVisWidget import * 
     
    2525class OWLinProj(OWVisWidget): 
    2626    settingsList = ["graph.pointWidth", "graph.jitterSize", "graph.globalValueScaling", "graph.showFilledSymbols", "graph.scaleFactor", 
    27                     "graph.showLegend", "graph.optimizedDrawing", "graph.useDifferentSymbols", "autoSendSelection", "graph.useDifferentColors", 
    28                     "graph.tooltipKind", "graph.tooltipValue", "toolbarSelection",  
     27                    "graph.showLegend", "graph.useDifferentSymbols", "autoSendSelection", "graph.useDifferentColors", 
     28                    "graph.tooltipKind", "graph.tooltipValue", "toolbarSelection", 
    2929                    "showProbabilitiesDetails", "graph.showProbabilities", "graph.squareGranularity", "graph.spaceBetweenCells", 
    30                     "valueScalingType", "showAllAttributes", "learnerIndex", "colorSettings", "addProjectedPositions", "VizRankLearnerName"] 
     30                    "valueScalingType", "showAllAttributes", "colorSettings", "selectedSchemaIndex", "addProjectedPositions"] 
    3131    jitterSizeNums = [0.0, 0.01, 0.1, 0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20] 
    3232    jitterSizeList = [str(x) for x in jitterSizeNums] 
    33     scaleFactorNums = [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 15.0] 
    3433 
    3534    contextHandlers = {"": DomainContextHandler("", [ContextField("shownAttributes", DomainContextHandler.RequiredList, selected="selectedShown", reservoir="hiddenAttributes")])} 
    36          
     35 
    3736    def __init__(self,parent=None, signalManager = None, name = "Linear Projection", graphClass = None): 
    3837        OWVisWidget.__init__(self, parent, signalManager, name, TRUE) 
    3938 
    40         self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setAttributeSelection), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] 
    41         self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList), ("Learner", orange.Learner)] 
     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)] 
    4241 
    4342        # local variables 
    44         self.learnersArray = [None, None, None, None]   # VizRank, Cluster, FreeViz, S2N Heuristic Learner 
    4543        self.showAllAttributes = 0 
    4644        self.valueScalingType = 0 
    4745        self.autoSendSelection = 1 
    4846        self.data = None 
     47        self.unprocessedSubsetData = None 
    4948        self.toolbarSelection = 0 
    50         self.VizRankLearnerName = "VizRank (%s)" % name 
    51 ##        self.clusterClassifierName = "Visual cluster classifier (Linear Projection)" 
    5249        self.classificationResults = None 
    5350        self.outlierValues = None 
    5451        self.attributeSelectionList = None 
    55         self.learnerIndex = 0 
    5652        self.colorSettings = None 
     53        self.selectedSchemaIndex = 0 
    5754        self.addProjectedPositions = 0 
     55        self.resetAnchors = 0 
    5856 
    5957        self.showProbabilitiesDetails = 0 
    6058        self.boxGeneral = 1 
    61          
     59 
    6260        #add a graph widget 
    6361        self.box = QVBoxLayout(self.mainArea) 
     
    7573        self.graph.jitterContinuous = 0 
    7674        self.graph.showProbabilities = 0 
    77         self.graph.optimizedDrawing = 1 
    7875        self.graph.useDifferentSymbols = 0 
    7976        self.graph.useDifferentColors = 1 
     
    8380        self.graph.squareGranularity = 3 
    8481        self.graph.spaceBetweenCells = 1 
    85  
    8682        self.graph.showAxisScale = 0 
     83 
     84        #load settings 
     85        self.loadSettings() 
    8786 
    8887##        # cluster dialog 
     
    9190 
    9291        # freeviz dialog 
    93         self.freeVizDlg = FreeVizOptimization(self, self.signalManager, self.graph, name)     
    94          
     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 
    9597        # optimization dialog 
    9698        if name.lower() == "radviz": 
    9799            self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.RADVIZ, name) 
    98             self.learnersArray[0] = VizRankLearner(RADVIZ, self.vizrank, self.graph) 
    99100            self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFile) 
    100101        elif name.lower() == "polyviz": 
    101102            self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.POLYVIZ, name) 
    102             self.learnersArray[0] = VizRankLearner(POLYVIZ, self.vizrank, self.graph) 
    103103            self.connect(self.graphButton, SIGNAL("clicked()"), self.graph.saveToFile) 
    104104        else: 
    105105            self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.LINEAR_PROJECTION, name) 
    106             self.learnersArray[0] = VizRankLearner(LINEAR_PROJECTION, self.vizrank, self.graph) 
    107106            self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFile) 
    108107 
    109108        self.optimizationDlg = self.vizrank  # for backward compatibility 
    110109 
    111         self.learnersArray[2] = FreeVizLearner(self.freeVizDlg) 
    112  
    113         #load settings 
    114         self.loadSettings() 
    115110        self.graph.normalizeExamples = (name.lower() == "radviz")       # ignore settings!! if we have radviz then normalize, otherwise not. 
    116111 
     
    123118        self.tabs.insertTab(self.GeneralTab, "Main") 
    124119        self.tabs.insertTab(self.SettingsTab, "Settings") 
    125   
     120 
    126121        #add controls to self.controlArea widget 
    127122        self.createShowHiddenLists(self.GeneralTab, callback = self.updateGraphAndAnchors) 
     
    138133 
    139134        self.zoomSelectToolbar = OWToolbars.ZoomSelectToolbar(self, self.GeneralTab, self.graph, self.autoSendSelection) 
    140         self.graph.autoSendSelectionCallback = self.selectionChanged 
     135        self.graph.selectionChangedCallback = self.selectionChanged 
    141136        self.connect(self.zoomSelectToolbar.buttonSendSelections, SIGNAL("clicked()"), self.sendSelections) 
    142                                 
     137 
    143138        # #################################### 
    144139        # SETTINGS TAB 
     
    157152        OWGUI.comboBox(box9, self, "graph.tooltipKind", items = ["Show line tooltips", "Show visible attributes", "Show all attributes"], callback = self.updateGraph) 
    158153        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.") 
    159          
     154 
    160155        OWGUI.checkBox(box10, self, 'autoSendSelection', 'Auto send selected/unselected data', callback = self.selectionChanged, tooltip = "Send signals with selected data whenever the selection changes.") 
    161156        OWGUI.comboBox(box10, self, "addProjectedPositions", items = ["Do not modify the domain", "Append projection as attributes", "Append projection as meta attributes"], callback = self.sendSelections) 
    162157        self.selectionChanged() 
    163158 
    164         self.activeLearnerCombo = OWGUI.comboBox(self.SettingsTab, self, "learnerIndex", box = "Set Active Learner", items = ["VizRank Learner", "Cluster Learner", "FreeViz Learner", "S2N Feature Selection Learner"], tooltip = "Select which of the possible learners do you want to send on the widget output.", callback = self.setActiveLearner) 
    165  
    166         # this is needed so that the tabs are wide enough!  
     159        # this is needed so that the tabs are wide enough! 
    167160        self.safeProcessEvents() 
    168         self.tabs.updateGeometry()         
    169          
    170         OWGUI.comboBoxWithCaption(box, self, "graph.jitterSize", 'Jittering size (% of size)  ', callback = self.resetGraphData, items = self.jitterSizeNums, sendSelectedValue = 1, valueType = float) 
     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) 
    171164        OWGUI.checkBox(box, self, 'graph.jitterContinuous', 'Jitter continuous attributes', callback = self.resetGraphData, tooltip = "Does jittering apply also on continuous attributes?") 
    172          
    173         OWGUI.comboBoxWithCaption(box2, self, "graph.scaleFactor", 'Scale point position by: ', callback = self.updateGraph, items = self.scaleFactorNums, sendSelectedValue = 1, valueType = float) 
    174  
     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") 
    175167        valueScalingList = ["attribute range", "global range", "attribute variance"] 
    176168        if name.lower() in ["radviz", "polyviz"]: 
    177169            valueScalingList.pop(); self.valueScalingType = min(self.valueScalingType, 1) 
    178170        OWGUI.comboBoxWithCaption(box2, self, "valueScalingType", 'Scale values by: ', callback = self.setValueScaling, items = valueScalingList) 
    179          
     171 
    180172        #OWGUI.checkBox(box3, self, 'graph.normalizeExamples', 'Normalize examples', callback = self.updateGraph) 
    181173        OWGUI.checkBox(box3, self, 'graph.showLegend', 'Show legend', callback = self.updateGraph) 
    182         OWGUI.checkBox(box3, self, 'graph.optimizedDrawing', 'Optimize drawing', callback = self.updateGraph, tooltip = "Speed up drawing by drawing all point belonging to one class value at once") 
    183174        OWGUI.checkBox(box3, self, 'graph.useDifferentSymbols', 'Use different symbols', callback = self.updateGraph, tooltip = "Show different class values using different symbols") 
    184175        OWGUI.checkBox(box3, self, 'graph.useDifferentColors', 'Use different colors', callback = self.updateGraph, tooltip = "Show different class values using different colors") 
     
    189180        box6 = OWGUI.widgetBox(box3, orientation = "horizontal") 
    190181        box7 = OWGUI.widgetBox(box3, orientation = "horizontal") 
    191          
     182 
    192183        OWGUI.checkBox(box5, self, 'graph.showProbabilities', 'Show probabilities  ', callback = self.updateGraph, tooltip = "Show a background image with class probabilities") 
    193184        hider = OWGUI.widgetHider(box5, self, "showProbabilitiesDetails", tooltip = "Show/hide extra settings") 
    194185        rubb = OWGUI.rubber(box5) 
    195186        rubb.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Maximum)) 
    196          
     187 
    197188        OWGUI.separator(box6, width=20) 
    198189        OWGUI.label(box6, self, "Granularity:  ") 
     
    212203        self.setValueScaling() # XXX is there any better way to do this?! 
    213204        self.resize(900, 700) 
    214          
     205 
    215206 
    216207    def saveToFile(self): 
     
    222213        self.graph.discPalette = dlg.getDiscretePalette() 
    223214        self.graph.setCanvasBackground(dlg.getColor("Canvas")) 
    224          
     215 
    225216        apply([self.zoomSelectToolbar.actionZooming, self.zoomSelectToolbar.actionRectangleSelection, self.zoomSelectToolbar.actionPolygonSelection][self.toolbarSelection], []) 
    226217 
    227 ##        self.clusterDlg.changeLearnerName(self.clusterClassifierName) 
    228          
    229218        self.cbShowAllAttributes() 
    230         self.setActiveLearner() 
    231219        self.setValueScaling() 
    232          
     220 
    233221 
    234222    # ######################### 
     
    261249##            if text == "ALL": maxLen = len(listOfAttributes) 
    262250##            else:             maxLen = int(text) 
    263 ##             
     251## 
    264252##            if self.clusterDlg.getOptimizationType() == self.clusterDlg.EXACT_NUMBER_OF_ATTRS: minLen = maxLen 
    265253##            else: minLen = 3 
    266 ##                         
     254## 
    267255##            possibilities = 0 
    268256##            for i in range(minLen, maxLen+1): possibilities += orngVisFuncts.combinationsCount(i, len(listOfAttributes))* orngVisFuncts.fact(i-1)/2 
    269 ##                 
     257## 
    270258##            self.graph.totalPossibilities = possibilities 
    271259##            self.graph.triedPossibilities = 0 
    272 ##         
     260## 
    273261##            if self.graph.totalPossibilities > 20000: 
    274262##                proj = str(self.graph.totalPossibilities) 
     
    277265##                    if (l-i)%3 == 0: proj = proj[:i] + "," + proj[i:] 
    278266##                self.printEvent("OWLinProj: Warning: There are %s possible projections using currently visualized attributes"% (proj), eventVerbosity = 1) 
    279 ##             
     267## 
    280268##            self.clusterDlg.disableControls() 
    281 ##             
     269## 
    282270##            self.graph.getOptimalClusters(listOfAttributes, minLen, maxLen, self.clusterDlg.addResult) 
    283271##        except: 
     
    288276##        self.clusterDlg.finishedAddingResults() 
    289277##        self.showSelectedCluster() 
    290     
     278 
    291279 
    292280    # send signals with selected and unselected examples as two datasets 
     
    294282        if not self.data: return 
    295283        (selected, unselected) = self.graph.getSelectionsAsExampleTables(self.getShownAttributeList(), addProjectedPositions = self.addProjectedPositions) 
    296      
     284 
    297285        self.send("Selected Examples",selected) 
    298286        self.send("Unselected Examples",unselected) 
     
    320308##            insideColors = (numpy.compress(validData, self.clusterDlg.pointStability), "Point inside a cluster in %.2f%%") 
    321309##        else: insideColors = None 
    322 ##         
     310## 
    323311##        self.updateGraph(attrList, 1, insideColors, clusterClosure = (closure, enlargedClosure, classValue)) 
    324312##        self.graph.removeAllSelections() 
     
    327315    def updateGraphAndAnchors(self): 
    328316        self.updateGraph(setAnchors = 1) 
    329      
     317 
    330318    def updateGraph(self, attrList = None, setAnchors = 0, insideColors = None, clusterClosure = None, **args): 
    331319        if not attrList: 
     
    336324        self.graph.showKNN = 0 
    337325        if self.hasDiscreteClass(self.data): 
    338             self.graph.showKNN = self.vizrank.showKNNCorrectButton.isOn() and 1 or  self.vizrank.showKNNCorrectButton.isOn() and 2  
    339          
     326            self.graph.showKNN = self.vizrank.showKNNCorrectButton.isOn() and 1 or  self.vizrank.showKNNCorrectButton.isOn() and 2 
     327 
    340328        self.graph.insideColors = insideColors or self.classificationResults or self.outlierValues 
    341329##        self.graph.clusterClosure = clusterClosure 
     
    343331        self.graph.updateData(attrList, setAnchors, **args) 
    344332        self.graph.repaint() 
    345          
     333 
    346334 
    347335    # ############################################################################################################### 
    348336    # INPUT SIGNALS 
    349      
     337 
    350338    # receive new data and update all fields 
    351339    def setData(self, data): 
     
    357345            return    # check if the new data set is the same as the old one 
    358346 
    359         self.closeContext()         
     347        self.closeContext() 
    360348        exData = self.data 
    361349        self.data = data 
    362         self.vizrank.setData(data)   
     350        self.vizrank.setData(data) 
    363351##        self.clusterDlg.setData(data) 
    364352        self.freeVizDlg.setData(data) 
    365353        self.classificationResults = None 
    366354        self.outlierValues = None 
    367          
     355 
    368356        sameDomain = self.data and exData and exData.domain.checksum() == self.data.domain.checksum() # preserve attribute choice if the domain is the same 
    369357        if not sameDomain: 
    370358            self.setShownAttributeList(self.data, self.attributeSelectionList) 
    371              
     359        self.resetAnchors += not sameDomain 
     360 
    372361        self.openContext("", data) 
    373362        self.resetAttrManipulation() 
    374         self.updateGraph(setAnchors = not sameDomain)             
    375         self.sendSelections() 
     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 
    376368 
    377369    def setSubsetData(self, data, update = 1): 
    378         if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): return    # check if the new data set is the same as the old one 
    379         self.graph.subsetData = data 
    380         if update: self.updateGraph() 
    381         self.vizrank.setSubsetData(data) 
     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() 
    382387##        self.clusterDlg.setSubsetData(data) 
    383         qApp.processEvents() 
    384         
     388#        qApp.processEvents() 
     389 
    385390 
    386391    # attribute selection signal - info about which attributes to show 
    387     def setAttributeSelection(self, attributeSelectionList): 
     392    def setShownAttributes(self, attributeSelectionList): 
    388393        self.attributeSelectionList = attributeSelectionList 
    389394        if self.data and self.attributeSelectionList: 
     
    393398 
    394399            self.setShownAttributeList(self.data, self.attributeSelectionList) 
     400            self.attributeSelectionList = None 
    395401            self.selectionChanged() 
    396      
    397         self.updateGraph(setAnchors = 1) 
     402        self.resetAnchors += 1 
    398403 
    399404    # visualize the results of the classification 
     
    402407        if isinstance(results, orngTest.ExperimentResults) and len(results.results) > 0 and len(results.results[0].probabilities) > 0: 
    403408            self.classificationResults = ([results.results[i].probabilities[0][results.results[i].actualClass] for i in range(len(results.results))], "Probability of correct classificatioin = %.2f%%") 
    404         self.updateGraph(setAnchors = 1) 
    405  
    406      
     409        self.resetAnchors += 1 
     410 
     411 
    407412    # set the learning method to be used in VizRank 
    408413    def setVizRankLearner(self, learner): 
    409         self.vizrank.externalLearner = learner         
    410          
     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 
    411421 
    412422    # EVENTS 
     
    415425        self.updateGraph() 
    416426 
    417     def setActiveLearner(self): 
    418         self.send("Learner", self.learnersArray[self.learnerIndex]) 
    419          
    420427    def resetGraphData(self): 
    421428        orngScaleLinProjData.setData(self.graph, self.data) 
    422429        #self.graph.setData(self.data) 
    423430        self.updateGraph() 
    424          
     431 
    425432    def setValueScaling(self): 
    426433        self.graph.insideColors = self.graph.clusterClosure = None 
     
    437444        self.graph.potentialsBmp = None 
    438445        self.updateGraph() 
    439          
     446 
    440447 
    441448    def selectionChanged(self): 
     
    448455        if dlg.exec_loop(): 
    449456            self.colorSettings = dlg.getColorSchemas() 
     457            self.selectedSchemaIndex = dlg.selectedSchemaIndex 
    450458            self.graph.contPalette = dlg.getContinuousPalette("contPalette") 
    451459            self.graph.discPalette = dlg.getDiscretePalette() 
     
    459467        box = c.createBox("otherColors", " Other Colors ") 
    460468        c.createColorButton(box, "Canvas", "Canvas color", Qt.white) 
     469        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) 
    461470        box.addSpace(5) 
    462471        box.adjustSize() 
    463         c.setColorSchemas(self.colorSettings) 
    464472        return c 
    465473 
     
    480488    a.exec_loop() 
    481489 
    482     #save settings  
     490    #save settings 
    483491    ow.saveSettings() 
  • orange/OrangeWidgets/Visualize/OWLinProjGraph.py

    r3415 r3483  
    2727        OWGraph.__init__(self, parent, name) 
    2828        orngScaleLinProjData.__init__(self) 
    29          
     29 
    3030        self.totalPossibilities = 0 # a variable used in optimization - tells us the total number of different attribute positions 
    3131        self.triedPossibilities = 0 # how many possibilities did we already try 
    3232        self.startTime = time.time() 
    3333        self.p = None 
    34          
     34 
    3535        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]) 
    3636        self.tooltipCurveKeys = [] 
     
    4545        self.hideRadius = 0 
    4646        self.showAnchors = 1 
    47          
     47 
    4848        self.onlyOnePerSubset = 1 
    4949        self.showLegend = 1 
     
    6363        self.setAxisScaleDraw(QwtPlot.yLeft, HiddenScaleDraw()) 
    6464        scaleDraw = self.axisScaleDraw(QwtPlot.xBottom) 
    65         scaleDraw.setOptions(0)  
     65        scaleDraw.setOptions(0) 
    6666        scaleDraw.setTickLength(0, 0, 0) 
    6767        scaleDraw = self.axisScaleDraw(QwtPlot.yLeft) 
    68         scaleDraw.setOptions(0)  
     68        scaleDraw.setOptions(0) 
    6969        scaleDraw.setTickLength(0, 0, 0) 
    7070        self.setAxisScale(QwtPlot.xBottom, -1.13, 1.13, 1) 
     
    9999 
    100100        if self.scaledData == None or len(labels) < 3: self.updateLayout(); return 
    101          
    102         haveSubsetData = self.subsetData and self.rawdata and self.subsetData.domain == self.rawdata.domain 
     101 
     102        haveSubsetData = self.subsetData and self.rawdata and self.subsetData.domain.checksum() == self.rawdata.domain.checksum() 
    103103        hasClass = self.rawdata and self.rawdata.domain.classVar != None 
    104104        hasDiscreteClass = hasClass and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete 
    105105        hasContinuousClass = hasClass and self.rawdata.domain.classVar.varType == orange.VarTypes.Continuous 
    106          
     106 
    107107        indices = [self.attributeNameIndex[label] for label in labels]  # store indices to shown attributes 
    108          
     108 
    109109        if setAnchors or (args.has_key("XAnchors") and args.has_key("YAnchors")): 
    110110            self.potentialsBmp = None 
     
    118118                ydata = self.createYAnchors(100)*(self.hideRadius / 10) 
    119119                self.addCurve("hidecircle", QColor(200,200,200), QColor(200,200,200), 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = xdata.tolist() + [xdata[0]], yData = ydata.tolist() + [ydata[0]]) 
    120                  
     120 
    121121            # draw dots at anchors 
    122122            shownAnchorData = filter(lambda p, r=self.hideRadius**2/100: p[0]**2+p[1]**2>r, self.anchorData) 
     
    143143            xdata = self.createXAnchors(100) 
    144144            ydata = self.createYAnchors(100) 
    145             self.addCurve("circle", QColor(0,0,0), QColor(0,0,0), 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = xdata.tolist() + [xdata[0]], yData = ydata.tolist() + [ydata[0]]) 
     145            self.addCurve("circle", Qt.black, Qt.black, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = xdata.tolist() + [xdata[0]], yData = ydata.tolist() + [ydata[0]]) 
    146146 
    147147        self.potentialsClassifier = None # remove the classifier so that repaint won't recompute it 
     
    151151        if hasClass: 
    152152            classNameIndex = self.attributeNameIndex[self.rawdata.domain.classVar.name] 
    153              
     153 
    154154        if hasDiscreteClass: 
    155155            valLen = len(self.rawdata.domain.classVar.values) 
    156             classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name)    # we create a hash table of variable values and their indices             
     156            classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name)    # we create a hash table of variable values and their indices 
    157157        else:    # if we have a continuous class 
    158158            valLen = 0 
     
    168168        x_positions = projData[0] 
    169169        y_positions = projData[1] 
     170        xPointsToAdd = {} 
     171        yPointsToAdd = {} 
    170172 
    171173        if self.showProbabilities and hasClass: 
     
    178180            self.potentialsClassifier = orange.P2NN(domain, numpy.transpose(numpy.array([self.unscaled_x_positions, self.unscaled_y_positions, [float(ex.getclass()) for ex in self.rawdata]])), 
    179181                                                    self.anchorData, offsets, normalizers, averages, self.normalizeExamples, law=1) 
    180              
    181  
    182             
     182 
     183 
    183184##        # do we have cluster closure information 
    184185##        if self.showClusters and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete: 
     
    201202##            """ 
    202203## 
    203 ##        elif self.clusterClosure: self.showClusterLines(indices, validData)         
     204##        elif self.clusterClosure: self.showClusterLines(indices, validData) 
    204205## 
    205206        # ############################################################## 
    206207        # show model quality 
    207         # ##############################################################  
     208        # ############################################################## 
    208209        if self.insideColors != None or self.showKNN: 
    209210            # if we want to show knn classifications of the examples then turn the projection into example table and run knn 
     
    215216                if self.showKNN == 2: insideData, stringData = [1.0 - val for val in predictions], "Probability of wrong classification = %.2f%%" 
    216217                else:                 insideData, stringData = predictions, "Probability of correct classification = %.2f%%" 
    217                  
     218 
    218219            if hasDiscreteClass:        classColors = self.discPalette 
    219220            elif hasContinuousClass:    classColors = self.contPalette 
     
    243244                    self.addTooltipKey(x_positions[i], y_positions[i], edgeColor, i, stringData % (100*insideData[i])) 
    244245 
    245         # ##############################################################  
     246        # ############################################################## 
    246247        # do we have a subset data to show? 
    247248        # ############################################################## 
    248249        elif haveSubsetData: 
    249250            shownSubsetCount = 0 
    250             subsetReferencesToDraw = [example.reference() for example in self.subsetData] 
    251              
     251            subsetReferencesToDraw = dict([(example.reference(),1) for example in self.subsetData]) 
     252 
    252253            # draw the rawdata data set. examples that exist also in the subset data draw full, other empty 
    253254            for i in range(dataSize): 
    254                 showFilled = self.rawdata[i].reference() in subsetReferencesToDraw 
     255                showFilled = subsetReferencesToDraw.has_key(self.rawdata[i].reference()) 
     256                shownSubsetCount += showFilled 
    255257                if showFilled: 
    256                     shownSubsetCount += 1 
    257                     subsetReferencesToDraw.remove(self.rawdata[i].reference()) 
    258                  
     258                    subsetReferencesToDraw.pop(self.rawdata[i].reference()) 
     259 
    259260                if not validData[i]: continue 
    260                 if hasDiscreteClass: 
     261                if hasDiscreteClass and self.useDifferentColors: 
    261262                    newColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]] 
    262                 elif hasContinuousClass: 
     263                elif hasContinuousClass and self.useDifferentColors: 
    263264                    newColor = self.contPalette[self.noJitteringScaledData[classNameIndex][i]] 
    264265                else: 
     
    269270                else: 
    270271                    curveSymbol = self.curveSymbols[0] 
    271                  
    272                 key = self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = [x_positions[i]], yData = [y_positions[i]], showFilledSymbols = showFilled) 
     272 
     273                if not xPointsToAdd.has_key((newColor, curveSymbol, showFilled)): 
     274                    xPointsToAdd[(newColor, curveSymbol, showFilled)] = [] 
     275                    yPointsToAdd[(newColor, curveSymbol, showFilled)] = [] 
     276                xPointsToAdd[(newColor, curveSymbol, showFilled)].append(x_positions[i]) 
     277                yPointsToAdd[(newColor, curveSymbol, showFilled)].append(y_positions[i]) 
     278 
    273279                self.addTooltipKey(x_positions[i], y_positions[i], newColor, i) 
    274280 
     
    278284                YAnchors = numpy.array([val[1] for val in self.anchorData]) 
    279285                anchorRadius = numpy.sqrt(XAnchors*XAnchors + YAnchors*YAnchors) 
    280                  
     286 
    281287                for i in range(len(self.subsetData)): 
    282                     if not self.subsetData[i].reference() in subsetReferencesToDraw: continue 
    283                     subsetReferencesToDraw.remove(self.subsetData[i].reference()) 
     288                    if not subsetReferencesToDraw.has_key(self.subsetData[i].reference()): continue 
    284289 
    285290                    # check if has missing values 
    286291                    if 1 in [self.subsetData[i][ind].isSpecial() for ind in indices]: continue 
    287                      
     292 
    288293                    # scale data values for example i 
    289294                    dataVals = [self.scaleExampleValue(self.subsetData[i], ind) for ind in indices] 
    290295 
    291296                    [x,y] = self.getProjectedPointPosition(indices, dataVals, useAnchorData = 1, anchorRadius = anchorRadius)  # compute position of the point 
    292              
    293                     if not self.subsetData[i].getclass().isSpecial(): 
     297 
     298                    if not self.subsetData.domain.classVar or self.subsetData[i].getclass().isSpecial(): 
     299                        newColor = Qt.black 
     300                    else: 
    294301                        if classValueIndices: 
    295302                            newColor = self.discPalette[classValueIndices[self.subsetData[i].getclass().value]] 
    296303                        else: 
    297304                            newColor = self.contPalette[self.scaleExampleValue(self.subsetData[i], classNameIndex)] 
    298                     else: 
    299                         newColor = QColor(0,0,0) 
    300305 
    301306                    if self.useDifferentSymbols and hasDiscreteClass and not self.subsetData[i].getclass().isSpecial(): 
     
    305310                            sys.stderr.write("Exception:\n%s\n%s\n%s\n" % (self.subsetData[i].getclass().value, str(classValueIndices), str(self.curveSymbols))) 
    306311                    else: curveSymbol = self.curveSymbols[0] 
    307                     self.addCurve("", newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = [x], yData = [y], showFilledSymbols = 1) 
     312 
     313                    if not xPointsToAdd.has_key((newColor, curveSymbol, 1)): 
     314                        xPointsToAdd[(newColor, curveSymbol, 1)] = [] 
     315                        yPointsToAdd[(newColor, curveSymbol, 1)] = [] 
     316                    xPointsToAdd[(newColor, curveSymbol, 1)].append(x) 
     317                    yPointsToAdd[(newColor, curveSymbol, 1)].append(y) 
    308318 
    309319        elif not hasClass: 
     
    317327            key = self.addCurve(str(1), Qt.black, Qt.black, self.pointWidth, symbol = self.curveSymbols[0], xData = xs, yData = ys) 
    318328 
    319         # ##############################################################  
     329        # ############################################################## 
    320330        # CONTINUOUS class 
    321         # ##############################################################  
     331        # ############################################################## 
    322332        elif hasContinuousClass: 
    323333            for i in range(dataSize): 
     
    327337                self.addTooltipKey(x_positions[i], y_positions[i], newColor, i) 
    328338 
    329         # ##############################################################  
    330         # DISCRETE class + optimize drawing 
    331         # ##############################################################  
    332         elif self.optimizedDrawing and hasDiscreteClass: 
    333             pos = [[ [] , [], [] ] for i in range(valLen)] 
    334             for i in range(dataSize): 
    335                 if not validData[i]: continue 
    336                 index = classValueIndices[self.rawdata[i].getclass().value] 
    337                 pos[index][0].append(x_positions[i]) 
    338                 pos[index][1].append(y_positions[i]) 
    339                 pos[index][2].append(i) 
    340  
    341             for i in range(valLen): 
    342                 if self.useDifferentColors: newColor = self.discPalette[i] 
    343                 else:                       newColor = QColor(0,0,0) 
    344                  
    345                 if self.useDifferentSymbols: curveSymbol = self.curveSymbols[i] 
    346                 else: curveSymbol = self.curveSymbols[0] 
    347  
    348                 key = self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = pos[i][0], yData = pos[i][1]) 
    349                 for k in range(len(pos[i][0])): 
    350                     self.addTooltipKey(pos[i][0][k], pos[i][1][k], newColor, pos[i][2][k]) 
    351  
    352         # ##############################################################  
     339        # ############################################################## 
    353340        # DISCRETE class 
    354         # ##############################################################  
     341        # ############################################################## 
    355342        elif hasDiscreteClass: 
    356343            for i in range(dataSize): 
    357344                if not validData[i]: continue 
    358345                if self.useDifferentColors: newColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]] 
    359                 else:                       newColor = QColor(0,0,0) 
     346                else:                       newColor = Qt.black 
    360347                if self.useDifferentSymbols: curveSymbol = self.curveSymbols[classValueIndices[self.rawdata[i].getclass().value]] 
    361348                else:                        curveSymbol = self.curveSymbols[0] 
    362                 self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = [x_positions[i]], yData = [y_positions[i]]) 
     349 
     350                if not xPointsToAdd.has_key((newColor, curveSymbol, self.showFilledSymbols)): 
     351                    xPointsToAdd[(newColor, curveSymbol, self.showFilledSymbols)] = [] 
     352                    yPointsToAdd[(newColor, curveSymbol, self.showFilledSymbols)] = [] 
     353                xPointsToAdd[(newColor, curveSymbol, self.showFilledSymbols)].append(x_positions[i]) 
     354                yPointsToAdd[(newColor, curveSymbol, self.showFilledSymbols)].append(y_positions[i]) 
     355 
    363356                self.addTooltipKey(x_positions[i], y_positions[i], newColor, i) 
    364                      
    365         # ##############################################################  
     357 
     358        # draw all the points with a small number of curves 
     359        for i, (color, symbol, showFilled) in enumerate(xPointsToAdd.keys()): 
     360            xData = xPointsToAdd[(color, symbol, showFilled)] 
     361            yData = yPointsToAdd[(color, symbol, showFilled)] 
     362            self.addCurve(str(i), color, color, self.pointWidth, symbol = symbol, xData = xData, yData = yData, showFilledSymbols = showFilled) 
     363 
     364        # ############################################################## 
    366365        # draw the legend 
    367         # ##############################################################  
     366        # ############################################################## 
    368367        if self.showLegend: 
    369368            # show legend for discrete class 
    370369            if hasDiscreteClass: 
    371370                self.addMarker(self.rawdata.domain.classVar.name, 0.87, 1.05, Qt.AlignLeft + Qt.AlignVCenter) 
    372                      
     371 
    373372                classVariableValues = getVariableValuesSorted(self.rawdata, self.rawdata.domain.classVar.name) 
    374373                for index in range(len(classVariableValues)): 
    375374                    if self.useDifferentColors: color = self.discPalette[index] 
    376                     else:                       color = QColor(0,0,0) 
     375                    else:                       color = Qt.black 
    377376                    y = 1.0 - index * 0.05 
    378377 
     
    401400        self.repaint()  # we have to repaint to update scale to get right coordinates for tooltip rectangles 
    402401        self.updateLayout() 
    403          
    404  
    405     # ##############################################################  
     402 
     403 
     404    # ############################################################## 
    406405    # create a dictionary value for the data point 
    407406    # this will enable to show tooltips faster and to make selection of examples available 
     
    453452            OWGraph.onMouseReleased(self, e) 
    454453 
    455     # ##############################################################  
     454    # ############################################################## 
    456455    # draw tooltips 
    457456    def onMouseMoved(self, e): 
     
    483482                        xFloat = rad * cos(phi) 
    484483                        yFloat = rad * sin(phi) 
    485                     self.anchorData[self.selectedAnchorIndex] = (xFloat, yFloat, self.anchorData[self.selectedAnchorIndex][2])  
     484                    self.anchorData[self.selectedAnchorIndex] = (xFloat, yFloat, self.anchorData[self.selectedAnchorIndex][2]) 
    486485                    self.updateData(self.shownAttributes) 
    487486                    self.repaint() 
    488487                    #self.replot() 
    489488                    #self.widget.recomputeEnergy() 
    490             return  
    491              
     489            return 
     490 
    492491        dictValue = "%.1f-%.1f"%(xFloat, yFloat) 
    493492        if self.dataMap.has_key(dictValue): 
     
    521520                        fontsize = 12 
    522521                        markerAlign = Qt.AlignCenter 
    523                      
     522 
    524523                    self.tooltipCurveKeys.append(key) 
    525524 
     
    550549 
    551550                self.showTip(intX, intY, text) 
    552                  
     551 
    553552        OWGraph.onMouseMoved(self, e) 
    554553        self.replot() 
    555   
    556      
     554 
     555 
    557556    # send 2 example tables. in first is the data that is inside selected rects (polygons), in the second is unselected data 
    558557    def getSelectionsAsExampleTables(self, attrList, useAnchorData = 1, addProjectedPositions = 0): 
     
    573572 
    574573        domain.addmetas(self.rawdata.domain.getmetas()) 
    575          
     574 
    576575        if useAnchorData: indices = [self.attributeNameIndex[val[2]] for val in self.anchorData] 
    577576        else:             indices = [self.attributeNameIndex[label] for label in attrList] 
    578577        validData = self.getValidList(indices) 
    579578        if len(validData) == 0: return (None, None) 
    580          
     579 
    581580        array = self.createProjectionAsNumericArray(attrList, scaleFactor = self.scaleFactor, useAnchorData = useAnchorData, removeMissingData = 0) 
    582581        if array == None:       # if all examples have missing values 
     
    584583 
    585584        selIndices, unselIndices = self.getSelectionsAsIndices(attrList, useAnchorData, validData) 
    586          
     585 
    587586        if addProjectedPositions: 
    588587            selected = orange.ExampleTable(domain, self.rawdata.selectref(selIndices)) 
     
    605604        if len(unselected) == 0: unselected = None 
    606605        return (selected, unselected) 
    607      
     606 
    608607 
    609608    def getSelectionsAsIndices(self, attrList, useAnchorData = 1, validData = None): 
     
    613612        if validData == None: 
    614613            validData = self.getValidList(attrIndices) 
    615          
     614 
    616615        array = self.createProjectionAsNumericArray(attrList, scaleFactor = self.scaleFactor, useAnchorData = useAnchorData, removeMissingData = 0) 
    617616        if array == None: 
     
    619618        array = numpy.transpose(array) 
    620619        return self.getSelectedPoints(array[0], array[1], validData) 
    621              
    622          
     620 
     621 
    623622##    def getOptimalClusters(self, attributes, minLength, maxLength, addResultFunct): 
    624623##        self.triedPossibilities = 0 
     
    649648##                XAnchors = anchorList[u+1-minLength][0] 
    650649##                YAnchors = anchorList[u+1-minLength][1] 
    651 ##                 
     650## 
    652651##                for attrList in combinations: 
    653652##                    attrs = attrList + [attributes[z]] # remove the value of this attribute subset 
    654653##                    permutations = permutationIndices[len(attrs)] 
    655 ##                     
     654## 
    656655##                    validData = self.getValidList(attrs) 
    657656##                    classList = numpy.compress(validData, classListFull) 
     
    661660##                    tempList = [] 
    662661## 
    663 ##                    # for every permutation compute how good it separates different classes             
     662##                    # for every permutation compute how good it separates different classes 
    664663##                    for ind in permutations: 
    665664##                        permutation = [attrs[val] for val in ind] 
    666 ##                        permutationAttributes = [self.attributeNames[i] for i in permutation]                         
     665##                        permutationAttributes = [self.attributeNames[i] for i in permutation] 
    667666##                        if self.clusterOptimization.isOptimizationCanceled(): 
    668667##                            secs = time.time() - startTime 
     
    682681##                                allValue += valueDict[key] 
    683682##                            addResultFunct(allValue, closureDict, polygonVerticesDict, permutationAttributes, classesDict, enlargedClosureDict, otherDict)     # add all the clusters 
    684 ##                             
     683## 
    685684##                        else: 
    686685##                            value = 0.0 
    687686##                            for val in valueDict.values(): value += val 
    688687##                            tempList.append((value, valueDict, closureDict, polygonVerticesDict, permutationAttributes, enlargedClosureDict, otherDict)) 
    689 ##                             
     688## 
    690689##                        self.triedPossibilities += 1 
    691690##                        qApp.processEvents()        # allow processing of other events 
    692691##                        del permutation, data, graph, valueDict, closureDict, polygonVerticesDict, enlargedClosureDict, otherDict, classesDict, 
    693 ##                         
     692## 
    694693##                    self.widget.progressBarSet(100.0*self.triedPossibilities/float(self.totalPossibilities)) 
    695694##                    self.clusterOptimization.setStatusBarText("Evaluated %s projections..." % (orngVisFuncts.createStringFromNumber(self.triedPossibilities))) 
     
    720719        if fileName == "": 
    721720            return 
    722          
     721 
    723722        if not os.path.splitext(fileName)[1][1:]: 
    724723            fileName = fileName + ".pictex" 
     
    726725        self.lastSave = os.path.split(fileName)[0]+"/" 
    727726        file = open(fileName, "wt") 
    728          
     727 
    729728        file.write("\\mbox{\n") 
    730729        file.write("  \\beginpicture\n") 
     
    734733        if not self.anchorsAsVectors: 
    735734            file.write("\\circulararc 360 degrees from 1 0 center at 0 0\n") 
    736              
     735 
    737736        if self.showAnchors: 
    738737            if self.hideRadius > 0: 
     
    751750                    for x,y,l in shownAnchorData: 
    752751                        file.write("\\put {{\\footnotesize %s}} [b] at %5.3f %5.3f\n" % (l.replace("_", "-"), x*1.07, y*1.04)) 
    753          
     752 
    754753        symbols = ("{\\small $\\circ$}", "{\\tiny $\\times$}", "{\\tiny $+$}", "{\\small $\\star$}", 
    755754                   "{\\small $\\ast$}", "{\\tiny $\\div$}", "{\\small $\\bullet$}", ) + tuple([chr(x) for x in range(97, 123)]) 
     
    765764        XAnchors *= r                                               # we need to normalize the anchors by r, otherwise the anchors won't attract points less if they are placed at the center of the circle 
    766765        YAnchors *= r 
    767          
     766 
    768767        x_positions = numpy.dot(XAnchors, selectedData) 
    769768        y_positions = numpy.dot(YAnchors, selectedData) 
     
    773772            x_positions /= sum_i 
    774773            y_positions /= sum_i 
    775              
     774 
    776775        if self.scaleFactor: 
    777776            self.trueScaleFactor = self.scaleFactor 
     
    782781        x_positions *= self.trueScaleFactor 
    783782        y_positions *= self.trueScaleFactor 
    784              
     783 
    785784        validData = self.getValidList(indices) 
    786785        valLen = len(self.rawdata.domain.classVar.values) 
     
    842841            self.potentialsBmp.convertFromImage(image) 
    843842            self.potentialContext = (rx, ry, self.trueScaleFactor, self.squareGranularity, self.jitterSize, self.jitterContinuous, self.spaceBetweenCells) 
    844              
     843 
    845844 
    846845 
     
    855854    #Draw a simple graph 
    856855    import os 
    857     a = QApplication(sys.argv)         
     856    a = QApplication(sys.argv) 
    858857    graph = OWLinProjGraph(None) 
    859858    fname = r"..\..\datasets\microarray\brown\brown-selected.tab" 
  • orange/OrangeWidgets/Visualize/OWMosaicDisplay.py

    r3415 r3483  
    1818from OWQCanvasFuncts import * 
    1919from OWGraphTools import * 
    20 import OWDlgs 
     20import OWDlgs, OWExplorer 
    2121from orngVisFuncts import permutations 
    2222from copy import copy 
     
    4747        self.bMouseDown = True 
    4848        self.contentsMouseMoveEvent(ev) 
    49          
     49 
    5050    # mouse button was pressed and mouse is moving ###################### 
    5151    def contentsMouseMoveEvent(self, ev): 
    5252        if ev.button() == Qt.RightButton: 
    5353            return 
    54          
     54 
    5555        if self.tempRect: 
    5656            self.tempRect.setCanvas(None) 
     
    6363            self.canvas().update() 
    6464 
    65          
     65 
    6666    # mouse button was released ######################################### 
    6767    def contentsMouseReleaseEvent(self, ev): 
     
    7171            self.widget.removeLastSelection() 
    7272            return 
    73          
     73 
    7474        if self.tempRect: 
    7575            self.widget.addSelection(self.tempRect.rect()) 
     
    7878            self.tempRect = None 
    7979            self.canvas().update() 
    80              
     80 
    8181 
    8282class OWMosaicDisplay(OWWidget): 
    8383    settingsList = ["horizontalDistribution", "showAprioriDistributionLines", "showAprioriDistributionBoxes", 
    84                     "horizontalDistribution", "useBoxes", "interiorColoring", "boxSize", "colorSettings", "cellspace", 
     84                    "horizontalDistribution", "useBoxes", "interiorColoring", "boxSize", "colorSettings", "selectedSchemaIndex", "cellspace", 
    8585                    "showSubsetDataBoxes", "removeUnusedValues"] 
    8686 
    8787    contextHandlers = {"": DomainContextHandler("", ["manualAttributeValuesDict"], loadImperfect = 0)} 
    88          
     88 
    8989    def __init__(self,parent=None, signalManager = None): 
    9090        OWWidget.__init__(self, parent, signalManager, "Mosaic display", TRUE, TRUE) 
     
    9292        #set default settings 
    9393        self.data = None 
     94        self.unprocessedSubsetData = None 
    9495        self.subsetData = None 
    9596        self.tooltips = [] 
    9697        self.names = []     # class values 
    97          
     98 
    9899        self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData)] 
    99100        self.outputs = [("Selected Examples", ExampleTable), ("Learner", orange.Learner)] 
    100      
     101 
    101102        #load settings 
    102103        self.colorSettings = None 
     104        self.selectedSchemaIndex = 0 
    103105        self.interiorColoring = 0 
    104106        self.showAprioriDistributionLines = 1 
     
    129131        self.selectionConditionsHistorically = [] 
    130132        self.selectionConditions = [] 
    131          
     133 
     134        # color paletes for visualizing pearsons residuals 
    132135        #self.blueColors = [QColor(255, 255, 255), QColor(117, 149, 255), QColor(38, 43, 232), QColor(1,5,173)] 
    133136        self.blueColors = [QColor(255, 255, 255), QColor(210, 210, 255), QColor(110, 110, 255), QColor(0,0,255)] 
    134137        self.redColors = [QColor(255, 255, 255), QColor(255, 200, 200), QColor(255, 100, 100), QColor(255, 0, 0)] 
    135          
     138 
    136139        self.loadSettings() 
    137140 
     
    139142        self.GeneralTab = QVGroupBox(self) 
    140143        self.SettingsTab = QVGroupBox(self) 
    141         self.tabs.insertTab(self.GeneralTab, "General") 
     144        self.tabs.insertTab(self.GeneralTab, "Main") 
    142145        self.tabs.insertTab(self.SettingsTab, "Settings") 
    143146 
     
    148151        self.canvasView.show() 
    149152        self.canvas.resize(self.canvasView.size().width()-5, self.canvasView.size().height()-5) 
    150          
     153 
    151154        #GUI 
    152155        #add controls to self.controlArea widget 
    153156        self.controlArea.setMinimumWidth(235) 
    154          
     157 
    155158        texts = ["1st Attribute", "2nd Attribute", "3rd Attribute", "4th Attribute"] 
    156159        for i in range(1,5): 
     
    158161            box.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed )) 
    159162            combo = OWGUI.comboBox(box, self, "attr" + str(i), None, callback = self.updateGraphAndPermList, sendSelectedValue = 1, valueType = str) 
    160                          
     163 
    161164            butt = OWGUI.button(box, self, "", callback = self.orderAttributeValues, tooltip = "Change the order of attribute values", debuggingEnabled = 0) 
    162165            butt.setMaximumWidth(26); butt.setMaximumHeight(26); butt.setMinimumWidth(24); butt.setMinimumHeight(26) 
     
    168171 
    169172        self.optimizationDlg = OWMosaicOptimization(self, self.signalManager) 
    170         self.mosaicTreeDialog = OWMosaicTreeDialog(self.optimizationDlg, self) 
    171          
     173        self.explorerDlg = OWExplorer.OWExplorerDialog(self, self.optimizationDlg, "Mosaic", self.signalManager) 
     174 
    172175        optimizationButtons = OWGUI.widgetBox(self.GeneralTab, "Dialogs", orientation = "horizontal") 
    173         optimizationButtons.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed )) 
     176        optimizationButtons.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed)) 
    174177        OWGUI.button(optimizationButtons, self, "VizRank", callback = self.optimizationDlg.reshow, debuggingEnabled = 0, tooltip = "Find attribute combinations that will separate different classes as clearly as possible.") 
    175         OWGUI.button(optimizationButtons, self, "Explorer", callback = self.mosaicTreeDialog.reshow, debuggingEnabled = 0, tooltip = "Select specific cells in mosaic and explore this data further.\nBuild a decision tree with mosaic diagrams.") 
     178        OWGUI.button(optimizationButtons, self, "Explorer", callback = self.explorerDlg.reshow, debuggingEnabled = 0, tooltip = "Select specific cells in mosaic and explore this data further.\nBuild a decision tree with mosaic diagrams.") 
    176179 
    177180        self.box7 = OWGUI.collapsableWidgetBox(self.GeneralTab, "Explore Attribute Permutations", self, "exploreAttrPermutations", callback = self.permutationListToggle) 
    178          
     181 
    179182        self.permutationList = QListBox(self.box7) 
    180183        self.connect(self.permutationList, SIGNAL("selectionChanged()"), self.setSelectedPermutation) 
     
    185188        # ###################### 
    186189        box5 = OWGUI.widgetBox(self.SettingsTab, "Colors in Cells Represent...") 
    187         OWGUI.comboBox(box5, self, "interiorColoring", None, items = ["Standardized (Pearson) residuals", "Class distribution"], callback = self.changedInteriorColoring) 
     190        OWGUI.comboBox(box5, self, "interiorColoring", None, items = ["Standardized (Pearson) residuals", "Class distribution"], callback = self.updateGraph) 
    188191        box5.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed )) 
    189192 
    190193        OWGUI.comboBoxWithCaption(self.SettingsTab, self, "cellspace", "Minimum cell distance: ", box = "Visual Settings", items = range(1,11), callback = self.updateGraph, sendSelectedValue = 1, valueType = int, tooltip = "What is the minimum distance between two rectangles in the plot?") 
    191          
     194 
    192195        self.box6 = OWGUI.widgetBox(self.SettingsTab, "Cell Distribution Settings") 
    193196        OWGUI.comboBox(self.box6, self, 'horizontalDistribution', items = ["Show Distribution Vertically", "Show Distribution Horizontally"], tooltip = "Do you wish to see class distribution drawn horizontally or vertically?", callback = self.updateGraph) 
     
    202205 
    203206        OWGUI.checkBox(self.SettingsTab, self, "removeUnusedValues", "Remove unused values", box = "Attributes", tooltip = "Do you want to remove unused attribute values?\nThis setting will not be considered until new data is received.") 
    204          
     207 
    205208        hbox = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal") 
    206209        OWGUI.button(hbox, self, "Set Colors", self.setColors, tooltip = "Set the color palette for coloring different class values", debuggingEnabled = 0) 
     
    216219        dlg = self.createColorDialog() 
    217220        self.colorPalette = dlg.getDiscretePalette() 
    218          
    219         #self.changedInteriorColoring() 
    220         #self.box6.setEnabled(self.interiorColoring) 
    221221 
    222222        self.VizRankLearner = MosaicVizRankLearner(self.optimizationDlg) 
     
    226226        self.safeProcessEvents() 
    227227        self.tabs.updateGeometry() 
    228          
     228 
    229229    def permutationListToggle(self): 
    230230        if self.exploreAttrPermutations: 
     
    249249        elif self.sort4.isOn(): attr = self.attr4 
    250250 
    251         if self.data and attr  != "" and attr != "(None)":  
     251        if self.data and attr  != "" and attr != "(None)": 
    252252            dlg = SortAttributeValuesDlg(self, self.manualAttributeValuesDict.get(attr, None) or getVariableValuesSorted(self.data, attr)) 
    253253            if dlg.exec_loop() == QDialog.Accepted: 
     
    257257            control.setOn(0) 
    258258        self.updateGraph() 
    259          
     259 
    260260    # initialize combo boxes with discrete attributes 
    261261    def initCombos(self, data): 
     
    272272                for combo in [self.attr1Combo, self.attr2Combo, self.attr3Combo, self.attr4Combo]: 
    273273                    combo.insertItem(self.icons[orange.VarTypes.Discrete], attr.name) 
    274                  
     274 
    275275        if self.attr1Combo.count() > 0: 
    276276            self.attr1 = str(self.attr1Combo.text(0)) 
     
    278278        self.attr3 = str(self.attr3Combo.text(0)) 
    279279        self.attr4 = str(self.attr4Combo.text(0)) 
    280          
     280 
    281281    #  when we resize the widget, we have to redraw the data 
    282282    def resizeEvent(self, e): 
     
    285285        self.updateGraph() 
    286286 
     287    # ------------- SIGNALS -------------------------- 
    287288    # # DATA signal - receive new data and update all fields 
    288     def setData(self, data, onlyDrilling = 0): 
     289    def setData(self, data): 
    289290        self.closeContext() 
    290291        self.data = None 
     
    292293        self.manualAttributeValuesDict = {} 
    293294        self.attributeValuesDict = {} 
    294         self.information(0) 
    295         self.information(1) 
    296         self.information(2) 
    297  
    298         self.data = self.optimizationDlg.setData(data, self.removeUnusedValues, onlyDrilling) 
    299         if not onlyDrilling: 
    300             self.mosaicTreeDialog.setData(data) 
     295        self.information([0,1,2]) 
     296 
     297        self.data = self.optimizationDlg.setData(data, self.removeUnusedValues) 
     298        self.explorerDlg.setData(self.data) 
    301299 
    302300        if self.data: 
     
    307305            if self.removeUnusedValues and len(data) != len(self.data): 
    308306                self.information(2, "Unused attribute values were removed.") 
    309              
     307 
    310308            if self.data.domain.classVar and self.data.domain.classVar.varType == orange.VarTypes.Discrete: 
    311309                self.interiorColoring = CLASS_DISTRIBUTION 
    312310            else: 
    313311                self.interiorColoring = PEARSON 
    314                          
     312 
    315313        self.initCombos(self.data) 
    316314        self.openContext("", self.data) 
    317315 
     316        if data and self.unprocessedSubsetData:        # if we first received subset data we now have to call setSubsetData to process it 
     317            self.setSubsetData(self.unprocessedSubsetData) 
     318            self.unprocessedSubsetData = None 
     319 
     320    def setSubsetData(self, data): 
     321        if not self.data: 
     322            self.unprocessedSubsetData = data 
     323            self.warning(10) 
     324        else: 
     325            try: 
     326                self.subsetData = data.select(self.data.domain) 
     327                self.warning(10) 
     328            except: 
     329                self.subsetData = None 
     330                self.warning(10, data and "'Examples' and 'Example Subset' data do not have copatible domains. Unable to draw 'Example Subset' data." or "") 
     331 
     332 
     333    # this is called by OWBaseWidget after setData and setSubsetData are called. this way the graph is updated only once 
     334    def handleNewSignals(self): 
    318335        self.updateGraphAndPermList() 
    319336 
    320     def setSubsetData(self, data): 
    321         try: 
    322             self.subsetData = data.select(self.data.domain) 
    323         except: 
    324             self.subsetData = None 
    325                  
    326         self.updateGraphAndPermList() 
    327          
     337    # ------------------------------------------------ 
    328338 
    329339    def setShownAttributes(self, attrList, **args): 
    330340        if not attrList: return 
    331341        self.attr1 = attrList[0] 
    332          
     342 
    333343        if len(attrList) > 1: self.attr2 = attrList[1] 
    334344        else: self.attr2 = "(None)" 
     
    342352        self.attributeValuesDict = args.get("customValueOrderDict", None) 
    343353        self.updateGraphAndPermList() 
    344          
    345     def getShownAttributes(self): 
     354 
     355    def getShownAttributeList(self): 
    346356        attrList = [self.attr1, self.attr2, self.attr3, self.attr4] 
    347357        while "(None)" in attrList: attrList.remove("(None)") 
     
    349359        return attrList 
    350360 
    351     def changedInteriorColoring(self): 
    352         #self.box6.setEnabled(self.interiorColoring) 
    353         self.updateGraph() 
    354  
    355361    def updateGraphAndPermList(self, **args): 
    356362        self.removeAllSelections() 
     
    358364 
    359365        if self.exploreAttrPermutations: 
    360             attrList = self.getShownAttributes() 
     366            attrList = self.getShownAttributeList() 
    361367            if not getattr(self, "bestPlacements", []) or 0 in [attr in self.bestPlacements[0][1] for attr in attrList]:        # we might have bestPlacements for a different set of attributes 
    362368                self.setStatusBarText("Evaluating different attribute permutations. You can stop evaluation by opening VizRank dialog and pressing 'Stop optimization' button.") 
    363369                self.bestPlacements = self.optimizationDlg.optimizeCurrentAttributeOrder(attrList, updateGraph = 0) 
    364370                self.setStatusBarText("") 
    365                  
    366             if self.bestPlacements:  
     371 
     372            if self.bestPlacements: 
    367373                for (val, attrs, order) in self.bestPlacements: 
    368374                    self.permutationList.insertItem("%.2f - %s" % (val, attrs)) 
    369375                attrList, valueOrder = self.bestPlacements[0][1], self.bestPlacements[0][2] 
    370376                self.attributeValuesDict = dict([(attrList[i], tuple(valueOrder[i])) for i in range(len(attrList))]) 
    371              
     377 
    372378        self.updateGraph(**args) 
    373379 
    374     # ############################################################################ 
    375380    # ############################################################################ 
    376381    # updateGraph - gets called every time the graph has to be updated 
    377     def updateGraph(self, **args): 
    378         # hide all rectangles 
    379         for item in self.canvas.allItems(): 
    380             if item.rtti() != 123: item.setCanvas(None)    # remove all canvas items, except SelectionCurves 
    381         for tip in self.tooltips: QToolTip.remove(self.canvasView, tip) 
    382         self.names = []; self.tooltips = [] 
    383          
    384         if self.data == None : return 
    385  
    386         attrList = [self.attr1, self.attr2, self.attr3, self.attr4] 
     382    def updateGraph(self, data = -1, subsetData = -1, attrList = -1, erasePrevious = 1, **args): 
     383        # do we want to erase previous diagram? 
     384        if erasePrevious: 
     385            for item in self.canvas.allItems(): 
     386                if item.rtti() != 123: item.setCanvas(None)    # remove all canvas items, except SelectionCurves 
     387            for (rect, tip) in self.tooltips: QToolTip.remove(self.canvasView, rect) 
     388            self.names = []; self.tooltips = [] 
     389 
     390        if data == -1: 
     391            data = self.data 
     392 
     393        if subsetData == -1: 
     394            subsetData = self.subsetData 
     395 
     396        if attrList == -1: 
     397            attrList = [self.attr1, self.attr2, self.attr3, self.attr4] 
     398 
     399        if data == None : return 
     400 
    387401        while "(None)" in attrList: attrList.remove("(None)") 
    388402        while "" in attrList:       attrList.remove("") 
     
    391405 
    392406        selectList = attrList 
    393         if self.data.domain.classVar: 
    394             data = self.data.select(attrList + [self.data.domain.classVar]) 
     407        if data.domain.classVar: 
     408            data = data.select(attrList + [data.domain.classVar]) 
    395409        else: 
    396             data = self.data.select(attrList) 
     410            data = data.select(attrList) 
    397411        data = orange.Preprocessor_dropMissing(data) 
    398412 
    399         self.warning(10) 
    400413        if len(data) == 0: 
    401             self.warning(10, "There are no examples with valid values for currently visualized attributes. Unable to visualize.") 
     414            self.warning(5, "There are no examples with valid values for currently visualized attributes. Unable to visualize.") 
    402415            return 
     416        else: 
     417            self.warning(5) 
    403418 
    404419        self.aprioriDistributions = [] 
    405420        if self.interiorColoring == PEARSON: 
    406             for attr in attrList: 
    407                 self.aprioriDistributions = [orange.Distribution(attr, data) for attr in attrList] 
    408  
    409         # get the maximum width of rectangle 
    410         xOff = 50 
    411         width = 50 
    412         if len(attrList) > 1: 
    413             text = QCanvasText(attrList[1], self.canvas); 
    414             font = text.font(); font.setBold(1); text.setFont(font) 
    415             width = text.boundingRect().right() - text.boundingRect().left() + 30 + 20 
    416             xOff = width 
    417             if len(attrList) == 4: 
    418                 text = QCanvasText(attrList[3], self.canvas); 
     421            self.aprioriDistributions = [orange.Distribution(attr, data) for attr in attrList] 
     422 
     423        if args.get("positions"): 
     424            xOff, yOff, squareSize = args.get("positions") 
     425        else: 
     426            # get the maximum width of rectangle 
     427            xOff = 50 
     428            width = 50 
     429            if len(attrList) > 1: 
     430                text = QCanvasText(attrList[1], self.canvas); 
    419431                font = text.font(); font.setBold(1); text.setFont(font) 
    420                 width += text.boundingRect().right() - text.boundingRect().left() + 30 + 20 
    421          
    422         # get the maximum height of rectangle         
    423         height = 90 
    424         yOff = 40 
    425         squareSize = min(self.canvasView.size().width() - width - 20, self.canvasView.size().height() - height - 20) 
     432                width = text.boundingRect().right() - text.boundingRect().left() + 30 + 20 
     433                xOff = width 
     434                if len(attrList) == 4: 
     435                    text = QCanvasText(attrList[3], self.canvas); 
     436                    font = text.font(); font.setBold(1); text.setFont(font) 
     437                    width += text.boundingRect().right() - text.boundingRect().left() + 30 + 20 
     438 
     439            # get the maximum height of rectangle 
     440            height = 90 
     441            yOff = 40 
     442            squareSize = min(self.canvasView.size().width() - width - 20, self.canvasView.size().height() - height - 20) 
     443 
    426444        if squareSize < 0: return    # canvas is too small to draw rectangles 
    427445 
     
    434452        if not getattr(self, "attributeValuesDict", None): 
    435453            self.attributeValuesDict = self.manualAttributeValuesDict 
    436          
     454 
    437455        # compute distributions 
    438456        self.conditionalDict = self.optimizationDlg.getConditionalDistributions(data, attrList) 
    439457        self.conditionalDict[""] = len(data) 
    440458        self.conditionalSubsetDict = None 
    441 ##        print self.conditionalDict 
    442  
    443         if self.subsetData and self.data.domain == self.subsetData.domain: 
    444             #subData = orange.Preprocessor_select(self.subsetData, attributes = [self.subsetData.domain[attr] for attr in attrList] + [self.subsetData.domain.classVar]) 
    445             #subData = orange.Preprocessor_dropMissing(subData) 
    446             #if subData and len(subData) > 0: 
    447             #    self.conditionalSubsetDict = self.optimizationDlg.getConditionalDistributions(subData, attrList) 
    448             #    self.conditionalSubsetDict[""] = len(subData) 
    449             self.conditionalSubsetDict = self.optimizationDlg.getConditionalDistributions(self.subsetData, attrList) 
    450             self.conditionalSubsetDict[""] = len(self.subsetData) 
     459        if subsetData: 
     460            self.conditionalSubsetDict = self.optimizationDlg.getConditionalDistributions(subsetData, attrList) 
     461            self.conditionalSubsetDict[""] = len(subsetData) 
    451462 
    452463        # draw rectangles 
    453464        self.DrawData(attrList, (xOff, xOff+squareSize), (yOff, yOff+squareSize), 0, "", len(attrList)) 
    454         self.DrawLegend(data, (xOff, xOff+squareSize), (yOff, yOff+squareSize)) # draw class legend 
     465        if args.get("drawLegend", 1): 
     466            self.DrawLegend(data, (xOff, xOff+squareSize), (yOff, yOff+squareSize)) # draw class legend 
    455467 
    456468        if args.get("drillUpdateSelection", 1): 
    457             self.mosaicTreeDialog.updateSelection() 
     469            self.explorerDlg.updateState() 
    458470 
    459471        self.canvas.update() 
     
    461473    # ############################################################################ 
    462474    # ############################################################################ 
    463      
     475 
    464476    ##  DRAW DATA - draw rectangles for attributes in attrList inside rect (x0,x1), (y0,y1) 
    465477    def DrawData(self, attrList, (x0, x1), (y0, y1), side, condition, totalAttrs, lastValueForFirstAttribute = 0, usedAttrs = [], usedVals = [], attrVals = ""): 
     
    468480            self.DrawText(side, attrList[0], (x0, x1), (y0, y1), totalAttrs, lastValueForFirstAttribute, attrVals)  # store coordinates for later drawing of labels 
    469481            return 
    470          
     482 
    471483        attr = attrList[0] 
    472484        edge = len(attrList) * self.cellspace  # how much smaller rectangles do we draw 
     
    485497        else:              counts = [self.conditionalDict[attrVals + "-" + val] for val in values] 
    486498        total = sum(counts) 
    487          
     499 
    488500        for i in range(len(counts)): 
    489501            val = values[i] 
    490             size = whole*float(counts[i])/float(total)             
     502            size = whole*float(counts[i])/float(total) 
    491503            htmlVal = getHtmlCompatibleString(val) 
    492504            if attrVals != "": newAttrVals = attrVals + "-" + val 
     
    503515        self.DrawText(side, attrList[0], (x0, x1), (y0, y1), totalAttrs, lastValueForFirstAttribute, attrVals) 
    504516 
    505     
     517 
    506518    ###################################################################### 
    507519    ## DRAW TEXT - draw legend for all attributes in attrList and their possible values 
     
    513525##            elif not self.conditionalDict[attrVals]: 
    514526##                self.conditionalDict[attrVals] = [1 for i in range(len(getVariableValuesSorted(self.data, attr)))] 
    515          
     527 
    516528        if not self.conditionalDict[attrVals]: 
    517529            if not self.drawPositions.has_key(side): self.drawPositions[side] = (x0, x1, y0, y1) 
     
    519531        else: 
    520532            if self.drawPositions.has_key(side): (x0, x1, y0, y1) = self.drawPositions[side]        # restore the positions where we have to draw the attribute values and attribute name 
    521              
     533 
    522534        self.drawnSides[side] = 1 
    523535 
     
    527539        width  = x1-x0 - (side % 2 == 0) * self.cellspace*(totalAttrs-side)*(len(values)-1) 
    528540        height = y1-y0 - (side % 2 == 1) * self.cellspace*(totalAttrs-side)*(len(values)-1) 
    529          
     541 
    530542        #calculate position of first attribute 
    531543        if side == 0:    OWCanvasText(self.canvas, attr, x0+(x1-x0)/2, y1 + self.attributeNameOffset, Qt.AlignCenter, bold = 1) 
     
    533545        elif side == 2:  OWCanvasText(self.canvas, attr, x0+(x1-x0)/2, y0 - self.attributeNameOffset, Qt.AlignCenter, bold = 1) 
    534546        else:            OWCanvasText(self.canvas, attr, x1 + self.attributeNameOffset, y0+(y1-y0)/2, Qt.AlignLeft + Qt.AlignVCenter, bold = 1) 
    535                  
     547 
    536548        currPos = 0 
    537                  
     549 
    538550        if attrVals == "":  counts = [self.conditionalDict.get(val, 1) for val in values] 
    539551        else:               counts = [self.conditionalDict.get(attrVals + "-" + val, 1) for val in values] 
     
    554566            else :            currPos += perc*height+ self.cellspace*(totalAttrs-side) 
    555567 
    556              
     568 
    557569     # draw the class legend below the square 
    558570    def DrawLegend(self, data, (x0, x1), (y0, y1)): 
     
    565577            names = (list(self.attributeValuesDict.get(data.domain.classVar.name, [])) or getVariableValuesSorted(data, data.domain.classVar.name)) + [data.domain.classVar.name+":"] 
    566578            colors = [self.colorPalette[i] for i in range(len(data.domain.classVar.values))] 
    567          
     579 
    568580        for name in names: 
    569581            self.names.append(OWCanvasText(self.canvas, name)) 
    570              
     582 
    571583        totalWidth = sum([self.names[i].boundingRect().width() for i in range(len(self.names))]) 
    572584 
     
    580592 
    581593        size = 16 # 8 + 8*(self.interiorColoring == PEARSON) 
    582          
     594 
    583595        for i in range(len(names)-1): 
    584596            if self.interiorColoring == PEARSON: edgeColor = Qt.black 
     
    590602 
    591603 
    592     # draw a rectangle, set it to back and add it to rect list                 
     604    # draw a rectangle, set it to back and add it to rect list 
    593605    def addRect(self, x0, x1, y0, y1, condition = "", usedAttrs = [], usedVals = [], attrVals = ""): 
    594606        x0 = int(x0); x1 = int(x1); y0 = int(y0); y1 = int(y1) 
     
    618630                    r = OWCanvasRectangle(self.canvas, x0-d, y0-d, x1-x0+2*d+1, y1-y0+2*d+1, z = 50) 
    619631                    r.setPen(QPen(self.colorPalette[counts.index(max(counts))], 2, Qt.DashLine)) 
    620                 
     632 
    621633 
    622634        if not self.conditionalDict[attrVals]: return rect 
     
    677689                        boxCounts.append(tempVal) 
    678690                        #boxCounts.append(aprioriDist[val]/float(sum(aprioriDist.values())) * reduce(operator.mul, [contingencies[usedAttrs[i]][usedVals[i]][clsVal]/float(sum(contingencies[usedAttrs[i]][usedVals[i]].values())) for i in range(len(usedAttrs))])) 
    679                          
     691 
    680692                total1 = 0; total2 = 0 
    681693                if self.useBoxes: 
    682694                    if self.horizontalDistribution:  OWCanvasLine(self.canvas, x0, y0+self.boxSize, x1, y0+self.boxSize, z = 30) 
    683695                    else:                            OWCanvasLine(self.canvas, x0+self.boxSize, y0, x0+self.boxSize, y1, z = 30) 
    684                      
     696 
    685697                for i in range(len(clsValues)): 
    686698                    val1 = apriori[i] 
     
    703715                            v2 = int((y1-y0)* val2) 
    704716                        x,y,w,h, xL1, yL1, xL2, yL2 = x0, y0+total2, self.boxSize, v2, x0, y0+total1+v1, x1, y0+total1+v1 
    705                          
     717 
    706718                    if self.useBoxes: 
    707719                        OWCanvasRectangle(self.canvas, x, y, w, h, self.colorPalette[i], self.colorPalette[i], z = 20) 
     
    747759    def addTooltip(self, x, y, w, h, condition, apriori = None, attrVals = None, pearson = None, expected = None): 
    748760        tooltipText = "Examples in this area have:<br>" + condition 
    749          
     761 
    750762        if apriori: 
    751763            clsValues = list(self.attributeValuesDict.get(self.data.domain.classVar.name, [])) or getVariableValuesSorted(self.data, self.data.domain.classVar.name) 
     
    762774        tipRect = QRect(x, y, w, h) 
    763775        QToolTip.add(self.canvasView, tipRect, tooltipText) 
    764         self.tooltips.append(tipRect) 
    765     
     776        self.tooltips.append((tipRect, tooltipText)) 
     777 
    766778    def saveToFileCanvas(self): 
    767779        sizeDlg = OWDlgs.OWChooseImageSizeDlg(self.canvas) 
     
    772784        if dlg.exec_loop(): 
    773785            self.colorSettings = dlg.getColorSchemas() 
     786            self.selectedSchemaIndex = dlg.selectedSchemaIndex 
    774787            self.colorPalette = dlg.getDiscretePalette() 
    775788            self.updateGraph() 
     
    778791        c = OWDlgs.ColorPalette(self, "Color Palette") 
    779792        c.createDiscretePalette(" Discrete Palette ") 
    780         c.setColorSchemas(self.colorSettings) 
     793        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) 
    781794        return c 
    782795 
     
    792805        self.updateGraph(drillUpdateSelection = 0) 
    793806        self.sendSelectedData() 
    794          
     807 
    795808        if getattr(self, "recentlyAdded", []): 
    796809            self.selectionConditionsHistorically = self.selectionConditionsHistorically + [self.recentlyAdded] 
    797810            self.recentlyAdded = [] 
    798811 
    799         self.mosaicTreeDialog.updateSelection()            # we have already called this in self.updateGraph() call 
     812        self.explorerDlg.updateState()            # we have already called this in self.updateGraph() call 
    800813        self.selectionRectangle = None 
    801814 
     
    809822 
    810823        self.updateGraph() 
    811 ##        self.mosaicTreeDialog.updateSelection()       # we have already called this in self.updateGraph() call 
     824##        self.explorerDlg.updateState()       # we have already called this in self.updateGraph() call 
    812825        self.sendSelectedData() 
    813826 
     
    815828        self.selectionConditions = [] 
    816829        self.selectionConditionsHistorically = [] 
    817 ##        self.mosaicTreeDialog.updateSelection()       # removeAllSelections is always called before updateGraph() - where updateSelection is called 
     830##        self.explorerDlg.updateState()       # removeAllSelections is always called before updateGraph() - where updateState is called 
    818831        self.sendSelectedData() 
    819832 
    820833    # return examples in currently selected boxes as example table or array of 0/1 values 
    821     def getSelectedExamples(self, asExampleTable = 1, negate = 0): 
    822         attrs = self.getShownAttributes() 
     834    def getSelectedExamples(self, asExampleTable = 1, negate = 0, selectionConditions = None): 
     835        attrs = self.getShownAttributeList() 
    823836        if attrs == [] or not self.data: 
    824837            return None 
    825838 
     839        if selectionConditions == None: 
     840            selectionConditions = self.selectionConditions 
     841 
    826842        pp = orange.Preprocessor_take() 
    827  
    828         sumIndices = numpy.zeros(len(self.data))       
    829         for val in self.selectionConditions: 
     843        sumIndices = numpy.zeros(len(self.data)) 
     844        for val in selectionConditions: 
    830845            for i, attr in enumerate(attrs): 
    831846                pp.values[self.data.domain[attr]] = val[i] 
    832847            indices = numpy.array(pp.selectionVector(self.data)) 
    833848            sumIndices += indices 
    834  
    835849        selectedIndices = list(numpy.where(sumIndices > 0, 1 - negate, 0 + negate)) 
    836          
     850 
    837851        if asExampleTable: 
    838852            return self.data.selectref(selectedIndices) 
    839853        else: 
    840854            return selectedIndices 
    841          
     855 
    842856 
    843857 
     
    850864        self.layout = QVBoxLayout(self, 4) 
    851865        self.layout.addWidget(self.space) 
    852          
     866 
    853867        box1 = OWGUI.widgetBox(self.space, 1, orientation = "horizontal") 
    854          
     868 
    855869        self.attributeList = QListBox(box1) 
    856870        self.attributeList.setSelectionMode(QListBox.Extended) 
     
    891905                self.attributeList.setSelected(i+1, TRUE) 
    892906 
    893      
     907 
    894908#test widget appearance 
    895909if __name__=="__main__": 
  • orange/OrangeWidgets/Visualize/OWParallelCoordinates.py

    r3415 r3483  
    99# 
    1010# Show data using parallel coordinates visualization method 
    11 #  
     11# 
    1212 
    1313from OWVisWidget import * 
    1414from OWParallelGraph import * 
    15 import OWToolbars, OWGUI, OWDlgs, orngVisFuncts  
     15import OWToolbars, OWGUI, OWDlgs, orngVisFuncts 
    1616from sys import getrecursionlimit, setrecursionlimit 
    1717 
     
    2020########################################################################################### 
    2121class OWParallelCoordinates(OWVisWidget): 
    22     settingsList = ["attrContOrder", "attrDiscOrder", "graph.jitterSize", "graph.showDistributions", 
     22    settingsList = ["graph.jitterSize", "graph.showDistributions", 
    2323                    "graph.showAttrValues", "graph.hidePureExamples", "graph.globalValueScaling", "linesDistance", 
    2424                    "graph.useSplines", "graph.lineTracking", "graph.enabledLegend", "autoSendSelection", 
    25                     "toolbarSelection", "graph.showStatistics", "colorSettings", "showAllAttributes"] 
    26     attributeContOrder = ["None", "ReliefF", "Fisher discriminant", "Signal to Noise", "Signal to Noise For Each Class"] 
    27     attributeDiscOrder = ["None", "ReliefF", "GainRatio"] 
     25                    "toolbarSelection", "graph.showStatistics", "colorSettings", "selectedSchemaIndex", "showAllAttributes"] 
    2826    jitterSizeNums = [0, 2,  5,  10, 15, 20, 30] 
    2927    linesDistanceNums = [10, 20, 30, 40, 50, 60, 70, 80, 100, 120, 150] 
     
    4139        self.isResizing = 0 
    4240        self.showAllAttributes = 0 
    43          
     41 
    4442        self.box.addWidget(self.graph) 
    4543        self.box.addWidget(self.slider) 
    4644 
    47         self.inputs = [("Examples", ExampleTable, self.setData), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setAttributeSelection)] 
     45        self.inputs = [("Examples", ExampleTable, self.setData), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setShownAttributes)] 
    4846        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList)] 
    49      
     47 
    5048        #set default settings 
    5149        self.data = None 
     
    5755        self.correlationDict = {} 
    5856        self.middleLabels = "Correlations" 
    59         self.attributeSelectionList = None   
     57        self.attributeSelectionList = None 
    6058        self.toolbarSelection = 0 
    6159        self.colorSettings = None 
    62          
     60        self.selectedSchemaIndex = 0 
     61 
    6362        self.graph.jitterSize = 10 
    6463        self.graph.showDistributions = 1 
     
    104103        OWGUI.comboBox(boxX, self, "graph.jitterSize", label = 'Jittering size (% of size):  ', orientation='horizontal', callback = self.setJitteringSize, items = self.jitterSizeNums, sendSelectedValue = 1, valueType = float) 
    105104        OWGUI.comboBox(boxX, self, "linesDistance", label = 'Minimum axis distance:  ', orientation='horizontal', callback = self.updateGraph, items = self.linesDistanceNums, tooltip = "What is the minimum distance between two adjecent attribute axis", sendSelectedValue = 1, valueType = int) 
    106          
     105 
    107106        # visual settings 
    108107        box = OWGUI.widgetBox(self.SettingsTab, "Visual settings") 
     
    119118 
    120119        OWGUI.comboBox(self.SettingsTab, self, "middleLabels", box = "Middle labels", items = ["Off", "Correlations", "VizRank"], callback = self.updateGraph, tooltip = "What information do you wish to view on top in the middle of coordinate axes?", sendSelectedValue = 1, valueType = str) 
    121          
     120 
    122121        hbox4 = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal") 
    123122        OWGUI.button(hbox4, self, "Set Colors", self.setColors, tooltip = "Set the canvas background color and color palette for coloring continuous variables", debuggingEnabled = 0) 
    124123 
    125124        box2 = OWGUI.widgetBox(self.SettingsTab, "Sending selection") 
    126         OWGUI.checkBox(box2, self, 'autoSendSelection', 'Auto send selected data', callback = self.setAutoSendSelection, tooltip = "Send signals with selected data whenever the selection changes.") 
    127  
    128         # continuous attribute ordering 
    129         OWGUI.comboBox(self.SettingsTab, self, "attrContOrder", box = "Continuous attribute ordering", items = self.attributeContOrder, callback = self.updateShownAttributeList, sendSelectedValue = 1, valueType = str) 
    130         OWGUI.comboBox(self.SettingsTab, self, "attrDiscOrder", box = "Discrete attribute ordering", items = self.attributeDiscOrder, callback = self.updateShownAttributeList, sendSelectedValue = 1, valueType = str) 
     125        OWGUI.checkBox(box2, self, 'autoSendSelection', 'Auto send selected data', callback = self.selectionChanged, tooltip = "Send signals with selected data whenever the selection changes.") 
    131126 
    132127        self.safeProcessEvents() 
    133128        self.tabs.updateGeometry() 
    134129 
    135         self.graph.autoSendSelectionCallback = self.setAutoSendSelection 
     130        self.graph.selectionChangedCallback = self.selectionChanged 
    136131        self.icons = self.createAttributeIconDict() 
    137          
    138         # add a settings dialog and initialize its values         
     132 
     133        # add a settings dialog and initialize its values 
    139134        self.activateLoadedSettings() 
    140135        self.resize(900, 700) 
    141          
     136 
    142137 
    143138    # ######################### 
     
    158153        else: 
    159154            self.information(0, "Didn't flip the attribute. To flip a continuous attribute uncheck 'Global value scaling' checkbox.") 
    160          
     155 
    161156    def updateGraph(self, *args): 
    162157        attrs = self.getShownAttributeList() 
     
    219214                else: labels.append("") 
    220215        return labels 
    221                  
    222        
    223     def sendShownAttributes(self): 
    224         self.send("Attribute Selection List", self.getShownAttributeList()) 
     216 
    225217 
    226218    # ############################################# 
    227219 
    228     # had to override standart show to call updateGraph. otherwise self.mainArea.width() gives incorrect value     
     220    # had to override standart show to call updateGraph. otherwise self.mainArea.width() gives incorrect value 
    229221    def show(self): 
    230222        OWWidget.show(self) 
     
    232224 
    233225    def setSubsetData(self, data, update = 1): 
    234         if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): return    # check if the new data set is the same as the old one 
    235         self.graph.setSubsetData(data) 
     226        if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): 
     227            return    # check if the new data set is the same as the old one 
     228 
     229        try: 
     230            subsetData = data.select(self.data.domain) 
     231            self.warning(10) 
     232        except: 
     233            subsetData = None 
     234            self.warning(10, "'Examples' and 'Example Subset' data do not have copatible domains. Unable to draw 'Example Subset' data.") 
     235 
     236        self.graph.setSubsetData(subsetData) 
    236237        qApp.processEvents() 
    237238        if update: 
    238239            self.updateGraph() 
    239240            qApp.processEvents() 
    240      
    241     # ###### DATA ################################ 
     241 
     242    # ------------- SIGNALS -------------------------- 
    242243    # receive new data and update all fields 
    243244    def setData(self, data): 
     
    248249        if self.data != None and data != None and self.data.checksum() == data.checksum(): 
    249250            return    # check if the new data set is the same as the old one 
    250              
     251 
    251252        self.projections = None 
    252253        self.correlationDict = {} 
    253          
     254 
    254255        exData = self.data 
    255256        self.data = data 
    256          
     257 
    257258        self.graph.setData(self.data) 
    258259        self.optimizationDlg.setData(self.data) 
     
    260261        # preserve attribute choice if the domain is the same 
    261262        sameDomain = self.data and exData and exData.domain.checksum() == self.data.domain.checksum() # preserve attribute choice if the domain is the same 
    262         if sameDomain: 
    263             self.updateGraph() 
    264             self.sendSelections() 
    265         else: 
    266             self.shownAttribsLB.clear() 
    267             self.hiddenAttribsLB.clear() 
    268  
     263        if not sameDomain: 
     264            self.setShownAttributeList(self.data, self.attributeSelectionList) 
    269265            self.targetValueCombo.clear() 
    270266            self.targetValueCombo.insertItem("(None)") 
     
    275271                    self.targetValueCombo.insertItem(val) 
    276272                self.targetValueCombo.setCurrentItem(0) 
    277             self.setAttributeSelection()       # this will show first 10 attributes or attributes that were received in attributeSelection signal 
    278              
    279  
    280273        self.resetAttrManipulation()    # update up down buttons 
    281              
    282     # ################################################ 
    283      
    284     def setAttributeSelection(self, attributeSelectionList = None): 
    285         if not attributeSelectionList: 
    286             attributeSelectionList = self.attributeSelectionList 
    287         else: 
    288             self.attributeSelectionList = attributeSelectionList 
    289  
    290         if not self.data:       # if we don't have data we have nothing to do 
    291             return 
    292          
    293         if attributeSelectionList:  # check if we have attributes that actually exist in the current domain. we might get this signal before the actual data 
    294             exist = [self.graph.attributeNameIndex.has_key(attr) for attr in attributeSelectionList] 
    295             if 0 in exist:      # current attributeSelectionList is not valid 
    296                 attributeSelectionList = None 
    297             else: 
    298                 self.attributeSelectionList = None 
    299                 print "this must be valid:", attributeSelectionList 
    300  
    301         if not attributeSelectionList: 
    302             attributeSelectionList = [attr.name for attr in self.data.domain.attributes[:10]] 
    303  
    304         if attributeSelectionList:      # here we have a valid list of attributes that can be visualized 
    305             self.setShownAttributeList(self.data, attributeSelectionList) 
    306             self.updateGraph() 
    307         self.sendSelections() 
    308  
     274 
     275    # attribute selection signal - info about which attributes to show 
     276    def setShownAttributes(self, attributeSelectionList): 
     277        self.attributeSelectionList = attributeSelectionList 
     278        if self.data and self.attributeSelectionList: 
     279            for attr in self.attributeSelectionList: 
     280                if not self.graph.attributeNameIndex.has_key(attr):  # this attribute list belongs to a new dataset that has not come yet 
     281                    return 
     282 
     283            self.setShownAttributeList(self.data, self.attributeSelectionList) 
     284            self.attributeSelectionList = None 
     285            self.selectionChanged() 
     286 
     287    # this is called by OWBaseWidget after setData and setSubsetData are called. this way the graph is updated only once 
     288    def handleNewSignals(self): 
     289        self.updateGraph() 
     290        self.selectionChanged() 
     291 
     292    # ------------------------------------------------ 
     293    def sendShownAttributes(self): 
     294        self.send("Attribute Selection List", self.getShownAttributeList()) 
     295 
     296    def selectionChanged(self): 
     297        self.zoomSelectToolbar.buttonSendSelections.setEnabled(not self.autoSendSelection) 
     298        if self.autoSendSelection: 
     299            self.sendSelections() 
    309300 
    310301    # send signals with selected and unselected examples as two datasets 
     
    320311 
    321312        (selected, unselected) = self.graph.getSelectionsAsExampleTables(targetVal) 
    322          
     313 
    323314        self.send("Selected Examples", selected) 
    324315        self.send("Unselected Examples", unselected) 
    325316 
    326     ################################################# 
     317    # ------------------------------------------------ 
    327318 
    328319    def updateValues(self): 
     
    354345        self.updateGraph() 
    355346 
    356     def setAutoSendSelection(self): 
    357         if self.autoSendSelection: 
    358             self.zoomSelectToolbar.buttonSendSelections.setEnabled(0) 
    359             self.sendSelections() 
    360         else: 
    361             self.zoomSelectToolbar.buttonSendSelections.setEnabled(1) 
    362              
    363  
    364347    def setColors(self): 
    365348        dlg = self.createColorDialog() 
    366349        if dlg.exec_loop(): 
    367350            self.colorSettings = dlg.getColorSchemas() 
     351            self.selectedSchemaIndex = dlg.selectedSchemaIndex 
    368352            self.graph.contPalette = dlg.getContinuousPalette("contPalette") 
    369353            self.graph.discPalette = dlg.getDiscretePalette() 
     
    379363        box.addSpace(5) 
    380364        box.adjustSize() 
    381         c.setColorSchemas(self.colorSettings) 
     365        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) 
    382366        return c 
    383367 
     
    395379    qualityMeasure =  ["Classification accuracy", "Average correct", "Brier score"] 
    396380    testingMethod = ["Leave one out", "10-fold cross validation", "Test on learning set"] 
    397      
     381 
    398382    settingsList = ["attributeCount", "fileBuffer", "lastSaveDirName", "optimizationMeasure", 
    399383                    "numberOfAttributes", "orderAllAttributes", "optimizationMeasure"] 
    400      
     384 
    401385    def __init__(self, parallelWidget, parent=None, signalManager = None): 
    402386        OWBaseWidget.__init__(self, parent, signalManager, "Parallel Optimization Dialog", FALSE) 
    403387 
    404388        self.setCaption("Qt Parallel Optimization Dialog") 
    405         self.topLayout = QVBoxLayout( self, 10 )  
     389        self.topLayout = QVBoxLayout( self, 10 ) 
    406390        self.grid=QGridLayout(4,2) 
    407391        self.topLayout.addLayout( self.grid, 10 ) 
     
    445429        self.resultList.setMinimumSize(200,200) 
    446430        self.connect(self.resultList, SIGNAL("selectionChanged()"), self.showSelectedAttributes) 
    447          
    448                
     431 
     432 
    449433        # remove non-existing files 
    450434        names = [] 
     
    456440        names.append("(None)") 
    457441        self.fileName = "(None)" 
    458                  
     442 
    459443        self.hbox1 = OWGUI.widgetBox(self.vizrankSettingsBox, "VizRank projections file", orientation = "horizontal") 
    460444        self.vizrankFileCombo = OWGUI.comboBox(self.hbox1, self, "fileName", items = names, tooltip = "File that contains information about interestingness of scatterplots \ngenerated by VizRank method in scatterplot widget", callback = self.changeProjectionFile, sendSelectedValue = 1, valueType = str) 
     
    476460        self.subsetAttributeEdit = OWGUI.lineEdit(box, self, "numberOfAttributes", valueType = int) 
    477461        label  = OWGUI.widgetLabel(box, "   attributes") 
    478          
     462 
    479463        self.startOptimizationButton = OWGUI.button(self.optimizeBox, self, "Start optimization", callback = self.startOptimization) 
    480464        f = self.startOptimizationButton.font() 
     
    486470        self.connect(self.stopOptimizationButton , SIGNAL("clicked()"), self.stopOptimizationClick) 
    487471 
    488          
     472 
    489473        self.clearButton = OWGUI.button(self.manageBox, self, "Clear results", self.clearResults) 
    490474        self.loadButton  = OWGUI.button(self.manageBox, self, "Load", self.loadResults) 
     
    538522        if hasattr(data, "name"): 
    539523            self.datasetName = data.name 
    540         else: self.datasetName = ""         
    541          
     524        else: self.datasetName = "" 
     525 
    542526    # called when optimization is in progress 
    543527    def canContinueOptimization(self): 
     
    546530    def getWorstVal(self): 
    547531        return self.worstVal 
    548          
     532 
    549533    def stopOptimizationClick(self): 
    550534        self.canOptimize = 0 
     
    573557        self.testingMethodLabel.setText("Testing method used:" ) 
    574558        self.qualityMeasureLabel.setText("Quality measure used:" ) 
    575          
     559 
    576560        if name == None: 
    577561            name = str(QFileDialog.getOpenFileName( self.lastSaveDirName, "Interesting projections (*.proj)", self, "", "Open Projections")) 
     
    587571            file.close() 
    588572            return 
    589          
     573 
    590574        if type(eval(file.readline()[:-1])) != list:    # second line must contain a list of classes that we tried to separate 
    591575            QMessageBox.critical(None,'Old version of projection file','This file was saved with an older version of k-NN Optimization Dialog. The new version of dialog offers \nsome additional functionality and therefore you have to compute the projection quality again.',QMessageBox.Ok) 
     
    600584                file.close() 
    601585                return 
    602              
     586 
    603587            while (line != ""): 
    604588                (acc, other_results, lenTable, attrList, tryIndex, strList) = eval(line) 
     
    617601 
    618602        self.fileBuffer.insert(0, (shortFileName, name)) 
    619          
     603 
    620604 
    621605        if len(self.fileBuffer) > 10: 
    622606            self.fileBuffer.remove(self.fileBuffer[-1]) 
    623              
     607 
    624608        self.vizrankFileCombo.clear() 
    625609        for i in range(len(self.fileBuffer)): 
    626610            self.vizrankFileCombo.insertItem(self.fileBuffer[i][0]) 
    627611        self.fileName = shortFileName 
    628              
     612 
    629613        self.kNeighborsLabel.setText("Number of neighbors (k): %s" % (str(settings["kValue"]))) 
    630614        self.percentDataUsedLabel.setText("Percent of data used: %d %%" % (settings["percentDataUsed"])) 
     
    637621        self.allResults.insert(index, (val, attrList)) 
    638622        self.resultList.insertItem("%.3f - %s" % (val, str(attrList)), index) 
    639         
     623 
    640624 
    641625    def findTargetIndex(self, accuracy, funct): 
     
    651635        if funct(accuracy, self.allResults[top][0]) == accuracy: 
    652636            return top 
    653         else:  
     637        else: 
    654638            return bottom 
    655639 
     
    658642        self.clearResults() 
    659643        if self.parallelWidget.data == None: return 
    660          
     644 
    661645        if self.optimizationMeasure == VIZRANK and self.fileName == "": 
    662646            QMessageBox.information(self, "No projection file", "If you wish to optimize using VizRank you first have to load a projection file \ncreated by VizRank using Scatterplot widget.", QMessageBox.Ok) 
     
    693677        self.stopOptimizationButton.show() 
    694678        qApp.processEvents()        # allow processing of other events 
    695          
     679 
    696680        if self.orderAllAttributes: 
    697681            orngVisFuncts.optimizeAttributeOrder(attrInfo, len(self.parallelWidget.data.domain.attributes), self, qApp) 
     
    701685        self.stopOptimizationButton.hide() 
    702686        self.startOptimizationButton.show() 
    703                      
     687 
    704688 
    705689    # ################################ 
     
    709693        for i in range(len(self.allResults)): 
    710694            self.resultList.insertItem("%.2f - %s" % (self.allResults[i][0], str(self.allResults[i][1])), i) 
    711         if self.resultList.count() > 0: self.resultList.setCurrentItem(0)   
    712      
     695        if self.resultList.count() > 0: self.resultList.setCurrentItem(0) 
     696 
    713697    def clearResults(self): 
    714698        self.allResults = [] 
     
    723707            if self.optimizationMeasure == CORRELATION: filename += " - " + "correlation" 
    724708            else:                                       filename += " - " + "vizrank" 
    725                  
     709 
    726710            name = str(QFileDialog.getSaveFileName( os.path.join(self.lastSaveDirName, filename), "Parallel projections (*.papr)", self, "", "Save Parallel Projections")) 
    727711            if name == "": return 
     
    743727    def loadResults(self): 
    744728        self.clearResults() 
    745                  
     729 
    746730        name = str(QFileDialog.getOpenFileName( self.lastSaveDirName, "Parallel projections (*.papr)", self, "", "Open Parallel Projections")) 
    747731        if name == "": return 
     
    760744        file.close() 
    761745 
    762          
    763     
     746 
     747 
    764748 
    765749#test widget appearance 
     
    771755    a.exec_loop() 
    772756 
    773     #save settings  
     757    #save settings 
    774758    ow.saveSettings() 
  • orange/OrangeWidgets/Visualize/OWParallelGraph.py

    r3415 r3483  
    3333        OWGraph.setData(self, data) 
    3434        orngScaleData.setData(self, data) 
    35          
     35 
    3636 
    3737    # update shown data. Set attributes, coloring by className .... 
     
    4545 
    4646        blackColor = QColor(0, 0, 0) 
    47          
     47 
    4848        if self.scaledData == None:  return 
    4949        if len(attributes) == 0: return 
     
    6969        self.axisScaleDraw(QwtPlot.xBottom).setOptions(0)           # hide horizontal line representing x axis 
    7070        self.axisScaleDraw(QwtPlot.yLeft).setTickLength(0, 0, 0) 
    71         self.axisScaleDraw(QwtPlot.yLeft).setOptions(0)  
    72          
     71        self.axisScaleDraw(QwtPlot.yLeft).setOptions(0) 
     72 
    7373        self.setAxisMaxMajor(QwtPlot.xBottom, len(attributes)) 
    7474        self.setAxisMaxMinor(QwtPlot.xBottom, 0) 
     
    8080            continuousClass = self.rawdata.domain.classVar.varType == orange.VarTypes.Continuous 
    8181 
    82         haveSubsetData = 0 
    83         if self.subsetData and self.rawdata and self.subsetData.domain == self.rawdata.domain: 
    84             haveSubsetData = 1 
    85          
     82        haveSubsetData = self.subsetData and self.rawdata and self.subsetData.domain.checksum() == self.rawdata.domain.checksum() 
     83 
    8684        length = len(attributes) 
    8785        indices = [self.attributeNameIndex[label] for label in attributes] 
    8886        xs = range(length) 
    8987        dataSize = len(self.scaledData[0]) 
    90          
     88 
    9189        if self.rawdata.domain.classVar and not continuousClass: 
    9290            classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name) 
     
    108106                if self.rawdata.domain[indices[i]].varType != orange.VarTypes.Discrete or attributes[i] == self.rawdata.domain.classVar.name: continue 
    109107 
    110                 attr = self.rawdata.domain[indices[i]]                 
     108                attr = self.rawdata.domain[indices[i]] 
    111109                for attrVal in attr.values: 
    112110                    tempData = self.rawdata.select({attr.name:attrVal}) 
     
    118116                            break 
    119117                        ind += 1 
    120                          
     118 
    121119                    # do all instances belong to the same class? 
    122120                    while ind < len(tempData): 
     
    146144                self.curvePoints.append([]) # add an empty list 
    147145                continue 
    148                          
     146 
    149147            curve = QwtPlotCurve(self) 
    150148            if targetValue != None: 
     
    169167                    if subsetReferencesToDraw: 
    170168                        subsetReferencesToDraw.remove(self.rawdata[i].reference()) 
    171                      
     169 
    172170            curve.setPen(QPen(newColor, 1)) 
    173171            if not dataStop: 
     
    189187                subData[i] = self.scaleData(self.subsetData, indices[i])[0] 
    190188            subData = subData.transpose() 
    191              
     189 
    192190            for i in range(len(self.subsetData)): 
    193191                if not self.subsetData[i].reference() in subsetReferencesToDraw: continue 
    194192                subsetReferencesToDraw.remove(self.subsetData[i].reference()) 
    195                  
     193 
    196194                # check if has missing values 
    197195                if 1 in [self.subsetData[i][ind].isSpecial() for ind in indices]: continue 
     
    213211                        newColor = self.discPalette[classValueIndices[self.subsetData[i].getclass().value]] 
    214212                    curves[1].append(curve) 
    215                      
     213 
    216214                curve.setPen(QPen(newColor, 1)) 
    217215                curve.setData(xs, subData[i].tolist()) 
    218216                if self.useSplines: 
    219217                    curve.setStyle(QwtCurve.Spline) 
    220                  
     218 
    221219        # now add all curves. First add the gray curves (they will be shown in the back) and then the blue (target value) curves (shown in front) 
    222220        for curve in curves[0]: self.insertCurve(curve) 
     
    228226        if self.showDistributions and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete: 
    229227            self.showDistributionValues(targetValue, validData, indices, dataStop) 
    230              
     228 
    231229        # ############################################ 
    232230        # draw vertical lines that represent attributes 
     
    278276                    continue  # only for continuous attributes 
    279277                array = numpy.compress(numpy.equal(self.validDataArray[indices[i]], 1), self.scaledData[indices[i]])  # remove missing values 
    280                  
     278 
    281279                if classNameIndex == -1 or continuousClass:    # no class 
    282280                    if self.showStatistics == MEANS: 
     
    331329                self.nonDataKeys.append(self.addCurve("", self.discPalette[c], self.discPalette[c], 1, QwtCurve.Lines, QwtSymbol.None, xData = xs, yData = ys, lineWidth = 4)) 
    332330 
    333          
     331 
    334332        # ################################################## 
    335333        # show labels in the middle of the axis 
     
    370368    # SHOW DISTRIBUTION BAR GRAPH 
    371369    def showDistributionValues(self, targetValue, validData, indices, dataStop): 
    372         # get index of class          
     370        # get index of class 
    373371        classNameIndex = self.attributeNameIndex[self.rawdata.domain.classVar.name] 
    374372 
    375         # create color table             
     373        # create color table 
    376374        count = len(self.rawdata.domain.classVar.values) 
    377375        #if count < 1: count = 1.0 
     
    381379        classValueSorted  = getVariableValuesSorted(self.rawdata, self.rawdata.domain.classVar.name) 
    382380 
    383         self.toolInfo = []         
     381        self.toolInfo = [] 
    384382        for graphAttrIndex in range(len(indices)): 
    385383            index = indices[graphAttrIndex] 
     
    387385            attr = self.rawdata.domain[index] 
    388386            attrLen = len(attr.values) 
    389              
     387 
    390388            values = [] 
    391389            totals = [0] * attrLen 
     
    394392            variableValueIndices = getVariableValueIndices(self.rawdata, index) 
    395393            variableValueSorted = getVariableValuesSorted(self.rawdata, index) 
    396              
     394 
    397395            for i in range(count): 
    398396                values.append([0] * attrLen) 
     
    449447 
    450448        self.addTooltips() 
    451          
     449 
    452450    def addTooltips(self): 
    453451        for i in range(len(self.toolInfo)): 
     
    464462            y_2 = self.transform(QwtPlot.yLeft, y_end) 
    465463            rect = QRect(x_1, y_1, x_2-x_1, y_2-y_1) 
    466             self.toolRects.append(rect)             
     464            self.toolRects.append(rect) 
    467465            QToolTip.add(self, rect, tooltipText) 
    468466 
     
    473471 
    474472 
    475     # if user clicked between two lines send signal that  
     473    # if user clicked between two lines send signal that 
    476474    def staticMouseClick(self, e): 
    477475        if self.parallelDlg: 
     
    487485    """ 
    488486    def updateAxes(self): 
    489         OWGraph.updateAxes()         
     487        OWGraph.updateAxes() 
    490488        self.removeTooltips() 
    491489        self.addTooltips() 
     
    495493        self.addTooltips() 
    496494 
    497     # if we zoomed, we have to update tooltips     
     495    # if we zoomed, we have to update tooltips 
    498496    def onMouseReleased(self, e): 
    499497        OWGraph.onMouseReleased(self, e) 
     
    520518                    existingPen.setWidth(3) 
    521519                    self.setCurvePen(self.lastSelectedKey, existingPen) 
    522                      
     520 
    523521            else: 
    524522                OWGraph.onMouseMoved(self, e) 
    525523                return 
    526              
     524 
    527525            OWGraph.onMouseMoved(self, e) 
    528526            self.replot() 
     
    533531        if self.selectionCurveKeyList == []: 
    534532            return (None, self.rawdata) 
    535          
     533 
    536534        selIndices = [] 
    537535        unselIndices = range(len(self.rawdata)) 
     
    548546        selected = self.rawdata.getitemsref(selIndices) 
    549547        unselected = self.rawdata.getitemsref(unselIndices) 
    550          
     548 
    551549        if len(selected) == 0: selected = None 
    552550        if len(unselected) == 0: unselected = None 
  • orange/OrangeWidgets/Visualize/OWPolyviz.py

    r3415 r3483  
    2121                    "graph.showLegend", "graph.showFilledSymbols", "graph.optimizedDrawing", "graph.useDifferentSymbols", "autoSendSelection", 
    2222                    "graph.useDifferentColors", "graph.tooltipKind", "graph.tooltipValue", "toolbarSelection", "VizRankLearnerName", 
    23                     "colorSettings", "addProjectedPositions", "showAllAttributes", "graph.lineLength"] 
     23                    "colorSettings", "selectedSchemaIndex", "addProjectedPositions", "showAllAttributes", "graph.lineLength"] 
    2424         
    2525    def __init__(self,parent=None, signalManager = None): 
    2626        OWLinProj.__init__(self, parent, signalManager, "Polyviz", graphClass = OWPolyvizGraph) 
    2727 
    28         self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setAttributeSelection), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] 
    29         self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList), ("Learner", orange.Learner)] 
     28        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)] 
     29        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList)] 
    3030 
    3131        # SETTINGS TAB 
  • orange/OrangeWidgets/Visualize/OWPolyvizGraph.py

    r3415 r3483  
    55from orngScalePolyvizData import * 
    66import orngVisFuncts 
    7 #import orange 
     7from OWGraphTools import UnconnectedLinesCurve 
    88 
    99# #################################################################### 
     
    172172         
    173173        dataSize = len(self.rawdata) 
    174         blackColor = QColor(0,0,0) 
    175         curveData = [[0, 0, 0, QwtSymbol.Ellipse, blackColor, blackColor, [], []] for i in range(dataSize)] 
    176  
    177          
     174        curveData = [[0, 0, 0, QwtSymbol.Ellipse, Qt.black, Qt.black, [], []] for i in range(dataSize)] 
     175 
    178176        # ########## 
    179177        # draw text at lines 
     
    230228            curveData[i][YANCHORS] = YAnchorPositions[i] 
    231229 
     230        xPointsToAdd = {} 
     231        yPointsToAdd = {} 
     232        self.xLinesToAdd = {}   # this is filled in addAnchorLine function 
     233        self.yLinesToAdd = {} 
    232234 
    233235        if self.showKNNModel == 1 and hasClass: 
     
    265267                fillColor = bwColors.getColor(kNNValues[i]) 
    266268                edgeColor = classColors.getColor(classValueIndices[table[i].getclass().value]) 
    267                 self.addCurve(str(i), fillColor, edgeColor, self.pointWidth, xData = [table[i][0].value], yData = [table[i][1].value]) 
     269                if not xPointsToAdd.has_key((fillColor, edgeColor, QwtSymbol.Ellipse, 1)): 
     270                    xPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)] = [] 
     271                    yPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)] = [] 
     272                xPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)].append(table[i][0].value) 
     273                yPointsToAdd[(fillColor, edgeColor, QwtSymbol.Ellipse, 1)].append(table[i][1].value) 
    268274                self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], fillColor, i, length) 
    269275 
     
    280286                self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], newColor, i, length) 
    281287 
    282         # DISCRETE class + optimize drawing 
    283         elif self.optimizedDrawing or not hasClass: 
    284             pos = [[ [] , [], [],  [], [] ] for i in range(valLen)] 
    285             posIndex = 0 
     288        # DISCRETE class or no class at all 
     289        else: 
     290            color = Qt.black 
     291            symbol = self.curveSymbols[0] 
    286292            for i in range(dataSize): 
    287293                if not validData[i]: continue 
    288294                if hasClass: 
    289                     posIndex = classValueIndices[self.rawdata[i].getclass().value] 
    290                 pos[posIndex][0].append(x_positions[i]) 
    291                 pos[posIndex][1].append(y_positions[i]) 
    292                 pos[posIndex][2].append(i) 
    293                 pos[posIndex][3].append(curveData[i][XANCHORS]) 
    294                 pos[posIndex][4].append(curveData[i][YANCHORS]) 
    295                 if useDifferentColors: self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], self.discPalette[classValueIndices[self.rawdata[i].getclass().value]], i, length) 
    296                 else:                  self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], QColor(0,0,0), i, length) 
    297  
    298             for i in range(valLen): 
    299                 if useDifferentColors: newColor = self.discPalette[i] 
    300                 else:                  newColor = QColor(0,0,0) 
     295                    ind = classValueIndices[self.rawdata[i].getclass().value] 
     296                    if self.useDifferentSymbols: 
     297                        symbol = self.curveSymbols[ind] 
     298                    if useDifferentColors: 
     299                        color = self.discPalette[ind] 
     300                if not xPointsToAdd.has_key((color, color, symbol, 1)): 
     301                    xPointsToAdd[(color, color, symbol, 1)] = [] 
     302                    yPointsToAdd[(color, color, symbol, 1)] = [] 
     303                xPointsToAdd[(color, color, symbol, 1)].append(x_positions[i]) 
     304                yPointsToAdd[(color, color, symbol, 1)].append(y_positions[i]) 
    301305                 
    302                 if self.useDifferentSymbols: curveSymbol = self.curveSymbols[i] 
    303                 else: curveSymbol = self.curveSymbols[0] 
    304  
    305                 key = self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = pos[i][0], yData = pos[i][1]) 
    306                 for k in range(len(pos[i][0])): 
    307                     self.addTooltipKey(pos[i][0][k], pos[i][1][k], pos[i][3][k], pos[i][4][k], newColor, pos[i][2][k]) 
    308  
    309         # unoptimized drawing in case of discrete class 
    310         elif hasDiscreteClass: 
    311             for i in range(dataSize): 
    312                 if not validData[i]: continue 
    313                 if useDifferentColors: newColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]] 
    314                 else:                  newColor = QColor(0,0,0) 
    315                 if self.useDifferentSymbols: curveSymbol = self.curveSymbols[classValueIndices[self.rawdata[i].getclass().value]] 
    316                 else:                        curveSymbol = self.curveSymbols[0] 
    317                 self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = curveSymbol, xData = [x_positions[i]], yData = [y_positions[i]]) 
    318                 self.addTooltipKey(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], newColor, i) 
    319                 self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], newColor, i, length) 
     306                self.addAnchorLine(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], color, i, length) 
     307                self.addTooltipKey(x_positions[i], y_positions[i], curveData[i][XANCHORS], curveData[i][YANCHORS], color, i) 
     308 
     309        # draw the points 
     310        for i, (fillColor, edgeColor, symbol, showFilled) in enumerate(xPointsToAdd.keys()): 
     311            xData = xPointsToAdd[(fillColor, edgeColor, symbol, showFilled)] 
     312            yData = yPointsToAdd[(fillColor, edgeColor, symbol, showFilled)] 
     313            self.addCurve(str(i), fillColor, edgeColor, self.pointWidth, symbol = symbol, xData = xData, yData = yData, showFilledSymbols = showFilled) 
     314 
     315        self.showAnchorLines() 
     316        self.xLinesToAdd = {} 
     317        self.yLinesToAdd = {} 
    320318 
    321319        # draw polygon 
     
    371369                lineX2 = (1.0 - kvoc)*xAnchors[j] + kvoc * lineX1 
    372370                lineY2 = (1.0 - kvoc)*yAnchors[j] + kvoc * lineY1 
    373  
    374             self.addCurve('line' + str(index), color, color, 0, QwtCurve.Lines, symbol = QwtSymbol.None, xData = [xAnchors[j], lineX2], yData = [yAnchors[j], lineY2]) 
    375  
     371             
     372            self.xLinesToAdd[color] = self.xLinesToAdd.get(color, []) + [xAnchors[j], lineX2] 
     373            self.yLinesToAdd[color] = self.yLinesToAdd.get(color, []) + [yAnchors[j], lineY2] 
     374 
     375 
     376    def showAnchorLines(self): 
     377        for i, color in enumerate(self.xLinesToAdd.keys()): 
     378            curve = UnconnectedLinesCurve(self, QPen(color), self.xLinesToAdd[color], self.yLinesToAdd[color]) 
     379            self.insertCurve(curve) 
    376380 
    377381    # create a dictionary value for the data point 
  • orange/OrangeWidgets/Visualize/OWRadviz.py

    r3415 r3483  
    99# 
    1010# Show a radviz projection of the data 
    11 #  
     11# 
    1212 
    1313from OWLinProj import * 
     
    1818                    "graph.tooltipKind", "graph.tooltipValue", "toolbarSelection", "graph.showClusters", "clusterClassifierName", 
    1919                    "valueScalingType", "graph.showProbabilities", "showAllAttributes", 
    20                     "learnerIndex", "colorSettings", "addProjectedPositions", "VizRankLearnerName"] 
    21              
     20                    "learnerIndex", "colorSettings", "selectedSchemaIndex", "addProjectedPositions", "VizRankLearnerName"] 
     21 
    2222    def __init__(self, parent=None, signalManager = None): 
    2323        OWLinProj.__init__(self, parent, signalManager, "Radviz") 
    2424 
    25         self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute Selection List", AttributeList, self.setAttributeSelection), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] 
    26         self.outputs = [("Selected Examples", ExampleTableWithClass), ("Unselected Examples", ExampleTableWithClass), ("Attribute Selection List", AttributeList), ("Learner", orange.Learner)] 
     25        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)] 
     26        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Attribute Selection List", AttributeList)] 
    2727 
    2828 
     
    3535    a.exec_loop() 
    3636 
    37     #save settings  
     37    #save settings 
    3838    ow.saveSettings() 
  • orange/OrangeWidgets/Visualize/OWScatterPlot.py

    r3415 r3483  
    99# 
    1010# Show data using scatterplot 
    11 #  
     11# 
    1212 
    1313from OWWidget import * 
    1414from OWScatterPlotGraph import * 
    1515from OWkNNOptimization import * 
    16 import orngVizRank 
     16import orngVizRank, OWExplorer 
    1717##from OWClusterOptimization import * 
    1818import OWGUI, OWToolbars, OWDlgs 
     
    2020from OWGraph import OWGraph 
    2121 
    22         
     22 
    2323########################################################################################### 
    2424##### WIDGET : Scatterplot visualization 
     
    2727    settingsList = ["graph.pointWidth", "graph.showXaxisTitle", "graph.showYLaxisTitle", "showGridlines", "graph.showAxisScale", 
    2828                    "graph.showLegend", "graph.jitterSize", "graph.jitterContinuous", "graph.showFilledSymbols", "graph.showProbabilities", 
    29                     "graph.showDistributions", "autoSendSelection", "graph.optimizedDrawing", "toolbarSelection",  
    30                     "learnerIndex", "colorSettings", "VizRankLearnerName", "showProbabilitiesDetails"] 
     29                    "graph.showDistributions", "autoSendSelection", "toolbarSelection", 
     30                    "colorSettings", "selectedSchemaIndex", "VizRankLearnerName", "showProbabilitiesDetails"] 
    3131    jitterSizeNums = [0.0, 0.1,   0.5,  1,  2 , 3,  4 , 5 , 7 ,  10,   15,   20 ,  30 ,  40 ,  50 ] 
    3232 
    3333    contextHandlers = {"": DomainContextHandler("", ["attrX", "attrY", (["attrLabel", "attrShape", "attrSize"], DomainContextHandler.Optional)])} 
    34      
     34 
    3535    def __init__(self, parent=None, signalManager = None): 
    3636        OWWidget.__init__(self, parent, signalManager, "ScatterPlot", TRUE) 
    3737 
    38         self.inputs =  [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute selection", list, self.setAttributeSelection), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] 
    39         self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable), ("Learner", orange.Learner)] 
    40  
    41         # local variables     
     38        self.inputs =  [("Examples", ExampleTable, self.setData, Default), ("Example Subset", ExampleTable, self.setSubsetData), ("Attribute selection", AttributeList, self.setShownAttributes), ("Evaluation Results", orngTest.ExperimentResults, self.setTestResults), ("VizRank Learner", orange.Learner, self.setVizRankLearner)] 
     39        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)] 
     40 
     41        # local variables 
    4242        self.showGridlines = 0 
    4343        self.autoSendSelection = 1 
    4444        self.toolbarSelection = 0 
    45 ##        self.clusterClassifierName = "Visual cluster classifier (Scatterplot)" 
    46         self.VizRankLearnerName = "VizRank (Scatterplot)" 
    4745        self.classificationResults = None 
    4846        self.outlierValues = None 
    49         self.learnerIndex = 0 
    50         self.learnersArray = [None, None]   # VizRank, Cluster 
    5147        self.colorSettings = None 
     48        self.selectedSchemaIndex = 0 
    5249        self.showProbabilitiesDetails = 0 
    5350 
     
    5754        self.vizrank = OWVizRank(self, self.signalManager, self.graph, orngVizRank.SCATTERPLOT, "ScatterPlot") 
    5855##        self.clusterDlg = ClusterOptimization(self, self.signalManager, self.graph, "ScatterPlot") 
     56        self.explorerDlg = OWExplorer.OWExplorerDialog(self, self.vizrank, "Scatterplot", signalManager) 
    5957        self.optimizationDlg = self.vizrank 
    60         
     58 
    6159        self.data = None 
     60        self.unprocessedSubsetData = None 
    6261 
    6362        #load settings 
     
    9089        OWGUI.checkBox(box, self, 'showColorLegend', 'Show color legend', callback = self.updateGraph) 
    9190        self.attrColorCombo = OWGUI.comboBox(box, self, "attrColor", callback = self.updateGraph, sendSelectedValue=1, valueType = str, emptyString = "(One color)") 
    92          
     91 
    9392        # labelling 
    9493        self.attrLabel = "" 
     
    9897        self.attrShape = "" 
    9998        self.attrShapeCombo = OWGUI.comboBox(self.GeneralTab, self, "attrShape", "Shape Attribute", callback = self.updateGraph, sendSelectedValue=1, valueType = str, emptyString = "(One shape)") 
    100                  
     99 
    101100        # sizing 
    102101        self.attrSize = "" 
    103102        self.attrSizeCombo = OWGUI.comboBox(self.GeneralTab, self, "attrSize", "Size Attribute", callback = self.updateGraph, sendSelectedValue=1, valueType = str, emptyString = "(One size)") 
    104          
     103 
    105104##        # cluster dialog 
    106105##        self.clusterDlg.label1.hide() 
     
    109108##        self.clusterDlg.attributeLabel.hide() 
    110109##        self.graph.clusterOptimization = self.clusterDlg 
    111          
    112          
     110 
     111 
    113112        self.optimizationButtons = OWGUI.widgetBox(self.GeneralTab, "Optimization Dialogs", orientation = "horizontal") 
    114113        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) 
     114        OWGUI.button(self.optimizationButtons, self, "Explorer", callback = self.explorerDlg.reshow, debuggingEnabled = 0, tooltip = "Select specific cells in mosaic and explore this data further.\nBuild a decision tree with mosaic diagrams.") 
    115115##        OWGUI.button(self.optimizationButtons, self, "Cluster", callback = self.clusterDlg.reshow, debuggingEnabled = 0) 
    116116##        self.connect(self.clusterDlg.startOptimizationButton , SIGNAL("clicked()"), self.optimizeClusters) 
     
    134134        self.jitterSizeCombo = OWGUI.comboBox(box3, self, "graph.jitterSize", callback = self.resetGraphData, items = self.jitterSizeNums, sendSelectedValue = 1, valueType = float) 
    135135        OWGUI.checkBox(box2, self, 'graph.jitterContinuous', 'Jitter continuous attributes', callback = self.resetGraphData, tooltip = "Does jittering apply also on continuous attributes?") 
    136          
     136 
    137137        # general graph settings 
    138138        box4 = OWGUI.collapsableWidgetBox(self.SettingsTab, "General Graph Settings", self, "boxGeneral") 
     
    142142        OWGUI.checkBox(box4, self, 'graph.showLegend', 'Show legend', callback = self.updateGraph) 
    143143        OWGUI.checkBox(box4, self, 'graph.showFilledSymbols', 'Show filled symbols', callback = self.updateGraph) 
    144         OWGUI.checkBox(box4, self, 'graph.optimizedDrawing', 'Optimize drawing', callback = self.updateGraph, tooltip = "Speed up drawing by drawing all point belonging to one class value at once") 
    145144        OWGUI.checkBox(box4, self, 'showGridlines', 'Show gridlines', callback = self.setShowGridlines) 
    146145##        OWGUI.checkBox(box4, self, 'graph.showClusters', 'Show clusters', callback = self.updateGraph, tooltip = "Show a line boundary around a significant cluster") 
     
    166165        self.colorButtonsBox = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal") 
    167166        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) 
    168          
     167 
    169168        box5 = OWGUI.widgetBox(self.SettingsTab, "Tooltips Settings") 
    170169        OWGUI.comboBox(box5, self, "graph.tooltipKind", items = ["Don't show tooltips", "Show visible attributes", "Show all attributes"], callback = self.updateGraph) 
    171170 
    172 ##        self.activeLearnerCombo = OWGUI.comboBox(self.SettingsTab, self, "learnerIndex", box = "Set Active Learner", items = ["VizRank Learner", "Cluster Learner"], tooltip = "Select which of the possible learners do you want to send on the widget output.") 
    173         self.activeLearnerCombo = OWGUI.comboBox(self.SettingsTab, self, "learnerIndex", box = "Set Active Learner", items = ["VizRank Learner"], tooltip = "Select which of the possible learners do you want to send on the widget output.") 
    174         self.connect(self.activeLearnerCombo, SIGNAL("activated(int)"), self.setActiveLearner) 
    175      
    176171        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.") 
    177         self.graph.autoSendSelectionCallback = self.setAutoSendSelection 
    178  
    179         OWGUI.rubber(self.SettingsTab)         
     172        self.graph.selectionChangedCallback = self.setAutoSendSelection 
     173 
     174        OWGUI.rubber(self.SettingsTab) 
    180175        self.SettingsTab.setMinimumWidth(max(self.GeneralTab.sizeHint().width(), self.SettingsTab.sizeHint().width())+20) 
    181176        self.icons = self.createAttributeIconDict() 
    182          
     177 
    183178        self.debugSettings = ["attrX", "attrY", "attrColor", "attrLabel", "attrShape", "attrSize"] 
    184179        self.activateLoadedSettings() 
    185180        self.resize(700, 550) 
    186181 
    187      
     182 
    188183    def activateLoadedSettings(self): 
    189184        dlg = self.createColorDialog() 
     
    192187        self.graph.setCanvasBackground(dlg.getColor("Canvas")) 
    193188        self.graph.setGridPen(QPen(dlg.getColor("Grid"))) 
    194                  
     189 
    195190        self.graph.enableGridXB(self.showGridlines) 
    196191        self.graph.enableGridYL(self.showGridlines) 
    197192 
    198193        apply([self.zoomSelectToolbar.actionZooming, self.zoomSelectToolbar.actionRectangleSelection, self.zoomSelectToolbar.actionPolygonSelection][self.toolbarSelection], []) 
    199  
    200 ##        self.clusterDlg.changeLearnerName(self.clusterClassifierName) 
    201         self.learnersArray[1] = VizRankLearner(SCATTERPLOT, self.vizrank, self.graph) 
    202         self.setActiveLearner(self.learnerIndex) 
    203194 
    204195    def settingsFromWidgetCallback(self, handler, context): 
     
    227218 
    228219    # receive new data and update all fields 
    229     def setData(self, data, clearResults = 1): 
     220    def setData(self, data, clearResults = 1, onlyDataSubset = 0): 
    230221        if data: 
    231222            name = getattr(data, "name", "") 
     
    244235        self.classificationResults = None 
    245236        self.outlierValues = None 
    246          
     237 
    247238        self.vizrank.setData(data) 
     239        self.explorerDlg.setData(self.data) 
    248240##        self.clusterDlg.setData(data, clearResults) 
    249          
     241 
    250242        sameDomain = self.data and exData and exData.domain.checksum() == self.data.domain.checksum() # preserve attribute choice if the domain is the same 
    251243        if not sameDomain: 
     
    253245 
    254246        self.openContext("", data) 
     247 
     248        if data and self.unprocessedSubsetData:        # if we first received subset data we now have to call setSubsetData to process it 
     249            self.setSubsetData(self.unprocessedSubsetData) 
     250            self.unprocessedSubsetData = None 
     251 
     252 
     253    # set an example table with a data subset subset of the data. if called by a visual classifier, the update parameter will be 0 
     254    def setSubsetData(self, data): 
     255        # if we haven't yet received the main data we just remember this data and return 
     256        if not self.data: 
     257            self.unprocessedSubsetData = data 
     258            self.warning(10) 
     259            return 
     260 
     261        # check if the new data set is the same as the old one 
     262        if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): 
     263            return 
     264 
     265        try: 
     266            subsetData = data.select(self.data.domain) 
     267            self.warning(10) 
     268        except: 
     269            subsetData = None 
     270            self.warning(10, data and "'Examples' and 'Example Subset' data do not have copatible domains. Unable to draw 'Example Subset' data." or "") 
     271 
     272        self.vizrank.setSubsetData(subsetData) 
     273##        self.clusterDlg.setSubsetData(data) 
     274#        qApp.processEvents()            # TODO: find out why scatterplot crashes if we remove this line and send a subset of data that is not in self.rawdata - as in cluster argumentation 
     275 
     276    # this is called by OWBaseWidget after setData and setSubsetData are called. this way the graph is updated only once 
     277    def handleNewSignals(self): 
    255278        self.updateGraph() 
    256  
    257279        self.sendSelections() 
    258280 
    259     # set an example table with a data subset subset of the data. if called by a visual classifier, the update parameter will be 0 
    260     def setSubsetData(self, data, update = 1): 
    261         if self.graph.subsetData != None and data != None and self.graph.subsetData.checksum() == data.checksum(): return    # check if the new data set is the same as the old one 
    262         self.graph.subsetData = data 
    263         qApp.processEvents()            # TODO: find out why scatterplot crashes if we remove this line and send a subset of data that is not in self.rawdata - as in cluster argumentation 
    264         if update: self.updateGraph() 
    265         self.vizrank.setSubsetData(data) 
    266 ##        self.clusterDlg.setSubsetData(data) 
    267         
    268281 
    269282    # receive information about which attributes we want to show on x and y axis 
    270     def setAttributeSelection(self, list): 
     283    def setShownAttributes(self, list): 
    271284        if not self.data or not list or len(list) < 2: return 
    272285        self.attrX = list[0] 
     
    276289 
    277290    # visualize the results of the classification 
    278     def setTestResults(self, results):         
     291    def setTestResults(self, results): 
    279292        self.classificationResults = None 
    280293        if isinstance(results, orngTest.ExperimentResults) and len(results.results) > 0 and len(results.results[0].probabilities) > 0: 
     
    283296 
    284297        self.updateGraph() 
    285  
    286298 
    287299    # set the learning method to be used in VizRank 
     
    300312    # ############################################################################################################################################################## 
    301313 
    302     def setActiveLearner(self, idx): 
    303         self.send("Learner", self.learnersArray[self.learnerIndex]) 
    304     
    305      
    306314##    # ################################################################################################ 
    307315##    # find projections that have tight clusters of points that belong to the same class value 
    308316##    def optimizeClusters(self): 
    309317##        if self.data == None: return 
    310 ##         
     318## 
    311319##        self.clusterDlg.clearResults() 
    312320##        self.clusterDlg.clusterStabilityButton.setOn(0) 
     
    334342 
    335343        self.majorUpdateGraph(attrs) 
    336          
     344 
    337345 
    338346##    def showSelectedCluster(self): 
     
    348356##        self.majorUpdateGraph(attrList, insideColors, (closure, enlargedClosure, classValue)) 
    349357 
    350         
     358 
    351359    # ############################################################################################################################################################## 
    352360    # ATTRIBUTE SELECTION 
     
    388396        if self.attrYCombo.count() > 1: self.attrY = str(self.attrYCombo.text(1)) 
    389397        else:                           self.attrY = str(self.attrYCombo.text(0)) 
    390              
     398 
    391399        if self.data.domain.classVar: 
    392400            self.attrColor = self.data.domain.classVar.name 
     
    405413        if not self.data: 
    406414            return 
    407      
     415 
    408416        if attrList and len(attrList) == 2: 
    409417            self.attrX = attrList[0] 
     
    417425        else: 
    418426            kNNExampleAccuracy = None 
    419              
     427 
    420428        self.graph.insideColors = insideColors or self.classificationResults or kNNExampleAccuracy or self.outlierValues 
    421429##        self.graph.clusterClosure = clusterClosure 
     
    423431        self.graph.updateData(self.attrX, self.attrY, self.attrColor, self.attrShape, self.attrSize, self.showColorLegend, self.attrLabel) 
    424432        self.graph.repaint() 
    425  
    426      
     433        self.explorerDlg.updateState() 
     434 
     435 
    427436    # ############################################################################################################################################################## 
    428437    # SCATTERPLOT SETTINGS 
     
    446455 
    447456    def setAutoSendSelection(self): 
     457        self.explorerDlg.updateState() 
    448458        if self.autoSendSelection: 
    449459            self.zoomSelectToolbar.buttonSendSelections.setEnabled(0) 
     
    456466        if dlg.exec_loop(): 
    457467            self.colorSettings = dlg.getColorSchemas() 
     468            self.selectedSchemaIndex = dlg.selectedSchemaIndex 
    458469            self.graph.contPalette = dlg.getContinuousPalette("contPalette") 
    459470            self.graph.discPalette = dlg.getDiscretePalette() 
     
    472483        box.addSpace(5) 
    473484        box.adjustSize() 
    474         c.setColorSchemas(self.colorSettings) 
     485        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) 
    475486        return c 
    476487 
     
    493504    ow.show() 
    494505    a.exec_loop() 
    495     #save settings  
     506    #save settings 
    496507    ow.saveSettings() 
  • orange/OrangeWidgets/Visualize/OWScatterPlotGraph.py

    r3454 r3483  
    2424        OWGraph.__init__(self, parent, name) 
    2525        orngScaleScatterPlotData.__init__(self) 
    26      
     26 
    2727        self.pointWidth = 5 
    2828        self.jitterContinuous = 0 
     
    3232        self.showYLaxisTitle = 1 
    3333        self.showLegend = 1 
    34         self.showDistributions = 0         
    35         self.optimizedDrawing = 1 
    3634##        self.showClusters = 0 
    3735        self.tooltipKind = 1 
    3836        self.showFilledSymbols = 1 
    3937        self.showProbabilities = 1 
    40          
     38 
    4139        self.toolRects = [] 
    4240        self.tooltipData = [] 
     
    5048        self.squareGranularity = 3 
    5149        self.spaceBetweenCells = 1 
    52          
     50 
    5351        self.oldShowColorLegend = -1 
    5452        self.oldLegendKeys = {} 
     
    6967        self.shownXAttribute = xAttr 
    7068        self.shownYAttribute = yAttr 
    71          
     69 
    7270        # if we have some subset data then we show the examples in the data set with full symbols, others with empty 
    73         haveSubsetData = (self.subsetData and self.rawdata and self.subsetData.domain == self.rawdata.domain) 
    74              
     71        haveSubsetData = (self.subsetData and self.rawdata and self.subsetData.domain.checksum() == self.rawdata.domain.checksum()) 
     72 
    7573        if self.scaledData == None or len(self.scaledData) == 0: 
    7674            #self.setAxisScale(QwtPlot.xBottom, 0, 1, 1); self.setAxisScale(QwtPlot.yLeft, 0, 1, 1) 
    7775            self.setXaxisTitle(""); self.setYLaxisTitle("") 
    7876            return 
    79          
     77 
    8078        self.__dict__.update(args)      # set value from args dictionary 
    8179 
     
    8583            if self.rawdata.domain[colorAttr].varType == orange.VarTypes.Discrete: 
    8684                colorIndices = getVariableValueIndices(self.rawdata, colorIndex) 
    87              
     85 
    8886        shapeIndex = -1 
    8987        shapeIndices = {} 
     
    9391                shapeIndices = getVariableValueIndices(self.rawdata, shapeIndex) 
    9492 
    95         sizeShapeIndex = -1 
     93        sizeIndex = -1 
    9694        if sizeShapeAttr != "" and sizeShapeAttr != "(One size)": 
    97             sizeShapeIndex = self.attributeNameIndex[sizeShapeAttr] 
     95            sizeIndex = self.attributeNameIndex[sizeShapeAttr] 
    9896 
    9997        showColorLegend = showColorLegend and colorIndex != -1 and self.rawdata.domain[colorIndex].varType == orange.VarTypes.Continuous 
     
    10199        (xVarMin, xVarMax) = self.attrValues[xAttr] 
    102100        (yVarMin, yVarMax) = self.attrValues[yAttr] 
     101        if haveSubsetData: 
     102            xVarMin = min(xVarMin, self.attrSubValues[xAttr][0]) 
     103            xVarMax = max(xVarMax, self.attrSubValues[xAttr][1]) 
     104            yVarMin = min(yVarMin, self.attrSubValues[yAttr][0]) 
     105            yVarMax = max(yVarMax, self.attrSubValues[yAttr][1]) 
    103106        xVar = xVarMax - xVarMin 
    104107        yVar = yVarMax - yVarMin 
     
    106109        yAttrIndex = self.attributeNameIndex[yAttr] 
    107110 
    108         attrIndices = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeShapeIndex] 
     111        attrIndices = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeIndex] 
    109112        while -1 in attrIndices: attrIndices.remove(-1) 
    110113        self.shownAttributeIndices = attrIndices 
    111      
     114 
    112115        # set axis for x attribute 
    113116        attrXIndices = {} 
     
    126129        self.setXlabels(labels) 
    127130        self.setAxisScale(QwtPlot.xBottom, xmin, xmax + showColorLegend * xVar * 0.07, discreteX) 
    128          
     131 
    129132        # set axis for y attribute 
    130133        attrYIndices = {} 
     
    132135        if discreteY: 
    133136            yVarMax -= 1; yVar -= 1 
    134             ymin = yVarMin - (self.jitterSize + 10.)/100.  
     137            ymin = yVarMin - (self.jitterSize + 10.)/100. 
    135138            ymax = yVarMax + (self.jitterSize + 10.)/100. 
    136139            attrYIndices = getVariableValueIndices(self.rawdata, yAttrIndex) 
     
    138141        else: 
    139142            off  = (yVarMax - yVarMin) * (self.jitterSize * self.jitterContinuous + 2) / 100.0 
    140             ymin = yVarMin - off  
     143            ymin = yVarMin - off 
    141144            ymax = yVarMax + off 
    142145            labels = None 
     
    148151        self.oldShowColorLegend = showColorLegend 
    149152 
    150         # compute x and y positions of the points in the scatterplot         
     153        # compute x and y positions of the points in the scatterplot 
    151154        xData, yData = self.getXYPositions(xAttr, yAttr) 
    152155        validData = self.getValidList(attrIndices)      # get examples that have valid data for each used attribute 
     
    154157        # ####################################################### 
    155158        # show probabilities 
    156         if self.showProbabilities and colorIndex >= 0: 
    157             domain = orange.Domain([self.rawdata.domain[xAttrIndex], self.rawdata.domain[yAttrIndex], self.rawdata.domain[colorIndex]], self.rawdata.domain) 
     159        if self.showProbabilities and colorIndex >= 0 and self.rawdata.domain.classVar: 
     160            domain = orange.Domain([self.rawdata.domain[xAttrIndex], self.rawdata.domain[yAttrIndex], self.rawdata.domain.classVar], self.rawdata.domain) 
    158161            xdiff = xmax-xmin; ydiff = ymax-ymin 
    159162            scX = [x/xdiff for x in xData] 
    160163            scY = [y/ydiff for y in yData] 
    161164            clsData = list(numpy.transpose(numpy.take(self.originalData, [colorIndex], axis = 0))) 
    162              
     165 
    163166            data = numpy.transpose(numpy.array([scX, scY, clsData])) 
    164167            data = numpy.compress(validData, data, axis = 0) 
     
    167170            self.xmin = xmin; self.xmax = xmax 
    168171            self.ymin = ymin; self.ymax = ymax 
    169              
     172 
    170173 
    171174##        # ####################################################### 
     
    174177##            data = self.createProjectionAsExampleTable([xAttrIndex, yAttrIndex], validData = validData, jitterSize = 0.001 * self.clusterOptimization.jitterDataBeforeTriangulation) 
    175178##            graph, valueDict, closureDict, polygonVerticesDict, enlargedClosureDict, otherDict = self.clusterOptimization.evaluateClusters(data) 
    176 ##             
     179## 
    177180##            classIndices = getVariableValueIndices(self.rawdata, self.attributeNameIndex[self.rawdata.domain.classVar.name]) 
    178181##            indices = numpy.compress(validData, numpy.array(range(len(self.rawdata)))) 
    179 ##             
     182## 
    180183##            for key in valueDict.keys(): 
    181184##                if not polygonVerticesDict.has_key(key): continue 
     
    191194##                self.marker(mkey).setYValue(float(self.rawdata[i][yAttrIndex])) 
    192195##                self.marker(mkey).setLabelAlignment(Qt.AlignCenter + Qt.AlignBottom) 
    193 ##             
     196## 
    194197##        elif self.clusterClosure: self.showClusterLines(xAttr, yAttr) 
    195198 
    196199        # ############################################################## 
    197         # show the distributions 
    198         if self.showDistributions == 1 and colorIndex != -1 and self.rawdata.domain[colorIndex].varType == orange.VarTypes.Discrete and self.rawdata.domain[xAttrIndex].varType == orange.VarTypes.Discrete and self.rawdata.domain[yAttrIndex].varType == orange.VarTypes.Discrete and not self.insideColors: 
    199             (cart, profit) = FeatureByCartesianProduct(self.rawdata, [self.rawdata.domain[xAttrIndex], self.rawdata.domain[yAttrIndex]]) 
    200             tempData = self.rawdata.select(list(self.rawdata.domain) + [cart]) 
    201             contXY = orange.ContingencyAttrClass(cart, tempData)   # distribution of X attribute 
    202             xValues = getVariableValuesSorted(self.rawdata, xAttr) 
    203             yValues = getVariableValuesSorted(self.rawdata, yAttr) 
    204             classValuesSorted = getVariableValuesSorted(self.rawdata, colorIndex) 
    205             classValues = list(self.rawdata.domain[colorIndex].values) 
    206             self.tooltipData = [] 
    207  
    208             sum = 0 
    209             for table in contXY: 
    210                 for val in table: sum += val 
    211  
    212             for i in range(len(xValues)): 
    213                 for j in range(len(yValues)): 
    214                     try: distribution = contXY[str(xValues[i])+'-'+str(yValues[j])] 
    215                     except: continue 
    216                     tempSum = 0 
    217                     for val in distribution: tempSum += val 
    218                     if tempSum == 0: continue 
    219  
    220                     tooltipText = "Nr. of examples: <b>%d</b> (%.2f%%) <br>Distribution:" % (tempSum, 100.0*float(tempSum)/float(sum)) 
    221                     out = [0.0] 
    222                     key = self.addCurve(QwtPlotCurvePieChart(self), QColor(), QColor(), 0, style = QwtCurve.UserCurve, symbol = QwtSymbol.None) 
    223                     for classVal in classValuesSorted: 
    224                         val = classValues.index(classVal) 
    225                         out += [out[-1] + float(distribution[val])/float(tempSum)] 
    226                         tooltipText += "<br>%s : <b>%d</b> (%.2f%%)" % (classVal, distribution[val], 100.0*distribution[val]/float(tempSum)) 
    227                     self.setCurveData(key, [i, j] + [0]*(len(out)-2), out) 
    228                     self.curve(key).percentOfTotalData = float(tempSum) / float(sum) 
    229                     self.tooltipData.append((tooltipText, i, j)) 
    230             self.addTooltips() 
     200        # if we have insideColors defined 
     201        if self.insideColors and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete: 
     202            # variables and domain for the table 
     203            classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name) 
     204            (insideData, stringData) = self.insideColors 
     205            j = 0 
     206            equalSize = len(self.rawdata) == len(insideData) 
     207            for i in range(len(self.rawdata)): 
     208                if not validData[i]: 
     209                    j += equalSize 
     210                    continue 
     211 
     212                fillColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value], 255*insideData[j]] 
     213                edgeColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]] 
     214 
     215                x = xData[i] 
     216                y = yData[i] 
     217                key = self.addCurve(str(i), fillColor, edgeColor, self.pointWidth, xData = [x], yData = [y]) 
     218 
     219                # we add a tooltip for this point 
     220                self.addTip(x, y, text = self.getExampleTooltipText(self.rawdata, self.rawdata[j], attrIndices)) 
     221                j+=1 
    231222 
    232223        # ############################################################## 
    233         # show normal scatterplot with dots 
     224        # no subset data and discrete color index 
     225        elif (colorIndex == -1 or self.rawdata.domain[colorIndex].varType == orange.VarTypes.Discrete) and shapeIndex == -1 and sizeIndex == -1 and not haveSubsetData and not labelAttr: 
     226            if colorIndex != -1: 
     227                classCount = len(colorIndices) 
     228            else: classCount = 1 
     229 
     230            pos = [[ [] , [], [] ] for i in range(classCount)] 
     231            indices = [colorIndex, xAttrIndex, yAttrIndex] 
     232            if -1 in indices: indices.remove(-1) 
     233            validData = self.getValidList(indices) 
     234            for i in range(len(self.rawdata)): 
     235                if not validData[i]: continue 
     236                x = xData[i] 
     237                y = yData[i] 
     238 
     239                if colorIndex != -1: index = colorIndices[self.rawdata[i][colorIndex].value] 
     240                else:                index = 0 
     241                pos[index][0].append(x) 
     242                pos[index][1].append(y) 
     243                pos[index][2].append(i) 
     244 
     245                # we add a tooltip for this point 
     246                self.tips.addToolTip(x, y, i) 
     247 
     248            for i in range(classCount): 
     249                if colorIndex != -1: newColor = self.discPalette[i] 
     250                else:                newColor = Qt.black 
     251                key = self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = self.curveSymbols[0], xData = pos[i][0], yData = pos[i][1]) 
     252 
     253 
     254        # ############################################################## 
     255        # slower, unoptimized drawing because we use different symbols and/or different sizes of symbols 
    234256        else: 
    235             if self.insideColors and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete: 
    236                 # variables and domain for the table 
    237                 classValueIndices = getVariableValueIndices(self.rawdata, self.rawdata.domain.classVar.name) 
    238                 (insideData, stringData) = self.insideColors 
    239                 j = 0 
    240                 equalSize = len(self.rawdata) == len(insideData) 
    241                 for i in range(len(self.rawdata)): 
    242                     if not validData[i]: 
    243                         j += equalSize 
    244                         continue 
    245                      
    246                     fillColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value], 255*insideData[j]] 
    247                     edgeColor = self.discPalette[classValueIndices[self.rawdata[i].getclass().value]] 
    248  
    249                     x = xData[i] 
    250                     y = yData[i] 
    251                     key = self.addCurve(str(i), fillColor, edgeColor, self.pointWidth, xData = [x], yData = [y]) 
    252  
    253                     # we add a tooltip for this point 
    254                     self.addTip(x, y, text = self.getExampleTooltipText(self.rawdata, self.rawdata[j], attrIndices)) 
    255                     j+=1 
    256                      
    257             # ############################################################## 
    258             # create a small number of curves which will make drawing much faster 
    259             # ############################################################## 
    260             elif self.optimizedDrawing and (colorIndex == -1 or self.rawdata.domain[colorIndex].varType == orange.VarTypes.Discrete) and shapeIndex == -1 and sizeShapeIndex == -1 and not haveSubsetData and not labelAttr: 
     257            shownSubsetCount = 0 
     258            attrs = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeIndex] 
     259            while -1 in attrs: attrs.remove(-1) 
     260            validData = self.getValidList(attrs) 
     261            if self.subsetData: 
     262                subsetReferencesToDraw = [example.reference() for example in self.subsetData] 
     263            showFilled = self.showFilledSymbols 
     264 
     265            xPointsToAdd = {} 
     266            yPointsToAdd = {} 
     267            for i in range(len(self.rawdata)): 
     268                if not validData[i]: continue 
     269                x = xData[i] 
     270                y = yData[i] 
     271 
    261272                if colorIndex != -1: 
    262                     classCount = len(colorIndices) 
    263                 else: classCount = 1 
    264  
    265                 pos = [[ [] , [], [] ] for i in range(classCount)] 
    266                 indices = [colorIndex, xAttrIndex, yAttrIndex] 
    267                 if -1 in indices: indices.remove(-1) 
    268                 validData = self.getValidList(indices) 
    269                 for i in range(len(self.rawdata)): 
    270                     if not validData[i]: continue 
    271                     x = xData[i] 
    272                     y = yData[i] 
    273  
    274                     if colorIndex != -1: index = colorIndices[self.rawdata[i][colorIndex].value] 
    275                     else:                index = 0 
    276                     pos[index][0].append(x) 
    277                     pos[index][1].append(y) 
    278                     pos[index][2].append(i) 
    279  
    280                     # we add a tooltip for this point 
    281                     self.tips.addToolTip(x, y, i) 
    282  
    283                 for i in range(classCount): 
    284                     if colorIndex != -1: newColor = self.discPalette[i] 
    285                     else:                newColor = QColor(0,0,0) 
    286                     key = self.addCurve(str(i), newColor, newColor, self.pointWidth, symbol = self.curveSymbols[0], xData = pos[i][0], yData = pos[i][1]) 
    287                  
    288  
    289             # ############################################################## 
    290             # slow, unoptimized drawing because we use different symbols and/or different sizes of symbols 
    291             # ############################################################## 
    292             else: 
    293                 shownSubsetCount = 0 
    294                 attrs = [xAttrIndex, yAttrIndex, colorIndex, shapeIndex, sizeShapeIndex] 
    295                 while -1 in attrs: attrs.remove(-1) 
    296                 validData = self.getValidList(attrs) 
    297                 if self.subsetData: 
    298                     subsetReferencesToDraw = [example.reference() for example in self.subsetData] 
    299                 showFilled = self.showFilledSymbols 
    300                  
    301                 for i in range(len(self.rawdata)): 
    302                     if not validData[i]: continue 
    303                     x = xData[i] 
    304                     y = yData[i] 
    305                      
    306                     if colorIndex != -1: 
     273                    if self.rawdata.domain[colorIndex].varType == orange.VarTypes.Continuous: 
     274                        newColor = self.contPalette[self.noJitteringScaledData[colorIndex][i]] 
     275                    else: 
     276                        newColor = self.discPalette[colorIndices[self.rawdata[i][colorIndex].value]] 
     277                else: newColor = Qt.black 
     278 
     279                Symbol = self.curveSymbols[0] 
     280                if shapeIndex != -1: Symbol = self.curveSymbols[shapeIndices[self.rawdata[i][shapeIndex].value]] 
     281 
     282                size = self.pointWidth 
     283                if sizeIndex != -1: size = MIN_SHAPE_SIZE + round(self.noJitteringScaledData[sizeIndex][i] * self.pointWidth) 
     284 
     285                if haveSubsetData: 
     286                    showFilled = self.rawdata[i].reference() in subsetReferencesToDraw 
     287                    shownSubsetCount += showFilled 
     288 
     289                if not xPointsToAdd.has_key((newColor, size, Symbol, showFilled)): 
     290                    xPointsToAdd[(newColor, size, Symbol, showFilled)] = [] 
     291                    yPointsToAdd[(newColor, size, Symbol, showFilled)] = [] 
     292                xPointsToAdd[(newColor, size, Symbol, showFilled)].append(x) 
     293                yPointsToAdd[(newColor, size, Symbol, showFilled)].append(y) 
     294                self.tips.addToolTip(x, y, i)     # we add a tooltip for this point 
     295 
     296                # Show a label by each marker 
     297                if labelAttr: 
     298                    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]: 
     299                        if self.rawdata[i][labelAttr].isSpecial(): continue 
     300                        if self.rawdata[i][labelAttr].varType==orange.VarTypes.Continuous: 
     301                            lbl = "%4.1f" % orange.Value(self.rawdata[i][labelAttr]) 
     302                        else: 
     303                            lbl = str(self.rawdata[i][labelAttr].value) 
     304                        mkey = self.insertMarker(lbl) 
     305                        self.marker(mkey).setXValue(float(x)) 
     306                        self.marker(mkey).setYValue(float(y)) 
     307                        self.marker(mkey).setLabelAlignment(Qt.AlignCenter + Qt.AlignBottom) 
     308 
     309            # if we have a data subset that contains examples that don't exist in the original dataset we show them here 
     310            if haveSubsetData and shownSubsetCount < len(self.subsetData): 
     311                for i in range(len(self.subsetData)): 
     312                    if not self.subsetData[i].reference() in subsetReferencesToDraw: continue 
     313                    if self.subsetData[i][xAttrIndex].isSpecial() or self.subsetData[i][yAttrIndex].isSpecial() : continue 
     314                    if colorIndex != -1 and self.subsetData[i][colorIndex].isSpecial() : continue 
     315                    if shapeIndex != -1 and self.subsetData[i][shapeIndex].isSpecial() : continue 
     316                    if sizeIndex != -1 and self.subsetData[i][sizeIndex].isSpecial() : continue 
     317 
     318                    if discreteX == 1: x = attrXIndices[self.subsetData[i][xAttrIndex].value] + self.rndCorrection(float(self.jitterSize) / 100.0) 
     319                    elif self.jitterContinuous:     x = self.subsetData[i][xAttrIndex].value + self.rndCorrection(float(self.jitterSize*xVar) / 100.0) 
     320                    else:                           x = self.subsetData[i][xAttrIndex].value 
     321 
     322                    if discreteY == 1: y = attrYIndices[self.subsetData[i][yAttrIndex].value] + self.rndCorrection(float(self.jitterSize) / 100.0) 
     323                    elif self.jitterContinuous:     y = self.subsetData[i][yAttrIndex].value + self.rndCorrection(float(self.jitterSize*yVar) / 100.0) 
     324                    else:                           y = self.subsetData[i][yAttrIndex].value 
     325 
     326                    if colorIndex != -1 and not self.subsetData[i][colorIndex].isSpecial(): 
     327                        val = min(1.0, max(0.0, self.scaleExampleValue(self.subsetData[i], colorIndex)))    # scale to 0-1 interval 
    307328                        if self.rawdata.domain[colorIndex].varType == orange.VarTypes.Continuous: 
    308                             newColor = self.contPalette[self.noJitteringScaledData[colorIndex][i]] 
     329                            newColor = self.contPalette[val] 
    309330                        else: 
    310                             newColor = self.discPalette[colorIndices[self.rawdata[i][colorIndex].value]] 
    311                     else: newColor = QColor(0,0,0) 
    312                              
    313                     Symbol = self.curveSymbols[0] 
    314                     if shapeIndex != -1: Symbol = self.curveSymbols[shapeIndices[self.rawdata[i][shapeIndex].value]] 
    315  
    316                     size = self.pointWidth 
    317                     if sizeShapeIndex != -1: size = MIN_SHAPE_SIZE + round(self.noJitteringScaledData[sizeShapeIndex][i] * self.pointWidth) 
    318                      
    319                     if haveSubsetData: 
    320                         showFilled = self.rawdata[i].reference() in subsetReferencesToDraw 
    321                         shownSubsetCount += showFilled 
    322  
    323                     self.addCurve(str(i), newColor, newColor, size, symbol = Symbol, xData = [x], yData = [y], showFilledSymbols = showFilled) 
     331                            newColor = self.discPalette[colorIndices[self.subsetData[i][colorIndex].value]] 
     332                    else: newColor = Qt.black 
     333 
     334                    if shapeIndex != -1: Symbol = self.curveSymbols[shapeIndices[self.subsetData[i][shapeIndex].value]] 
     335                    else:                Symbol = self.curveSymbols[0] 
     336 
     337                    size = self.pointWidth        # we don't have the scaled subsetData so we just use the pointWidth 
     338 
     339                    if not xPointsToAdd.has_key((newColor, size, Symbol, 1)): 
     340                        xPointsToAdd[(newColor, size, Symbol, 1)] = [] 
     341                        yPointsToAdd[(newColor, size, Symbol, 1)] = [] 
     342                    xPointsToAdd[(newColor, size, Symbol, 1)].append(x) 
     343                    yPointsToAdd[(newColor, size, Symbol, 1)].append(y) 
    324344 
    325345                    # Show a label by each marker 
    326346                    if labelAttr: 
    327                         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]: 
    328                             if self.rawdata[i][labelAttr].isSpecial(): continue 
    329                             if self.rawdata[i][labelAttr].varType==orange.VarTypes.Continuous: 
    330                                 lbl = "%4.1f" % orange.Value(self.rawdata[i][labelAttr]) 
     347                        if labelAttr in [self.subsetData.domain.getmeta(mykey).name for mykey in self.subsetData.domain.getmetas().keys()] + [var.name for var in self.subsetData.domain]: 
     348                            if self.subsetData[i][labelAttr].isSpecial(): continue 
     349                            if self.subsetData[i][labelAttr].varType==orange.VarTypes.Continuous: 
     350                                lbl = "%4.1f" % orange.Value(self.subsetData[i][labelAttr]) 
    331351                            else: 
    332                                 lbl = str(self.rawdata[i][labelAttr].value) 
     352                                lbl = str(self.subsetData[i][labelAttr].value) 
    333353                            mkey = self.insertMarker(lbl) 
    334354                            self.marker(mkey).setXValue(float(x)) 
    335355                            self.marker(mkey).setYValue(float(y)) 
    336356                            self.marker(mkey).setLabelAlignment(Qt.AlignCenter + Qt.AlignBottom) 
    337                          
    338                     # we add a tooltip for this point 
    339                     self.tips.addToolTip(x, y, i) 
    340  
    341                 # if we have a data subset that contains examples that don't exist in the original dataset we show them here 
    342                 if haveSubsetData and shownSubsetCount < len(self.subsetData): 
    343                     for i in range(len(self.subsetData)): 
    344                         if not self.subsetData[i].reference() in subsetReferencesToDraw: continue 
    345                         if self.subsetData[i][xAttrIndex].isSpecial() or self.subsetData[i][yAttrIndex].isSpecial() : continue 
    346                         if colorIndex != -1 and self.subsetData[i][colorIndex].isSpecial() : continue 
    347                         if shapeIndex != -1 and self.subsetData[i][shapeIndex].isSpecial() : continue 
    348                         if sizeShapeIndex != -1 and self.subsetData[i][sizeShapeIndex].isSpecial() : continue 
    349                          
    350                         if discreteX == 1: x = attrXIndices[self.subsetData[i][xAttrIndex].value] + self.rndCorrection(float(self.jitterSize) / 100.0) 
    351                         elif self.jitterContinuous:     x = self.subsetData[i][xAttrIndex].value + self.rndCorrection(float(self.jitterSize*xVar) / 100.0) 
    352                         else:                           x = self.subsetData[i][xAttrIndex].value 
    353  
    354                         if discreteY == 1: y = attrYIndices[self.subsetData[i][yAttrIndex].value] + self.rndCorrection(float(self.jitterSize) / 100.0) 
    355                         elif self.jitterContinuous:     y = self.subsetData[i][yAttrIndex].value + self.rndCorrection(float(self.jitterSize*yVar) / 100.0) 
    356                         else:                           y = self.subsetData[i][yAttrIndex].value 
    357  
    358                         if colorIndex != -1 and not self.subsetData[i][colorIndex].isSpecial(): 
    359                             val = min(1.0, max(0.0, self.scaleExampleValue(self.subsetData[i], colorIndex)))    # scale to 0-1 interval 
    360                             if self.rawdata.domain[colorIndex].varType == orange.VarTypes.Continuous: 
    361                                 newColor = self.contPalette[val] 
    362                             else: 
    363                                 newColor = self.discPalette[colorIndices[self.subsetData[i][colorIndex].value]] 
    364                         else: newColor = QColor(0,0,0) 
    365                                  
    366                         Symbol = self.curveSymbols[0] 
    367                         if shapeIndex != -1: Symbol = self.curveSymbols[shapeIndices[self.subsetData[i][shapeIndex].value]] 
    368  
    369                         size = self.pointWidth 
    370                         #if sizeShapeIndex != -1: size = MIN_SHAPE_SIZE + round(self.noJitteringScaledData[sizeShapeIndex][i] * self.pointWidth) 
    371                         self.addCurve(str(i), newColor, newColor, size, symbol = Symbol, xData = [x], yData = [y], showFilledSymbols = 1) 
    372  
    373                         # Show a label by each marker 
    374                         if labelAttr: 
    375                             if labelAttr in [self.subsetData.domain.getmeta(mykey).name for mykey in self.subsetData.domain.getmetas().keys()] + [var.name for var in self.subsetData.domain]: 
    376                                 if self.subsetData[i][labelAttr].isSpecial(): continue 
    377                                 if self.subsetData[i][labelAttr].varType==orange.VarTypes.Continuous: 
    378                                     lbl = "%4.1f" % orange.Value(self.subsetData[i][labelAttr]) 
    379                                 else: 
    380                                     lbl = str(self.subsetData[i][labelAttr].value) 
    381                                 mkey = self.insertMarker(lbl) 
    382                                 self.marker(mkey).setXValue(float(x)) 
    383                                 self.marker(mkey).setYValue(float(y)) 
    384                                 self.marker(mkey).setLabelAlignment(Qt.AlignCenter + Qt.AlignBottom) 
    385  
    386          
     357 
     358            for i, (color, size, symbol, showFilled) in enumerate(xPointsToAdd.keys()): 
     359                xData = xPointsToAdd[(color, size, symbol, showFilled)] 
     360                yData = yPointsToAdd[(color, size, symbol, showFilled)] 
     361                self.addCurve(str(i), color, color, size, symbol = symbol, xData = xData, yData = yData, showFilledSymbols = showFilled) 
     362 
    387363        # ############################################################## 
    388364        # show legend if necessary 
     
    401377                num = len(self.rawdata.domain[shapeIndex].values) 
    402378                if legendKeys.has_key(shapeIndex):  val = legendKeys[shapeIndex] 
    403                 else:                               val = [[], [QColor(0,0,0)]*num, [self.pointWidth]*num, []] 
     379                else:                               val = [[], [Qt.black]*num, [self.pointWidth]*num, []] 
    404380                varValues = getVariableValuesSorted(self.rawdata, shapeIndex) 
    405381                val[3] = []; val[0] = [] 
     
    409385                legendKeys[shapeIndex] = val 
    410386 
    411             if sizeShapeIndex != -1 and self.rawdata.domain[sizeShapeIndex].varType == orange.VarTypes.Discrete: 
    412                 num = len(self.rawdata.domain[sizeShapeIndex ].values) 
    413                 if legendKeys.has_key(sizeShapeIndex):  val = legendKeys[sizeShapeIndex] 
    414                 else:                               val = [[], [QColor(0,0,0)]*num, [], [QwtSymbol.Ellipse]*num] 
     387            if sizeIndex != -1 and self.rawdata.domain[sizeIndex].varType == orange.VarTypes.Discrete: 
     388                num = len(self.rawdata.domain[sizeIndex].values) 
     389                if legendKeys.has_key(sizeIndex):  val = legendKeys[sizeIndex] 
     390                else:                               val = [[], [Qt.black]*num, [], [QwtSymbol.Ellipse]*num] 
    415391                val[2] = []; val[0] = [] 
    416                 varValues = getVariableValuesSorted(self.rawdata, sizeShapeIndex) 
     392                varValues = getVariableValuesSorted(self.rawdata, sizeIndex) 
    417393                for ind in range(num): 
    418                     val[0].append(self.rawdata.domain[sizeShapeIndex].name + "=" + varValues[ind]) 
     394                    val[0].append(self.rawdata.domain[sizeIndex].name + "=" + varValues[ind]) 
    419395                    val[2].append(MIN_SHAPE_SIZE + round(ind*self.pointWidth/len(varValues))) 
    420                 legendKeys[sizeShapeIndex] = val 
     396                legendKeys[sizeIndex] = val 
    421397        else: 
    422398            legendKeys = {} 
     
    431407                    self.legendCurveKeys.append(k) 
    432408        self.oldLegendKeys = legendKeys 
    433              
     409 
    434410        # ############################################################## 
    435411        # draw color scale for continuous coloring attribute 
     
    461437##        shortData = orange.Preprocessor_dropMissing(shortData) 
    462438## 
    463 ##        (closure, enlargedClosure, classValue) = self.clusterClosure         
     439##        (closure, enlargedClosure, classValue) = self.clusterClosure 
    464440## 
    465441##        (xVarMin, xVarMax) = self.attrValues[xAttr] 
    466442##        (yVarMin, yVarMax) = self.attrValues[yAttr] 
    467443##        xVar = xVarMax - xVarMin 
    468 ##        yVar = yVarMax - yVarMin                 
     444##        yVar = yVarMax - yVarMin 
    469445## 
    470446##        if type(closure) == dict: 
     
    478454##            for (p1, p2) in closure: 
    479455##                self.addCurve("", color, color, 1, QwtCurve.Lines, QwtSymbol.None, xData = [float(shortData[p1][0]), float(shortData[p2][0])], yData = [float(shortData[p1][1]), float(shortData[p2][1])], lineWidth = width) 
    480          
     456 
    481457    def addTip(self, x, y, attrIndices = None, dataindex = None, text = None): 
    482458        if self.tooltipKind == DONT_SHOW_TOOLTIPS: return 
     
    493469        return text 
    494470 
    495      
     471 
    496472    # ############################################################## 
    497473    # send 2 example tables. in first is the data that is inside selected rects (polygons), in the second is unselected data 
     
    501477        if not self.rawdata: return (None, None) 
    502478        if not self.selectionCurveKeyList: return (None, self.rawdata)       # if no selections exist 
    503          
     479 
    504480        selIndices, unselIndices = self.getSelectionsAsIndices(attrList) 
    505481 
    506482        selected = self.rawdata.selectref(selIndices) 
    507483        unselected = self.rawdata.selectref(unselIndices) 
    508          
     484 
    509485        if len(selected) == 0: selected = None 
    510486        if len(unselected) == 0: unselected = None 
     
    520496        if validData == None: 
    521497            validData = self.getValidList(attrIndices) 
    522          
     498 
    523499        (xArray, yArray) = self.getXYPositions(xAttr, yAttr) 
    524500 
    525501        return self.getSelectedPoints(xArray, yArray, validData) 
    526      
    527             
     502 
     503 
    528504    # add tooltips for pie charts 
    529505    def addTooltips(self): 
     
    532508            y_1 = self.transform(QwtPlot.yLeft, j+0.5);   y_2 = self.transform(QwtPlot.yLeft, j-0.5) 
    533509            rect = QRect(x_1, y_1, x_2-x_1, y_2-y_1) 
    534             self.toolRects.append(rect)             
     510            self.toolRects.append(rect) 
    535511            QToolTip.add(self, rect, text) 
    536              
     512 
    537513 
    538514    def removeTooltips(self): 
     
    551527        rx -= rx % self.squareGranularity 
    552528        ry -= ry % self.squareGranularity 
    553          
     529 
    554530        ox = self.transform(QwtPlot.xBottom, 0) - self.transform(QwtPlot.xBottom, self.xmin) 
    555531        oy = self.transform(QwtPlot.yLeft, self.ymin) - self.transform(QwtPlot.yLeft, 0) 
     
    578554            self.potentialContext = (rx, ry, self.shownXAttribute, self.shownYAttribute, self.squareGranularity, self.jitterSize, self.jitterContinuous, self.spaceBetweenCells) 
    579555 
    580      
     556 
    581557    def drawCanvasItems(self, painter, rect, map, pfilter): 
    582558        if self.showProbabilities and getattr(self, "potentialsClassifier", None): 
     
    619595        p.setBrush(brush) 
    620596 
    621          
     597 
    622598if __name__== "__main__": 
    623599    #Draw a simple graph 
    624     a = QApplication(sys.argv)         
     600    a = QApplication(sys.argv) 
    625601    c = OWScatterPlotGraph(None) 
    626          
     602 
    627603    a.setMainWidget(c) 
    628604    c.show() 
  • orange/OrangeWidgets/Visualize/OWScatterPlotMatrix.py

    r3415 r3483  
    4040        OWWidget.__init__(self, parent, signalManager, "Scatterplot matrix", TRUE) 
    4141 
    42         self.inputs = [("Examples", ExampleTable, self.setData), ("Attribute Selection List", AttributeList, self.setAttributeSelection)] 
     42        self.inputs = [("Examples", ExampleTable, self.setData), ("Attribute Selection List", AttributeList, self.setShownAttributes)] 
    4343        self.outputs = [("Attribute Selection List", AttributeList)]  
    4444 
     
    379379            return   
    380380 
    381         if not self.setAttributeSelection(self.attributeSelection): 
     381        if not self.setShownAttributes(self.attributeSelection): 
    382382            self.shownAttribsLB.clear() 
    383383            self.hiddenAttribsLB.clear() 
     
    390390    ################################################# 
    391391 
    392     def setAttributeSelection(self, attrList): 
     392    def setShownAttributes(self, attrList): 
    393393        self.attributeSelection = attrList 
    394394 
  • orange/OrangeWidgets/Visualize/OWSieveDiagram.py

    r3415 r3483  
    3232        self.controlArea.setMinimumWidth(250) 
    3333 
    34         self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Attribute Selection List", AttributeList, self.setAttributeSelection)] 
     34        self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Attribute Selection List", AttributeList, self.setShownAttributes)] 
    3535        self.outputs = [] 
    3636 
     
    109109            self.initCombos() 
    110110 
    111         self.setAttributeSelection(self.attributeSelectionList) 
     111        self.setShownAttributes(self.attributeSelectionList) 
    112112 
    113113    ## Attribute selection signal 
    114     def setAttributeSelection(self, attrList): 
     114    def setShownAttributes(self, attrList): 
    115115        self.attributeSelectionList = attrList 
    116116        if self.data and self.attributeSelectionList and len(attrList) >= 2: 
  • orange/OrangeWidgets/Visualize/OWSieveMultigram.py

    r3415 r3483  
    2424        OWWidget.__init__(self, parent, signalManager, "Sieve Multigram", TRUE) 
    2525 
    26         self.inputs = [("Examples", ExampleTable, self.setData), ("Attribute Selection List", AttributeList, self.setAttributeSelection)] 
     26        self.inputs = [("Examples", ExampleTable, self.setData), ("Attribute Selection List", AttributeList, self.setShownAttributes)] 
    2727        self.outputs = []  
    2828 
     
    196196 
    197197    # receive info about which attributes to show 
    198     def setAttributeSelection(self, list): 
     198    def setShownAttributes(self, list): 
    199199        self.shownAttribsLB.clear() 
    200200        self.hiddenAttribsLB.clear() 
  • orange/OrangeWidgets/Visualize/OWSurveyPlot.py

    r3415 r3483  
    1313from OWVisWidget import * 
    1414from OWSurveyPlotGraph import * 
     15from OWDlgs import ColorPalette 
    1516import orngVisFuncts 
    1617import OWGUI 
     
    2021########################################################################################### 
    2122class OWSurveyPlot(OWVisWidget): 
    22     settingsList = ["attrDiscOrder", "attrContOrder", "graph.globalValueScaling", "graph.exampleTracking", "graph.enabledLegend", "graph.tooltipKind", "showAllAttributes"] 
     23    settingsList = ["attrDiscOrder", "attrContOrder", "graph.globalValueScaling", "graph.exampleTracking", "graph.enabledLegend", 
     24                    "graph.tooltipKind", "showAllAttributes", "colorSettings", "selectedSchemaIndex"] 
    2325    attributeContOrder = ["None","ReliefF", "Fisher discriminant"] 
    2426    attributeDiscOrder = ["None","ReliefF","GainRatio"] 
     
    2729        OWWidget.__init__(self, parent, signalManager, "Survey Plot", TRUE) 
    2830 
    29         self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Attribute Selection List", AttributeList, self.setAttributeSelection)] 
     31        self.inputs = [("Examples", ExampleTable, self.setData, Default), ("Attribute Selection List", AttributeList, self.setShownAttributes)] 
    3032        self.outputs = [("Attribute Selection List", AttributeList)] 
    3133 
     
    5052        self.primaryAttribute = "(None)" 
    5153        self.secondaryAttribute = "(None)" 
     54        self.colorSettings = None 
     55        self.selectedSchemaIndex = 0 
    5256 
    5357        #load settings 
     
    5761        self.tabs = QTabWidget(self.space, 'tabWidget') 
    5862        self.GeneralTab = QVGroupBox(self) 
    59         self.SettingsTab = QVGroupBox(self, "Settings") 
     63        self.SettingsTab = QVGroupBox(self) 
    6064        self.tabs.insertTab(self.GeneralTab, "Main") 
    6165        self.tabs.insertTab(self.SettingsTab, "Settings") 
     
    8185        OWGUI.comboBox(box, self, "graph.tooltipKind", items = ["Don't show tooltips", "Show visible attributes", "Show all attributes"], callback = self.updateGraph) 
    8286 
    83         OWGUI.button(self.SettingsTab, self, "Canvas Color", callback = self.setGraphCanvasColor, tooltip = "Set color for canvas background", debuggingEnabled = 0) 
     87        self.colorButtonsBox = OWGUI.widgetBox(self.SettingsTab, "Colors", orientation = "horizontal") 
     88        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) 
    8489 
    8590        self.icons = self.createAttributeIconDict() 
     
    97102    # ######################### 
    98103    def activateLoadedSettings(self): 
    99         self.graph.setCanvasColor(QColor(self.graphCanvasColor)) 
     104        dlg = self.createColorDialog() 
     105        self.graph.contPalette = dlg.getContinuousPalette("contPalette") 
     106        self.graph.discPalette = dlg.getDiscretePalette() 
     107        self.graph.setCanvasBackground(dlg.getColor("Canvas")) 
     108        self.graph.setGridPen(QPen(dlg.getColor("Grid"))) 
     109         
    100110        #self.graph.setCanvasBackground(QColor(self.graphCanvasColor)) 
    101111        self.cbShowAllAttributes() 
     
    154164    ####### SELECTION signal ################################ 
    155165    # receive info about which attributes to show 
    156     def setAttributeSelection(self, attributeSelectionList): 
     166    def setShownAttributes(self, attributeSelectionList): 
    157167        self.attributeSelectionList = attributeSelectionList 
    158168        if self.data and self.attributeSelectionList: 
     
    185195        self.updateGraph() 
    186196 
    187     def setGraphCanvasColor(self): 
    188         newColor = QColorDialog.getColor(QColor(self.graphCanvasColor)) 
    189         if newColor.isValid(): 
    190             self.graphCanvasColor = str(newColor.name()) 
    191             self.graph.setCanvasColor(QColor(newColor)) 
    192  
    193  
     197    def setColors(self): 
     198        dlg = self.createColorDialog() 
     199        if dlg.exec_loop(): 
     200            self.colorSettings = dlg.getColorSchemas() 
     201            self.selectedSchemaIndex = dlg.selectedSchemaIndex 
     202            self.graph.contPalette = dlg.getContinuousPalette("contPalette") 
     203            self.graph.discPalette = dlg.getDiscretePalette() 
     204            self.graph.setCanvasBackground(dlg.getColor("Canvas")) 
     205            self.graph.setGridPen(QPen(dlg.getColor("Grid"))) 
     206            self.updateGraph() 
     207 
     208    def createColorDialog(self): 
     209        c = ColorPalette(self, "Color Palette") 
     210        c.createDiscretePalette("Discrete Palette") 
     211        c.createContinuousPalette("contPalette", "Continuous palette") 
     212        box = c.createBox("otherColors", "Other Colors") 
     213        c.createColorButton(box, "Canvas", "Canvas color", Qt.white) 
     214        box.addSpace(5) 
     215        c.createColorButton(box, "Grid", "Grid color", Qt.black) 
     216        box.addSpace(5) 
     217        box.adjustSize() 
     218        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex) 
     219        return c 
    194220 
    195221#test widget appearance 
  • orange/OrangeWidgets/Visualize/OWSurveyPlotGraph.py

    r3333 r3483  
    6060        self.updateLayout() 
    6161 
     62        xRectsToAdd = {} 
     63        yRectsToAdd = {} 
    6264        classNameIndex = -1 
    6365        if self.rawdata.domain.classVar: 
     
    7577            for j in range(self.length): 
    7678                width = self.noJitteringScaledData[indices[j]][i] * 0.45 
    77                 ckey = self.insertCurve(PolygonCurve(self, pen = QPen(newColor), brush = QBrush(newColor))) 
    78                 self.setCurveData(ckey, [j-width, j+width, j+width, j-width], [y, y, y+1, y+1]) 
     79                xRectsToAdd[newColor] = xRectsToAdd.get(newColor, []) + [j-width, j+width, j+width, j-width] 
     80                yRectsToAdd[newColor] = yRectsToAdd.get(newColor, []) + [y, y, y+1, y+1] 
     81            y += 1 
    7982 
    80             ########## 
    81             y += 1 
     83        for i, key in enumerate(xRectsToAdd.keys()): 
     84            self.insertCurve(PolygonCurve(self, QPen(key), QBrush(key), xRectsToAdd[key], yRectsToAdd[key])) 
    8285 
    8386        if self.enabledLegend and self.rawdata.domain.classVar and self.rawdata.domain.classVar.varType == orange.VarTypes.Discrete: 
Note: See TracChangeset for help on using the changeset viewer.