Sense of Direction

Proof

Every number the piece runs on, and where each one came from. It is meant to be searched rather than read, so every section has an address.

No measurement below is typed into this page. Each is read, when the site is built, either straight out of the code the piece runs or out of a published results file. If a number changes in the model it changes here, and if a measurement has not been made its section says so and keeps its place.

Four things were measured against results published from living flies. Two did not pass, one came back with nothing, and the fourth had no published target to hit. All four are below at the same size, and a partial match is counted as a partial match.


(a)
Read from the connectome.
(b)
A published physiology result implemented as a rule.
(c)
A physical model or a published measurement.
(d)
A stated free parameter.

The four results(a) + (b) + (d)

Bump width and drift
PARTIAL
2 of the 3 criteria are met: a single bump forms from the raw MaleCNS synapse counts and holds for the whole run, at 92.6° full width at half maximum against a target of 90°. The third is not met and is not scored as met: the bump does not drift in darkness, Seelig & Jayaraman 2015 report that it should, and the artefact records that criterion as neither passed nor failed.
Hue selectivity
PARTIAL
1 of 4 outputs match their published hue selectivity outright; 2 match partly and are counted as partial rather than folded in with the passes; Tm20 fails, and the mechanism for why is stated rather than hidden.
The closed colour loop
DULL
The loop converges to a fixed point at every one of the 4 pigment orderings and in all 25 cells of the parameter scan. Measured to be dull rather than assumed to be lively, with no noise added to disguise it.
Colour under the light a piece runs in
REPORTED
Reported, not scored: there is no published target to hit, so there is nothing to pass. Separation 0.067, conditioning 0.033, and two of the four outputs barely move across the whole ensemble.

A null result deserves the same scrutiny as a positive one, which is the only reason it is worth printing: a fallback presented as a success would make everything else on this page worthless.

Dataset and hashes(a)

Dataset
male-cns:v1.0
The version string carried by every published results file.
Source
male-cns.janelia.org/download
Flat files over plain HTTPS. No access token is needed for any file used here.
Licence
CC-BY 4.0 (HHMI Janelia / Google Research / Univ. Cambridge / MRC LMB)

The sha256 of each raw input, as recorded by the stage that read it. Several stages hash the same downloads independently, so this table is a cross-check as well as a record: had two results files been built from different copies of a file, the line under it would say so.

body-annotations-male-cns-v1.0-minconf-0.5.feather
2177e24611…1f99a9a3b2
Declared by column.json, pace.json, parity.json, ring.json.
body-neurotransmitters-male-cns-v1.0.feather
95c9289220…8da8879621
Declared by column.json, pace.json, ring.json.
connectome-weights-male-cns-v1.0-minconf-0.5.feather
e35da783d1…2c1a56afc1
Declared by column.json, pace.json, parity.json, ring.json.

Every file that declares a hash for these 3 inputs declares the same hash.

Every number on this page regenerates from those three downloads. Each stage is deterministic and seeded, and every seed is printed below, so a rerun that produces different numbers means a different input — and the hashes say which.

What is in the model(a)

The heading circuit
348 bodies
25,553 edges, 349,786 synapses, 17 types. The weights are the MaleCNS connection weights as downloaded, and are never edited.
Wedges
16
Heading is the population vector of EPG over the wedges. EPG cells per wedge: 2, 4, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2. The counts are uneven because the dataset is uneven; they are not balanced.
Steering readout
omega = k * (rate[DNa02_R] - rate[DNa02_L])
DNa02 left body 523769, right body 10360.
Sign provenance
consensus_nt 169 · ground_truth 179
Signs come from the dataset’s own neurotransmitter tables where it has them, ground truth first. Literature is the fallback, not the source.
The colour circuit
99 cells
424 edges, 4,627 synapses. Unit: one medulla column (the home column) plus its six immediate hex neighbours, right optic lobe.
Why not one column
No single column in MaleCNS v1.0 contains the SPEC §3.1B roster. Pale and yellow are alternative ommatidial types: a column has either R7p/R8p or R7y/R8y, never both, so 'R8 (p/y)' is already a multi-column request. Measured: 0 of 892 right-lobe columns contain all 15 types and only 2 of 892 contain one of each functional group. The seven-column hex disc is the smallest unit that does, and it is also the documented receptive-field extent of the multi-columnar cells the spec names (Dm8 pools R7 across neighbouring columns; Dm9 spans several).
Cells per type
Dm8a 2 · Dm8b 2 · Dm9 1 · L1 7 · L2 7 · L3 7 · R1-R6 42 · R7p 4 · R7y 3 · R8p 4 · R8y 3 · Tm20 7 · Tm5a 3 · Tm5b 2 · Tm5c 5
Input retained
Fraction of each type’s total input synapses that stays inside this seven-column patch: Dm8a 0.65 · Dm8b 0.54 · Dm9 0.37 · L1 1.00 · L2 1.00 · L3 0.98 · R1-R6 1.00 · R7p 0.47 · R7y 0.53 · R8p 0.40 · R8y 0.42 · Tm20 0.84 · Tm5a 0.66 · Tm5b 0.30 · Tm5c 0.52. A cell whose number is low is being driven, in the real fly, by cells that are not in this model.
The pace circuit
24 bodies
Types: ExR2, FB1C, FB1H, FB2A, FB4L, FB4M, FB5H. Measured edges with the heading circuit: 6,200 synapses in, 6,454 synapses out. Measured, not assumed. The dopaminergic cells are recurrently wired with the ring in both directions, so the dopamine level in the model is driven by circuit A rather than imposed as a free input.

How a cell was assigned to a column(a)

Each cell in the colour circuit has to be placed in a medulla column, and the assignment is a claim, so the rule is quoted in full rather than summarised. It has no threshold, which is the same as saying it has no knob. The last paragraph is the part worth reading: the rule is checked against a fact it was never given.

