Esempio n. 1
0
class OWDataSort(OWWidget):
    contextHandlers = {
        "": DomainContextHandler(
            "", ["sortroles"]
        )
    }
    settingsList = ["autoCommit"]

    def __init__(self, parent=None, signalManger=None, title="Data Sort"):
        super(OWDataSort, self).__init__(parent, signalManger, title,
                                         wantMainArea=False)

        #: Mapping (feature.name, feature.var_type) to (sort_index, sort_order)
        #: where sirt index is the position of the feature in the sortByModel
        #: and sort_order the Qt.SortOrder flag
        self.sortroles = {}

        self.autoCommit = False
        self._outputChanged = False

        box = OWGUI.widgetBox(self.controlArea, "Sort By Features")
        self.sortByView = QListView()
        self.sortByView.setItemDelegate(SortParamDelegate(self))
        self.sortByView.setSelectionMode(QListView.ExtendedSelection)
        self.sortByView.setDragDropMode(QListView.DragDrop)
        self.sortByView.setDefaultDropAction(Qt.MoveAction)
        self.sortByView.viewport().setAcceptDrops(True)

        self.sortByModel = VariableListModel(
            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable |
                  Qt.ItemIsDragEnabled | Qt.ItemIsEditable
        )
        self.sortByView.setModel(self.sortByModel)

        box.layout().addWidget(self.sortByView)

        box = OWGUI.widgetBox(self.controlArea, "Unused Features")
        self.unusedView = QListView()
        self.unusedView.setSelectionMode(QListView.ExtendedSelection)
        self.unusedView.setDragDropMode(QListView.DragDrop)
        self.unusedView.setDefaultDropAction(Qt.MoveAction)
        self.unusedView.viewport().setAcceptDrops(True)

        self.unusedModel = VariableListModel(
            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable |
                  Qt.ItemIsDragEnabled
        )
        self.unusedView.setModel(self.unusedModel)

        box.layout().addWidget(self.unusedView)

        box = OWGUI.widgetBox(self.controlArea, "Output")
        cb = OWGUI.checkBox(box, self, "autoCommit", "Auto commit")
        b = OWGUI.button(box, self, "Commit", callback=self.commit)
        OWGUI.setStopper(self, b, cb, "_outputChanged", callback=self.commit)

    def setData(self, data):
        """
        Set the input data.
        """
        self._storeRoles()

        self.closeContext("")
        self.data = data

        if data is not None:
            self.openContext("", data)
            domain = data.domain
            features = (domain.variables + domain.class_vars +
                        domain.get_metas().values())
            sort_by = []
            unused = []

            for feat in features:
                hint = self.sortroles.get((feat.name, feat.var_type), None)
                if hint is not None:
                    index, order = hint
                    sort_by.append((feat, index, order))
                else:
                    unused.append(feat)

            sort_by = sorted(sort_by, key=itemgetter(1))
            self.sortByModel[:] = [feat for feat, _, _ in sort_by]
            self.unusedModel[:] = unused

            # Restore the sort orders
            for i, (_, _, order) in enumerate(sort_by):
                index = self.sortByModel.index(i, 0)
                self.sortByModel.setData(index, order, SortOrderRole)

        self.commit()

    def _invalidate(self):
        if self.autoCommit:
            self.commit()
        else:
            self._outputChanged = True

    def _sortingParams(self):
        params = []

        for i, feature in enumerate(self.sortByModel):
            index = self.sortByModel.index(i, 0)
            order = toSortOrder(index.data(SortOrderRole))
            params.append((feature, order))

        return params

    def commit(self):
        params = self._sortingParams()

        if self.data:
            instances = sorted(self.data, key=sort_key(params))

            data = Orange.data.Table(self.data.domain, instances)
        else:
            data = self.data

        self.send("Data", data)

    def _storeRoles(self):
        """
        Store the sorting roles back into the stored settings.
        """
        roles = {}
        for i, feature in enumerate(self.sortByModel):
            index = self.sortByModel.index(i, 0)
            order = toSortOrder(index.data(SortOrderRole))
            roles[(feature.name, feature.var_type)] = (i, int(order))

        self.sortroles = roles

    def getSettings(self, *args, **kwargs):
        self._storeRoles()
        return OWWidget.getSettings(self, *args, **kwargs)
Esempio n. 2
0
class OWGroupBy(OWWidget):
    contextHandlers = {"": DomainContextHandler("", ["hints"])}
    settingsList = []

    def __init__(self, parent=None, signalManager=None, title="Group By"):
        OWWidget.__init__(self,
                          parent,
                          signalManager,
                          title,
                          wantMainArea=False)

        self.inputs = [("Data", Table, self.set_data)]
        self.outputs = [("Data", Table)]

        self.auto_commit = True
        self.hints = {}

        self.state_changed_flag = False

        self.loadSettings()

        #############
        # Data Models
        #############

        self.group_list = VariableListModel(parent=self,
                            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \
                            Qt.ItemIsDragEnabled )
        self.aggregate_list = VariableAggragateModel(parent=self,
                            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \
                            Qt.ItemIsDragEnabled | \
                            Qt.ItemIsEditable)

        self.aggregate_delegate = AggregateDelegate()

        #####
        # GUI
        #####

        box = OWGUI.widgetBox(self.controlArea, "Group By Attributes")
        self.group_view = QListView()
        self.group_view.setSelectionMode(QListView.ExtendedSelection)
        self.group_view.setDragDropMode(QListView.DragDrop)
        self.group_view.setModel(self.group_list)
        #        self.group_view.setDragDropOverwriteMode(True)
        self.group_view.setDefaultDropAction(Qt.MoveAction)
        self.group_view.viewport().setAcceptDrops(True)
        #        self.group_view.setDropIndicatorShown(True)
        self.group_view.setToolTip("A set of attributes to group by (drag \
values to 'Aggregate Attributes' to remove them from this group).")
        box.layout().addWidget(self.group_view)

        box = OWGUI.widgetBox(self.controlArea, "Aggregate Attributes")
        self.aggregate_view = AggregateListView()
        self.aggregate_view.setSelectionMode(QListView.ExtendedSelection)
        self.aggregate_view.setDragDropMode(QListView.DragDrop)
        self.aggregate_view.setItemDelegate(self.aggregate_delegate)
        self.aggregate_view.setModel(self.aggregate_list)
        self.aggregate_view.setEditTriggers(QListView.DoubleClicked
                                            | QListView.EditKeyPressed)
        #        self.aggregate_view.setDragDropOverwriteMode(False)
        self.aggregate_view.setDefaultDropAction(Qt.MoveAction)
        self.aggregate_view.viewport().setAcceptDrops(True)
        self.aggregate_view.setToolTip("Aggregated attributes.")

        box.layout().addWidget(self.aggregate_view)

        OWGUI.rubber(self.controlArea)
        box = OWGUI.widgetBox(self.controlArea, "Commit")
        cb = OWGUI.checkBox(
            box,
            self,
            "auto_commit",
            "Commit on input change.",
            tooltip="Send the data on output on change of input.",
            callback=self.commit_if)
        b = OWGUI.button(box,
                         self,
                         "Commit",
                         callback=self.commit,
                         tooltip="Send data on output.",
                         autoDefault=True)


