Changeset 4047:79856d4801fa in orange


Ignore:
Timestamp:
08/04/07 12:15:01 (7 years ago)
Author:
janezd <janez.demsar@…>
Branch:
default
Convert:
2115109b365e078a94558da3c3cb27d80b01a041
Message:
  • merged ExtendedFile and File into a single widget
  • File now gives more information and adds the new functionality supported by the data loaders regarding the reuse of the existing attributes
Location:
orange/OrangeWidgets/Data
Files:
1 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Data/OWFile.py

    r4004 r4047  
    1616import OWGUI, string, os.path, user, sys 
    1717 
    18 class OWSubFile(OWWidget): 
    19     settingsList=["recentFiles"] 
    20     allFileWidgets = [] 
    21  
    22     def __init__(self, parent=None, signalManager = None, name = "File"): 
    23         OWWidget.__init__(self, parent, signalManager, name) 
    24         OWSubFile.allFileWidgets.append(self) 
    25  
    26     def destroy(self, destroyWindow, destroySubWindows): 
    27         OWSubFile.allFileWidgets.remove(self) 
    28         OWWidget.destroy(self, destroyWindow, destroySubWindows) 
     18class OWFile(OWWidget): 
     19    settingsList=["recentFiles", "symbolDC", "symbolDK", "createNewOn"] 
     20    def __init__(self, parent=None, signalManager = None): 
     21        OWWidget.__init__(self, parent, signalManager, "File") 
     22 
     23        self.inputs = [] 
     24        self.outputs = [("Examples", ExampleTable), ("Attribute Definitions", orange.Domain)] 
     25 
     26        #set default settings 
     27        self.recentFiles=["(none)"] 
     28        self.symbolDC = "?" 
     29        self.symbolDK = "~" 
     30        self.createNewOn = orange.Variable.MakeStatus.NoRecognizedValues 
     31        self.domain = None 
     32        #get settings from the ini file, if they exist 
     33        self.loadSettings() 
     34 
     35        box = OWGUI.widgetBox(self.controlArea, "Data File", addSpace = True, orientation=0) 
     36        self.filecombo=QComboBox(box) 
     37        self.filecombo.setMinimumWidth(150) 
     38        button = OWGUI.button(box, self, '...', callback = self.browseFile, disabled=0) 
     39        self.reloadBtn = OWGUI.button(box, self, "Reload", callback = self.reload) 
     40        button.setMaximumWidth(25) 
     41 
     42        OWGUI.separator(self.controlArea, 0, 32) 
     43        box = OWGUI.widgetBox(self.controlArea, "Advanced") 
     44 
     45        OWGUI.widgetLabel(box, "Settings for tab-delimited files") 
     46#        hbox = OWGUI.widgetBox(box, orientation=0) 
     47        hbox = OWGUI.indentedBox(box, addSpace=True) 
     48        OWGUI.lineEdit(hbox, self, "symbolDC", "Don't care symbol:  ", orientation="horizontal", tooltip="Default values: empty fields (space), '?' or 'NA'") 
     49        OWGUI.lineEdit(hbox, self, "symbolDK", "Don't know symbol:  ", orientation="horizontal", tooltip="Default values: '~' or '*'") 
     50        OWGUI.comboBox(box, self, "createNewOn",  
     51                       label = "Create a new attribute when existing attribute(s) ...",  
     52                       items = ["... Always create a new attribute",  
     53                                "Miss some values of the new attribute",  
     54                                "Have no common values with the new (recommended)",  
     55                                "Have mismatching order of values" 
     56                               ]) 
     57 
     58        OWGUI.rubber(self.controlArea) 
     59         
     60        self.layout = QVBoxLayout(self.mainArea) 
     61        box = OWGUI.widgetBox(self.mainArea, "Info") 
     62        self.layout.addWidget(box) 
     63        self.info = QTextView(box) 
     64        self.info.setPaper(QBrush(self.backgroundColor())) 
     65        self.info.setFrameShape(0) 
     66        self.info.setFixedSize(400, 400) 
     67        self.info.setText("No data loaded") 
     68         
     69        self.adjustSize() 
     70 
     71    # set the file combo box 
     72    def setFileList(self): 
     73        self.filecombo.clear() 
     74        if not self.recentFiles: 
     75            self.filecombo.insertItem("(none)") 
     76        for file in self.recentFiles: 
     77            if file == "(none)": 
     78                self.filecombo.insertItem("(none)") 
     79            else: 
     80                self.filecombo.insertItem(os.path.split(file)[1]) 
     81        self.filecombo.insertItem("Browse documentation data sets...") 
     82        #self.filecombo.adjustSize() #doesn't work properly :( 
     83        self.filecombo.updateGeometry() 
     84 
     85 
     86    def reload(self): 
     87        if self.recentFiles: 
     88            return self.openFile(self.recentFiles[0], 1) 
    2989 
    3090    def activateLoadedSettings(self): 
     
    107167            self.info[i].setText(s) 
    108168 
    109     # checks whether any file widget knows of any variable from the current domain 
    110     def attributesOverlap(self, domain): 
    111         for fw in OWSubFile.allFileWidgets: 
    112             if fw != self and getattr(fw, "dataDomain", None): 
    113                 for var in domain: 
    114                     if var in fw.dataDomain: 
    115                         return True 
    116         return False 
    117  
    118169    # Open a file, create data from it and send it over the data channel 
    119     def openFileBase(self,fn, throughReload = 0, DK=None, DC=None): 
    120         dontCheckStored = throughReload and self.resetDomain 
    121         self.resetDomain = self.domain != None 
    122         oldDomain = getattr(self, "dataDomain", None) 
    123         if fn != "(none)": 
    124             fileExt=lower(os.path.splitext(fn)[1]) 
    125             argdict = {"dontCheckStored": dontCheckStored, "use": self.domain} 
    126             if fileExt == ".basket": 
    127                 data = orange.ExampleTable(fn, **argdict) 
    128             else: 
    129                 if fileExt in (".txt",".tab",".xls"): 
    130                     preloader, loader = orange.ExampleGenerator, orange.ExampleTable 
    131                     if DK: 
    132                         argdict["DK"] = DK 
    133                     if DC: 
    134                         argdict["DC"] = DC 
    135                 elif fileExt in (".c45",): 
    136                     preloader = loader = orange.C45ExampleGenerator 
    137                 else: 
    138                     self.error("Unrecognized file format") 
    139                     self.send("Examples", None) 
    140                     self.send("Attribute Definitions", None) 
    141                     return 
    142      
    143                 if dontCheckStored: 
    144                     data = loader(fn, **argdict) 
    145                 else: 
    146                     # Load; if the domain is the same and there is no other file widget which 
    147                     # uses any of the same attributes like this one, reload 
    148                     # If the loader for a particular format cannot load the examle generator 
    149                     # (i.e. if it always returns an example table), the data is loaded twice. 
    150                     try: 
    151                         data = preloader(fn, **argdict) 
    152                         if oldDomain == data.domain and not self.attributesOverlap(data.domain): 
    153                             argdict["dontCheckStored"] = 1 
    154                             data = loader(fn, **argdict) 
    155                         elif not isinstance(data, orange.ExampleTable): 
    156                             data = loader(fn, **argdict) 
    157                     except Exception, (errValue): 
    158                         self.error(str(errValue)) 
    159                         self.send("Examples", None) 
    160                         self.send("Attribute Definitions", None) 
    161                         self.dataDomain = None 
    162                         self.infoa.setText('No data loaded due to an error.') 
    163                         self.infob.setText('') 
    164                         return 
    165                              
    166             self.dataDomain = data.domain 
    167  
    168             # update data info 
    169             def sp(l): 
    170                 n = len(l) 
    171                 if n <> 1: return n, 's' 
    172                 else: return n, '' 
    173  
    174             self.infoa.setText('%d example%s, ' % sp(data) + '%d attribute%s, ' % sp(data.domain.attributes) + '%d meta attribute%s.' % sp(data.domain.getmetas())) 
    175             cl = data.domain.classVar 
    176             if cl: 
    177                 if cl.varType == orange.VarTypes.Continuous: 
    178                     self.infob.setText('Regression; Numerical class.') 
    179                 elif cl.varType == orange.VarTypes.Discrete: 
    180                     self.infob.setText('Classification; Discrete class with %d value%s.' % sp(cl.values)) 
    181                 else: 
    182                     self.infob.setText("Class neither descrete nor continuous.") 
    183             else: 
    184                 self.infob.setText('Classless domain') 
    185  
    186             # make new data and send it 
    187             fName = os.path.split(fn)[1] 
    188             if "." in fName: 
    189                 data.name = string.join(string.split(fName, '.')[:-1], '.') 
    190             else: 
    191                 data.name = fName 
    192             self.send("Examples", data) 
    193             self.send("Attribute Definitions", data.domain) 
    194         else: 
     170    def openFile(self, fn, throughReload=0, DK=None, DC=None): 
     171        self.error() 
     172 
     173        if fn == "(none)": 
    195174            self.send("Examples", None) 
    196175            self.send("Attribute Definitions", None) 
    197         self.error() 
    198  
    199  
    200  
    201 class OWFile(OWSubFile): 
    202     def __init__(self,parent=None, signalManager = None): 
    203         OWSubFile.__init__(self, parent, signalManager, "File") 
    204  
    205         self.inputs = [] 
    206         self.outputs = [("Examples", ExampleTable), ("Attribute Definitions", orange.Domain)] 
    207  
    208         #set default settings 
    209         self.recentFiles=["(none)"] 
    210         self.domain = None 
    211         #get settings from the ini file, if they exist 
    212         self.loadSettings() 
    213  
    214         #GUI 
    215         self.box = QHGroupBox("Data File", self.controlArea) 
    216         self.filecombo=QComboBox(self.box) 
    217         self.filecombo.setMinimumWidth(250) 
    218         button = OWGUI.button(self.box, self, '...', callback = self.browseFile, disabled=0) 
    219         button.setMaximumWidth(25) 
    220  
    221         # info 
    222         box = QVGroupBox("Info", self.controlArea) 
    223         self.infoa = QLabel('No data loaded.', box) 
    224         self.infob = QLabel('', box) 
    225  
    226         self.resize(150,100) 
    227  
    228     # set the file combo box 
    229     def setFileList(self): 
    230         self.filecombo.clear() 
    231         if not self.recentFiles: 
    232             self.filecombo.insertItem("(none)") 
    233         for file in self.recentFiles: 
    234             if file == "(none)": 
    235                 self.filecombo.insertItem("(none)") 
    236             else: 
    237                 self.filecombo.insertItem(os.path.split(file)[1]) 
    238         self.filecombo.insertItem("Browse documentation data sets...") 
    239         #self.filecombo.adjustSize() #doesn't work properly :( 
    240         self.filecombo.updateGeometry() 
    241  
    242  
    243     def openFile(self,fn, throughReload = 0): 
    244         self.openFileBase(fn, throughReload=throughReload) 
     176            self.info.setText("No data loaded") 
     177            return 
     178             
     179        argdict = {"createNewOn": self.createNewOn} 
     180        if DK: 
     181            argdict["DK"] = DK 
     182        if DC: 
     183            argdict["DC"] = DC 
     184 
     185        try: 
     186            data = orange.ExampleTable(fn, **argdict) 
     187        except Exception, (errValue): 
     188            if not data: 
     189                self.error(str(errValue)) 
     190                self.dataDomain = None 
     191                self.info.setText('No data loaded due to an error') 
     192                return 
     193                         
     194        self.dataDomain = data.domain 
     195 
     196        # update data info 
     197        def describeAttribute(attr): 
     198            vs = "<b>%s</b>: " % attr.name 
     199            if attr.varType == orange.VarTypes.Discrete: 
     200                if attr.values: 
     201                    vs += ", ".join(attr.values[:5]) 
     202                    if len(attr.values) > 5: 
     203                        vs += " + %d more" % (len(attr.values)-5) 
     204                    else: 
     205                        vs += "." 
     206                else: 
     207                    vs += "(none)" 
     208            elif attr.varType == orange.VarTypes.Continuous: 
     209                vs += "continuous (%i dig.)" % attr.numberOfDecimals 
     210            elif attr.varType == orange.VarTypes.String: 
     211                vs += "text" 
     212            else: 
     213                vs += "other" 
     214            return vs 
     215             
     216        infos = "" 
     217        cl = data.domain.classVar 
     218        if cl: 
     219            if cl.varType == orange.VarTypes.Continuous: 
     220                infos += "<b>Regression:</b> Numerical class '%s'." % cl.name 
     221            elif cl.varType == orange.VarTypes.Discrete: 
     222                infos += "<b>Classification:</b> Discrete class '%s' with %d value(s)." % (cl.name, len(cl.values)) 
     223            else: 
     224                infos += "<b>Class '%s'</b>: neither discrete nor continuous." % cl.name 
     225        else: 
     226            infos += '<b>Data without a dependent variable.</b>' 
     227         
     228        infos += '<br/><br/><b>Examples:</b> %d example(s)' % len(data) 
     229 
     230        warnings = "" 
     231        metas = data.domain.getmetas() 
     232        for status, messageUsed, messageNotUsed in [ 
     233                                (orange.Variable.MakeStatus.Incompatible, 
     234                                 "", 
     235                                 "The following attributes already existed but had a different order of values, so new attributes needed to be created"), 
     236                                (orange.Variable.MakeStatus.NoRecognizedValues, 
     237                                 "The following attributes were reused although they share no common values with the existing attribute of the same names", 
     238                                 "The following attributes were not reused since they share no common values with the existing attribute of the same names"), 
     239                                (orange.Variable.MakeStatus.MissingValues,  
     240                                 "The following attribute(s) were reused although some values needed to be added", 
     241                                 "The following attribute(s) were not reused since they miss some values") 
     242                                ]: 
     243            if self.createNewOn > status: 
     244                message = messageUsed 
     245            else: 
     246                message = messageNotUsed 
     247            if not message: 
     248                continue 
     249            attrs = [attr.name for attr, stat in zip(data.domain, data.attributeLoadStatus) if stat == status] \ 
     250                  + [attr.name for id, attr in metas.items() if data.metaAttributeLoadStatus[id] == status] 
     251            print attrs 
     252            if attrs: 
     253                warnings += "<li>%s: %s</li>" % (message, ", ".join(attrs)) 
     254             
     255        if warnings: 
     256            infos += "<br/><br/><b>"+"Attribute reuse warnings"+":</b><ul>%s</ul>" % warnings 
     257 
     258        infos += '<br/><br/><b>Attributes:</b><br/>' 
     259        if data.domain.attributes: 
     260            for attr in data.domain.attributes: 
     261                infos += "&nbsp;&nbsp;&nbsp;&nbsp;%s<br/>" % describeAttribute(attr) 
     262        else: 
     263            infos += "&nbsp;&nbsp;&nbsp;&nbsp;(none)" 
     264                     
     265        if metas: 
     266            infos += '<br/><b>Meta attributes</b><br/>' 
     267            for attr in metas.values(): 
     268                infos += "&nbsp;&nbsp;&nbsp;&nbsp;%s<br/>" % describeAttribute(attr) 
     269             
     270        self.info.setText(infos) 
     271 
     272        # make new data and send it 
     273        fName = os.path.split(fn)[1] 
     274        if "." in fName: 
     275            data.name = data.name[:data.name.rfind('.')] 
     276        else: 
     277            data.name = fName 
     278             
     279        self.send("Examples", data) 
     280        self.send("Attribute Definitions", data.domain) 
     281 
    245282 
    246283 
Note: See TracChangeset for help on using the changeset viewer.