JS filter controls for 2+ filter criteria

Hi!
This is more a design than a specific code question (and generating the MRE from 1k+ lines of the working version is pretty tough atm).

Currently using 2.4.3 with filter lists in the CDS Views, and coding for mode= ‘inline’ usage. There isn’t the capability to run Bokeh server in the target environment.

I implemented a CDS of data rows that are boolean filtered via a slider chosen relative time value and subselected by a CheckboxButtonGroup to a source domain (string). Each CustomJS block modifies their respective booleanFilter indices in the CDSView.filters[i].booleans arrays to limit the view to the time/source as selected by user.

This works well (on 2.4.3).

I’m trying to further make different glyphs for each data row dependent on a new parameter in the underlying DataFrame. For simplicity, I’ll just call the row ‘shape’.

I’m struggling to figure out how I can use a column of the CDS to filter the data items into a view for each desired glyph renderer without breaking the JS controls over the time/domain selections.
What I’d like to do is take a second CDSView (that filters ‘shape’) of the existing CDSView filtered by time/domain to further split these to the renderers. Since this isn’t possible (as far as I have played with and read):

  1. Any general ideas on the best way to structure this sort of stacked filtering job?
  2. With 3.0+'s single filter setup on CDS Views is there a general approach to updating a CDSView filter from CustomJS blocks that would give me the ability to control time/domain filtering for all three views, and have them filter for ‘shape?’

Thanks–and appreciate any gentle nudges in the right direction!

S

What I’ve done for 2 is to use IndexFilter, then use CustomJS to basically just collect the state of every widget and use that to calculate the corresponding indices that should be included, then update the indices property of the IndexFilter.

1 Like

OK, thanks @gmerritt123!
I had rewritten as a CustomJSFilter that attempted to return a boolean array to accomplish this end (and then make three instances, each filtered for one of the complementary output glyphs), but I’ve not been having success. I get a very small subset of the data that looks heavily duplicated in the output plots and then get some odd page behavior in the JS console. It raises a ‘TypeError: cannot read property of undefined’ when I try to select a glyph. Probable bad code–I’m learning JS as I go, but I’ll keep trying to chase it down on my own for a while.

One thing I saw was that the resulting CDSViews were referencing the correct object, but didn’t have filters[0].booleans attribute, but I guess since the JSFilter doesn’t execute until page run, so maybe that’s why.

I’ll try a change to the IndexFilter approach, which is a little closer to what I had working before and see if I can get something that works. Will update if this works better for my case.

Just to check–I should be fine making multiple CDSViews from the same CDS, and then passing each CDSView to separate glyph renderers, right? The category that filters the views results in complementary, non-equal length outputs. It does look as though my assigment of CDSViews to the glyph renderers is doing what I think it should (each glyph renderer seems to be getting the right view object reference), but maybe there is a limitation I haven’t understood.

S

If anyone else is looking to do this, I found the @gmerritt123’s unified CustomJS approach to work well for sorting different CDSViews to different renderers.

I also realized that figure.scatter() with a variety of marker and fill attributes pushed into the time/domain filtered CDS was far more straight-forward than piping different CDSViews to different glyph renderers–so I definitely learned something as I read through the references!

S

2 Likes