Repository: bokeh/bokeh

Issue:
Expose the more detailed geometry data to the tap tool
When a callback is written for the tap_tool, it exposes the screen geometry of the point that was tapped, available as 
```
cb_data["geometries"]["sx"]
cb_data["geometries"]["sy"]
```
However, to be truly useful it should also provide the converted data coordinates as 
```
cb_data["geometries"]["x"]
cb_data["geometries"]["y"]
```
 This would emulate the hover tool functionality. (Apart from calling one geometry and the other geometries)

There are many cases where it is useful to know exactly what the data values are when a point is tapped. On a line, the point tapped may be somewhere between two distant points, and we need the extrapolated values for that exact point along the line.

Currently, the only way to get these values is to hack an additional callback on the hover tool, and save the values in a CDS so we can interrogate them during the tap tool callback. This is very expensive as we are using the hover event to continually store this data even if we never hit the tap tool.

Below is a current example of this hack:
```
# Create a CDS so we can store the hover x and y coordinates.
locator = ColumnDataSource(name="pred_locator", data=dict(x=[0], y=[0]))

# Define a call back for the hover tool
callback_hover = CustomJS(args=dict(locator=locator), code="""
         geometry = cb_data["geometry"];
         locator.data["x"][0] = geometry["x"];
         locator.data["y"][0] = geometry["y"];
         """)

# define a callback for the tap tool
callback_tap = CustomJS(args=dict(locator=locator), code="""
         geometry = cb_data["geometries"];

         var y_data_val = locator.data["y"][0];
         var y_screen_val = geometry["sy"]; 
         alert("Tapped at " + y_screen_val + ", actual value is " + y_data_val);
         """)


plot.add_tools(HoverTool(callback=callback_hover))
plot.add_tools(TapTool(callback=callback_tap))

```
This is related to the original request to expose the geometry to the tap tool.

Expose Geometries to TapTool Callbacks #4082



Discussion:
> Currently, the only way to get these values is to hack an additional callback on the hover tool, and save the values in a CDS so we can interrogate them during the tap tool callback. 

I don't see why this would be necessary. You should be able to turn the screen coordinates into data coordinates the same way that other code does internally, e.g.

https://github.com/bokeh/bokeh/blob/master/bokehjs/src/lib/models/tools/inspectors/hover_tool.ts#L201-L206
Thanks for your comment Bryan, and after reviewing this in greater depth, I agree that it can be done as you suggest, using cb_obj and cb_data to access the values required. 

(cb_obj is only valid in the tap tool callback from version 0.12.7 onwards)

This is a working example:
```
            const sx = cb_data.geometries.sx;
            const sy = cb_data.geometries.sy;
            console.log("Tap at Screen points SX: " + sx + " SY: " + sy);
            
            const x = cb_obj.plot_model.frame.xscales['default'].invert(sx)
            const y = cb_obj.plot_model.frame.yscales['default'].invert(sy)
            console.log("Tap at Data points X: " + x + " Y: " + y);
```
However, this does require a deep understanding of the internal structure of the rendering objects, and may result in very breakable code if the internal calls are ever refactored. 

As far as I am aware, this level of detail is not documented and these values are probably useful enough to be included, and to provide some consistency between the tap and hover behaviour.

I'll leave this open for now as I may attempt to implement it if I get a chance, but my javascript and typescript is limited (as is my time right now).
**Disclaimer**: The above example code works in my use case, where I am clicking on a multi_line glyph. It may break if multiple objects are selected, or if the underlying renderer is something else - again my knowledge of the internals of how the renderer manages the scales and how the cb_obj changes when multiple different glyphs are selected in a single tap.
@euandekock that will always return the x/y coords on the default scale. For most plots, that's all there is. If there are multiple/twin axes, then there coud be non-default scales, but I think that's something that could be left as an advanced case. I would be perfectly fine adding that conversion of `sx` and `sy` here:

https://github.com/bokeh/bokeh/blob/master/bokehjs/src/lib/models/tools/gestures/tap_tool.ts#L11

If you'd like to put together a small PR I'd be happy to help you work through it. I think it would be a very useful addition, as you have pointed out.  The only difference  I can think of from your code above is that it would be `this.plot_model` inside the tool view method (not `cb_obj.plot_model`)
Additionally it would be good to make a few words about what is in the `geometries` object in the docstring here:

https://github.com/bokeh/bokeh/blob/master/bokeh/models/tools.py#L382

Resolving patch:
diff --git a/bokeh/models/tools.py b/bokeh/models/tools.py
--- a/bokeh/models/tools.py
+++ b/bokeh/models/tools.py
@@ -394,6 +394,13 @@ class TapTool(Tap):
     its ``.source`` attribute and the selection geometry as its
     ``.geometries`` attribute.
 
+    The ``.geometries`` attribute has 5 members.
+    ``.type`` is the geometry type, which always a ``.point`` for a tap event.
+    ``.sx`` and ``.sy`` are the screen X and Y coordinates where the tap occurred.
+    ``.x`` and ``.y`` are the converted data coordinates for the item that has
+    been selected. The ``.x`` and ``.y`` values are based on the axis assiged
+    to that glyph.
+
     .. note::
         This callback does *not* execute on every tap, only when a glyphs is
         "hit". If you would like to execute a callback on every mouse tap,


Test patch: