Liking cljdoc? Tell your friends :D

scicloj.plotje.impl.pose

Pose substrate -- the recursive plain-map type that is the library's spec vocabulary. This namespace holds the pure tree operations (resolve, layout, shared-scale injection) and the leaf->draft emitter that feeds plan.clj.

Shape of a pose: {:data ? dataset (inherited from ancestor if absent) :mapping ? aesthetic mappings (merges with ancestors) :layers ? layers at this level (accumulate into leaves) :poses ? sub-poses; absence = leaf :layout ? {:direction :horizontal|:vertical :weights [pos-num ...]} :opts ? plot options (inheritable) :share-scales ? #{:x :y} for composites}

Pose substrate -- the recursive plain-map type that is the
library's spec vocabulary. This namespace holds the pure tree
operations (resolve, layout, shared-scale injection) and the
leaf->draft emitter that feeds plan.clj.

Shape of a pose:
  {:data         ?  dataset (inherited from ancestor if absent)
   :mapping      ?  aesthetic mappings (merges with ancestors)
   :layers       ?  layers at this level (accumulate into leaves)
   :poses       ?  sub-poses; absence = leaf
   :layout       ?  {:direction :horizontal|:vertical
                     :weights   [pos-num ...]}
   :opts         ?  plot options (inheritable)
   :share-scales ?  #{:x :y}  for composites}
raw docstring

check-explicit-mapping!clj

(check-explicit-mapping! k v)

Throw when an explicit mapping is malformed. Nothing here reads the layer's data, which is what lets api run it at the pj/pose or lay-* call rather than at pj/draft: a mistyped key inside the map is a mistake about the form, and the form is fully visible where it is written. The checks that need the data -- whether the column is there, whether the value is one the aesthetic can draw -- stay in validate-columns.

Called both from the call site and from normalize-explicit-mapping, so a pose built by hand and threaded straight to pj/draft is held to the same rules.

Throw when an explicit mapping is malformed. Nothing here reads the
layer's data, which is what lets `api` run it at the `pj/pose` or
`lay-*` call rather than at `pj/draft`: a mistyped key inside the
map is a mistake about the form, and the form is fully visible
where it is written. The checks that need the data -- whether the
column is there, whether the value is one the aesthetic can draw --
stay in `validate-columns`.

Called both from the call site and from
`normalize-explicit-mapping`, so a pose built by hand and threaded
straight to `pj/draft` is held to the same rules.
sourceraw docstring

combine-scalesclj

(combine-scales outer inner)

Combine an outer scale statement with an inner one.

Scale settings accumulate down the scope chain: where both name a spec the two merge key by key, so a pose that sets a range and a layer that names a type give a plot with both. The innermost wins per key.

true and false are not specs and do not merge. false says the value passes through no scale at all, so it replaces whatever was set above; true says it does pass through one without saying which, so it leaves an outer spec standing.

Combine an outer scale statement with an inner one.

Scale settings accumulate down the scope chain: where both name a
spec the two merge key by key, so a pose that sets a range and a
layer that names a type give a plot with both. The innermost wins
per key.

`true` and `false` are not specs and do not merge. `false` says the
value passes through no scale at all, so it replaces whatever was
set above; `true` says it does pass through one without saying
which, so it leaves an outer spec standing.
sourceraw docstring

composite?clj

(composite? f)

A composite pose has at least one sub-pose.

A composite pose has at least one sub-pose.
sourceraw docstring

compute-layoutclj

(compute-layout pose rect)
(compute-layout pose [x y w h] path)

Walk the pose tree and assign a pixel rectangle to each leaf. Returns a map of path -> [x y w h].

Composite :layout is {:direction :horizontal|:vertical|:matrix :weights [pos-num ...]}. Defaults: :direction :horizontal :weights (repeat n 1) (equal share)

Matrix layout (:direction :matrix) places leaves on a grid derived from their :x / :y mappings -- distinct x-cols become grid columns, distinct y-cols become grid rows, leaves land at their (x, y) intersection cell. Duplicate (x, y) pairs stack into new rows in DFS order. Empty cells get no entry. See matrix-axes for the full algorithm and the corresponding strip-label derivation. :weights are ignored under :matrix.

Rectangle arithmetic is in doubles; callers that need integer pixels should coerce at the render boundary (see pj/plot's width/height coercion).

Walk the pose tree and assign a pixel rectangle to each leaf.
Returns a map of path -> [x y w h].

Composite :layout is {:direction :horizontal|:vertical|:matrix
                      :weights   [pos-num ...]}. Defaults:
  :direction :horizontal
  :weights   (repeat n 1)  (equal share)

Matrix layout (`:direction :matrix`) places leaves on a grid
derived from their :x / :y mappings -- distinct x-cols become
grid columns, distinct y-cols become grid rows, leaves land at
their (x, y) intersection cell. Duplicate (x, y) pairs stack
into new rows in DFS order. Empty cells get no entry. See
`matrix-axes` for the full algorithm and the corresponding
strip-label derivation. :weights are ignored under :matrix.

Rectangle arithmetic is in doubles; callers that need integer
pixels should coerce at the render boundary (see pj/plot's
width/height coercion).
sourceraw docstring

default-series-labelclj

The name the key column a series invents takes when the writer does not give one. It titles the legend, so it is a word a reader can read there.

The name the key column a series invents takes when the writer does
not give one. It titles the legend, so it is a word a reader can read
there.
sourceraw docstring

explicit-mapping-keysclj

The keys an explicit mapping map may carry: one source, and optionally the scale to read it through.

The keys an explicit mapping map may carry: one source, and
optionally the scale to read it through.
sourceraw docstring

explicit-mapping?clj

(explicit-mapping? v)

True of a mapping value written in the explicit form -- a map naming its source, as {:column :species} or {:value "red" :scale true}, or naming only a scale, as pj/scale writes.

A map is unambiguous here because no aesthetic takes one as a value: a color is a string or a keyword, a size is a number, a shape is a symbol from a fixed list.

True of a mapping value written in the explicit form -- a map naming
its source, as `{:column :species}` or `{:value "red" :scale true}`,
or naming only a scale, as `pj/scale` writes.

A map is unambiguous here because no aesthetic takes one as a value:
a color is a string or a keyword, a size is a number, a shape is a
symbol from a fixed list.
sourceraw docstring

facet-label-separatorclj

What joins the parts of a compound facet label. A panel faceted by several columns is labelled by each column's value in turn, and this is what stands between them.

What joins the parts of a compound facet label. A panel faceted by
several columns is labelled by each column's value in turn, and this
is what stands between them.
sourceraw docstring

inject-shared-scalesclj

(inject-shared-scales pose)
(inject-shared-scales pose inherited-domains inherited-mapping inherited-data)

Walk a pose tree. For each composite with :share-scales, compute a union domain per (axis, effective-column) bucket across descendant leaves, and stamp those domains onto matching leaves' :opts as :x-scale-domain / :y-scale-domain. Returns a new tree.

:share-scales may live in (:opts pose) (the canonical location; set via pj/options or pj/arrange) or directly at the top of the pose (legacy location for hand-built composites). The :opts entry wins if both are present.

inherited-domains carries {axis {col-ref [lo hi]}} down the tree. inherited-mapping carries the ancestor-merged mapping so a leaf can resolve its effective axis column from (inherited + own + layer) when deciding which bucket to claim. inherited-data is the nearest-ancestor dataset, threaded through so a leaf can predict whether its layers' y axis is stat-driven (count/density) and skip the shared y-domain stamp on such leaves -- e.g., the diagonal histogram cells of a SPLOM.

Walk a pose tree. For each composite with :share-scales, compute a
union domain per (axis, effective-column) bucket across descendant
leaves, and stamp those domains onto matching leaves' :opts as
:x-scale-domain / :y-scale-domain. Returns a new tree.

:share-scales may live in `(:opts pose)` (the canonical location;
set via pj/options or pj/arrange) or directly at the top of the
pose (legacy location for hand-built composites). The :opts entry
wins if both are present.

`inherited-domains` carries `{axis {col-ref [lo hi]}}` down the
tree. `inherited-mapping` carries the ancestor-merged mapping so a
leaf can resolve its effective axis column from (inherited + own +
layer) when deciding which bucket to claim. `inherited-data` is
the nearest-ancestor dataset, threaded through so a leaf can
predict whether its layers' y axis is stat-driven (count/density)
and skip the shared y-domain stamp on such leaves -- e.g., the
diagonal histogram cells of a SPLOM.
sourceraw docstring

last-leaf-pathclj

(last-leaf-path pose)

Return the path vector of the last leaf visited in left-to-right depth-first order. Nil if the pose is itself a leaf with no path context (the caller is the root leaf).

Return the path vector of the last leaf visited in left-to-right
depth-first order. Nil if the pose is itself a leaf with no path
context (the caller is the root leaf).
sourceraw docstring

last-matching-leaf-pathclj

(last-matching-leaf-path pose position-mapping)

Walk pose in left-to-right DFS order. Return the :path of the last leaf whose effective :x and :y (after ancestor-merge of :mapping) match position-mapping. Matching is strict equality: :x and "x" are different column references. Returns nil if no leaf matches.

position-mapping may carry either or both of :x and :y; a nil value matches a leaf whose effective mapping has no entry for that axis. Matching is against resolved positional mappings only -- a bare leaf (no :x/:y) matches a bare position mapping.

What a mapping names decides the match, not how it is written: a position carrying a scale names the same position as the plain form, and a mapping that names only a scale names no position at all.

Walk `pose` in left-to-right DFS order. Return the `:path` of the
last leaf whose effective `:x` and `:y` (after ancestor-merge of
`:mapping`) match `position-mapping`. Matching is strict equality:
`:x` and `"x"` are different column references. Returns `nil` if
no leaf matches.

`position-mapping` may carry either or both of `:x` and `:y`; a
`nil` value matches a leaf whose effective mapping has no entry
for that axis. Matching is against resolved positional mappings
only -- a bare leaf (no `:x`/`:y`) matches a bare position
mapping.

What a mapping names decides the match, not how it is written: a
position carrying a scale names the same position as the plain
form, and a mapping that names only a scale names no position at
all.
sourceraw docstring

layer-overlays?clj

(layer-overlays? leaf layer)

Whether a layer joins the panel the leaf's own mapping names, rather than taking one of its own.

The layer's own :overlay answers first and the leaf's answers otherwise, which is the same precedence every mapping has: written nearer wins. Read here rather than where the layer was added, so that pj/overlay says the same thing wherever in a thread it is written.

Whether a layer joins the panel the leaf's own mapping names, rather
than taking one of its own.

The layer's own `:overlay` answers first and the leaf's answers
otherwise, which is the same precedence every mapping has: written
nearer wins. Read here rather than where the layer was added, so that
`pj/overlay` says the same thing wherever in a thread it is written.
sourceraw docstring

layer-panel-indicesclj

(layer-panel-indices leaf panel-keys)

The panels each layer of a leaf is drawn on, as a vector of index vectors aligned with (:layers leaf).

A layer that names a place is drawn on the panel for that place. A layer that overlays is drawn on the first panel, which is the one the leaf's own mapping names. A layer that names no place is drawn on every panel -- the rule that lets a bare lay-* added after a split annotate all of them.

The panels each layer of a leaf is drawn on, as a vector of index
vectors aligned with `(:layers leaf)`.

A layer that names a place is drawn on the panel for that place. A
layer that overlays is drawn on the first panel, which is the one the
leaf's own mapping names. A layer that names no place is drawn on
every panel -- the rule that lets a bare `lay-*` added after a split
annotate all of them.
sourceraw docstring

layer-position-keyclj

(layer-position-key leaf-mapping layer data)

The place a layer draws at, as [x-source y-source] -- what decides which panel it lands on. Nil where the layer names no place of its own, which is what makes it draw on every panel.

Whether the layer names a place is read from its own :mapping: a layer that names none is not choosing the leaf's, it is declining to choose, and the two answers place it differently. The place itself is read from the leaf's mapping merged with the layer's, so that a layer naming one axis draws at the same place as one naming both.

The place a layer draws at, as `[x-source y-source]` -- what decides
which panel it lands on. Nil where the layer names no place of its
own, which is what makes it draw on every panel.

Whether the layer names a place is read from its own `:mapping`: a
layer that names none is not choosing the leaf's, it is declining to
choose, and the two answers place it differently. The place itself is
read from the leaf's mapping merged with the layer's, so that a layer
naming one axis draws at the same place as one naming both.
sourceraw docstring

leaf->draftclj

(leaf->draft leaf)

Emit a draft vector from a leaf pose. A draft has one entry per applicable layer; each entry is a flat map carrying the merged aesthetic mapping (pose < layer-type-info < layer), the layer's :stat/:position/:mark as first-class siblings, each aesthetic's resolved scale spec under its own key, and plot-level :coord stamped from :opts. The scales come from the mapping, which is where pj/scale writes them; only :coord is still an option.

If the leaf's :opts carry :facet-col or :facet-row, the draft is multiplied over distinct facet values. Each variant carries a filtered :data plus :facet-col / :facet-row labels that plan.clj detects to build the facet grid.

The leaf's :opts is passed through to plan/draft->plan; in particular the compositor uses :suppress-legend on grid cells.

An empty :layers vector yields one {:mark :infer ...} placeholder so downstream inference can still choose a layer type from the data.

Data precedence: layer :data > leaf :data.

:__panel-idx is the panel a draft entry belongs to, which plan.clj groups by. A leaf draws one panel per place its layers name -- see leaf-panel-keys -- and faceting multiplies those, so the index is the facet variant crossed with the place. A layer that names no place is emitted once per panel, which is how a bare lay-* annotates all of them.

Emit a draft vector from a leaf pose. A draft has one entry per
applicable layer; each entry is a flat map carrying the merged
aesthetic mapping (pose < layer-type-info < layer), the layer's
:stat/:position/:mark as first-class siblings, each aesthetic's
resolved scale spec under its own key, and plot-level :coord
stamped from :opts. The scales come from the mapping, which is
where `pj/scale` writes them; only :coord is still an option.

If the leaf's :opts carry :facet-col or :facet-row, the draft is
multiplied over distinct facet values. Each variant carries a
filtered :data plus :facet-col / :facet-row labels that plan.clj
detects to build the facet grid.

The leaf's :opts is passed through to plan/draft->plan; in
particular the compositor uses :suppress-legend on grid cells.

An empty :layers vector yields one {:mark :infer ...} placeholder so
downstream inference can still choose a layer type from the data.

Data precedence: layer :data > leaf :data.

:__panel-idx is the panel a draft entry belongs to, which plan.clj
groups by. A leaf draws one panel per place its layers name -- see
`leaf-panel-keys` -- and faceting multiplies those, so the index is
the facet variant crossed with the place. A layer that names no place
is emitted once per panel, which is how a bare `lay-*` annotates all
of them.
sourceraw docstring

leaf-atclj

(leaf-at pose path)

Fetch the leaf at path in pose. Returns nil if the path does not land on a leaf.

Fetch the leaf at `path` in `pose`. Returns nil if the path does
not land on a leaf.
sourceraw docstring

leaf-panel-keysclj

(leaf-panel-keys leaf)

The places a leaf draws at, in the order its layers first name them. One entry per panel the leaf produces.

A layer that overlays, and a layer that names no position, name no panel of their own -- the first joins the panel the leaf's mapping names, and the second draws on all of them. Where no layer names a place, the leaf draws one panel, which is the leaf's own mapping.

The places a leaf draws at, in the order its layers first name them.
One entry per panel the leaf produces.

A layer that overlays, and a layer that names no position, name no
panel of their own -- the first joins the panel the leaf's mapping
names, and the second draws on all of them. Where no layer names a
place, the leaf draws one panel, which is the leaf's own mapping.
sourceraw docstring

leaf?clj

(leaf? f)

A leaf pose has no sub-poses. (An empty :poses vector also counts as leaf because it has nothing to tile.)

A leaf pose has no sub-poses. (An empty :poses vector also
counts as leaf because it has nothing to tile.)
sourceraw docstring

mapping-sourceclj

(mapping-source v)

What a mapping value names, with the full form unwrapped: the :column, the :value or the :from. A mapping that names only a scale names no source, and answers nil.

Identity is decided on this rather than on the written value, so that {:x {:from :a :scale ...}} and a plain {:x :a} are the same position -- which they are, since pj/scale produces the first from the second.

What a mapping value names, with the full form unwrapped: the
`:column`, the `:value` or the `:from`. A mapping that names only a
scale names no source, and answers nil.

Identity is decided on this rather than on the written value, so
that `{:x {:from :a :scale ...}}` and a plain `{:x :a}` are the same
position -- which they are, since `pj/scale` produces the first from
the second.
sourceraw docstring

matrix-axesclj

(matrix-axes composite)

For a composite whose layout is :matrix, walk its leaves in DFS order and compute the grid axes:

  • col-key per leaf: the leaf's :x mapping. Two leaves sharing (x, y) keep the same col-key.
  • row-key per leaf: the leaf's :y mapping, with a DFS-occurrence discriminator when (x, y) repeats. The first (a, b) gets row b; the second (a, b) gets row [b 1]; the third [b 2]; etc. Same column, new row in DFS order.
  • col-keys / row-keys: distinct keys in order of first appearance.
  • col-labels / row-labels: human-readable strings via defaults/fmt-name; nil when only one column or one row exists so we don't render a redundant strip header.

Univariate leaves (missing :x or :y) use the no-x-key / no-y-key sentinels so they get their own grid lane.

Returns {:col-keys [...] :row-keys [...] :col-labels [...|nil] :row-labels [...|nil] :positions {path -> [col-idx row-idx]} :x-vars [...] :y-vars [...]}.

The compositor consumes :positions for rect math and the labels for strip rendering; :x-vars / :y-vars surface in plan introspection.

For a composite whose layout is `:matrix`, walk its leaves in
DFS order and compute the grid axes:

- col-key per leaf: the leaf's :x mapping. Two leaves sharing
  (x, y) keep the same col-key.
- row-key per leaf: the leaf's :y mapping, with a DFS-occurrence
  discriminator when (x, y) repeats. The first (a, b) gets row
  b; the second (a, b) gets row [b 1]; the third [b 2]; etc.
  Same column, new row in DFS order.
- col-keys / row-keys: distinct keys in order of first appearance.
- col-labels / row-labels: human-readable strings via
  defaults/fmt-name; nil when only one column or one row exists
  so we don't render a redundant strip header.

Univariate leaves (missing :x or :y) use the no-x-key / no-y-key
sentinels so they get their own grid lane.

Returns {:col-keys [...] :row-keys [...]
         :col-labels [...|nil] :row-labels [...|nil]
         :positions {path -> [col-idx row-idx]}
         :x-vars [...] :y-vars [...]}.

The compositor consumes :positions for rect math and the labels
for strip rendering; :x-vars / :y-vars surface in plan introspection.
sourceraw docstring

merge-mappingsclj

(merge-mappings outer inner)

Merge an outer mapping into an inner one, the way pose mappings have always merged -- the inner value wins -- except for the scale, which accumulates. See merge-mapping-value.

Merge an outer mapping into an inner one, the way pose mappings have
always merged -- the inner value wins -- except for the scale, which
accumulates. See `merge-mapping-value`.
sourceraw docstring

overlay-labelsclj

(overlay-labels leaf)

What tells each overlaid layer apart, as a vector aligned with (:layers leaf), or nil where nothing does.

Layers that disagree about a column take a panel each, and the panels name the columns. Overlaid, they share a panel and nothing names them: the marks are drawn in one colour under an axis titled after whichever layer came first, which is a picture that shows less than the writer asked for and says nothing about it.

The label is the column a layer draws where the layers disagree. Answered nil where the writer has said how the marks are told apart -- any layer mapping :color -- and where nothing distinguishes them, which is the ordinary case of layers drawing one place.

What tells each overlaid layer apart, as a vector aligned with
`(:layers leaf)`, or nil where nothing does.

Layers that disagree about a column take a panel each, and the
panels name the columns. Overlaid, they share a panel and nothing
names them: the marks are drawn in one colour under an axis titled
after whichever layer came first, which is a picture that shows
less than the writer asked for and says nothing about it.

The label is the column a layer draws where the layers disagree.
Answered nil where the writer has said how the marks are told apart
-- any layer mapping `:color` -- and where nothing distinguishes
them, which is the ordinary case of layers drawing one place.
sourceraw docstring

path->update-in-pathclj

(path->update-in-path path)

Translate a leaf path like [0 1] into the get-in / update-in navigation [:poses 0 :poses 1]. A root path [] translates to [].

Translate a leaf path like [0 1] into the get-in / update-in navigation
[:poses 0 :poses 1]. A root path [] translates to [].
sourceraw docstring

pose?clj

(pose? x)

True if x looks pose-shaped: a map carrying :layers, :poses, or a map-valued :mapping. Permissive by design -- schema-level validation lives in impl.pose-schema.

A pose carrying only a mapping draws, a layer being inferred for it, and is completed later by api/with-data. Read as data instead -- which is what a map with none of these keys is -- it became a dataset whose columns were :mapping and :data, and drew that.

The :mapping value is tested rather than the key, because a dataset written as a map of columns may hold a column called :mapping. Its value is then the column, a sequence, and not a mapping.

True if x looks pose-shaped: a map carrying :layers, :poses, or a
map-valued :mapping. Permissive by design -- schema-level
validation lives in impl.pose-schema.

A pose carrying only a mapping draws, a layer being inferred for
it, and is completed later by `api/with-data`. Read as data instead
-- which is what a map with none of these keys is -- it became a
dataset whose columns were :mapping and :data, and drew that.

The :mapping value is tested rather than the key, because a dataset
written as a map of columns may hold a column called :mapping. Its
value is then the column, a sequence, and not a mapping.
sourceraw docstring

position-mapping-keyclj

(position-mapping-key m)

A mapping's place, as [x-source y-source], or nil where it names neither.

A mapping's place, as `[x-source y-source]`, or nil where it names
neither.
sourceraw docstring

put-scaleclj

(put-scale mapping aesthetic spec)

Write a scale spec into mapping for aesthetic -- what pj/scale does.

A scale lives with the mapping it reads, so this is an update of the mapping rather than of the pose's options. Where the aesthetic is mapped plainly there is no room for a scale, so the value is rewritten in the full form under :from, which says the same thing: ask the data. Where it is not mapped here at all, the scale is written on its own and applies to whatever source is named below.

A mapping cancelled with nil stays cancelled: an aesthetic that draws nothing has nothing to scale. A mapping that says :scale false on this same pose is refused rather than overridden: one pose cannot both draw a value as it stands and read it through a scale.

Write a scale spec into `mapping` for `aesthetic` -- what `pj/scale`
does.

A scale lives with the mapping it reads, so this is an update of the
mapping rather than of the pose's options. Where the aesthetic is
mapped plainly there is no room for a scale, so the value is
rewritten in the full form under `:from`, which says the same thing:
ask the data. Where it is not mapped here at all, the scale is
written on its own and applies to whatever source is named below.

A mapping cancelled with `nil` stays cancelled: an aesthetic that
draws nothing has nothing to scale. A mapping that says `:scale
false` on this same pose is refused rather than overridden: one pose
cannot both draw a value as it stands and read it through a scale.
sourceraw docstring

report-panel-aesthetic-on-layerclj

(report-panel-aesthetic-on-layer layer-mapping)

Report a panel aesthetic written on a layer.

:row and :col send a distinction to panels, and a facet multiplies the whole leaf rather than one layer of it, so a panel aesthetic on a layer names a division the draft cannot build. It is reported here rather than dropped, which is what a mapping key with no reading used to do.

Report a panel aesthetic written on a layer.

`:row` and `:col` send a distinction to panels, and a facet
multiplies the whole leaf rather than one layer of it, so a panel
aesthetic on a layer names a division the draft cannot build. It is
reported here rather than dropped, which is what a mapping key with
no reading used to do.
sourceraw docstring

report-panel-splitclj

(report-panel-split panel-keys data)

Say that a leaf drew more than one panel, and name the ways to ask for one instead.

The split is the library's answer to layers that disagree about what an axis holds, and it is the right answer for two unrelated measures. It used to happen in silence, so a writer who meant them to be read against one another saw a picture they had not asked for and no reason for it.

Said here rather than at the lay-* call, because here is where the split is decided: :overlay is read at draft time, so a note printed as a layer was added would state an outcome a later pj/overlay can still change. Every other warning in the library is emitted at this stage for the same reason.

Two routes, and the second is named only where following it draws. pj/overlay puts the layers on the panel the leaf's own mapping names and always applies. Several columns in one slot pivot them into series that can be dodged, piled or normalized against each other, which needs one dataset carrying both columns, one axis disagreeing -- a call takes one series, so a second disagreement would be left standing -- and no column the pivot would write over, which is what a pose already reading a series has.

Say that a leaf drew more than one panel, and name the ways to ask
for one instead.

The split is the library's answer to layers that disagree about what
an axis holds, and it is the right answer for two unrelated measures.
It used to happen in silence, so a writer who meant them to be read
against one another saw a picture they had not asked for and no
reason for it.

Said here rather than at the `lay-*` call, because here is where the
split is decided: `:overlay` is read at draft time, so a note printed
as a layer was added would state an outcome a later `pj/overlay` can
still change. Every other warning in the library is emitted at this
stage for the same reason.

Two routes, and the second is named only where following it draws.
`pj/overlay` puts the layers on the panel the leaf's own mapping
names and always applies. Several columns in one slot pivot them into
series that can be dodged, piled or normalized against each other,
which needs one dataset carrying both columns, one axis disagreeing
-- a call takes one series, so a second disagreement would be left
standing -- and no column the pivot would write over, which is what
a pose already reading a series has.
sourceraw docstring

report-unread-seriesclj

(report-unread-series leaf-mapping)

Report a series still standing in a leaf's mapping when it is drafted.

A series is pivoted when a layer is added to the pose that carries it -- that is the only place the pivot happens. A cell of a composite written as a mapping map, {:x :quarter :y [:revenue :cost]}, takes its layers from the pose it is arranged into, so no layer is ever added to the cell itself and its series reaches the plan unread, where it failed with a bare schema error naming nothing written. A pj/pose given a series and no layer at all failed the same way, with an index out of bounds.

Report a series still standing in a leaf's mapping when it is drafted.

A series is pivoted when a layer is added to the pose that carries
it -- that is the only place the pivot happens. A cell of a composite
written as a mapping map, `{:x :quarter :y [:revenue :cost]}`, takes
its layers from the pose it is arranged into, so no layer is ever
added to the cell itself and its series reaches the plan unread,
where it failed with a bare schema error naming nothing written. A
`pj/pose` given a series and no layer at all failed the same way,
with an index out of bounds.
sourceraw docstring

resolve-treeclj

(resolve-tree pose)
(resolve-tree pose parent-ctx path)

Walk the pose tree top-down, merging parent context into each descendant. Returns a vector of resolved leaves; each leaf carries merged :data, :mapping, :layers, :opts, and a :path vector of indices describing its position in the tree.

Context inheritance rules:

  • :data -- nearest ancestor wins (child overrides parent).
  • :mapping -- merged, with child keys overriding parent keys, and scale settings accumulating (see merge-mappings).
  • :layers -- concatenated (ancestor layers distribute down, then the leaf's own layers append).
  • :opts -- merged (child overrides on key collision).

Extra keys on a leaf (anything not in #{:data :mapping :layers :poses :layout :opts :share-scales}) pass through to the resolved leaf so callers can attach metadata like :path-labels from facet-style generators.

Walk the pose tree top-down, merging parent context into each
descendant. Returns a vector of resolved leaves; each leaf carries
merged :data, :mapping, :layers, :opts, and a :path vector of
indices describing its position in the tree.

Context inheritance rules:
- :data     -- nearest ancestor wins (child overrides parent).
- :mapping  -- merged, with child keys overriding parent keys, and
               scale settings accumulating (see `merge-mappings`).
- :layers   -- concatenated (ancestor layers distribute down, then
               the leaf's own layers append).
- :opts     -- merged (child overrides on key collision).

Extra keys on a leaf (anything not in
#{:data :mapping :layers :poses :layout :opts :share-scales})
pass through to the resolved leaf so callers can attach metadata
like :path-labels from facet-style generators.
sourceraw docstring

scale-only-mapping?clj

(scale-only-mapping? v)

True of a mapping value that names a scale and no source -- what pj/scale writes for an aesthetic this pose does not map. It says how to read whatever source is named elsewhere, and where none is, nothing is drawn and the scale is inert.

True of a mapping value that names a scale and no source -- what
`pj/scale` writes for an aesthetic this pose does not map. It says
how to read whatever source is named elsewhere, and where none is,
nothing is drawn and the scale is inert.
sourceraw docstring

series-clashesclj

(series-clashes cols label column-names)

The columns a series reading cols, with its key column named label, would write over in data whose columns are column-names, as {:key <label or nil> :value <value column or nil>}.

The pivot drops the columns it reads and writes the two it invents, so only the columns it leaves are at risk. One rule for both places that ask: api/pivot-series reports a clash, and report-panel-split offers a series only where there is none -- offering it where the pivot would then refuse sent a writer from one message straight into another.

The columns a series reading `cols`, with its key column named
`label`, would write over in data whose columns are `column-names`,
as `{:key <label or nil> :value <value column or nil>}`.

The pivot drops the columns it reads and writes the two it invents,
so only the columns it leaves are at risk. One rule for both places
that ask: `api/pivot-series` reports a clash, and
`report-panel-split` offers a series only where there is none --
offering it where the pivot would then refuse sent a writer from one
message straight into another.
sourceraw docstring

series-value-columnclj

The name the value column a series invents takes. It titles the value axis, which :x-label and :y-label already rename, so it needs no second spelling of its own.

The name the value column a series invents takes. It titles the
value axis, which `:x-label` and `:y-label` already rename, so it
needs no second spelling of its own.
sourceraw docstring

source-keysclj

The three ways an explicit mapping can name its source.

:column reads the value from the layer's data and :value is the value itself; :from is the plain reading spelled out -- ask the data, and take whichever answer it gives, exactly as a mapping written plainly does. :from is what lets a plain mapping carry a :scale, since a bare :size :weight has no room for one.

The three ways an explicit mapping can name its source.

`:column` reads the value from the layer's data and `:value` is the
value itself; `:from` is the plain reading spelled out -- ask the
data, and take whichever answer it gives, exactly as a mapping
written plainly does. `:from` is what lets a plain mapping carry a
`:scale`, since a bare `:size :weight` has no room for one.
sourceraw docstring

written-axis-valuesclj

(written-axis-values leaf axis)

The values the rules and bands among a leaf's layers write on axis, for the shared-domain union.

A shared axis is built from the columns its leaves name, and a rule writes its value on the layer rather than into a column, so without this the union never sees it: a rule at 99 on data reaching 6 gave a shared domain of [1.8 6.2] and drew the line thousands of drawing units below the panel, where the same rule on an unshared axis widened it to [-2.85 103.85]. Faceting and pj/marginal already reach the written value, so this is what makes the three composition paths answer alike.

A layer is still {:layer-type k :mapping m} here -- the mark and the written value only come together at draft time -- so this puts the two back together for resolve/written-values to read.

The values the rules and bands among a leaf's layers write on
`axis`, for the shared-domain union.

A shared axis is built from the columns its leaves name, and a rule
writes its value on the layer rather than into a column, so without
this the union never sees it: a rule at 99 on data reaching 6 gave a
shared domain of [1.8 6.2] and drew the line thousands of drawing
units below the panel, where the same rule on an unshared axis
widened it to [-2.85 103.85]. Faceting and `pj/marginal` already
reach the written value, so this is what makes the three composition
paths answer alike.

A layer is still `{:layer-type k :mapping m}` here -- the mark and
the written value only come together at draft time -- so this puts
the two back together for `resolve/written-values` to read.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close