matplotlibtextsubfigure

Using a subfigure as textbody fails on tight layout with a lot of text


Using a subfigure as textbody fails on tight layout with a lot of text. As seen in the provided example, the bound of a figure are overreached by one subfigure, as if the text was not wrapped.

import pandas as pd
from matplotlib import pyplot as plt

# Paramters for A4 Paper
fullheight = 11.69
fullwidth = 8.27

# how the subfigures dive the space
fig0_factor = 0.7
fig1_factor = 0.3

# generate the figure
fig = plt.figure(constrained_layout = True, figsize=(fullwidth, fullheight)) # 

# generate 2 subfigures
subfigs = fig.subfigures(2,height_ratios=[fig0_factor,fig1_factor])


# fill the fist subfigure
axes = subfigs[0].subplots(nrows=1)
# some plot
ax = plt.plot([0,0],[-1,1], lw=1, c='b', figure=subfigs[0])
# some text
subfigs[0].text(0.55, 0.00001, 'Figure 1', ha='center', va='center', rotation='horizontal',weight='bold')

# fill the second subfigure
text_ax = subfigs[1].subplots(1)
# make its background transparent
subfigs[1].patch.set_alpha(0.0)
# remove the axis, not removing it makes no difference regarding the problem
text_ax.set_axis_off()

# generate some text
message = ['word']*50 # 50 is enough to make the problem visable, my usecase has a way longer text
message = ' '.join(message)    

# fill in the Text and wrap it
text_ax.text(0.00001, 0.8, message, horizontalalignment='left', verticalalignment='top',size=7, wrap=True)


# call tight layout
# this is neccecary for the whole plot, that is not shown for simplicity reasons
# explaination: subfigure one would be an array of subplots with different scales and descriptions, 
#               ever changing depending on the data that is to be plotted, so tight_layout mittigates
#               a lot of tideos formatting
fig.tight_layout()

Please notice the figures right edge reaches for the whole panel, as seen in the second image figure with wrapping and tight_layout

# omitting the wrap, it is clear why the figure is out of bound: somehow the layout gets its information from the unwrapped text
text_ax.text(0.00001, 0.8, message, horizontalalignment='left', verticalalignment='top',size=7, wrap=False)

figure without wrapping or tight_layout

Is there another way to have the text rendered in the subplot with it correctly noticing the wrapped bounds instead of the unwrapped bounds?


Solution

  • If you modify your code above to remove fig.tight_layout() and to take the text out of the layout then everything works as expected.

    # fill in the Text and wrap it
    thetext = text_ax.text(0.00001, 0.8, message, horizontalalignment='left',
                 verticalalignment='top',size=7, wrap=True)
    thetext.set_in_layout(False)
    

    There should be nothing that tight_layout does that layout='constrained' cannot do, and constrained layout is much more flexible.

    BTW, you might consider subfigs[0].supxlabel() instead of the text command for "Figure 1"