def __updatePen(self): self.prepareGeometryChange() self.__boundingRect = None if self.__dynamic: if self.__dynamicEnabled: color = QColor(0, 150, 0, 150) else: color = QColor(150, 0, 0, 150) normal = QPen(QBrush(color), 2.0) hover = QPen(QBrush(color.darker(120)), 2.1) else: normal = QPen(QBrush(QColor("#9CACB4")), 2.0) hover = QPen(QBrush(QColor("#7D7D7D")), 2.1) if self.__state & LinkItem.Empty: pen_style = Qt.DashLine else: pen_style = Qt.SolidLine normal.setStyle(pen_style) hover.setStyle(pen_style) if self.hover: pen = hover else: pen = normal self.curveItem.setPen(pen)
def make_color_legend(self): if self.attr_color is None: return use_shape = self.attr_shape == self.get_color() if self.attr_color.is_discrete: if not self.legend: self.create_legend() palette = self.discrete_palette for i, value in enumerate(self._get_values(self.attr_color)): color = QColor(*palette.getRGB(i)) pen = _make_pen(color.darker(self.DarkerValue), 1.5) color.setAlpha( self.alpha_value if self.subset_indices is None else 255) brush = QBrush(color) self.legend.addItem( ScatterPlotItem( pen=pen, brush=brush, size=10, symbol=self.CurveSymbols[i] if use_shape else "o"), escape(value)) else: legend = self.color_legend = LegendItem() legend.setParentItem(self.plot_widget.getViewBox()) legend.restoreAnchor(self.__color_legend_anchor) label = PaletteItemSample(self.continuous_palette, self.scale) legend.addItem(label, "") legend.setGeometry(label.boundingRect())
def make_color_legend(self): if self.attr_color is None: return use_shape = self.attr_shape == self.get_color() if self.attr_color.is_discrete: if not self.legend: self.create_legend() palette = self.discrete_palette for i, value in enumerate(self._get_values(self.attr_color)): color = QColor(*palette.getRGB(i)) pen = _make_pen(color.darker(self.DarkerValue), 1.5) color.setAlpha(self.alpha_value if self.subset_indices is None else 255) brush = QBrush(color) self.legend.addItem( ScatterPlotItem( pen=pen, brush=brush, size=10, symbol=self.CurveSymbols[i] if use_shape else "o"), escape(value)) else: legend = self.color_legend = LegendItem() legend.setParentItem(self.plot_widget.getViewBox()) legend.restoreAnchor(self.__color_legend_anchor) label = PaletteItemSample(self.continuous_palette, self.scale) legend.addItem(label, "") legend.setGeometry(label.boundingRect())
def add_points(): nonlocal cur, image_token if image_token != self._image_token: return batch = visible[cur:cur + self.N_POINTS_PER_ITER] batch_lat = lat[batch] batch_lon = lon[batch] x, y = self.Projection.latlon_to_easting_northing(batch_lat, batch_lon) x, y = self.Projection.easting_northing_to_pixel(x, y, zoom, origin, map_pane_pos) if self._jittering: dx, dy = self._jittering_offsets[batch].T x, y = x + dx, y + dy colors = (self._colorgen.getRGB(self._scaled_color_values[batch]).tolist() if self._color_attr else repeat((0xff, 0, 0))) sizes = self._size_coef * \ (self._sizes[batch] if self._size_attr else np.tile(10, len(batch))) for x, y, is_selected, size, color, _in_subset in \ zip(x, y, selected[batch], sizes, colors, in_subset[batch]): pensize2, selpensize2 = (.35, 1.5) if size >= 5 else (.15, .7) pensize2 *= self._size_coef selpensize2 *= self._size_coef size2 = size / 2 if is_selected: painter.setPen(QPen(QBrush(Qt.green), 2 * selpensize2)) painter.drawEllipse(x - size2 - selpensize2, y - size2 - selpensize2, size + selpensize2, size + selpensize2) color = QColor(*color) color.setAlpha(self._opacity) painter.setBrush(QBrush(color) if _in_subset else Qt.NoBrush) painter.setPen(QPen(QBrush(color.darker(180)), 2 * pensize2)) painter.drawEllipse(x - size2 - pensize2, y - size2 - pensize2, size + pensize2, size + pensize2) im.save(self._overlay_image_path, 'PNG') self.evalJS('markersImageLayer.setUrl("{}#{}"); 0;' .format(self.toFileURL(self._overlay_image_path), np.random.random())) cur += self.N_POINTS_PER_ITER if cur < len(visible): QTimer.singleShot(10, add_points) self._owwidget.progressBarAdvance(100 / n_iters, None) else: self._owwidget.progressBarFinished(None)
def _update_color_legend(self, labels): symbols = ['o' for _ in range(len(labels))] colors = self.palette.values_to_colors(np.arange(len(labels))) for color, label, symbol in zip(colors, labels, symbols): color = QColor(*color) pen = self._make_pen(color.darker(120), 1.5) color.setAlpha(self.alpha_value) brush = QBrush(color) sis = SymbolItemSample(pen=pen, brush=brush, size=10, symbol=symbol) self.color_legend.addItem(sis, escape(label))
def __get_line_color(self, data_index=None, mean_index=None): color = QColor(LinePlotColors.DEFAULT_COLOR) if self.group_var is not None: if data_index is not None: value = self.data[data_index][self.group_var] if np.isnan(value): return color index = int(value) if data_index is not None else mean_index color = LinePlotColors()(len(self.group_var.values))[index] return color.darker(110) if data_index is None else color
def add_points(): nonlocal cur, image_token if image_token != self._image_token: return batch = visible[cur:cur + self.N_POINTS_PER_ITER] batch_lat = lat[batch] batch_lon = lon[batch] x, y = self.Projection.latlon_to_easting_northing( batch_lat, batch_lon) x, y = self.Projection.easting_northing_to_pixel( x, y, zoom, origin, map_pane_pos) if self._jittering: dx, dy = self._jittering_offsets[batch].T x, y = x + dx, y + dy colors = (self._colorgen.getRGB( self._scaled_color_values[batch]).tolist() if self._color_attr else repeat((0xff, 0, 0))) sizes = self._size_coef * \ (self._sizes[batch] if self._size_attr else np.tile(10, len(batch))) for x, y, is_selected, size, color, _in_subset in \ zip(x, y, selected[batch], sizes, colors, in_subset[batch]): pensize2, selpensize2 = (.35, 1.5) if size >= 5 else (.15, .7) pensize2 *= self._size_coef selpensize2 *= self._size_coef size2 = size / 2 if is_selected: painter.setPen(QPen(QBrush(Qt.green), 2 * selpensize2)) painter.drawEllipse(x - size2 - selpensize2, y - size2 - selpensize2, size + selpensize2, size + selpensize2) color = QColor(*color) color.setAlpha(self._opacity) painter.setBrush(QBrush(color) if _in_subset else Qt.NoBrush) painter.setPen(QPen(QBrush(color.darker(180)), 2 * pensize2)) painter.drawEllipse(x - size2 - pensize2, y - size2 - pensize2, size + pensize2, size + pensize2) im.save(self._overlay_image_path, 'PNG') self.evalJS('markersImageLayer.setUrl("{}#{}"); 0;'.format( self.toFileURL(self._overlay_image_path), np.random.random())) cur += self.N_POINTS_PER_ITER if cur < len(visible): QTimer.singleShot(10, add_points) self._owwidget.progressBarAdvance(100 / n_iters, None) else: self._owwidget.progressBarFinished(None)
def create_gradient(base_color: QColor, stop=QPointF(0, 0), finalStop=QPointF(0, 1)) -> QLinearGradient: """ Create a default linear gradient using `base_color` . """ grad = QLinearGradient(stop, finalStop) grad.setStops([(0.0, base_color), (0.5, base_color), (0.8, base_color.darker(105)), (1.0, base_color.darker(110)), ]) grad.setCoordinateMode(QLinearGradient.ObjectBoundingMode) return grad
def _update_colored_legend(self, legend, labels, symbols): if self.scatterplot_item is None or not self.palette: return if isinstance(symbols, str): symbols = itertools.repeat(symbols, times=len(labels)) for i, (label, symbol) in enumerate(zip(labels, symbols)): color = QColor(*self.palette.getRGB(i)) pen = _make_pen(color.darker(self.DarkerValue), 1.5) color.setAlpha(255 if self.subset_is_shown else self.alpha_value) brush = QBrush(color) legend.addItem( ScatterPlotItem(pen=pen, brush=brush, size=10, symbol=symbol), escape(label))
def __hightlight(self, point: QPointF): if not self.__highlight_feature: return for index, item in enumerate(self.__fill_items): if self._contains_point(item, point): n = len(self.__neg_labels) if index < n: name = self.__pos_labels[index] index_other = self.__neg_labels.index(name) + n else: name = self.__neg_labels[index - n] index_other = self.__pos_labels.index(name) for i in (index, index_other): item = self.__fill_items[i] color = QColor(*item.rgb) color = color.darker(120) item.setBrush(pg.mkBrush(color)) break
class ArrowAnnotation(Annotation): def __init__(self, parent=None, line=None, **kwargs): # type: (Optional[QGraphicsItem], Optional[QLineF], Any) -> None super().__init__(parent, **kwargs) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFocusPolicy(Qt.ClickFocus) if line is None: line = QLineF(0, 0, 20, 0) self.__line = QLineF(line) self.__color = QColor(Qt.red) # An item with the same shape as this arrow, stacked behind this # item as a source for QGraphicsDropShadowEffect. Cannot attach # the effect to this item directly as QGraphicsEffect makes the item # non devicePixelRatio aware. self.__arrowShadowBase = ArrowItem(self, line=line) self.__arrowShadowBase.setPen(Qt.NoPen) # no pen -> slightly thinner self.__arrowShadowBase.setBrush(QBrush(self.__color)) self.__arrowShadowBase.setArrowStyle(ArrowItem.Concave) self.__arrowShadowBase.setLineWidth(5) self.__shadow = QGraphicsDropShadowEffect( blurRadius=5, offset=QPointF(1.0, 2.0), ) self.__arrowShadowBase.setGraphicsEffect(self.__shadow) self.__shadow.setEnabled(True) # The 'real' shape item self.__arrowItem = ArrowItem(self, line=line) self.__arrowItem.setBrush(self.__color) self.__arrowItem.setPen(QPen(self.__color)) self.__arrowItem.setArrowStyle(ArrowItem.Concave) self.__arrowItem.setLineWidth(5) self.__autoAdjustGeometry = True def setAutoAdjustGeometry(self, autoAdjust): # type: (bool) -> None """ If set to `True` then the geometry will be adjusted whenever the arrow is changed with `setLine`. Otherwise the geometry of the item is only updated so the `line` lies within the `geometry()` rect (i.e. it only grows). True by default """ self.__autoAdjustGeometry = autoAdjust if autoAdjust: self.adjustGeometry() def autoAdjustGeometry(self): # type: () -> bool """ Should the geometry of the item be adjusted automatically when `setLine` is called. """ return self.__autoAdjustGeometry def setLine(self, line): # type: (QLineF) -> None """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = QLineF(line) # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__arrowShadowBase.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom) def line(self): # type: () -> QLineF """ Return the arrow base line (`QLineF` in object coordinates). """ return QLineF(self.__line) def setColor(self, color): # type: (QColor) -> None """ Set arrow brush color. """ if self.__color != color: self.__color = QColor(color) self.__updateStyleState() def color(self): # type: () -> QColor """ Return the arrow brush color. """ return QColor(self.__color) def setLineWidth(self, lineWidth): # type: (float) -> None """ Set the arrow line width. """ self.__arrowItem.setLineWidth(lineWidth) self.__arrowShadowBase.setLineWidth(lineWidth) def lineWidth(self): # type: () -> float """ Return the arrow line width. """ return self.__arrowItem.lineWidth() def adjustGeometry(self): # type: () -> None """ Adjust the widget geometry to exactly fit the arrow inside while preserving the arrow path scene geometry. """ # local system coordinate geom = self.geometry().translated(-self.pos()) line = self.__line arrow_rect = self.__arrowItem.shape().boundingRect() if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) geom = geom.intersected(arrow_rect) diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) geom.translate(self.pos()) self.setGeometry(geom) self.setLine(line) def shape(self): # type: () -> QPainterPath arrow_shape = self.__arrowItem.shape() return self.mapFromItem(self.__arrowItem, arrow_shape) def itemChange(self, change, value): # type: (QGraphicsItem.GraphicsItemChange, Any) -> Any if change == QGraphicsItem.ItemSelectedHasChanged: self.__updateStyleState() return super().itemChange(change, value) def __updateStyleState(self): # type: () -> None """ Update the arrows' brush, pen, ... based on it's state """ if self.isSelected(): color = self.__color.darker(150) pen = QPen(QColor(96, 158, 215), Qt.DashDotLine) pen.setWidthF(1.25) pen.setCosmetic(True) shadow = pen.color().darker(150) else: color = self.__color pen = QPen(color) shadow = QColor(63, 63, 63, 180) self.__arrowShadowBase.setBrush(color) self.__shadow.setColor(shadow) self.__arrowItem.setBrush(color) self.__arrowItem.setPen(pen)
class ArrowAnnotation(Annotation): def __init__(self, parent=None, line=None, **kwargs): Annotation.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFocusPolicy(Qt.ClickFocus) if line is None: line = QLineF(0, 0, 20, 0) self.__line = QLineF(line) self.__color = QColor(Qt.red) # An item with the same shape as this arrow, stacked behind this # item as a source for QGraphicsDropShadowEffect. Cannot attach # the effect to this item directly as QGraphicsEffect makes the item # non devicePixelRatio aware. self.__arrowShadowBase = ArrowItem(self, line=line) self.__arrowShadowBase.setPen(Qt.NoPen) # no pen -> slightly thinner self.__arrowShadowBase.setBrush(QBrush(self.__color)) self.__arrowShadowBase.setArrowStyle(ArrowItem.Concave) self.__arrowShadowBase.setLineWidth(5) self.__shadow = QGraphicsDropShadowEffect( blurRadius=5, offset=QPointF(1.0, 2.0), ) self.__arrowShadowBase.setGraphicsEffect(self.__shadow) self.__shadow.setEnabled(True) # The 'real' shape item self.__arrowItem = ArrowItem(self, line=line) self.__arrowItem.setBrush(self.__color) self.__arrowItem.setPen(QPen(self.__color)) self.__arrowItem.setArrowStyle(ArrowItem.Concave) self.__arrowItem.setLineWidth(5) self.__autoAdjustGeometry = True def setAutoAdjustGeometry(self, autoAdjust): """ If set to `True` then the geometry will be adjusted whenever the arrow is changed with `setLine`. Otherwise the geometry of the item is only updated so the `line` lies within the `geometry()` rect (i.e. it only grows). True by default """ self.__autoAdjustGeometry = autoAdjust if autoAdjust: self.adjustGeometry() def autoAdjustGeometry(self): """ Should the geometry of the item be adjusted automatically when `setLine` is called. """ return self.__autoAdjustGeometry def setLine(self, line): """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = QLineF(line) # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__arrowShadowBase.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom) def line(self): """ Return the arrow base line (`QLineF` in object coordinates). """ return QLineF(self.__line) def setColor(self, color): """ Set arrow brush color. """ if self.__color != color: self.__color = QColor(color) self.__updateStyleState() def color(self): """ Return the arrow brush color. """ return QColor(self.__color) def setLineWidth(self, lineWidth): """ Set the arrow line width. """ self.__arrowItem.setLineWidth(lineWidth) self.__arrowShadowBase.setLineWidth(lineWidth) def lineWidth(self): """ Return the arrow line width. """ return self.__arrowItem.lineWidth() def adjustGeometry(self): """ Adjust the widget geometry to exactly fit the arrow inside while preserving the arrow path scene geometry. """ # local system coordinate geom = self.geometry().translated(-self.pos()) line = self.__line arrow_rect = self.__arrowItem.shape().boundingRect() if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) geom = geom.intersected(arrow_rect) diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) geom.translate(self.pos()) self.setGeometry(geom) self.setLine(line) def shape(self): arrow_shape = self.__arrowItem.shape() return self.mapFromItem(self.__arrowItem, arrow_shape) def itemChange(self, change, value): if change == QGraphicsItem.ItemSelectedHasChanged: self.__updateStyleState() return Annotation.itemChange(self, change, value) def __updateStyleState(self): """ Update the arrows' brush, pen, ... based on it's state """ if self.isSelected(): color = self.__color.darker(150) pen = QPen(QColor(96, 158, 215), Qt.DashDotLine) pen.setWidthF(1.25) pen.setCosmetic(True) shadow = pen.color().darker(150) else: color = self.__color pen = QPen(color) shadow = QColor(63, 63, 63, 180) self.__arrowShadowBase.setBrush(color) self.__shadow.setColor(shadow) self.__arrowItem.setBrush(color) self.__arrowItem.setPen(pen)