Dynamics¶
Different dynamical rules can be imposed on the network. Each dynamic is
organized into a separate module, implemented as a class (inherited from the
base Dynamic) alongside all necessary integration methods and utilities.
Every rule answers the same four questions, which is what makes them
interchangeable behind --dyn:
how the run and its state files are named, from the dynamic’s own parameters;
how the input arrays are laid out in memory before integration;
how a batch of networks is integrated – a numerical solver for the rate networks,
brian2for the spiking ones;where the states are written, and in what layout the rest of the package reads them back from (
hetero.dataloader).
A dynamic also fixes what the readout may be: VALID_ACTIVATIONS in
hetero.config pairs each dynamic with the readout activations that make
sense for it, and the command line falls back to a safe default when the two
are incompatible.
Warning
These utilities and methods are aimed to be used only locally within the methods of the corresponding class. They are exposed to the user only for inspiration and guidance on how to extend for other rules.
Abstract dynamics¶
- class hetero.dynamics.base.Dynamic(sim_path, namespace, name, ext)[source]¶
Bases:
objectBase class for for the dynamic object, that serves as containter for orchestrating the integration of the dynamical systems and storing them on the disk.
- Parameters:
sim_path (str) – Path of the simulation directory
namespace (dict) – The dynaimc rule’s argument (passed to the integrators)
name (str) – Name of the specific dynamic rule
ext (str) – The extension of the state file (pkl or npy)
Rate dynamics¶
Integrates the leaky integrator with scipy, either through
solve_ivp or through the in-house Euler and Runge–Kutta integrators, and
can drive the batch serially or across processes with joblib. Also holds
the activation_func family, which the readouts of a rate network reuse
verbatim.
Leaky-Integrator dynamic¶
The evolution of the membrane voltage \(v_i(t)\) of neuron \(i\) is described by the following rule:
where \(f(.)\) is some activation function and \('xi\) is the white noise imposed on the neuron. Note that time constants are in general neuron-specific, which renders the network heterogeneous.
- class hetero.dynamics.li.LI(sim_path, namespace, dyn_params={})[source]¶
Bases:
DynamicThe object for integrating neworks of Leaking-Integrator (LI) neurons.
- run(solver, state_name, stype=float, ncpu=-1, **kwargs)[source]¶
Runs the LI dynamic.
- Parameters:
solver (str) – Integrator’s name (euler or runge_kutta)
state_name (str) – State file name
stype (str or type, optional) – The data type in which the state is stoerd on the disk, by default float
ncpu (int, optional) – Number of CPU cores to use. The default of -1 means use all.
- hetero.dynamics.li.LI_grad(t, y, taus=None, A_adj=None, wu=None, w=None, Ju=1, J=1, Jn=1, af='possig', ut=None, xit=None, dt=1., delay=0, **kwargs)[source]¶
Implentation of the LI dynamics with noise.
- hetero.dynamics.li.integrate_n_save_joblib(integrator, namespace, taus, net_ids, sim_path, state_name, stype, ncpu)[source]¶
- hetero.dynamics.li.integrate_n_save_serial(integrator, namespace, taus, net_ids, sim_path, state_name, stype, ncpu)[source]¶
- hetero.dynamics.li.runge_kutta(**arg_dict)[source]¶
Implementation of the Runge-Kutta solver. This function is a wrapper around Scipy’s
solve_ivpmethod.
- hetero.dynamics.li.activation_func(x, af, x0=1., thr=0, **kwargs)[source]¶
Apply a specified activation function to input data with optional scaling and thresholding. The valid activation fucntions are:
‘lin’: linear
‘relu’: rectified linear unit
‘caplin’ : same as ‘lin’ but capped between 0 and 1
‘caprelu’: same as ‘relu’ but capped between 0 and 1
‘capquad’: quadratic function capped between 0 and 1
‘capcube’: cubic function capped between 0 and 1
‘capcube’: cubic function capped between 0 and 1
‘capexp’: exponential function capped between 0 and 1
‘tanh’: tangent hyperbolic
symsig: an even sigmoidal function centered at t=0 with range between -1 and 1.
‘possig’: sigmoidal function centered at y=0.5 with range between 0 and 1 .
‘possig_plus’: same as ‘possig’ but only for values larger than threshold and zero otherwise.
‘bell’ : non-normalized Gaussian activation function
- ‘camel’: a gaussian multiplied by a pure quadratic function, resulting in two identical bumps
at (±1, 1).
‘switch’: a binary activation. Zero for values smaller than thr and 1 otherwise.
- Parameters:
x (float or ndarray) – Input array or value to be transformed
af (str) – Name of the activation function to apply (e.g., ‘relu’, ‘tanh’, ‘possig’, etc.)
x0 (float) – Scaling factor for the input (default: 1.0)
thr (float) – Threshold (bias) value to shift the input (default: 0)
kwargs (dict) – Additional keyword arguments for specific activation functions
- Returns:
float or ndarray – The result of applying the chosen activation function to the input
Spiking dynamics¶
Integrates the leaky integrate-and-fire neurons with brian2. Instead of a
solver call it builds a brian2 network with a StateMonitor per
quantity, so the monitors are written chunk by chunk to keep the memory
footprint bounded on long runs. The conversion helpers between voltage,
background current and firing rate live here too.
Leaky Integrate-and-Fire dynamic¶
The evolution of the membrane voltage \(v_i(t)\) of neuron \(i\) is described by the following rule:
- class hetero.dynamics.lif.LIF(sim_path, namespace, dyn_params={})[source]¶
Bases:
DynamicThe object for integrating neworks of Leaking-Integrator (LI) neurons.
- run(state_name, solver='euler', nu0=None, nchunks=10, **kwargs)[source]¶
Runs the LIF dynamic.
- Parameters:
state_name (str) – State file name
solver (str) – Integrator’s name (euler or heun)
nu0 (float, optional) – The background firing rate of the neurons (in Hz). A unitless number must be provided. By default is None.
nchunks (int, optional) – Number of simulation chunks, by default 10
Note
When networks are large, it is better to break down the simulation into several chunks. Otherwise
Brianaccumulates all recoreded variables in RAM and soon the simulation stalls.
- hetero.dynamics.lif.get_eqs(params)[source]¶
Returns the neuronal and synaptic equations in Brian-compatible format. Note that for simplcity, we treat the feedforward, recurrent, and noise inputs as unit-free quantities (
unit: 1) and absorb their overall unit in the newly introduced parameterRIwhich matches to the dimension of the voltage (i.e., it can bevolt,mV, or even dimensionless, if voltage is expressed like so).- Parameters:
params (dict) – The arguments of the dynamical rule, specifying the type of synaptic kernels to be used.
- hetero.dynamics.lif.get_obj(net_id, objs, obj_name)[source]¶
Returns the object associated with network
net_idwhose name containsobj_name. The list of all objectsobjsmust be passed as well.
- hetero.dynamics.lif.save_chunked_monitors(mons, chunk_id, sim_path, state_name)[source]¶
saves the recorded vars of the monitor on disk
- hetero.dynamics.lif.save_merged_monitors(nchunks, net_ids, sim_path, state_name, cleanup=True)[source]¶
Merges all monitors and saves them on the disk. Moreover, cleans the old monitor chunks.
- hetero.dynamics.lif.nu2ubg(nu, E, vreset, thr, tau, tau_ref)[source]¶
Convert target firing rate to required background voltage.
- Parameters:
nu (float) – Target firing rate in Hz
E (float) – Reversal potential
vreset (float) – Reset potential
thr (float) – Threshold potential
tau (float) – Membrane time constant
tau_ref (float) – Refractory period
- Returns:
float – Required background voltage to achieve target rate