API Reference

Core computations live in two modules: mnesis_chains (pattern generators, the HD_SNN network, analytical initialisation, training and inference) and mnesis_boilerplate (imports, device setup, the Params dataclass and utilities). Documentation is generated from the docstrings via sphinx.ext.autodoc/napoleon.

mnesis_chains — core network and pattern generators

Core module of the MNESIS library.

Defines the spiking-pattern generators (SpikingPattern, StochasticSpikingPattern) and the HD_SNN network class – a recurrent spiking neural network with heterogeneous synaptic delays – together with its analytical weight initialisation, training (HD_SNN.learn_model()) and inference (HD_SNN.forward_pass()) methods, and a load() helper for trained checkpoints.

class mnesis_chains.SpikingPattern

Bases: object

Generate a frozen spiking pattern based on a Bernoulli process.

The target is a single, reproducible spike raster of shape (N_pattern, N_neuron, N_time) drawn once from a Bernoulli distribution of rate p_A, seeded with opt.seed so that the same pattern is obtained across runs.

init(opt, verbose=False)

Draw the frozen target pattern.

Parameters:
  • opt – A Params instance providing N_pattern, N_neuron, N_time, p_A, seed and device.

  • verbose – If True, print the shape and mean firing rate of the generated target.

__call__(seed=None, verbose=False)

Return the frozen target pattern.

Parameters:
  • seed – Ignored; accepted so that every generator can be called with the same signature as StochasticSpikingPattern.

  • verbose – Ignored, for the same reason.

Returns:

The stored spike raster, of shape (N_pattern, N_neuron, N_time).

Return type:

torch.Tensor

class mnesis_chains.StochasticSpikingPattern

Bases: SpikingPattern

A stochastic spiking pattern generator.

Extends SpikingPattern with stochastic variability: each call returns a new realization of the base pattern in which bits are flipped independently with probability opt.p_flip (“balanced bit flipping”), so the marginal firing rate is preserved while the pattern structure is stochastically modified.

__call__(seed=None, verbose=False)

Generate a stochastic realization of the spiking pattern.

Each call returns a new realization of the base pattern where bits are independently flipped with probability self.opt.p_flip. The balanced-flip operation preserves the marginal frequency while introducing temporal and spatial variability in the structure.

Parameters:
  • seed – Seed for the bit-flip generator; None draws a fresh random seed.

  • verbose – If True, report the number of flipped bits.

Returns:

Stochastic realization of the spiking pattern, with the same dimensions as the base pattern.

Return type:

torch.Tensor

class mnesis_chains.HD_SNN(opt, pattern_object)

Bases: Module

Recurrent spiking neural network with Heterogeneous Delays (HD-SNN).

Each of the num_delay delays of every synapse carries an independent learnable weight, gathered in a single tensor W of shape (N_neuron, N_neuron * num_delay): the membrane of a neuron is driven by the last num_delay spikes of all its presynaptic peers. The network is a lin (the delay-expanded linear layer, no bias) followed by dropout and a leaky integrate-and-fire neuron (snntorch snn.Leaky) whose non-differentiable threshold crossing is trained through a surrogate gradient.

opt

The Params configuration.

pattern_object

The spiking-pattern generator providing the targets.

net

nn.Sequential of the ('lin', 'dropout', 'lif') modules.

Build the network and initialise the pattern generator.

Parameters:
  • opt – A Params instance.

  • pattern_object – A SpikingPattern-like object; its init(opt) method is called to produce the targets.

forward_pass(input_spikes, reset_spikes=None, feedback=True)

Unroll the network over time and record its activations.

Starting at t = num_delay, each neuron receives the last num_delay spikes of every neuron, taken from the recurrent output, the external input and (optionally) a reset mask, combined as (A + B - C).clamp(0, 1) and ravelled into the delay-expanded linear layer before the leaky integrate-and-fire step.

On MPS the loop synchronises every sync_every steps: without it, a long run (about 1e5 steps) piles up all its kernels in a single Metal command buffer, which the driver rejects as a whole (kIOGPUCommandBufferCallbackErrorOutOfMemory) while PyTorch silently returns all-zero tensors.

