Пример #1
0
    def _drawPlotLine(self, painter, xvals, yvals, posn, xdata, ydata,
                      cliprect):
        """Draw the line connecting the points."""

        pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata)
        if len(pts) < 2:
            return
        s = self.settings

        if not s.FillBelow.hide:
            # construct polygon to draw filled region
            polypts = qt4.QPolygonF([qt4.QPointF(pts[0].x(), posn[3])])
            polypts += pts
            polypts.append(qt4.QPointF(pts[len(pts) - 1].x(), posn[3]))

            utils.brushExtFillPolygon(painter, s.FillBelow, cliprect, polypts)

        if not s.FillAbove.hide:
            polypts = qt4.QPolygonF([qt4.QPointF(pts[0].x(), posn[1])])
            polypts += pts
            polypts.append(qt4.QPointF(pts[len(pts) - 1].x(), posn[1]))

            utils.brushExtFillPolygon(painter, s.FillAbove, cliprect, polypts)

        # draw line between points
        if not s.PlotLine.hide:
            painter.setPen(s.PlotLine.makeQPen(painter))
            utils.plotClippedPolyline(painter, cliprect, pts)
Пример #2
0
    def areaDrawStacked(self, painter, posns, maxwidth, dsvals, axes,
                        widgetposn, clip):
        """Draw a stacked area plot"""

        s = self.settings

        # get axis which values are plotted along
        ishorz = s.direction == 'horizontal'
        vaxis = axes[not ishorz]

        # compute stacked coordinates
        stackedvals, stackedcoords = self.calcStackedPoints(
            dsvals, vaxis, widgetposn)
        # coordinates of origin
        zerocoords = vaxis.dataToPlotterCoords(widgetposn,
                                               N.zeros(posns.shape))

        # draw areas (reverse order, so edges are plotted correctly)
        for dsnum, coords in izip(xrange(len(stackedcoords) - 1, -1, -1),
                                  stackedcoords[::-1]):

            # add points at end to make polygon
            p1 = N.hstack([[zerocoords[0]], coords, [zerocoords[-1]]])
            p2 = N.hstack([[posns[0]], posns, [posns[-1]]])

            # construct polygon on path, clipped
            poly = qt4.QPolygonF()
            if ishorz:
                utils.addNumpyToPolygonF(poly, p1, p2)
            else:
                utils.addNumpyToPolygonF(poly, p2, p1)
            clippoly = qt4.QPolygonF()
            utils.polygonClip(poly, clip, clippoly)
            path = qt4.QPainterPath()
            path.addPolygon(clippoly)
            path.closeSubpath()

            # actually draw polygon
            brush = s.BarFill.get('fills').returnBrushExtended(dsnum)
            utils.brushExtFillPath(painter, brush, path)

            # now draw lines
            poly = qt4.QPolygonF()
            if ishorz:
                utils.addNumpyToPolygonF(poly, coords, posns)
            else:
                utils.addNumpyToPolygonF(poly, posns, coords)

            pen = s.BarLine.get('lines').makePen(painter, dsnum)
            painter.setPen(pen)
            utils.plotClippedPolyline(painter, clip, poly)

        # draw error bars
        barwidth = maxwidth * s.barfill
        for barval, dsval in izip(stackedvals, dsvals):
            self.drawErrorBars(painter, posns, barwidth, barval, dsval, axes,
                               widgetposn)
Пример #3
0
    def _plotLine(self, painter, xpts, ypts, bounds, clip):
        """ Plot the points in xpts, ypts."""
        x1, y1, x2, y2 = bounds

        maxdeltax = (x2 - x1) * 3 / 4
        maxdeltay = (y2 - y1) * 3 / 4

        # idea is to collect points until we go out of the bounds
        # or reach the end, then plot them
        pts = qt4.QPolygonF()
        lastx = lasty = -65536
        for x, y in itertools.izip(xpts, ypts):

            # ignore point if it outside sensible bounds
            if x < -32767 or y < -32767 or x > 32767 or y > 32767:
                if len(pts) >= 2:
                    utils.plotClippedPolyline(painter, clip, pts)
                    pts.clear()
            else:
                # if the jump wasn't too large, add the point to the points
                if abs(x - lastx) < maxdeltax and abs(y - lasty) < maxdeltay:
                    pts.append(qt4.QPointF(x, y))
                else:
                    # draw what we have until now, and start a new line
                    if len(pts) >= 2:
                        utils.plotClippedPolyline(painter, clip, pts)
                    pts.clear()
                    pts.append(qt4.QPointF(x, y))

            lastx = x
            lasty = y

        # draw remaining points
        if len(pts) >= 2:
            utils.plotClippedPolyline(painter, clip, pts)
Пример #4
0
    def drawFillPts(self, painter, brushext, cliprect, ptsx, ptsy):
        '''Draw points for plotting a fill.'''
        pts = qt4.QPolygonF()
        utils.addNumpyToPolygonF(pts, ptsx, ptsy)

        filltype = brushext.filltype
        # this is broken: FIXME
        if filltype == 'left':
            dyend = ptsy[-1]-self._box[1]
            pts.append( qt4.QPointF(ptsx[-1]-dyend*tan30, self._box[1]) )
            dystart = ptsy[0]-self._box[1]
            pts.append( qt4.QPointF(ptsx[0]-dystart*tan30, self._box[1]) )
        elif filltype == 'right':
            pts.append( qt4.QPointF(self._box[2], ptsy[-1]) )
            pts.append( qt4.QPointF(self._box[2], ptsy[0]) )
        elif filltype == 'bottom':
            dyend = self._box[3]-ptsy[-1]
            pts.append( qt4.QPointF(ptsx[-1]-dyend*tan30, self._box[3]) )
            dystart = self._box[3]-ptsy[0]
            pts.append( qt4.QPointF(ptsx[0]-dystart*tan30, self._box[3]) )
        elif filltype == 'polygon':
            pass
        else:
            pts = None

        if pts is not None:
            utils.brushExtFillPolygon(painter, brushext, cliprect, pts)
Пример #5
0
def _errorBarsFilled(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                     painter, clip):
    """Draw filled region as error region."""

    ptsabove = qt4.QPolygonF()
    ptsbelow = qt4.QPolygonF()

    hidevert = True  # keep track of what's shown
    hidehorz = True
    if ('vert' in style and (ymin is not None and ymax is not None)
            and not s.ErrorBarLine.hideVert):
        hidevert = False
        # lines above/below points
        utils.addNumpyToPolygonF(ptsbelow, xplotter, ymin)
        utils.addNumpyToPolygonF(ptsabove, xplotter, ymax)

    elif ('horz' in style and (xmin is not None and xmax is not None)
          and not s.ErrorBarLine.hideHorz):
        hidehorz = False
        # lines left/right points
        utils.addNumpyToPolygonF(ptsbelow, xmin, yplotter)
        utils.addNumpyToPolygonF(ptsabove, xmax, yplotter)

    # draw filled regions above/left and below/right
    if 'fill' in style and not (hidehorz and hidevert):
        # construct points for error bar regions
        retnpts = qt4.QPolygonF()
        utils.addNumpyToPolygonF(retnpts, xplotter[::-1], yplotter[::-1])

        # polygons consist of lines joining the points and continuing
        # back along the plot line (retnpts)
        if not s.FillBelow.hideerror:
            utils.brushExtFillPolygon(painter,
                                      s.FillBelow,
                                      clip,
                                      ptsbelow + retnpts,
                                      ignorehide=True)
        if not s.FillAbove.hideerror:
            utils.brushExtFillPolygon(painter,
                                      s.FillAbove,
                                      clip,
                                      ptsabove + retnpts,
                                      ignorehide=True)

    # draw optional line (on top of fill)
    utils.plotClippedPolyline(painter, clip, ptsabove)
    utils.plotClippedPolyline(painter, clip, ptsbelow)
Пример #6
0
def brushExtFillPolygon(painter,
                        extbrush,
                        cliprect,
                        polygon,
                        ignorehide=False):
    """Fill a polygon with an extended brush."""
    clipped = qt4.QPolygonF()
    polygonClip(polygon, cliprect, clipped)
    path = qt4.QPainterPath()
    path.addPolygon(clipped)
    brushExtFillPath(painter, extbrush, path, ignorehide=ignorehide)
Пример #7
0
    def _fillRegion(self, painter, pxpts, pypts, bounds, belowleft, clip,
                    brush):
        """Fill the region above/below or left/right of the points.

        belowleft fills below if the variable is 'x', or left if 'y'
        otherwise it fills above/right."""

        # find starting and ending points for the filled region
        x1, y1, x2, y2 = bounds

        pts = qt4.QPolygonF()
        if self.settings.variable == 'x':
            if belowleft:
                pts.append(qt4.QPointF(pxpts[0], y2))
                endpt = qt4.QPointF(pxpts[-1], y2)
            else:
                pts.append(qt4.QPointF(pxpts[0], y1))
                endpt = qt4.QPointF(pxpts[-1], y1)
        else:
            if belowleft:
                pts.append(qt4.QPointF(x1, pypts[0]))
                endpt = qt4.QPointF(x1, pypts[-1])
            else:
                pts.append(qt4.QPointF(x2, pypts[0]))
                endpt = qt4.QPointF(x2, pypts[-1])

        # add the points between
        utils.addNumpyToPolygonF(pts, pxpts, pypts)

        # stick on the ending point
        pts.append(endpt)

        # draw the clipped polygon
        clipped = qt4.QPolygonF()
        utils.polygonClip(pts, clip, clipped)
        path = qt4.QPainterPath()
        path.addPolygon(clipped)
        utils.brushExtFillPath(painter, brush, path)