Assign every circuit-B cell to one column of the hex lattice.

THE RULE, in full, because it is a claim on the proof page:

1. ANCHORS.  A cell of type L1, L2, L3 or Tm20 carrying an (assignedOlHex1,
   assignedOlHex2) pair is labelled with that pair. This is the dataset's own
   label, not ours. These four types tile the medulla one cell per column.
2. ROUNDS.  Repeat until nothing changes. For every still-unlabelled cell c and
   every column k, score
       w(c, k) = sum over labelled cells l of column k of  W[c, l] + W[l, c]
   i.e. total synapses between c and the cells already assigned to k, in either
   direction, exactly as counted in the connectome. Every cell with a non-zero
   score is labelled in the same round with its arg-max column; ties go to the
   lowest (hex1, hex2). Newly labelled cells become sources for the next round.
3. PURITY.  p(c) = w(c, home) / sum_k w(c, k) is recorded per cell. It is a
   diagnostic, not a filter — there is no threshold, so there is no knob.

Two rounds converge. Round 1 labels everything with direct anchor contact
(R1-R6 via L1/L2, R8 via L1/Tm20, Tm5a/b/c via L3/Tm20, Dm9 via L3). Round 2
labels R7 (via R8 and Dm8) and the remaining Dm8.

The rule is validated against a fact it was never given: pale/yellow identity.
R7 and R8 of the same ommatidium must be the same subtype. Across the 438
columns that receive exactly one R7 and one R8, agreement is 438/438 = 1.000
against a chance level of 0.441. The rule also puts Dm8a in yellow columns
(201 y vs 8 p) and Dm8b in pale columns (94 p vs 39 y), which is the published
Dm8 subtype/ommatidium association.
Anchors
L1, L2, L3, Tm20
Anchor labels come from assignedOlHex1 / assignedOlHex2 in the MaleCNS annotations. Converged in 2 rounds.
Excluded
R7d, R8d
R7d: dorsal rim area, polarisation not colour · R8d: dorsal rim area, polarisation not colour

The query that defines the pace circuit(a)

The pace circuit is the PPM3-cluster dopaminergic neurons. MaleCNS v1.0 has no PPM3 type string — the public Cell Type Explorer returns 404 for it — so the circuit is defined by a role query against the annotations and neurotransmitter tables, and the query is the definition:

class == 'CX' AND consensus_nt == 'dopamine'
Why
MaleCNS v1.0 has no PPM3 type string. SPEC 3.1C permits and expects a role query. The query is the definition.
Confirmation
The instance strings independently carry the cluster identity: FB4M(PPM3-FB3/4-NO-DAN). This was not assumed, it was found.
Sign provenance
consensus_nt 2 · ground_truth 22
Determinism
No stochastic step in this file; output is a pure function of the inputs.

The 24 bodies the query returns:

FB4L 10568 · FB1C 11255 · FB4M 12333 · FB4M 15888 · FB5H 16430 · FB4L 17061 · ExR2 18156 · FB2A 21519 · FB2A 25529 · FB2A 35293 · FB4L 36423 · ExR2 38706 · FB4M 43756 · FB4M 44903 · FB1C 45024 · ExR2 515933 · ExR2 517512 · FB1H 521584 · FB2A 523775 · FB1C 523776 · FB1H 533103 · FB4L 536057 · FB5H 536208 · FB1C 539227

What was tuned, and by how much(d)

Synapse counts are never edited. Tuning enters the model in exactly one place: a gain per (pre, post) class pair that multiplies the raw count. There are 11 named pairs in the ring table and 14 in the colour table, each with a background gain underneath it for every pair nobody fitted. Beside them the engine declares 50 other free parameters. Every one of them is listed here, with its value and the sentence saying where the value came from.

The count is the ceiling, not the result, and the honest number is smaller. 6 of the 11 named ring pairs hold exactly the background value — the grid search did not distinguish them from the floor. 5 differ from it, and between them they take 3 distinct values, so the whole ring table is 4 numbers: 0.0003, 0.001, 0.002, 0.009.

Stated the other way round, which is the stronger claim and the true one: the 92.6° bump measured below comes out of 348 real neurons and 349,786 real synapses run through 3 tuned scalars above a background gain. Most of this model is the connectome.

The colour table was fitted rather than hand-set, by log-uniform random search then coordinate polish, and the objective it was fitted against is published with it so the fit can be judged and not just the result.

Bump width and drift, against Seelig & Jayaraman 2015(a) + (b) + (d)

Bump full width at half maximum
92.60°
bump full width at half maximum, 16-wedge EPG profile, linearly interpolated Target 90°, window 72–108°.
Within 20% of 90°
PASS
The condition was fixed before the measurement, and is evaluated in the results file rather than on this page.
Single stable bump
PASS
a single bump forms from the raw MaleCNS synapse counts and persists for the whole 60 s run Mean bump concentration over the second half of the run: 0.864; fraction of samples with one peak: 1.
Reproduces the published drift
REPORTED
The third of the three criteria. The results file records no pass or fail for it, so neither is shown: the comparison below is what it does record, and this is the row that makes the whole result partial.
Drift in darkness
0.0012 °/s
least-squares slope of the unwrapped 16-wedge population vector over 60 s, mean of |slope| over 16 seeds
Drift under a landmark
0.0017 °/s
Wander, dark and landmark
0.1312 / 0.1822 °/s
Reported alongside the slope, because a slope near zero can hide movement that goes nowhere.

Seelig & Jayaraman 2015 (Nature 521:186-191) report that the EPG bump tracks heading with a stable offset under a visual landmark and that in darkness the offset accumulates error. This model reproduces the landmark case and does NOT reproduce the darkness drift: it is effectively pinned in both conditions (see caveats). No numeric drift rate is quoted from that paper because none was verified here.

