Ignore:
Timestamp:
12/17/13 11:49:13 (4 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Added "Sample on any change" check box. Code cleanup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeWidgets/Data/OWDataSampler.py

    r11748 r11816  
    11import random 
     2 
    23import Orange 
     4from Orange.data import sample 
     5 
    36import OWGUI 
    47from OWWidget import * 
     
    1720 
    1821class OWDataSampler(OWWidget): 
    19     settingsList=["Stratified", "Repeat", "UseSpecificSeed", "RandomSeed", 
    20     "GroupSeed", "outFold", "Folds", "SelectType", "useCases", "nCases", 
    21     "selPercentage", "LOO", 
    22     "CVFolds", "CVFoldsInternal", "nGroups", "pGroups", "GroupText"] 
    23      
    24     contextHandlers = {"":DomainContextHandler("", ["nCases","selPercentage"])} 
     22    settingsList = [ 
     23        "Stratified", "Repeat", "UseSpecificSeed", "RandomSeed", 
     24        "GroupSeed", "outFold", "Folds", "SelectType", "useCases", "nCases", 
     25        "selPercentage", "CVFolds", "nGroups", 
     26        "pGroups", "GroupText", "autocommit"] 
     27 
     28    contextHandlers = { 
     29        "": DomainContextHandler("", ["nCases", "selPercentage"]) 
     30    } 
     31 
    2532    def __init__(self, parent=None, signalManager=None): 
    26         OWWidget.__init__(self, parent, signalManager, 'SampleData', wantMainArea = 0) 
     33        OWWidget.__init__(self, parent, signalManager, 'SampleData', 
     34                          wantMainArea=0) 
    2735 
    2836        self.inputs = [("Data", ExampleTable, self.setData)] 
    29         self.outputs = [("Data Sample", ExampleTable), ("Remaining Data", ExampleTable)] 
     37        self.outputs = [("Data Sample", ExampleTable), 
     38                        ("Remaining Data", ExampleTable)] 
    3039 
    3140        # initialization of variables 
    3241        self.data = None                        # dataset (incoming stream) 
    3342        self.indices = None                     # indices that control sampling 
    34         self.ind = None                         # indices that control sampling 
    3543 
    3644        self.Stratified = 1                     # use stratified sampling if possible? 
     
    4654        self.nCases = 25                        # number of cases to use 
    4755        self.selPercentage = 30                 # sample size in % 
    48         self.LOO = 1                            # use LOO? 
    4956        self.CVFolds = 10                       # number of CV folds 
    50         self.CVFoldsInternal = 10               # number of CV folds (for internal use) 
    5157        self.nGroups = 3                        # number of groups 
    52         self.pGroups = [0.1,0.25,0.5]           # sizes of groups 
     58        self.pGroups = [0.1, 0.25, 0.5]         # sizes of groups 
    5359        self.GroupText = '0.1,0.25,0.5'         # assigned to Groups Control (for internal use) 
     60        self.autocommit = False 
     61 
     62        # Invalidated settings flag. 
     63        self.outputInvalidateFlag = False 
    5464 
    5565        self.loadSettings() 
     66 
    5667        # GUI 
    57          
     68 
    5869        # Info Box 
    5970        box1 = OWGUI.widgetBox(self.controlArea, "Information", addSpace=True) 
     71        # Input data set info 
    6072        self.infoa = OWGUI.widgetLabel(box1, 'No data on input.') 
     73        # Sampling type/parameters info 
    6174        self.infob = OWGUI.widgetLabel(box1, ' ') 
     75        # Output data set info 
    6276        self.infoc = OWGUI.widgetLabel(box1, ' ') 
    63          
     77 
    6478        # Options Box 
    6579        box2 = OWGUI.widgetBox(self.controlArea, 'Options', addSpace=True) 
    66         OWGUI.checkBox(box2, self, 'Stratified', 'Stratified (if possible)', callback=self.settingsChanged) 
    67         OWGUI.checkWithSpin(box2, self, 'Set random seed:', 0, 32767, 'UseSpecificSeed', 'RandomSeed', checkCallback=self.settingsChanged, spinCallback=self.settingsChanged) 
     80        OWGUI.checkBox(box2, self, 'Stratified', 'Stratified (if possible)', 
     81                       callback=self.settingsChanged) 
     82 
     83        OWGUI.checkWithSpin( 
     84            box2, self, 'Set random seed:', 0, 32767, 
     85            'UseSpecificSeed', 
     86            'RandomSeed', 
     87            checkCallback=self.settingsChanged, 
     88            spinCallback=self.settingsChanged 
     89        ) 
    6890 
    6991        # Sampling Type Box 
    7092        self.s = [None, None, None, None] 
    71         self.sBox = OWGUI.widgetBox(self.controlArea, "Sampling type", addSpace=True) 
     93        self.sBox = OWGUI.widgetBox(self.controlArea, "Sampling type", 
     94                                    addSpace=True) 
    7295        self.sBox.buttons = [] 
    7396 
    7497        # Random Sampling 
    75         self.s[0] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 'Random sampling') 
    76          
    77         # indent  
    78         indent = sep=OWGUI.checkButtonOffsetHint(self.s[0]) 
     98        self.s[0] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 
     99                                            'Random sampling') 
     100 
     101        # indent 
     102        indent = OWGUI.checkButtonOffsetHint(self.s[0]) 
    79103        # repeat checkbox 
    80         self.h1Box = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
    81         OWGUI.checkBox(self.h1Box, self, 'Repeat', 'With replacement', callback=self.settingsChanged) 
     104        self.h1Box = OWGUI.indentedBox(self.sBox, sep=indent, 
     105                                       orientation="horizontal") 
     106        OWGUI.checkBox(self.h1Box, self, 'Repeat', 'With replacement', 
     107                       callback=self.settingsChanged) 
    82108 
    83109        # specified number of elements checkbox 
    84         self.h2Box = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
    85         OWGUI.checkWithSpin(self.h2Box, self, 'Sample size (instances):', 1, 1000000000, 'useCases', 'nCases', checkCallback=[self.uCases, self.settingsChanged], spinCallback=self.settingsChanged) 
    86         OWGUI.rubber(self.h2Box) 
    87          
     110        self.h2Box = OWGUI.indentedBox(self.sBox, sep=indent, 
     111                                       orientation="horizontal") 
     112        check, _ = OWGUI.checkWithSpin( 
     113            self.h2Box, self, 'Sample size (instances):', 1, 1000000000, 
     114            'useCases', 'nCases', 
     115            checkCallback=self.settingsChanged, 
     116            spinCallback=self.settingsChanged 
     117        ) 
     118 
    88119        # percentage slider 
    89         self.h3Box = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
     120        self.h3Box = OWGUI.indentedBox(self.sBox, sep=indent) 
    90121        OWGUI.widgetLabel(self.h3Box, "Sample size:") 
    91         self.slidebox = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
    92         OWGUI.hSlider(self.slidebox, self, 'selPercentage', minValue=1, maxValue=100, step=1, ticks=10, labelFormat="   %d%%", callback=self.settingsChanged) 
    93  
    94         # Cross Validation 
    95         self.s[1] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 'Cross validation') 
    96          
    97         box = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
    98         OWGUI.spin(box, self, 'CVFolds', 2, 100, step=1, label='Number of folds:  ', callback=[self.changeCombo, self.settingsChanged]) 
    99         OWGUI.rubber(box) 
     122 
     123        self.slidebox = OWGUI.widgetBox(self.h3Box, orientation="horizontal") 
     124        OWGUI.hSlider(self.slidebox, self, 'selPercentage', 
     125                      minValue=1, maxValue=100, step=1, ticks=10, 
     126                      labelFormat="   %d%%", 
     127                      callback=self.settingsChanged) 
     128 
     129        # Sample size (instances) check disables the Percentage slider. 
     130        # TODO: Should be an exclusive option (radio buttons) 
     131        check.disables.extend([(-1, self.h3Box)]) 
     132        check.makeConsistent() 
     133 
     134        # Cross Validation sampling options 
     135        self.s[1] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 
     136                                            "Cross validation") 
     137 
     138        box = OWGUI.indentedBox(self.sBox, sep=indent, 
     139                                orientation="horizontal") 
     140        OWGUI.spin(box, self, 'CVFolds', 2, 100, step=1, 
     141                   label='Number of folds:  ', 
     142                   callback=self.settingsChanged) 
    100143 
    101144        # Leave-One-Out 
    102         self.s[2] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 'Leave-one-out') 
     145        self.s[2] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 
     146                                            "Leave-one-out") 
    103147 
    104148        # Multiple Groups 
    105         self.s[3] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 'Multiple subsets') 
    106         gbox = OWGUI.indentedBox(self.sBox, sep=indent, orientation = "horizontal") 
    107         OWGUI.lineEdit(gbox, self, 'GroupText', label='Subset sizes (e.g. "0.1, 0.2, 0.5"):', callback=self.multipleChanged) 
     149        self.s[3] = OWGUI.appendRadioButton(self.sBox, self, "SelectType", 
     150                                            'Multiple subsets') 
     151        gbox = OWGUI.indentedBox(self.sBox, sep=indent, 
     152                                 orientation="horizontal") 
     153        OWGUI.lineEdit(gbox, self, 'GroupText', 
     154                       label='Subset sizes (e.g. "0.1, 0.2, 0.5"):', 
     155                       callback=self.multipleChanged) 
    108156 
    109157        # Output Group Box 
    110         self.foldcombo = OWGUI.comboBox(self.controlArea, self, "outFold", 'Output Data for Fold / Group', 'Fold / group:', orientation = "horizontal", items = range(1,101), callback = self.foldChanged, sendSelectedValue = 1, valueType = int) 
    111         self.foldcombo.setEnabled(False) 
    112  
    113         # Select Data Button 
     158        box = OWGUI.widgetBox(self.controlArea, 'Output Data for Fold / Group', 
     159                              addSpace=True) 
     160        self.foldcombo = OWGUI.comboBox( 
     161            box, self, "outFold", items=range(1, 101), 
     162            label='Fold / group:', orientation="horizontal", 
     163            sendSelectedValue=1, valueType=int, 
     164            callback=self.invalidate 
     165        ) 
     166        self.foldcombo.setEnabled(self.SelectType != 0) 
     167 
     168        # Sample Data box 
    114169        OWGUI.rubber(self.controlArea) 
    115         self.sampleButton = OWGUI.button(self.controlArea, self, 'Sample &Data', callback = self.process, addToLayout=False, default=True) 
    116         self.buttonBackground.layout().setDirection(QBoxLayout.TopToBottom) 
    117         self.buttonBackground.layout().insertWidget(0, self.sampleButton) 
    118         self.buttonBackground.show() 
    119         self.s[self.SelectType].setChecked(True)    # set initial radio button on (default sample type) 
    120  
    121         # CONNECTIONS 
    122         # set connections for RadioButton (SelectType) 
    123         self.dummy1 = [None]*len(self.s) 
    124         for i in range(len(self.s)): 
    125             self.dummy1[i] = lambda x, v=i: self.sChanged(x, v) 
    126             self.connect(self.s[i], SIGNAL("toggled(bool)"), self.dummy1[i]) 
    127  
    128         # final touch 
     170        box = OWGUI.widgetBox(self.controlArea, "Sample Data") 
     171        cb = OWGUI.checkBox(box, self, "autocommit", "Sample on any change") 
     172        self.sampleButton = OWGUI.button(box, self, 'Sample &Data', 
     173                                         callback=self.sdata, default=True) 
     174        OWGUI.setStopper(self, self.sampleButton, cb, "outputInvalidateFlag", 
     175                         callback=self.sdata) 
     176 
     177        # set initial radio button on (default sample type) 
     178        self.s[self.SelectType].setChecked(True) 
     179 
     180        # Connect radio buttons (SelectType) 
     181        for i, button in enumerate(self.s): 
     182            button.toggled[bool].connect( 
     183                lambda state, i=i: self.samplingTypeChanged(state, i) 
     184            ) 
     185 
     186        self.process() 
     187 
    129188        self.resize(200, 275) 
    130189 
    131190    # CONNECTION TRIGGER AND GUI ROUTINES 
    132191    # enables RadioButton switching 
    133     def sChanged(self, value, id): 
    134         self.SelectType = id 
    135         self.process() 
     192    def samplingTypeChanged(self, value, i): 
     193        """Sampling type changed.""" 
     194        self.SelectType = i 
     195        self.settingsChanged() 
    136196 
    137197    def multipleChanged(self): 
     198        """Multiple subsets (Groups) changed.""" 
     199        self.error(1) 
    138200        try: 
    139201            self.pGroups = [float(x) for x in self.GroupText.split(',')] 
    140202            self.nGroups = len(self.pGroups) 
    141             self.error(1) 
    142203        except: 
    143             self.error("Invalid specification for sizes of subsets.", 1) 
    144         self.changeCombo() 
    145         self.settingsChanged() 
    146  
    147     # reflect user's actions that change combobox contents 
    148     def changeCombo(self): 
    149         # refill combobox 
     204            self.error(1, "Invalid specification for sizes of subsets.") 
     205        else: 
     206            self.settingsChanged() 
     207 
     208    def updateFoldCombo(self): 
     209        """Update the 'Folds' combo box contents.""" 
     210        fold = self.outFold 
    150211        self.Folds = 1 
    151212        if self.SelectType == 1: 
     
    158219        elif self.SelectType == 3: 
    159220            self.Folds = self.nGroups 
     221 
    160222        self.foldcombo.clear() 
    161223        for x in range(self.Folds): 
    162             self.foldcombo.addItem(str(x+1)) 
    163  
    164     # triggered on change in output fold combobox 
    165     def foldChanged(self): 
    166         #self.outFold = int(ix+1) 
    167         if self.data: 
    168             self.sdata() 
    169  
    170     # switches between cases and percentage (random sampling) 
    171     def uCases(self): 
    172         if self.useCases == 1: 
    173             self.h3Box.setEnabled(False) 
    174             self.slidebox.setEnabled(False) 
    175         else: 
    176             self.h3Box.setEnabled(True) 
    177             self.slidebox.setEnabled(True) 
    178  
    179     # I/O STREAM ROUTINES 
    180     # handles changes of input stream 
     224            self.foldcombo.addItem(str(x + 1)) 
     225        self.outFold = min(fold, self.Folds) 
     226 
    181227    def setData(self, dataset): 
     228        """Set the input data set.""" 
    182229        self.closeContext() 
    183         if dataset: 
    184             self.infoa.setText('%d instances in input data set.' % len(dataset)) 
     230        if dataset is not None: 
     231            self.infoa.setText('%d instances in input data set.' % 
     232                               len(dataset)) 
    185233            self.data = dataset 
    186234            self.openContext("", dataset) 
    187235            self.process() 
     236            self.sdata() 
    188237        else: 
    189238            self.infoa.setText('No data on input.') 
     
    196245    # feeds the output stream 
    197246    def sdata(self): 
     247        if not self.data: 
     248            return 
     249 
    198250        # select data 
    199251        if self.SelectType == 0: 
    200252            if self.useCases == 1 and self.Repeat == 1: 
    201                 sample = orange.ExampleTable(self.data.domain) 
    202                 for x in range(self.nCases): 
    203                     sample.append(self.data[random.randint(0,len(self.data)-1)]) 
     253                indices = self.indices(self.data) 
     254                sample = [self.data[i] for i in indices] 
     255                sample = Orange.data.Table(self.data.domain, sample) 
    204256                remainder = None 
    205                 self.infob.setText('Random sampling with repetitions, %d instances.' % self.nCases) 
    206             else: 
    207                 sample = self.data.select(self.ind, 0) 
    208                 remainder = self.data.select(self.ind, 1) 
     257            else: 
     258                indices = self.indices(self.data) 
     259                sample = self.data.select(indices, 0) 
     260                remainder = self.data.select(indices, 1) 
    209261            self.infoc.setText('Output: %d instances.' % len(sample)) 
    210262        elif self.SelectType == 3: 
    211             self.ind = self.indices(self.data, p0 = self.pGroups[self.outFold-1]) 
    212             sample = self.data.select(self.ind, 0) 
    213             remainder = self.data.select(self.ind, 1) 
    214             self.infoc.setText('Output: subset %(outFold)d of %(folds)d, %(instances)d instance(s).' % {"outFold": self.outFold, "folds": self.Folds, "instances": len(sample)}) 
    215         else: 
    216             sample = self.data.select(self.ind, self.outFold-1) 
    217             remainder = self.data.select(self.ind, self.outFold-1, negate=1) 
    218             self.infoc.setText('Output: fold %(outFold)d of %(folds)d, %(instances)d instance(s).' % {"outFold": self.outFold, "folds": self.Folds, "instances": len(sample)}) 
    219         # set name (by PJ) 
    220         if sample: 
     263            indices = self.indices(self.data, p0=self.pGroups[self.outFold - 1]) 
     264            sample = self.data.select(indices, 0) 
     265            remainder = self.data.select(indices, 1) 
     266            self.infoc.setText( 
     267                'Output: subset %(fold)d of %(folds)d, %(len)d instance(s).' % 
     268                {"fold": self.outFold, "folds": self.Folds, "len": len(sample)} 
     269            ) 
     270        else: 
     271            # CV/LOO 
     272            indices = self.indices(self.data) 
     273            sample = self.data.select(indices, self.outFold - 1) 
     274            remainder = self.data.select(indices, self.outFold - 1, negate=1) 
     275            self.infoc.setText( 
     276                'Output: fold %(fold)d of %(folds)d, %(len)d instance(s).' % 
     277                {"fold": self.outFold, "folds": self.Folds, "len": len(sample)} 
     278            ) 
     279 
     280        if sample is not None: 
    221281            sample.name = self.data.name 
    222         if remainder: 
     282        if remainder is not None: 
    223283            remainder.name = self.data.name 
     284 
    224285        # send data 
    225286        self.nSample = len(sample) 
     
    227288        self.send("Data Sample", sample) 
    228289        self.send("Remaining Data", remainder) 
    229          
    230         self.sampleButton.setEnabled(False) 
    231  
    232     # MAIN SWITCH 
    233     # processes data after the user requests it 
     290 
     291        self.outputInvalidateFlag = False 
     292 
    234293    def process(self): 
    235         # reset errors, fold selected 
    236294        self.error(0) 
    237         self.outFold = 1 
    238  
    239         # check for data 
    240         if self.data == None: 
    241             return 
    242         else: 
    243             self.infob.setText('') 
    244             self.infoc.setText('') 
    245  
    246         # Random Selection 
     295        self.warning(0) 
     296 
     297        self.infob.setText('') 
     298 
    247299        if self.SelectType == 0: 
    248             # apply selected options 
    249             if self.useCases == 1 and self.Repeat != 1: 
    250                 if self.nCases > len(self.data): 
    251                     self.error(0, "Sample size (w/o repetitions) larger than dataset.") 
    252                     return 
    253                 self.indices = orange.MakeRandomIndices2(p0=int(self.nCases)) 
    254                 self.infob.setText('Random sampling, using exactly %d instances.' % self.nCases) 
     300            # Random Selection 
     301            if self.useCases == 1: 
     302                ncases = self.nCases 
     303                if self.Repeat == 0: 
     304                    ncases = self.nCases 
     305                    if self.data is not None and ncases > len(self.data): 
     306                        self.warning(0, "Sample size (w/o repetitions) larger than dataset.") 
     307                        ncases = len(self.data) 
     308                    p0 = ncases + 1e-7 if ncases == 1 else ncases 
     309                    self.indices = sample.SubsetIndices2(p0=p0) 
     310                    self.infob.setText('Random sampling, using exactly %d instances.' % ncases) 
     311                else: 
     312                    p0 = ncases + 1e-7 if ncases == 1 else ncases 
     313                    self.indices = sample.SubsetIndicesMultiple(p0=p0) 
     314                    self.infob.setText('Random sampling with repetitions, %d instances.' % ncases) 
    255315            else: 
    256316                if self.selPercentage == 100: 
    257                     self.indices = orange.MakeRandomIndices2(p0=int(len(self.data))) 
     317                    p0 = len(self.data) if self.data is not None else 1.0 
    258318                else: 
    259                     self.indices = orange.MakeRandomIndices2(p0=float(self.selPercentage/100.0)) 
     319                    p0 = float(self.selPercentage) / 100.0 
     320                self.indices = sample.SubsetIndices2(p0=p0) 
    260321                self.infob.setText('Random sampling, %d%% of input instances.' % self.selPercentage) 
    261             if self.Stratified == 1: self.indices.stratified = self.indices.StratifiedIfPossible 
    262             else:                    self.indices.stratified = self.indices.NotStratified 
    263             if self.UseSpecificSeed == 1: self.indices.randseed = self.RandomSeed 
    264             else:                         self.indices.randomGenerator = orange.RandomGenerator(random.randint(0,65536)) 
    265  
    266             # call output stream handler to send data 
    267             self.ind = self.indices(self.data) 
     322            if self.Stratified == 1: 
     323                self.indices.stratified = self.indices.StratifiedIfPossible 
     324            else: 
     325                self.indices.stratified = self.indices.NotStratified 
     326            if self.UseSpecificSeed == 1: 
     327                self.indices.randseed = self.RandomSeed 
     328            else: 
     329                self.indices.randomGenerator = Orange.misc.Random(random.randint(0,65536)) 
    268330 
    269331        # Cross Validation / LOO 
     
    271333            # apply selected options 
    272334            if self.SelectType == 2: 
    273                 self.CVFoldsInternal = len(self.data) 
     335                folds = len(self.data) if self.data is not None else 1 
    274336                self.infob.setText('Leave-one-out.') 
    275337            else: 
    276                 self.CVFoldsInternal = self.CVFolds 
     338                folds = self.CVFolds 
    277339                self.infob.setText('%d-fold cross validation.' % self.CVFolds) 
    278             self.indices = orange.MakeRandomIndicesCV(folds = self.CVFoldsInternal) 
     340            self.indices = sample.SubsetIndicesCV(folds=folds) 
    279341            if self.Stratified == 1: 
    280342                self.indices.stratified = self.indices.StratifiedIfPossible 
     
    282344                self.indices.stratified = self.indices.NotStratified 
    283345            if self.UseSpecificSeed == 1: 
    284                 #self.indices.randomGenerator = orange.RandomGenerator(random.randint(0,65536)) 
    285346                self.indices.randseed = self.RandomSeed 
    286347            else: 
    287                 #self.indices.randomGenerator = orange.RandomGenerator(random.randint(0,65536)) 
    288                 self.indices.randseed = random.randint(0,65536) 
    289  
    290             # call output stream handler to send data 
    291             self.ind = self.indices(self.data) 
     348                self.indices.randseed = random.randint(0, 65536) 
    292349 
    293350        # MultiGroup 
    294351        elif self.SelectType == 3: 
    295352            self.infob.setText('Multiple subsets.') 
    296             #parse group specification string 
    297  
    298353            #prepare indices generator 
    299             self.indices = orange.MakeRandomIndices2() 
    300             if self.Stratified == 1: self.indices.stratified = self.indices.StratifiedIfPossible 
    301             else:                    self.indices.stratified = self.indices.NotStratified 
    302             if self.UseSpecificSeed == 1: self.indices.randseed = self.RandomSeed 
    303             else:                         self.indices.randomGenerator = orange.RandomGenerator(random.randint(0,65536)) 
    304  
     354            self.indices = sample.SubsetIndices2() 
     355            if self.Stratified == 1: 
     356                self.indices.stratified = self.indices.StratifiedIfPossible 
     357            else: 
     358                self.indices.stratified = self.indices.NotStratified 
     359            if self.UseSpecificSeed == 1: 
     360                self.indices.randseed = self.RandomSeed 
     361            else: 
     362                self.indices.randomGenerator = Orange.misc.Random(random.randint(0,65536)) 
     363 
     364    def settingsChanged(self): 
    305365        # enable fold selection and fill combobox if applicable 
    306366        if self.SelectType == 0: 
     
    308368        else: 
    309369            self.foldcombo.setEnabled(True) 
    310             self.changeCombo() 
    311  
    312         # call data output routine 
    313         self.sdata() 
    314          
    315     def settingsChanged(self): 
    316         self.sampleButton.setEnabled(True) 
     370            self.updateFoldCombo() 
     371 
     372        self.process() 
     373        self.invalidate() 
     374 
     375    def invalidate(self): 
     376        """Invalidate current output.""" 
     377        self.infoc.setText('...') 
     378        if self.autocommit: 
     379            self.sdata() 
     380        else: 
     381            self.outputInvalidateFlag = True 
    317382 
    318383    def sendReport(self): 
     
    338403            self.reportSettings("Data", [("Input", "None")]) 
    339404 
    340 ############################################################################## 
    341 # Test the widget, run from prompt 
    342  
    343 if __name__=="__main__": 
     405 
     406if __name__ == "__main__": 
    344407    appl = QApplication(sys.argv) 
    345408    ow = OWDataSampler() 
Note: See TracChangeset for help on using the changeset viewer.