Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new child to existing column #5518

Closed
mrocklin opened this issue Dec 7, 2016 · 18 comments
Closed

Add new child to existing column #5518

mrocklin opened this issue Dec 7, 2016 · 18 comments

Comments

@mrocklin
Copy link
Contributor

@mrocklin mrocklin commented Dec 7, 2016

When adding a child plot to an existing column and then updating the plot appears but then I get the following error:

bokeh.server.protocol.server_handler - ERROR - error handling message Message 'PATCH-DOC' (revision 1): RuntimeError('Cannot apply patch to 8cf5ddd0-9b96-49fc-8099-c792733d0ff5 which is not in the document',)

And my figures come out wonky:

image

 
    def __init__(...):
        ...
        self.sizing_mode = 'scale_width'
        self.figures = {}
        self.sources = {}
        self.root = column(sizing_mode=self.sizing_mode)

    def add_figure(self, name):
        source = ColumnDataSource({'x': [], 'y': []})
        fig = figure(title=name, tools='', height=150, sizing_mode=self.sizing_mode)
        fig.line(source=source, x='x', y='y')
        self.sources[name] = source
        self.figures[name] = fig
        self.root.children = self.root.children + [fig]

    def update(self):
        for name, counter in self.server.counters.items():
            if name not in self.figures:
                self.add_figure(name)
            else:
                xs = [counter.quantile(i / 100) for i in range(101)]
                ys = [xs[i + 1] - xs[i] for i in range(len(xs) - 1)]
                self.sources[name].data.update({'x': xs, 'y': ys})
@mattpap
Copy link
Contributor

@mattpap mattpap commented Dec 7, 2016

That error is unexpected. Failing on layout is something that would normally happen. Layout, as currently implemented, doesn't like changes.

@mrocklin
Copy link
Contributor Author

@mrocklin mrocklin commented Dec 7, 2016

I'm also fine with a "this is not supported" answer. I can find ways around this if necessary.

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Dec 7, 2016

It should be supported, we've always intended to have a second pass to shore up some rough edges around layout there just have not been resources to do it yet.

@mattpap
Copy link
Contributor

@mattpap mattpap commented Dec 7, 2016

I'm also fine with a "this is not supported" answer.

No, 'PATCH-DOC' (revision 1): RuntimeError('Cannot apply patch (...)') always indicates a bug in core bokeh's (or bokehjs') infrastructure (or around it, e.g. API allowing data structures not supported down the chain).

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Dec 7, 2016

Yes, the protocol is supposed to afford adding new models, not just patching existing ones.

@azjps
Copy link
Contributor

@azjps azjps commented Jan 6, 2017

Encountered similar issue, although was not adding a new figure but instead adding a new completely unrelated DOM element. This apparently causes the constraint solver to fail, but only when certain other models like figures are in the document.

Here's a minimal reproducible example:

from bokeh.layouts import column
from bokeh.models.widgets import (Button, Div)
from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import curdoc, figure

source = ColumnDataSource(data={"x": [0], "y": [0]})
fig = figure(plot_width=500, plot_height=300)
fig.circle(x="x", y="y", source=source)
button = Button(label="Add point")

column1 = column([fig,
                  button])
column2 = column([])

counter = 0 
def on_click():
  global counter
  counter += 1 
  source.stream({"x": [counter], "y": [counter]})
  column2.children = [Div(text=str(counter))]  # new, completely unrelated, element

button.on_click(on_click)

curdoc().add_root(column([column1, column2]))

When you click on the button, it gives a JS error:

Uncaught Error: unknown constraint
    at Solver.removeConstraint (bokeh.js:46936)
    at Solver.exports.Solver.Solver.remove_constraint (bokeh.js:2324)
    at Object.exports.update_constraints (bokeh.js:2158)
    at PlotCanvasView.exports.PlotCanvasView.PlotCanvasView.update_constraints (bokeh.js:18141)
    at PlotCanvasView.exports.PlotCanvasView.PlotCanvasView.render (bokeh.js:18079)
    at later (bokeh.js:4381)

Note that no error arises however if either

  • The figure is removed from the example
  • The unrelated layout is not updated in on_click

I recall reading a related issue which suggested that there could be issues with changing the children of a layout, unfortunately I can't find that issue ticket right now. I forget though if its a todo or a won't-do; if the latter it would not be possible to say have a dynamic number of plots, which would be a blocking issue for me.

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Jan 6, 2017

Thanks for the test case, just FYI resolving this is one of my top two priorities for 0.12.5

@azjps
Copy link
Contributor

@azjps azjps commented Jan 6, 2017

