Skip to content

Repository files navigation

Dynamic Engrams Model

ISTA Internship at Prof. Tim Vogels group

Project title: Cross-Implementation and Verification in Brian2 of the Dynamic Engrams Consolidation Model

Internship dates: June - September 2025

This project is a verification of a memory consolidation simulation with a Spiking Neural Networks (SNN) model implemented in Brian2 (Python), originally defined in Auryn (C++) in:

Sources

Everything here is a re-implementation, so it is worth being explicit about where the inputs come from:

What Source
Model definition The paper cited above
All parameter values The supplementary information table of that paper (PDF)
Stimulus patterns (stimuli/*.pat) Downloaded from the original Auryn implementation, under src/data/: douglastome/dynamic-engrams v1.0.0

The .pat files are used as downloaded rather than regenerated, so the stimulus this model sees is the same one the original simulation used. Every constant in config/parameters.py is taken from the supplementary table, which is the reference to check against when a value looks surprising.

What the model is

A recurrent spiking network of 4096 excitatory and 1024 inhibitory adaptive leaky integrate-and-fire neurons, driven by a 4096-unit Poisson stimulus population. Recurrent connectivity is random with probability epsilon_rec.

Three plasticity mechanisms run concurrently:

Mechanism Where Purpose
Long-term excitatory plasticity (triplet STDP, heterosynaptic term, consolidation variable w_tilde) Stim→E, E→E forms and consolidates the engram
Inhibitory STDP gated by a global signal G I→E holds the network at the target rate r_target
Short-term plasticity (u, x) Stim→E, E→E scales release by R = u * x (off by default, see scripts/README.md)

A single-neuron controller group integrates the excitatory population rate into H and exposes G = H - r_target * tau_H, which is linked into every I→E synapse. This is the homeostatic feedback loop.

An engram is the set of excitatory neurons whose stimulus-evoked firing rate during stimulus-ON bins exceeds thres_sefr.

Simulation phases

scripts/simulate_and_probe.py runs the full pipeline:

# Phase Simulated duration Stimulus What happens
1 Burn-in T_burn background only (v_bg) network settles to the homeostatic setpoint before anything is learned
2 Training T_training ON/OFF windows the engram forms, then it is computed from the last 60 s of activity
3 Consolidation T_consolidation ON/OFF windows the engram reorganises, and a checkpoint is stored every probe_interval
4 Probing 60 s per checkpoint replayed training gate re-measures the engram at each checkpoint, so its drift over time can be tracked
5 Recall 90 s partial cue (squarev5_cues_1-4.pat) tests whether a partial cue reactivates the stored engram

Protocol timeline: training, 24 h consolidation, and checkpoint detail

Compromises made for computational cost

The model is expensive, so two phases had to be cut down from the original design and one mechanism is left switched off:

  • Consolidation was reduced from 24 h to 10 h of simulated time. The original design consolidates for 24 h (86400*second), while the active setting is T_consolidation = 36000*second.
  • Recall could not be run over the whole time course. The intended sweep runs recall from every consolidation checkpoint. That block is left commented out in scripts/simulate_and_probe.py, and only the final checkpoint is actually run.
  • Short-term plasticity is implemented but switched off by default. Turning it on adds two event-driven variables (u and x), which makes the simulation considerably more expensive to run.

All three are single-line changes if more compute becomes available. See config/README.md and scripts/README.md, the latter for how to switch short-term plasticity on and what it does to the network.

Repository map

Folder What lives there
config/ parameters, the profile toggle, save and load helpers
model/ neuron and synapse group construction
network/ assembles neurons, synapses, stimulus and controller into one Network
simulation/ run directories, logging, phase execution, sanity checks
scripts/ entry points you actually execute
analysis/ engram definition, probing and recall, loaders and plotting
stimuli/ input patterns from the original implementation: squarev5.pat, squarev5_cues_1-4.pat
data/ generated stimulus-to-excitatory connectivity (pre_ids.npy, post_ids.npy), git-ignored
src/ simulation outputs, one directory per run, git-ignored

Notebooks at the root:

  • 1_activity_plots.ipynb loads a burn-in run (rasters, rates, weight distributions, homeostatic H)
  • 2_probing_n_recall_plots.ipynb loads a full pipeline run (engram overlap across consolidation, and recall)

Setup

  1. Create and activate a virtual environment
python -m venv .venv
.venv\Scripts\Activate.ps1      # PowerShell; source .venv/bin/activate on Linux/macOS
  1. Install dependencies
pip install -r requirements.txt
  1. Generate the stimulus-to-excitatory connectivity map
python -m scripts.generate_stim_input_map

Important

This draws a random receptive-field centre for every excitatory neuron and writes the resulting connectivity to data/pre_ids.npy and data/post_ids.npy. model/synapses.py loads those files at import time, so nothing runs until they exist. Because the draw is unseeded, re-running the script produces a different network, which is precisely why the map is generated once and then reused by every run. See scripts/README.md.

  1. Run the pipeline
python -m scripts.simulate_and_probe

Note

To run only the burn-in phase, with monitors recording both excitatory and inhibitory populations:

python -m scripts.monitor_stable_activity

This script takes an optional profile, an optional duration in seconds, and an optional stp flag. Short-term plasticity is off by default. See scripts/README.md.

Parameter profiles

Parameters come from one place at runtime: config.active. Which set it resolves to is chosen by a single toggle, with no source edits anywhere:

python -m scripts.monitor_stable_activity              # config.parameters
python -m scripts.monitor_stable_activity calibration  # config.parameters_calibration

Every module (model, network, scripts, analysis) imports from config.active, never from config.parameters directly. The calibration profile lists only what it overrides, and the run log prints those overrides at the top. See config/README.md.

Outputs

Each run creates src/run_<timestamp>_seed<N>/:

run_<id>/
    run_<id>.log        # full stdout and stderr, starting with the parameter banner
    monitor_data/       # spike monitors and controller H, as .npz
    weights/            # per-synapse w / w_tilde snapshots, as .npz
    engrams/            # engram indices per probe checkpoint
        recall/         # recall engrams
    ckpt/               # created but unused: net.store() checkpoints live in memory

Set SEED_N to control the seed (and the directory name). RUN_ID overrides the name entirely. scripts/run_many.sh sweeps a list of seeds.

Analysis

1_activity_plots.ipynb loads a burn-in run, 2_probing_n_recall_plots.ipynb loads a full pipeline run. Both read from src/run_<id>/ through the loaders in analysis/.

Notes

  • Run every script from the project root, so that python -m ... and the relative paths (data/, stimuli/) resolve correctly.
  • Brian2 uses compiled (Cython) code when a C++ toolchain is available and falls back to a slower numpy target otherwise. The fallback is reported in the log.

About

ISTA Scientific Internship 2025. Cross-Implementation and Verification of the Dynamic Engrams Model in Brian2

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages