You are looking at historical revision 45629 of this page. It may differ significantly from its current revision.
gg-plot
A declarative plotting system built on top of the Cairo graphics library which provides ggplot2-style plotting routines, with s-expression plot specifications, automatic scale training, and four output formats (PNG, SVG, PostScript, PDF).
Requirements
- cairo egg (Cairo graphics bindings)
- matchable egg
- datatype egg
- yasos egg
- statistics egg
Overview
The library is organised into nine modules that correspond to the tiers of the Grammar of Graphics:
- {gg-vge}
- Virtual Graphics Engine — algebraic IR for graphics instructions
- {gg-backend}
- Abstract backend protocol (YASOS interface)
- {gg-backend-cairo}
- Cairo backend; PNG, SVG, PostScript, and PDF output
- {gg-primitives-vge}
- Composable drawer abstraction; shapes, text, transforms
- {gg-scales}
- Data-to-visual mappings (linear, log, ordinal, color)
- {gg-data}
- Columnar data utilities
- {gg-aes}
- Aesthetic (column-channel) mapping
- {gg-geom}
- Geometry functions (scatter, line, bar, errorbar, raster...)
- {gg-guides}
- Axis and legend drawers
- {gg-plot}
- Full declarative plot API
Most users only need to (import gg-plot); the lower-level modules are available for custom rendering pipelines.
The translation pipeline
s-expression spec -> normalize / validate defaults -> train scales from all layers -> compute facet panels -> render each panel (background, geometries, axes) -> render global elements (title, legends) -> emit via Cairo (PNG / SVG / PS / PDF)
Module: gg-primitives-vge
Low-level composable drawing layer. A drawer is a record wrapping a procedure that emits instructions into a VGE (Virtual Graphics Engine). Drawers are first-class values: they can be stored, composed with combine, and wrapped with style or transform combinators before being rendered to any backend.
Coordinate convention: right-handed, origin at bottom-left, Y-up. All coordinates are in user space; the backend maps them to device pixels.
Drawer record
[procedure] (make-drawer proc bounds)Create a drawer from a procedure (vge -> void) and an optional bounding box (or #f).
[procedure] (drawer? obj)True if obj is a drawer record.
[procedure] (drawer-proc drawer)[procedure] (drawer-bounds drawer)
Accessors.
[procedure] empty-drawerA drawer that does nothing (identity for combine).
Composition
[procedure] (combine drawer ...)Return a new drawer that executes each argument drawer left-to-right with no additional scoping.
[procedure] (combine-group drawer ...)Like combine but wraps the result in a gfx:group scope.
Rendering
[procedure] (render-drawer drawer vge)Emit a drawer's instructions into vge (a VGE accumulator created by make-vge from gg-vge). Does not perform I/O; call vge-render! afterwards to send the instructions to a backend.
Scoped state wrappers
Each wrapper produces a gfx:group, so the state change is automatically scoped; no explicit push/pop is needed.
[procedure] (with-pushed-state drawer)Raw push/pop scope (low-level; prefer the typed wrappers below).
[procedure] (with-translate dx dy drawer)[procedure] (with-viewport x0 y0 x1 y1 drawer)
[procedure] (with-clip-rect x y w h drawer)
[procedure] (with-rotate angle drawer)
angle in radians.
Style wrappers
[procedure] (with-pen-color color drawer)color is a color string ("\"steelblue\"", "\"#3f7ab5\"") or a color:rgba / color:named value from gg-backend.
[procedure] (with-fill-color color drawer)[procedure] (with-line-width width drawer)
width in user coordinates.
[procedure] (with-dash dashes offset drawer)dashes is a list of on/off lengths; offset is the phase.
[procedure] (with-font family size slant weight drawer)family is a font family string (e.g. "\"sans-serif\""); slant is 'normal or 'italic; weight is 'normal or 'bold.
Stroked drawing primitives
[procedure] (line-drawer x1 y1 x2 y2)[procedure] (polyline-drawer pts)
pts is a list of (x . y) pairs.
[procedure] (rect-drawer x y w h)Outline rectangle; bottom-left corner at (x, y).
[procedure] (circle-drawer cx cy r)[procedure] (polygon-drawer pts)
Filled drawing primitives
[procedure] (filled-rect-drawer x y w h)[procedure] (filled-circle-drawer cx cy r)
[procedure] (filled-polygon-drawer pts)
Text
[procedure] (text-drawer x y text #!key halign valign)Draw text anchored at (x, y).
- halign
- 'left, 'center (default), or 'right
- valign
- 'top, 'center, 'bottom, or 'baseline (default)
Convenience drawers
[procedure] (h-line-drawer x1 x2 y)[procedure] (v-line-drawer x y1 y2)
[procedure] (filled-rect+border-drawer x y w h fill-color edge-color)
[procedure] (path-drawer cmds #!key filled?)
cmds is a list of path commands from gg-backend: path:move-to, path:line-to, path:curve-to, path:arc, path:close.
Module: gg-backend-cairo
Cairo graphics backend. Implements the abstract backend protocol from gg-backend for four output formats.
[procedure] (make-cairo-png-backend filename width height)PNG raster output. width and height are in pixels.
[procedure] (make-cairo-svg-backend filename width height)SVG vector output.
[procedure] (make-cairo-ps-backend filename width height)PostScript output.
[procedure] (make-cairo-pdf-backend filename width height)PDF output. width and height are in points (72 pt = 1 inch; A4 portrait = 595 × 842 pt).
Module: gg-scales
Scales map between the data domain and the visual range. All scale objects implement the same protocol (via YASOS), so geometry and guide code is scale-type–agnostic.
Scale protocol
[procedure] (scale? obj)[procedure] (scale-type scale)
Returns a symbol: 'linear, 'log, 'sqrt, 'power, 'ordinal, 'band, 'color-gradient, 'color-manual, …
[procedure] (scale-train! scale values)Extend the domain to include values (a list). Mutates the scale.
[procedure] (scale-map scale value)Map a single domain value to the visual range.
[procedure] (scale-inverse scale value)Map from visual range back to domain.
[procedure] (scale-breaks scale [n])Return a list of n (default 5) nicely-placed tick positions.
[procedure] (scale-labels scale breaks)Return formatted label strings for the given break positions.
[procedure] (scale-domain scale)Current domain as a (min . max) pair, or a list for discrete scales.
[procedure] (scale-range scale)Current visual range as a (min . max) pair.
[procedure] (scale-set-domain! scale domain)[procedure] (scale-set-range! scale range)
Mutating setters.
[procedure] (scale-bandwidth scale)Width of a single band (for band scales only).
Functional scale combinators
These return a new scale and leave the original unmodified.
[procedure] (scale-with-domain scale domain)[procedure] (scale-with-range scale range)
[procedure] (scale-with-trained scale values)
[procedure] (scale-with-transform scale transform-type)
transform-type is one of: 'log, 'log10, 'log2, 'ln, 'sqrt, 'identity.
[procedure] (scale-with-breaks scale explicit-breaks)Override automatic break computation with a fixed list.
Continuous scale constructors
[procedure] (make-scale-linear #!key domain range)[procedure] (make-scale-log #!key domain range base)
base defaults to 10.
[procedure] (make-scale-sqrt #!key domain range)[procedure] (make-scale-power #!key domain range exponent)
exponent defaults to 2.
Discrete scale constructors
[procedure] (make-scale-ordinal #!key domain range)Maps each domain value to the corresponding entry in range, cycling if necessary.
[procedure] (make-scale-band #!key domain range padding)Like ordinal but maps to a continuous sub-interval (band) for bar charts. padding (default 0.1) is the fraction of each step reserved for spacing.
Color scale constructors
[procedure] (make-scale-color-gradient #!key domain low high)Continuous gradient interpolating between low and high color strings. Accepts named colors ("\"blue\"") and hex strings ("\"#3f7ab5\"").
[procedure] (make-scale-color-diverging #!key domain low mid high midpoint)Two-segment gradient with a midpoint color.
[procedure] (make-scale-color-ordinal #!key domain palette)Ordinal scale backed by a list of color strings.
[procedure] (make-scale-color-manual value-map)Explicit category -> color alist, e.g. `(("Control" . "blue") ("Treatment" . "red"))
Break utilities
[procedure] (nice-breaks min-val max-val n)[procedure] (compute-pretty-breaks min max n)
[procedure] (extend-domain domain expansion)
Extend domain by the fractional expansion on each side (e.g. 0.05 adds 5 % padding).
Module: gg-data
Columnar data frames: an association list mapping column names (symbols) to parallel value lists.
(define data
'((time . (0 10 20 30 40 50))
(value . (1.2 1.5 2.3 1.8 1.4 1.9))
(group . ("A" "A" "A" "B" "B" "B"))))[procedure] (data-column data column-name)
Extract a column list. Signals an error if the column is absent.
[procedure] (data-columns data)List of column name symbols.
[procedure] (data-n-rows data)[procedure] (data-row data index)
Single row as an association list ((col . value) ...).
[procedure] (data-rows data)All rows as a list of association lists. Used internally by geometries.
[procedure] (columns->rows data)[procedure] (rows->columns rows)
Convert between the columnar and row-oriented representations.
Module: gg-aes
Aesthetic mappings link data columns to visual channels.
Creating mappings
[procedure] (aes #!key x y color fill size shape alpha linetype group label)[procedure] (make-aes ...)
Both are equivalent. Column references are symbols; literal values are strings or numbers:
(aes #:x 'time #:y 'value #:color 'condition) ; x, y, color mapped to columns (aes #:x 'time #:y 'value #:color "steelblue") ; color is a constant[procedure] (aesthetic-mapping? obj)
Accessors
[procedure] (aes-x mapping)[procedure] (aes-y mapping)
[procedure] (aes-color mapping)
[procedure] (aes-fill mapping)
[procedure] (aes-size mapping)
[procedure] (aes-shape mapping)
[procedure] (aes-alpha mapping)
[procedure] (aes-linetype mapping)
[procedure] (aes-group mapping)
[procedure] (aes-label mapping)
[procedure] (aes-get mapping key [default])
Utilities
[procedure] (aes-merge base override)Merge two mappings; override wins on conflicts.
[procedure] (aes-has? mapping key)[procedure] (aes-keys mapping)
[procedure] (aes-map-value mapping key data-row)
Resolve an aesthetic: if the stored value is a symbol, look it up in data-row (an association list); otherwise return the literal value.
[procedure] (constant-value? value)[procedure] (mapped-value? value)
Module: gg-geom
Geometry functions take a columnar data frame and an aesthetic mapping and return (values drawer trained-scales). They are normally used indirectly through the layer constructors in gg-plot, but can be called directly for custom pipelines.
Core geometries
[procedure] (geom-point data aes #!key scales size shape alpha)Scatter plot. Required aesthetics: x, y. Optional: color, fill, size.
[procedure] (geom-line data aes #!key scales width style)Line plot. Groups rows by the color or group aesthetic and draws a separate polyline per group. Required: x, y.
[procedure] (geom-path data aes #!key scales width color)Like geom-line but connects points in data order without sorting.
[procedure] (geom-area data aes #!key scales fill alpha)Filled area. With only x/y aesthetics, fills from 0 to y (simple area). With ymin/ymax aesthetics, fills between the two curves (ribbon).
[procedure] (geom-bar data aes #!key scales fill width)Bar chart. Required: x, y.
[procedure] (geom-rect data aes #!key scales)Draws rectangles from xmin/xmax/ymin/ymax aesthetics.
[procedure] (geom-text data aes #!key scales size color)Text labels positioned at x/y, string from label aesthetic.
[procedure] (geom-segment data aes #!key scales color width)Line segments from (x, y) to (xend, yend).
[procedure] (geom-hline data aes #!key scales color width linetype)[procedure] (geom-vline data aes #!key scales color width linetype)
Reference lines.
Event plot
[procedure] (geom-eventplot data aes #!key scales line-length width color)Draws one vertical tick per event time. Expects x to hold a list of timestamps per row and y to hold the row index (trial number).
(define spike-data '((trial . (0 1 2 3 4)) (spikes . ((12 25 38) (15 28 42) (10 23 40) (18 30 45) (13 27 41))))) (geom-eventplot spike-data (aes #:x 'spikes #:y 'trial) #:line-length 0.7 #:width 1 #:color "black")
Statistical geometries
[procedure] (geom-histogram data aes #!key scales bins fill color alpha)[procedure] (geom-density data aes #!key scales fill color alpha)
[procedure] (geom-boxplot data aes #!key scales fill color width)
[procedure] (geom-violin data aes #!key scales fill color alpha)
[procedure] (geom-errorbar data aes #!key scales color width cap-width)
[procedure] (geom-crossbar data aes #!key scales fill color width)
[procedure] (geom-linerange data aes #!key scales color width)
[procedure] (geom-pointrange data aes #!key scales color point-size line-width)
Module: gg-guides
Axis and legend rendering. Returns drawers positioned in axis-local coordinates; gg-plot translates them to panel coordinates.
Axes
[procedure] (make-axis-bottom scale #!key label tick-count)[procedure] (make-axis-top scale #!key label tick-count)
[procedure] (make-axis-left scale #!key label tick-count)
[procedure] (make-axis-right scale #!key label tick-count)
Convenience wrappers around:
[procedure] (make-axis scale position #!key label tick-count tick-length tick-width label-size label-offset line-color)- position
- 'bottom, 'top, 'left, or 'right
- tick-count
- target number of ticks (default 5)
- tick-length
- length of tick marks in user units (default 5)
- tick-width
- stroke width of ticks (default 1)
- label-size
- font size for tick labels (default 10.0)
- label-offset
- distance from axis line to label anchor in user units (default 15)
- line-color
- color string (default "\"black\"")
Return a drawer for the axis. The drawer is in axis-local coordinates (the axis line lies at x=0 for vertical axes, y=0 for horizontal ones); the caller must apply with-translate to place it at the panel edge.
Legends
[procedure] (make-legend-continuous scale #!key title position width height label-size)[procedure] (make-legend-discrete scale #!key title position width height label-size)
[procedure] (legend-drawer legend-config)
Module: gg-plot
The top-level declarative API. Import only this module for typical use.
(import gg-plot)
Plot construction
[procedure] (ggplot data . specs)Create a plot-spec record.
data is a columnar alist. specs is a mixed list of:
- an (aes ...) call for the default aesthetic mapping,
- layer constructors (layer-point, layer-line, …),
- scale specifications (scale-x-continuous, …),
- a coordinate system (coord-cartesian, …),
- a faceting specification (facet-wrap, facet-grid),
- a theme (theme-minimal, …),
- (labs ...) for title and axis labels.
(define p
(ggplot data (aes #:x 'time #:y 'value #:color 'condition)
(layer-line #:width 2)
(layer-point #:size 5)
(scale-x-continuous #:name "Time (ms)")
(scale-y-continuous #:name "Response (mV)")
(scale-color-manual #:values '(("Control" . "blue") ("Treatment" . "red")))
(theme-minimal #:base-size 12)
(labs #:title "Treatment vs Control")))
Rendering
[procedure] (render-plot plot-spec backend)Execute the full rendering pipeline and write output. backend is a Cairo backend constructed with one of the make-cairo-*-backend procedures from gg-backend-cairo.
[procedure] (ggsave plot-spec filename #!key width height format scale)Save to a file. format is inferred from the extension (.png, .svg, .ps) or can be given explicitly as 'png, 'svg, or 'ps. width/height default to 800×600.
[procedure] (ggdisplay plot-spec #!key width height)Render to an X11 window.
Plot serialisation
[procedure] (plot->sexp plot-spec)Convert a plot specification to a pure s-expression (no closures). The result can be written to a file with write and read back later.
[procedure] (sexp->plot sexp)Reconstruct a plot-spec from a serialised s-expression.
Layer constructors
All layer constructors accept #:data (override dataset), #:mapping (override or extend the plot-level aesthetic mapping), plus geometry-specific keyword arguments.
Basic geometries
[procedure] (layer-point #!key data mapping size shape alpha color)[procedure] (layer-line #!key data mapping width style color)
[procedure] (layer-path #!key data mapping width color)
[procedure] (layer-area #!key data mapping fill alpha)
[procedure] (layer-bar #!key data mapping fill width)
[procedure] (layer-rect #!key data mapping fill color)
[procedure] (layer-text #!key data mapping size color)
[procedure] (layer-segment #!key data mapping color width)
[procedure] (layer-eventplot #!key data mapping line-length width color)
Reference lines
[procedure] (layer-hline yintercept #!key color width linetype alpha)[procedure] (layer-vline xintercept #!key color width linetype alpha)
linetype is 'solid, 'dashed, or 'dotted.
Statistical geometry layers
[procedure] (layer-histogram #!key data mapping bins binwidth breaks method fill color alpha)- bins
- number of bins (default 30)
- binwidth
- bin width in data units (overrides bins)
- method
- 'sturges (default), 'scott, 'fd, 'equal-width
- kernel
- 'gaussian (default), 'epanechnikov, 'rectangular, 'triangular, 'biweight
- n
- number of evaluation points (default 512)
- coef
- IQR multiplier for whisker length (default 1.5)
- scale
- 'area (equal area, default) or 'count (proportional to n)
- draw-quantiles
- list of quantile levels, e.g. '(0.25 0.5 0.75)
- stat
- 'identity (use ymin/ymax columns) or 'summary (compute from raw values)
[procedure] (layer-linerange #!key data mapping stat fun-ymin fun-ymax color width)
[procedure] (layer-crossbar #!key data mapping stat fun-y fun-ymin fun-ymax fill color width)
[procedure] (layer-col #!key data mapping fun position fill color width)
- position
- 'stack (default), 'dodge, 'fill
Annotation layers
[procedure] (layer-annotate-text text x y #!key size color hjust vjust angle)[procedure] (layer-annotate-rect xmin ymin xmax ymax #!key fill alpha color line-width)
[procedure] (layer-annotate-segment x1 y1 x2 y2 #!key color width)
[procedure] (layer-annotate-arrow x1 y1 x2 y2 #!key color width)
Coordinates are in data space.
For reference lines with full linetype support, the following are recommended over layer-hline/layer-vline when annotation-layer dispatch is needed:
[procedure] (annotate-vline x #!key color width linetype)[procedure] (annotate-hline y #!key color width linetype)
[procedure] (annotate-abline slope intercept #!key color width)
Scale specifications
Scale specification functions return tagged lists consumed by ggplot.
Continuous position scales
[procedure] (scale-x-continuous #!key name limits breaks trans expand)[procedure] (scale-y-continuous #!key name limits breaks trans expand)
- name
- axis title string
- limits
- explicit domain (min max)
- breaks
- explicit tick positions
- trans
- transformation symbol: 'log, 'log10, 'sqrt, …
- expand
- fractional padding added to domain on each side
[procedure] (scale-y-log #!key name base breaks)
Shorthand for a continuous scale with trans: 'log and the given base (default 10).
Discrete position scales
[procedure] (scale-x-discrete #!key name limits)[procedure] (scale-y-discrete #!key name limits)
Color / fill scales
[procedure] (scale-color-manual #!key values)[procedure] (scale-fill-manual #!key values)
values is an alist: '(("Control" . "blue") ("Treatment" . "red")).
[procedure] (scale-color-gradient #!key low high limits)Two-stop continuous gradient.
Coordinate systems
[procedure] (coord-cartesian #!key xlim ylim)Default Cartesian coordinates with optional axis limits.
[procedure] (coord-fixed #!key ratio xlim ylim)Fixed aspect ratio (default 1:1).
[procedure] (coord-flip)Swap x and y axes.
Faceting
[procedure] (facet-null)No faceting (single panel, default).
[procedure] (facet-wrap var #!key ncol nrow scales)Wrap panels by var (a quoted symbol). scales is one of "\"fixed\"" (default), "\"free\"", "\"free_x\"", "\"free_y\"".
[procedure] (facet-grid row-var col-var #!key scales space shrink labeller)Two-dimensional panel grid. Pass #f for either variable to omit that dimension.
Themes
[procedure] (theme-gray #!key base-size base-family)Gray background with white grid lines (the default ggplot2-style theme).
[procedure] (theme-minimal #!key base-size base-family)White background, no border, gray grid lines. base-size defaults to 11.
[procedure] (theme-classic #!key base-size base-family)White background, no grid lines, axis lines present.
[procedure] (theme-bw #!key base-size)White background, black border, gray grid lines.
[procedure] (theme-linedraw #!key base-size base-family)White background, black grid lines and border.
[procedure] (theme-light #!key base-size base-family)Light gray border and grid lines.
[procedure] (theme-dark #!key base-size base-family)Dark background with contrasting grid lines; suitable for bright-colored data.
[procedure] (theme-void #!key base-size)No background, no axes, no grid.
Legend position modifiers
[procedure] (theme-legend-position position)position: 'right (default), 'left, 'top, 'bottom, 'none, 'inside, 'outside.
[procedure] (theme-legend-inside position)position: 'top-right, 'top-left, 'bottom-right, 'bottom-left, 'center.
[procedure] (theme-legend-outside position)position: 'right, 'left, 'top, 'bottom.
Labels
[procedure] (labs #!key title subtitle x y caption)[procedure] (xlab name)
[procedure] (ylab name)
[procedure] (ggtitle title [subtitle])
Collision-avoiding text
[procedure] (geom-text-repel ...)[procedure] (geom-label-repel ...)
Repel overlapping text labels using a force-directed algorithm. Accepts the same arguments as layer-text.
Plot-spec accessors
[procedure] (plot-spec? obj)[procedure] (plot-spec-data spec)
[procedure] (plot-spec-default-aes spec)
[procedure] (plot-spec-layers spec)
[procedure] (plot-spec-scales spec)
[procedure] (plot-spec-coord spec)
[procedure] (plot-spec-facet spec)
[procedure] (plot-spec-theme spec)
[procedure] (plot-spec-labels spec)
Data format
All geometries expect data as a columnar alist, an association list mapping column names (symbols) to lists of equal length:
;; Columnar alist (required by the library) '((time . (0 10 20 30 40 50)) (response . (0.89 1.29 2.35 1.68 2.58 2.08)) (condition . ("A" "A" "A" "B" "B" "B")))
Use columns->rows / rows->columns from gg-data to convert between row-oriented and column-oriented representations.
Examples
Minimal scatter plot
(import gg-plot gg-backend-cairo) (define data '((x . (1 2 3 4 5)) (y . (2.1 3.8 2.9 5.1 4.3)))) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6 #:color "steelblue") (scale-x-continuous #:name "X") (scale-y-continuous #:name "Y") (theme-minimal) (labs #:title "Simple Scatter"))) (ggsave p "scatter.png" #:width 600 #:height 400)
Time series with confidence ribbon
(import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 40 50 60 70 80 90 100)) (value . (0.89 1.29 2.35 1.68 1.15 1.81 2.58 2.08 1.57 1.94 2.35)) (upper . (1.66 1.95 2.72 2.12 1.71 2.21 2.96 2.39 2.00 2.27 2.67)) (lower . (0.55 0.83 1.56 0.75 0.76 1.16 2.19 1.50 0.91 1.16 2.00)))) (define p (ggplot data (aes #:x 'time #:y 'value) ;; Shaded confidence band (layer-area #:mapping (aes #:ymin 'lower #:ymax 'upper) #:fill "steelblue" #:alpha 0.3) ;; Central line and points (layer-line #:width 2 #:color "black") (layer-point #:size 5 #:color "black") (scale-x-continuous #:name "Time (seconds)") (scale-y-continuous #:name "Response (mV)") (theme-minimal #:base-size 12) (labs #:title "Time Series with Confidence Band" #:subtitle "Example of layered composition"))) (ggsave p "timeseries.png" #:width 800 #:height 600)
Multi-series line plot with manual colors
(import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 40 50 60 0 10 20 30 40 50 60)) (value . (1.2 2.3 1.8 2.5 2.1 1.9 2.4 0.8 1.5 1.2 1.8 1.6 1.4 1.7)) (condition . ("Control" "Control" "Control" "Control" "Control" "Control" "Control" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment")))) (define p (ggplot data (aes #:x 'time #:y 'value #:color 'condition) (layer-line #:width 2) (layer-point #:size 4) (scale-x-continuous #:name "Time (ms)") (scale-y-continuous #:name "Response") (scale-color-manual #:values '(("Control" . "blue") ("Treatment" . "red"))) (theme-classic #:base-size 11) (labs #:title "Treatment vs Control"))) (ggsave p "multiseries.png" #:width 800 #:height 600)
Bar chart with categorical x axis
(import gg-plot gg-backend-cairo) (define data '((region . ("V1" "V2" "V4" "MT" "IT")) (firing-rate . (12.5 8.3 15.7 22.1 9.4)))) (define p (ggplot data (aes #:x 'region #:y 'firing-rate) (layer-bar #:fill "steelblue" #:width 0.7) (scale-x-discrete #:name "Brain Region") (scale-y-continuous #:name "Firing Rate (Hz)" #:limits '(0 25)) (theme-bw) (labs #:title "Firing Rates Across Brain Regions"))) (ggsave p "bars.png" #:width 700 #:height 500)
Spike raster (neuroscience event plot)
(import gg-plot gg-backend-cairo) (define spike-data '((trial . (0 1 2 3 4 5 6 7 8 9)) (spikes . ((12 25 38 55 67) (15 28 42 58 71) (10 23 40 52 65) (18 30 45 60 73) (13 27 41 56 68) (16 29 43 59 72) (11 24 39 54 66) (14 26 44 57 70) (17 31 46 61 74) (9 22 37 53 64))) (condition . ("Pre" "Pre" "Pre" "Pre" "Pre" "Post" "Post" "Post" "Post" "Post")))) (define p (ggplot spike-data (aes #:x 'spikes #:y 'trial #:color 'condition) (layer-eventplot #:line-length 0.7 #:width 4) ;; Stimulus onset marker (layer-vline #:xintercept 20 #:color "red" #:linetype 'dashed #:width 1.5) (scale-x-continuous #:name "Time (ms)" #:limits '(0 80)) (scale-y-continuous #:name "Trial #") (scale-color-manual #:values '(("Pre" . "black") ("Post" . "royalblue"))) (theme-classic #:base-size 11) (labs #:title "Spike Raster Plot" #:subtitle "Pre vs Post stimulus"))) (ggsave p "raster.png" #:width 800 #:height 600)
Logarithmic axes
(import gg-plot gg-backend-cairo) (define data '((concentration . (0.1 1 10 100 1000)) (response . (2.1 8.5 42.3 201.7 987.2)))) (define p (ggplot data (aes #:x 'concentration #:y 'response) (layer-point #:size 6 #:color "coral") (layer-line #:width 2 #:color "coral") (scale-x-log #:name "Concentration (uM)" #:base 10) (scale-y-log #:name "Response (% baseline)" #:base 10) (theme-minimal #:base-size 12) (labs #:title "Dose-Response Curve" #:subtitle "Log-log axes"))) (ggsave p "logscale.png" #:width 700 #:height 600)
Faceted plot (small multiples)
(import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 0 10 20 30 0 10 20 30)) (power . (8 12 15 11 5 9 14 10 12 18 22 17)) (band . ("Alpha" "Alpha" "Alpha" "Alpha" "Beta" "Beta" "Beta" "Beta" "Gamma" "Gamma" "Gamma" "Gamma")))) (define p (ggplot data (aes #:x 'time #:y 'power) (layer-line #:color "steelblue" #:width 2) (layer-point #:size 4 #:color "darkblue") (facet-wrap 'band #:ncol 3 #:scales "free_y") (scale-x-continuous #:name "Time (s)") (scale-y-continuous #:name "Power (dB)") (theme-bw #:base-size 10) (labs #:title "Power Across Frequency Bands"))) (ggsave p "faceted.png" #:width 1200 #:height 400)
Multiple output formats
(import gg-plot gg-backend-cairo) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6) (theme-minimal) (labs #:title "Multi-format"))) ;; PNG raster (ggsave p "out.png" #:width 600 #:height 400) ;; High-resolution PNG (larger pixel dimensions) (ggsave p "out-hires.png" #:width 2400 #:height 1600) ;; SVG vector (ggsave p "out.svg" #:width 600 #:height 400) ;; PostScript (ggsave p "out.ps" #:width 600 #:height 400) ;; PDF (A4 portrait, dimensions in points) (render-plot p (make-cairo-pdf-backend "out.pdf" 595 842))
Plot specification serialisation
(import gg-plot gg-backend-cairo) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6) (scale-x-continuous #:name "X") (scale-y-continuous #:name "Y") (theme-classic) (labs #:title "Saved plot"))) ;; Serialise to an s-expression and write to disk (define spec (plot->sexp p)) (with-output-to-file "my-plot.scm" (lambda () (write spec) (newline))) ;; Later: load and re-render (define restored (sexp->plot (with-input-from-file "my-plot.scm" read))) (ggsave restored "restored.png" #:width 700 #:height 500)
Programmatic plot generation
;; Build a plot that layers one line per variable (define (multi-line-plot data vars) (apply ggplot data (aes #:x 'time) (append (map (lambda (var) (layer-line #:mapping (aes #:y var) #:width 2)) vars) (list (scale-x-continuous #:name "Time (s)") (scale-y-continuous #:name "Value") (theme-minimal) (labs #:title (format "Variables: ~a" vars))))))
Architecture notes
Scale training
Scales are mutable: scale-train! extends the domain and scale-map reflects the updated domain. The plot pipeline trains each scale by scanning all layers before any geometry is rendered, which allows automatic axis limits that span the full data range across layers.
Drawer composition model
All rendering is expressed as composable drawer values (drawer?). The pipeline builds one large combined drawer per panel and then executes it in a single pass over the plotter.
Author
Repository
https://github.com/iraikov/chicken-ggplot
Version History
- 1.0
- Initial release
: * Core ggplot engine
License
LPGL-3
References
- Wilkinson, Leland. The grammar of graphics. Springer Science & Business Media, 2005.
- The R ggplot2 package is described in the manuscript, "A layered grammar of graphics", by Hadley Wickham in the Journal of Computational and Graphical Statistics, 2010.