Example #1
0
 def swaplines(self, painter, a1, b1, a2, b2):
     """Multiline version of swapline where a1, b1, a2, b2 are arrays."""
     if self.settings.direction == 'horizontal':
         a = (a1, b1, a2, b2)
     else:
         a = (b1, a1, b2, a2)
     utils.plotLinesToPainter(painter, a[0], a[1], a[2], a[3])
Example #2
0
def _errorBarsBar(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip):
    """Draw bar style error lines."""
    # vertical error bars
    if ymin is not None and ymax is not None and not s.ErrorBarLine.hideVert:
        utils.plotLinesToPainter(painter, xplotter, ymin, xplotter, ymax, clip)

    # horizontal error bars
    if xmin is not None and xmax is not None and not s.ErrorBarLine.hideHorz:
        utils.plotLinesToPainter(painter, xmin, yplotter, xmax, yplotter, clip)
Example #3
0
def _errorBarsBar(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                  painter, clip):
    """Draw bar style error lines."""
    # vertical error bars
    if ymin is not None and ymax is not None and not s.ErrorBarLine.hideVert:
        utils.plotLinesToPainter(painter, xplotter, ymin, xplotter, ymax, clip)

    # horizontal error bars
    if xmin is not None and xmax is not None and not s.ErrorBarLine.hideHorz:
        utils.plotLinesToPainter(painter, xmin, yplotter, xmax, yplotter, clip)
Example #4
0
def _errorBarsEnds(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip):
    """Draw perpendiclar ends on error bars."""
    size = s.get("markerSize").convert(painter) * s.ErrorBarLine.endsize

    if ymin is not None and ymax is not None and not s.ErrorBarLine.hideVert:
        utils.plotLinesToPainter(painter, xplotter - size, ymin, xplotter + size, ymin, clip)
        utils.plotLinesToPainter(painter, xplotter - size, ymax, xplotter + size, ymax, clip)

    if xmin is not None and xmax is not None and not s.ErrorBarLine.hideHorz:
        utils.plotLinesToPainter(painter, xmin, yplotter - size, xmin, yplotter + size, clip)
        utils.plotLinesToPainter(painter, xmax, yplotter - size, xmax, yplotter + size, clip)
Example #5
0
def _errorBarsEnds(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s,
                   painter, clip):
    """Draw perpendiclar ends on error bars."""
    size = (s.get('markerSize').convert(painter) * s.ErrorBarLine.endsize)

    if ymin is not None and ymax is not None and not s.ErrorBarLine.hideVert:
        utils.plotLinesToPainter(painter, xplotter - size, ymin,
                                 xplotter + size, ymin, clip)
        utils.plotLinesToPainter(painter, xplotter - size, ymax,
                                 xplotter + size, ymax, clip)

    if xmin is not None and xmax is not None and not s.ErrorBarLine.hideHorz:
        utils.plotLinesToPainter(painter, xmin, yplotter - size, xmin,
                                 yplotter + size, clip)
        utils.plotLinesToPainter(painter, xmax, yplotter - size, xmax,
                                 yplotter + size, clip)
