I am having serious difficulties in setting the Text styles of the xlabels and ylabels from the cartopy's gridlines.
When I follow the example given the cartopy's website, everything goes well, and I get the expected figure: .
Nevertheless, when I try to create multiple subplots, and each subplot with its own gridline (notice that they are all from the same geographical region, and thus, have the same gridline X and Y coordinates), I am unable to properly set the Gridlines' Text styles of its labels. In fact, some of the xlabels end up missing from the plot, as presented in this second example .
For sake of reproducibility, here is the code I used for the creation of Figure 2:
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import cartopy.crs as ccrs
from cartopy.mpl.ticker import (LongitudeFormatter, LatitudeFormatter,
LatitudeLocator)
fig, axes = plt.subplots(2,2, subplot_kw={'projection':ccrs.Mercator()})
axes = axes.ravel()
for ax in axes:
ax.coastlines()
ax.set_extent([-120, -25, -45, 25])
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5, linestyle='--')
gl.top_labels = False
gl.left_labels = False
gl.xlines = False
gl.ylocator = LatitudeLocator()
gl.xformatter = LongitudeFormatter()
gl.yformatter = LatitudeFormatter()
gl.xlocator = ticker.MaxNLocator(6)
gl.ylocator = ticker.MaxNLocator(6)
gl.xlabel_style = {'size': 12, 'color': 'k', 'rotation':45}
gl.ylabel_style = {'color': 'red', 'weight': 'bold', 'size':6}
plt.tight_layout()
plt.show()
The present issue may also help other parties, as the present topic has been indirectly subject of third other posts: 1) How can I rotate gridline labels on a cartopy map?; 2) How to set curvilinear lat lon gridline labels parallel to gridlines with cartopy?;
Sincerely,
Questions:
Answer to question 1
Difficulties found:
From ref. document: https://scitools.org.uk/cartopy/docs/latest/matplotlib/gridliner.html
Cartopy's gridliner function is a new feature that will be evolving a lot in the future (mentioned in its documentation).
The current status is very good for most cylindrical types of projection with default style settings.
If one manipulates some label text's styles without proper settings of associate options, you don't get what you expect.
For gridlines' labels, the following rules apply:
Extracted from help(gl._update_labels_visibility)
Here are some of the options that should be set with proper values, default values often lead to unexpect results.
gridlines() options 'xpadding' and 'ypadding', can be set to get more space to plot label texts
gridlines.xlabel_style() keys
Here is the runnable code that generates the subplots of maps with all 4 sets of tick-labels on all sides of each map.
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import cartopy.crs as ccrs
from cartopy.mpl.ticker import (LongitudeFormatter, LatitudeFormatter,
LatitudeLocator)
fig = plt.figure(figsize=(8, 10)) # set reasonable width, height in inches
axes = fig.subplots(2,2, subplot_kw={'projection':ccrs.Mercator()})
axes = axes.ravel()
# This plots all axes, adds most of map contents/components
# some maps' marginal info will be plotted in second for-loop
for ax in axes:
ax.coastlines()
ax.set_extent([-120, -25, -45, 25])
# plot grid lable text: left, right, bottom
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=2, color='gray', alpha=0.5, linestyle='--')
# manipulate the `gl` object as needed as follows
# some of these are not accepted as options in the statment above (cause errors)
gl.top_labels = False
#gl.left_labels = True #default already
#gl.right_labels = True
#gl.bottom_labels = True
gl.xlines = True
gl.ylines = True
gl.ylocator = LatitudeLocator()
gl.xformatter = LongitudeFormatter()
gl.yformatter = LatitudeFormatter()
gl.xlocator = mticker.MaxNLocator(6)
gl.ylocator = mticker.MaxNLocator(6)
# declare text size
XTEXT_SIZE = 10
YTEXT_SIZE = 10
# to facilitate text rotation at bottom edge, ...
# text justification: 'ha':'right' is used to avoid clashing with map's boundary
# default of 'ha' is center, often causes trouble when text rotation is not zero
gl.xlabel_style = {'size': XTEXT_SIZE, 'color': 'k', 'rotation':45, 'ha':'right'}
gl.ylabel_style = {'size':YTEXT_SIZE, 'color': 'k', 'weight': 'normal'}
# Second round of plots, do the top marginal texts in particular
# also plot title text of each axes
for ix,ax in enumerate(axes):
gl2 = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, color='none')
gl2.left_labels = False
gl2.right_labels = False
gl2.bottom_labels = False
gl2.xlines = False # already plotted in first loop, so we hide them
gl2.ylines = False
XTEXT_SIZE = 12 # ***intended larger value***
# to facilitate text rotation on top edge, ...
# text justification: 'ha':'left' is used here to avoid clashing with map's boundary
# default of 'ha' is center, often causes trouble when text rotation is not zero
gl2.xlabel_style = {'size': XTEXT_SIZE, 'color': 'blue', 'rotation':45, 'ha':'left'}
# plot title
ax.set_title("Subplot:"+str(ix))
plt.draw() # draw/update enables better tight_layout adjustment
plt.tight_layout() # without plt.draw(), real tight!!
plt.show()
Answer to question 2 (concepts only):
gl._labels
to get access to all label texts, you get them as a listSome comments