# `Tucan.Polar`
[🔗](https://github.com/pnezis/tucan/blob/v0.7.0/lib/tucan/polar.ex#L1)

Plots in polar coordinates.

The following plots are supported:

* `lineplot/4`, `scatter/4` and `area/4` for lines, points and filled areas.
* `radar/4` for comparing the values of several categories.
* `bar/4`, `histogram/3` and `windrose/4` for circular sectors per category, per
angle bin, or per direction and speed.
* `heatmap/5` for cells binned by angle and radius.

> #### Experimental {: .error}
>
> This API is experimental and may change. `VegaLite` does not support polar
> coordinates for lines and points, so the polar data are converted to cartesian
> coordinates, while circular sectors are drawn as arc marks. The polar grid is
> drawn manually as extra layers. As a result polar plots are layered plots and
> helpers like `Tucan.Axes`, `Tucan.Grid` or `Tucan.Scale` do not apply to them.

## Coordinates

Each data point is defined by a radius `r` and an angle `theta`:

* By default angles are in degrees. Set `angle_unit: :radians` if your data are
in radians.
* An angle of `0` points to the right (east) and angles increase counter clockwise.
Use the `:direction` option to reverse the direction and the `:angle_offset` option
to rotate the plot.
* Negative radius values are drawn on the opposite side of the origin.

## The polar grid

The grid consists of circles at the radius ticks and lines from the origin at the
angle marks. The outer circle is drawn at the maximum radius, which is set:

* explicitly with the `:max_radius` option, or
* to the largest of the `:radius_ticks`, if set, or
* from the data, rounded up to a round number. This is possible only if the data
are passed inline and not as a URL or a dataset name. In this case you must set
either `:max_radius` or `:radius_ticks`.

Polar plots are always square. Use the `:width` option to set their size.

## Cyclic data

Polar plots are well suited for cyclic data, like the hours of a day or the days
of a year, since the end of a period is next to its start. With the `:period`
option a full turn corresponds to the given period. By default the plot then
looks like a clock, starting at the top and going clockwise, and the angle marks
are labeled with the period's divisions.

Daily temperatures of two cities over a year, where the `theta` field is a date:

```tucan
data =
  for {city, mean, amplitude} <- [{"Dublin", 10, 5}, {"Madrid", 16, 10}],
      date <- Date.range(~D[2024-01-01], ~D[2024-12-31]) do
    day = Date.day_of_year(date)
    wiggle = :math.sin(day / 3) + 0.6 * :math.sin(day / 1.7)
    temp = mean - amplitude * :math.cos(2 * :math.pi() * (day - 20) / 366) + wiggle

    %{city: city, date: date, temp: temp}
  end

Tucan.Polar.lineplot(data, "temp", "date", period: :year, color_by: "city")
```

With a numeric period the `theta` field is a number, e.g. the hour of the day
with a period of `24`. Notice that the hour `24` is the same as the hour `0`:

```tucan
demand = [30, 26, 24, 23, 24, 28, 38, 52, 60, 58, 55, 54,
          56, 55, 53, 54, 60, 72, 80, 78, 70, 58, 45, 36]

data = Enum.with_index(demand, fn value, hour -> %{hour: hour, demand: value} end)

Tucan.Polar.area(data, "demand", "hour",
  period: 24,
  fill_color: "orange",
  line_color: "darkorange",
  tooltip: true
)
```

# `area`

```elixir
@spec area(
  plotdata :: Tucan.plotdata(),
  r :: String.t(),
  theta :: String.t(),
  opts :: keyword()
) ::
  VegaLite.t()
```

Draws a filled area in polar coordinates.

`r` is the field with the radius and `theta` the field with the angle of each
point. The points are connected in increasing order of `theta` and the shape is
closed by connecting the last point to the first one. To fill the area between a
curve and the origin, include a point with a zero radius at the start or the end
of the curve.

The areas are not outlined by default, set `:line_color` to draw an outline.

See the module documentation for the coordinate conventions and the polar grid.

## Options

* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set.
* `:angle_unit` - The unit of the `theta` field values, one of `:degrees` or `:radians`. Ignored
  if `:period` is set. The default value is `:degrees`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set.
* `:interpolate` (`t:binary/0`) - The line interpolation method to use for line and area marks. One of the following:

  * `"linear"` - piecewise linear segments, as in a poly-line.
  * `"linear-closed"` - close the linear segments to form a polygon.
  * `"step"` - alternate between horizontal and vertical segments, as in a step function.
  * `"step-before"` - alternate between vertical and horizontal segments, as in a step function.
  * `"step-after"` - alternate between horizontal and vertical segments, as in a step function.
  * `"basis"` - a B-spline, with control point duplication on the ends.
  * `"basis-open"` - an open B-spline; may not intersect the start or end.
  * `"basis-closed"` - a closed B-spline, as in a loop.
  * `"cardinal"` - a Cardinal spline, with control point duplication on the ends.
  * `"cardinal-open"` - an open Cardinal spline; may not intersect the start or end, but will
  intersect other control points.
  * `"cardinal-closed"` - a closed Cardinal spline, as in a loop.
  * `"bundle"` - equivalent to basis, except the tension parameter is used to straighten the spline.
  * `"monotone"` - cubic interpolation that preserves monotonicity in y.

  The default value is `"linear-closed"`.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:period` (`t:atom/0` or `t:number/0`) - Plots cyclic data, where a full turn corresponds to the given period. One of:

  * `:day`, `:week` or `:year` - the `theta` field is a date or datetime and a
  full turn corresponds to a day, a week starting on Monday, or a year.
  * a number - the `theta` field is a number and a full turn corresponds to the
  given value, e.g. `24` for the hours of a day.

  See the "Cyclic data" section of the module documentation for more details.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.
* `:tension` (`t:number/0`) - Depending on the interpolation type, sets the tension parameter

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field that will be used for coloring the data. It is considered
  `:nominal` by default.
* `:group_by` (`t:String.t/0`) - A field to group by the areas without affecting the style of it.

### Styling Options

* `:fill_color` (`t:String.t/0`) - The fill color of the marks. This will override the `color` encoding if set.
* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `0.5`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:stroke_dash` (list of `t:pos_integer/0`) - An array of alternating stroke, space lengths in pixels for creating dashed
  or dotted lines.
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

A cardioid, drawn with an outline:

```tucan
theta = Enum.to_list(0..355//5)
r = Enum.map(theta, fn t -> 1 + :math.cos(t * :math.pi() / 180) end)

Tucan.Polar.area([r: r, theta: theta], "r", "theta",
  fill_color: "teal",
  line_color: "teal",
  stroke_width: 2
)
```

Two overlapping shapes colored by a field. With a smooth closed interpolation the
few points of each shape are connected with curves:

```tucan
data =
  for {shape, radiuses} <- [a: [5, 1, 5, 1, 5, 1], b: [1, 4, 1, 4, 1, 4]],
      {r, i} <- Enum.with_index(radiuses) do
    %{shape: shape, r: r, theta: i * 60}
  end

Tucan.Polar.area(data, "r", "theta",
  color_by: "shape",
  interpolate: "cardinal-closed",
  angle_marks: [0, 60, 120, 180, 240, 300]
)
```

# `bar`

```elixir
@spec bar(
  plotdata :: Tucan.plotdata(),
  value :: String.t(),
  category :: String.t(),
  opts :: keyword()
) ::
  VegaLite.t()
```

Draws a polar bar chart.

Each category is drawn as a circular sector of the same angle and a radius equal
to its `value`. This is also known as a Nightingale rose or coxcomb chart.
Compared to `Tucan.radial/4`, where the angle of each wedge depends on its value,
here the values are compared only through the radius.

The categories are placed at equal angles, starting at the top and going
clockwise. If `:color_by` is set, the bars are stacked.

See the module documentation for more details on the polar grid.

## Options

* `:aggregate` - The statistic used for aggregating the values of each category, and of each
  `:color_by` group if set. If not set each row is drawn as is.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set. The default value is `90`.
* `:categories` (list of `t:String.t/0`) - The categories in the order they are drawn. If not set they are inferred from
  the data, in the order they first appear. This is possible only if the data are
  passed inline.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set. The default value is `:clockwise`.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field used for coloring the bars. The bars of each category are
  stacked outwards, in the order of the colors in the legend.

### Styling Options

* `:fill_color` (`t:String.t/0`) - The fill color of the marks. This will override the `color` encoding if set.
* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

The monthly rainfall of a city:

```tucan
months = ~w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
rainfall = [120, 95, 80, 60, 45, 30, 20, 25, 50, 90, 130, 140]

data = Enum.zip_with(months, rainfall, fn month, mm -> %{month: month, rainfall: mm} end)

Tucan.Polar.bar(data, "rainfall", "month",
  fill_color: "steelblue",
  line_color: "white",
  tooltip: true
)
```

Stacked bars, with the total yield of each barley variety, grouped by site:

```tucan
Tucan.Polar.bar(:barley, "yield", "variety",
  color_by: "site",
  aggregate: :sum,
  categories: [
    "Manchuria", "Glabron", "Svansota", "Velvet", "Trebi",
    "No. 457", "No. 462", "Peatland", "No. 475", "Wisconsin No. 38"
  ],
  max_radius: 600,
  line_color: "white",
  width: 400
)
```

# `heatmap`

```elixir
@spec heatmap(
  plotdata :: Tucan.plotdata(),
  theta :: String.t(),
  r :: String.t(),
  color :: String.t() | nil,
  opts :: keyword()
) :: VegaLite.t()
```

Draws a polar heatmap.

The observations are binned by their angle, the `theta` field, and their radius,
the `r` field, and each cell is colored by the aggregated values of the `color`
field. If `color` is `nil` the cells are colored by the number of observations.

Radius values below zero or above the maximum radius are ignored.

See the module documentation for the coordinate conventions, cyclic data and the
polar grid.

## Options

* `:aggregate` - The statistic used for aggregating the values of the `color` field within each
  cell. Defaults to `:mean`. Ignored if `color` is `nil`.
* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set.
* `:angle_unit` - The unit of the `theta` field values, one of `:degrees` or `:radians`. Ignored
  if `:period` is set. The default value is `:degrees`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:period` (`t:atom/0` or `t:number/0`) - Plots cyclic data, where a full turn corresponds to the given period. One of:

  * `:day`, `:week` or `:year` - the `theta` field is a date or datetime and a
  full turn corresponds to a day, a week starting on Monday, or a year.
  * a number - the `theta` field is a number and a full turn corresponds to the
  given value, e.g. `24` for the hours of a day.

  See the "Cyclic data" section of the module documentation for more details.
* `:radius_bins` (`t:pos_integer/0`) - The number of equal radius bins. If not set the radius ticks of the grid are
  used as the bin limits, so that the grid circles are the edges of the cells.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.
* `:theta_bins` (`t:pos_integer/0`) - The number of equal angle bins a full turn is split to. The default value is `24`.

### Styling Options

* `:color_scheme` (`t:atom/0`) - The color scheme to use, for supported color schemes check `Tucan.Scale`.
* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

The number of generated wind observations by direction and speed:

```tucan
:rand.seed(:exsss, {1, 2, 3})

data =
  for _i <- 1..2000 do
    direction = 225 + 50 * :rand.normal()
    %{direction: direction, speed: abs(6 + 2.5 * :rand.normal())}
  end

Tucan.Polar.heatmap(data, "direction", "speed", nil,
  theta_bins: 36,
  radius_bins: 12,
  direction: :clockwise,
  angle_offset: 90,
  angle_labels: :compass,
  color_scheme: :viridis
)
```

The activity of a website per hour of the day and day of the week, from Monday at
the center to Sunday at the edge:

```tucan
data =
  for day <- 0..6, hour <- 0..23 do
    weekend? = day >= 5
    peak = if weekend?, do: 15, else: 11
    activity = 100 * :math.exp(-:math.pow((hour - peak) / 4, 2)) * if(weekend?, do: 0.6, else: 1)

    %{day: day, hour: hour, activity: activity}
  end

Tucan.Polar.heatmap(data, "hour", "day", "activity",
  period: 24,
  radius_ticks: [1, 2, 3, 4, 5, 6, 7],
  color_scheme: :oranges,
  tooltip: true
)
```

# `histogram`

```elixir
@spec histogram(plotdata :: Tucan.plotdata(), theta :: String.t(), opts :: keyword()) ::
  VegaLite.t()
```

Draws a circular histogram of the angles in the `theta` field.

A full turn is split in `:bins` equal sectors and the radius of each sector is
the number of values in it. Circular histograms are useful for cyclic data, like
directions or the times of a day, since values near the end of the cycle are next
to values near its start.

See the module documentation for the coordinate conventions, cyclic data and the
polar grid.

## Options

* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set.
* `:angle_unit` - The unit of the `theta` field values, one of `:degrees` or `:radians`. Ignored
  if `:period` is set. The default value is `:degrees`.
* `:bins` (`t:pos_integer/0`) - The number of equal angle bins a full turn is split to. The default value is `16`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:period` (`t:atom/0` or `t:number/0`) - Plots cyclic data, where a full turn corresponds to the given period. One of:

  * `:day`, `:week` or `:year` - the `theta` field is a date or datetime and a
  full turn corresponds to a day, a week starting on Monday, or a year.
  * a number - the `theta` field is a number and a full turn corresponds to the
  given value, e.g. `24` for the hours of a day.

  See the "Cyclic data" section of the module documentation for more details.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.
* `:relative` (`t:boolean/0`) - If set the radius is the percentage of the values in each bin instead of
  their count. The default value is `false`.

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field used for coloring the bars. The bars of each bin are
  stacked outwards, in the order of the colors in the legend.

### Styling Options

* `:fill_color` (`t:String.t/0`) - The fill color of the marks. This will override the `color` encoding if set.
* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

The directions of 400 generated observations, mostly around 60 degrees and some
around the opposite direction:

```tucan
:rand.seed(:exsss, {1, 2, 3})

directions =
  for i <- 1..400 do
    60 + 25 * :rand.normal() + if(rem(i, 5) == 0, do: 180, else: 0)
  end

Tucan.Polar.histogram([direction: directions], "direction",
  bins: 24,
  fill_color: "seagreen",
  line_color: "white"
)
```

The times of the day at which the purchases of an online store were made, as a
percentage per hour and colored by the kind of device:

```tucan
:rand.seed(:exsss, {1, 2, 3})

purchases =
  for i <- 1..600 do
    device = if rem(i, 3) == 0, do: "mobile", else: "desktop"
    peak = if device == "mobile", do: 21, else: 14
    hour = peak + 2.5 * :rand.normal()

    %{hour: hour, device: device}
  end

Tucan.Polar.histogram(purchases, "hour",
  period: 24,
  bins: 24,
  color_by: "device",
  relative: true,
  tooltip: true
)
```

# `lineplot`

```elixir
@spec lineplot(
  plotdata :: Tucan.plotdata(),
  r :: String.t(),
  theta :: String.t(),
  opts :: keyword()
) ::
  VegaLite.t()
```

Draws a line plot in polar coordinates.

`r` is the field with the radius and `theta` the field with the angle of each
point. The points are connected in increasing order of `theta`. Use a closed
interpolation, e.g. `interpolate: "linear-closed"`, to connect the last point
to the first one.

See the module documentation for the coordinate conventions and the polar grid.

## Options

* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set.
* `:angle_unit` - The unit of the `theta` field values, one of `:degrees` or `:radians`. Ignored
  if `:period` is set. The default value is `:degrees`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set.
* `:interpolate` (`t:binary/0`) - The line interpolation method to use for line and area marks. One of the following:

  * `"linear"` - piecewise linear segments, as in a poly-line.
  * `"linear-closed"` - close the linear segments to form a polygon.
  * `"step"` - alternate between horizontal and vertical segments, as in a step function.
  * `"step-before"` - alternate between vertical and horizontal segments, as in a step function.
  * `"step-after"` - alternate between horizontal and vertical segments, as in a step function.
  * `"basis"` - a B-spline, with control point duplication on the ends.
  * `"basis-open"` - an open B-spline; may not intersect the start or end.
  * `"basis-closed"` - a closed B-spline, as in a loop.
  * `"cardinal"` - a Cardinal spline, with control point duplication on the ends.
  * `"cardinal-open"` - an open Cardinal spline; may not intersect the start or end, but will
  intersect other control points.
  * `"cardinal-closed"` - a closed Cardinal spline, as in a loop.
  * `"bundle"` - equivalent to basis, except the tension parameter is used to straighten the spline.
  * `"monotone"` - cubic interpolation that preserves monotonicity in y.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:period` (`t:atom/0` or `t:number/0`) - Plots cyclic data, where a full turn corresponds to the given period. One of:

  * `:day`, `:week` or `:year` - the `theta` field is a date or datetime and a
  full turn corresponds to a day, a week starting on Monday, or a year.
  * a number - the `theta` field is a number and a full turn corresponds to the
  given value, e.g. `24` for the hours of a day.

  See the "Cyclic data" section of the module documentation for more details.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.
* `:tension` (`t:number/0`) - Depending on the interpolation type, sets the tension parameter

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field that will be used for coloring the data. It is considered
  `:nominal` by default.
* `:group_by` (`t:String.t/0`) - A field to group by the lines without affecting the style of it.

### Styling Options

* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:point_color` (`t:String.t/0`) - The color of the points, if `:points` is set to `true`.
* `:point_size` (`t:pos_integer/0`) - The size of the points, if `:points` is set to `true`.
* `:points` (`t:boolean/0`) - Whether points will be included in the chart. The default value is `false`.
* `:stroke_dash` (list of `t:pos_integer/0`) - An array of alternating stroke, space lengths in pixels for creating dashed
  or dotted lines.
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

An Archimedean spiral, where the radius grows linearly with the angle:

```tucan
theta = Enum.to_list(0..720//5)
r = Enum.map(theta, &(&1 / 360))

Tucan.Polar.lineplot([r: r, theta: theta], "r", "theta")
```

A rose with three petals. Negative radius values are drawn on the opposite side
of the origin, so over a full turn each petal is traced twice:

```tucan
theta = Enum.to_list(0..360)
r = Enum.map(theta, fn t -> :math.cos(3 * t * :math.pi() / 180) end)

Tucan.Polar.lineplot([r: r, theta: theta], "r", "theta", line_color: "purple")
```

For radar charts see `radar/4`.

# `radar`

```elixir
@spec radar(
  plotdata :: Tucan.plotdata(),
  value :: String.t(),
  category :: String.t(),
  opts :: keyword()
) :: VegaLite.t()
```

Draws a radar chart.

A radar chart, also known as a spider or star chart, compares the values of
several categories. Each category has its own axis starting from the center and
the values of each series are connected into a closed outline. The data must have
one row per category and series, with the `value` of the category.

The categories are placed at equal angles, starting at the top and going
clockwise, and the grid lines are labeled with the category names.

See the module documentation for more details on the polar grid.

## Options

* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set. The default value is `90`.
* `:categories` (list of `t:String.t/0`) - The categories in the order they are drawn. If not set they are inferred from
  the data, in the order they first appear. This is possible only if the data are
  passed inline.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set. The default value is `:clockwise`.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field that will be used for coloring the data. It is considered
  `:nominal` by default.
* `:group_by` (`t:String.t/0`) - A field to group by the outlines without affecting the style of it.

### Styling Options

* `:fill_opacity` (`t:number/0`) - The opacity of the fill, if `:filled` is set. The default value is `0.3`.
* `:filled` (`t:boolean/0`) - Whether the outlines will be filled. The default value is `false`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:point_color` (`t:String.t/0`) - The color of the points, if `:points` is set to `true`.
* `:point_size` (`t:pos_integer/0`) - The size of the points, if `:points` is set to `true`.
* `:points` (`t:boolean/0`) - Whether points will be drawn at the values. The default value is `true`.
* `:stroke_dash` (list of `t:pos_integer/0`) - An array of alternating stroke, space lengths in pixels for creating dashed
  or dotted lines.
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

Two players compared across six skills:

```tucan
data =
  for {player, scores} <- [
        {"Alice", [8, 6, 9, 7, 4, 8]},
        {"Bob", [5, 9, 6, 8, 7, 6]}
      ],
      {skill, score} <-
        Enum.zip(["Speed", "Shooting", "Passing", "Dribbling", "Defense", "Stamina"], scores) do
    %{player: player, skill: skill, score: score}
  end

Tucan.Polar.radar(data, "score", "skill",
  color_by: "player",
  filled: true,
  max_radius: 10,
  tooltip: true
)
```

The monthly average temperatures of Seattle. The `:categories` option sets the
order of the categories explicitly, which is required if the data are not passed
inline:

```tucan
months = ~w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)

data =
  Enum.zip_with(
    months,
    [5.5, 6.5, 8.4, 10.8, 14.4, 17.0, 19.9, 20.1, 17.2, 12.6, 8.2, 5.8],
    fn month, temp -> %{month: month, temp: temp} end
  )

Tucan.Polar.radar(data, "temp", "month",
  categories: months,
  line_color: "firebrick",
  point_color: "firebrick",
  max_radius: 25,
  radius_ticks: [5, 10, 15, 20, 25]
)
```

# `scatter`

```elixir
@spec scatter(
  plotdata :: Tucan.plotdata(),
  r :: String.t(),
  theta :: String.t(),
  opts :: keyword()
) ::
  VegaLite.t()
```

Draws a scatter plot in polar coordinates.

`r` is the field with the radius and `theta` the field with the angle of each
point. Similarly to `Tucan.scatter/4` the points can be colored, shaped and sized
by data fields.

See the module documentation for the coordinate conventions and the polar grid.

## Options

* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set.
* `:angle_unit` - The unit of the `theta` field values, one of `:degrees` or `:radians`. Ignored
  if `:period` is set. The default value is `:degrees`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:period` (`t:atom/0` or `t:number/0`) - Plots cyclic data, where a full turn corresponds to the given period. One of:

  * `:day`, `:week` or `:year` - the `theta` field is a date or datetime and a
  full turn corresponds to a day, a week starting on Monday, or a year.
  * a number - the `theta` field is a number and a full turn corresponds to the
  given value, e.g. `24` for the hours of a day.

  See the "Cyclic data" section of the module documentation for more details.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.

