Select text in Bokeh plot - python

I would like to be able to search for specific words in my Bokeh plot. Say that I have a very simple plot:
import numpy as np
from bokeh.plotting import figure, show, output_file
x = np.linspace(0, 4*np.pi, 100)
y = np.sin(x)
TOOLS = "pan,wheel_zoom,box_zoom,reset,save,box_select"
p1 = figure(title="Some sample title", tools=TOOLS)
p1.circle(x,y, legend="sin(x)")
output_file("legend.html", title="legend.py example")
show(p1)
Which results in
I would like to be able to search the text in my browser using [ctrl+f] or [cmd+f]. Is there any way to do that? I would like to be able to search for the title and/or for labels, so in this case, example queries would be one of {sample, title,1,0.5}. Of course this example is hypothetical, but I think it's enough to illustrate the question.
Is there any way to use browser search functionality inside a Bokeh plot?

There is no way to do this in Boken currently, as it renders to an HTML5 canvas object, so the browser just sees the final result of the rendering. If you're willing to use Bokeh's sister library HoloViews, it however has a both Bokeh and SVG backend. When rendered through that SVG backend, your browser will then have access to all the text elements.
To help evaluate plotting libraries to see if they're suitable for your purpose, what you're looking for is basically a SVG backend. Usually it's easy to find a list of supported backends in the documentation of each library.
Also note that "having all individual plot elements accessible to the browser" and "plotting a lot of data points" are conflicting goals. The HTML5 canvas backend works well for plotting lots of data (even more so with datashader) partly because it only exposes the final plot image to the browser. If you want to expose the details of your plot to the browser (e.g via the SVG backend), you should expect to see a performance hit at some point if your plots get bigger (more data) or otherwise more complex, compared to the HTML5 canvas backend.

There is no way to do this. Bokeh plots are not textual DOM elements, everything is rendered on an HTML raster canvas, which the browser only sees as an rectangular area of RGBA pixels.

Related

Embedding Bokeh graphs while maintaining linked axis

I have linked the x axis of my bokeh graphs together by simply sharing the same x_range:
graph2.x_range = graph1.x_range
When I zoom-in/out or change the x-axis of one graph in any way, the other graph adjust with it. I really like this functionality.
However, when I embed the bokeh graphs in an html template they are not connected anymore.
script, div = components(graphs).
The components function returns a script that contains the data for your plot and provides a target div to display the plot view.
I added script and div in the placeholders of my html template, which is then loaded with Flask.
Everything works fine, but the graphs are not connected anymore.
It looks like the graps are embedded separately and therefore they cannot be linked together. I wonder if there is a method to do this.
If anyone has had this issue before, pls help :)
I used this documentation:
https://docs.bokeh.org/en/2.4.1/docs/user_guide/embed.html

How does this Bokeh Column Data Source Work?

I am trying to get a better understanding about the column data source in Bokeh (for Python). I found this code, but I can't seem to find the documentation that explains some things I am looking for, For instance:
Where is the callback from the lasso_select tool? I want to see where the expected functionality is described.
How is the functionality of the lasso_select described in code? (What if I want to change it?)
What is happening to the column data source so that the circles outside the lasso-select region change appearance? (I want to know how I can use the column data source for more complex visualization than is shown by this demo. So I'd like to know what dictionary field is being manipulated, and how is it being manipulated. For example, is there a hidden "color" field or something like that, which isn't explicit in this code?)
What code causes the figure to be redrawn when a lasso_select action is made?
I have many more questions related to this and the CDSView, but I'll stop here for now.
from bokeh.io import output_file, show
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
output_file("brushing.html")
x = list(range(-20, 21))
y0 = [abs(xx) for xx in x]
y1 = [xx**2 for xx in x]
# create a column data source for the plots to share
source = ColumnDataSource(data=dict(x=x, y0=y0, y1=y1))
TOOLS = "box_select,lasso_select,help"
# create a new plot and add a renderer
left = figure(tools=TOOLS, plot_width=300, plot_height=300, title=None)
left.circle('x', 'y0', source=source)
# create another new plot and add a renderer
right = figure(tools=TOOLS, plot_width=300, plot_height=300, title=None)
right.circle('x', 'y1', source=source)
p = gridplot([[left, right]])
show(p)
This is related to my previous question, where the only answer was very narrow in explaining for that specific question. However, I am really interested in what's going on under the hood to give the results that are seen. It would help my understanding a lot more if I could know some of those details.
1) There is no callback. The tool is responsible for defining a selection geometry, and and then hit-testing baed on that geometry. The hit test results are store in a selection property of the data source. Glyph renderers draw glyphs based on the selection property of their data source. If two glyph renderers (even on different plots) share the same data source, they will both draw the same set of selected/nonselected as a result.
2) If you mean the appearance of the normal vs selected vs non-selected objects, how to configure that is described in the docs here:
https://docs.bokeh.org/en/latest/docs/user_guide/styling.html#selected-and-unselected-glyphs
There are also a few properties on the LassoTool object itself, that control, e.g. whether a selection should be made on every mousemove, or only on mouseup, and what the selection overlay looks like. All of these are recorded in the ReferenceGuide. If you are asking how to change the implementation, as with msot everything in Bokeh, the real work is not done in Python, it is done in the JavaScript library BokehJS. The implementation of the LassoTool is here:
https://github.com/bokeh/bokeh/blob/master/bokehjs/src/lib/models/tools/gestures/lasso_select_tool.ts
If you want something fundamentally different you would need to implement your own custom model, including its JavaScript component. There is an entire User's Guide section about building custom extensions:
https://docs.bokeh.org/en/latest/docs/user_guide/extensions.html
3) The Plot is configured with various Renderers, one of which can be a GlyphRenderer. The GlyphRenderer itself does not draw anything, but it configures various sub-glyphs that are used to draw in specific situations:
glyph draws "normal" versions of glyphs (i.e. when there is no selection on the data source)
selected_glyph draws "selected" versions of glyphs (i.e. the ones inside a lasso or box tool when a selection is active)
nonselected_glyph draws the "non-selected" versions of glyphs (i.e. the ones outside a lasso or box tool when a selection is active) By default the non selection glyph is just a copy of the "normal" glyph with the alpha value set very low.
hover_glyph draws the "hovered" versions of glyphs (i.e. when a hover tool has inspected them)
You configure the appearance in the different situation by configuring properties on the glyphs that are used in each situation. There are sensible defaults for them, but they can be updated as described in the first link of 2)
4) BokehJS has an internal signal/slots event system that is used (among other things) to request canvas redraws whenever various properties change.

