@header@
matplotlib.transforms | index /matplotlib/transforms.py |
This module contains the newfangled transform class which allows the
placement of artists (lines, patches, text) in a variety of coordinate
systems (display, arbitrary data, relative axes, physical sizes)
The default Transform() is identity.
t = Transform()
x == Transform.positions(x) True
x == Transform.scale(x) True
A linear Transformation is specified by giving a Bound1D (min, max)
instance for the domain and range. The transform below maps the
interval [0,1] to [-10,10]
t = Transform( Bound1D(0,1), Bound1D(-10,10) )
Since all Transforms know their inverse function, you can compute an
inverse transformation by calling inverse_positions or inverse_scale
t = Transform( Bound1D(0,1), Bound1D(-10,10) )
val = t.inverse_positions(5) # maps [-10,10] to [0,1]
The difference between 'positions' and 'scale' is that the positions
func is appropriate for locations (eg, x,y) and the scale func is
appropriate for lengths (eg, width, height).
The Bound1D methods provide a number of utility functions: the
interval max-min, determining if a point is in the open or closed
interval, constraining the bound to be positive (useful for log
transforms), and so on. These are useful for storing view, data and
display limits of a given axis.
The Bound2D is a straight-forward generalization of Bound1D, and
stores 2 Bound1D instances 'x' and 'y' to represent a 2D Bound (useful
for Axes bounding boxes, clipping etc). All Artists are responsible
for returning their extent in display coords as a Bound2D instance,
which is useful for determining whether 2 Artists overlap. Some
utility functions, eg, bound2d_all, return the Bound2D instance that
bounds all the Bound2D instances passed as args. This helps in text
layout, eg, in positioning the axis labels to not overlap the tick
labels.
The Bound1D instances store their max and min values as RWVals
(read/write references). These are mutable scalars that can be shared
among all the figure components. When a figure clas resizes and thus
changes the display limits of an Axes, the Axes and all its components
know about the changes because they store a reference to the
displaylim, not the scalar value of the display lim. Likewise for
DPI.
Also, it is possible to do simple arithmetic in RRefs via the derived
BinOp class, which stores both sides of a binary arithmetic operation,
as well as the binary function to return the result of the binop
applied to the dereferenced scalars. This allows you to place artists
with locations like '3 centimenters below the x axis'
Here are some concepts and how to apply them via the transform
architecture
* Map view limits to display limits via a linear tranformation
# viewlim and displaylim are Bound1D instances
tx = Transform( axes.xaxis.viewlim, axes.xaxis.displaylim )
ty = Transform( axes.yaxis.viewlim, axes.yaxis.displaylim )
l = Line2D(dpi, bbox, xdata, ydata, transx=tx, transy=ty)
* Map relative axes coords ( 0,0 is lower left and 1,1 is upper
right ) to display coords. This example puts text in the middle
of the axes (0.5, 0.5)
tx = Transform( Bound1D(0,1), axes.xaxis.displaylim )
ty = Transform( Bound1D(0,1), axes.yaxis.displaylim )
text = AxisText(dpi, bbox, 0.5, 0.5, transx=tx, transy=ty)
* Map x view limits to display limits via a log tranformation and y
view limits via linear transform. The funcs pair is the
transform/inverse pair
funcs = logwarn, pow10
tx = Transform( axes.xaxis.viewlim, axes.xaxis.displaylim, funcs )
ty = Transform( axes.yaxis.viewlim, axes.yaxis.displaylim )
l = Line2D(dpi, bbox, xdata, ydata, transx=tx, transy=ty)
* You can also do transformation from one physical scale (inches, cm,
points, ...) to another. You need to specify an offset in output
coords.
offset = 100 # dots
cm = Centimeter( self.dpi)
dots = Dots( self.dpi)
t = TransformSize(cm, dots, offset)
If you don't know the offset in output coords, you can supply an
optional transform to transform the offset to output coords. Eg,
if you want to offset by x in data coords, and the output is
display coords, you can do
offset = 0.2 # x data coords
cm = Centimeter( self.dpi)
dots = Dots( self.dpi)
t = TransformSize(cm, dots, offset, axes.xaxis.transData)
* Combining the above, we can specify that a text instance is at an x
location in data coords and a y location in points relative to an
axis. Eg. the transformation below indicates that the x value of
an xticklabel position is in data corrdinates and the y value is 3
points below the x axis, top justified
# the top of the x ticklabel text is the bottom of the y axis
# minus 3 points. Note the code below uses the overloading of
# __sub__ and __mul__ to return a BinOp. Changes in the
# position of bbox.y or dpi, eg, on a resize event, are
# automagically reflected in the tick label position.
# dpi*3/72 converts 3 points to dots.
top = self.bbox.y.get_refmin() - self.dpi*RRef(3/72.0)
text = backends.AxisText(dpi, bbox, x=xdata, y=top,
verticalalignment='top',
horizontalalignment='center',
transx = self.axes.xaxis.transData,
# transy is default, identity transform)
The unittest code for the transforms module is unit/transforms_unit.py
Modules | ||||||
|
Classes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Functions | ||
|
Data | ||
division = _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192) log10 = <ufunc 'log10'> |