Packages

Elixir bindings to Rust vl-convert library

Current section

Files

Jump to
vega_lite_convert lib vega_lite convert.ex
Raw

lib/vega_lite/convert.ex

defmodule VegaLite.Convert do
@moduledoc """
Various export methods for a `VegaLite` specification.
All of the exports are performed via a Rustler NIF that wraps the
[vl-convert-rs](https://github.com/vega/vl-convert) Rust library.
alias VegaLite, as: Vl
vl =
Vl.new(width: 400, height: 400)
|> Vl.data_from_values(iteration: 1..100, score: 1..100)
|> Vl.mark(:line)
|> Vl.encode_field(:x, "iteration", type: :quantitative)
|> Vl.encode_field(:y, "score", type: :quantitative)
# Saves graphic to a file
VegaLite.Convert.save!(vl, "image.png")
# Returns graphic as a binary
VegaLite.Convert.to_png(vl)
"""
alias VegaLite.Convert.WxViewer
alias VegaLite.Convert.Native
@doc """
Renders a `VegaLite` graphic to a file in one of the supported
formats.
Any additional options provided beyond `:format` are passed to the
functions that export to the desired format.
## Options
* `:format` - the format to export the graphic as, must be either
of: `:json`, `:html`, `:png`, `:svg`, `:pdf`, `:jpeg`, `:jpg`.
By default the format is inferred from the file extension.
"""
@spec save!(VegaLite.t(), Path.t(), keyword()) :: :ok
def save!(vl, path, opts \\ []) do
{format, opts} =
Keyword.pop_lazy(opts, :format, fn ->
path
|> Path.extname()
|> String.trim_leading(".")
|> String.to_existing_atom()
end)
content =
case format do
:json ->
to_json(vl, opts)
:html ->
to_html(vl, opts)
:png ->
to_png(vl, opts)
:svg ->
to_svg(vl)
:pdf ->
to_pdf(vl)
jpeg when jpeg in [:jpeg, :jpg] ->
to_jpeg(vl, opts)
_ ->
raise ArgumentError,
"unsupported export format, expected :json, :html, :png, :svg, :pdf, :jpeg or :jpg got: #{inspect(format)}"
end
File.write!(path, content)
end
@doc """
Returns the underlying Vega-Lite specification as JSON.
## Options
* `:target` - specifies whether JSON export is in the VegaLite
format or Vega. Valid options are `:vega_lite` or `:vega`.
Defaults to `:vega_lite`.
"""
@spec to_json(vl :: VegaLite.t(), opts :: keyword()) :: String.t()
def to_json(vl, opts \\ []) do
vega_lite_json =
vl
|> VegaLite.to_spec()
|> Jason.encode!()
case Keyword.get(opts, :target, :vega_lite) do
:vega_lite ->
vega_lite_json
:vega ->
vega_lite_json
|> Native.vegalite_to_vega()
|> unwrap!()
end
end
@doc """
Builds an HTML page that renders the given graphic.
The HTML page loads necessary JavaScript dependencies from a CDN
and then renders the graphic in a root element.
## Options
* `:bundle` - configures whether the VegaLite client side JS library
is embedded in the document or if it is pulled down from the CDN.
Defaults to `true`.
* `:renderer` - determines how the VegaLite chart is rendered in
the HTML document. Possible values are: `:svg`, `:canvas`, or
`:hybrid`. Defaults to `:svg`.
"""
@spec to_html(VegaLite.t()) :: binary()
def to_html(vl, opts \\ []) do
bundle = Keyword.get(opts, :bundle, true)
renderer = opts |> Keyword.get(:renderer, :svg) |> to_string()
vl
|> to_json()
|> Native.vegalite_to_html(bundle, renderer)
|> unwrap!()
end
@doc """
Renders the given graphic as a PNG image and returns its binary
content.
## Options
* `:scale` - the image scale factor. Defaults to `1.0`.
* `:ppi` - the number of pixels per inch. Defaults to `72.0`.
"""
@spec to_png(VegaLite.t(), keyword()) :: binary()
def to_png(vl, opts \\ []) do
scale = Keyword.get(opts, :scale, 1.0)
ppi = Keyword.get(opts, :ppi, 72.0)
vl
|> to_json()
|> Native.vegalite_to_png(scale, ppi)
|> unwrap!()
end
@doc """
Renders the given graphic as an SVG image and returns its binary
content.
"""
@spec to_svg(VegaLite.t()) :: binary()
def to_svg(vl) do
vl
|> to_json()
|> Native.vegalite_to_svg()
|> unwrap!()
end
@doc """
Renders the given graphic as a PDF and returns its binary content.
"""
@spec to_pdf(VegaLite.t()) :: binary()
def to_pdf(vl) do
vl
|> to_json()
|> Native.vegalite_to_pdf()
|> unwrap!()
end
@doc """
Renders the given graphic as a JPEG image and returns its binary
content.
## Options
* `:scale` - the image scale factor. Defaults to `1.0`.
* `:quality` - the quality of the generated JPEG between 0 (worst)
and 100 (best). Defaults to `90`.
"""
@spec to_jpeg(VegaLite.t(), keyword()) :: binary()
def to_jpeg(vl, opts \\ []) do
scale = Keyword.get(opts, :scale, 1.0)
quality = Keyword.get(opts, :quality, 90)
vl
|> to_json()
|> Native.vegalite_to_jpeg(scale, quality)
|> unwrap!()
end
@doc """
Renders a `VegaLite` graphic in a GUI window widget.
This requires the Erlang compilation to include the `:wx` module.
"""
@spec open_viewer(VegaLite.t()) :: :ok | :error
def open_viewer(vl) do
with {:ok, _pid} <- start_wx_viewer(vl), do: :ok
end
@doc """
Same as `show/1`, but blocks until the window widget is closed.
"""
@spec open_viewer_and_wait(VegaLite.t()) :: :ok | :error
def open_viewer_and_wait(vl) do
with {:ok, pid} <- start_wx_viewer(vl) do
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, :process, _object, _reason} -> :ok
end
end
end
defp start_wx_viewer(vl) do
vl
|> to_html()
|> WxViewer.start()
end
defp unwrap!(:ok), do: :ok
defp unwrap!({:ok, value}), do: value
defp unwrap!({:error, error}), do: raise(error)
end