Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Plotting Functions

plotting-functions.livemd

Plotting Functions

Mix.install([
  {:vega_lite, "~> 0.1.5"},
  {:kino_vega_lite, "~> 0.1.7"},
  {:kino, "~> 0.8.0"}
])

Imports

import :math
alias VegaLite, as: Vl

Producing Data

Lets look at a function:

$ f(x) = sin(2x) \cdot cos(x) $

We can bind the f variable to an anonymous function that implements this:

f = fn x -> :math.sin(x * 2) * :math.cos(x) end

Lets test it by using the . operator to call the function:

f.(12)

Presenting Data

Using a comprehension we can produce a timeseries:

values =
  for x <- 1..10000,
      do:
        (x / 100)
        |> (fn x -> %{x: x, y: f.(x)} end).()

Lets try to plot it:

Vl.new(width: 720, height: 100)
|> Vl.data_from_values(values)
|> Vl.mark(:line)
|> Vl.encode_field(:x, "x", type: :quantitative, title: "x")
|> Vl.encode_field(:y, "y", type: :quantitative, title: "sin(2x)*cos(x)")

Live Data

Alternatively, lets try to produce the data on demand and update the view periodically:

# how quickly to produce a new point
interval = 100

# where to plot
kino =
  Vl.new(width: 400, height: 400)
  |> Vl.mark(:line)
  |> Vl.encode_field(:x, "x", type: :quantitative)
  |> Vl.encode_field(:y, "y", type: :quantitative)
  |> Kino.VegaLite.new()
  |> Kino.render()

# add a new point
fun = fn _, {kino, x} ->
  Kino.VegaLite.push(kino, %{x: x, y: f.(x)}, window: 100)
  {:cont, {kino, x + 0.1}}
end

Kino.listen(interval, {kino, 0}, fun)