#        OWGUI.setStopper(self, b, cb, "state_changed_flag",
#                         callback=self.commit)

    def set_data(self, data=None):
        """ Set the input data for the widget.
        """
        self.update_hints()
        self.closeContext("")
        self.clear()
        if data is not None:
            self.init_with_data(data)
            self.openContext("", data)
            self.init_state_from_hints()

        self.commit_if()

    def init_with_data(self, data):
        """ Init widget state from data
        """
        attrs = data.domain.variables + data.domain.get_metas().values()
        #        self.group_list.set_items(attrs)
        self.all_attrs = attrs
        self.hints = dict([((a.name, a.varType), ("group_by", "First"))
                           for a in attrs])
        self.data = data

    def init_state_from_hints(self):
        """ Init the group and aggregate from hints (call after openContext) 
        """
        group = []
        aggregate = []
        aggregate_hint = {}
        for a in self.all_attrs:
            try:
                place, hint = self.hints.get((a.name, a.var_type),
                                             ("group_by", DEFAULT_METHOD))
            except Exception:
                place, hint = ("group_by", DEFAULT_METHOD)
            if place == "group_by":
                group.append(a)
            else:
                aggregate.append(a)
            aggregate_hint[a] = hint
        self.group_list[:] = group
        self.aggregate_list[:] = aggregate

        for i, a in enumerate(group):
            self.group_list.setData(self.group_list.index(i),
                                    aggregate_hint[a], AggregateMethodRole)

        for i, a in enumerate(aggregate):
            self.aggregate_list.setData(self.aggregate_list.index(i),
                                        aggregate_hint[a], AggregateMethodRole)

    def update_hints(self):
        for i, var in enumerate(self.group_list):
            self.hints[var.name, var.var_type] = \
                ("group_by", str(self.group_list.data( \
                                         self.group_list.index(i),
                                         AggregateMethodRole).toPyObject()))

        for i, var in enumerate(self.aggregate_list):
            self.hints[var.name, var.var_type] = \
                ("aggregate", str(self.aggregate_list.data( \
                                        self.aggregate_list.index(i),
                                        AggregateMethodRole).toPyObject()))

    def clear(self):
        """ Clear the widget state.
        """
        self.data = None
        self.group_list[:] = []  #clear()
        self.aggregate_list[:] = []  #.clear()
        self.all_attrs = []
        self.hints = {}

    def get_aggregates_from_hints(self):
        aggregates = {}
        for i, v in enumerate(self.aggregate_list):
            _, hint = self.hints.get((v.name, v.var_type),
                                     ("", DEFAULT_METHOD))

            aggregates[v] = hint.lower()
        return aggregates

    def commit_if(self):
        if self.auto_commit:
            self.commit()
        else:
            self.state_changed_flag = True

    def commit(self):
        self.update_hints()
        if self.data is not None:
            group = list(self.group_list)
            aggregates = self.get_aggregates_from_hints()
            print aggregates
            data = utils.group_by(self.data, group, attr_aggregate=aggregates)
        else:
            data = None
        self.send("Data", data)
        self.state_changed_flag = False
Esempio n. 3
0
class OWGroupBy(OWWidget):
    contextHandlers = {"": DomainContextHandler("", ["hints"])}
    settingsList = []
    def __init__(self, parent=None, signalManager=None, title="Group By"):
        OWWidget.__init__(self, parent, signalManager, title, 
                          wantMainArea=False)
        
        self.inputs = [("Data", Table, self.set_data)]
        self.outputs = [("Data", Table)]
        
        self.auto_commit = True
        self.hints = {}
        
        self.state_changed_flag = False
        
        self.loadSettings()
        
        #############
        # Data Models
        #############
        
        self.group_list = VariableListModel(parent=self, 
                            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \
                            Qt.ItemIsDragEnabled )
        self.aggregate_list = VariableAggragateModel(parent=self,
                            flags=Qt.ItemIsEnabled | Qt.ItemIsSelectable | \
                            Qt.ItemIsDragEnabled | \
                            Qt.ItemIsEditable)
        
        self.aggregate_delegate = AggregateDelegate()
        
        #####
        # GUI
        #####
        
        box = OWGUI.widgetBox(self.controlArea, "Group By Attributes")
        self.group_view = QListView()
        self.group_view.setSelectionMode(QListView.ExtendedSelection)
        self.group_view.setDragDropMode(QListView.DragDrop)
        self.group_view.setModel(self.group_list)
#        self.group_view.setDragDropOverwriteMode(True)
        self.group_view.setDefaultDropAction(Qt.MoveAction)
        self.group_view.viewport().setAcceptDrops(True)
#        self.group_view.setDropIndicatorShown(True)
        self.group_view.setToolTip("A set of attributes to group by (drag \
values to 'Aggregate Attributes' to remove them from this group).")
        box.layout().addWidget(self.group_view)
        
        box = OWGUI.widgetBox(self.controlArea, "Aggregate Attributes")
        self.aggregate_view = AggregateListView()
        self.aggregate_view.setSelectionMode(QListView.ExtendedSelection)
        self.aggregate_view.setDragDropMode(QListView.DragDrop)
        self.aggregate_view.setItemDelegate(self.aggregate_delegate)
        self.aggregate_view.setModel(self.aggregate_list)
        self.aggregate_view.setEditTriggers(QListView.DoubleClicked | QListView.EditKeyPressed)
