How to sync datasource between Python/customJS tool callback in server mode?

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute("dataSource[\'undefined\'].data[\'x\'].append(" + x + ")");

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool

  • In the callback, access the geometry property of cb_data

  • In the callback, update a datasource

  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

  from bokeh.io import curdoc
  from bokeh.models.tools import BoxSelectTool
  from bokeh.plotting import figure

  p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])

  def cb(attr, old, new):
      print(new)

  p.tool_events.on_change('geometries', cb)

  curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

  [{'vx0': 228.40625,
          'vx1': 422.40625,
          'vy0': 255,
          'vy1': 435,
          'x0': 3.7384416740761086,
          'y0': 4.0435015998508685,
          'x1': 7.294543959990985,
          'y1': 7.196941929341586,
          'type': 'rect'
         }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

···

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz <[email protected]> wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data['geometry'] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example...
IPython.notebook.kernel.execute("dataSource[\'undefined\'].data[\'x\'].append(" + x + ")");
Because I'm no longer using a notebook, I don't have access to the user's Python kernel. I'm looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. <datasource>.on_change doesn't seem to provide access to the geometry feature of the boxSelectTool, so I think I'm stuck with javascript.

To summarize my needs...
- Execute a callback in response to a box select tool
- In the callback, access the geometry property of cb_data
- In the callback, update a datasource
- Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

--
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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD
···

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc

    from bokeh.models.tools import BoxSelectTool

    from bokeh.plotting import figure



    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])



    def cb(attr, old, new):

        print(new)



    p.tool_events.on_change('geometries', cb)



    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,

      'vx1': 422.40625,

      'vy0': 255,

      'vy1': 435,

      'x0': 3.7384416740761086,

      'y0': 4.0435015998508685,

      'x1': 7.294543959990985,

      'y1': 7.196941929341586,

      'type': 'rect'

     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

drawRectangles.py (4.91 KB)

···

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc

    from bokeh.models.tools import BoxSelectTool

    from bokeh.plotting import figure



    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])



    def cb(attr, old, new):

        print(new)



    p.tool_events.on_change('geometries', cb)



    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,

      'vx1': 422.40625,

      'vy0': 255,

      'vy1': 435,

      'x0': 3.7384416740761086,

      'y0': 4.0435015998508685,

      'x1': 7.294543959990985,

      'y1': 7.196941929341586,

      'type': 'rect'

     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.

···

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc

    from bokeh.models.tools import BoxSelectTool

    from bokeh.plotting import figure



    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])



    def cb(attr, old, new):

        print(new)



    p.tool_events.on_change('geometries', cb)



    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,

      'vx1': 422.40625,

      'vy0': 255,

      'vy1': 435,

      'x0': 3.7384416740761086,

      'y0': 4.0435015998508685,

      'x1': 7.294543959990985,

      'y1': 7.196941929341586,

      'type': 'rect'

     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

First note that you should *always* update a CDS .data dictionary "all at once". There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don't think this was the issue here though. I had to add an explicit .trigger to get things to work:

        new_data = dict(self.undefinedSource.data)

        new_data['x'].append(x)
        new_data['y'].append(y)
        new_data['width'].append(width)
        new_data['height'].append(height)
        new_data['startTime'].append(startTime)
        new_data['endTime'].append(endTime)
        new_data['boxID'].append(self.nextBoxID)
        new_data['trialNum'].append(self.trialNum)
  
  # update entire .data in one go
        self.undefinedSource.data = new_data

  # explicit trigger
        self.undefinedSource.trigger('data', new_data, new_data)

I don't think this explicit trigger should be needed, so I'd encourage you to open an issue on GH with these details. I expect is has something to so with the "bokeh.client" style of use. There are many "app" examples that do not require the explicit trigger call to function. That said, this potential issue asise, I'd also say that this way of interacting with the server, using `bokeh.client` still definitely has intrinsic downsides compared to "app" style (i.e. when you run "bokeh serve myapp.py"). If that is at all an option I would recommend that style as preferable.

Bryan

···

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz <[email protected]> wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz <[email protected]> wrote:
Bryan, there is no change in my browser after updating my sources within the Python callback. I've attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I've looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

- gD

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz <[email protected]> wrote:
Thanks, Bryan! Yes, I'm still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

