3D olfactory bulb: operators (Migliore et al, 2015)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:168591
"... Using a 3D model of mitral and granule cell interactions supported by experimental findings, combined with a matrix-based representation of glomerular operations, we identify the mechanisms for forming one or more glomerular units in response to a given odor, how and to what extent the glomerular units interfere or interact with each other during learning, their computational role within the olfactory bulb microcircuit, and how their actions can be formalized into a theoretical framework in which the olfactory bulb can be considered to contain "odor operators" unique to each individual. ..."
Reference:
1 . Migliore M, Cavarretta F, Marasco A, Tulumello E, Hines ML, Shepherd GM (2015) Synaptic clusters function as odor operators in the olfactory bulb. Proc Natl Acad Sci U S A 112:8499-504 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network;
Brain Region(s)/Organism:
Cell Type(s): Olfactory bulb main mitral cell; Olfactory bulb main interneuron granule MC cell;
Channel(s): I Na,t; I A; I K;
Gap Junctions:
Receptor(s): AMPA; NMDA; Gaba;
Gene(s):
Transmitter(s): Gaba; Glutamate;
Simulation Environment: NEURON; Python;
Model Concept(s): Activity Patterns; Dendritic Action Potentials; Active Dendrites; Synaptic Plasticity; Action Potentials; Synaptic Integration; Unsupervised Learning; Sensory processing; Olfaction;
Implementer(s): Migliore, Michele [Michele.Migliore at Yale.edu]; Cavarretta, Francesco [francescocavarretta at hotmail.it];
Search NeuronDB for information about:  Olfactory bulb main mitral cell; Olfactory bulb main interneuron granule MC cell; AMPA; NMDA; Gaba; I Na,t; I A; I K; Gaba; Glutamate;
/
figure1eBulb3D
readme.html
ampanmda.mod *
distrt.mod *
fi.mod *
fi_stdp.mod *
kamt.mod *
kdrmt.mod *
naxn.mod *
ThreshDetect.mod *
.hg_archival.txt
all2all.py *
balance.py *
bindict.py
binsave.py
binspikes.py
BulbSurf.py
catfiles.sh
colors.py *
common.py
complexity.py *
custom_params.py *
customsim.py
destroy_model.py *
determine_connections.py
distribute.py *
falsegloms.txt
fixnseg.hoc *
g37e1i002.py
gidfunc.py *
Glom.py *
granule.hoc *
granules.py
grow.py
input-odors.txt *
loadbalutil.py *
lpt.py *
m2g_connections.py
mayasyn.py
mgrs.py
misc.py
mitral.hoc *
mkdict.py
mkmitral.py
modeldata.py *
multisplit_distrib.py *
net_mitral_centric.py
odordisp.py *
odors.py *
odorstim.py
params.py
parrun.py
realgloms.txt *
realSoma.py *
runsim.py
spike2file.hoc *
split.py *
util.py *
vrecord.py
weightsave.py *
                            
'''
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