Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This project connects a computational model of a fruit fly’s nervous system to a small quadrotor. The nervous system model is built directly from the wiring diagram of a real fly. The quadrotor is a Bitcraze Crazyflie 2.1 carrying a forward-facing camera and a downward-facing flow and range sensor. The camera feeds the model’s photoreceptors, the gyroscope feeds the neurons that a fly uses to sense body rotation, and the model’s wing motor neurons are read out and turned into flight commands. A learning procedure tunes the boundaries of the system, the way sensors are encoded and the way motor neurons are decoded, along with a small number of physiological constants, so that the whole thing can keep the drone in the air. The wiring itself is never changed.

The project is named Flatline, after the Dixie Flatline of Gibson’s Neuromancer: a recorded mind, run as a program, to do a job. The recorded wiring that the engine runs is called an imago, the entomological term for the adult insect and the Latin for image. A built imago is a file, and the engine animates it.

This section explains the ideas the design rests on, for readers who know software or robotics but not neuroscience, or the reverse.

Connectomes

A connectome is a map of every neuron in a piece of nervous tissue and every synapse between them, reconstructed from electron microscopy at a resolution fine enough to see individual synaptic contacts. The dataset used here is the Janelia FlyEM male central nervous system (CNS) release, version 1.0. It covers the brain, the optic lobes, and the ventral nerve cord (the fly’s equivalent of a spinal cord) of one adult male Drosophila melanogaster. It contains about 166,000 neurons with assigned cell types and about 25 million significant connections, where each connection records how many synapses link a presynaptic neuron to a postsynaptic one.

Three properties of this dataset make the project possible.

  • It is complete from sense organ to muscle. Photoreceptors, the mechanosensory neurons of the halteres (the fly’s gyroscopic organs), the descending neurons that carry commands from the brain to the body, and the motor neurons that drive the wing muscles are all present and labeled.
  • Each neuron has a predicted neurotransmitter. In the fly, acetylcholine is the main excitatory transmitter and GABA and glutamate are the main inhibitory ones. Knowing the transmitter tells us the sign of every connection.
  • The optic lobe neurons carry coordinates on the hexagonal lattice of the compound eye, which lets us place each photoreceptor in the visual field.

A connectome is a structure, not a program. It says which neurons talk to which and how strongly, but not what any of them are doing at a given moment. To get behavior out of it, the structure has to be animated with a model of how neurons work.

Leaky integrate-and-fire models

The simplest useful model of a neuron treats its membrane voltage as a leaky capacitor. Incoming spikes push the voltage up (excitatory) or down (inhibitory), the voltage relaxes back toward a resting level with a characteristic time constant, and when it crosses a threshold the neuron emits a spike of its own, resets, and stays quiet for a brief refractory period. This is the leaky integrate-and-fire (LIF) model.

In 2024, Shiu and colleagues built a LIF model of an entire fly brain from the FlyWire connectome, with one free parameter, the voltage jump per synapse, and with connection signs taken from neurotransmitter predictions. Despite its simplicity the model reproduced known sensorimotor circuits: stimulating sugar-sensing neurons activated the feeding motor program, and stimulating specific mechanosensory neurons activated grooming. That result is the license for this project. If a signed LIF network built from a connectome recapitulates real circuits, it is worth asking what its flight circuits do when connected to a flying machine.

This project uses the same neuron model and the same initial constants, applied to the male CNS connectome, which unlike FlyWire includes the ventral nerve cord and therefore the wing motor neurons. One caution is owed up front: Shiu et al. drove spiking taste and touch neurons. This project’s main input is the retina, whose photoreceptors release histamine, an inhibitory transmitter, onto lamina cells that in the real fly signal by graded potentials rather than spikes. The design spec, section 8.6, states how this design keeps that pathway alive and how it will be checked.

How a fly flies, briefly

A fly’s flight control loop has four stages that the design mirrors.

  • Vision. The compound eyes each have about 800 facets, and each facet samples one direction in the visual field. Downstream circuits in the optic lobes compute local motion, and wide-field neurons in the lobula plate integrate that motion into estimates of self-rotation and self-translation. This is optic flow processing, and it is the fly’s main source of information about drift.
  • Halteres. The hindwings of flies have evolved into small club-shaped organs that beat with the wings. When the body rotates, Coriolis forces deflect them, and strain-sensing neurons at their base report the rotation. Halteres are fast gyroscopes and are essential for stable flight.
  • Descending neurons. About 1,300 neurons carry commands from the brain down into the ventral nerve cord.
  • Wing motor neurons. Two large power muscles drive the wingbeat, and about a dozen small steering muscles per side adjust wing stroke to produce turns, climbs, and corrections. The male CNS contains 67 wing motor neurons and 16 haltere motor neurons.

A quadrotor has none of this anatomy, so the last stage requires a translation: the pattern of activity across the wing motor neurons is mapped to the four things a quadrotor can be told to do, move sideways, move forward, turn, and climb.

The Crazyflie platform

The Crazyflie 2.1 is a 27 gram open-source quadrotor with a well-documented firmware and a Python client library. Two expansion decks are used. The AI deck adds a monochrome 324 by 324 pixel camera with an 87 degree field of view, a small processor, and a WiFi radio that can stream frames to a laptop. The flow deck v2 adds a downward time-of-flight range sensor and an optical-flow sensor, which let the firmware hold height and estimate horizontal velocity.

The firmware’s own stabilizer stays in the loop. The fly brain does not drive motors directly; it issues setpoints that the firmware executes. Two levels of setpoint are used. In hover mode the brain commands velocities and the firmware nulls drift on its own, which is safe but masks the brain’s contribution. In attitude mode the brain commands roll and pitch angles and must correct drift itself from vision and haltere input, which is the real experiment.

Evolution strategies

The parameters that must be learned are few, roughly ten thousand, and the system being tuned is a spiking network that is not differentiable in any convenient way. Evolution strategies fit this case. The optimizer keeps a mean parameter vector, samples a population of perturbed copies, runs each through a simulated flight, scores it, and moves the mean toward the perturbations that scored well. It needs only episode returns, runs identically on any hardware, and parallelizes across a population. The price is sample inefficiency, which is paid for with a batched simulator that advances many brains and many drones at once.

What to expect

It is not known whether a frozen connectome with tuned boundaries can hold a quadrotor in a hover. The literature suggests the visual and haltere circuits are the right ones, and the model will be given every sensible advantage: correct signs, correct sensory placement, a stabilizing firmware underneath, and a training curriculum that starts easy. But the project is an experiment, and the documentation is built as a lab notebook so that negative results are recorded as carefully as positive ones.

Background and related work

This chapter surveys the connectome dataset, the modeling approaches borrowed, and the flight hardware.

The male CNS connectome

The Janelia FlyEM male CNS v1.0 release is a full central nervous system reconstruction of one adult male Drosophila melanogaster: brain, optic lobes, and ventral nerve cord, imaged by electron microscopy and segmented into identified neurons. It contains roughly 166,700 typed neurons and about 25.6 million significant connections, recording how many synapses link a presynaptic neuron to a postsynaptic one. Every neuron carries a predicted neurotransmitter, giving a sign to each synapse, and optic lobe neurons carry column coordinates on the eye’s hexagonal lattice, letting photoreceptors be placed in a visual field.

A separate dataset, FlyWire, reconstructs a female whole brain but lacks a ventral nerve cord, and therefore wing motor neurons: it stops at the brain’s outputs, not muscle. That completeness is why this project uses the male CNS dataset.

Whole-brain spiking models

Shiu et al. 2024 built a leaky integrate-and-fire model of the entire FlyWire brain. Every synapse’s sign came from its presynaptic neuron’s predicted transmitter, and the model had one fitted free parameter, a voltage jump of 0.275 mV per synapse. Despite that simplicity, driving sugar-sensing neurons activated the feeding motor program, and driving mechanosensory neurons activated grooming. That result is this project’s license: a signed network built directly from a connectome can reproduce real circuit behavior without tuning individual connections.

A caution carries over rather than a guarantee. Shiu et al. drove excitatory taste and touch neurons, and their success says nothing about pathways that start differently. This project’s main input is the retina, and photoreceptors are histaminergic, an inhibitory transmitter; inhibition onto a resting spiking neuron does nothing, so vision needs its own answer first.

Connectome-constrained visual models

Lappalainen et al. 2024 took a different approach: a connectome-constrained rate model of the fly visual system, trained by task optimization rather than fit synapse by synapse, that predicted neural responses with good accuracy. The result matters here because fixed connectome structure plus a small set of learned parameters can produce function that matches a real nervous system. This project differs on three axes: spiking rather than rate-based, the whole nervous system rather than one pathway, and closed loop on a physical body rather than scored against recorded activity.

The optic lobe and the eye map

Nern et al. 2025 (Connectome-driven neural inventory of a complete visual system) is the source of the column coordinates used to place photoreceptors in the visual field. Zhao et al. 2025 (Eye structure shapes neuron function in Drosophila motion vision) reports measured facet directions for the compound eye, obtained directly rather than inferred from connectivity. The current design uses a parametric eye model built from the column coordinates; the measured directions are a natural input to a future, more accurate map.

Fly flight control

A fly’s flight loop runs through the stages this design mirrors. Vision starts at the compound eyes, where each facet samples one direction; motion detector neurons T4 and T5 compute local motion, and wide-field lobula plate neurons HS and VS integrate it into estimates of the fly’s own rotation and translation. This optic flow processing is the fly’s primary source of information about drift.

Halteres, the fly’s reduced hindwings, deflect under Coriolis forces when the body rotates; sensory neurons at their base report the deflection, making halteres fast gyroscopes feeding the wing motor system. Descending neurons, about 1,300 of them, carry commands from the brain into the ventral nerve cord, reaching the wing motor neurons: 67 in this dataset, driving the power muscles and the smaller steering muscles per side that produce turns, climbs, and corrections.

The Crazyflie platform

The Crazyflie 2.1 is a 27 gram open-source quadrotor with documented firmware and a Python client library, cflib. Two expansion decks supply the sensors used here: the AI deck adds a monochrome camera with an 87 degree field of view, streaming frames over WiFi to a laptop, and the flow deck v2 adds a downward time-of-flight range sensor and an optical-flow sensor for height and horizontal velocity. The firmware’s own stabilizer stays in the loop; the brain issues setpoints for it to execute rather than driving motors directly, and cflib sends the setpoints and reads telemetry back.

Where this project sits

This project is an early attempt to put a whole-CNS connectome model on a physical body and close the loop in real flight. The wiring itself is never changed; only the boundaries, sensory encoding, motor decoding, and a few global constants, are learned, by evolution strategies rather than by hand. What that framing does and does not claim about the resulting system is the subject of the ethics chapter.

See the References chapter for full citations.

Ethics and philosophical implications

This project sits at the meeting point of three lines of work that each carry their own questions: whole-brain modeling, embodied artificial agents, and autonomous flight. The questions are recorded here so that the project’s claims, and its limits, are stated before any result exists to tempt overstatement.

What is being simulated

The model is built from the wiring of one individual male fly. It keeps the neurons, the synapse counts, and the transmitter signs, and it discards nearly everything else: dendritic computation, graded signaling, electrical synapses, neuromodulation, plasticity, glia, development, and the hormonal and metabolic state of a living animal. It is a connectome-constrained spiking network, a structural echo of a fly, not an emulation of one. The project will describe it that way. Phrases such as “a fly brain flies a drone” are convenient and will be avoided in favor of “a network built from a fly connectome”. The boundary parameters and global constants are tuned by an optimizer, so any behavior the system shows is a joint product of the wiring and the tuning, and the paper must separate the two.

