Пример #1
0
 def rect(self):
     if getattr(self, "_rect", QRectF()).isValid():
         return self._rect
     else:
         return QRectF(QPointF(0, 0), self.document().size()) | \
                getattr(self, "_rect", QRectF(0, 0, 1, 1))
Пример #2
0
    def setup_plot(self, scoreindex, scores, nulldist=None):
        """
        Setup the score histogram plot

        Parameters
        ----------
        scoreindex : int
            Score index (into OWFeatureSelection.Scores)
        scores : (N, ) array
            The scores obtained
        nulldist (P, N) array optional
            The scores obtained under P permutations of labels.
        """
        score_name, side, test_type, _ = self.Scores[scoreindex]
        low, high = self.thresholds.get(score_name, (-np.inf, np.inf))

        validmask = np.isfinite(scores)
        validscores = scores[validmask]

        nbins = int(max(np.ceil(np.sqrt(len(validscores))), 20))
        freq, edges = np.histogram(validscores, bins=nbins)
        self.histogram.setHistogramCurve(
            pg.PlotCurveItem(x=edges,
                             y=freq,
                             stepMode=True,
                             pen=pg.mkPen("b", width=2)))

        if nulldist is not None:
            nulldist = nulldist.ravel()
            validmask = np.isfinite(nulldist)
            validnulldist = nulldist[validmask]
            nullbins = edges  # XXX: extend to the full range of nulldist
            nullfreq, _ = np.histogram(validnulldist, bins=nullbins)
            nullfreq = nullfreq * (freq.sum() / nullfreq.sum())
            nullitem = pg.PlotCurveItem(x=nullbins,
                                        y=nullfreq,
                                        stepMode=True,
                                        pen=pg.mkPen((50, 50, 50, 100)))
            # Ensure it stacks behind the main curve
            nullitem.setZValue(nullitem.zValue() - 10)
            self.histogram.addItem(nullitem)

        # Restore saved thresholds
        eps = np.finfo(float).eps
        minx, maxx = edges[0] - eps, edges[-1] + eps
        low, high = max(low, minx), min(high, maxx)

        if side == OWFeatureSelection.LowTail:
            mode = Histogram.Low
        elif side == OWFeatureSelection.HighTail:
            mode = Histogram.High
        elif side == OWFeatureSelection.TwoTail:
            mode = Histogram.TwoSided
        else:
            assert False
        self.histogram.setSelectionMode(mode)
        self.histogram.setBoundary(low, high)

        # If this is a two sample test add markers to the left and right
        # plot indicating which group is over-expressed in that part
        if test_type == OWFeatureSelection.TwoSampleTest and \
                side == OWFeatureSelection.TwoTail:
            maxy = np.max(freq)
            # XXX: Change use of integer constant
            if scoreindex == 0:  # fold change is centered on 1.0
                x1, y1 = (minx + 1) / 2, maxy
                x2, y2 = (maxx + 1) / 2, maxy
            else:
                x1, y1 = minx / 2, maxy
                x2, y2 = maxx / 2, maxy

            grp, selected_indices = self.selected_split()

            values = grp.values
            selected_values = [values[i] for i in selected_indices]

            left = ", ".join(v for v in values if v not in selected_values)
            right = ", ".join(v for v in selected_values)

            labelitem = pg.TextItem(left, color=(40, 40, 40))
            labelitem.setPos(x1, y1)
            self.histogram.addItem(labelitem)

            labelitem = pg.TextItem(right, color=(40, 40, 40))
            labelitem.setPos(x2, y2)
            self.histogram.addItem(labelitem)

        miny, maxy = 0.0, np.max(freq)
        if nulldist is not None:
            maxy = max(np.max(nullfreq), maxy)

        if not np.any(np.isnan([maxx, minx, maxy])):
            self.histogram.setRange(QRectF(minx, miny, maxx - minx,
                                           maxy - miny),
                                    padding=0.05)
Пример #3
0
 def _select_data(self):
     self.widget.graph.select_by_rectangle(QRectF(4, 3, 3, 1))
     return self.widget.graph.get_selection()
Пример #4
0
 def boundingRect(self):
     return QRectF(-self.r, -self.r, 2 * self.r, 2 * self.r)
Пример #5
0
 def boundingRect(self):
     return QRectF(0, 0, 40 + self.text_width, 20 + self.scale.bins * 15)
Пример #6
0
 def _ensureSceneRect(self, scene):
     r = scene.addRect(QRectF(0, 0, 400, 400))
     scene.sceneRect()
     scene.removeItem(r)
Пример #7
0
    def update_data(self, attr_x, attr_y, reset_view=True):
        self.master.Warning.missing_coords.clear()
        self.master.Information.missing_coords.clear()
        self._clear_plot_widget()

        self.shown_x, self.shown_y = attr_x, attr_y

        if self.jittered_data is None or not len(self.jittered_data):
            self.valid_data = None
        else:
            index_x = self.domain.index(attr_x)
            index_y = self.domain.index(attr_y)
            self.valid_data = self.get_valid_list([index_x, index_y])
            if not np.any(self.valid_data):
                self.valid_data = None
        if self.valid_data is None:
            self.selection = None
            self.n_points = 0
            self.master.Warning.missing_coords(
                self.shown_x.name, self.shown_y.name)
            return

        x_data, y_data = self.get_xy_data_positions(
            attr_x, attr_y, self.valid_data)
        self.n_points = len(x_data)

        if reset_view:
            min_x, max_x = np.nanmin(x_data), np.nanmax(x_data)
            min_y, max_y = np.nanmin(y_data), np.nanmax(y_data)
            self.view_box.setRange(
                QRectF(min_x, min_y, max_x - min_x, max_y - min_y),
                padding=0.025)
            self.view_box.init_history()
            self.view_box.tag_history()
        [min_x, max_x], [min_y, max_y] = self.view_box.viewRange()

        for axis, name, index in (("bottom", attr_x, index_x),
                                  ("left", attr_y, index_y)):
            self.set_axis_title(axis, name)
            var = self.domain[index]
            if var.is_discrete:
                self.set_labels(axis, get_variable_values_sorted(var))
            else:
                self.set_labels(axis, None)

        color_data, brush_data = self.compute_colors()
        color_data_sel, brush_data_sel = self.compute_colors_sel()
        size_data = self.compute_sizes()
        shape_data = self.compute_symbols()

        if self.should_draw_density():
            rgb_data = [pen.color().getRgb()[:3] for pen in color_data]
            self.density_img = classdensity.class_density_image(
                min_x, max_x, min_y, max_y, self.resolution,
                x_data, y_data, rgb_data)
            self.plot_widget.addItem(self.density_img)

        data_indices = np.flatnonzero(self.valid_data)
        if len(data_indices) != self.original_data.shape[1]:
            self.master.Information.missing_coords(
                self.shown_x.name, self.shown_y.name)

        self.scatterplot_item = ScatterPlotItem(
            x=x_data, y=y_data, data=data_indices,
            symbol=shape_data, size=size_data, pen=color_data, brush=brush_data
        )
        self.scatterplot_item_sel = ScatterPlotItem(
            x=x_data, y=y_data, data=data_indices,
            symbol=shape_data, size=size_data + SELECTION_WIDTH,
            pen=color_data_sel, brush=brush_data_sel
        )
        self.plot_widget.addItem(self.scatterplot_item_sel)
        self.plot_widget.addItem(self.scatterplot_item)

        self.scatterplot_item.selected_points = []
        self.scatterplot_item.sigClicked.connect(self.select_by_click)

        self.update_labels()
        self.make_legend()
        self.plot_widget.replot()
Пример #8
0
 def setSelectionRect(self, rect):
     if self._selection_rect != rect:
         self._selection_rect = QRectF(rect)
         self._item.setRect(self._selection_rect)
Пример #9
0
 def _reset(self):
     self.setSelectionRect(QRectF())
     self._item.setVisible(False)
     self._mouse_dragging = False
Пример #10
0
 def basic_scene():
     scene = QGraphicsScene()
     scene.addRect(QRectF(0, 0, 100, 100))
     return scene
