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

set_titles_and_labels : title location strongly changes when adding a subtitle, in portrait format #212

Closed
senesis opened this issue Feb 10, 2024 · 6 comments
Assignees
Labels
bug Something isn't working support Support request opened by outside user/collaborator

Comments

@senesis
Copy link

senesis commented Feb 10, 2024

Describe the bug
set_titles_and_labels : Vertical space between the title and the map strongly changes when adding a subtitle, in portrait format

To Reproduce
When using the code below and the same code un-commenting the commented part, we got the two figures further below

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import geocat.viz as gv

fig = plt.figure(figsize=(8.5,11))
projection = ccrs.PlateCarree()
ax = plt.axes(projection=projection)
ax.add_feature(cfeature.LAND, color='silver',zorder=1)

gv.set_titles_and_labels(ax,maintitle='Main title')#,subtitle='Subtitle')

plt.show();

Fist figure, without subtitle : title is close to the map
image

Second figre, with subtitle : title is much far from the map
image

Expected behavior
I expected to get the title much closer to the figure and to the subtitle

OS:
Linux spirit1.ipsl.fr 5.4.0-170-generic #188 SMP Wed Jan 10 09:51:01 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Environment
See #210

@senesis senesis added bug Something isn't working support Support request opened by outside user/collaborator labels Feb 10, 2024
@kafitzgerald
Copy link
Collaborator

Thanks for the report!

I'm not sure I've seen such a clear example before, but I believe it's a known issue that some of the utilities in geocat-viz work best with sizes and layouts similar to those used in the GeoCAT-examples gallery. This is something we'd love to improve, but I don't know that it's a high priority at the moment.

That said, if this was something you or someone else had interest in working on, we'd be open to a contribution. We would need to make sure it doesn't break other functionality or negatively impact the examples gallery, but this is something we could help with.

In the meantime, adjusting the figure size to better fit the proportions of the figure should help.

@jukent may be able to say more or have additional suggestions for this case.

@jukent
Copy link
Collaborator

jukent commented Feb 12, 2024

Thanks for bringing this to our attention. The subtitle functionality works by calling on matplotlib's figure suptitle. For some reason, even with default figure size, this is not playing well with a Cartopy projection. I will look more into this.

@jukent
Copy link
Collaborator

jukent commented Feb 12, 2024

Adding here that another workaround for matplotlib subtitles:

ax.xaxis.set_label_position('top')
ax.xaxis.tick_top()
ax.set_xlabel('Subtitle')
ax.set_title('Title')

Is also thwarted by incorporating a Cartopy projection.

@senesis
Copy link
Author

senesis commented Feb 13, 2024

Thanks, but the workaround just above doesn't apply to the case where you want the ticks and tick labels at the bottom.

@jukent
Copy link
Collaborator

jukent commented Mar 18, 2024

Hi @senesis yes that is what I meant. Here are 3 work arounds for you to try out and see what is best for your work. Unfortunately this issue is with Cartopy's figure handling, which tries to automatically be helpful and in this case adds an entire figure's worth of space above the intended title location.

  1. Simply add a line break to your main title call. The drawback of this method is that your title and subtitle will have the same fontsize.
fig, ax = plt.subplots(figsize=(8.5, 11), subplot_kw={'projection': ccrs.PlateCarree()})
ax.add_feature(cfeature.LAND, color='silver',zorder=1)

gv.set_titles_and_labels(ax,maintitle='Main title\nSubtitle')

newlinesubtitle

  1. Add spaces to the lefttitle keyword argument so that it is visually in the center.
fig, ax = plt.subplots(figsize=(8.5, 11), subplot_kw={'projection': ccrs.PlateCarree()})
ax.add_feature(cfeature.LAND, color='silver',zorder=1)

gv.set_titles_and_labels(ax,maintitle='Main title', lefttitle=f'{' ' * 45}Subtitle')
plt.tight_layout()

spacedlefttitle

  1. Use text annotations to add text blocks in specific locations of your figure. This offers the most customization
fig, ax = plt.subplots(figsize=(8.5, 11), subplot_kw={'projection': ccrs.PlateCarree()})
ax.add_feature(cfeature.LAND, color='silver', zorder=1)

# Left title text with offset
title = ax.text(0.5, 1.10, "Main Title", ha='center', va='center', 
                     fontsize=15, transform=ax.transAxes)

# Right title text with offset
sub_title = ax.text(0.5, 1.04, "Subtitle", ha='center', va='center', 
                     fontsize=12, transform=ax.transAxes)

textbox

Unfortunately each of these methods is non-trivial to implement in a way that works for all user's figure sizes etc, I have added a note to the docstring warning users that the subtitle functionality will not work as expected for Cartopy plots. Thank you again for bringing this to our attention. I hope one of these methods works for your work.

@jukent jukent self-assigned this Mar 18, 2024
@jukent
Copy link
Collaborator

jukent commented Mar 22, 2024

I was specifically looking into Cartopy subplots to see how that affects the above subtitle routines. It seems to me that Cartopy subplots always have more vertical space than I would expect.

The easiest way to fix the vertical space is to adjust your figure size. Your example is set to be 11 inches tall, by making it shorter, the suptitle at the top of the figure and the actual axes will be closer together:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import geocat.viz as gv

fig = plt.figure(figsize=(8.5,4))
projection = ccrs.PlateCarree()
ax = plt.axes(projection=projection)
ax.add_feature(cfeature.LAND, color='silver',zorder=1)

gv.set_titles_and_labels(ax,maintitle='Main title',subtitle='Subtitle')

plt.show();

@kafitzgerald original solution is the recommended one for dealing with Cartopy vertical spacing.

Here is another example of a similar spacing issue with Cartopy resolved by figure size adjustment.

@jukent jukent closed this as completed Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working support Support request opened by outside user/collaborator
Projects
None yet
Development

No branches or pull requests

3 participants