File: //opt/alt/python27/lib64/python2.7/site-packages/matplotlib/patheffects.py
"""
Defines classes for path effects. The path effects are supported in
:class:`~matplotlib.text.Text` and :class:`~matplotlib.patches.Patch`
matplotlib.text.Text.
"""
from matplotlib.backend_bases import RendererBase
from matplotlib.backends.backend_mixed import MixedModeRenderer
import matplotlib.transforms as transforms
class _Base(object):
"""
A base class for PathEffect. Derived must override draw_path method.
"""
def __init__(self):
"""
initializtion.
"""
super(_Base, self).__init__()
def _update_gc(self, gc, new_gc_dict):
new_gc_dict = new_gc_dict.copy()
dashes = new_gc_dict.pop("dashes", None)
if dashes:
gc.set_dashes(**dashes)
for k, v in new_gc_dict.iteritems():
set_method = getattr(gc, 'set_'+k, None)
if set_method is None or not callable(set_method):
raise AttributeError('Unknown property %s'%k)
set_method(v)
return gc
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
"""
Derived should override this method. The argument is same
as *draw_path* method of :class:`matplotlib.backend_bases.RendererBase`
except the first argument is a renderer. The base definition is ::
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
renderer.draw_path(gc, tpath, affine, rgbFace)
"""
renderer.draw_path(gc, tpath, affine, rgbFace)
def draw_tex(self, renderer, gc, x, y, s, prop, angle, ismath='TeX!'):
self._draw_text_as_path(renderer, gc, x, y, s, prop, angle, ismath="TeX")
def draw_text(self, renderer, gc, x, y, s, prop, angle, ismath=False):
self._draw_text_as_path(renderer, gc, x, y, s, prop, angle, ismath)
def _draw_text_as_path(self, renderer, gc, x, y, s, prop, angle, ismath):
if isinstance(renderer, MixedModeRenderer):
renderer = renderer._renderer
path, transform = RendererBase._get_text_path_transform(renderer,
x, y, s,
prop, angle,
ismath)
color = gc.get_rgb()[:3]
gc.set_linewidth(0.0)
self.draw_path(renderer, gc, path, transform, rgbFace=color)
# def draw_path_collection(self, renderer,
# gc, master_transform, paths, all_transforms,
# offsets, offsetTrans, facecolors, edgecolors,
# linewidths, linestyles, antialiaseds, urls):
# path_ids = []
# for path, transform in renderer._iter_collection_raw_paths(
# master_transform, paths, all_transforms):
# path_ids.append((path, transform))
# for xo, yo, path_id, gc0, rgbFace in renderer._iter_collection(
# gc, path_ids, offsets, offsetTrans, facecolors, edgecolors,
# linewidths, linestyles, antialiaseds, urls):
# path, transform = path_id
# transform = transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
# self.draw_path(renderer, gc0, path, transform, rgbFace)
class Normal(_Base):
"""
path effect with no effect
"""
pass
class Stroke(_Base):
"""
stroke the path with updated gc.
"""
def __init__(self, **kwargs):
"""
The path will be stroked with its gc updated with the given
keyword arguments, i.e., the keyword arguments should be valid
gc parameter values.
"""
super(Stroke, self).__init__()
self._gc = kwargs
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
"""
draw the path with update gc.
"""
# Do not modify the input! Use copy instead.
gc0 = renderer.new_gc()
gc0.copy_properties(gc)
gc0 = self._update_gc(gc0, self._gc)
renderer.draw_path(gc0, tpath, affine, None)
gc0.restore()
class withStroke(Stroke):
"""
Same as Stroke, but add a stroke with the original gc at the end.
"""
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
Stroke.draw_path(self, renderer, gc, tpath, affine, rgbFace)
renderer.draw_path(gc, tpath, affine, rgbFace)
import matplotlib.transforms as mtransforms
class SimplePatchShadow(_Base):
"""
simple shadow
"""
def __init__(self, offset_xy=(2,-2),
shadow_rgbFace=None, patch_alpha=0.7,
**kwargs):
"""
"""
super(_Base, self).__init__()
self._offset_xy = offset_xy
self._shadow_rgbFace = shadow_rgbFace
self._patch_alpha = patch_alpha
self._gc = kwargs
self._offset_tran = mtransforms.Affine2D()
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
"""
"""
# Do not modify the input! Use copy instead.
offset_x = renderer.points_to_pixels(self._offset_xy[0])
offset_y = renderer.points_to_pixels(self._offset_xy[1])
affine0 = affine + self._offset_tran.clear().translate(offset_x, offset_y)
gc0 = renderer.new_gc()
gc0.copy_properties(gc)
if self._shadow_rgbFace is None:
r,g,b = rgbFace[:3]
rho = 0.3
r = rho*r
g = rho*g
b = rho*b
shadow_rgbFace = (r,g,b)
else:
shadow_rgbFace = self._shadow_rgbFace
gc0.set_foreground("none")
gc0.set_alpha(1.-self._patch_alpha)
gc0.set_linewidth(0)
gc0 = self._update_gc(gc0, self._gc)
renderer.draw_path(gc0, tpath, affine0, shadow_rgbFace)
gc0.restore()
class withSimplePatchShadow(SimplePatchShadow):
"""
simple shadow
"""
def draw_path(self, renderer, gc, tpath, affine, rgbFace):
SimplePatchShadow.draw_path(self, renderer, gc, tpath, affine, rgbFace)
gc1 = renderer.new_gc()
gc1.copy_properties(gc)
gc1.set_alpha(gc1.get_alpha()*self._patch_alpha)
renderer.draw_path(gc1, tpath, affine, rgbFace)
gc1.restore()
if __name__ == '__main__':
clf()
imshow([[1,2],[2,3]])
#eff = PathEffects.Thicken()
txt = annotate("test", (1., 1.), (0., 0),
arrowprops=dict(arrowstyle="->", connectionstyle="angle3", lw=2),
size=12, ha="center")
txt.set_path_effects([withStroke(linewidth=3, foreground="w")])
#txt.arrow_patch.set_path_effects([PathEffects.withStroke(width=3, color="w")])
txt.arrow_patch.set_path_effects([Stroke(linewidth=5, foreground="w"),
Normal()])