Logo Search packages:      
Sourcecode: mascyma version File versions  Download package


00001 """
Abstract base classes definine the primitives that renderers and
graphics contexts must implement to serve as a matplotlib backend


from __future__ import division
import sys
from Numeric import array
from artist import Artist, DPI
from patches import Rectangle
from cbook import is_string_like, enumerate, True, False
from transforms import Bound1D, Bound2D, Transform, BinOp
import axes

colors = {
    'b' : (0.0, 0.0, 1.0),
    'g' : (0.0, 0.5, 0.0),
    'r' : (1.0, 0.0, 0.0),
    'c' : (0.0, 0.75, 0.75),
    'm' : (0.75, 0, 0.75),
    'y' : (0.75, 0.75, 0),
    'k' : (0.0, 0.0, 0.0),
    'w' : (1.0, 1.0, 1.0),

00029 def arg_to_rgb(arg):
    returns a tuple of three floats from 0-1.  arg can be a
    matlab format string, a html hex color string, an rgb tuple,
    or a float between 0 and 1.  In the latter case, grayscale is

    def looks_like_rgb():
        try: float(arg[2])
        except: return 0
        else: return 1

    if looks_like_rgb():
        return arg

    try: float(arg)
        if is_string_like(arg) and len(arg)==7 and arg[0]=='#':
            #print 'hex string:', arg
            return  hex2color(arg)
            return colors.get(arg, (0.0, 0.0, 0.0))
        if arg>=0 and arg<=1:
            return (arg,arg,arg)
            msg = 'Floating point color arg must be between 0 and 1\n' +\
                  'Found %1.2f' % arg

class RendererBase:

    def draw_arc(self, gcEdge, faceColor, x, y, width, height, angle1, angle2):
        Draw an arc centered at x,y with width and height and angles
        from 0.0 to 360.0

        If faceColor is not None, fill the rectangle with it.  gcEdge
        is a GraphicsContext instance
        pass  # derived must override

    def draw_line(self, gc, x1, y1, x2, y2):
        Draw a single line from x1,y1 to x2,y2
        pass  # derived must override

    def draw_lines(self, gc, x, y):
        x and y are equal length arrays, draw lines connecting each
        point in x, y
        pass  # derived must override

    def draw_point(self, gc, x, y):
        Draw a single point at x,y
        pass  # derived must override

    def draw_polygon(self, gcEdge, faceColor, points):
        Draw a polygon.  points is a len vertices tuple, each element
        giving the x,y coords a vertex

        If faceColor is not None, fill the rectangle with it.  gcEdge
        is a GraphicsContext instance

        pass # derived must override

    def draw_rectangle(self, gcEdge, faceColor, x, y, width, height):
        Draw a rectangle with lower left at x,y with width and height.

        If faceColor is not None, fill the rectangle with it.  gcEdge
        is a GraphicsContext instance
        pass # derived must override

    def new_gc(self):
        Return an instance of a GraphicsContextBase
        return GraphicsContextBase()

def hex2color(s):
    "Convert hex string (like html uses, eg, #efefef) to a r,g,b tuple"
    if s.find('#')!=0 or len(s)!=7:
        raise ValueError('s must be a hex string like "#efefef#')
    r,g,b = map(lambda x: int('0x' + x, 16)/256.0, (s[1:3], s[3:5], s[5:7]))
    return r,g,b

class GraphicsContextBase:    

    # a mapping from dash styles to suggested offset, dash pairs
    _dashd = {
        'solid'   : (None, None),
        'dashed'  : (0, array([6.0, 6.0])),
        'dashdot' : (0, array([3.0, 5.0, 1.0, 5.0])),
        'dotted'  : (0, array([1.0, 2.0]))

    def __init__(self):
        self._rgb = (0.0, 0.0, 0.0)
        self._linewidth = 1
        self._capstyle = 'butt'
        self._joinstyle = 'miter'
        self._dashes = None, None
        self._cliprect = None
        self._linestyle = 'solid'

    def get_clip_rectangle(self):
        Return the clip rectangle as (left, bottom, width, height)
        return self._cliprect

    def get_dashes(self):
        Return the dash information as an offset dashlist tuple The
        dash list is a even size list that gives the ink on, ink off
        in pixels.  See p107 of to postscript BLUEBOOK for more info

        Default value is None
        return self._dashes

    def get_capstyle(self):
        Return the capstyle as a string in ('butt', 'round', 'projecting')
        return self._capstyle

    def get_joinstyle(self):
        Return the line join style as one of ('miter', 'round', 'bevel')
        return self._joinstyle

    def get_linestyle(self, style):
        Return the linestyle: one of ('solid', 'dashed', 'dashdot',
        return self._linestyle

    def get_rgb(self):
        returns a tuple of three floats from 0-1.  color can be a
        matlab format string, a html hex color string, or a rgb tuple
        return self._rgb

    def set_clip_rectangle(self, rectangle):
        Set the clip rectangle with sequence (left, bottom, width, height)
        self._cliprect = rectangle

    def set_linestyle(self, style):
        Set the linestyle to be one of ('solid', 'dashed', 'dashdot',
        if style not in ('solid', 'dashed', 'dashdot', 'dotted'):
            error_msg('Unrecognized linestyle.  Found %s' % js)
        self._linestyle = style

    def set_dashes(self, dash_offset, dash_list):
        Set the dash style for the gc.  dash offset is the offset
        (usually 0).  Dash list specifies the on-off sequence as
        self._dashes = dash_offset, dash_list
    def set_foreground(self, fg):
        Set the foreground color.  fg can be a matlab format string, a
        html hex color string, an rgb unit tuple, or a float between 0
        and 1.  In the latter case, grayscale is used.
        self._rgb = arg_to_rgb(fg)

    def set_graylevel(self, frac):
        Set the foreground color to be a gray level with frac frac
        self._rgb = (frac, frac, frac)

    def set_linewidth(self, w):
        Set the linewidth in points
        self._linewidth = w

    def set_capstyle(self, cs):
        Set the capstyle as a string in ('butt', 'round', 'projecting')
        if cs not in ('butt', 'round', 'projecting'):
            error_msg('Unrecognized cap style.  Found %s' % cs)
        self._capstyle = cs

    def set_joinstyle(self, js):
        Set the join style to be one of ('miter', 'round', 'bevel')
        if js not in ('miter', 'round', 'bevel'):
            error_msg('Unrecognized join style.  Found %s' % js)
        self._joinstyle = js

    def get_linewidth(self):
        Return the line width in points as a scalar
        return self._linewidth

    def copy_properties(self, gc):
        'Copy properties from gc to self'
        self._rgb = gc._rgb
        self._linewidth = gc._linewidth
        self._capstyle = gc._capstyle
        self._joinstyle = gc._joinstyle
        self._dashes = gc._dashes
        self._cliprect = gc._cliprect
00270 class AxisTextBase(Artist):
    Handle storing and drawing of text in window or data coordinates

    Publicly accessible attributes
      dpi     : a DPI instance
      bbox    : the display bounding box Bound2D instance
      transx : the transform of the x data
      transy : the transform of the y data

    fontweights = {'normal' : None,  # set these constants as app for backend
                   'bold' : None,
                   'heavy' : None,
                   'light' : None,
                   'ultrabold' : None,
                   'ultralight' : None,
    fontangles = {
        'italic': None,
        'normal' : None,
        'oblique' : None,

    def __init__(self,
                 x=0, y=0, text='',
        Artist.__init__(self, dpi, bbox)
        self.transx = transx
        self.transy = transy
        self._x, self._y = x, y
        self._color = color
        self._text = text
        self._verticalalignment = verticalalignment
        self._horizontalalignment = horizontalalignment
        self._rotation = rotation
        self._fontname = fontname
        self._fontsize = fontsize
        self._fontweight = fontweight
        self._fontangle = fontangle
        self._reset = True
        self._eraseImg = None
        self._lastDPI = self.dpi.get()  # watch for changes in dpi
00328     def _compute_offsets(self):
        Return the (x,y) offsets to adjust for the alignment
        return 0,0  # derived must override

    def erase(self):
        pass # derived must override (optional)

    def get_fontname(self):
        "Return the font name as string"
        return self._fontname

    def get_fontsize(self):
        "Return the font size as integer"
        return self._fontsize

    def get_fontweight(self):
        "Get the font weight as string"
        return self._fontweight

    def get_fontangle(self):
        "Get the font angle as string"
        return self._fontangle

    def get_horizontalalignment(self):
        "Return the horizontal alignment as string"
        return self._horizontalalignment

    def get_position(self):
        "Return x, y as tuple"
        return self._x, self._y

    def get_text(self):
        "Get the text as string"
        return self._text

    def get_verticalalignment(self):
        "Return the vertical alignment as string"
        return self._verticalalignment

    def _get_xy_display(self):
        try: x = self._x.get()
        except AttributeError: x = self._x
        try: y = self._y.get()
        except AttributeError: y = self._y

        return self.transx.positions(x), self.transy.positions(y)
    def wash_brushes(self):
        "Flush all state vars and prepare for a clean redraw"
        self._reset = 1
        self._eraseImg = None
    def set_backgroundcolor(self, color):
        "Set the background color of the text"
        if color == self._backgroundcolor: return 
        self._backgroundcolor = color

    def set_color(self, color):
        "Set the foreground color of the text"
        if self._color == color: return 
        self._color = color

00398     def set_horizontalalignment(self, align):
        Set the horizontal alignment to one of
        'center', 'right', or 'left'
        legal = ('center', 'right', 'left')
        if align not in legal:
            raise ValueError('Horizontal alignment must be one of %s' % legal)
        if self._horizontalalignment == align: return     
        self._horizontalalignment = align

    def _set_font(self):
        "Update the font object"
        pass # derived must override

    def _set_font_on_dpi_change(self):
        if self.dpi.get() != self._lastDPI:
00419     def set_fontname(self, fontname):
        Set the font name, eg, 'Sans', 'Courier', 'Helvetica'
        if self._fontname == fontname: return
        self._fontname = fontname

00428     def set_fontsize(self, fontsize):
        Set the font size, eg, 8, 10, 12, 14...
        if self._fontsize == fontsize: return
        self._fontsize = fontsize
00437     def set_fontweight(self, weight):
        Set the font weight, one of:
        'normal', 'bold', 'heavy', 'light', 'ultrabold',  'ultralight'
        if self._fontweight == weight: return
        self._fontweight = weight
00447     def set_fontangle(self, angle):
        Set the font angle, one of 'normal', 'italic', 'oblique'
        if self._fontangle == angle: return  
        self._fontangle = angle
    def set_position(self, xy):

    def set_x(self, x):        
        if x == self._x: return
        try: self._x.set(x)
        except AttributeError: self._x = x

    def set_y(self, y):
        if y == self._y: return
        try: self._y.set(y)
        except AttributeError: self._y = y
    def set_rotation(self, s):
        "Currently only s='vertical', or s='horizontal' are supported"
        if s==self._rotation: return
        self._rotation = s
00480     def set_verticalalignment(self, align):
        Set the vertical alignment to one of
        'center', 'top', or 'bottom'

        legal = ('top', 'bottom', 'center')
        if align not in legal:
            raise ValueError('Vertical alignment must be one of %s' % legal)

        if self._verticalalignment == align: return
        self._verticalalignment = align
    def set_text(self, text):
        "Set the text"
        if self._text == text: return
        self._text = text
    def _state_change(self):
        self._reset = 1

    def update_properties(self, d):
        "Update the font attributes with the dictionary in d"
        #check the keys
        legal = ('color', 'verticalalignment', 'horizontalalignment',
                 'fontname', 'fontsize', 'fontweight',
                 'fontangle', 'rotation')
        for k,v in d.items():
            if k not in legal:
                raise ValueError('Illegal key %s.  Legal values are %s' % (
                    k, legal))
            self.__dict__['_' + k] = v
            #print self.__dict__
    def __del__(self):
        "Bye bye"

class FigureBase:
    def __init__(self, figsize, dpi, facecolor=0.75, edgecolor='k'):
        paper size is a w,h tuple in inches
        DPI is dots per inch 
        self.figsize = figsize
        self.bbox = Bound2D(0, 0, figsize[0]*dpi, figsize[1]*dpi)
        self.dpi = DPI(dpi)
        self.axes = []
        self.drawable = None
        self._figurePatch = Rectangle(
            self.dpi, self.bbox, 
            (0,0), 1, 1,
            facecolor=facecolor, edgecolor=edgecolor,
            transx = Transform( Bound1D(0,1), self.bbox.x),
            transy = Transform( Bound1D(0,1), self.bbox.y),

    def add_axis(self, a):
    def clear(self):
        self.axes = []
    def draw(self, drawable=None, *args, **kwargs):
        Render the figure using Renderer instance drawable
        pass  # derived must override 

    def get_axes(self):
        return self.axes

    def realize(self, *args):
        This method will be called when the system is ready to draw,
        eg when a GUI window is realized
        pass   # derived must override

    def text(self, x, y, s, *args, **kwargs):
        Add text to figure at location x,y (relative 0-1 coords) See
        the help for Axis text for the meaning of the other arguments

class FigureManagerBase:
    def __init__(self, figure, num):
        self.figure = figure
        self.num = num
        self.axes = {}

    def add_subplot(self, *args, **kwargs):
        Add a subplot to the current figure
        if self.axes.has_key(args):
            self.currentAxis = self.axes[args]
            a = axes.Subplot(self.figure, *args, **kwargs)
            self.axes[args] = a
            self.currentAxis = a
            return a
    def add_axes(self, rect, axisbg):
        Add an axes to the current figure
        rect = tuple(rect)
        if self.axes.has_key(rect):
            self.currentAxis = self.axes[rect]
            return self.currentAxis
            a = axes.Axes(self.figure, position=rect, axisbg=axisbg)
            self.axes[rect] = a
            self.currentAxis = a
            return a

    def get_current_axis(self):
        Return the current axes
            return self.currentAxis
        except AttributeError:
            return self.currentAxis

    def set_current_axes(self, a):
        Set the current axes to be a
        if a not in self.axes.values():
            error_msg('Axes is not in current figure')
        self.currentAxis = a

    def destroy(self):

def _process_text_args(override, fontdict=None, **kwargs):
    "Return an override dict.  See 'text' docstring for info"

    if fontdict is not None:

    return override

00645 def error_msg(msg, *args, **kwargs):
    Alert an error condition with message
    print >>sys.stderr, msg

Generated by  Doxygen 1.6.0   Back to index