Blaz Zupan avatar Blaz Zupan committed afd9213 Merge

Merge with recent head, new tutorial.

Comments (0)

Files changed (501)

 import numpydoc
 sphinx.ext.autodoc.inspect = myinspect
 numpydoc.docscrape.inspect = myinspect
-
 module_setup = imp.load_source('module_setup', os.path.join(PATH, '..', 'setup.py'))
 VERSION = module_setup.VERSION
 AUTHOR = module_setup.AUTHOR
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 sys.path.append(os.path.abspath(os.path.join(PATH, "..")))
+sys.path.append(os.path.abspath(os.path.join(PATH, "..", "Orange")))
 import Orange
 
 # -- General configuration -----------------------------------------------------
Add a comment to this file

docs/extend-widgets/rst/DataSamplerB.png

Added
New image

docs/extend-widgets/rst/OWAttributeSampler.py

+"""
+<name>Attribute Sampler</name>
+<description>Lets the user select a list of attributes and the class attribute</description>
+<icon>icons/AttributeSampler.png</icon>
+<priority>1020</priority>
+"""
+
+from OWWidget import *
+import OWGUI
+
+class OWAttributeSampler(OWWidget):
+    settingsList = []
+    contextHandlers = {"": DomainContextHandler("", [
+            ContextField("classAttribute", DomainContextHandler.Required),
+            ContextField("attributeList", DomainContextHandler.List + DomainContextHandler.SelectedRequired,
+                         selected="selectedAttributes")])}
+
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'AttributeSampler')
+
+        self.inputs = [("Examples", ExampleTable, self.dataset)]
+        self.outputs = [("Examples", ExampleTable)]
+
+        self.icons = self.createAttributeIconDict()
+
+        self.attributeList = []
+        self.selectedAttributes = []
+        self.classAttribute = None
+        self.loadSettings()
+
+        OWGUI.listBox(self.controlArea, self, "selectedAttributes", "attributeList", box="Selected attributes", selectionMode = QListWidget.ExtendedSelection)
+        OWGUI.separator(self.controlArea)
+        self.classAttrCombo = OWGUI.comboBox(self.controlArea, self, "classAttribute", box="Class attribute")
+        OWGUI.separator(self.controlArea)
+        OWGUI.button(self.controlArea, self, "Commit", callback = self.outputData)
+
+        self.resize(150,400)
+
+
+    def dataset(self, data):
+        self.closeContext()
+
+        self.classAttrCombo.clear()
+        if data:
+            self.attributeList = [(attr.name, attr.varType) for attr in data.domain]
+            self.selectedAttributes = []
+            for attrName, attrType in self.attributeList:
+                self.classAttrCombo.addItem(self.icons[attrType], attrName)
+            self.classAttribute = 0
+        else:
+            self.attributeList = []
+            self.selectedAttributes = []
+            self.classAttrCombo.addItem("")
+
+        self.openContext("", data)
+
+        self.data = data
+        self.outputData()
+
+
+    def outputData(self):
+        if not self.data:
+            self.send("Examples", None)
+        else:
+            newDomain = orange.Domain([self.data.domain[i] for i in self.selectedAttributes], self.data.domain[self.classAttribute])
+            newData = orange.ExampleTable(newDomain, self.data)
+            self.send("Examples", newData)
+
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWAttributeSampler()
+    ow.show()
+
+    data = orange.ExampleTable('../datasets/iris.tab')
+    ow.dataset(data)
+
+    appl.exec_()

docs/extend-widgets/rst/OWDataSamplerB.py

+"""
+<name>Data Sampler (B)</name>
+<description>Randomly selects a subset of instances from the data set</description>
+<icon>icons/DataSamplerB.png</icon>
+<priority>20</priority>
+"""
+from OWWidget import *
+import OWGUI
+
+class OWDataSamplerB(OWWidget):
+    settingsList = ['proportion', 'commitOnChange']
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'SampleDataB')
+
+        self.inputs = [("Data", ExampleTable, self.data)]
+        self.outputs = [("Sampled Data", ExampleTable)]
+
+        self.proportion = 50
+        self.commitOnChange = 0
+        self.loadSettings()
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input yet, waiting to get something.')
+        self.infob = OWGUI.widgetLabel(box, '')
+
+        OWGUI.separator(self.controlArea)
+        self.optionsBox = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(self.optionsBox, self, 'proportion', min=10, max=90, step=10,
+                   label='Sample Size [%]:', callback=[self.selection, self.checkCommit])
+        OWGUI.checkBox(self.optionsBox, self, 'commitOnChange', 'Commit data on selection change')
+        OWGUI.button(self.optionsBox, self, "Commit", callback=self.commit)
+        self.optionsBox.setDisabled(1)
+
+        self.resize(100,50)
+
+    def data(self, dataset):
+        if dataset:
+            self.dataset = dataset
+            self.infoa.setText('%d instances in input data set' % len(dataset))
+            self.optionsBox.setDisabled(0)
+            self.selection()
+            self.commit()
+        else:
+            self.send("Sampled Data", None)
+            self.optionsBox.setDisabled(1)
+            self.infoa.setText('No data on input yet, waiting to get something.')
+            self.infob.setText('')
+
+    def selection(self):
+        indices = orange.MakeRandomIndices2(p0=self.proportion / 100.)
+        ind = indices(self.dataset)
+        self.sample = self.dataset.select(ind, 0)
+        self.infob.setText('%d sampled instances' % len(self.sample))
+
+    def commit(self):
+        self.send("Sampled Data", self.sample)
+
+    def checkCommit(self):
+        if self.commitOnChange:
+            self.commit()
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWDataSamplerB()
+    ow.show()
+    dataset = orange.ExampleTable('../datasets/iris.tab')
+    ow.data(dataset)
+    appl.exec_()

docs/extend-widgets/rst/OWDataSamplerC.py

+"""
+<name>Data Sampler (C)</name>
+<description>Randomly selects a subset of instances from the data set</description>
+<icon>icons/DataSamplerC.png</icon>
+<priority>30</priority>
+"""
+from OWWidget import *
+import OWGUI
+
+class OWDataSamplerC(OWWidget):
+    settingsList = ['proportion', 'commitOnChange']
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'SampleDataC')
+        
+        self.inputs = [("Data", ExampleTable, self.data)]
+        self.outputs = [("Sampled Data", ExampleTable), ("Other Data", ExampleTable)]
+
+        self.proportion = 50
+        self.commitOnChange = 0
+        self.loadSettings()
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input yet, waiting to get something.')
+        self.infob = OWGUI.widgetLabel(box, '')
+
+        OWGUI.separator(self.controlArea)
+        self.optionsBox = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(self.optionsBox, self, 'proportion', min=10, max=90, step=10,
+                   label='Sample Size [%]:', callback=[self.selection, self.checkCommit])
+        OWGUI.checkBox(self.optionsBox, self, 'commitOnChange', 'Commit data on selection change')
+        OWGUI.button(self.optionsBox, self, "Commit", callback=self.commit)
+        self.optionsBox.setDisabled(1)
+
+        self.resize(100,50)
+
+    def data(self, dataset):
+        if dataset:
+            self.dataset = dataset
+            self.infoa.setText('%d instances in input data set' % len(dataset))
+            self.optionsBox.setDisabled(0)
+            self.selection()
+            self.commit()
+        else:
+            self.send("Sampled Data", None)
+            self.optionsBox.setDisabled(1)
+            self.infoa.setText('No data on input yet, waiting to get something.')
+            self.infob.setText('')
+
+    def selection(self):
+        indices = orange.MakeRandomIndices2(p0=self.proportion / 100.)
+        ind = indices(self.dataset)
+        self.sample = self.dataset.select(ind, 0)
+        self.otherdata = self.dataset.select(ind, 1)
+        self.infob.setText('%d sampled instances' % len(self.sample))
+
+    def commit(self):
+        self.send("Sampled Data", self.sample)
+        self.send("Other Data", self.otherdata)
+
+    def checkCommit(self):
+        if self.commitOnChange:
+            self.commit()
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWDataSamplerC()
+    ow.show()
+    dataset = orange.ExampleTable('../datasets/iris.tab')
+    ow.data(dataset)
+    appl.exec_()

docs/extend-widgets/rst/OWLearningCurveA.py

+"""
+<name>Learning Curve (A)</name>
+<description>Takes a data set and a set of learners and shows a learning curve in a table</description>
+<icon>icons/LearningCurveA.png</icon>
+<priority>1000</priority>
+"""
+
+from OWWidget import *
+import OWGUI, orngTest, orngStat
+
+class OWLearningCurveA(OWWidget):
+    settingsList = ["folds", "steps", "scoringF", "commitOnChange"]
+    
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'LearningCurveA')
+
+        self.inputs = [("Data", ExampleTable, self.dataset),
+                       ("Learner", orange.Learner, self.learner, Multiple)]
+        
+        self.folds = 5     # cross validation folds
+        self.steps = 10    # points in the learning curve
+        self.scoringF = 0  # scoring function
+        self.commitOnChange = 1 # compute curve on any change of parameters
+        self.loadSettings()
+        self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1
+        self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)]
+        self.learners = [] # list of current learners from input channel, tuples (id, learner)
+        self.data = None   # data on which to construct the learning curve
+        self.curves = []   # list of evaluation results (one per learning curve point)
+        self.scores = []   # list of current scores, learnerID:[learner scores]
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input.')
+        self.infob = OWGUI.widgetLabel(box, 'No learners.')
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores")
+        scoringNames = [x[0] for x in self.scoring]
+        OWGUI.comboBox(box, self, "scoringF", items=scoringNames, callback=self.computeScores)
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(box, self, 'folds', 2, 100, step=1, label='Cross validation folds:  ',
+                   callback=lambda: self.computeCurve(self.commitOnChange))
+        OWGUI.spin(box, self, 'steps', 2, 100, step=1, label='Learning curve points:  ',
+                   callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)])
+
+        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change')
+        self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1)
+
+        # table widget
+        self.table = OWGUI.table(self.mainArea, selectionMode=QTableWidget.NoSelection)
+                
+        self.resize(500,200)
+
+    ##############################################################################    
+    # slots: handle input signals        
+
+    def dataset(self, data):
+        if data:
+            self.infoa.setText('%d instances in input data set' % len(data))
+            self.data = data
+            if (len(self.learners)):
+                self.computeCurve()
+        else:
+            self.infoa.setText('No data on input.')
+            self.curves = []
+            self.scores = []
+        self.commitBtn.setEnabled(self.data<>None)
+
+    def learner(self, learner, id=None):
+        ids = [x[0] for x in self.learners]
+        if not learner: # remove a learner and corresponding results
+            if not ids.count(id):
+                return # no such learner, removed before
+            indx = ids.index(id)
+            for i in range(self.steps):
+                self.curves[i].remove(indx)
+            del self.scores[indx]
+            del self.learners[indx]
+            self.setTable()
+        else:
+            if ids.count(id): # update (already seen a learner from this source)
+                indx = ids.index(id)
+                self.learners[indx] = (id, learner)
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores[indx] = score
+                    for i in range(self.steps):
+                        self.curves[i].add(curve[i], 0, replace=indx)
+            else: # add new learner
+                self.learners.append((id, learner))
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores.append(score)
+                    if len(self.curves):
+                        for i in range(self.steps):
+                            self.curves[i].add(curve[i], 0)
+                    else:
+                        self.curves = curve
+        if len(self.learners):
+            self.infob.setText("%d learners on input." % len(self.learners))
+        else:
+            self.infob.setText("No learners.")
+        self.commitBtn.setEnabled(len(self.learners))
+##        if len(self.scores):
+        if self.data:
+            self.setTable()
+
+    ##############################################################################    
+    # learning curve table, callbacks
+
+    # recomputes the learning curve
+    def computeCurve(self, condition=1):
+        if condition:
+            learners = [x[1] for x in self.learners]
+            self.curves = self.getLearningCurve(learners)
+            self.computeScores()
+
+    def computeScores(self):            
+        self.scores = [[] for i in range(len(self.learners))]
+        for x in self.curves:
+            for (i,s) in enumerate(self.scoring[self.scoringF][1](x)):
+                self.scores[i].append(s)
+        self.setTable()
+
+    def getLearningCurve(self, learners):   
+        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds)
+        curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance)
+        pb.finish()
+        return curve
+
+    def setCurvePoints(self):
+        self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)]
+
+    def setTable(self):
+        self.table.setColumnCount(0)
+        self.table.setColumnCount(len(self.learners))
+        self.table.setRowCount(self.steps)
+
+        # set the headers
+        self.table.setHorizontalHeaderLabels([l.name for i,l in self.learners])
+        self.table.setVerticalHeaderLabels(["%4.2f" % p for p in self.curvePoints])
+
+        # set the table contents
+        for l in range(len(self.learners)):
+            for p in range(self.steps):
+                OWGUI.tableItem(self.table, p, l, "%7.5f" % self.scores[l][p])
+
+        for i in range(len(self.learners)):
+            self.table.setColumnWidth(i, 80)
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWLearningCurveA()
+    ow.show()
+    
+    l1 = orange.BayesLearner()
+    l1.name = 'Naive Bayes'
+    ow.learner(l1, 1)
+
+    data = orange.ExampleTable('../datasets/iris.tab')
+    ow.dataset(data)
+
+    l2 = orange.BayesLearner()
+    l2.name = 'Naive Bayes (m=10)'
+    l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)
+    l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10))
+    ow.learner(l2, 2)
+
+    import orngTree
+    l4 = orngTree.TreeLearner(minSubset=2)
+    l4.name = "Decision Tree"
+    ow.learner(l4, 4)
+
+#    ow.learner(None, 1)
+#    ow.learner(None, 2)
+#    ow.learner(None, 4)
+
+    appl.exec_()

docs/extend-widgets/rst/OWLearningCurveB.py

+"""
+<name>Learning Curve (B)</name>
+<description>Takes a data set and a set of learners and shows a learning curve in a table</description>
+<icon>icons/LearningCurveB.png</icon>
+<priority>1010</priority>
+"""
+
+from OWWidget import *
+import OWGUI, orngTest, orngStat
+
+class OWLearningCurveB(OWWidget):
+    settingsList = ["folds", "steps", "scoringF", "commitOnChange"]
+    
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'LearningCurveA')
+
+        self.inputs = [("Train Data", ExampleTable, self.trainset, Default),
+                       ("Test Data", ExampleTable, self.testset),
+                       ("Learner", orange.Learner, self.learner, Multiple)]
+        
+        self.folds = 5     # cross validation folds
+        self.steps = 10    # points in the learning curve
+        self.scoringF = 0  # scoring function
+        self.commitOnChange = 1 # compute curve on any change of parameters
+        self.loadSettings()
+        self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1
+        self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)]
+        self.learners = [] # list of current learners from input channel, tuples (id, learner)
+        self.data = None   # data on which to construct the learning curve
+        self.testdata = None # optional test data
+        self.curves = []   # list of evaluation results (one per learning curve point)
+        self.scores = []   # list of current scores, learnerID:[learner scores]
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input.')
+        self.infob = OWGUI.widgetLabel(box, 'No learners.')
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores")
+        scoringNames = [x[0] for x in self.scoring]
+        OWGUI.comboBox(box, self, "scoringF", items=scoringNames, callback=self.computeScores)
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(box, self, 'folds', 2, 100, step=1, label='Cross validation folds:  ',
+                   callback=lambda: self.computeCurve(self.commitOnChange))
+        OWGUI.spin(box, self, 'steps', 2, 100, step=1, label='Learning curve points:  ',
+                   callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)])
+
+        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change')
+        self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1)
+
+        # table widget
+        self.table = OWGUI.table(self.mainArea, selectionMode=QTableWidget.NoSelection)
+                
+        self.resize(500,200)
+
+    ##############################################################################    
+    # slots: handle input signals        
+
+    def trainset(self, data):
+        if data:
+            self.infoa.setText('%d instances in input data set' % len(data))
+            self.data = data
+            if (len(self.learners)):
+                self.computeCurve()
+        else:
+            self.infoa.setText('No data on input.')
+            self.curves = []
+            self.scores = []
+        self.commitBtn.setEnabled(self.data<>None)
+
+    def testset(self, testdata):
+        if not testdata and not self.testdata:
+            return # avoid any unnecessary computation
+        self.testdata = testdata
+        if self.data and len(self.learners):
+            self.computeCurve()
+
+    def learner(self, learner, id=None):
+        ids = [x[0] for x in self.learners]
+        if not learner: # remove a learner and corresponding results
+            if not ids.count(id):
+                return # no such learner, removed before
+            indx = ids.index(id)
+            for i in range(self.steps):
+                self.curves[i].remove(indx)
+            del self.scores[indx]
+            del self.learners[indx]
+            self.setTable()
+        else:
+            if ids.count(id): # update (already seen a learner from this source)
+                indx = ids.index(id)
+                self.learners[indx] = (id, learner)
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores[indx] = score
+                    for i in range(self.steps):
+                        self.curves[i].add(curve[i], 0, replace=indx)
+            else: # add new learner
+                self.learners.append((id, learner))
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores.append(score)
+                    if len(self.curves):
+                        for i in range(self.steps):
+                            self.curves[i].add(curve[i], 0)
+                    else:
+                        self.curves = curve
+        if len(self.learners):
+            self.infob.setText("%d learners on input." % len(self.learners))
+        else:
+            self.infob.setText("No learners.")
+        self.commitBtn.setEnabled(len(self.learners))
+##        if len(self.scores):
+        if self.data:
+            self.setTable()
+
+    ##############################################################################    
+    # learning curve table, callbacks
+
+    # recomputes the learning curve
+    def computeCurve(self, condition=1):
+        if condition:
+            learners = [x[1] for x in self.learners]
+            self.curves = self.getLearningCurve(learners)
+            self.computeScores()
+
+    def computeScores(self):            
+        self.scores = [[] for i in range(len(self.learners))]
+        for x in self.curves:
+            for (i,s) in enumerate(self.scoring[self.scoringF][1](x)):
+                self.scores[i].append(s)
+        self.setTable()
+
+    def getLearningCurve(self, learners):   
+        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds)
+        if not self.testdata:
+            curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance)
+        else:
+            curve = orngTest.learningCurveWithTestData(learners,
+              self.data, self.testdata, times=self.folds, proportions=self.curvePoints, callback=pb.advance)            
+        pb.finish()
+        return curve
+
+    def setCurvePoints(self):
+        self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)]
+
+    def setTable(self):
+        self.table.setColumnCount(0)
+        self.table.setColumnCount(len(self.learners))
+        self.table.setRowCount(self.steps)
+
+        # set the headers
+        self.table.setHorizontalHeaderLabels([l.name for i,l in self.learners])
+        self.table.setVerticalHeaderLabels(["%4.2f" % p for p in self.curvePoints])
+
+        # set the table contents
+        for l in range(len(self.learners)):
+            for p in range(self.steps):
+                OWGUI.tableItem(self.table, p, l, "%7.5f" % self.scores[l][p])
+
+        for i in range(len(self.learners)):
+            self.table.setColumnWidth(i, 80)
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWLearningCurveB()
+    ow.show()
+    
+    l1 = orange.BayesLearner()
+    l1.name = 'Naive Bayes'
+    ow.learner(l1, 1)
+
+    data = orange.ExampleTable('../datasets/iris.tab')
+    indices = orange.MakeRandomIndices2(data, p0 = 0.7)
+    train = data.select(indices, 0)
+    test = data.select(indices, 1)
+
+    ow.trainset(train)
+    ow.testset(test)
+
+    l2 = orange.BayesLearner()
+    l2.name = 'Naive Bayes (m=10)'
+    l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)
+    l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10))
+    ow.learner(l2, 2)
+
+    import orngTree
+    l4 = orngTree.TreeLearner(minSubset=2)
+    l4.name = "Decision Tree"
+    ow.learner(l4, 4)
+
+#    ow.learner(None, 1)
+#    ow.learner(None, 2)
+#    ow.learner(None, 4)
+
+    appl.exec_()

docs/extend-widgets/rst/OWLearningCurveC.py

