Parallel odor processing by mitral and middle tufted cells in the OB (Cavarretta et al 2016, 2018)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:240116
"[...] experimental findings suggest that MC and mTC may encode parallel and complementary odor representations. We have analyzed the functional roles of these pathways by using a morphologically and physiologically realistic three-dimensional model to explore the MC and mTC microcircuits in the glomerular layer and deeper plexiform layers. [...]"
Reference:
1 . Cavarretta F, Burton SD, Igarashi KM, Shepherd GM, Hines ML, Migliore M (2018) Parallel odor processing by mitral and middle tufted cells in the olfactory bulb. Sci Rep 8:7625 [PubMed]
2 . Cavarretta F, Marasco A, Hines ML, Shepherd GM, Migliore M (2016) Glomerular and Mitral-Granule Cell Microcircuits Coordinate Temporal and Spatial Information Processing in the Olfactory Bulb. Front Comput Neurosci 10:67 [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: Olfactory bulb;
Cell Type(s): Olfactory bulb main tufted middle GLU cell; Olfactory bulb main interneuron granule MC GABA cell; Olfactory bulb main interneuron granule TC GABA cell; Olfactory bulb (accessory) mitral cell; Olfactory bulb main tufted cell external; Olfactory bulb short axon cell;
Channel(s): I A; I Na,t; I_Ks; I K;
Gap Junctions: Gap junctions;
Receptor(s): AMPA; GabaA; NMDA;
Gene(s):
Transmitter(s): Glutamate; Gaba;
Simulation Environment: NEURON;
Model Concept(s): Action Potentials; Action Potential Initiation; Active Dendrites; Long-term Synaptic Plasticity; Synaptic Integration; Synchronization; Pattern Recognition; Spatio-temporal Activity Patterns; Temporal Pattern Generation; Sensory coding; Sensory processing; Olfaction;
Implementer(s): Cavarretta, Francesco [francescocavarretta at hotmail.it]; Hines, Michael [Michael.Hines at Yale.edu];
Search NeuronDB for information about:  Olfactory bulb main interneuron granule MC GABA cell; Olfactory bulb main tufted middle GLU cell; Olfactory bulb main interneuron granule TC GABA cell; GabaA; AMPA; NMDA; I Na,t; I A; I K; I_Ks; Gaba; Glutamate;
/
modeldb-bulb3d
sim
ampanmda.mod
distrt.mod *
fi.mod
fi_stdp.mod *
gap.mod
Gfluct.mod
kamt.mod
kdrmt.mod
ks.mod
naxn.mod
orn.mod
ThreshDetect.mod *
all.py
all2all.py *
assembly.py
balance.py *
bindict.py
binsave.py
binspikes.py
blanes.hoc
blanes.py
blanes_exc_conn.txt
blanes6.dic
bulb3dtest.py
cancel.py
catfiles.sh
cellreader.py
cellwriter.py
cfg27.py
common.py
complexity.py *
convertdic.py
destroy_model.py
determine_connections.py
distribute.py *
dsac.py
Eta.txt *
fillgloms.py
fixnseg.hoc *
g_conn_stats.py
gapjunc.py
gen_weights.py
geodist.py
geodist.txt
getmitral.py
gidfunc.py
GJ.py
gj_nrn.hoc
Glom.py *
granule.hoc
granules.py
graphmeat.py
grow.py
growdef.py *
growout.py
job
Kod.txt *
lateral_connections.py
loadbalutil.py *
lpt.py *
mcgrow.py
MCrealSoma.py *
mgrs.py
misc.py
mitral.hoc
mkassembly.py
mkmitral.py
modeldata.py
mtgrow.py
MTrealSoma.py
MTrealSoma2.py
mtufted.hoc
multisplit_distrib.py
net_mitral_centric.py
Nod.txt *
odors.py
odorstim.py
odstim2.txt *
pad.txt *
params.py
parrun.py
pathdist.py
realgloms.txt *
runsim.py
spike2file.hoc *
spk2weight.py
split.py
subsetsim.py
test_complexity.py
txt2bin.py
util.py *
vrecord.py
weightsave.py
                            
'''
mitral-granule reciprocal synapse

patterned after mgrs.hoc of the bulb3test model but allow any number of
secondary dendrite processes (indexed by mitral.secden[i]).  Ie a
connection is defined (in python) by the 6 tuple (mitral_gid,
secden_index, x, granule_gid, priden_index, x). Connection algorithms
allow more than one mgrs with the same mitral and granule.
Therefore, when the function map from (mgid, ggid) to synapse_gid is used,
it may be necessary to do futher disambiguation.
'''

from common import *
from gidfunc import mgrs_gid, ismitral, ismtufted
from params import gid_mgrs_begin

import split
nmitral = params.Nmitral
ngranule = params.Ngranule
ngloms = params.Ngloms
nmxg = params.Nmitral_per_glom

from lateral_connections import gc_is_superficial as gcissup

from dsac import *



class MGRS:
  '''From a mitral and granule synapse location, and consistent with what
     exists on this process, construct the 5 parts of the reciprocal synapse.
     If the granule location exists, then a spine, ThreshDetect, and
     AmpaNmda synapse will be created. If the mitral location exists, then
     a ThreshDetect and FastInhib synapse will be created. The appropriate gid
     for the ThreshDetect instances will be registered. And the appropriate
     NetCons will connect to the synapses.
  '''
  '''
     To allow use of the FastInhibSTDP synapse on the Mitral side of the
     MGRS, there is an additional part which is a negative weight netcon
     connecting from the mitral side ThreshDetect to the FastInhibSTDP
     instance which provides the post synaptic spike timing information.
     There are major administrative differences due to the weight vector
     differences between FastInhib and FastInhibSTDP.
  '''

  def __init__(self, mgid, isec, xm, ggid, ipri, xg, slot):
    self.mgid = mgid
    self.ggid = ggid
    self.slot = slot
    self.xm = xm
    self.xg = xg
    self.isec = isec
    self.ipri = ipri
    
    self.msecden = split.msecden(mgid, isec)
    self.gpriden = split.gpriden(ggid, ipri)
    self.md_gid = mgrs_gid(mgid, ggid)
    self.gd_gid = mgrs_gid(ggid, mgid)
    self.md = None #ThreshDetect on mitral
    self.gd = None #ThreshDetect on granule
    if params.use_fi_stdp:
      self.fi = None #FastInhibSTDP on mitral
      self.postspike2fi = None # negative weight NetCon from md to fi
    else:
      self.fi = None #FastInhib on mitral
    self.ampanmda = None #AmpaNmda on granule
    self.gd2fi = None #NetCon to fi
    self.md2ampanmda = None #NetCon to ampanmda

    if pc.gid_exists(self.md_gid) > 0. or pc.gid_exists(self.gd_gid) > 0.:
      print "md_gid=%d and/or gd_gid=%d already registered" % (self.md_gid, self.gd_gid)
      raise RuntimeError

    if self.msecden:
      self.md = h.ThreshDetect(self.msecden(xm))
      if params.use_fi_stdp:
        self.fi = h.FastInhibSTDP(self.msecden(xm))
        nc = h.NetCon(self.md, self.fi)
        self.postspike2fi = nc
        nc.weight[0] = -1
        nc.delay = 1

      else:
        self.fi = h.FastInhib(self.msecden(xm))
        try:
          if params.training_inh:
            self.fi.training = 1
          else:
            self.fi.training = 0
        except:
#          print 'error'
          self.fi.training = 1
          
      if ismitral(mgid):
        self.fi.gmax = params.mc_inh_gmax
        self.fi.tau1 = params.mc_fi_tau1
        self.fi.tau2 = params.mc_fi_tau2
      elif ismtufted(mgid):
        self.fi.gmax = params.mt_inh_gmax
        self.fi.tau1 = params.mt_fi_tau1
        self.fi.tau2 = params.mt_fi_tau2

      pc.set_gid2node(self.md_gid, pc.id())
      pc.cell(self.md_gid, h.NetCon(self.md, None), 1)

    if self.gpriden:
      self.spine = h.GranuleSpine()
      if gcissup(self.ggid):
        self.spine.sup_deep_flag(1)
      else:
        self.spine.sup_deep_flag(0)

      self.spine.neck.connect(self.gpriden(xg))
      
      #self.dsac = dSAC(self.ggid, self.spine)
      
      self.gd = h.ThreshDetect(self.spine.head(0.5))
      self.gd.vthresh = -50
      self.ampanmda = h.AmpaNmda(self.spine.head(0.5))
      if ismitral(mgid):
        self.ampanmda.gmax = params.mc_exc_gmax
      elif ismtufted(mgid):
        self.ampanmda.gmax = params.mt_exc_gmax
      try:
        if params.training_exc:
          self.ampanmda.training = 1
        else:
          self.ampanmda.training = 0
      except:
#        print 'error'
        self.ampanmda.training = 1

      pc.set_gid2node(self.gd_gid, pc.id())
      pc.cell(self.gd_gid, h.NetCon(self.gd, None), 1)

    # Cannot be done above because output ports must exist prior to using 
    # an output gid as an input port on the same process.
    if self.fi:
      self.gd2fi = pc.gid_connect(self.gd_gid, self.fi)
      if params.use_fi_stdp:
        self.gd2fi.weight[0] = 1
      else:
        self.gd2fi.weight[0] = 1 # normalized
        try:
          init_inh_weight = params.init_inh_weight
        except:
          init_inh_weight = 0
        self.gd2fi.weight[1] = init_inh_weight
      self.gd2fi.delay = 1
      
    if self.ampanmda:
      self.md2ampanmda = pc.gid_connect(self.md_gid, self.ampanmda)
      self.md2ampanmda.weight[0] = 1 #normalized
      try:
        init_exc_weight = params.init_exc_weight
      except:
        init_exc_weight = 0
      self.md2ampanmda.weight[1] = init_exc_weight
      self.md2ampanmda.delay = 1

  def pr(self):
    print "%d %d <-> %d %d"%(self.mgid, self.md_gid, self.gd_gid, self.ggid)
    if self.msecden:
      print self.msecden.name(), self.md.hname(), self.fi.hname(), self.gd2fi.hname(), " ", int(self.gd2fi.srcgid())
    if self.gpriden:
      print self.gpriden.name(), self.gd.hname(), self.ampanmda.hname(), self.md2ampanmda.hname(), " ", int(self.md2ampanmda.srcgid())


  def mg_dic_str(self):
    s = ''
    if self.gd2fi:
      s += '%d %d %d %g %d\n' % (self.gd_gid, self.ggid, self.ipri, self.xg, self.slot)
    if self.md2ampanmda:
      s += '%d %d %d %g %d\n' % (self.md_gid, self.mgid, self.isec, self.xm, self.slot)
    return s

  def wstr(self):
    ''' return string in proper wsfile format '''
    s = ''
    if self.gd2fi:
      s += '%d %g %g\n'%(self.gd_gid, self.sm(), self.wm())
    if self.md2ampanmda:
      s += '%d %g %g\n'%(self.md_gid, self.sg(), self.wg())
    return s

  def sm(self):
    if params.use_fi_stdp:
      return self.fi.wsyn
    else:
      return self.gd2fi.weight[1]
  def sg(self):
    return self.md2ampanmda.weight[1]
  def wm(self):
    if params.use_fi_stdp:
      return self.fi.wsyn * self.fi.gmax
    else:
      return self.gd2fi.weight[2] * self.fi.gmax
  def wg(self):
    return self.md2ampanmda.weight[2] * self.ampanmda.gmax

def mk_mgrs(mgid, isec, xm, ggid, ipri, xg, slot):
  ''' Return MGRS instance if at least on half exists, otherwise None.'''
  if split.msecden(mgid, isec) or split.gpriden(ggid, ipri):
    return MGRS(mgid, isec, xm, ggid, ipri, xg, slot)
  return None
    
def multiple_cnt():
  cnt = 0;
  for mgrs in getmodel().mgrss.values():
    if mgrs.slot > 0:
      if mgrs.gd: cnt += 1
      if mgrs.md: cnt += 1
  return cnt

if __name__ == "__main__":
  import mkmitral, split
  h.load_file("granule.hoc")

  m = mkmitral.mkmitral(1)
  pieces = split.secden_indices_connected_to_soma(m)
  pieces.append(-1)
  split.splitmitral(1, m, pieces)
  pc.set_gid2node(1, pc.id())
  pc.cell(1, h.NetCon(m.soma(.5)._ref_v, None, sec=m.soma))

  g = h.Granule()
  pc.set_gid2node(10000, pc.id())
  pc.cell(10000, h.NetCon(g.soma(.5)._ref_v, None, sec=g.soma))

  mgrs = MGRS(1, 0, .8, 10000, 0, .1)
  mgrs.pr()
  mgrs2 = MGRS(1, 0, .8, 10000, 0, .1)