SciTools / cartopy

Cartopy - a cartographic python library with matplotlib support
https://scitools.org.uk/cartopy/docs/latest
BSD 3-Clause "New" or "Revised" License
1.41k stars 359 forks source link

Cartopy does not format longitude/latitude axis #2417

Open oliviermarti opened 1 month ago

oliviermarti commented 1 month ago

Description

Cartopy does not format longitude/latitude axis

Code to reproduce

import matplotlib.pyplot as plt
import cartopy.mpl.ticker, cartopy.crs as ccrs

# Describe the model projection in the file
ProjIn   = ccrs.PlateCarree (central_longitude=0) 
# Projection for plots
ProjPlot = ccrs.PlateCarree (central_longitude=0) 

fig, ax = plt.subplots ( figsize=(6,3), subplot_kw={'projection':ProjPlot} )
ax.set_extent ( ( -60, 10, -10, 10,), crs=ProjIn )
ax.gridlines (draw_labels=True, crs=ProjIn)
ax.coastlines ()
ax.xaxis.set_major_formatter (cartopy.mpl.ticker.LongitudeFormatter(dms=False, number_format='07.1f'))
ax.yaxis.set_major_formatter (cartopy.mpl.ticker.LatitudeFormatter (number_format='07.1f'))

The problem

The last two lines are not effective, and cartopy still displays latitudes as '7.5°S 7°S ...', when it should be '7.5°S 7.0°S ...'

Work around

The result is correct if one uses :

lon_fmt=cartopy.mpl.ticker.LongitudeFormatter(dms=False, number_format='03.1f')
lat_fmt=cartopy.mpl.ticker.LatitudeFormatter (dms=False, number_format='03.1f')
ax.gridlines (draw_labels=True, crs=ProjIn, xformatter=lon_fmt, yformatter=lat_fmt)

Operating system and others

Version python : 3.12.4 | packaged by conda-forge | (main, Jun 17 2024, 10:13:44) [Clang 16.0.6 ] Version numpy : 1.26.4 Version xarray : 2024.6.0 Version Matplotlib : 3.9.1 Version Cartopy : 0.23.0

greglucas commented 1 month ago

I think this is because the gridliner does not use/respect the xaxis.get_major_formatter(). It is more general and also has "geo" labels that aren't on the x/y axis. So, you're forced to pass in the formatter to the gridliner directly.

I'm not sure how hard it would be to make the gridliner be aware of the x/y axis properties, but it seems like it would be a nice update.

rcomer commented 1 month ago

The formatters are just attributes on the gridliner so if you want to change them after you created it you can just do

gl = ax.gridlines(draw_labels=True, crs=ProjIn)

gl.xformatter = cartopy.mpl.ticker.LongitudeFormatter(dms=False, number_format='03.1f')
gl.yformatter = cartopy.mpl.ticker.LatitudeFormatter(number_format='03.1f')

image

I'm not convinced that GridLiner should respect the settings in .xaxis and .yaxis: users can use them instead of gridliner if they prefer (see example). There is also nothing to stop you using the x/y-axis labels and a gridliner (or multiple gridliners) and you might want different formats for each of them. I admit I do not have use-cases in mind for those but to me it makes sense to maintain separation of concerns.