### Data Grouping Options

* `:color_by` (`t:String.t/0`) - If set a data field that will be used for coloring the data. It is considered
  `:nominal` by default.
* `:shape_by` (`t:String.t/0`) - If set a data field that will be used for setting the shape of the data points.
  It is considered `:nominal` by default.
* `:size_by` (`t:String.t/0`) - If set a data field that will be used for controlling the size of the data points.
  It is considered `:quantitative` by default.

### Styling Options

* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:filled` (`t:boolean/0`) - Whether the mark will be filled or not
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:point_color` (`t:String.t/0`) - The color of the points
* `:point_shape` - Shape of the point marks. Circle by default.
* `:point_size` (`t:pos_integer/0`) - The pixel area of the marks. Note that this value sets the area of the symbol;
  the side lengths will increase with the square root of this value.
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.
* `:shape` (`t:keyword/0`) - Extra vega lite options for the `:shape` encoding. The default value is `[]`.
* `:size` (`t:keyword/0`) - Extra vega lite options for the `:size` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

Seeds of a sunflower head are placed at successive multiples of the golden angle,
at a radius proportional to the square root of their index:

```tucan
seeds = 1..300
theta = Enum.map(seeds, &(&1 * 137.508))
r = Enum.map(seeds, &:math.sqrt/1)

Tucan.Polar.scatter([r: r, theta: theta], "r", "theta",
  point_color: "darkorange",
  point_size: 20,
  filled: true,
  angle_marks: []
)
```