- gD

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven <[email protected]> wrote:
Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

        from bokeh.io import curdoc
        from bokeh.models.tools import BoxSelectTool
        from bokeh.plotting import figure

        p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])

        def cb(attr, old, new):
            print(new)

        p.tool_events.on_change('geometries', cb)

        curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

        [{'vx0': 228.40625,
          'vx1': 422.40625,
          'vy0': 255,
          'vy1': 435,
          'x0': 3.7384416740761086,
          'y0': 4.0435015998508685,
          'x1': 7.294543959990985,
          'y1': 7.196941929341586,
          'type': 'rect'
         }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

> On Jul 5, 2016, at 10:07 PM, Gabriel Diaz <[email protected]> wrote:
>
> Hello!
>
> I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data['geometry'] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.
>
> In the notebook, I solved this problem by executing Python code inside of the callback. For example...
> IPython.notebook.kernel.execute("dataSource[\'undefined\'].data[\'x\'].append(" + x + ")");
> Because I'm no longer using a notebook, I don't have access to the user's Python kernel. I'm looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. <datasource>.on_change doesn't seem to provide access to the geometry feature of the boxSelectTool, so I think I'm stuck with javascript.
>
> To summarize my needs...
> - Execute a callback in response to a box select tool
> - In the callback, access the geometry property of cb_data
> - In the callback, update a datasource
> - Once the callback has executed, my Python must be in sync with the Javascript environment
>
> Thanks!
>
> --
> 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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io\.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

drawRectanglesB.py (5.24 KB)

···

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)



    new_data['x'].append(x)

    new_data['y'].append(y)

    new_data['width'].append(width)

    new_data['height'].append(height)

    new_data['startTime'].append(startTime)

    new_data['endTime'].append(endTime)

    new_data['boxID'].append(self.nextBoxID)

    new_data['trialNum'].append(self.trialNum)



    # update entire .data in one go

    self.undefinedSource.data = new_data



    # explicit trigger

    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

···

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)



    new_data['x'].append(x)

    new_data['y'].append(y)

    new_data['width'].append(width)

    new_data['height'].append(height)

    new_data['startTime'].append(startTime)

    new_data['endTime'].append(endTime)

    new_data['boxID'].append(self.nextBoxID)

    new_data['trialNum'].append(self.trialNum)



    # update entire .data in one go

    self.undefinedSource.data = new_data



    # explicit trigger

    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

Thanks, Bryan.

···

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven [email protected] wrote:

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz [email protected] wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com.

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

<drawRectanglesB.py>

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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io.

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


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)



    new_data['x'].append(x)

    new_data['y'].append(y)

    new_data['width'].append(width)

    new_data['height'].append(height)

    new_data['startTime'].append(startTime)

    new_data['endTime'].append(endTime)

    new_data['boxID'].append(self.nextBoxID)

    new_data['trialNum'].append(self.trialNum)



    # update entire .data in one go

    self.undefinedSource.data = new_data



    # explicit trigger

    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

​I’ve figured it out. The correct way to establish a callback is…

self.undefinedSource.on_change('selected', self.tap_callback)
···

On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven [email protected] wrote:

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz [email protected] wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com.

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

<drawRectanglesB.py>

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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io.

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


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)



    new_data['x'].append(x)

    new_data['y'].append(y)

    new_data['width'].append(width)

    new_data['height'].append(height)

    new_data['startTime'].append(startTime)

    new_data['endTime'].append(endTime)

    new_data['boxID'].append(self.nextBoxID)

    new_data['trialNum'].append(self.trialNum)



    # update entire .data in one go

    self.undefinedSource.data = new_data



    # explicit trigger

    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Gabriel,

Yes sorry, selections are a property of data sources. If you are interested in doing things when selections change, it is the relevant data source that you would attach a callback too.

Bryan

···

On Jul 8, 2016, at 8:43 AM, Gabriel Diaz <[email protected]> wrote:

​I've figured it out. The correct way to establish a callback is...
self.undefinedSource.on_change('selected', self.tap_callback)

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz <[email protected]> wrote:
Thanks, Bryan.

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven <[email protected]> wrote:
ToolEvents don't have a "selected" property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz <[email protected]> wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I've stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change('selected', self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I'm missing?

Thanks again! I'm getting good at finding these bugs, eH?

- gD

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven <[email protected]> wrote:
First note that you should *always* update a CDS .data dictionary "all at once". There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don't think this was the issue here though. I had to add an explicit .trigger to get things to work:

        new_data = dict(self.undefinedSource.data)

        new_data['x'].append(x)
        new_data['y'].append(y)
        new_data['width'].append(width)
        new_data['height'].append(height)
        new_data['startTime'].append(startTime)
        new_data['endTime'].append(endTime)
        new_data['boxID'].append(self.nextBoxID)
        new_data['trialNum'].append(self.trialNum)

        # update entire .data in one go
        self.undefinedSource.data = new_data

        # explicit trigger
        self.undefinedSource.trigger('data', new_data, new_data)

I don't think this explicit trigger should be needed, so I'd encourage you to open an issue on GH with these details. I expect is has something to so with the "bokeh.client" style of use. There are many "app" examples that do not require the explicit trigger call to function. That said, this potential issue asise, I'd also say that this way of interacting with the server, using `bokeh.client` still definitely has intrinsic downsides compared to "app" style (i.e. when you run "bokeh serve myapp.py"). If that is at all an option I would recommend that style as preferable.

Bokeh server — Bokeh 3.3.2 Documentation

Bryan

> On Jul 7, 2016, at 12:10 PM, Gabriel Diaz <[email protected]> wrote:
>
> Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.
>
>
> ----------------------
>
> Gabriel J. Diaz, Ph.D.
> Assistant Professor
> Rochester Institute of Technology
> Chester F. Carlson Center for Imaging Science
>
> Founder of PerForM Labs
> Click for demos.
>
> Office 2108, Building #76
> Rochester, NY 14623
> Office: (585) 475-6215
> [email protected]
>
>
>
>
>
> On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz <[email protected]> wrote:
> Bryan, there is no change in my browser after updating my sources within the Python callback. I've attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.
>
> I've looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?
>
> Thanks,
>
> - gD
>
>
> ----------------------
>
> Gabriel J. Diaz, Ph.D.
> Assistant Professor
> Rochester Institute of Technology
> Chester F. Carlson Center for Imaging Science
>
> Founder of PerForM Labs
> Click for demos.
>
> Office 2108, Building #76
> Rochester, NY 14623
> Office: (585) 475-6215
> [email protected]
>
>
>
>
>
> On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz <[email protected]> wrote:
> Thanks, Bryan! Yes, I'm still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.
>
> - gD
>
>
> ----------------------
>
> Gabriel J. Diaz, Ph.D.
> Assistant Professor
> Rochester Institute of Technology
> Chester F. Carlson Center for Imaging Science
>
> Founder of PerForM Labs
> Click for demos.
>
> Office 2108, Building #76
> Rochester, NY 14623
> Office: (585) 475-6215
> [email protected]
>
>
>
>
>
> On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven <[email protected]> wrote:
> Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:
>
> from bokeh.io import curdoc
> from bokeh.models.tools import BoxSelectTool
> from bokeh.plotting import figure
>
> p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
>
> def cb(attr, old, new):
> print(new)
>
> p.tool_events.on_change('geometries', cb)
>
> curdoc().add_root(p)
>
> This outputs, e.g. for a BoxSelectTool:
>
> [{'vx0': 228.40625,
> 'vx1': 422.40625,
> 'vy0': 255,
> 'vy1': 435,
> 'x0': 3.7384416740761086,
> 'y0': 4.0435015998508685,
> 'x1': 7.294543959990985,
> 'y1': 7.196941929341586,
> 'type': 'rect'
> }]
>
> (Note: I formatted the output with line breaks, etc. for better presentation in the email)
>
> If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.
>
> Thanks,
>
> Bryan
>
> > On Jul 5, 2016, at 10:07 PM, Gabriel Diaz <[email protected]> wrote:
> >
> > Hello!
> >
> > I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data['geometry'] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.
> >
> > In the notebook, I solved this problem by executing Python code inside of the callback. For example...
> > IPython.notebook.kernel.execute("dataSource[\'undefined\'].data[\'x\'].append(" + x + ")");
> > Because I'm no longer using a notebook, I don't have access to the user's Python kernel. I'm looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. <datasource>.on_change doesn't seem to provide access to the geometry feature of the boxSelectTool, so I think I'm stuck with javascript.
> >
> > To summarize my needs...
> > - Execute a callback in response to a box select tool
> > - In the callback, access the geometry property of cb_data
> > - In the callback, update a datasource
> > - Once the callback has executed, my Python must be in sync with the Javascript environment
> >
> > Thanks!
> >
> > --
> > 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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io\.
> > For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>
> --
> 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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io\.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>
>
>
>
> --
> 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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com\.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
<drawRectanglesB.py>

--
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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io\.

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

--
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/CAFvLWO2%3Doq1xTqOpVJ%2BjUX_w1keKRDrEVwA-DPz08JB0O5HHRg%40mail.gmail.com\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Time for the reveal! Thanks for your continued support. Unfortunately, there are still issues related to the proper updating of the figure in response to a change in source data. It does not appear that the trigger issue is specific to the use of bokeh.client. In fact, the fix you had suggested previously, to use an explicit trigger, doesn’t always work.

I demonstrate this here:

https://github.com/performlabrit/label_events

The method, “changeTrial()” is called in response to a change in the trial number in the text input box. Try switching between trials 10 and 0. If you look at the console, printouts show that the data sources do change, and accurately reflect the new trial number. The datasources have been made global inside changeTrial(), so this change should affect the figure. However, it does not! The sources change, but the figure remains the same. Any more suggestions?

Oh, and you want to explore the full functionality of the app, feel free to play around with the boxSelectTool to add more events, select them with tap tool, and label / remove them with the buttons. It will work just fine until you change the trial number (using the text input box). Subsequent issues are likely related to mismatches between sources in the figure and javascript.

  • gD
···

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 1:28 PM, Bryan Van de Ven [email protected] wrote:

Gabriel,

Yes sorry, selections are a property of data sources. If you are interested in doing things when selections change, it is the relevant data source that you would attach a callback too.

Bryan

On Jul 8, 2016, at 8:43 AM, Gabriel Diaz [email protected] wrote:

​I’ve figured it out. The correct way to establish a callback is…

self.undefinedSource.on_change(‘selected’, self.tap_callback)


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven [email protected] wrote:

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz [email protected] wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)
    new_data['x'].append(x)
    new_data['y'].append(y)
    new_data['width'].append(width)
    new_data['height'].append(height)
    new_data['startTime'].append(startTime)
    new_data['endTime'].append(endTime)
    new_data['boxID'].append(self.nextBoxID)
    new_data['trialNum'].append(self.trialNum)
    # update entire .data in one go
    self.undefinedSource.data = new_data
    # explicit trigger
    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.

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

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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com.

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

<drawRectanglesB.py>

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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io.

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

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/CAFvLWO2%3Doq1xTqOpVJ%2BjUX_w1keKRDrEVwA-DPz08JB0O5HHRg%40mail.gmail.com.

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

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/6D659CF3-624F-47B8-BE52-D2D351076327%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Ok, problem solved! I was rewriting the datasources, rather than just datasource.data. This broke the connection between the figure and sources. Pushing to github now.

Thanks again,

  • gD
···

On Sun, Jul 10, 2016 at 10:39 AM, Gabriel Diaz [email protected] wrote:

Time for the reveal! Thanks for your continued support. Unfortunately, there are still issues related to the proper updating of the figure in response to a change in source data. It does not appear that the trigger issue is specific to the use of bokeh.client. In fact, the fix you had suggested previously, to use an explicit trigger, doesn’t always work.

I demonstrate this here:

https://github.com/performlabrit/label_events

The method, “changeTrial()” is called in response to a change in the trial number in the text input box. Try switching between trials 10 and 0. If you look at the console, printouts show that the data sources do change, and accurately reflect the new trial number. The datasources have been made global inside changeTrial(), so this change should affect the figure. However, it does not! The sources change, but the figure remains the same. Any more suggestions?

Oh, and you want to explore the full functionality of the app, feel free to play around with the boxSelectTool to add more events, select them with tap tool, and label / remove them with the buttons. It will work just fine until you change the trial number (using the text input box). Subsequent issues are likely related to mismatches between sources in the figure and javascript.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 1:28 PM, Bryan Van de Ven [email protected] wrote:

Gabriel,

Yes sorry, selections are a property of data sources. If you are interested in doing things when selections change, it is the relevant data source that you would attach a callback too.

Bryan

On Jul 8, 2016, at 8:43 AM, Gabriel Diaz [email protected] wrote:

​I’ve figured it out. The correct way to establish a callback is…

self.undefinedSource.on_change(‘selected’, self.tap_callback)


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven [email protected] wrote:

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz [email protected] wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)
    new_data['x'].append(x)
    new_data['y'].append(y)
    new_data['width'].append(width)
    new_data['height'].append(height)
    new_data['startTime'].append(startTime)
    new_data['endTime'].append(endTime)
    new_data['boxID'].append(self.nextBoxID)
    new_data['trialNum'].append(self.trialNum)
    # update entire .data in one go
    self.undefinedSource.data = new_data
    # explicit trigger
    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.

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

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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com.

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

<drawRectanglesB.py>

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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io.

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

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/CAFvLWO2%3Doq1xTqOpVJ%2BjUX_w1keKRDrEVwA-DPz08JB0O5HHRg%40mail.gmail.com.

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

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/6D659CF3-624F-47B8-BE52-D2D351076327%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Gabriel,

I've been pretty swamped this past week, but I am glad to hear that the issue is figured out. I look forward to checkout out the final app. If there are suggestions for docs or examples improvements based on your experience (or if you would be interested in writing up something for our new Bokeh blog), please let us know.

Thanks,

Bryan

···

On Jul 12, 2016, at 9:36 AM, Gabriel Diaz <[email protected]> wrote:

Ok, problem solved! I was rewriting the datasources, rather than just datasource.data. This broke the connection between the figure and sources. Pushing to github now.

Thanks again,
- gD

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Sun, Jul 10, 2016 at 10:39 AM, Gabriel Diaz <[email protected]> wrote:
Time for the reveal! Thanks for your continued support. Unfortunately, there are still issues related to the proper updating of the figure in response to a change in source data. It does not appear that the trigger issue is specific to the use of bokeh.client. In fact, the fix you had suggested previously, to use an explicit trigger, doesn't always work.

I demonstrate this here:
GitHub - gabrielDiaz-performlab/label_events: A bokeh app to enable the manual labelling of events in time series data.

