Fly Rig Anatomy

boat.horse · projects
MaleCNS v1.0 · 166,700 neurons · 25.6 M edges

This is a working simulation of a fruit fly's entire nervous system: every one of its 166,700 neurons and the 25 million connections between them, as mapped in the MaleCNS connectome released by HHMI Janelia and Google Research in 2026. It has been given eyes, a body and a world. A webcam is its vision. Its motor neurons, the cells that would move a real fly's muscles, light a 16×16 LED map of the fly's body and drive the legs of a small walking machine (a Strandbeest). The machine's own motion sensors feed back into the fly's sense of balance, closing the loop.

This page explains how it is put together. It starts with the whole system and how signals travel around it, then opens up each part in turn: how the camera image is turned into nerve signals, what happens inside the connectome between eye and muscle, what a single simulated neuron does, and how neural activity becomes light and movement. After that comes an account of the other fly-brain simulations this one learned from and where it does things differently, a table of the numbers that set the scale, and a glossary of the biological terms, which are also linked where they first appear.

1 · The loop ONE 20 ms TICK

Everything runs in one process on the PC, in a fixed rhythm: 20 ms of the fly's time per tick. Sensors are read, the brain is stepped 200 times (0.1 ms each), the outputs are sent. On the CPU one tick takes ~85 ms of wall time (0.23× real time); on the GPU it takes ~14 ms (1.46×). The model is the MaleCNS connectome, every neuron and synapse of one male fruit fly's brain and nerve cord, run as leaky integrate-and-fire units with the parameters of Shiu et al. 2024, in the schedule DOOMFLY ported them to. The one-process, fixed-tick shape is shared with DOOMFLY and Fly64; what those systems lack is the return arrow.

Webcam AUKEY PC-LM1 · 640×360 PC · Windows (numba kernel) or WSL2 (GeNN kernel on the RTX 3070 Ti) Medulla encoder optic flow → T4/T5 expansion → LC4/LPLC2 Proprio encoder gyro → halteres motor speed → chordotonal Brain 166,700 LIF neurons 25.6 M synapses step(drive, 20 ms) → spike counts[n] numba on CPU · 0.23× GeNN on GPU · 1.46× LED decoder 815 motor neurons → 256 cells Motor decoder leg pools L / R → speed −100…100 USB · 30 fps drive (mV) drive (mV) counts Sparkle Motion · WLED · 256 WS2812B 16×16 body map DDP · UDP 4048 ≤ 50 fps · 768 B Strandbeest Atom Matrix S2 S4 IMU · 5×5 LEDs BST1 · UDP 5006 50 Hz · L, R + 5×5 TEL1 · UDP 5007 · 100 Hz · gyro, accel, actual motor speeds one tick = encoders write drive → brain.step(20 ms) → decoders read counts
The whole loop. Solid arrows are the forward path once per tick; the dashed arrow is the only feedback: the beest's IMU and actual servo speeds return at 100 Hz and become drive on the fly's balance sense (halteres) and leg-position sense (chordotonal organs). The panel gets a frame per tick over DDP; the beest gets a command per tick whether or not it changed; 500 ms of silence stops its motors.
LinkProtocolRatePayload
Webcam → PCUSB / OpenCV30 fps640×360 BGR; optic flow computed at 192×108
PC → panelDDP, UDP 4048≤ 50 fps10-byte header + 256 × RGB; WLED maps to the serpentine strip
PC → beestBST1, UDP 500650 Hzleft, right (−100…100), 25-byte 5×5 summary, sequence, xor checksum
beest → PCTEL1, UDP 5007100 Hzgyro xyz, accel xyz, left/right actual, sequence, xor checksum

2 · Breakaway: what the fly sees MEDULLA ENCODER

The camera frame is split down the middle into a left and a right eye. The encoder does the job the fly's first three visual stages would do, because in the spiking model those stages don't transmit (drawing 3, inside the connectome), and injects current where the pathway becomes spiking: the motion detectors (T4/T5) and the looming detectors (LC4, LPLC2). Motion is measured as optical flow with the Farnebäck algorithm. This is the point where this project departs from every other MaleCNS game demo: DOOMFLY, Fly64 and flybrain.online all inject at the photoreceptors or lamina and then need extra help (DOOMFLY a 12 mV tonic current into the lamina, Fly64 a background drive and noise on every neuron) and still report silent or weak downstream responses. We measured why (drawing 3, inside the connectome) and moved the injection point past the dead stages.

left eye · 150° right eye · 150° 15° binocular overlap at the midline translation fx expansion div Optic flow Farnebäck · 192×108 per eye: fx, fy, divergence 60 ms low-pass 1 mV per °/s 100 mV per /s T4 / T5 motion detectors a · front-to-backb · back-to-front c · upwardd · downward ~1,700 cells per subtype per eye LC4 + LPLC2 looming detectors 311 cells · fire the Giant Fiber thresholds: motion > 5 °/s · expansion > 0.15 /s (camera noise floor 0.07) R1–R6 photoreceptors · 3,335 cells luminance path · off by default brightness per eye column (1,780 columns) → Brain as tonic drive (mV)
A medulla stand-in. Image motion in each eye becomes drive on the matching direction-selective population (front-to-back on the left eye is leftward image motion, on the right eye rightward); image expansion becomes drive on the looming detectors. The dotted path is the literal retina model, brightness into photoreceptors, which works as far as the lamina and then stops, so it is off. The medulla is the second neuropil of the insect optic lobe.

3 · Breakaway: inside the connectome SIGNAL PATH, SENSE TO MUSCLE

The brain is not a black box; it is 166,700 named cells in known groups. This drawing follows the visual signal from the eye to the legs and marks where the spiking model breaks down (grey, dotted), where we inject instead (bold arrows), and the loop that latches once lit. Commands leave the brain through descending neurons; the Giant Fiber is the escape command; the ventral nerve cord is the insect equivalent of a spinal cord.

OPTIC LOBE · 89,403 + 6,098 cells CENTRAL BRAIN · 32,164 cells VENTRAL NERVE CORD · 13,161 cells R1–R6 photoreceptors graded · histaminergic Lamina L1 L2 L3 responds · correct sign Medulla Mi1 Tm1 Tm2 Dm Dm amacrines clamp it ✕ nothing gets past here T4 / T5 13,580 cells · 4 directions LC4 · LPLC2 311 cells · looming inject inject Lobula plate tangentials HS · VS · wide-field flow direct to the Giant Fiber Premotor · LAL, PS, GNG turn and walk commands LAL046/083 inhibit DNa02 R Antennal lobe · Mushroom body lLN1/2 · Kenyon cells · APL · DPM ~410 cells at 400 Hz latches on · never releases any stimulus above ~7 mV lights it; a LIF neuron never tires 1,314 descending neurons GF · DNp01 DNa02 L / R DNp09 MDN escape · steer · forward · backward VNC circuits T1 T2 T3 leg premotor wing · neck · abdominal GF → TTM jump muscle 815 motor neurons proboscis · neck 107 wing · haltere 88 legs ×6 384 abdomen 236 Proprioceptors halteres 205 chordotonal 425 · JO-CE 475 ← beest IMU + speeds Sugar taste · LB3 78 cells test stimulus → proboscis MNs
Where the visual signal goes. Grey dotted: the real retina → lamina → medulla chain, whose cells are graded (non-spiking) in the fly and go silent in a spiking model: visual projection neurons stayed at 0.9 Hz whatever the image. Bold "inject": where the encoder puts current instead. From there the wiring works: T4/T5 subtype a in both eyes gives DNa02 left 26 Hz vs right 2 Hz; looming gives the Giant Fiber 132 Hz. Amber: the antennal-lobe / mushroom-body loop that ignites at any stimulus above ~7 mV and keeps the whole network humming at ~12 Hz afterwards. The sugar path at the bottom is the validation stimulus from Shiu et al.: labellar sugar taste neurons → proboscis (feeding) motor neurons, the same experiment eonsystems/fly-brain uses as its benchmark case. DOOMFLY’s note that its biological readouts stayed silent under visual input is the same wall drawn here in grey.
head, neck · proboscis row
wings, halteres
legs, front → hind
abdomen A1 → A10

4 · Breakaway: one neuron, one synapse LEAKY INTEGRATE-AND-FIRE

Every one of the 166,700 cells is the same simple unit. What differs between them is only who they connect to and how strongly (the connectome), and the sign, guessed from each cell's neurotransmitter (acetylcholine excites; GABA, glutamate and histamine inhibit in the fly). The constants are from Shiu et al. 2024.

−45 mV threshold −52 mV rest v time → refractory 2.2 ms excitatory arrivals push v up (+g) inhibitory arrival (−g) spike leak: v decays to −52 mV with τ = 20 ms · synaptic g decays with τ = 5 ms · simulation step 0.1 ms A B axonal delay 1.8 ms Δg = sign(A) × contacts × 0.275 mV dropped if B is refractory sign of A, from its predicted transmitter + acetylcholine · 103,720 cells glutamate 29,302 · GABA 22,069 · histamine 7,891 + assumed: dopamine, serotonin, octopamine, unclear · 3,718 weights stored once as CSR: ptr[n+1] · post[E] · weight[E] · 205 MB
The unit. A cell's voltage drifts toward rest and is pushed by arriving input; at threshold it fires, resets, and ignores everything for 2.2 ms (the refractory period). Each spike reaches its targets 1.8 ms later with a strength set by the synapse count in the electron-microscopy data. The model has no adaptation, no mechanism by which a cell tires under sustained drive, which is why the loop in drawing 3, inside the connectome never releases; adding one is the change under test.

5 · Breakaway: from motor neurons to light and legs DECODERS

Both outputs read the same 815 motor neurons. The panel shows all of them, arranged as the body; the beest reads only the two leg pools. Neither shows raw rate: a slow baseline is subtracted so a change in what the fly is doing is what you see, not its resting hum. Reading motor neurons is unusual: DOOMFLY, Fly64 and flybrain.online all decode a handful of descending neurons (DNa02 for turning, DNp09/DNa01 or DNg100 for forward, MDN for reverse) with hand-set gains; only desktop-fly reads MaleCNS motor neurons, for its leg animation. We keep the descending-neuron decoder as an alternative mode.

815 motor neurons spike counts per 20 ms 409 left · 406 right Body map · rows are anatomy, columns are left | right rows 0–1 · proboscis, neck rows 2–3 · wings, halteres rows 4–9 · front, middle, hind legs16 muscle groups per leg, coxa → tarsus rows 10–15 · abdomen A1 → A10 fly's leftfly's right value = 1 − exp(−(rate − baseline) / 40 Hz) · gamma 2.2 · master 0.25 baseline τ 5 s, 15 % of it still shown · → DDP at ≤ 50 fps all 815 → 256 cells Motor decoder · leg pools left = mean rate of 192 left-leg MNs right = mean rate of 192 right-leg MNs − baseline (τ 4 s) · dead band 0.05 reverse if MDN out-rates DNp09 any non-zero output → 65…100 (the servos ignore less) leg pools only S2 · left servo1500 − v·10 µs S4 · right servo1500 + v·10 µs BST1 Atom Matrix in Atom Motion ESP32 · MPU6886 IMU · 5×5 LEDs slew 20 / 20 ms · watchdog 500 ms button = e-stop 5×5 shows the body map pooled: head / wing / front / mid / hind + abdomen Proprio encoder → Brain yaw → halteres · tilt → JO-CE actual speed → chordotonal TEL1 · 100 Hz mount rotation [90, 0, 180] from the tilt tests
Two readouts of one output. The panel pools every motor neuron into the cell for its muscle group; the beest pools only the leg motor neurons, left and right, into two continuous-rotation servo speeds. The dashed return path is what closes the loop: the beest's yaw rate becomes haltere drive (left turn → left halteres), tilt becomes drive on the gravity-sensing cells of Johnston's organ (JO-CE), and each side's actual speed becomes that side's leg-position sense.
Measured, not assumed: with a symmetric stimulus the model turns left more readily than right (DNa02 left 35 Hz vs right 4 Hz). The wiring totals onto the two cells match; the difference is extra inhibition reaching the right one from four named premotor cells. Whether that is the fly, the reconstruction, or a transmitter-sign prediction is an open question, and now a specific one.

6 · Lineage: what was borrowed, what was measured, what is new

The design was built on a reading of the other simulators that appeared around the MaleCNS release (September 2026) and the earlier FlyWire work they descend from. The table is the audit trail: for each element, where it came from and whether this project aligns with or departs from the source, and why.

ElementSourceRelationship
Neuron model and constantsShiu et al. 2024 (FlyWire; Brian2; code)Aligned. τm 20 ms, τsyn 5 ms, −52/−45 mV, 2.2 ms refractory, 1.8 ms delay, 0.275 mV per contact, 0.1 ms step. The only parameter set with a peer-reviewed validation behind it. The kernel reproduces its sugar → proboscis experiment (34 Hz, silent before).
Kernel scheduleDOOMFLY (MIT), doom/engine.pyAligned, then extended. Same event-driven CSR kernel, same reset-at-delivery schedule and “unless refractory” semantics, adapted with attribution. Ours adds an active set with parking, checkpointing, and a GPU twin with cross-kernel state transfer.
Graph constructionDOOMFLY datasets.json node/edge policyAligned, verified. Same node policy (assigned superclass, glia excluded), same edge policy (all edges, autapses kept). Our build reproduces DOOMFLY’s counts exactly: 166,700 neurons, 25,582,938 edges, 124,177,617 contacts, 3,718 uncertain-sign cells treated as excitatory.
Photoreceptor eye columnsDOOMFLY (receptor positions inferred from hex-annotated L1/L2/L3 targets)Aligned. Same inference; 3,335 receptors mapped and 42 not, DOOMFLY’s numbers. Then found not to matter, because the path is dead in LIF.
Where vision is injectedDOOMFLY, Fly64, flybrain.online, mrfly: photoreceptors or L1/L2Departs. Measured that visual projection neurons stay at 0.9 Hz whatever the image under photoreceptor drive, and that T4/T5 never fire from any Mi1/Tm drive. Inject at T4/T5 (4 directions per eye) and LC4/LPLC2 instead; both reach descending neurons (DNa02 26 vs 2 Hz; Giant Fiber 132 Hz).
Background drive and noiseFly64 (tonic drive + Bernoulli noise on all neurons; dt 20 ms)Tested and rejected. 3–6 mV tonic + 1 mV noise lights the whole network but adds no image dependence (visual projection neurons flat across dark / left / right stimuli). Fly64’s 20 ms step also makes the network a rate model; we keep 0.1 ms.
ReadoutDOOMFLY (DNp20, DNpe017; alt. DNa02/DNp09/MDN/MN9), Fly64 (DNg100, DNa02/DNg13, DNp01/DNp10), flybrain.online (DNa02/DNa01/MDN/DNp09)Departs. Primary readout is the 815 motor neurons pooled by muscle group: the VNC’s result rather than the brain’s command. Descending-neuron decoding kept as a mode; the harness found DNa02 R suppressed under symmetric drive (extra inhibition via LAL046/083/120_a, GNG515), which would bias a DN-only decoder left.
Closed loopdesktop-fly (looming from cursor, motor rates → leg joints); all game demos open-loopNew. Real IMU and servo speeds return into halteres, JO-CE and chordotonal populations. Harness result so far: measurable (+1.5–2 Hz leg MN) but tonic: positive feedback, no gait rhythm.
Network latchDOOMFLY logs (“network stays busy”), kernel agent reportCharacterised. AL/MB loop, ~410 cells at the refractory ceiling, ignites at the T4/T5 firing threshold (~7 mV), all-or-nothing, never releases. Panel and motor decoders subtract a slow baseline; spike-frequency adaptation is the change under test.
GPU kerneleonsystems/fly-brain benchmarks (GPL-2; reference only): GeNN 2.0× on an RTX 4070, Brian2CUDA 0.27×, PyTorch 0.10×Aligned in choice, independent in code. Their table is why GeNN and not torch. Our PyGeNN kernel (out-degree-banded relays, integer weights for determinism) reaches 1.46× real time on the 3070 Ti in the latched regime.
Vision geometryNeuroMechFly v2 (cited by Fly64 for wide-angle eyes)Loosely aligned. Two ~150° eyes with 15° overlap; hex-axis orientation is an engineered guess, recorded as such.
Panel and robotWLED + DDP; the previous MQTT-era sparkbeest sketch and controllerReused. Servo ports, pulse mapping (1500 ± v·10 µs, left mirrored) and I²C pins taken from the old sketch; transport changed from MQTT to direct UDP with a watchdog.

