def add_zoom_actions(self, menu): zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_in) if menu: menu.addAction(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_fit) if menu: menu.addAction(zoom_fit)
def add_zoom_actions(self, menu): zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_in) if menu: menu.addAction(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_fit) if menu: menu.addAction(zoom_fit)
def __init__(self): super().__init__() self.libraryListSource = [] for name in self.signal_names: setattr(self, name, {}) self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, 'Info') gui.label( self.infoBox, self, "<p>Execute python script.</p><p>Input variables:<ul><li> " + "<li>".join(map("in_{0}, in_{0}s".format, self.signal_names)) + "</ul></p><p>Output variables:<ul><li>" + "<li>".join(map("out_{0}".format, self.signal_names)) + "</ul></p>") self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) restore_saved = QAction("Undo Changes to Selected Script", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) restore_saved.triggered.connect(self.restoreSaved) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) menu.addAction(restore_saved) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.button(self.controlArea, self, 'Run', callback=self.commit) run = QAction("Run script", self, triggered=self.commit, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R)) self.addAction(run) self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python Script') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, 'Console') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) self.splitCanvas.setSizes([2, 1]) self.setAcceptDrops(True) self.controlArea.layout().addStretch(10) self._restoreState() self.settingsAboutToBePacked.connect(self._saveState)
def __init__(self): super().__init__() for name in self.signal_names: setattr(self, name, {}) for s in self.libraryListSource: s.flags = 0 self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, 'Info') gui.label( self.infoBox, self, "<p>Execute python script.</p><p>Input variables:<ul><li> " + "<li>".join(map("in_{0}, in_{0}s".format, self.signal_names)) + "</ul></p><p>Output variables:<ul><li>" + "<li>".join(map("out_{0}".format, self.signal_names)) + "</ul></p>" ) self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) ) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged ) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) restore_saved = QAction("Undo Changes to Selected Script", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) restore_saved.triggered.connect(self.restoreSaved) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) menu.addAction(restore_saved) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.button(self.controlArea, self, 'Run', callback=self.commit) self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python Script') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, 'Console') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) select_row(self.libraryView, self.currentScriptIndex) self.restoreScriptText() self.splitCanvas.setSizes([2, 1]) if self.splitterState is not None: self.splitCanvas.restoreState(QByteArray(self.splitterState)) self.splitCanvas.splitterMoved[int, int].connect(self.onSpliterMoved) self.controlArea.layout().addStretch(1) self.resize(800, 600)
def __init__(self, parent, select_fn=None): QWidget.__init__(self) OWComponent.__init__(self, parent) self.parent = parent self.select_fn = select_fn self.selection_type = SELECTMANY self.saving_enabled = hasattr(self.parent, "save_graph") self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.selection = None self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBox(self)) self.plot = self.plotview.getPlotItem() self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("View", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) actions = [] zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_fit) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict( labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True, valueType=str) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox( box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox( box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) self.color_cb = gui.comboBox(box, self, "palette_index", label="Color:", labelWidth=50, orientation=Qt.Horizontal) self.color_cb.setIconSize(QSize(64, 16)) palettes = _color_palettes self.palette_index = min(self.palette_index, len(palettes) - 1) model = color_palette_model(palettes, self.color_cb.iconSize()) model.setParent(self) self.color_cb.setModel(model) self.color_cb.activated.connect(self.update_color_schema) self.color_cb.setCurrentIndex(self.palette_index) form = QFormLayout( formAlignment=Qt.AlignLeft, labelAlignment=Qt.AlignLeft, fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow ) lowslider = gui.hSlider( box, self, "threshold_low", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_color_schema) highslider = gui.hSlider( box, self, "threshold_high", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_color_schema) form.addRow("Low:", lowslider) form.addRow("High:", highslider) box.layout().addLayout(form) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.markings_integral = [] self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}
def __init__(self, parent): QWidget.__init__(self) OWComponent.__init__(self, parent) SelectionGroupMixin.__init__(self) ImageColorSettingMixin.__init__(self) ImageZoomMixin.__init__(self) ConcurrentMixin.__init__(self) self.parent = parent self.selection_type = SELECTMANY self.saving_enabled = True self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.data_valid_positions = None self.plotview = pg.GraphicsLayoutWidget() self.plot = pg.PlotItem(background="w", viewBox=InteractiveViewBox(self)) self.plotview.addItem(self.plot) self.legend = ImageColorLegend() self.plotview.addItem(self.legend) self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.vis_img = pg.ImageItem() self.vis_img.setOpts(axisOrder='row-major') self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("Menu", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect( lambda x: self.init_interface_data(x[0])) actions = [] self.add_zoom_actions(view_menu) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts( [QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict(labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox(box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox(box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) box.layout().addWidget(self.color_settings_box()) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}
def __init__(self): super().__init__() for name in self.signal_names: setattr(self, name, {}) for s in self.libraryListSource: s.flags = 0 self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, '信息') gui.label( self.infoBox, self, "<p>执行Python脚本。</p><p>输入变量:<ul><li> " + "<li>".join(map("in_{0}, in_{0}s".format, self.signal_names)) + "</ul></p><p>输出变量:<ul><li>" + "<li>".join(map("out_{0}".format, self.signal_names)) + "</ul></p>") self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, '脚本库') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("向库中添加新脚本") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("从库中删除脚本") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("保存", self) action.setToolTip("将编辑器中的更改的脚本保存到库中") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("更多", self, toolTip="更多操作") new_from_file = QAction("从文件导入脚本", self) save_to_file = QAction("将所选脚本保存到文件", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) auto = gui.auto_commit(self.controlArea, self, "auto_execute", "运行", checkbox_label="对新数据自动运行") self.execute_button, self.autobox = auto.button, auto.checkbox self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python脚本') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, '控制台') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) select_row(self.libraryView, self.currentScriptIndex) self.splitCanvas.setSizes([2, 1]) if self.splitterState is not None: self.splitCanvas.restoreState(QByteArray(self.splitterState)) self.splitCanvas.splitterMoved[int, int].connect(self.onSpliterMoved) self.controlArea.layout().addStretch(1) self.resize(800, 600)
def __init__(self, parent=None, select=SELECTNONE): QWidget.__init__(self) OWComponent.__init__(self, parent) self.parent = parent self.selection_type = select self.saving_enabled = hasattr(self.parent, "save_graph") self.clear_data(init=True) self.subset = None # current subset input self.subset_indices = None # boolean index array with indices in self.data self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBoxC(self)) self.plot = self.plotview.getPlotItem() self.plot.setDownsampling(auto=True, mode="peak") self.markings = [] self.vLine = pg.InfiniteLine(angle=90, movable=False) self.hLine = pg.InfiniteLine(angle=0, movable=False) self.proxy = pg.SignalProxy(self.plot.scene().sigMouseMoved, rateLimit=20, slot=self.mouseMoved, delay=0.1) self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) self.plot.vb.sigRangeChanged.connect(self.resized) self.pen_mouse = pg.mkPen(color=(0, 0, 255), width=2) self.pen_normal = defaultdict(lambda: pg.mkPen(color=(200, 200, 200, 127), width=1)) self.pen_subset = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=1)) self.pen_selected = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=2, style=Qt.DotLine)) self.label = pg.TextItem("", anchor=(1, 0)) self.label.setText("", color=(0, 0, 0)) self.discrete_palette = None QPixmapCache.setCacheLimit(max(QPixmapCache.cacheLimit(), 100 * 1024)) self.curves_cont = PlotCurvesItem() self.important_decimals = 4, 4 # whether to rescale at next update self.rescale_next = True self.MOUSE_RADIUS = 20 self.clear_graph() # interface settings self.location = True # show current position self.markclosest = True # mark self.crosshair = True self.crosshair_hidden = True layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) actions = [] resample_curves = QAction( "Resample curves", self, shortcut=Qt.Key_R, triggered=lambda x: self.resample_curves(self.sample_seed+1) ) actions.append(resample_curves) reset_curves = QAction( "Resampling reset", self, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R), triggered=lambda x: self.resample_curves(0) ) actions.append(reset_curves) zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_fit) rescale_y = QAction( "Rescale Y to fit", self, shortcut=Qt.Key_D, triggered=self.rescale_current_view_y ) actions.append(rescale_y) self.view_average_menu = QAction( "Show averages", self, shortcut=Qt.Key_A, checkable=True, triggered=lambda x: self.viewtype_changed() ) actions.append(self.view_average_menu) self.show_grid = False self.show_grid_a = QAction( "Show grid", self, shortcut=Qt.Key_G, checkable=True, triggered=self.grid_changed ) actions.append(self.show_grid_a) self.invertX_menu = QAction( "Invert X", self, shortcut=Qt.Key_X, checkable=True, triggered=self.invertX_changed ) actions.append(self.invertX_menu) if self.selection_type == SELECTMANY: select_curves = QAction( "Select (line)", self, triggered=self.plot.vb.set_mode_select, ) select_curves.setShortcuts([Qt.Key_S]) select_curves.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_curves) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_S)]) actions.append(save_graph) range_menu = MenuFocus("Define view range", self) range_action = QWidgetAction(self) layout = QGridLayout() range_box = gui.widgetBox(self, margin=5, orientation=layout) range_box.setFocusPolicy(Qt.TabFocus) self.range_e_x1 = lineEditFloatOrNone(None, self, "range_x1", label="e") range_box.setFocusProxy(self.range_e_x1) self.range_e_x2 = lineEditFloatOrNone(None, self, "range_x2", label="e") layout.addWidget(QLabel("X"), 0, 0, Qt.AlignRight) layout.addWidget(self.range_e_x1, 0, 1) layout.addWidget(QLabel("-"), 0, 2) layout.addWidget(self.range_e_x2, 0, 3) self.range_e_y1 = lineEditFloatOrNone(None, self, "range_y1", label="e") self.range_e_y2 = lineEditFloatOrNone(None, self, "range_y2", label="e") layout.addWidget(QLabel("Y"), 1, 0, Qt.AlignRight) layout.addWidget(self.range_e_y1, 1, 1) layout.addWidget(QLabel("-"), 1, 2) layout.addWidget(self.range_e_y2, 1, 3) b = gui.button(None, self, "Apply", callback=self.set_limits) layout.addWidget(b, 2, 3, Qt.AlignRight) range_action.setDefaultWidget(range_box) range_menu.addAction(range_action) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("View", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) view_menu.addActions(actions) view_menu.addMenu(range_menu) self.addActions(actions) choose_color_action = QWidgetAction(self) choose_color_box = gui.hBox(self) choose_color_box.setFocusPolicy(Qt.TabFocus) model = VariableListModel() self.attrs = [] model.wrap(self.attrs) label = gui.label(choose_color_box, self, "Color by") label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.attrCombo = gui.comboBox( choose_color_box, self, value="color_attr", contentsLength=12, callback=self.update_view) self.attrCombo.setModel(model) choose_color_box.setFocusProxy(self.attrCombo) choose_color_action.setDefaultWidget(choose_color_box) view_menu.addAction(choose_color_action) cycle_colors = QShortcut(Qt.Key_C, self, self.cycle_color_attr, context=Qt.WidgetWithChildrenShortcut) labels_action = QWidgetAction(self) layout = QGridLayout() labels_box = gui.widgetBox(self, margin=0, orientation=layout) t = gui.lineEdit(None, self, "label_title", label="Title:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Title:"), 0, 0, Qt.AlignRight) layout.addWidget(t, 0, 1) t = gui.lineEdit(None, self, "label_xaxis", label="X-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("X-axis:"), 1, 0, Qt.AlignRight) layout.addWidget(t, 1, 1) t = gui.lineEdit(None, self, "label_yaxis", label="Y-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Y-axis:"), 2, 0, Qt.AlignRight) layout.addWidget(t, 2, 1) labels_action.setDefaultWidget(labels_box) view_menu.addAction(labels_action) self.labels_changed() # apply saved labels self.invertX_apply() self.plot.vb.set_mode_panning() self.reports = {} # current reports self.viewhelpers_show()
def __init__(self): super().__init__() for name in self.signal_names: setattr(self, name, []) self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) # Styling self.defaultFont = defaultFont = ( 'Menlo' if sys.platform == 'darwin' else 'Courier' if sys.platform in ['win32', 'cygwin'] else 'DejaVu Sans Mono') self.defaultFontSize = defaultFontSize = 13 self.editorBox = gui.vBox(self, box="Editor", spacing=4) self.splitCanvas.addWidget(self.editorBox) darkMode = QApplication.instance().property('darkMode') scheme_name = 'Dark' if darkMode else 'Light' syntax_highlighting_scheme = SYNTAX_HIGHLIGHTING_STYLES[scheme_name] self.pygments_style_class = make_pygments_style(scheme_name) eFont = QFont(defaultFont) eFont.setPointSize(defaultFontSize) # Fake Signature self.func_sig = func_sig = FunctionSignature( self.editorBox, syntax_highlighting_scheme, eFont) # Editor editor = PythonEditor(self) editor.setFont(eFont) editor.setup_completer_appearance((300, 180), eFont) # Fake return return_stmt = ReturnStatement(self.editorBox, syntax_highlighting_scheme, eFont) self.return_stmt = return_stmt # Match indentation textEditBox = QWidget(self.editorBox) textEditBox.setLayout(QHBoxLayout()) char_4_width = QFontMetrics(eFont).horizontalAdvance('0000') @editor.viewport_margins_updated.connect def _(width): func_sig.setIndent(width) textEditMargin = max(0, round(char_4_width - width)) return_stmt.setIndent(textEditMargin + width) textEditBox.layout().setContentsMargins(textEditMargin, 0, 0, 0) self.text = editor textEditBox.layout().addWidget(editor) self.editorBox.layout().addWidget(func_sig) self.editorBox.layout().addWidget(textEditBox) self.editorBox.layout().addWidget(return_stmt) self.editorBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) # Controls self.editor_controls = gui.vBox(self.controlArea, box='Preferences') self.vim_box = gui.hBox(self.editor_controls, spacing=20) self.vim_indicator = VimIndicator(self.vim_box) vim_sp = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) vim_sp.setRetainSizeWhenHidden(True) self.vim_indicator.setSizePolicy(vim_sp) def enable_vim_mode(): editor.vimModeEnabled = self.vimModeEnabled self.vim_indicator.setVisible(self.vimModeEnabled) enable_vim_mode() gui.checkBox(self.vim_box, self, 'vimModeEnabled', 'Vim mode', tooltip="Only for the coolest.", callback=enable_vim_mode) self.vim_box.layout().addWidget(self.vim_indicator) @editor.vimModeIndicationChanged.connect def _(color, text): self.vim_indicator.indicator_color = color self.vim_indicator.indicator_text = text self.vim_indicator.update() # Library self.libraryListSource = [] self._cachedDocuments = {} self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) restore_saved = QAction("Undo Changes to Selected Script", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) restore_saved.triggered.connect(self.restoreSaved) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) menu.addAction(restore_saved) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.button(self.buttonsArea, self, 'Run', callback=self.commit) self.run_action = QAction("Run script", self, triggered=self.commit, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R)) self.addAction(self.run_action) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self.splitCanvas, 'Console') self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.splitCanvas.setSizes([2, 1]) self.controlArea.layout().addStretch(10) self._restoreState() self.settingsAboutToBePacked.connect(self._saveState)
def __init__(self): super().__init__() self.in_data = None self.in_distance = None self.in_learner = None self.in_classifier = None self.in_object = None for s in self.libraryListSource: s.flags = 0 self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, 'Info') gui.label( self.infoBox, self, "<p>Execute python script.</p><p>Input variables:<ul><li> " + \ "<li>".join(t.name for t in self.inputs) + \ "</ul></p><p>Output variables:<ul><li>" + \ "<li>".join(t.name for t in self.outputs) + \ "</ul></p>" ) self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.auto_commit(self.controlArea, self, "auto_execute", "Execute", auto_label="Auto Execute") self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python Script') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, 'Console') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) select_row(self.libraryView, self.currentScriptIndex) self.splitCanvas.setSizes([2, 1]) if self.splitterState is not None: self.splitCanvas.restoreState(QByteArray(self.splitterState)) self.splitCanvas.splitterMoved[int, int].connect(self.onSpliterMoved) self.controlArea.layout().addStretch(1) self.resize(800, 600)
def __init__(self, parent): QWidget.__init__(self) OWComponent.__init__(self, parent) SelectionGroupMixin.__init__(self) ImageColorSettingMixin.__init__(self) ImageZoomMixin.__init__(self) self.parent = parent self.selection_type = SELECTMANY self.saving_enabled = True self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBox(self)) self.plot = self.plotview.getPlotItem() self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("Menu", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) actions = [] self.add_zoom_actions(view_menu) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict( labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True, valueType=str) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox( box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox( box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) box.layout().addWidget(self.color_settings_box()) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.markings_integral = [] self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}
class CurvePlot(QWidget, OWComponent): sample_seed = Setting(0, schema_only=True) label_title = Setting("") label_xaxis = Setting("") label_yaxis = Setting("") range_x1 = Setting(None) range_x2 = Setting(None) range_y1 = Setting(None) range_y2 = Setting(None) feature_color = ContextSetting(None) invertX = Setting(False) selected_indices = Setting(None, schema_only=True) viewtype = Setting(INDIVIDUAL) def __init__(self, parent: OWWidget, select=SELECTNONE): QWidget.__init__(self) OWComponent.__init__(self, parent) self.parent = parent self.selection_type = select self.select_at_least_1 = False self.saving_enabled = hasattr(self.parent, "save_graph") self.clear_data() self.subset = None # current subset input, an array of indices self.subset_indices = None # boolean index array with indices in self.data self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBoxC(self)) self.plot = self.plotview.getPlotItem() self.plot.setDownsampling(auto=True, mode="peak") self.markings = [] self.vLine = pg.InfiniteLine(angle=90, movable=False) self.hLine = pg.InfiniteLine(angle=0, movable=False) self.proxy = pg.SignalProxy(self.plot.scene().sigMouseMoved, rateLimit=20, slot=self.mouseMoved, delay=0.1) self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) self.plot.vb.sigRangeChanged.connect(self.resized) self.plot.vb.sigResized.connect(self.resized) self.pen_mouse = pg.mkPen(color=(0, 0, 255), width=2) self.pen_normal = defaultdict(lambda: pg.mkPen(color=(200, 200, 200, 127), width=1)) self.pen_subset = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=1)) self.pen_selected = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=2, style=Qt.DotLine)) self.label = pg.TextItem("", anchor=(1, 0)) self.label.setText("", color=(0, 0, 0)) self.discrete_palette = None QPixmapCache.setCacheLimit(max(QPixmapCache.cacheLimit(), 100 * 1024)) self.curves_cont = PlotCurvesItem() self.important_decimals = 4, 4 self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) # whether to rescale at next update self.rescale_next = True self.MOUSE_RADIUS = 20 self.clear_graph() # interface settings self.location = True # show current position self.markclosest = True # mark self.crosshair = True self.crosshair_hidden = True layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) actions = [] resample_curves = QAction( "Resample curves", self, shortcut=Qt.Key_R, triggered=lambda x: self.resample_curves(self.sample_seed+1) ) resample_curves.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(resample_curves) reset_curves = QAction( "Resampling reset", self, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R), triggered=lambda x: self.resample_curves(0) ) reset_curves.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(reset_curves) zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_fit) rescale_y = QAction( "Rescale Y to fit", self, shortcut=Qt.Key_D, triggered=self.rescale_current_view_y ) rescale_y.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(rescale_y) self.view_average_menu = QAction( "Show averages", self, shortcut=Qt.Key_A, checkable=True, triggered=lambda x: self.viewtype_changed() ) self.view_average_menu.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(self.view_average_menu) self.show_grid = False self.show_grid_a = QAction( "Show grid", self, shortcut=Qt.Key_G, checkable=True, triggered=self.grid_changed ) self.show_grid_a.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(self.show_grid_a) self.invertX_menu = QAction( "Invert X", self, shortcut=Qt.Key_X, checkable=True, triggered=self.invertX_changed ) self.invertX_menu.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(self.invertX_menu) if self.selection_type == SELECTMANY: select_curves = QAction( "Select (line)", self, triggered=self.line_select_start, ) select_curves.setShortcuts([Qt.Key_S]) select_curves.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_curves) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_S)]) save_graph.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(save_graph) range_menu = MenuFocus("Define view range", self) range_action = QWidgetAction(self) layout = QGridLayout() range_box = gui.widgetBox(self, margin=5, orientation=layout) range_box.setFocusPolicy(Qt.TabFocus) self.range_e_x1 = lineEditFloatOrNone(None, self, "range_x1", label="e") range_box.setFocusProxy(self.range_e_x1) self.range_e_x2 = lineEditFloatOrNone(None, self, "range_x2", label="e") layout.addWidget(QLabel("X"), 0, 0, Qt.AlignRight) layout.addWidget(self.range_e_x1, 0, 1) layout.addWidget(QLabel("-"), 0, 2) layout.addWidget(self.range_e_x2, 0, 3) self.range_e_y1 = lineEditFloatOrNone(None, self, "range_y1", label="e") self.range_e_y2 = lineEditFloatOrNone(None, self, "range_y2", label="e") layout.addWidget(QLabel("Y"), 1, 0, Qt.AlignRight) layout.addWidget(self.range_e_y1, 1, 1) layout.addWidget(QLabel("-"), 1, 2) layout.addWidget(self.range_e_y2, 1, 3) b = gui.button(None, self, "Apply", callback=self.set_limits) layout.addWidget(b, 2, 3, Qt.AlignRight) range_action.setDefaultWidget(range_box) range_menu.addAction(range_action) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("View", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) view_menu.addActions(actions) view_menu.addMenu(range_menu) self.addActions(actions) choose_color_action = QWidgetAction(self) choose_color_box = gui.hBox(self) choose_color_box.setFocusPolicy(Qt.TabFocus) label = gui.label(choose_color_box, self, "Color by") label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.feature_color_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=(DiscreteVariable,), placeholder="None") self.feature_color_combo = gui.comboBox( choose_color_box, self, "feature_color", callback=self.update_view, model=self.feature_color_model, valueType=str) choose_color_box.setFocusProxy(self.feature_color_combo) choose_color_action.setDefaultWidget(choose_color_box) view_menu.addAction(choose_color_action) cycle_colors = QShortcut(Qt.Key_C, self, self.cycle_color_attr, context=Qt.WidgetWithChildrenShortcut) labels_action = QWidgetAction(self) layout = QGridLayout() labels_box = gui.widgetBox(self, margin=0, orientation=layout) t = gui.lineEdit(None, self, "label_title", label="Title:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Title:"), 0, 0, Qt.AlignRight) layout.addWidget(t, 0, 1) t = gui.lineEdit(None, self, "label_xaxis", label="X-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("X-axis:"), 1, 0, Qt.AlignRight) layout.addWidget(t, 1, 1) t = gui.lineEdit(None, self, "label_yaxis", label="Y-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Y-axis:"), 2, 0, Qt.AlignRight) layout.addWidget(t, 2, 1) labels_action.setDefaultWidget(labels_box) view_menu.addAction(labels_action) self.labels_changed() # apply saved labels self.invertX_apply() self.plot.vb.set_mode_panning() self.reports = {} # current reports self.viewhelpers_show() def init_interface_data(self, data): old_domain = self.data.domain if self.data else None self.clear_data() domain = data.domain if data is not None else None self.feature_color_model.set_domain(domain) if old_domain and domain != old_domain: # do not reset feature_color self.feature_color = self.feature_color_model[0] if self.feature_color_model else None def line_select_start(self): if self.viewtype == INDIVIDUAL: self.plot.vb.set_mode_select() def help_event(self, ev): text = "" if self.highlighted is not None: if self.viewtype == INDIVIDUAL: index = self.sampled_indices[self.highlighted] variables = self.data.domain.metas + self.data.domain.class_vars text += "".join( '{} = {}\n'.format(attr.name, self.data[index][attr]) for attr in variables) elif self.viewtype == AVERAGE: c = self.multiple_curves_info[self.highlighted] nc = sum(c[2]) if c[0] is not None: text += str(c[0]) + " " if c[1]: text += "({})".format(c[1]) if text: text += "\n" text += "{} curves".format(nc) if text: text = text.rstrip() text = ('<span style="white-space:pre">{}</span>' .format(escape(text))) QToolTip.showText(ev.screenPos(), text, widget=self.plotview) return True else: return False def report(self, reporter, contents): self.reports[id(reporter)] = contents def report_finished(self, reporter): try: self.reports.pop(id(reporter)) except KeyError: pass # ok if it was already removed if not self.reports: pass def cycle_color_attr(self): elements = [(a.name if isinstance(a, Variable) else a) for a in self.feature_color_model] currentind = 0 try: currentind = elements.index(self.feature_color) except ValueError: pass next = (currentind + 1) % len(self.feature_color_model) self.feature_color = elements[next] self.update_view() def set_limits(self): vr = self.plot.vb.viewRect() x1 = self.range_x1 if self.range_x1 is not None else vr.left() x2 = self.range_x2 if self.range_x2 is not None else vr.right() y1 = self.range_y1 if self.range_y1 is not None else vr.top() y2 = self.range_y2 if self.range_y2 is not None else vr.bottom() self.plot.vb.setXRange(x1, x2) self.plot.vb.setYRange(y1, y2) def labels_changed(self): self.plot.setTitle(self.label_title) if not self.label_title: self.plot.setTitle(None) self.plot.setLabels(bottom=self.label_xaxis) self.plot.showLabel("bottom", bool(self.label_xaxis)) self.plot.getAxis("bottom").resizeEvent() # align text self.plot.setLabels(left=self.label_yaxis) self.plot.showLabel("left", bool(self.label_yaxis)) self.plot.getAxis("left").resizeEvent() # align text def grid_changed(self): self.show_grid = not self.show_grid self.grid_apply() def grid_apply(self): self.plot.showGrid(self.show_grid, self.show_grid, alpha=0.3) self.show_grid_a.setChecked(self.show_grid) def invertX_changed(self): self.invertX = not self.invertX self.invertX_apply() def invertX_apply(self): self.plot.vb.invertX(self.invertX) self.resized() # force redraw of axes (to avoid a pyqtgraph bug) vr = self.plot.vb.viewRect() self.plot.vb.setRange(xRange=(0, 1), yRange=(0, 1)) self.plot.vb.setRange(rect=vr) self.invertX_menu.setChecked(self.invertX) def save_graph(self): self.viewhelpers_hide() self.plot.showAxis("top", True) self.plot.showAxis("right", True) self.parent.save_graph() self.plot.showAxis("top", False) self.plot.showAxis("right", False) self.viewhelpers_show() def clear_data(self): self.data = None self.data_x = None # already sorted x-axis self.data_xsind = None # sorting indices for x-axis self.sampled_indices = [] self.sampled_indices_inverse = {} self.sampling = None self.discrete_palette = None def clear_graph(self): # reset caching. if not, it is not cleared when view changing when zoomed self.highlighted = None self.curves_cont.setCacheMode(QGraphicsItem.NoCache) self.curves_cont.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.plot.vb.disableAutoRange() self.curves_cont.clear() self.curves_cont.update() self.plotview.clear() self.multiple_curves_info = [] self.curves_plotted = [] # currently plotted elements (for rescale) self.curves = [] # for finding closest curve self.plotview.addItem(self.label, ignoreBounds=True) self.highlighted_curve = pg.PlotCurveItem(pen=self.pen_mouse) self.highlighted_curve.setZValue(10) self.highlighted_curve.hide() self.plot.addItem(self.highlighted_curve) self.plot.addItem(self.vLine, ignoreBounds=True) self.plot.addItem(self.hLine, ignoreBounds=True) self.viewhelpers = True self.plot.addItem(self.curves_cont) for m in self.markings: self.plot.addItem(m, ignoreBounds=True) def resized(self): try: vr = self.plot.vb.viewRect() xpixel, ypixel = self.plot.vb.viewPixelSize() except: # if vb is not shown we can not get viewPixelSize return def important_decimals(n): return max(-int(math.floor(math.log10(n))) + 1, 0) self.important_decimals = important_decimals(xpixel), important_decimals(ypixel) if self.invertX: self.label.setPos(vr.bottomLeft()) else: self.label.setPos(vr.bottomRight()) xd, yd = self.important_decimals self.range_e_x1.setPlaceholderText(("%0." + str(xd) + "f") % vr.left()) self.range_e_x2.setPlaceholderText(("%0." + str(xd) + "f") % vr.right()) self.range_e_y1.setPlaceholderText(("%0." + str(yd) + "f") % vr.top()) self.range_e_y2.setPlaceholderText(("%0." + str(yd) + "f") % vr.bottom()) def make_selection(self, data_indices, add=False): selected_indices = self.selected_indices oldids = selected_indices.copy() invd = self.sampled_indices_inverse if data_indices is None: if not add: selected_indices.clear() self.set_curve_pens([invd[a] for a in oldids if a in invd]) else: if add: selected_indices.update(data_indices) self.set_curve_pens([invd[a] for a in data_indices if a in invd]) else: selected_indices.clear() selected_indices.update(data_indices) self.set_curve_pens([invd[a] for a in (oldids | selected_indices) if a in invd]) if self.select_at_least_1 and not selected_indices and len(self.data) > 0: # no selection selected_indices.update([0]) if 0 in invd: self.set_curve_pens([invd[0]]) self.selection_changed() def selection_changed(self): # reset average view; individual was already handled in make_selection if self.viewtype == AVERAGE: self.show_average() if self.selection_type: self.parent.selection_changed() def viewhelpers_hide(self): self.label.hide() self.vLine.hide() self.hLine.hide() def viewhelpers_show(self): self.label.show() if self.crosshair and not self.crosshair_hidden: self.vLine.show() self.hLine.show() else: self.vLine.hide() self.hLine.hide() def mouseMoved(self, evt): pos = evt[0] if self.plot.sceneBoundingRect().contains(pos): mousePoint = self.plot.vb.mapSceneToView(pos) posx, posy = mousePoint.x(), mousePoint.y() labels = [] for a, vs in sorted(self.reports.items()): for v in vs: if isinstance(v, tuple) and len(v) == 2: if v[0] == "x": labels.append(("%0." + str(self.important_decimals[0]) + "f") % v[1]) continue labels.append(str(v)) labels = " ".join(labels) self.crosshair_hidden = bool(labels) if self.location and not labels: fs = "%0." + str(self.important_decimals[0]) + "f %0." + str(self.important_decimals[1]) + "f" labels = fs % (posx, posy) self.label.setText(labels, color=(0, 0, 0)) if self.curves and len(self.curves[0][0]): # need non-zero x axis! cache = {} bd = None if self.markclosest and self.plot.vb.action != ZOOMING: xpixel, ypixel = self.plot.vb.viewPixelSize() distances = distancetocurves(self.curves[0], posx, posy, xpixel, ypixel, r=self.MOUSE_RADIUS, cache=cache) try: mindi = np.nanargmin(distances) if distances[mindi] < self.MOUSE_RADIUS: bd = mindi except ValueError: # if all distances are NaN pass if self.highlighted != bd: QToolTip.hideText() if self.highlighted is not None and bd is None: self.highlighted = None self.highlighted_curve.hide() if bd is not None: self.highlighted = bd x = self.curves[0][0] y = self.curves[0][1][self.highlighted] self.highlighted_curve.setData(x=x, y=y) self.highlighted_curve.show() self.vLine.setPos(posx) self.hLine.setPos(posy) self.viewhelpers_show() else: self.viewhelpers_hide() def set_curve_pen(self, idc): idcdata = self.sampled_indices[idc] insubset = self.subset_indices[idcdata] inselected = self.selection_type and idcdata in self.selected_indices have_subset = np.any(self.subset_indices) thispen = self.pen_subset if insubset or not have_subset else self.pen_normal if inselected: thispen = self.pen_selected color_var = self._current_color_var() value = None if color_var is None else str(self.data[idcdata][color_var]) self.curves_cont.objs[idc].setPen(thispen[value]) self.curves_cont.objs[idc].setZValue(int(insubset) + int(inselected)) def set_curve_pens(self, curves=None): if self.viewtype == INDIVIDUAL and self.curves: curves = range(len(self.curves[0][1])) if curves is None else curves for i in curves: self.set_curve_pen(i) self.curves_cont.update() def add_marking(self, item): self.markings.append(item) self.plot.addItem(item, ignoreBounds=True) def remove_marking(self, item): self.plot.removeItem(item) self.markings.remove(item) def clear_markings(self): for m in self.markings: self.plot.removeItem(m) self.markings = [] def add_curves(self, x, ys, addc=True): """ Add multiple curves with the same x domain. """ if len(ys) > MAX_INSTANCES_DRAWN: sample_selection = random.Random(self.sample_seed).sample(range(len(ys)), MAX_INSTANCES_DRAWN) # with random selection also show at most MAX_INSTANCES_DRAW elements from the subset subset = set(np.where(self.subset_indices)[0]) subset_to_show = subset - set(sample_selection) subset_additional = MAX_INSTANCES_DRAWN - (len(subset) - len(subset_to_show)) if len(subset_to_show) > subset_additional: subset_to_show = random.Random(self.sample_seed).sample(subset_to_show, subset_additional) self.sampled_indices = sorted(sample_selection + list(subset_to_show)) self.sampling = True else: self.sampled_indices = list(range(len(ys))) random.Random(self.sample_seed).shuffle(self.sampled_indices) # for sequential classes# self.sampled_indices_inverse = {s: i for i, s in enumerate(self.sampled_indices)} ys = self.data.X[self.sampled_indices][:, self.data_xsind] self.curves.append((x, ys)) for y in ys: c = pg.PlotCurveItem(x=x, y=y, pen=self.pen_normal[None]) self.curves_cont.add_curve(c) self.curves_plotted = self.curves def add_curve(self, x, y, pen=None): c = pg.PlotCurveItem(x=x, y=y, pen=pen if pen else self.pen_normal[None]) self.curves_cont.add_curve(c) # for rescale to work correctly self.curves_plotted.append((x, np.array([y]))) def add_fill_curve(self, x, ylow, yhigh, pen): phigh = pg.PlotCurveItem(x, yhigh, pen=pen) plow = pg.PlotCurveItem(x, ylow, pen=pen) color = pen.color() color.setAlphaF(0.2) cc = pg.mkBrush(color) pfill = pg.FillBetweenItem(plow, phigh, brush=cc) pfill.setZValue(10) self.curves_cont.add_bounds(phigh) self.curves_cont.add_bounds(plow) self.curves_cont.add_curve(pfill, ignore_bounds=True) # for zoom to work correctly self.curves_plotted.append((x, np.array([ylow, yhigh]))) def _current_color_var(self): color_var = None if self.feature_color and self.data: color_var = self.data.domain[self.feature_color] return color_var def set_pen_colors(self): self.pen_normal.clear() self.pen_subset.clear() self.pen_selected.clear() color_var = self._current_color_var() if color_var is not None: colors = color_var.colors discrete_palette = ColorPaletteGenerator( number_of_colors=len(colors), rgb_colors=colors) for v in color_var.values: basecolor = discrete_palette[color_var.to_val(v)] basecolor = QColor(basecolor) basecolor.setAlphaF(0.9) self.pen_subset[v] = pg.mkPen(color=basecolor, width=1) self.pen_selected[v] = pg.mkPen(color=basecolor, width=2, style=Qt.DotLine) notselcolor = basecolor.lighter(150) notselcolor.setAlphaF(0.5) self.pen_normal[v] = pg.mkPen(color=notselcolor, width=1) def show_individual(self): self.view_average_menu.setChecked(False) self.set_pen_colors() self.clear_graph() self.viewtype = INDIVIDUAL if not self.data: return self.add_curves(self.data_x, self.data.X) self.set_curve_pens() self.curves_cont.update() self.plot.vb.set_mode_panning() def resample_curves(self, seed): self.sample_seed = seed self.update_view() def rescale_current_view_y(self): if self.curves_plotted: cache = {} qrect = self.plot.vb.targetRect() bleft = qrect.left() bright = qrect.right() ymax = max(np.max(ys[:, searchsorted_cached(cache, x, bleft): searchsorted_cached(cache, x, bright, side="right")]) for x, ys in self.curves_plotted) ymin = min(np.min(ys[:, searchsorted_cached(cache, x, bleft): searchsorted_cached(cache, x, bright, side="right")]) for x, ys in self.curves_plotted) self.plot.vb.setYRange(ymin, ymax, padding=0.0) self.plot.vb.pad_current_view_y() def _split_by_color_value(self, data): color_var = self._current_color_var() rd = {} if color_var is None: rd[None] = np.full((len(data.X),), True, dtype=bool) else: cvd = Orange.data.Table(Orange.data.Domain([color_var]), data) for v in range(len(color_var.values)): v1 = np.in1d(cvd.X, v) if np.any(v1): rd[color_var.values[v]] = v1 nanind = np.isnan(cvd.X) if np.any(nanind): rd[None] = nanind return rd def viewtype_changed(self): if self.viewtype == AVERAGE: self.viewtype = INDIVIDUAL else: self.viewtype = AVERAGE self.update_view() def show_average(self): self.view_average_menu.setChecked(True) self.set_pen_colors() self.clear_graph() self.viewtype = AVERAGE if not self.data: return x = self.data_x if self.data: ysall = [] cinfo = [] selected_indices = np.full(len(self.data), False, dtype=bool) selected_indices[list(self.selected_indices)] = True dsplit = self._split_by_color_value(self.data) for colorv, indices in dsplit.items(): for part in [None, "subset", "selection"]: if part is None: part_selection = indices pen = self.pen_normal if np.any(self.subset_indices) else self.pen_subset elif part == "selection" and self.selection_type: part_selection = indices & selected_indices pen = self.pen_selected elif part == "subset": part_selection = indices & self.subset_indices pen = self.pen_subset if np.any(part_selection): ys = self.data.X[part_selection] std = np.nanstd(ys, axis=0) mean = np.nanmean(ys, axis=0) std = std[self.data_xsind] mean = mean[self.data_xsind] ysall.append(mean) penc = QPen(pen[colorv]) penc.setWidth(3) self.add_curve(x, mean, pen=penc) self.add_fill_curve(x, mean + std, mean - std, pen=penc) cinfo.append((colorv, part, part_selection)) self.curves.append((x, np.array(ysall))) self.multiple_curves_info = cinfo self.curves_cont.update() self.plot.vb.set_mode_panning() def update_view(self): if self.viewtype == INDIVIDUAL: self.show_individual() elif self.viewtype == AVERAGE: self.show_average() if self.rescale_next: self.plot.vb.autoRange() def set_data(self, data, auto_update=True): if not self.selected_indices: # either None or previously saved empty set self.selected_indices = set() if self.data is data: return if data is not None: if self.data: self.rescale_next = not data.domain == self.data.domain else: self.rescale_next = True self.data = data if self.select_at_least_1: self.make_selection([], add=True) # make selection valid # get and sort input data x = getx(self.data) xsind = np.argsort(x) self.data_x = x[xsind] self.data_xsind = xsind self._set_subset_indices() # refresh subset indices according to the current subset if auto_update: self.update_view() def _set_subset_indices(self): ids = self.subset if ids is None: ids = [] if self.data: self.subset_indices = np.in1d(self.data.ids, ids) def set_data_subset(self, ids, auto_update=True): self.subset = ids # an array of indices self._set_subset_indices() if auto_update: self.update_view() def select_by_click(self, pos, add): clicked_curve = self.highlighted if clicked_curve is not None: if self.viewtype == INDIVIDUAL: self.make_selection([self.sampled_indices[clicked_curve]], add) elif self.viewtype == AVERAGE: sel = np.where(self.multiple_curves_info[clicked_curve][2])[0] self.make_selection(sel, add) else: self.make_selection(None, add) def select_line(self, startp, endp, add): intersected = self.intersect_curves((startp.x(), startp.y()), (endp.x(), endp.y())) self.make_selection(intersected if len(intersected) else None, add) def intersect_curves(self, q1, q2): x, ys = self.data_x, self.data.X if len(x) < 2: return [] x1, x2 = min(q1[0], q2[0]), max(q1[0], q2[0]) xmin = closestindex(x, x1) xmax = closestindex(x, x2, side="right") xmin = max(0, xmin - 1) xmax = xmax + 2 sel = np.flatnonzero(intersect_curves_chunked(x, ys, self.data_xsind, q1, q2, xmin, xmax)) return sel
def __init__(self, parent): QWidget.__init__(self) OWComponent.__init__(self, parent) SelectionGroupMixin.__init__(self) self.parent = parent self.selection_type = SELECTMANY self.saving_enabled = True self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBox(self)) self.plot = self.plotview.getPlotItem() self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("Menu", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) actions = [] zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_fit) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict( labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True, valueType=str) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox( box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox( box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) self.color_cb = gui.comboBox(box, self, "palette_index", label="Color:", labelWidth=50, orientation=Qt.Horizontal) self.color_cb.setIconSize(QSize(64, 16)) palettes = _color_palettes self.palette_index = min(self.palette_index, len(palettes) - 1) model = color_palette_model(palettes, self.color_cb.iconSize()) model.setParent(self) self.color_cb.setModel(model) self.color_cb.activated.connect(self.update_color_schema) self.color_cb.setCurrentIndex(self.palette_index) form = QFormLayout( formAlignment=Qt.AlignLeft, labelAlignment=Qt.AlignLeft, fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow ) def limit_changed(): self.update_levels() self.reset_thresholds() self._level_low_le = lineEditDecimalOrNone(self, self, "level_low", callback=limit_changed) self._level_low_le.validator().setDefault(0) form.addRow("Low limit:", self._level_low_le) self._level_high_le = lineEditDecimalOrNone(self, self, "level_high", callback=limit_changed) self._level_high_le.validator().setDefault(1) form.addRow("High limit:", self._level_high_le) lowslider = gui.hSlider( box, self, "threshold_low", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_levels) highslider = gui.hSlider( box, self, "threshold_high", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_levels) form.addRow("Low:", lowslider) form.addRow("High:", highslider) box.layout().addLayout(form) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.markings_integral = [] self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}