Wind measurements, where the angle is the direction the wind blows from and the
radius its speed. The angle offset and direction match the compass, with North
on top and angles increasing clockwise, and the angle marks are labeled with the
compass points:

```tucan
data = [
  %{speed: 4.2, direction: 10, station: "A"},
  %{speed: 6.1, direction: 35, station: "A"},
  %{speed: 3.5, direction: 80, station: "A"},
  %{speed: 7.8, direction: 200, station: "A"},
  %{speed: 5.4, direction: 230, station: "A"},
  %{speed: 2.1, direction: 300, station: "B"},
  %{speed: 3.3, direction: 320, station: "B"},
  %{speed: 6.7, direction: 250, station: "B"},
  %{speed: 8.9, direction: 270, station: "B"},
  %{speed: 4.8, direction: 150, station: "B"}
]

Tucan.Polar.scatter(data, "speed", "direction",
  color_by: "station",
  shape_by: "station",
  point_size: 80,
  angle_offset: 90,
  direction: :clockwise,
  angle_labels: :compass,
  tooltip: true
)
```

# `windrose`

```elixir
@spec windrose(
  plotdata :: Tucan.plotdata(),
  direction :: String.t(),
  speed :: String.t(),
  opts :: keyword()
) :: VegaLite.t()
```

Draws a wind rose.