Distinct settling positions
2 of 16
Cue the bump into each wedge in turn, release it, and count where it ends up. A continuous attractor would hold every position. The raw MaleCNS weights are not rotationally symmetric, and they are not symmetrised here, because symmetrising is editing the connection counts.
The compass cannot be turned
under 1° in 25 s, at every drive tried
A sustained left–right asymmetry injected into PEN of 0.01, 0.05, 0.2 and 0.5 — against a rate ceiling of 1 — each rotated the bump by under a degree in twenty-five seconds. The PEN population’s map onto EPG carries a mean angular offset of 6°, a quarter of a wedge, and the wells are tens of degrees apart. Reported, not fixed: fixing it would mean symmetrising the matrix. What moves the bump is the sun.
Gains fitted to
bump FWHM = 90 deg, one target, coarse grid search
12 free parameters in the ring gain table, background gain included. Of the 11 named pairs, only 5 were moved off the background value by the search, taking 3 distinct values. Units: per synapse (a gain multiplies a raw synapse count).
Run
60 s × 16 seeds
dt 1 ms, τ 100 ms, noise sd 0.020, r_max 1, seed 11. tau*dr/dt = -r + phi(sum_pre g[cls_pre,cls_post]*sign[pre]*W[pre,post]*r[pre] + I + xi) phi(x) = min(max(x, 0), r_max) — threshold-linear, saturating

What this does not show

  • The attractor is discrete, not continuous. Cueing the bump into each of the 16 wedges and releasing it leaves 2 distinct settling positions at the operating point (see stable_positions_sweep for the gain dependence: it peaks at 6/16). The raw MaleCNS weights are not rotationally symmetric, and this model does not symmetrise them, because symmetrising is editing W.
  • Consequently the dark-drift measurement is near zero and does not match Seelig & Jayaraman 2015. Reported, not fixed.
  • The landmark is a tonic drive to the whole ER population, not an azimuth-resolved visual scene. An azimuth-resolved ER->EPG map is what SPEC 3.7's plasticity produces and is out of Gate A's scope.
  • Gains are free parameters. Only the pathway structure and the signs are read from elsewhere (Hulse et al. 2021 architecture; MaleCNS neurotransmitter predictions).
Measured EPG activity across the sixteen wedges, with bump concentration and heading over a sixty-second run, in darkness and under a landmark.
Bump profile, concentration and heading

Hue selectivity, against Christenson 2024(a) + (b) + (d)

The published comparison
Christenson et al. 2024
Nat Neurosci 27:1137–1147. The two things that paper publishes as numbers — a hue sensitivity index per type, and a preferred colour band per type — are the two terms this is scored against; what it does not publish is set out in the calibration note further down.
Index
lifetime sparseness (Rolls & Tovee 1995; Vinje & Gallant 2000): S = (1 - <r>^2/<r^2>) / (1 - 1/N), baseline-subtracted
What is and is not like-for-like
Christenson et al. 2024 report a hue SENSITIVITY index over a 2D opponent stimulus space (their eqs. 13-15, ||h_vec||_2). The index here is lifetime sparseness over 61 narrowband probes. They are both bounded 0-1 and both measure how narrowly a cell responds, but they are not the same statistic, so the two numbers are reported side by side rather than claimed to be equal. The preferred-wavelength-versus-published-colour-band comparison IS a like-for-like check.
How a verdict is decided
PASS: the preferred wavelength falls inside the published colour band AND the index is within 0.15 of the published one. PARTIAL: one of those holds, and the preferred wavelength is within 50 nm of the band. FAIL: neither. Both tolerances are free and are stated here; they reproduce the four grades this gate carried before they were generated.

Of the 4 outputs, 1 passes, 2 are partial and 1 fails: Tm20. A partial is a partial: it is not counted towards the passes anywhere on this page. Every verdict below is computed from the row above it by the rule stated here, not written out by hand.

Tm20 FAIL
0.393 vs 0.550 · peak 600 nm
FAIL - index 0.39 vs 0.55 (less selective than measured), preferred 600 nm, 110 nm outside the published blue band. Mechanism, stated rather than hidden: in this roster every input Tm20 has is monotone in light and of one sign. Its lamina drive (L2/L3, cholinergic +) falls with light and its R8 drive (histamine -) subtracts with light, so Tm20 can only be a decreasing function of any illumination and its maximum is forced to the end of the probe range. The opponency Christenson measures comes through Mi1 and Mi4, which supply about 17% of Tm20's input in their reconstruction and are NOT in the SPEC 3.1B roster, and through their fitted sign exception R8->Tm5c excitatory, which the MaleCNS neurotransmitter tables do not support. No gain setting in the searched ranges fixes this; the residual loss is almost entirely Tm20's band term. Putting Mi1 and Mi4 in the roster WAS tried, on 2026-09-16, with the route through them fitted rather than left on the floor, and it moved this peak from 600 nm to 375 nm and took the whole gate's loss from 1.28282 to 0.59498 - and it took the colour range of an actual piece from rms dE 1.32 to 0.29, so it was reverted. The header of COLUMN_TYPES above carries that measurement in full. It is a fact about this gate rather than about the roster: the index here is lifetime sparseness over NARROWBAND probes, a piece runs under broadband daylight, and fitting harder to the first makes four outputs more alike under the second.
Tm5a PASS
0.608 vs 0.650 · peak 325 nm
PASS - index 0.61 vs 0.65, preferred 325 nm inside the published UV band.
Tm5b PARTIAL
0.765 vs 0.650 · peak 365 nm
PARTIAL - index 0.77 vs 0.65, preferred 365 nm, 15 nm outside the published violet band.
Tm5c PARTIAL
0.348 vs 0.375 · peak 370 nm
PARTIAL - index 0.35 vs 0.375, preferred 370 nm, 10 nm outside the published violet/blue/green (broad) band.