Parameters:
  • input_spikes – External spikes of shape (N_pattern, N_neuron, N_time).

  • reset_spikes – Spikes to clamp off from the recurrent drive, same shape as input_spikes; None means no reset.

  • feedback – If False, the output spikes are not fed back (open loop): each neuron only sees the external input, so that the replay cannot outlast the trigger by more than num_delay steps. A control showing that the replay is sustained by the recurrent positive feedback.

Returns:

(current, mem_rec, spikes) – the post-synaptic current, the membrane potential and the output spikes, each of shape (N_pattern, N_neuron, N_time).

Return type:

tuple

get_W_init()

Compute the closed-form (analytical) weight initialisation.

The target patterns are cast as a linear regression problem: every sliding window of num_delay past spikes (the “context”) should predict the next time step of activity. Two orthogonal flags select the estimator:

  • do_deconv: deconvolve the LIF membrane, i.e. regress onto the input current s*(t) - beta * s*(t-1) rather than onto the raw target spikes; a perfect context then drives the membrane to 1, a margin 1 - lif_threshold above the threshold.

  • do_pinv: solve exactly with the (CPU-computed) pseudo-inverse W = pinv(C) T; otherwise use the normalised Hebbian cross-correlation T^T C / <||c||^2>.

The regression is fitted on the frozen pattern, the noise-free reference that every evaluation scores against, so that the initialisation is deterministic for a given opt.seed.

Returns:

The initial weights for net.lin, of shape (N_neuron, N_neuron * num_delay).

Return type:

torch.Tensor

update_weight()

Set net.lin.weight to the analytical initialisation.

Copies get_W_init() into the linear layer in-place, under torch.no_grad().

get_input_spikes(target, p_A=None, N_pretime=None, N_trigger_time=None, N_time=None, seed=None)

Build the trigger input spikes for the network.

The input concatenates a N_pretime chunk of spontaneous Bernoulli activity at rate p_A, then the trigger window of num_delay steps, which shows the last N_trigger_time steps of its spiking-motif window (target steps num_delay - N_trigger_time to num_delay - 1); its first num_delay - N_trigger_time steps prolong the spontaneous activity. Any remaining time bins stay silent. The total length is N_time + 2*N_pretime.

A partial trigger is aligned on the end of the window because the readout is only trained on complete spiking-motif windows, which end where the replay starts: the partial window shown to the first evoked step is then a subset of a trained context, not a context shifted into the spontaneous activity.

Parameters:
  • target – The memorised pattern of shape (N_pattern, N_neuron, N_time).

  • p_A – Spontaneous firing rate; defaults to opt.p_A.

  • N_pretime – Length of the spontaneous prefix; defaults to opt.N_pretime.

  • N_trigger_time – Number of steps of the cue, taken at the end of the trigger window (time bins, 0 <= N_trigger_time <= num_delay); defaults to opt.num_delay (full trigger).

  • N_time – Length of the memory stretch; defaults to opt.N_time.

  • seed – Seed for the spontaneous activity; None draws from the global torch generator (seeded by Params). As in flip_bits(), the generator is seeded with a value derived from seed (on a stream of its own), so that a seed equal to the seed of the frozen motif does not replay its uniform draws as spontaneous activity.

Returns:

Detached input spikes of shape (N_pattern, N_neuron, N_time + 2*N_pretime).

Return type:

torch.Tensor

get_recall_time(input_spikes, feedback=True, bin_width=None)

Recall of each motif in successive bins of the evoked window.

Runs forward_pass() and scores the evoked window against the frozen motif with get_recall_time().

Parameters:
  • input_spikes – External spikes, as built by get_input_spikes().

  • feedback – False for the open-loop control (see forward_pass()).

  • bin_width – Width of a time bin (time bins); defaults to num_delay.

Returns:

recall of shape (N_pattern, N_bin).

Return type:

np.ndarray

learn_model(verbose=True)

Train the delay weights by surrogate-gradient BPTT.

At each epoch a fresh noisy realisation is drawn from pattern_object (data augmentation), the network is unrolled through forward_pass() on the cued input from get_input_spikes(), and the loss (SpikeF1scoreLoss by default, or MSELoss) between the output and that realisation is evaluated only after the spontaneous pre-time and the trigger window. The learning rate follows a cosine decay with linear warmup. An evaluation pass (dropout disabled), cued by another realisation and scored against the frozen pattern, logs loss, precision, recall and F1 every num_epochs // 64 epochs. All realisations are seeded from opt.seed, so a run is reproducible.