Пример #8
0
    def draw(self, posn, phelper, outerbounds=None):
        """Plot the data on a plotter."""

        s = self.settings

        # exit if hidden
        if s.hide:
            return

        # get points in plotter coordinates
        xp, yp = self._getPlotterCoords(posn)
        if xp is None or yp is None:
            # we can't calculate coordinates
            return

        x1, y1, x2, y2 = posn
        cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2))
        painter = phelper.painter(self, posn, clip=cliprect)

        pen = s.Line.makeQPenWHide(painter)
        pw = pen.widthF() * 2
        lineclip = qt4.QRectF(qt4.QPointF(x1 - pw, y1 - pw),
                              qt4.QPointF(x2 + pw, y2 + pw))

        # this is a hack as we generate temporary fake datasets
        path = qt4.QPainterPath()
        for xvals, yvals in document.generateValidDatasetParts(
                document.Dataset(xp), document.Dataset(yp)):

            poly = qt4.QPolygonF()
            utils.addNumpyToPolygonF(poly, xvals.data, yvals.data)
            clippedpoly = qt4.QPolygonF()
            utils.polygonClip(poly, lineclip, clippedpoly)
            path.addPolygon(clippedpoly)
            path.closeSubpath()

        utils.brushExtFillPath(painter, s.Fill, path, stroke=pen)
Пример #9
0
    def drawGraph(self, painter, bounds, datarange, outerbounds=None):
        '''Plot graph area and axes.'''

        s = self.settings

        xw, yw = bounds[2]-bounds[0], bounds[3]-bounds[1]

        d60 = 60./180.*math.pi
        ang = math.atan2(yw, xw/2.)
        if ang > d60:
            # taller than wider
            widthh = xw/2
            height = math.tan(d60) * widthh
        else:
            # wider than taller
            height = yw
            widthh = height / math.tan(d60)

        # box for equilateral triangle
        self._box = ( (bounds[2]+bounds[0])/2 - widthh,
                      (bounds[1]+bounds[3])/2 - height/2,
                      (bounds[2]+bounds[0])/2 + widthh,
                      (bounds[1]+bounds[3])/2 + height/2 )
        self._width = widthh*2
        self._height = height

        # triangle shaped polygon for graph
        self._tripoly = p = qt4.QPolygonF()
        p.append( qt4.QPointF(self._box[0], self._box[3]) )
        p.append( qt4.QPointF(self._box[0]+widthh, self._box[1]) )
        p.append( qt4.QPointF(self._box[2], self._box[3]) )

        path = qt4.QPainterPath()
        path.addPolygon(p)
        path.closeSubpath()
        utils.brushExtFillPath(painter, s.Background, path,
                               stroke=s.Border.makeQPenWHide(painter))

        # work out origins and size
        self._size = max(min(s.fracsize, 1.), 0.)

        # make sure we don't go past the ends of the allowed range
        # value of origin of left axis at top
        self._orgleft = min(s.originleft, 1.-self._size)
        # value of origin of bottom axis at left
        self._orgbot = min(s.originbottom, 1.-self._size)
        # origin of right axis at bottom
        self._orgright = 1. - self._orgleft - (self._orgbot + self._size)
Пример #10
0
    def getPreviewPixmap(self, ds):
        """Get a preview pixmap for a dataset."""
        size = (140, 70)
        if ds.dimensions != 1 or ds.datatype != "numeric":
            return None

        pixmap = qt4.QPixmap(*size)
        pixmap.fill(qt4.Qt.transparent)
        p = qt4.QPainter(pixmap)
        p.setRenderHint(qt4.QPainter.Antialiasing)

        # calculate data points
        try:
            if len(ds.data) < size[1]:
                y = ds.data
            else:
                intvl = len(ds.data) / size[1] + 1
                y = ds.data[::intvl]
            x = N.arange(len(y))

            # plot data points on image
            minval, maxval = N.nanmin(y), N.nanmax(y)
            y = (y - minval) / (maxval - minval) * size[1]
            finite = N.isfinite(y)
            x, y = x[finite], y[finite]
            x = x * (1. / len(x)) * size[0]

            poly = qt4.QPolygonF()
            utils.addNumpyToPolygonF(poly, x, size[1] - y)
            p.setPen(qt4.QPen(qt4.Qt.blue))
            p.drawPolyline(poly)

            # draw x axis if span 0
            p.setPen(qt4.QPen(qt4.Qt.black))
            if minval <= 0 and maxval > 0:
                y0 = size[1] - (0 - minval) / (maxval - minval) * size[1]
                p.drawLine(x[0], y0, x[-1], y0)
            else:
                p.drawLine(x[0], size[1], x[-1], size[1])
            p.drawLine(x[0], 0, x[0], size[1])

        except (ValueError, ZeroDivisionError):
            # zero sized array after filtering or min == max, so return None
            p.end()
            return None

        p.end()
        return pixmap