The method, "changeTrial()" is called in response to a change in the trial number in the text input box. Try switching between trials 10 and 0. If you look at the console, printouts show that the data sources do change, and accurately reflect the new trial number. The datasources have been made global inside changeTrial(), so this change should affect the figure. However, it does not! The sources change, but the figure remains the same. Any more suggestions?

Oh, and you want to explore the full functionality of the app, feel free to play around with the boxSelectTool to add more events, select them with tap tool, and label / remove them with the buttons. It will work just fine until you change the trial number (using the text input box). Subsequent issues are likely related to mismatches between sources in the figure and javascript.

- gD

----------------------

Gabriel J. Diaz, Ph.D.
Assistant Professor
Rochester Institute of Technology
Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs
Click for demos.

Office 2108, Building #76
Rochester, NY 14623
Office: (585) 475-6215
[email protected]

On Fri, Jul 8, 2016 at 1:28 PM, Bryan Van de Ven <[email protected]> wrote:
Gabriel,

Yes sorry, selections are a property of data sources. If you are interested in doing things when selections change, it is the relevant data source that you would attach a callback too.

Bryan

> On Jul 8, 2016, at 8:43 AM, Gabriel Diaz <[email protected]> wrote:
>
> ​I've figured it out. The correct way to establish a callback is...
> self.undefinedSource.on_change('selected', self.tap_callback)
>
>
>
> ----------------------
>
> Gabriel J. Diaz, Ph.D.
> Assistant Professor
> Rochester Institute of Technology
> Chester F. Carlson Center for Imaging Science
>
> Founder of PerForM Labs
> Click for demos.
>
> Office 2108, Building #76
> Rochester, NY 14623
> Office: (585) 475-6215
> [email protected]
>
>
>
>
>
> On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz <[email protected]> wrote:
> Thanks, Bryan.
>
>
> ----------------------
>
> Gabriel J. Diaz, Ph.D.
> Assistant Professor
> Rochester Institute of Technology
> Chester F. Carlson Center for Imaging Science
>
> Founder of PerForM Labs
> Click for demos.
>
> Office 2108, Building #76
> Rochester, NY 14623
> Office: (585) 475-6215
> [email protected]
>
>
>
>
>
> On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven <[email protected]> wrote:
> ToolEvents don't have a "selected" property. You want callback on the data source for the rects. Sorry on phone can say more later
>
> On Jul 7, 2016, at 18:23, Gabriel Diaz <[email protected]> wrote:
>
>> Thanks, Bryan. That does work, and I will report it. However, it looks like I've stumbled across another potentially related bug.
>>
>> In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change('selected', self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.
>>
>> See the attached example for a demo.
>>
>> Shall I submit this one, as well, or is there something I'm missing?
>>
>> Thanks again! I'm getting good at finding these bugs, eH?
>>
>> - gD
>>
>>
>> ----------------------
>>
>> Gabriel J. Diaz, Ph.D.
>> Assistant Professor
>> Rochester Institute of Technology
>> Chester F. Carlson Center for Imaging Science
>>
>> Founder of PerForM Labs
>> Click for demos.
>>
>> Office 2108, Building #76
>> Rochester, NY 14623
>> Office: (585) 475-6215
>> [email protected]
>>
>>
>>
>>
>>
>> On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven <[email protected]> wrote:
>> First note that you should *always* update a CDS .data dictionary "all at once". There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don't think this was the issue here though. I had to add an explicit .trigger to get things to work:
>>
>> new_data = dict(self.undefinedSource.data)
>>
>> new_data['x'].append(x)
>> new_data['y'].append(y)
>> new_data['width'].append(width)
>> new_data['height'].append(height)
>> new_data['startTime'].append(startTime)
>> new_data['endTime'].append(endTime)
>> new_data['boxID'].append(self.nextBoxID)
>> new_data['trialNum'].append(self.trialNum)
>>
>> # update entire .data in one go
>> self.undefinedSource.data = new_data
>>
>> # explicit trigger
>> self.undefinedSource.trigger('data', new_data, new_data)
>>
>>
>> I don't think this explicit trigger should be needed, so I'd encourage you to open an issue on GH with these details. I expect is has something to so with the "bokeh.client" style of use. There are many "app" examples that do not require the explicit trigger call to function. That said, this potential issue asise, I'd also say that this way of interacting with the server, using `bokeh.client` still definitely has intrinsic downsides compared to "app" style (i.e. when you run "bokeh serve myapp.py"). If that is at all an option I would recommend that style as preferable.
>>
>> Bokeh server — Bokeh 3.3.2 Documentation
>>
>> Bryan
>>
>> > On Jul 7, 2016, at 12:10 PM, Gabriel Diaz <[email protected]> wrote:
>> >
>> > Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.
>> >
>> >
>> > ----------------------
>> >
>> > Gabriel J. Diaz, Ph.D.
>> > Assistant Professor
>> > Rochester Institute of Technology
>> > Chester F. Carlson Center for Imaging Science
>> >
>> > Founder of PerForM Labs
>> > Click for demos.
>> >
>> > Office 2108, Building #76
>> > Rochester, NY 14623
>> > Office: (585) 475-6215
>> > [email protected]
>> >
>> >
>> >
>> >
>> >
>> > On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz <[email protected]> wrote:
>> > Bryan, there is no change in my browser after updating my sources within the Python callback. I've attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.
>> >
>> > I've looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?
>> >
>> > Thanks,
>> >
>> > - gD
>> >
>> >
>> > ----------------------
>> >
>> > Gabriel J. Diaz, Ph.D.
>> > Assistant Professor
>> > Rochester Institute of Technology
>> > Chester F. Carlson Center for Imaging Science
>> >
>> > Founder of PerForM Labs
>> > Click for demos.
>> >
>> > Office 2108, Building #76
>> > Rochester, NY 14623
>> > Office: (585) 475-6215
>> > [email protected]
>> >
>> >
>> >
>> >
>> >
>> > On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz <[email protected]> wrote:
>> > Thanks, Bryan! Yes, I'm still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.
>> >
>> > - gD
>> >
>> >
>> > ----------------------
>> >
>> > Gabriel J. Diaz, Ph.D.
>> > Assistant Professor
>> > Rochester Institute of Technology
>> > Chester F. Carlson Center for Imaging Science
>> >
>> > Founder of PerForM Labs
>> > Click for demos.
>> >
>> > Office 2108, Building #76
>> > Rochester, NY 14623
>> > Office: (585) 475-6215
>> > [email protected]
>> >
>> >
>> >
>> >
>> >
>> > On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven <[email protected]> wrote:
>> > Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:
>> >
>> > from bokeh.io import curdoc
>> > from bokeh.models.tools import BoxSelectTool
>> > from bokeh.plotting import figure
>> >
>> > p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
>> >
>> > def cb(attr, old, new):
>> > print(new)
>> >
>> > p.tool_events.on_change('geometries', cb)
>> >
>> > curdoc().add_root(p)
>> >
>> > This outputs, e.g. for a BoxSelectTool:
>> >
>> > [{'vx0': 228.40625,
>> > 'vx1': 422.40625,
>> > 'vy0': 255,
>> > 'vy1': 435,
>> > 'x0': 3.7384416740761086,
>> > 'y0': 4.0435015998508685,
>> > 'x1': 7.294543959990985,
>> > 'y1': 7.196941929341586,
>> > 'type': 'rect'
>> > }]
>> >
>> > (Note: I formatted the output with line breaks, etc. for better presentation in the email)
>> >
>> > If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.
>> >
>> > Thanks,
>> >
>> > Bryan
>> >
>> > > On Jul 5, 2016, at 10:07 PM, Gabriel Diaz <[email protected]> wrote:
>> > >
>> > > Hello!
>> > >
>> > > I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data['geometry'] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.
>> > >
>> > > In the notebook, I solved this problem by executing Python code inside of the callback. For example...
>> > > IPython.notebook.kernel.execute("dataSource[\'undefined\'].data[\'x\'].append(" + x + ")");
>> > > Because I'm no longer using a notebook, I don't have access to the user's Python kernel. I'm looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. <datasource>.on_change doesn't seem to provide access to the geometry feature of the boxSelectTool, so I think I'm stuck with javascript.
>> > >
>> > > To summarize my needs...
>> > > - Execute a callback in response to a box select tool
>> > > - In the callback, access the geometry property of cb_data
>> > > - In the callback, update a datasource
>> > > - Once the callback has executed, my Python must be in sync with the Javascript environment
>> > >
>> > > Thanks!
>> > >
>> > > --
>> > > 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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io\.
>> > > For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>> >
>> > --
>> > 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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io\.
>> > For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>> >
>> >
>> >
>> >
>> > --
>> > 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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com\.
>> > For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>>
>> --
>> 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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io\.
>> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>>
>>
>> --
>> 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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com\.
>> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>> <drawRectanglesB.py>
>
> --
> 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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io\.
>
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
>
>
>
> --
> 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/CAFvLWO2%3Doq1xTqOpVJ%2BjUX_w1keKRDrEVwA-DPz08JB0O5HHRg%40mail.gmail.com\.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/6D659CF3-624F-47B8-BE52-D2D351076327%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

--
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/CAFvLWO0JWbPXr4LoNpw2VX_JXaZGh0Rm4xAJ-dO-G6Ax97NGPw%40mail.gmail.com\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Will do! Thanks.

···

On Tue, Jul 12, 2016 at 10:42 AM, Bryan Van de Ven [email protected] wrote:

Gabriel,

I’ve been pretty swamped this past week, but I am glad to hear that the issue is figured out. I look forward to checkout out the final app. If there are suggestions for docs or examples improvements based on your experience (or if you would be interested in writing up something for our new Bokeh blog), please let us know.

Thanks,

Bryan

On Jul 12, 2016, at 9:36 AM, Gabriel Diaz [email protected] wrote:

Ok, problem solved! I was rewriting the datasources, rather than just datasource.data. This broke the connection between the figure and sources. Pushing to github now.

Thanks again,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Sun, Jul 10, 2016 at 10:39 AM, Gabriel Diaz [email protected] wrote:

Time for the reveal! Thanks for your continued support. Unfortunately, there are still issues related to the proper updating of the figure in response to a change in source data. It does not appear that the trigger issue is specific to the use of bokeh.client. In fact, the fix you had suggested previously, to use an explicit trigger, doesn’t always work.

I demonstrate this here:

https://github.com/performlabrit/label_events

The method, “changeTrial()” is called in response to a change in the trial number in the text input box. Try switching between trials 10 and 0. If you look at the console, printouts show that the data sources do change, and accurately reflect the new trial number. The datasources have been made global inside changeTrial(), so this change should affect the figure. However, it does not! The sources change, but the figure remains the same. Any more suggestions?

Oh, and you want to explore the full functionality of the app, feel free to play around with the boxSelectTool to add more events, select them with tap tool, and label / remove them with the buttons. It will work just fine until you change the trial number (using the text input box). Subsequent issues are likely related to mismatches between sources in the figure and javascript.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 1:28 PM, Bryan Van de Ven [email protected] wrote:

Gabriel,

Yes sorry, selections are a property of data sources. If you are interested in doing things when selections change, it is the relevant data source that you would attach a callback too.

Bryan

On Jul 8, 2016, at 8:43 AM, Gabriel Diaz [email protected] wrote:

​I’ve figured it out. The correct way to establish a callback is…

self.undefinedSource.on_change(‘selected’, self.tap_callback)


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Fri, Jul 8, 2016 at 9:04 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 8:17 PM, Bryan Van de Ven [email protected] wrote:

ToolEvents don’t have a “selected” property. You want callback on the data source for the rects. Sorry on phone can say more later

On Jul 7, 2016, at 18:23, Gabriel Diaz [email protected] wrote:

Thanks, Bryan. That does work, and I will report it. However, it looks like I’ve stumbled across another potentially related bug.

In addition to using the boxSelectionTool to draw rectangles, I would like to use the tapTool to select among the drawn rectangles. The tap tool should activate a callback a separate callback from boxCallback. I thought I could use self.fig.tool_events.on_change(‘selected’, self.tap_callback). Unfortunately, after adding this line of code, taptool ALSO has the effect of calling boxCallback. This throws an error unless I add a check to boxCallback to make sure that the new argument has a geometry component.

See the attached example for a demo.

Shall I submit this one, as well, or is there something I’m missing?

Thanks again! I’m getting good at finding these bugs, eH?

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 2:05 PM, Bryan Van de Ven [email protected] wrote:

First note that you should always update a CDS .data dictionary “all at once”. There is an assumption that column lengths are always all the same length, and appending to one at a time breaks this assumption. I don’t think this was the issue here though. I had to add an explicit .trigger to get things to work:

    new_data = dict(self.undefinedSource.data)
    new_data['x'].append(x)
    new_data['y'].append(y)
    new_data['width'].append(width)
    new_data['height'].append(height)
    new_data['startTime'].append(startTime)
    new_data['endTime'].append(endTime)
    new_data['boxID'].append(self.nextBoxID)
    new_data['trialNum'].append(self.trialNum)
    # update entire .data in one go
    self.undefinedSource.data = new_data
    # explicit trigger
    self.undefinedSource.trigger('data', new_data, new_data)

I don’t think this explicit trigger should be needed, so I’d encourage you to open an issue on GH with these details. I expect is has something to so with the “bokeh.client” style of use. There are many “app” examples that do not require the explicit trigger call to function. That said, this potential issue asise, I’d also say that this way of interacting with the server, using bokeh.client still definitely has intrinsic downsides compared to “app” style (i.e. when you run “bokeh serve myapp.py”). If that is at all an option I would recommend that style as preferable.

http://bokeh.pydata.org/en/latest/docs/user_guide/server.html#userguide-server-applications

Bryan

On Jul 7, 2016, at 12:10 PM, Gabriel Diaz [email protected] wrote:

Apologies - in the init function, self.addGlyphs should be called after the figure is created. This still does not solve my problem.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Thu, Jul 7, 2016 at 1:07 PM, Gabriel Diaz [email protected] wrote:

Bryan, there is no change in my browser after updating my sources within the Python callback. I’ve attached an example to this email. Notice that the periodic callback to _on_timer() prints out the contents of the undefinedSource every few seconds. If you use boxSelecttool, the printout shows that the callback does append new data to undefinedSource. However, no models are added to the figure.

I’ve looked at other examples for something similar to push_notebook, to push from my server to my browser. Am I missing something?

Thanks,

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 9:09 AM, Gabriel Diaz [email protected] wrote:

Thanks, Bryan! Yes, I’m still working on the same problem we had discussed earlier. I put it aside for a while, and upon revisiting the issue have decided to try and make it a server based application. I will share what I produce, eventually.

  • gD

Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]

