Known Issue: Left-flushing of annotations relies on the monospace font
sjiang40 opened this issue · 3 comments
I would like to use different fonts (e.g. Helvetica, Arial) to match journal font requirements for publication-ready figures.
A potential fix could be to use matplotlib.pyplot.table to render the table text to allow left-align with any font.
Hey sjiang40, thanks so much for pointing me to matplotlib.pyplot.table. I was not aware of this. Seems like a potential solution to aligning the y-labels. Will investigate this for a future release. @sjiang40 Let me know if it's something you want to work on.
@LSYS I would love to help but I will be on rotations in the hospital for the foreseeable future and I will have to spend my free time working on other research. Assuming you get to this before I get a chance to, I suspect matplotlib.pyplot.table
will be a viable solution for this.
Alternatively, if matplotlib.pyplot.table
ends up being too much of a code refactor, I recently wrote some code to add multiple Text()
objects in series as if it were a single object. The purpose was to add a bolded subfigure label with normal subfigure title without using LaTeX (e.g. "A) Subfigure title"). I think the core algorithm can be adapted to align columns in a table independent of the font. The steps would essentially be:
- Place all text on the axis
- Draw the plot
- Identify the maximum width
Text()
object in each column - Horizontally shift each column accordingly
Here's some example code from my use case (note: this example is not robust and assumes va= 'center'
and loc='center'
):
import matplotlib.pyplot as plt
# Assign variables
fig, ax = plt.subplots(1, 1)
renderer = fig.canvas.get_renderer()
transform = ax.transAxes
# Draw center line reference
ax.vlines(.5, ymin=0, ymax=1, transform=transform)
# Place title and label on ax in arbitrary location and draw objects
title_obj = ax.set_title('Subfigure title', va='center', loc='center')
label_obj = ax.text(.5, .5, 'A) ', va='center', fontweight='bold', transform=transform)
plt.draw()
# Get title coordinates, width, and position
bb = title_obj.get_window_extent(renderer=renderer)
bb_coords = bb.transformed(transform.inverted()).get_points()
title_x1, title_x2, title_y1, title_y2 = bb_coords[0][0], bb_coords[1][0], bb_coords[0][1], bb_coords[1][1]
title_w = title_x2 - title_x1
x_pos = title_obj.get_position()[0]
y_pos = (title_y1 + title_y2) / 2
# Get label coordinates and width
bb = label_obj.get_window_extent(renderer=renderer)
bb_coords = bb.transformed(transform.inverted()).get_points()
label_x1, label_x2, label_y1, label_y2 = bb_coords[0][0], bb_coords[1][0], bb_coords[0][1], bb_coords[1][1]
label_w = label_x2 - label_x1
# Define shift offsets
title_offset = label_w / 2
label_offset = -(title_w + label_w) / 2
# Shift title and label horizontally
title_obj.set_position((x_pos + title_offset, y_pos))
label_obj.set_position((x_pos + label_offset, y_pos))
fig.set_facecolor('w')
would be good to see the text to allow left-align with any font.