Figures in layout: when I export these figures to PNGs, each next image is 100px wider than previous

Hi folks! I’m trying to export some figures to PNGs with bokeh.io.export_png(fig, filename=fname, width=width, height=height).

And I’m getting some strange behaviour: when I call this function second time, the next image is 100px wider than I ordered by width argument. Third image is 200px wider — and so on.

Here’s a small code example:

import numpy as np
import bokeh.io
from bokeh.plotting import *
from bokeh.layouts import column, gridplot, layout
from bokeh.models import ColumnDataSource

if __name__ == "__main__":
    # lets' prepare some date
    N = 300
    x = np.linspace(0, 4 * np.pi, N)
    y0 = np.sin(x)
    y1 = np.cos(x)
    y2 = np.abs(np.cos(x))

    # create a column data source for the plots to share
    source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1, y2=y2))

    # create a new plot and add a renderer
    left = figure(width=600, height=400, title=None)
    left.circle('x', 'y0', source=source)

    right = figure(width=600, height=350, title=None)
    right.circle('x', 'y1', source=source)

    bottom = figure(width=600, height=400, title=None)
    bottom.circle('x', 'y2', source=source)

    # put the subplots in a gridplot
    layout = layout([[left, right], [bottom]], sizing_mode='stretch_width', height=1800)

    show(layout)  # show the plots in layout: layout looks okay...

    # And let's try to export some figures to PNGs (here we export only two images, but for real tasks we have more
    # complicated layouts, and we use bokeh server to modify plots on-the-fly and export them again and again).

    for i in range(5):
        bokeh.io.export_png(left, filename="left{}.png".format(i), width=800, height=500)
        bokeh.io.export_png(right, filename="right{}.png".format(i), width=800, height=500)

    # And what we get? After each export to PNG each next image becomes 100px wider. I don't know why = (((

    # left0.png: 800x500
    # right0.png: 900x500
    # left1.png: 1000x500
    # right1.png: 1100x500
    # left2.png: 1200x500
    # right2.png: 1300x500
    # left3.png: 1400x500
    # right3.png: 1500x500
    # left4.png: 1600x500
    # left4.png: 1700x500, it's almost twice wider than ordered!

Can you please tell me how to fix it?

P.S. I use bokeh version 2.2.1 (installed by pip install --force bokeh), OS: Windows 10x64, webdriver: chromium

@Felix-neko Without getting too far in the weeds, I do think that some of this combination of usage is a bit unusual, so I guess issues aren’t too surprising. That said, I’d still probably recommend making a Github issue with all this information.

In the mean time I only have two suggestions:

  • setting a "fixed" sizing mode on the plots before passing to export_png
  • manually create and pass in a new webdriver to every export_png call (I expect the combination of responsive sizing modes and re-used webdriver state is somehow at the root of the issue). This will be slower as creating a webdriver is somewhat expensive (why we try to re-use one by default)
1 Like

To set? Can you please explain in more details?

@Felix-neko it was an accidental mis-post and I got called away to a work call before I could finish editing and re-posting. It is updated now.

Well, I think we don’t need to create a separate webdriver but can tell our current driver to have the given viewport size.

https://github.com/bokeh/bokeh/issues/10496#issuecomment-692561200 – here’s a small description how I do it, maybe you can do it automatically in next version of bokeh, I think it will be useful.