NEURON + Python Michael Hines HBP CodeJam Workshop #7 Manchester - - PowerPoint PPT Presentation

neuron python
SMART_READER_LITE
LIVE PREVIEW

NEURON + Python Michael Hines HBP CodeJam Workshop #7 Manchester - - PowerPoint PPT Presentation

NEURON + Python Michael Hines HBP CodeJam Workshop #7 Manchester 2016 NINDS I r n e t t e e r r p p r r e e t Python t e n HOC r I Neuron specific syntax Compiled I r n e t t e e r r p p r r e e t


slide-1
SLIDE 1

NINDS Michael Hines HBP CodeJam Workshop #7 Manchester 2016

NEURON + Python

slide-2
SLIDE 2

Compiled

Neuron specific syntax

I n t e r p r e t e r

HOC

I n t e r p r e t e r

Python

slide-3
SLIDE 3

Compiled

Neuron specific syntax

I n t e r p r e t e r

HOC

I n t e r p r e t e r

Python

Run: compute model

slide-4
SLIDE 4

Compiled

Neuron specific syntax

I n t e r p r e t e r

HOC

I n t e r p r e t e r

Python

Run: compute model LFP RxD

slide-5
SLIDE 5

Compiled Interpreter

Python

Gather values into numpy array.

slide-6
SLIDE 6

Compiled Interpreter

Python

Gather values into numpy array. from neuron import h import numpy

slide-7
SLIDE 7

Compiled Interpreter

Python

Gather values into numpy array. from neuron import h import numpy hv = h.Vector(size) v = hv.as_numpy()

slide-8
SLIDE 8

Compiled Interpreter

Python

Gather values into numpy array. from neuron import h import numpy pv = h.PtrVector(size) pv.pset(i, _ref_hocvar) hv = h.Vector(size) v = hv.as_numpy() pv.gather(hv)

slide-9
SLIDE 9

Compiled Interpreter

Python

Gather values into numpy array. from neuron import h import numpy pv = h.PtrVector(size) pv.pset(i, _ref_hocvar) i=0 for sec in h.allsec(): for seg in sec: pv.pset(i, seg._ref_v) i += 1 hv = h.Vector(size) v = hv.as_numpy() pv.gather(hv)

slide-10
SLIDE 10

Python API for NEURON solvers

slide-11
SLIDE 11

Python API for NEURON solvers nonvint_block_supervisor

dy/dt = f(y, v, t) y can affect channel conductance

slide-12
SLIDE 12

High performance evaluation of M*x = b f ∂ y ∂ / M ~ 1 − dt*

Python API for NEURON solvers nonvint_block_supervisor

dy/dt = f(y, v, t) y can affect channel conductance

slide-13
SLIDE 13

NMODL

KINETIC pmp { } Pump M e m b r a n e a d j a c e n t Bulk [Ca] ica

20 40 60 80 100 0.02 0.04 0.06 0.08 0.1 soma.cai( 0.5 ) 65 73 0.005 mM ms 20 40 60 80 100 0.001 0.002 0.003 soma.ica( 0.5 ) mA/cm2 ms

ica_pmp = 2*FARADAY*(f_flux − b_flux) COMPARTMENT 1 {pump capump}: area is dimensionless COMPARTMENT 1(m) {cao cabulk} ~ cabulk <−> cai (1/tau, 1/tau) ~ cai + pump <−> capump (k1, k2) ~ capump <−> cao + pump (k3, k4) ~ cai << −(ica) : there is a problem here COMPARTMENT width {cai} : volume has dimensions of (um)

slide-14
SLIDE 14

NMODL

KINETIC pmp { } Pump M e m b r a n e a d j a c e n t Bulk [Ca] ica

20 40 60 80 100 0.02 0.04 0.06 0.08 0.1 soma.cai( 0.5 ) 65 73 0.005 mM ms 20 40 60 80 100 0.001 0.002 0.003 soma.ica( 0.5 ) mA/cm2 ms

ica_pmp = 2*FARADAY*(f_flux − b_flux) COMPARTMENT 1 {pump capump}: area is dimensionless COMPARTMENT 1(m) {cao cabulk} ~ cabulk <−> cai (1/tau, 1/tau) ~ cai + pump <−> capump (k1, k2) ~ capump <−> cao + pump (k3, k4) ~ cai << −(ica) : there is a problem here COMPARTMENT width {cai} : volume has dimensions of (um)

slide-15
SLIDE 15

from neuron import nonvint_block_supervisor as nbs callables = [ setup, initialize, current, conductance, fixed_step_solve, count, reinit, fun, msolve, jacobian, abs_tolerance ] nbs.register(callables)