Example #6
0
    def dataDraw(self, painter, axes, posn, cliprect):
        """Draw the widget."""

        s = self.settings
        d = self.document

        # ignore non existing datasets
        try:
            data1 = d.data[s.data1]
            data2 = d.data[s.data2]
        except KeyError:
            return

        # require 2d datasets
        if data1.dimensions != 2 or data2.dimensions != 2:
            return

        # get base length (ensure > 0)
        baselength = max(s.get('baselength').convert(painter), 1e-6)

        # try to be nice if the datasets don't match
        data1st, data2nd = data1.data, data2.data
        xw = min(data1st.shape[1], data2nd.shape[1])
        yw = min(data1st.shape[0], data2nd.shape[0])

        # construct indices into datasets
        yvals, xvals = N.mgrid[0:yw, 0:xw]
        # convert using 1st dataset to axes values
        xdsvals, ydsvals = data1.indexToPoint(xvals.ravel(), yvals.ravel())

        # convert using axes to plotter values
        xplotter = axes[0].dataToPlotterCoords(posn, xdsvals)
        yplotter = axes[1].dataToPlotterCoords(posn, ydsvals)

        pen = s.Line.makeQPenWHide(painter)
        painter.setPen(pen)

        if s.mode == 'cartesian':
            dx = (data1st[:yw, :xw] * baselength).ravel()
            dy = (data2nd[:yw, :xw] * baselength).ravel()

        elif s.mode == 'polar':
            r = data1st[:yw, :xw].ravel() * baselength
            theta = data2nd[:yw, :xw].ravel()
            dx = r * N.cos(theta)
            dy = r * N.sin(theta)

        x1, x2 = xplotter-dx, xplotter+dx
        y1, y2 = yplotter+dy, yplotter-dy

        if s.arrowfront == 'none' and s.arrowback == 'none':
            utils.plotLinesToPainter(painter, x1, y1, x2, y2,
                                     cliprect)
        else:
            arrowsize = s.get('arrowsize').convert(painter)
            painter.setBrush( s.get('Fill').makeQBrushWHide() )

            # this is backward - have to convert from dx, dy to angle, length
            angles = 180 - N.arctan2(dy, dx) * (180./N.pi)
            lengths = N.sqrt(dx**2+dy**2) * 2
            
            # scale arrow heads by arrow length if requested
            if s.scalearrow:
                arrowsizes = (arrowsize/baselength/2) * lengths
            else:
                arrowsizes = N.zeros(lengths.shape) + arrowsize

            for x, y, l, a, asize in itertools.izip(x2, y2, lengths, angles,
                                                    arrowsizes):
                if l != 0.:
                    utils.plotLineArrow(painter, x, y, l, a, asize,
                                        arrowleft=s.arrowfront,
                                        arrowright=s.arrowback)
Example #7
0
    def _drawTickSet(self, painter, tickSetn, gridSetn,
                     tickbot, tickleft, tickright,
                     tickLabelSetn=None, labelSetn=None):
        '''Draw a set of ticks (major or minor).

        tickSetn: tick setting to get line details
        gridSetn: setting for grid line (if any)
        tickXXX: tick arrays for each axis
        tickLabelSetn: setting used to label ticks, or None if minor ticks
        labelSetn: setting for labels, if any
        '''

        # this is mostly a lot of annoying trigonometry
        # compute line ends for ticks and grid lines

        tl = tickSetn.get('length').convert(painter)
        mv = self._maxVal()

        reverse = bool(self.settings.reverse)
        revsign = [1, -1][reverse]

        # bottom ticks
        x1 = (tickbot - self._orgbot)/self._size*self._width + self._box[0]
        y1 = self._box[3] + N.zeros(x1.shape)
        x2 = x1 - revsign * tl * sin30
        y2 = y1 + tl * cos30
        tickbotline = (x1, y1, x2, y2)

        # bottom grid (removing lines at edge of plot)
        scaletick = 1 - (tickbot-self._orgbot)/self._size
        gx = x1 + scaletick*self._width*sin30
        gy = y1 - scaletick*self._width*cos30
        ne = (scaletick > 1e-6) & (scaletick < (1-1e-6))
        gridbotline = (x1[ne], y1[ne], gx[ne], gy[ne])

        # left ticks
        x1 = -(tickleft - self._orgleft)/self._size*self._width*sin30 + (
            self._box[0] + self._box[2])*0.5
        y1 = (tickleft - self._orgleft)/self._size*self._width*cos30 + self._box[1]
        if reverse:
            x2 = x1 - tl
            y2 = y1
        else:
            x2 = x1 - tl * sin30
            y2 = y1 - tl * cos30
        tickleftline = (x1, y1, x2, y2)

        # left grid
        scaletick = 1 - (tickleft-self._orgleft)/self._size
        gx = x1 + scaletick*self._width*sin30
        gy = self._box[3] + N.zeros(y1.shape)
        ne = (scaletick > 1e-6) & (scaletick < (1-1e-6))
        gridleftline = (x1[ne], y1[ne], gx[ne], gy[ne])

        # right ticks
        x1 = -(tickright - self._orgright)/self._size*self._width*sin30+self._box[2]
        y1 = -(tickright - self._orgright)/self._size*self._width*cos30+self._box[3]
        if reverse:
            x2 = x1 + tl * sin30
            y2 = y1 - tl * cos30
        else:
            x2 = x1 + tl
            y2 = y1
        tickrightline = (x1, y1, x2, y2)

        # right grid
        scaletick = 1 - (tickright-self._orgright)/self._size
        gx = x1 - scaletick*self._width
        gy = y1
        gridrightline = (x1[ne], y1[ne], gx[ne], gy[ne])

        if not gridSetn.hide:
            # draw the grid
            pen = gridSetn.makeQPen(painter)
            painter.setPen(pen)
            utils.plotLinesToPainter(painter, *gridbotline)
            utils.plotLinesToPainter(painter, *gridleftline)
            utils.plotLinesToPainter(painter, *gridrightline)

        # calculate deltas for ticks
        bdelta = ldelta = rdelta = 0

        if not tickSetn.hide:
            # draw ticks themselves
            pen = tickSetn.makeQPen(painter)
            pen.setCapStyle(qt4.Qt.FlatCap)
            painter.setPen(pen)
            utils.plotLinesToPainter(painter, *tickbotline)
            utils.plotLinesToPainter(painter, *tickleftline)
            utils.plotLinesToPainter(painter, *tickrightline)

            ldelta += tl*sin30
            bdelta += tl*cos30
            rdelta += tl

        if tickLabelSetn is not None and not tickLabelSetn.hide:
            # compute the labels for the ticks
            tleftlabels = self._getLabels(tickleft*mv, '%Vg')
            trightlabels = self._getLabels(tickright*mv, '%Vg')
            tbotlabels = self._getLabels(tickbot*mv, '%Vg')

            painter.setPen( tickLabelSetn.makeQPen() )
            font = tickLabelSetn.makeQFont(painter)
            painter.setFont(font)

            fm = utils.FontMetrics(font, painter.device())
            sp = fm.leading() + fm.descent()
            off = tickLabelSetn.get('offset').convert(painter)

            # draw tick labels in each direction
            hlabbot = wlableft = wlabright = 0
            for l, x, y in izip(tbotlabels, tickbotline[2], tickbotline[3]+off):
                r = utils.Renderer(painter, font, x, y, l, 0, 1, 0)
                bounds = r.render()
                hlabbot = max(hlabbot, bounds[3]-bounds[1])
            for l, x, y in izip(tleftlabels, tickleftline[2]-off-sp, tickleftline[3]):
                r = utils.Renderer(painter, font, x, y, l, 1, 0, 0)
                bounds = r.render()
                wlableft = max(wlableft, bounds[2]-bounds[0])
            for l, x, y in izip(trightlabels,tickrightline[2]+off+sp, tickrightline[3]):
                r = utils.Renderer(painter, font, x, y, l, -1, 0, 0)
                bounds = r.render()
                wlabright = max(wlabright, bounds[2]-bounds[0])

            bdelta += hlabbot+off+sp
            ldelta += wlableft+off+sp
            rdelta += wlabright+off+sp

        if labelSetn is not None and not labelSetn.hide:
            # draw label on edges (if requested)
            painter.setPen( labelSetn.makeQPen() )
            font = labelSetn.makeQFont(painter)
            painter.setFont(font)

            fm = utils.FontMetrics(font, painter.device())
            sp = fm.leading() + fm.descent()
            off = labelSetn.get('offset').convert(painter)

            # bottom label
            r = utils.Renderer(painter, font,
                               self._box[0]+self._width/2,
                               self._box[3] + bdelta + off,
                               self.settings.labelbottom,
                               0, 1)
            r.render()

            # left label - rotate frame before drawing so we can get
            # the bounds correct
            r = utils.Renderer(painter, font, 0, -sp,
                               self.settings.labelleft,
                               0, -1)
            painter.save()
            painter.translate(self._box[0]+self._width*0.25 - ldelta - off,
                              0.5*(self._box[1]+self._box[3]))
            painter.rotate(-60)
            r.render()
            painter.restore()

            # right label
            r = utils.Renderer(painter, font, 0, -sp,
                               self.settings.labelright,
                               0, -1)
            painter.save()
            painter.translate(self._box[0]+self._width*0.75 + ldelta + off,
                              0.5*(self._box[1]+self._box[3]))
            painter.rotate(60)
            r.render()
            painter.restore()
Example #8
0
    def drawErrorBars(self, painter, posns, barwidth,
                      yvals, dataset, axes, widgetposn):
        """Draw (optional) error bars on bars."""
        s = self.settings
        if s.errorstyle == 'none':
            return

        minval, maxval = self.calculateErrorBars(dataset, yvals)
        if minval is None and maxval is None:
            return

        # handle one sided errors
        if minval is None:
            minval = yvals
        if maxval is None:
            maxval = yvals

        # convert errors to coordinates
        ishorz = s.direction == 'horizontal'
        mincoord = axes[not ishorz].dataToPlotterCoords(widgetposn, minval)
        mincoord = N.clip(mincoord, -32767, 32767)
        maxcoord = axes[not ishorz].dataToPlotterCoords(widgetposn, maxval)
        maxcoord = N.clip(maxcoord, -32767, 32767)

        # draw error bars
        painter.setPen( self.settings.ErrorBarLine.makeQPenWHide(painter) )
        w = barwidth*0.25
        if ishorz:
            utils.plotLinesToPainter(painter, mincoord, posns,
                                     maxcoord, posns)
            if s.errorstyle == 'barends':
                utils.plotLinesToPainter(painter, mincoord, posns-w,
                                         mincoord, posns+w)
                utils.plotLinesToPainter(painter, maxcoord, posns-w,
                                         maxcoord, posns+w)
        else:
            utils.plotLinesToPainter(painter, posns, mincoord,
                                     posns, maxcoord)
            if s.errorstyle == 'barends':
                utils.plotLinesToPainter(painter, posns-w, mincoord,
                                         posns+w, mincoord)
                utils.plotLinesToPainter(painter, posns-w, maxcoord,
                                         posns+w, maxcoord)
Example #9
0
    def drawErrorBars(self, painter, posns, barwidth, yvals, dataset, axes,
                      widgetposn):
        """Draw (optional) error bars on bars."""
        s = self.settings
        if s.errorstyle == 'none':
            return

        minval, maxval = self.calculateErrorBars(dataset, yvals)
        if minval is None and maxval is None:
            return

        # handle one sided errors
        if minval is None:
            minval = yvals
        if maxval is None:
            maxval = yvals

        # convert errors to coordinates
        ishorz = s.direction == 'horizontal'
        mincoord = axes[not ishorz].dataToPlotterCoords(widgetposn, minval)
        mincoord = N.clip(mincoord, -32767, 32767)
        maxcoord = axes[not ishorz].dataToPlotterCoords(widgetposn, maxval)
        maxcoord = N.clip(maxcoord, -32767, 32767)

        # draw error bars
        painter.setPen(self.settings.ErrorBarLine.makeQPenWHide(painter))
        w = barwidth * 0.25
        if ishorz:
            utils.plotLinesToPainter(painter, mincoord, posns, maxcoord, posns)
            if s.errorstyle == 'barends':
                utils.plotLinesToPainter(painter, mincoord, posns - w,
                                         mincoord, posns + w)
                utils.plotLinesToPainter(painter, maxcoord, posns - w,
                                         maxcoord, posns + w)
        else:
            utils.plotLinesToPainter(painter, posns, mincoord, posns, maxcoord)
            if s.errorstyle == 'barends':
                utils.plotLinesToPainter(painter, posns - w, mincoord,
                                         posns + w, mincoord)
                utils.plotLinesToPainter(painter, posns - w, maxcoord,
                                         posns + w, maxcoord)