Parameters:

verbose – If True, print periodic training logs.

mnesis_chains.load(opt, model_filename, pattern_object=None)

Load a trained checkpoint into a fresh HD_SNN.

Rebuild the network (re-initialising the pattern generator), restore the saved net state dict and switch it to evaluation mode.

Parameters:
  • opt – A Params instance.

  • model_filename – Path to a .pth state dict saved from hd.net.

  • pattern_object – Generator providing the targets; defaults to a StochasticSpikingPattern.

Returns:

The trained network in eval() mode.

Return type:

HD_SNN

mnesis_boilerplate — hyperparameters and utilities

Shared boilerplate for the MNESIS experiments.

Provides the entry-point imports (torch, snntorch, numpy, matplotlib, …), automatic device detection (MPS -> CUDA -> CPU), the Params dataclass that is the single source of hyperparameter truth, and the utilities reused by mnesis_chains and all notebooks: random bit flipping (flip_bits()), figure saving (printfig()), spike-score metrics (get_scores(), get_f1score(), SpikeF1scoreLoss), the F1 scores expected from theory for a degraded trigger (get_f1_noisy_copy(), get_f1_ignition(), and the simulated cascade get_f1_cascade()), the recall of each motif against time (get_recall_time(), plot_recall_time()) and the cosine learning-rate schedule (get_cosine_schedule_with_warmup()).

class mnesis_boilerplate.Params(datetag='2026-09-07', N_neuron=1024, num_delay=41, N_pattern=16, N_time=1000, N_pretime=50, p_A=0.00016, p_flip=0.01, seed=2026, lif_beta=0.7, lif_threshold=0.75, learn_beta=False, learn_threshold=False, do_pinv=True, do_deconv=True, num_epochs=256, num_warmup_epochs=16, base_lr=0.04, final_lr=0.0004, delta1=0.003, delta2=1e-05, dropout=0.6, alpha_surrogate=5.0, surrogate_name='FastSigmoid', loss_name='SpikeF1scoreLoss', reset_mechanism='zero', optimizer='adadelta', verbose=False, fig_width=15.92, phi=1.61803, fig_height=9.839125356142963, N_time_show=1000, N_neuron_show=1024, i_pattern=1, N_scan=14, N_cv=11)

Bases: object

Single source of hyperparameter truth for the MNESIS experiments.

Instances also seed torch and numpy (in __post_init__) so that a given seed reproduces a run. Field groups:

Parameters:
N_neuron, num_delay, N_pattern,

N_time, N_pretime, p_A, p_flip, seed: network size and statistics.

lif_beta, lif_threshold, learn_beta, learn_threshold, do_pinv,

do_deconv: membrane dynamics and analytical-init flags.

num_epochs, num_warmup_epochs, base_lr, final_lr, delta1, delta2,

dropout, alpha_surrogate, surrogate_name, loss_name, reset_mechanism, optimizer: learning dynamics.

verbose, fig_width, fig_height, phi, N_time_show, N_neuron_show,

i_pattern, N_scan, N_cv: figure/scan settings.

datetag: str = '2026-09-07'
N_neuron: int = 1024
num_delay: int = 41
N_pattern: int = 16
N_time: int = 1000
N_pretime: int = 50
p_A: float = 0.00016
p_flip: float = 0.01
seed: int = 2026
device = device(type='cpu')
lif_beta: float = 0.7
lif_threshold: float = 0.75
learn_beta: bool = False
learn_threshold: bool = False
do_pinv: bool = True
do_deconv: bool = True
num_epochs: int = 256
num_warmup_epochs: int = 16
base_lr: float = 0.04
final_lr: float = 0.0004
delta1: float = 0.003
delta2: float = 1e-05
dropout: float = 0.6
alpha_surrogate: float = 5.0
surrogate_name: str = 'FastSigmoid'
loss_name: str = 'SpikeF1scoreLoss'
reset_mechanism: str = 'zero'
optimizer: str = 'adadelta'
verbose: bool = False
fig_width: float = 15.92
phi: float = 1.61803
fig_height: float = 9.839125356142963
N_time_show: int = 1000
N_neuron_show: int = 1024
i_pattern: int = 1
N_scan: int = 14
N_cv: int = 11
mnesis_boilerplate.pprint(s)

Print a headline surrounded by ‘=’ banners of the same length.

