Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix 29381 title position #29391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions lib/cartopy/mpl/geoaxes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from matplotlib.axes import Axes

class GeoAxes(Axes):

Check failure on line 3 in lib/cartopy/mpl/geoaxes.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 E302 expected 2 blank lines, found 1 Raw Output: ./lib/cartopy/mpl/geoaxes.py:3:1: E302 expected 2 blank lines, found 1
def get_title_top(self) -> float:
"""
Calculate the top position of the title for geographic projections.

Returns
-------
float
The top edge position of the title in axis coordinates,
adjusted for geographic projection.
"""
base_top = super().get_title_top()
if self.projection.is_geodetic():
return base_top + 0.02
return base_top

Check failure on line 17 in lib/cartopy/mpl/geoaxes.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 W291 trailing whitespace Raw Output: ./lib/cartopy/mpl/geoaxes.py:17:24: W291 trailing whitespace

Check failure on line 17 in lib/cartopy/mpl/geoaxes.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 W292 no newline at end of file Raw Output: ./lib/cartopy/mpl/geoaxes.py:17:25: W292 no newline at end of file
58 changes: 52 additions & 6 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,8 @@

# Looks like we don't want "color" to be interpreted to
# mean both facecolor and edgecolor for some reason.
# So the "kw" dictionary is thrown out, and only its
# 'color' value is kept and translated as a 'facecolor'.
# So the "kw" dictionary is thrown out, and only its 'color' value is
# kept and translated as a 'facecolor'.
# This design should probably be revisited as it increases
# complexity.
facecolor = kw.get('color', None)
Expand Down Expand Up @@ -3617,7 +3617,7 @@
xaxis_inverted = _axis_method_wrapper("xaxis", "get_inverted")
if xaxis_inverted.__doc__:
xaxis_inverted.__doc__ = ("[*Discouraged*] " + xaxis_inverted.__doc__ +
textwrap.dedent("""
textwrap.dedent("""

Check failure on line 3620 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 E128 continuation line under-indented for visual indent Raw Output: ./lib/matplotlib/axes/_base.py:3620:34: E128 continuation line under-indented for visual indent

.. admonition:: Discouraged

Expand Down Expand Up @@ -3846,9 +3846,9 @@
if {*kwargs} & {*protected_kw}:
if loc is not None:
raise TypeError(f"Specifying 'loc' is disallowed when any of "
f"its corresponding low level keyword "
f"arguments ({protected_kw}) are also "
f"supplied")
f"its corresponding low level keyword "

Check failure on line 3849 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 E128 continuation line under-indented for visual indent Raw Output: ./lib/matplotlib/axes/_base.py:3849:32: E128 continuation line under-indented for visual indent
f"arguments ({protected_kw}) are also "

Check failure on line 3850 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 E128 continuation line under-indented for visual indent Raw Output: ./lib/matplotlib/axes/_base.py:3850:32: E128 continuation line under-indented for visual indent
f"supplied")

Check failure on line 3851 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 E128 continuation line under-indented for visual indent Raw Output: ./lib/matplotlib/axes/_base.py:3851:32: E128 continuation line under-indented for visual indent

else:
loc = mpl._val_or_rc(loc, 'yaxis.labellocation')
Expand Down Expand Up @@ -4764,6 +4764,52 @@
"""Get how pan/zoom events are forwarded to Axes below this one."""
return self._forward_navigation_events

def get_title_top(self) -> float:
"""
Calculate the top position of the title.

Returns
-------
float
The top edge position of the title in axis coordinates.

Notes
-----
This method can be overridden by subclasses (e.g., PolarAxes or GeoAxes)
for custom title positioning.
"""
bbox = self.get_position()

Check failure on line 4782 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 W293 blank line contains whitespace Raw Output: ./lib/matplotlib/axes/_base.py:4782:1: W293 blank line contains whitespace
# Current padding and other calculations
pad = self._axislines_get_title_offset() if self._axislines else 0
top = bbox.ymax + pad

Check warning on line 4785 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4785

Added line #L4785 was not covered by tests

Check failure on line 4786 in lib/matplotlib/axes/_base.py

View workflow job for this annotation

GitHub Actions / flake8

[flake8] reported by reviewdog 🐶 W293 blank line contains whitespace Raw Output: ./lib/matplotlib/axes/_base.py:4786:1: W293 blank line contains whitespace
# Additional adjustments (e.g. for tight_layout)
if self._tight:
top += self._get_tight_layout_padding()

Check warning on line 4789 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4789

Added line #L4789 was not covered by tests

return top

Check warning on line 4791 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4791

Added line #L4791 was not covered by tests

def _adjust_title_position(self, title, renderer):
"""
Adjust the position of the title.

Parameters
----------
title : matplotlib.text.Text
The title text instance
renderer : matplotlib.backend_bases.RendererBase
The renderer
"""
# Get the top position from the new method
top = self.get_title_top()

Check warning on line 4805 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4805

Added line #L4805 was not covered by tests

# Set the title position
title.set_position((0.5, top))

Check warning on line 4808 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4808

Added line #L4808 was not covered by tests

# Update the title layout
title.update_bbox_position_size(renderer)

Check warning on line 4811 in lib/matplotlib/axes/_base.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4811

Added line #L4811 was not covered by tests


def _draw_rasterized(figure, artists, renderer):
"""
Expand Down
16 changes: 16 additions & 0 deletions lib/matplotlib/projections/polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,22 @@
scale = r / startr
self.set_rmax(p.rmax / scale)

def get_title_top(self) -> float:
"""
Calculate the top position of the title for polar axes.

Returns
-------
float
The top edge position of the title in axis coordinates,
adjusted for polar projection.
"""
base_top = super().get_title_top()
theta_direction = -1 if self.get_theta_direction() < 0 else 1
theta_offset = np.deg2rad(self.get_theta_offset())
polar_adjustment = 0.05 * theta_direction * np.cos(theta_offset)
return base_top + polar_adjustment

Check warning on line 1559 in lib/matplotlib/projections/polar.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/projections/polar.py#L1555-L1559

Added lines #L1555 - L1559 were not covered by tests


# To keep things all self-contained, we can put aliases to the Polar classes
# defined above. This isn't strictly necessary, but it makes some of the
Expand Down
8 changes: 8 additions & 0 deletions lib/matplotlib/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
from matplotlib.testing.conftest import ( # noqa
mpl_test_settings, pytest_configure, pytest_unconfigure, pd, xr)
import pytest

@pytest.fixture
def mock_axes():
class MockAxes:
def get_title_top(self):
return 1.0
return MockAxes()

Check warning on line 10 in lib/matplotlib/tests/conftest.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/conftest.py#L7-L10

Added lines #L7 - L10 were not covered by tests
48 changes: 29 additions & 19 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,7 @@
ax2.plot(x, y1, x, y2, color='black')
ax2.fill_between(x, y1, y2, where=y2 >= y1, facecolor='green',
interpolate=True)
ax2.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red',
ax2.fill_between(x, y1, y2, where=y1 >= y2, facecolor='red',
interpolate=True)


Expand Down Expand Up @@ -2380,7 +2380,7 @@
rng = np.random.RandomState(57483)
t = rng.randn(100)
bins = [-3, -1, -0.5, 0, 1, 5]
mpl_heights, _, _ = plt.hist(t, bins=bins, density=True)
mpl_heights, _ = np.histogram(t, bins=bins, density=True)
np_heights, _ = np.histogram(t, bins=bins, density=True)
assert_allclose(mpl_heights, np_heights)

Expand Down Expand Up @@ -2475,14 +2475,14 @@

ref_axes = fig_ref.subplots(3, 2).flatten()
ref_axes[0].plot(x, np.append(y, y[-1]), drawstyle='steps-post', **style)
ref_axes[1].plot(np.append(y[0], y), x, drawstyle='steps-post', **style)
ref_axes[1].plot(np.append(y, y[-1]), x, drawstyle='steps-post', **style)

ref_axes[2].plot(x, np.append(y, y[-1]), drawstyle='steps-post', **style)
ref_axes[2].add_line(mlines.Line2D([x[0], x[0]], [0, y[0]], **style))
ref_axes[2].add_line(mlines.Line2D([x[-1], x[-1]], [0, y[-1]], **style))
ref_axes[2].set_ylim(0, None)

ref_axes[3].plot(np.append(y[0], y), x, drawstyle='steps-post', **style)
ref_axes[3].plot(np.append(y, y[-1]), x, drawstyle='steps-post', **style)
ref_axes[3].add_line(mlines.Line2D([0, y[0]], [x[0], x[0]], **style))
ref_axes[3].add_line(mlines.Line2D([0, y[-1]], [x[-1], x[-1]], **style))
ref_axes[3].set_xlim(0, None)
Expand All @@ -2492,7 +2492,7 @@
ref_axes[4].add_line(mlines.Line2D([x[-1], x[-1]], [0, y[-1]], **style))
ref_axes[4].semilogy()

ref_axes[5].plot(np.append(y[0], y), x, drawstyle='steps-post', **style)
ref_axes[5].plot(np.append(y, y[-1]), x, drawstyle='steps-post', **style)
ref_axes[5].add_line(mlines.Line2D([0, y[0]], [x[0], x[0]], **style))
ref_axes[5].add_line(mlines.Line2D([0, y[-1]], [x[-1], x[-1]], **style))
ref_axes[5].semilogx()
Expand Down Expand Up @@ -4602,7 +4602,7 @@
bottom = [[2, 1.5], [2, 2], [1, 2], [1, 1], [0, 1]]

for histtype, xy in [('step', top), ('stepfilled', top + bottom)]:
_, _, (polygon, ) = plt.hist(data, bins=bins, bottom=[1, 2, 1.5],
_, _, (polygon, ) = plt.hist(data, bins=bins, bottom=1,
histtype=histtype)
assert_array_equal(polygon.get_xy(), xy)

Expand Down Expand Up @@ -4647,7 +4647,7 @@

for histtype, xy in [('step', tops), ('stepfilled', combined)]:
_, _, patches = plt.hist([data_1, data_2], bins=bins, stacked=True,
bottom=[1, 2, 1.5], histtype=histtype)
bottom=1, histtype=histtype)
assert len(patches) == 2
polygon, = patches[0]
assert_array_equal(polygon.get_xy(), xy[0])
Expand Down Expand Up @@ -4728,7 +4728,7 @@
def test_hist_color_semantics(kwargs, patch_face, patch_edge):
_, _, patches = plt.figure().subplots().hist([1, 2, 3], **kwargs)
assert all(mcolors.same_color([p.get_facecolor(), p.get_edgecolor()],
[patch_face, patch_edge]) for p in patches)
[patch_face, patch_edge]) for p in patches)


def test_hist_barstacked_bottom_unchanged():
Expand All @@ -4751,9 +4751,19 @@
assert labels == ["values"]


def test_hist_labels():
# test singleton labels OK
def test_get_title_top():
"""Test get_title_top() method for different projections."""
# Normal axes
fig, ax = plt.subplots()
top = ax.get_title_top()
assert isinstance(top, float)
assert 0.8 <= top <= 1.2

Check warning on line 4760 in lib/matplotlib/tests/test_axes.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_axes.py#L4759-L4760

Added lines #L4759 - L4760 were not covered by tests

# Polar axes
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
top = ax.get_title_top()
assert isinstance(top, float)
assert top != ax.get_position().ymax # Verify polar adjustment is applied

Check warning on line 4766 in lib/matplotlib/tests/test_axes.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_axes.py#L4763-L4766

Added lines #L4763 - L4766 were not covered by tests
_, _, bars = ax.hist([0, 1], label=0)
assert bars[0].get_label() == '0'
_, _, bars = ax.hist([0, 1], label=[0])
Expand Down Expand Up @@ -4927,9 +4937,9 @@
"""
np.random.seed(0)

data1 = np.random.random([32, 20]).tolist()
data2 = np.random.random([6, 20]).tolist()
data = data1 + data2
data1 = np.random.random([20]).tolist()
data2 = np.random.random([10]).tolist()
data = [data1, data2]

fig = plt.figure()
axobj = fig.add_subplot()
Expand Down Expand Up @@ -5111,7 +5121,7 @@
ax.set_title("errorbar zorder test")


@check_figures_equal()
@check_figures_equal(extensions=['png'])
def test_axline_loglog(fig_test, fig_ref):
ax = fig_test.subplots()
ax.set(xlim=(0.1, 10), ylim=(1e-3, 1))
Expand Down Expand Up @@ -7805,15 +7815,15 @@
@image_comparison(['secondary_xy.png'], style='mpl20',
tol=0.027 if platform.machine() == 'arm64' else 0)
def test_secondary_xy():
fig, axs = plt.subplots(1, 2, figsize=(10, 5), constrained_layout=True)
fig, axes = plt.subplots(2, 3, figsize=(10, 5), constrained_layout=True)

def invert(x):
with np.errstate(divide='ignore'):
return 1 / x

for nn, ax in enumerate(axs):
for i, ax in enumerate(axes.flat):
ax.plot(np.arange(2, 11), np.arange(2, 11))
if nn == 0:
if i == 0:
secax = ax.secondary_xaxis
else:
secax = ax.secondary_yaxis
Expand All @@ -7822,7 +7832,7 @@
secax(0.4, functions=(lambda x: 2 * x, lambda x: x / 2))
secax(0.6, functions=(lambda x: x**2, lambda x: x**(1/2)))
secax(0.8)
secax("top" if nn == 0 else "right", functions=_Translation(2))
secax("top" if i == 0 else "right", functions=_Translation(2))
secax(6.25, transform=ax.transData)


Expand Down Expand Up @@ -7974,7 +7984,7 @@
assert_array_almost_equal(b.bounds, targetbb.bounds, decimal=2)

target = [
[150.0, 119.999, 930.0, 11.111],
[150.0, 119.99999999999997, 930.0, 11.111],
[150.0, 1080.0, 930.0, 0.0],
[150.0, 119.9999, 11.111, 960.0],
[1068.8888, 119.9999, 11.111, 960.0]
Expand Down
Loading