Gribouille

repository·main·Indexed 42 days ago

https://github.com/mcanouil/gribouille

A Typst library for creating elegant, declarative graphics based on the Grammar of Graphics, inspired by ggplot2 (R) and plotnine (Python). It provides a declarative API using the plot() function, supporting various geoms, stats, scales, and themes.

Tokens
7.3K
Snippets
13
Records
33
Agent score
55%

What's inside Gribouille

  1. Understand the Gribouille Pipeline abstractions

    main

    The Gribouille plotting pipeline is composed of several core abstractions that define how data is transformed and rendered:

    • spec (Plot Specification): The primary dictionary built by the user and consumed by render-plot to define the entire visualization.
    • layer: An entry within spec.layers. Each layer contains a name (the geom), a mapping (aesthetic connections), data, and params (layer-specific settings).
    • geom (Geometric Layer): The visual representation of data (e.g., points, lines). Every geom must export a draw(layer, ctx) function.
    • aes (Aesthetic Mapping): Created via the aes() constructor to map data columns to visual channels (e.g., aes(x: "col", y: "col", colour: "col")). This results in a flattened mapping dictionary.
    • stat (Statistical Transform): A transformation applied to data (e.g., calculating means or counts) via the stat_* namespace.
    • pos (Position Adjustment): Adjustments to how geoms are placed, such as stack, dodge, fill, or jitter.
    • coord (Coordinate System): Defines the coordinate space, such as cartesian, fixed, radial, or transform.
    • ctx (Per-draw Context): A dictionary passed to every geom's draw method. It contains environment information like trained scales, palette, theme, and canvas dimensions (canvas-w/canvas-h).
    • scales: A dictionary fed to plot() that binds aesthetics to specific scales. A later entry for an aesthetic will override previous ones.
  2. Understand the Gribouille data pipeline

    main

    Gribouille follows a unidirectional data flow. Data moves through a fixed sequence of stages where each stage processes the output of the previous one. No stage can reach back into an earlier stage in the pipeline.

    The Pipeline Sequence: data ──▶ stat ──▶ position ──▶ scale ──▶ coord ──▶ facet ──▶ theme ──▶ render

  3. Configure Legend placement

    main

    Legends are positioned using a placement record and can be sized using extents.

    • placement: A record containing (side, align, dx, dy, direction, order, byrow) consumed by legend.draw.
    • side: The placement side. Options are:
      • "top", "right", "bottom", "left" (for margin slots).
      • "inside" (for panel-overlay placement).
      • "none" (to suppress the legend).
    • extents: A dictionary (top, right, bottom, left, inside) returned by legend.estimate-extents representing cm totals and inside-anchor records.
  4. Understand Gribouille geometry and helper terminology

    main

    When working with geometries, statistics, or layout helpers, the following terms are used:

    • band: A rectangular shaded region.
    • gap: The x-distance between adjacent bin centres.
    • pad: Padding (in cm) around laid-out content.
    • sub: A nested theme element (e.g., theme-sub-axis).
    • qq: Quantile-quantile related functions (geom-qq, stat-qq, stat-qq-line).
    • segment: A thin connector line from a label to its anchor (enabled via segment: true on text/label/typst geoms).
    • route: The output of route-segment, which can be a straight (p0, p1) line, an L-bend (p0, mid, p1), or none.
    • se: Standard error (e.g., mean-se, geom-errorbar).
    • sp: Species (used in example datasets like penguins/iris).
    • mm: Millimetres (used in example datasets).
    • cb: A callback closure.
    • fn: A suffix for names holding a closure rather than a value (e.g., key-fn, to-stat-fn). These are read once and called many times.
  5. Configure the social card appearance

    main

    The social card image is generated from several input files. To change its content, branding, or typography, modify the following files and then re-run ./build.sh:

    • Content/Figure: examples/gribouille.typ (the homepage penguins figure).
    • Typst Configuration: docs/_typst-preamble.typ.
    • Branding/Colors: docs/_brand.yml (specifically the light palette).
    • Typography: docs/assets/fonts/*.woff2.
    • Logo: docs/assets/images/logo.svg.
  6. Benchmark specific cases and variants

    main

    Gribouille provides several built-in cases that represent different scaling behaviors:

    CaseGeomScaling
    pointgeom-pointLinear: one marker per row
    linegeom-lineLinear: one vertex per row, single path
    colgeom-colLinear: one bar per row
    tilegeom-tileLinear: one rectangle per row
    polygongeom-polygonFlat in marks: many vertices on twelve rings
    bin2dgeom-bin-2dSublinear: rows aggregated into a fixed grid
    boxplotgeom-boxplotSublinear: rows reduced to a per-group summary
    facet-smoothfacet-wrap + geom-smoothPer-panel stat re-training on a per-row point layer

    Variants allow you to isolate the cost of specific render settings. For example, the point case supports:

    • base: small filled circle (Reference)
    • large: larger filled circle
    • star: star glyph
    • alpha: translucent small circle

    If you pass --variants to the CLI, it overrides the case's default variants and applies the listed ones to every selected case.

  7. Understand Gribouille colour and theme terminology

    main

    Gribouille uses specific shorthand for theme and colour properties. Use these terms when configuring palettes or theme elements:

    • pal: The colour palette dictionary (can be discrete or continuous).
    • ink: The foreground colour (primary text/line colour), defaults to black.
    • paper: The background colour (canvas/panel background), defaults to white.
    • accent: The highlight colour used by some geometry defaults.
    • tint: The fill role for bars or areas. It is calculated as colour-mix(ink, paper, fill-tint-amount), where the default fill-tint-amount is 0.35 (equivalent to grey35).
  8. Configure scales using the scales() dictionary

    main

    Scales in Gribouille are aesthetic-agnostic. You do not use prefixed constructors like scale-x-log10(). Instead, you pass the appropriate constructor into the scales() dictionary under the key of the aesthetic it controls.

    Pattern: scales(aesthetic: scale-constructor())

    Examples:

    • scales(x: scale-log10()) for a logarithmic x-axis.
    • scales(colour: scale-viridis-d()) for a discrete color palette.
    • scales(y: scale-continuous(labels: format-comma())) for formatted y-axis labels.
    #plot(
      data: penguins,
      mapping: aes(x: "flipper-len", y: "body-mass", colour: "species"),
      scales: scales(
        x: scale-continuous(),
        y: scale-continuous(labels: format-comma()),
        colour: scale-discrete(limits: ("Adelie", "Chinstrap", "Gentoo"), palette: (rgb("#ff8c00"), rgb("#008B8B"), rgb("#800080")),
      ),
    )
  9. Understand Scale training and transformations

    main

    Scales in Gribouille manage the relationship between data values and visual values. Key concepts include:

    • trained (Scale-trained dict): Stored in ctx.trained.<aes>, this contains the metadata for a resolved scale, including its type, domain, transform, and typst-mark. It is built during the training phase.
    • fwd (Forward Transform): The process of converting raw data into a transformed value (e.g., transform-fwd).
    • inv (Inverse Transform): The process of converting a transformed value back into raw data (e.g., transform-inv).
    • sec (Secondary Axis): A secondary axis configured via sec-axis() and bound to the primary scale.
    • stub (Deferred Scale Spec): A temporary scale specification (kind: "scale", name, args) created by a scale-* constructor and later resolved by scales().
  10. Understand Geometry and Panel coordinate systems

    main

    When rendering geoms, Gribouille uses several coordinate and measurement concepts:

    • cx / cy (Canvas X/Y): The final pixel coordinates within the panel coordinate system after scales have been applied.
    • px / py (Panel X/Y): The range of the panel in pixels, found in ctx.px-range and ctx.py-range.
    • nudge-x / nudge-y: Aesthetics used by geom-text, label, or typst to offset text. A numeric value represents data/level units, while a length represents canvas units.
    • aabb (Axis-Aligned Bounding Box): A dictionary (x-lo, y-lo, x-hi, y-hi) representing a rectangular area.
    • lo / hi / mid: Represent the lower bound, upper bound, or midpoint of an interval (e.g., whiskers or error bars).
    • ext (Measured Extents): The (width, height) in centimeters measured for labels to ensure proper layout.
  11. How Gribouille plots work (Mental Model)

    main

    Gribouille follows a grammar-of-graphics approach where a plot is constructed through a forward-only pipeline:

    data → stat → position → scale → coord → facet → theme → render

    Key Components:

    • data: A dictionary of column arrays or a built-in dataset (e.g., penguins, mpg, economics).
    • mapping: aes(...): Maps data columns to aesthetics. Supported channels include x, y, colour, fill, shape, size, alpha, linetype, and label. Note: Use British spelling colour, not color.
    • layers: A tuple of geom-* objects. Each geom can override stat, position, mapping, and key (legend glyph). Stat-backed geoms use stat: auto by default.
    • scales: Defines how values map to axes and palettes.
    • coord, facet, labels, guides, theme: Control coordinate systems, faceting, labeling, legends, and visual styling respectively.
    • Late Binding: Use functions like after-stat(...), after-scale(...), from-theme(...), and stage(...) for advanced transformations.
    #plot(
      data: penguins,
      mapping: aes(x: "flipper-len", y: "body-mass", colour: "species"),
      layers: (geom-point(),),
      theme: theme-minimal()
    )
  12. Understand the Guide Layer abstractions

    main

    The Guide Layer manages how axes, legends, and colour bars are drawn. Key abstractions include:

    • entry: A single drawn row in a guide (e.g., an axis tick or legend row). It is represented as (value, frac, label, tier) or (start, end, label, depth) for ranges.
    • entries: An array of entry dictionaries.
    • tier: The tick weight ("major", "mid", or "minor") which determines tick length and label visibility.
    • depth: The nesting level for range entries (0 is nearest the panel).
    • gctx: The guide context (src/guide/gctx.typ) containing position, aesthetic, mode, direction, axis, span, and injected closures like place, tick-length, key-draw, and bar-draw.
    • mode: The guide mode ("axis" or "legend") derived from the aesthetic.
    • across: The thickness axis of a guide side, growing away from the panel.
    • along: The axis the guide runs along (paired with across).
    • place: A (frac, across) -> (x, y) closure on a gctx used for mapping guide points.
    • role: The theme surface role requested by a part (e.g., "text", "ticks", "line").
    • side-pt: A side-ordered point used to allow a single routine to serve all four sides of a plot.
    • sweep: The along-guide angle in radians. A part running along the guide is a straight segment if none, otherwise a sampled polyline.
    • span: The along-guide length in cm. Parts laying out contents in cm divide by this value.
    • metrics: The cm allocated to a legend key cell (includes off, drop, last, line-h, slack, lead, label-lead, label-drop).
    • flow: The direction of a key label relative to its key ("right" for vertical legends, "below" for horizontal).
    • gizmo: A guide part that paints its own body (e.g., a colour bar in src/guide/gizmo/).
    • band (Guide context):
      • On a colour bar: The cm reserved across the guide past the strip.
      • On an axis: The cm between the panel edge and the ticks/gap/labels (built by axis-band).
    • lead: The cm reserved before a label for the key glyph or tick flank. label-lead is the specific offset where the label is pinned.
    • justify: The alignment of a key grid inside the guide width (distinct from label-align).