mnesis_boilerplate.printfig(fig, name='', fig_width=12, fig_height=None, exts=['pdf', 'png', 'svg'], figpath=PosixPath('../figures'), dpi_exp=None, bbox=None, layout='constrained', verbose=True, do_overwrite=True)

Save a matplotlib figure to figpath under several extensions.

Sizes the figure in centimetres, defaulting the height to fig_width / phi (golden ratio). On the Jean Zay cluster (figpath is None) saving is silently skipped. Existing files are overwritten only if do_overwrite is true.

Parameters:
  • fig_width – Width of the saved figure (cm); match it to the width the paper gives to \includegraphics so fonts print at their nominal size.

  • fig_height – Height of the saved figure (cm); defaults to fig_width / phi.

  • bbox – Passed to savefig(bbox_inches=...). The default None keeps the exact fig_width x fig_height canvas, whereas 'tight' crops it to the artists and so changes the printed scale.

  • layout – Layout engine set before saving ('constrained' fits labels inside the canvas); None keeps a manual subplots_adjust.

mnesis_boilerplate.flip_bits(a, p_flip, seed=None, verbose=False)

Balanced bit flipping preserving the marginal firing rate of a.

Each entry of the binary tensor a is replaced, with probability p_flip, by a fresh Bernoulli draw of rate a.mean(), so the expected spike rate is preserved while the pattern is perturbed.

Parameters:
  • a (torch.Tensor) – binary tensor to perturb.

  • p_flip (float) – probability of redrawing an entry (dimensionless).

  • seed (int) – seed of the flips; None draws a fresh random seed. The generator is seeded with a value derived from seed, not with seed itself, so that a flip seed equal to the seed of the frozen motif does not read the same uniform draws.

  • verbose (bool) – if True, report the number of flipped bits.

Returns:

A new tensor of the same shape as a.

Return type:

torch.Tensor

mnesis_boilerplate.stop()

Raise an AssertionError on purpose: temporary end of the script.

mnesis_boilerplate.approx_equals(series, value, rtol=1e-06, atol=1e-12)

Elementwise np.isclose for a pandas Series, falling back to ==.

Returns:

Boolean mask selecting the entries close to value.

mnesis_boilerplate.cache_lock(filename)

Hold the .lock sentinel of a cache file while this file is computed.

The lock is taken atomically (O_EXCL), so two processes started together cannot both compute the same file. It is released in a finally clause, so an exception or an interrupt during the computation does not leave a stale lock behind, which would make every later run skip the computation.

Parameters:

filename – Path of the cache file to compute; the lock is the same path with a .lock suffix.

Yields:

True if this process now holds the lock and should compute the file; False if the lock already exists (another process is computing the file, or one died before releasing it), in which case nothing is removed.

mnesis_boilerplate.purge_unfinished_scans(datetag=None, data_cache=PosixPath('../cached_data'), ignore_locks=False, remove_locks=False, dry_run=False)

Remove the placeholder rows left by interrupted scans, so they are recomputed.

A scan notebook reserves a row loss=inf, time=0.0 (stored as null in JSON) before computing it, and overwrites it when done. A row still in that state means the process died in between, yet the scan loop treats it as “already computed” and never retries it. Deleting the row lifts that block. A failed evaluation also stores loss=inf but with a non-zero time, so it is kept.

Parameters:
  • datetag – Cache-filename prefix of the batch to clean (ISO 8601 date); None cleans the scans of all batches.

  • data_cache – Directory holding the {datetag}_*.json scan files.

  • ignore_locks – If False, skip the scans that have a .lock file, as they may still be running.

  • remove_locks – If True, also delete every .lock file of the selected batches, which lifts the block on resuming the scans. Only use it when no scan is running (e.g. at the start of the orchestrator), as it implies ignore_locks.

  • dry_run – If True, only report what would be removed.

Returns:

Dictionary mapping each file name to the number of rows removed (or to be removed).

mnesis_boilerplate.get_scores(pred, target, epsilon=1e-12, dim=None)

Precision, recall and F1 between two (soft) spike tensors.

Sums the elementwise true/false positives and negatives; high precision means few false positives, high recall few false negatives. epsilon avoids division by zero. High precision means few false positives (FP), high recall few false negatives (FN).