Thanks, good to know. (also figured it'd be helpful to have the JS error pasted above so that it could be searched for in the issue tracker.)

@mattpap mattpap added this to the 0.12.5 milestone Jan 6, 2017
@mattpap mattpap self-assigned this Jan 6, 2017
@mattpap
Copy link
Contributor

@mattpap mattpap commented Feb 21, 2017

I tried to reproduce the original issue on top of master and I wasn't able. Perhaps this issue may depend on how bokeh server is used. @mrocklin, can you provide a complete setup for the snipped you gave earlier?

@mattpap
Copy link
Contributor

@mattpap mattpap commented Feb 21, 2017

@azjps' issue is something different and easily reproducible. Also, replacing widgets with plots gives you different kinds of errors (e.g. unknown edit variable).

@pstoeckl
Copy link

@pstoeckl pstoeckl commented Feb 22, 2017

Came across a similar issue, so am chiming in here with another toy example in case it proves useful. Clicking 'Replace Plot', then 'Expand Range', will trigger the same 'unknown constraint' error reported above:

from bokeh.layouts import row, column
from bokeh.models.sources import ColumnDataSource
from bokeh.models.widgets import Button
from bokeh.plotting import figure, curdoc

x = range(0,13)
y = range(2,15)
circ = ColumnDataSource(dict(x=[0,1],y=[0,1]))

fig = figure(y_axis_type='log')
fig.line(x,y)
fig2 = figure()
fig2.circle(x='x',y='y',source=circ)

but = Button(label="Replace Plot")
but2 = Button(label="Expand Range")

c = column(but, but2, fig, fig2)

def replace_plot():
    fig3 = figure(y_axis_type='linear')
    fig3.line(x,y)
    c.children[2] = fig3

def expand_range():
    circ.data['y'] = [0, 5001]

but.on_click(replace_plot)
but2.on_click(expand_range)

curdoc().add_root(c)

Differences to the previous example:

  • here, a figure is replaced rather than added
  • the triggering condition is a dynamic plot range update

Similarly to the previous example, the error also occurs if replace_plot adds a new figure instead, but does not occur if replace_plot is never called. (Tested on Bokeh 0.12.4 via bokeh serve.)

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Feb 26, 2017

@mattpap just FYI I think some things I'm recording in #4875 might have some (at least tnagential) bearing here. You should merge in the array intersection fix at the very least, since caused problems when new models were added. But see also the comments about attach_document in the other issue. Those changes alone don't fix this issue, but they might be necessary preconditions.

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Apr 26, 2017

@azjps example was fixed by #5976 but there is still some follow on work to get @pstoeckl example working as well, so leaving open for now.

@philippjfr
Copy link
Contributor

@philippjfr philippjfr commented May 15, 2017

Seeing the same issue in a condition similar to @pstoeckl's example using bokeh 0.12.6dev4, it all seems to work despite the errors though.

@mattpap
Copy link
Contributor

@mattpap mattpap commented May 15, 2017

@philippjfr, because those errors come from views that aren't relevant anymore, but weren't destroyed yet.

@bryevdv
Copy link
Member

@bryevdv bryevdv commented Jun 1, 2017

I think this might also be related to #4810 (same PATCH-DOC error messages)

Also, confirming still an issue as of 0.12.6dev7

@dantamont
Copy link

@dantamont dantamont commented Dec 8, 2017

Has this issue been resolved? I am encountering the same error when trying to replace a row in my layout with some new widgets.

@RobMulla
Copy link

@RobMulla RobMulla commented Jan 18, 2018

I'm also experiencing this issue.

My version of python and bokeh:

>>> import sys
>>> import bokeh
>>> print(sys.version)
3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 12:04:33)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
>>> print(bokeh.__version__)
0.12.13

This is a simplified version of the main.py that creates the error.

from bokeh.io import curdoc
from bokeh.layouts import row, column, widgetbox
from bokeh.models.widgets import Slider, TextInput, Button
from bokeh.plotting import figure
from bokeh.models.widgets import Panel, Tabs


def query_prop_data():
    # Query data goes in here
    tab1_plots.children[0] = figure(plot_height=500,
                                    plot_width=1000,
                                    title='QUERY PLOT DONE')
    tab2_plots.children[0] = figure(plot_height=500,
                                    plot_width=1000,
                                    title='QUERY PLOT DONE')
    return


def refresh_plots():
    # Refresh Plot goes in here
    tab1_plots.children[0] = figure(plot_height=500,
                                    plot_width=1000,
                                    title='PLOT REFRESHED')
    return


def update(attr, old, new):
    refresh_plots()
    return


# Setup Widgets
window = Slider(title="Change only tab 1", value=0, start=0, end=35, step=7)
prop_txt = TextInput(placeholder='enter prop code', title='PROPERTY CODE:')
run_button = Button(label='Query', button_type='success')

for widget in [window]:
    widget.on_change('value', update)

for widget in [run_button]:
    widget.on_click(query_prop_data)

inputs = widgetbox(prop_txt, run_button, window)

tab1_plots = row(column())
tab2_plots = row(column())

tab1_plots.children[0] = figure(plot_height=500,
                                plot_width=1000,
                                title='QUERY A PROPERTY TO GENERATE PLOT')
tab2_plots.children[0] = figure(plot_height=500,
                                plot_width=1000,
                                title='QUERY A PROPERTY TO GENERATE PLOT')


tab1 = Panel(child=tab1_plots, title="Tab1")
tab2 = Panel(child=tab2_plots, title="Tab2")

tabs = Tabs(tabs=[tab1, tab2], width=1000)
page_layout = row(children=[inputs, tabs], sizing_mode='fixed')

curdoc().add_root(page_layout)
curdoc().title = "Forecast Analysis"

Only occurs when query_prop_data is called (by clicking the Button)

I start up my server with
$bokeh serve --show bokehtest

Each time the query button is clicked I get four lines like this:

2018-01-18 13:48:51,357 Cannot apply patch to aa41f426-0641-4ddf-b418-f0c92bcd3d24 which is not in the document anymore
2018-01-18 13:48:51,359 Cannot apply patch to aa41f426-0641-4ddf-b418-f0c92bcd3d24 which is not in the document anymore
2018-01-18 13:48:51,360 Cannot apply patch to aa41f426-0641-4ddf-b418-f0c92bcd3d24 which is not in the document anymore
2018-01-18 13:48:51,361 Cannot apply patch to aa41f426-0641-4ddf-b418-f0c92bcd3d24 which is not in the document anymore

Not sure if this is a code issue on my part or a bug. Hope that helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

8 participants
You can’t perform that action at this time.