An internal check that could have failed

The photoreceptor tuning peaks are MEASURED out of the running rate model, not read back from the opsin table. They should land on the Salcedo et al. 1999 lambda_max the curves were built from (for Rh1, its curve peak); any offset is the recurrent circuit (Dm9 feedback and the R7<->R8 axo-axonal inhibition) pulling the peak.

Largest offset
5 nm
Across every photoreceptor type. The probe grid is 5 nm, so this is one grid step.
R1-R6
measured 345 nm · curve 345 nm · offset 0 nm
Opsin Rh1, λmax 478 nm.
R7p
measured 345 nm · curve 345 nm · offset 0 nm
Opsin Rh3, λmax 345 nm.
R7y
measured 370 nm · curve 375 nm · offset -5 nm
Opsin Rh4, λmax 375 nm.
R8p
measured 435 nm · curve 435 nm · offset 0 nm
Opsin Rh5, λmax 437 nm.
R8y
measured 510 nm · curve 510 nm · offset 0 nm
Opsin Rh6, λmax 508 nm.

Rh1's curve peaks at 345 nm, not at its 478 nm lambda_max, because R1-R6 carry the 3-hydroxyretinol sensitising pigment. The curve published with Christenson et al. 2024 (rh1_standard.csv) peaks at 345 nm too. So R1-R6 is checked against its curve peak, and the lambda_max column is kept alongside so the difference is visible rather than hidden.

One qualification on “could have failed”, since it is the point of the check. Four of the five rows are measured against a λmax this model did not choose. R1–R6 is not: the 345 nm peak its curve is checked against is produced by the sensitising-pigment amplitude listed as a free parameter under the pigment table below. That row could still have failed — the recurrent circuit could have pulled the measured peak off the curve, as it did by 5 nm for R7y — but the curve it is checked against is partly ours.

Was the circuit actually being exercised

Is the circuit actually being exercised, or idling near its background? For every type, over the whole probe set: the rate range, how much of the total input is recurrent rather than the tonic background, and whether the cell is ever silenced (r = 0) or ever pinned at r_max. A circuit whose outputs never move more than a few percent off background is not reporting anything about hue and must not be read as if it were.

Dm8a
rate 0–0.50 · recurrent/background 0.76
Silenced on 0.18 of probes, pinned at r_max on 0.
Dm8b
rate 0–0.50 · recurrent/background 0.56
Silenced on 0.13 of probes, pinned at r_max on 0.
Dm9
rate 0–0.51 · recurrent/background 1.15
Silenced on 0.44 of probes, pinned at r_max on 0.
L1
rate 0–0.50 · recurrent/background 2.28
Silenced on 0.62 of probes, pinned at r_max on 0.
L2
rate 0–0.49 · recurrent/background 2.57
Silenced on 0.69 of probes, pinned at r_max on 0.
L3
rate 0–0.50 · recurrent/background 0.30
Silenced on 0 of probes, pinned at r_max on 0.
R1-R6
rate 0–0.98 · recurrent/background 0.00
Silenced on 0 of probes, pinned at r_max on 0.
R7p
rate 0–0.99 · recurrent/background 0.17
Silenced on 0.43 of probes, pinned at r_max on 0.
R7y
rate 0–0.99 · recurrent/background 0.23
Silenced on 0.54 of probes, pinned at r_max on 0.
R8p
rate 0–0.99 · recurrent/background 0.16
Silenced on 0.08 of probes, pinned at r_max on 0.
R8y
rate 0–1.00 · recurrent/background 0.18
Silenced on 0.23 of probes, pinned at r_max on 0.
Tm20
rate 0.45–1 · recurrent/background 0.80
Silenced on 0 of probes, pinned at r_max on 0.
Tm5a
rate 0–0.43 · recurrent/background 3.14
Silenced on 0 of probes, pinned at r_max on 0.
Tm5b
rate 0–0.58 · recurrent/background 1.98
Silenced on 0 of probes, pinned at r_max on 0.
Tm5c
rate 0.15–0.72 · recurrent/background 0.26
Silenced on 0 of probes, pinned at r_max on 0.
Probe set
61 bands, 10 nm FWHM
Normalisation: equal quantum flux.

The closed colour loop(a) + (c) + (d)

The fly paints what it sees, which changes what it sees. Whether that settles, oscillates or does something better was the first thing to find out. It settles: held still under a fixed illuminant, the loop is a contraction with one stable fixed point, and how quickly it gets there is a measurement rather than a sentence, so it is quoted below.

Read that as a statement about this loop. It uses the opaque reflectance, which returns the same colour however much paint is present, so it is a map on the pigment ratio alone and settling is the only thing it could have done — its second half figures below are exactly zero for that reason. The engine runs a finite layer over the paper, where the amount of paint is visible. What that is worth over a whole piece is the block after this one.

Verdict
DULL

DULL, and measured to be dull rather than assumed. Every one of the four pigment orderings converges to a FIXED POINT within about two seconds. Second-half colour variance is 0.000000 for all four, and 0.000000 in all 25 cells of the deposition x renewal scan. The whole-run variance the SPEC §15 metric reports (0.06 to 0.32, RMS deltaE 0.24 to 0.56) is entirely the single transient from white paper to the equilibrium colour, and every one of those numbers is below deltaE 1, a just-noticeable difference. So the ordering chosen by the stated metric is chosen on the length of a transient, not on liveliness, and the choice should be read as close to arbitrary. All four numbers are recorded above so that is auditable. No noise was added to make this look otherwise (CLAUDE.md rule 4). Why, mechanistically: SPEC §3.4's loop, taken literally at one point on the canvas, is a contraction. More ink makes the patch darker, which lowers every photoreceptor's quantum catch; every photoreceptor in the dataset is histaminergic and therefore subtractive, so less catch means less inhibition downstream and slightly more ink. That is a monotone map with a single stable fixed point and no phase lag anywhere in it — the circuit's time constant (20 ms) is far shorter than the 100 ms tick, so each tick lands on the map's fixed point before the next one starts. There is nothing in the loop that could oscillate. What this means for the piece, stated for the engine rather than buried: colour variation in a finished piece will NOT come from temporal dynamics at a point. It has to come from the fly moving across a canvas that has history — crossing its own dried strokes, meeting wet paint of a different mix, and the illuminant changing with the real sky over the length of a piece. Those are all in the spec already (§3.3, §3.5, §6); none of them is in this gate, which deliberately holds the fly still under D65 to isolate the circuit. The honest headline is that the closed colour loop contributes a stable equilibrium colour, and the variation comes from the world and the walk.

All four orderings, so the choice is auditable

rot0
variance 0.137 · RMS ΔE 0.370 · second half 0
Tm20 → PG7 · Tm5a → PY3 · Tm5b → PV19 · Tm5c → PB29
rot1 — picked
variance 0.316 · RMS ΔE 0.562 · second half 0
Tm20 → PY3 · Tm5a → PV19 · Tm5b → PB29 · Tm5c → PG7
rot2
variance 0.309 · RMS ΔE 0.556 · second half 0
Tm20 → PV19 · Tm5a → PB29 · Tm5b → PG7 · Tm5c → PY3
rot3
variance 0.060 · RMS ΔE 0.245 · second half 0
Tm20 → PB29 · Tm5a → PG7 · Tm5b → PY3 · Tm5c → PV19
Selection rule
rot1
largest colour variance over the 10-minute run. The fallback was fixed in advance, which is the only reason picking one ordering afterwards is not a post-hoc choice. Every ΔE above is below 1, a just-noticeable difference, so the pick should be read as close to arbitrary.
Noise added
none. No noise is added anywhere in this loop (CLAUDE.md rule 4).
Illuminant
CIE D65 (CVRL table), gate measurement only; the piece uses the SPEC §3.3 sky model
Run for 10 minutes at 1 Hz, tick 100 ms.

The metric, stated once

THE METRIC, stated once.

Colour variance over the run = the mean squared CIELAB distance of the
1 Hz samples of DEPOSITED INK from their own mean:

    V = (1/N) sum_i ||Lab_i - mean(Lab)||^2

which is the trace of the covariance of (L*, a*, b*). Its square root is an
RMS deltaE_ab from the run's mean colour, so it reads in familiar units.
Deposited ink, not accumulated canvas, because the canvas integrates and would
report a large variance for a run that simply drifts once and stops.
Parameter scan
25 cells
Deposition rate against renewal. Second-half variance is 0 at its largest anywhere in the scan, so the fixed point is not an artefact of one parameter choice.

How far the colour actually moves over a piece

Measured on deposited ink sampled over a whole piece, as rms ΔEab from the run’s own mean, against 2.3 for a difference you could see. Across thirteen measurements — three seeds in the morning, at midday and in the afternoon, and four at night — it runs 1.26 to 1.37. So a piece is a wash that shifts, seen side by side, rather than one you would notice shifting, and that is printed rather than tuned away.

What is compressing it is which cells are in the model, not how far the fly walks. Tm5a and Tm5b swing across three-quarters of their range over a piece (0.725 and 0.761); Tm5c and Tm20 move 0.127 and 0.095 of theirs. Those are the two outputs the modelled patch is most missing the inputs of: 78% and 77% of the synapses reaching them in this dataset come from cells that are not in it.

Putting those cells in was tried, in full, and it made the painting worse. The fifteen tiling types that reach all seven columns took the colour circuit from 99 cells and 4,627 synapses to 205 and 21,704 and closed 55.8% of the missing input. Refitted, it scored 0.59498 on the hue-selectivity objective against 1.28282 — the best score ever measured — and the piece came out at rms ΔE 0.29 against 1.32. The reason is in the two stimuli: that objective is scored over sixty-one narrowband probes, and fitting it harder buys a cell that responds to fewer wavelengths, while a piece runs under a broadband illuminant where a more selective column produces four output rates that are more alike — and four alike concentrations mix to one colour. The wider roster was reverted. What would make it worth its cost is an objective scored under the light a piece actually runs in; that is the measurement below, and it is a new question rather than a bigger roster.

Where the engine no longer runs these numbers

The loop measured above is not the loop the engine runs, so two of its three canvas parameters have moved. The measured numbers stay published as measured. Every key where the engine differs is listed here, and a test asserts this list covers exactly the keys that differ, so a third divergence cannot appear without being written down.

depositRate
measured at 0.3 → engine 0.02
The gate ran an opaque layer, whose reflectance is unchanged when every concentration is multiplied by the same number, so the concentration scale was unobservable and this parameter could not be calibrated against anything. The engine runs a finite layer over the paper, where the scale is observable, and 0.02 is where a piece spans the optically thin-to-mid range instead of sitting opaque from the first second. Measured across the scan: rms deltaE of deposited ink from its own mean is 0.011 at 0.3, 0.098 at 0.1, 0.177 at 0.02 and 0.037 at 0.001.
renewal
measured at 0.1 → engine 1
The gate had no record of where the paint went, so it needed a leak to stop the patch being a closed accumulator. The engine has that record — `sheet` below — so the leak is no longer load-bearing, and at 1 the fly simply sees the paint under its feet rather than a one-second average of the paint it has walked over. That is both simpler and what an eye does. Measured, it is also where the positional term shows: 0.021 rms deltaE at 0.1, 0.062 at 0.3, 0.177 at 1.
Deposited ink in CIELAB over a closed-loop run, pigment ordering rot0. The trace reaches a constant value in the first seconds and stays there.
Closed colour loop, ordering rot0
Deposited ink in CIELAB over a closed-loop run, pigment ordering rot1. The trace reaches a constant value in the first seconds and stays there.
Closed colour loop, ordering rot1
Deposited ink in CIELAB over a closed-loop run, pigment ordering rot2. The trace reaches a constant value in the first seconds and stays there.
Closed colour loop, ordering rot2
Deposited ink in CIELAB over a closed-loop run, pigment ordering rot3. The trace reaches a constant value in the first seconds and stays there.
Closed colour loop, ordering rot3