Example #10
0
    def _drawTickSet(self, painter, tickSetn, gridSetn,
                     tickbot, tickleft, tickright,
                     tickLabelSetn=None, labelSetn=None):
        '''Draw a set of ticks (major or minor).

        tickSetn: tick setting to get line details
        gridSetn: setting for grid line (if any)
        tickXXX: tick arrays for each axis
        tickLabelSetn: setting used to label ticks, or None if minor ticks
        labelSetn: setting for labels, if any
        '''

        # this is mostly a lot of annoying trigonometry
        # compute line ends for ticks and grid lines

        tl = tickSetn.get('length').convert(painter)
        mv = self._maxVal()

        # bottom ticks
        x1 = (tickbot - self._orgbot)/self._size*self._width + self._box[0]
        x2 = x1 - tl * sin30
        y1 = self._box[3] + N.zeros(x1.shape)
        y2 = y1 + tl * cos30
        tickbotline = (x1, y1, x2, y2)

        # bottom grid (removing lines at edge of plot)
        scaletick = 1 - (tickbot-self._orgbot)/self._size
        gx = x1 + scaletick*self._width*sin30
        gy = y1 - scaletick*self._width*cos30
        ne = (scaletick > 1e-6) & (scaletick < (1-1e-6))
        gridbotline = (x1[ne], y1[ne], gx[ne], gy[ne])

        # left ticks
        x1 = -(tickleft - self._orgleft)/self._size*self._width*sin30 + (
            self._box[0] + self._box[2])*0.5
        x2 = x1 - tl * sin30
        y1 = (tickleft - self._orgleft)/self._size*self._width*cos30 + self._box[1]
        y2 = y1 - tl * cos30
        tickleftline = (x1, y1, x2, y2)

        # left grid
        scaletick = 1 - (tickleft-self._orgleft)/self._size
        gx = x1 + scaletick*self._width*sin30
        gy = self._box[3] + N.zeros(y1.shape)
        ne = (scaletick > 1e-6) & (scaletick < (1-1e-6))
        gridleftline = (x1[ne], y1[ne], gx[ne], gy[ne])

        # right ticks
        x1 = -(tickright - self._orgright)/self._size*self._width*sin30+self._box[2]
        x2 = x1 + tl
        y1 = -(tickright - self._orgright)/self._size*self._width*cos30+self._box[3]
        y2 = y1
        tickrightline = (x1, y1, x2, y2)

        # right grid
        scaletick = 1 - (tickright-self._orgright)/self._size
        gx = x1 - scaletick*self._width
        gy = y1
        gridrightline = (x1[ne], y1[ne], gx[ne], gy[ne])

        if not gridSetn.hide:
            # draw the grid
            pen = gridSetn.makeQPen(painter)
            painter.setPen(pen)
            utils.plotLinesToPainter(painter, *gridbotline)
            utils.plotLinesToPainter(painter, *gridleftline)
            utils.plotLinesToPainter(painter, *gridrightline)

        # calculate deltas for ticks
        bdelta = ldelta = rdelta = 0

        if not tickSetn.hide:
            # draw ticks themselves
            pen = tickSetn.makeQPen(painter)
            pen.setCapStyle(qt4.Qt.FlatCap)
            painter.setPen(pen)
            utils.plotLinesToPainter(painter, *tickbotline)
            utils.plotLinesToPainter(painter, *tickleftline)
            utils.plotLinesToPainter(painter, *tickrightline)

            ldelta += tl*sin30
            bdelta += tl*cos30
            rdelta += tl

        if tickLabelSetn is not None and not tickLabelSetn.hide:
            # compute the labels for the ticks
            tleftlabels = self._getLabels(tickleft*mv, '%Vg')
            trightlabels = self._getLabels(tickright*mv, '%Vg')
            tbotlabels = self._getLabels(tickbot*mv, '%Vg')

            painter.setPen( tickLabelSetn.makeQPen() )
            font = tickLabelSetn.makeQFont(painter)
            painter.setFont(font)

            fm = utils.FontMetrics(font, painter.device())
            sp = fm.leading() + fm.descent()
            off = tickLabelSetn.get('offset').convert(painter)

            # draw tick labels in each direction
            hlabbot = wlableft = wlabright = 0
            for l, x, y in izip(tbotlabels, tickbotline[2], tickbotline[3]+off):
                r = utils.Renderer(painter, font, x, y, l, 0, 1, 0)
                bounds = r.render()
                hlabbot = max(hlabbot, bounds[3]-bounds[1])
            for l, x, y in izip(tleftlabels, tickleftline[2]-off-sp, tickleftline[3]):
                r = utils.Renderer(painter, font, x, y, l, 1, 0, 0)
                bounds = r.render()
                wlableft = max(wlableft, bounds[2]-bounds[0])
            for l, x, y in izip(trightlabels,tickrightline[2]+off+sp, tickrightline[3]):
                r = utils.Renderer(painter, font, x, y, l, -1, 0, 0)
                bounds = r.render()
                wlabright = max(wlabright, bounds[2]-bounds[0])

            bdelta += hlabbot+off+sp
            ldelta += wlableft+off+sp
            rdelta += wlabright+off+sp

        if labelSetn is not None and not labelSetn.hide:
            # draw label on edges (if requested)
            painter.setPen( labelSetn.makeQPen() )
            font = labelSetn.makeQFont(painter)
            painter.setFont(font)

            fm = utils.FontMetrics(font, painter.device())
            sp = fm.leading() + fm.descent()
            off = labelSetn.get('offset').convert(painter)

            # bottom label
            r = utils.Renderer(painter, font,
                               self._box[0]+self._width/2,
                               self._box[3] + bdelta + off,
                               self.settings.labelbottom,
                               0, 1)
            r.render()

            # left label - rotate frame before drawing so we can get
            # the bounds correct
            r = utils.Renderer(painter, font, 0, -sp,
                               self.settings.labelleft,
                               0, -1)
            painter.save()
            painter.translate(self._box[0]+self._width*0.25 - ldelta - off,
                              0.5*(self._box[1]+self._box[3]))
            painter.rotate(-60)
            r.render()
            painter.restore()

            # right label
            r = utils.Renderer(painter, font, 0, -sp,
                               self.settings.labelright,
                               0, -1)
            painter.save()
            painter.translate(self._box[0]+self._width*0.75 + ldelta + off,
                              0.5*(self._box[1]+self._box[3]))
            painter.rotate(60)
            r.render()
            painter.restore()
Example #11
0
    def draw(self, parentposn, phelper, outerbounds=None):
        """Draw the widget."""

        posn = plotters.GenericPlotter.draw(self,
                                            parentposn,
                                            phelper,
                                            outerbounds=outerbounds)
        x1, y1, x2, y2 = posn
        s = self.settings
        d = self.document

        # hide if hidden!
        if s.hide:
            return

        # get axes widgets
        axes = self.parent.getAxes((s.xAxis, s.yAxis))

        # return if there's no proper axes
        if (None in axes or axes[0].settings.direction != 'horizontal'
                or axes[1].settings.direction != 'vertical'):
            return

        # ignore non existing datasets
        try:
            data1 = d.data[s.data1]
            data2 = d.data[s.data2]
        except KeyError:
            return

        # require 2d datasets
        if data1.dimensions != 2 or data2.dimensions != 2:
            return

        # clip data within bounds of plotter
        cliprect = self.clipAxesBounds(axes, posn)
        painter = phelper.painter(self, posn, clip=cliprect)

        # get base length (ensure > 0)
        baselength = max(s.get('baselength').convert(painter), 1e-6)

        # try to be nice if the datasets don't match
        data1st, data2nd = data1.data, data2.data
        xw = min(data1st.shape[1], data2nd.shape[1])
        yw = min(data1st.shape[0], data2nd.shape[0])

        # construct indices into datasets
        yvals, xvals = N.mgrid[0:yw, 0:xw]
        # convert using 1st dataset to axes values
        xdsvals, ydsvals = data1.indexToPoint(xvals.ravel(), yvals.ravel())

        # convert using axes to plotter values
        xplotter = axes[0].dataToPlotterCoords(posn, xdsvals)
        yplotter = axes[1].dataToPlotterCoords(posn, ydsvals)

        pen = s.Line.makeQPenWHide(painter)
        painter.setPen(pen)

        if s.mode == 'cartesian':
            dx = (data1st[:yw, :xw] * baselength).ravel()
            dy = (data2nd[:yw, :xw] * baselength).ravel()

        elif s.mode == 'polar':
            r = data1st[:yw, :xw].ravel() * baselength
            theta = data2nd[:yw, :xw].ravel()
            dx = r * N.cos(theta)
            dy = r * N.sin(theta)

        x1, x2 = xplotter - dx, xplotter + dx
        y1, y2 = yplotter + dy, yplotter - dy

        if s.arrowfront == 'none' and s.arrowback == 'none':
            utils.plotLinesToPainter(painter, x1, y1, x2, y2, cliprect)
        else:
            arrowsize = s.get('arrowsize').convert(painter)
            painter.setBrush(s.get('Fill').makeQBrushWHide())

            # this is backward - have to convert from dx, dy to angle, length
            angles = 180 - N.arctan2(dy, dx) * (180. / N.pi)
            lengths = N.sqrt(dx**2 + dy**2) * 2

            # scale arrow heads by arrow length if requested
            if s.scalearrow:
                arrowsizes = (arrowsize / baselength / 2) * lengths
            else:
                arrowsizes = N.zeros(lengths.shape) + arrowsize

            for x, y, l, a, asize in itertools.izip(x2, y2, lengths, angles,
                                                    arrowsizes):
                if l != 0.:
                    utils.plotLineArrow(painter,
                                        x,
                                        y,
                                        l,
                                        a,
                                        asize,
                                        arrowleft=s.arrowfront,
                                        arrowright=s.arrowback)
