def _anchor_circle(self, variables): # minimum visible anchor radius (radius) min_radius = self._get_min_radius() axisitems = [] for anchor, var in zip(self.plotdata.axes, variables[:]): axitem = AnchorItem(line=QLineF(0, 0, *anchor), text=var.name,) axitem.setVisible(np.linalg.norm(anchor) > min_radius) axitem.setPen(pg.mkPen((100, 100, 100))) axitem.setArrowVisible(True) self.viewbox.addItem(axitem) axisitems.append(axitem) self.plotdata.axisitems = axisitems if self.placement == self.Placement.Circular: return hidecircle = QGraphicsEllipseItem() hidecircle.setRect(QRectF(-min_radius, -min_radius, 2 * min_radius, 2 * min_radius)) _pen = QPen(Qt.lightGray, 1) _pen.setCosmetic(True) hidecircle.setPen(_pen) self.viewbox.addItem(hidecircle) self.plotdata.hidecircle = hidecircle
def _anchor_circle(self): # minimum visible anchor radius (radius) minradius = self.radius / 100 + 1e-5 for item in chain(self.plotdata.anchoritem, self.plotdata.items): self.viewbox.removeItem(item) self.plotdata.anchoritem = [] self.plotdata.items = [] for anchor, var in zip(self.plotdata.anchors, self.data.domain.attributes): if True or np.linalg.norm(anchor) > minradius: axitem = AnchorItem( line=QLineF(0, 0, *anchor), text=var.name,) axitem.setVisible(np.linalg.norm(anchor) > minradius) axitem.setPen(pg.mkPen((100, 100, 100))) axitem.setArrowVisible(True) self.plotdata.anchoritem.append(axitem) self.viewbox.addItem(axitem) hidecircle = QGraphicsEllipseItem() hidecircle.setRect( QRectF(-minradius, -minradius, 2 * minradius, 2 * minradius)) _pen = QPen(Qt.lightGray, 1) _pen.setCosmetic(True) hidecircle.setPen(_pen) self.viewbox.addItem(hidecircle) self.plotdata.items.append(hidecircle) self.plotdata.hidecircle = hidecircle
def _draw_border(point_1, point_2, border_width, parent): pen = QPen(QColor(self.border_color)) pen.setCosmetic(True) pen.setWidth(border_width) line = QGraphicsLineItem(QLineF(point_1, point_2), parent) line.setPen(pen) return line
def generate_pens(basecolor): pen = QPen(basecolor, 1) pen.setCosmetic(True) shadow_pen = QPen(pen.color().lighter(160), 2.5) shadow_pen.setCosmetic(True) return pen, shadow_pen
def __init__(self, tree_node, parent=None, **kwargs): self.tree_node = tree_node super().__init__(self._get_rect_attributes(), parent) self.tree_node.graphics_item = self self.setTransformOriginPoint(self.boundingRect().center()) self.setRotation(degrees(self.tree_node.square.angle)) self.setBrush(kwargs.get('brush', QColor('#297A1F'))) # The border should be invariant to scaling pen = QPen(QColor(Qt.black)) pen.setWidthF(0.75) pen.setCosmetic(True) self.setPen(pen) self.setAcceptHoverEvents(True) self.setZValue(kwargs.get('zvalue', 0)) self.z_step = Z_STEP # calculate the correct z values based on the parent if self.tree_node.parent != TreeAdapter.ROOT_PARENT: p = self.tree_node.parent # override root z step num_children = len(p.children) own_index = [1 if c.label == self.tree_node.label else 0 for c in p.children].index(1) self.z_step = int(p.graphics_item.z_step / num_children) base_z = p.graphics_item.zValue() self.setZValue(base_z + own_index * self.z_step)
def paint(self, painter, option, widget=None): painter.save() palette = self.palette() border = palette.brush(QPalette.Mid) pen = QPen(border, 1) pen.setCosmetic(True) painter.setPen(pen) painter.setBrush(palette.brush(QPalette.Window)) brect = self.boundingRect() painter.drawRoundedRect(brect, 4, 4) painter.restore()
def _setup_plot(self): target = self.target_index selected = self.selected_classifiers curves = [self.plot_curves(target, clf_idx) for clf_idx in selected] for curve in curves: self.plot.addItem(curve.curve_item) if self.display_convex_hull: hull = convex_hull([c.curve.hull for c in curves]) self.plot.plot(hull[0], hull[1], pen="y", antialias=True) pen = QPen(QColor(100, 100, 100, 100), 1, Qt.DashLine) pen.setCosmetic(True) self.plot.plot([0, 1], [0, 1], pen=pen, antialias=True)
def __init__(self, size=None, offset=None, pen=None, brush=None): super().__init__(size, offset) self.layout.setContentsMargins(5, 5, 5, 5) self.layout.setHorizontalSpacing(15) self.layout.setColumnAlignment(1, Qt.AlignLeft | Qt.AlignVCenter) if pen is None: pen = QPen(QColor(196, 197, 193, 200), 1) pen.setCosmetic(True) self.__pen = pen if brush is None: brush = QBrush(QColor(232, 232, 232, 100)) self.__brush = brush
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) self.__shadow.setColor(pen.color().darker(150)) else: color = self.__color pen = QPen(Qt.NoPen) self.__shadow.setColor(QColor(63, 63, 63, 180)) self.__arrowItem.setBrush(color) self.__arrowItem.setPen(pen)
def paint(self, painter, option, widget=None): # Override the default selected appearance if self.isSelected(): option.state ^= QStyle.State_Selected rect = self.rect() # this must render before overlay due to order in which it's drawn super().paint(painter, option, widget) painter.save() pen = QPen(QColor(Qt.black)) pen.setWidthF(2) pen.setCosmetic(True) pen.setJoinStyle(Qt.MiterJoin) painter.setPen(pen) painter.drawRect(rect) painter.restore() else: super().paint(painter, option, widget)
def __paint(self): picture = QPicture() painter = QPainter(picture) pen = QPen(QBrush(Qt.white), 0.5) pen.setCosmetic(True) painter.setPen(pen) geom = self.geometry x, y = geom.x(), geom.y() w, h = geom.width(), geom.height() wsingle = w / len(self.dist) for d, c in zip(self.dist, self.colors): painter.setBrush(QBrush(c)) painter.drawRect(QRectF(x, y, wsingle, d * h)) x += wsingle painter.end() self.__picture = picture
def display_distribution(self): dist = self.distributions var = self.var if dist is None or not len(dist): return self.plot.clear() self.plot_prob.clear() self.ploti.hideAxis('right') self.tooltip_items = [] bottomaxis = self.ploti.getAxis("bottom") bottomaxis.setLabel(var.name) bottomaxis.resizeEvent() self.set_left_axis_name() if var and var.is_continuous: bottomaxis.setTicks(None) if not len(dist[0]): return edges, curve = ash_curve(dist, None, m=OWDistributions.ASH_HIST, smoothing_factor=self.smoothing_factor) edges = edges + (edges[1] - edges[0])/2 edges = edges[:-1] if self.cumulative_distr: dx = edges[1] - edges[0] curve = numpy.cumsum(curve) * dx item = pg.PlotCurveItem() pen = QPen(QBrush(Qt.white), 3) pen.setCosmetic(True) item.setData(edges, curve, antialias=True, stepMode=False, fillLevel=0, brush=QBrush(Qt.gray), pen=pen) self.plot.addItem(item) item.tooltip = "Density" self.tooltip_items.append((self.plot, item)) else: bottomaxis.setTicks([list(enumerate(var.values))]) for i, w in enumerate(dist): geom = QRectF(i - 0.33, 0, 0.66, w) item = DistributionBarItem(geom, [1.0], [QColor(128, 128, 128)]) self.plot.addItem(item) item.tooltip = "Frequency for %s: %r" % (var.values[i], w) self.tooltip_items.append((self.plot, item))
def plot_curves(self, target, clf_idx): if (target, clf_idx) not in self._curve_data: curve = liftCurve_from_results(self.results, clf_idx, target) color = self.colors[clf_idx] pen = QPen(color, 1) pen.setCosmetic(True) shadow_pen = QPen(pen.color().lighter(160), 2.5) shadow_pen.setCosmetic(True) item = pg.PlotDataItem( curve.points[0], curve.points[1], pen=pen, shadowPen=shadow_pen, symbol="+", symbolSize=3, symbolPen=shadow_pen, antialias=True ) hull_item = pg.PlotDataItem( curve.hull[0], curve.hull[1], pen=pen, antialias=True ) self._curve_data[target, clf_idx] = \ PlotCurve(curve, item, hull_item) return self._curve_data[target, clf_idx]
def _setup_plot(self): target = self.target_index selected = self.selected_classifiers curves = [self.plot_curves(target, clf_idx) for clf_idx in selected] for curve in curves: self.plot.addItem(curve.curve_item) if self.display_convex_hull: hull = convex_hull([c.curve.hull for c in curves]) self.plot.plot(hull[0], hull[1], pen="y", antialias=True) pen = QPen(QColor(100, 100, 100, 100), 1, Qt.DashLine) pen.setCosmetic(True) self.plot.plot([0, 1], [0, 1], pen=pen, antialias=True) warning = "" if not all(c.curve.is_valid for c in curves): if any(c.curve.is_valid for c in curves): warning = "Some lift curves are undefined" else: warning = "All lift curves are undefined" self.warning(warning)
def _setup_plot(self): target = self.target_index selected = self.selected_classifiers curves = [self.plot_curves(target, i) for i in selected] selected = [self.curve_data(target, i) for i in selected] if self.roc_averaging == OWROCAnalysis.Merge: for curve in curves: graphics = curve.merge() curve = graphics.curve self.plot.addItem(graphics.curve_item) if self.display_convex_curve: self.plot.addItem(graphics.hull_item) if self.display_def_threshold: points = curve.points ind = numpy.argmin(numpy.abs(points.thresholds - 0.5)) item = pg.TextItem(text="{:.3f}".format( points.thresholds[ind]), ) item.setPos(points.fpr[ind], points.tpr[ind]) self.plot.addItem(item) hull_curves = [curve.merged.hull for curve in selected] if hull_curves: self._rocch = convex_hull(hull_curves) iso_pen = QPen(QColor(Qt.black), 1) iso_pen.setCosmetic(True) self._perf_line = InfiniteLine(pen=iso_pen, antialias=True) self.plot.addItem(self._perf_line) elif self.roc_averaging == OWROCAnalysis.Vertical: for curve in curves: graphics = curve.avg_vertical() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) hull_curves = [curve.avg_vertical.hull for curve in selected] elif self.roc_averaging == OWROCAnalysis.Threshold: for curve in curves: graphics = curve.avg_threshold() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) hull_curves = [curve.avg_threshold.hull for curve in selected] elif self.roc_averaging == OWROCAnalysis.NoAveraging: for curve in curves: graphics = curve.folds() for fold in graphics: self.plot.addItem(fold.curve_item) if self.display_convex_curve: self.plot.addItem(fold.hull_item) hull_curves = [ fold.hull for curve in selected for fold in curve.folds ] if self.display_convex_hull and hull_curves: hull = convex_hull(hull_curves) hull_pen = QPen(QColor(200, 200, 200, 100), 2) hull_pen.setCosmetic(True) item = self.plot.plot(hull.fpr, hull.tpr, pen=hull_pen, brush=QBrush(QColor(200, 200, 200, 50)), fillLevel=0) item.setZValue(-10000) pen = QPen(QColor(100, 100, 100, 100), 1, Qt.DashLine) pen.setCosmetic(True) self.plot.plot([0, 1], [0, 1], pen=pen, antialias=True) if self.roc_averaging == OWROCAnalysis.Merge: self._update_perf_line()
def _setup_plot(self): """Setup the plot with new curve data.""" assert self.data is not None data, domain = self.data, self.data.domain if is_discrete(domain.class_var): class_col_data, _ = data.get_column_view(domain.class_var) group_indices = [ np.flatnonzero(class_col_data == i) for i in range(len(domain.class_var.values)) ] else: group_indices = [np.arange(len(data))] X = np.arange(1, len(domain.attributes) + 1) groups = [] for i, indices in enumerate(group_indices): if self.classes: color = self.class_colors[i] else: color = QColor(Qt.darkGray) group_data = data[indices, :] plot_x, plot_y, connect = disconnected_curve_data(group_data.X, x=X) color.setAlpha(200) lightcolor = QColor(color.lighter(factor=150)) lightcolor.setAlpha(150) pen = QPen(color, 2) pen.setCosmetic(True) lightpen = QPen(lightcolor, 1) lightpen.setCosmetic(True) hoverpen = QPen(pen) hoverpen.setWidth(2) curve = pg.PlotCurveItem( x=plot_x, y=plot_y, connect=connect, pen=lightpen, symbolSize=2, antialias=True, ) self.graph.addItem(curve) hovercurves = [] for index, profile in zip(indices, group_data.X): hcurve = HoverCurve(x=X, y=profile, pen=hoverpen, antialias=True) hcurve.setToolTip('{}'.format(index)) hcurve._data_index = index hovercurves.append(hcurve) self.graph.addItem(hcurve) mean = np.nanmean(group_data.X, axis=0) meancurve = pg.PlotDataItem(x=X, y=mean, pen=pen, size=5, symbol="o", pxMode=True, symbolSize=5, antialias=True) hoverpen = QPen(hoverpen) hoverpen.setWidth(5) hc = HoverCurve(x=X, y=mean, pen=hoverpen, antialias=True) hc.setFlag(QGraphicsItem.ItemIsSelectable, False) self.graph.addItem(hc) self.graph.addItem(meancurve) self.legend_items.append(meancurve) q1, q2, q3 = np.nanpercentile(group_data.X, [25, 50, 75], axis=0) # TODO: implement and use a box plot item errorbar = pg.ErrorBarItem(x=X, y=mean, bottom=np.clip(mean - q1, 0, mean - q1), top=np.clip(q3 - mean, 0, q3 - mean), beam=0.5) self.graph.addItem(errorbar) groups.append( namespace(data=group_data, indices=indices, profiles=curve, hovercurves=hovercurves, mean=meancurve, boxplot=errorbar)) self.__groups = groups self.__update_visibility() self.__update_tooltips()
def pen(color): pen = QPen(color, 1) pen.setCosmetic(True) return pen
def makeline(pos): pen = QPen(Qt.darkGray, 1) pen.setCosmetic(True) line = InfiniteLine(angle=90, pos=pos, pen=pen, movable=True) line.setCursor(Qt.SizeHorCursor) return line
def make_pen(color, width=1): pen = QPen(color, width) pen.setCosmetic(True) return pen
def _make_pen(color, width): p = QPen(color, width) p.setCosmetic(True) return p
def _setup_plot(self): def merge_averaging(): for curve in curves: graphics = curve.merge() curve = graphics.curve self.plot.addItem(graphics.curve_item) if self.display_convex_curve: self.plot.addItem(graphics.hull_item) if self.display_def_threshold and curve.is_valid: points = curve.points ind = np.argmin(np.abs(points.thresholds - 0.5)) item = pg.TextItem(text="{:.3f}".format( points.thresholds[ind]), ) item.setPos(points.fpr[ind], points.tpr[ind]) self.plot.addItem(item) hull_curves = [curve.merged.hull for curve in selected] if hull_curves: self._rocch = convex_hull(hull_curves) iso_pen = QPen(QColor(Qt.black), 1) iso_pen.setCosmetic(True) self._perf_line = InfiniteLine(pen=iso_pen, antialias=True) self.plot.addItem(self._perf_line) return hull_curves def vertical_averaging(): for curve in curves: graphics = curve.avg_vertical() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) return [curve.avg_vertical.hull for curve in selected] def threshold_averaging(): for curve in curves: graphics = curve.avg_threshold() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) return [curve.avg_threshold.hull for curve in selected] def no_averaging(): for curve in curves: graphics = curve.folds() for fold in graphics: self.plot.addItem(fold.curve_item) if self.display_convex_curve: self.plot.addItem(fold.hull_item) return [fold.hull for curve in selected for fold in curve.folds] averagings = { OWROCAnalysis.Merge: merge_averaging, OWROCAnalysis.Vertical: vertical_averaging, OWROCAnalysis.Threshold: threshold_averaging, OWROCAnalysis.NoAveraging: no_averaging } target = self.target_index selected = self.selected_classifiers curves = [self.plot_curves(target, i) for i in selected] selected = [self.curve_data(target, i) for i in selected] hull_curves = averagings[self.roc_averaging]() if self.display_convex_hull and hull_curves: hull = convex_hull(hull_curves) hull_pen = QPen(QColor(200, 200, 200, 100), 2) hull_pen.setCosmetic(True) item = self.plot.plot(hull.fpr, hull.tpr, pen=hull_pen, brush=QBrush(QColor(200, 200, 200, 50)), fillLevel=0) item.setZValue(-10000) pen = QPen(QColor(100, 100, 100, 100), 1, Qt.DashLine) pen.setCosmetic(True) self.plot.plot([0, 1], [0, 1], pen=pen, antialias=True) if self.roc_averaging == OWROCAnalysis.Merge: self._update_perf_line() self._update_axes_ticks() warning = "" if not all(c.is_valid for c in hull_curves): if any(c.is_valid for c in hull_curves): warning = "Some ROC curves are undefined" else: warning = "All ROC curves are undefined" self.warning(warning)
def _setup_plot(self): target = self.target_index selected = self.selected_classifiers curves = [self.plot_curves(target, i) for i in selected] selected = [self.curve_data(target, i) for i in selected] if self.roc_averaging == OWROCAnalysis.Merge: for curve in curves: graphics = curve.merge() curve = graphics.curve self.plot.addItem(graphics.curve_item) if self.display_convex_curve: self.plot.addItem(graphics.hull_item) if self.display_def_threshold and curve.is_valid: points = curve.points ind = numpy.argmin(numpy.abs(points.thresholds - 0.5)) item = pg.TextItem( text="{:.3f}".format(points.thresholds[ind]), ) item.setPos(points.fpr[ind], points.tpr[ind]) self.plot.addItem(item) hull_curves = [curve.merged.hull for curve in selected] if hull_curves: self._rocch = convex_hull(hull_curves) iso_pen = QPen(QColor(Qt.black), 1) iso_pen.setCosmetic(True) self._perf_line = InfiniteLine(pen=iso_pen, antialias=True) self.plot.addItem(self._perf_line) elif self.roc_averaging == OWROCAnalysis.Vertical: for curve in curves: graphics = curve.avg_vertical() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) hull_curves = [curve.avg_vertical.hull for curve in selected] elif self.roc_averaging == OWROCAnalysis.Threshold: for curve in curves: graphics = curve.avg_threshold() self.plot.addItem(graphics.curve_item) self.plot.addItem(graphics.confint_item) hull_curves = [curve.avg_threshold.hull for curve in selected] elif self.roc_averaging == OWROCAnalysis.NoAveraging: for curve in curves: graphics = curve.folds() for fold in graphics: self.plot.addItem(fold.curve_item) if self.display_convex_curve: self.plot.addItem(fold.hull_item) hull_curves = [fold.hull for curve in selected for fold in curve.folds] else: assert False if self.display_convex_hull and hull_curves: hull = convex_hull(hull_curves) hull_pen = QPen(QColor(200, 200, 200, 100), 2) hull_pen.setCosmetic(True) item = self.plot.plot( hull.fpr, hull.tpr, pen=hull_pen, brush=QBrush(QColor(200, 200, 200, 50)), fillLevel=0) item.setZValue(-10000) pen = QPen(QColor(100, 100, 100, 100), 1, Qt.DashLine) pen.setCosmetic(True) self.plot.plot([0, 1], [0, 1], pen=pen, antialias=True) if self.roc_averaging == OWROCAnalysis.Merge: self._update_perf_line() warning = "" if not all(c.is_valid for c in hull_curves): if any(c.is_valid for c in hull_curves): warning = "Some ROC curves are undefined" else: warning = "All ROC curves are undefined" self.warning(warning)
def make_pen(color, width): p = QPen(color, width) p.setCosmetic(True) return p
def display_contingency(self): """ Set the contingency to display. """ cont = self.contingencies var, cvar = self.var, self.cvar if cont is None or not len(cont): return self.plot.clear() self.plot_prob.clear() self._legend.clear() self.tooltip_items = [] if self.show_prob: self.ploti.showAxis('right') else: self.ploti.hideAxis('right') bottomaxis = self.ploti.getAxis("bottom") bottomaxis.setLabel(var.name) bottomaxis.resizeEvent() cvar_values = cvar.values colors = [QColor(*col) for col in cvar.colors] if var and var.is_continuous: bottomaxis.setTicks(None) weights, cols, cvar_values, curves = [], [], [], [] for i, dist in enumerate(cont): v, W = dist if len(v): weights.append(numpy.sum(W)) cols.append(colors[i]) cvar_values.append(cvar.values[i]) curves.append(ash_curve( dist, cont, m=OWDistributions.ASH_HIST, smoothing_factor=self.smoothing_factor)) weights = numpy.array(weights) sumw = numpy.sum(weights) weights /= sumw colors = cols curves = [(X, Y * w) for (X, Y), w in zip(curves, weights)] curvesline = [] #from histograms to lines for X, Y in curves: X = X + (X[1] - X[0])/2 X = X[:-1] X = numpy.array(X) Y = numpy.array(Y) curvesline.append((X, Y)) for t in ["fill", "line"]: curve_data = list(zip(curvesline, colors, weights, cvar_values)) for (X, Y), color, w, cval in reversed(curve_data): item = pg.PlotCurveItem() pen = QPen(QBrush(color), 3) pen.setCosmetic(True) color = QColor(color) color.setAlphaF(0.2) item.setData(X, Y/(w if self.relative_freq else 1), antialias=True, stepMode=False, fillLevel=0 if t == "fill" else None, brush=QBrush(color), pen=pen) self.plot.addItem(item) if t == "line": item.tooltip = "{}\n{}={}".format( "Normalized density " if self.relative_freq else "Density ", cvar.name, cval) self.tooltip_items.append((self.plot, item)) if self.show_prob: all_X = numpy.array(numpy.unique(numpy.hstack([X for X, _ in curvesline]))) inter_X = numpy.array(numpy.linspace(all_X[0], all_X[-1], len(all_X)*2)) curvesinterp = [numpy.interp(inter_X, X, Y) for (X, Y) in curvesline] sumprob = numpy.sum(curvesinterp, axis=0) legal = sumprob > 0.05 * numpy.max(sumprob) i = len(curvesinterp) + 1 show_all = self.show_prob == i for Y, color, cval in reversed(list(zip(curvesinterp, colors, cvar_values))): i -= 1 if show_all or self.show_prob == i: item = pg.PlotCurveItem() pen = QPen(QBrush(color), 3, style=Qt.DotLine) pen.setCosmetic(True) prob = Y[legal] / sumprob[legal] item.setData( inter_X[legal], prob, antialias=True, stepMode=False, fillLevel=None, brush=None, pen=pen) self.plot_prob.addItem(item) item.tooltip = "Probability that \n" + cvar.name + "=" + cval self.tooltip_items.append((self.plot_prob, item)) elif var and var.is_discrete: bottomaxis.setTicks([list(enumerate(var.values))]) cont = numpy.array(cont) maxh = 0 #maximal column height maxrh = 0 #maximal relative column height scvar = cont.sum(axis=1) #a cvar with sum=0 with allways have distribution counts 0, #therefore we can divide it by anything scvar[scvar == 0] = 1 for i, (value, dist) in enumerate(zip(var.values, cont.T)): maxh = max(maxh, max(dist)) maxrh = max(maxrh, max(dist/scvar)) for i, (value, dist) in enumerate(zip(var.values, cont.T)): dsum = sum(dist) geom = QRectF(i - 0.333, 0, 0.666, maxrh if self.relative_freq else maxh) if self.show_prob: prob = dist / dsum ci = 1.96 * numpy.sqrt(prob * (1 - prob) / dsum) else: ci = None item = DistributionBarItem(geom, dist/scvar/maxrh if self.relative_freq else dist/maxh, colors) self.plot.addItem(item) tooltip = "\n".join( "%s: %.*f" % (n, 3 if self.relative_freq else 1, v) for n, v in zip(cvar_values, dist/scvar if self.relative_freq else dist)) item.tooltip = "{} ({}={}):\n{}".format( "Normalized frequency " if self.relative_freq else "Frequency ", cvar.name, value, tooltip) self.tooltip_items.append((self.plot, item)) if self.show_prob: item.tooltip += "\n\nProbabilities:" for ic, a in enumerate(dist): if self.show_prob - 1 != ic and \ self.show_prob - 1 != len(dist): continue position = -0.333 + ((ic+0.5)*0.666/len(dist)) if dsum < 1e-6: continue prob = a / dsum if not 1e-6 < prob < 1 - 1e-6: continue ci = 1.96 * sqrt(prob * (1 - prob) / dsum) item.tooltip += "\n%s: %.3f ± %.3f" % (cvar_values[ic], prob, ci) mark = pg.ScatterPlotItem() errorbar = pg.ErrorBarItem() pen = QPen(QBrush(QColor(0)), 1) pen.setCosmetic(True) errorbar.setData(x=[i+position], y=[prob], bottom=min(numpy.array([ci]), prob), top=min(numpy.array([ci]), 1 - prob), beam=numpy.array([0.05]), brush=QColor(1), pen=pen) mark.setData([i+position], [prob], antialias=True, symbol="o", fillLevel=None, pxMode=True, size=10, brush=QColor(colors[ic]), pen=pen) self.plot_prob.addItem(errorbar) self.plot_prob.addItem(mark) for color, name in zip(colors, cvar_values): self._legend.addItem( ScatterPlotItem(pen=color, brush=color, size=10, shape="s"), escape(name) ) self._legend.show()
def display_contingency(self): """ Set the contingency to display. """ cont = self.contingencies var, cvar = self.var, self.cvar assert len(cont) > 0 self.plot.clear() self.plot_prob.clear() self._legend.clear() self.tooltip_items = [] if self.show_prob: self.ploti.showAxis('right') else: self.ploti.hideAxis('right') bottomaxis = self.ploti.getAxis("bottom") bottomaxis.setLabel(var.name) bottomaxis.resizeEvent() cvar_values = cvar.values colors = [QColor(*col) for col in cvar.colors] if var and var.is_continuous: bottomaxis.setTicks(None) weights, cols, cvar_values, curves = [], [], [], [] for i, dist in enumerate(cont): v, W = dist if len(v): weights.append(numpy.sum(W)) cols.append(colors[i]) cvar_values.append(cvar.values[i]) curves.append( ash_curve(dist, cont, m=OWDistributions.ASH_HIST, smoothing_factor=self.smoothing_facs[ self.smoothing_index])) weights = numpy.array(weights) sumw = numpy.sum(weights) weights /= sumw colors = cols curves = [(X, Y * w) for (X, Y), w in zip(curves, weights)] ncval = len(cvar_values) curvesline = [] #from histograms to lines for (X, Y) in curves: X = X + (X[1] - X[0]) / 2 X = X[:-1] X = numpy.array(X) Y = numpy.array(Y) curvesline.append((X, Y)) for t in ["fill", "line"]: for (X, Y), color, w, cval in reversed( list(zip(curvesline, colors, weights, cvar_values))): item = pg.PlotCurveItem() pen = QPen(QBrush(color), 3) pen.setCosmetic(True) color = QColor(color) color.setAlphaF(0.2) item.setData(X, Y / (w if self.relative_freq else 1), antialias=True, stepMode=False, fillLevel=0 if t == "fill" else None, brush=QBrush(color), pen=pen) self.plot.addItem(item) if t == "line": item.tooltip = ("Normalized density " if self.relative_freq else "Density ") \ + "\n"+ cvar.name + "=" + cval self.tooltip_items.append((self.plot, item)) if self.show_prob: M_EST = 5 #for M estimate all_X = numpy.array( numpy.unique(numpy.hstack([X for X, _ in curvesline]))) inter_X = numpy.array( numpy.linspace(all_X[0], all_X[-1], len(all_X) * 2)) curvesinterp = [ numpy.interp(inter_X, X, Y) for (X, Y) in curvesline ] sumprob = numpy.sum(curvesinterp, axis=0) # allcorrection = M_EST/sumw*numpy.sum(sumprob)/len(inter_X) legal = sumprob > 0.05 * numpy.max(sumprob) i = len(curvesinterp) + 1 show_all = self.show_prob == i for Y, color, cval in reversed( list(zip(curvesinterp, colors, cvar_values))): i -= 1 if show_all or self.show_prob == i: item = pg.PlotCurveItem() pen = QPen(QBrush(color), 3, style=Qt.DotLine) pen.setCosmetic(True) #prob = (Y+allcorrection/ncval)/(sumprob+allcorrection) prob = Y[legal] / sumprob[legal] item.setData(inter_X[legal], prob, antialias=True, stepMode=False, fillLevel=None, brush=None, pen=pen) self.plot_prob.addItem(item) item.tooltip = "Probability that \n" + cvar.name + "=" + cval self.tooltip_items.append((self.plot_prob, item)) elif var and var.is_discrete: bottomaxis.setTicks([list(enumerate(var.values))]) cont = numpy.array(cont) ncval = len(cvar_values) maxh = 0 #maximal column height maxrh = 0 #maximal relative column height scvar = cont.sum(axis=1) #a cvar with sum=0 with allways have distribution counts 0, #therefore we can divide it by anything scvar[scvar == 0] = 1 for i, (value, dist) in enumerate(zip(var.values, cont.T)): maxh = max(maxh, max(dist)) maxrh = max(maxrh, max(dist / scvar)) for i, (value, dist) in enumerate(zip(var.values, cont.T)): dsum = sum(dist) geom = QRectF(i - 0.333, 0, 0.666, maxrh if self.relative_freq else maxh) if self.show_prob: prob = dist / dsum ci = 1.96 * numpy.sqrt(prob * (1 - prob) / dsum) else: ci = None item = DistributionBarItem( geom, dist / scvar / maxrh if self.relative_freq else dist / maxh, colors) self.plot.addItem(item) tooltip = "\n".join("%s: %.*f" % (n, 3 if self.relative_freq else 1, v) for n, v in zip( cvar_values, dist / scvar if self.relative_freq else dist)) item.tooltip = ("Normalized frequency " if self.relative_freq else "Frequency ") \ + "(" + cvar.name + "=" + value + "):" \ + "\n" + tooltip self.tooltip_items.append((self.plot, item)) if self.show_prob: item.tooltip += "\n\nProbabilities:" for ic, a in enumerate(dist): if self.show_prob - 1 != ic and \ self.show_prob - 1 != len(dist): continue position = -0.333 + ((ic + 0.5) * 0.666 / len(dist)) if dsum < 1e-6: continue prob = a / dsum if not 1e-6 < prob < 1 - 1e-6: continue ci = 1.96 * sqrt(prob * (1 - prob) / dsum) item.tooltip += "\n%s: %.3f ± %.3f" % (cvar_values[ic], prob, ci) mark = pg.ScatterPlotItem() bar = pg.ErrorBarItem() pen = QPen(QBrush(QColor(0)), 1) pen.setCosmetic(True) bar.setData(x=[i + position], y=[prob], bottom=min(numpy.array([ci]), prob), top=min(numpy.array([ci]), 1 - prob), beam=numpy.array([0.05]), brush=QColor(1), pen=pen) mark.setData([i + position], [prob], antialias=True, symbol="o", fillLevel=None, pxMode=True, size=10, brush=QColor(colors[ic]), pen=pen) self.plot_prob.addItem(bar) self.plot_prob.addItem(mark) for color, name in zip(colors, cvar_values): self._legend.addItem( ScatterPlotItem(pen=color, brush=color, size=10, shape="s"), escape(name)) self._legend.show()
def _setup_plot(self): """Setup the plot with new curve data.""" assert self.data is not None data, domain = self.data, self.data.domain if is_discrete(domain.class_var): class_col_data, _ = data.get_column_view(domain.class_var) group_indices = [np.flatnonzero(class_col_data == i) for i in range(len(domain.class_var.values))] else: group_indices = [np.arange(len(data))] X = np.arange(1, len(domain.attributes)+1) groups = [] for i, indices in enumerate(group_indices): if self.classes: color = self.class_colors[i] else: color = QColor(Qt.darkGray) group_data = data[indices, :] plot_x, plot_y, connect = disconnected_curve_data(group_data.X, x=X) color.setAlpha(200) lightcolor = QColor(color.lighter(factor=150)) lightcolor.setAlpha(150) pen = QPen(color, 2) pen.setCosmetic(True) lightpen = QPen(lightcolor, 1) lightpen.setCosmetic(True) hoverpen = QPen(pen) hoverpen.setWidth(2) curve = pg.PlotCurveItem( x=plot_x, y=plot_y, connect=connect, pen=lightpen, symbolSize=2, antialias=True, ) self.graph.addItem(curve) hovercurves = [] for index, profile in zip(indices, group_data.X): hcurve = HoverCurve(x=X, y=profile, pen=hoverpen, antialias=True) hcurve.setToolTip('{}'.format(index)) hcurve._data_index = index hovercurves.append(hcurve) self.graph.addItem(hcurve) mean = np.nanmean(group_data.X, axis=0) meancurve = pg.PlotDataItem( x=X, y=mean, pen=pen, size=5, symbol="o", pxMode=True, symbolSize=5, antialias=True ) hoverpen = QPen(hoverpen) hoverpen.setWidth(5) hc = HoverCurve(x=X, y=mean, pen=hoverpen, antialias=True) hc.setFlag(QGraphicsItem.ItemIsSelectable, False) self.graph.addItem(hc) self.graph.addItem(meancurve) self.legend_items.append(meancurve) q1, q2, q3 = np.nanpercentile(group_data.X, [25, 50, 75], axis=0) # TODO: implement and use a box plot item errorbar = pg.ErrorBarItem( x=X, y=mean, bottom=np.clip(mean - q1, 0, mean - q1), top=np.clip(q3 - mean, 0, q3 - mean), beam=0.5 ) self.graph.addItem(errorbar) groups.append( namespace( data=group_data, indices=indices, profiles=curve, hovercurves=hovercurves, mean=meancurve, boxplot=errorbar) ) self.__groups = groups self.__update_visibility() self.__update_tooltips()
def setData(self, data, nsamples, sample_range=None, color=Qt.magenta): assert np.all(np.isfinite(data)) if data.size > 0: xmin, xmax = np.min(data), np.max(data) else: xmin = xmax = 0.0 if sample_range is None: xrange = xmax - xmin sample_min = xmin - xrange * 0.025 sample_max = xmax + xrange * 0.025 else: sample_min, sample_max = sample_range sample = np.linspace(sample_min, sample_max, nsamples) if data.size < 2: est = np.full( sample.size, 1. / sample.size, ) else: try: density = stats.gaussian_kde(data) est = density.evaluate(sample) except np.linalg.LinAlgError: est = np.zeros(sample.size) item = QGraphicsPathItem(violin_shape(sample, est)) color = QColor(color) color.setAlphaF(0.5) item.setBrush(QBrush(color)) pen = QPen(self.palette().color(QPalette.Shadow)) pen.setCosmetic(True) item.setPen(pen) est_max = np.max(est) x = np.random.RandomState(0xD06F00D).uniform(-est_max, est_max, size=data.size) dots = ScatterPlotItem( x=x, y=data, size=3, ) dots.setVisible(self.__dataPointsVisible) pen = QPen(self.palette().color(QPalette.Shadow), 1) hoverPen = QPen(self.palette().color(QPalette.Highlight), 1.5) cmax = SelectionLine(angle=0, pos=xmax, movable=True, bounds=(sample_min, sample_max), pen=pen, hoverPen=hoverPen) cmin = SelectionLine(angle=0, pos=xmin, movable=True, bounds=(sample_min, sample_max), pen=pen, hoverPen=hoverPen) cmax.setCursor(Qt.SizeVerCursor) cmin.setCursor(Qt.SizeVerCursor) selection_item = QGraphicsRectItem( QRectF(-est_max, xmin, est_max * 2, xmax - xmin)) selection_item.setPen(QPen(Qt.NoPen)) selection_item.setBrush(QColor(0, 250, 0, 50)) def update_selection_rect(): mode = self.__selectionMode p = selection_item.parentItem() # type: Optional[QGraphicsItem] while p is not None and not isinstance(p, pg.ViewBox): p = p.parentItem() if p is not None: viewbox = p # type: pg.ViewBox else: viewbox = None rect = selection_item.rect() # type: QRectF if mode & ViolinPlot.High: rect.setTop(cmax.value()) elif viewbox is not None: rect.setTop(viewbox.viewRect().bottom()) else: rect.setTop(cmax.maxRange[1]) if mode & ViolinPlot.Low: rect.setBottom(cmin.value()) elif viewbox is not None: rect.setBottom(viewbox.viewRect().top()) else: rect.setBottom(cmin.maxRange[0]) selection_item.setRect(rect.normalized()) cmax.sigPositionChanged.connect(update_selection_rect) cmin.sigPositionChanged.connect(update_selection_rect) cmax.visibleChanged.connect(update_selection_rect) cmin.visibleChanged.connect(update_selection_rect) def setupper(line): ebound = self.__effectiveBoundary() elower, eupper = ebound mode = self.__selectionMode if not mode & ViolinPlot.High: return upper = line.value() lower = min(elower, upper) if lower != elower and mode & ViolinPlot.Low: self.__min = lower cmin.setValue(lower) if upper != eupper: self.__max = upper if ebound != self.__effectiveBoundary(): self.selectionEdited.emit() self.selectionChanged.emit() def setlower(line): ebound = self.__effectiveBoundary() elower, eupper = ebound mode = self.__selectionMode if not mode & ViolinPlot.Low: return lower = line.value() upper = max(eupper, lower) if upper != eupper and mode & ViolinPlot.High: self.__max = upper cmax.setValue(upper) if lower != elower: self.__min = lower if ebound != self.__effectiveBoundary(): self.selectionEdited.emit() self.selectionChanged.emit() cmax.sigPositionChanged.connect(setupper) cmin.sigPositionChanged.connect(setlower) selmode = self.__selectionMode cmax.setVisible(selmode & ViolinPlot.High) cmin.setVisible(selmode & ViolinPlot.Low) selection_item.setVisible(selmode) self.addItem(dots) self.addItem(item) self.addItem(cmax) self.addItem(cmin) self.addItem(selection_item) self.setRange( QRectF(-est_max, np.min(sample), est_max * 2, np.ptp(sample))) self._plotitems = SimpleNamespace(pointsitem=dots, densityitem=item, cmax=cmax, cmin=cmin, selection_item=selection_item) self.__min = xmin self.__max = xmax
def _setup_plot(self): """Setup the plot with new curve data.""" assert self.data is not None self.graph.clear() data, domain = self.data, self.data.domain var = domain[self.group_var] class_col_data, _ = data.get_column_view(var) group_indices = [ np.flatnonzero(class_col_data == i) for i in range(len(self.classes)) ] self.graph.getAxis('bottom').setTicks([[ (i + 1, str(a)) for i, a in enumerate(self.graph_variables) ]]) X = np.arange(1, len(self.graph_variables) + 1) groups = [] for i, indices in enumerate(group_indices): if len(indices) == 0: groups.append(None) else: if self.classes: color = self.class_colors[i] else: color = QColor(Qt.darkGray) group_data = data[indices, self.graph_variables] plot_x, plot_y, connect = disconnected_curve_data(group_data.X, x=X) color.setAlpha(200) lightcolor = QColor(color.lighter(factor=150)) lightcolor.setAlpha(150) pen = QPen(color, 2) pen.setCosmetic(True) lightpen = QPen(lightcolor, 1) lightpen.setCosmetic(True) curve = pg.PlotCurveItem( x=plot_x, y=plot_y, connect=connect, pen=lightpen, symbolSize=2, antialias=True, ) self.graph.addItem(curve) mean = np.nanmean(group_data.X, axis=0) meancurve = pg.PlotDataItem(x=X, y=mean, pen=pen, size=5, symbol="o", pxMode=True, symbolSize=5, antialias=True) self.graph.addItem(meancurve) q1, q2, q3 = np.nanpercentile(group_data.X, [25, 50, 75], axis=0) # TODO: implement and use a box plot item errorbar = pg.ErrorBarItem(x=X, y=mean, bottom=np.clip( mean - q1, 0, mean - q1), top=np.clip(q3 - mean, 0, q3 - mean), beam=0.5) self.graph.addItem(errorbar) groups.append( namespace(data=group_data, indices=indices, profiles=curve, mean=meancurve, boxplot=errorbar)) self.__groups = groups self.__update_visibility()