Source code for neuronunit.models.backends.rawpy
import io
import math
import pdb
from numba import jit
import numpy as np
from .base import *
import quantities as qt
from quantities import mV, ms, s
#import matplotlib.pyplot as plt
from pyneuroml import pynml
hc = {}
hc['vr'] = -65.2261863636364
hc['vPeak'] = hc['vr'] + 86.364525297619
hc['C'] = 89.7960714285714
[docs]@jit
def get_vm(C=89.7960714285714, a=0.01, b=15, c=-60, d=10, k=1.6, vPeak=(86.364525297619-65.2261863636364), vr=-65.2261863636364, vt=-50, dt=0.030, Iext=[]):
'''
dt determined by
Apply izhikevich equation as model
This function can't get too pythonic (functional), it needs to be a simple loop for
numba/jit to understand it.
'''
N = len(Iext)
v = np.zeros(N)
u = np.zeros(N)
v[0] = vr
for m in range(0,N-1):
vT = v[m]+ (dt/2) * (k*(v[m] - vr)*(v[m] - vt)-u[m] + Iext[m])/C;
v[m+1] = vT + (dt/2) * (k*(v[m] - vr)*(v[m] - vt)-u[m] + Iext[m])/C;
u[m+1] = u[m] + dt * a*(b*(v[m]-vr)-u[m]);
u[m+1] = u[m] + dt * a*(b*(v[m+1]-vr)-u[m]);
if v[m+1]>= vPeak:# % a spike is fired!
v[m] = vPeak;# % padding the spike amplitude
v[m+1] = c;# % membrane voltage reset
u[m+1] = u[m+1] + d;# % recovery variable update
v = np.divide(v, 1000.0)
vm = AnalogSignal(v,
units = mV,
sampling_period = dt * ms)
return vm
[docs]class RAWBackend(Backend):
[docs] def init_backend(self, attrs = None, cell_name = 'alice', current_src_name = 'hannah', DTC = None):
backend = 'RAW'
super(RAWBackend,self).init_backend()
self.model._backend.use_memory_cache = False
self.current_src_name = current_src_name
self.cell_name = cell_name
self.vM = None
self.attrs = attrs
self.temp_attrs = None
if type(attrs) is not type(None):
self.set_attrs(**attrs)
self.sim_attrs = attrs
if type(DTC) is not type(None):
if type(DTC.attrs) is not type(None):
self.set_attrs(**DTC.attrs)
#print('gets here to DTC attrs',DTC.attrs)
if hasattr(DTC,'current_src_name'):
self._current_src_name = DTC.current_src_name
if hasattr(DTC,'cell_name'):
self.cell_name = DTC.cell_name
[docs] def set_stop_time(self, stop_time = 650*pq.ms):
"""Sets the simulation duration
stopTimeMs: duration in milliseconds
"""
self.tstop = float(stop_time.rescale(pq.ms))
[docs] def get_membrane_potential(self):
"""Must return a neo.core.AnalogSignal.
And must destroy the hoc vectors that comprise it.
"""
return self.vM
[docs] def set_attrs(self, **attrs):
self.model.attrs.update(attrs)
[docs] def inject_square_current(self, current):#, section = None, debug=False):
"""Inputs: current : a dictionary with exactly three items, whose keys are: 'amplitude', 'delay', 'duration'
Example: current = {'amplitude':float*pq.pA, 'delay':float*pq.ms, 'duration':float*pq.ms}}
where \'pq\' is a physical unit representation, implemented by casting float values to the quanitities \'type\'.
Description: A parameterized means of applying current injection into defined
Currently only single section neuronal models are supported, the neurite section is understood to be simply the soma.
"""
attrs = copy.copy(self.model.attrs)
if 'injected_square_current' in current.keys():
c = current['injected_square_current']
else:
c = current
amplitude = float(c['amplitude'])
duration = float(c['duration'])#/dt#/dt.rescale('ms')
delay = float(c['delay'])#/dt#.rescale('ms')
tMax = delay + duration + 200.0#/dt#*pq.ms
self.set_stop_time(tMax*pq.ms)
tMax = self.tstop
dt = 0.025
N = int(tMax/dt)
Iext = np.zeros(N)
delay_ind = int((delay/tMax)*N)
duration_ind = int((duration/tMax)*N)
Iext[0:delay_ind-1] = 0.0
Iext[delay_ind:delay_ind+duration_ind-1] = amplitude
Iext[delay_ind+duration_ind::] = 0.0
attrs['Iext'] = Iext
attrs['dt'] = dt
self.vM = get_vm(**attrs)
return self.vM
def _backend_run(self):
results = {}
results['vm'] = self.vM
results['t'] = self.vM.times
results['run_number'] = results.get('run_number',0) + 1
return results