Bokeh change quality export plot - python

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)

Related

Saving images from plotly

How can I save images generated with plotly in different formats? Only "Download as PNG" is possible from the generated HTML figure. I would need to interact with the figure (change rotation, choose which data to plot) and save an .eps figure for each online modified plot. Thanks a lot!
Plotly supports exporting to EPS (the docs mention that you need the poppler library) and the Figure object has a write_image method that saves a figure to a file.
You can specify the format through the filename and the resolution with the width and height keyword arguments, representing logical pixels.
You can read more on static image exporting in Plotly here. This is a code example:
fig.write_image("name.eps", width=1920, height=1080)
In order to select what is plotted you will have to set the figure's camera controls.

Select text in Bokeh plot

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.

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

With Bokeh, how to save to a png or jpg instead of a html file?

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

matplotlib shows different figure than saves from the show() window

I plot rather complex data with matplotlib's imshow(), so I prefer to first visually inspect if it is all right, before saving. So I usually call plt.show(), see if it is fine, and then manually save it with a GUI dialog in the show() window. And everything was always fine, but recently I started getting a weird thing. When I save the figure I get a very wrong picture, though it looks perfectly fine in the matplotlib's interactive window.
If I zoom to a specific location and then save what I see, I get a fine figure.
So, this is the correct one (a small area of the picture, saved with zooming first):
And this one is a zoom into approximately the same area of the figure, after I saved it all:
For some reason pixels in the second one are much bigger! That is vary bad for me - as you can see, it looses a lot of details in there.
Unfortunately, my code is quite complicated and I wasn't able to reproduce it with some randomly generated data. This problem appeared after I started to plot two triangles of the picture separately: I read my two huge data files with np.loadtxt(), get np.triu(data1) and np.tril(data2), mask zeroes, NAs, -inf and +inf and then plot them on the same axes with plt.imshow(data, interpolation='none', origin='lower', extent=extent). I do lot's of other different things to make it nicer, but I guess it doesn't matter, because it all worked like a charm before.
Please, let me know, if you need to know anything else specific from my code, that could be relevant to this problem.
When you save a figure in png/jpg you are forced to rasterize it, convert it to a finite number of pixels. If you want to keep the full resolution, you have a few options:
Use a very high dpi parameter, like 900. Saving the plot will be slow, and many image viewers will take some time to open it, but the information is there and you can always crop it.
Save the image data, the exact numbers you used to make the plot. Whenever you need to inspect it, load it in Matplotlib in interactive mode, navigate to your desired corner, and save it.
Use SVG: it is a vector graphics format, so you are not limited to pixels.
Here is how to use SVG:
import matplotlib
matplotlib.use('SVG')
import matplotlib.pyplot as plt
# Generate the image
plt.imshow(image, interpolation='none')
plt.savefig('output_image')
Edit:
To save a true SVG you need to use the SVG backend from the beginning, which is unfortunately, incompatible with interactive mode. Some backends, like GTKCairo seem to allow both, but the result is still rasterized, not a true SVG.
This may be a bug in matplotlib, at least, to the best of my knowledge, it is not documented.

Categories