Eye
MaleCNS optic-lobe columns, their measured viewing directions, and the T4/T5 locks that use them. The fetch, the licence and the files are in data. The body and the jump are in embodiment.
Eye geometry (#84)
flymsg eye joins the MaleCNS optic-lobe columns to measured viewing directions. Each
column has hex coordinates (assignedOlHex1/2, Nern et al. 2025, doi:10.1038/s41586-025-08746-0);
with p = hex2 − 19 and q = hex1 − 18 they are the (p, q) of the eye map of Zhao et al. 2025
(doi:10.1038/s41586-025-09276-5), whose lens directions come from a micro-CT of one female
head. Mi1 columns and lenses share (p, q) in all 778 of Zhao's pairs, so the registration is
the identity on the hex grid; nothing is fitted. The map is fetched from
reiserlab/eyemap_T4 at 99d2a43 (GPL-3.0) into data/raw/eyemap/ and never committed;
data/eye/columns.parquet and photoreceptors.parquet stay local.
| Left | Right | |
|---|---|---|
| Columns (one L1 each) | 875 | 892 |
| With a viewing direction | 835 | 843 |
| R1–R6 assigned to a cartridge | 498 | 888 |
| R7 / R8 assigned to a column | 541 / 624 | 687 / 698 |
Photoreceptors carry no hex label; each takes the column that receives most of its synapses among column-assigned neurons. Many R1–R6 bodies are out-of-scope fragments, more on the left. Check, independent of the map: the dorsal-rim photoreceptors (R7d, R8d) land on columns with a median elevation of 67.7°, the other R7/R8 at 3.7°. Named assumptions: the left eye is the right eye mirrored; a male optic lobe is read through a female eye; columns without a lens (mostly the anterior edge) get no direction. Expected error is about one column (≈ 5°) inside the eye, worse at its margins.
A looming stimulus per column. eye.looming_radius_deg gives the angular radius of an
object approaching at constant speed (tan θ/2 = l/(v·t), the stimulus of von Reyn et al.
2014), and eye.disk_coverage the share of each column's acceptance profile the dark disk
covers: a circular Gaussian of a given full width at half maximum around the column's
direction, exact in the small-angle limit (Rice CDF). The acceptance angle is an argument,
not a default; the value and its source go into the lock of the first run. With 5°, a disk
centred at 90° to the right covers more than half the profile of 5 right-eye columns at a
radius of 5°, 138 at 30° and 462 at 60°, and no left-eye column.
eye.photoreceptor_kicks turns the coverage into graded input for each photoreceptor of a
column: gain times the light left (1 − coverage), in units of the Poisson kick; the gain has
no measured value and is stated by the lock. That lock is the T4/T5 test below.
The giant fiber's size/velocity split (Ache et al. 2019) is a separate test on the
roadmap and is not part of this lock.
Geometric optics from a 6-DoF pose (G2, #179).
flymsg.optics measures dark spheres in the world from every column, given a B6 v2 body
state and eye mounts (flymsg.pose, embodiment):
the angle from the column's axis to each sphere, the sphere's angular radius asin(r/d) and its
rate, its angular velocity relative to the eye (so a turning fly sees the world turn the other
way), the covered share of the acceptance profile and which sphere the column's axis meets
first, and the sphere's azimuth and elevation in the body frame. Every column of an eye looks
out from the position of that eye's mount; a column without a lens keeps NaN. Shares are per sphere as if alone; where silhouettes overlap only nearest resolves
which one the axis sees. Nothing is a photoreceptor response, and the module imports no
viewer, renderer or physics engine. Columns enter the body frame only through an explicit,
sourced Registration of the micro-CT head frame: the rotation between that frame and
NeuroMechFly's head is not measured, so no default exists and only tests use the identity. It
may only pitch and shift in the sagittal plane, because the left eye's columns are the right
eye's mirrored. Each sample carries a hash of the column source, registration, mounts, spheres
and acceptance.
That gap, not the optics, is what keeps G2 from running on the real eye.
The planar Rice CDF of disk_coverage is checked against optics.coverage_exact, the same
Gaussian profile integrated over the sphere: with an acceptance of 8.23° its largest error is
0.0007 for caps up to 10° in radius, 0.0022 up to 30°, 0.0046 up to 60° and 0.0076 up to 89°
(coverage is a share, 0 to 1).
tests/test_optics_oracle.py independently integrates the acceptance profile with Sobol
3D rays and closest-approach sphere hits, without using the production cap quadrature or
Rice CDF as its reference. The numerical checks allow 0.0005 absolute spherical error and
0.0085 planar error at acceptance 8.23° for the declared test cases. This checks the assumed
profile's geometry, not its physiology, the missing head registration or a camera renderer.
The separate scripts/check_optics_camera.py oracle uses FlyGym 2.1.0's actual eye cameras
and renderer, with the body hidden to isolate a synthetic target. At 1024×1024, all six
left/right centred, offset and approaching-target cases pass the predeclared one-pixel
silhouette erosion/dilation interval plus the existing planar error allowance. The
rendered-camera record
retains the absolute errors (up to 0.0122) and pixel bounds. It qualifies these synthetic
camera cases, not the missing MaleCNS-head registration or a physiological transfer.
T4/T5 direction selectivity through the eye (lock, 2026-10-13)
eye.edge_coverage moves a straight edge across each eye's measured columns (direction per
eye, so front-to-back points away from the midline on both sides).
validation/t4t5.yaml, locked before its run, drives the 640
photoreceptors of the 336 columns within 30° of each eye's centre with ON and OFF edges in
the four cardinal directions at 30°/s (Haag et al. 2017), acceptance 8.23° (Gonzalez-Bellido
et al. 2011), and a gain equal to the mean input of every flymsg protocol (a named
compensation). It decides on two levels: polarity (every T4 subtype fires more to ON than
to OFF edges, every T5 subtype the reverse; Maisak et al. 2013), which signs alone predict,
and direction (the vector sum of at least 6 of the 8 subtypes within 45° of the measured
preferred direction: a front-to-back, b back-to-front, c up, d down). The prior is stated in
the lock: Lappalainen et al. 2024 found untrained connectome models get polarity right and
direction wrong. DSI is reported next to the 0.8 measured in calcium.
Result of version 1 (2026-10-13): neither. Run from 0c574f5. No T4 or T5 neuron spikes
for any edge, direction or polarity, so neither level passes. An exploratory count after the
verdict (seed 0, one sweep each polarity) shows where the signal stops: the 640
photoreceptors fire about 370,000 spikes per sweep, and L1, L2, L3, Mi1, Tm3, Mi4, Mi9, Tm1,
Tm2 and Tm9 fire none. Photoreceptor synapses are histaminergic, inhibitory; in the fly the
lamina monopolar cells are graded neurons with a resting tone that light hyperpolarises and
darkness depolarises, which is where ON and OFF begin. A spiking point neuron at rest that
receives only inhibition stays silent in light and in darkness, so contrast cannot cross the
first synapse. The eye and its geometry work; the model's neurons do not, at this stage. This
is the case for graded, tonically active neurons
(#97), now with a concrete failure.
Outputs: results/t4t5/v1/.
T4/T5 version 2: graded photoreceptors and lamina (lock, 2026-10-13, #84, #97)
Version 2 of validation/t4t5.yaml, locked after the v1 run and
before any v2 run, makes photoreceptors and L1–L3 graded (model).
Photoreceptors release nothing at rest and saturate at their light response; L1–L3 release
half their maximum at rest, nothing at the measured maximal hyperpolarization and saturate
as far above rest. The light gain holds a fully lit photoreceptor at its response, and the
photoreceptor release rate makes full light hyperpolarize the median receiving LMC by the
LMC range, both from the steady state of the membrane equation. Because no release curve is
measured in Drosophila, the test runs an envelope of 17 configurations: LMC ranges 20, 32.5
and 45 mV times LMC release rates 25–400 Hz (unmeasured, four doublings) at a 52.5 mV
photoreceptor response, plus 40 and 65 mV. The edge's first frame is held 200 ms before it
moves and spikes count only during motion; the input is deterministic, so one run per
stimulus and configuration. The decision per configuration is v1's; the test reports
robust: <verdict> only if all 17 agree, and otherwise depends with the counts. The
pathway's spikes per type (Mi1 to Tm9) and the LMC potentials are reported next to the
measured ranges.
Result of version 2 (2026-10-13): robust: neither. Run from 17173c2, the lock commit,
seed 93, 136 simulations; interrupted once after 8 configurations and resumed from saved ones
(the manifest lists them). All 17 configurations give neither: no T4 or T5 neuron spikes
for any edge, direction or polarity. Contrast now crosses the lamina: under light the graded
L1–L3 receiving window photoreceptors hyperpolarize by 14–33 mV at their lowest (the measured
range is 20–45 mV; the 20 mV configurations stay below it). It stops in the medulla. The ON
inputs of T4 (Mi1, Tm3, Mi4) fire in no configuration. The OFF inputs (Tm1, Tm2, Tm4, Mi9)
fire only when the LMC release rate is 200 or 400 Hz, with 7 to about 560,000 spikes per type
over the eight stimuli; at 25–100 Hz the whole medulla stage is silent. In the fly Mi1 and Tm3
are graded and the medulla inputs differ in timing (Behnia et al. 2014; leads);
here they are spiking point neurons at rest, which disinhibition from the lamina does not
lift, the outcome the lock's prior names. Outputs: results/t4t5/v2/.
T4/T5 version 3: graded medulla inputs (lock, 2026-10-13, #140)
T4's medulla inputs Mi1, Tm3, Mi4, Mi9 and
C3 become graded over the potentials Groschner et al. 2022 recorded in vivo to the same
30°/s edges (Edmond doi:10.17617/3.8G, CC BY 4.0; flymsg.medulla fetches the five files by
sha256 and the run recomputes the ranges). Per type, the mean dark potential stands at the
model's rest, release is 0 at the lowest mean potential and saturates at the highest: Mi1
−69.2 to −41.3 mV around a dark level of −65.2, Tm3 −69.4 to −42.5 (−64.4), Mi4 −66.7 to
−52.3 (−65.1), Mi9 −62.5 to −50.4 (−58.0, an OFF cell releasing in darkness), C3 −74.0 to
−46.9 (−66.8). The release rate of the medulla and of L1–L3 is not measured: both are scanned
over 25–400 Hz (25 configurations, seed 94) at the middle photoreceptor and LMC ranges. T5's
inputs Tm1, Tm2, Tm4 and Tm9 have no voltage in mV in any source found (Behnia et al. 2014,
Kohn et al. 2021, Yang et al. 2016), so they stay spiking and v3 decides on the four T4
subtypes; T5 is reported. Per-type timing (Mi1 71 ms against Tm3 53 ms, Behnia et al. 2014)
is not set: the model has one membrane time constant. Graded types never spike, so the
pathway table counts 0 for Mi1, Tm3, Mi4 and Mi9; their potentials are in medulla.csv,
next to the measured range.
Result of version 3 (2026-10-14): robust: neither. Run from 406f622, the lock commit,
seed 94, 200 simulations in one attempt (11.3 h). No T4 neuron spikes in any configuration, for
any edge, direction or polarity, and T5 is neither in all 25. The LMCs still carry contrast
(−20.6 to −25.4 mV at their lowest under light). The graded medulla receives it with the
measured sign only for Tm3 and C3 (ON, up to +1.4 and +0.8 mV) and Mi9 (OFF, ±0.6 mV); Mi1 and
Mi4 move by at most 0.5 mV, without a consistent sign (mostly the OFF one at LMC rates of
100 Hz and above). The measured ranges span 12–28 mV, so the evoked swings are at most about 5% of
the measured ones. Before the edge, tonic lamina release holds Mi1, Tm3, Mi4 and C3 below the
measured dark level (Mi9, an OFF cell, above it), the more so the higher the LMC rate (Mi1 −1.0
to −16.8 mV, Tm3 to −16.7 mV). Below its lowest measured potential a graded type releases
nothing: Mi1 and Mi4 from an LMC rate of 100 Hz, Tm3 from 200 Hz and C3 at 400 Hz. T5's spiking
inputs fire only at LMC rates of 200–400 Hz (Tm1 up to about 381,000 spikes over the eight
stimuli). Making the medulla graded therefore does not carry the edge to T4: at low LMC rates
the lamina → medulla step is too small, and at high rates tonic release pushes the medulla
below release. Outputs: results/t4t5/v3.executions/d85c3913…/output/.
T4/T5 version 4: dark anchor, lamina gain and measured delays (lock, 2026-10-14, #140)
Version 3 failed for two reasons its tables show: tonic L1–L3 release at rest held the medulla
below its measured dark level, and the edge moved the graded medulla by at most 1.4 mV. Version
4 (validation/t4t5.yaml v4, seed 98, 12 configurations) changes three things and nothing
else. Each graded medulla neuron's measured range is anchored at its own settled potential
after 200 ms of darkness with every graded release on (six passes; the median change between the last
two is reported), so the dark state, tonic lamina input included, stands for the measured dark
potential. Every synapse from L1–L3 onto the five graded medulla types is multiplied by 1, 4 or
16 (16 brings v3's largest swing to the order of the measured 12–28 mV), at LMC and medulla
release rates of 50 and 200 Hz; the gain is scanned, not chosen. Behnia et al. 2014's two
delays (Mi1 18 ms after Tm3, Tm1 13 ms after Tm2; Fig. 3B, 3E, verified in PMC4243710) are set
through the slower cell's synaptic time constant (38.45 and 24.83 ms), with its incoming
weights scaled by the ratio of steady gains (0.130, 0.201) so only the timing changes; Mi4 and
Mi9 have no measured peak time here and keep the default. The decision is version 3's, on the
four T4 subtypes; the Gruntman et al. recordings stay held out. The membrane is current-based, so
at high gain the anchored dark potentials lie far from rest; only potentials relative to the
anchor carry meaning. Not run when locked.
Result of version 4 (2026-10-15): robust: neither. Run from 111e3c5 (the lock
is 8d0660b, unchanged since), seed 98, 96 simulations in one attempt (18.9 h). The dark anchor settles: after six passes the
median change per type is below 0.5 mV in 52 of the 60 type and configuration cells and at
most 2.0 mV. The lamina → medulla gain carries the edge into the medulla: the swings around the
anchor grow from at most 0.6 mV at gain 1 and 2.1 mV at gain 4 to about ±10 mV at gain 16
with an LMC rate of 200 Hz (Tm3 +10.2/−9.9, Mi1 +7.6/−6.8, C3 +6.6/−7.7, Mi9 ±5; Mi4 at most
0.6; with LMC 50 Hz at most 2.0 mV), the order of the
measured 12–28 mV, but each type swings about as far each way, and at gain 16 with LMC 200 Hz the
anchored dark potentials lie up to 113 mV from rest (the current-based membrane's limit the lock names). T4
fires only at a medulla release rate of 200 Hz: a few tens of spikes at gains 1 and 4
(configurations 3 and 5, single-digit counts per subtype whose indices of 1.0 mean
nothing), thousands at gain 4 with LMC 200 Hz and at gain
16 (configurations 7, 9 and 11, up to about 350,000 spikes), where the other polarity fires more
than the preferred one and the direction selectivity indices lie between −0.15 and 0.18. T5 is
neither in all 12. A larger lamina → medulla step therefore brings the medulla to the order of the measured
amplitudes, not to their shape (the recordings depolarize 12.8–23.9 mV and hyperpolarize
1.6–7.2 mV), and not T4 to selectivity: the edge reaches T4 without the ON/OFF split or the
direction the recordings show (by the lock's criterion; T4a and T4d point the measured way in
some of these configurations). Outputs: results/t4t5/v4.executions/7a550844…/output/.
Post-hoc audit of version 4 (2026-10-16, not a score). Read from the archived
medulla.csv, metrics.csv and spikes.csv; nothing was rerun and the verdict stands. The
archive holds spike counts and per-type potential extremes, not time series, so latency and
timing cannot be reconstructed from it. At gain 16 with LMC 200 Hz (configurations 10 and
11, medulla release 50 and 200 Hz), the largest medulla swings relative to the settled potential
over both are Tm3 +10.2/−9.9, Mi1 +7.6/−6.8, C3 +6.6/−7.7, Mi9 +5.1/−5.3 and Mi4 ±0.6 mV
(configuration 11 alone: Tm3 +8.7/−9.7, Mi1 +4.8/−6.8, C3 +6.0/−7.7), against measured ranges
of +21.9/−5.0, +23.9/−4.0, +19.9/−7.2, +7.6/−4.5 and +12.8/−1.6 mV. The depolarizations reach
about a fifth to two thirds of the measured ones (Mi4 about 5%), while the hyperpolarizations
match or exceed them except in Mi4. T5 fires no spike in any of the 12 configurations. Where T4
fires in thousands (7, 9, 11), OFF exceeds ON in every subtype, and the response vectors of all
four subtypes lie between 265° and 345° whatever their measured direction (0°, 90°, 180°,
270°), with vertical motion driving 1–31% more spikes than horizontal motion in every subtype
and polarity. So T4a and T4d pointing near the measured way
follows from a bias shared by all four subtypes, not from a tuning of their own. This audit
describes v4; it selects no mechanism for a version 5, which waits on the release curve.