8000 Minor speed improvements in new transformations. · matplotlib/matplotlib@15a3f87 · GitHub
[go: up one dir, main page]

Skip to content

Commit 15a3f87

Browse files
committed
Minor speed improvements in new transformations.
svn path=/branches/transforms/; revision=3890
1 parent d0a6d4b commit 15a3f87

File tree

3 files changed

+79
-68
lines changed

3 files changed

+79
-68
lines changed

lib/matplotlib/path.py

Lines changed: 4 additions & 3 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ def __init__(self, vertices, codes=None, closed=True):
4141
assert len(codes) == len(vertices)
4242

4343
# The path being passed in may have masked values. However,
44-
# the backends are not expected to deal with masked arrays, so
45-
# we must remove them from the array (using compressed), and
46-
# add MOVETO commands to the codes array accordingly.
44+
# the backends (and any affine transformations in matplotlib
45+
# itself), are not expected to deal with masked arrays, so we
46+
# must remove them from the array (using compressed), and add
47+
# MOVETO commands to the codes array accordingly.
4748
mask = ma.getmask(vertices)
4849
if mask is not ma.nomask:
4950
mask1d = ma.mask_or(mask[:, 0], mask[:, 1])

lib/matplotlib/text.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,7 @@ def get_prop_tup(self):
402402
return (x, y, self._text, self._color,
403403
self._verticalalignment, self._horizontalalignment,
404404
hash(self._fontproperties), self._rotation,
405-
# MGDTODO: Find a better way to determine if the
406-
# transform as changed
407-
str(self.get_transform())
405+
self.get_transform().get_id()
408406
)
409407

410408
def get_text(self): 8000

lib/matplotlib/transforms.py

Lines changed: 74 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,28 @@
2121
# relationships
2222

2323
class TransformNode(object):
24+
_gid = 0
25+
2426
def __init__(self):
25-
self._parents = Set()
26-
self._children = []
27+
self._parents = WeakKeyDictionary()
28+
self._children = Set()
29+
self._id = TransformNode._gid
2730

28-
def invalidate(self, which_child=None, affine_only=[]):
29-
if which_child is None:
30-
which_child = self
31-
self._do_invalidation(which_child, affine_only)
32-
# affine_only = affine_only and (self.is_affine() or self.is_bbox())
33-
for parent in self._parents:
34-
parent.invalidate(self, affine_only + [self])
35-
36-
def _do_invalidation(self, which_child, affine_only):
37-
pass
31+
def invalidate(self, affine_only=None):
32+
if affine_only is None:
33+
affine_only = self.is_affine() or self.is_bbox()
34+
if not self._do_invalidation(affine_only):
35+
self._id = TransformNode._gid
36+
TransformNode._gid += 1
37+
for parent in self._parents.iterkeys():
38+
parent.invalidate(affine_only)
39+
40+
def _do_invalidation(self, affine_only):
41+
return False
3842

3943
def set_children(self, children):
4044
for child in children:
41-
getattr(self, child)._parents.add(self)
45+
getattr(self, child)._parents[self] = None
4246
self._children = children
4347

4448
def make_graphviz(self, fobj):
@@ -74,6 +78,9 @@ def is_affine(self):
7478
def is_bbox(self):
7579
return False
7680

81+
def get_id(self):
82+
return self._id
83+
7784

