Generated sources (spec/08 §8): a chart under design has feeds that move without a host supplying any.
A signal is a description — a kind, its fields, a window, a period, a range — from
which rows/2 yields the rows of a window ending at a tick, pure and deterministic, so
the same tick always draws the same rows and a chart replays. The first field is time
and carries the tick; every other field is a value column following the kind's wave,
each shifted from the last so two columns are never the same line. A deployed design
still binds to the host's pool under the same names; signals stand in for it while the
chart is designed.
iex> sine = Visualize.Signals.new(:sine, [:t, :value], window: 3, period: 4)
iex> Visualize.Signals.rows(sine, 2) |> Enum.map(&{&1.t, round(&1.value)})
[{0, 50}, {1, 100}, {2, 50}]
iex> Visualize.Signals.rows(sine, 0) |> Enum.map(& &1.t)
[0]
iex> counter = Visualize.Signals.new(:discrete, [:t, :n], window: 2, min: 0, max: 2)
iex> Visualize.Signals.rows(counter, 3)
[%{t: 2, n: 2}, %{t: 3, n: 0}]
Summary
Functions
The four kinds, in the order of spec/08 §8.1.
As new/3 with no options.
A signal of the kind over the fields — the first field time, the rest values — with
the defaults of spec/08 §8.1 under the given options (window, period, min, max,
seed).
A pool — name to rows — from a map of named signals at a tick, ready for
Visualize.Chart.apply/2.
The window of rows ending at the tick (spec/08 §8.2): one row per tick from
tick − window + 1 to tick, a tick below zero yielding none, the time column the
tick and each value column its kind's value there.
One row per tick from max(from, 0) to to, whatever the signal's window — none when
to is below that (spec/08 §8.2). How Visualize.Feed.Signals serves a window of
ticks.
Types
Functions
@spec kinds() :: [atom(), ...]
The four kinds, in the order of spec/08 §8.1.
As new/3 with no options.
A signal of the kind over the fields — the first field time, the rest values — with
the defaults of spec/08 §8.1 under the given options (window, period, min, max,
seed).
iex> Visualize.Signals.new(:square, [:hour, :on], period: 2)
%{kind: :square, fields: [:hour, :on], window: 24, period: 2, min: 0, max: 100, seed: 0}
@spec pool(%{required(atom()) => t()}, non_neg_integer()) :: %{ required(atom()) => [map()] }
A pool — name to rows — from a map of named signals at a tick, ready for
Visualize.Chart.apply/2.
iex> pool = Visualize.Signals.pool(%{a: Visualize.Signals.new(:discrete, [:t, :n], window: 1)}, 5)
iex> pool
%{a: [%{t: 5, n: 5}]}
@spec rows(t(), non_neg_integer()) :: [map()]
The window of rows ending at the tick (spec/08 §8.2): one row per tick from
tick − window + 1 to tick, a tick below zero yielding none, the time column the
tick and each value column its kind's value there.
One row per tick from max(from, 0) to to, whatever the signal's window — none when
to is below that (spec/08 §8.2). How Visualize.Feed.Signals serves a window of
ticks.
iex> counter = Visualize.Signals.new(:discrete, [:t, :n], window: 2)
iex> Visualize.Signals.rows(counter, -1, 2) |> Enum.map(& &1.t)
[0, 1, 2]