def plotContourFills(self, painter, posn, axes, clip): """Plot the traced contours on the painter.""" s = self.settings # don't draw if there are no cached polygons if self._cachedpolygons is None or s.Fills.hide: return # iterate over each level, and list of lines for num, polylist in enumerate(self._cachedpolygons): # iterate over each complete line of the contour path = qt4.QPainterPath() for poly in polylist: # convert coordinates from graph to plotter xplt = axes[0].dataToPlotterCoords(posn, poly[:,0]) yplt = axes[1].dataToPlotterCoords(posn, poly[:,1]) pts = qt4.QPolygonF() utils.addNumpyToPolygonF(pts, xplt, yplt) clippedpoly = qt4.QPolygonF() utils.polygonClip(pts, clip, clippedpoly) path.addPolygon(clippedpoly) # fill polygons brush = s.Fills.get('fills').returnBrushExtended(num) utils.brushExtFillPath(painter, brush, path)
def _drawBezierLine( self, painter, xvals, yvals, posn, xdata, ydata): """Handle bezier lines and fills.""" pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata) if len(pts) < 2: return path = self._getBezierLine(pts) s = self.settings # See note in addSettings about names of FillAbove and FillBelow for fill in (s.FillBelow, s.FillAbove): if not fill.hide: temppath = qt4.QPainterPath(path) temppath.lineTo({ 'bottom': qt4.QPointF(pts[-1].x(), posn[3]), 'top': qt4.QPointF(pts[-1].x(), posn[1]), 'left': qt4.QPointF(posn[0], pts[-1].y()), 'right': qt4.QPointF(posn[2], pts[-1].y()), }[fill.edge]) temppath.lineTo({ 'bottom': qt4.QPointF(pts[0].x(), posn[3]), 'top': qt4.QPointF(pts[0].x(), posn[1]), 'left': qt4.QPointF(posn[0], pts[0].y()), 'right': qt4.QPointF(posn[2], pts[0].y()), }[fill.edge]) utils.brushExtFillPath(painter, fill, temppath) if not s.PlotLine.hide: painter.strokePath(path, s.PlotLine.makeQPen(painter))
def draw(self, parentposn, painthelper, outerbounds=None): '''Update the margins before drawing.''' s = self.settings margins = (s.get('leftMargin').convert(painthelper), s.get('topMargin').convert(painthelper), s.get('rightMargin').convert(painthelper), s.get('bottomMargin').convert(painthelper)) bounds = self.computeBounds(parentposn, painthelper, margins=margins) maxbounds = self.computeBounds(parentposn, painthelper) # controls for adjusting graph margins painter = painthelper.painter(self, bounds) painthelper.setControlGraph(self, [ controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper) ]) # do no painting if hidden if s.hide: return bounds # set graph rectangle attributes path = qt4.QPainterPath() path.addRect( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]))) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter)) # do normal drawing of children # iterate over children in reverse order for c in reversed(self.children): c.draw(bounds, painthelper, outerbounds=outerbounds) # now need to find axes which aren't children, and draw those again axestodraw = set() childrennames = set() for c in self.children: childrennames.add(c.name) try: for axis in c.getAxesNames(): axestodraw.add(axis) except AttributeError: pass axestodraw = axestodraw - childrennames if axestodraw: # now redraw all these axes if they aren't children of us axeswidgets = self.getAxes(axestodraw) for w in axeswidgets: if w is not None: w.draw(bounds, painthelper, outerbounds=outerbounds) return bounds
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)
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)
def drawShape(self, painter, rect): s = self.settings path = qt4.QPainterPath() if s.rounding == 0: path.addRect(rect) else: path.addRoundedRect(rect, s.rounding, s.rounding) utils.brushExtFillPath(painter, s.Fill, path, stroke=painter.pen())
def draw(self, parentposn, painthelper, outerbounds = None): '''Update the margins before drawing.''' s = self.settings margins = ( s.get('leftMargin').convert(painthelper), s.get('topMargin').convert(painthelper), s.get('rightMargin').convert(painthelper), s.get('bottomMargin').convert(painthelper) ) bounds = self.computeBounds(parentposn, painthelper, margins=margins) maxbounds = self.computeBounds(parentposn, painthelper) # controls for adjusting graph margins painter = painthelper.painter(self, bounds) painthelper.setControlGraph(self, [ controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper) ]) # do no painting if hidden if s.hide: return bounds # set graph rectangle attributes path = qt4.QPainterPath() path.addRect( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3])) ) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter)) # do normal drawing of children # iterate over children in reverse order for c in reversed(self.children): c.draw(bounds, painthelper, outerbounds=outerbounds) # now need to find axes which aren't children, and draw those again axestodraw = set() childrennames = set() for c in self.children: childrennames.add(c.name) try: for axis in c.getAxesNames(): axestodraw.add(axis) except AttributeError: pass axestodraw = axestodraw - childrennames if axestodraw: # now redraw all these axes if they aren't children of us axeswidgets = self.getAxes(axestodraw) for w in axeswidgets: if w is not None: w.draw(bounds, painthelper, outerbounds=outerbounds) return bounds
def _errorBarsDiamondFilled(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw diamond filled region inside error bars.""" if None not in (xmin, xmax, ymin, ymax): if not s.FillBelow.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymin, xmax, yplotter) utils.brushExtFillPath(painter, s.FillBelow, path, ignorehide=True) if not s.FillAbove.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax, xmax, yplotter) utils.brushExtFillPath(painter, s.FillAbove, path, ignorehide=True)
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)
def plotBars(self, painter, s, dsnum, clip, corners): """Plot a set of boxes.""" # get style brush = s.BarFill.get('fills').returnBrushExtended(dsnum) pen = s.BarLine.get('lines').makePen(painter, dsnum) lw = pen.widthF() * 2 # make clip box bigger to avoid lines showing extclip = qt4.QRectF(qt4.QPointF(clip.left()-lw, clip.top()-lw), qt4.QPointF(clip.right()+lw, clip.bottom()+lw)) # plot bars path = qt4.QPainterPath() utils.addNumpyPolygonToPath( path, extclip, corners[0], corners[1], corners[2], corners[1], corners[2], corners[3], corners[0], corners[3]) utils.brushExtFillPath(painter, brush, path, stroke=pen)
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)
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)
def drawGraph(self, painter, bounds, datarange, outerbounds=None): '''Plot graph area and axes.''' s = self.settings if s.maxradius == 'Auto': self._maxradius = datarange[1] else: self._maxradius = s.maxradius self._xscale = (bounds[2]-bounds[0])*0.5 self._yscale = (bounds[3]-bounds[1])*0.5 self._xc = 0.5*(bounds[0]+bounds[2]) self._yc = 0.5*(bounds[3]+bounds[1]) path = qt4.QPainterPath() path.addEllipse( qt4.QRectF( qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]) ) ) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter))
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 # trimming can lead to too few points if len(pxpts) < 2 or len(pypts) < 2: return 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)
def plotBars(self, painter, s, dsnum, clip, corners): """Plot a set of boxes.""" # get style brush = s.BarFill.get('fills').returnBrushExtended(dsnum) pen = s.BarLine.get('lines').makePen(painter, dsnum) lw = pen.widthF() * 2 # make clip box bigger to avoid lines showing extclip = qt4.QRectF( qt4.QPointF(clip.left() - lw, clip.top() - lw), qt4.QPointF(clip.right() + lw, clip.bottom() + lw)) # plot bars path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, extclip, corners[0], corners[1], corners[2], corners[1], corners[2], corners[3], corners[0], corners[3]) utils.brushExtFillPath(painter, brush, path, stroke=pen)
def drawGraph(self, painter, bounds, datarange, outerbounds=None): '''Plot graph area and axes.''' s = self.settings if datarange is None: datarange = [0., 1., 0., 1.] if s.maxradius == 'Auto': self._maxradius = datarange[1] else: self._maxradius = s.maxradius if s.minradius == 'Auto': if s.log: if datarange[0] > 0.: self._minradius = datarange[0] else: self._minradius = self._maxradius / 100. else: self._minradius = 0. else: self._minradius = s.minradius # stop negative values if s.log: self._minradius = N.clip(self._minradius, 1e-99, 1e99) self._maxradius = N.clip(self._maxradius, 1e-99, 1e99) if self._minradius == self._maxradius: self._maxradius = self._minradius + 1 self._xscale = (bounds[2]-bounds[0])*0.5 self._yscale = (bounds[3]-bounds[1])*0.5 self._xc = 0.5*(bounds[0]+bounds[2]) self._yc = 0.5*(bounds[3]+bounds[1]) path = qt4.QPainterPath() path.addEllipse( qt4.QRectF( qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]) ) ) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter))
def drawGraph(self, painter, bounds, datarange, outerbounds=None): '''Plot graph area and axes.''' s = self.settings if s.maxradius == 'Auto': self._maxradius = datarange[1] else: self._maxradius = s.maxradius self._xscale = (bounds[2] - bounds[0]) * 0.5 self._yscale = (bounds[3] - bounds[1]) * 0.5 self._xc = 0.5 * (bounds[0] + bounds[2]) self._yc = 0.5 * (bounds[3] + bounds[1]) path = qt4.QPainterPath() path.addEllipse( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]))) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter))
def _errorBarsBoxFilled(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw box filled region inside error bars.""" print "_errorBarsBoxFilled" print xplotter print yplotter if None not in (xmin, xmax, ymin, ymax): # filled region below if not s.FillBelow.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, ymin, xmin, yplotter, xmax, yplotter, xmax, ymin) utils.brushExtFillPath(painter, s.FillBelow, path, ignorehide=True) # filled region above if not s.FillAbove.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xmax, yplotter, xmax, ymax, xmin, ymax) utils.brushExtFillPath(painter, s.FillAbove, path, ignorehide=True)
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)
def _drawBezierLine(self, painter, xvals, yvals, posn, xdata, ydata): """Handle bezier lines and fills.""" pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata) if len(pts) < 2: return path = self._getBezierLine(pts) s = self.settings if not s.FillBelow.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[3]) temppath.lineTo(pts[0].x(), posn[3]) utils.brushExtFillPath(painter, s.FillBelow, temppath) if not s.FillAbove.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[1]) temppath.lineTo(pts[0].x(), posn[1]) utils.brushExtFillPath(painter, s.FillAbove, temppath) if not s.PlotLine.hide: painter.strokePath(path, s.PlotLine.makeQPen(painter))
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)
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)
def _drawBezierLine( self, painter, xvals, yvals, posn, xdata, ydata): """Handle bezier lines and fills.""" pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata) if len(pts) < 2: return path = self._getBezierLine(pts) s = self.settings if not s.FillBelow.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[3]) temppath.lineTo(pts[0].x(), posn[3]) utils.brushExtFillPath(painter, s.FillBelow, temppath) if not s.FillAbove.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[1]) temppath.lineTo(pts[0].x(), posn[1]) utils.brushExtFillPath(painter, s.FillAbove, temppath) if not s.PlotLine.hide: painter.strokePath(path, s.PlotLine.makeQPen(painter))
def draw(self, parentposn, phelper, outerbounds = None): """Plot the key on a plotter.""" s = self.settings if s.hide: return painter = phelper.painter(self, parentposn) font = s.get('Text').makeQFont(painter) painter.setFont(font) height = utils.FontMetrics(font, painter.device()).height() margin = s.marginSize * height showtext = not s.Text.hide # maximum width of text required maxwidth = 1 # total number of layout lines required totallines = 0 # reserve space for the title titlewidth, titleheight = 0, 0 if s.title != '': titlefont = qt4.QFont(font) titlefont.setPointSize(max(font.pointSize() * 1.2, font.pointSize() + 2)) titlewidth, titleheight = utils.Renderer(painter, titlefont, 0, 0, s.title).getDimensions() titleheight += 0.5*margin maxwidth = titlewidth entries = [] # iterate over children and find widgets which are suitable for c in self.parent.children: try: num = c.getNumberKeys() except AttributeError: continue if not c.settings.hide: # add an entry for each key entry for each widget for i in xrange(num): lines = 1 if showtext: w, h = utils.Renderer(painter, font, 0, 0, c.getKeyText(i)).getDimensions() maxwidth = max(maxwidth, w) lines = max(1, math.ceil(float(h)/float(height))) totallines += lines entries.append( (c, i, lines) ) # layout the box layout, (numrows, numcols) = self._layout(entries, totallines) # total size of box symbolwidth = s.get('keyLength').convert(painter) totalwidth = ( (maxwidth + height + symbolwidth)*numcols + height*(numcols-1) ) totalheight = numrows * height + titleheight if not s.Border.hide: totalwidth += 2*margin totalheight += margin # work out horizontal position h = s.horzPosn if h == 'left': x = parentposn[0] + height elif h == 'right': x = parentposn[2] - height - totalwidth elif h == 'centre': x = ( parentposn[0] + 0.5*(parentposn[2] - parentposn[0] - totalwidth) ) elif h == 'manual': x = parentposn[0] + (parentposn[2]-parentposn[0])*s.horzManual # work out vertical position v = s.vertPosn if v == 'top': y = parentposn[1] + height elif v == 'bottom': y = parentposn[3] - totalheight - height elif v == 'centre': y = ( parentposn[1] + 0.5*(parentposn[3] - parentposn[1] - totalheight) ) elif v == 'manual': y = ( parentposn[3] - (parentposn[3]-parentposn[1])*s.vertManual - totalheight ) # for controlgraph boxposn = (x, y) boxdims = (totalwidth, totalheight) # draw surrounding box boxpath = qt4.QPainterPath() boxpath.addRect(qt4.QRectF(x, y, totalwidth, totalheight)) if not s.Background.hide: utils.brushExtFillPath(painter, s.Background, boxpath) if not s.Border.hide: painter.strokePath(boxpath, s.get('Border').makeQPen(painter) ) x += margin y += margin*0.5 # center and draw the title if s.title: xpos = x + 0.5*(totalwidth - (0 if s.Border.hide else 2*margin) - titlewidth) utils.Renderer(painter, titlefont, xpos, y, s.title, alignvert=1).render() y += titleheight textpen = s.get('Text').makeQPen() # plot dataset entries for (plotter, num, xp, yp, lines) in layout: xpos = x + xp*(maxwidth+2*height+symbolwidth) ypos = y + yp*height # plot key symbol painter.save() keyoffset = 0 if s.keyAlign == 'centre': keyoffset = (lines-1)*height/2.0 elif s.keyAlign == 'bottom': keyoffset = (lines-1)*height plotter.drawKeySymbol(num, painter, xpos, ypos+keyoffset, symbolwidth, height) painter.restore() # write key text if showtext: painter.setPen(textpen) utils.Renderer(painter, font, xpos + height + symbolwidth, ypos, plotter.getKeyText(num), -1, 1).render() phelper.setControlGraph( self, [ControlKey(self, parentposn, boxposn, boxdims, height)] )
def plotBox(self, painter, axes, boxposn, posn, width, clip, stats): """Draw box for dataset.""" if not N.isfinite(stats.median): # skip bad datapoints return s = self.settings horz = (s.direction == 'horizontal') # convert quartiles, top and bottom whiskers to plotter medplt, botplt, topplt, botwhisplt, topwhisplt = tuple( axes[not horz].dataToPlotterCoords( posn, N.array([ stats.median, stats.botquart, stats.topquart, stats.botwhisker, stats.topwhisker ]))) # draw whisker top to bottom p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn, topwhisplt, boxposn, botwhisplt, horz) # draw ends of whiskers endsize = width / 2 swapline(painter, boxposn - endsize / 2, topwhisplt, boxposn + endsize / 2, topwhisplt, horz) swapline(painter, boxposn - endsize / 2, botwhisplt, boxposn + endsize / 2, botwhisplt, horz) # draw box fill boxpath = qt4.QPainterPath() boxpath.addRect( swapbox(painter, boxposn - width / 2, botplt, boxposn + width / 2, topplt, horz)) utils.brushExtFillPath(painter, s.Fill, boxpath) # draw line across box p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn - width / 2, medplt, boxposn + width / 2, medplt, horz) # draw box painter.strokePath(boxpath, s.Border.makeQPenWHide(painter)) # draw outliers painter.setPen(s.MarkersLine.makeQPenWHide(painter)) painter.setBrush(s.MarkersFill.makeQBrushWHide()) markersize = s.get('markerSize').convert(painter) if stats.outliers.shape[0] != 0: pltvals = axes[not horz].dataToPlotterCoords(posn, stats.outliers) otherpos = N.zeros(pltvals.shape) + boxposn if horz: x, y = pltvals, otherpos else: x, y = otherpos, pltvals utils.plotMarkers(painter, x, y, s.outliersmarker, markersize, clip=clip) # draw mean meanplt = axes[not horz].dataToPlotterCoords(posn, N.array([stats.mean]))[0] if horz: x, y = meanplt, boxposn else: x, y = boxposn, meanplt utils.plotMarker(painter, x, y, s.meanmarker, markersize)
def drawShape(self, painter, rect): s = self.settings path = qt4.QPainterPath() path.addEllipse(rect) utils.brushExtFillPath(painter, s.Fill, path, stroke=painter.pen())
def draw(self, parentposn, painthelper, outerbounds = None): '''Update the margins before drawing.''' # yuck, avoid circular imports import axisbroken s = self.settings bounds = self.computeBounds(parentposn, painthelper) maxbounds = self.computeBounds(parentposn, painthelper, withmargin=False) # do no painting if hidden if s.hide: return bounds # controls for adjusting graph margins painter = painthelper.painter(self, bounds) painthelper.setControlGraph(self, [ controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper) ]) with painter: # set graph rectangle attributes path = qt4.QPainterPath() path.addRect( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3])) ) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter)) # child drawing algorithm is a bit complex due to axes # being shared between graphs and broken axes # this is a map of axis names to plot to axis widgets axestodraw = {} # axes widgets for each plotter (precalculated by Page) axesofwidget = painthelper.plotteraxismap for c in self.children: try: for a in axesofwidget[c]: axestodraw[a.name] = a except (KeyError, AttributeError): if hasattr(c, 'isaxis'): axestodraw[c.name] = c # grid lines are normally plotted before other child widgets axisdrawlist = sorted(axestodraw.items(), reverse=True) for aname, awidget in axisdrawlist: awidget.updateAxisLocation(bounds) awidget.computePlottedRange() awidget.drawGrid(bounds, painthelper, outerbounds=outerbounds, ontop=False) # broken axis handling brokenaxes = set() for name, axis in axestodraw.iteritems(): if isinstance(axis, axisbroken.AxisBroken): brokenaxes.add(axis) # do normal drawing of children # iterate over children in reverse order for c in reversed(self.children): if hasattr(c, 'isaxis'): continue axes = axesofwidget.get(c, None) if axes is not None and any((a in brokenaxes for a in axes)): # handle broken axes childbrokenaxes = sorted([ (a.name, a) for a in axes if a in brokenaxes ]) childbrokenaxes.sort() def iteratebrokenaxes(b): """Recursively iterate over each broken axis and redraw child for each. We might have more than one broken axis per child, so hence this rather strange iteration. """ ax = b[0][1] for i in xrange(ax.breakvnum): ax.switchBreak(i, bounds) if len(b) == 1: c.draw(bounds, painthelper, outerbounds=outerbounds) else: iteratebrokenaxes(b[1:]) ax.switchBreak(None, bounds) iteratebrokenaxes(childbrokenaxes) else: # standard non broken axis drawing c.draw(bounds, painthelper, outerbounds=outerbounds) # then for grid lines on top for aname, awidget in axisdrawlist: axis.drawGrid(bounds, painthelper, outerbounds=outerbounds, ontop=True) # draw axes on top of grid lines for aname, awidget in axisdrawlist: awidget.draw(bounds, painthelper, outerbounds=outerbounds) return bounds
def plotBox(self, painter, axes, boxposn, posn, width, clip, stats): """Draw box for dataset.""" s = self.settings horz = (s.direction == 'horizontal') # convert quartiles, top and bottom whiskers to plotter medplt, botplt, topplt, botwhisplt, topwhisplt = tuple( axes[not horz].dataToPlotterCoords( posn, N.array([ stats.median, stats.botquart, stats.topquart, stats.botwhisker, stats.topwhisker ])) ) # draw whisker top to bottom p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn, topwhisplt, boxposn, botwhisplt, horz) # draw ends of whiskers endsize = width/2 swapline(painter, boxposn-endsize/2, topwhisplt, boxposn+endsize/2, topwhisplt, horz) swapline(painter, boxposn-endsize/2, botwhisplt, boxposn+endsize/2, botwhisplt, horz) # draw box fill boxpath = qt4.QPainterPath() boxpath.addRect( swapbox(painter, boxposn-width/2, botplt, boxposn+width/2, topplt, horz) ) utils.brushExtFillPath(painter, s.Fill, boxpath) # draw line across box p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn-width/2, medplt, boxposn+width/2, medplt, horz) # draw box painter.strokePath(boxpath, s.Border.makeQPenWHide(painter) ) # draw outliers painter.setPen( s.MarkersLine.makeQPenWHide(painter) ) painter.setBrush( s.MarkersFill.makeQBrushWHide() ) markersize = s.get('markerSize').convert(painter) if stats.outliers.shape[0] != 0: pltvals = axes[not horz].dataToPlotterCoords(posn, stats.outliers) otherpos = N.zeros(pltvals.shape) + boxposn if horz: x, y = pltvals, otherpos else: x, y = otherpos, pltvals utils.plotMarkers( painter, x, y, s.outliersmarker, markersize, clip=clip ) # draw mean meanplt = axes[not horz].dataToPlotterCoords( posn, N.array([stats.mean]))[0] if horz: x, y = meanplt, boxposn else: x, y = boxposn, meanplt utils.plotMarker( painter, x, y, s.meanmarker, markersize )