7885
class BboxBase(TransformNode):
7986
'''
@@ -214,6 +221,7 @@ class Bbox(BboxBase):
214221
def __init__(self, points):
215222
BboxBase.__init__(self)
216223
self._points = npy.asarray(points, npy.float_)
224+
self._invalid = False
217225

218226
#@staticmethod
219227
def unit():
@@ -235,6 +243,11 @@ def __repr__(self):
235243
return 'Bbox(%s)' % repr(self._points)
236244
__str__ = __repr__
237245

246+
def _do_invalidation(self, affine_only):
247+
result = self._invalid
248+
self._invalid = True
249+
return result
250+
238251
def update_from_data(self, x, y, ignore=True):
239252
if ignore:
240253
self._points = npy.array(
@@ -294,6 +307,7 @@ def _set_bounds(self, bounds):
294307
bounds = property(BboxBase._get_bounds, _set_bounds)
295308

296309
def get_points(self):
310+
self._invalid = False
297311
return self._points
298312

299313
def set_points(self, points):
@@ -348,21 +362,23 @@ def __init__(self, bbox, transform):
348362
assert transform.output_dims == 2
349363

350364
BboxBase.__init__(self)
351-
self.bbox = bbox
352-
self.transform = transform
353-
self.set_children(['bbox', 'transform'])
365+
self._bbox = bbox
366+
self._transform = transform
367+
self.set_children(['_bbox', '_transform'])
354368
self._points = None
355369

356370
def __repr__(self):
357-
return "TransformedBbox(%s, %s)" % (self.bbox, self.transform)
371+
return "TransformedBbox(%s, %s)" % (self._bbox, self._transform)
358372
__str__ = __repr__
359373

360-
def _do_invalidation(self, which_child, affine_only):
374+
def _do_invalidation(self, affine_only):
375+
result = self._points is None
361376
self._points = None
377+
return result
362378

363379
def get_points(self):
364380
if self._points is None:
365-
self._points = self.transform.transform(self.bbox.get_points())
381+
self._points = self._transform.transform(self._bbox.get_points())
366382
return self._points
367383

368384

@@ -461,9 +477,6 @@ def is_affine(self):
461477
def __array__(self, *args, **kwargs):
462478
return self.get_matrix()
463479

464-
def _do_invalidation(self, which_child, affine_only):
465-
self._inverted = None
466-
467480
#@staticmethod
468481
def _concat(a, b):
469482
return npy.dot(b, a)
@@ -477,9 +490,6 @@ def concat(a, b):
477490
def get_matrix(self):
478491
raise NotImplementedError()
479492

480-
def transform_affine(self, points):
481-
return self.transform(points)
482-
483493
def transform_non_affine(self, points):
484494
return points
485495

@@ -528,9 +538,11 @@ def transform(self, values):
528538
# print "".join(traceback.format_stack())
529539
# print points
530540
mtx = self.get_matrix()
531-
points = ma.asarray(values, npy.float_)
541+
points = npy.asarray(values, npy.float_)
532542
return points * mtx[0,0] + mtx[0,1]
533543

544+
transform_affine = transform
545+
534546
def inverted(self):
535547
if self._inverted is None:
536548
mtx = self.get_matrix()
@@ -575,7 +587,7 @@ def get_matrix(self):
575587
def set_matrix(self, mtx):
576588
self._mtx = mtx
577589
self.invalidate()
578-
590+
579591
def set(self, other):
580592
self._mtx = other.get_matrix()
581593
self.invalidate()
@@ -620,9 +632,11 @@ def __repr__(self):
620632
return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction))
621633
__str__ = __repr__
622634

623-
def _do_invalidation(self, which_child, affine_only):
635+
def _do_invalidation(self, affine_only):
636+
result = self._mtx is None
624637
self._mtx = None
625-
Affine1DBase._do_invalidation(self, which_child, affine_only)
638+
self._inverted = None
639+
return result
626640

627641
def get_matrix(self):
628642
if self._mtx is None:
@@ -678,12 +692,14 @@ def transform(self, points):
678692
# print "".join(traceback.format_stack())
679693
# print points
680694
mtx = self.get_matrix()
681-
points = ma.asarray(points, npy.float_)
695+
points = npy.asarray(points, npy.float_)
682696
points = points.transpose()
683-
points = ma.dot(mtx[0:2, 0:2], points)
697+
points = npy.dot(mtx[0:2, 0:2], points)
684698
points = points + mtx[0:2, 2:]
685699
return points.transpose()
686700

701+
transform_affine = transform
702+
687703
def inverted(self):
688704
if self._inverted is None:
689705
mtx = self.get_matrix()
@@ -801,19 +817,12 @@ def get_matrix(self):
801817

802818
def transform(self, points):
803819
return points
804-
805-
def transform_affine(self, points):
806-
return points
807-
808-
def transform_non_affine(self, points):
809-
return points
820+
transform_affine = transform_non_affine = transform
810821

811822
def get_affine(self):
812823
return self
824+
inverted = get_affine
813825

814-
def inverted(self):
815-
return self
816-
817826

818827
class BlendedGenericTransform(Transform):
819828
input_dims = 2
@@ -857,14 +866,12 @@ def transform(self, points):
857866
y_points = y.transform(points[:, 1])
858867
y_points = y_points.reshape((len(y_points), 1))
859868

860-
return ma.concatenate((x_points, y_points), 1)
861-
869+
return npy.concatenate((x_points, y_points), 1)
870+
transform_non_affine = transform
871+
862872
def transform_affine(self, points):
863873
return points
864874

865-
def transform_non_affine(self, points):
866-
return self.transform(points)
867-
868875
def get_affine(self):
869876
return IdentityTransform()
870877

@@ -892,9 +899,10 @@ def __repr__(self):
892899
return "BlendedAffine1D(%s,%s)" % (self._x, self._y)
893900
__str__ = __repr__
894901

895-
def _do_invalidation(self, which_child, affine_only):
902+
def _do_invalidation(self, affine_only):
903+
result = self._mtx is None
896904
self._mtx = None
897-
Affine2DBase._do_invalidation(self, which_child, affine_only)
905+
self._inverted = None
898906

899907
def get_matrix(self):
900908
if self._mtx is None:
@@ -928,9 +936,11 @@ def __repr__(self):
928936
return "BlendedAffine2D(%s,%s)" % (self._x, self._y)
929937
__str__ = __repr__
930938

931-
def _do_invalidation(self, which_child, affine_only):
939+
def _do_invalidation(self, affine_only):
940+
result = self._mtx is None
932941
self._mtx = None
933-
Affine2DBase._do_invalidation(self, which_child, affine_only)
942+
self._inverted = None
943+
return result
934944

935945
def get_matrix(self):
936946
if self._mtx is None:
@@ -985,7 +995,7 @@ def transform_non_affine(self, points):
985995
return self._b.transform_non_affine(self._a.transform_non_affine(points))
986996

987997
def get_affine(self):
988-
return self._a.get_affine() + self._b.get_affine()
998+
return CompositeAffine2D(self._a.get_affine(), self._b.get_affine())
989999

9901000
def inverted(self):
9911001
return CompositeGenericTransform(self._b.inverted(), self._a.inverted())
@@ -1009,9 +1019,11 @@ def __repr__(self):
10091019
return "CompositeAffine2D(%s, %s)" % (self._a, self._b)
10101020
__str__ = __repr__
10111021

1012-
def _do_invalidation(self, which_child, affine_only):
1022+
def _do_invalidation(self, affine_only):
1023+
result = self._mtx is None
10131024
self._mtx = None
1014-
Affine2DBase._do_invalidation(self, which_child, affine_only)
1025+
self._inverted = None
1026+
return result
10151027

10161028
def get_matrix(self):
10171029
if self._mtx is None:
@@ -1117,10 +1129,12 @@ def __repr__(self):
11171129
return "BboxTransform(%s, %s)" % (self._boxin, self._boxout)
11181130
__str__ = __repr__
11191131

1120-
def _do_invalidation(self, which_child, affine_only):
1132+
def _do_invalidation(self, affine_only):
1133+
result = self._mtx is None
11211134
self._mtx = None
1122-
Affine2DBase._do_invalidation(self, which_child, affine_only)
1123-
1135+
self._inverted = None
1136+
return result
1137+
11241138
def is_separable(self):
11251139
return True
11261140

@@ -1148,21 +1162,19 @@ def __init__(self, path, transform):
11481162

11491163
self._path = path
11501164
self._transform = transform
1151-
self.set_children(['_transform'])
11521165
self._transformed_path = None
1166+
self._last_id = transform.get_id()
11531167

1154-
def _do_invalidation(self, which_child, affine_only):
1155-
if not (affine_only[0].is_affine() or affine_only[0].is_bbox()):
1156-
self._transformed_path = None
1157-
11581168
def get_path_and_affine(self):
1159-
if self._transformed_path is None:
1169+
if (self._transformed_path is None or
1170+
self._last_id != self._transform.get_id()):
11601171
vertices = self._transform.transform_non_affine(self._path.vertices)
11611172
self._transformed_path = Path(vertices, self._path.codes)
11621173
return self._transformed_path, self._transform.get_affine()
11631174

11641175
def get_path(self):
1165-
if self._transformed_path is None:
1176+
if (self._transformed_path is None or
1177+
self._last_id != self._transform.get_id()):
11661178
vertices = self._tranform.transform_non_affine(self._path.vertices)
11671179
self._transformed_path = Path(vertices, self._path.codes)
11681180
vertices = self._transform.transform_affine(self._transformed_path.vertices)

0 commit comments

Comments
 (0)
0