A wind rose shows how the observations of wind speed and direction are distributed.
The observations are binned by direction, and the bar of each direction is split
by speed, with the lower speeds closer to the center. By default the radius is the
percentage of the observations in each bin.

`direction` is the field with the direction the wind blows from, in degrees, and
`speed` the field with the wind speed. The plot follows the compass, with North on
top and directions increasing clockwise.

See the module documentation for more details on the polar grid.

## Options

* `:angle_labels` (`t:atom/0` or list of `t:String.t/0`) - The labels of the angle marks. Defaults to `:degrees`, or to the period's
  divisions if `:period` is set and `:angle_marks` is not. One of:

  * `:degrees` - the angle in degrees, e.g. `"45°"`.
  * `:compass` - the compass point of the angle, e.g. `"NE"`, for multiples of
  22.5 degrees. The angles are treated as compass bearings, so you should usually
  also set `direction: :clockwise` and `angle_offset: 90`.
  * `:none` - no labels.
  * a list of strings, one for each angle mark.

  The default value is `:compass`.
* `:angle_marks` (list of `t:number/0`) - The angles in degrees at which grid lines from the origin are drawn. Always in
  degrees, regardless of the `:angle_unit` and the `:period`. Defaults to every
  45 degrees, or to the period's divisions if `:period` is set.
* `:angle_offset` - Rotates the plot counter clockwise by the given angle in degrees. For example
  with `angle_offset: 90` an angle of `0` points up. Defaults to `0`, or to `90`
  if `:period` is set. The default value is `90`.
* `:direction` - The direction in which angles increase. Defaults to `:counter_clockwise`, or to
  `:clockwise` if `:period` is set. The default value is `:clockwise`.
* `:directions` (`t:pos_integer/0`) - The number of direction bins. The bins are centered at the directions, e.g. with
  the default 16 bins the North bin spans from -11.25 to 11.25 degrees. The default value is `16`.
* `:max_radius` (`t:number/0`) - The radius of the outer grid circle. If not set it is the largest radius tick,
  or if these are not set either it is inferred from the data.
* `:radius_ticks` (list of `t:number/0`) - The radiuses at which grid circles are drawn. If not set they are derived from
  the maximum radius.
* `:relative` (`t:boolean/0`) - If set the radius is the percentage of the observations in each bin, otherwise
  their count. The default value is `true`.
* `:speed_bins` (list of `t:number/0`) - The increasing lower limits of the speed bins. The last bin contains all speeds
  above the last limit and speeds below the first limit are ignored. If not set,
  five equal bins starting from `0` are used, which is possible only if the data
  are passed inline.

