Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Diagrams

In Argon, the source is the truth and visuals are lenses onto it. A diagram is not a separate document you maintain alongside the model; it is a block of source code in the same file as the rest of the model, evaluated by the compiler, rendered to SVG or OntoUML JSON by ox diagram. (PNG / PDF are produced by passing the SVG through an external rasterizer such as rsvg-convert or cairosvg.)

When the model changes, the diagram changes with it. When you want to look at a different facet of the same model, you write a different diagram block — not a different ontology.

This chapter teaches the diagram surface and ends the running example with a set of pictures of the lease model.

A first diagram

diagram "lease participants" {
    include {
        Property,
        Person,
        Tenant,
        Landlord,
        Lease,
        ResidentialLease,
        CommercialLease,
    }
}

Render it:

$ ox diagram "lease participants"

ox diagram writes one SVG per diagram into the output directory (diagrams/ by default; override with -o <dir>). The file for the example above lands at diagrams/lease participants.svg — an SVG showing the seven concepts and the supertype + role + relator edges between them. No layout work, no manual node placement — the renderer’s layout engine handles that.

Anatomy of a diagram block

Three slots:

diagram "<name>" [from "<base>"] {
    <statements>
}
  • "<name>" is a string literal — diagram names admit spaces and Unicode so they read well in figure captions.
  • from "<base>" is optional inheritance: a diagram can derive from another by adding/removing/overriding statements. We use it sparingly; it is occasionally useful when you have a base diagram for an audience and want a tightened version for a different one.
  • <statements> are the eight families of diagram statements — include/exclude, set/show, color/label/highlight, group/layer/collapse, layout/direction/align, ensure/encourage, title/description, format/size.

Most diagrams need only a couple of statement families. We will mostly use include/exclude.

Source forms

The include statement takes a source. Argon admits seven source forms:

FormExampleUse
Explicit listinclude { Person, Lease }Enumerate the concepts you want
Wildcardinclude *Every concept in scope
Module scopeinclude mod ufo::aEvery concept in a module
Module globinclude mod ufo::a::*Every concept in a module subtree
Predicate filterinclude where metatype == kindFilter by a structural predicate
Neighborhoodinclude 2 from LeaseConcepts within N hops of an anchor
Relation traversalinclude connected_by mediates to LeaseConcepts reachable via a specific relation

The same forms work for exclude (which removes concepts from the diagram). exclude runs after include, so the typical pattern is “include broad, exclude narrow.”

Pipe chains

A trailing pipe-chain refines the source via predicate filters:

include * | where metatype == kind | where rigidity == rigid

Each | where ... filters the running selection. The grammar inside where is the same predicate vocabulary you use in rule-atom positions: comparisons, type tests, and the ontology-aware predicates that come from the metatype calculus (metatype, rigidity, sortality, …).

Use pipes when you want to show a facet of the model rather than every concept — “all rigid kinds,” “every concept with a non-empty lifecycle,” and so on.

Styling and layout

A handful of statement families let you reach into the visual:

diagram "lease participants" {
    include { Person, Tenant, Landlord, Property, Lease }

    color by metatype {
        kind: blue,
        role: green,
        relator: orange,
    }

    layout sugiyama(spread: 1.5)
    direction left-to-right
    format svg, png
}
  • color by metatype { ... } — colour-code nodes by metatype. Other axes (color by rigidity, color by sortality) work too.
  • layout <algo>(...) — pick a layout algorithm. sugiyama is the default; alternatives include force, tree, circular. The (...) arguments are layout-specific.
  • directionleft-to-right, right-to-left, top-to-bottom, bottom-to-top.
  • format svg, pdf, png — declare output formats at the diagram level. The CLI flag --format overrides.

You can usually leave layout alone for small diagrams; the defaults work well up to about 30 nodes.

OntoUML round-trip

For audiences who use OntoUML tooling — Visual Paradigm, Menthor Editor, the ontouml-vp-plugin — Argon can emit an OntoUML JSON document instead of (or in addition to) a visual format:

$ ox diagram "lease participants" --format ontouml

The OntoUML format writes a single <package-name>.ontouml.json whose diagrams array carries every (filtered) diagram as an OntoUML 2.0 diagram-section entry — landing in the same output directory (diagrams/ by default; override with -o <dir>).

Round-trip is layout-stable: the visual layout decisions an OntoUML editor adds when a human curates the model can be preserved through a @[layout] attribute and round-tripped on re-export. The mechanism is in flight; treat it as the way to keep visual edits when collaborating with OntoUML-native colleagues.

Inheriting a diagram

Use from "<base>" to extend a base diagram with refinements:

diagram "lease participants" {
    include { Person, Tenant, Landlord, Property, Lease }
}

diagram "lease lifecycle" from "lease participants" {
    include connected_by lifecycle to Lease
        | where metatype == phase

    color by phase {
        Pending: gray,
        Active: green,
        Expired: yellow,
        Terminated: red,
    }
}

"lease lifecycle" carries everything from "lease participants" and adds the lifecycle phases plus a colour scheme. Inheritance composes — you can derive again, and again — though in practice two layers is plenty.

Status note: lifecycle-as-relation projection. Today’s diagram parser does not yet recognise a lifecycle { … } block as a binary-relation source for connected_by, so the connected_by lifecycle form above currently produces OE1102 unknown relation 'lifecycle'. The form shown is the trajectory; the tutorial therefore ships its participants and ontology-overview diagrams and defers the lifecycle projection to a follow-up. If you need a phase view in the meantime, render the lifecycle states by including the phase concepts directly: include { Pending, Active, Expired, Terminated }.

Variations

A handful of common diagram shapes worth remembering.

Module map

The shape of a package’s vocabulary, seen at one glance:

diagram "lease-tutorial overview" {
    include mod lease_tutorial::*
    color by metatype {
        kind: blue,
        role: green,
        relator: orange,
        phase: gray,
    }
}

Neighborhood around a focal concept

What does Lease connect to, two hops out?

diagram "lease neighborhood" {
    include 2 from Lease
}

Filtered facet

Just the rigid sortals — the things with their own permanent identity:

diagram "rigid sortals" {
    include * | where metatype == kind
}

Relator and its mediates

The lease and only the concepts it mediates:

diagram "lease-mediated" {
    include { Lease }
    include connected_by mediates to Lease
}

Edge cases worth knowing

  • Diagrams are evaluated, not stored. ox diagram re-renders from source every time. There is no cached SVG that drifts from the model.
  • include accumulates; exclude subtracts. Order between an include and a later exclude matters; order between two includes does not.
  • Anchor concepts must exist. include 2 from Lease fails to compile if Lease is not in scope.
  • Diagram names are visible in ox show. ox show diagrams enumerates every diagram in the package.

Putting it in the running example

Add src/diagrams.ar:

use lease::*

diagram "lease participants" {
    include {
        Property,
        Person,
        Tenant,
        Landlord,
        Lease,
        ResidentialLease,
        CommercialLease,
    }
}

diagram "lease ontology overview" {
    include 2 from Lease
}

(The "lease lifecycle" projection shown earlier in this chapter is on the roadmap — see the Status note above. The tutorial ships the two diagrams that compile cleanly today and will pick up the lifecycle projection when the diagram parser learns to treat lifecycle as a structural source.)

We do not need to re-export diagrams through prelude.ar; they are runtime artifacts, not items consumers use.

Render them:

$ ox diagram --all
   Rendering lease-participants.svg
   Rendering lease-ontology-overview.svg
✓ 2 diagrams.

You now have two SVGs of the model. The first shows the structural skeleton around the lease’s participants; the second gives a two-hop overview around Lease.

Diagrams in the example workspaces

Two example packages ship diagrams in source form:

  • argon/examples/pizza/src/diagrams.ar (when present) renders the Manchester pizza ontology’s class lattice with color by metatype to distinguish kind (the abstract Food, Pizza) from subkind (specific pizza varieties) from concrete phase examples. The diagram is the same data as the source — change the supertypes in prelude.ar, re-render, the picture updates.
  • argon/examples/ontology-tour/ is itself a “diagram-driven tour”: the package re-exports concepts from pizza, foaf, and wine, and the tour diagram uses include 2 from tour_role (a pub metaxis tour_role for type { event, venue }) to show the cross-package connections.

Both packages render with ox diagram --all from inside the workspace; the SVGs land in diagrams/.

Summary

A diagram block is source code that compiles to a picture. The body uses include/exclude statements with seven source forms and pipe-chain filters; styling and layout are first-class statements; from "<base>" lets diagrams inherit from one another. ox diagram renders to SVG or OntoUML JSON; raster formats (PNG / PDF) are produced by piping the SVG through an external rasterizer. The lease tutorial ships two diagrams today (structural participants + ontology overview), generated from the same model the rest of the book has been building; the lifecycle projection lands when the diagram parser picks up lifecycle-as-source. When the model changes, the diagrams catch up automatically.