|
From: <md...@us...> - 2007-09-20 18:00:34
|
Revision: 3869
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3869&view=rev
Author: mdboom
Date: 2007-09-20 11:00:32 -0700 (Thu, 20 Sep 2007)
Log Message:
-----------
First baby step in getting arbitrary non-linear transformations into
the pipeline.
Modified Paths:
--------------
branches/transforms/lib/matplotlib/axes.py
branches/transforms/lib/matplotlib/axis.py
branches/transforms/lib/matplotlib/backends/backend_agg.py
branches/transforms/lib/matplotlib/lines.py
branches/transforms/lib/matplotlib/path.py
branches/transforms/lib/matplotlib/text.py
branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/axes.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -633,10 +633,16 @@
self.transAxes = mtransforms.BboxTransform(
mtransforms.Bbox.unit(), self.bbox)
# self.set_transform(self.transAxes)
- self.transData = mtransforms.BboxTransform(
- self.viewLim, self.bbox)
+# self.transData = mtransforms.BboxTransform(
+# self.viewLim, self.bbox)
+ self.preDataTransform = mtransforms.BboxTransform(
+ self.viewLim, mtransforms.Bbox.unit())
+ self.dataTransform = mtransforms.TestLogTransform()
+ # self.dataTransform = mtransforms.Affine2D().scale(1.5)
+ self.transData = self.preDataTransform + self.dataTransform + mtransforms.BboxTransform(
+ mtransforms.Bbox.unit(), self.bbox)
+
-
def get_position(self, original=False):
'Return the axes rectangle left, bottom, width, height'
if original:
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/axis.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -1032,18 +1032,17 @@
else:
bbox = Bbox.union(bboxes)
bottom = bbox.ymin
-
- self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi / 72.0))
-
+ self.label.set_position( (x, bottom - self.LABELPAD*self.figure.dpi / 72.0))
+
else:
if not len(bboxes2):
top = self.axes.bbox.ymax
else:
bbox = bbox_union(bboxes2)
top = bbox.ymax
+
+ self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi / 72.0))
- self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi.get()/72.0))
-
def _update_offset_text_position(self, bboxes, bboxes2):
"""
Update the offset_text position based on the sequence of bounding
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -84,7 +84,8 @@
from matplotlib.font_manager import findfont
from matplotlib.ft2font import FT2Font, LOAD_DEFAULT
from matplotlib.mathtext import MathTextParser
-from matplotlib.transforms import Bbox
+from matplotlib.path import Path
+from matplotlib.transforms import Affine2D, Bbox
from _backend_agg import RendererAgg as _RendererAgg
@@ -117,8 +118,8 @@
debug=False)
if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
'debug-annoying')
- self.draw_path = self._renderer.draw_path
- self.draw_markers = self._renderer.draw_markers
+ #self.draw_path = self._renderer.draw_path
+ #self.draw_markers = self._renderer.draw_markers
self.draw_image = self._renderer.draw_image
self.copy_from_bbox = self._renderer.copy_from_bbox
self.restore_region = self._renderer.restore_region
@@ -129,6 +130,17 @@
if __debug__: verbose.report('RendererAgg.__init__ done',
'debug-annoying')
+ # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ def draw_path(self, gc, path, trans, rgbFace=None):
+ new_path, affine = path.transformed_without_affine(trans)
+ self._renderer.draw_path(gc, new_path, affine, rgbFace)
+
+ # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
+ assert marker_trans.is_affine()
+ new_path, affine = path.transformed_without_affine(trans)
+ self._renderer.draw_markers(gc, marker_path, marker_trans, new_path, affine, rgbFace)
+
def draw_mathtext(self, gc, x, y, s, prop, angle):
"""
Draw the math text using matplotlib.mathtext
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/lines.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -1102,12 +1102,14 @@
"""
return self._dashcapstyle
+
def get_solid_capstyle(self):
"""
Get the cap style for solid linestyles
"""
return self._solidcapstyle
+
def is_dashed(self):
'return True if line is dashstyle'
return self._linestyle in ('--', '-.', ':')
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/path.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -70,6 +70,13 @@
yield vertices[i]
i += 1
+ def transformed(self, transform):
+ return Path(transform.transform(self.vertices), self.codes)
+
+ def transformed_without_affine(self, transform):
+ vertices, affine = transform.transform_without_affine(self.vertices)
+ return Path(vertices, self.codes), affine
+
_unit_rectangle = None
#@classmethod
def unit_rectangle(cls):
Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/text.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -185,7 +185,8 @@
xmin, ymin = thisx, thisy
lines = self._text.split('\n')
-
+
+ # MGDTODO: whs could be a numpy.array
whs = []
# Find full vertical extent of font,
# including ascenders and descenders:
@@ -260,27 +261,21 @@
else: offsety = ty - ymin
xmin += offsetx
- xmax += offsetx
ymin += offsety
- ymax += offsety
bbox = Bbox.from_lbwh(xmin, ymin, width, height)
-
-
# now rotate the positions around the first x,y position
xys = M.transform(offsetLayout)
- tx = xys[:, 0]
- ty = xys[:, 1]
- tx += offsetx
- ty += offsety
+ xys[:, 0] += offsetx
+ xys[:, 1] += offsety
# now inverse transform back to data coords
inverse_transform = self.get_transform().inverted()
xys = inverse_transform.transform(xys)
- xs, ys = zip(*xys)
-
+ xs, ys = xys[:, 0], xys[:, 1]
+
ret = bbox, zip(lines, whs, xs, ys)
self.cached[key] = ret
return ret
@@ -331,15 +326,15 @@
for line, wh, x, y in info:
x, y = trans.transform_point((x, y))
-
+
if renderer.flipy():
canvasw, canvash = renderer.get_canvas_width_height()
y = canvash-y
-
+
renderer.draw_text(gc, x, y, line,
self._fontproperties, angle,
ismath=self.is_math_text(line))
-
+
def get_color(self):
"Return the color of the text"
return self._color
@@ -407,7 +402,9 @@
return (x, y, self._text, self._color,
self._verticalalignment, self._horizontalalignment,
hash(self._fontproperties), self._rotation,
- self.get_transform(),
+ # MGDTODO: Find a better way to determine if the
+ # transform as changed
+ str(self.get_transform())
)
def get_text(self):
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py 2007-09-20 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/transforms.py 2007-09-20 18:00:32 UTC (rev 3869)
@@ -256,10 +256,10 @@
self.invalidate()
def transformed(self, transform):
- return Bbox(transform(self._points))
+ return Bbox(transform.transform(self._points))
def inverse_transformed(self, transform):
- return Bbox(transform.inverted()(self._points))
+ return Bbox(transform.inverted().transform(self._points))
def expanded(self, sw, sh):
width = self.width
@@ -408,13 +408,13 @@
# MGDTODO: The major speed trap here is just converting to
# the points to an array in the first place. If we can use
# more arrays upstream, that should help here.
- if not isinstance(points, npy.ndarray):
- import traceback
- print '-' * 60
- print 'A non-numpy array was passed in for transformation. Please '
- print 'correct this.'
- print "".join(traceback.format_stack())
- print points
+# if not isinstance(points, npy.ndarray):
+# import traceback
+# print '-' * 60
+# print 'A non-numpy array was passed in for transformation. Please '
+# print 'correct this.'
+# print "".join(traceback.format_stack())
+# print points
mtx = self.get_matrix()
points = npy.asarray(points, npy.float_)
points = points.transpose()
@@ -563,6 +563,10 @@
self._y = y_transform
self.set_children(['_x', '_y'])
+ def __repr__(self):
+ return "BlendedGenericTransform(%s,%s)" % (self._x, self._y)
+ __str__ = __repr__
+
def transform(self, points):
# MGDTODO: Optimize the case where one of these is
# an affine
@@ -590,28 +594,6 @@
return True
-class BlendedSeparableTransform(Transform):
- input_dims = 2
- output_dims = 2
-
- def __init__(self, x_transform, y_transform):
- # Here we ask: "Does it blend?"
- assert x_transform.is_separable()
- assert y_transform.is_separable()
- assert x_transform.input_dims == x.transform.output_dims == 1
- assert y_transform.input_dims == y.transform.output_dims == 1
-
- Transform.__init__(self)
- self._x = x_transform
- self._y = y_transform
- self.set_children(['_x', '_y'])
-
- def transform(self, points):
- x_points = self._x(points[:, 0])
- y_points = self._y(points[:, 1])
- return npy.vstack((x_points[:, 0:1], y_points[:, 1:2])).transpose()
-
-
class BlendedAffine2D(Affine2DBase, Transform):
def __init__(self, x_transform, y_transform):
assert x_transform.is_affine()
@@ -666,6 +648,10 @@
self._a = a
self._b = b
self.set_children(['_a', '_b'])
+
+ def __repr__(self):
+ return "CompositeGenericTransform(%s, %s)" % (self._a, self._b)
+ __str__ = __repr__
def transform(self, points):
return self._b.transform(self._a.transform(points))
@@ -724,10 +710,21 @@
input_dims = 2
output_dims = 2
def transform(self, xy):
- return xy * 2
+ marray = npy.ma.masked_where(xy <= 0.0, xy * 10.0)
+ return npy.log10(marray)
+
+ def inverted(self):
+ return TestInvertLogTransform()
+
+class TestInvertLogTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+ def transform(self, xy):
+ return npy.power(10, xy) / 10.0
+
def inverted(self):
- return self
+ return TestLogTransform()
class BboxTransform(Affine2DBase):
@@ -825,7 +822,7 @@
assert bbox.bounds == (10, 15, 10, 10)
- print npy.asarray(bbox)
+ assert tuple(npy.asarray(bbox).flatten()) == (10, 15, 20, 25)
bbox.intervalx = (11, 21)
bbox.intervaly = (16, 26)
@@ -859,29 +856,35 @@
scale = Affine2D().scale(10, 20)
assert scale.to_values() == (10, 0, 0, 20, 0, 0)
rotation = Affine2D().rotate_deg(30)
- print rotation.to_values() == (0.86602540378443871, 0.49999999999999994,
+ assert rotation.to_values() == (0.86602540378443871, 0.49999999999999994,
-0.49999999999999994, 0.86602540378443871,
0.0, 0.0)
points = npy.array([[1,2],[3,4],[5,6],[7,8]], npy.float_)
- translated_points = translation(points)
+ translated_points = translation.transform(points)
assert (translated_points == [[11., 22.], [13., 24.], [15., 26.], [17., 28.]]).all()
- scaled_points = scale(points)
+ scaled_points = scale.transform(points)
print scaled_points
- rotated_points = rotation(points)
+ rotated_points = rotation.transform(points)
print rotated_points
- tpoints1 = rotation(translation(scale(points)))
+ tpoints1 = rotation.transform(translation.transform(scale.transform(points)))
trans_sum = scale + translation + rotation
- tpoints2 = trans_sum(points)
- print tpoints1, tpoints2
- print tpoints1 == tpoints2
+ tpoints2 = trans_sum.transform(points)
# Need to do some sort of fuzzy comparison here?
- # assert (tpoints1 == tpoints2).all()
+ assert (tpoints1.round() == tpoints2.round()).all()
+ print points
+
+ comp = TestLogTransform() + Affine2D().rotate_deg(15)
+ tpoints = comp.transform(points)
+ itpoints = comp.inverted().transform(tpoints)
+ print tpoints, itpoints
+ assert (points.round() == itpoints.round()).all()
+
# Here are some timing tests
points = npy.asarray([(random(), random()) for i in xrange(10000)])
- t = timeit.Timer("trans_sum(points)", "from __main__ import trans_sum, points")
+ t = timeit.Timer("trans_sum.transform(points)", "from __main__ import trans_sum, points")
print "Time to transform 10000 x 10 points:", t.timeit(10)
__all__ = ['Transform', 'Affine2D']
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|