Skip to content
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

Allow WCSAxes ticklabels to be rasterized #14760

Merged
merged 8 commits into from Sep 29, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 12 additions & 7 deletions astropy/visualization/wcsaxes/coordinate_helpers.py
Expand Up @@ -628,18 +628,23 @@ def _draw_grid(self, renderer):

renderer.close_group("grid lines")

def _draw_ticks(self, renderer, bboxes, ticklabels_bbox):
def _draw_ticks(self, renderer, existing_bboxes):
"""
Draw all ticks and ticklabels.

Parameters
----------
existing_bboxes : list[Bbox]
All bboxes for ticks that have already been drawn by other
coordinates.
"""
renderer.open_group("ticks")
self.ticks.draw(renderer)
self.ticklabels.draw(
renderer,
bboxes=bboxes,
ticklabels_bbox=ticklabels_bbox,
tick_out_size=self.ticks.out_size,
)

self.ticklabels._tick_out_size = self.ticks.out_size

self.ticklabels._set_existing_bboxes(existing_bboxes)
self.ticklabels.draw(renderer)

renderer.close_group("ticks")

Expand Down
10 changes: 5 additions & 5 deletions astropy/visualization/wcsaxes/core.py
Expand Up @@ -511,12 +511,12 @@ def draw_wcsaxes(self, renderer):
for coords in self._all_coords:
# Draw tick labels
for coord in coords:
coord._draw_ticks(
renderer,
bboxes=self._bboxes,
ticklabels_bbox=ticklabels_bbox[coord],
)
coord._draw_ticks(renderer, self._bboxes)

visible_ticks.extend(coord.ticklabels.get_visible_axes())
# Save ticklabel bboxes
ticklabels_bbox[coord] = coord.ticklabels._axis_bboxes
self._bboxes += coord.ticklabels._all_bboxes

for coords in self._all_coords:
# Draw axis labels
Expand Down
41 changes: 32 additions & 9 deletions astropy/visualization/wcsaxes/ticklabels.py
Expand Up @@ -4,8 +4,10 @@

import numpy as np
from matplotlib import rcParams
from matplotlib.artist import allow_rasterization
from matplotlib.text import Text

from astropy.utils.decorators import deprecated_renamed_argument
from astropy.utils.exceptions import AstropyDeprecationWarning

from .frame import RectangularFrame
Expand All @@ -25,12 +27,14 @@ def __init__(self, frame, *args, **kwargs):
self.set_pad(rcParams["xtick.major.pad"])
self._exclude_overlapping = False

# Mapping from axis > list[bounding boxes]
self._axis_bboxes = defaultdict(list)

# Stale if either xy positions haven't been calculated, or if
# something changes that requires recomputing the positions
self._stale = True

# Check rcParams

if "color" not in kwargs:
self.set_color(rcParams["xtick.color"])

Expand Down Expand Up @@ -170,7 +174,7 @@ def get_visible_axes(self):
def set_exclude_overlapping(self, exclude_overlapping):
self._exclude_overlapping = exclude_overlapping

def _set_xy_alignments(self, renderer, tick_out_size):
def _set_xy_alignments(self, renderer):
"""
Compute and set the x, y positions and the horizontal/vertical alignment of
each label.
Expand All @@ -195,7 +199,7 @@ def _set_xy_alignments(self, renderer, tick_out_size):
continue

x, y = self._frame.parent_axes.transData.transform(self.data[axis][i])
pad = renderer.points_to_pixels(self.get_pad() + tick_out_size)
pad = renderer.points_to_pixels(self.get_pad() + self._tick_out_size)

if isinstance(self._frame, RectangularFrame):
# This is just to preserve the current results, but can be
Expand Down Expand Up @@ -297,11 +301,29 @@ def _get_bb(self, axis, i, renderer):
self.set_va(self.va[axis][i])
return super().get_window_extent(renderer)

def draw(self, renderer, bboxes, ticklabels_bbox, tick_out_size):
@property
def _all_bboxes(self):
# List of all tick label bounding boxes
ret = []
for axis in self._axis_bboxes:
ret += self._axis_bboxes[axis]
return ret

def _set_existing_bboxes(self, bboxes):
self._existing_bboxes = bboxes

@allow_rasterization
@deprecated_renamed_argument(old_name="bboxes", new_name=None, since="6.0")
@deprecated_renamed_argument(old_name="ticklabels_bbox", new_name=None, since="6.0")
@deprecated_renamed_argument(old_name="tick_out_size", new_name=None, since="6.0")
def draw(self, renderer, bboxes=None, ticklabels_bbox=None, tick_out_size=None):
# Reset bounding boxes
self._axis_bboxes = defaultdict(list)

if not self.get_visible():
return

self._set_xy_alignments(renderer, tick_out_size)
self._set_xy_alignments(renderer)

for axis in self.get_visible_axes():
for i in range(len(self.world[axis])):
Expand All @@ -313,8 +335,9 @@ def draw(self, renderer, bboxes, ticklabels_bbox, tick_out_size):
# TODO: the problem here is that we might get rid of a label
# that has a key starting bit such as -0:30 where the -0
# might be dropped from all other labels.

if not self._exclude_overlapping or bb.count_overlaps(bboxes) == 0:
if (
not self._exclude_overlapping
or bb.count_overlaps(self._all_bboxes + self._existing_bboxes) == 0
):
super().draw(renderer)
bboxes.append(bb)
ticklabels_bbox[axis].append(bb)
self._axis_bboxes[axis].append(bb)
2 changes: 2 additions & 0 deletions docs/changes/visualization/14760.api.rst
@@ -0,0 +1,2 @@
The ``bboxes``, ``ticklabels_bbox``, and ``tick_out_size`` arguments to ``astropy.visualization.wcaxes.ticklabels.TickLabels.draw()`` now have no effect and are deprecated.
This is to allow rasterized ticks to be drawn correctly on WCSAxes.
1 change: 1 addition & 0 deletions docs/changes/visualization/14760.bugfix.rst
@@ -0,0 +1 @@
The location of ticklabels on a WCSAxes is now correctly calculated when the figure is rasterized.