Welcome to LFPykernels’ documentation!

LFPykernels

The LFPykernels package incorporates forward-model based calculations of causal spike-signal impulse response functions for finite-sized neuronal network models.

Build Status

DOI Coverage Status Documentation Status flake8 lint Python application Upload Python Package License

Citation

These codes correspond to results shown in the peer-reviewed manuscript:

Hagen E, Magnusson SH, Ness TV, Halnes G, Babu PN, et al. (2022) Brain signal predictions from multi-scale networks using a linearized framework. PLOS Computational Biology 18(8): e1010353. https://doi.org/10.1371/journal.pcbi.1010353

Bibtex format:

@article{10.1371/journal.pcbi.1010353,
    doi = {10.1371/journal.pcbi.1010353},
    author = {Hagen, Espen AND Magnusson, Steinn H. AND Ness, Torbjørn V. AND Halnes, Geir AND Babu, Pooja N. AND Linssen, Charl AND Morrison, Abigail AND Einevoll, Gaute T.},
    journal = {PLOS Computational Biology},
    publisher = {Public Library of Science},
    title = {Brain signal predictions from multi-scale networks using a linearized framework},
    year = {2022},
    month = {08},
    volume = {18},
    url = {https://doi.org/10.1371/journal.pcbi.1010353},
    pages = {1-51},
    number = {8},
}

If you use this software, please cite it as (change <version>/<git-SHA>/<git-tag> accordingly):

Hagen, Espen. (2021). LFPykernels (<version>/<git-SHA>/<git-tag>). Zenodo. https://doi.org/10.5281/zenodo.5720619

BibTex format:

@software{hagen_espen_2021_5720619,
  author       = {Hagen, Espen},
  title        = {LFPykernels},
  month        = nov,
  year         = 2021,
  note         = {If you use this software, please cite it as below.},
  publisher    = {Zenodo},
  version      = {<version>/<git-SHA>/<git-tag>},
  doi          = {10.5281/zenodo.5720619},
  url          = {https://doi.org/10.5281/zenodo.5720619}
}

If you use or refer to this work, please cite it as above. Adaptations or modifications of this work should comply with the provided LICENSE file provided with this repository.

Features

The LFPykernels package incorporates forward-model based calculations of causal spike-signal impulse response functions for finite-sized neuronal network models. The signals considered are low-frequency extracellular potentials (“local field potential” - LFP) or current dipole moments (and by extension EEG and MEG like signals) that are thought to mainly stem from synaptic currents and associated return currents. The basic idea is that the effect of any spike event in each presynaptic population on each signal type can be captured by single linearised multicompartment neuron models representative of each population and simultaneously accounting for known distributions of cells and synapses in space, distributions of delays, synaptic currents and associated return currents.

The present methodology is described in detail by Hagen E et al., 2022. The intended use for filter kernels predicted using LFPykernels is forward-model based signal predictions from neuronal network simulation frameworks using simplified neuron representations like leaky integrate-and-fire point neurons or rate-based neurons, but can also be used with biophysically detailed network models.

Let \(\nu_X(t)\) describe presynaptic population spike rates in units of spikes/dt and \(H_{YX}(\mathbf{R}, \tau)\) predicted spike-signal kernels for the connections between presynaptic populations \(X\) and postsynaptic populations \(Y\) the full signal may then be computed via the sum over linear convolutions:

\[V(\mathbf{R}, t) = \sum_X \sum_Y (\nu_X \ast H_{YX})(\mathbf{R}, t)\]

A more elaborate example combining kernel predictions with a spiking point-neuron network simulation is provided in the example notebook https://github.com/LFPy/LFPykernels/blob/main/examples/LIF_net_forward_model_predictions.ipynb

For questions, please raise an issue at https://github.com/LFPy/LFPykernels/issues.

Usage

Example prediction of kernel function \(H(\mathbf{R},\tau)\) mapping spike events of a presynaptic inhibitory population \(X==\mathrm{I}\) to extracellular potential contributions by a postsynaptic excitatory population \(Y==\mathrm{E}\) (see https://github.com/LFPy/LFPykernels/blob/main/examples/README_example.ipynb):

import os
import matplotlib.pyplot as plt
import scipy.stats as st
import numpy as np
from lfpykernels import GaussCylinderPotential, KernelApprox
import neuron

# recompile mod files if needed
mech_loaded = neuron.load_mechanisms('mod')
if not mech_loaded:
    os.system('cd mod && nrnivmodl && cd -')
    mech_loaded = neuron.load_mechanisms('mod')
print(f'mechanisms loaded: {mech_loaded}')

# misc parameters
dt = 2**-4  # time resolution (ms)
t_X = 500  # time of synaptic activations (ms)
tau = 50  # duration of impulse response function after onset (ms)
Vrest = -65  # assumed average postsynaptic potential (mV)

X=['E', 'I']   # presynaptic population names
N_X = np.array([8192, 1024])  # presynpatic population sizes
Y = 'E' # postsynaptic population
N_Y = 8192  # postsynaptic population size
C_YX = np.array([0.05, 0.05])  # pairwise connection probability between populations X and Y
nu_X = {'E': 2.5, 'I': 5.0}  # assumed spike rates of each population (spikes/s)
g_eff = True  # account for changes in passive leak due to persistent synaptic activations

def set_passive(cell, Vrest):
    """Insert passive leak channel across all sections

    Parameters
    ----------
    cell: object
        LFPy.NetworkCell like object
    Vrest: float
        Steady state potential
    """
    for sec in cell.template.all:
        sec.insert('pas')
        sec.g_pas = 0.0003  # (S/cm2)
        sec.e_pas = Vrest  # (mV)

# parameters for LFPy.NetworkCell representative of postsynaptic population
cellParameters={
    'templatefile': 'BallAndSticksTemplate.hoc',
    'templatename': 'BallAndSticksTemplate',
    'custom_fun': [set_passive],
    'custom_fun_args': [{'Vrest': Vrest}],
    'templateargs': None,
    'delete_sections': False,
    'morphology': 'BallAndSticks_E.hoc'}

populationParameters={
        'radius': 150.0,  # population radius (µm)
        'loc': 0.0,  # average depth of cell bodies (µm)
        'scale': 75.0}  # standard deviation (µm)

# Predictor for extracellular potentials across depth assuming planar disk source
# elements convolved with Gaussian along z-axis.
# See https://lfpykernels.readthedocs.io/en/latest/#class-gausscylinderpotential for details
probe = GaussCylinderPotential(
    cell=None,
    z=np.linspace(1000., -200., 13),  # depth of contacts (µm)
    sigma=0.3,  # tissue conductivity (S/m)
    R=populationParameters['radius'],  #
    sigma_z=populationParameters['scale'],
    )

# Create KernelApprox object. See https://lfpykernels.readthedocs.io/en/latest/#class-kernelapprox for details
kernel = KernelApprox(
    X=X,
    Y=Y,
    N_X=N_X,
    N_Y=N_Y,
    C_YX=C_YX,
    cellParameters=cellParameters,
    populationParameters=populationParameters,
    # function and parameters used to estimate average multapse count:
    multapseFunction=st.truncnorm,
    multapseParameters=[
        {'a': (1 - 2.) / .6, 'b': (10 - 2.) / .6, 'loc': 2.0, 'scale': 0.6},
        {'a': (1 - 5.) / 1.1, 'b': (10 - 5.) / 1.1, 'loc': 5.0, 'scale': 1.1}],
    # function and parameters for delay distribution from connections between a
    # population in X onto population Y:
    delayFunction=st.truncnorm,
    delayParameters=[{'a': -2.2, 'b': np.inf, 'loc': 1.3, 'scale': 0.5},
                     {'a': -1.5, 'b': np.inf, 'loc': 1.2, 'scale': 0.6}],
    # parameters for synapses from connections by populations X onto Y
    synapseParameters=[
        {'weight': 0.00012, 'syntype': 'Exp2Syn', 'tau1': 0.2, 'tau2': 1.8, 'e': 0.0},
        {'weight': 0.002, 'syntype': 'Exp2Syn', 'tau1': 0.1, 'tau2': 9.0, 'e': -80.0}],
    # parameters for spatial synaptic connectivity by populations X onto Y
    synapsePositionArguments=[
        {'section': ['apic', 'dend'],
         'fun': [st.norm],
         'funargs': [{'loc': 50.0, 'scale': 100.0}],
         'funweights': [1.0]},
        {'section': ['soma', 'apic', 'dend'],
         'fun': [st.norm],
         'funargs': [{'loc': -100.0, 'scale': 100.0}],
         'funweights': [1.0]}],
    # parameters for extrinsic synaptic input
    extSynapseParameters={'syntype': 'Exp2Syn', 'weight': 0.0002, 'tau1': 0.2, 'tau2': 1.8, 'e': 0.0},
    nu_ext=40.,  # external activation rate (spikes/s)
    n_ext=450,  # number of extrinsic synapses
    nu_X=nu_X,
)

# make kernel predictions for connection from populations X='I' onto Y='E'
H = kernel.get_kernel(
    probes=[probe],
    Vrest=Vrest, dt=dt, X='I', t_X=t_X, tau=tau,
    g_eff=g_eff)

Physical units

Notes on physical units used in LFPykernels:

  • There are no explicit checks for physical units

  • Transmembrane currents are assumed to be in units of (nA)

  • Spatial information is assumed to be in units of (µm)

  • Voltages are assumed to be in units of (mV)

  • Extracellular conductivities are assumed to be in units of (S/m)

  • current dipole moments are assumed to be in units of (nA µm)

  • Magnetic fields are assumed to be in units of (nA/µm)

  • Simulation times are assumed to be in units of (ms) with step size ∆t

  • Spike rates are assumed to be in units of (# spikes / ∆t)

Documentation

The online Documentation of LFPykernels can be found here: https://lfpykernels.readthedocs.io/en/latest

Dependencies

LFPykernels is implemented in Python and is written (and continuously tested) for Python >= 3.7 (older versions may or may not work). The main LFPykernels module depends on LFPy (https://github.com/LFPy/LFPy, https://LFPy.readthedocs.io).

Running all unit tests and example files may in addition require py.test, matplotlib, LFPy.

Installation

From development sources (https://github.com/LFPy/LFPykernels)

Install the current development version on https://GitHub.com using git (https://git-scm.com):

git clone https://github.com/LFPy/LFPykernels.git
cd LFPykernels
python setup.py install  # --user optional

or using pip:

pip install .  # --user optional

For active development, link the repository location

pip install -e .  # --user optional

Installation of stable releases on PyPI.org (https://www.pypi.org)

Installing stable releases from the Python Package Index (https://www.pypi.org/project/lfpykernels):

pip install lfpykernels  # --user optional

To upgrade the installation using pip:

pip install --upgrade --no-deps lfpykernels

Docker

We provide a Docker (https://www.docker.com) container recipe file with LFPykernels etc. To get started, install Docker and issue either:

# build Dockerfile from GitHub
docker build -t lfpykernels https://raw.githubusercontent.com/LFPy/LFPykernels/main/Dockerfile
docker run -it -p 5000:5000 lfpykernels

or

# build local Dockerfile (obtained by cloning repo, checkout branch etc.)
docker build -t lfpykernels - < Dockerfile
docker run -it -p 5000:5000 lfpykernels

If the docker file should fail for some reason it is possible to store the build log and avoid build caches by issuing

docker build --no-cache --progress=plain -t lfpykernels - < Dockerfile 2>&1 | tee lfpykernels.log

For successful builds, the --mount option can be used to mount a folder on the host to a target folder as:

docker run --mount type=bind,source="$(pwd)",target=/opt/data -it -p 5000:5000 lfpykernels

which mounts the present working dirctory ($(pwd)) to the /opt/data directory of the container. Try mounting the LFPykernels source directory for example (by setting source="<path-to-LFPykernels>"). Various example files can then be found in the folder /opt/data/examples/ when the container is running.

Jupyter notebook servers running from within the container can be accessed after invoking them by issuing:

cd /opt/data/examples/
jupyter-notebook --ip 0.0.0.0 --port=5000 --no-browser --allow-root

and opening the resulting URL in a browser on the host computer, similar to: http://127.0.0.1:5000/?token=dcf8f859f859740fc858c568bdd5b015e0cf15bfc2c5b0c1

Acknowledgements

This work was supported by the European Union Horizon 2020 Research and Innovation Programme under Grant Agreement No. 785907 and No. 945539 Human Brain Project (HBP) SGA2 and SGA3. We also acknowledge the use of Fenix Infrastructure resources, which are partially funded from the European Union’s Horizon 2020 Research and Innovation Programme through the ICEI Project under the Grant Agreement No. 800858; The Helmholtz Alliance through the Initiative and Networking Fund of the Helmholtz Association and the Helmholtz Portfolio theme Supercomputing and Modeling for the Human Brain; and The Excellence Strategy of the Federal Government and the La¨nder [G:(DE-82)EXS-PF-JARA-SDS005, G: (DE-82)EXS-SF-neuroIC002].

Module lfpykernels

Initialization of LFPykernels

Copyright (C) 2021 Computational Neuroscience Group, NMBU.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

Classes
  • KernelApprox:

    Class for computing linear spike-to-signal filter kernels resulting from presynaptic spiking activity and resulting postsynaptic currents

  • GaussCylinderPotential:

    Compute electric potential of electric sources that are treated as inhomogeneous current source density cylinders that are Gaussian along the vertical z-axis and constant within a fixed radius in the radial directions (xy-plane).

  • KernelApproxCurrentDipoleMoment:

    Modified lfpykit.CurrentDipoleMoment class that ignores contributions to the current dipole moment in the the x- and y-directions due to rotational symmetry around the z-axis.

Modules
  • kernel_approx

  • version

class KernelApprox

class lfpykernels.KernelApprox(X=['E'], Y='E', N_X=array([1024]), N_Y=1024, C_YX=array([0.1]), cellParameters={}, populationParameters={'loc': 0, 'radius': 100, 'scale': 50}, rotationParameters={'x': 0.0, 'y': 0.0}, multapseFunction=<scipy.stats._continuous_distns.truncnorm_gen object>, multapseParameters=[{'a': -0.2, 'b': 1.6, 'loc': 2, 'scale': 5}], delayFunction=<scipy.stats._continuous_distns.truncnorm_gen object>, delayParameters=[{'a': -4.0, 'b': inf, 'loc': 1.5, 'scale': 0.3}], synapseParameters=[{'weight': 0.001, 'syntype': 'Exp2Syn', 'tau1': 0.2, 'tau2': 1.8, 'e': 0.0}], synapsePositionArguments=[{'section': ['soma', 'apic'], 'fun': [<scipy.stats._continuous_distns.norm_gen object>, <scipy.stats._continuous_distns.norm_gen object>], 'funargs': [{'loc': 0.0, 'scale': 100.0}, {'loc': 750.0, 'scale': 100.0}], 'funweights': [0.5, 1.0]}], extSynapseParameters={'e': 0.0, 'syntype': 'Exp2Syn', 'tau1': 0.2, 'tau2': 1.8, 'weight': 0.0005}, nu_ext=40.0, n_ext=128.0, nu_X={'E': 1.0}, conductance_based=True)[source]

Bases: object

Class for computing linear spike-to-signal filter kernels resulting from presynaptic spiking activity and resulting postsynaptic currents

Parameters
X: list of str

presynaptic populations

Y: str

postsynaptic population

N_X: array of int

presynaptic population sizes

N_Y: int

postsynaptic population size

C_YX: array of float

pairwise connection probabilities between populations X and Y

multapseFunction: callable

scipy.stats.rv_discrete or scipy.stats.rv_continuous like function for determining mean number of synapse instances per connection between populations X and Y. Default is scipy.stats.truncnorm.

multapseParameters: list of dict

kwargs for multapseFunction

cellParameters: dict

kwargs for LFPy.TemplateCell class for cell representative of the entire postsynaptic population

populationParameters: dict

keys: radius, loc, scale with float values representing radius in xy-plane and mean and standard deviation of cell positions along the z-axis

delayFunction: callable

scipy.stats.rv_continuous like callable with pdf method for delays between presynaptic populations X and postsynaptic population Y. Default is scipy.stats.truncnorm.

delayParameters: list of dict

kwargs for callable delayFunction

synapseParameters: list of dict

kwargs for LFPy.Synapse, assuming conductance based synapse which will be linearized to current based synapse for connections between populations X and Y

synapsePositionArguments: list of dict

kwargs for KernelApprox.get_rand_idx_area_and_distribution_prob method for connections between populations X and Y

extSynapseParameters: dict

shared parameters for extrinsic synapses distributed homogeneously across morphology

nu_ext: float

activation rate of extrinsic synapses (1/s)

n_ext: float

number of extrinsic synapses

nu_X: dict of floats

presynaptic population rates (1/s)

conductance_based: bool

True (default) if the original network model has conductance-based synapses, False if it uses current-based synapses

draw_rand_pos(SIZE, radius, loc, scale, cap=None)[source]

Draw SIZE random locations within radius radius in xy-plane, at mean depth loc and standard deviation scale along z-axis.

Parameters
SIZE: int

Population size

radius: float

Population radius (µm)

loc: float

expected mean depth (µm)

scale: float

expected standard deviation of depth (µm)

cap: None, float or length to list of floats

if float, cap distribution between [loc-cap, loc+cap), if list, cap distribution between [loc-cap[0], loc+cap[1]]

Returns
pos: ndarray

shape (SIZE, 3) ndarray with randomly chosen locations

get_delay(X, dt, tau)[source]

Get normalized transfer function for conduction delay distribution for connections between population X and Y

Parameters
X: str

presynaptic population name

dt: float

time resolution

tau: float

time lag

Returns
h_delta: ndarray

shape (2 * tau // dt + 1) array with transfer function for delay distribution

get_kernel(probes, Vrest=-65, dt=0.0625, X='E', t_X=200, tau=50, g_eff=True, fir=False)[source]

Compute linear spike-to-signal filter kernel mapping presynaptic population firing rates/spike trains to signal measurement, e.g., LFP.

Parameters
probes: list of objects

list of LFPykit.models like instances (should be instantiated with cell=None).

Vrest: float or list of float

Mean/Expectation value of postsynaptic membrane voltage used for linearization of synapse conductances. If list of length equal to the number of compartments, the corresponding synapse current magnitude will be computed on a per compartment basis.

dt: float

temporal resolution (ms)

X: str

presynaptic population for kernel, must be element in <KernelApprox instance>.X

t_X: float

time of presynaptic event (ms)

tau: float

half-duration of filter kernel – full duration is (2 * tau + dt) if fir==False

g_eff: bool

if True (default), account for contributions by synaptic conductances to the effective membrane time constant from presynaptic populations X and extrinsic connections.

fir: bool

if True, return only filter coefficients corresponding to time lags greater than zero on the interval [dt, tau] corresponding to that of a finite impulse response (FIR) filter. If False (default), the full set of coefficients on the interval [-tau, tau] is returned.

Returns
H_YX: dict of ndarray

shape (n_channels, 2 * tau // dt + 1) linear response kernel

get_rand_idx_area_and_distribution_prob(cell, section='allsec', z_min=-1000000.0, z_max=1000000.0, fun=<scipy.stats._continuous_distns.norm_gen object>, funargs={'loc': 0, 'scale': 100}, funweights=None)[source]

Return probability normalized to the membrane area of each segment multiplied by the value of the probability density function of fun, a function in the scipy.stats module with corresponding function arguments in funargs on the interval [z_min, z_max]

Parameters
section: str

string matching a section name

z_min: float

lower depth interval

z_max: float

upper depth interval

fun: function or str, or iterable of function or str

if function a scipy.stats method, if str, must be method in scipy.stats module with the same name (like norm), if iterable (list, tuple, numpy.array) of function or str some probability distribution in scipy.stats module

funargs: dict or iterable

iterable (list, tuple, numpy.array) of dict, arguments to fun.pdf method (e.g., w. keys loc and scale)

funweights: None or iterable

iterable (list, tuple, numpy.array) of floats, scaling of each individual fun (i.e., introduces layer specificity)

class GaussCylinderPotential

class lfpykernels.GaussCylinderPotential(cell, z, sigma=0.3, R=100, sigma_z=50.0)[source]

Bases: LinearModel

Compute electric potential of electric sources that are treated as inhomogeneous current source density cylinders that are Gaussian along the vertical z-axis and constant within a fixed radius in the radial directions (xy-plane).

Parameters
cell: object

CellGeometry object or similar

z: ndarray

contact point locations

sigma: float

conductivity

R: float

disk radius

sigma_z: float > 0

standard deviation of spatial filter

get_transformation_matrix()[source]

Get linear response matrix

Returns
response_matrix: ndarray

shape (n_coords, n_seg) ndarray

Raises
AttributeError

if cell is None

class KernelApproxCurrentDipoleMoment

class lfpykernels.KernelApproxCurrentDipoleMoment(cell)[source]

Bases: CurrentDipoleMoment

Modified lfpykit.CurrentDipoleMoment like class that ignores contributions to the current dipole moment in the x- and y-directions due to rotational symmetry around the z-axis.

Parameters
cell: object

CellGeometry object or similar

get_transformation_matrix()[source]

Get linear response matrix

Returns
response_matrix: ndarray

shape (3, n_seg) ndarray

Raises
AttributeError

if cell is None

Indices and tables