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

Feature Request: Support SVG output for bokeh #8

Closed
syntonym opened this issue Jul 30, 2020 · 9 comments
Closed

Feature Request: Support SVG output for bokeh #8

syntonym opened this issue Jul 30, 2020 · 9 comments
Labels
enhancement New feature or request

Comments

@syntonym
Copy link

Currently pandoc-plot with the bokeh toolkit only supports png and html output. Bokeh itself can output svgs source. This is especially relevant for bokeh as the bokeh png export unfortunately ignores DPI and always generates pngs with 92 DPI (ticket) which makes it less useful for pdf files.

@LaurentRDC
Copy link
Owner

Yes we can do this! I'll add support for this over lunch.

BTW, how do you set the dpi on a Bokeh plot?

@syntonym
Copy link
Author

BTW, how do you set the dpi on a Bokeh plot?

As far as I know you can't currently. Bokeh itself always deals in css pixels, when exported the DPI is up to the browser, and apparently selenium always uses 92 DPI. Hm, apparently that is not true this blogpost says there is an easy way to set DPI. But that should be implemented in bokeh.

Does pandoc-plot currently support multiple bokeh plots/layouts? Bokeh SVGs unfortunately don't support this, but I don't think there is any good way around that.

@LaurentRDC
Copy link
Owner

pandoc-plot can only include one file per figure. I have not tested using layouts, but there's no reason it should not be possible in the near future.

Right now, for technical reasons, pandoc-plot determines the most recent bokeh Plot object and saves that to file.

I think the most general plotting object in Bokeh is a Document, so we would need to tweak pandoc-plot a little to create multi-plot layouts by saving the most recent Document.

@LaurentRDC LaurentRDC added the enhancement New feature or request label Jul 30, 2020
@LaurentRDC
Copy link
Owner

So SVG support is in (I just tested it).

I also changed (in 8599869) the way the "current" figure is found, which implies that plots made with bokeh.layouts will be saved appropriately. This will come in the next version (probably 0.8.2.0).

Is there anything else related to bokeh that you think we should include in the next release?

@syntonym
Copy link
Author

There is actually one more thing which bothers me with bokeh plots:
If bokeh plots include a lot of data, no plot and no text/html/other plots following are rendered.
This is because bokeh generated HTML as following:

<script type="application/json" id="$ID">
    {"id": $DATA}
</script>
<script type="text/javascript">

(function() {
     var fn = function() {
     ...
     root.Bokeh.embed.embed_items($JSON_WITH_ID_$ID, render_items);
     ...
     };
     if (document.readyState != "loading") fn();
     else document.addEventListener("DOMContentLoaded", fn);
 })()
</script>

So if $DATA is big, this just takes a long time to parse.
This is inline, so text/html/plots/whatever after these script tags are not shown until the script tag is parsed.

One possible solution is moving the first script tag with all the data to the bottom of the document.
The cons for this is 1) additional work needs to be done to identify this script tag (there should be some support in the bokeh library, see this function 2) now the filter needs to be stateful to include something at the bottom of the document and 3) pandoc-plot is now tied more closely to the bokeh library, making it more brittle.

This can actually be circumvented by using bokeh.sources.AjaxDataSource and putting the data as separate json files.

All in all I don't think it's worth solving this in pandoc-plot.

@syntonym
Copy link
Author

One more thing came to my mind, although unrelated to bokeh: Currently pandoc-plot caches figures on the sourcecode used. When figures depend on external code or data, these dependencies are not taken into account and the figures are not rerendered when the dependencies change. Would it be possible to incorporate this?

One possible solution would be an option depends=FILE which would additionally hash FILE. Option for multiple files would be great.

A different solution would be an optional user defined function which evaluates whether the figure needs regeneration. This seems very complicated.

Another option could be to inject a function "open" into the code and automatically registering dependencies whenever this function is used to read files.

@LaurentRDC
Copy link
Owner

LaurentRDC commented Jul 31, 2020

There is actually one more thing which bothers me with bokeh plots:
If bokeh plots include a lot of data, no plot and no text/html/other plots following are rendered.
This is because bokeh generated HTML as following:

<script type="application/json" id="$ID">
    {"id": $DATA}
</script>
<script type="text/javascript">

(function() {
     var fn = function() {
     ...
     root.Bokeh.embed.embed_items($JSON_WITH_ID_$ID, render_items);
     ...
     };
     if (document.readyState != "loading") fn();
     else document.addEventListener("DOMContentLoaded", fn);
 })()
</script>

So if $DATA is big, this just takes a long time to parse.
This is inline, so text/html/plots/whatever after these script tags are not shown until the script tag is parsed.

One possible solution is moving the first script tag with all the data to the bottom of the document.
The cons for this is 1) additional work needs to be done to identify this script tag (there should be some support in the bokeh library, see this function 2) now the filter needs to be stateful to include something at the bottom of the document and 3) pandoc-plot is now tied more closely to the bokeh library, making it more brittle.

This can actually be circumvented by using bokeh.sources.AjaxDataSource and putting the data as separate json files.

All in all I don't think it's worth solving this in pandoc-plot.

Actually, pandoc-plot parses <script> tags to be to embed them correctly. Is this something that can be fixed by replacing <script> with <script async> ? That's an easy change. Please open another issue for this.

Edit: it appears that replacing <script> with <script defer> would fix it. That's easy.

@LaurentRDC
Copy link
Owner

One more thing came to my mind, although unrelated to bokeh: Currently pandoc-plot caches figures on the sourcecode used. When figures depend on external code or data, these dependencies are not taken into account and the figures are not rerendered when the dependencies change. Would it be possible to incorporate this?

One possible solution would be an option depends=FILE which would additionally hash FILE. Option for multiple files would be great.

A different solution would be an optional user defined function which evaluates whether the figure needs regeneration. This seems very complicated.

Another option could be to inject a function "open" into the code and automatically registering dependencies whenever this function is used to read files.

I can see adding a parameter cache=True|False on a particular plot, to always re-render a figure if it depends on external (non-deterministic) data. Please open another issue for this :)

@LaurentRDC
Copy link
Owner

The change is live in the latest version (0.9.0.0). Thank you for your suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants