Skip to content

Commit

Permalink
Allow WCSAxes ticklabels to be rasterized (#14760)
Browse files Browse the repository at this point in the history
* Replace tick_out_size argument

* Replace ticklabels_bbox argument

* Replace bboxes argument

* Remove _draw_ticks arguemnts

* Allow rasterization on tick labels

* Fix overlapping ticks

* Deprecate draw args

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
dstansby and pre-commit-ci[bot] committed Sep 29, 2023
1 parent e135a78 commit dac44e8
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 21 deletions.
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.

0 comments on commit dac44e8

Please sign in to comment.