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

Save static vegalite plot to livemd #676

Merged
merged 12 commits into from
Nov 4, 2021
Merged

Save static vegalite plot to livemd #676

merged 12 commits into from
Nov 4, 2021

Conversation

cocoa-xu
Copy link
Contributor

@cocoa-xu cocoa-xu commented Nov 4, 2021

Hi, I added support for saving static VegaLite plot to the livemd file.

Currently, it saves the VegaLite JSON data and automatically plots it when a user opens the livebook.

This feature can be quite useful in the following situations

  • When users only want to view the livebook.
  • The livebook is shared as read-only.
  • When it takes too much time to rerun the code to get the plot.

Furthermore, if there are more users sharing livebooks on GitHub (or other platforms), then perhaps GitHub will add support for the livemd file, and the embedded plots can be rendered by vegalite.js.

@CLAassistant
Copy link

CLAassistant commented Nov 4, 2021

CLA assistant check
All committers have signed the CLA.

@josevalim
Copy link
Contributor

Hi @cocoa-xu! 👋

Thank you for the PR! This is fine for me, here are some other options to consider:

  1. We could also have the svg format but I think it is going to be much bigger, right?

  2. For the fenced code block, I think we should call it vega-lite.

One of the cool things about this is that we may be able to handle it on ExDoc too, and have it load vega-lite codeblocks.

@cocoa-xu
Copy link
Contributor Author

cocoa-xu commented Nov 4, 2021

Hi @josevalim ! Thanks for the reply!

  1. We could also have the svg format but I think it is going to be much bigger, right?

I was considering that maybe in the future we can add an option (either globally or as cell metadata) for the user to specify whether they want to save figures and if yes, then which format (SVG, PNG or JSON) is preferred.

For SVG and PNG types, the size of the livebook will be increased a lot compared to JSON data. But I think that should be fine because it's chosen by the user. Another upside is that saving as SVG or PNG removes the dependency on vegalite.js

  1. For the fenced code block, I think we should call it vega-lite.

I agree with you! I'll rename it in the next commit.

I was overthinking this as I thought we might need another type to tell whether it was :vega_lite_static or :vega_lite_dynamic, but now I realise that it will work the same way for the dynamic ones as we are capturing their content at the moment of saving. Though more work needs to be discussed and done for the dynamic plots because it seems to me that we will need to request the content through the WebSocket connection.

@jonatanklosko
Copy link
Member

Hey @cocoa-xu, sounds good to me too!

+1 on calling it vega-lite. Also, please a test in ExportTest and ImportTest in the outputs section :)

We could also have the svg format but I think it is going to be much bigger, right?

Exporting SVG is tricky, as on the server we would need the vegalite cli dependencies. Also embedding SVG directly into markdown wouldn't necessarily be rendered, unless we turn it into data URL, which can be huge.

One of the cool things about this is that we may be able to handle it on ExDoc too, and have it load vega-lite codeblocks.

Absolutely, it should be a couple lines of JS, I will give it a go!

@jonatanklosko
Copy link
Member

jonatanklosko commented Nov 4, 2021

@josevalim FTR here is a size comparison for all the example plots we have, and the JSON is a tiny fraction of regular images. One thing to keep in mind is that all the data points are included in the spec, so for a large data set it could get large (though depending on the plot, the same could apply to images).

@jonatanklosko
Copy link
Member

  defp before_closing_body_tag(:html) do
    """
    <script src="https://cdn.jsdelivr.net/npm/vega@5.20.2"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5.1.1"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@6.18.2"></script>
    <script>
      document.addEventListener("DOMContentLoaded", function() {
        for (const codeEl of document.querySelectorAll("pre code.vega-lite")) {
          try {
            const preEl = codeEl.parentElement;
            const spec = JSON.parse(codeEl.textContent)
            const plotEl = document.createElement("div");
            preEl.insertAdjacentElement("afterend", plotEl);
            vegaEmbed(plotEl, spec);
            preEl.remove();
          } catch (error) {
            console.log("Failed to render Vega-Lite plot: " + error)
          }
        }
      });
    </script>
    """
  end

Before

image

After

image

@cocoa-xu
Copy link
Contributor Author

cocoa-xu commented Nov 4, 2021

@josevalim FTR here is a size comparison for all the example plots we have, and the JSON is a tiny fraction of regular images. One thing to keep in mind is that all the data points are included in the spec, so for a large data set it could get large (though depending on the plot, the same could apply to images).

Perhaps we can add an option to enable/disable this?

I was considering that maybe in the future we can add an option (either globally or as cell metadata) for the user to specify whether they want to save figures and if yes, then which format (SVG, PNG or JSON) is preferred.

@jonatanklosko
Copy link
Member

Perhaps we can add an option to enable/disable this?

The outputs are already optional, so that should be enough for now. The problem with other export formats is that we cannot easily do it on the server, because it requires some npm CLIs to be available (npm install -g vega vega-lite canvas). And since JSON seems superior size-wise, I think it's fine :)

Copy link
Member

@jonatanklosko jonatanklosko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beautiful, thanks a lot!! :shipit:

@jonatanklosko jonatanklosko merged commit a15ec1c into livebook-dev:main Nov 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants