# `Fude.Channel`
[🔗](https://github.com/hattoriai/fude/blob/v0.7.0/lib/fude/channel.ex#L1)

What a channel of a chart shows: the field of the data it reads, and
how. `x`, `y`, `color` and `size` are channels.

A channel is given in a short form or in full:

    Fude.bar(sales, x: :region, y: :revenue)
    Fude.bar(sales, x: :region, y: {:sum, :revenue})
    Fude.line(visits, x: {:month, :day}, y: {:count, :id})
    Fude.histogram(orders, x: {:bin, :total})
    Fude.bar(sales, x: :region, y: [field: :revenue, aggregate: :sum, format: :compact])
    Fude.rule(y: 1000)

  * an atom or a string is a field;
  * `{aggregate, field}` aggregates the field: `:count`, `:sum`, `:mean`,
    `:median`, `:min`, `:max` or `:distinct`;
  * `{unit, field}` takes a unit of a time: `:year`, `:quarter`,
    `:month`, `:week`, `:day`, `:hour` or `:minute`;
  * `{:bin, field}` puts the numbers of a field in bins;
  * a number is a constant, as the height of a rule;
  * a keyword list is the full form, with the keys below.

## Keys

  * `:field` - the field of the data.
  * `:type` - `:number`, `:time`, `:category` or `:ordinal`; learned from
    the data when not given.
  * `:aggregate` - see above.
  * `:time` - a unit of a time, see above.
  * `:bin` - `true`, or a keyword list with `:count` (about how many bins)
    or `:step` (the width of a bin).
  * `:sort` - the order of a field's categories: `:ascending`,
    `:descending`, `:x`, `:y`, `:"-x"` or `:"-y"` (by another channel,
    the minus for descending), or a list of the categories in order.
  * `:format` - how the browser writes the values: `:number`, `:integer`,
    `:percent`, `:compact`, `{:currency, "EUR"}`, `:bytes`, or a unit
    of a time for times.
  * `:digits` - how many decimals the values are written with, from 0 to
    20, for `:number`, `:compact`, `:percent` and currencies:
    `[field: :revenue, format: :number, digits: 0]` writes 6,893,914. Not
    given, `:number` keeps a value's decimals up to 2, `:compact` and
    `:percent` write up to 1, and a currency 2 under 1,000 and none from
    there. An axis's ticks take the decimals their step needs.
  * `:scheme` - the colors of a `color` channel, by name: sequential
    `:blue` (the default), `:green`, `:orange`, `:purple`, `:gray`,
    `:viridis`; diverging `:red_blue`, `:red_green` (around `:mid`);
    categorical `:categorical` (the default) and `:okabe_ito`. Or a list
    of colors (`["#0b6e4f", "#f2c14e", "#d1495b"]`): a ramp for numbers,
    a color for each category, in order.
  * `:mid` - the value at the middle of a diverging scheme: 0 when not
    given.
  * `:title` - the title of the axis or the legend; the field's name when
    not given, `false` for none.
  * `:scale` - a keyword list: `:type` (`:linear`, `:log`, `:sqrt`),
    `:domain` (`[min, max]`, or the categories), `:zero` (whether a
    number scale starts at zero), `:nice`.
  * `:stack` - `:zero` (the default of bars and areas with a color),
    `:normalize` (to 100%), `:center` or `false`.
  * `:value` - a constant instead of a field.
  * `:axis` - `:right` for a `y` of its own scale, on an axis at the
    right of the plot: a layer of other units over another, as a line
    of revenue over bars of orders (`Fude.layers/3`). `:left` is the
    default.

# `aggregate`

```elixir
@type aggregate() :: :count | :sum | :mean | :median | :min | :max | :distinct
```

# `t`

```elixir
@type t() :: %Fude.Channel{
  aggregate: aggregate() | nil,
  axis: :left | :right | nil,
  bin: boolean() | map() | nil,
  digits: non_neg_integer() | nil,
  field: String.t() | nil,
  format: atom() | {atom(), String.t()} | nil,
  mid: number() | nil,
  scale: map() | nil,
  scheme: atom() | [String.t()] | nil,
  sort: atom() | [term()] | nil,
  stack: atom() | false | nil,
  time: time_unit() | nil,
  title: String.t() | false | nil,
  type: type() | nil,
  value: term()
}
```

# `time_unit`

```elixir
@type time_unit() :: :year | :quarter | :month | :week | :day | :hour | :minute
```

# `type`

```elixir
@type type() :: :number | :time | :category | :ordinal
```

# `field?`

```elixir
@spec field?(t()) :: boolean()
```

Whether the channel reads a field (and not a constant).

# `new`

```elixir
@spec new(atom(), term()) :: t()
```

A channel from its short form or its full form (see above). Raises an
`ArgumentError` that names the channel and the value when it is neither.

# `title`

```elixir
@spec title(t()) :: String.t() | nil
```

The title of the channel's axis or legend: its own, or its field's name.

---

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