Problem adjusting plot size

I’ve worked up a toy example that reproduces a problem I’m seeing in a larger app I’m building (on Bokeh 0.12.2):

I have a plot that uses a FactorRage. When I first render that plot, it has about 42 factors in it. I want to give the user the ability to filter the plot to only show subsets of those factors. In the toy example linked above, I’ve recreated that condition with a simple drop-down menu that specifies how many factors I want in the plot.

As you can see by running the example, changing the number of factors changes the data that are rendered, but the plot width and heigh (defined by 25 * the number of factors) doesn’t change in the browser. I’ve include a PreText field that shows that the width does change on the python side. Now I read recently (I think in this forum) that plot_width and plot_height don’t get updated in JS when changed in Python, so I changed the app to just replace the entire plot. The ref_id in the PreText field shows that this does, in fact, happen, but the plot size still doesn’t change.

The only way I could get it to work was to add line 62 (currently commented out in the example) that re-adds all of the children to the overall app layout. This successfully resizes the plot, but throws an ‘Uncaught Error: unknown edit variable’ in the console. That error seems to to not mess anything up too badly in the toy example, but in my much more complicated app (where the plot is in a Column, which is the child of a Panel, which is a Row, which is in a Column), trying to replace all children up the tree ends up destroying the entire layout of the app (plots just disappear, all Panels are shown at one time, etc.)

Is there a way for me to trigger a re-render of a plot with new plot_height and plot_width? If the answer involves a JS callback, please help me understand how I can trigger that callback from the Python side, since I already need to run a Python callback to do other things at the same time that the plot is resized.

Thanks in advance for any help you can offer!

So I’ve figured out that everything works fine if I change plot.width and plot.height instead of plot.plot_width and plot.plot_height, and if I manually resize the canvas, something like this:

var plot_view = document.querySelector(‘#modelid_{ref_id}’)
var canvas_view = document.querySelector(‘#modelid_{ref_id} canvas’)
canvas_view.style[‘width’] = plot_view.style[‘width’]
canvas_view.style[‘height’] = plot_view.style[‘height’]

``

So now my question is: how do I run this javascript after I run the python callback that changes the plot.width and plot.height? If I add a CustomJS object to the Select widget, then the javascript callback runs before the Python callback has a chance to run. Is there a way to manually trigger a CustomJS callback from the Python side?

···

On Wednesday, September 21, 2016 at 3:14:10 PM UTC-4, [email protected] wrote:

I’ve worked up a toy example that reproduces a problem I’m seeing in a larger app I’m building (on Bokeh 0.12.2):

https://gist.github.com/schaunwheeler/30f205f405c859995bebb23a2d87c36f

I have a plot that uses a FactorRage. When I first render that plot, it has about 42 factors in it. I want to give the user the ability to filter the plot to only show subsets of those factors. In the toy example linked above, I’ve recreated that condition with a simple drop-down menu that specifies how many factors I want in the plot.

As you can see by running the example, changing the number of factors changes the data that are rendered, but the plot width and heigh (defined by 25 * the number of factors) doesn’t change in the browser. I’ve include a PreText field that shows that the width does change on the python side. Now I read recently (I think in this forum) that plot_width and plot_height don’t get updated in JS when changed in Python, so I changed the app to just replace the entire plot. The ref_id in the PreText field shows that this does, in fact, happen, but the plot size still doesn’t change.

The only way I could get it to work was to add line 62 (currently commented out in the example) that re-adds all of the children to the overall app layout. This successfully resizes the plot, but throws an ‘Uncaught Error: unknown edit variable’ in the console. That error seems to to not mess anything up too badly in the toy example, but in my much more complicated app (where the plot is in a Column, which is the child of a Panel, which is a Row, which is in a Column), trying to replace all children up the tree ends up destroying the entire layout of the app (plots just disappear, all Panels are shown at one time, etc.)

Is there a way for me to trigger a re-render of a plot with new plot_height and plot_width? If the answer involves a JS callback, please help me understand how I can trigger that callback from the Python side, since I already need to run a Python callback to do other things at the same time that the plot is resized.

Thanks in advance for any help you can offer!

Upon further investigation, it looks like I can trigger any changes I make to plot size on the python side by triggering a window resize. I don’t want to make my users do that, so I want to run just a single line of javascript after my python callback:

window.dispatchEvent(new Event(‘resize’));

``

Is there any way to do that? I know how to do just a python callback, and how to do just a javascript callback. Is there a way to do one of each, in order?

···

On Thursday, September 22, 2016 at 1:16:38 PM UTC-4, [email protected] wrote:

So I’ve figured out that everything works fine if I change plot.width and plot.height instead of plot.plot_width and plot.plot_height, and if I manually resize the canvas, something like this:

var plot_view = document.querySelector(‘#modelid_{ref_id}’)
var canvas_view = document.querySelector(‘#modelid_{ref_id} canvas’)
canvas_view.style[‘width’] = plot_view.style[‘width’]
canvas_view.style[‘height’] = plot_view.style[‘height’]

``

So now my question is: how do I run this javascript after I run the python callback that changes the plot.width and plot.height? If I add a CustomJS object to the Select widget, then the javascript callback runs before the Python callback has a chance to run. Is there a way to manually trigger a CustomJS callback from the Python side?

On Wednesday, September 21, 2016 at 3:14:10 PM UTC-4, [email protected] wrote:

I’ve worked up a toy example that reproduces a problem I’m seeing in a larger app I’m building (on Bokeh 0.12.2):

https://gist.github.com/schaunwheeler/30f205f405c859995bebb23a2d87c36f

I have a plot that uses a FactorRage. When I first render that plot, it has about 42 factors in it. I want to give the user the ability to filter the plot to only show subsets of those factors. In the toy example linked above, I’ve recreated that condition with a simple drop-down menu that specifies how many factors I want in the plot.

As you can see by running the example, changing the number of factors changes the data that are rendered, but the plot width and heigh (defined by 25 * the number of factors) doesn’t change in the browser. I’ve include a PreText field that shows that the width does change on the python side. Now I read recently (I think in this forum) that plot_width and plot_height don’t get updated in JS when changed in Python, so I changed the app to just replace the entire plot. The ref_id in the PreText field shows that this does, in fact, happen, but the plot size still doesn’t change.

The only way I could get it to work was to add line 62 (currently commented out in the example) that re-adds all of the children to the overall app layout. This successfully resizes the plot, but throws an ‘Uncaught Error: unknown edit variable’ in the console. That error seems to to not mess anything up too badly in the toy example, but in my much more complicated app (where the plot is in a Column, which is the child of a Panel, which is a Row, which is in a Column), trying to replace all children up the tree ends up destroying the entire layout of the app (plots just disappear, all Panels are shown at one time, etc.)

Is there a way for me to trigger a re-render of a plot with new plot_height and plot_width? If the answer involves a JS callback, please help me understand how I can trigger that callback from the Python side, since I already need to run a Python callback to do other things at the same time that the plot is resized.

Thanks in advance for any help you can offer!

So I'm not sure there's a clean way to do this at the moment (might make a nice feature, to trigger arbitrary JS callbacks). But what would probably work for now as a hacky workaround: Add an "extra range" like you would for adding a twinned axis, but don't actually add a second axis that uses the range. Then add a callback to the range, as described:

  http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-range-update

Then to "trigger" the callback you just make some arbitrary change to the extra range. Alternatively, an invisible glyph with a selection callback on its data source could work too.

Thanks,

Bryan

···

On Sep 22, 2016, at 8:06 PM, [email protected] wrote:

Upon further investigation, it looks like I can trigger any changes I make to plot size on the python side by triggering a window resize. I don't want to make my users do that, so I want to run just a single line of javascript after my python callback:

window.dispatchEvent(new Event('resize'));

Is there any way to do that? I know how to do just a python callback, and how to do just a javascript callback. Is there a way to do one of each, in order?

On Thursday, September 22, 2016 at 1:16:38 PM UTC-4, schaun....@successacademies.org wrote:
So I've figured out that everything works fine if I change plot.width and plot.height instead of plot.plot_width and plot.plot_height, and if I manually resize the canvas, something like this:

var plot_view = document.querySelector('#modelid_{ref_id}')
var canvas_view = document.querySelector('#modelid_{ref_id} canvas')
canvas_view.style['width'] = plot_view.style['width']
canvas_view.style['height'] = plot_view.style['height']

So now my question is: how do I run this javascript after I run the python callback that changes the plot.width and plot.height? If I add a CustomJS object to the Select widget, then the javascript callback runs before the Python callback has a chance to run. Is there a way to manually trigger a CustomJS callback from the Python side?

On Wednesday, September 21, 2016 at 3:14:10 PM UTC-4, schaun....@successacademies.org wrote:
I've worked up a toy example that reproduces a problem I'm seeing in a larger app I'm building (on Bokeh 0.12.2):

https://gist.github.com/schaunwheeler/30f205f405c859995bebb23a2d87c36f

I have a plot that uses a FactorRage. When I first render that plot, it has about 42 factors in it. I want to give the user the ability to filter the plot to only show subsets of those factors. In the toy example linked above, I've recreated that condition with a simple drop-down menu that specifies how many factors I want in the plot.

As you can see by running the example, changing the number of factors changes the data that are rendered, but the plot width and heigh (defined by 25 * the number of factors) doesn't change in the browser. I've include a PreText field that shows that the width does change on the python side. Now I read recently (I think in this forum) that plot_width and plot_height don't get updated in JS when changed in Python, so I changed the app to just replace the entire plot. The ref_id in the PreText field shows that this does, in fact, happen, but the plot size still doesn't change.

The only way I could get it to work was to add line 62 (currently commented out in the example) that re-adds all of the children to the overall app layout. This successfully resizes the plot, but throws an 'Uncaught Error: unknown edit variable' in the console. That error seems to to not mess anything up too badly in the toy example, but in my much more complicated app (where the plot is in a Column, which is the child of a Panel, which is a Row, which is in a Column), trying to replace all children up the tree ends up destroying the entire layout of the app (plots just disappear, all Panels are shown at one time, etc.)

Is there a way for me to trigger a re-render of a plot with new plot_height and plot_width? If the answer involves a JS callback, please help me understand how I can trigger that callback from the Python side, since I already need to run a Python callback to do other things at the same time that the plot is resized.

Thanks in advance for any help you can offer!

--
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/b99168a5-2bb0-429c-8a3e-2f9007f29829%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Hi Bryan,

That’s a helpful lead. Thank you. I tried implementing what you suggested (an extra Range1d where I increment up the start property each time a new selection is made), but it still doesn’t seem to be triggering the callback. Am I missing something?

···

On Friday, September 23, 2016 at 11:35:44 AM UTC-4, Bryan Van de ven wrote:

So I’m not sure there’s a clean way to do this at the moment (might make a nice feature, to trigger arbitrary JS callbacks). But what would probably work for now as a hacky workaround: Add an “extra range” like you would for adding a twinned axis, but don’t actually add a second axis that uses the range. Then add a callback to the range, as described:

    [http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-range-update](http://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-range-update)

Then to “trigger” the callback you just make some arbitrary change to the extra range. Alternatively, an invisible glyph with a selection callback on its data source could work too.

Thanks,

Bryan

On Sep 22, 2016, at 8:06 PM, [email protected] wrote:

Upon further investigation, it looks like I can trigger any changes I make to plot size on the python side by triggering a window resize. I don’t want to make my users do that, so I want to run just a single line of javascript after my python callback:

window.dispatchEvent(new Event(‘resize’));

Is there any way to do that? I know how to do just a python callback, and how to do just a javascript callback. Is there a way to do one of each, in order?

On Thursday, September 22, 2016 at 1:16:38 PM UTC-4, [email protected] wrote:

So I’ve figured out that everything works fine if I change plot.width and plot.height instead of plot.plot_width and plot.plot_height, and if I manually resize the canvas, something like this:

var plot_view = document.querySelector(‘#modelid_{ref_id}’)

var canvas_view = document.querySelector(‘#modelid_{ref_id} canvas’)

canvas_view.style[‘width’] = plot_view.style[‘width’]

canvas_view.style[‘height’] = plot_view.style[‘height’]

So now my question is: how do I run this javascript after I run the python callback that changes the plot.width and plot.height? If I add a CustomJS object to the Select widget, then the javascript callback runs before the Python callback has a chance to run. Is there a way to manually trigger a CustomJS callback from the Python side?

On Wednesday, September 21, 2016 at 3:14:10 PM UTC-4, [email protected] wrote:

I’ve worked up a toy example that reproduces a problem I’m seeing in a larger app I’m building (on Bokeh 0.12.2):

https://gist.github.com/schaunwheeler/30f205f405c859995bebb23a2d87c36f

I have a plot that uses a FactorRage. When I first render that plot, it has about 42 factors in it. I want to give the user the ability to filter the plot to only show subsets of those factors. In the toy example linked above, I’ve recreated that condition with a simple drop-down menu that specifies how many factors I want in the plot.

As you can see by running the example, changing the number of factors changes the data that are rendered, but the plot width and heigh (defined by 25 * the number of factors) doesn’t change in the browser. I’ve include a PreText field that shows that the width does change on the python side. Now I read recently (I think in this forum) that plot_width and plot_height don’t get updated in JS when changed in Python, so I changed the app to just replace the entire plot. The ref_id in the PreText field shows that this does, in fact, happen, but the plot size still doesn’t change.

The only way I could get it to work was to add line 62 (currently commented out in the example) that re-adds all of the children to the overall app layout. This successfully resizes the plot, but throws an ‘Uncaught Error: unknown edit variable’ in the console. That error seems to to not mess anything up too badly in the toy example, but in my much more complicated app (where the plot is in a Column, which is the child of a Panel, which is a Row, which is in a Column), trying to replace all children up the tree ends up destroying the entire layout of the app (plots just disappear, all Panels are shown at one time, etc.)

Is there a way for me to trigger a re-render of a plot with new plot_height and plot_width? If the answer involves a JS callback, please help me understand how I can trigger that callback from the Python side, since I already need to run a Python callback to do other things at the same time that the plot is resized.

Thanks in advance for any help you can offer!


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/b99168a5-2bb0-429c-8a3e-2f9007f29829%40continuum.io.

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