Epistemic commitments

Two commitments follow. First, the wiring stays frozen and the learnable set stays small, so that whatever the optimizer finds is constrained by the connectome rather than replacing it. Second, every claim about the connectome’s contribution is tested against controls with the same learnable set: a connectome whose internal wiring is shuffled within synapse-count classes, preserving every neuron’s synapse totals, sign, and sensory interface, and an untrained network with default constants. If the shuffled control flies as well, the wiring did no work, and that is the result to report. Negative results are recorded in the notebook with the same care as positive ones.

Moral status

Whether insects have experiences that matter morally is an open scientific and philosophical question; recent statements by researchers in animal consciousness treat it as a realistic possibility rather than a settled negative. This project takes the position that the simulation is not the animal. It lacks the biophysics, the body, and the internal states that any current theory of experience relies on, and it is far coarser than the models that would raise the question seriously. That position is stated as an assumption, not a proof, and it is one the field will have to revisit as models become richer. No live animals are used in this project. The dataset derives from a single fly that was sacrificed for the connectome; using that data carefully and crediting it properly is the only way to honor that cost.

Re-embodiment

A fly’s nervous system evolved for a body with wings, halteres, legs, and eyes that span nearly the full sphere. Here it is given a quadrotor with a single 87 degree camera and a gyroscope, and a control interface that is at best an analogy to wing steering. Success would suggest that some of the circuits compute something general enough to survive that transplant, for example an estimate of self-rotation from optic flow that is useful to any flying body. Failure would be harder to interpret, because it could reflect the model, the interface, the sensors, or the optimizer. The design tries to make failure informative through ablations and through the hover-mode curriculum, which isolates the brain’s contribution stage by stage. Closed-loop embodiment is a stronger test than replaying recorded stimuli, because errors feed back into the input, and that is why the project puts the model on a physical machine rather than only in a simulator.

Whole-brain emulation

The fly is the first organism for which a complete central nervous system wiring diagram and a working functional model both exist. Giving such a model a body is the natural next step, and this project is among the early attempts to do so in hardware. That places it on a path that leads, in the long run, toward emulating larger nervous systems, with all the questions about identity, consent, and welfare that path raises. Nothing in this project approaches those questions directly, but a project on the path should say so, and should keep its methods and its language modest enough that others can build on them without inheriting exaggerated claims.

Dual use and physical safety

Autonomous flight controllers derived from neural networks have obvious uses beyond science, and a biologically derived controller is no exception in principle. In practice this controller is a 27 gram research platform that struggles to hover in a workshop, and its scientific value lies in what it reveals about a fly’s circuits, not in its performance as a controller. The repository is private during development and the results will be published as science. Physical safety is a direct obligation: the supervisor, geofence, kill switch, and prop guards exist to protect people in the workshop, and no flight takes place with a person inside the geofence.

Credit and provenance

The connectome is the product of years of work by the Janelia FlyEM project and its collaborators, and the eye-map and visual-system analyses come from the Reiser lab. Their data are used under their published terms and cited in every output. The imago built by this project records the source file hashes so that derived results can be traced to the exact release. No code from those groups is copied into this repository; their conventions are followed and referenced.

Design

This section documents how Flatline Imago is put together: how the raw connectome files are ingested into a single .imago construct, and how the brain engine animates that construct as a signed leaky integrate-and-fire network. It also carries the external review that shaped the current design.

Connectome ingestion and brain engine

Connectome ingestion

Inputs

From ~/models/fly/model/flat-connectome/:

FileUsed for
body-annotations-male-cns-v1.0-minconf-0.5.featherNeuron identity: bodyId, superclass, class, subclass, type, instance, somaSide, rootSide, entryNerve, exitNerve, assignedOlHex1, assignedOlHex2, status
body-neurotransmitters-male-cns-v1.0.featherconsensus_nt per body
connectome-weights-male-cns-v1.0-minconf-0.5-significant-only.featherEdges: body_pre, body_post, weight (synapse count)
connectome-weights-male-cns-v1.0-minconf-0.5.featherFull edge list, used only to infer photoreceptor columns

The synapse-point and synapse-partner files are not used.

Neuron set

Neurons are the bodies with a non-null superclass, about 166,000. Each receives a dense index in a stable order (sorted by bodyId). Region masks (see Region masks) select subsets at load time without rebuilding.

Signs and effective weights

Each synapse’s sign comes from the presynaptic neuron’s consensus neurotransmitter, following Shiu et al.:

TransmitterSign
acetylcholine, dopamine, serotonin, octopamine+1
GABA, glutamate, histamine−1
unclear (the dataset’s own label, 2,999 neurons)+1, and the neuron is flagged
no row in the transmitter file (178 neurons)treated as unclear and flagged

The effective weight of an edge from neuron \(i\) to neuron \(j\) is

\[ w_{ij} = c_{ij} \cdot \mathrm{sign}(nt_i) \cdot s[nt_i] \cdot g[t_i] \cdot W_{\mathrm{syn}} \]

where \(c_{ij}\) is the synapse count, \(nt_i\) and \(t_i\) are the presynaptic neuron’s transmitter and gain group, \(s\) is a learnable per-transmitter scale (eight values in the fixed table order acetylcholine, gaba, glutamate, dopamine, serotonin, octopamine, histamine, unclear; initialized to 1 and constrained non-negative so learning can never flip a sign), \(g\) is a learnable per-gain-group factor (design spec, section 12.1), and \(W_{\mathrm{syn}}\) is 0.275 mV, the Shiu et al. value. Monoamines are excitatory here because Shiu et al. treated them so; that is a recorded decision (design spec, section 4), not a fact about the fly. \(W_{\mathrm{syn}}\) was fitted by Shiu et al. on FlyWire feeding circuits, and its transfer to this dataset is a risk carried in the design spec, section 15. The imago stores counts and signs; scales and gains are applied at load.

Edges whose postsynaptic neuron is an input neuron are dropped at build time and counted in the metadata: input neurons are driven by encoders, never by the network.

A build option produces a shuffled imago for the control condition of the design spec, section 12.5. Edges are grouped by synapse count and, within each group, their destinations are permuted with a seeded generator. Every neuron therefore keeps its exact outgoing edges and their counts, its exact incoming synapse total and incoming count distribution, and its transmitter sign, while its partners are randomized: the synapse totals are preserved exactly, but the number of distinct partners a neuron has may change, because two permuted edges occasionally land on the same pair and are merged. Edges whose presynaptic neuron is an input neuron are never shuffled, so the control shares the real sensory interface and randomizes only the brain’s internal wiring. The sidecar records the seed, the number of edges shuffled, and the number merged.

Imago format

A single safetensors file with the .imago extension plus a JSON sidecar, about 300 MB:

  • pre_indptr, pre_indices, pre_counts: edges grouped by presynaptic neuron (int64 pointers, int32 indices, int16 counts). Used by the event propagator.
  • post_indptr, post_indices, post_counts: the same edges grouped by postsynaptic neuron. Used by the batched propagator.
  • Per-neuron arrays: body_id (int64), nt (int8 index into the transmitter table), type_id (int32 index into the type table), superclass_id, side (int8: left, right, unknown).
  • Tables in the sidecar: transmitter names, type names, superclass names, build metadata (source file hashes, date, git describe).
  • Named neuron sets: photoreceptors with per-neuron eye and column, virtual_photoreceptors, haltere_afferents with side, wing_motor and haltere_motor with side and type, descending.

Photoreceptor placement

Photoreceptor cell bodies lie in the retina, outside the imaged volume, so they carry no hex coordinates and no soma side. Two inferences supply them:

  • Eye: rootSide (3,746 right, 2,345 left).
  • Column: the hex column receiving the largest summed synapse count from the photoreceptor, over hex-bearing targets, using the full edge list (only 4,038 photoreceptors have any significant-only outgoing edge). The column is chosen by summed weight rather than by the single strongest target because a lamina cartridge, not a cell, is what a photoreceptor innervates; on this dataset the two rules agree on nearly every cell (median fraction of weight on the best column is 1.0). The eye fallback and the recorded target side are the side of that winning column. Hex-bearing targets in v1.0 are exactly the 23,720 optic lobe intrinsic cells of fifteen types: L1, L2, L3, L5, C2, C3, T1, Mi1, Mi4, Mi9, Tm1, Tm2, Tm4, Tm9, Tm20. Placement succeeds for 5,895 of 6,091 photoreceptors, and the target side agrees with the root side in every case.

Coverage of the resulting map:

EyeColumnsWith any photoreceptorWith R1-R6With R7 or R8
Right892784526730
Left879682300638

The reconstructed retina is incomplete and imperfectly placed: a real column has six R1-R6 cells, but placed columns hold between one and eleven (v1.0 build, 826 columns with any R1-R6: 240 hold six, 547 hold fewer, 39 hold seven to eleven, the last being placement errors), and 2,054 of the 6,091 photoreceptors have no outgoing edge at all in the significant graph. The design spec, section 8.3, describes the two corrections that follow from this — a per-lamina-cell factor \(6m/S\), where \(S\) is the R1-R6 synapse count a lamina cell receives and \(m\) the median single-cell count onto its type, and a virtual photoreceptor for every column holding an undriven lamina cell — and the build report that records these counts.

Other named sets

SetCountSelection
Haltere afferents439 (220 right, 219 left)sensory superclass, entryNerve DMetaN, side from rootSide
Wing motor neurons67 (33 left, 34 right)subclass wm; side from somaSide
Haltere motor neurons16 (8 per side)subclass hm; side from somaSide
Descending neurons1,314superclass exactly descending_neuron

Side rule: sensory neurons carry rootSide and a null somaSide; motor and central neurons carry somaSide and a null rootSide. The imago records somaSide when present, else rootSide. The haltere afferent set keeps each cell’s subclass (haltere 205, campaniform sensilla 195, mechanosensory bristle 39) and type (22 types) as fields, so downstream encoders can group by type rather than by cell.

Brain engine

Neuron model

Each neuron has a membrane voltage \(v\) and a synaptic variable \(g\), following the Shiu et al. formulation:

\[ \tau_m \frac{dv}{dt} = (v_{\mathrm{rest}} - v) + g + b \qquad \text{(unless refractory)} \]

\[ \tau_s \frac{dg}{dt} = -g \qquad \text{(unless refractory)} \]

\[ g_j \leftarrow g_j + w_{ij} \qquad \text{on presynaptic spike } i \text{ after delay } d \text{, also while refractory} \]

\[ \text{if } v > v_{th}: \quad \text{spike}, \; v = v_{\mathrm{reset}}, \; g = 0, \; \text{refractory for } t_{\mathrm{ref}} \]

These are the Shiu et al. rules as implemented in their released code: both differential equations are frozen while refractory, incoming synaptic weight still accumulates into g during that time, the threshold is strict, and the reset zeroes g. The term b is a per-neuron bias in mV, zero by default, used by the visual transmission policy of the design spec, section 8.6.

Initial constants (Shiu et al. 2024):

ConstantValue
τ_m (membrane time constant)20 ms
τ_s (synaptic time constant)5 ms
v_rest−52 mV
v_th−45 mV
v_reset−52 mV
t_ref2.2 ms
d (spike delay)1.8 ms, rounded to 2 steps at 1 ms
W_syn0.275 mV per synapse

Integration is exponential Euler with step \(dt\), default 1 ms, with 0.1 ms available for fidelity checks. For a non-refractory neuron:

\[ g \leftarrow g \, e^{-dt/\tau_s} + (\text{delayed incoming weights}) \]

\[ v \leftarrow v_{\mathrm{rest}} + g + b + (v - v_{\mathrm{rest}} - g - b) \, e^{-dt/\tau_m} \]

For a refractory neuron \(v\) stays at \(v_{\mathrm{reset}}\) and \(g\) keeps its value plus any delayed incoming weights (no decay). Step counts are round(t_ref/dt) for the refractory period (2 at 1 ms) and max(1, round(d/dt)) for the delay (2 at 1 ms).

Learnable global knobs: the eight transmitter scales (non-negative), \(\tau_m\), \(\tau_s\), an additive threshold offset, the per-group gains and the lamina bias of the design spec, sections 12.1 and 8.6. Gains are regularized toward 1 in the training objective. Optional Gaussian membrane noise is available as a knob but off by default.

Input neurons

Photoreceptors, virtual photoreceptors, and haltere afferents are input neurons. Their membrane dynamics are bypassed: v and g are held at rest and no edge targets them (see Signs and effective weights). Each step they spike with probability rate_hz × dt_ms / 1000 where the rate is supplied by an encoder. This is a deliberate simplification of Shiu et al., who added Poisson input to the membrane of otherwise normal neurons; forcing the spikes directly makes the encoder’s rate the exact firing rate and costs nothing in the pathway we care about, since photoreceptor output is the spike train itself.

Propagation interface

class Propagator(Protocol):
    def propagate(self, spikes: Tensor) -> Tensor:
        """spikes: bool [B, N] (B=1 in flight). Returns weight input [B, N]."""

Two implementations:

  • Event propagator. Finds spiking indices, gathers their outgoing segments from the presynaptic CSR, expands with repeat_interleave, and index_add_s effective weights into the input vector. Works on Metal, ROCm, and CPU. Used in flight (B = 1).
  • Batched propagator. Computes the input for all B brains as a sparse-by-dense product using the postsynaptic CSR on CPU and ROCm. On Metal, where sparse support is thin, the event propagator handles all B brains in one packed gather and scatter over the flattened [B × N] state, never a Python loop over brains.

The event path pays one device-to-host synchronization per step to size the gathered index (the spike count is data dependent); that is inherent to event-driven propagation and is accounted for in the compute budget of the design spec, section 19.

A native (Rust or C++) event kernel may be substituted behind the same interface later. Tests require the two implementations to agree exactly on weights that are exact in float32 (dyadic rationals) and to within a small tolerance on random graphs, because scatter-add order differs between devices and implementations.

Delays

A ring buffer of two spike vectors implements the 2 ms delay. The propagator consumes the vector from two steps ago.

Real-time clock

In flight the engine steps to keep brain time within a configured tolerance of wall time, default 20 ms. Falling behind by more than the tolerance raises a brain-lag fault to the supervisor. Before takeoff the supervisor requires a measured real-time ratio above 1.0 for the configured mask on the current device, taken from the benchmark tool.

Region masks

A mask is a TOML file listing superclasses, classes, or explicit types to include or exclude. Masks are a benchmarking and ablation tool, not a real-time strategy: the optic lobes alone are 89,403 of the 166,700 neurons and cannot be dropped without dropping vision, and excluding everything that is not plausibly involved in flight removes only about 0.2% of neurons. Presets:

  • full: every neuron in the imago (166,700 real plus 1,250 virtual photoreceptors, 167,950 in all).
  • no-optic-lobe: excludes superclasses ol_intrinsic, ol_sensory, visual_projection, visual_projection_tbc, and visual_centrifugal, and the virtual photoreceptors, leaving 61,433 neurons and 12,165,352 edges. A compute probe and a “blind” ablation; it is never a flight configuration.

Edges to or from excluded neurons are dropped at load. The benchmark tool reports steps per second for each preset on each device, and flight is gated on the measured real-time ratio of the configuration actually flown.

Recording

Named neuron sets can be recorded to a spike ring buffer and flushed to disk as compressed arrays. Flight runs record motor neurons and descending neurons by default; full-brain rasters are available for offline analysis.

Determinism

All randomness is seeded and drawn on the CPU so the random stream is identical across backends. Given the same device, backend, and seed, a run is reproducible up to floating-point scatter order, which is not bitwise stable on GPUs; comparisons across runs use tolerances, and exactness is asserted only on CPU.

Tests

  • Three-neuron chains and excitation-inhibition motifs on synthetic graphs with analytically known spike times.
  • Event and batched propagators agree exactly on dyadic weights and to tolerance on random graphs.
  • Input neurons hold v and g at rest under a strong incoming edge, and such edges are absent from the built imago.
  • Delay buffer ordering.
  • Refractory handling and reset.
  • Mask application drops the right edges.

The benchmark is a tool, not a test.

Implementation notes

Module layout

The engine is implemented across the following modules, per the sub-project plan’s File Structure table:

ModuleContents
src/flatline/cli.pyCLI entry point: the three subcommands build-imago, imago-info, and bench
src/flatline/util/devices.pyDevice selection (cuda/ROCm, mps, cpu)
src/flatline/connectome/sources.pyReading the feather source files
src/flatline/connectome/imago.pyThe .imago safetensors file and JSON sidecar format
src/flatline/connectome/ingest.pyNeuron set construction and edge ingestion
src/flatline/connectome/photoreceptors.pyPhotoreceptor eye and column placement
src/flatline/connectome/sets.pyNamed neuron sets (photoreceptors, haltere afferents, wing motor, haltere motor, descending)
src/flatline/connectome/shuffle.pyWithin-synapse-count-class partner shuffle for the control condition
src/flatline/brain/params.pyLIF parameters and learnable knobs
src/flatline/brain/weights.pyEffective edge weights, lamina-scoped retina scaling
src/flatline/brain/mask.pyRegion mask loading and application
src/flatline/brain/propagate.pyEvent and batched propagators
src/flatline/brain/engine.pyThe stepped LIF engine
src/flatline/brain/record.pySpike recording to disk
src/flatline/brain/clock.pyReal-time clock and lag detection
src/flatline/brain/bench.pyThe benchmark tool

Mask presets live at configs/masks/full.toml and configs/masks/no-optic-lobe.toml.

Build metadata, v1.0 release

Running flatline imago-info against the male CNS v1.0 imago built by build-imago on this release reports:

FieldValue
n_neurons167,950 (166,700 real + 1,250 virtual photoreceptors)
n_edges25,530,591 (after dropping edges onto input neurons)
n_virtual1,250
n_edges_dropped_onto_inputs32,441
nt_flagged3,177
n_gain_groups1,296
photoreceptors (named set)6,091
haltere_afferents (named set)439
wing_motor (named set)67
haltere_motor (named set)16
descending (named set)1,314

The same build writes a retina report into the sidecar:

FieldValue
photoreceptors_without_outgoing_edge2,054 of 6,091
columns_over_six_r1639
lamina_cells_zero_drive_before3,673 of 5,327
lamina_cells_zero_drive_after720
virtual_photoreceptors_added1,250
lamina_norm min / median / max0.476 / 6.0 / 252.0

The 720 lamina cells still without drive all lack a hex column (901 lamina cells do), so no virtual photoreceptor can reach them. A lamina_norm of 252 is a cell whose whole reconstructed input is a single small synapse count; the factor is uncapped by design, and whether it should be is an open question for the encoder work.

Build time on the Mac M3 Max is about 12 s.

Neuron model fidelity

The neuron model follows the Shiu et al. released code, not just the published equations: both differential equations are frozen while refractory, incoming synaptic weight still accumulates into g during the refractory period, the threshold is strict, and reset zeroes g. Input neurons (photoreceptors, virtual photoreceptors, and haltere afferents) are held at rest with no incoming edges; they are driven entirely by their encoder’s spike probability, never by the network.

Propagator agreement

The event propagator and the batched propagator are required to agree exactly on weights that are exact in float32 (dyadic rationals), and to within a small tolerance on random graphs, since scatter-add order differs across devices and implementations.

External review, 2026-09-15

An external review dated 2026-09-15 examined the spec and the first implementation plan against the dataset, the Shiu et al. code, and the cflib source. Its findings and their dispositions follow. The section numbers in the disposition column refer to the design specification, docs/superpowers/specs/2026-09-15-flatline-imago-design.md, not to chapters of this book.

FindingDisposition
Signed LIF with histaminergic photoreceptors silences the laminaAccepted; section 8.6 policy and probe
LIF differs from Shiu et al. (g reset, refractory freeze, strict threshold)Accepted after checking the released code; section 7.1
Hover curriculum solvable by a zero decoderAccepted; section 12.3
No optic-flow diagnosticAccepted; section 8.6 probe
10 Hz camera far below motion-vision bandwidthAccepted as risk and measurement; section 8.5
Haltere round-robin discards type structureAccepted; grouping by type; section 8.4
flight-core mask removes 0.2% of neuronsAccepted; replaced by no-optic-lobe, masks are not a real-time strategy; section 7.6
Training compute unbudgetedAccepted; section 19
Safety envelope inadequate for an open workshopAccepted; section 10.5
Missing success criteria and open questionsAccepted; section 17
Connectome contract errors (unclear label, eight scales, 1,314 descending, side rule, hex target types)Accepted; sections 6.3, 6.5, 6.6
Decision log lacks alternatives and reasonsAccepted; section 4
Spec and plan file names divergeAccepted; section 13.1
Command-axis signs half-specifiedAccepted after checking cflib; section 10.4
Clock, threads, determinism underspecifiedAccepted; sections 7.8 and 10.1
Shuffle does not preserve in-degreeAccepted; the shuffle permutes partners within synapse-count classes, section 6.3
Retina normalization scaled every photoreceptor edgeAccepted; section 8.3
Photoreceptor column should be the strongest single targetRejected; strongest column by summed weight retained with the reason in section 4
Input neurons not bypassed and edges onto them keptAccepted; sections 6.3 and 7.2
Full edge table loaded whole for placementAccepted; plan filters by photoreceptor before materializing
Event propagator loops per brain on MetalAccepted; packed batch; section 7.3
Config and checkpoint schemas missingDeferred to the sub-project plans that create them

The full review is filed at docs/reviews/2026-09-15-grok-review.md in the repository.

Execution rulings, sub-project 1

Sub-project 1 (connectome ingestion, brain engine, and this book) was implemented on 2026-09-15 by a controller session dispatching one fresh implementer per plan task with a review after each, followed by a whole-branch review, two independent code reviews, and one consolidated fix wave. Decisions the controller took on the owner’s behalf are listed here in the order they were made, with what each costs if it turns out wrong. The ledger they were copied from lived in the gitignored SDD workspace and was deleted after the merge; this chapter is the record.

Process rulings

  1. Work proceeded on branch engine in the main checkout rather than a worktree: the repository was new with nothing on master to protect. Cost if wrong: a branch switch.
  2. .superpowers/ was added to .gitignore before the first task so the execution workspace could never be committed. Cost: a one-line merge.
  3. Docstring-only __init__.py stubs need no from __future__ import annotations; the style rule exists for annotated code. Cost: one import per stub.
  4. A commit-message-only amend was verified by the controller instead of a scoped re-review, since the file diff was empty. Cost: none.
  5. The commit trailer named in the plan binds every subagent regardless of the model that actually ran it. Cost: none.
  6. Two small changes to finished modules (the gain_group field and the pre_ids filter) were folded into a later task rather than reopening finished ones. Cost: none.
  7. At the owner’s request the book task ran in parallel with the engine tasks in a separate worktree on branch book, with the benchmark notebook entry deferred until the benchmark existed. Cost: a merge, which was clean.
  8. Two defects in the plan’s own test code (a zip(..., strict=True) over a shifted slice, and a mutable default argument) were fixed by ruling rather than by changing the engine. Cost: none.
  9. After the re-review of the fix wave, the controller edited two documentation lines and one configuration comment directly, gated by make all. Cost: none.