Colour under the light a piece runs in(c) + (d)

The hue-selectivity measurement above has to use the stimulus the published paper used: sixty-one narrowband probes. That is the right instrument for that question and the wrong one for any other — the block above records what happened when it was used as one. This is the same question asked under the light and the paint a piece actually has.

A stimulus here is a pair: light and paint, both computed the way the piece computes them — the sky model plus the practical lamp below its threshold, and the finite paint layer over the paper rather than the opaque one. Both are held to the engine’s own code at 1e-12 by a test, so “the light the piece runs in” is a checked claim rather than an intention. Nothing here is fitted: there is no published target to fit to, and fitting gains until a piece had more colour in it would be tuning away a dull measurement. What it is for is rejecting a circuit that scores well on narrowband probes by going blind under daylight.

Separation
0.067
The coefficient of variation of the four-output vector over 150 stimuli — 5 skies × 3 pigment loads × 10 mixtures. It is 0 when the column says the same thing about every patch of paint it will ever see.
Conditioning
0.033
The smallest singular value of the centred output matrix over the largest. It is 0 when the four outputs are redundant. Separation alone is not enough: four outputs that rise and fall together do vary, but they hold the pigment mixture at a fixed ratio, and a fixed ratio is one colour however much of it there is. Singular values 0.774 · 0.326 · 0.095 · 0.026.

What each output does under this light

This is the row that matters, and it is the one no narrowband probe could show. Two of the four outputs barely move across the whole ensemble, so two of the four pigments are close to a constant and the mixture the fly can reach is close to a line rather than a volume. That is a fact about this roster measured against this light; it is not a verdict on the connectome, and it is not being corrected here.

Tm20
0.837 – 0.881
range over mean 0.050, mean rate 0.865
Tm5a
0.108 – 0.401
range over mean 2.294, mean rate 0.128
Tm5b
0.082 – 0.341
range over mean 1.954, mean rate 0.133
Tm5c
0.505 – 0.582
range over mean 0.145, mean rate 0.531
Separation floor
0.049 — enforced in the gain fit
enforced. fit_objective rejects any candidate below it. The floor is the geometric mean of Gate D measured on this roster (0.06696) and on the 205-cell 15-tiling-type roster refit at FIT_N 20000 (0.03543) -- the circuit that scored the best Gate B ever measured and painted the worst piece ever measured. See GATE_D_MIN_SEPARATION in prep/circuit_b.py.

The floor’s job is to reject the collapse the wider roster produced. Setting it honestly needed this measurement on that circuit as well as on this one, so that circuit was rebuilt outside the tree and both ends are measured on the same ensemble by the same code:

99-cell roster (published)
separation 0.067
Hue-selectivity loss 1.283, conditioning 0.033. The circuit this site runs.
205-cell roster (+15 tiling types)
separation 0.035
Hue-selectivity loss 0.630, conditioning 0.107. Half the loss, half the separation: the wider roster decompresses Tm20 from a range-over-mean of 0.050 to 1.322 and still loses overall, because Tm5a falls from 2.294 to 0.360. The patch did not move; both rosters resolve the same seven columns.

The floor is the geometric mean of those two separations, which puts the published circuit exactly as far above it in ratio as the collapse is below it — 1.375× either way. A geometric mean rather than an arithmetic one because separation is a coefficient of variation, so the halfway point between two of them is multiplicative. That rule is the whole of the choice.

It is a constraint and never a term. The gain fit still optimises the published numbers and nothing else; this only refuses candidates below the floor. No gain is moved in order to raise a colour range — that would be tuning away a measured dullness. Re-running the fit with the constraint switched on returns the published table unchanged, to five decimal places, at loss 1.28284 against 1.28282: it does not bind here, and it would have rejected the collapse.

The shuffle ladder(a) + (d)

Four rungs in increasing strength — a random graph at matched density, the real topology with unit weights, a degree-preserving shuffle with cell types kept, and the real matrix. Gains, signs, type labels, inputs and probes are held fixed across the rungs, so the only thing that changes is the wiring.

Ring

fraction of a 60 s run with EPG bump concentration > 0.5; drift = |least-squares slope of unwrapped heading|, deg/s

The ladder as designed: 100 seeds per rung, 60 s each, seed 4242. All 4 rungs completed at that count, in every gain setting each was run in. Real network leading eigenvalue: 1.7358. Every rung, with its numbers.

What the measured rungs do and do not show

The number to be careful with is the random rung with its gains rescaled to λ_max. It holds a bump — concentration above 0.5 for more than half the run — in 44 of 100 seeds, and read alone that looks like the control half working. The spread says otherwise. Across those 100 seeds the fraction of the run spent above 0.5 has mean 0.438 and standard deviation 0.484, against 0.496: the largest standard deviation any quantity bounded between 0 and 1 with that mean can have, which is reached only by a quantity that is always exactly 0 or exactly 1. The measured spread is 97.5% of that bound and the maximum is 1.000, so the seeds sit at the two ends and not in the middle. A rescaled random graph either localises for essentially the whole run or for essentially none of it. It is bimodal, not partial.