Пример #11
0
 def rect(self):
     return QRectF(self.pos(), QSizeF(*self.size()))
Пример #12
0
 def boundingRect(self):
     return QRectF(0, 0, self.width, self.height)
Пример #13
0
 def clear_scene(self):
     self.scene.clear()
     self.scene.setSceneRect(QRectF())
Пример #14
0
 def boundingRect(self):
     return self._rect if getattr(self, "_rect", QRectF()).isValid() \
         else super().boundingRect()
Пример #15
0
 def boundingRect(self):
     return QRectF()
Пример #16
0
    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
Пример #17
0
 def set_view_box_range(self):
     self.view_box.setRange(QRectF(-1.05, -1.05, 2.1, 2.1))
 def clear_scene(self):
     self.scene.clear()
     self.scene.setSceneRect(QRectF())
     self.view.setSceneRect(QRectF())
     self._stripe_plot = None
 def adjustLeft(rect):
     rect = QRectF(rect)
     rect.setLeft(geom.left())
     return rect
Пример #20
0
    def update_data(self, attr_x, attr_y, reset_view=True):
        self.master.Warning.missing_coords.clear()
        self.master.Information.missing_coords.clear()
        self._clear_plot_widget()

        if self.shown_y != attr_y:
            # 'reset' the axis text width estimation. Without this the left
            # axis tick labels space only ever expands
            yaxis = self.plot_widget.getAxis("left")
            yaxis.textWidth = 30

        self.shown_x, self.shown_y = attr_x, attr_y
        if attr_x not in self.data.domain or attr_y not in self.data.domain:
            data = self.sparse_to_dense()
            self.set_data(data)

        if self.jittered_data is None or not len(self.jittered_data):
            self.valid_data = None
        else:
            self.valid_data = self.get_valid_list([attr_x, attr_y])
            if not np.any(self.valid_data):
                self.valid_data = None
        if self.valid_data is None:
            self.selection = None
            self.n_points = 0
            self.master.Warning.missing_coords(self.shown_x.name,
                                               self.shown_y.name)
            return

        x_data, y_data = self.get_xy_data_positions(attr_x, attr_y,
                                                    self.valid_data)
        self.n_points = len(x_data)

        if reset_view:
            min_x, max_x = np.nanmin(x_data), np.nanmax(x_data)
            min_y, max_y = np.nanmin(y_data), np.nanmax(y_data)
            self.view_box.setRange(QRectF(min_x, min_y, max_x - min_x,
                                          max_y - min_y),
                                   padding=0.025)
            self.view_box.init_history()
            self.view_box.tag_history()
        [min_x, max_x], [min_y, max_y] = self.view_box.viewRange()

        for axis, var in (("bottom", attr_x), ("left", attr_y)):
            self.set_axis_title(axis, var)
            if var.is_discrete:
                self.set_labels(axis, get_variable_values_sorted(var))
            else:
                self.set_labels(axis, None)

        color_data, brush_data = self.compute_colors()
        color_data_sel, brush_data_sel = self.compute_colors_sel()
        size_data = self.compute_sizes()
        shape_data = self.compute_symbols()

        if self.should_draw_density():
            rgb_data = [pen.color().getRgb()[:3] for pen in color_data]
            self.density_img = classdensity.class_density_image(
                min_x, max_x, min_y, max_y, self.resolution, x_data, y_data,
                rgb_data)
            self.plot_widget.addItem(self.density_img)

        self.data_indices = np.flatnonzero(self.valid_data)
        if len(self.data_indices) != len(self.data):
            self.master.Information.missing_coords(self.shown_x.name,
                                                   self.shown_y.name)

        self.scatterplot_item = ScatterPlotItem(x=x_data,
                                                y=y_data,
                                                data=self.data_indices,
                                                symbol=shape_data,
                                                size=size_data,
                                                pen=color_data,
                                                brush=brush_data)
        self.scatterplot_item_sel = ScatterPlotItem(x=x_data,
                                                    y=y_data,
                                                    data=self.data_indices,
                                                    symbol=shape_data,
                                                    size=size_data +
                                                    SELECTION_WIDTH,
                                                    pen=color_data_sel,
                                                    brush=brush_data_sel)
        self.plot_widget.addItem(self.scatterplot_item_sel)
        self.plot_widget.addItem(self.scatterplot_item)

        self.scatterplot_item.selected_points = []
        self.scatterplot_item.sigClicked.connect(self.select_by_click)
        if self.show_reg_line:
            _x_data = self.data.get_column_view(self.shown_x)[0]
            _y_data = self.data.get_column_view(self.shown_y)[0]
            _x_data = _x_data[self.valid_data]
            _y_data = _y_data[self.valid_data]
            assert _x_data.size
            assert _y_data.size
            self.draw_regression_line(_x_data, _y_data, np.min(_x_data),
                                      np.max(_y_data))

        self.update_labels()
        self.make_legend()
        self.plot_widget.replot()
