Commits

Aleš Erjavec  committed f4c8559

Fixed an error when the input data set does not have any suitable attributes.

The widget will now issue a warning.

  • Participants
  • Parent commits 5e94e30

Comments (0)

Files changed (1)

File orangecontrib/bio/widgets/OWVennDiagram.py

 
         # Stored input set hints
         # {(index, inputname, attributes): (selectedattrname, itemsettitle)}
+        # The 'selectedattrname' can be None
         self.inputhints = {}
 
         self.loadSettings()
     def _add(self, key, table):
         name = table.name
         index = len(self.data)
+        attrs = source_attributes(table.domain)
+        if not attrs:
+            self.warning(
+                index, "Input {} has no suitable attributes.".format(index))
+
         self.data[key] = _InputData(key, name, table)
 
-        attrs = string_attributes(table.domain)
         self._setAttributes(index, attrs)
 
         self._invalidate([key], incremental=False)
 
     def _remove(self, key):
         index = self.data.keys().index(key)
-        box, combo = self._controlAtIndex(index)
+
+        # Clear possible warnings.
+        self.warning(index)
+
         self._setAttributes(index, None)
 
         del self.data[key]
     def _update(self, key, table):
         name = table.name
         index = self.data.keys().index(key)
+        attrs = source_attributes(table.domain)
+        if not attrs:
+            self.warning(
+                index, "Input {} has no suitable attributes.".format(index))
+        else:
+            # Clear possible warnings.
+            self.warning(index)
         self.data[key] = self.data[key]._replace(name=name, table=table)
 
-        attrs = string_attributes(table.domain)
-
         self._setAttributes(index, attrs)
         self._invalidate([key])
 
         assert self.data.keys() == self.itemsets.keys()
         for key, input in self.data.items():
             attr = self.itemsetAttr(key)
-            items = [str(inst[attr]) for inst in input.table
-                     if not inst[attr].is_special()]
+            if attr is not None:
+                items = [str(inst[attr]) for inst in input.table
+                         if not inst[attr].is_special()]
+            else:
+                items = []
 
             item = self.itemsets[key]
             item = item._replace(items=items)
         self.itemsets.clear()
         for key, input in self.data.items():
             attr = self.itemsetAttr(key)
-            items = [str(inst[attr]) for inst in input.table
-                     if not inst[attr].is_special()]
+            if attr is not None:
+                items = [str(inst[attr]) for inst in input.table
+                         if not inst[attr].is_special()]
+            else:
+                items = []
 
             title = input.name
             if key in olditemsets and olditemsets[key].name == input.name:
+                # Reuse the title (which might have been changed by the user)
                 title = olditemsets[key].title
 
             itemset = _ItemSet(key=key, name=input.name, title=title,
         if self.data:
             self.inputhints.clear()
             for i, (key, input) in enumerate(self.data.items()):
-                attrs = string_attributes(input.table.domain)
+                attrs = source_attributes(input.table.domain)
                 attrs = tuple(attr.name for attr in attrs)
                 selected = self.itemsetAttr(key)
+                if selected is not None:
+                    attr_name = selected.name
+                else:
+                    attr_name = None
                 itemset = self.itemsets[key]
                 self.inputhints[(i, input.name, attrs)] = \
-                    (selected.name, itemset.title)
+                    (attr_name, itemset.title)
 
     def _restoreHints(self):
         settings = []
         for i, (key, input) in enumerate(self.data.items()):
-            attrs = string_attributes(input.table.domain)
+            attrs = source_attributes(input.table.domain)
             attrs = tuple(attr.name for attr in attrs)
             hint = self.inputhints.get((i, input.name, attrs), None)
             if hint is not None:
                 attr, name = hint
-                attr_ind = attrs.index(attr)
+                attr_ind = attrs.index(attr) if attr is not None else -1
                 settings.append((attr_ind, name))
             else:
                 return
 
         for key, input in self.data.items():
             attr = self.itemsetAttr(key)
-            mask = map(match, (inst[attr] for inst in input.table))
+            if attr is not None:
+                mask = map(match, (inst[attr] for inst in input.table))
+            else:
+                mask = [False] * len(input.table)
+
             subset = input.table.select(mask)
 
             if subset:
             if isinstance(attr, Orange.feature.String)]
 
 
+def discrete_attributes(domain):
+    """
+    Return all discrete attributes from the domain.
+    """
+    return filter(lambda attr: isinstance(attr, Orange.feature.Discrete),
+                  domain.variables + domain.getmetas().values())
+
+
+def source_attributes(domain):
+    """
+    Return all suitable attributes for the venn diagram.
+    """
+    return string_attributes(domain) + discrete_attributes(domain)
+
+
 def disjoint(sets):
     """
     Return all disjoint subsets.