Re-stack standalone varea_stack when interactively hiding stack member via legend

I’m attempting to visualize some time-series data on memory utilization and make it available as a standalone/offline interactive html. There are several PIDs of interest that I’m showing together using varea_stack render, and above that in the same figure is a line render showing the over all system memory utilization. (any space inbetween varea_stack and the line is memory used by other processes we don’t care about)

With an interactive legend I can hid the line render or the varea_stack members easily enough. What I’m not sure about is if it is possible to have a callback that “re-stacks” the varea_stack if one of the stack members are hidden. Also, is it possible to have the y-axis range recalculated to adjust, re-scale everything and re-draw based on what is visible?

I have one PID that uses a massive amount of memory, and several others that uses a tiny amount of memory, and I’d like to have everything re-scale and restack on the y axis if I turn off the PID with high utilization, as well as the system utilization line, so that details can be seen on how the utilization of the remaining PIDs related to each other.

Is this even possible with an offline html file? I’m can’t find a lot of info on how the BokehJS API relates to the Python API when trying to hook CustomJS code into events triggered by hiding things.

Unfortunately “re-stacking” areas is not something that is going to be simple to do. Stacks are specified locally, by stating what previous things a given “level” stacks on, so updating involves changing mulitple configurations. From a Bokeh server app I would say just clear the plot and call varea_stack from scratch. I am not sure I have any good suggestion for standalone (i.e. CustomJS) case. The only thing that comes to mind is temporarily zeroing out the stacks that you want to “hide” but that seems quite clunky/fragile.

Zeroing of the stacks items turned out to be a lot less messy than I thought it would be.

    for item in legend_instance.items:
        item.renderers[0].js_on_change( 'visible', CustomJS( code =
            '''
            if ( typeof cb_obj.data_source.data[ cb_obj.name + '_visible' ] == 'undefined' ){
                cb_obj.data_source.data[ cb_obj.name + '_visible' ] = cb_obj.data_source.data[ cb_obj.name ]
            }

            if ( cb_obj.visible ){
                cb_obj.data_source.data[ cb_obj.name ] = cb_obj.data_source.data[ cb_obj.name + '_visible' ]
            } else {
                cb_obj.data_source.data[ cb_obj.name ] = new Array( cb_obj.data_source.data[ cb_obj.name ].length ).fill( 0 )
            }

            cb_obj.data_source.change.emit()
            '''
        ))

It has one minor fault that it assumes you’ve set the name attribute of the cb_obj to match the name used in the data_source.data objects. Perhaps I’ll see if I can accomplish the same thing using id attributes rather than name attributes.