Skip to content

Commit 8dfe68b

Browse files
committed
aog wip
1 parent d91faba commit 8dfe68b

1 file changed

Lines changed: 104 additions & 118 deletions

File tree

src/data_visualization/aog_in_clojure_part1.clj

Lines changed: 104 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,13 @@
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
@@ -1288,12 +1291,12 @@
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

13111314
iris
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

Comments
 (0)