Parameters:
  • pred (torch.Tensor) – predicted spikes.

  • target (torch.Tensor) – target spikes, of the same shape.

  • epsilon (float) – regularisation of the divisions.

  • dim (int or tuple) – dimensions to sum over; None sums over all of them, (1, 2) gives one score per motif for tensors of shape (N_pattern, N_neuron, N_time).

Returns:

(precision, recall, f1_score), scalar tensors or tensors over the dimensions left by dim.

Return type:

tuple

mnesis_boilerplate.get_f1score(pred, target, epsilon=1e-12, dim=None)

F1 score: the harmonic mean of precision and recall.

High only when both precision and recall are high; one minus this value is the training loss (SpikeF1scoreLoss). dim is passed to get_scores() ((1, 2): one score per motif).

mnesis_boilerplate.get_beta_errorbar(scores, quantiles=(0.05, 0.95), axis=1)

Mean and asymmetric error bars of repeated scores bounded in [0, 1].

An F1 score lives in [0, 1], so a symmetric mean +/- std bar can cross the bounds; instead a beta distribution is fitted to the repetitions by the method of moments (mean m, variance v): k = m (1 - m) / v - 1, a = m k, b = (1 - m) k, and the bars span its quantiles. Where no beta fit exists (v = 0, e.g. all repetitions at F1 = 0, or k <= 0 for data piled at 0 and 1), the empirical quantiles are used instead (equal to m when v = 0).

Parameters:
  • scores (np.ndarray) – repeated scores in [0, 1], repetitions along axis.

  • quantiles (tuple) – lower and upper quantiles of the error bars.

  • axis (int) – axis holding the repetitions.

Returns:

(mean, yerr), ready for ax.errorbar(x, mean, yerr=yerr); yerr has shape (2, ...): distances from the mean down to the lower quantile and up to the upper one.

Return type:

tuple

mnesis_boilerplate.get_f1_noisy_copy(p_flip, p_A)

F1 score of a balanced-flipped motif against the frozen one.

A balanced flip (flip_bits()) keeps a spike of the motif with probability q = 1 - p_flip (1 - p_A) and turns an empty bin into a spike with probability p_flip p_A, so the expected precision and recall are both equal to q. This is the score of a readout that would copy the corrupted motif as is, without any pattern completion: it falls linearly from 1 to chance level (F1 = p_A) at p_flip = 1.

Parameters:
  • p_flip (float or np.ndarray) – bit-flip probability (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time bin).

Returns:

expected F1 score, shaped like p_flip.

Return type:

np.ndarray

mnesis_boilerplate.get_f1_from_ignition(R, precision_0=1.0, recall_0=1.0)

F1 score of the replay when a fraction R of the motifs ignites.

An ignited motif is replayed with the precision and recall of the intact trigger, a silent one only adds false negatives. Per spike of the motifs, the true positives are R recall_0, the false negatives 1 - R recall_0 and the false positives R recall_0 (1 / precision_0 - 1), so that F1 = 2 R recall_0 / (1 + R recall_0 / precision_0).

Parameters:
  • R (float or np.ndarray) – ignition probability of a motif (dimensionless).

  • precision_0 (float) – precision of the replay with the intact trigger.

  • recall_0 (float) – recall of the replay with the intact trigger.

Returns:

expected F1 score, shaped like R.

Return type:

np.ndarray

mnesis_boilerplate.get_trigger_presence(p_flip, p_A, num_delay, fraction=1.0, N_trigger_time=None)

Probability that a spike of the spiking-motif window is present in a degraded trigger.

A spike of the motif lying in bin i of the window (0 <= i < num_delay) is present if it falls in the part that the trigger shows, the last N_trigger_time bins (a truncated trigger) on the fraction of neurons left active (a lesioned one), and survives the balanced flips, which keep it with probability 1 - p_flip (1 - p_A).

Parameters:
  • p_flip (float or np.ndarray) – bit-flip probability of the trigger (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time bin).

  • num_delay (int) – width of the spiking-motif window (time bins).

  • fraction (float or np.ndarray) – fraction of the neurons shown by the trigger (dimensionless, 1 for an intact trigger).

  • N_trigger_time (float or np.ndarray) – number of bins shown at the end of the window (time bins); None shows the whole window.

Returns:

presence probability, shaped like the broadcast of the arguments with a last axis of num_delay bins.

Return type:

np.ndarray

mnesis_boilerplate.get_f1_ignition(p_flip, p_A, N_neuron, num_delay, lif_threshold, precision_0=1.0, recall_0=1.0, fraction=1.0, N_trigger_time=None)

F1 score expected when a degraded trigger ignites, or not, the replay of each motif.

Mean-field model of the pseudo-inverse readout (mnesis_chains.HD_SNN.get_W_init()): each spike of a motif is supported by the K spikes of that motif in the num_delay bins before it. The minimum-norm solution gives these supporting spikes equal weights, so the membrane reaches 1 when all of them are present and k / K when only k of them are: the spike is emitted if k >= ceil(lif_threshold K). A spurious spike of the trigger falls on a near-zero weight, as the motifs are sparse.

The replay is a cascade, a positive feedback loop: each emitted spike joins the support of the next ones, so that once the first evoked spike of a motif is emitted, the following ones see more and more of their support and the replay ignites as a whole (the noise-free motif being a stable fixed point); if it fails, the support of the next spikes keeps shrinking and the replay dies out (get_f1_cascade() simulates the whole cascade and checks that its first step decides it). The ignition probability is thus that of the first evoked spike. The motif fires mu = p_A N_neuron spikes per bin, so this spike comes j bins after the trigger with probability P(j) = exp(-mu j) (1 - exp(-mu)); its support then lies in the last num_delay - j bins of the trigger window, so that K is Poisson of mean lam_j = mu (num_delay - j) and a supporting spike is present with the mean q_j of get_trigger_presence() over these bins. Hence

R = sum_j P(j) sum_{K >= 1} Poisson(K; lam_j) P(Binomial(K, q_j) >= ceil(lif_threshold K)),

normalised by its value for an intact trigger, whose failures (motifs with a gap longer than the window) are already counted in recall_0. For scattered losses (flips, lesioned neurons), q_j = q does not depend on j; for a truncated trigger, the support of the first evoked spike is more recent than a whole window, and so better shown than the fraction N_trigger_time / num_delay of the window. The F1 score follows from R by get_f1_from_ignition().

Parameters:
  • p_flip (float or np.ndarray) – bit-flip probability of the trigger (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time bin).

  • N_neuron (int) – number of neurons.

  • num_delay (int) – width of the spiking-motif window (time bins).

  • lif_threshold (float) – firing threshold, relative to the membrane potential reached on the motif (dimensionless).

  • precision_0 (float) – precision of the replay with the intact trigger.

  • recall_0 (float) – recall of the replay with the intact trigger.

  • fraction (float or np.ndarray) – fraction of the neurons shown by the trigger (dimensionless, 1 for an intact trigger).

  • N_trigger_time (float or np.ndarray) – number of bins shown at the end of the window (time bins); None shows the whole window.

Returns:

expected F1 score, shaped like the broadcast of p_flip, fraction and N_trigger_time.

Return type:

np.ndarray

mnesis_boilerplate.get_replay_hazard(p_drop, p_A, N_neuron, num_delay, lif_threshold)

Failure rate of a sustained replay under spike transmission failures.

During a sustained replay, the context of each spike of a motif is made of the network’s own output only. If every emitted spike fails to reach the recurrent input with probability p_drop, independently, each spike of the motif is a new ignition test: the first evoked spike of get_f1_ignition(), with a context spanning the whole window (K Poisson of mean p_A N_neuron num_delay) and a presence probability q = 1 - p_drop. A step holds a spike of the motif with probability 1 - exp(-p_A N_neuron), and the first failed spike is taken to end the replay (the positive feedback loop then shrinks the next contexts), so that the replay survives t steps with probability exp(-h t). The contexts with K = 0 (a gap of num_delay silent steps) are left out, as their failures are already counted in the recall of the intact replay.

Parameters:
  • p_drop (float or np.ndarray) – probability that an emitted spike is not transmitted to the recurrent input (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time step).

  • N_neuron (int) – number of neurons.

  • num_delay (int) – width of the spiking-motif window (time steps).

  • lif_threshold (float) – firing threshold, relative to the membrane potential reached on the motif (dimensionless).

Returns:

failure rate h (per time step), shaped like p_drop.

Return type:

np.ndarray

mnesis_boilerplate.simulate_cascade(counts, present_trigger, num_delay, lif_threshold)

Replay of motifs by the mean-field threshold readout, bin after bin (the cascade).