Пример #11
0
    def drawFillPts(self, painter, extfill, cliprect, ptsx, ptsy):
        '''Draw points for plotting a fill.'''
        pts = qt4.QPolygonF()
        utils.addNumpyToPolygonF(pts, ptsx, ptsy)

        filltype = extfill.filltype
        if filltype == 'center':
            pts.append(qt4.QPointF(self._xc, self._yc))
            utils.brushExtFillPolygon(painter, extfill, cliprect, pts)
        elif filltype == 'outside':
            pp = qt4.QPainterPath()
            pp.moveTo(self._xc, self._yc)
            pp.arcTo(cliprect, 0, 360)
            pp.addPolygon(pts)
            utils.brushExtFillPath(painter, extfill, pp)
        elif filltype == 'polygon':
            utils.brushExtFillPolygon(painter, extfill, cliprect, pts)
Пример #12
0
    def _getLinePoints(self, xvals, yvals, posn, xdata, ydata):
        """Get the points corresponding to the line connecting the points."""

        pts = qt4.QPolygonF()

        s = self.settings
        steps = s.PlotLine.steps

        # simple continuous line
        if steps == 'off':
            utils.addNumpyToPolygonF(pts, xvals, yvals)

        # stepped line, with points on left
        elif steps[:4] == 'left':
            x1 = xvals[:-1]
            x2 = xvals[1:]
            y1 = yvals[:-1]
            y2 = yvals[1:]
            utils.addNumpyToPolygonF(pts, x1, y1, x2, y1, x2, y2)

        # stepped line, with points on right
        elif steps[:5] == 'right':
            x1 = xvals[:-1]
            x2 = xvals[1:]
            y1 = yvals[:-1]
            y2 = yvals[1:]
            utils.addNumpyToPolygonF(pts, x1, y1, x1, y2, x2, y2)

        # stepped line, with points in centre
        # this is complex as we can't use the mean of the plotter coords,
        #  as the axis could be log
        elif steps[:6] == 'centre':
            axes = self.parent.getAxes((s.xAxis, s.yAxis))

            if xdata.hasErrors():
                # Special case if error bars on x points:
                # here we use the error bars to define the steps
                xmin, xmax = xdata.getPointRanges()

                # this is duplicated from drawing error bars: bad
                # convert xmin and xmax to graph coordinates
                xmin = axes[0].dataToPlotterCoords(posn, xmin)
                xmax = axes[0].dataToPlotterCoords(posn, xmax)
                utils.addNumpyToPolygonF(pts, xmin, yvals, xmax, yvals)

            else:
                # we put the bin edges half way between the points
                # we assume this is the correct thing to do even in log space
                x1 = xvals[:-1]
                x2 = xvals[1:]
                y1 = yvals[:-1]
                y2 = yvals[1:]
                xc = 0.5 * (x1 + x2)
                utils.addNumpyToPolygonF(pts, x1, y1, xc, y1, xc, y2)

                if len(xvals) > 0:
                    pts.append(qt4.QPointF(xvals[-1], yvals[-1]))

        else:
            assert False

        return pts
Пример #13
0
        try:
            self.checker.check(s.function, s.variable)
        except RuntimeError, e:
            self.logEvalError(e)
            return

        x1, y1, x2, y2 = posn
        cliprect = qt4.QRectF( qt4.QPointF(x1, y1), qt4.QPointF(x2, y2) )
        painter = phelper.painter(self, posn)
        self.parent.setClip(painter, posn)

        apts, bpts = self.getFunctionPoints()
        px, py = self.parent.graphToPlotCoords(apts, bpts)

        # plot line
        painter.setBrush(qt4.QBrush())
        painter.setPen( s.PlotLine.makeQPenWHide(painter) )
        for x, y in utils.validLinePoints(px, py):
            if not s.Fill1.hide:
                self.parent.drawFillPts(painter, s.Fill1, cliprect, x, y)
            if not s.Fill2.hide:
                self.parent.drawFillPts(painter, s.Fill2, cliprect, x, y)
            if not s.PlotLine.hide:
                p = qt4.QPolygonF()
                utils.addNumpyToPolygonF(p, x, y)
                painter.setBrush(qt4.QBrush())
                painter.setPen( s.PlotLine.makeQPen(painter) )
                utils.plotClippedPolyline(painter, cliprect, p)

document.thefactory.register( NonOrthFunction )