slide-16
SLIDE 16

from neuron import nonvint_block_supervisor as nbs callables = [ setup, initialize, current, conductance, fixed_step_solve, count, reinit, fun, msolve, jacobian, abs_tolerance ] nbs.register(callables) class ExtraEquations(): def __init__(self): self.callables = [...] nbs.register(self.callables) ... def __del__(self): nbs.unregister(self.callables) ...

slide-17
SLIDE 17

from neuron import nonvint_block_supervisor as nbs callables = [ setup, initialize, current, conductance, fixed_step_solve, count, reinit, fun, msolve, jacobian, abs_tolerance ] nbs.register(callables)

Contribution to current balance eqns

slide-18
SLIDE 18

from neuron import nonvint_block_supervisor as nbs callables = [ setup, initialize, current, conductance, fixed_step_solve, count, reinit, fun, msolve, jacobian, abs_tolerance ] nbs.register(callables)

y(t) −> y(t + dt)

slide-19
SLIDE 19

from neuron import nonvint_block_supervisor as nbs callables = [ setup, initialize, current, conductance, fixed_step_solve, count, reinit, fun, msolve, jacobian, abs_tolerance ] nbs.register(callables)

Additional equations for CVODE

slide-20
SLIDE 20

def current(self, rhs): self.pv.gather(self.hv) n = self.n self.g = self.gkbar*n*n*n*n i = self.g*(self.v + 77.) rhs[self.nodeindices] −= i def conductance(self, d): d[self.nodeindices] += self.g

Add conductance to matrix diagonal numpy array. Contribution to current balance eqns. Subtract current from rhs numpy array.

slide-21
SLIDE 21

def current(self, rhs): self.pv.gather(self.hv) n = self.n self.g = self.gkbar*n*n*n*n i = self.g*(self.v + 77.) rhs[self.nodeindices] −= i def conductance(self, d): d[self.nodeindices] += self.g

Contribution to current balance eqns. Copy seg.node_index() during setup.

slide-22
SLIDE 22

def current(self, rhs): self.pv.gather(self.hv) n = self.n self.g = self.gkbar*n*n*n*n i = self.g*(self.v + 77.) rhs[self.nodeindices] −= i def conductance(self, d): d[self.nodeindices] += self.g

Contribution to current balance eqns. Voltage needed ... ... to compute current

slide-23
SLIDE 23

def current(self, rhs): self.pv.gather(self.hv) n = self.n self.g = self.gkbar*n*n*n*n i = self.g*(self.v + 77.) rhs[self.nodeindices] −= i def conductance(self, d): d[self.nodeindices] += self.g

Contribution to current balance eqns. Instance gating states... ... needed for current as well

slide-24
SLIDE 24

def count(self, offset): self.offset = offset return len(self.v) def fun(self, t, y, ydot): last = self.offset + len(self.n) self.pv.gather(self.hv) self.n = y[self.offset:last] if ydot == None: return ninf, nrate = self.ninftau(self.v) ydot[self.offset:last] = (ninf − self.n)*nrate last = self.offset + len(self.n) self.pv.gather(self.hv) x,nrate = self.ninftau(self.v) def msolve(self, dt, t, b, y): b[self.offset:last] /= 1. + dt*nrate

Where our portion of the CVODE state vector begins. CVODE interface

slide-25
SLIDE 25

def count(self, offset): self.offset = offset return len(self.v) def fun(self, t, y, ydot): last = self.offset + len(self.n) self.pv.gather(self.hv) if ydot == None: return ninf, nrate = self.ninftau(self.v) ydot[self.offset:last] = (ninf − self.n)*nrate last = self.offset + len(self.n) self.pv.gather(self.hv) x,nrate = self.ninftau(self.v) def msolve(self, dt, t, b, y): b[self.offset:last] /= 1. + dt*nrate

CVODE interface

self.n = y[self.offset:last]

y’, y are numpy arrays Our portion of y’ = f(y, t) Our portion of y

slide-26
SLIDE 26

def count(self, offset): self.offset = offset return len(self.v) def fun(self, t, y, ydot): last = self.offset + len(self.n) self.pv.gather(self.hv) if ydot == None: return ninf, nrate = self.ninftau(self.v) ydot[self.offset:last] = (ninf − self.n)*nrate last = self.offset + len(self.n) self.pv.gather(self.hv) x,nrate = self.ninftau(self.v) def msolve(self, dt, t, b, y): b[self.offset:last] /= 1. + dt*nrate

CVODE interface

self.n = y[self.offset:last]

Solve M*x = b x−>b y is rarely used M is implicitly 1 + dt/ntau(v)