Analysis
The analytic suite reads the statistics of self-organised dynamics at three scales.
These measures are the qualities — the dynamical signatures that underwrite a capacity;
where a score indicates that a capacity is present, these help explain how.
Every measure below carries its equation, a one-line reading, and a Source callout to its
Julia implementation. All operate on channels recorded by the Recorder (off the compute hot
path), so nothing here perturbs a run.
For a concrete, runnable end-to-end example that collects these measures at both scales
from a single forage rollout — per-agent branching, node/agent susceptibility,
correlation length, contact-graph clusters, and a crossshift_null control — see the
two-scale data-collection harness:
Source: examples/forage_criticality.jl.
Criticality (node scale)
Branching ratio — the MR estimator
For a population-activity series , the branching ratio is how much activity one tick begets the next. The naive slope is biased under subsampling (Wilting & Priesemann 2018) — and this is subsampling (a scalar summary of the population). The multistep-regression estimator fixes it: for lags take the (intercept-corrected) slope of on , then fit
and read off the exponential decay — which is invariant to the subsampling that distorts the single-lag slope.
Source: src/analysis/Branching.jl — branching_ratio (per-tick + legacy σ), branching_ratio_mr.
Neuronal avalanches
Threshold into supra-threshold excursions; each avalanche has a size (summed activity) and duration . Near criticality both are power laws, and , tied by the crackling-noise scaling relation
Agreement of the three exponents is a far stronger criticality claim than any single (Beggs & Plenz 2003).
Source: src/analysis/Avalanches.jl — avalanches (τ, α, γ_fit vs γ_pred).
Spectral radius
The dominant magnitude of the learned recurrent matrix, — the linear-stability read that complements the branching (avalanche) read. Tracked over the rollout, and per agent.
Source: src/analysis/Spectral.jl.
Per-node distance-to-target
Each node has a homeostatic target ; its instantaneous strain is . The across-node distribution is an “internal effort map” — which nodes are working, which are settled.
Source: src/analysis/TargetError.jl — node_target_error.
Cross-level — the same measure at two scales
The point of the whole programme: measure the same signature at the node scale and
the agent scale, and ask where each sits relative to its own critical point — because
information transmission is expected to peak near criticality,
so locating the transition at each scale is the prerequisite for everything downstream.
Every criticality estimator takes a level:
:node— each agent’s own reservoir, as its per-agent population rate (fit per agent, then averaged — not node-to-node despite the name),:agent— the per-tick count of agents undergoing a turn event (, default ) — a genuine agent-scale cascade, not the pooled node rate rescaled,:pooled— all nodes of all agents in one series (the legacy default; it mixes distinct reservoirs, so read it as a population summary, not “the reservoir’s” dynamics).
Not every measure is comparable across levels — this matters, because plotting an incomparable pair against each other is a real inferential error. Susceptibility is the natural candidate pair: node () and agent () are formally the same quantity. But a powered re-test refuted the apparent agent-scale signal against the circular-shift null, and branching fails it outright (agent-scale branching is dominated by within-agent maneuvers). So, stated honestly: no ensemble-scale criticality measure has yet survived the null as a validated cross-level quantity — agent-branching is a labelled negative control, and agent-susceptibility is not (yet) trustworthy either. Node-scale measures stand on their own; cross-level pairing remains an open, actively-nulled question. When a pair does survive, compare its peak positions as a control parameter is swept, not raw magnitudes (the prefactors vs differ by an order of magnitude).
Source: src/analysis/ActivityLevels.jl; consumed by Branching / Avalanches / SecondOrder.
Second-order signatures (both levels)
Susceptibility (order parameter = synchrony at node scale, polarization at agent scale), the Fano factor , and the participation ratio PR (effective dimensionality of the activity covariance). A criticality hypothesis predicts these peak together across levels as a control parameter is swept.
Source: src/analysis/SecondOrder.jl.
Null test — crossshift_null
Before a cross-scale coupling number is trusted, run it through the circular-shift null.
Each surrogate independently circular-shifts every agent’s recorded time series, so each
agent’s own dynamics are preserved while the inter-agent timing is destroyed. The
measure is recomputed on the surrogate ensemble; comparing the real value against the
null distribution separates genuine cross-agent coupling from what any independent set of
single-agent series would produce by chance. Returns
(real, null_mean, null_std, ratio) over n_shifts draws — a ratio near means the
apparent coupling is indistinguishable from the null. Because the null strips both real
coupling and common-source drive, read the coupling as the vision-on minus vision-off
difference, not the raw ratio.
Source: src/analysis/NullTest.jl — crossshift_null.
Collective (agent scale)
These are descriptors (qualities), not competence scores — they measure how a swarm is organised, read alongside a task’s capacity-indicator, never as a competence measure in their own right (see Scoring).
- Polarization — heading alignment, disordered → aligned.
- Milling — rotational order about the torus-aware circular centroid.
- Cohesion — mean nearest-neighbour + pairwise distance (periodic-boundary aware).
- Swarm regime — a discrete label (polarized, milling, swarming, or static) from , milling, and speed.
- Correlation length — the distance at which the velocity-fluctuation correlation crosses zero (Cavagna et al. 2010 form: subtract the global mean velocity, normalize once globally).
- Contact-graph clusters — build the per-tick within-vision-radius contact graph and summarize its connected components: number of components, largest-component fraction, and mean component size (torus-aware). A graph-level readout of how the swarm fragments and coalesces (surfaced in sweeps as the
contact_clustersmeasure).
Source: src/world/Metrics.jl (polarization, milling, cohesion) and src/analysis/SwarmAnalysis.jl (swarm_regime, correlation_length, contact_graph_clusters).
Information flow
Transfer entropy — directional, order-1 discrete plug-in estimator:
Two variants: node-to-node within a reservoir (spike trains), and agent-to-agent (binarised heading change) — the direct measure for the social-foraging “do they use each other as a guide?” question. Experimental (plug-in bias; a KSG upgrade is flagged).
Source: src/analysis/TransferEntropy.jl — transfer_entropy, node_transfer_entropy, agent_transfer_entropy.
References
Beggs & Plenz (2003), J. Neurosci. · Wilting & Priesemann (2018), Nat. Commun. · Del Papa, Priesemann & Triesch (2017), PLOS ONE · Cavagna et al. (2010), PNAS.