Spiking neural network model of the larval Drosophila olfactory pathway, constrained by the complete Winding et al. (2023) connectome. All connectivity (368 neurons, ~50,000 chemical synaptic contacts, ~12,000 synaptic edges) is fixed to the connectome; only 449 scalar biophysical parameters are learned.
Paper: "Connectome-Constrained Spiking Neural Networks Reproduce Emergent Computations in the Larval Drosophila Olfactory Pathway" (Cognitive Computation Neuroscience 2026).
git clone https://github.com/InsectRobotics/connectome_emergence.git
cd connectome_emergence
python3 -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install .Create the environment with Python ≥3.10 (check with
python3 --version). Installing into a fresh virtual environment matters: a system Python below 3.10 (e.g. macOS's/usr/bin/python3, which is 3.9) is rejected bypip install .(requires-python >=3.10), and installing into a system/Homebrew Python can fail withexternally-managed-environment(PEP 668). The venv avoids both.
This installs the model code as the importable core, analysis, and scripts packages
(source root code/). Dependencies (requirements.txt / pyproject.toml): Python ≥3.10,
PyTorch ≥2.0, NumPy, SciPy, Pandas, scikit-learn (odor-mixture SVM metric), Matplotlib,
JupyterLab, and psutil (auto-detects parallel-training worker count, falls back to
os.cpu_count()).
Running the training / figure scripts in place? Use an editable install —
pip install -e .— so they resolvedata/andresults/relative to the cloned repo.
Conda alternative: conda env create -f environment.yml && conda activate connectome-emergence.
The env uses only the conda-forge and pytorch channels, so no Anaconda Terms-of-Service prompt is
required. (If an older environment.yml or your conda config pulls in the defaults channel and the
create stops with a Terms-of-Service error, run conda tos accept once, then retry.)
OR (rate, 21 types) -> ORN (LIF, 42) -> LN (LIF, 108) -> PN (LIF, 72) -> KC (2-comp, 144) <- APL (graded, 2) -> Decoder (28 odors)
^___v gap junctions ^___v KC-KC recurrent
- ORN, LN, PN: Leaky integrate-and-fire with surrogate gradients
- KC: Two-compartment (dendrite + axon) with learnable soma conductance
- APL: Graded (non-spiking) global inhibition
- Gap junctions: LN-LN (354 pairs), PN-PN sister (929), eLN-PN (103)
- Non-AD contacts: 6 pathways, weakly initialized, low learning rate
- STD: Tsodyks-Markram short-term depression on all chemical synapses
- Noise: 6 biologically motivated sources (OR 30% CV, membrane 1 mV, background 15 pA, synaptic 25%, threshold 1 mV, receptor 10%)
Everything lives inside code/. Data, results, figures, and the paper sit at the repo root.
connectome_emergence/
|-- code/ # source root — installs as the `core`, `analysis`, `scripts` packages
| |-- core/ # model files (spiking + rate-based teacher)
| | |-- model.py # SpikingConnectomeConstrainedModel — full OR->ORN->AL->KC<-APL->decoder pipeline
| | |-- layers.py # spiking neuron/synapse layers (LIF, TwoCompartmentKC, APL, gap junctions, STD, non-AD)
| | |-- dataset.py # Kreher-2008 OR-response loading + noisy DataLoaders
| | |-- rate_model.py # ConnectomeConstrainedModel — rate-based ANN teacher for ANN->SNN transfer
| | +-- rate_layers.py # rate-based layers (ConnectomeLinear, AntennalLobe, KenyonCellLayer)
| |-- analysis/ # metric / recompute / plot helpers (no training)
| | |-- recompute.py # deterministic engine: checkpoint -> metrics (eval seed 42)
| | |-- compute.py # decorrelation, Mancini APL test, concentration invariance
| | |-- utils.py # shared primitives (cosine similarity, noisy forward pass, v_th bounds)
| | +-- plotting.py # figure functions (each returns a fig, accepts show=)
| |-- scripts/ # experiment drivers (each self-bootstraps sys.path)
| | |-- run_training.py # canonical 5-seed training + R1 energy/sparsity variants
| | |-- run_ablation.py # R3 retrained ablations + posthoc + std subcommands
| | |-- run_odor_mixtures.py # R5: odor-mixture KC coding + Honegger sub-additivity
| | |-- run_teacher_consistency.py # R2: teacher/student parameter consistency
| | |-- run_task_complexity.py # R6: task complexity / KC-threshold scaling
| | |-- recompute_one.py # per-checkpoint recompute -> results/recompute_cache/ JSON (R1/R3/R4/STD cells fan it out, cached)
| | +-- regen.sh # regenerate all results: bash code/scripts/regen.sh fast|heavy
| +-- paper_figures.ipynb # MAIN entry point: loads checkpoints, recomputes metrics, makes figures
|
|-- data/ # bundled inputs
| |-- kreher2008/ # ORN response matrices (Kreher et al. 2008)
| |-- winding2023/ # collapsed connectivity matrices (Winding et al. 2023)
| +-- winding2023_compartments/ # compartment-resolved contacts (aa, ad, da, dd)
|-- results/ # per-experiment outputs + trained checkpoints (.pt)
| |-- all_connections_nonad_canonical/ # canonical 5-seed models + results.json
| |-- energy_only_r1/ ablations_r1/ posthoc_ablations/ std_ablation/
| |-- odor_mixtures_r5/ teacher_consistency_r2/ task_complexity_r6/
| +-- _shuffled_connectomes/ recompute_cache/ f4_extra/
|-- figures/ # notebook outputs: PNGs + vector PDFs + paper_values.json
+-- environment.yml pyproject.toml requirements.txt .gitignore LICENSE README.md
Install dependencies first — see Installation.
jupyter lab code/paper_figures.ipynbRun all cells. The notebook loads pre-trained checkpoints and pre-computed results from
results/, recomputes every metric at runtime via analysis/recompute.py (deterministic,
eval seed 42), generates all figures into figures/, and prints every value cited in the
paper — also persisted to figures/paper_values.json.
Parallel training: the notebook's "Option A" cells auto-detect the machine (CPU cores + free RAM) and dispatch seeds in parallel (~30–60 min on a modern multi-core machine).
Run scripts directly from the repo root — they self-bootstrap sys.path:
python code/scripts/run_training.py # canonical models (5 seeds, ~2 h)
python code/scripts/run_training.py --label ce_only # R1 energy/sparsity variants (~8 h)
python code/scripts/run_ablation.py --no-gap --kc-sparsity # R3 retrained ablations (~4 h)
python code/scripts/run_ablation.py posthoc # R3 post-hoc ablations (~30 min)
python code/scripts/run_ablation.py std --condition both # STD ablation (~2 h)
python code/scripts/run_odor_mixtures.py # R5 mixture coding (~25 min)
python code/scripts/run_odor_mixtures.py --honegger # R5 Honegger sub-additivity (~10 min)
python code/scripts/run_teacher_consistency.py # R2 parameter consistency (~5 min)
python code/scripts/run_task_complexity.py --n-odors 14 --seed 42 # R6 task complexityOr in one go: bash code/scripts/regen.sh fast (eval-only, ~50 min) /
bash code/scripts/regen.sh heavy (all retraining, ~18–20 h).
| Output | Location | Written by |
|---|---|---|
| Figures (PNG) | figures/ |
notebook figure cells |
| All paper values (JSON) | figures/paper_values.json |
notebook final cell |
| Per-experiment results (JSON) | results/<subdir>/*.json |
code/scripts/run_*.py |
Trained checkpoints (.pt) |
results/<subdir>/*.pt |
training drivers |
| Figure | File | Description |
|---|---|---|
| Figure 2 | figures/2_core.png |
Pairwise cosine-similarity matrices (OR→PN→KC decorrelation) |
| Figure 3 | figures/3_concentration.png |
Concentration invariance (gain control, accuracy, similarity) |
| Figure 4 | figures/4_abl.png |
Architecture / ablation bars |
| Figure S2 | figures/S2_confusion_matrix.png |
Classification confusion matrix |
| Figure S3 | figures/S3_within_odor_consistency.png |
Within-odor KC consistency |
| Figure S4 | figures/S4_threshold_scaling.png |
KC threshold saturation vs task difficulty |
| KC heatmap | figures/S1_kc_heat.png |
KC activity heatmap across odors |
| Metric | Value | Biological comparison |
|---|---|---|
| Test accuracy | 70.3% ± 1.1% | ~20× chance (3.6%) |
| Centroid accuracy | 65.9% ± 0.5% | decoder-free odor discrimination |
| KC sparsity | 12.5% ± 0.2% | sparse expansion coding |
| AL decorrelation | 4.4% | modest, as expected |
| MB decorrelation | 35.8% | expansion coding (Bhandawat et al., 2007) |
| APL suppression | 1.85 ± 0.05 (~46%) | ~50% (Mancini et al., 2023) |
| PN dynamic range | 1.23 ± 0.02× | sublinear gain (Olsen et al., 2010) |
| KC pattern similarity | 0.942 | cross-model convergence |
| Parameter correlation | 0.909 | connectome constrains the solution |
- MB-localized decorrelation: 35.8% in MB vs 4.4% in AL
- APL suppression: KC activity reduced by ~46%, matching optogenetic data
- Concentration invariance: gain control compresses the OR→PN→KC dynamic range
- Sub-additive mixture coding: 69.4% of KCs sub-additive (Honegger 2011: 73%)
Connectome from Winding et al. (2023); ORN responses from Kreher et al. (2008); bundled in data/:
kreher2008/— ORN response matrices (normalized + raw)winding2023/— collapsed connectivity matrices (.pt)winding2023_compartments/— compartment-resolved contacts (aa, ad, da, dd)
This code was written by Jordan Watts, in Barbara Webb's Insect Robotics Group at the University of Edinburgh, School of Informatics.