16
16
17
17
18
18
class PolarTransform (mtransforms .Transform ):
19
- """
19
+ r """
20
20
The base polar transform.
21
21
22
- This transform maps polar coordinates ``(theta, r)`` into Cartesian
23
- coordinates ``(x, y) = (r * cos(theta), r * sin(theta))`` (but does not
22
+ This transform maps polar coordinates :math:`\theta, r` into Cartesian
23
+ coordinates :math:`x, y = r \cos(\theta), r \sin(\theta)`
24
+ (but does not fully transform into Axes coordinates or
24
25
handle positioning in screen space).
25
26
27
+ This transformation is designed to be applied to data after any scaling
28
+ along the radial axis (e.g. log-scaling) has been applied to the input
29
+ data.
30
+
26
31
Path segments at a fixed radius are automatically transformed to circular
27
32
arcs as long as ``path._interpolation_steps > 1``.
28
33
"""
29
34
30
35
input_dims = output_dims = 2
31
36
32
37
def __init__ (self , axis = None , use_rmin = True ,
33
- _apply_theta_transforms = True ):
38
+ _apply_theta_transforms = True , * , scale_transform = None ):
34
39
"""
35
40
Parameters
36
41
----------
@@ -46,12 +51,18 @@ def __init__(self, axis=None, use_rmin=True,
46
51
self ._axis = axis
47
52
self ._use_rmin = use_rmin
48
53
self ._apply_theta_transforms = _apply_theta_transforms
54
+ self ._scale_transform = scale_transform
49
55
50
56
__str__ = mtransforms ._make_str_method (
51
57
"_axis" ,
52
58
use_rmin = "_use_rmin" ,
53
59
_apply_theta_transforms = "_apply_theta_transforms" )
54
60
61
+ def _get_rorigin (self ):
62
+ # Get lower r limit after being scaled by the radial scale transform
63
+ return self ._scale_transform .transform (
64
+ (0 , self ._axis .get_rorigin ()))[1 ]
65
+
55
66
def transform_non_affine (self , tr ):
56
67
# docstring inherited
57
68
theta , r = np .transpose (tr )
@@ -61,7 +72,7 @@ def transform_non_affine(self, tr):
61
72
theta *= self ._axis .get_theta_direction ()
62
73
theta += self ._axis .get_theta_offset ()
63
74
if self ._use_rmin and self ._axis is not None :
64
- r = (r - self ._axis . get_rorigin ()) * self ._axis .get_rsign ()
75
+ r = (r - self ._get_rorigin ()) * self ._axis .get_rsign ()
65
76
r = np .where (r >= 0 , r , np .nan )
66
77
return np .column_stack ([r * np .cos (theta ), r * np .sin (theta )])
67
78
@@ -85,7 +96,7 @@ def transform_path_non_affine(self, path):
85
96
# that behavior here.
86
97
last_td , td = np .rad2deg ([last_t , t ])
87
98
if self ._use_rmin and self ._axis is not None :
88
- r = ((r - self ._axis . get_rorigin ())
99
+ r = ((r - self ._get_rorigin ())
89
100
* self ._axis .get_rsign ())
90
101
if last_td <= td :
91
102
while td - last_td > 360 :
@@ -877,7 +888,9 @@ def _set_lim_and_transforms(self):
877
888
# data. This one is aware of rmin
878
889
self .transProjection = self .PolarTransform (
879
890
self ,
880
- _apply_theta_transforms = False )
891
+ _apply_theta_transforms = False ,
892
+ scale_transform = self .transScale
893
+ )
881
894
# Add dependency on rorigin.
882
895
self .transProjection .set_children (self ._originViewLim )
883
896
@@ -888,9 +901,25 @@ def _set_lim_and_transforms(self):
888
901
889
902
# The complete data transformation stack -- from data all the
890
903
# way to display coordinates
904
+ #
905
+ # 1. Remove any radial axis scaling (e.g. log scaling)
906
+ # 2. Shift data in the theta direction
907
+ # 3. Project the data from polar to cartesian values
908
+ # (with the origin in the same place)
909
+ # 4. Scale and translate the cartesian values to Axes coordinates
910
+ # (here the origin is moved to the lower left of the Axes)
911
+ # 5. Move and scale to fill the Axes
912
+ # 6. Convert from Axes coordinates to Figure coordinates
891
913
self .transData = (
892
- self .transScale + self .transShift + self .transProjection +
893
- (self .transProjectionAffine + self .transWedge + self .transAxes ))
914
+ self .transScale +
915
+ self .transShift +
916
+ self .transProjection +
917
+ (
918
+ self .transProjectionAffine +
919
+ self .transWedge +
920
+ self .transAxes
921
+ )
922
+ )
894
923
895
924
# This is the transform for theta-axis ticks. It is
896
925
# equivalent to transData, except it always puts r == 0.0 and r == 1.0
0 commit comments