In the mean-field picture of the pseudo-inverse readout (see get_f1_ignition()), all the spikes of a motif in bin t share the same support, the K spikes of the motif in the num_delay bins before t, with equal weights: they are emitted together if at least ceil(lif_threshold K) of these K spikes are present, and never if K = 0 (a gap of num_delay silent bins, which the replay cannot cross). The emitted spikes join the support of the next ones (the positive feedback loop); spurious spikes, which fall on near-zero weights, are left out, so that only the number of spikes per bin matters.

Parameters:
  • counts (np.ndarray) – spikes of each motif per bin, (N_motif, N_time).

  • present_trigger (np.ndarray) – spikes of each motif present in the trigger, per bin of the window, (N_motif, num_delay).

  • num_delay (int) – width of the spiking-motif window (time bins).

  • lif_threshold (float) – firing threshold, relative to the membrane potential reached on the motif (dimensionless).

Returns:

emitted spikes per bin, (N_motif, N_time); the first num_delay bins hold the trigger.

Return type:

np.ndarray

mnesis_boilerplate.get_cascade_motifs(N_motif, N_neuron, N_time, p_A, num_delay, seed=2026)

Random motifs for the cascade model, with the identity of the trigger spikes.

Draws Binomial(N_neuron, p_A) spikes per bin, as the frozen motifs of the network (mnesis_chains.StochasticSpikingPattern), and, for each spike of the trigger window, the neuron that fires it and a uniform number that decides whether a bit flip removes it: the identity of the neurons matters for a lesioned trigger, which always silences the same neurons.

Parameters:
  • N_motif (int) – number of motifs.

  • N_neuron (int) – number of neurons.

  • N_time (int) – duration of a motif (time bins).

  • p_A (float) – firing probability of the motif (spike per time bin).

  • num_delay (int) – width of the spiking-motif window (time bins).

  • seed (int) – seed of the random generator.

Returns:

counts (N_motif, N_time), and per trigger spike slot (N_motif, num_delay, n_max): in_bin (the slot holds a spike), neuron and u; input of get_cascade_presence().

Return type:

dict

mnesis_boilerplate.get_cascade_presence(motifs, p_flip, p_A, n_lesion=0, N_trigger_time=None)

Spikes of each motif present in a degraded trigger, per bin of the window.

A spike of the trigger window is present if it falls in the last N_trigger_time bins (a truncated trigger), is not fired by one of the first n_lesion neurons (a lesioned trigger, as in notebook 16) and survives the balanced flips, which keep it with probability 1 - p_flip (1 - p_A) (get_trigger_presence() gives the same probabilities, averaged over the neurons).

Parameters:
  • motifs (dict) – motifs drawn by get_cascade_motifs().

  • p_flip (float) – bit-flip probability of the trigger (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time bin).

  • n_lesion (int) – number of silenced neurons.

  • N_trigger_time (int) – number of bins shown at the end of the window (time bins); None shows the whole window.

Returns:

present spikes per bin, (N_motif, num_delay).

Return type:

np.ndarray

mnesis_boilerplate.get_f1_cascade(p_flip, p_A, N_neuron, num_delay, lif_threshold, precision_0=1.0, recall_0=1.0, fraction=1.0, N_trigger_time=None, N_time=1000, N_motif=1000, seed=2026)

F1 score expected from the simulated cascade of the replay, on random motifs (Monte Carlo).

Simulates the threshold network that get_f1_ignition() reduces to its first step (simulate_cascade()) on N_motif random motifs of the whole duration N_time (get_cascade_motifs()), so that it also checks that the first evoked spike decides the replay. The pooled recall of the motifs, normalised by its value for an intact trigger on the same motifs (which removes the failures at a gap of num_delay silent bins, already counted in recall_0), is the ignition probability R, and the F1 score follows from get_f1_from_ignition(). All the degradation levels share the same motifs and draws (common random numbers), so that the curve is smooth.

