Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 88e40cb

Browse filesBrowse files
committed
Micro-optimize transforms, copy given array upon transform initialization.
Fix revealed bug in backend bases, save some transformation copys
1 parent 005c7a6 commit 88e40cb
Copy full SHA for 88e40cb

File tree

Expand file treeCollapse file tree

3 files changed

+36
-32
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+36
-32
lines changed

‎lib/matplotlib/backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backend_bases.py
+8-9Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343

4444
import matplotlib as mpl
4545
from matplotlib import (
46-
backend_tools as tools, cbook, colors, textpath, tight_bbox, transforms,
47-
widgets, get_backend, is_interactive, rcParams)
46+
backend_tools as tools, cbook, colors, textpath, tight_bbox,
47+
transforms, widgets, get_backend, is_interactive, rcParams)
4848
from matplotlib._pylab_helpers import Gcf
4949
from matplotlib.backend_managers import ToolManager
5050
from matplotlib.transforms import Affine2D
@@ -220,18 +220,17 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms,
220220
recommended to use those generators, so that changes to the
221221
behavior of :meth:`draw_path_collection` can be made globally.
222222
"""
223-
path_ids = [
224-
(path, transforms.Affine2D(transform))
225-
for path, transform in self._iter_collection_raw_paths(
226-
master_transform, paths, all_transforms)]
223+
path_ids = self._iter_collection_raw_paths(master_transform,
224+
paths, all_transforms)
227225

228226
for xo, yo, path_id, gc0, rgbFace in self._iter_collection(
229-
gc, master_transform, all_transforms, path_ids, offsets,
227+
gc, master_transform, all_transforms, list(path_ids), offsets,
230228
offsetTrans, facecolors, edgecolors, linewidths, linestyles,
231229
antialiaseds, urls, offset_position):
232230
path, transform = path_id
233-
transform = transforms.Affine2D(
234-
transform.get_matrix()).translate(xo, yo)
231+
if xo != 0 or yo != 0:
232+
transform = transform.frozen()
233+
transform.translate(xo, yo)
235234
self.draw_path(gc0, path, transform, rgbFace)
236235

237236
def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight,

‎lib/matplotlib/tests/test_backend_bases.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_backend_bases.py
+11-10Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
def test_uses_per_path():
1515
id = transforms.Affine2D()
1616
paths = [path.Path.unit_regular_polygon(i) for i in range(3, 7)]
17-
tforms = [id.rotate(i) for i in range(1, 5)]
17+
tforms_matrices = [id.rotate(i).get_matrix().copy() for i in range(1, 5)]
1818
offsets = np.arange(20).reshape((10, 2))
1919
facecolors = ['red', 'green']
2020
edgecolors = ['red', 'green']
@@ -37,17 +37,18 @@ def check(master_transform, paths, all_transforms,
3737
seen = np.bincount(ids, minlength=len(raw_paths))
3838
assert set(seen).issubset([uses - 1, uses])
3939

40-
check(id, paths, tforms, offsets, facecolors, edgecolors)
41-
check(id, paths[0:1], tforms, offsets, facecolors, edgecolors)
42-
check(id, [], tforms, offsets, facecolors, edgecolors)
43-
check(id, paths, tforms[0:1], offsets, facecolors, edgecolors)
40+
check(id, paths, tforms_matrices, offsets, facecolors, edgecolors)
41+
check(id, paths[0:1], tforms_matrices, offsets, facecolors, edgecolors)
42+
check(id, [], tforms_matrices, offsets, facecolors, edgecolors)
43+
check(id, paths, tforms_matrices[0:1], offsets, facecolors, edgecolors)
4444
check(id, paths, [], offsets, facecolors, edgecolors)
4545
for n in range(0, offsets.shape[0]):
46-
check(id, paths, tforms, offsets[0:n, :], facecolors, edgecolors)
47-
check(id, paths, tforms, offsets, [], edgecolors)
48-
check(id, paths, tforms, offsets, facecolors, [])
49-
check(id, paths, tforms, offsets, [], [])
50-
check(id, paths, tforms, offsets, facecolors[0:1], edgecolors)
46+
check(id, paths, tforms_matrices, offsets[0:n, :],
47+
facecolors, edgecolors)
48+
check(id, paths, tforms_matrices, offsets, [], edgecolors)
49+
check(id, paths, tforms_matrices, offsets, facecolors, [])
50+
check(id, paths, tforms_matrices, offsets, [], [])
51+
check(id, paths, tforms_matrices, offsets, facecolors[0:1], edgecolors)
5152

5253

5354
def test_get_default_filename(tmpdir):

‎lib/matplotlib/transforms.py

Copy file name to clipboardExpand all lines: lib/matplotlib/transforms.py
+17-13Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import functools
3737
import textwrap
3838
import weakref
39+
import math
3940

4041
import numpy as np
4142
from numpy.linalg import inv
@@ -1831,7 +1832,7 @@ def __init__(self, matrix=None, **kwargs):
18311832
if matrix is None:
18321833
# A bit faster than np.identity(3).
18331834
matrix = IdentityTransform._mtx.copy()
1834-
self._mtx = matrix
1835+
self._mtx = matrix.copy()
18351836
self._invalid = 0
18361837

18371838
__str__ = _make_str_method("_mtx")
@@ -1914,8 +1915,8 @@ def rotate(self, theta):
19141915
calls to :meth:`rotate`, :meth:`rotate_deg`, :meth:`translate`
19151916
and :meth:`scale`.
19161917
"""
1917-
a = np.cos(theta)
1918-
b = np.sin(theta)
1918+
a = math.cos(theta)
1919+
b = math.sin(theta)
19191920
rotate_mtx = np.array([[a, -b, 0.0], [b, a, 0.0], [0.0, 0.0, 1.0]],
19201921
float)
19211922
self._mtx = np.dot(rotate_mtx, self._mtx)
@@ -1930,7 +1931,7 @@ def rotate_deg(self, degrees):
19301931
calls to :meth:`rotate`, :meth:`rotate_deg`, :meth:`translate`
19311932
and :meth:`scale`.
19321933
"""
1933-
return self.rotate(np.deg2rad(degrees))
1934+
return self.rotate(math.radians(degrees))
19341935

19351936
def rotate_around(self, x, y, theta):
19361937
"""
@@ -1962,9 +1963,8 @@ def translate(self, tx, ty):
19621963
calls to :meth:`rotate`, :meth:`rotate_deg`, :meth:`translate`
19631964
and :meth:`scale`.
19641965
"""
1965-
translate_mtx = np.array(
1966-
[[1.0, 0.0, tx], [0.0, 1.0, ty], [0.0, 0.0, 1.0]], float)
1967-
self._mtx = np.dot(translate_mtx, self._mtx)
1966+
self._mtx[0, 2] += tx
1967+
self._mtx[1, 2] += ty
19681968
self.invalidate()
19691969
return self
19701970

@@ -1981,9 +1981,13 @@ def scale(self, sx, sy=None):
19811981
"""
19821982
if sy is None:
19831983
sy = sx
1984-
scale_mtx = np.array(
1985-
[[sx, 0.0, 0.0], [0.0, sy, 0.0], [0.0, 0.0, 1.0]], float)
1986-
self._mtx = np.dot(scale_mtx, self._mtx)
1984+
# explicit element-wise scaling is fastest
1985+
self._mtx[0, 0] *= sx
1986+
self._mtx[0, 1] *= sx
1987+
self._mtx[0, 2] *= sx
1988+
self._mtx[1, 0] *= sy
1989+
self._mtx[1, 1] *= sy
1990+
self._mtx[1, 2] *= sy
19871991
self.invalidate()
19881992
return self
19891993

@@ -1998,8 +2002,8 @@ def skew(self, xShear, yShear):
19982002
calls to :meth:`rotate`, :meth:`rotate_deg`, :meth:`translate`
19992003
and :meth:`scale`.
20002004
"""
2001-
rotX = np.tan(xShear)
2002-
rotY = np.tan(yShear)
2005+
rotX = math.tan(xShear)
2006+
rotY = math.tan(yShear)
20032007
skew_mtx = np.array(
20042008
[[1.0, rotX, 0.0], [rotY, 1.0, 0.0], [0.0, 0.0, 1.0]], float)
20052009
self._mtx = np.dot(skew_mtx, self._mtx)
@@ -2017,7 +2021,7 @@ def skew_deg(self, xShear, yShear):
20172021
calls to :meth:`rotate`, :meth:`rotate_deg`, :meth:`translate`
20182022
and :meth:`scale`.
20192023
"""
2020-
return self.skew(np.deg2rad(xShear), np.deg2rad(yShear))
2024+
return self.skew(math.radians(xShear), math.radians(yShear))
20212025

20222026

20232027
class IdentityTransform(Affine2DBase):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.