Bokeh change quality export plot

I am trying to export some grid into either png or svg but with svg option—as the doc states-the plots are exported as multiple files. So the only option is png. (For some reason if I use the toolbar, I only get the first plot and not the other).
But the quality of the png is terrible. Is there an option to set dpi or whatever? Even I you try to save graphs on the official documentation, you obtain poor quality.
I really like Bokeh and found it nicer to use that any other libs but this quality export is critical for me (publication purpose).
In recent versions of Bokeh the export_png accepts width and height parameters that you can set as arbitrarily large as you like, e.g:
export_png(p, "plot.png", width=2400, height=1000)

Does Bokeh's WebGL speed up heatmaps?

I have been reading a lot about Bokeh for visualisations of large datasets. I plan on plotting a heatmap with over 25 million points.
I saw read the page on speeding up WebGL and they mention that any plots with glyphs are accelerated.
Does the Heatmap plot use glyphs? Will there be any benefits in turning on WebGL for heatmap plots?
Pretty much everything that Bokeh draws is a glyph of some type. However, the text on that page you link actually states that "allows rendering some glyph types on graphics hardware." Currently (as of Bokeh 0.12.3) WebGL support only extends to scatter-type markers (e.g. circle, x, etc) and to lines. But HeatMap is implemented using the Rect glyph, so I would not expect WebGL to offer any improvement at the present time.
But I would add: It's good to thoroughly investigate any actual performance hotspots. Bokeh is really two libraries: a Python library and a JavaScript library. If you are seeing performance issues, are you sure it's on the JS side? For example, you have not said what your data sizes are. Are you sure it's not actually the binning/aggregation (that happens on the Python side) that is your issue?
Finally, if you have data sizes that are in the millions-to-billions of points range, you should probably be looking at the separate bokeh/datashader project.

How to save bokeh plots in non html formats [duplicate]

I need to export pictures of the graphs and plots I am creating with Bokeh.
Usually I do
output_file("test.html")
However, I want to copy that graph into an Excel Sheet.
It does not have to be interactive anymore, though that would be brillant.
How do I export the graph as a picture? Using code, not clicking on "preview/save".
As of Bokeh 0.12.6, it is now possible to export PNG and SVG directly from
Python code.
Exporting PNGs looks like this
export_png(plot, filename="plot.png")
And exporting SVGs looks like this
plot.output_backend = "svg"
export_svgs(plot, filename="plot.svg")
There are some optional dependencies that need to be installed.
You can find more information in the Exporting Plots section of the User Guide.
Alternatively, if you are willing to work with JavaScript. And, for instance, if you want to save many canvas (each canvas element has a plot) at the same time you can use the JavaScript method canvas.toDataUrl() to convert the canvas to png as base64. When you get all the images you can do whatever you want with them. These images have 96dpi and it cannot be changed, so if you want more resolution you will have to update the sizes of all the elements of the plot before the convertion as well: fonts, axis, plot size...
If you use this approach you do not need to install selenium and phantomjs dependencies in your python environment.
Also, be aware that if you use export_png and you export the plot with a bigger size, the axis and fonts are not going to be proportionally bigger

Categories