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 81ba63f

Browse filesBrowse files
authored
Merge pull request #24960 from meeseeksmachine/auto-backport-of-pr-24825-on-v3.7.x
Backport PR #24825 on branch v3.7.x (Allow non-default scales on polar axes)
2 parents 7ffc3e4 + 9b30fdf commit 81ba63f
Copy full SHA for 81ba63f

File tree

Expand file treeCollapse file tree

3 files changed

+50
-9
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+50
-9
lines changed

‎lib/matplotlib/projections/polar.py

Copy file name to clipboardExpand all lines: lib/matplotlib/projections/polar.py
+38-9Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,26 @@
1616

1717

1818
class PolarTransform(mtransforms.Transform):
19-
"""
19+
r"""
2020
The base polar transform.
2121
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
2425
handle positioning in screen space).
2526
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+
2631
Path segments at a fixed radius are automatically transformed to circular
2732
arcs as long as ``path._interpolation_steps > 1``.
2833
"""
2934

3035
input_dims = output_dims = 2
3136

3237
def __init__(self, axis=None, use_rmin=True,
33-
_apply_theta_transforms=True):
38+
_apply_theta_transforms=True, *, scale_transform=None):
3439
"""
3540
Parameters
3641
----------
@@ -46,12 +51,18 @@ def __init__(self, axis=None, use_rmin=True,
4651
self._axis = axis
4752
self._use_rmin = use_rmin
4853
self._apply_theta_transforms = _apply_theta_transforms
54+
self._scale_transform = scale_transform
4955

5056
__str__ = mtransforms._make_str_method(
5157
"_axis",
5258
use_rmin="_use_rmin",
5359
_apply_theta_transforms="_apply_theta_transforms")
5460

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+
5566
def transform_non_affine(self, tr):
5667
# docstring inherited
5768
theta, r = np.transpose(tr)
@@ -61,7 +72,7 @@ def transform_non_affine(self, tr):
6172
theta *= self._axis.get_theta_direction()
6273
theta += self._axis.get_theta_offset()
6374
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()
6576
r = np.where(r >= 0, r, np.nan)
6677
return np.column_stack([r * np.cos(theta), r * np.sin(theta)])
6778

@@ -85,7 +96,7 @@ def transform_path_non_affine(self, path):
8596
# that behavior here.
8697
last_td, td = np.rad2deg([last_t, t])
8798
if self._use_rmin and self._axis is not None:
88-
r = ((r - self._axis.get_rorigin())
99+
r = ((r - self._get_rorigin())
89100
* self._axis.get_rsign())
90101
if last_td <= td:
91102
while td - last_td > 360:
@@ -877,7 +888,9 @@ def _set_lim_and_transforms(self):
877888
# data. This one is aware of rmin
878889
self.transProjection = self.PolarTransform(
879890
self,
880-
_apply_theta_transforms=False)
891+
_apply_theta_transforms=False,
892+
scale_transform=self.transScale
893+
)
881894
# Add dependency on rorigin.
882895
self.transProjection.set_children(self._originViewLim)
883896

@@ -888,9 +901,25 @@ def _set_lim_and_transforms(self):
888901

889902
# The complete data transformation stack -- from data all the
890903
# 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
891913
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+
)
894923

895924
# This is the transform for theta-axis ticks. It is
896925
# equivalent to transData, except it always puts r == 0.0 and r == 1.0
Loading

‎lib/matplotlib/tests/test_polar.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_polar.py
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,15 @@ def test_cursor_precision():
434434
assert ax.format_coord(2, 0) == "θ=0.6π (115°), r=0.000"
435435
assert ax.format_coord(2, .1) == "θ=0.64π (115°), r=0.100"
436436
assert ax.format_coord(2, 1) == "θ=0.637π (114.6°), r=1.000"
437+
438+
439+
@image_comparison(['polar_log.png'], style='default')
440+
def test_polar_log():
441+
fig = plt.figure()
442+
ax = fig.add_subplot(polar=True)
443+
444+
ax.set_rscale('log')
445+
ax.set_rlim(1, 1000)
446+
447+
n = 100
448+
ax.plot(np.linspace(0, 2 * np.pi, n), np.logspace(0, 2, n))

0 commit comments

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