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

Skip to content

Remove internal use of Artist.figure #28550

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

Merged
merged 3 commits into from
Sep 7, 2024
Merged
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
4 changes: 2 additions & 2 deletions lib/matplotlib/_constrained_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ def get_pos_and_bbox(ax, renderer):
bbox : `~matplotlib.transforms.Bbox`
Tight bounding box in figure coordinates.
"""
fig = ax.figure
fig = ax.get_figure(root=False)
pos = ax.get_position(original=True)
# pos is in panel co-ords, but we need in figure for the layout
pos = pos.transformed(fig.transSubfigure - fig.transFigure)
Expand Down Expand Up @@ -699,7 +699,7 @@ def reposition_colorbar(layoutgrids, cbax, renderer, *, offset=None):

parents = cbax._colorbar_info['parents']
gs = parents[0].get_gridspec()
fig = cbax.figure
fig = cbax.get_figure(root=False)
trans_fig_to_subfig = fig.transFigure - fig.transSubfigure

cb_rspans, cb_cspans = get_cb_parent_spans(cbax)
Expand Down
17 changes: 9 additions & 8 deletions lib/matplotlib/artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ def draw_wrapper(artist, renderer):
renderer.stop_filter(artist.get_agg_filter())
if artist.get_rasterized():
renderer._raster_depth -= 1
if (renderer._rasterizing and artist.figure and
artist.figure.suppressComposite):
if (renderer._rasterizing and (fig := artist.get_figure(root=True)) and
fig.suppressComposite):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not really understood what it does, but suppressComposite appears to only exist on Figure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In vector outputs if you have multiple images or things you are pre-rasterizing you may want to rasterize them all into one image in the final output (which is good because it saves space if they overlap, the pathological example is 100 4kx4k images with alpha that are all exactly on top of each other, by pre-merging them you get a 100x size win!). On the other hand, if you have a bunch of images that only slightly overlap or you want to be able to re-extract the individual layers later you do not want to merge them. As both are reasonable we have an (esoteric) flag to control it 🤣 .

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation.

# restart rasterizing to prevent merging
renderer.stop_rasterizing()
renderer.start_rasterizing()
Expand Down Expand Up @@ -248,9 +248,9 @@ def remove(self):
self.axes = None # decouple the artist from the Axes
_ax_flag = True

if self.figure:
if (fig := self.get_figure(root=False)) is not None:
if not _ax_flag:
self.figure.stale = True
fig.stale = True
self._parent_figure = None

else:
Expand Down Expand Up @@ -473,8 +473,9 @@ def _different_canvas(self, event):
return False, {}
# subclass-specific implementation follows
"""
return (getattr(event, "canvas", None) is not None and self.figure is not None
and event.canvas is not self.figure.canvas)
return (getattr(event, "canvas", None) is not None
and (fig := self.get_figure(root=True)) is not None
and event.canvas is not fig.canvas)

def contains(self, mouseevent):
"""
Expand Down Expand Up @@ -504,7 +505,7 @@ def pickable(self):
--------
.Artist.set_picker, .Artist.get_picker, .Artist.pick
"""
return self.figure is not None and self._picker is not None
return self.get_figure(root=False) is not None and self._picker is not None

def pick(self, mouseevent):
"""
Expand All @@ -526,7 +527,7 @@ def pick(self, mouseevent):
else:
inside, prop = self.contains(mouseevent)
if inside:
PickEvent("pick_event", self.figure.canvas,
PickEvent("pick_event", self.get_figure(root=True).canvas,
mouseevent, self, **prop)._process()

# Pick children
Expand Down
7 changes: 6 additions & 1 deletion lib/matplotlib/artist.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ from .transforms import (
import numpy as np

from collections.abc import Callable, Iterable
from typing import Any, NamedTuple, TextIO, overload, TypeVar
from typing import Any, Literal, NamedTuple, TextIO, overload, TypeVar
from numpy.typing import ArrayLike

_T_Artist = TypeVar("_T_Artist", bound=Artist)
Expand Down Expand Up @@ -88,6 +88,11 @@ class Artist:
) -> None: ...
def set_path_effects(self, path_effects: list[AbstractPathEffect]) -> None: ...
def get_path_effects(self) -> list[AbstractPathEffect]: ...
@overload
def get_figure(self, root: Literal[True]) -> Figure | None: ...
@overload
def get_figure(self, root: Literal[False]) -> Figure | SubFigure | None: ...
@overload
def get_figure(self, root: bool = ...) -> Figure | SubFigure | None: ...
def set_figure(self, fig: Figure | SubFigure) -> None: ...
def set_clip_box(self, clipbox: BboxBase | None) -> None: ...
Expand Down
7 changes: 4 additions & 3 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,9 @@ def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs):
# This puts the rectangle into figure-relative coordinates.
inset_locator = _TransformedBoundsLocator(bounds, transform)
bounds = inset_locator(self, None).bounds
projection_class, pkw = self.figure._process_projection_requirements(**kwargs)
inset_ax = projection_class(self.figure, bounds, zorder=zorder, **pkw)
fig = self.get_figure(root=False)
projection_class, pkw = fig._process_projection_requirements(**kwargs)
inset_ax = projection_class(fig, bounds, zorder=zorder, **pkw)

# this locator lets the axes move if in data coordinates.
# it gets called in `ax.apply_aspect() (of all places)
Expand Down Expand Up @@ -515,7 +516,7 @@ def indicate_inset(self, bounds, inset_ax=None, *, transform=None,

# decide which two of the lines to keep visible....
pos = inset_ax.get_position()
bboxins = pos.transformed(self.figure.transSubfigure)
bboxins = pos.transformed(self.get_figure(root=False).transSubfigure)
rectbbox = mtransforms.Bbox.from_bounds(
*bounds
).transformed(transform)
Expand Down
59 changes: 35 additions & 24 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
# time as transSubfigure may otherwise change after this is evaluated.
return mtransforms.TransformedBbox(
mtransforms.Bbox.from_bounds(*self._bounds),
self._transform - ax.figure.transSubfigure)
self._transform - ax.get_figure(root=False).transSubfigure)


def _process_plot_format(fmt, *, ambiguous_fmt_datakey=False):
Expand Down Expand Up @@ -788,7 +788,7 @@
def set_subplotspec(self, subplotspec):
"""Set the `.SubplotSpec`. associated with the subplot."""
self._subplotspec = subplotspec
self._set_position(subplotspec.get_position(self.figure))
self._set_position(subplotspec.get_position(self.get_figure(root=False)))

def get_gridspec(self):
"""Return the `.GridSpec` associated with the subplot, or None."""
Expand Down Expand Up @@ -959,8 +959,9 @@
"""
labels_align = mpl.rcParams["xtick.alignment"]
return (self.get_xaxis_transform(which='tick1') +
mtransforms.ScaledTranslation(0, -1 * pad_points / 72,
self.figure.dpi_scale_trans),
mtransforms.ScaledTranslation(
0, -1 * pad_points / 72,
self.get_figure(root=False).dpi_scale_trans),
"top", labels_align)

def get_xaxis_text2_transform(self, pad_points):
Expand All @@ -985,8 +986,9 @@
"""
labels_align = mpl.rcParams["xtick.alignment"]
return (self.get_xaxis_transform(which='tick2') +
mtransforms.ScaledTranslation(0, pad_points / 72,
self.figure.dpi_scale_trans),
mtransforms.ScaledTranslation(
0, pad_points / 72,
self.get_figure(root=False).dpi_scale_trans),
"bottom", labels_align)

def get_yaxis_transform(self, which='grid'):
Expand Down Expand Up @@ -1039,8 +1041,9 @@
"""
labels_align = mpl.rcParams["ytick.alignment"]
return (self.get_yaxis_transform(which='tick1') +
mtransforms.ScaledTranslation(-1 * pad_points / 72, 0,
self.figure.dpi_scale_trans),
mtransforms.ScaledTranslation(
-1 * pad_points / 72, 0,
self.get_figure(root=False).dpi_scale_trans),
labels_align, "right")

def get_yaxis_text2_transform(self, pad_points):
Expand All @@ -1065,8 +1068,9 @@
"""
labels_align = mpl.rcParams["ytick.alignment"]
return (self.get_yaxis_transform(which='tick2') +
mtransforms.ScaledTranslation(pad_points / 72, 0,
self.figure.dpi_scale_trans),
mtransforms.ScaledTranslation(
pad_points / 72, 0,
self.get_figure(root=False).dpi_scale_trans),
labels_align, "left")

def _update_transScale(self):
Expand Down Expand Up @@ -1173,7 +1177,7 @@

def _set_artist_props(self, a):
"""Set the boilerplate props for artists added to Axes."""
a.set_figure(self.figure)
a.set_figure(self.get_figure(root=False))
if not a.is_transform_set():
a.set_transform(self.transData)

Expand Down Expand Up @@ -1347,7 +1351,7 @@
# the other artists. We use the frame to draw the edges so we are
# setting the edgecolor to None.
self.patch = self._gen_axes_patch()
self.patch.set_figure(self.figure)
self.patch.set_figure(self.get_figure(root=False))
self.patch.set_facecolor(self._facecolor)
self.patch.set_edgecolor('none')
self.patch.set_linewidth(0)
Expand Down Expand Up @@ -1522,7 +1526,7 @@
"""
self.titleOffsetTrans = mtransforms.ScaledTranslation(
0.0, title_offset_points / 72,
self.figure.dpi_scale_trans)
self.get_figure(root=False).dpi_scale_trans)
for _title in (self.title, self._left_title, self._right_title):
_title.set_transform(self.transAxes + self.titleOffsetTrans)
_title.set_clip_box(None)
Expand Down Expand Up @@ -1937,7 +1941,7 @@
self._set_position(position, which='active')
return

trans = self.get_figure().transSubfigure
trans = self.get_figure(root=False).transSubfigure
bb = mtransforms.Bbox.unit().transformed(trans)
# this is the physical aspect of the panel (or figure):
fig_aspect = bb.height / bb.width
Expand Down Expand Up @@ -2274,7 +2278,7 @@

self.child_axes.append(ax)
ax._remove_method = functools.partial(
self.figure._remove_axes, owners=[self.child_axes])
self.get_figure(root=False)._remove_axes, owners=[self.child_axes])
self.stale = True
return ax

Expand Down Expand Up @@ -3022,7 +3026,8 @@
axs = set()
axs.update(self.child_axes)
axs.update(self._twinned_axes.get_siblings(self))
axs.update(self.figure._align_label_groups['title'].get_siblings(self))
axs.update(
self.get_figure(root=False)._align_label_groups['title'].get_siblings(self))

for ax in self.child_axes: # Child positions must be updated first.
locator = ax.get_axes_locator()
Expand Down Expand Up @@ -3108,7 +3113,7 @@
for _axis in self._axis_map.values():
artists.remove(_axis)

if not self.figure.canvas.is_saving():
if not self.get_figure(root=True).canvas.is_saving():
artists = [
a for a in artists
if not a.get_animated() or isinstance(a, mimage.AxesImage)]
Expand Down Expand Up @@ -3136,10 +3141,10 @@
artists = [self.patch] + artists

if artists_rasterized:
_draw_rasterized(self.figure, artists_rasterized, renderer)
_draw_rasterized(self.get_figure(root=True), artists_rasterized, renderer)

mimage._draw_list_compositing_images(
renderer, self, artists, self.figure.suppressComposite)
renderer, self, artists, self.get_figure(root=True).suppressComposite)

renderer.close_group('axes')
self.stale = False
Expand All @@ -3148,7 +3153,7 @@
"""
Efficiently redraw a single artist.
"""
a.draw(self.figure.canvas.get_renderer())
a.draw(self.get_figure(root=True).canvas.get_renderer())

def redraw_in_frame(self):
"""
Expand All @@ -3158,7 +3163,7 @@
for artist in [*self._axis_map.values(),
self.title, self._left_title, self._right_title]:
stack.enter_context(artist._cm_set(visible=False))
self.draw(self.figure.canvas.get_renderer())
self.draw(self.get_figure(root=True).canvas.get_renderer())

# Axes rectangle characteristics

Expand Down Expand Up @@ -4466,7 +4471,7 @@

bb = []
if renderer is None:
renderer = self.figure._get_renderer()
renderer = self.get_figure(root=True)._get_renderer()

if not self.get_visible():
return None
Expand Down Expand Up @@ -4517,9 +4522,9 @@
raise ValueError("Twinned Axes may share only one axis")
ss = self.get_subplotspec()
if ss:
twin = self.figure.add_subplot(ss, *args, **kwargs)
twin = self.get_figure(root=False).add_subplot(ss, *args, **kwargs)
else:
twin = self.figure.add_axes(
twin = self.get_figure(root=False).add_axes(
self.get_position(True), *args, **kwargs,
axes_locator=_TransformedBoundsLocator(
[0, 0, 1, 1], self.transAxes))
Expand Down Expand Up @@ -4748,6 +4753,12 @@
self.figure = figure
self.artists = artists

def get_figure(self, root=False):
if root:
return self.figure.get_figure(root=True)
else:
return self.figure

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

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/axes/_base.py#L4760

Added line #L4760 was not covered by tests

@martist.allow_rasterization
def draw(self, renderer):
for a in self.artists:
Expand Down
5 changes: 3 additions & 2 deletions lib/matplotlib/axes/_secondary_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ def __init__(self, parent, orientation, location, functions, transform=None,
self._orientation = orientation
self._ticks_set = False

fig = self._parent.get_figure(root=False)
if self._orientation == 'x':
super().__init__(self._parent.figure, [0, 1., 1, 0.0001], **kwargs)
super().__init__(fig, [0, 1., 1, 0.0001], **kwargs)
self._axis = self.xaxis
self._locstrings = ['top', 'bottom']
self._otherstrings = ['left', 'right']
else: # 'y'
super().__init__(self._parent.figure, [0, 1., 0.0001, 1], **kwargs)
super().__init__(fig, [0, 1., 0.0001, 1], **kwargs)
self._axis = self.yaxis
self._locstrings = ['right', 'left']
self._otherstrings = ['top', 'bottom']
Expand Down
Loading
Loading