Example #12
0
    def draw(self, parentposn, phelper, outerbounds = None):
        """Draw the widget."""

        posn = plotters.GenericPlotter.draw(self, parentposn, phelper,
                                            outerbounds = outerbounds)
        x1, y1, x2, y2 = posn
        s = self.settings
        d = self.document

        # hide if hidden!
        if s.hide:
            return

        # get axes widgets
        axes = self.parent.getAxes( (s.xAxis, s.yAxis) )

        # return if there's no proper axes
        if ( None in axes or
             axes[0].settings.direction != 'horizontal' or
             axes[1].settings.direction != 'vertical' ):
            return

        # ignore non existing datasets
        try:
            data1 = d.data[s.data1]
            data2 = d.data[s.data2]
        except KeyError:
            return

        # require 2d datasets
        if data1.dimensions != 2 or data2.dimensions != 2:
            return

        # clip data within bounds of plotter
        cliprect = self.clipAxesBounds(axes, posn)
        painter = phelper.painter(self, posn, clip=cliprect)

        baselength = s.get('baselength').convert(painter)

        # try to be nice if the datasets don't match
        data1st, data2nd = data1.data, data2.data
        xw = min(data1st.shape[1], data2nd.shape[1])
        yw = min(data1st.shape[0], data2nd.shape[0])

        # construct indices into datasets
        yvals, xvals = N.mgrid[0:yw, 0:xw]
        # convert using 1st dataset to axes values
        xdsvals, ydsvals = data1.indexToPoint(xvals.ravel(), yvals.ravel())

        # convert using axes to plotter values
        xplotter = axes[0].dataToPlotterCoords(posn, xdsvals)
        yplotter = axes[1].dataToPlotterCoords(posn, ydsvals)

        pen = s.Line.makeQPenWHide(painter)
        painter.setPen(pen)

        if s.mode == 'cartesian':
            dx = (data1st[:yw, :xw] * baselength).ravel()
            dy = (data2nd[:yw, :xw] * baselength).ravel()

        elif s.mode == 'polar':
            r = data1st[:yw, :xw].ravel() * baselength
            theta = data2nd[:yw, :xw].ravel()
            dx = r * N.cos(theta)
            dy = r * N.sin(theta)

        x1, x2 = xplotter-dx, xplotter+dx
        y1, y2 = yplotter+dy, yplotter-dy

        if s.arrowfront == 'none' and s.arrowback == 'none':
            utils.plotLinesToPainter(painter, x1, y1, x2, y2,
                                     cliprect)
        else:
            arrowsize = s.get('arrowsize').convert(painter)
            painter.setBrush( s.get('Fill').makeQBrushWHide() )

            # this is backward - have to convert from dx, dy to angle, length
            angles = 180 - N.arctan2(dy, dx) * (180./N.pi)
            lengths = N.sqrt(dx**2+dy**2) * 2
            
            # scale arrow heads by arrow length if requested
            if s.scalearrow:
                arrowsizes = (arrowsize/baselength/2) * lengths
            else:
                arrowsizes = N.zeros(lengths.shape) + arrowsize

            for x, y, l, a, asize in itertools.izip(x2, y2, lengths, angles,
                                                    arrowsizes):
                utils.plotLineArrow(painter, x, y, l, a, asize,
                                    arrowleft=s.arrowfront,
                                    arrowright=s.arrowback)