#        self.aggregate_view.setDragDropOverwriteMode(False)
        self.aggregate_view.setDefaultDropAction(Qt.MoveAction)
        self.aggregate_view.viewport().setAcceptDrops(True)
        self.aggregate_view.setToolTip("Aggregated attributes.")
        
        box.layout().addWidget(self.aggregate_view)
        
        OWGUI.rubber(self.controlArea)
        box = OWGUI.widgetBox(self.controlArea, "Commit")
        cb = OWGUI.checkBox(box, self, "auto_commit", "Commit on input change.",
                            tooltip="Send the data on output on change of input.",
                            callback=self.commit_if
                            )
        b = OWGUI.button(box, self, "Commit", callback=self.commit, 
                         tooltip="Send data on output.", 
                         autoDefault=True)
#        OWGUI.setStopper(self, b, cb, "state_changed_flag",
#                         callback=self.commit)
        
    def set_data(self, data=None):
        """ Set the input data for the widget.
        """
        self.update_hints()
        self.closeContext("")
        self.clear()
        if data is not None:
            self.init_with_data(data)
            self.openContext("", data)
            self.init_state_from_hints()
        
        self.commit_if()
        
    def init_with_data(self, data):
        """ Init widget state from data
        """
        attrs = data.domain.variables + data.domain.get_metas().values()
#        self.group_list.set_items(attrs)
        self.all_attrs = attrs
        self.hints = dict([((a.name, a.varType), ("group_by", "First")) for a in attrs])
        self.data = data
        
    def init_state_from_hints(self):
        """ Init the group and aggregate from hints (call after openContext) 
        """
        group = []
        aggregate = []
        aggregate_hint = {}
        for a in self.all_attrs:
            try:
                place, hint = self.hints.get((a.name, a.var_type), ("group_by", DEFAULT_METHOD))
            except Exception:
                place, hint = ("group_by", DEFAULT_METHOD)
            if place == "group_by":
                group.append(a)
            else:
                aggregate.append(a)
            aggregate_hint[a] = hint
        self.group_list[:] = group
        self.aggregate_list[:] = aggregate
        
        for i, a in enumerate(group):
            self.group_list.setData(self.group_list.index(i),
                                    aggregate_hint[a],
                                    AggregateMethodRole)
            
        for i, a in enumerate(aggregate):
            self.aggregate_list.setData(self.aggregate_list.index(i),
                                        aggregate_hint[a],
                                        AggregateMethodRole)
        
    def update_hints(self):
        for i, var in enumerate(self.group_list):
            self.hints[var.name, var.var_type] = \
                ("group_by", str(self.group_list.data( \
                                         self.group_list.index(i),
                                         AggregateMethodRole).toPyObject()))
                
        for i, var in enumerate(self.aggregate_list):
            self.hints[var.name, var.var_type] = \
                ("aggregate", str(self.aggregate_list.data( \
                                        self.aggregate_list.index(i),
                                        AggregateMethodRole).toPyObject()))
        
        
    def clear(self):
        """ Clear the widget state.
        """
        self.data = None
        self.group_list[:] = [] #clear()
        self.aggregate_list[:] = [] #.clear()
        self.all_attrs = []
        self.hints = {}
        
    def get_aggregates_from_hints(self):
        aggregates = {}
        for i, v in enumerate(self.aggregate_list):
            _, hint = self.hints.get((v.name, v.var_type), ("", DEFAULT_METHOD))
            
            aggregates[v] = hint.lower()
        return aggregates
    
    def commit_if(self):
        if self.auto_commit:
            self.commit()
        else:
            self.state_changed_flag = True
            
    def commit(self):
        self.update_hints()
        if self.data is not None:
            group = list(self.group_list)
            aggregates = self.get_aggregates_from_hints()
            print aggregates
            data = utils.group_by(self.data, group, attr_aggregate=aggregates)
        else:
            data = None
        self.send("Data", data)
        self.state_changed_flag = False