### Styling Options

* `:fill_opacity` (`t:number/0`) - The fill opacity of the plotted elements. The default value is `1`.
* `:grid_color` (`t:String.t/0`) - The color of the polar grid lines. The default value is `"#dddddd"`.
* `:grid_opacity` (`t:number/0`) - The opacity of the polar grid lines. The default value is `1`.
* `:line_color` (`t:String.t/0`) - The color of the line
* `:stroke_width` (`t:pos_integer/0`) - The stroke width in pixels
* `:title` (`t:String.t/0`) - The title of the plot.
* `:width` (`t:pos_integer/0`) - The width and height of the plot in pixels. The default value is `300`.

### Encodings Custom Options

All Tucan plots are building a `VegaLite` specification based on some sane
default parameters. Through these encodings options you are free to set any
vega-lite supported option to any encoding channel of the plot.

Notice that if set they will be merged with any option set by the plot. Since they
have a higher precedence they may override the default settings and affect the
generated plot.

You can set an arbitrary keyword list. Notice that **the contents are not validated.**

* `:color` (`t:keyword/0`) - Extra vega lite options for the `:color` encoding. The default value is `[]`.

### Interactivity Options

* `:tooltip` (`boolean() | :data | :encoding`) - The tooltip text string to show upon mouse hover or an object defining which fields
  should the tooltip be derived from. Can be one of the following:

  * `:encoding` - all fields from encoding are used
  * `:data` - all fields of the highlighted data point are used
  * `true` - same as `:encoding`
  * `false`, `nil` - no tooltip is used

## Examples

Generated observations with a prevailing south west wind:

```tucan
:rand.seed(:exsss, {1, 2, 3})

data =
  for _i <- 1..500 do
    direction = 225 + 45 * :rand.normal()
    speed = abs(6 + 3 * :rand.normal() + 2 * :math.cos((direction - 225) * :math.pi() / 180))

    %{direction: direction, speed: speed}
  end

Tucan.Polar.windrose(data, "direction", "speed", line_color: "white", tooltip: true)
```

With custom speed bins, eight directions, counts instead of percentages and a
different color scheme:

```tucan
:rand.seed(:exsss, {1, 2, 3})

data =
  for _i <- 1..300 do
    direction = if :rand.uniform() < 0.6, do: 20 * :rand.normal(), else: 360 * :rand.uniform()
    %{direction: direction, speed: 12 * :rand.uniform()}
  end

Tucan.Polar.windrose(data, "direction", "speed",
  directions: 8,
  speed_bins: [0, 3, 6, 9],
  relative: false,
  color: [scale: [scheme: "viridis"]]
)
```

---

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