That is why the concentration metric is stated as narrowly as it is. Concentration above 0.5 measures localisation — activity gathered into one place on the ring rather than smeared around it — and enough recurrent gain will localise a random graph. It does not measure a heading map. Nothing in it ties where the activity sits to where the fly is pointing, and the drift column does not fill the gap: a lump of activity that sits still because nothing is moving it has as little drift as one held in place by a landmark, which is what 0.0055 °/s on the rescaled random rung against 0.0012 °/s on the real matrix is showing. So the honest reading of this rung is the narrow one: rescaled recurrent gain buys localisation on some seeds and nothing else the ladder can see. The rescaling is the steel-man — the control is handed the same amount of recurrent gain as the real network and still has to produce the behaviour out of its own topology.

This is one circuit and one computation — a heading representation in the ellipsoid body and protocerebral bridge of one fly. It is not a claim about the brain.

Two bar panels. Left panel, the fraction of a sixty-second run with bump concentration above 0.5: four rungs along the axis — random matched density, real topology unit weights, Maslov–Sneppen types kept, and real — each drawn as a dark bar at the operating-point gains beside an orange bar at λ-matched gains, with the hundred individual seeds scattered over each bar as small pale blue dots. Every operating-point bar is flat at zero except the real rung, which stands at 1.0 with all hundred of its seeds sitting on it; the real rung has no orange bar, because the real matrix is run only at its own gains. The orange λ-matched bars reach about 0.44 on the random rung and about 0.19 on Maslov–Sneppen, and in both the seeds cluster at the top and the bottom of the range rather than around the bar; the unit-weights rung is flat at zero in both gain settings. Right panel, absolute drift in degrees per second on the same four rungs: only real topology with unit weights at the operating-point gains rises, to about 35 °/s with its seeds spread from zero to about 100 °/s, and every other bar sits against the axis.
Shuffle ladder, ring, all four rungs at 100 seeds

Colour column

hue-selectivity index (lifetime sparseness) per output type

Degree-preserving over real, per output
Tm20 0.815 · Tm5a 0.962 · Tm5b 0.941 · Tm5c 1.072
A ratio at or above 1 means the shuffle matched or beat the real matrix on that output. This is the result of the colour ladder, so it stays here rather than going to the tables.

What the ladder shows

MIXED, and the mix is the interesting part. A random graph at matched density destroys hue selectivity completely (0.21-0.23 across all four outputs, against 0.35-0.77 real) - so the selectivity is not an artefact of the gains, the signs or the input. But the SPEC §10 degree-preserving shuffle WITH TYPES KEPT does not collapse it: it retains 82-107% of the real index. Lifting the type restriction collapses it to 0.26-0.29, i.e. to the random-graph level. Read plainly: in this 99-cell patch the selectivity is carried by the TYPE-LEVEL connectivity read from the connectome - which type contacts which type, and how heavily - and not by which individual cell contacts which individual cell. A same-type-preserving swap leaves the type-by-type weight matrix intact, so there is nothing left for it to destroy. The live 'shuffle wiring' toggle on the page must therefore use the types-free shuffle, or the random rung, and say which. Every number in this paragraph is read out of `results` above rather than typed: they were typed once, and the roster change of 2026-09-16 made all of them wrong at once while the page went on printing them.

100 seeds, 10 swaps per edge, seed 20260915. Held fixed: gains, signs, type labels, inputs, integrator, probe set. Every rung, and the diagnostic rung, with its numbers.

This circuit, this computation. Not the whole brain, and not a claim that shuffling any connectome destroys any function.

The pigment table(c) + (d)

The one aesthetic decision in the project, and the only lever on the colour loop. Each hue-selective output drives one pigment; the four concentrations mix under Kubelka–Munk.

Tm5a
PY3
Chosen, not measured. The engine and the measured pigment file agree on this pairing.
Tm5b
PV19
Chosen, not measured. The engine and the measured pigment file agree on this pairing.
Tm5c
PB29
Chosen, not measured. The engine and the measured pigment file agree on this pairing.
Tm20
PG7
Chosen, not measured. The engine and the measured pigment file agree on this pairing.
Engine against the measurement
differ
The colour-loop measurement picked rot1 (Tm5a → PV19, Tm5b → PB29, Tm5c → PG7, Tm20 → PY3); the engine ships the ordering above. They differ, and it is printed rather than hidden. Every ordering's colour variance was also measured to be below one just-noticeable difference, so by that report the choice between them is close to arbitrary — but "close to arbitrary" is not "agreed", and this line will keep saying so until one of the two changes.
Reflectance model
single-constant Kubelka-Munk, K/S = (1-R)^2 / (2R), Duncan 1940 concentration-weighted mixing, opaque-layer inversion
Reflectance measured from: PB29 360.2 nm · PG7 360.2 nm · PV19 291 nm · PY3 291 nm. Below the first measured wavelength the curve is not extrapolated: it is held constant at the first measured value, which is the weakest thing that could be done there and is an assumption rather than a measurement. That is the ultraviolet caveat made specific, and the caveats below name which two of the four pigments it affects and which of the fly’s opsins sit in the gap.
Who reads these numbers
the fly and the picture, both
Both halves of the piece integrate them: the paint layer through a three-channel table for what you see, and the fly spectrally across all 81 bands — including the ultraviolet, because R7p peaks at 340 nm and no RGB triple reaches it. Single-constant K/S, so the fly’s mixing is Duncan 1940, the model these measurements were inverted under, and a test asserts the engine is reading them rather than falling back.

