Repository navigation
Description
Description
I've been working with plotting points on a WCSAxes with sunpy maps, as part of our work migrating sunpy.map.Map to be based on ndcube, and it seems that plotting a Quantity on WCSAxes with transform=ax.get_transform("world") silently drops its unit. The bare number is then read in the WCS's world units, so the marker can end up in the wrong place with no warning or error.
So like here,
ax.plot(100 * u.deg, 10 * u.deg, "o", transform=ax.get_transform("world"))
ax.plot(100 * u.arcsec, 10 * u.arcsec, "o", transform=ax.get_transform("world"))these two calls draw markers at the same position. On a default WCS, where the world units are degrees, the arcsec marker is plotted at 10 degrees (which is the case for sunpy maps as the wcs is in degrees).
for example:
import sunpy.map
import sunpy.data.sample
from astropy import units as u
aia = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)
fig = plt.figure(figsize=(7, 7))
ax = fig.add_subplot(projection=aia)
aia.plot(axes=ax, clip_interval=(1, 99.9) * u.percent)
ax.plot(10*u.deg, 10*u.deg, transform=ax.get_transform("world"), marker='o', color='r', ms=10, label="(100, 100) degrees")
ax.plot(10*u.arcsec, 10*u.arcsec, transform=ax.get_transform("world"), marker='o', color='k', label="(100, 100) arcsec")
ax.legend(loc="lower right", fontsize=8)
so you can see its plotting both as 10 degrees and ignoring the quantities.
this is because:
aia.wcs.world_axis_units
['deg', 'deg']as far as I can tell, this is why it happens:
- Matplotlib has no converter registered for
Quantityby default, so it keeps only the values. - The world transform receives plain floats and assumes they are in
wcs.world_axis_units.
quantity_support() doesn't help, matplotlib's unit conversion works per axis and doesn't know about the transform, so values are converted to the first unit plotted on the axis rather than to the WCS units. The result is only correct if that first unit happens to match the WCS.
plot_coord with a SkyCoord gives the right position. scatter, errorbar and fill drop the unit in the same way as plot.
also the overlays page doesnt mention any of this. It shows ax.scatter([34], [3.2], transform=ax.get_transform('world')) with plain numbers, but doesn't say that the numbers must be in the WCS's world units or that a Quantity would lose its unit. It also doesn't mention world_axis_units, or plot_coord as the safe alternative. The same page passes a Quantity with a transform to Quadrangle, which does convert units, so it's reasonable to expect plot and scatter to do the same.
Expected behavior
I guess a Quantity should either be plotted where its value and unit say it is, or raise an error? It should not be silently reinterpreted.
If possible i'd suggest that WCSAxes converts a Quantity to the transform's input units before calling matplotlib, and raises UnitConversionError for incompatible units such as metres on an angle axis?
WCSAxes is the only place that knows both the data's unit and what the transform expects. raising an error for any Quantity would also be an improvement over the current behaviour, if that is preferred.
Versions
import astropy
astropy.system_info()platform
--------
platform.platform() = 'macOS-15.7.3-arm64-arm-64bit-Mach-O'
platform.version() = 'Darwin Kernel Version 24.6.0: Wed Nov 5 21:30:44 PST 2025; root:xnu-11417.140.69.705.2~1/RELEASE_ARM64_T6041'
platform.python_version() = '3.15.2'
packages
--------
astropy 8.0.2
numpy 2.5.4
scipy 1.18.1
matplotlib 3.11.2
pandas 3.1.1
pyerfa 2.0.1.5
Activity
astrofrog commentedon Nov 5, 2026
Thanks for reporting this - I have a fix which I'll open tomorrow