'''
OdorStim supplies an odors[name] stimulus to each mitral tuft dendrite
defined by odors[name].glom_weights. Thus there is a separate NetCon for
each tuft dendrite on this process.
'''
from common import *
from gidfunc import *
import fileinput
import params
from odors import odors
class OdorStim():
def __init__(self, od, start, dur, rel_conc=1.):
''' Specifies the odor for an OdorStim. Note that the OdorStim is
activated with setup which can only be called after the mitrals
dict exists (usually from determine_connections.py).
'''
# set odor weights
if type(od) == str:
self.odor = odors[od]
else:
self.odor = od
self.rel_conc = rel_conc
#self.setup(start)
self.verbose = True
#self.rngsniff = True
#self.nxt_invl = 800.
self.tstop = start + dur
#def setup(self, mitrals, start, stop):
#def setup(self, start):
mitrals = getmodel().mitrals
self.netcons = {}
self.rng_act = params.ranstream(0, params.stream_ods_act)
self.rng_act.uniform(params.ods_freql, params.ods_freqh)
for gid in mitrals:
m = mitrals[gid]
# in case of multisplit
if not h.section_exists("tuftden", 0, m):
continue
iglom = mgid2glom(gid)
w = self.odor.glom_weights[iglom]
for i in range(int(m.synls.count())):
nc = h.NetCon(None, m.synls.o(i))
# rng for weights
rw = params.ranstream(gid, params.stream_ods_w + i)
nc.weight[0] = w * self.rel_conc * rw.uniform(params.ods_wl, params.ods_wh)
self.netcons.update({(gid, i):(nc, rw)})
self.fih = h.FInitializeHandler(0, (self.init_ev, (start,)))
def init_ev(self, start):
''' first event at start.
In principle this can be called by the user during a simulation
but if h.t < the previous stop, the randomness will be mixed
between the multiple (start,stop) intervals.
'''
if params.sniff_invl == None:
self.nxt_invl = self.rng_act.repick()
start += self.nxt_invl
else:
self.nxt_invl = params.sniff_invl
h.cvode.event(start, (self.ev, (start,)))
#def ev(self, time, interval, stop):
def ev(self, time):
''' time is the standard time with no randomness.
h.t may be before or after and each syapse will receive its event
at h.t + individual netcon delay
'''
# update weights
for key in self.netcons:
iglom = mgid2glom(key[0])
w = self.odor.glom_weights[iglom]
nc, rw = self.netcons[key]
nc.weight[0] = w * self.rel_conc * rw.repick()
nc.delay = 0.
# call event queue
nc.event(h.t)
# fix next activations
if params.sniff_invl == None:
self.nxt_invl = 1000. / self.rng_act.repick()
if time + self.nxt_invl < self.tstop:
if rank == 0 and self.verbose: print 'activation of %s at %.3g (ms)\tinterval %.3g' % (self.odor.name, h.t, self.nxt_invl)
h.cvode.event(time + self.nxt_invl, (self.ev, (time + self.nxt_invl,)))
class BGNoise(OdorStim):
# repick weights
def rndweights(self):
w=[0.]*params.Ngloms
for i in range(params.Ngloms):
w[i]=self.rw.repick()
while w[i]<0 or w[i]>1:
w[i]=self.rw.repick()
return w
def __init__(self,start,dur,wmu=0.5,wvar=0.0025):
# dummy odor
OdorStim.__init__(self,'Apple',start,dur)
self.verbose=False
# weights on glomerulus
self.rw=params.ranstream(0,params.stream_ods_bg)
self.rw.normal(wmu,wvar)
from odors import odor
self.odor=odor(-1,'noise',self.rndweights())
self.rel_conc=4e-3
def ev(self,start):
self.odor.glom_weights=self.rndweights()
OdorStim.ev(self,start)
# create odorseq
def OdorSequence(seq):
odseq = []
if type(seq) == str:
for i, line in enumerate(fileinput.input(seq)):
tk = line.split()
if len(tk) < 4 and rank == 0:
print 'line %i of %s was ignored' % (i, seq)
continue
name = tk[0]
init = float(tk[1])
dur = float(tk[2])
conc = float(tk[3])
odseq.append(OdorStim(name, init, dur, conc))
elif type(seq) == list:
for odinfo in seq:
odseq.append(OdorStim(*odinfo))
return odseq
if __name__ == '__main__':
h.load_file("nrngui.hoc")
import common
common.nmitral = 2
common.ncell = 10
import determine_connections
import odors
ods = OdorStim(odors.odors['Apple'])
ods.setup(determine_connections.mitrals, 10., 20., 100.)
h.tstop = 150
h.run()
print 't=', h.t