What I'm Trying to Do
I am using matplotlib
and I want to be able to create some dynamic footnotes with the capability to both wrap and highlight left-aligned text.
The easiest solution would be to identify a reliable method to convert fontsize scale to graph axes scale (e.g. how much does space on the y axis does text take up if fontsize is 8 vs 30) but I would be open to a smarter way to solve the problem.
For Example:
My hokey code:
I modified some code from this question but it still requires highlighted text be on a new line so word wrap isn't exactly ideal.
Basically it assumes the paragraph is split into three categories, and formats each accordingly:
- Plain Text
- Highlighted Text
- One, really large, word or number
This code feels pretty weak in general so, in addition to finding something that can both wrap and highlight text, I would also be open to cleaner solutions. **Note that this only works in interactive mode (e.g. ipython notebook or similar) because text.draw(fig.canvas.get_renderer())
doesn't work from non-interactive.
from matplotlib import transforms
from matplotlib import pyplot as plt
def parse_text_type(story, highlight_text, bold, num_tag, highlight_tag):
str_list = []
for x in story.split("___"):
if x == 'highlight':
str_list.append([highlight_text,highlight_tag])
elif x == 'bold':
str_list.append([bold,num_tag])
elif x != '':
str_list.append([x,"___background___"])
return str_list
def make_plot(parsed_story):
ax = plt.subplot(111)
plt.plot([0,0.5],[0,1],lw=0)
t = plt.gca().transData
fig = plt.gcf()
for i,x in enumerate(parsed_story):
if x[1] == '___background___':
text = plt.text(
-1, 1, x[0], ha='left', transform=t,
va='top', fontsize=18, color='#999999')
elif x[1] == '___highlight___':
text = plt.text(
-1, 1, x[0], ha='left', transform=t, weight='bold',
va='top', fontsize=18, color='#32618b'
)
elif x[1] == '___bold___':
text = plt.text(
-1, 1, x[0], ha='left', transform=t,
va='top', fontsize=100, color='#32618b', rasterized=None
)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, y=-ex.height - 5, units='dots')
plt.axis('off');
return fig, ax
def generate_wordplot(number, highlight_text, story):
num_tag = '___number___'
highlight_tag = '___highlight___'
story = story.format(number=num_tag, highlight=highlight_tag)
parsed_story = parse_text_type(story,highlight_text, number, num_tag, highlight_tag)
return make_plot(parsed_story)
if __name__ == '__main__':
bold = "99.9%"
highlight_text = "humans drink water"
story = "One survey found that {bold}of {highlight}"
fig, ax = generate_wordplot(bold, highlight_text, story)