Model of peripheral nerve with ephaptic coupling (Capllonch-Juan & Sepulveda 2020)

 Download zip file   Auto-launch 
Help downloading and running models
We built a computational model of a peripheral nerve trunk in which the interstitial space between the fibers and the tissues is modelled using a resistor network, thus enabling distance-dependent ephaptic coupling between myelinated axons and between fascicles as well. We used the model to simulate a) the stimulation of a nerve trunk model with a cuff electrode, and b) the propagation of action potentials along the axons. Results were used to investigate the effect of ephaptic interactions on recruitment and selectivity stemming from artificial (i.e., neural implant) stimulation and on the relative timing between action potentials during propagation.
1 . Capllonch-Juan M, Sepulveda F (2020) Modelling the effects of ephaptic coupling on selectivity and response patterns during artificial stimulation of peripheral nerves. PLoS Comput Biol 16:e1007826 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Extracellular; Axon;
Brain Region(s)/Organism:
Cell Type(s): Myelinated neuron;
Gap Junctions:
Simulation Environment: NEURON; Python;
Model Concept(s): Ephaptic coupling; Stimulus selectivity;
AXNODE.mod *
aaa_info_dataset * * * * * * * * * * * * * * * * *
Algebraic operations

import csv
import numpy as np
from collections import OrderedDict
from scipy.stats import linregress

import algebra as alg
import geometry as geo
import workspace as ws

def parameter_regressions(filename):
	""" Open and read a file with parameters over which to make 
	regressions and obtain new expressions and values """
	# Read data
	with open(filename, 'r') as f:
		frl = list(csv.reader(f))
		keys = frl[0]
		data = np.array(frl[1:], dtype=np.float64)

	n_fields = len(keys)
	n_entries = len(data)
	data_dict = OrderedDict()
	for i in range(n_fields):
		data_dict[keys[i]] = data[:, i]

	# Independent variable
	indepvar = keys[0]

	# Dictionary containing the regressions
	regressions = OrderedDict()
	# Of course, indicate which one is the independent variable
	regressions['independent variable'] = indepvar

	for i, (k, v) in enumerate(list(data_dict.items())[1:]):

		x = data_dict[indepvar]

		# Linear regression
		slope, intercept, r_value, p_value, std_err = linregress(x, v)
		# Check if it's valid
		if intercept < 0:
			# Negative values, unacceptable. Use a polynomial fit
			# Quadratic fit
			parabolic_coeffs = np.polyfit(x, v, 2)
			if parabolic_coeffs[-1] < 0:
				# Not even a quadratic fit worked
				msg = 'ERROR: Could not obtain positive values for ' + k + ' for small ' + indepvar
			# Give it a x-array that covers the whole domain
			x_ = np.linspace(0, x.max(), 100)
			ypol = polynomial(x_, parabolic_coeffs)
			# return polynomial regression
			a, b, c = parabolic_coeffs
			regressions[k] = lambda x: a * x ** 2 + b * x + c
			# Plot linear regression
			# Create straight line object and draw it
			sl = geo.StraightLine((0, intercept), slope)
			regressions[k] = sl.equation
	return regressions

def polynomial(x, c):
	""" Get the values of y from a polynomial of degree len(c) - 1 with 
	coefficients c, using abscissa x 
	The coefficients c must start from the higher order, just like in 
	np.polyfit (for consistency) """
	y = np.zeros(len(x), dtype=np.float64)
	for i, cc in enumerate(c[::-1]):
		y += cc * x ** i
	return y

def nan_to_inf(m):
	""" Turn all nan elements of a matrix m to infinity """
	m[np.where(np.isnan(m))] = np.inf
	return m

def diagv(v):
	""" Put the vector v on the diagonal of a square matrix """
	eye = np.eye(v.size)
	r = v * eye
	r[np.where(eye == 0.)] = 0.
	return r
def vectomat(v):
	""" Create a matrix from a vector by repeating it """
	n = v.size
	return v.repeat(n).reshape((n, n))

def compl_mat(v):
	""" Obtain a particular matrix from a vector """
	vm = vectomat(v)
	return vm - vm.T

def one_side(m):
	""" Return a vector containing one side of the off-diagonal terms of a 
	matrix and their indices """

	# Create list of pairs
	nc = m.shape[0]
	ids = np.arange(nc)
	idvm = vectomat(ids)
	# pairs = np.array([idvm, idvm.T]).reshape((nc, nc, 2))
	idvm2 = idvm.T

	# Create mask
	x = np.arange(nc)
	y = np.arange(nc)
	x, y = np.meshgrid(x, y)
	mask = x - y

	# Mask the values of m and pairs
	# pairs = <= 0, pairs)
	ids1 = <= 0, idvm)
	ids2 = <= 0, idvm2)
	m = <= 0, m)
	ids1 = ids1.compressed()
	ids2 = ids2.compressed()
	pairs = np.array([ids1, ids2]).T
	m = m.compressed()

	return pairs, m

def make_sym_rem_nans(m):
	""" Given a matrix m which is supposed to be symmetric but it's 
	not because there are nans, remove the non-due nans to make 
	the matrix symmetric """
	mmasked =, m)
	mask = mmasked.mask
	nonan = np.where(mask.T == False)
	m[nonan] = mmasked.T[nonan]
	return m