Skip to content

Commit 07d2e94

Browse files
authored
Merge pull request #9421 from anntzer/transforms-repr
Improve reprs of transforms.
2 parents a5ce728 + dbefd27 commit 07d2e94

File tree

4 files changed

+211
-161
lines changed

4 files changed

+211
-161
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Improved `repr` for `Transform`\s
2+
---------------------------------
3+
4+
`Transform`\s now indent their `repr`\s in a more legible manner:
5+
6+
.. code-block:: ipython
7+
8+
In [1]: l, = plt.plot([]); l.get_transform()
9+
Out[1]:
10+
CompositeGenericTransform(
11+
TransformWrapper(
12+
BlendedAffine2D(
13+
IdentityTransform(),
14+
IdentityTransform())),
15+
CompositeGenericTransform(
16+
BboxTransformFrom(
17+
TransformedBbox(
18+
Bbox(x0=-0.05500000000000001, y0=-0.05500000000000001, x1=0.05500000000000001, y1=0.05500000000000001),
19+
TransformWrapper(
20+
BlendedAffine2D(
21+
IdentityTransform(),
22+
IdentityTransform())))),
23+
BboxTransformTo(
24+
TransformedBbox(
25+
Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),
26+
BboxTransformTo(
27+
TransformedBbox(
28+
Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),
29+
Affine2D(
30+
[[ 100. 0. 0.]
31+
[ 0. 100. 0.]
32+
[ 0. 0. 1.]])))))))

lib/matplotlib/projections/geo.py

Lines changed: 42 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@
1717
import matplotlib.spines as mspines
1818
import matplotlib.axis as maxis
1919
from matplotlib.ticker import Formatter, Locator, NullLocator, FixedLocator, NullFormatter
20-
from matplotlib.transforms import Affine2D, Affine2DBase, Bbox, \
21-
BboxTransformTo, IdentityTransform, Transform, TransformWrapper
20+
from matplotlib.transforms import Affine2D, BboxTransformTo, Transform
21+
2222

2323
class GeoAxes(Axes):
24-
"""
25-
An abstract base class for geographic projections
26-
"""
24+
"""An abstract base class for geographic projections."""
2725
class ThetaFormatter(Formatter):
2826
"""
2927
Used to format the theta tick labels. Converts the native
@@ -248,25 +246,37 @@ def drag_pan(self, button, key, x, y):
248246
pass
249247

250248

251-
class AitoffAxes(GeoAxes):
252-
name = 'aitoff'
249+
class _GeoTransform(Transform):
250+
# Factoring out some common functionality.
251+
input_dims = 2
252+
output_dims = 2
253+
is_separable = False
253254

254-
class AitoffTransform(Transform):
255+
def __init__(self, resolution):
255256
"""
256-
The base Aitoff transform.
257+
Create a new geographical transform.
258+
259+
Resolution is the number of steps to interpolate between each input
260+
line segment to approximate its path in curved space.
257261
"""
258-
input_dims = 2
259-
output_dims = 2
260-
is_separable = False
262+
Transform.__init__(self)
263+
self._resolution = resolution
264+
265+
def __str__(self):
266+
return "{}({})".format(type(self).__name__, self._resolution)
267+
268+
def transform_path_non_affine(self, path):
269+
vertices = path.vertices
270+
ipath = path.interpolated(self._resolution)
271+
return Path(self.transform(ipath.vertices), ipath.codes)
272+
transform_path_non_affine.__doc__ = Transform.transform_path_non_affine.__doc__
261273

262-
def __init__(self, resolution):
263-
"""
264-
Create a new Aitoff transform. Resolution is the number of steps
265-
to interpolate between each input line segment to approximate its
266-
path in curved Aitoff space.
267-
"""
268-
Transform.__init__(self)
269-
self._resolution = resolution
274+
275+
class AitoffAxes(GeoAxes):
276+
name = 'aitoff'
277+
278+
class AitoffTransform(_GeoTransform):
279+
"""The base Aitoff transform."""
270280

271281
def transform_non_affine(self, ll):
272282
longitude = ll[:, 0]
@@ -288,24 +298,11 @@ def transform_non_affine(self, ll):
288298
return xy
289299
transform_non_affine.__doc__ = Transform.transform_non_affine.__doc__
290300

291-
def transform_path_non_affine(self, path):
292-
vertices = path.vertices
293-
ipath = path.interpolated(self._resolution)
294-
return Path(self.transform(ipath.vertices), ipath.codes)
295-
transform_path_non_affine.__doc__ = Transform.transform_path_non_affine.__doc__
296-
297301
def inverted(self):
298302
return AitoffAxes.InvertedAitoffTransform(self._resolution)
299303
inverted.__doc__ = Transform.inverted.__doc__
300304

301-
class InvertedAitoffTransform(Transform):
302-
input_dims = 2
303-
output_dims = 2
304-
is_separable = False
305-
306-
def __init__(self, resolution):
307-
Transform.__init__(self)
308-
self._resolution = resolution
305+
class InvertedAitoffTransform(_GeoTransform):
309306

310307
def transform_non_affine(self, xy):
311308
# MGDTODO: Math is hard ;(
@@ -329,22 +326,8 @@ def _get_core_transform(self, resolution):
329326
class HammerAxes(GeoAxes):
330327
name = 'hammer'
331328

332-
class HammerTransform(Transform):
333-
"""
334-
The base Hammer transform.
335-
"""
336-
input_dims = 2
337-
output_dims = 2
338-
is_separable = False
339-
340-
def __init__(self, resolution):
341-
"""
342-
Create a new Hammer transform. Resolution is the number of steps
343-
to interpolate between each input line segment to approximate its
344-
path in curved Hammer space.
345-
"""
346-
Transform.__init__(self)
347-
self._resolution = resolution
329+
class HammerTransform(_GeoTransform):
330+
"""The base Hammer transform."""
348331

349332
def transform_non_affine(self, ll):
350333
longitude = ll[:, 0:1]
@@ -361,24 +344,11 @@ def transform_non_affine(self, ll):
361344
return np.concatenate((x, y), 1)
362345
transform_non_affine.__doc__ = Transform.transform_non_affine.__doc__
363346

364-
def transform_path_non_affine(self, path):
365-
vertices = path.vertices
366-
ipath = path.interpolated(self._resolution)
367-
return Path(self.transform(ipath.vertices), ipath.codes)
368-
transform_path_non_affine.__doc__ = Transform.transform_path_non_affine.__doc__
369-
370347
def inverted(self):
371348
return HammerAxes.InvertedHammerTransform(self._resolution)
372349
inverted.__doc__ = Transform.inverted.__doc__
373350

374-
class InvertedHammerTransform(Transform):
375-
input_dims = 2
376-
output_dims = 2
377-
is_separable = False
378-
379-
def __init__(self, resolution):
380-
Transform.__init__(self)
381-
self._resolution = resolution
351+
class InvertedHammerTransform(_GeoTransform):
382352

383353
def transform_non_affine(self, xy):
384354
x, y = xy.T
@@ -405,22 +375,8 @@ def _get_core_transform(self, resolution):
405375
class MollweideAxes(GeoAxes):
406376
name = 'mollweide'
407377

408-
class MollweideTransform(Transform):
409-
"""
410-
The base Mollweide transform.
411-
"""
412-
input_dims = 2
413-
output_dims = 2
414-
is_separable = False
415-
416-
def __init__(self, resolution):
417-
"""
418-
Create a new Mollweide transform. Resolution is the number of steps
419-
to interpolate between each input line segment to approximate its
420-
path in curved Mollweide space.
421-
"""
422-
Transform.__init__(self)
423-
self._resolution = resolution
378+
class MollweideTransform(_GeoTransform):
379+
"""The base Mollweide transform."""
424380

425381
def transform_non_affine(self, ll):
426382
def d(theta):
@@ -456,24 +412,11 @@ def d(theta):
456412
return xy
457413
transform_non_affine.__doc__ = Transform.transform_non_affine.__doc__
458414

459-
def transform_path_non_affine(self, path):
460-
vertices = path.vertices
461-
ipath = path.interpolated(self._resolution)
462-
return Path(self.transform(ipath.vertices), ipath.codes)
463-
transform_path_non_affine.__doc__ = Transform.transform_path_non_affine.__doc__
464-
465415
def inverted(self):
466416
return MollweideAxes.InvertedMollweideTransform(self._resolution)
467417
inverted.__doc__ = Transform.inverted.__doc__
468418

469-
class InvertedMollweideTransform(Transform):
470-
input_dims = 2
471-
output_dims = 2
472-
is_separable = False
473-
474-
def __init__(self, resolution):
475-
Transform.__init__(self)
476-
self._resolution = resolution
419+
class InvertedMollweideTransform(_GeoTransform):
477420

478421
def transform_non_affine(self, xy):
479422
x = xy[:, 0:1]
@@ -505,22 +448,16 @@ def _get_core_transform(self, resolution):
505448
class LambertAxes(GeoAxes):
506449
name = 'lambert'
507450

508-
class LambertTransform(Transform):
509-
"""
510-
The base Lambert transform.
511-
"""
512-
input_dims = 2
513-
output_dims = 2
514-
is_separable = False
451+
class LambertTransform(_GeoTransform):
452+
"""The base Lambert transform."""
515453

516454
def __init__(self, center_longitude, center_latitude, resolution):
517455
"""
518456
Create a new Lambert transform. Resolution is the number of steps
519457
to interpolate between each input line segment to approximate its
520458
path in curved Lambert space.
521459
"""
522-
Transform.__init__(self)
523-
self._resolution = resolution
460+
_GeoTransform.__init__(self, resolution)
524461
self._center_longitude = center_longitude
525462
self._center_latitude = center_latitude
526463

@@ -547,27 +484,17 @@ def transform_non_affine(self, ll):
547484
return np.concatenate((x, y), 1)
548485
transform_non_affine.__doc__ = Transform.transform_non_affine.__doc__
549486

550-
def transform_path_non_affine(self, path):
551-
vertices = path.vertices
552-
ipath = path.interpolated(self._resolution)
553-
return Path(self.transform(ipath.vertices), ipath.codes)
554-
transform_path_non_affine.__doc__ = Transform.transform_path_non_affine.__doc__
555-
556487
def inverted(self):
557488
return LambertAxes.InvertedLambertTransform(
558489
self._center_longitude,
559490
self._center_latitude,
560491
self._resolution)
561492
inverted.__doc__ = Transform.inverted.__doc__
562493

563-
class InvertedLambertTransform(Transform):
564-
input_dims = 2
565-
output_dims = 2
566-
is_separable = False
494+
class InvertedLambertTransform(_GeoTransform):
567495

568496
def __init__(self, center_longitude, center_latitude, resolution):
569-
Transform.__init__(self)
570-
self._resolution = resolution
497+
_GeoTransform.__init__(self, resolution)
571498
self._center_longitude = center_longitude
572499
self._center_latitude = center_latitude
573500

lib/matplotlib/projections/polar.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ def __init__(self, axis=None, use_rmin=True,
3939
self._use_rmin = use_rmin
4040
self._apply_theta_transforms = _apply_theta_transforms
4141

42+
def __str__(self):
43+
return ("{}(\n"
44+
"{},\n"
45+
" use_rmin={},\n"
46+
" _apply_theta_transforms={})"
47+
.format(type(self).__name__,
48+
mtransforms._indent_str(self._axis),
49+
self._use_rmin,
50+
self._apply_theta_transforms))
51+
4252
def transform_non_affine(self, tr):
4353
xy = np.empty(tr.shape, float)
4454

@@ -95,6 +105,14 @@ def __init__(self, scale_transform, limits):
95105
self.set_children(scale_transform, limits)
96106
self._mtx = None
97107

108+
def __str__(self):
109+
return ("{}(\n"
110+
"{},\n"
111+
"{})"
112+
.format(type(self).__name__,
113+
mtransforms._indent_str(self._scale_transform),
114+
mtransforms._indent_str(self._limits)))
115+
98116
def get_matrix(self):
99117
if self._invalid:
100118
limits_scaled = self._limits.transformed(self._scale_transform)
@@ -125,6 +143,16 @@ def __init__(self, axis=None, use_rmin=True,
125143
self._use_rmin = use_rmin
126144
self._apply_theta_transforms = _apply_theta_transforms
127145

146+
def __str__(self):
147+
return ("{}(\n"
148+
"{},\n"
149+
" use_rmin={},\n"
150+
" _apply_theta_transforms={})"
151+
.format(type(self).__name__,
152+
mtransforms._indent_str(self._axis),
153+
self._use_rmin,
154+
self._apply_theta_transforms))
155+
128156
def transform_non_affine(self, xy):
129157
x = xy[:, 0:1]
130158
y = xy[:, 1:]
@@ -459,6 +487,16 @@ def __init__(self, axes, pad, mode):
459487
self.mode = mode
460488
self.pad = pad
461489

490+
def __str__(self):
491+
return ("{}(\n"
492+
"{},\n"
493+
"{},\n"
494+
"{})"
495+
.format(type(self).__name__,
496+
mtransforms._indent_str(self.axes),
497+
mtransforms._indent_str(self.pad),
498+
mtransforms._indent_str(repr(self.mode))))
499+
462500
def get_matrix(self):
463501
if self._invalid:
464502
if self.mode == 'rlabel':
@@ -697,9 +735,15 @@ def __init__(self, center, viewLim, originLim, **kwargs):
697735
self._originLim = originLim
698736
self.set_children(viewLim, originLim)
699737

700-
def __repr__(self):
701-
return "_WedgeBbox(%r, %r, %r)" % (self._center, self._viewLim,
702-
self._originLim)
738+
def __str__(self):
739+
return ("{}(\n"
740+
"{},\n"
741+
"{},\n"
742+
"{})"
743+
.format(type(self).__name__,
744+
mtransforms._indent_str(self._center),
745+
mtransforms._indent_str(self._viewLim),
746+
mtransforms._indent_str(self._originLim)))
703747

704748
def get_points(self):
705749
if self._invalid:

0 commit comments

Comments
 (0)