Design rulings

  1. A photoreceptor’s column is the hex column receiving the largest summed synapse count, not its single strongest target, because a lamina cartridge is what a photoreceptor innervates; the side comes from the winning column. On this dataset the two rules agree on nearly every cell. Cost if wrong: a re-placement pass.
  2. The external review’s findings were accepted and folded into the spec and plan, except the single-strongest-target rule above.
  3. Config and checkpoint schemas are deferred to the sub-project plans that create them.
  4. The book keeps a paraphrased lead-in and drops a cross-reference in the data chapter, because the referenced section is not in the book. A reviewer’s objections to the background chapter’s sourcing were overruled: the neuron and edge counts, the FlyWire brain being female, and the characterizations of the cited work are correct. Cost: a sentence edit.
  5. MathJax stays enabled and genuine equations are rendered as math, at the owner’s instruction.
  6. The retina correction was redesigned after the whole-branch review measured that the per-photoreceptor rule left the median lamina cell with one sixth of the intended drive and 27% of lamina cells with none. It is now per lamina cell (six cell-equivalents from whatever reaches the cell) with virtual photoreceptors wherever a lamina cell has no drive. Cost: a rebuild, already done; the first benchmark entry records both builds.
  7. The shuffled control was redesigned after the code review measured that the synapse-stub model quadrupled the edge count and flattened every weight. It now permutes destinations within synapse-count classes, preserving each neuron’s synapse totals, the edge count, and the weight distribution, and it never touches edges from input neurons, so the control shares the real sensory interface. Cost: the control’s definition changed before any training used it.
  8. The event propagator’s second host synchronization per step, the pandas typing convention, and the duplication between the spec and the book chapters are deferred follow-ups, recorded in the notebook and below.

Parked and deferred

  • The shuffle’s int16 merge clamp is latent: the largest merged count in the v1.0 control is 2,601 against a ceiling of 32,767, and no counter reports a clamp. Real, not load-bearing.
  • Per-task minor findings, all triaged “can wait” by the whole-branch review: broader ruff selection than the standard; pick_device("") auto-selects; shared tables and meta between derived imagos; the fixture’s repeated photoreceptor loops; mislabeled type-ignore codes and an unused import in one test; pandas cast density; path comments and a rebound local in ingestion; an untyped test helper; no CLI handling of missing paths (must be fixed before the flight supervisor ships); a shared helper for the two edge-orientation functions; no direct test of class-based mask inclusion or of the Metal batched propagator selection; per-step temporaries in the engine step and an untested noise branch; recorder docstrings; two type-ignores in the benchmark test.

Data

This section documents the data artifacts Flatline Imago builds and consumes: the .imago file that packages the connectome into a form the brain engine can load directly, its named neuron sets, and how the photoreceptor and other sensory placements were derived from the source dataset.

The imago

Format

A single safetensors file with the .imago extension plus a JSON sidecar, about 300 MB:

  • pre_indptr, pre_indices, pre_counts: edges grouped by presynaptic neuron (int64 pointers, int32 indices, int16 counts). Used by the event propagator.
  • post_indptr, post_indices, post_counts: the same edges grouped by postsynaptic neuron. Used by the batched propagator.
  • Per-neuron arrays: body_id (int64), nt (int8 index into the transmitter table), type_id (int32 index into the type table), superclass_id, side (int8: left, right, unknown).
  • Tables in the sidecar: transmitter names, type names, superclass names, build metadata (source file hashes, date, git describe).
  • Named neuron sets: photoreceptors with per-neuron eye and column, virtual_photoreceptors, haltere_afferents with side, wing_motor and haltere_motor with side and type, descending.

Transmitter signs

Each synapse’s sign comes from the presynaptic neuron’s consensus neurotransmitter, following Shiu et al.:

TransmitterSign
acetylcholine, dopamine, serotonin, octopamine+1
GABA, glutamate, histamine−1
unclear (the dataset’s own label, 2,999 neurons)+1, and the neuron is flagged
no row in the transmitter file (178 neurons)treated as unclear and flagged

Photoreceptor coverage

Coverage of the reconstructed retina map, produced by inferring each photoreceptor’s eye from rootSide and its column from the hex column receiving the largest summed synapse count over hex-bearing targets:

EyeColumnsWith any photoreceptorWith R1-R6With R7 or R8
Right892784526730
Left879682300638

The reconstructed retina is incomplete and imperfectly placed: a real column has six R1-R6 cells, but placed columns hold between one and eleven (v1.0 build, 826 columns with any R1-R6: 240 hold six, 547 hold fewer, 39 hold seven to eleven, the last being placement errors), and 2,054 of the 6,091 photoreceptors have no outgoing edge at all in the significant graph.

Side rule

Sensory neurons carry rootSide and a null somaSide; motor and central neurons carry somaSide and a null rootSide. The imago records somaSide when present, else rootSide. The haltere afferent set keeps each cell’s subclass (haltere 205, campaniform sensilla 195, mechanosensory bristle 39) and type (22 types) as fields, so downstream encoders can group by type rather than by cell.

Lab notebook

Dated entries, newest last. Every entry has the same shape: goal, setup, what happened, results, conclusions, next steps. Setup always records the git describe string, the machine, the device, the imago build metadata, and the exact command.

First benchmark of the whole-CNS imago

Goal

