proplot-dev / proplot

🎨 A succinct matplotlib wrapper for making beautiful, publication-quality graphics
https://proplot.readthedocs.io
MIT License
1.07k stars 96 forks source link

TypeError when passing unit-string xlabelpad or ylabelpad to format #366

Closed tariks closed 1 year ago

tariks commented 2 years ago

Description

Bug on savefig when xlabelpad != ylabelpad (I think). Would complete all plotting code but throw: TypeError: can't multiply sequence by non-int of type 'float' when savefig is called. vscode traceback leads to this line:

self.label.set_position( (x, bottom - self.labelpad * self.figure.dpi / 72) )

I think self.labelpad is a list in this case, or similar, causing the error on multiplication. This resolved after changing subplots call from

xlabelpad='.5em', ylabelpad='.3em',

to

labelpad='.3em',

Steps to reproduce

a 1x2 figure with a panel, axes creation/format calls were:

fig, axs = pplt.subplots(
    nrows=1,
    ncols=2,
    figwidth='8.7cm',
    share=False,
    gridalpha=.6,
    gridstyle=(0,(1,2.5)),
    left=None,
    right=None,
    yticks=None,
    yticklen=0,
    xlabelpad='.5m',
    ylabelpad='.3m',
    #labelpad='.3em',
    xloc=('axes',-.04),
    yloc='left',
    refaspect=.75,
    wpad='.1em',
)
# plotting code
axs[0].format(
    xlim=(-0, 4.5),
    grid=False,
    ylim=ylim,
    xlabel="Hazard ratio",
    title="Univariate Cox analysis",
    titleloc="left",
    yloc="none",
    xticks=[0,1,2,3,4],
)
# code
panel = ax.panel("left", share=True)
# more code
panel.format(
    xlim=(-0.02, 2),
    ylim=ax.get_ylim(),
    grid=False,
    xloc="none",
    yloc="none",
)
# second subplot starts next
axs[1].format(
    yloc=("axes", -0.08),
    ylim=(0.2, 1.01),
    xlim=(0, 40),
    yticks=np.array([.2,.4,.6,.8,1]),
    ticklen=2,
    yminorlocator='minor',
    yminorlocator_kw={'n': 2},
    yformatter="{x:.0%}",
    xlabel="Days from admission",
    grid=True,
    title="Kaplan-Meier curves",
    ylabel="Survival",
)
# plot, legend, then
fig.savefig("../plots/forest.pdf", dpi=1200, transparent=True, ) # crash here

Expected behavior: To render and save fig normally if separate label pads are given.

Actual behavior: Crash on savefig

lukelbd commented 1 year ago

This should be fixed by d44b25b. Axis label keyword args are now run through the rc setting validators, so that xlabelpad and ylabelpad unit-strings get converted to points. Example:

fig, ax = pplt.subplots()
ax.format(xlabel='xlabel', ylabel='ylabel')
ax.format(labelcolor='red', xlabelpad='1em', ylabelpad='3em')

iTerm2 AXV3Dr tmpnu2mpdcs