+"""
+<name>Learning Curve (C)</name>
+<description>Takes a data set and a set of learners and plots a learning curve in a table</description>
+<icon>icons/LearningCurveC.png</icon>
+<priority>1020</priority>
+"""
+
+from OWWidget import *
+from OWColorPalette import ColorPixmap
+import OWGUI, orngTest, orngStat
+from OWGraph import *
+
+import warnings
+
+class OWLearningCurveC(OWWidget):
+    settingsList = ["folds", "steps", "scoringF", "commitOnChange",
+                    "graphPointSize", "graphDrawLines", "graphShowGrid"]
+
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'LearningCurveC')
+
+        self.inputs = [("Data", ExampleTable, self.dataset),
+                       ("Learner", orange.Learner, self.learner, Multiple)]
+
+        self.folds = 5     # cross validation folds
+        self.steps = 10    # points in the learning curve
+        self.scoringF = 0  # scoring function
+        self.commitOnChange = 1 # compute curve on any change of parameters
+        self.graphPointSize = 5 # size of points in the graphs
+        self.graphDrawLines = 1 # draw lines between points in the graph
+        self.graphShowGrid = 1  # show gridlines in the graph
+        self.selectedLearners = [] 
+        self.loadSettings()
+
+        warnings.filterwarnings("ignore", ".*builtin attribute.*", orange.AttributeWarning)
+
+        self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1
+        self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)]
+        self.learners = [] # list of current learners from input channel, tuples (id, learner)
+        self.data = None   # data on which to construct the learning curve
+        self.curves = []   # list of evaluation results (one per learning curve point)
+        self.scores = []   # list of current scores, learnerID:[learner scores]
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input.')
+        self.infob = OWGUI.widgetLabel(box, 'No learners.')
+
+        ## class selection (classQLB)
+        OWGUI.separator(self.controlArea)
+        self.cbox = OWGUI.widgetBox(self.controlArea, "Learners")
+        self.llb = OWGUI.listBox(self.cbox, self, "selectedLearners", selectionMode=QListWidget.MultiSelection, callback=self.learnerSelectionChanged)
+        
+        self.llb.setMinimumHeight(50)
+        self.blockSelectionChanges = 0
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores")
+        scoringNames = [x[0] for x in self.scoring]
+        OWGUI.comboBox(box, self, "scoringF", items=scoringNames,
+                       callback=self.computeScores)
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(box, self, 'folds', 2, 100, step=1,
+                   label='Cross validation folds:  ',
+                   callback=lambda: self.computeCurve(self.commitOnChange))
+        OWGUI.spin(box, self, 'steps', 2, 100, step=1,
+                   label='Learning curve points:  ',
+                   callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)])
+
+        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change')
+        self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1)
+
+        # start of content (right) area
+        tabs = OWGUI.tabWidget(self.mainArea)
+
+        # graph widget
+        tab = OWGUI.createTabPage(tabs, "Graph")
+        self.graph = OWGraph(tab)
+        self.graph.setAxisAutoScale(QwtPlot.xBottom)
+        self.graph.setAxisAutoScale(QwtPlot.yLeft)
+        tab.layout().addWidget(self.graph)
+        self.setGraphGrid()
+
+        # table widget
+        tab = OWGUI.createTabPage(tabs, "Table")
+        self.table = OWGUI.table(tab, selectionMode=QTableWidget.NoSelection)
+
+        self.resize(550,200)
+
+    ##############################################################################
+    # slots: handle input signals
+
+    def dataset(self, data):
+        if data:
+            self.infoa.setText('%d instances in input data set' % len(data))
+            self.data = data
+            if (len(self.learners)):
+                self.computeCurve()
+            self.replotGraph()
+        else:
+            self.infoa.setText('No data on input.')
+            self.curves = []
+            self.scores = []
+            self.graph.removeDrawingCurves()
+            self.graph.replot()
+        self.commitBtn.setEnabled(self.data<>None)
+
+    # manage learner signal
+    # we use following additional attributes for learner:
+    # - isSelected, learner is selected (display the learning curve)
+    # - curve, learning curve for the learner
+    # - score, evaluation score for the learning
+    def learner(self, learner, id=None):
+        ids = [x[0] for x in self.learners]
+        if not learner: # remove a learner and corresponding results
+            if not ids.count(id):
+                return # no such learner, removed before
+            indx = ids.index(id)
+            for i in range(self.steps):
+                self.curves[i].remove(indx)
+            del self.scores[indx]
+            self.learners[indx][1].curve.detach()
+            del self.learners[indx]
+            self.setTable()
+            self.updatellb()
+        else:
+            if ids.count(id): # update (already seen a learner from this source)
+                indx = ids.index(id)
+                prevLearner = self.learners[indx][1]
+                learner.isSelected = prevLearner.isSelected
+                self.learners[indx] = (id, learner)
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores[indx] = score
+                    for i in range(self.steps):
+                        self.curves[i].add(curve[i], 0, replace=indx)
+                    learner.score = score
+                    prevLearner.curve.detach()
+                    self.drawLearningCurve(learner)
+                self.updatellb()
+            else: # add new learner
+                learner.isSelected = 1
+                self.learners.append((id, learner))
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores.append(score)
+                    if len(self.curves):
+                        for i in range(self.steps):
+                            self.curves[i].add(curve[i], 0)
+                    else:
+                        self.curves = curve
+                    learner.score = score
+                self.updatellb()
+                self.drawLearningCurve(learner)
+        if len(self.learners):
+            self.infob.setText("%d learners on input." % len(self.learners))
+        else:
+            self.infob.setText("No learners.")
+        self.commitBtn.setEnabled(len(self.learners))
+        if self.data:
+            self.setTable()
+
+    ##############################################################################
+    # learning curve table, callbacks
+
+    # recomputes the learning curve
+    def computeCurve(self, condition=1):
+        if condition:
+            learners = [x[1] for x in self.learners]
+            self.curves = self.getLearningCurve(learners)
+            self.computeScores()
+
+    def computeScores(self):
+        self.scores = [[] for i in range(len(self.learners))]
+        for x in self.curves:
+            for (i,s) in enumerate(self.scoring[self.scoringF][1](x)):
+                self.scores[i].append(s)
+        for (i,l) in enumerate(self.learners):
+            l[1].score = self.scores[i]
+        self.setTable()
+        self.replotGraph()
+
+    def getLearningCurve(self, learners):
+        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds)
+        curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance)
+        pb.finish()
+        return curve
+
+    def setCurvePoints(self):
+        self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)]
+
+    def setTable(self):
+        self.table.setColumnCount(0)
+        self.table.setColumnCount(len(self.learners))
+        self.table.setRowCount(self.steps)
+
+        # set the headers
+        self.table.setHorizontalHeaderLabels([l.name for i,l in self.learners])
+        self.table.setVerticalHeaderLabels(["%4.2f" % p for p in self.curvePoints])
+
+        # set the table contents
+        for l in range(len(self.learners)):
+            for p in range(self.steps):
+                OWGUI.tableItem(self.table, p, l, "%7.5f" % self.scores[l][p])
+
+        for i in range(len(self.learners)):
+            self.table.setColumnWidth(i, 80)
+
+
+    # management of learner selection
+
+    def updatellb(self):
+        self.blockSelectionChanges = 1
+        self.llb.clear()
+        colors = ColorPaletteHSV(len(self.learners))
+        for (i,lt) in enumerate(self.learners):
+            l = lt[1]
+            item = QListWidgetItem(ColorPixmap(colors[i]), l.name)
+            self.llb.addItem(item)
+            item.setSelected(l.isSelected)
+            l.color = colors[i]
+        self.blockSelectionChanges = 0
+
+    def learnerSelectionChanged(self):
+        if self.blockSelectionChanges: return
+        for (i,lt) in enumerate(self.learners):
+            l = lt[1]
+            if l.isSelected != (i in self.selectedLearners):
+                if l.isSelected: # learner was deselected
+                    l.curve.detach()
+                else: # learner was selected
+                    self.drawLearningCurve(l)
+                self.graph.replot()
+            l.isSelected = i in self.selectedLearners
+
+    # Graph specific methods
+
+    def setGraphGrid(self):
+        self.graph.enableGridYL(self.graphShowGrid)
+        self.graph.enableGridXB(self.graphShowGrid)
+
+    def setGraphStyle(self, learner):
+        curve = learner.curve
+        if self.graphDrawLines:
+            curve.setStyle(QwtPlotCurve.Lines)
+        else:
+            curve.setStyle(QwtPlotCurve.NoCurve)
+        curve.setSymbol(QwtSymbol(QwtSymbol.Ellipse, \
+          QBrush(QColor(0,0,0)), QPen(QColor(0,0,0)),
+          QSize(self.graphPointSize, self.graphPointSize)))
+        curve.setPen(QPen(learner.color, 5))
+
+    def drawLearningCurve(self, learner):
+        if not self.data: return
+        curve = self.graph.addCurve(learner.name, xData=self.curvePoints, yData=learner.score, autoScale=True)
+        
+        learner.curve = curve
+        self.setGraphStyle(learner)
+        self.graph.replot()
+
+    def replotGraph(self):
+        self.graph.removeDrawingCurves()
+        for l in self.learners:
+            self.drawLearningCurve(l[1])
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWLearningCurveC()
+    ow.show()
+
+    l1 = orange.BayesLearner()
+    l1.name = 'Naive Bayes'
+    ow.learner(l1, 1)
+
+    data = orange.ExampleTable('../datasets/iris.tab')
+    ow.dataset(data)
+
+    l2 = orange.BayesLearner()
+    l2.name = 'Naive Bayes (m=10)'
+    l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)
+    l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10))
+
+    l3 = orange.kNNLearner(name="k-NN")
+    ow.learner(l3, 3)
+
+    import orngTree
+    l4 = orngTree.TreeLearner(minSubset=2)
+    l4.name = "Decision Tree"
+    ow.learner(l4, 4)
+
+#    ow.learner(None, 1)
+#    ow.learner(None, 2)
+#    ow.learner(None, 4)
+    
+
+
+    appl.exec_()

docs/extend-widgets/rst/OWLearningCurve_plot.py

+"""
+<name>Learning Curve (C)</name>
+<description>Takes a data set and a set of learners and plots a learning curve in a table</description>
+<icon>icons/LearningCurveC.png</icon>
+<priority>1020</priority>
+"""
+
+from OWWidget import *
+from OWColorPalette import ColorPixmap
+import OWGUI, orngTest, orngStat
+from owplot import *
+
+import warnings
+
+class OWLearningCurveC(OWWidget):
+    settingsList = ["folds", "steps", "scoringF", "commitOnChange",
+                    "graphPointSize", "graphDrawLines", "graphShowGrid"]
+
+    def __init__(self, parent=None, signalManager=None):
+        OWWidget.__init__(self, parent, signalManager, 'LearningCurveC')
+
+        self.inputs = [("Data", ExampleTable, self.dataset),
+                       ("Learner", orange.Learner, self.learner, Multiple)]
+
+        self.folds = 5     # cross validation folds
+        self.steps = 10    # points in the learning curve
+        self.scoringF = 0  # scoring function
+        self.commitOnChange = 1 # compute curve on any change of parameters
+        self.graphPointSize = 5 # size of points in the graphs
+        self.graphDrawLines = 1 # draw lines between points in the graph
+        self.graphShowGrid = 1  # show gridlines in the graph
+        self.selectedLearners = [] 
+        self.loadSettings()
+
+        warnings.filterwarnings("ignore", ".*builtin attribute.*", orange.AttributeWarning)
+
+        self.setCurvePoints() # sets self.curvePoints, self.steps equidistantpoints from 1/self.steps to 1
+        self.scoring = [("Classification Accuracy", orngStat.CA), ("AUC", orngStat.AUC), ("BrierScore", orngStat.BrierScore), ("Information Score", orngStat.IS), ("Sensitivity", orngStat.sens), ("Specificity", orngStat.spec)]
+        self.learners = [] # list of current learners from input channel, tuples (id, learner)
+        self.data = None   # data on which to construct the learning curve
+        self.curves = []   # list of evaluation results (one per learning curve point)
+        self.scores = []   # list of current scores, learnerID:[learner scores]
+
+        # GUI
+        box = OWGUI.widgetBox(self.controlArea, "Info")
+        self.infoa = OWGUI.widgetLabel(box, 'No data on input.')
+        self.infob = OWGUI.widgetLabel(box, 'No learners.')
+
+        ## class selection (classQLB)
+        OWGUI.separator(self.controlArea)
+        self.cbox = OWGUI.widgetBox(self.controlArea, "Learners")
+        self.llb = OWGUI.listBox(self.cbox, self, "selectedLearners", selectionMode=QListWidget.MultiSelection, callback=self.learnerSelectionChanged)
+        
+        self.llb.setMinimumHeight(50)
+        self.blockSelectionChanges = 0
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores")
+        scoringNames = [x[0] for x in self.scoring]
+        OWGUI.comboBox(box, self, "scoringF", items=scoringNames,
+                       callback=self.computeScores)
+
+        OWGUI.separator(self.controlArea)
+        box = OWGUI.widgetBox(self.controlArea, "Options")
+        OWGUI.spin(box, self, 'folds', 2, 100, step=1,
+                   label='Cross validation folds:  ',
+                   callback=lambda: self.computeCurve(self.commitOnChange))
+        OWGUI.spin(box, self, 'steps', 2, 100, step=1,
+                   label='Learning curve points:  ',
+                   callback=[self.setCurvePoints, lambda: self.computeCurve(self.commitOnChange)])
+
+        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change')
+        self.commitBtn = OWGUI.button(box, self, "Apply Setting", callback=self.computeCurve, disabled=1)
+
+        # start of content (right) area
+        tabs = OWGUI.tabWidget(self.mainArea)
+
+        # graph widget
+        tab = OWGUI.createTabPage(tabs, "Graph")
+        self.graph = OWPlot(tab)
+        self.graph.set_axis_autoscale(xBottom)
+        self.graph.set_axis_autoscale(yLeft)
+        tab.layout().addWidget(self.graph)
+        self.setGraphGrid()
+
+        # table widget
+        tab = OWGUI.createTabPage(tabs, "Table")
+        self.table = OWGUI.table(tab, selectionMode=QTableWidget.NoSelection)
+
+        self.resize(550,200)
+
+    ##############################################################################
+    # slots: handle input signals
+
+    def dataset(self, data):
+        if data:
+            self.infoa.setText('%d instances in input data set' % len(data))
+            self.data = data
+            if (len(self.learners)):
+                self.computeCurve()
+            self.replotGraph()
+        else:
+            self.infoa.setText('No data on input.')
+            self.curves = []
+            self.scores = []
+            self.graph.clear()
+            self.graph.replot()
+        self.commitBtn.setEnabled(self.data<>None)
+
+    # manage learner signal
+    # we use following additional attributes for learner:
+    # - isSelected, learner is selected (display the learning curve)
+    # - curve, learning curve for the learner
+    # - score, evaluation score for the learning
+    def learner(self, learner, id=None):
+        ids = [x[0] for x in self.learners]
+        if not learner: # remove a learner and corresponding results
+            if not ids.count(id):
+                return # no such learner, removed before
+            indx = ids.index(id)
+            for i in range(self.steps):
+                self.curves[i].remove(indx)
+            del self.scores[indx]
+            self.learners[indx][1].curve.detach()
+            del self.learners[indx]
+            self.setTable()
+            self.updatellb()
+        else:
+            if ids.count(id): # update (already seen a learner from this source)
+                indx = ids.index(id)
+                prevLearner = self.learners[indx][1]
+                learner.isSelected = prevLearner.isSelected
+                self.learners[indx] = (id, learner)
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores[indx] = score
+                    for i in range(self.steps):
+                        self.curves[i].add(curve[i], 0, replace=indx)
+                    learner.score = score
+                    prevLearner.curve.detach()
+                    self.drawLearningCurve(learner)
+                self.updatellb()
+            else: # add new learner
+                learner.isSelected = 1
+                self.learners.append((id, learner))
+                if self.data:
+                    curve = self.getLearningCurve([learner])
+                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
+                    self.scores.append(score)
+                    if len(self.curves):
+                        for i in range(self.steps):
+                            self.curves[i].add(curve[i], 0)
+                    else:
+                        self.curves = curve
+                    learner.score = score
+                self.updatellb()
+                self.drawLearningCurve(learner)
+        if len(self.learners):
+            self.infob.setText("%d learners on input." % len(self.learners))
+        else:
+            self.infob.setText("No learners.")
+        self.commitBtn.setEnabled(len(self.learners))
+        if self.data:
+            self.setTable()
+
+    ##############################################################################
+    # learning curve table, callbacks
+
+    # recomputes the learning curve
+    def computeCurve(self, condition=1):
+        if condition:
+            learners = [x[1] for x in self.learners]
+            self.curves = self.getLearningCurve(learners)
+            self.computeScores()
+
+    def computeScores(self):
+        self.scores = [[] for i in range(len(self.learners))]
+        for x in self.curves:
+            for (i,s) in enumerate(self.scoring[self.scoringF][1](x)):
+                self.scores[i].append(s)
+        for (i,l) in enumerate(self.learners):
+            l[1].score = self.scores[i]
+        self.setTable()
+        self.replotGraph()
+
+    def getLearningCurve(self, learners):
+        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds)
+        curve = orngTest.learningCurveN(learners, self.data, folds=self.folds, proportions=self.curvePoints, callback=pb.advance)
+        pb.finish()
+        return curve
+
+    def setCurvePoints(self):
+        self.curvePoints = [(x+1.)/self.steps for x in range(self.steps)]
+
+    def setTable(self):
+        self.table.setColumnCount(0)
+        self.table.setColumnCount(len(self.learners))
+        self.table.setRowCount(self.steps)
+
+        # set the headers
+        self.table.setHorizontalHeaderLabels([l.name for i,l in self.learners])
+        self.table.setVerticalHeaderLabels(["%4.2f" % p for p in self.curvePoints])
+
+        # set the table contents
+        for l in range(len(self.learners)):
+            for p in range(self.steps):
+                OWGUI.tableItem(self.table, p, l, "%7.5f" % self.scores[l][p])
+
+        for i in range(len(self.learners)):
+            self.table.setColumnWidth(i, 80)
+
+
+    # management of learner selection
+
+    def updatellb(self):
+        self.blockSelectionChanges = 1
+        self.llb.clear()
+        colors = ColorPaletteHSV(len(self.learners))
+        for (i,lt) in enumerate(self.learners):
+            l = lt[1]
+            item = QListWidgetItem(ColorPixmap(colors[i]), l.name)
+            self.llb.addItem(item)
+            item.setSelected(l.isSelected)
+            l.color = colors[i]
+        self.blockSelectionChanges = 0
+
+    def learnerSelectionChanged(self):
+        if self.blockSelectionChanges: return
+        for (i,lt) in enumerate(self.learners):
+            l = lt[1]
+            if l.isSelected != (i in self.selectedLearners):
+                if l.isSelected: # learner was deselected
+                    l.curve.detach()
+                else: # learner was selected
+                    self.drawLearningCurve(l)
+                self.graph.replot()
+            l.isSelected = i in self.selectedLearners
+
+    # Graph specific methods
+
+    def setGraphGrid(self):
+        self.graph.enableGridYL(self.graphShowGrid)
+        self.graph.enableGridXB(self.graphShowGrid)
+
+    def setGraphStyle(self, learner):
+        curve = learner.curve
+        if self.graphDrawLines:
+            curve.set_style(OWCurve.LinesPoints)
+        else:
+            curve.set_style(OWCurve.Points)
+        curve.set_symbol(OWPoint.Ellipse)
+        curve.set_point_size(self.graphPointSize)
+        curve.set_color(self.graph.color(OWPalette.Data))
+        curve.set_pen(QPen(learner.color, 5))
+
+    def drawLearningCurve(self, learner):
+        if not self.data: return
+        curve = self.graph.add_curve(learner.name, xData=self.curvePoints, yData=learner.score, autoScale=True)
+        
+        learner.curve = curve
+        self.setGraphStyle(learner)
+        self.graph.replot()
+
+    def replotGraph(self):
+        self.graph.clear()
+        for l in self.learners:
+            self.drawLearningCurve(l[1])
+
+##############################################################################
+# Test the widget, run from prompt
+
+if __name__=="__main__":
+    appl = QApplication(sys.argv)
+    ow = OWLearningCurveC()
+    ow.show()
+
+    l1 = orange.BayesLearner()
+    l1.name = 'Naive Bayes'
+    ow.learner(l1, 1)
+
+    data = orange.ExampleTable('../datasets/iris.tab')
+    ow.dataset(data)
+
+    l2 = orange.BayesLearner()
+    l2.name = 'Naive Bayes (m=10)'
+    l2.estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10)
+    l2.conditionalEstimatorConstructor = orange.ConditionalProbabilityEstimatorConstructor_ByRows(estimatorConstructor = orange.ProbabilityEstimatorConstructor_m(m=10))
+
+    l3 = orange.kNNLearner(name="k-NN")
+    ow.learner(l3, 3)
+
+    import orngTree
+    l4 = orngTree.TreeLearner(minSubset=2)
+    l4.name = "Decision Tree"
+    ow.learner(l4, 4)
+
+#    ow.learner(None, 1)
+#    ow.learner(None, 2)
+#    ow.learner(None, 4)
+    
+
+
+    appl.exec_()

