427427; ; ### 📖 What's Coming
428428; ;
429429; ; The rest of this notebook:
430- ; ; 1. Schemas and validation (reference material, can skim)
431- ; ; 2. Implementation (operators, constructors, helpers, rendering)
432- ; ; 3. Examples showing the API in action (scatter, linear, histogram, faceting)
433- ; ; 4. Multi-target rendering (same spec, different backends)
430+ ; ; 1. How plots display (auto-display behavior, when to use `plot` explicitly)
431+ ; ; 2. Implementation status (what works, what's missing)
432+ ; ; 3. Rendering targets & delegation strategy (design principles)
433+ ; ; 4. Schemas and validation (reference material, can skim)
434+ ; ; 5. API implementation (operators, constructors, rendering function)
435+ ; ; 6. Examples showing the API in action (scatter, linear, histogram, faceting)
436+ ; ; 7. Multi-target rendering (same spec works across geom, Vega-Lite, Plotly)
434437; ;
435438; ; **Note on IR:** The internal representation uses maps with `:=layers` keys,
436439; ; separating plot-level properties from layer specs. This enables clean composition
12881291 ([spec width height]
12891292 (=* spec (size width height))))
12901293
1291- ; ; # Examples
1294+ ; ; # Setup & Constants
12921295; ;
12931296; ; These examples demonstrate the design in practice, showing how minimal
12941297; ; delegation works.
12951298
1296- ; ; ### ⚙️ Setup: Load Datasets
1299+ ; ; ### ⚙️ Datasets for Examples
12971300
12981301; ; Palmer Penguins - 344 observations, 3 species
12991302(def penguins (tc/drop-missing (rdatasets/palmerpenguins-penguins )))
@@ -1310,7 +1313,7 @@ mtcars
13101313
13111314iris
13121315
1313- ; ; # Visual Theme Constants
1316+ ; ; ### ⚙️ Visual Theme Constants
13141317; ;
13151318; ; These constants define the ggplot2-compatible visual theme used across
13161319; ; all rendering targets. Extracted here for maintainability.
@@ -1345,7 +1348,13 @@ iris
13451348; ; Notice: We get precise type information (`:float64`, `:string`) without
13461349; ; examining values. This eliminates the need for complex type inference.
13471350
1348- ; ; ## ⚙️ Implementation: Helper Functions & :geom Target
1351+ ; ; # Core Implementation: Helpers & Rendering Infrastructure
1352+ ; ;
1353+ ; ; This section contains the foundational helper functions and the core
1354+ ; ; rendering infrastructure for the :geom target. These are used by all
1355+ ; ; plot types but aren't part of the user-facing API.
1356+
1357+ ; ; ## Helper Functions & Utilities
13491358; ;
13501359; ; Before we can render examples, we need basic implementation.
13511360; ; This version follows the minimal delegation strategy.
@@ -1703,7 +1712,11 @@ iris
17031712 [categories]
17041713 (zipmap categories (cycle ggplot2-colors)))
17051714
1706- ; ; ## ⚙️ Rendering Multimethod
1715+ ; ; ## Geom Target Rendering
1716+ ; ;
1717+ ; ; Core rendering infrastructure for the :geom (thi.ng/geom) target.
1718+
1719+ ; ; ### ⚙️ Core Rendering Multimethods
17071720; ;
17081721; ; The render-layer multimethod dispatches on [target plottype-or-transform].
17091722; ; This allows us to define each rendering strategy separately and introduce
@@ -2675,7 +2688,7 @@ iris
26752688 (mapping :bill-length-mm nil )
26762689 (histogram {:bins 15 }))
26772690
2678- ; ; # Grouping ;; # 📊 Grouping & Color Color
2691+ ; ; # Grouping & Color
26792692; ;
26802693; ; Type-aware grouping: categorical colors create groups for statistical transforms.
26812694
@@ -2803,7 +2816,11 @@ iris
28032816; ; See the Multi-Target Rendering section for examples of using `plot`
28042817; ; with :vl and :plotly targets.
28052818
2806- ; ; # Faceting: Architectural Questions Revealed
2819+ ; ; # Faceting
2820+ ; ;
2821+ ; ; Small multiples: splitting data across rows and columns for comparison.
2822+
2823+ ; ; ## 📖 Architectural Considerations
28072824; ;
28082825; ; Implementing faceting has exposed several important design questions:
28092826; ;
@@ -2884,11 +2901,7 @@ iris
28842901; ; **This is our value proposition**: Compute on JVM, send summaries to browser.
28852902; ; With faceting, even more important!"
28862903
2887- ; ; # Faceting Exploration
2888- ; ;
2889- ; ; Let's explore faceting to see what architectural questions emerge.
2890-
2891- ; ; ### 📖 Faceting Design Decisions
2904+ ; ; ## 📖 Design Decisions
28922905; ;
28932906; ; After prototyping, we've decided:
28942907; ;
@@ -2897,7 +2910,7 @@ iris
28972910; ; 3. **Shared scales by default** - All facets use same domain (easier comparison)
28982911; ; 4. **Statistical transforms per-facet** - Histogram by species = 3 separate histograms
28992912; ;
2900- ; ; ### ⚙️ Implementation Strategy
2913+ ; ; ## ⚙️ Implementation Strategy
29012914; ;
29022915; ; 1. `split-by-facets` - Groups data by facet variable(s)
29032916; ; 2. Apply transforms to each facet group separately
@@ -2907,14 +2920,11 @@ iris
29072920; ; For :geom target - compute layout positions manually
29082921; ; For :vl/:plotly targets - could use their grid layout features
29092922
2923+ ; ; ## 🧪 Examples
2924+
29102925; ; ### 🧪 Example 10: Simple Column Faceting
29112926; ;
29122927; ; Facet a scatter plot by species - this creates 3 side-by-side plots.
2913- ; ; # Faceting
2914- ; ;
2915- ; ; Small multiples: splitting data across rows and columns.
2916-
2917- ; ; Test faceted scatter plot - 3 side-by-side plots
29182928(facet (=* (data penguins)
29192929 (mapping :bill-length-mm :bill-depth-mm )
29202930 (scatter ))
@@ -3046,14 +3056,6 @@ iris
30463056; ; 2. Zooms into a specific region of the data
30473057; ; 3. Useful for focusing on areas of interest or ensuring consistent scales across multiple plots
30483058
3049- ; ; # Multiple Rendering Targets
3050- ; ;
3051- ; ; One of the key benefits of our API design is **backend agnosticism**. The same
3052- ; ; plot specification can be rendered by different visualization libraries.
3053- ; ;
3054- ; ; So far, all examples have used the `:geom` target (thi.ng/geom for static SVG),
3055- ; ; which is the default. To select a different target, use the `target` function.
3056-
30573059; ; # Multi-Target Rendering
30583060; ;
30593061; ; Same API, different backends: :geom (SVG), :vl (Vega-Lite), :plotly (Plotly.js).
@@ -3504,7 +3506,7 @@ iris
35043506
35053507 (kind/plotly spec)))
35063508
3507- ; ; ## 🧪 Examples
3509+ ; ; ## 🧪 Vega-Lite Examples
35083510
35093511; ; ### 🧪 Example 14: Simple Scatter with Vega-Lite
35103512
@@ -3650,7 +3652,7 @@ iris
36503652; ; 2. VL respects our domain constraints
36513653; ; 3. Same composition semantics across targets
36523654
3653- ; ; ### 📖 The Power of Backend Agnosticism
3655+ ; ; ## 📖 The Power of Backend Agnosticism
36543656; ;
36553657; ; **Key insight**: Our flat map representation with `:=...` keys creates a
36563658; ; separation between plot semantics and rendering implementation.
@@ -3672,10 +3674,7 @@ iris
36723674
36733675; ; Now we can demonstrate multi-target rendering with the same spec.
36743676
3675- ; ; # Plotly.js Target Examples
3676- ; ;
3677- ; ; Now let's explore the `:plotly` target, which provides interactivity
3678- ; ; and is particularly strong for dashboards and web applications.
3677+ ; ; ## 🧪 Plotly Examples
36793678
36803679; ; ### 🧪 Example 21: Simple Scatter with Plotly
36813680
@@ -3818,7 +3817,7 @@ iris
38183817; ; 2. Zoom/pan constrained to specified ranges
38193818; ; 3. Same composition semantics across all targets
38203819
3821- ; ; ### 🧪 Example 15: Compositional Size Specification
3820+ ; ; ## 🧪 Compositional Size Specification
38223821
38233822; ; Width and height can be specified compositionally using the `size` constructor,
38243823; ; just like `target`. This enables full threading and keeps plot dimensions as
@@ -3870,85 +3869,7 @@ iris
38703869; ; Both approaches work. The `size` constructor enables full threading and
38713870; ; treats dimensions as compositional layer properties.
38723871
3873- ; ; # Design Discussion
3874- ; ;
3875- ; ; ## 📖 Map-Based IR: Separating Layers from Plot Configuration
3876- ; ;
3877- ; ; ### The Design Choice
3878- ; ;
3879- ; ; The internal representation uses a map structure with explicit separation:
3880-
3881- (-> penguins
3882- (mapping :bill-length-mm :bill-depth-mm )
3883- (scatter )
3884- (target :vl )
3885- (size 800 600 ))
3886-
3887- ; ; This produces a map with `:=layers` and plot-level properties separated:
3888-
3889- ; ; ```clojure
3890- ; ; {:=layers [{:=data penguins
3891- ; ; :=x :bill-length-mm
3892- ; ; :=y :bill-depth-mm
3893- ; ; :=plottype :scatter}]
3894- ; ; :=target :vl
3895- ; ; :=width 800
3896- ; ; :=height 600}
3897- ; ; ```
3898- ; ;
3899- ; ; ### Why This Structure?
3900- ; ;
3901- ; ; **Clean separation of concerns:**
3902- ; ; - **Layer properties** (`:=data`, `:=x`, `:=y`, `:=plottype`) describe what to visualize
3903- ; ; - **Plot properties** (`:=target`, `:=width`, `:=height`, scales) describe how to render
3904- ; ;
3905- ; ; **Benefits:**
3906- ; ; 1. **Inspectable** - `kind/pprint` shows clear structure
3907- ; ; 2. **No duplication** - Plot config appears once, not in every layer
3908- ; ; 3. **Composable** - `=*` and `=+` can merge both levels correctly
3909- ; ; 4. **Extensible** - Easy to add new plot-level properties (themes, titles, etc.)
3910- ; ;
3911- ; ; ### How Operators Handle It
3912- ; ;
3913- ; ; **`=*` (merge):**
3914- ; ; - Performs cross-product on `:=layers` vectors
3915- ; ; - Merges plot-level properties (right side wins)
3916- ; ;
3917- ; ; **`=+` (overlay):**
3918- ; ; - Concatenates `:=layers` vectors
3919- ; ; - Merges plot-level properties (right side wins)
3920- ; ;
3921- ; ; **Constructors:**
3922- ; ; - Layer constructors (`data`, `mapping`, `scatter`) return `{:=layers [...]}`
3923- ; ; - Plot constructors (`target`, `size`, `scale`) return `{:=property value}`
3924- ; ; - Both compose naturally via `=*`
3925- ; ;
3926- ; ; This design balances compositional elegance with practical clarity.
3927-
3928- ; ; # Summary
3929- ; ;
3930- ; ; ### 📖 What We've Explored
3931- ; ;
3932- ; ; This notebook demonstrates a composable graphics API with **minimal delegation**:
3933- ; ;
3934- ; ; **Core Design**:
3935- ; ; - Layers as flat maps with `:=...` distinctive keys
3936- ; ; - Composition using `*` (merge) and `+` (overlay)
3937- ; ; - Standard library operations work natively
3938- ; ; - Backend-agnostic IR
3939- ; ;
3940- ; ; **Delegation Strategy**:
3941-
3942- ; ; 1. ✅ **We compute**: Statistical transforms, domains (when needed), types (from Tablecloth)
3943- ; ; 2. ❌ **We delegate**: Axis rendering, ranges, ticks, "nice numbers", layout
3944- ; ;
3945- ; ; **Key Wins**:
3946- ; ; - Type information from Tablecloth (free!)
3947- ; ; - Domain computation only for statistical transforms
3948- ; ; - Leverage rendering target polish for rendering
3949- ; ; - Simple, focused implementation
3950-
3951- ; ; # 🧪 Validation Examples
3872+ ; ; # Validation Examples
39523873; ;
39533874; ; The Malli schemas enable validation at two points:
39543875; ; - Construction time
@@ -4007,9 +3928,54 @@ iris
40073928; ; Get detailed error information
40083929(validate Layer {:=plottype :invalid :=alpha 2.0 })
40093930
4010- ; ; ## Design Discussions
3931+ ; ; # Design Discussions
40113932
4012- ; ; ### 📖 Auto-display vs Explicit Rendering
3933+ ; ; ## 📖 Map-Based IR: Separating Layers from Plot Configuration
3934+ ; ;
3935+ ; ; ### The Design Choice
3936+ ; ;
3937+ ; ; The internal representation uses a map structure with explicit separation:
3938+ ; ;
3939+ ; ; ```clojure
3940+ ; ; {:=layers [{:=data penguins
3941+ ; ; :=x :bill-length-mm
3942+ ; ; :=y :bill-depth-mm
3943+ ; ; :=plottype :scatter}]
3944+ ; ; :=target :vl
3945+ ; ; :=width 800
3946+ ; ; :=height 600}
3947+ ; ; ```
3948+ ; ;
3949+ ; ; ### Why This Structure?
3950+ ; ;
3951+ ; ; **Clean separation of concerns:**
3952+ ; ; - **Layer properties** (`:=data`, `:=x`, `:=y`, `:=plottype`) describe what to visualize
3953+ ; ; - **Plot properties** (`:=target`, `:=width`, `:=height`, scales) describe how to render
3954+ ; ;
3955+ ; ; **Benefits:**
3956+ ; ; 1. **Inspectable** - `kind/pprint` shows clear structure
3957+ ; ; 2. **No duplication** - Plot config appears once, not in every layer
3958+ ; ; 3. **Composable** - `=*` and `=+` can merge both levels correctly
3959+ ; ; 4. **Extensible** - Easy to add new plot-level properties (themes, titles, etc.)
3960+ ; ;
3961+ ; ; ### How Operators Handle It
3962+ ; ;
3963+ ; ; **`=*` (merge):**
3964+ ; ; - Performs cross-product on `:=layers` vectors
3965+ ; ; - Merges plot-level properties (right side wins)
3966+ ; ;
3967+ ; ; **`=+` (overlay):**
3968+ ; ; - Concatenates `:=layers` vectors
3969+ ; ; - Merges plot-level properties (right side wins)
3970+ ; ;
3971+ ; ; **Constructors:**
3972+ ; ; - Layer constructors (`data`, `mapping`, `scatter`) return `{:=layers [...]}`
3973+ ; ; - Plot constructors (`target`, `size`, `scale`) return `{:=property value}`
3974+ ; ; - Both compose naturally via `=*`
3975+ ; ;
3976+ ; ; This design balances compositional elegance with practical clarity.
3977+
3978+ ; ; ## 📖 Auto-display vs Explicit Rendering
40133979
40143980; ; The current design supports two rendering modes:
40153981; ; 1. Auto-display: `(=* ...)` returns an object that automatically renders in notebooks
@@ -4239,6 +4205,26 @@ iris
42394205
42404206; ; # Conclusion
42414207
4208+ ; ; ### 📖 What We've Explored
4209+ ; ;
4210+ ; ; This notebook demonstrates a composable graphics API with **minimal delegation**:
4211+ ; ;
4212+ ; ; **Core Design**:
4213+ ; ; - Layers as flat maps with `:=...` distinctive keys
4214+ ; ; - Composition using `*` (merge) and `+` (overlay)
4215+ ; ; - Standard library operations work natively
4216+ ; ; - Backend-agnostic IR
4217+ ; ;
4218+ ; ; **Delegation Strategy**:
4219+ ; ; 1. ✅ **We compute**: Statistical transforms, domains (when needed), types (from Tablecloth)
4220+ ; ; 2. ❌ **We delegate**: Axis rendering, ranges, ticks, "nice numbers", layout
4221+ ; ;
4222+ ; ; **Key Wins**:
4223+ ; ; - Type information from Tablecloth (free!)
4224+ ; ; - Domain computation only for statistical transforms
4225+ ; ; - Leverage rendering target polish for rendering
4226+ ; ; - Simple, focused implementation
4227+
42424228; ; ### 📖 Where We Are
42434229
42444230; ; So that's the exploration. We set out to see if AlgebraOfGraphics.jl's compositional
0 commit comments