I've been working to build an application in which allows interacting with data through brushing. I've made a few posts on the subject in the past and have received a lot of valuable support. I've stumbled across a problem that I could solve, but I'm not sure of the best way.
There appears to be some disagreement between the selection models implemented in a scatter plot and those in a line plot. To clarify, I'm speaking of range selections. There are demos of line and scatter plot combinations, however, none with the range selection tool attached. To observe the problem, run the attached example. Try selecting a range and then deselecting it.
When the range selection tool is first used, it sets a selection mask on the datasource. Later, if the selection is cleared, it removes the mask(rather than set the selections to false). This causes a problem with scatter plots. If the selection_masks metadata attribute is an empty list(as the range selector may leave it when a selection is cleared), the scatter plot will show all of the points as being selected.
This excerpt from scatterplot.py shows the problem:
... if ds.metadata.get('selection_masks', None) is not None: try: for mask in ds.metadata['selection_masks']:
point_mask &= mask indices = where(point_mask == True) points = transpose(array((index[indices], value[indices]))) ...
So, early in the method, point_mask is initialized based on the visible points on the plot( it is True for every visible point), the empty list in selection_masks (left behind by the range selection tool) causes this array of true values to be assigned to the selected points and so the plot is rendered as if all of the points were selected.
My question is, where should this be fixed? Should the range selector be modified to stop leaving an empty list or should the scatter plot be modified to stop assuming all points are selected? I am leaning toward the range selection tool maintaining it's selection mask once its created. The lazy initialization isn't really a problem, but once initialized, deselecting shouldn't necessarily delete the mask, it should simply set it all to false.