Changeset 11593:6edc44eb9655 in orange


Ignore:
Timestamp:
06/13/13 18:12:28 (10 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Updated Widget development tutorial.

Location:
docs/extend-widgets/rst
Files:
6 added
5 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • docs/extend-widgets/rst/OWAttributeSampler.py

    r11085 r11593  
    55<priority>1020</priority> 
    66""" 
     7import Orange 
    78 
    89from OWWidget import * 
     
    1112class OWAttributeSampler(OWWidget): 
    1213    settingsList = [] 
    13     contextHandlers = {"": DomainContextHandler("", [ 
    14             ContextField("classAttribute", DomainContextHandler.Required), 
    15             ContextField("attributeList", DomainContextHandler.List + DomainContextHandler.SelectedRequired, 
    16                          selected="selectedAttributes")])} 
     14 
     15    # ~start context handler~ 
     16    contextHandlers = { 
     17        "": DomainContextHandler( 
     18            "", 
     19            [ContextField("classAttribute", DomainContextHandler.Required), 
     20             ContextField("attributeList", 
     21                          DomainContextHandler.List + 
     22                          DomainContextHandler.SelectedRequired, 
     23                          selected="selectedAttributes")])} 
     24    # ~end context handler~ 
    1725 
    1826    def __init__(self, parent=None, signalManager=None): 
    1927        OWWidget.__init__(self, parent, signalManager, 'AttributeSampler') 
    2028 
    21         self.inputs = [("Examples", ExampleTable, self.dataset)] 
    22         self.outputs = [("Examples", ExampleTable)] 
     29        self.inputs = [("Examples", Orange.data.Table, self.dataset)] 
     30        self.outputs = [("Examples", Orange.data.Table)] 
    2331 
    2432        self.icons = self.createAttributeIconDict() 
     
    2937        self.loadSettings() 
    3038 
    31         OWGUI.listBox(self.controlArea, self, "selectedAttributes", "attributeList", box="Selected attributes", selectionMode = QListWidget.ExtendedSelection) 
     39        OWGUI.listBox(self.controlArea, self, "selectedAttributes", 
     40                      "attributeList", 
     41                      box="Selected attributes", 
     42                      selectionMode=QListWidget.ExtendedSelection) 
     43 
    3244        OWGUI.separator(self.controlArea) 
    33         self.classAttrCombo = OWGUI.comboBox(self.controlArea, self, "classAttribute", box="Class attribute") 
     45        self.classAttrCombo = OWGUI.comboBox( 
     46            self.controlArea, self, "classAttribute", 
     47            box="Class attribute") 
     48 
    3449        OWGUI.separator(self.controlArea) 
    35         OWGUI.button(self.controlArea, self, "Commit", callback = self.outputData) 
     50        OWGUI.button(self.controlArea, self, "Commit", 
     51                     callback=self.outputData) 
    3652 
    3753        self.resize(150,400) 
     
    4359        self.classAttrCombo.clear() 
    4460        if data: 
    45             self.attributeList = [(attr.name, attr.varType) for attr in data.domain] 
     61            self.attributeList = [(attr.name, attr.varType) 
     62                                  for attr in data.domain] 
    4663            self.selectedAttributes = [] 
    4764            for attrName, attrType in self.attributeList: 
     
    6380            self.send("Examples", None) 
    6481        else: 
    65             newDomain = orange.Domain([self.data.domain[i] for i in self.selectedAttributes], self.data.domain[self.classAttribute]) 
    66             newData = orange.ExampleTable(newDomain, self.data) 
     82            newDomain = Orange.data.Domain( 
     83                [self.data.domain[i] for i in self.selectedAttributes], 
     84                self.data.domain[self.classAttribute]) 
     85 
     86            newData = Orange.data.Table(newDomain, self.data) 
    6787            self.send("Examples", newData) 
    6888 
    69  
    70 ############################################################################## 
    71 # Test the widget, run from prompt 
    7289 
    7390if __name__=="__main__": 
     
    7693    ow.show() 
    7794 
    78     data = orange.ExampleTable('iris.tab') 
     95    data = Orange.data.Table('iris.tab') 
    7996    ow.dataset(data) 
    8097 
  • docs/extend-widgets/rst/OWDataSamplerB.py

    r11085 r11593  
    22<name>Data Sampler (B)</name> 
    33<description>Randomly selects a subset of instances from the data set</description> 
    4 <icon>icons/DataSamplerB.png</icon> 
     4<icon>icons/DataSamplerB.svg</icon> 
    55<priority>20</priority> 
    66""" 
     7import Orange 
    78from OWWidget import * 
    89import OWGUI 
     
    1112    settingsList = ['proportion', 'commitOnChange'] 
    1213    def __init__(self, parent=None, signalManager=None): 
    13         OWWidget.__init__(self, parent, signalManager, 'SampleDataB') 
     14        OWWidget.__init__(self, parent, signalManager) 
    1415 
    15         self.inputs = [("Data", ExampleTable, self.data)] 
    16         self.outputs = [("Sampled Data", ExampleTable)] 
     16        self.inputs = [("Data", Orange.data.Table, self.data)] 
     17        self.outputs = [("Sampled Data", Orange.data.Table)] 
    1718 
    1819        self.proportion = 50 
     
    4950 
    5051    def selection(self): 
    51         indices = orange.MakeRandomIndices2(p0=self.proportion / 100.) 
     52        indices = Orange.data.sample.SubsetIndices2(p0=self.proportion / 100.) 
    5253        ind = indices(self.dataset) 
    5354        self.sample = self.dataset.select(ind, 0) 
     
    6162            self.commit() 
    6263 
    63 ############################################################################## 
    64 # Test the widget, run from prompt 
    6564 
    6665if __name__=="__main__": 
     
    6867    ow = OWDataSamplerB() 
    6968    ow.show() 
    70     dataset = orange.ExampleTable('iris.tab') 
     69    dataset = Orange.data.Table('iris.tab') 
    7170    ow.data(dataset) 
    7271    appl.exec_() 
  • docs/extend-widgets/rst/OWDataSamplerC.py

    r11085 r11593  
    22<name>Data Sampler (C)</name> 
    33<description>Randomly selects a subset of instances from the data set</description> 
    4 <icon>icons/DataSamplerC.png</icon> 
     4<icon>icons/DataSamplerC.svg</icon> 
    55<priority>30</priority> 
    66""" 
     7import Orange 
     8 
    79from OWWidget import * 
    810import OWGUI 
     
    1315        OWWidget.__init__(self, parent, signalManager, 'SampleDataC') 
    1416         
    15         self.inputs = [("Data", ExampleTable, self.data)] 
    16         self.outputs = [("Sampled Data", ExampleTable), ("Other Data", ExampleTable)] 
     17        self.inputs = [("Data", Orange.data.Table, self.data)] 
     18        self.outputs = [("Sampled Data", Orange.data.Table), 
     19                        ("Other Data", Orange.data.Table)] 
    1720 
    1821        self.proportion = 50 
     
    4952 
    5053    def selection(self): 
    51         indices = orange.MakeRandomIndices2(p0=self.proportion / 100.) 
     54        indices = Orange.data.sample.SubsetIndices2(p0=self.proportion / 100.) 
    5255        ind = indices(self.dataset) 
    5356        self.sample = self.dataset.select(ind, 0) 
     
    6366            self.commit() 
    6467 
    65 ############################################################################## 
    66 # Test the widget, run from prompt 
    6768 
    6869if __name__=="__main__": 
     
    7071    ow = OWDataSamplerC() 
    7172    ow.show() 
    72     dataset = orange.ExampleTable('iris.tab') 
     73    dataset = Orange.data.Table('iris.tab') 
    7374    ow.data(dataset) 
    7475    appl.exec_() 
  • docs/extend-widgets/rst/OWLearningCurveA.py

    r11085 r11593  
    22<name>Learning Curve (A)</name> 
    33<description>Takes a data set and a set of learners and shows a learning curve in a table</description> 
    4 <icon>icons/LearningCurveA.png</icon> 
     4<icon>icons/LearningCurve.svg</icon> 
    55<priority>1000</priority> 
    66""" 
    77 
     8import Orange 
     9 
    810from OWWidget import * 
    9 import OWGUI, orngTest, orngStat 
     11import OWGUI 
    1012 
    1113class OWLearningCurveA(OWWidget): 
    1214    settingsList = ["folds", "steps", "scoringF", "commitOnChange"] 
    13      
     15 
    1416    def __init__(self, parent=None, signalManager=None): 
    1517        OWWidget.__init__(self, parent, signalManager, 'LearningCurveA') 
    1618 
    17         self.inputs = [("Data", ExampleTable, self.dataset), 
    18                        ("Learner", orange.Learner, self.learner, Multiple)] 
    19          
     19        self.inputs = [("Data", Orange.data.Table, self.dataset), 
     20                       ("Learner", Orange.core.Learner, self.learner, 
     21                        Multiple)] 
     22 
    2023        self.folds = 5     # cross validation folds 
    2124        self.steps = 10    # points in the learning curve 
     
    2326        self.commitOnChange = 1 # compute curve on any change of parameters 
    2427        self.loadSettings() 
    25         self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1 
    26         self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)] 
     28        self.setCurvePoints() # sets self.curvePoints, self.steps equidistant points from 1/self.steps to 1 
     29        self.scoring = [("Classification Accuracy", Orange.evaluation.scoring.CA), 
     30                        ("AUC", Orange.evaluation.scoring.AUC), 
     31                        ("BrierScore", Orange.evaluation.scoring.Brier_score), 
     32                        ("Information Score", Orange.evaluation.scoring.IS), 
     33                        ("Sensitivity", Orange.evaluation.scoring.Sensitivity), 
     34                        ("Specificity", Orange.evaluation.scoring.Specificity)] 
    2735        self.learners = [] # list of current learners from input channel, tuples (id, learner) 
    2836        self.data = None   # data on which to construct the learning curve 
     
    3644 
    3745        OWGUI.separator(self.controlArea) 
     46 
    3847        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores") 
    3948        scoringNames = [x[0] for x in self.scoring] 
    40         OWGUI.comboBox(box, self, "scoringF", items=scoringNames, callback=self.computeScores) 
     49        OWGUI.comboBox(box, self, "scoringF", items=scoringNames, 
     50                       callback=self.computeScores) 
    4151 
    4252        OWGUI.separator(self.controlArea) 
     53 
    4354        box = OWGUI.widgetBox(self.controlArea, "Options") 
    44         OWGUI.spin(box, self, 'folds', 2, 100, step=1, label='Cross validation folds:  ', 
     55        OWGUI.spin(box, self, 'folds', 2, 100, step=1, 
     56                   label='Cross validation folds:  ', 
    4557                   callback=lambda: self.computeCurve(self.commitOnChange)) 
    46         OWGUI.spin(box, self, 'steps', 2, 100, step=1, label='Learning curve points:  ', 
    47                    callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)]) 
    48  
     58        OWGUI.spin(box, self, 'steps', 2, 100, step=1, 
     59                   label='Learning curve points:  ', 
     60                   callback=[self.setCurvePoints, 
     61                             lambda: self.computeCurve(self.commitOnChange)]) 
    4962        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change') 
    50         self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1) 
     63        self.commitBtn = OWGUI.button(box, self, "Apply Setting", 
     64                                      callback=self.computeCurve, disabled=1) 
     65 
     66        OWGUI.rubber(self.controlArea) 
    5167 
    5268        # table widget 
    53         self.table = OWGUI.table(self.mainArea, selectionMode=QTableWidget.NoSelection) 
    54                  
     69        self.table = OWGUI.table(self.mainArea, 
     70                                 selectionMode=QTableWidget.NoSelection) 
     71 
    5572        self.resize(500,200) 
    5673 
    5774    ##############################################################################     
    58     # slots: handle input signals         
     75    # slots: handle input signals 
    5976 
    6077    def dataset(self, data): 
     
    6885            self.curves = [] 
    6986            self.scores = [] 
    70         self.commitBtn.setEnabled(self.data<>None) 
     87        self.commitBtn.setEnabled(self.data is not None) 
    7188 
    7289    def learner(self, learner, id=None): 
     
    107124            self.infob.setText("No learners.") 
    108125        self.commitBtn.setEnabled(len(self.learners)) 
    109 ##        if len(self.scores): 
     126 
    110127        if self.data: 
    111128            self.setTable() 
     
    130147    def getLearningCurve(self, learners):    
    131148        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds) 
    132         curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance) 
     149        curve = Orange.evaluation.testing.learning_curve_n( 
     150            learners, self.data, folds=self.folds, 
     151            proportions=self.curvePoints, callback=pb.advance) 
    133152        pb.finish() 
    134153        return curve 
    135154 
    136155    def setCurvePoints(self): 
    137         self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)] 
     156        self.curvePoints = [(x + 1.)/self.steps for x in range(self.steps)] 
    138157 
    139158    def setTable(self): 
     
    154173            self.table.setColumnWidth(i, 80) 
    155174 
    156 ############################################################################## 
    157 # Test the widget, run from prompt 
    158175 
    159176if __name__=="__main__": 
     
    162179    ow.show() 
    163180     
    164     l1 = orange.BayesLearner() 
     181    l1 = Orange.classification.bayes.NaiveLearner() 
    165182    l1.name = 'Naive Bayes' 
    166183    ow.learner(l1, 1) 
    167184 
    168     data = orange.ExampleTable('iris.tab') 
     185    data = Orange.data.Table('iris.tab') 
    169186    ow.dataset(data) 
    170187 
    171     l2 = orange.BayesLearner() 
     188    l2 = Orange.classification.bayes.NaiveLearner() 
    172189    l2.name = 'Naive Bayes (m=10)' 
    173     l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10) 
    174     l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)) 
     190    l2.estimatorConstructor = Orange.statistics.estimate.M(m=10) 
     191    l2.conditionalEstimatorConstructor = \ 
     192        Orange.statistics.estimate.ConditionalByRows( 
     193            estimatorConstructor = Orange.statistics.estimate.M(m=10)) 
    175194    ow.learner(l2, 2) 
    176195 
    177     import orngTree 
    178     l4 = orngTree.TreeLearner(minSubset=2) 
     196    l4 = Orange.classification.tree.TreeLearner(minSubset=2) 
    179197    l4.name = "Decision Tree" 
    180198    ow.learner(l4, 4) 
  • docs/extend-widgets/rst/OWLearningCurveB.py

    r11085 r11593  
    22<name>Learning Curve (B)</name> 
    33<description>Takes a data set and a set of learners and shows a learning curve in a table</description> 
    4 <icon>icons/LearningCurveB.png</icon> 
     4<icon>icons/LearningCurve.svg</icon> 
    55<priority>1010</priority> 
    66""" 
    77 
     8import Orange 
     9 
    810from OWWidget import * 
    9 import OWGUI, orngTest, orngStat 
     11import OWGUI 
     12 
    1013 
    1114class OWLearningCurveB(OWWidget): 
     
    1518        OWWidget.__init__(self, parent, signalManager, 'LearningCurveA') 
    1619 
    17         self.inputs = [("Train Data", ExampleTable, self.trainset, Default), 
    18                        ("Test Data", ExampleTable, self.testset), 
    19                        ("Learner", orange.Learner, self.learner, Multiple)] 
     20        self.inputs = [("Train Data", Orange.data.Table, self.trainset, Default), 
     21                       ("Test Data", Orange.data.Table, self.testset), 
     22                       ("Learner", Orange.classification.Learner, 
     23                        self.learner, Multiple)] 
    2024         
    2125        self.folds = 5     # cross validation folds 
     
    2428        self.commitOnChange = 1 # compute curve on any change of parameters 
    2529        self.loadSettings() 
    26         self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1 
    27         self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)] 
     30        self.setCurvePoints() # sets self.curvePoints, self.steps equidistan points from 1/self.steps to 1 
     31        self.scoring = [("Classification Accuracy", Orange.evaluation.scoring.CA), 
     32                        ("AUC", Orange.evaluation.scoring.AUC), 
     33                        ("BrierScore", Orange.evaluation.scoring.Brier_score), 
     34                        ("Information Score", Orange.evaluation.scoring.IS), 
     35                        ("Sensitivity", Orange.evaluation.scoring.Sensitivity), 
     36                        ("Specificity", Orange.evaluation.scoring.Specificity)] 
    2837        self.learners = [] # list of current learners from input channel, tuples (id, learner) 
    2938        self.data = None   # data on which to construct the learning curve 
     
    3847 
    3948        OWGUI.separator(self.controlArea) 
     49 
    4050        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores") 
    4151        scoringNames = [x[0] for x in self.scoring] 
    42         OWGUI.comboBox(box, self, "scoringF", items=scoringNames, callback=self.computeScores) 
     52        OWGUI.comboBox(box, self, "scoringF", items=scoringNames, 
     53                       callback=self.computeScores) 
    4354 
    4455        OWGUI.separator(self.controlArea) 
     56 
    4557        box = OWGUI.widgetBox(self.controlArea, "Options") 
    46         OWGUI.spin(box, self, 'folds', 2, 100, step=1, label='Cross validation folds:  ', 
     58        OWGUI.spin(box, self, 'folds', 2, 100, step=1, 
     59                   label='Cross validation folds:  ', 
    4760                   callback=lambda: self.computeCurve(self.commitOnChange)) 
    48         OWGUI.spin(box, self, 'steps', 2, 100, step=1, label='Learning curve points:  ', 
    49                    callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)]) 
     61 
     62        OWGUI.spin(box, self, 'steps', 2, 100, step=1, 
     63                   label='Learning curve points:  ', 
     64                   callback=[self.setCurvePoints, 
     65                             lambda: self.computeCurve(self.commitOnChange)]) 
    5066 
    5167        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change') 
    52         self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1) 
     68        self.commitBtn = OWGUI.button(box, self, "Apply Setting", 
     69                                      callback=self.computeCurve, disabled=1) 
    5370 
    5471        # table widget 
    55         self.table = OWGUI.table(self.mainArea, selectionMode=QTableWidget.NoSelection) 
     72        self.table = OWGUI.table(self.mainArea, 
     73                                 selectionMode=QTableWidget.NoSelection) 
    5674                 
    5775        self.resize(500,200) 
    5876 
    59     ##############################################################################     
    60     # slots: handle input signals         
     77    ############################################################################## 
     78    # slots: handle input signals 
    6179 
    6280    def trainset(self, data): 
     
    7088            self.curves = [] 
    7189            self.scores = [] 
    72         self.commitBtn.setEnabled(self.data<>None) 
     90        self.commitBtn.setEnabled(self.data is not None) 
    7391 
    7492    def testset(self, testdata): 
     
    140158        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds) 
    141159        if not self.testdata: 
    142             curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance) 
    143         else: 
    144             curve = orngTest.learningCurveWithTestData(learners, 
    145               self.data, self.testdata, times=self.folds, proportions=self.curvePoints, callback=pb.advance)             
     160            curve = Orange.evaluation.testing.learning_curve_n( 
     161                learners, self.data, folds=self.folds, 
     162                proportions=self.curvePoints, 
     163                callback=pb.advance) 
     164        else: 
     165            curve = Orange.evaluation.testing.learning_curve_with_test_data( 
     166                learners, self.data, self.testdata, times=self.folds, 
     167                proportions=self.curvePoints, 
     168#                callback=pb.advance 
     169                ) 
    146170        pb.finish() 
    147171        return curve 
    148172 
    149173    def setCurvePoints(self): 
    150         self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)] 
     174        self.curvePoints = [(x + 1.)/self.steps for x in range(self.steps)] 
    151175 
    152176    def setTable(self): 
     
    167191            self.table.setColumnWidth(i, 80) 
    168192 
    169 ############################################################################## 
    170 # Test the widget, run from prompt 
    171193 
    172194if __name__=="__main__": 
     
    175197    ow.show() 
    176198     
    177     l1 = orange.BayesLearner() 
     199    l1 = Orange.classification.bayes.NaiveLearner() 
    178200    l1.name = 'Naive Bayes' 
    179201    ow.learner(l1, 1) 
    180202 
    181     data = orange.ExampleTable('iris.tab') 
    182     indices = orange.MakeRandomIndices2(data, p0 = 0.7) 
     203    data = Orange.data.Table('iris.tab') 
     204    indices = Orange.data.sample.SubsetIndices2(data, p0 = 0.7) 
    183205    train = data.select(indices, 0) 
    184206    test = data.select(indices, 1) 
     
    187209    ow.testset(test) 
    188210 
    189     l2 = orange.BayesLearner() 
     211    l2 = Orange.classification.bayes.NaiveLearner() 
    190212    l2.name = 'Naive Bayes (m=10)' 
    191     l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10) 
    192     l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)) 
     213    l2.estimatorConstructor = Orange.statistics.estimate.M(m=10) 
     214    l2.conditionalEstimatorConstructor = \ 
     215        Orange.statistics.estimate.ConditionalByRows( 
     216            estimatorConstructor = Orange.statistics.estimate.M(m=10)) 
    193217    ow.learner(l2, 2) 
    194218 
    195     import orngTree 
    196     l4 = orngTree.TreeLearner(minSubset=2) 
     219    l4 = Orange.classification.tree.TreeLearner(minSubset=2) 
    197220    l4.name = "Decision Tree" 
    198221    ow.learner(l4, 4) 
  • docs/extend-widgets/rst/OWLearningCurveC.py

    r11085 r11593  
    66""" 
    77 
     8import Orange 
     9 
    810from OWWidget import * 
    911from OWColorPalette import ColorPixmap 
    10 import OWGUI, orngTest, orngStat 
    1112from OWGraph import * 
     13 
     14import OWGUI 
    1215 
    1316import warnings 
     
    2023        OWWidget.__init__(self, parent, signalManager, 'LearningCurveC') 
    2124 
    22         self.inputs = [("Data", ExampleTable, self.dataset), 
    23                        ("Learner", orange.Learner, self.learner, Multiple)] 
     25        self.inputs = [("Data", Orange.data.Table, self.dataset), 
     26                       ("Learner", Orange.classification.Learner, 
     27                        self.learner, Multiple)] 
    2428 
    2529        self.folds = 5     # cross validation folds 
     
    3034        self.graphDrawLines = 1 # draw lines between points in the graph 
    3135        self.graphShowGrid = 1  # show gridlines in the graph 
    32         self.selectedLearners = []  
     36        self.selectedLearners = [] 
     37 
    3338        self.loadSettings() 
    3439 
    35         warnings.filterwarnings("ignore", ".*builtin attribute.*", orange.AttributeWarning) 
    36  
    37         self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1 
    38         self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)] 
     40        warnings.filterwarnings("ignore", ".*builtin attribute.*", Orange.core.AttributeWarning) 
     41 
     42        self.setCurvePoints() # sets self.curvePoints, self.steps equidistant points from 1/self.steps to 1 
     43        self.scoring = [("Classification Accuracy", 
     44                         Orange.evaluation.scoring.CA), 
     45                        ("AUC", Orange.evaluation.scoring.AUC), 
     46                        ("BrierScore", Orange.evaluation.scoring.Brier_score), 
     47                        ("Information Score", Orange.evaluation.scoring.IS), 
     48                        ("Sensitivity", Orange.evaluation.scoring.sens), 
     49                        ("Specificity", Orange.evaluation.scoring.spec)] 
    3950        self.learners = [] # list of current learners from input channel, tuples (id, learner) 
    4051        self.data = None   # data on which to construct the learning curve 
     
    4960        ## class selection (classQLB) 
    5061        OWGUI.separator(self.controlArea) 
     62 
     63        # ~SPHINX start color cb~ 
    5164        self.cbox = OWGUI.widgetBox(self.controlArea, "Learners") 
    52         self.llb = OWGUI.listBox(self.cbox, self, "selectedLearners", selectionMode=QListWidget.MultiSelection, callback=self.learnerSelectionChanged) 
     65        self.llb = OWGUI.listBox(self.cbox, self, "selectedLearners", 
     66                                 selectionMode=QListWidget.MultiSelection, 
     67                                 callback=self.learnerSelectionChanged) 
    5368         
    5469        self.llb.setMinimumHeight(50) 
    5570        self.blockSelectionChanges = 0 
     71        # ~SPHINX end color cb~ 
    5672 
    5773        OWGUI.separator(self.controlArea) 
     74 
    5875        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores") 
    5976        scoringNames = [x[0] for x in self.scoring] 
     
    6279 
    6380        OWGUI.separator(self.controlArea) 
     81 
    6482        box = OWGUI.widgetBox(self.controlArea, "Options") 
    6583        OWGUI.spin(box, self, 'folds', 2, 100, step=1, 
     
    6886        OWGUI.spin(box, self, 'steps', 2, 100, step=1, 
    6987                   label='Learning curve points:  ', 
    70                    callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)]) 
     88                   callback=[self.setCurvePoints, 
     89                             lambda: self.computeCurve(self.commitOnChange)]) 
    7190 
    7291        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change') 
    73         self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1) 
    74  
     92        self.commitBtn = OWGUI.button(box, self, "Apply Setting", 
     93                                      callback=self.computeCurve, disabled=1) 
     94 
     95        # ~SPHINX start main area tabs~ 
    7596        # start of content (right) area 
    7697        tabs = OWGUI.tabWidget(self.mainArea) 
    7798 
    78         # graph widget 
     99        # graph tab 
    79100        tab = OWGUI.createTabPage(tabs, "Graph") 
    80101        self.graph = OWGraph(tab) 
     
    84105        self.setGraphGrid() 
    85106 
    86         # table widget 
     107        # table tab 
    87108        tab = OWGUI.createTabPage(tabs, "Table") 
    88109        self.table = OWGUI.table(tab, selectionMode=QTableWidget.NoSelection) 
     110        # ~SPHINX end main area tabs~ 
    89111 
    90112        self.resize(550,200) 
     
    187209    def getLearningCurve(self, learners): 
    188210        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds) 
    189         curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance) 
     211        curve = Orange.evaluation.testing.learning_curve_n( 
     212            learners, self.data, folds=self.folds, 
     213            proportions=self.curvePoints, 
     214            callback=pb.advance) 
     215 
    190216        pb.finish() 
    191217        return curve 
     
    250276        else: 
    251277            curve.setStyle(QwtPlotCurve.NoCurve) 
    252         curve.setSymbol(QwtSymbol(QwtSymbol.Ellipse, \ 
    253           QBrush(QColor(0,0,0)), QPen(QColor(0,0,0)), 
    254           QSize(self.graphPointSize, self.graphPointSize))) 
     278 
     279        curve.setSymbol( 
     280            QwtSymbol(QwtSymbol.Ellipse, 
     281                      QBrush(QColor(0,0,0)), QPen(QColor(0,0,0)), 
     282                      QSize(self.graphPointSize, self.graphPointSize))) 
     283 
    255284        curve.setPen(QPen(learner.color, 5)) 
    256285 
    257286    def drawLearningCurve(self, learner): 
    258         if not self.data: return 
    259         curve = self.graph.addCurve(learner.name, xData=self.curvePoints, yData=learner.score, autoScale=True) 
     287        if not self.data: 
     288            return 
     289        curve = self.graph.addCurve( 
     290            learner.name, 
     291            xData=self.curvePoints, 
     292            yData=learner.score, 
     293            autoScale=True) 
    260294         
    261295        learner.curve = curve 
     
    268302            self.drawLearningCurve(l[1]) 
    269303 
    270 ############################################################################## 
    271 # Test the widget, run from prompt 
    272304 
    273305if __name__=="__main__": 
     
    276308    ow.show() 
    277309 
    278     l1 = orange.BayesLearner() 
     310    l1 = Orange.classification.bayes.NaiveLearner() 
    279311    l1.name = 'Naive Bayes' 
    280312    ow.learner(l1, 1) 
    281313 
    282     data = orange.ExampleTable('iris.tab') 
     314    data = Orange.data.Table('iris.tab') 
    283315    ow.dataset(data) 
    284316 
    285     l2 = orange.BayesLearner() 
     317    l2 = Orange.classification.bayes.NaiveLearner() 
    286318    l2.name = 'Naive Bayes (m=10)' 
    287     l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10) 
    288     l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)) 
    289  
    290     l3 = orange.kNNLearner(name="k-NN") 
     319    l2.estimatorConstructor = Orange.statistics.estimate.M(m=10) 
     320    l2.conditionalEstimatorConstructor = Orange.statistics.estimate.ConditionalByRows(estimatorConstructor = Orange.statistics.estimate.M(m=10)) 
     321 
     322    l3 = Orange.classification.knn.kNNLearner(name="k-NN") 
    291323    ow.learner(l3, 3) 
    292324 
    293     import orngTree 
    294     l4 = orngTree.TreeLearner(minSubset=2) 
     325    l4 = Orange.classification.tree.TreeLearner(minSubset=2) 
    295326    l4.name = "Decision Tree" 
    296327    ow.learner(l4, 4) 
     
    299330#    ow.learner(None, 2) 
    300331#    ow.learner(None, 4) 
    301      
    302  
    303332 
    304333    appl.exec_() 
  • docs/extend-widgets/rst/OWLearningCurve_plot.py

    r11085 r11593  
    7373        self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1) 
    7474 
     75        # ~start main area tabs~ 
    7576        # start of content (right) area 
    7677        tabs = OWGUI.tabWidget(self.mainArea) 
    7778 
    78         # graph widget 
     79        # graph tab 
    7980        tab = OWGUI.createTabPage(tabs, "Graph") 
    8081        self.graph = OWPlot(tab) 
     
    8485        self.setGraphGrid() 
    8586 
    86         # table widget 
     87        # table tab 
    8788        tab = OWGUI.createTabPage(tabs, "Table") 
    8889        self.table = OWGUI.table(tab, selectionMode=QTableWidget.NoSelection) 
     90        # ~end main area tabs~ 
    8991 
    9092        self.resize(550,200) 
     
    256258 
    257259    def drawLearningCurve(self, learner): 
    258         if not self.data: return 
    259         curve = self.graph.add_curve(learner.name, xData=self.curvePoints, yData=learner.score, autoScale=True) 
     260        if not self.data: 
     261            return 
     262        curve = self.graph.add_curve( 
     263            learner.name, 
     264            xData=self.curvePoints, 
     265            yData=learner.score, 
     266            autoScale=True) 
    260267         
    261268        learner.curve = curve 
  • docs/extend-widgets/rst/basics.rst

    r11439 r11593  
    1414some really nice interaction may be over 1000 lines long. 
    1515 
    16 When we have started to write this tutorial, we have been working 
    17 on widgets for quite a while. There are now (now being in the very 
    18 time this page has been crafted) about 50 widgets available, and we 
    19 have pretty much defined how widgets and their interfaces should look 
    20 like. We have also made some libraries that help set up GUI with only 
    21 a few lines of code, and some mechanisms that one may found useful and 
    22 user friendly, like progress bars and alike. 
    23  
    2416On this page, we will start with some simple essentials, and then 
    2517show how to build a simple widget that will be ready to run within 
     
    3325category has an associated priority. Opening Orange Canvas, a visual 
    3426programming environment that comes with Orange, widgets are listed in 
    35 toolbox on the top of the window: 
     27a toolbox on the left: 
    3628 
    3729.. image:: widgettoolbox.png 
    3830 
    39 By default, Orange is installed in site-packages directory of 
    40 Python libraries. Widgets are all put in the subdirectories of 
    41 OrangeWidget directory; these subdirectories define widget 
    42 categories. For instance, under windows and default settings, a 
    43 directory that stores all the widgets displayed in the Evaluate pane is 
    44 *C:\\Python23\\Lib\\site-packages\\Orange\\OrangeWidgets\\Evaluate*. Figure 
    45 above shows that at the time of writing of this text there were five 
    46 widgets for evaluation of classifiers, and this is how my Evaluate 
    47 directory looked like: 
    48  
    49 .. image:: explorer.png 
    50  
    51 Notice that there are a number of files in Evaluate directory, so 
    52 how does Orange Canvas distinguish those that define widgets? Well, 
    53 widgets are Python script files that start with a header. Here is a 
    54 header for OWTestLearners.py:: 
    55  
     31The widgets and categories to which they belong are discovered at Orange 
     32Canvas startup leveraging setuptools/distribute and it's `entry points 
     33<http://pythonhosted.org/distribute/setuptools.html#dynamic-discovery-of-services-and-plugins>`_ 
     34protocol. In particular Orange Canvas looks for widgets using a 
     35`orange.widgets` entry point. 
     36 
     37 
     38First we will examine an existing widget in Orange. The Test Learners 
     39widget which is implemented in `OWTestLearners.py 
     40<http://orange.biolab.si/trac/browser/orange/Orange/OrangeWidgets/Evaluate/OWTestLearners.py>`_. 
     41 
     42Here is its header:: 
     43 
     44    """ 
    5645    <name>Test Learners</name> 
    5746    <description>Estimates the predictive performance of learners on a data set.</description> 
    58     <icon>icons/TestLearners.png</icon> 
     47    <icon>icons/TestLearners1.svg</icon> 
    5948    <priority>200</priority> 
    60  
    61 OWTestLearners is a Python script, so the header information we 
     49    """ 
     50 
     51OWTestLearners is a Python module, so the header information we 
    6252show about lies within the comment block, with triple quote opening 
    6353and closing the comment. Header defines the name of the widget, its 
     
    6555icon, and a number expressing the priority of the widget. The name of 
    6656the widget as given in the header will be the one that will be used 
    67 throughout in Orange Canvas. As for naming, the actual file name of 
    68 the widget is not important. The description of the widget is shown 
    69 once mouse rests on an toolbar icon representing the widget. And for 
     57throughout in Orange Canvas. The description of the widget is shown 
     58once mouse rests on an toolbox icon representing the widget. And for 
    7059the priority: this determines the order in which widgets appear in the 
    71 toolbox. The one shown above for Evaluate groups has widget named Test 
    72 Learners with priority 200, Classifications with 300, ROC Analysis 
    73 with 1010, Lift Curve with 1020 and Calibration Plot with 1030. Notice 
    74 that every time the priority number crosses a multiplier of a 1000, 
    75 there is a gap in the toolbox between the widgets; in this way, a 
    76 subgroups of the widgets within the same group can be imposed. 
     60toolbox within a category. 
    7761 
    7862Widgets communicate. They use typed channels, and exchange 
     
    8468    self.outputs = [("Evaluation Results", orngTest.ExperimentResults)] 
    8569 
    86 Above two lines are for Test Learners widget, so hovering with your 
    87 mouse over its icon in the widget toolbox would yield: 
    88  
    89 .. image:: mouseoverwidgetintoolbox.png 
    9070 
    9171We will go over the syntax of channel definitions later, but for 
     
    9373 
    9474   - Widgets are defined in a Python files. 
    95    - For Orange and Orange canvas to find them, they reside in subdirectories 
    96      in OrangeWidgets directory of Orange installation. The name of the 
    97      subdirectory matters, as this is the name of the widget category. Widgets 
    98      in the same directory will be grouped in the same pane of widget toolbox 
    99      in Orange Canvas. 
    100    - A file describing a widget starts with a header. This, given in sort of 
    101      XMLish style, tells about the name, short description, location of an 
    102      icon and priority of the widget. 
     75   - Widgets are registered through entry points and are discovered at 
     76     runtime. 
     77   - A python module implementing a widget starts with a header. This, given 
     78     in sort of XMLish style, tells about the name, short description, 
     79     location of an icon and priority of the widget. 
    10380   - The sole role of priority is to specify the placement (order) of widgets 
    10481     in the Orange Canvas toolbox. 
     
    10885     is seen from the outside. 
    10986 
    110 Oh, by the way. Orange caches widget descriptions to achieve a faster 
    111 startup, but this cache is automatically refreshed at startup if any change 
    112 is detected in widgets' files. 
     87.. note:: 
     88   Orange caches widget descriptions to achieve a faster startup, 
     89   but this cache is automatically refreshed at startup if any change 
     90   is detected in widgets' file. 
    11391 
    11492*********** 
     
    11997have some fun and write a widget. We will start with a very simple 
    12098one, that will receive a data set on the input and will output a data 
    121 set with 10% of the data instances. Not to mess with other widgets, we 
    122 will create a Test directory within OrangeWidgets directory, and write 
    123 the widget in a file called `OWDataSamplerA.py`: OW for Orange Widget, 
    124 DataSampler since this is what widget will be doing, and A since we 
    125 prototype a number of this widgets in our tutorial. 
    126  
    127 The script defining the OWDataSamplerA widget starts with a follwing header:: 
     99set with 10% of the data instances. We will call this widget 
     100`OWDataSamplerA.py` (OW for Orange Widget, DataSampler since this is what 
     101widget will be doing, and A since we prototype a number of this widgets 
     102in our tutorial). 
     103 
     104But first we must create a simple `python project`_ layout called *Demo*, 
     105that we will use in the rest of this tutorial. 
     106 
     107.. _`python project`: http://docs.python.org/2/distutils/examples.html#pure-python-distribution-by-package 
     108 
     109The layout should be:: 
     110 
     111   Demo/ 
     112         setup.py 
     113         orangedemo/ 
     114                     __init__.py 
     115                     OWDataSamplerA.py 
     116 
     117and the :download:`setup.py` should contain 
     118 
     119.. literalinclude:: setup.py 
     120 
     121Note that we declare our *orangedemo* package as containing widgets 
     122from an ad hoc defined category *Demo*. 
     123 
     124Following the previous example of OWTestLearners, our module defining 
     125the OWDataSamplerA widget starts with a following header:: 
    128126 
    129127    <name>Data Sampler</name> 
    130128    <description>Randomly selects a subset of instances from the data set</description> 
    131     <icon>icons/DataSamplerA.png</icon> 
     129    <icon>icons/DataSamplerA.svg</icon> 
    132130    <priority>10</priority> 
    133131 
     
    138136 
    139137Orange Widgets are all derived from the class OWWidget. The name of 
    140 the class should be match the file name, so the lines following the 
     138the class should match the file name, so the lines following the 
    141139header in our Data Sampler widget should look something like:: 
    142140 
     141    import Orange 
    143142    from OWWidget import * 
    144143    import OWGUI 
     
    147146 
    148147        def __init__(self, parent=None, signalManager=None): 
    149             OWWidget.__init__(self, parent, signalManager, 'SampleDataA') 
    150  
    151             self.inputs = [("Data", ExampleTable, self.data)] 
    152             self.outputs = [("Sampled Data", ExampleTable)] 
     148            OWWidget.__init__(self, parent, signalManager) 
     149 
     150            self.inputs = [("Data", Orange.data.Table, self.data)] 
     151            self.outputs = [("Sampled Data", Orange.data.Table)] 
    153152 
    154153            # GUI 
     
    158157            self.resize(100,50) 
    159158 
    160 In initialization, the widget calls the :obj:`__init__` function 
    161 of a base class, passing the name 'SampleData' which will, 
    162 essentially, be used for nothing else than a stem of a file for saving 
    163 the parameters of the widgets (we will regress on these somehow 
    164 latter in tutorial). Widget then defines inputs and outputs. For 
    165 input, widget defines a "Data" channel, accepting tokens of the type 
    166 orange.ExampleTable and specifying that :obj:`data` function will 
     159In initialization, the widget calls the :func:`__init__` method 
     160of a base class. Widget then defines inputs and outputs. For input, 
     161this is a *Data* channel, accepting tokens of the type 
     162:class:`Orange.data.Table` and specifying that :func:`data` method will 
    167163be used to handle them. For now, we will use a single output channel 
    168164called "Sampled Data", which will be of the same type 
    169 (orange.ExampleTable). 
    170  
    171 Notice that the types of the channels are 
    172 specified by a class name; you can use any classes here, but if your 
    173 widgets need to talk with other widgets in Orange, you will need to 
    174 check which classes are used there. Luckily, and as one of the main 
    175 design principles, there are just a few channel types that current 
    176 Orange widgets are using. 
     165(Orange.data.Table). 
     166 
     167Notice that the types of the channels are specified by a class; 
     168you can use any class here, but if your widgets need to talk with 
     169other widgets in Orange, you will need to check which classes are 
     170used there. Luckily, and as one of the main design principles, 
     171there are just a few channel types that current Orange widgets are 
     172using. 
    177173 
    178174The next four lines specify the GUI of our widget. This will be 
     
    196192 
    197193In order to complete our widget, we now need to define how will it 
    198 handle the input data. This is done in a function called 
    199 :obj:`data` (remember, we did introduce this name in the 
    200 specification of the input channel):: 
     194handle the input data. This is done in a method called :func:`data` 
     195(remember, we did introduce this name in the specification of the 
     196input channel):: 
    201197 
    202198    def data(self, dataset): 
     
    213209            self.send("Sampled Data", None) 
    214210 
    215 The function is defined within a class definition, so its first 
    216 argument has to be :obj:`self`. The second argument called 
    217 :obj:`dataset` is the token sent through the input channel which 
    218 our function needs to handle. 
     211The :obj:`dataset` argument is the token sent through the input 
     212channel which our method needs to handle. 
    219213 
    220214To handle the non-empty token, the widget updates the interface 
     
    225219"Sampled Data". 
    226220 
    227 Notice that the token can be empty (``dataset is None``), 
    228 resulting from either the sending widget to which we have connected 
    229 intentionally emptying the channel, or when the link between the two 
    230 widgets is removed. In any case, it is important that we always write 
    231 token handlers that appropriately handle the empty tokens. In our 
    232 implementation, we took care of empty input data set by appropriately 
    233 setting the GUI of a widget and sending an empty token to the 
    234 output channel. 
    235  
    236 .. 
    237    Although our widget is now ready to test, for a final touch, let's 
    238    design an icon for our widget. As specified in the widget header, we 
    239    will call it :download:`DataSamplerA.png <DataSamplerA.png>` and will 
    240    put it in icons subdirectory of OrangeWidgets directory (together with 
    241    all other icons of other widgets). 
     221Notice that the token can be empty (``None``), resulting from either 
     222the sending widget to which we have connected intentionally emptying 
     223the channel, or when the link between the two widgets is removed. 
     224In any case, it is important that we always write token handlers 
     225that appropriately handle the empty tokens. In our implementation, 
     226we took care of empty input data set by appropriately setting the 
     227GUI of a widget and sending an empty token to the output channel. 
     228 
     229 
     230Although our widget is now ready to test, for a final touch, let's 
     231design an icon for our widget. As specified in the widget header, we 
     232will call it :download:`DataSamplerA.svg <DataSamplerA.svg>` and will 
     233put it in `icons` subdirectory of `orangedemo` directory. 
     234 
     235With this we cen now go ahead and install the orangedemo package. We 
     236will do this by running :code:`python setup.py develop` command from 
     237the `Demo` directory. 
     238 
     239.. note:: 
     240   Depending on your python installation you might need 
     241   administrator/superuser privileges. 
    242242 
    243243For a test, we now open Orange Canvas. There should be a new pane in a 
    244 widget toolbox called Test (this is the name of the directory we have 
    245 used to put in our widget). If we click on this pane, it displays an 
    246 icon of our widget. Try to hoover on it to see if the header and 
    247 channel info was processed correctly: 
     244widget toolbox called Demo. If we click on this pane, it displays an 
     245icon of our widget. Try to hover on it to see if the header and channel 
     246info was processed correctly: 
    248247 
    249248.. image:: samplewidgetontoolbox.png 
    250249 
    251250Now for the real test. We put the File widget on the schema (from 
    252 Data pane), read iris.tab data set. We also put our Data Sampler widget on the pane and 
    253 open it (double click on the icon, or right-click and choose 
    254 Open): 
     251Data pane) and load the iris.tab data set. We also put our Data 
     252Sampler widget on the scheme and open it (double click on the icon, 
     253or right-click and choose Open): 
    255254 
    256255.. image:: datasamplerAempty.png 
    257256 
    258 Drag this window off the window with the widget schema of Orange 
    259 Canvas, and connect File and Data Sampler widget (click on an ouput 
    260 connector - green box - of the File widget, and drag the line to the 
    261 input connector of the Data Sampler). If everything is ok, as soon as 
    262 you release the mouse the connection is established and, the token 
    263 that was waiting on the output of the file widget was sent to the Data 
    264 Sampler widget, which in turn updated its window: 
     257Now connect the File and Data Sampler widget (click on an output 
     258connector of the File widget, and drag the line to the input connector 
     259of the Data Sampler). If everything is ok, as soon as you release the 
     260mouse, the connection is established and, the token that was waiting 
     261on the output of the file widget was sent to the Data Sampler widget, 
     262which in turn updated its window: 
    265263 
    266264.. image:: datasamplerAupdated.png 
     
    292290        ow = OWDataSamplerA() 
    293291        ow.show() 
    294         dataset = orange.ExampleTable('iris.tab') 
     292        dataset = Orange.data.Table('iris.tab') 
    295293        ow.data(dataset) 
    296294        appl.exec_() 
    297295 
    298296These are essentially some calls to Qt routines that run GUI for our 
    299 widgets. At the core, however, notice that instead of sending the 
    300 token to the input channel, we directly called the routine for token 
    301 handling (:obj:`data`). 
    302  
    303 To test your widget in more complex environment, that for instance 
    304 requires to set a complex schema in which your widget collaborates, 
    305 use Orange Canvas to set the schema and then either 1) save the schema 
    306 to be opened every time you run Orange Canvas, or 2) save this schema 
    307 (File menu) as an application within a single file you will need to 
    308 run each time you will test your widget. 
     297widgets. Notice that we call the :func:`data` method directly. 
  • docs/extend-widgets/rst/channels.rst

    r11439 r11593  
    1818******************** 
    1919 
    20 First, I do not like the name, but can't make up anything better. In 
    21 essence, the basic idea about "multi-input" channels is that they can 
     20In essence, the basic idea about "multi-input" channels is that they can 
    2221be used to connect them with several output channels. That is, if a 
    2322widget supports such a channel, several widgets can feed their input 
     
    2524 
    2625Say we want to build a widget that takes a data set and test 
    27 various predictive modelling techniques on it. A widget has to have an 
     26various predictive modeling techniques on it. A widget has to have an 
    2827input data channel, and this we know how to deal with from our 
    2928:doc:`previous <settings>` lesson. But, somehow differently, we 
     
    5049widget are defined by:: 
    5150 
    52     self.inputs = [("Data", ExampleTable, self.dataset), 
    53                    ("Learner", orange.Learner, self.learner, Multiple + Default)] 
     51    self.inputs = [("Data", Orange.data.Table, self.dataset), 
     52                   ("Learner", Orange.classification.Learner, 
     53                    self.learner, Multiple + Default)] 
    5454 
    5555Notice that everything is pretty much the same as it was with 
     
    6363channel for its type (more on default channels later). 
    6464 
    65 .. note:: :obj:`Default` flag here is used for illustration. Since *Learner* 
    66           channel is the only channel for a :class:`orange.Learner` type 
    67           it is also the default. 
     65.. note:: 
     66   :obj:`Default` flag here is used for illustration. Since *"Learner"* 
     67   channel is the only channel for a :class:`Orange.classification.Learner` 
     68   type it is also the default. 
    6869 
    6970How does the widget know from which widget did the token come from? 
     
    7172sending the token, and having a multi-input channel only tells Orange to 
    7273send a token together with sending widget id, the two arguments with 
    73 which the receiving function is called. For our :obj:`Learner` 
    74 channel the receiving function is :obj:`learner`, and this looks 
     74which the receiving function is called. For our *"Learner"* 
     75channel the receiving function is :func:`learner`, and this looks 
    7576like the following:: 
    7677 
     
    131132(:obj:`None`). Remember that sending an empty learner 
    132133essentially means that the link with the sending widget was removed, 
    133 hance we need to remove such learner from our list. If a non-empty 
     134hence we need to remove such learner from our list. If a non-empty 
    134135learner was sent, then it is either a new learner (say, from a widget 
    135136we have just linked to our learning curve widget), or an update 
     
    149150all that is needed is the augmenting the list:: 
    150151 
    151     self.scoring = [("Classification Accuracy", orngStat.CA), 
    152                     ("AUC", orngStat.AUC), 
    153                     ("BrierScore", orngStat.BrierScore), 
    154                     ("Information Score", orngStat.IS), 
    155                     ("Sensitivity", orngStat.sens), 
    156                     ("Specificity", orngStat.spec)] 
     152    self.scoring = [("Classification Accuracy", Orange.evaluation.scoring.CA), 
     153                    ("AUC", Orange.evaluation.scoring.AUC), 
     154                    ("BrierScore", Orange.evaluation.scoring.Brier_score), 
     155                    ("Information Score", Orange.evaluation.scoring.IS), 
     156                    ("Sensitivity", Orange.evaluation.scoring.Sensitivity), 
     157                    ("Specificity", Orange.evaluation.scoring.Specificity)] 
    157158 
    158159which is defined in the initialization part of the widget. The 
     
    178179is:: 
    179180 
    180     self.outputs = [("Sampled Data", ExampleTable), ("Other Data", ExampleTable)] 
     181    self.outputs = [("Sampled Data", Orange.data.Table), 
     182                    ("Other Data", Orange.data.Table)] 
    181183 
    182184We used this in the third incarnation of :download:`data sampler widget <OWDataSamplerC.py>`, 
    183 with essentially the only other change in the code in the :obj:`selection` and 
    184 :obj:`commit` functions:: 
     185with essentially the only other change in the code in the :func:`selection` and 
     186:func:`commit` functions:: 
    185187 
    186188    def selection(self): 
    187         indices = orange.MakeRandomIndices2(p0=self.proportion / 100.) 
     189        indices = Orange.data.sample.SubsetIndices2(p0=self.proportion / 100.) 
    188190        ind = indices(self.dataset) 
    189191        self.sample = self.dataset.select(ind, 0) 
     
    197199If a widget that has multiple channels of the same type is 
    198200connected to a widget that accepts such tokens, Orange Canvas opens a 
    199 window asking the user to confirm which channels to connect. The 
    200 channel mentioned in :obj:`self.outputs` is connected by 
    201 default. Hence, if we have just connected Data Sampler 
    202 (C) widget to a Data Table widget in a schema below: 
     201window asking the user to confirm which channels to connect. Hence, 
     202if we have just connected *Data Sampler (C)* widget to a Data Table 
     203widget in a schema below: 
    203204 
    204205.. image:: datasampler-totable.png 
     
    223224training data set channel will be the default one. 
    224225 
    225 When enlisting the input channel of the same type, the non-default 
     226When enlisting the input channel of the same type, the default 
    226227channels have a special flag in the channel specification list. So for 
    227228our new :download:`learning curve <OWLearningCurveB.py>` widget, the 
    228229channel specification is:: 
    229230 
    230     self.inputs = [("Train Data", ExampleTable, self.trainset, Default), 
    231                    ("Test Data", ExampleTable, self.testset), 
    232                    ("Learner", orange.Learner, self.learner, Multiple)] 
     231    self.inputs = [("Train Data", Orange.data.Table, self.trainset, Default), 
     232                   ("Test Data", Orange.data.Table, self.testset), 
     233                   ("Learner", Orange.classification.Learner, self.learner, Multiple)] 
    233234 
    234235That is, the :obj:`Train Data` channel is a single-token 
     
    240241.. image:: file-to-learningcurveb.png 
    241242 
    242 That is, no window with a query on which channels 
    243 to connect to will open. To find out which channels got connected, 
    244 double click on the green link between the two widgets: 
    245  
    246 .. image:: file-to-learningcurveb-channels.png 
     243That is, no window with a query on which channels to connect to will 
     244open, as the default *"Train Data"* was selected. 
  • docs/extend-widgets/rst/contextsettings.rst

    r11408 r11593  
    2121selecting a subset of attributes and the class attributes (note that a 
    2222better widget for this task is already included in your Orange 
    23 instalation). 
     23installation). 
    2424 
    2525.. image:: attributesampler.png 
     
    2929somehow store the user's selection. 
    3030 
    31 Here's the widget's :obj:`__init__` function. 
    32  
    33 Part of :download:`OWAttributeSampler.py <OWAttributeSampler.py>`:: 
    34  
    35     def __init__(self, parent=None, signalManager=None): 
    36         OWWidget.__init__(self, parent, signalManager, 'AttributeSampler') 
    37  
    38         self.inputs = [("Examples", ExampleTable, self.dataset)] 
    39         self.outputs = [("Examples", ExampleTable)] 
    40  
    41         self.icons = self.createAttributeIconDict() 
    42  
    43         self.attributeList = [] 
    44         self.selectedAttributes = [] 
    45         self.classAttribute = None 
    46         self.loadSettings() 
    47  
    48         OWGUI.listBox(self.controlArea, self, "selectedAttributes", "attributeList", box="Selected attributes", selectionMode = QListWidget.ExtendedSelection) 
    49         OWGUI.separator(self.controlArea) 
    50         self.classAttrCombo = OWGUI.comboBox(self.controlArea, self, "classAttribute", box="Class attribute") 
    51         OWGUI.separator(self.controlArea) 
    52         OWGUI.button(self.controlArea, self, "Commit", callback = self.outputData) 
    53  
    54         self.resize(150,400) 
     31Here's the widget's :func:`__init__` function. 
     32 
     33Part of :download:`OWAttributeSampler.py <OWAttributeSampler.py>` 
     34 
     35.. literalinclude:: OWAttributeSampler.py 
     36   :pyobject: OWAttributeSampler.__init__ 
    5537 
    5638Note that we are strictly using controls from OWGUI. As for the 
     
    6446 
    6547When the widget gets the data, a function :obj:`dataset` is 
    66 called. 
    67  
    68 Part of :download:`OWAttributeSampler.py`:: 
     48called:: 
    6949 
    7050    def dataset(self, data): 
     
    8565 
    8666 
    87     def outputData(self): 
    88         if not self.data: 
    89             self.send("Examples", None) 
    90         else: 
    91             newDomain = orange.Domain([self.data.domain[i] for i in self.selectedAttributes], self.data.domain[self.classAttribute]) 
    92             newData = orange.ExampleTable(newDomain, self.data) 
    93             self.send("Examples", newData) 
     67.. literalinclude:: OWAttributeSampler.py 
     68   :pyobject: OWAttributeSampler.outputData 
     69 
    9470 
    9571Nothing special here (yet). We fill the list box, deselect all 
     
    11086exist in the actual domain at all. 
    11187 
    112 To make the setting dependent on the context, we put :: 
    113  
    114     contextHandlers = {"": DomainContextHandler("", [ 
    115             ContextField("classAttribute", DomainContextHandler.Required), 
    116             ContextField("attributeList", DomainContextHandler.List + 
    117                                           DomainContextHandler.SelectedRequired, 
    118                          selected="selectedAttributes")])} 
     88To make the setting dependent on the context, we put 
     89 
     90.. literalinclude:: OWAttributeSampler.py 
     91   :start-after: # ~start context handler~ 
     92   :end-before: # ~end context handler~ 
    11993 
    12094at the same place where we usually declare :obj:`settingsList`. 
     
    156130(:obj:`DomainContextHandler.Optional`); sometimes certain 
    157131attribute doesn't really matter, so if it is present in the domain, 
    158 it's gonna be used, otherwise not. And for the list, we could say 
     132it's going to be used, otherwise not. And for the list, we could say 
    159133:obj:`DomainContextHandler.List + DomainContextHandler.Required` 
    160134in which case all the attributes on the list would be required for the 
    161135domain to match. 
    162136 
    163 The default flag is :obj:`DomainContextHandler.Required`, and there are other shortcuts for declaring the context, too. The above code could be simplified as :: 
    164  
    165     contextHandlers = {"": DomainContextHandler("", [ 
    166             "classAttribute", 
    167             ContextField("attributeList", DomainContextHandler.SelectedRequiredList, 
    168                          selected="selectedAttributes")])} 
     137The default flag is :obj:`DomainContextHandler.Required`, and there 
     138are other shortcuts for declaring the context, too. The above code could 
     139be simplified as :: 
     140 
     141    contextHandlers = { 
     142        "": DomainContextHandler( 
     143            "", 
     144            ["classAttribute", 
     145             ContextField("attributeList", 
     146                          DomainContextHandler.SelectedRequiredList, 
     147                          selected="selectedAttributes")])} 
    169148 
    170149Why the dictionary and the empty string as the key? A widget can 
     
    186165function :obj:`dataset` 
    187166 
    188 Part of :download:`OWAttributeSampler.py`:: 
    189  
    190     def dataset(self, data): 
    191         self.closeContext() 
    192      
    193         self.classAttrCombo.clear() 
    194         if data: 
    195             self.attributeList = [(attr.name, attr.varType) for attr in data.domain] 
    196             self.selectedAttributes = [] 
    197             for attrName, attrType in self.attributeList: 
    198                 self.classAttrCombo.addItem(self.icons[attrType], attrName) 
    199             self.classAttribute = 0 
    200         else: 
    201             self.attributeList = [] 
    202             self.selectedAttributes = [] 
    203             self.classAttrCombo.addItem("") 
    204      
    205         self.openContext("", data) 
    206      
    207         self.data = data 
    208         self.outputData() 
    209  
    210 We added only two lines. First, before you change any controls in the widget, you need to call :obj:`self.closeContext` (the function has an optional argument, the context name, but since we use the default name, an empty string, we can omit it). This reads the data from the widget into the stored context. Then the function proceeds as before: the controls (the list box and combo box) are filled in as if there were no context handling (this is important, so once again: widget should be set up as if there were not context dependent settings). When the controls are put in a consistent state, we call :obj:`self.openContext`. The first argument is the context name and the second is the object from which the handler reads the context. In case of :obj:`DomainContextHandler` this can be either a domain or the data. :obj:`openContext` will make the context handler search through the stored context for the one that (best) matches the data, and if one is find the widget's state is set accordingly (that is, the list boxes are filled, attributes in it are selected etc.). If no context is found, a new context is established and the data from widget is copied to the context. 
     167.. literalinclude:: OWAttributeSampler.py 
     168   :pyobject: OWAttributeSampler.dataset 
     169 
     170We added only two lines. First, before you change any controls in 
     171the widget, you need to call :obj:`self.closeContext` (the function 
     172has an optional argument, the context name, but since we use the 
     173default name, an empty string, we can omit it). This reads the 
     174data from the widget into the stored context. Then the function 
     175proceeds as before: the controls (the list box and combo box) 
     176are filled in as if there were no context handling (this is 
     177important, so once again: widget should be set up as if there 
     178were not context dependent settings). When the controls are put 
     179in a consistent state, we call :obj:`self.openContext`. The first 
     180argument is the context name and the second is the object from 
     181which the handler reads the context. In case of 
     182:obj:`DomainContextHandler` this can be either a domain or the 
     183data. :obj:`openContext` will make the context handler search 
     184through the stored context for the one that (best) matches the 
     185data, and if one is find the widget's state is set accordingly 
     186(that is, the list boxes are filled, attributes in it are selected 
     187etc.). If no context is found, a new context is established and the 
     188data from widget is copied to the context. 
    211189 
    212190What can be stored as a context dependent setting? Anything, even 
  • docs/extend-widgets/rst/graphing.rst

    r11439 r11593  
    44 
    55The most fun widgets are of course those that include graphics. For 
    6 this we either use control called canvas, which is Qt's general 
    7 control for doing any graphics of choice (widgets for tree and heat map 
    8 visualizations, for instance, use this), or use a special control for 
    9 drawing data plots as provided in Qwt library and PyQwt 
     6this we either use Qt's :class:`QGraphicsScene` (widgets for tree and 
     7heat map visualizations, for instance, use this), or use a special 
     8control for drawing data plots as provided in Qwt library and :mod:`PyQwt` 
    109interface. Here we look at the latter, and extend our learning curve 
    1110widget with a control that plots the curve. 
     
    2625The widget still provides learning curve table, but this is now 
    2726offered in a tabbed pane together with a graph. The code for 
    28 definition of the tabbed pane, and initialization of the graph is:: 
     27definition of the tabbed pane, and initialization of the graph is 
    2928 
    30     # start of content (right) area 
    31     tabs = OWGUI.tabWidget(self.mainArea) 
     29.. literalinclude:: OWLearningCurveC.py 
     30   :start-after: # ~SPHINX start main area tabs~ 
     31   :end-before: # ~SPHINX end main area tabs~ 
    3232 
    33     # graph widget 
    34     tab = OWGUI.createTabPage(tabs, "Graph") 
    35     self.graph = OWGraph(tab) 
    36     self.graph.setAxisAutoScale(QwtPlot.xBottom) 
    37     self.graph.setAxisAutoScale(QwtPlot.yLeft) 
    38     tab.layout().addWidget(self.graph) 
    39     self.setGraphGrid() 
     33:class:`~OWGraph.OWGrap` is a convenience subclass of :class:`QwtPlot` 
     34and is imported from OWGraph module. For the graph, we use 
     35:func:`setAxisAutoScale` to request that the axis are automatically 
     36set in regard to the data that is plotted in the graph. We plot 
     37the graph in using the following code 
    4038 
    41 :obj:`OWGrap` is a convenience subclass of QwtPlot and is imported from 
    42 OWGraph module. For the graph, we use :obj:`setAxisAutoScale` to 
    43 request that the axis are automatically set in regard to the data that 
    44 is plotted in the graph. We plot the graph in using the following 
    45 code:: 
    46  
    47     def drawLearningCurve(self, learner): 
    48         if not self.data: return 
    49         curve = self.graph.addCurve(learner.name, xData=self.curvePoints, yData=learner.score, autoScale=True) 
    50  
    51         learner.curve = curve 
    52         self.setGraphStyle(learner) 
    53         self.graph.replot() 
     39.. literalinclude:: OWLearningCurveC.py 
     40   :pyobject: OWLearningCurveC.drawLearningCurve 
    5441 
    5542This is simple. We store the curve returned from :obj:`addCurve` with a 
    56 learner, and use a trick allowed in Orange that we can simply store 
    57 this as a new attribute to the learning object. By default, Orange 
    58 would give a warning of the type:: 
    59  
    60     c:\Python23\Lib\site-packages\orange\OrangeWidgets\Test\OWLearningCurveC.py:269: 
    61      AttributeWarning: 'curve' is not a builtin attribute of 'kNNLearner' 
    62       setattr(learner, "curve", curve) 
    63  
    64 but we surpress such warnings with a line:: 
    65  
    66     warnings.filterwarnings("ignore", ".*builtin attribute.*", orange.AttributeWarning) 
    67  
     43learner. 
    6844 
    6945.. warning:: 
    7046 
    71    This is a very bad design. Please do **not** store widget data in the 
    72    input objects. 
     47   This is a very bad design. Please do **not** store widget specific 
     48   data in the input objects. 
    7349 
    7450 
    75 in the initialization part of the widget. In this way, each learner 
    76 also stores the current scores, which is a list of numbers to be 
    77 plotted in Qwt graph. The details on how the plot is set are dealt 
    78 with in :obj:`setGraphStyle` function:` :: 
     51In this way, each learner also stores the current scores, which is a 
     52list of numbers to be plotted in Qwt graph. The details on how the 
     53plot is set are dealt with in :obj:`setGraphStyle` function: 
    7954 
    80     def setGraphStyle(self, learner): 
    81         curve = learner.curve 
    82         if self.graphDrawLines: 
    83             curve.setStyle(QwtPlotCurve.Lines) 
    84         else: 
    85             curve.setStyle(QwtPlotCurve.NoCurve) 
    86         curve.setSymbol(QwtSymbol(QwtSymbol.Ellipse, \ 
    87           QBrush(QColor(0,0,0)), QPen(QColor(0,0,0)), 
    88           QSize(self.graphPointSize, self.graphPointSize))) 
    89         curve.setPen(QPen(learner.color, 5)) 
     55.. literalinclude:: OWLearningCurveC.py 
     56   :pyobject: OWLearningCurveC.setGraphStyle 
     57 
    9058 
    9159Notice that the color of the plot line that is specific to the 
     
    10371instances of one class should be plotted in scatter plot and parallel 
    10472axis plot using the same color. Developers are thus advised to use 
    105 :obj:`ColorPaletteHSV`, which is provided as a method within 
    106 :mod:`OWWidget` module. :obj:`ColorPaletteHSV` takes an 
    107 integer as an attribute, and returns a list of corresponding number of 
     73:obj:`ColorPaletteHSV`, which can be imported from :mod:`OWWidget` 
     74module. :obj:`ColorPaletteHSV` takes an 
     75integer as an parameter, and returns a list of corresponding number of 
    10876colors. In our learning curve widget, we use it within a function that 
    109 sets the list box with learners:: 
     77sets the list box with learners 
    11078 
    111     def updatellb(self): 
    112         self.blockSelectionChanges = 1 
    113         self.llb.clear() 
    114         colors = ColorPaletteHSV(len(self.learners)) 
    115         for (i,lt) in enumerate(self.learners): 
    116             l = lt[1] 
    117             item = QListWidgetItem(ColorPixmap(colors[i]), l.name) 
    118             self.llb.addItem(item) 
    119             item.setSelected(l.isSelected) 
    120             l.color = colors[i] 
    121         self.blockSelectionChanges = 0 
     79.. literalinclude:: OWLearningCurveC.py 
     80   :pyobject: OWLearningCurveC.updatellb 
    12281 
    12382The code above sets the items of the list box, where each item 
     
    12685returned by :obj:`ColorPixmap` function defined in 
    12786:obj:`OWColorPalette.py`. Else, the classifier's list box control is 
    128 defined in the initialization of the widget using:: 
     87defined in the initialization of the widget using 
    12988 
    130     self.cbox = OWGUI.widgetBox(self.controlArea, "Learners") 
    131     self.llb = OWGUI.listBox(self.cbox, self, "selectedLearners", 
    132                              selectionMode=QListWidget.MultiSelection, 
    133                              callback=self.learnerSelectionChanged) 
    134  
    135     self.llb.setMinimumHeight(50) 
    136     self.blockSelectionChanges = 0 
     89.. literalinclude:: OWLearningCurveC.py 
     90   :start-after: # ~SPHINX start color cb~ 
     91   :end-before: # ~SPHINX end color cb~ 
    13792 
    13893Now, what is this :obj:`blockSelectionChanges`? Any time 
    13994user makes a selection change in list box of classifiers, we want to 
    14095invoke the procedure called 
    141 :obj:`learnerSelectionChanged`. But we want to perform 
     96:func:`learnerSelectionChanged`. But we want to perform 
    14297actions there when changes in the list box are invoked from clicking 
    14398by a user, and not by changing list box items from a program. This is 
    144 why, every time we want :obj:`learnerSelectionChanged` not to 
     99why, every time we want :func:`learnerSelectionChanged` not to 
    145100perform its function, we set :obj:`self.blockSelectionChanges` 
    146101to 1. 
    147102 
    148 In our widget, :obj:`learnerSelectionChanged` figures out 
     103In our widget, :func:`learnerSelectionChanged` figures out 
    149104if any curve should be removed from the graph (the user has just 
    150105deselected the corresponding item in the list box) or added to the 
    151 graph (the user just selected a learner):: 
     106graph (the user just selected a learner) 
    152107 
     108.. literalinclude:: OWLearningCurveC.py 
     109   :pyobject: OWLearningCurveC.learnerSelectionChanged 
     110 
     111.. 
    153112    def learnerSelectionChanged(self): 
    154113        if self.blockSelectionChanges: 
  • docs/extend-widgets/rst/progressbar.rst

    r11408 r11593  
    77computation. For that purpose orange widgets use progress bar 
    88functions, to which they report progress in terms of per-cent 
    9 completion of the task. The progress is then either reported above the 
    10 icon of the widget in Orange Canvas. 
     9completion of the task. The progress is then either on the icon 
     10of the widget in Orange Canvas 
    1111 
    12 .. image:: progressbar-canvas.png 
     12.. image:: learningcurve.png 
    1313 
    1414or in the title bar of the widget's window. There, Orange also 
    1515reports on the estimated time of completion of the task: 
    1616 
    17 .. image:: progressbar-widget.png 
     17.. image:: learningcurve-output.png 
    1818 
    19 Class :obj:`OWWidget`, the mother class of all 
    20 widgets, has for this purpose a set of functions, which include: 
     19:class:`OWWidget` has for this purpose a set of functions, which include: 
    2120 
    2221.. method:: progressBarInit() 
     
    2625.. method:: progressBarFinished() 
    2726 
    28  
    2927where value is any number between 0 and 100. Sometimes, like it is 
    3028the case for our widgets, we know about the number of iterations involved in 
    3129computation, and we would only like to advance the progress bar for 
    3230some constant at the end of the iteration. For this, we use 
    33 :obj:`ProgressBar` class in :obj:`OWGUI`, and the code in 
     31:class:`ProgressBar` class in :mod:`OWGUI`, and the code in 
    3432the learning curve widget described in the previous lesson that does 
    3533it is as follows:: 
    3634 
    3735    def getLearningCurve(self, learners): 
    38         pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds) 
    39         curve = orngTest.learningCurveN(learners, self.data, 
    40             folds=self.folds, proportions=self.curvePoints, callback=pb.advance) 
     36        pb = OWGUI.ProgressBar(self, iterations=self.steps * self.folds) 
     37        curve = Orange.evaluation.testing.learning_curve_n( 
     38            learners, self.data, folds=self.folds, 
     39            proportions=self.curvePoints, callback=pb.advance) 
    4140        pb.finish() 
    4241        return curve 
    4342 
    44 :obj:`ProgressBar` class removes the need to define any 
    45 special function to compute the percent of the task done and set the 
    46 progress bar, and instead uses :obj:`ProgressBar`'s method 
    47 :obj:`advance` for this purpose. 
     43:class:`ProgressBar` class removes the need to define any special 
     44function to compute the percent of the task done and set the 
     45progress bar, and instead uses :class:`ProgressBar`'s method 
     46:func:`advance` for this purpose. 
  • docs/extend-widgets/rst/settings.rst

    r11439 r11593  
    4646    class OWDataSamplerB(OWWidget): 
    4747        settingsList = ['proportion', 'commitOnChange'] 
    48         def __init__(self, parent=None, signalManager=None): 
    4948 
    5049Any setting has to be initialized, and then we need to call 
     
    157156of this widget. To distinguish it with a widget we have developed in the 
    158157previous section, we have designed a special 
    159 :download:`icon <DataSamplerB.png>` for it. If you wish to test is 
     158:download:`icon <DataSamplerB.svg>` for it. If you wish to test is 
    160159widget in the Orange Canvas, put its code in the Test directory we 
    161160have created for the previous widget, update the Canvas registry, and 
     
    410409:obj:`ContextField("attrX", DomainContextHandler.Required)` 
    411410 
    412 .. 
    413    But see this monster from widget "Select Attributes" (file OWDataDomain.py):: 
    414  
    415        contextHandlers = {"": DomainContextHandler("", 
    416            [ContextField("chosenAttributes", 
    417                           DomainContextHandler.RequiredList, 
    418                           selected="selectedChosen", reservoir="inputAttributes"), 
    419             ContextField("classAttribute", 
    420                           DomainContextHandler.RequiredList, 
    421                           selected="selectedClass", reservoir="inputAttributes"), 
    422             ContextField("metaAttributes", 
    423                           DomainContextHandler.RequiredList, 
    424                           selected="selectedMeta", reservoir="inputAttributes") 
    425        ])} 
    426  
    427  
    428    :obj:`ContextField`'s constructor gets the name and flags and a list of 
    429    arguments that are written directly into the object instance. To follow the 
    430    example, recall what Select Attributes looks like: it allows you to select a 
    431    subset of attributes, the class attribute and the meta attributes that you 
    432    want to use; the attributes in the corresponding three list boxes are stored 
    433    in the widget's variables :obj:`chosenAttributes`, :obj:`classAttribute` 
    434    and :obj:`metaAttributes` respectively. When the user selects some attributes 
    435    in any of these boxes, the selection is stored in :obj:`selectedChosen`, 
    436    :obj:`selectedClass` and :obj:`selectedMeta`. The remaining attributes 
    437    - those that are not in any of these three list boxes - are in the leftover 
    438    listbox on the left-hand side of the widget, and the content of the box is 
    439    stored in the widget's variable :obj:`inputAttributes`. 
    440  
    441    The above definition tells that the context needs to store the contents of 
    442    the three list boxes by specifying the corresponding variables; the list of 
    443    attributes is given as the name of the field and the list of selected 
    444    attributes is in the optional named attribute :obj:`selected`. By 
    445    :obj:`reservoir` we told the context handler that the attributes are taken 
    446    from :obj:`inputAttributes`. So, when a context is retrieved, all the 
    447    attributes that are not in any of the three list boxes are put into 
    448    :obj:`inputAttributes`. 
    449  
    450    Why the mess? Couldn't we just store :obj:`inputAttributes` as the fourth 
    451    list box? Imagine that the user first loads the data with attributes A, B, 
    452    C, D, E and F, puts A, B, C in chosen and D in class. E and F are left in 
    453    :obj:`inputAttributes`. Now she loads another data which has attributes A, 
    454    B, C, D, E, and G. The contexts should match (the new data has all the 
    455    attributes we need), but :obj:`inputAttributes` should now contain E and 
    456    G, not E and F, since F doesn't exist any more, while G needs to be made 
    457    available. 
    458  
    459    You can use :obj:`ContextField` (instead of tuples and strings) for 
    460    declaring any fields, but you will usually need them only for lists or, 
    461    maybe, some complicated future controls. 
    462  
    463411 
    464412***************************** 
Note: See TracChangeset for help on using the changeset viewer.