Problem directory format apps and sizing_mode='stretch_both'

Aloha, all -
I’ve been writing some bokeh apps for my place of work, and have run into a bit of a difficulty in my first attempt to use directory-format apps.

My app consists of six real-time plots in a 2x3 grid. The plots are updated every second. When I run the app as a stand-alone app (not directory format), everything works just fine. The problem comes in when I try to implement the app as a directory app for greater control and options for page formatting.

The problems is this: implementing “sizing_mode=‘stretch_both’” and “stretch_height” both fail spectacularly in exactly the same way: All six plots are reduced to two thin lines at the top of the screen, and do NOT resize with the window at all. This only happens when running in directory mode, and only with ‘stretch_height’ or ‘stretch_both’. I haven’t seen anything here expressing this as a problem, so I’m wondering if somehow I’m doing something wrong.

My editing machine is a mac running 14.1.1 macOS, with bokeh version 3.3.1 and python 3.11.5 and tornado 6.33

Incidentally, directory mode fails completely when running on our production machine, showing only a completely blank browser page. I suspect that is a version issue, as the production machines are Linux with Bokeh 2.3.3, Tornado 6.1, and python 3.6.8.

I’d be most grateful for any ideas on the sizing_mode issue!

This could be a bug or a usage issue. Either way it’s not really possible to speculate at all about anything (i.e. a workaround or different code approach) without a complete Minimal Reproducible Example.

As Bryan said, it is not possible to get a clear picture of the problem without a minimal working code.

Though, I can share my experience with the sizing_mode settings stretch_both, stretch_width and stretch_height.
I observed that the parent layouts (like grid_plot, row, column etc.) up to top level layout have to have the same sizing_mode setting.
This can be done by manually setting the same sizing_mode parameter for all, or setting it for the top level layout and using sizing_mode="inherit" for the children layouts.

Here is a simple example illustrating this behavior:

from bokeh.io import show
from bokeh.plotting import figure
from bokeh.layouts import gridplot

# Prepare some data:
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]

# Create six (identical) plots and store them to a list:
plot_list = []
for i in range(6):
    p = figure(x_axis_label="x", y_axis_label="y", sizing_mode="stretch_both") # <-- Try with or without sizing_mode="stretch_both"
    l = p.line(x, y)
    plot_list.append(p)

# Position the plots in a grid:
my_layout = gridplot([plot_list[:3], plot_list[3:]], sizing_mode="stretch_both") # <-- Try with or without sizing_mode="stretch_both"

show(my_layout)

Following is displayed without any sizing_mode="stretch_both" setting:

With sizing_mode="stretch_both" only for the plots:

The plot areas are collapsed, this has similarities to the problem cfigura described.

With sizing_mode="stretch_both" for the plots as well as for the gridplot:


As expected, the plots fit to the window.

One additional information:
It is possible to combine sizing_mode="stretch_..." with min_width, max_width, min_height and / or max_height settings.
My experience is that these settings are also inherited, but the inheritance get broken in a Tabs layout, so for the tab, the min / max settings have to be given again.

Mahalo Bryan and Icoti for your responses. I’ve put together a minimal working example. Icoti, I appreciate your response, but I think you’ve missed a vital component here (understandable, as I gave no MWE) – the problem exists when I run this as a directory app.

I don’t seem to be able to upload this as a zip file, so let me paste what I’ve got and see if anyone has any ideas.

Note:
if I execute the code as standalone python I get exactly the stretch behaviour one would expect:
python3 -m bokeh serve --show stretch_test/main.py

However, if I execute the code as a directory app, I see correct width behaviour but the collapsed height behaviour:
python3 - m bokeh serve --show stretch_test

If I change “stretch_both” to “stretch_width” or “fixed”, the behaviour is identical across the two execution methods. “stretch_width” shows the same vertically collapsed plots as “stretch_both”.

directory stretch_test contains:
main.py:

from bokeh.layouts import layout, row
from bokeh.plotting import figure, curdoc

# create a few test plots
x = list(range(11))
y0 = x
y1 = [10 - i for i in x]
y2 = [abs(i - 5) for i in x]
y3 = [y2i - y1i for (y2i, y1i) in zip(y2, y1)]

# create three plots
s0 = figure(sizing_mode='stretch_both')
s0.circle(x, y0, size=12, alpha=0.8, color='red')

s1 = figure(sizing_mode='stretch_both')
s1.circle(x, y1, size=12, alpha=0.8, color='blue')

s2 = figure(sizing_mode='stretch_both')
s2.triangle(x, y2, size=12, alpha=0.8, color='green')

s3 = figure(sizing_mode='stretch_both')
s3.square(x, y3, size=12, alpha=0.8, color='orange')

grid = layout([[row(s0, s1)],
               [row(s2, s3)]], sizing_mode='stretch_both')

# put the button and plot in a layout and add to the document
curdoc().add_root(grid)
curdoc().title = 'Stretch Test'

templates/index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>GPP</title>
    <style>
      body { background: #2F2F2F; }
    </style>
    <meta charset="utf-8">
    {{ bokeh_css }}
    {{ bokeh_js }}
    
  </head>
  
  <body>
    {{ plot_div|indent(8) }}
    {{ plot_script|indent(8) }}

  </body>
  
</html>

init.py (empty file)

Yes, I can reproduce the problem.
In the directory format without the index.html file, the problem is not there, so your index.html seems to be broken.

Based on the docs:

and

I tried with the proposed template from the second link and the display works as expected:

{% from macros import embed %}
<!DOCTYPE html>
<html lang="en">
  {% block head %}
  <head>
  {% block inner_head %}
    <meta charset="utf-8">
    <title>{% block title %}{{ title | e if title else "Bokeh Plot" }}{% endblock %}</title>
  {%  block preamble -%}{%- endblock %}
  {%  block resources %}
    <style>
      html, body {
        box-sizing: border-box;
        display: flow-root;
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  {%   block css_resources -%}
    {{- bokeh_css if bokeh_css }}
  {%-  endblock css_resources %}
  {%   block js_resources -%}
    {{  bokeh_js if bokeh_js }}
  {%-  endblock js_resources %}
  {%  endblock resources %}
  {%  block postamble %}{% endblock %}
  {% endblock inner_head %}
  </head>
  {% endblock head%}
  {% block body %}
  <body>
  {%  block inner_body %}
  {%    block contents %}
  {%      for doc in docs %}
  {{        embed(doc) if doc.elementid }}
  {%-       for root in doc.roots %}
  {%          block root scoped %}
  {{            embed(root) }}
  {%          endblock %}
  {%        endfor %}
  {%      endfor %}
  {%    endblock contents %}
  {{ plot_script | indent(4) }}
  {%  endblock inner_body %}
  </body>
  {% endblock body%}
</html>

Then I tried to edit your index.html and replaced the <style> section with the following:

<style>
    html, body {
    height: 100%;
    /* margin: 0; */
    background: #2F2F2F; 
    }
</style>

Then the app is correctly displayed.

For your production machine, you could try to use the template mentioned above and add the parameters you need with as least changes as possible.

@cfigura For further settings to the theme of your app, you might want to have a look here:
Set canvas root elem css in python eg change background of root parent that holds the widgets

1 Like

Icoti, thank you so very much! I finally had the chance to try your fix, and that did work very well! I suspected that there was a problem in the html, I was working off of a very basic HTML template from the documentation, but I obviously don’t know enough HTML to have sorted that out myself.

I really appreciate your help, and thank you for the links to the additional resources!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.