Esempio n. 1
0
class OWDataGenerator(OWWidget):
    TOOLS = [
        ("Brush", "Create multiple instances", BrushTool, icon_brush),
        ("Put", "Put individual instances", PutInstanceTool, icon_put),
        ("Select", "Select and move instances", SelectTool, icon_select),
        ("Lasso", "Select and move instances", LassoTool, icon_lasso),
        ("Jitter", "Jitter instances", JitterTool, icon_jitter),
        ("Magnet", "Move (drag) multiple instances", MagnetTool, icon_magnet),
        ("Zoom", "Zoom", ZoomTool, OWToolbars.dlg_zoom
         )  #"GenerateDataZoomTool.png")
    ]

    def __init__(self, parent=None, signalManager=None, name="Data Generator"):
        OWWidget.__init__(self, parent, signalManager, name, wantGraph=True)

        self.outputs = [("Example Table", ExampleTable)]

        self.addClassAsMeta = False
        self.attributes = []
        self.cov = []

        self.loadSettings()

        self.variablesModel = VariableListModel(
            [orange.FloatVariable(name) for name in ["X", "Y"]],
            self,
            flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable)

        self.classVariable = orange.EnumVariable("Class label",
                                                 values=["Class 1", "Class 2"],
                                                 baseValue=0)

        w = OWGUI.widgetBox(self.controlArea, "Class Label")

        self.classValuesView = listView = QListView()
        listView.setSelectionMode(QListView.SingleSelection)

        self.classValuesModel = EnumVariableModel(
            self.classVariable,
            self,
            flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable)
        self.classValuesModel.wrap(self.classVariable.values)

        listView.setModel(self.classValuesModel)
        listView.selectionModel().select(self.classValuesModel.index(0),
                                         QItemSelectionModel.ClearAndSelect)
        self.connect(
            listView.selectionModel(),
            SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
            self.onClassLabelSelection)
        listView.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Maximum)
        w.layout().addWidget(listView)

        self.addClassLabel = addClassLabel = QAction("+", self)
        addClassLabel.pyqtConfigure(
            toolTip="Add class label")  #, icon=QIcon(icon_put))
        self.connect(addClassLabel, SIGNAL("triggered()"),
                     self.addNewClassLabel)

        self.removeClassLabel = removeClassLabel = QAction("-", self)
        removeClassLabel.pyqtConfigure(
            toolTip="Remove class label")  #, icon=QIcon(icon_remove))
        self.connect(removeClassLabel, SIGNAL("triggered()"),
                     self.removeSelectedClassLabel)

        actionsWidget = ModelActionsWidget([addClassLabel, removeClassLabel],
                                           self)
        actionsWidget.layout().addStretch(10)
        actionsWidget.layout().setSpacing(1)

        w.layout().addWidget(actionsWidget)

        toolbox = OWGUI.widgetBox(self.controlArea,
                                  "Tools",
                                  orientation=QGridLayout())
        self.toolActions = QActionGroup(self)
        self.toolActions.setExclusive(True)
        for i, (name, tooltip, tool, icon) in enumerate(self.TOOLS):
            action = QAction(name, self)
            action.setToolTip(tooltip)
            action.setCheckable(True)
            if os.path.exists(icon):
                action.setIcon(QIcon(icon))
            self.connect(action,
                         SIGNAL("triggered()"),
                         lambda tool=tool: self.onToolAction(tool))
            button = QToolButton()
            button.setDefaultAction(action)
            button.setIconSize(QSize(24, 24))
            button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            button.setSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Fixed)
            toolbox.layout().addWidget(button, i / 3, i % 3)
            self.toolActions.addAction(action)

        for column in range(3):
            toolbox.layout().setColumnMinimumWidth(column, 10)
            toolbox.layout().setColumnStretch(column, 1)

        self.optionsLayout = QStackedLayout()
        self.toolsStackCache = {}
        optionsbox = OWGUI.widgetBox(self.controlArea,
                                     "Options",
                                     orientation=self.optionsLayout)

        #        OWGUI.checkBox(self.controlArea, self, "addClassAsMeta", "Add class ids as meta attributes")

        OWGUI.rubber(self.controlArea)
        OWGUI.button(self.controlArea, self, "Commit", callback=self.commit)

        self.graph = DataGeneratorGraph(self)
        self.graph.setAxisScale(QwtPlot.xBottom, 0.0, 1.0)
        self.graph.setAxisScale(QwtPlot.yLeft, 0.0, 1.0)
        self.graph.setAttribute(Qt.WA_Hover, True)
        self.mainArea.layout().addWidget(self.graph)

        self.currentOptionsWidget = None
        self.data = []
        self.domain = None

        self.onDomainChanged()
        self.toolActions.actions()[0].trigger()

        self.resize(800, 600)

    def addNewClassLabel(self):
        i = 1
        while True:
            newlabel = "Class %i" % i
            if newlabel not in self.classValuesModel:
                #                self.classValuesModel.append(newlabel)
                break
            i += 1
        values = list(self.classValuesModel) + [newlabel]
        newclass = orange.EnumVariable("Class label", values=values)
        newdomain = orange.Domain(self.graph.data.domain.attributes, newclass)
        newdata = orange.ExampleTable(newdomain)
        for ex in self.graph.data:
            newdata.append(
                orange.Example(newdomain,
                               [ex[a] for a in ex.domain.attributes] +
                               [str(ex.getclass())]))

        self.classVariable = newclass
        self.classValuesModel.wrap(self.classVariable.values)

        self.graph.data = newdata
        self.graph.updateGraph()

        newindex = self.classValuesModel.index(len(self.classValuesModel) - 1)
        self.classValuesView.selectionModel().select(
            newindex, QItemSelectionModel.ClearAndSelect)

        self.removeClassLabel.setEnabled(len(self.classValuesModel) > 1)

    def removeSelectedClassLabel(self):
        index = self.selectedClassLabelIndex()
        if index is not None and len(self.classValuesModel) > 1:
            label = self.classValuesModel[index]
            examples = [
                ex for ex in self.graph.data if str(ex.getclass()) != label
            ]

            values = [val for val in self.classValuesModel if val != label]
            newclass = orange.EnumVariable("Class label", values=values)
            newdomain = orange.Domain(self.graph.data.domain.attributes,
                                      newclass)
            newdata = orange.ExampleTable(newdomain)
            for ex in examples:
                if ex[self.classVariable] != label and ex[
                        self.classVariable] in values:
                    newdata.append(
                        orange.Example(newdomain,
                                       [ex[a] for a in ex.domain.attributes] +
                                       [str(ex.getclass())]))

            self.classVariable = newclass
            self.classValuesModel.wrap(self.classVariable.values)

            self.graph.data = newdata
            self.graph.updateGraph()

            newindex = self.classValuesModel.index(max(0, index - 1))
            self.classValuesView.selectionModel().select(
                newindex, QItemSelectionModel.ClearAndSelect)

            self.removeClassLabel.setEnabled(len(self.classValuesModel) > 1)

    def selectedClassLabelIndex(self):
        rows = [
            i.row()
            for i in self.classValuesView.selectionModel().selectedRows()
        ]
        if rows:
            return rows[0]
        else:
            return None

    def onClassLabelSelection(self, selected, unselected):
        index = self.selectedClassLabelIndex()
        if index is not None:
            self.classVariable.baseValue = index

    def onAddFeature(self):
        self.variablesModel.append(orange.FloatVariable("New feature"))
        self.varListView.edit(
            self.variablesModel.index(len(self.variablesModel) - 1))

    def onRemoveFeature(self):
        raise NotImplemented

    def onVariableSelectionChange(self, selected, deselected):
        self.selected

    def onToolAction(self, tool):
        self.setCurrentTool(tool)

    def setCurrentTool(self, tool):
        if tool not in self.toolsStackCache:
            newtool = tool(None, self)
            option = newtool.optionsWidget(newtool, self)
            self.optionsLayout.addWidget(option)
            self.connect(newtool, SIGNAL("dataChanged()"),
                         self.graph.updateGraph)
            self.toolsStackCache[tool] = (newtool, option)

        self.currentTool, self.currentOptionsWidget = tool, option = self.toolsStackCache[
            tool]
        self.optionsLayout.setCurrentWidget(option)
        self.currentTool.setGraph(self.graph)

    def onDomainChanged(self, *args):
        if self.variablesModel:
            self.domain = orange.Domain(list(self.variablesModel),
                                        self.classVariable)
            if self.data:
                self.data = orange.ExampleTable(self.domain, self.data)
            else:
                self.data = orange.ExampleTable(self.domain)
            self.graph.setData(self.data, 0, 1)

    def commit(self):
        if self.addClassAsMeta:
            domain = orange.Domain(self.graph.data.domain.attributes, None)
            domain.addmeta(orange.newmetaid(), self.graph.data.domain.classVar)
            data = orange.ExampleTable(domain, self.graph.data)
        else:
            data = self.graph.data
        self.send("Example Table", self.graph.data)