Use a custom model with bokeh serve

Hi everyone,
I needed to modify the ResetTool so that it resets the plot view but not the data selection. I did that using the custom tool mechanism to create a new ResetView tool. Things work well in a minimal example that I launch as >python custom_tool.py , but it doesn’t work if I include the new class in my larger application that I launch with >bokeh serve -app.py, in which case I get the following error:

Traceback (most recent call last):

File “src/bokeh_apps/example_1.py”, line 289, in

SESSION = push_session(DOC, session_id=sys.argv[1])

File “/Users/…/bokeh/client/session.py”, line 63, in push_session

session.push(document)

File “/Users/…/bokeh/client/session.py”, line 270, in push

self._connection.push_doc(doc)

File “/Users/…/bokeh/client/_connection.py”, line 231, in push_doc

raise RuntimeError("Failed to push document: " + reply.content['text'])

RuntimeError: Failed to push document: KeyError(“View model name ‘ResetView’ not found”,)

The new class is simply the original ResetTool class stripped of a few lines:

class ResetView(Tool):

__implementation__ = """

    ActionTool = require "models/tools/actions/action_tool"

    class ResetViewView extends ActionTool.View

      do: () ->

        @plot_view.clear_state()

        @plot_view.reset_range()

    class ResetView extends ActionTool.Model

      default_view: ResetViewView

      type: "ResetTool"

      tool_name: "Reset view"

      icon: "bk-tool-icon-reset"

    module.exports = {

      Model: ResetView

      View: ResetViewView

    }

    """

I did look at the models/custom.py example but that didn’t help me to understand what I am missing.

Thanks a lot for any help!

Gerardo

I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!

Thanks for the feedback David. I am indeed doing it in a django context and will try that right away.

I just realized though that i get the same error also in a bokeh-only context. The following code replicate the error (launch >bokeh serve and separately >python script.py)

script.py:

from bokeh.models import ColumnDataSource, Tool, WheelZoomTool, BoxSelectTool

from bokeh.plotting import figure

from bokeh.io import curdoc, push_session

class ResetView(Tool):

__implementation__ = """

    ActionTool = require "models/tools/actions/action_tool"

    class ResetViewView extends ActionTool.View

      do: () ->

        @plot_view.clear_state()

        @plot_view.reset_range()

    class ResetView extends ActionTool.Model

      default_view: ResetViewView

      type: "ResetTool"

      tool_name: "Reset view"

      icon: "bk-tool-icon-reset"

    module.exports = {q 

      Model: ResetView

      View: ResetViewView

    }

    """

source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 7, 9, 4, 6]))

plot = figure(x_range=(0,10), y_range=(0,10), tools=[ResetView(), WheelZoomTool(), BoxSelectTool()])

plot.circle(‘x’, ‘y’, source=source)

doc = curdoc()

doc.add_root(plot)

session = push_session(doc)

session.show()

session.loop_until_closed()

Thanks again!

Gerardo

···

On Wednesday, 28 September 2016 15:58:15 UTC+2, David Pugh wrote:

I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!

Hi Gerardo,

There are definitely examples of Bokeh server apps using custom models: the spectrogram example, and the surface3d example. But I can confirm that your code does not seem to work, although I cannot see anything wrong with it, and trying a few other variations did not get it working as expected, either. I think there is at least the possibility of some kind of bug that is specific to something about this example. Can you post this code in a new GitHub issue, so that I can bring it to the attention of the core dev that should take a look?

Thanks,

Bryan

···

On Sep 28, 2016, at 10:33 AM, [email protected] wrote:

Thanks for the feedback David. I am indeed doing it in a django context and will try that right away.

I just realized though that i get the same error also in a bokeh-only context. The following code replicate the error (launch >bokeh serve and separately >python script.py)

script.py:
from bokeh.models import ColumnDataSource, Tool, WheelZoomTool, BoxSelectTool
from bokeh.plotting import figure
from bokeh.io import curdoc, push_session

class ResetView(Tool):
    __implementation__ = """
        ActionTool = require "models/tools/actions/action_tool"

        class ResetViewView extends ActionTool.View
          do: () ->
            @plot_view.clear_state()
            @plot_view.reset_range()

        class ResetView extends ActionTool.Model
          default_view: ResetViewView
          type: "ResetTool"
          tool_name: "Reset view"
          icon: "bk-tool-icon-reset"

        module.exports = {q
          Model: ResetView
          View: ResetViewView
        }
        """

source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 7, 9, 4, 6]))

plot = figure(x_range=(0,10), y_range=(0,10), tools=[ResetView(), WheelZoomTool(), BoxSelectTool()])
plot.circle('x', 'y', source=source)