Пример #21
0
 def _select_data(self):
     rect = QRectF(QPointF(-20, -20), QPointF(20, 20))
     self.widget.graph.select_by_rectangle(rect)
     return self.widget.graph.get_selection()
Пример #22
0
    def update_scene(self):
        self.clear_scene()
        if self.domain is None or not len(self.points[0]):
            return

        n_attrs = self.n_attributes if self.display_index else int(1e10)
        attr_inds, attributes = zip(*self.get_ordered_attributes()[:n_attrs])

        name_items = [QGraphicsTextItem(attr.name) for attr in attributes]
        point_text = QGraphicsTextItem("Points")
        probs_text = QGraphicsTextItem("Probabilities (%)")
        all_items = name_items + [point_text, probs_text]
        name_offset = -max(t.boundingRect().width() for t in all_items) - 10
        w = self.view.viewport().rect().width()
        max_width = w + name_offset - 30

        points = [self.points[i][self.target_class_index] for i in attr_inds]
        if self.align == OWNomogram.ALIGN_LEFT:
            points = [p - p.min() for p in points]
        max_ = np.nan_to_num(max(max(abs(p)) for p in points))
        d = 100 / max_ if max_ else 1
        minimums = [p[self.target_class_index].min() for p in self.points]
        if self.scale == OWNomogram.POINT_SCALE:
            points = [p * d for p in points]

            if self.align == OWNomogram.ALIGN_LEFT:
                self.scale_marker_values = lambda x: (x - minimums) * d
            else:
                self.scale_marker_values = lambda x: x * d
        else:
            if self.align == OWNomogram.ALIGN_LEFT:
                self.scale_marker_values = lambda x: x - minimums
            else:
                self.scale_marker_values = lambda x: x

        point_item, nomogram_head = self.create_main_nomogram(
            attributes, attr_inds, name_items, points, max_width, point_text,
            name_offset)
        probs_item, nomogram_foot = self.create_footer_nomogram(
            probs_text, d, minimums, max_width, name_offset)
        for item in self.feature_items.values():
            item.dot.point_dot = point_item.dot
            item.dot.probs_dot = probs_item.dot
            item.dot.vertical_line = self.hidden_vertical_line

        self.nomogram = nomogram = NomogramItem()
        nomogram.add_items([nomogram_head, self.nomogram_main, nomogram_foot])
        self.scene.addItem(nomogram)

        self.set_feature_marker_values()

        rect = QRectF(self.scene.itemsBoundingRect().x(),
                      self.scene.itemsBoundingRect().y(),
                      self.scene.itemsBoundingRect().width(),
                      self.nomogram.preferredSize().height()).adjusted(
                          10, 0, 20, 0)
        self.scene.setSceneRect(rect)

        # Clip top and bottom (60 and 150) parts from the main view
        self.view.setSceneRect(rect.x(),
                               rect.y() + 80,
                               rect.width() - 10,
                               rect.height() - 160)
        self.view.viewport().setMaximumHeight(rect.height() - 160)
        # Clip main part from top/bottom views
        # below point values are imprecise (less/more than required) but this
        # is not a problem due to clipped scene content still being drawn
        self.top_view.setSceneRect(rect.x(),
                                   rect.y() + 3,
                                   rect.width() - 10, 20)
        self.bottom_view.setSceneRect(rect.x(),
                                      rect.height() - 110,
                                      rect.width() - 10, 30)
Пример #23
0
    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()
Пример #24
0
    def paint(self, p, opt, widget):
        def get_arrows():
            # Compute (n, 4) array of coordinates of arrows' ends
            # Arrows are at 15 degrees; length is 10, clipped to edge length
            x0, y0, x1, y1 = edge_coords.T
            arr_len = np.clip(lengths - sizes1 - w3, 0, 10)
            cos12 = arr_len * np.cos(np.pi / 12)
            sin12 = arr_len * np.sin(np.pi / 12)

            # cos(a ± 15) = cos(a) cos(15) ∓ sin(a) sin(15)
            tx = sins * (fx * sin12)
            x1a = x1 - coss * (fx * cos12)
            x2a = x1a - tx
            x1a += tx

            # sin(a ± 15) = sin(a) cos(15) ± sin(15) cos(a)
            ty = (fy * sin12) * coss
            y1a = y1 + sins * (fy * cos12)
            y2a = y1a - ty
            y1a += ty
            return np.vstack((x1a, y1a, x2a, y2a)).T

        def get_short_edge_coords():
            # Compute the target-side coordinates of edges with arrows
            # Such edges are shorted by 8 pixels + width / 3
            off = 8 + w3
            return edge_coords[:, 2:] + (off * np.vstack((-fxcos, fysin))).T

        if self.xData is None or len(self.xData) == 0:
            return

        # Widths of edges, divided by 3; used for adjusting sizes
        w3 = (self.widths if self.widths is not None else self.pen.width()) / 3

        # Sizes of source and target nodes; they are used for adjusting the
        # edge lengths, so we increase the sizes by edge widths / 3
        sizes0, sizes1 = self.sizes[::2] + w3, self.sizes[1::2] + w3

        # Coordinates of vertices for all end points (in real world)
        x0s, x1s = self.xData[::2], self.xData[1::2]
        y0s, y1s = self.yData[::2], self.yData[1::2]

        # Factors for transforming real-worlds coordinates into pixels
        fx = 1 / p.worldTransform().m11()
        fy = 1 / p.worldTransform().m22()

        # Computations of angles (lengths are also used to clip the arrows)
        # We need sine and cosine of angles, and never the actual angles.
        # Sine and cosine are compute as ratios in triangles rather than with
        # trigonometric functions
        diffx, diffy = (x1s - x0s) / fx, -(y1s - y0s) / fy
        lengths = np.sqrt(diffx**2 + diffy**2)
        arcs = lengths == 0
        coss, sins = np.nan_to_num(diffx / lengths), np.nan_to_num(diffy /
                                                                   lengths)

        # A slower version of the above, with trigonometry
        #  angles = np.arctan2(-(y1s - y0s) / fy, (x1s - x0s) / fx)
        #  return np.cos(angles), np.sin(angles)

        # Sin and cos are mostly used as mulitplied with fx and fy; precompute
        fxcos, fysin = fx * coss, fy * sins

        # Coordinates of edges' end points: coordinates of vertices, adjusted
        # by sizes. When drawing arraws, the target coordinate is used for
        # the tip of the arrow, not the edge
        edge_coords = np.vstack((x0s + fxcos * sizes0, y0s - fysin * sizes0,
                                 x1s - fxcos * sizes1, y1s + fysin * sizes1)).T

        pen = QPen(self.pen)
        p.setRenderHint(p.Antialiasing, True)
        p.setCompositionMode(p.CompositionMode_SourceOver)
        if self.widths is None:
            p.setPen(pen)
            if self.directed:
                for (x0, y0, x1,
                     y1), (x1w,
                           y1w), (xa1, ya1, xa2,
                                  ya2), arc in zip(edge_coords,
                                                   get_short_edge_coords(),
                                                   get_arrows(), arcs):
                    if not arc:
                        p.drawLine(QLineF(x0, y0, x1w, y1w))
                        p.drawLine(QLineF(xa1, ya1, x1, y1))
                        p.drawLine(QLineF(xa2, ya2, x1, y1))
            else:
                for ecoords in edge_coords[~arcs]:
                    p.drawLine(QLineF(*ecoords))
        else:
            if self.directed:
                for (x0, y0, x1,
                     y1), (x1w,
                           y1w), (xa1, ya1, xa2,
                                  ya2), w, arc in zip(edge_coords,
                                                      get_short_edge_coords(),
                                                      get_arrows(),
                                                      self.widths, arcs):
                    if not arc:
                        pen.setWidth(w)
                        p.setPen(pen)
                        p.drawLine(QLineF(x0, y0, x1w, y1w))
                        p.drawLine(QLineF(xa1, ya1, x1, y1))
                        p.drawLine(QLineF(xa2, ya2, x1, y1))
            else:
                for ecoords, w in zip(edge_coords[~arcs], self.widths[~arcs]):
                    pen.setWidth(w)
                    p.setPen(pen)
                    p.drawLine(QLineF(*ecoords))

        # This part is not so optimized because there can't be that many loops
        if np.any(arcs):
            xs, ys = self.xData[::2][arcs], self.yData[1::2][arcs]
            sizes = self.sizes[::2][arcs]
            sizes += w3 if isinstance(w3, float) else w3[arcs]
            # if radius of loop would be size, then distance betwween
            # vertex and loop centers would be
            # d = np.sqrt(size ** 2 - r ** 2 / 2) + r / np.sqrt(2) + r / 2
            ds = sizes * (1 + np.sqrt(2) / 4)
            rxs = xs - ds * fx
            rys = ys - ds * fy
            rfxs = sizes * fx
            rfys = sizes * fy

            ax0o = 6 * np.cos(np.pi * 5 / 6) * fx
            ax1o = 6 * np.cos(np.pi * 7 / 12) * fx
            ay0o = 6 * np.sin(np.pi * 5 / 6) * fy
            ay1o = 6 * np.sin(np.pi * 7 / 12) * fy

            if self.widths is None:
                widths = np.full(len(rxs), pen.width())
            else:
                widths = self.widths[arcs]
            for rx, ry, rfx, rfy, w in zip(rxs, rys, rfxs, rfys, widths):
                rect = QRectF(rx, ry, rfx, rfy)
                pen.setWidth(w)
                p.setPen(pen)
                p.drawArc(rect, 100 * 16, 250 * 16)
                if self.directed:
                    rx += 1.1 * rfx
                    ry += rfy / 2
                    p.drawLine(QLineF(rx, ry, rx + ax0o, ry - ay0o))
                    p.drawLine(QLineF(rx, ry, rx + ax1o, ry - ay1o))
