Dynamic var for thread-local config overrides. Bind to a map to override any config keys for the current thread. (binding [defaults/config {:theme {:bg "#FFF"}}] ...)
Dynamic var for thread-local config overrides.
Bind to a map to override any config keys for the current thread.
(binding [defaults/*config* {:theme {:bg "#FFF"}}] ...)Per-aesthetic properties, and the single table the rest of the library derives its per-aesthetic sets from. One entry per aesthetic, each carrying everything any consumer needs to know about it, so a new aesthetic is added here and nowhere else.
:category -- :positional places a mark, :appearance decides
how it looks, :grouping splits the data and draws nothing of its
own. The glossary's Aesthetic entry teaches the same three, under
those names.
:column? -- whether the aesthetic can name a dataset column at
all. :x-min and :x-max cannot: only lay-band-v reads them,
and it reads a value straight from the mapping. :y-min and
:y-max can, because lay-errorbar reads them as columns -- see
the note on layer-dependent readings at the end.
:numeric? -- whether the column it names, when it names one,
holds numbers. Those are the keys eligible for finite-value
filtering at plan time.
:value? -- whether a written value is accepted beside a column
reference. :fill and :group take a column and nothing else
today. For :fill that is a gap, and :scale-default below says
what a value there would mean once it is closed; for :group it
is not, since it splits the data and draws nothing of its own, so
there is nothing a value could mean.
:scale-default -- which side of the scale a written value
falls on when the mapping does not say. It has nothing to say
about a column: a column passes through the aesthetic's scale
wherever there is one, uniformly, and nothing reads its contents.
:by-source draws it, and the aesthetic's vocabulary is what
the gate refuses it against: "red" is a color and is drawn,
"notacolor" is neither a column nor a color and is reported.
:always scales it instead -- {:x 6.5} is a datum on the axis,
not 6.5 drawing units. :never means no scale to pass through;
nil means no scale at all. A :scale in the mapping overrides
it in either direction, and is the only way to move a column off
its scale or to read a written value as data.
The split is by category, not by aesthetic. Every appearance
aesthetic is :by-source and every positional one is :always,
which is the same distinction the glossary draws and the
:category entry above records. The reason the two differ is
that position already has a second vocabulary for page geometry
and appearance does not: {:in :drawing-area} says "these
coordinates are drawing units", so a bare {:x 6.5} is free to
mean the data value, while nothing but {:size 7} can say a
radius of seven. Both readings stay reachable either way --
{:x {:value 6.5 :scale false}} and
{:size {:value 7 :scale true}}.
:drawn-column? -- whether a column of this aesthetic can be
drawn as it stands, which is what {:scale false} on a column
asks for. It is the only route to an identity scale now that a
column never leaves its scale by convention. False where the
reading is not written: :shape would draw a column of symbols
and does not, and :fill derives its color through a gradient
with no branch for a value that already is one. Kept as a flag
rather than a silence for the same reason :value? is: one
entry says what a reading would mean and another says whether it
exists, and a gate needs both. See dev-notes/backlog.md.
:categorical-column? -- whether the column it names may hold
categories. False on the three column-bearing aesthetics that
encode a magnitude and have no categorical counterpart --
:alpha, :fill, :size, which is continuous-column-aesthetics
-- and on :x-min / :x-max, which name no column at all.
:scale-key -- the key a draft layer carries this channel's
resolved scale spec under, for the aesthetics that have a scale.
pj/scale writes the mapping rather than :opts, so this names
where the spec arrives, not where it is written.
:legend? -- whether the compositor may hoist this aesthetic's
legend to composite level when every leaf agrees on it. It is not
which aesthetics draw a legend: :fill draws a continuous one and
is not hoisted, so it carries no :legend?.
:literal->column? -- whether impl.pose/resolve-positional-values
turns a literal value here into a constant column before anything
else reads the mapping. True of the three the stat and the extract
read; the band bounds are read straight from the mapping by their
own marks instead, so normalizing them would take the value away
from the only code that wants it.
:scale-default says what a value means once the aesthetic accepts
one, so :fill carries :by-source while :value? is still false.
Setting :value? before the reading exists would make a value pass
every check and then draw nothing, which is the defect this table is
here to prevent.
One pair records a reading that depends on the layer rather than on
the value, which is a wart the table makes visible rather than
hides: :y-min / :y-max are a column on :errorbar and a value
on :band-h. :text is not such a pair -- a written label
broadcasts over the layer's rows whether or not the layer has
data.
Per-aesthetic properties, and the single table the rest of the
library derives its per-aesthetic sets from. One entry per
aesthetic, each carrying everything any consumer needs to know about
it, so a new aesthetic is added here and nowhere else.
- `:category` -- `:positional` places a mark, `:appearance` decides
how it looks, `:grouping` splits the data and draws nothing of its
own. The glossary's Aesthetic entry teaches the same three, under
those names.
- `:column?` -- whether the aesthetic can name a dataset column at
all. `:x-min` and `:x-max` cannot: only `lay-band-v` reads them,
and it reads a value straight from the mapping. `:y-min` and
`:y-max` can, because `lay-errorbar` reads them as columns -- see
the note on layer-dependent readings at the end.
- `:numeric?` -- whether the column it names, when it names one,
holds numbers. Those are the keys eligible for finite-value
filtering at plan time.
- `:value?` -- whether a written value is accepted beside a column
reference. `:fill` and `:group` take a column and nothing else
today. For `:fill` that is a gap, and `:scale-default` below says
what a value there would mean once it is closed; for `:group` it
is not, since it splits the data and draws nothing of its own, so
there is nothing a value could mean.
- `:scale-default` -- which side of the scale a **written value**
falls on when the mapping does not say. It has nothing to say
about a column: a column passes through the aesthetic's scale
wherever there is one, uniformly, and nothing reads its contents.
`:by-source` draws it, and the aesthetic's vocabulary is what
the gate refuses it against: `"red"` is a color and is drawn,
`"notacolor"` is neither a column nor a color and is reported.
`:always` scales it instead -- `{:x 6.5}` is a datum on the axis,
not 6.5 drawing units. `:never` means no scale to pass through;
`nil` means no scale at all. A `:scale` in the mapping overrides
it in either direction, and is the only way to move a column off
its scale or to read a written value as data.
**The split is by category, not by aesthetic.** Every appearance
aesthetic is `:by-source` and every positional one is `:always`,
which is the same distinction the glossary draws and the
`:category` entry above records. The reason the two differ is
that position already has a second vocabulary for page geometry
and appearance does not: `{:in :drawing-area}` says "these
coordinates are drawing units", so a bare `{:x 6.5}` is free to
mean the data value, while nothing but `{:size 7}` can say a
radius of seven. Both readings stay reachable either way --
`{:x {:value 6.5 :scale false}}` and
`{:size {:value 7 :scale true}}`.
- `:drawn-column?` -- whether a column of this aesthetic can be
drawn as it stands, which is what `{:scale false}` on a column
asks for. It is the only route to an identity scale now that a
column never leaves its scale by convention. False where the
reading is not written: `:shape` would draw a column of symbols
and does not, and `:fill` derives its color through a gradient
with no branch for a value that already is one. Kept as a flag
rather than a silence for the same reason `:value?` is: **one
entry says what a reading would mean and another says whether it
exists, and a gate needs both.** See `dev-notes/backlog.md`.
- `:categorical-column?` -- whether the column it names may hold
categories. False on the three column-bearing aesthetics that
encode a magnitude and have no categorical counterpart --
`:alpha`, `:fill`, `:size`, which is `continuous-column-aesthetics`
-- and on `:x-min` / `:x-max`, which name no column at all.
- `:scale-key` -- the key a draft layer carries this channel's
resolved scale spec under, for the aesthetics that have a scale.
`pj/scale` writes the mapping rather than `:opts`, so this names
where the spec arrives, not where it is written.
- `:legend?` -- whether the compositor may hoist this aesthetic's
legend to composite level when every leaf agrees on it. It is not
which aesthetics draw a legend: `:fill` draws a continuous one and
is not hoisted, so it carries no `:legend?`.
- `:literal->column?` -- whether `impl.pose/resolve-positional-values`
turns a literal value here into a constant column before anything
else reads the mapping. True of the three the stat and the extract
read; the band bounds are read straight from the mapping by their
own marks instead, so normalizing them would take the value away
from the only code that wants it.
`:scale-default` says what a value means once the aesthetic accepts
one, so `:fill` carries `:by-source` while `:value?` is still false.
Setting `:value?` before the reading exists would make a value pass
every check and then draw nothing, which is the defect this table is
here to prevent.
One pair records a reading that depends on the layer rather than on
the value, which is a wart the table makes visible rather than
hides: `:y-min` / `:y-max` are a column on `:errorbar` and a value
on `:band-h`. `:text` is not such a pair -- a written label
broadcasts over the layer's rows whether or not the layer has
data.What each aesthetic's scale accepts, one entry per aesthetic that has a scale, in display order.
Each entry carries :aesthetic, the :types it can be read
through, and the spec :keys it reads beside :type and :domain,
which belong to every scale. Both are ordered vectors.
Derived from channel-scale-types and channel-scale-options so
that documentation cannot drift from what the validators enforce.
What each aesthetic's scale accepts, one entry per aesthetic that has a scale, in display order. Each entry carries `:aesthetic`, the `:types` it can be read through, and the spec `:keys` it reads beside `:type` and `:domain`, which belong to every scale. Both are ordered vectors. Derived from `channel-scale-types` and `channel-scale-options` so that documentation cannot drift from what the validators enforce.
(aesthetics-where pred)The aesthetics whose registry entry satisfies pred, in a stable
order. Every per-aesthetic set in the library comes from here.
The aesthetics whose registry entry satisfies `pred`, in a stable order. Every per-aesthetic set in the library comes from here.
(c2d->rgba color)Convert a clojure2d color (Vec4, 0-255 channels) to [r g b a] in 0-1 range.
Convert a clojure2d color (Vec4, 0-255 channels) to [r g b a] in 0-1 range.
Channel keyword to the key a draft layer holds its scale spec under.
Channel keyword to the key a draft layer holds its scale spec under.
What a continuous appearance channel spans when its scale names no
:range, in the quantity the mark draws it as: :size in drawing
units of radius, :alpha in opacity.
Stated here because the marks and the legend both need it and each held its own copy -- the same defect the shared mapper exists to prevent, one level up. The alpha range is ggplot2's.
What a continuous appearance channel spans when its scale names no `:range`, in the quantity the mark draws it as: `:size` in drawing units of radius, `:alpha` in opacity. Stated here because the marks and the legend both need it and each held its own copy -- the same defect the shared mapper exists to prevent, one level up. The alpha range is ggplot2's.
The scale-spec keys each channel reads, beside :type and
:domain, which every scale that has a type has.
A key a channel does not read is refused where it is written rather than dropped in silence.
:range and :values are the two shapes the output set takes.
:range is spanned between two ends: an interval of radii for
:size, an interval of opacities for :alpha, a gradient for the
two colour channels. :values is enumerated and assigned by index:
the marker symbols :shape draws, the colours a categorical
:color column is drawn in. :color reads both, because a colour
column may be of either type, and its type decides which is read;
:fill takes only numbers, so it reads :range alone. An axis
reads neither -- the panel decides what it spans.
:by asks how a value spreads across a range in the quantity the
mark draws it as, correcting for the way ink grows with that
quantity. An opacity has no shape and so no area to correct for,
which leaves the three methods one function: :size reads :by
and :alpha does not.
:from-zero asks a different question -- whether the drawn quantity
is proportional to the value -- and an opacity can answer it, since
zero opacity is absence the way zero area is. A colour cannot: the
low end of a gradient is a colour rather than an absence, so there
is no quantity there to be proportional to anything. :midpoint is
what the two colour channels anchor with instead. It names the value
the middle of the range is drawn at, which is what centres a
diverging gradient on zero rather than halfway along the data.
:breaks, :tick-labels, :n-ticks and :tick-spacing place and
word tick marks, so all four belong to the two channels drawn as an
axis. :n-ticks asks for about that many ticks and :tick-spacing
for about that much room each; a numeric axis reads whichever is
named, and a categorical one is ticked at its categories, which
:n-ticks thins.
:label titles what explains the scale to a reader: the axis for
:x and :y, the legend for the rest. Every channel with a scale
reads it. (:label is that title; :tick-labels is the text drawn
at the ticks of an axis.)
The scale-spec keys each channel reads, beside `:type` and `:domain`, which every scale that has a type has. A key a channel does not read is refused where it is written rather than dropped in silence. `:range` and `:values` are the two shapes the output set takes. `:range` is spanned between two ends: an interval of radii for `:size`, an interval of opacities for `:alpha`, a gradient for the two colour channels. `:values` is enumerated and assigned by index: the marker symbols `:shape` draws, the colours a categorical `:color` column is drawn in. `:color` reads both, because a colour column may be of either type, and its type decides which is read; `:fill` takes only numbers, so it reads `:range` alone. An axis reads neither -- the panel decides what it spans. `:by` asks how a value spreads across a range in the quantity the mark draws it as, correcting for the way ink grows with that quantity. An opacity has no shape and so no area to correct for, which leaves the three methods one function: `:size` reads `:by` and `:alpha` does not. `:from-zero` asks a different question -- whether the drawn quantity is proportional to the value -- and an opacity can answer it, since zero opacity is absence the way zero area is. A colour cannot: the low end of a gradient is a colour rather than an absence, so there is no quantity there to be proportional to anything. `:midpoint` is what the two colour channels anchor with instead. It names the value the middle of the range is drawn at, which is what centres a diverging gradient on zero rather than halfway along the data. `:breaks`, `:tick-labels`, `:n-ticks` and `:tick-spacing` place and word tick marks, so all four belong to the two channels drawn as an axis. `:n-ticks` asks for about that many ticks and `:tick-spacing` for about that much room each; a numeric axis reads whichever is named, and a categorical one is ticked at its categories, which `:n-ticks` thins. `:label` titles what explains the scale to a reader: the axis for `:x` and `:y`, the legend for the rest. Every channel with a scale reads it. (`:label` is that title; `:tick-labels` is the text drawn at the ticks of an axis.)
The scale types each channel accepts.
:categorical places a value by which category it is, which the two
channels drawn as an axis can do and :shape can only do. The
continuous visual channels have no categorical reading: a size or an
opacity is a magnitude, and a symbol is not.
The scale types each channel accepts. `:categorical` places a value by which category it is, which the two channels drawn as an axis can do and `:shape` can only do. The continuous visual channels have no categorical reading: a size or an opacity is a magnitude, and a symbol is not.
(color-for categories val)(color-for categories val palette)Look up the color for a categorical value from the palette. Returns [r g b a] in 0-1 range. palette can be: nil (default), a keyword (any clojure2d palette name), a vector of hex strings, or a map of {category-value color}.
Map lookup is tolerant of string/keyword mismatch: {:setosa "#F00"} matches both :setosa and "setosa" data values.
For keyword/vector palettes, the i-th category gets the i-th
palette entry (wrapping modulo the palette size). This preserves
the authorial ordering of designed-categorical palettes like
:set1, :dark2, :tableau-10. If you want a continuous color ramp
(viridis, inferno, etc.) for a numeric column, use the colour
scale's :range instead -- that's the canonical gradient path and
interpolates the full color range smoothly.
Look up the color for a categorical value from the palette.
Returns [r g b a] in 0-1 range.
palette can be: nil (default), a keyword (any clojure2d palette name),
a vector of hex strings, or a map of {category-value color}.
Map lookup is tolerant of string/keyword mismatch: {:setosa "#F00"}
matches both :setosa and "setosa" data values.
For keyword/vector palettes, the i-th category gets the i-th
palette entry (wrapping modulo the palette size). This preserves
the authorial ordering of designed-categorical palettes like
:set1, :dark2, :tableau-10. If you want a continuous color ramp
(viridis, inferno, etc.) for a numeric column, use the colour
scale's `:range` instead -- that's the canonical gradient path and
interpolates the full color range smoothly.Set of keywords that can reference dataset columns in mappings.
Set of keywords that can reference dataset columns in mappings.
Aesthetics that read a column and have no reading for a value.
Aesthetics that read a column and have no reading for a value.
(config)Return the effective resolved configuration as a map. Deep-merges: library defaults < plotje.edn < set-config! < config. Nested maps (e.g. :theme) are merged recursively. Useful for inspecting which values are in effect.
Return the effective resolved configuration as a map. Deep-merges: library defaults < plotje.edn < set-config! < *config*. Nested maps (e.g. :theme) are merged recursively. Useful for inspecting which values are in effect.
Documentation metadata for configuration keys. Each entry maps a key to [category description].
Documentation metadata for configuration keys. Each entry maps a key to [category description].
Aesthetics whose column must hold numbers, because what they encode
is a magnitude. :color is not among them: a categorical color
column is a palette, which is the reading these three lack.
Aesthetics whose column must hold numbers, because what they encode is a magnitude. `:color` is not among them: a categorical color column is a palette, which is the reading these three lack.
Default categorical palette name (clojure2d palette keyword).
Default categorical palette name (clojure2d palette keyword).
(default-scale-type aesthetic)The scale type an aesthetic falls back on when no scope named one.
Derived from channel-scale-types rather than listed again: an
aesthetic with no continuous reading is placed by category, and
every other one is linear.
A spec that names no type is not an opinion that the scale is linear, so the fallback is applied once, after every scope has accumulated, rather than where a scale is written.
The scale type an aesthetic falls back on when no scope named one. Derived from `channel-scale-types` rather than listed again: an aesthetic with no continuous reading is placed by category, and every other one is linear. A spec that names no type is not an opinion that the scale is linear, so the fallback is applied once, after every scope has accumulated, rather than where a scale is written.
In-code fallback for keys not present in the EDN resource. The EDN
file (resources/plotje-defaults.edn) is the canonical source;
this map is consulted only when the EDN load fails or as a secondary
lookup in (or cfg defaults) patterns in stat/layout code.
In-code fallback for keys not present in the EDN resource. The EDN file (`resources/plotje-defaults.edn`) is the canonical source; this map is consulted only when the EDN load fails or as a secondary lookup in `(or cfg defaults)` patterns in stat/layout code.
Diverging gradient function (RdBu). Takes t in [0,1], returns [r g b a] 0-1.
Diverging gradient function (RdBu). Takes t in [0,1], returns [r g b a] 0-1.
The scale-spec keys that describe how a value spreads across what a
mark draws it as. Only some channels read them; see
channel-scale-options.
The scale-spec keys that describe how a value spreads across what a mark draws it as. Only some channels read them; see `channel-scale-options`.
(fmt-category-label v)Format a category value (keyword, string, number, etc.) for display. Used for axis tick labels, legend entries, facet strip labels, and any other user-visible category text.
Formats by the same rule as fmt-name, so a keyword category reads as
words: :not-applicable becomes not applicable. Hyphenated keyword
categories are common and are nearly always meant as words, which is
what makes the rule worth applying to data as well as to names.
Two keyword categories differing only by separator -- :a-b and :a_b --
therefore format alike. On a categorical axis that combines them, since
impl/stat.clj maps the column through this function before grouping;
format-category-column there warns when it happens. Convert such a
column to strings to keep the values apart.
Format a category value (keyword, string, number, etc.) for display. Used for axis tick labels, legend entries, facet strip labels, and any other user-visible category text. Formats by the same rule as `fmt-name`, so a keyword category reads as words: :not-applicable becomes not applicable. Hyphenated keyword categories are common and are nearly always meant as words, which is what makes the rule worth applying to data as well as to names. Two keyword categories differing only by separator -- :a-b and :a_b -- therefore format alike. On a categorical axis that combines them, since `impl/stat.clj` maps the column through this function before grouping; `format-category-column` there warns when it happens. Convert such a column to strings to keep the values apart.
(fmt-legend-number v cfg)Format a legend's numeric value: an integral value loses its trailing
.0, and the digits are grouped per :thousands-separator, so a legend
reads the same way as the axis ticks beside it.
Here rather than beside the renderer because the layout has to measure the same string the renderer will draw. A size legend's entries carry a value and no label, so measuring the label read nothing and the column was sized as if the numbers were not there.
Format a legend's numeric value: an integral value loses its trailing .0, and the digits are grouped per `:thousands-separator`, so a legend reads the same way as the axis ticks beside it. Here rather than beside the renderer because the layout has to measure the same string the renderer will draw. A size legend's entries carry a value and no label, so measuring the label read nothing and the column was sized as if the numbers were not there.
(fmt-name k)Format a column name for display: :sepal-length becomes sepal length. Hyphens and underscores turn into spaces in a keyword or a symbol, neither of which can hold a space, so a separator in one stands in for a word break. A string is left as written -- a string can hold a space, so a hyphen in one was chosen rather than substituted, as in Cost-Benefit Ratio. Any other name -- a dataset built without column names gets integer ones -- formats as its printed form, so auto-labelling does not crash on it.
Format a column name for display: :sepal-length becomes sepal length. Hyphens and underscores turn into spaces in a keyword or a symbol, neither of which can hold a space, so a separator in one stands in for a word break. A string is left as written -- a string can hold a space, so a hyphen in one was chosen rather than substituted, as in Cost-Benefit Ratio. Any other name -- a dataset built without column names gets integer ones -- formats as its printed form, so auto-labelling does not crash on it.
(fmt-number s {:keys [thousands decimal]})Rewrite an already-formatted number string with a plot's separators:
:thousands between each group of three digits in the integer part,
:decimal in place of the point.
Every number reaching here was formatted under Locale/ROOT, so its
decimal point is always a . and the two separators can be chosen
independently: {:thousands "." :decimal ","} turns 1234.5 into
1.234,5. Either one absent leaves that part as it was, so the default
of neither leaves the string alone.
Returns s unchanged when it does not begin with digits, so a
category name passes through.
Rewrite an already-formatted number string with a plot's separators:
`:thousands` between each group of three digits in the integer part,
`:decimal` in place of the point.
Every number reaching here was formatted under `Locale/ROOT`, so its
decimal point is always a `.` and the two separators can be chosen
independently: `{:thousands "." :decimal ","}` turns 1234.5 into
1.234,5. Either one absent leaves that part as it was, so the default
of neither leaves the string alone.
Returns `s` unchanged when it does not begin with digits, so a
category name passes through.(fmt-root fmt v)format pinned to Locale/ROOT.
clojure.core/format reads the JVM's default locale, so a tick that
read 1.2 here read 1,2 on a German JVM -- and beside a grouped axis
the same comma then meant a decimal point on one axis and a thousands
separator on the other. render/svg.clj pinned its coordinates in
0.2.2 (PR #3); the label text is pinned for the same reason. Which
glyph a plot draws for the point is chosen with :decimal-separator,
not inherited from the machine.
`format` pinned to `Locale/ROOT`. `clojure.core/format` reads the JVM's default locale, so a tick that read 1.2 here read 1,2 on a German JVM -- and beside a grouped axis the same comma then meant a decimal point on one axis and a thousands separator on the other. `render/svg.clj` pinned its coordinates in 0.2.2 (PR #3); the label text is pinned for the same reason. Which glyph a plot draws for the point is chosen with `:decimal-separator`, not inherited from the machine.
(fmt-value-label v separators)Format a data value for display as text on a plot, writing a number
with the plot's separators. Non-numeric values format as
fmt-category-label does.
Format a data value for display as text on a plot, writing a number with the plot's `separators`. Non-numeric values format as `fmt-category-label` does.
Default gradient function (dark blue → light blue, matching ggplot2). Takes t in [0,1], returns [r g b a] 0-1.
Default gradient function (dark blue → light blue, matching ggplot2). Takes t in [0,1], returns [r g b a] 0-1.
(gradient-map? m)True of a map that describes a custom gradient -- one naming at least
one of :low, :mid and :high.
A gradient reaches resolve-gradient-fn as the :range of a colour
scale, which holds a gradient and nothing else. The check remains
because a map is also how a whole scale spec is written, and a spec
read as a gradient would resolve to three default stops: a plot
asking for a log colour scale would silently change its colours as
well as its spacing.
True of a map that describes a custom gradient -- one naming at least one of `:low`, `:mid` and `:high`. A gradient reaches `resolve-gradient-fn` as the `:range` of a colour scale, which holds a gradient and nothing else. The check remains because a map is also how a whole scale spec is written, and a spec read as a gradient would resolve to three default stops: a plot asking for a log colour scale would silently change its colours as well as its spacing.
Set of keywords that resolve to a continuous gradient rather than a
categorical palette. Users who pass one as a colour scale's
:values almost always meant its :range with a numeric color
column. plan/warn-palette-wrap! fires a warning when it sees one
of these among the values.
Set of keywords that resolve to a continuous gradient rather than a categorical palette. Users who pass one as a colour scale's `:values` almost always meant its `:range` with a numeric color column. `plan/warn-palette-wrap!` fires a warning when it sees one of these among the values.
(group-digits s separator)Insert separator between three-digit groups in the integer part of an
already-formatted number string: 462389 with a comma gives 462,389.
A leading sign, a fractional part, and any exponent are left alone.
The thousands half of fmt-number, for a caller that has only that
separator to hand.
Insert `separator` between three-digit groups in the integer part of an already-formatted number string: 462389 with a comma gives 462,389. A leading sign, a fractional part, and any exponent are left alone. The thousands half of `fmt-number`, for a caller that has only that separator to hand.
(hex->rgba color)Convert any color representation to [r g b a] in 0-1 range. Accepts hex strings (#RGB, #RRGGBB, #RRGGBBAA, or without #), named color strings ("red", "steelblue"), keywords (:red, :darkblue), or any value that clojure2d.color/to-color understands.
Converting is not deciding. names-a-color? answers the narrower
question of whether a value was meant as a color, and refuses the
bare hex this function accepts, because a three-letter string is a
mistyped column name more often than it is a shade.
Convert any color representation to [r g b a] in 0-1 range.
Accepts hex strings (#RGB, #RRGGBB, #RRGGBBAA, or without #),
named color strings ("red", "steelblue"), keywords (:red, :darkblue),
or any value that clojure2d.color/to-color understands.
Converting is not deciding. `names-a-color?` answers the narrower
question of whether a value was *meant* as a color, and refuses the
bare hex this function accepts, because a three-letter string is a
mistyped column name more often than it is a shade.Aesthetics that produce a legend at render time.
Aesthetics that produce a legend at render time.
Side length of the colored key drawn beside a legend entry (square).
Side length of the colored key drawn beside a legend entry (square).
The aesthetics whose literal value becomes a constant column in the
draft. A subset of positional-aesthetics -- see :literal->column?.
The aesthetics whose literal value becomes a constant column in the draft. A subset of `positional-aesthetics` -- see `:literal->column?`.
(names-a-color? v)True of a value that unmistakably names a color: a #-prefixed hex
string, or a CSS color name as a string or a keyword.
Deliberately narrower than what hex->rgba will convert, which also
reads a bare abc as the hex #aabbcc. That extra latitude is fine
once something has decided the value is a color, and wrong while
deciding: abc and fff are far likelier to be mistyped column
names than colors, and reading them as colors is exactly the silent
failure asking the vocabulary was meant to prevent.
True of a value that unmistakably names a color: a `#`-prefixed hex string, or a CSS color name as a string or a keyword. Deliberately narrower than what `hex->rgba` will convert, which also reads a bare `abc` as the hex `#aabbcc`. That extra latitude is fine once something has decided the value is a color, and wrong while deciding: `abc` and `fff` are far likelier to be mistyped column names than colors, and reading them as colors is exactly the silent failure asking the vocabulary was meant to prevent.
(normalize-continuous scale-type v vmin vmax midpoint)Remap a value v from [vmin, vmax] to [0,1] using a scale-type aware transform. :linear (default) uses normalize-midpoint with the optional midpoint. :log uses log10 endpoints; midpoint is ignored under :log.
The result is clamped to [0,1], which is the whole gradient. Every
caller reads it as a place along one, and the endpoints used to come
from the data itself, so nothing could fall outside. A :domain
narrower than the data can, and a value beyond it is drawn at the
nearer end of the gradient -- the same answer :size and :alpha
give a value outside their domain.
Remap a value v from [vmin, vmax] to [0,1] using a scale-type aware transform. :linear (default) uses normalize-midpoint with the optional midpoint. :log uses log10 endpoints; midpoint is ignored under :log. The result is clamped to [0,1], which is the whole gradient. Every caller reads it as a place along one, and the endpoints used to come from the data itself, so nothing could fall outside. A `:domain` narrower than the data can, and a value beyond it is drawn at the nearer end of the gradient -- the same answer `:size` and `:alpha` give a value outside their domain.
(normalize-midpoint v vmin vmax midpoint)Remap a value v from [vmin, vmax] to [0,1] with optional midpoint. Without midpoint: linear (v-vmin)/(vmax-vmin). With midpoint: values below midpoint → [0, 0.5], above → [0.5, 1.0].
Remap a value v from [vmin, vmax] to [0,1] with optional midpoint. Without midpoint: linear (v-vmin)/(vmax-vmin). With midpoint: values below midpoint → [0, 0.5], above → [0.5, 1.0].
(number-separators cfg)The two separators a plot writes its numbers with, read off a resolved
config as {:thousands ... :decimal ...}. Threaded as one value
rather than as two scalars, because it passes through six layers of
tick layout on its way to the formatter.
The two separators a plot writes its numbers with, read off a resolved
config as `{:thousands ... :decimal ...}`. Threaded as one value
rather than as two scalars, because it passes through six layers of
tick layout on its way to the formatter.Aesthetics whose column values are numeric -- subject to finite-value filtering. Derived from aesthetic-registry.
Aesthetics whose column values are numeric -- subject to finite-value filtering. Derived from aesthetic-registry.
Documentation for plot-level option keys. These are accepted by pj/options, pj/plan, and pj/plot but are inherently per-plot (text content or nested config override). Each entry maps a key to [category description].
Documentation for plot-level option keys. These are accepted by pj/options, pj/plan, and pj/plot but are inherently per-plot (text content or nested config override). Each entry maps a key to [category description].
The aesthetics that place a mark, and so may be given as a value.
Named for the glossary's sake: :position there is the dodge /
stack / fill adjustment, which these have nothing to do with.
The aesthetics that place a mark, and so may be given as a value. Named for the glossary's sake: `:position` there is the dodge / stack / fill adjustment, which these have nothing to do with.
(resolve-config plot-opts)Resolve config with plot options deep-merged on top of the precedence chain.
Plot options have the highest priority. Any key from config-key-docs
passed directly in plot-opts is forwarded to the resolved cfg. Nested
maps (:theme) are merged recursively. The :config key is a deep-merge
escape hatch for arbitrary overrides.
Resolve config with plot options deep-merged on top of the precedence chain. Plot options have the highest priority. Any key from `config-key-docs` passed directly in plot-opts is forwarded to the resolved cfg. Nested maps (:theme) are merged recursively. The `:config` key is a deep-merge escape hatch for arbitrary overrides.
(resolve-gradient-fn gradient)Resolve a colour scale's :range to a gradient function
t→[r g b a] (0-1 range).
nil or :sequential → dark blue to light blue (ggplot2 default).
:diverging → RdBu.
keyword → clojure2d gradient name (:inferno, :viridis/plasma, etc.).
map {:low hex :mid hex :high hex} → custom 3-stop gradient.
function → used directly.
Throws on an unrecognized keyword, and on a map naming none of the
three stops -- that map is a whole scale spec written where a
gradient belongs, and drawing it as three default stops would change
a plot's colours without saying so.
Resolve a colour scale's `:range` to a gradient function
t→[r g b a] (0-1 range).
nil or :sequential → dark blue to light blue (ggplot2 default).
:diverging → RdBu.
keyword → clojure2d gradient name (:inferno, :viridis/plasma, etc.).
map {:low hex :mid hex :high hex} → custom 3-stop gradient.
function → used directly.
Throws on an unrecognized keyword, and on a map naming none of the
three stops -- that map is a whole scale spec written where a
gradient belongs, and drawing it as three default stops would change
a plot's colours without saying so.(resolve-palette k)Resolve a keyword to a clojure2d palette, trying aliases. Returns a non-empty palette vector, falling back to the default palette.
Resolve a keyword to a clojure2d palette, trying aliases. Returns a non-empty palette vector, falling back to the default palette.
Display order for the aesthetics that have a scale: the two drawn as an axis first, then the appearance aesthetics. Aesthetics sharing a set of capabilities are adjacent, so a table can group them.
Display order for the aesthetics that have a scale: the two drawn as an axis first, then the appearance aesthetics. Aesthetics sharing a set of capabilities are adjacent, so a table can group them.
(scale-gradient-fn aesthetic spec cfg)The gradient function aesthetic reads a numeric column through.
One resolution, used by the marks and by the legend alike, so the
bar a reader matches a colour against is drawn from the same
function the marks were. Takes the :range the scale spec names,
and failing that the :color-range or :fill-range plot option.
The gradient function `aesthetic` reads a numeric column through. One resolution, used by the marks and by the legend alike, so the bar a reader matches a colour against is drawn from the same function the marks were. Takes the `:range` the scale spec names, and failing that the `:color-range` or `:fill-range` plot option.
(scale-option-key aesthetic k)The plot option that is the outer scope of scale spec key k on
aesthetic: the two names joined by a hyphen. :label on :x is
:x-label, :values on :color is :color-values, :midpoint on
:fill is :fill-midpoint.
Computed rather than listed, so an option and the spec key it is the outer scope of cannot drift apart, and so a new spec key gets its option spelling by being named.
The plot option that is the outer scope of scale spec key `k` on `aesthetic`: the two names joined by a hyphen. `:label` on `:x` is `:x-label`, `:values` on `:color` is `:color-values`, `:midpoint` on `:fill` is `:fill-midpoint`. Computed rather than listed, so an option and the spec key it is the outer scope of cannot drift apart, and so a new spec key gets its option spelling by being named.
(scale-setting aesthetic k spec options)The effective value of scale setting k for aesthetic: what the
scale spec says, and failing that what the plot option of the same
name says.
A setting belonging to one aesthetic is written in two places: in a
scale spec, and as the plot option scale-option-key names. The
spec is written further in, so it wins, and it wins by naming the
key at all -- a spec giving the key the value nil means nil, and
does not fall back to the option.
spec is the resolved scale spec, nil where none was written.
options is the map the plot option is looked up in: the resolved
configuration for a setting that has a configuration level, and a
pose's own options for one that is per-plot, such as a title.
The effective value of scale setting `k` for `aesthetic`: what the scale spec says, and failing that what the plot option of the same name says. A setting belonging to one aesthetic is written in two places: in a scale spec, and as the plot option `scale-option-key` names. The spec is written further in, so it wins, and it wins by naming the key at all -- a spec giving the key the value nil means nil, and does not fall back to the option. `spec` is the resolved scale spec, nil where none was written. `options` is the map the plot option is looked up in: the resolved configuration for a setting that has a configuration level, and a pose's own options for one that is per-plot, such as a title.
Display order for the per-aesthetic scale spec keys: the output set an aesthetic is drawn from, then how a value spreads across it and where it is anchored, then the keys that place and word tick marks, then the axis title.
Display order for the per-aesthetic scale spec keys: the output set an aesthetic is drawn from, then how a value spreads across it and where it is anchored, then the keys that place and word tick marks, then the axis title.
Display order for scale types: the continuous readings, then the categorical one.
Display order for scale types: the continuous readings, then the categorical one.
(set-config! m)Set global config overrides. Persists across calls until reset. (set-config! {:color-values :dark2 :theme {:bg "#FFFFFF"}}) (set-config! nil) — reset to defaults
Set global config overrides. Persists across calls until reset.
(set-config! {:color-values :dark2 :theme {:bg "#FFFFFF"}})
(set-config! nil) — reset to defaultsShape symbols assigned to categorical shape values, in assignment order. A plot with more categories than symbols reuses them from the start of the list, which makes two categories indistinguishable -- plan time warns before that happens.
Shape symbols assigned to categorical shape values, in assignment order. A plot with more categories than symbols reuses them from the start of the list, which makes two categories indistinguishable -- plan time warns before that happens.
Default theme: background color, grid color, and font size.
Default theme: background color, grid color, and font size.
(validate-config-keys! where m)Report configuration keys Plotje does not read, naming where they
were written. Warns, or throws under :strict.
pj/options has always refused a key it does not read, and the
configuration path did not. A key a release removed -- :palette,
:color-scale, :tick-spacing-x -- written in plotje.edn or
passed to set-config!, with-config or the :config option was
merged into the resolved configuration, read by nothing, and drew
the default without a word. Upgrading a project reverted its palette
in silence.
The key is left in the map rather than stripped: nothing reads it
either way, and the resolved configuration is what pj/config
reports, so removing entries there would hide what was written.
Returns m, so it can sit in a threading position.
Report configuration keys Plotje does not read, naming `where` they were written. Warns, or throws under `:strict`. `pj/options` has always refused a key it does not read, and the configuration path did not. A key a release removed -- `:palette`, `:color-scale`, `:tick-spacing-x` -- written in `plotje.edn` or passed to `set-config!`, `with-config` or the `:config` option was merged into the resolved configuration, read by nothing, and drew the default without a word. Upgrading a project reverted its palette in silence. The key is left in the map rather than stripped: nothing reads it either way, and the resolved configuration is what `pj/config` reports, so removing entries there would hide what was written. Returns `m`, so it can sit in a threading position.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |