Repository: arviz-devs/arviz

Issue:
Bokeh hover tooltip
We need to implement better default hover settings.

https://docs.bokeh.org/en/1.4.0/docs/reference/models/tools.html#bokeh.models.tools.HoverTool


Discussion:
@ahartikainen I am unable to find the current default hover settings. I looked in the bokeh backend files but I wasn't able to find them. Do you know where I could find them?
It uses default by bokeh. We would nedd to create a custom hover tooltip. I think it needs to use ColumnDataSource.
@ahartikainen  Do you mean something like this ?: https://www.programcreek.com/python/example/106843/bokeh.models.HoverTool So I think I would have to add similar code to all the bokeh backend files
@ahartikainen I am also not sure about what sort of defaults I should add for each plot
I guess it depends on the plot.

At least draw, chain and value info for plots with "raw" data.
@ahartikainen I was going to work on the plot_ppc function as a function to start with but I don't understand how to extract the coordinates for the InferenceData object since it already seems to be heavily processed when it gets to using the bokeh backend file(especially the xarray_var_iter part). Could you please help me?
More specifically, I am unable to understand how the coordinates are stored after the iterator has been created and passed to the backend file
I would start from a function that already uses ColumnDataSource, and see how that can be used. First demo does not need chain and draw info first.
Do you mean I should begin with special fields like $x and $y for the canvas coordinates?
Ok, let's think about how we could implement this for `plot_pair` for (for scatter)

https://github.com/arviz-devs/arviz/blob/master/arviz/plots/backends/bokeh/pairplot.py

Currently hover just shows coordinate information, what is not optimal, in optimal case we want to see the value information + draw and chain info ( maybe some other info too)

So to start with point location against both variables

```
TOOLTIPS  = [
    (flat_var_names[0], "@{}".format(flat_var_names[0])),
    (flat_var_names[1], "@{}".format(flat_var_names[1]),
]
```

And then we need a way to add this information for hover.

```
ax = bkp.figure(
                width=int(figsize[0] * dpi), height=int(figsize[1] * dpi), tooltips=TOOLTIPS, **backend_kwargs
            )
```

It would be also good idea to check if backend_kwargs has tooltips already defined.

Also, if there is a way to check / add this after the figure is created, that would be great.

Resolving patch:
diff --git a/arviz/plots/backends/bokeh/pairplot.py b/arviz/plots/backends/bokeh/pairplot.py
--- a/arviz/plots/backends/bokeh/pairplot.py
+++ b/arviz/plots/backends/bokeh/pairplot.py
@@ -39,6 +39,13 @@ def plot_pair(
     }
     dpi = backend_kwargs.pop("dpi")
     if numvars == 2:
+        if kind == "scatter":
+            tooltips = [
+                (flat_var_names[1], "@{{{}}}".format(flat_var_names[1])),
+                (flat_var_names[0], "@{{{}}}".format(flat_var_names[0])),
+            ]
+            backend_kwargs.setdefault("tooltips", tooltips)
+
         (figsize, _, _, _, _, _) = _scale_fig_size(figsize, textsize, numvars - 1, numvars - 1)
 
         source_dict = dict(zip(flat_var_names, [list(post) for post in infdata_group]))
@@ -125,21 +132,6 @@ def plot_pair(
 
         (figsize, _, _, _, _, _) = _scale_fig_size(figsize, textsize, numvars - 2, numvars - 2)
 
-        if ax is None:
-            ax = []
-            backend_kwargs.setdefault("width", int(figsize[0] / (numvars - 1) * dpi))
-            backend_kwargs.setdefault("height", int(figsize[1] / (numvars - 1) * dpi))
-            for row in range(numvars - 1):
-                row_ax = []
-                for col in range(numvars - 1):
-                    if row < col:
-                        row_ax.append(None)
-                    else:
-                        ax_ = bkp.figure(**backend_kwargs)
-                        row_ax.append(ax_)
-                ax.append(row_ax)
-            ax = np.array(ax)
-
         tmp_flat_var_names = None
         if len(flat_var_names) == len(list(set(flat_var_names))):
             source_dict = dict(zip(flat_var_names, [list(post) for post in infdata_group]))
@@ -162,6 +154,40 @@ def plot_pair(
                 source=source, filters=[GroupFilter(column_name=divergenve_name, group="1")]
             )
 
+        if ax is None:
+            ax = []
+            backend_kwargs.setdefault("width", int(figsize[0] / (numvars - 1) * dpi))
+            backend_kwargs.setdefault("height", int(figsize[1] / (numvars - 1) * dpi))
+            for row in range(numvars - 1):
+                row_ax = []
+                var2 = (
+                    flat_var_names[row + 1]
+                    if tmp_flat_var_names is None
+                    else tmp_flat_var_names[row + 1]
+                )
+                for col in range(numvars - 1):
+                    if row < col:
+                        row_ax.append(None)
+                        continue
+
+                    var1 = (
+                        flat_var_names[col]
+                        if tmp_flat_var_names is None
+                        else tmp_flat_var_names[col]
+                    )
+                    backend_kwargs_copy = backend_kwargs.copy()
+                    if kind == "scatter":
+                        tooltips = [
+                            (var2, "@{{{}}}".format(var2)),
+                            (var1, "@{{{}}}".format(var1)),
+                        ]
+                        backend_kwargs_copy.setdefault("tooltips", tooltips)
+
+                    ax_ = bkp.figure(**backend_kwargs_copy)
+                    row_ax.append(ax_)
+                ax.append(row_ax)
+            ax = np.array(ax)
+
         for i in range(0, numvars - 1):
             var1 = flat_var_names[i] if tmp_flat_var_names is None else tmp_flat_var_names[i]
 


Test patch: