holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.7k stars 403 forks source link

Linked Brushing Tap not working #4642

Open WesleyTheGeolien opened 4 years ago

WesleyTheGeolien commented 4 years ago

ALL software version info

Python: 3.8.5 Holoviews: 1.13.4 Bokeh: 2.2.1 Jupyter Notebook Server: 6.0.3 JupyterLab: 1.2.0 Firefox: 81.0.1 (64-bit) Chrome: 87.0.4280.11 (Official Build) dev (64-bit) OS: Fedora release 32 (Thirty Two)

Description of expected behavior and the observed behavior

The tap selection whilst using linked brushing does not seem to be working (Tap does not do anything). I would expect the tap selection to work the same as the box or lasso select by clicking once on a data point. I have tried simple tap, double tap, holding on to left click, I have also varied the type of selection

Complete, minimal, self-contained example code that reproduces the issue

I observe this behaviour in the linked brushing demo notebook: https://holoviews.org/user_guide/Linked_Brushing.html / https://raw.githubusercontent.com/pyviz/holoviews/master/examples/user_guide/Linked_Brushing.ipynb when working on the chlorplet of the USA in the index based selections chapter.

import holoviews as hv
from holoviews.selection import link_selections

from bokeh.sampledata.us_counties import data as counties
from bokeh.sampledata.unemployment import data as unemployment

counties = [dict(county, Unemployment=unemployment[cid])
            for cid, county in counties.items()
            if county["state"] == "tx"]

choropleth = hv.Polygons(counties, ['lons', 'lats'], [('detailed name', 'County'), 'Unemployment'])
hist = choropleth.hist('Unemployment', adjoin=False, normed=False)

linked_choropleth = link_selections(choropleth + hist, index_cols=['detailed name'])

linked_choropleth.opts(
    hv.opts.Polygons(tools=['hover', 'tap', 'box_select'], xaxis=None, yaxis=None,
                   show_grid=False, show_frame=False, width=500, height=500,
                   color='Unemployment', colorbar=True, line_color='white'),
    hv.opts.Histogram(width=500, height=500)
)
philippjfr commented 4 years ago

Tap selection is not supported for one relatively simple reason, it simply does not fit the current model used for linked brushing. Basically linked brushing is generally expressed in terms of the coordinates of the axes you are selecting on while tap selections work by returning an index which refers to the specific item you have selected. In the particular example you are pointing to it would actually be possible to do this however since index_cols is provided and therefore we should be able to reverse map the selection to the selected 'detailed name', so for this particular use case this should actually be relatively straightforward.

In the more general case we could think of trying to reverse map the indexed selection to a range, e.g. when you select a county polygon that would get translated into the lat/lon extents of that county.

philippjfr commented 4 years ago

Implemented the first suggestion in #4643 and uncovered a general regression related to index_cols so this will likely be released been pretty soon in a 1.13.5 patch release.

gawells commented 2 years ago

@WesleyTheGeolien I was trying to do something similar, and found a workaround. By adding an id column identical to the index and passing that to index_cols it should work:

import numpy as np
import pandas as pd
import panel as pn
import holoviews as hv
import hvplot.pandas

hv.opts.defaults(hv.opts.Points(nonselection_alpha=0.4))
hv.Store.set_current_backend('bokeh') # panel doesn't work with plotly?

from bokeh.sampledata.autompg import autompg
autompg['uid'] = autompg.index

# hover_cols can't include those used for index_cols in linked selection?
all_cols = ['mpg', 'cyl', 'displ', 'hp', 'weight', 'accel', 'yr', 'origin', 'name'] 

ls = hv.link_selections.instance()

def plots():
    hcols = list(autompg.columns)
    return ls(autompg.hvplot.scatter(x='mpg',y='cyl',
                                     tools=['box_select', 'tap','lasso_select',],
                                     hover_cols=all_cols,
                                     width=500)
              +autompg.hvplot.scatter(x='displ',y='cyl',
                                      tools=['box_select', 'tap','lasso_select'],
                                      hover_cols=all_cols,
                                      width=500),
             index_cols=['uid'],unselected_alpha=0.1,selected_color='#00ff00',unselected_color='#0000ff')

pn.Column(
    plots 
)