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:
| Form | Example | Use |
|---|---|---|
| Explicit list | include { Person, Lease } | Enumerate the concepts you want |
| Wildcard | include * | Every concept in scope |
| Module scope | include mod ufo::a | Every concept in a module |
| Module glob | include mod ufo::a::* | Every concept in a module subtree |
| Predicate filter | include where metatype == kind | Filter by a structural predicate |
| Neighborhood | include 2 from Lease | Concepts within N hops of an anchor |
| Relation traversal | include connected_by mediates to Lease | Concepts 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.sugiyamais the default; alternatives includeforce,tree,circular. The(...)arguments are layout-specific.direction—left-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--formatoverrides.
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 forconnected_by, so theconnected_by lifecycleform above currently producesOE1102 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 diagramre-renders from source every time. There is no cached SVG that drifts from the model. includeaccumulates;excludesubtracts. Order between anincludeand a laterexcludematters; order between twoincludes does not.- Anchor concepts must exist.
include 2 from Leasefails to compile ifLeaseis not in scope. - Diagram names are visible in
ox show.ox show diagramsenumerates 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 withcolor by metatypeto distinguishkind(the abstractFood,Pizza) fromsubkind(specific pizza varieties) from concretephaseexamples. The diagram is the same data as the source — change the supertypes inprelude.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 usesinclude 2 from tour_role(apub 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.