What the pigment data is not

  • No public dataset of SEPARATE Kubelka-Munk K and S for named artist pigments exists. Berns 2016/2019 and Berns 2022 measured exactly that for PV19, PB29 and PG7; neither spreadsheet is downloadable (the 2022 one has been withdrawn by its author) and Okumura 2005 publishes its unit k and s as graphs only. So this is masstone reflectance turned into SINGLE-constant K/S, not two-constant Kubelka-Munk.
  • UV, and this is the SPEC §13 'UV is a translation' caveat made specific: PY3 and PV19 are measured from 291 nm, so their 300-400 nm reflectance is real data. PB29 and PG7 are measured only from 360.2 nm; from 300 to 360 nm their value is HELD CONSTANT at the 360.2 nm reading, which is an assumption, not a measurement. Rh3 (345 nm) and Rh4 (375 nm) both sit in or next to that gap, so two of the fly's five channels are reading partly-assumed numbers off two of the four pigments.
  • PG7: the source file is named only 'phthalo green' and carries no Colour Index number. The same archive family labels PG36 separately, so PG7 is a strong inference, not a reading. Its masstone is near-black (R 6.7-11% across the visible), the classic single-constant failure case: K/S comes out flat and noise-dominated.
  • PV19 here is the violet (beta) polymorph; SPEC §6 names quinacridone rose, which is the rose/gamma form and has a different spectrum.
  • Masstone films of transparent organics (PV19, PG7) may not be optically thick, which violates the opaque-layer assumption behind the inversion.

The opsins the ink is computed through are published measurements with one free parameter inside them. The peak sensitivities are not a choice; the curve shape is a published template evaluated at them; and the sensitising pigment carried by R1–R6 has an amplitude that is ours.

Rh1
478 nm
Rh3
345 nm
Rh4
375 nm
Rh5
437 nm
Rh6
508 nm

Salcedo et al. 1999, J Neurosci 19(24):10716-10726. Curve shape: Govardovskii et al. 2000, eqs. 1-5 (alpha + beta band).

How each curve was built, quoted rather than summarised

Salcedo et al. 1999 (J Neurosci 19:10716-10726) publish lambda_max for the Drosophila rhodopsins but not digitised sensitivity curves, so each curve here is the A1 visual-pigment template of Govardovskii, Fyhrquist, Reuter, Kuzmin & Donner 2000 (Visual Neuroscience 17:509-528), alpha band plus beta band, evaluated at the published lambda_max and normalised to a peak of 1. Nothing is hand-drawn. R1-R6 additionally carry the 3-hydroxyretinol sensitising pigment (Kirschfeld et al. 1977), added to Rh1 as a Gaussian antenna band at 350 nm; its relative amplitude is a FREE parameter, listed below.

The free parameter inside the opsins

peak_nm
345
provenance
amplitude free; peak/width from 3-hydroxyretinol absorbance
sd_nm
22
visible_to_uv_ratio
0.526

visible_to_uv_ratio is the free one, and it is not a small detail of the curve: at 0.526 the antenna band exceeds Rh1’s own 478 nm λmax, so the R1–R6 sensitivity curve peaks at 345 nm instead. That is the curve the internal check above measures R1–R6 against, and the note under that check says so.

The engine against the reference(a) + (d)

Every measurement above was made in Python. Everything you can watch on the studio page is computed in TypeScript. Those are two implementations of one rate equation, and if they have drifted apart then the proof on this page is proof of something the site does not run.

The reference writes a fixture out of the same code path that produced the heading measurement; the engine rebuilds the same quantities from its own circuit and is compared against it, so a disagreement implicates the engine rather than the fixture. The fixture is published with the rest of the results files, and everything below is counted out of it.

Body order
348 of 348
Index i has to mean the same neuron on both sides. Checked first, because every comparison under it is meaningless otherwise, and a re-sorted table breaks it silently.
Class assignment
348 cells
Every cell maps to the class the reference keyed its gain table by. A cell type with no class would take the default gain on one side and a fitted one on the other, and nothing else here would notice.
Effective-matrix entries
600
A deterministic spread of entries of the gain-weighted, sign-applied matrix. The whole 348 × 348 would be two megabytes; a spread catches a wrong gain, a wrong sign or a transpose just as well.
Row and column sums
348 + 348
Sampled entries can survive an index swap if the sample happens to land on zeros. Sums cannot, which is what these are here for.
Full rate vector
9 capture steps
Steps 1, 2, 5, 10, 50, 100, 500, 1000, 5000 of the Euler integration, all 348 rates at each. The early ones catch a wrong initialisation or a transposed matrix; the late ones catch slow drift, which is what an accumulated one-ulp difference in the matrix-vector product would look like.
Operating point
1.7358
The fixture's leading eigenvalue, against 1.7358 in the heading results. Not a parity check of the arithmetic — a guard that the fixture and the published measurement describe the same network. Integrated at dt 1 ms, τ 100 ms.
Tolerance
1e-9
Read out of the test that holds the two implementations together, so this page cannot advertise a tighter bound than the one being enforced. The bar was 1e-6; the test is set at 1e-9, so a real divergence shows up as a failing test rather than as a pass with a shrinking margin.

One thing is deliberately not compared: the noise term, which is zero on both sides of the fixture. Parity fixture for engine/parity.test.ts. Noise is zero by design; see the module docstring in prep/parity.py for why, and engine/rng.test.ts for the generator's own tests. The two implementations draw from different generators — splitmix64 with Box–Muller on one side, xoshiro128** on the other — so their noise streams cannot agree sample for sample, and porting one to the other language purely to satisfy a test would prove nothing about the model. What is compared is the part that could be wrong in a way nobody would notice: the effective matrix, the sparse accumulation, the rectifying nonlinearity and the Euler step. The generator has its own determinism and distribution tests, and so does the replay guarantee that makes a piece reproducible from its seed.

Licence(a)

Code
MIT
The engine, the paint layer, the renderer, the scene and this site.
Data
CC-BY 4.0
CC-BY 4.0 (HHMI Janelia / Google Research / Univ. Cambridge / MRC LMB). Attribution is a condition of the licence, and it appears on the about page and here.
Weather
Weather data by Open-Meteo.com
Attribution required by Open-Meteo’s licence, in this exact form.
Cell type names
Cell Type Explorer
Every cell type named on this site was checked against the public MaleCNS Cell Type Explorer catalogue, which needs no account. neuPrint itself now requires a Google sign-in for every query, so links to it are labelled as such.