11 Glossary
Key terms used throughout Plotje, with brief definitions and code examples.
(ns plotje-book.glossary
(:require
;; Rdatasets -- standard datasets
[scicloj.metamorph.ml.rdatasets :as rdatasets]
;; Kindly -- notebook rendering protocol
[scicloj.kindly.v4.kind :as kind]
;; Plotje -- composable plotting
[scicloj.plotje.api :as pj]
;; clojure2d -- color palettes and gradients
[clojure2d.color :as c2d]))Pose
A pose is the composable value in Plotje. A leaf pose describes one plot panel; a composite pose contains other poses arranged together. Every pose-shaping function in the API (pj/pose, pj/lay-*, pj/facet, pj/arrange, pj/options, pj/scale, pj/coord) takes a pose and returns a pose. pj/->pose is the polymorphic lift – it accepts raw data or a pose and returns a pose, so any of the output functions can start from a dataset directly. Poses auto-render in Kindly-compatible tools like Clay.
(def my-pose
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width {:color :species})
(pj/options {:title "Iris"})))my-poseA pose is a plain Clojure value – printed, the same value reveals its underlying map shape with :data, :mapping, :layers, and :opts:
(kind/pprint my-pose){:layers [{:layer-type :point, :mapping {:color :species}}],
:data
https://vincentarelbundock.github.io/Rdatasets/csv/datasets/iris.csv [150 6]:
| :rownames | :sepal-length | :sepal-width | :petal-length | :petal-width | :species |
|----------:|--------------:|-------------:|--------------:|-------------:|-----------|
| 1 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 2 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 3 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 6 | 5.4 | 3.9 | 1.7 | 0.4 | setosa |
| 7 | 4.6 | 3.4 | 1.4 | 0.3 | setosa |
| 8 | 5.0 | 3.4 | 1.5 | 0.2 | setosa |
| 9 | 4.4 | 2.9 | 1.4 | 0.2 | setosa |
| 10 | 4.9 | 3.1 | 1.5 | 0.1 | setosa |
| ... | ... | ... | ... | ... | ... |
| 140 | 6.9 | 3.1 | 5.4 | 2.1 | virginica |
| 141 | 6.7 | 3.1 | 5.6 | 2.4 | virginica |
| 142 | 6.9 | 3.1 | 5.1 | 2.3 | virginica |
| 143 | 5.8 | 2.7 | 5.1 | 1.9 | virginica |
| 144 | 6.8 | 3.2 | 5.9 | 2.3 | virginica |
| 145 | 6.7 | 3.3 | 5.7 | 2.5 | virginica |
| 146 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
| 147 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
| 148 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
| 149 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
| 150 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
,
:mapping {:x :sepal-length, :y :sepal-width},
:opts {:title "Iris"}}Leaf Pose
A leaf pose is a pose that describes a single plot panel. It carries :data, a :mapping from columns to aesthetics, and :layers – the chart-type layers attached to it. Created by pj/pose or pj/lay-*.
Composite Pose
A composite pose is a pose that contains other poses under :poses plus an optional :layout. Created by pj/arrange. Its leaves render independently and are tiled into the final plot.
Some features are not yet exposed through pj/arrange – unequal weights and nested composite cells. To use them, build the composite as a literal map; pj/pose accepts the literal form.
Arrange
pj/arrange builds a composite pose from a sequence of poses. Each input becomes one of the composite’s :poses; the composite tiles them via :layout. It accepts :cols, :title, :width, :height, and :share-scales. For features it does not yet expose – unequal weights and nested composite cells – pass a literal map to pj/pose.
Layer Type
A layer type is the bundle of mark + stat + position that determines how data becomes a visual element. It is a context-free recipe; placing it on a pose produces a layer (next entry). See the Layer Types chapter for detailed tables of all built-in layer types, marks, stats, and positions.
Layer
A layer is a layer type placed on a pose, optionally with scoped mappings. Created by pj/lay-*.
Layers attach to poses in three ways, depending on what you pass to pj/lay-*:
Bare –
pj/lay-*without columns attaches the layer using the current pose’s mapping (inherited frompj/poseor a priorpj/lay-*).Matching columns –
pj/lay-*with columns that match the most recent matching leaf reuses that leaf, so the new layer joins the existing panel.Non-matching columns –
pj/lay-*with columns that do not match any existing leaf creates a fresh leaf pose with the layer attached.
(-> my-pose :layers first :layer-type):pointMark
The mark is the visual shape shown for each data point or group. Several layer types may share the same mark – for instance, :line and :smooth both produce lines, and :area and :density both produce filled regions. See the Layer Types chapter for a table of all built-in marks.
Stat
A stat (statistical transform) processes raw data before rendering. Each stat takes data-space inputs and produces the geometry that its mark will show. See the Layer Types chapter for a table of all built-in stats.
Position
A position adjustment determines how overlapping marks are placed in coordinate space: kept at their data values (:identity), dodged side-by-side along a categorical band (:dodge), stacked end-to-end so bar tops sit on the previous bar’s top (:stack), or normalized to fill [0, 1] proportions (:fill). Position runs between stat computation and rendering. You can override the default position by passing :position in the layer options. When multiple layers share :position :dodge, they are coordinated together – error bars automatically align with bars. See the Layer Types chapter for a table of all built-in positions.
(def tips {:day ["Mon" "Mon" "Tue" "Tue"]
:count [30 20 45 15]
:meal ["lunch" "dinner" "lunch" "dinner"]})(-> tips
(pj/lay-value-bar :day :count {:color :meal :position :stack}))Draft
A draft is the record produced by pj/draft. For a leaf pose, it is a LeafDraft carrying :layers (a vector of flat maps, one per applicable layer with merged pose-and-layer scope) and :opts (the pose-level options that flow into the plan stage). For a composite pose, it is a CompositeDraft carrying per-leaf drafts plus chrome geometry. Draft layers carry all the information the plan stage needs: data, columns, mark, stat, color, grouping.
pj/draft is useful for inspecting exactly what the plan stage will consume before any domains, ticks, or coordinate math are computed.
Keys prefixed with double underscores (e.g. :__panel-idx) are internal markers used by later stages and follow the Clojure convention “do not consume.” Ignore them when reading a draft.
(-> my-pose pj/draft kind/pprint){:layers
[{:x :sepal-length,
:y :sepal-width,
:mark :point,
:stat :identity,
:layer-type :point,
:color :species,
:data
https://vincentarelbundock.github.io/Rdatasets/csv/datasets/iris.csv [150 6]:
| :rownames | :sepal-length | :sepal-width | :petal-length | :petal-width | :species |
|----------:|--------------:|-------------:|--------------:|-------------:|-----------|
| 1 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 2 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 3 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 6 | 5.4 | 3.9 | 1.7 | 0.4 | setosa |
| 7 | 4.6 | 3.4 | 1.4 | 0.3 | setosa |
| 8 | 5.0 | 3.4 | 1.5 | 0.2 | setosa |
| 9 | 4.4 | 2.9 | 1.4 | 0.2 | setosa |
| 10 | 4.9 | 3.1 | 1.5 | 0.1 | setosa |
| ... | ... | ... | ... | ... | ... |
| 140 | 6.9 | 3.1 | 5.4 | 2.1 | virginica |
| 141 | 6.7 | 3.1 | 5.6 | 2.4 | virginica |
| 142 | 6.9 | 3.1 | 5.1 | 2.3 | virginica |
| 143 | 5.8 | 2.7 | 5.1 | 1.9 | virginica |
| 144 | 6.8 | 3.2 | 5.9 | 2.3 | virginica |
| 145 | 6.7 | 3.3 | 5.7 | 2.5 | virginica |
| 146 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
| 147 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
| 148 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
| 149 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
| 150 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
,
:__panel-idx 0}],
:opts {:title "Iris"}}Draft Layer
A draft layer is one entry of a draft’s :layers vector – a single map that bundles the layer type, the merged mappings (pose + layer scopes), and the effective dataset for one (leaf, applicable-layer) pair. It is the specification of what the renderer will draw for that layer, before any geometry, domains, or ticks are computed. The plan layer (entry below) is the same idea after geometry has been resolved.
(-> my-pose pj/draft :layers first kind/pprint){:x :sepal-length,
:y :sepal-width,
:mark :point,
:stat :identity,
:layer-type :point,
:color :species,
:data
https://vincentarelbundock.github.io/Rdatasets/csv/datasets/iris.csv [150 6]:
| :rownames | :sepal-length | :sepal-width | :petal-length | :petal-width | :species |
|----------:|--------------:|-------------:|--------------:|-------------:|-----------|
| 1 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
| 2 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
| 3 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
| 4 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
| 5 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
| 6 | 5.4 | 3.9 | 1.7 | 0.4 | setosa |
| 7 | 4.6 | 3.4 | 1.4 | 0.3 | setosa |
| 8 | 5.0 | 3.4 | 1.5 | 0.2 | setosa |
| 9 | 4.4 | 2.9 | 1.4 | 0.2 | setosa |
| 10 | 4.9 | 3.1 | 1.5 | 0.1 | setosa |
| ... | ... | ... | ... | ... | ... |
| 140 | 6.9 | 3.1 | 5.4 | 2.1 | virginica |
| 141 | 6.7 | 3.1 | 5.6 | 2.4 | virginica |
| 142 | 6.9 | 3.1 | 5.1 | 2.3 | virginica |
| 143 | 5.8 | 2.7 | 5.1 | 1.9 | virginica |
| 144 | 6.8 | 3.2 | 5.9 | 2.3 | virginica |
| 145 | 6.7 | 3.3 | 5.7 | 2.5 | virginica |
| 146 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
| 147 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
| 148 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
| 149 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
| 150 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
,
:__panel-idx 0}Mapping
A mapping is a binding from a column (or literal value) to an aesthetic. Aesthetics come in two groups:
Positional aesthetics (
:x,:y, plus:x-end,:x-min,:x-max,:y-min,:y-maxfor marks that need them) place marks in coordinate space.Appearance aesthetics (
:color,:size,:alpha,:shape,:text,:fill) shape how each mark looks.
Mappings live on a pose – where they flow into every layer attached to it – or on a single layer, where they scope to that layer alone. Lower scope wins on conflict; an explicit nil cancels a mapping inherited from above.
Aesthetic
An aesthetic is a property of a mark that can be mapped to a data column or fixed to a literal value. Plotje supports two groups:
Positional aesthetics – where the mark sits:
| Key | Controls | Column type |
|---|---|---|
:x |
Horizontal position | Numerical, temporal, or categorical |
:y |
Vertical position | Numerical, temporal, or categorical |
:x-end, :x-min, :x-max |
Range endpoints (interval, band, rule marks) | Same type as :x |
:y-min, :y-max |
Range endpoints (band, ribbon) | Same type as :y |
Appearance aesthetics – how the mark looks:
| Key | Controls | Column type |
|---|---|---|
:color |
Fill/stroke color | Categorical or numerical |
:size |
Point radius | Numerical |
:alpha |
Opacity | Numerical |
:shape |
Point shape | Categorical |
:text |
Label content | Any |
:fill |
Tile gradient color | Numerical |
When a keyword is passed, it maps to a dataset column. A literal value (e.g., "#E74C3C", "red", 0.5) sets a fixed aesthetic for all points.
A single layer can mix all three: positional column refs (:x, :y), an appearance column ref (:color :species, :size :petal-length), and a literal appearance (:alpha 0.7, the same opacity for every point):
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width
{:color :species :size :petal-length :alpha 0.7}))Group
A group is a subset of data that is processed and rendered together. Mapping :color to a categorical column automatically creates groups – one per unique value. You can also create groups without color using the :group key.
(-> (rdatasets/datasets-iris)
(pj/lay-line :sepal-length :sepal-width {:group :species}))Nudge
A nudge shifts data coordinates by a constant offset. It is orthogonal to position – you can nudge within a dodge, or nudge at identity. Applied via :nudge-x and :nudge-y keys in the layer options.
(-> {:x [1 2 3] :y [4 5 6]}
(pj/lay-point :x :y {:nudge-x 0.5}))Jitter
Jitter adds random offsets in drawing units to reduce overplotting. Unlike position and nudge, jitter operates after scaling (not in data space) and is deterministic – seeded by a hash of the group’s color so repeated renders produce identical output.
On categorical x-axes, jitter is applied along the band axis only.
(merge (pj/layer-type-lookup :point) {:jitter true}){:mark :point,
:stat :identity,
:accepts [:size :shape :jitter :text :nudge-x :nudge-y],
:doc "Scatter — individual data points.",
:jitter true}Inference
Inference is the automatic selection of a layer type (mark + stat + position) when you bypass pj/lay-* and pass columns to pj/pose. Plotje picks a layer type based on column types: numerical x and y defaults to :point, categorical x with numerical y to :boxplot, a single numerical column to :histogram, and so on. Use :x-type / :y-type on a pose or layer to override the detected type.
(-> (rdatasets/datasets-iris)
(pj/pose :sepal-length :sepal-width)
pj/lay-point)Plan
A plan is the fully resolved intermediate representation – a plain Clojure map containing everything needed to render a plot: data-space geometry, domains, tick info, legend, layout dimensions. No membrane types, no datasets, no scale objects.
Created with pj/plan. Numeric arrays (:xs, :ys, etc.) are dtype-next buffers for efficiency – they print with their length and a small preview rather than every element.
(def my-plan (pj/plan my-pose))(kind/pprint my-plan){:panels
[{:coord :cartesian,
:y-domain [1.88 4.5200000000000005],
:x-scale {:type :linear},
:x-domain [4.12 8.08],
:x-ticks
{:values [4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0],
:labels ["4.5" "5.0" "5.5" "6.0" "6.5" "7.0" "7.5" "8.0"],
:categorical? false},
:col 0,
:layers
[{:mark :point,
:style {:opacity 0.75, :radius 3.0},
:size-scale nil,
:alpha-scale nil,
:groups
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[5.100, 4.900, 4.700, 4.600, 5.000, 5.400, 4.600, 5.000, 4.400, 4.900, 5.400, 4.800, 4.800, 4.300, 5.800, 5.700, 5.400, 5.100, 5.700, 5.100...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.500, 3.000, 3.200, 3.100, 3.600, 3.900, 3.400, 3.400, 2.900, 3.100, 3.700, 3.400, 3.000, 3.000, 4.000, 4.400, 3.900, 3.500, 3.800, 3.800...],
:label "setosa",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...]}
{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[7.000, 6.400, 6.900, 5.500, 6.500, 5.700, 6.300, 4.900, 6.600, 5.200, 5.000, 5.900, 6.000, 6.100, 5.600, 6.700, 5.600, 5.800, 6.200, 5.600...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.200, 3.200, 3.100, 2.300, 2.800, 2.800, 3.300, 2.400, 2.900, 2.700, 2.000, 3.000, 2.200, 2.900, 2.900, 3.100, 3.000, 2.700, 2.200, 2.500...],
:label "versicolor",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69...]}
{:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[6.300, 5.800, 7.100, 6.300, 6.500, 7.600, 4.900, 7.300, 6.700, 7.200, 6.500, 6.400, 6.800, 5.700, 5.800, 6.400, 6.500, 7.700, 7.700, 6.000...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.300, 2.700, 3.000, 2.900, 3.000, 3.000, 2.500, 2.900, 2.500, 3.600, 3.200, 2.700, 3.000, 2.500, 2.800, 3.200, 3.000, 3.800, 2.600, 2.200...],
:label "virginica",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119...]}],
:y-domain [2.0 4.4],
:x-domain [4.3 7.9]}],
:y-scale {:type :linear},
:y-ticks
{:values [2.0 2.5 3.0 3.5 4.0 4.5],
:labels ["2.0" "2.5" "3.0" "3.5" "4.0" "4.5"],
:categorical? false},
:row 0}],
:width 600,
:height 400,
:caption nil,
:total-width 600.0,
:legend-position :right,
:layout-type :single,
:layout
{:subtitle-pad 0,
:legend-w 102,
:caption-pad 0,
:y-label-pad 42.5,
:legend-h 0.0,
:title-pad 33,
:strip-h 0,
:x-label-pad 38,
:strip-w 0.0},
:grid {:rows 1, :cols 1},
:legend
{:title :species,
:entries
[{:label "setosa",
:color
[0.8941176470588236 0.10196078431372549 0.10980392156862745 1.0]}
{:label "versicolor",
:color
[0.21568627450980393 0.49411764705882355 0.7215686274509804 1.0]}
{:label "virginica",
:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0]}]},
:panel-height 329.0,
:title "Iris",
:y-label "sepal width",
:alpha-legend nil,
:x-label "sepal length",
:subtitle nil,
:panel-width 455.5,
:size-legend nil,
:total-height 400.0,
:tooltip nil,
:margin 10}Panel
A panel is a single plotting area within a plan. It contains x/y domains, scale specs, tick info, coordinate type, and layers. A simple plot has one panel; pj/facet and pj/facet-grid produce multiple.
(kind/pprint (first (:panels my-plan))){:coord :cartesian,
:y-domain [1.88 4.5200000000000005],
:x-scale {:type :linear},
:x-domain [4.12 8.08],
:x-ticks
{:values [4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0],
:labels ["4.5" "5.0" "5.5" "6.0" "6.5" "7.0" "7.5" "8.0"],
:categorical? false},
:col 0,
:layers
[{:mark :point,
:style {:opacity 0.75, :radius 3.0},
:size-scale nil,
:alpha-scale nil,
:groups
[{:color
[0.8941176470588236 0.10196078431372549 0.10980392156862745 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[5.100, 4.900, 4.700, 4.600, 5.000, 5.400, 4.600, 5.000, 4.400, 4.900, 5.400, 4.800, 4.800, 4.300, 5.800, 5.700, 5.400, 5.100, 5.700, 5.100...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.500, 3.000, 3.200, 3.100, 3.600, 3.900, 3.400, 3.400, 2.900, 3.100, 3.700, 3.400, 3.000, 3.000, 4.000, 4.400, 3.900, 3.500, 3.800, 3.800...],
:label "setosa",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...]}
{:color
[0.21568627450980393 0.49411764705882355 0.7215686274509804 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[7.000, 6.400, 6.900, 5.500, 6.500, 5.700, 6.300, 4.900, 6.600, 5.200, 5.000, 5.900, 6.000, 6.100, 5.600, 6.700, 5.600, 5.800, 6.200, 5.600...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.200, 3.200, 3.100, 2.300, 2.800, 2.800, 3.300, 2.400, 2.900, 2.700, 2.000, 3.000, 2.200, 2.900, 2.900, 3.100, 3.000, 2.700, 2.200, 2.500...],
:label "versicolor",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69...]}
{:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[6.300, 5.800, 7.100, 6.300, 6.500, 7.600, 4.900, 7.300, 6.700, 7.200, 6.500, 6.400, 6.800, 5.700, 5.800, 6.400, 6.500, 7.700, 7.700, 6.000...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.300, 2.700, 3.000, 2.900, 3.000, 3.000, 2.500, 2.900, 2.500, 3.600, 3.200, 2.700, 3.000, 2.500, 2.800, 3.200, 3.000, 3.800, 2.600, 2.200...],
:label "virginica",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119...]}],
:y-domain [2.0 4.4],
:x-domain [4.3 7.9]}],
:y-scale {:type :linear},
:y-ticks
{:values [2.0 2.5 3.0 3.5 4.0 4.5],
:labels ["2.0" "2.5" "3.0" "3.5" "4.0" "4.5"],
:categorical? false},
:row 0}Plan Layer
A plan layer is the resolved descriptor inside a plan panel: resolved mark type, style, and groups of data-space geometry. The user-level layer becomes the plan layer through pj/plan.
(kind/pprint (get-in my-plan [:panels 0 :layers 0])){:mark :point,
:style {:opacity 0.75, :radius 3.0},
:size-scale nil,
:alpha-scale nil,
:groups
[{:color
[0.8941176470588236 0.10196078431372549 0.10980392156862745 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[5.100, 4.900, 4.700, 4.600, 5.000, 5.400, 4.600, 5.000, 4.400, 4.900, 5.400, 4.800, 4.800, 4.300, 5.800, 5.700, 5.400, 5.100, 5.700, 5.100...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.500, 3.000, 3.200, 3.100, 3.600, 3.900, 3.400, 3.400, 2.900, 3.100, 3.700, 3.400, 3.000, 3.000, 4.000, 4.400, 3.900, 3.500, 3.800, 3.800...],
:label "setosa",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...]}
{:color
[0.21568627450980393 0.49411764705882355 0.7215686274509804 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[7.000, 6.400, 6.900, 5.500, 6.500, 5.700, 6.300, 4.900, 6.600, 5.200, 5.000, 5.900, 6.000, 6.100, 5.600, 6.700, 5.600, 5.800, 6.200, 5.600...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.200, 3.200, 3.100, 2.300, 2.800, 2.800, 3.300, 2.400, 2.900, 2.700, 2.000, 3.000, 2.200, 2.900, 2.900, 3.100, 3.000, 2.700, 2.200, 2.500...],
:label "versicolor",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69...]}
{:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0],
:xs #tech.v3.dataset.column<float64>[50]
:sepal-length
[6.300, 5.800, 7.100, 6.300, 6.500, 7.600, 4.900, 7.300, 6.700, 7.200, 6.500, 6.400, 6.800, 5.700, 5.800, 6.400, 6.500, 7.700, 7.700, 6.000...],
:ys #tech.v3.dataset.column<float64>[50]
:sepal-width
[3.300, 2.700, 3.000, 2.900, 3.000, 3.000, 2.500, 2.900, 2.500, 3.600, 3.200, 2.700, 3.000, 2.500, 2.800, 3.200, 3.000, 3.800, 2.600, 2.200...],
:label "virginica",
:row-indices #tech.v3.dataset.column<int64>[50]
:__row-idx
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119...]}],
:y-domain [2.0 4.4],
:x-domain [4.3 7.9]}Dataset
A dataset is the tabular data backing a plot. Plotje uses tech.ml.dataset datasets internally – column-oriented, dtype-next-backed tables. The most ergonomic way to create and manipulate them is the Tablecloth API, which is a Clojure-idiomatic wrapper over tech.ml.dataset.
Raw input (a map of {column-name [values]}, a sequence of row-maps, or a CSV/URL string) is coerced via tablecloth.api/dataset at construction time. The dataset lives on a pose under :data; layers can override with their own :data, and inside a composite each pose in :poses can carry its own :data too.
Pipeline
The pipeline is the five-stage flow from user code to rendered output: pose -> draft -> plan -> membrane -> plot. A pose is what you compose; pj/draft flattens it into a draft (a LeafDraft or CompositeDraft record); pj/plan resolves geometry and layout; the membrane stage turns the plan into drawable primitives; the plot is the terminal SVG hiccup or PNG output. See the Architecture chapter for the per-stage details.
Sub-plot
A sub-plot is one resolved entry of a composite pose’s :poses, in the plan. Where a leaf pose’s plan carries :panels (one per faceted variant), a composite pose’s plan carries :sub-plots (one per inner pose), each with its own nested :plan map. The compositor reads :sub-plots and tiles their rendered membranes into the final canvas.
Resolve Tree
The resolve tree is the scope-merge walk that propagates a root pose’s :mapping, :opts, and root-attached :layers downward into every descendant leaf during plan construction. Lower (narrower) scopes override higher ones; root-attached layers reach every applicable leaf in the tree.
Domain
A domain is the range of data values along an axis.
Numerical:
[min max], wheremin/maxare the raw data extent extended by 5% on each side so points do not sit on the panel edge. Formy-poseabove, sepal-length runs from4.3to7.9in the data; the x-domain becomes[4.12 8.08].Temporal: same
[min max]form, but the values are epoch-milliseconds (Plotje convertsLocalDate,LocalDateTime,Instant, andjava.util.Dateautomatically). Tick labels stay calendar-aware.Categorical: a vector of distinct values in the order they first appear in the data, not alphabetical (e.g., iris gives
["setosa" "versicolor" "virginica"]).
Each panel carries its own :x-domain and :y-domain. With :scales :shared faceting, all panels share one domain pair; with :scales :free (or :free-x/:free-y), each panel computes its own.
(let [p (first (:panels my-plan))]
{:x-domain (:x-domain p)
:y-domain (:y-domain p)}){:x-domain [4.12 8.08], :y-domain [1.88 4.5200000000000005]}Tick
A tick is an axis mark with a label at a domain value. Ticks are chosen at layout time to fit the axis length in drawing units – label widths, minimum spacing, and calendar boundaries (for temporal axes) all feed into the selection. Each panel in the plan carries its own :x-ticks and :y-ticks maps with parallel :values and :labels vectors.
(-> my-plan :panels first :x-ticks){:values [4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0],
:labels ["4.5" "5.0" "5.5" "6.0" "6.5" "7.0" "7.5" "8.0"],
:categorical? false}Scale
A scale maps data values to positions in drawing units. Built from a domain and an output range using wadogo.
| Type | Use |
|---|---|
:linear |
Numerical data (default) |
:log |
Orders-of-magnitude data |
:categorical |
Distinct categories (band scale) |
Scales are created at render time, not stored in the plan. The plan stores scale specs (:type, :domain).
Temporal columns (LocalDate, LocalDateTime, Instant, java.util.Date) are automatically detected and treated as numerical. Tick labels are calendar-aware – snapped to year, month, day, or hour boundaries depending on the time span.
Coord
A coord (coordinate system) defines how data-space maps to drawing units.
| Type | Behavior |
|---|---|
:cartesian |
Standard: x rightward, y upward |
:flip |
Swap x and y axes |
:polar |
Radial: x as angle, y as radius |
:fixed |
Equal aspect ratio: 1 data unit = 1 data unit |
(-> (rdatasets/datasets-iris)
(pj/lay-bar :species)
(pj/coord :flip))Facet
A facet splits data into multiple panels by a categorical column. Each panel shows a subset of the data.
pj/facetcreates a row or column of panelspj/facet-gridcreates a row-by-column grid from two columns
By default all panels share the same x and y domains, derived from the full dataset (:scales :shared). To let each panel use its own data range, set {:scales :free} (or :free-x/:free-y) in pj/options.
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width)
(pj/facet :species))Annotation
An annotation is a reference mark layered on a plot – horizontal/vertical lines (rules) or shaded bands. Today, positions live in the layer’s :mapping slot (:y-intercept or :x-intercept for rules; :y-min/:y-max or :x-min/:x-max for bands) as literal values rather than column references, and a single annotation draws at exactly one place. Data-driven annotations (column refs in those slots, producing one mark per row, like ggplot2’s geom_hline(aes(yintercept = ...))) are planned but not yet implemented.
Annotations are regular layers, so they attach under the same three cases as any lay-*: bare call sits on the pose, matching columns join the most recent matching leaf, non-matching columns create a new leaf.
| Constructor | What |
|---|---|
pj/lay-rule-v |
Vertical line at x = x-intercept |
pj/lay-rule-h |
Horizontal line at y = y-intercept |
pj/lay-band-v |
Vertical shaded region from x = x-min to x = x-max |
pj/lay-band-h |
Horizontal shaded region from y = y-min to y = y-max |
(def annotated
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width)
(pj/lay-rule-h {:y-intercept 3.0})))annotated(kind/pprint (nth (:layers annotated) 1)){:layer-type :rule-h, :mapping {:y-intercept 3.0}}Legend
A legend is generated automatically when a color (or shape) aesthetic maps to a data column. It appears in the plan as a :legend key containing entries with labels and colors. Position is controlled via {:legend-position :bottom} in options.
(kind/pprint (:legend my-plan)){:title :species,
:entries
[{:label "setosa",
:color
[0.8941176470588236 0.10196078431372549 0.10980392156862745 1.0]}
{:label "versicolor",
:color
[0.21568627450980393 0.49411764705882355 0.7215686274509804 1.0]}
{:label "virginica",
:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0]}]}Theme
A theme controls the visual appearance of non-data elements. It is a nested map under :theme with three keys:
| Key | Controls |
|---|---|
:bg |
Panel background color |
:grid |
Gridline color |
:font-size |
Base font size in pixels |
Passed as {:theme {...}} via pj/options, pj/with-config, or pj/set-config!. Other visual settings (margins, legend width, tick spacing) are top-level configuration keys, not theme entries – see pj/config-key-docs.
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width {:color :species})
(pj/options {:theme {:bg "#2d2d2d" :grid "#444444" :font-size 10}}))Membrane
A membrane is a PlotjeMembrane – a record carrying a tree of layout and drawing primitives (Translate, WithColor, RoundedRectangle, Label, etc.) sized to a complete plot canvas. The record itself implements the Membrane library’s UI protocols (IOrigin, IBounds, IChildren), so it composes with other Membrane elements and any Membrane consumer can use it without special-casing.
Plotje produces a membrane via pj/plan->membrane (single-step transition from a plan) or pj/membrane (composition shortcut from a pose). The record carries :width and :height as fields (read via (membrane.ui/width m)/(membrane.ui/height m)), and the title as :plotje/title. Direct renderers (e.g., Plotly) skip the membrane entirely. The Membranes chapter walks the stage in depth.
(def my-membrane (pj/plan->membrane my-plan))A complete membrane is large – one drawable per data point on top of axes, gridlines, ticks, and labels. The record’s children (the underlying drawable tree) for my-plan:
(kind/pprint my-membrane){:drawables
[{:x 270.25,
:y 14,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "Iris",
:font {:name nil, :size 15, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 12,
:y 197.5,
:drawable
{:degrees -90,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "sepal width",
:font
{:name nil, :size 13, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}}
{:x 270.25,
:y 382.0,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "sepal length",
:font {:name nil, :size 13, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 508.0,
:y 35,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "species",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil}})}}
{:x 508.0,
:y 53,
:drawable
[{:x 0,
:y 0,
:drawable
{:color
[0.8941176470588236 0.10196078431372549 0.10980392156862745 1.0],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 8, :height 8, :border-radius 4.0}]})}}
{:x 12,
:y 0,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "setosa",
:font
{:name nil,
:size 10,
:weight nil,
:width nil,
:slant nil}})}}]}
{:x 508.0,
:y 69,
:drawable
[{:x 0,
:y 0,
:drawable
{:color
[0.21568627450980393 0.49411764705882355 0.7215686274509804 1.0],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 8, :height 8, :border-radius 4.0}]})}}
{:x 12,
:y 0,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "versicolor",
:font
{:name nil,
:size 10,
:weight nil,
:width nil,
:slant nil}})}}]}
{:x 508.0,
:y 85,
:drawable
[{:x 0,
:y 0,
:drawable
{:color
[0.30196078431372547 0.6862745098039216 0.2901960784313726 1.0],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 8, :height 8, :border-radius 4.0}]})}}
{:x 12,
:y 0,
:drawable
{:color [0.2 0.2 0.2 1.0],
:drawables
({:text "virginica",
:font
{:name nil,
:size 10,
:weight nil,
:width nil,
:slant nil}})}}]}
{:x 52.5,
:y 43.0,
:drawable
{:color
[0.9098039215686274 0.9098039215686274 0.9098039215686274 1.0],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 435.5, :height 309.0}]})}}
{:x 42.5,
:y 33.0,
:drawable
[{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([51.790404040404034 10] [51.790404040404034 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([106.77777777777777 10] [106.77777777777777 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([161.7651515151515 10] [161.7651515151515 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([216.75252525252526 10] [216.75252525252526 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([271.73989898989896 10] [271.73989898989896 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([326.72727272727275 10] [326.72727272727275 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([381.7146464646464 10] [381.7146464646464 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([436.7020202020202 10] [436.7020202020202 319.0])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 304.95454545454544] [445.5 304.95454545454544])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 246.4318181818182] [445.5 246.4318181818182])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 187.90909090909093] [445.5 187.90909090909093])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 129.38636363636365] [445.5 129.38636363636365])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 70.8636363636364] [445.5 70.8636363636364])}]}]})}
{:color
[0.9607843137254902 0.9607843137254902 0.9607843137254902 1.0],
:drawables
({:stroke-width 0.6,
:drawables
[{:style :membrane.ui/style-stroke,
:drawables
[{:points
([10 12.340909090909179] [445.5 12.340909090909179])}]}]})}
{:x 114.77525252525247,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 0}
{:x 92.78030303030306,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 1}
{:x 70.78535353535355,
:y 161.5,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 2}
{:x 59.78787878787873,
:y 173.20454545454547,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 3}
{:x 103.77777777777777,
:y 114.68181818181819,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 4}
{:x 147.76767676767682,
:y 79.56818181818187,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 5}
{:x 59.78787878787873,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 6}
{:x 103.77777777777777,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 7}
{:x 37.79292929292932,
:y 196.61363636363637,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 8}
{:x 92.78030303030306,
:y 173.20454545454547,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 9}
{:x 147.76767676767682,
:y 102.97727272727275,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 10}
{:x 81.78282828282826,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 11}
{:x 81.78282828282826,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 12}
{:x 26.795454545454515,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 13}
{:x 191.75757575757575,
:y 67.8636363636364,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 14}
{:x 180.760101010101,
:y 21.04545454545456,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 15}
{:x 147.76767676767682,
:y 79.56818181818187,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 16}
{:x 114.77525252525247,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 17}
{:x 180.760101010101,
:y 91.27272727272734,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 18}
{:x 114.77525252525247,
:y 91.27272727272734,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 19}
{:x 147.76767676767682,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 20}
{:x 114.77525252525247,
:y 102.97727272727275,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 21}
{:x 59.78787878787873,
:y 114.68181818181819,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 22}
{:x 114.77525252525247,
:y 149.7954545454546,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 23}
{:x 81.78282828282826,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 24}
{:x 103.77777777777777,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 25}
{:x 103.77777777777777,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 26}
{:x 125.77272727272731,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 27}
{:x 125.77272727272731,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 28}
{:x 70.78535353535355,
:y 161.5,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 29}
{:x 81.78282828282826,
:y 173.20454545454547,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 30}
{:x 147.76767676767682,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 31}
{:x 125.77272727272731,
:y 56.15909090909099,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 32}
{:x 158.7651515151515,
:y 44.454545454545496,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 33}
{:x 92.78030303030306,
:y 173.20454545454547,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 34}
{:x 103.77777777777777,
:y 161.5,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 35}
{:x 158.7651515151515,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 36}
{:x 92.78030303030306,
:y 114.68181818181819,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 37}
{:x 37.79292929292932,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 38}
{:x 114.77525252525247,
:y 138.09090909090912,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 39}
{:x 103.77777777777777,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 40}
{:x 48.790404040404034,
:y 266.8409090909091,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 41}
{:x 37.79292929292932,
:y 161.5,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 42}
{:x 103.77777777777777,
:y 126.38636363636365,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 43}
{:x 114.77525252525247,
:y 91.27272727272734,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 44}
{:x 81.78282828282826,
:y 184.90909090909093,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 45}
{:x 114.77525252525247,
:y 91.27272727272734,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 46}
{:x 59.78787878787873,
:y 161.5,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 47}
{:x 136.770202020202,
:y 102.97727272727275,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 48}
{:x 103.77777777777777,
:y 149.7954545454546,
:drawable
[{:color
[0.8941176470588236
0.10196078431372549
0.10980392156862745
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 49}
{:x 323.72727272727275,
:y 161.5,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 50}
{:x 257.74242424242425,
:y 161.5,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 51}
{:x 312.72979797979804,
:y 173.20454545454547,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 52}
{:x 158.7651515151515,
:y 266.8409090909091,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 53}
{:x 268.73989898989896,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 54}
{:x 180.760101010101,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 55}
{:x 246.74494949494945,
:y 149.7954545454546,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 56}
{:x 92.78030303030306,
:y 255.13636363636363,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 57}
{:x 279.73737373737373,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 58}
{:x 125.77272727272731,
:y 220.02272727272725,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 59}
{:x 103.77777777777777,
:y 301.95454545454544,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 60}
{:x 202.75505050505052,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 61}
{:x 213.75252525252526,
:y 278.5454545454545,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 62}
{:x 224.74999999999994,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 63}
{:x 169.7626262626262,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 64}
{:x 290.7348484848485,
:y 173.20454545454547,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 65}
{:x 169.7626262626262,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 66}
{:x 191.75757575757575,
:y 220.02272727272725,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 67}
{:x 235.74747474747477,
:y 278.5454545454545,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 68}
{:x 169.7626262626262,
:y 243.4318181818182,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 69}
{:x 202.75505050505052,
:y 161.5,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 70}
{:x 224.74999999999994,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 71}
{:x 246.74494949494945,
:y 243.4318181818182,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 72}
{:x 224.74999999999994,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 73}
{:x 257.74242424242425,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 74}
{:x 279.73737373737373,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 75}
{:x 301.7323232323232,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 76}
{:x 290.7348484848485,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 77}
{:x 213.75252525252526,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 78}
{:x 180.760101010101,
:y 231.72727272727272,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 79}
{:x 158.7651515151515,
:y 255.13636363636363,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 80}
{:x 158.7651515151515,
:y 255.13636363636363,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 81}
{:x 191.75757575757575,
:y 220.02272727272725,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 82}
{:x 213.75252525252526,
:y 220.02272727272725,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 83}
{:x 147.76767676767682,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 84}
{:x 213.75252525252526,
:y 138.09090909090912,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 85}
{:x 290.7348484848485,
:y 173.20454545454547,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 86}
{:x 246.74494949494945,
:y 266.8409090909091,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 87}
{:x 169.7626262626262,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 88}
{:x 158.7651515151515,
:y 243.4318181818182,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 89}
{:x 158.7651515151515,
:y 231.72727272727272,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 90}
{:x 224.74999999999994,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 91}
{:x 191.75757575757575,
:y 231.72727272727272,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 92}
{:x 103.77777777777777,
:y 266.8409090909091,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 93}
{:x 169.7626262626262,
:y 220.02272727272725,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 94}
{:x 180.760101010101,
:y 184.90909090909093,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 95}
{:x 180.760101010101,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 96}
{:x 235.74747474747477,
:y 196.61363636363637,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 97}
{:x 114.77525252525247,
:y 243.4318181818182,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 98}
{:x 180.760101010101,
:y 208.31818181818184,
:drawable
[{:color
[0.21568627450980393
0.49411764705882355
0.7215686274509804
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 99}
{:x 246.74494949494945,
:y 149.7954545454546,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 100}
{:x 191.75757575757575,
:y 220.02272727272725,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 101}
{:x 334.7247474747474,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 102}
{:x 246.74494949494945,
:y 196.61363636363637,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 103}
{:x 268.73989898989896,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 104}
{:x 389.7121212121212,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 105}
{:x 92.78030303030306,
:y 243.4318181818182,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 106}
{:x 356.71969696969694,
:y 196.61363636363637,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 107}
{:x 290.7348484848485,
:y 243.4318181818182,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 108}
{:x 345.72222222222223,
:y 114.68181818181819,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 109}
{:x 268.73989898989896,
:y 161.5,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 110}
{:x 257.74242424242425,
:y 220.02272727272725,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 111}
{:x 301.7323232323232,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 112}
{:x 180.760101010101,
:y 243.4318181818182,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 113}
{:x 191.75757575757575,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 114}
{:x 257.74242424242425,
:y 161.5,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 115}
{:x 268.73989898989896,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 116}
{:x 400.70959595959596,
:y 91.27272727272734,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 117}
{:x 400.70959595959596,
:y 231.72727272727272,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 118}
{:x 213.75252525252526,
:y 278.5454545454545,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 119}
{:x 312.72979797979804,
:y 161.5,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 120}
{:x 169.7626262626262,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 121}
{:x 400.70959595959596,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 122}
{:x 246.74494949494945,
:y 220.02272727272725,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 123}
{:x 290.7348484848485,
:y 149.7954545454546,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 124}
{:x 345.72222222222223,
:y 161.5,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 125}
{:x 235.74747474747477,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 126}
{:x 224.74999999999994,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 127}
{:x 257.74242424242425,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 128}
{:x 345.72222222222223,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 129}
{:x 367.71717171717177,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 130}
{:x 422.7045454545455,
:y 91.27272727272734,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 131}
{:x 257.74242424242425,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 132}
{:x 246.74494949494945,
:y 208.31818181818184,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 133}
{:x 224.74999999999994,
:y 231.72727272727272,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 134}
{:x 400.70959595959596,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 135}
{:x 246.74494949494945,
:y 138.09090909090912,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 136}
{:x 257.74242424242425,
:y 173.20454545454547,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 137}
{:x 213.75252525252526,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 138}
{:x 312.72979797979804,
:y 173.20454545454547,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 139}
{:x 290.7348484848485,
:y 173.20454545454547,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 140}
{:x 312.72979797979804,
:y 173.20454545454547,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 141}
{:x 191.75757575757575,
:y 220.02272727272725,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 142}
{:x 301.7323232323232,
:y 161.5,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 143}
{:x 290.7348484848485,
:y 149.7954545454546,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 144}
{:x 290.7348484848485,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 145}
{:x 246.74494949494945,
:y 243.4318181818182,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 146}
{:x 268.73989898989896,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 147}
{:x 235.74747474747477,
:y 138.09090909090912,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 148}
{:x 202.75505050505052,
:y 184.90909090909093,
:drawable
[{:color
[0.30196078431372547
0.6862745098039216
0.2901960784313726
0.75],
:drawables
({:style :membrane.ui/style-fill,
:drawables [{:width 6.0, :height 6.0, :border-radius 3.0}]})}
nil],
:row-idx 149}
{:x 51.790404040404034,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "4.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 106.77777777777777,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "5.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 161.7651515151515,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "5.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 216.75252525252526,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "6.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 271.73989898989896,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "6.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 326.72727272727275,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "7.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 381.7146464646464,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "7.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 436.7020202020202,
:y 331.0,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "8.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "middle"})}}
{:x 7.0,
:y 299.45454545454544,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "2.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}
{:x 7.0,
:y 240.9318181818182,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "2.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}
{:x 7.0,
:y 182.40909090909093,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "3.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}
{:x 7.0,
:y 123.88636363636365,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "3.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}
{:x 7.0,
:y 65.3636363636364,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "4.0",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}
{:x 7.0,
:y 6.840909090909179,
:drawable
{:color [0.4 0.4 0.4 1.0],
:drawables
({:text "4.5",
:font
{:name nil, :size 11, :weight nil, :width nil, :slant nil},
:text-anchor "end"})}}]}],
:width 600,
:height 400,
:plotje/title "Iris"}Plot
A plot is the final rendered output – the result of rendering a plan to a specific format. For SVG, the plot is hiccup markup wrapped in kind/hiccup.
Created by pj/plot or by auto-rendering a pose.
(def my-plot (pj/plan->plot my-plan :svg {}))The plot is hiccup – a vector starting with :svg followed by an attribute map and the plot’s drawable elements. Wrapped in kind/hiccup, it renders as the same picture we saw at the top of this chapter:
(kind/hiccup my-plot)Palette
A palette is an ordered set of colors used for categorical aesthetics. When :color maps to a categorical column, colors are assigned from the active palette in order.
Plotje uses clojure2d for palettes. Set via {:palette :set2} in options:
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width {:color :species})
(pj/options {:palette :set2}))clojure2d provides thousands of named palettes – the count below is the size of the catalogue:
(count (c2d/find-palette #".*"))7024Gradient
A gradient (or color scale) maps a continuous numeric range to a smooth color ramp. Used when :color maps to a numerical column.
Common gradients: :viridis, :inferno, :plasma, :magma. Diverging gradients center on a midpoint value. Set via {:color-scale :inferno} in options:
(-> {:x (range 50) :y (range 50) :c (range 50)}
(pj/lay-point :x :y {:color :c})
(pj/options {:color-scale :inferno}))Configuration
Configuration controls rendering behavior – dimensions, theme, palette, color scale, margins, and more. It is one of three option scopes – the others are plot options and layer options. Configuration follows a precedence chain:
plot options > pj/with-config > pj/set-config! > plotje.edn > library defaults
plotje.edn is an optional file in your project root that provides project-level defaults (e.g., a consistent palette or theme across all plots).
See the Configuration chapter for details. The active configuration is itself a Clojure map – pj/config returns a snapshot:
(select-keys (pj/config) [:width :height :theme :palette :color-scale]){:width 600,
:height 400,
:theme {:bg "#E8E8E8", :grid "#F5F5F5", :font-size 11}}Plot Options
Plot options are per-plot settings passed to pj/options, pj/plan, or pj/plot. They include text content (title, subtitle, caption, axis labels) and a nested :config override. Unlike configuration keys, plot options are inherently per-plot – a title does not make sense as a global default.
See pj/plot-option-docs for the full list, or the Configuration chapter for usage examples.
(sort (keys pj/plot-option-docs))(:alpha-label
:caption
:color-label
:config
:fill-label
:panel-height
:panel-width
:scales
:share-scales
:size-label
:subtitle
:title
:x-label
:y-label)Layer Options
Layer options are per-layer settings passed in the options map of layer functions (pj/lay-point, pj/lay-histogram, etc.). They control aesthetics (:color, :size, :alpha, :shape), grouping (:group), position adjustment (:position), and layer-type-specific parameters (:bandwidth, :confidence-band, :normalize, etc.).
Four keys are universal – accepted by every layer – and each layer type may accept additional keys. The Layer Types chapter lists which options each layer type accepts. See also pj/layer-option-docs for descriptions, or inspect a specific layer type with pj/layer-type-lookup.
(sort (keys pj/layer-option-docs))(:alpha
:bandwidth
:bootstrap-resamples
:color
:color-type
:confidence-band
:density-2d-grid
:fill
:group
:interval-thickness
:jitter
:levels
:normalize
:nudge-x
:nudge-y
:position
:shape
:side
:size
:text
:x-end
:x-intercept
:x-max
:x-min
:x-type
:y-intercept
:y-max
:y-min
:y-type)Tooltip and Brush
A tooltip shows data values on hover. A brush enables click-and-drag selection that highlights a rectangular region. Both are JavaScript-based interactions added to the SVG output.
Enabled via {:tooltip true} and {:brush true} in options:
(-> (rdatasets/datasets-iris)
(pj/lay-point :sepal-length :sepal-width {:color :species})
(pj/options {:tooltip true :brush true}))Summary Table
| Term | What | Key functions |
|---|---|---|
| Pose | Composable value: data + mapping + layers (+ inner poses) | All pj/ functions return poses |
| Leaf pose | Pose describing one plot panel | pj/pose, pj/lay-* with columns |
| Composite pose | Pose containing other poses (in :poses) and a layout |
pj/arrange |
| Mapping | Column-to-aesthetic association on a pose or layer | pj/pose mapping, pj/lay-* options |
| Layer | Layer type attached to a pose, optionally with scoped mappings | pj/lay-* |
| Dataset | Tabular data backing a plot – a tech.ml.dataset, conveniently built and manipulated via the Tablecloth API |
:data slot, pj/with-data |
| Pipeline | Five-stage flow pose -> draft -> plan -> membrane -> plot |
Architecture chapter |
| Sub-plot | One resolved entry of a composite pose’s :poses, in the plan |
:sub-plots in plan |
| Resolve tree | Scope-merge walk: root mappings propagate to every leaf | Internal to pj/plan |
| Draft | LeafDraft or CompositeDraft record carrying merged layer maps and pose-level options |
pj/draft, automatic during pj/plan |
| Draft layer | One element of a draft: layer type + merged mappings + data | Element of pj/draft output |
| Layer type | Mark + stat + position bundle | pj/layer-type-lookup, pj/lay-* |
| Mark | Visual shape: point, line, bar, area, … | Key in layer-type map |
| Stat | Data transform: identity, bin, count, linear-model, density, … | Key in layer-type map |
| Position | How overlapping marks are placed: identity, dodge, stack, fill | Key in layer-type map |
| Inference | Auto-choosing mark/stat from column types | When pj/lay-* is omitted |
| Aesthetic | Mark property bindable to a column: positional (x, y, …) or appearance (color, size, alpha, …) | Key in mapping or layer |
| Group | Subset of data rendered together | From :color or :group |
| Plan | Fully resolved plot description | pj/plan |
| Panel | One plotting area (domain, ticks, layers) | One or more per plan |
| Plan layer | Resolved geometry + style for one mark | Inside plan panels |
| Domain | Data range on an axis | Part of panel |
| Tick | Axis mark with label at a domain value | Part of panel |
| Scale | Data-to-drawing-units mapping (linear, log, categorical) | pj/scale |
| Coord | Coordinate system (cartesian, flip, polar, fixed) | pj/coord |
| Facet | Split into panels by a categorical column | pj/facet, pj/facet-grid |
| Arrange | Compose multiple poses into a grid | pj/arrange |
| Share scales | Make sibling poses of a composite share data ranges across named axes | :share-scales in composite :opts |
| Annotation | Reference marks (rules, bands); positions in :mapping as literal values today, data-driven planned |
pj/lay-rule-*, pj/lay-band-* |
| Legend | Color/size/alpha key from aesthetic mappings | Automatic in plan |
| Plot options | Title, subtitle, caption, labels, dimensions | pj/options |
| Layer options | Per-layer aesthetics and layer-type parameters | pj/lay-* options map |
| Theme | Visual styling: background, grid, fonts | :theme in pj/options |
| Palette | Ordered color set for categorical aesthetics | :palette in pj/options |
| Gradient | Continuous color ramp for numerical mappings | :color-scale in pj/options |
| Configuration | Global rendering defaults | pj/config, pj/set-config!, pj/with-config |
| Membrane | PlotjeMembrane record – a Membrane UI component carrying the drawable tree, plan-derived dimensions, and :plotje/title |
pj/membrane, pj/plan->membrane |
| Plot | Final output (SVG hiccup) | pj/plot, pj/save |
| Tooltip / Brush | JavaScript hover and selection interactions | {:tooltip true} in options |