On Wed, Jul 6, 2016 at 12:01 AM, Bryan Van de Ven [email protected] wrote:

Bokeh is a large library, and sometimes there are capabilities we have simply not had the time or resources to adequately advertise or surface more generally. This is one of those instances. All plots have a .tool_events property that is configured with a ToolEvents object. This object is basically a bus for reporting tool events like selection geometries back to apps:

    from [bokeh.io](http://bokeh.io) import curdoc
    from bokeh.models.tools import BoxSelectTool
    from bokeh.plotting import figure
    p = figure(x_range=(0,10), y_range=(0,10), tools=[BoxSelectTool()])
    def cb(attr, old, new):
        print(new)
    p.tool_events.on_change('geometries', cb)
    curdoc().add_root(p)

This outputs, e.g. for a BoxSelectTool:

    [{'vx0': 228.40625,
      'vx1': 422.40625,
      'vy0': 255,
      'vy1': 435,
      'x0': 3.7384416740761086,
      'y0': 4.0435015998508685,
      'x1': 7.294543959990985,
      'y1': 7.196941929341586,
      'type': 'rect'
     }]

(Note: I formatted the output with line breaks, etc. for better presentation in the email)

If this information is valuable to you, please consider contributing back to the community with a Pull Request to add an example of this usage or an update to the documentation to highlight it, so that others may benefit as well.

Thanks,

Bryan

On Jul 5, 2016, at 10:07 PM, Gabriel Diaz [email protected] wrote:

Hello!

I am trying to convert a notebook to an application. In my notebook, I have been using a boxSelectTool callback to draw rectangles, similar to the demonstration here. This involves using cb_data[‘geometry’] to update a datasource passed as an argument into the callback. Because no Python code is executed inside the callback, and the datasources are manipulated inside the JS callback,execution of this callback means that the Python data sources will be out of sync with the JS datasources.

In the notebook, I solved this problem by executing Python code inside of the callback. For example…

IPython.notebook.kernel.execute(“dataSource['undefined'].data['x'].append(” + x + “)”);

Because I’m no longer using a notebook, I don’t have access to the user’s Python kernel. I’m looking for alternative solutions to use in my Bokeh app to keep my Python synchronized. I do not see how to avoid using a javascript callback. .on_change doesn’t seem to provide access to the geometry feature of the boxSelectTool, so I think I’m stuck with javascript.

To summarize my needs…

  • Execute a callback in response to a box select tool
  • In the callback, access the geometry property of cb_data
  • In the callback, update a datasource
  • Once the callback has executed, my Python must be in sync with the Javascript environment

Thanks!

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/6082b88a-455f-480d-956a-07d1aa50aeb0%40continuum.io.

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

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/87457B69-8249-47D1-8669-BD94691EDA06%40continuum.io.

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

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/CAFvLWO28f9LtjjEnE_iJJNEz9szqZiGjNU619RRhmVF5CebaEg%40mail.gmail.com.

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

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/9A92FAD8-AD1C-4863-A40B-40AA8A728B91%40continuum.io.

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

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/CAFvLWO00gy0sttfTWHGw8uah81eP0x-_dJgegPDo_cCu9msqTw%40mail.gmail.com.

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

<drawRectanglesB.py>

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/92F50061-08DC-4127-A6A4-779373D1BD41%40continuum.io.

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

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/CAFvLWO2%3Doq1xTqOpVJ%2BjUX_w1keKRDrEVwA-DPz08JB0O5HHRg%40mail.gmail.com.

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

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/6D659CF3-624F-47B8-BE52-D2D351076327%40continuum.io.

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

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/CAFvLWO0JWbPXr4LoNpw2VX_JXaZGh0Rm4xAJ-dO-G6Ax97NGPw%40mail.gmail.com.

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

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/5B8331F0-204E-4CD7-A7EB-9E27A99131B2%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.


Gabriel J. Diaz, Ph.D.

Assistant Professor

Rochester Institute of Technology

Chester F. Carlson Center for Imaging Science

Founder of PerForM Labs

Click for demos.

Office 2108, Building #76

Rochester, NY 14623

Office: (585) 475-6215

[email protected]