Ignore:
Timestamp:
05/29/13 16:35:17 (11 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Coalesce updates on input changes into a single update loop run.

(by reimplementing 'handleNewSignals' method and result invalidation).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeWidgets/Evaluate/OWTestLearners.py

    r11217 r11561  
    1414import warnings 
    1515from orngWrap import PreprocessedLearner 
    16 warnings.filterwarnings("ignore", "'id' is not a builtin attribute", 
    17                         orange.AttributeWarning) 
    1816 
    1917import Orange 
     
    447445         
    448446    def clearScores(self, ids=None): 
     447        """ 
     448        Clear/invalidate evaluation results/scores for learners for an 
     449        `ids` sequence (keys into self.learners). If `ids` is None then 
     450        invalidate data for all learners. 
     451 
     452        """ 
    449453        if ids is None: 
    450454            ids = self.learners.keys() 
     
    456460    # handle input signals 
    457461    def setData(self, data): 
    458         """handle input train data set""" 
     462        """ 
     463        Set the input train data set. 
     464        """ 
    459465        self.closeContext() 
    460          
    461         multilabel= self.ismultilabel(data) 
     466 
     467        self.clearScores() 
     468 
     469        multilabel = self.ismultilabel(data) 
    462470        if not multilabel: 
    463             self.data = self.isDataWithClass(data, checkMissing=True) and data or None 
     471            if self.isDataWithClass(data, checkMissing=True): 
     472                self.data = orange.Filter_hasClassValue(data) 
     473            else: 
     474                self.data = None 
    464475        else: 
    465476            self.data = data 
    466          
     477 
    467478        self.fillClassCombo() 
    468         if not self.data: 
    469             # data was removed, remove the scores 
    470             self.clearScores() 
    471             self.send("Evaluation Results", None) 
    472         else: 
    473             # new data has arrived 
    474             self.clearScores() 
    475  
    476             if not multilabel: 
    477                 self.data = orange.Filter_hasClassValue(self.data) 
    478  
    479             self.statLayout.setCurrentWidget([self.rbox, self.cbox, self.mbox][2 if self.ismultilabel() else self.isclassification()]) 
    480  
    481             self.stat = [self.rStatistics, self.cStatistics, self.mStatistics][2 if self.ismultilabel() else self.isclassification()] 
    482  
    483             if self.learners: 
    484                 self.recompute() 
    485              
    486         self.openContext("", data) 
    487         self.paintscores() 
     479 
     480        if self.data is not None: 
     481            # Ensure the correct statistics selection is visible. 
     482            if self.ismultilabel(): 
     483                statwidget = self.mbox 
     484                stat = self.mStatistics 
     485            elif self.isclassification(): 
     486                statwidget = self.cbox 
     487                stat = self.cStatistics 
     488            else: 
     489                statwidget = self.rbox 
     490                stat = self.rStatistics 
     491 
     492            self.statLayout.setCurrentWidget(statwidget) 
     493 
     494            self.stat = stat 
    488495 
    489496    def setTestData(self, data): 
    490         """handle test data set""" 
     497        """ 
     498        Set the 'Separate Test Data' input. 
     499        """ 
    491500        if data is None: 
    492501            self.testdata = None 
     
    496505        if self.testdata is not None: 
    497506            if self.resampling == 4: 
    498                 if self.data: 
    499                     self.recompute() 
    500                 else: 
    501                     for l in self.learners.values(): 
    502                         l.scores = [] 
    503                 self.paintscores() 
     507                self.clearScores() 
     508 
    504509        elif self.resampling == 4 and self.data: 
    505510            # test data removed, switch to testing on train data 
    506511            self.resampling = 3 
    507             self.recompute() 
     512            self.clearScores() 
    508513 
    509514    def fillClassCombo(self): 
     
    523528 
    524529    def setLearner(self, learner, id=None): 
    525         """add/remove a learner""" 
    526         if learner: # a new or updated learner 
    527             if id in self.learners: # updated learner 
     530        """ 
     531        Set the input learner with `id`. 
     532        """ 
     533        if learner is not None: 
     534            # a new or updated learner 
     535            if id in self.learners: 
    528536                time = self.learners[id].time 
    529537                self.learners[id] = Learner(learner, id) 
    530538                self.learners[id].time = time 
    531             else: # new learner 
     539                self.learners[id] = self.learners[id] 
     540                self.clearScores([id]) 
     541            else: 
    532542                self.learners[id] = Learner(learner, id) 
    533             if self.applyOnAnyChange: 
    534                 self.score([id]) 
    535             else: 
    536                 self.recompute() 
    537         else: # remove a learner and corresponding results 
     543        else: 
     544            # remove a learner and corresponding results 
    538545            if id in self.learners: 
    539546                res = self.learners[id].results 
    540547                if res and res.numberOfLearners > 1: 
     548                    # Remove the learner from the shared results instance 
    541549                    old_learner = self.learners[id].learner 
    542550                    indx = res.learners.index(old_learner) 
     
    544552                    del res.learners[indx] 
    545553                del self.learners[id] 
    546             self.sendResults() 
    547         self.paintscores() 
    548          
     554 
    549555    def setPreprocessor(self, pp): 
    550556        self.preprocessor = pp 
    551         if self.learners: 
    552             self.recompute() 
     557        self.clearScores() 
     558 
     559    def handleNewSignals(self): 
     560        """ 
     561        Update the evaluations/scores after new inputs were received. 
     562        """ 
     563        def needsupdate(learner_id): 
     564            return not (self.learners[learner_id].scores or 
     565                        self.learners[learner_id].results) 
     566 
     567        if self.applyOnAnyChange: 
     568            self.score(filter(needsupdate, self.learners)) 
     569            self.applyBtn.setEnabled(False) 
     570        else: 
     571            self.applyBtn.setEnabled(True) 
     572 
     573        self.paintscores() 
     574 
     575        if self.data is not None: 
     576            self.openContext("", self.data) 
     577        else: 
     578            self.send("Evaluation Results", None) 
    553579 
    554580    # handle output signals 
     
    594620            self.applyBtn.setDisabled(self.applyOnAnyChange) 
    595621        else: 
     622            self.clearScores() 
    596623            if self.learners: 
    597624                self.recompute() 
     
    623650 
    624651    def applyChange(self): 
     652        """ 
     653        A change of 'Apply on any change' check box. 
     654        """ 
     655        def needsupdate(learner_id): 
     656            return not (self.learners[learner_id].scores or 
     657                        self.learners[learner_id].results) 
     658 
    625659        if self.applyOnAnyChange: 
    626660            self.applyBtn.setDisabled(True) 
    627          
     661            pending = filter(needsupdate, self.learners) 
     662            if pending: 
     663                self.score(pending) 
     664                self.paintscores() 
     665 
    628666    def changedTarget(self): 
    629667        self.recomputeCM() 
Note: See TracChangeset for help on using the changeset viewer.