Source code for nnmt.models.microcircuit
"""
Defines the microcircuit model, a multilayer model of a cortical column.
"""
import numpy as np
from .network import Network
from .. import ureg
[docs]class Microcircuit(Network):
"""
The Potjans and Diesmann microcircuit model.
See :cite:t:`potjans2014` for details regarding the model. In short, it is
a four-layer (2/3, 4, 5, 6) network model with a population of excitatory
(E) and inhibitory (I) neurons of leaky integrate-and-fire neurons with
exponential synapses in each layer. The inhibitory synaptic weights are `g`
times as strong as the excitatory synaptic weights. The weights between all
populations are equally strong, except for layer 4E to layer 2/3E, where
the excitatory weights are twice as strong.
Given the parameter yaml files, the network model calculates the dependend
parameters. It converts the weights from pA to mV, calculates the weight
matrix, calculates relative thresholds, and the analysis frequencies.
The NNMT repository contains an :ref:`example <sec_examples>` providing the
yaml parameter files with all the parameters that need to be defined to use
this model.
Parameters
----------
network_params : [str | dict]
Network parameters yaml file name or dictionary including:
- `C` : float
Membrane capacitance in pF.
- `K_ext` : np.array
Number of external in-degrees.
- `V_th_abs` : [float | np.array]
Absolute threshold potential in mV.
- `V_0_abs` : [float | np.array]
Absolute reset potential in mV.
- `d_e` : float
Mean delay of excitatory connections in ms.
- `d_e_sd` : float
Standard deviation of delay of excitatory connections in ms.
- `d_i` : float
Mean delay of inhibitory connections in ms.
- `d_i_sd`
Standard deviation of delay of inhibitory connections in ms.
- `g` : float
Ratio of inhibitory to excitatory synaptic weights.
- `populations` : list of strings
Names of different populations.
- `tau_s` : float
Synaptic time constant in ms.
- `w` : float
Amplitude of excitatory post synaptic current in pA.
- `w_ext`: float
Amplitude of external excitatory post synaptic current in pA.
analysis_params : [str | dict]
Analysis parameters yaml file name or dictionary including:
- `df` : float
Step size between two analysis frequencies.
- `f_min` : float
Minimal analysis frequency.
- `f_max` : float
Maximal analysis frequency.
- `dk` : float
Step size between two analysis wavenumber.
- `k_min` : float
Minimum analysis wavenumber.
- `k_max`
Maximum analysis wavenumber.
See Also
--------
nnmt.models.Network : Parent class defining all arguments, attributes, and
methods.
"""
def __init__(self, network_params=None, analysis_params=None, file=None):
super().__init__(network_params, analysis_params, file)
self.network_params['label'] = 'microcircuit'
derived_network_params = (
self._calculate_dependent_network_parameters())
self.network_params.update(derived_network_params)
# calculate dependend analysis parameters
if analysis_params is not None:
derived_analysis_params = (
self._calculate_dependent_analysis_parameters())
self.analysis_params.update(derived_analysis_params)
self._convert_param_dicts_to_base_units_and_strip_units()
def _instantiate(self, new_network_params, new_analysis_params):
return Microcircuit(new_network_params, new_analysis_params)
def _calculate_dependent_network_parameters(self):
"""
Calculate all network parameters derived from parameters in yaml file.
Calculates the number of populations, the relative potentials, converts
the weights from pA to mV, constructs the weight matrix, and the delay
matrix.
Returns
-------
dict
Dictionary containing all derived network parameters.
"""
derived_params = {}
# calculate dimension of system
dim = len(self.network_params['populations'])
derived_params['dimension'] = dim
# reset reference potential to 0
derived_params['V_0_rel'] = 0 * ureg.mV
derived_params['V_th_rel'] = (self.network_params['V_th_abs']
- self.network_params['V_0_abs'])
# convert weights in pA (current) to weights in mV (voltage)
tau_s_div_C = self.network_params['tau_s'] / self.network_params['C']
derived_params['j'] = (tau_s_div_C
* self.network_params['w'])
try:
derived_params['j'].ito(ureg.mV)
except AttributeError:
pass
# weight matrix in pA (current)
W = np.ones((dim, dim)) * self.network_params['w']
W[1:dim:2] *= -self.network_params['g']
W = np.transpose(W)
derived_params['W'] = W
# weight matrix in mV (voltage)
derived_params['J'] = (tau_s_div_C * derived_params['W'])
try:
derived_params['J'].ito(ureg.mV)
except AttributeError:
pass
# mean delay matrix
D = np.ones((dim, dim)) * self.network_params['d_e']
D[1:dim:2] = np.ones(dim) * self.network_params['d_i']
D = np.transpose(D)
derived_params['Delay'] = D
# delay standard deviation matrix
D = np.ones((dim, dim)) * self.network_params['d_e_sd']
D[1:dim:2] = np.ones(dim) * self.network_params['d_i_sd']
D = np.transpose(D)
derived_params['Delay_sd'] = D
# larger weight for L4E->L23E connections
derived_params['W'][0][2] *= 2.0
derived_params['J'][0][2] *= 2.0
derived_params['J_ext'] = (
tau_s_div_C * np.ones(self.network_params['K_ext'].shape)
* self.network_params['w_ext'])
try:
derived_params['J_ext'].ito(ureg.mV)
except AttributeError:
pass
return derived_params
def _calculate_dependent_analysis_parameters(self):
"""
Calculate all analysis parameters derived from parameters in yaml file
Calculates the angular analysis frequencies, and optionally the
wavenumbers for a spatial analysis.
Returns
-------
dict
dictionary containing derived parameters
"""
derived_params = {}
# convert regular to angular frequencies
w_min = 2 * np.pi * self.analysis_params['f_min']
w_max = 2 * np.pi * self.analysis_params['f_max']
dw = 2 * np.pi * self.analysis_params['df']
try:
w_min = w_min.magnitude
w_max = w_max.magnitude
dw = dw.magnitude
except AttributeError:
pass
# enable usage of quantities
def calc_evaluated_omegas(w_min, w_max, dw):
""" Calculates omegas at which functions are to be evaluated """
return np.arange(w_min, w_max, dw)
derived_params['omegas'] = calc_evaluated_omegas(w_min, w_max, dw)
try:
w_min = w_min.magnitude
w_max = w_max.magnitude
dw = dw.magnitude
except AttributeError:
pass
def calc_evaluated_wavenumbers(k_min, k_max, dk):
return np.arange(k_min, k_max, dk)
try:
k_min = self.analysis_params['k_min']
k_max = self.analysis_params['k_max']
dk = self.analysis_params['dk']
try:
k_min = k_min.to_base_units().magnitude
k_max = k_max.to_base_units().magnitude
dk = dk.to_base_units().magnitude
except AttributeError:
pass
derived_params['k_wavenumbers'] = (
calc_evaluated_wavenumbers(k_min, k_max, dk))
except KeyError:
pass
return derived_params