Not used, but read: snedea/flybrain (FlyWire, LIF in a browser worker), lixiang1076/fly-brain, NeuroCraft Fly (Minecraft; no code released, “scripted body programs”), the Beat Saber demo (motor patterns recorded, per its author), and Jin et al. 2026, who use the connectome as a trained controller architecture rather than as a dynamical model, a different question.

Numbers that set the scale

QuantityValueWhere it bites
Neurons · synaptic edges · contacts166,700 · 25,582,938 · 124,177,617graph.npz, 205 MB in CSR
Tick · timestep20 ms · 0.1 ms200 kernel steps per I/O exchange
Real-time factor, latched networknumba 0.23× · GeNN 1.46×~1.5 M spikes/s to deliver
Eye columns · motion detectors · loom detectors1,780 · 13,580 · 311encoder targets
Motor neurons · descending neurons815 · 1,314outputs read; commands watched
Servo response floor · panel current cap≈ 60 / 100 · 2,000 mAmin_speed 65; WLED brightness limiter

Glossary

Connectome
A complete wiring diagram: every neuron and every synapse between them, reconstructed from electron-microscope images. MaleCNS is the first for a whole adult male fly nervous system.
LIF neuron
Leaky integrate-and-fire: the simplest spiking neuron model: a voltage that leaks, sums input, and fires when it crosses a threshold. drawing 4, one neuron.
Optic lobe
The visual processing stack behind each eye: lamina, medulla, lobula and lobula plate. 95,000 of the fly's neurons live here.
Ommatidium · eye column
One facet of the compound eye: a lens, eight photoreceptors, and the column of neurons behind it that keeps processing that one point of the scene. Each eye has ~800 of them, arranged in a hexagonal lattice ~5° apart, the "hex columns" in the data. The fly's image is 800 pixels per eye; everything downstream works column by column with neighbours.
R1–R6 photoreceptors
The six outer photoreceptors of each ommatidium: broadband, high-sensitivity, fast. They do the fly's luminance and motion vision (R7/R8 in the centre handle colour and UV). They respond to light with a graded voltage, not spikes, and release histamine, which inhibits their targets, so more light means less transmitter. Their job is to convert light to a fast analogue signal and to adapt to the mean brightness so the next stage sees contrast, not absolute level. Not used here: in a spiking model a graded, inhibitory-only cell transmits nothing useful; we measured L1 responding with the correct sign and nothing beyond it.
Lamina · L1, L2, L3
The first neuropil: one cartridge per column, receiving the six R1–R6 that look at the same point in space. L1 and L2 invert and split the signal into an ON channel (L1: brightening) and an OFF channel (L2: darkening), each reporting change in brightness rather than brightness itself, with lateral inhibition between neighbouring cartridges that sharpens edges. L3 carries a slower, sustained luminance signal. In engineering terms the lamina is a high-pass filter and a contrast normaliser with an ON/OFF split, the same first steps as a camera pipeline's auto-exposure and edge enhancement. Not used here: it works as far as it goes (our L1 rates fall on the lit side as they should) but the layer after it does not carry the signal on.
Medulla · Mi1, Tm1, Tm2, Dm
The second and largest neuropil (~40,000 neurons per eye, in ten layers). It takes the ON and OFF channels and builds the inputs the motion detectors need: Mi1 and Tm3 carry ON signals with different delays, Tm1, Tm2 and Tm4 carry OFF signals with different delays, and the Dm and Pm amacrine cells (glutamatergic and GABAergic, spanning many columns) provide the lateral inhibition that adapts gain and suppresses uniform illumination. Delaying one copy of the signal relative to a neighbouring column is the trick that lets T4/T5 compute direction: a moving edge arrives at column A first and column B a moment later, and the detector fires when the delayed A signal coincides with the fresh B signal (a Hassenstein–Reichardt / Barlow–Levick correlator). Not used here: in the spiking model the Dm amacrines lock at 40–100 Hz and clamp the columnar cells (Tm1 at 0.4 Hz), so no delayed-and-compared signal reaches T4/T5, which is why the encoder computes the flow itself and injects at T4/T5.
Lobula · lobula plate
The third and fourth neuropils. The lobula plate holds the T4/T5 terminals in four direction-specific layers and the wide-field tangential cells (HS, VS) that sum them into whole-eye optic-flow signals (yaw, pitch, roll) used for course control. The lobula holds the feature detectors: the LC and LPLC columnar neurons (LC4/LPLC2 for looming, LC11 for small objects, LC10 for courtship targets) that project to specific glomeruli in the central brain. These are the first stages that work in the spiking model, which is why they are the injection points.
T4 / T5
The fly's elementary motion detectors in the lobula plate: T4 for brightening edges, T5 for darkening ones, each in four subtypes tuned to the four directions. Maisak et al. 2013.
LC4, LPLC2
Lobula columnar and lobula-plate/lobula columnar neurons that respond to looming (approaching) objects and drive the escape circuit. Ache et al. 2019.
Descending neurons
The ~1,300 cells whose axons carry commands from the brain into the ventral nerve cord. DNa02 steers, DNp09 walks forward, MDN walks backward, DNp01 (the Giant Fiber) triggers escape.
Giant Fiber
A single very large descending neuron per side whose spike triggers the escape jump within milliseconds.
Ventral nerve cord
The insect's spinal-cord equivalent: the leg, wing and abdominal circuits and all 815 motor neurons.
Halteres
Club-shaped remnants of the hind wings that beat in antiphase to the wings and sense body rotation: the fly's gyroscopes. The beest's gyro drives them.
Chordotonal organ
Stretch-sensing organ at a joint; the leg chordotonal organs report joint angle and movement. The beest's actual servo speed drives them.
Johnston's organ
The mechanosensory organ in the antenna: some cells hear (courtship song), others sense wind and gravity (JO-C/E). The beest's tilt drives the latter.
Antennal lobe · Mushroom body
The fly's olfactory processing centre and its learning/memory centre. In this model their recurrent loop is what latches on after any stimulus.
Optic flow
The pattern of apparent motion in an image as the viewer or scene moves; computed here with the Farnebäck algorithm and split into per-eye translation and expansion.
WLED · DDP
Open-source ESP32 LED firmware and the UDP protocol it accepts for real-time pixel streaming.
Strandbeest
Theo Jansen's wind-walking linkage. Ours is driven by two continuous-rotation servos, one per side, so it steers like a tank.