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)