# `Giggly`
[🔗](https://github.com/giggleton/giggly/blob/v0.1.0/lib/giggly.ex#L1)

Giggly is a grammar-of-graphics plotting library for Elixir, modelled on ggplot2.

A plot is described with `Giggly.Plot`, which builds a value and runs nothing, and the functions
here take a finished plot and run it: `layer_data/2` shows the table a layer computes,
`panel_scales/2` the scales a panel is drawn on, and `to_svg/2` draws the plot.

# `panel_scale`

```elixir
@type panel_scale() :: Giggly.Scale.Continuous.t() | Giggly.Scale.Discrete.t()
```

A panel's trained position scale, continuous or discrete.

# `layer_data`

```elixir
@spec layer_data(Giggly.Plot.t(), integer()) :: Giggly.DataFrame.t()
```

The table the layer at `index` computes, counting from 0 in the order the layers were added; the
first layer when no index is given.

Its columns are named by aesthetic, plus the `:panel` each row is drawn in and its `:group`, the
series it belongs to; the data's own column names do not appear. Its x and y columns hold
positions on the panel's scales: a discrete value is its level's position, counting from 1.
Every aesthetic the layer draws with is a column: one the layer neither maps nor sets holds its
default under the plot's theme, a point's `size` the theme's points' size, `nil` where the
default is none, as a point's `fill`.
Raises `ArgumentError` when the plot has no layer at `index`; a negative index is refused too,
not counted from the end.

    iex> plot =
    ...>   %{"cyl" => ["6", "4", "6"], "mpg" => [21.0, 22.8, 21.4]}
    ...>   |> Giggly.Plot.new(%{x: :cyl, y: :mpg})
    ...>   |> Giggly.Plot.geom_point()
    iex> frame = Giggly.layer_data(plot)
    iex> Giggly.DataFrame.names(frame)
    [:x, :y, :panel, :group, :shape, :color, :fill, :size, :alpha, :stroke]
    iex> Giggly.DataFrame.pull(frame, :x)
    [2, 1, 2]
    iex> Giggly.DataFrame.pull(frame, :panel)
    [1, 1, 1]
    iex> Giggly.DataFrame.pull(frame, :group)
    [2, 1, 2]

# `panel_scales`

```elixir
@spec panel_scales(Giggly.Plot.t(), integer()) :: %{
  x: panel_scale(),
  y: panel_scale()
}
```

The trained x and y scales of the panel with id `panel`, counting from 1 as panel ids do; the
first panel when no id is given. Raises `ArgumentError` when the plot has no such panel.

    iex> plot =
    ...>   %{"cyl" => ["6", "4", "6"], "mpg" => [21.0, 22.8, 21.4]}
    ...>   |> Giggly.Plot.new(%{x: :cyl, y: :mpg})
    ...>   |> Giggly.Plot.geom_point()
    iex> Giggly.panel_scales(plot)
    %{
      x: %Giggly.Scale.Discrete{
        levels: ["4", "6"],
        factor: false,
        continuous_range: {1, 2},
        palette: :identity,
        na_value: nil,
        guide: :axis
      },
      y: %Giggly.Scale.Continuous{
        range: {21.0, 22.8},
        transform: :identity,
        palette: :identity,
        na_value: nil,
        guide: :axis
      }
    }

# `to_svg`

```elixir
@spec to_svg(Giggly.Plot.t(), keyword()) :: iodata()
```

The plot drawn as an SVG document, as iodata.

The drawing's size is given in pixels and written in the document in points, at 96 pixels to
the inch. Text, points and lines keep their sizes in points whatever the drawing's size, so a
smaller drawing gives them more of it.

## Options

* `:width` (`t:pos_integer/0`) - The drawing's width, in pixels. The default value is `700`.

* `:height` (`t:pos_integer/0`) - The drawing's height, in pixels. The default value is `433`.

* `:text` - How a label in a font Pica holds is written: `:outlines` draws it as the font's own shapes, keeping its words as unseen text; `:text` writes it as text naming its font. Every other label is written as text. The trade: the [fonts guide](fonts.md). The default value is `:outlines`.

* `:installed_fonts` (`t:boolean/0`) - In a project that lists Pica, whether a family no font is registered under with Pica is looked for among the machine's installed fonts too, by its exact name. `false` draws with the registered fonts alone. What the search costs, and which names it skips: the [fonts guide](fonts.md). The default value is `true`.

Raises `NimbleOptions.ValidationError` for an option it does not take or a size that is not a
positive whole number of pixels.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