docs/extend-widgets/rst/OrangeWidgets.plot.owcurve.rst

-.. automodule :: OrangeWidgets.plot.owcurve
+.. automodule :: Orange.OrangeWidgets.plot.owcurve

docs/extend-widgets/rst/OrangeWidgets.plot.owlegend.rst

-.. automodule :: OrangeWidgets.plot.owlegend
+.. automodule :: OrangeWidgets.plot.owlegend

docs/extend-widgets/rst/OrangeWidgets.plot.owplot.rst

-.. automodule :: OrangeWidgets.plot.owplot
+.. automodule :: OrangeWidgets.plot.owplot

docs/extend-widgets/rst/OrangeWidgets.plot.owplotgui.rst

-.. automodule :: OrangeWidgets.plot.owplotgui
+.. automodule :: OrangeWidgets.plot.owplotgui

docs/extend-widgets/rst/OrangeWidgets.plot.owpoint.rst

-.. automodule :: OrangeWidgets.plot.owpoint
+.. automodule :: OrangeWidgets.plot.owpoint

docs/extend-widgets/rst/OrangeWidgets.plot.owtools.rst

-.. automodule :: OrangeWidgets.plot.owtools
+.. automodule :: OrangeWidgets.plot.owtools

docs/extend-widgets/rst/api.rst

+#############################################
+Orange Widgets Reference Guide for Developers
+#############################################
+
+***********************************
+Channels Definitions, Data Exchange
+***********************************
+
+Input and output channels are defined anywhere within the
+:obj:`__init__` function of a main widget class. The definition
+is used when running a widget, but also when registering your widget
+within Orange Canvas. Channel definitions are optional, depending on
+what your widget does.
+
+Output Channels
+***************
+
+Following is an example that defines two output channels::
+
+    self.outputs = [("Sampled Data", orange.ExampleTable), ("Learner", orange.Learner)]
+
+:obj:`self.outputs` should thus be a list of tuples, within
+each the first element is a name of the channel, and the second the
+type of the tokens that will be passed through. Token types are class