Parameters:
  • p_flip (float or np.ndarray) – bit-flip probability of the trigger (dimensionless).

  • p_A (float) – firing probability of the motif (spike per time bin).

  • N_neuron (int) – number of neurons.

  • num_delay (int) – width of the spiking-motif window (time bins).

  • lif_threshold (float) – firing threshold, relative to the membrane potential reached on the motif (dimensionless).

  • precision_0 (float) – precision of the replay with the intact trigger.

  • recall_0 (float) – recall of the replay with the intact trigger.

  • fraction (float or np.ndarray) – fraction of the neurons shown by the trigger (dimensionless, 1 for an intact trigger); the (1 - fraction) N_neuron first neurons are silenced.

  • N_trigger_time (float or np.ndarray) – number of bins shown at the end of the window (time bins); None shows the whole window.

  • N_time (int) – duration of a motif (time bins).

  • N_motif (int) – number of simulated motifs.

  • seed (int) – seed of the random generator.

Returns:

expected F1 score, shaped like the broadcast of p_flip, fraction and N_trigger_time.

Return type:

np.ndarray

mnesis_boilerplate.get_cascade_prediction(frozen_target, num_delay, lif_threshold, cue=None, n_lesion=0, N_trigger_time=None)

Replay of each frozen motif of the network predicted by the cascade model.

Applies simulate_cascade() to the actual motifs, with no fitted parameter: a spike of the trigger window is present if it is shown (the last N_trigger_time bins, not one of the first n_lesion neurons) and, when a noisy realisation cue provides the trigger, if this realisation kept it. The model predicts the recall of each motif, not its precision, as it leaves out the crosstalk between motifs.

Parameters:
  • frozen_target (torch.Tensor or np.ndarray) – frozen motifs, (N_pattern, N_neuron, N_time).

  • num_delay (int) – width of the spiking-motif window (time bins).

  • lif_threshold (float) – firing threshold, relative to the membrane potential reached on the motif (dimensionless).

  • cue (torch.Tensor or np.ndarray) – noisy realisation providing the trigger, of the same shape; None for the frozen motif itself.

  • n_lesion (int) – number of silenced neurons (the first ones).

  • N_trigger_time (int) – number of bins shown at the end of the window (time bins); None shows the whole window.

Returns:

per motif, recall (predicted recall of the evoked window), t_stop (first spike of the motif that is not replayed, in time bins from the onset of the motif, nan if the replay reaches the end) and t_gap (onset of the first gap of num_delay silent bins in the evoked window, nan if there is none).

Return type:

dict

mnesis_boilerplate.get_recall_time(spikes, target, bin_width)

Recall of each motif in successive time bins of the evoked window.

Shows the dynamics of the replay: once ignited, the recall of a motif stays near that of the intact trigger; otherwise it falls to zero.

Parameters:
  • spikes (torch.Tensor) – evoked spikes, of shape (N_pattern, N_neuron, N_time).

  • target (torch.Tensor) – target spikes, of the same shape.

  • bin_width (int) – width of a time bin (time bins); the last incomplete bin is left out.

Returns:

recall of shape (N_pattern, N_time // bin_width), nan in a bin without any target spike.

Return type:

np.ndarray

mnesis_boilerplate.plot_recall_time(ax, recall_time, labels, recall_open=None, bin_width=1, cmap='viridis')

Plot the recall of each motif against time, one colour per degradation level.

Thin lines are single motifs (bistable: they stay near the recall of the intact trigger or fall to zero), thick lines their mean; the dashed black line is the mean recall of the open-loop control, and the grey dashed lines mark the extremal values 0 and 1.

Parameters:
  • ax (matplotlib.axes.Axes) – axes to draw in.

  • recall_time (list of np.ndarray) – one (N_pattern, N_bin) array per level, as returned by get_recall_time().

  • labels (list of str) – legend label of each level.

  • recall_open (np.ndarray) – recall of the open-loop control, or None.

  • bin_width (float) – width of a time bin (ms).

  • cmap (str) – colormap of the levels.

class mnesis_boilerplate.SpikeF1scoreLoss(epsilon=1e-12)

Bases: Module

Training loss L = 1 - F1 between predicted and target spikes.

Initialize internal Module state, shared by both nn.Module and ScriptModule.

forward(pred, target)

Return 1 - F1score(pred, target), differentiable via the surrogate.

mnesis_boilerplate.get_cosine_schedule_with_warmup(optimizer, num_warmup_epochs, num_epochs, rel_final_lr)

Cosine learning-rate decay with warmup, as a torch LambdaLR.

The learning-rate multiplier is constant (1) during num_warmup_epochs, then follows a half-cosine from 1 down to rel_final_lr (final_lr / base_lr) at num_epochs.