8000 Headless static (svg, png) image generation · Issue #538 · bokeh/bokeh · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headless static (svg, png) image generation #538

Closed
abastardi opened this issue Apr 18, 2014 · 42 comments · Fixed by #6189 or #6229
Closed

Headless static (svg, png) image generation #538

abastardi opened this issue Apr 18, 2014 · 42 comments · Fixed by #6189 or #6229

Comments

@abastardi
Copy link

Enable generation of PNG images directly on the server, similar to the Vega.js headless mode (https://github.com/trifacta/vega/wiki/Headless-Mode).

@bryevdv
Copy link
Member
bryevdv commented Apr 18, 2014

@mattpap do you have any thoughts about what it would take to expose the phantomjs PNG generation we do with the test script to users?

@damianavila
Copy link
Contributor

But using the phantom approach we have an image with the buttons and uncentered... so probably we need to pre-process the plot to render properly... just thoughts....

@bryevdv
Copy link
Member
bryevdv commented Apr 18, 2014

Right it won't work as-is. I can think of a few possible ways to use phantoms:

  • allow automation of the existing preview/save tool to save the image buffer directly to disk without having the user have to navigate a file save dialog.
  • putting 8000 the plot in a different template/div layout for headless image generation, that does not have the toolbar, etc., and using the current "screenshot" approach that the test script uses to save images.

There may be others too.

@damianavila damianavila added this to the long-term milestone Oct 6, 2014
@bryevdv bryevdv modified the milestones: short-term, long-term Dec 23, 2014
@bryevdv
Copy link
Member
bryevdv commented Dec 23, 2014

Update: it does look as though node-canvas may work for this, I am going to start some preliminary experimentation.

@bryevdv
Copy link
Member
bryevdv commented Dec 24, 2014

Initial experiments on OS X are encouraging that node-canvas should be suitable, even for plots with image data. However, installing node-canvas and its dependencies is not trivial and will take some work to make it as simple and easy as possible for users.

@bryevdv
Copy link
Member
bryevdv commented Dec 24, 2014

Getting BokehJS working in node.js is a first prerequisite, I have made a separate issue for that task,

@hhuuggoo
Copy link
Contributor

we should rename this issue - there is no reason to involve the server at all here right?

@abastardi
Copy link
Author

@hhuuggoo, the idea is to be able to produce plots on the server rather than having them rendered in the browser. This can be useful when you need to generate plots to be used in some context other than display in the browser (e.g., generation of a PDF report).

@bryevdv bryevdv changed the title Generate plots on the server (headless mode) Headless static(svg, png) image generation Dec 24, 2014
@bryevdv
Copy link
Member
bryevdv commented Dec 24, 2014

@abastardi yes but in general you will be able to generate images from python, whether that's in the server, or in an interactive session or IPython notebook makes no difference.

@bryevdv bryevdv changed the title Headless static(svg, png) image generation Headless static (svg, png) image generation Dec 24, 2014
@abastardi
Copy link
Author

Got it. It sounded like @hhuuggoo meant this shouldn't happen on the server.

@bryevdv bryevdv modified the milestones: 0.8, short-term Dec 25, 2014
@damianavila damianavila modified the milestones: short-term, 0.8 Jan 28, 2015
@scherrey
Copy link

I see that .8 has shipped but this issue is still open. Is there an update as to the disposition of this capability?

@bryevdv
Copy link
Member
bryevdv commented Mar 26, 2015

@scherrey Unfortunately not. Here is a message I sent recently the Bokeh mailing list on 2015/03/04:


Programmatic generation of static images is definitely something we would very much like to support. Unfortunately, it is also a surprisingly difficult proposition. The first observation is that browsers canvas implementation only generate raster images, and don't help with SVG or PDF. Worse, browser security models mean that getting the data out is also very problematic. You can follow this history of this topic in a few issues:

#538
#1589

MPL support is currently provided by a third party library, mplexporter. It is very useful in a large number of cases, but it is by no means complete, which explains errors you can run into with some MPL figures. There is an MPL enhancement proposal to make a "serious" complete JSON serialization layer, much better than mplexorter. In principle this would work fantastically, allowing us to leverage all the MPL work for static image generation. But realistically, there are no indications that this work will materialize or even really get started any time in the near future (best guess: years, if at all). The most recent plan was to try and use the BokehJS patched with node-canvas to generate images inside Node. But BokehJS is a large and complicated library and it is unclear that Node support is currently up to the task. Experiments and tests are ongoing, but not encouraging. In the past we have also tried PhantomJS, but the lack of support for typed arrays in PhantomJS means that it too is not up to the task (besides the fact that it also would only generate raster images).

If the node-canvas plan proves unworkable, I am afraid that really only leaves the very undesirable proposition of creating and maintaining our own "duplicate" rendering code path in python that mirrors the BokehJS rendering code, and uses something like Cairo or Agg directly to render static images. This is obviously bad from an effort/maintenance viewpoint, but it's also disappointing because it means static image generation won't "just work" for other language bindings without including some python code or a python tool. However, given that we are probably going to make a move to WebGL for browser rendering, this may truly be the "best worst" possibility. But obviously it is a nontrivial undertaking that will take a nontrivial amount of time and effort. As of yet, nothing concrete in this direction is scheduled.

I wish I had some better news to give you. It is my earnest hope that we will have a solution in 2015 but I can't provide any better estimates at this time.

@mfripp
Copy link
mfripp commented Jul 20, 2015

I'm probably out of my depth here, but would it be easier and nearly as useful to generate SVGs via a javascript library in the browser? My main concern with adopting bokeh for analysis and plotting would be that I eventually need to produce publication-ready or presentation-ready graphics. To minimize file sizes and maximize quality, I prefer to work with vector formats (eps, pdf or possibly svg). But as I understand it, bokeh cannot currently produce vector graphics. This would be a barrier for me, but I don't mind much whether the impasse is solved on the server side or browser side. e.g., I would be satisfied if I could develop plots in an IPython notebook and then export them as vector graphics from there.

In a quick search on this subject, I came across several javascript libraries that can generate SVG output using similar calls to drawing on an HTML5 canvas (which I assume is what bokeh does). I haven't investigated these very far, but I think they work either by accepting standard canvas drawing commands and then translating them into SVG elements, or they provide an alternative API which can be used both for drawing on the canvas and generating SVGs. Here are some of the key libraries I found:

Fabric.js was recommended in a couple of stackoverflow posts on this subject (1, 2). It seems to be one of the most mature options.

canvas-svg and canvas2svg were also mentioned in those stackoverflow posts but seem to be less mature.

two.js offers what may be a slightly different path forward -- a single API for drawing either to the canvas or to SVGs. I imagine this would block the two-way communication needed by Bokeh.

Another option, hinted at in yet another stackoverflow post might be to write graphs in the browser as SVG instead of canvas drawings. This would provide natural support for generating SVG files. This would also use a higher level interface than the canvas, which might simplify the interaction code (e.g., vertices could be native, clickable objects in the browser). Of course this would require a huge rewrite of the front end.

@bryevdv
Copy link
Member
bryevdv commented Jul 20, 2015

Hi @mfripp thanks for the researched and informative post. The landscape has definitely changed and we are in fact already planning to look into some of those options mentioned. However, by themselves those libraries don't solve the problem. People want to be able to do save(plot) in a python script on a headless server, and get and SVG file, without ever interacting with a browser. Any solution that requires running a browser and having a user actually push a button solves a different problem than this issue.

For headless output with JS libraries to work, Bokeh would need to be able to be run in Node.js or similar. But last time we tried, BokehJS was too big and unwieldy and we could not get it to run. So a possibility is to split up BokehJS so that (hopefully) a minimal part can be to run in Node.js (just enough to generate . And in fact, this absolutely must happen for a variety of reason, and so work is under way. But that is a very difficult architectural refactor to make that happen in a way that is as transparent and as least disruptive as possible. It will probably not be complete for a few months,

Completely unmentioned yet is that whatever solution we adopt of this has implications for being able to display math text in the saved output. Depending on the route we take, perhaps we have to give that up completely. To summarize, the core of the problem is that there are actually a few big pieces that interact in non-trivial ways. Some of the pieces have several possible options, none of which are very good or pleasant in some way. Or they may be blocked by major work in another area (splitting up BokehJS).

@mfripp
Copy link
mfripp commented Aug 6, 2015

Hi @bryevdv, thanks for your comments on this. Sorry for the slow response. I've been thinking a little more about this, but didn't get a chance to post until now.

From the user's perspective I can see three new features here:

  1. Produce vector graphics files from BokehJS.
  2. Produce graphics files from BokehJS under program control.
  3. Run BokehJS entirely on the "server" side (i.e., without a full web browser).

These are mostly independent, because any code written to provide features 1 and 2 in a web browser should also run in a server-side javascript environment (since you'll need a pretty robust javascript environment already).

For the needs of scientific users, I would rank 1 as very important, 2 as moderately important and 3 as interesting but not particularly important. I would also say that feature 3 is not useful without feature 2, and feature 2 is not useful without feature 1 (other users may want to produce raster images of plots programmatically, but for scientific applications, users will immediately want vector graphics).

Given that any code you write to implement features 1 and 2 in a full web browser would also be usable in a server-side environment, why not start with 1 and 2 in a web browser and then move them to the server environment along with the rest of BokehJS later?

This would be an especially attractive approach since it will take an unknown length of time to get BokehJS running on the server side. i.e., the high-priority features must work in a browser, can be implemented more easily in a browser, and can be migrated eventually from the browser to the server, so why wait for the server implementation before developing them?

@bryevdv
Copy link
Member
bryevdv commented Aug 6, 2015

@mfripp They are somewhat independent. However, BokehJS is already very large. Adding in yet another dependency and chunk of code to the current monolithic BokehJS, for a feature that is not actually the one that is most often requested [1] is not something I can justify. Once BokehJS is split up (we are about to have a kickoff on that front) it becomes more reasonable to think about adding an in-browser capability as an optional component, that users only have to pay for if they use. This is even more true if a new contributor wanted to help push on that front. (One of the biggest motivations for splitting up BokehJS is to enable outside contributions that can be developed independently and still integrated easily.)

[1] by far most users ask us for option 2: programmatic, headless generation. This is by any metric I can think of, the higher priority feature.

@bollwyvl
Copy link

Hi bokeh!

i've been working on nbpresent, and have made some decent progress on headless bokeh rendering in notebooks.

Here's a sample output. Actually, it's the first time it worked, fully.

I have given up on phantomjs in favor of ghost.py, which gives much finer-grained access to the underlying qt api.

Glad for any feedback... and maybe some thoughts on how to crank up the resolution on bokeh renders, as I am really gunning for print-quality output (>600dpi). I am totally fine with adding bokeh-specific fix-all lines, or giving users ways to apply specific patches!

@bryevdv
Copy link
Member
bryevdv commented Nov 19, 2015

We actually have an open PR already: #3047

This approach is a start to using node.js to create static raster images but it is hoped that we can leverage canvas-cairo to produce SVGs. If not, I think we will resort to implementing an alternative partial pycairo-based backed. Long term we would like to use MPL as a backend as well.

Being completely honest, I am personally fairly negative on the long term utility of "screenshot" approaches like the one above, I think they will be fragile by nature and of course limited to raster images in any case.

@bollwyvl
Copy link

Great, glad that's working out! Will there be a way to access the vector format in the frontend, a la output_svg? That would certainly nail my resolution issue!

@scherrey
Copy link

Brainstorming here but what about supporting png & jpeg creation by compiling those open source C libraries to asm.js and running in phantomjs? We've done a little bit of C++ coding that ran under asm.js with good result. Any ideas why this wouldn't work?

@birdsarah
Copy link
Member

@scherrey I think we want a solution that would also work without phantomjs - there's kind of a lot going on in this issue though, sowe may be talking about different things.

@birdsarah
Copy link
Member

@scherrey you may be right - I'm doing some experiments with phantomjs at the moment.

@birdsarah
Copy link
Member

@bryevdv pointed out that phantomjs won't be a solution until it supports TypedArrays. I'm poking around the currently in-development headless chrome.

@bittux
Copy link
bittux commented Aug 8, 2016

Hi Team,

I really love bokeh and am currently using it to host a grid of plots 6x11. I can load the first 5 plots just fine, clicking 1 plot at a time but then my browser (chrome) crashes if I try to open any other plot. It would be really great to be able to export the plots to png without the need of the 'save' tool. At this point I can try to create a hack by trying to use some third party tool (phantomjs) or just switch to another package (matplotlib, etc), which I don't really want to do because I really really like Bokeh :(

I see that this thread is over 2 years old... so it is safe to assume your team has no real interest in providing this feature?

Thanks for your time.

-- Grateful Bokeh User

@birdsarah
Copy link
Member

@tux2014, I'm confused, the last comment on this thread was 18 days ago.

Also "your team" seems like a bit of a misconception. This is open source. You are part of the team too. We welcome your help in getting this feature done.

@bryevdv
Copy link
Member
bryevdv commented Aug 8, 2016

I see that this thread is over 2 years old... so it is safe to assume your team has no real interest in providing this feature?

No that is not a safe assumption at all. What is actually the case, is that it is extremely difficult from a technical perspective, with lots of potentially unpleasant but also unavoidable trade-offs, and that it competes with many other very high priorities for extremely limited human resources, from a project management perspective.

@kilojoules
Copy link

+1 this would be so useful

@jrderuiter
Copy link

+1 The lack of static (SVG) image support is the main reason I'm not using bokeh right now.

@jsvp
Copy link
jsvp commented Feb 6, 2017

+1 Needed here as well

@jimmycallin
Copy link

Any updates to share? I would appreciate a sort of roadmap of what needs to be done before this is put into place.

@horta
Copy link
horta commented Feb 6, 2017

Please please please =)

SVG and PNG output would be amazing

@birdsarah
Copy link
Member

I believe chrome headless is going to be the right way to do this and that project is moving very quickly with decent linux support already. There is a lack of resources on this at the moment, but hopefully that will be changing in the coming months.

@nathanielatom
Copy link
Contributor

I don't know the current state of using headless chrome, but wkhtmltopdf (github) could be another option. It also may be useful in the short term for people to use as a workaround; I recently used it to programmatically generate a few hundred bokeh pdfs. I realize this issue is titled svg, png but I think it can also do pngs and maybe this could be useful for svgs.

Current Limitations:

  • For Bokeh plots to render the 0.13 alpha version is required.
  • This version so far only supports windows and linux (using xvfb, not fully headless yet).

After downloading the alpha build, I was able to use the following to generate a pdf:

wkhtmltopdf --no-stop-slow-scripts --javascript-delay 3000 http://bokeh.pydata.org/en/latest/docs/gallery/image_rgba.html image_rgba_out.pdf

It looks like there's also a handy python wrapper called pdfkit (github).

@canavandl canavandl mentioned this issue Apr 24, 2017
9 tasks
@canavandl
Copy link
Contributor

I have an open PR for generating PNGs that is seeking comment: #6189

@jbrockmendel
Copy link

This would be great for the purposes of unit testing.

@canavandl
Copy link
Contributor

re-opening issue until SVG PR is also merged.

@bryevdv
Copy link
Member
bryevdv commented May 30, 2017

Noting that current PRs support headless, static PNG, and static SVG (via toolbar button tool) A separate issue will be opened to extend SVG to headless programmatic usage.

@jimmycallin
Copy link
jimmycallin commented May 30, 2017

@bryevdv @canavandl @birdsarah This is great news, thank you so much for your effort!

Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
0