The catalogue
geoml.catalogue (0.7.0) describes every class and function a model or a
script may use, as JSON, for programs that build geoML models without
reading its code. GeoScape’s network editor is the first: its networks
round-trip through geoML’s saved spec, and it offers nothing the catalogue
has not declared. The format is specified on GeoScape’s side, in its
docs/geoml-catalogue.md; this record is geoML’s half.
What comes from where
From the code: every key is a class’s path as persistence records it
(module.qualname, geoml.latent.network.BasicGP rather than a re-export),
so a catalogue entry and a saved spec name a class the same way. The
parameters come from inspect.signature, which follows Parametric’s
wrapper to the real constructor; their types come from the annotations
where the module has them, their descriptions from the docstring’s
Parameters section, and a class’s summary from the first paragraph of its
docstring, or of its constructor’s where the class has none. The version,
and the format number a model save carries, are read from the package.
From declarations: every public class of the six catalogued modules
(latent.network, latent.fourier, kernels, transform, warping,
likelihood) carries a _catalogue dictionary, assigned in a block where
its module ends: its category, a label, its stability, its parents, how its
size follows from its arguments, whether inducing points pass through it
and whether it needs them, how it chains, the variable types a likelihood
accepts, and the types of arguments no annotation states. The block rather
than the class body keeps the classes as they were and the declarations in
one place per module. latent/network.py states every argument’s type
there, being outside pyright on purpose; most warping and transform
constructors carry none either.
Amendments to the format (agreed 2026-09-15)
Four were needed for the declarations to be true, and the spec was revised with them:
propagates_inducingmay be"parents": true exactly when every parent passes inducing points on and all share one root.Add,LinearCombination,Concatenateand every one-parent node behave so.parentsmay name the categories a parent must belong to:GPWalk’s parent must be a GP.A likelihood’s size may be
{"rule": "warping"}: its warping’s output width, the warping taking the variable’slength.No default is an object.
BasicInput,kernels.Covarianceandkernels.Lineardefaulted to oneIdentity()built at import and shared by every instance; they taketransform=Noneand build their own.
Added while building, and in the spec too: nullable on every parameter,
true where null is an answer of its own (a prior’s strength, where it
switches the prior off). A transform’s or warping’s size is {"in", "out"}, in null meaning any width and same_as_parent meaning the width
it took; chain.attaches_to names the parameter a chain is handed to.
Changed with GaussianMixture (0.8.0), the one node whose parents come
in two kinds: parents is a list of slots on every node, one per
constructor parameter taking parents and empty for an input – one form
for a parser rather than an object or a list – and a slot may carry the
size its parent must have (the weights,
one per component: {"rule": "len", "param": "components"}); a common
size rule may name the slot it reads. And every latent node carries
gaussian – true, false or "parents" – read off the class
attribute _GAUSSIAN rather than declared a second time, because a leaf
that is not Gaussian trains on its realizations.
Added in 0.8.3 for GeoScape’s items 35 and 36: workflow.fit.folds names
spatial_k_fold, and a container’s methods may hold what its family
declares for itself (CLASS_METHODS, inherited by subclasses) – the block
set’s split, crossed_by and unbalanced. Not a shared list by name:
Mesh3D.split separates a mesh’s pieces and would have been published as
the block set’s operation. A mesh argument is typed data:Mesh3D.
Found on the way
Each of these would have made a declaration false, and the tests below caught or would have caught it:
Identity()andPeriodic()given explicitly could not be saved. Neither they nor_Transformdefine__init__,Parametric.__init__was never wrapped, and no arguments were recorded;__init_subclass__now wraps an inherited initializer nothing has wrapped.Concatenatedeclared that it passed inducing points on without asking its parents, so a GP on aConcatenateof aMultiplywas built and failed at its first refresh. It asks them now, asAdddoes.An operation given no parents failed with an
IndexError,GPWalkon anything but a GP with anAttributeError, andMultiStructureGPtook one structure. All three refuse with a message.warping.__all__lacked the four parametric links andkernels.__all__CovarianceandRationalQuadratic.
Stability
By the user’s choice, conservatively: experimental are the two flows, the
four fault transforms, GaussianInput, UncertainInputGP, Mixture and
the legacy Spline warping; internal are geoml.latent.fourier,
BellFault2D (kept for saved models), NormalizeWithBoundingBox (a
BoundingBox argument no store can hold) and GradientIndicator (built by
the model itself for directional data). Everything else is public.
Every claim, tested
test_catalogue.py fails on a public class without a declaration of its
own – a subclass would otherwise inherit its parent’s – and checks every
declaration against its class: each node built on stand-in parents at two
sizes and its size compared with the rule, a GP placed on it to see whether
inducing points pass, and a parent that passes none put under it; each
transform and warping applied to data of the width it declares; every
likelihood trained a step on every variable type it accepts; every class
that can be offered sent through persistence’s encoding and back; and the
catalogue written by two processes under different hash seeds, compared
byte for byte. 238 tests, 78 s, 3.3 GB at the peak.
Left out
default_warping, optional in the spec, is not given: what to propose
depends on the variable’s sign and closure, which a likelihood class cannot
know. The catalogue is written by python -m geoml.catalogue wherever geoML
is installed; publishing it beside each release, so a reader need not
install TensorFlow to have it, would be the docs workflow’s job.