doc = curdoc()
doc.add_root(plot)
session = push_session(doc)
session.show()
session.loop_until_closed()

Thanks again!
Gerardo

On Wednesday, 28 September 2016 15:58:15 UTC+2, David Pugh wrote:
I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0cdb3a6d-621a-496a-a600-d61f2017fb45%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Gerardo,

Actually there is a typo in your implementation:

       module.exports = {q
         Model: ResetView
         View: ResetViewView
       }

There is an errant "q" after the brace on the first line. Your code works for me after removing that character.

Thanks,

Bryan

···

On Oct 1, 2016, at 8:37 PM, Bryan Van de Ven <[email protected]> wrote:

Hi Gerardo,

There are definitely examples of Bokeh server apps using custom models: the spectrogram example, and the surface3d example. But I can confirm that your code does not seem to work, although I cannot see anything wrong with it, and trying a few other variations did not get it working as expected, either. I think there is at least the possibility of some kind of bug that is specific to something about this example. Can you post this code in a new GitHub issue, so that I can bring it to the attention of the core dev that should take a look?

Thanks,

Bryan

On Sep 28, 2016, at 10:33 AM, [email protected] wrote:

Thanks for the feedback David. I am indeed doing it in a django context and will try that right away.

I just realized though that i get the same error also in a bokeh-only context. The following code replicate the error (launch >bokeh serve and separately >python script.py)

script.py:
from bokeh.models import ColumnDataSource, Tool, WheelZoomTool, BoxSelectTool
from bokeh.plotting import figure
from bokeh.io import curdoc, push_session

class ResetView(Tool):
   __implementation__ = """
       ActionTool = require "models/tools/actions/action_tool"

       class ResetViewView extends ActionTool.View
         do: () ->
           @plot_view.clear_state()
           @plot_view.reset_range()

       class ResetView extends ActionTool.Model
         default_view: ResetViewView
         type: "ResetTool"
         tool_name: "Reset view"
         icon: "bk-tool-icon-reset"

       module.exports = {q
         Model: ResetView
         View: ResetViewView
       }
       """

source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 7, 9, 4, 6]))

plot = figure(x_range=(0,10), y_range=(0,10), tools=[ResetView(), WheelZoomTool(), BoxSelectTool()])
plot.circle('x', 'y', source=source)

doc = curdoc()
doc.add_root(plot)
session = push_session(doc)
session.show()
session.loop_until_closed()

Thanks again!
Gerardo

On Wednesday, 28 September 2016 15:58:15 UTC+2, David Pugh wrote:
I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0cdb3a6d-621a-496a-a600-d61f2017fb45%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Well,

Sorry, let me add one more comment. Your code worked with a "bokeh serve app.py" version. When I tried again with the bokeh.client and push_session code that you have, it did not work. I cannot say for certain that custom models work with bokeh.client and push_session, so I guess you should open that GH issue after all. However, it may turn out that this is a fundamental limitation of bokeh.client and push_session compared to the "bokeh serve app.py" way of doing things (which is absolutely the recommended way of doing things).

Thanks,

Bryan

···

On Oct 1, 2016, at 8:46 PM, Bryan Van de Ven <[email protected]> wrote:

Gerardo,

Actually there is a typo in your implementation:

      module.exports = {q
        Model: ResetView
        View: ResetViewView
      }

There is an errant "q" after the brace on the first line. Your code works for me after removing that character.

Thanks,

Bryan

On Oct 1, 2016, at 8:37 PM, Bryan Van de Ven <[email protected]> wrote:

Hi Gerardo,

There are definitely examples of Bokeh server apps using custom models: the spectrogram example, and the surface3d example. But I can confirm that your code does not seem to work, although I cannot see anything wrong with it, and trying a few other variations did not get it working as expected, either. I think there is at least the possibility of some kind of bug that is specific to something about this example. Can you post this code in a new GitHub issue, so that I can bring it to the attention of the core dev that should take a look?

Thanks,

Bryan

On Sep 28, 2016, at 10:33 AM, [email protected] wrote:

Thanks for the feedback David. I am indeed doing it in a django context and will try that right away.

I just realized though that i get the same error also in a bokeh-only context. The following code replicate the error (launch >bokeh serve and separately >python script.py)

script.py:
from bokeh.models import ColumnDataSource, Tool, WheelZoomTool, BoxSelectTool
from bokeh.plotting import figure
from bokeh.io import curdoc, push_session

class ResetView(Tool):
  __implementation__ = """
      ActionTool = require "models/tools/actions/action_tool"

      class ResetViewView extends ActionTool.View
        do: () ->
          @plot_view.clear_state()
          @plot_view.reset_range()

      class ResetView extends ActionTool.Model
        default_view: ResetViewView
        type: "ResetTool"
        tool_name: "Reset view"
        icon: "bk-tool-icon-reset"

      module.exports = {q
        Model: ResetView
        View: ResetViewView
      }
      """

source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 7, 9, 4, 6]))

plot = figure(x_range=(0,10), y_range=(0,10), tools=[ResetView(), WheelZoomTool(), BoxSelectTool()])
plot.circle('x', 'y', source=source)

doc = curdoc()
doc.add_root(plot)
session = push_session(doc)
session.show()
session.loop_until_closed()

Thanks again!
Gerardo

On Wednesday, 28 September 2016 15:58:15 UTC+2, David Pugh wrote:
I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0cdb3a6d-621a-496a-a600-d61f2017fb45%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Bryan,
thanks a lot for looking into that! Using the approach discussed by you and the-neworder in this thread, I managed to make the example work also in the “push_session” version. I will add more details in the GH issue that I will post asap.

Although I did implement the “bokeh serve app.py” version successfully, the reason I was going the other route is that in my larger application I envision the user creating one or more plots, all at once or each plot at a different time. The natural approach to implement that seemed to launch the Bokeh server independently and then push new sessions for each new plot. Would you advise to instead launch a new server instance for each plot, essentially creating individual bokeh apps for each plot?

Thanks again, and keep up the great work with Bokeh!

Gerardo

···

On Sunday, 2 October 2016 03:55:46 UTC+2, Bryan Van de ven wrote:

Well,

Sorry, let me add one more comment. Your code worked with a “bokeh serve app.py” version. When I tried again with the bokeh.client and push_session code that you have, it did not work. I cannot say for certain that custom models work with bokeh.client and push_session, so I guess you should open that GH issue after all. However, it may turn out that this is a fundamental limitation of bokeh.client and push_session compared to the “bokeh serve app.py” way of doing things (which is absolutely the recommended way of doing things).

Thanks,

Bryan

On Oct 1, 2016, at 8:46 PM, Bryan Van de Ven [email protected] wrote:

Gerardo,

Actually there is a typo in your implementation:

  module.exports = {q
    Model: ResetView
    View: ResetViewView
  }

There is an errant “q” after the brace on the first line. Your code works for me after removing that character.

Thanks,

Bryan

On Oct 1, 2016, at 8:37 PM, Bryan Van de Ven [email protected] wrote:

Hi Gerardo,

There are definitely examples of Bokeh server apps using custom models: the spectrogram example, and the surface3d example. But I can confirm that your code does not seem to work, although I cannot see anything wrong with it, and trying a few other variations did not get it working as expected, either. I think there is at least the possibility of some kind of bug that is specific to something about this example. Can you post this code in a new GitHub issue, so that I can bring it to the attention of the core dev that should take a look?

Thanks,

Bryan

On Sep 28, 2016, at 10:33 AM, [email protected] wrote:

Thanks for the feedback David. I am indeed doing it in a django context and will try that right away.

I just realized though that i get the same error also in a bokeh-only context. The following code replicate the error (launch >bokeh serve and separately >python script.py)

script.py:

from bokeh.models import ColumnDataSource, Tool, WheelZoomTool, BoxSelectTool

from bokeh.plotting import figure

from bokeh.io import curdoc, push_session

class ResetView(Tool):

implementation = “”"

  ActionTool = require "models/tools/actions/action_tool"
  class ResetViewView extends ActionTool.View
    do: () ->
      @plot_view.clear_state()
      @plot_view.reset_range()
  class ResetView extends ActionTool.Model
    default_view: ResetViewView
    type: "ResetTool"
    tool_name: "Reset view"
    icon: "bk-tool-icon-reset"
  module.exports = {q
    Model: ResetView
    View: ResetViewView
  }
  """

source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 7, 9, 4, 6]))

plot = figure(x_range=(0,10), y_range=(0,10), tools=[ResetView(), WheelZoomTool(), BoxSelectTool()])

plot.circle(‘x’, ‘y’, source=source)

doc = curdoc()

doc.add_root(plot)

session = push_session(doc)

session.show()
session.loop_until_closed()

Thanks again!

Gerardo

On Wednesday, 28 September 2016 15:58:15 UTC+2, David Pugh wrote:

I did find when doing something like this with django as well that it needed the python class of the custom model to be imported when you are getting the session - I was embedding it in django, so had to make sure it was imported on the django side - not sure if this will help if you are just doing a bokeh serve, but the error I was getting was the same!


You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/0cdb3a6d-621a-496a-a600-d61f2017fb45%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.