Measure steps per second at batch 1 (the flight gate) for the full imago and for the no-optic-lobe probe on the Mac, on cpu and mps, at a baseline input rate and a high-contrast input rate, to learn whether real time is within reach before any optimization. Masks are a compute probe here, not a strategy: the no-optic-lobe run removes vision and can never fly.

Setup

  • git describe: 996072e, then the two mps batch-1 rows re-measured on the fix-wave build (see the note under Results)
  • machine: Mac M3 Max, 128 GB
  • imago: data/imagos/male-cns-v1.0.imago, meta: n_neurons 167,950 (166,700 real + 1,250 virtual photoreceptors), n_edges 25,530,591, n_virtual 1,250, n_edges_dropped_onto_inputs 32,441, n_gain_groups 1,296, nt_flagged 3,177
  • the edge count is arithmetic: 25,560,079 significant edges with both ends in the neuron set, minus 32,441 edges onto input neurons, plus 2,953 edges from the 1,250 virtual photoreceptors, is 25,530,591
  • command: uv run flatline bench --imago data/imagos/male-cns-v1.0.imago --mask configs/masks/<mask>.toml --device <device> --seconds 2 --rate <rate> (batch 1); the batch run used --mask configs/masks/full.toml --device cpu --batch 16 --seconds 0.5 --rate 50.

What happened

All nine runs completed with no crashes, timeouts, or memory problems. Each 2 s run took well under a minute including imago load and a 50-step warm-up.

Results

maskdevicerate Hzneuronsedgessteps/sreal-time ratiomean spikes/step
fullcpu5016764225529886129.10.1291926.9
fullcpu20016764225529886116.70.1172070.6
fullmps5016795025530591526.90.5271966.8
fullmps20016795025530591510.70.5112095.6
no-optic-lobecpu506143512165384152.90.1531907.0
no-optic-lobecpu2006143512165384145.20.1451994.6
no-optic-lobemps506143512165384588.40.5881907.0
no-optic-lobemps2006143512165384590.30.5901994.6

Training-shaped run (batch 16, cpu, full, 0.5 s, rate 50): 9.8 steps/s, about 157 brain-steps per second, mean spikes/step 1731.0.

The two mps full-imago rows were re-measured after the fix wave that redesigned the retina correction (the imago now carries 1,250 virtual photoreceptors rather than 942, and 705 more edges). At 50 Hz throughput rose from 494.0 to 526.9 steps per second, 6.7%; at 200 Hz it moved from 507.7 to 510.7, under 1%. The other six rows are the original measurements on the pre-fix build, whose counts were 167,642 neurons and 25,529,886 edges.

Conclusions

The flight gate, a real-time ratio above 1.0 at batch 1, is not met on either device. Metal reaches about half real time on the full imago, and the CPU reaches about an eighth.

Throughput looks bound by per-step overhead rather than edge count. Dropping the optic lobes removes 63% of neurons and most edges, yet Metal throughput only rises from about 500 to about 590 steps per second. Candidates for the bottleneck are the per-step host synchronization in the event propagator, the number of small kernel launches per step in the engine (several where operations with fresh temporaries), and the Bernoulli draw that is currently made on the CPU each step.

Mean activity sits between about 1,900 and 2,100 spikes per step, around 1.2% of neurons per millisecond (3.1% of the 61,435 neurons in the no-optic-lobe runs), and barely changes between 50 Hz and 200 Hz input. This suggests the network’s activity is dominated by its own recurrent dynamics under this drive rather than by the input rate. This needs a look before any encoder work: spike rasters by superclass, and a check on whether activity is stable or growing over a longer run.

Two structural facts from the final review bear on this. Of the 167,950 neurons, 3,270 have no outgoing edge at all and 2,337 are fully isolated, so about 2% of the graph can never contribute. And the optic lobe is nearly silent under inhibitory photoreceptor drive: that is why removing it barely changes spikes per step, and it is exactly the phenomenon the visual transmission policy of the design spec, section 8.6, is meant to address.

The CPU batched path gives no per-brain speedup at batch 16, about 157 brain-steps per second total, roughly the same as batch 1. CPU training is not viable at this scale. The training gate depends on straylight’s ROCm path or a faster kernel.

Next steps

Profile one step on Metal to attribute time between propagation, the engine’s elementwise updates, and the input draw. The event propagator makes two device-to-host synchronizations per step, one to list the spiking neurons and one to size the gather, at roughly 0.2 ms each on mps; a fixed-capacity padded gather that removes both is the lever to pull first. Fuse the engine’s elementwise updates and keep the Bernoulli draw on the device. Measure a longer run (30 s) to check activity stability and record rasters by superclass. Then measure batch 64 on straylight.

References

  • Shiu, P. K. et al. A Drosophila computational brain model reveals sensorimotor processing. Nature 634, 210–219 (2024). https://www.nature.com/articles/s41586-024-07763-9
  • Nern, A. et al. Connectome-driven neural inventory of a complete visual system. Nature (2025). https://doi.org/10.1038/s41586-025-08746-0 Code: https://github.com/reiserlab/male-drosophila-visual-system-connectome-code
  • Zhao, A. et al. Eye structure shapes neuron function in Drosophila motion vision. Nature (2025). https://www.nature.com/articles/s41586-025-09276-5 Code and eye map: https://github.com/reiserlab/eyemap_T4
  • Lappalainen, J. K. et al. Connectome-constrained networks predict neural activity across the fly visual system. Nature 634, 1132–1140 (2024).
  • Janelia FlyEM male CNS connectome v1.0 (dataset used here).
  • Bitcraze AB. Crazyflie 2.1, AI deck 1.1, and Flow deck v2 documentation (2025). https://www.bitcraze.io/documentation/
  • Bitcraze AB. cflib (crazyflie-lib-python) 0.1.30 (2024), commander API: send_hover_setpoint, send_zdistance_setpoint, send_stop_setpoint. https://github.com/bitcraze/crazyflie-lib-python

BibTeX entries for these references are in book/references.bib.