Пример #25
0
 def update_circle(self):
     if self.scatterplot_item is not None and not self.circle_item:
         self.circle_item = QGraphicsEllipseItem()
         self.circle_item.setRect(QRectF(-1, -1, 2, 2))
         self.circle_item.setPen(pg.mkPen(QColor(0, 0, 0), width=2))
         self.plot_widget.addItem(self.circle_item)
Пример #26
0
 def get_mapped_rect():
     p1, p2 = ev.buttonDownPos(ev.button()), ev.pos()
     p1 = self.mapToView(p1)
     p2 = self.mapToView(p2)
     return QRectF(p1, p2)
Пример #27
0
 def extend_horizontal(rect):
     # type: (QRectF) -> QRectF
     rect = QRectF(rect)
     rect.setLeft(geom.left())
     rect.setRight(geom.right())
     return rect
Пример #28
0
 def boundingRect(self):
     return QRectF(0, 0,
                   25 + self.text_width + self.bin_height,
                   20 + self.scale.bins * self.bin_height)
Пример #29
0
 def boundingRect(self):
     # type: () -> QRectF
     return QRectF()
Пример #30
0
 def set_rect(self, rect):
     self.prepareGeometryChange()
     rect = QRectF() if rect is None else rect
     self._rect = rect
     self.update_contents()
     self.update()