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. [...]"
References:
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]
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
vis
bulbdef.py
bulbdict.py
bulbgui.py
bulbvis.py
cellreader.py
cellwriter.py
cfg27.py
dummysyns.txt
Eta.txt *
firing.py
geodist.py
geodist.txt
ggid2type.txt
gidfunc.py
glomdist.py
granules.py
granules.txt
graphmeat.py
growdef.py *
ipsc.py
ispkdata.py
Kod.txt *
misc.py
Nod.txt *
odors.py
odstim2.txt *
pad.txt *
realgloms.txt *
spikes.py
spikesreader.py
spk2gd.py
spk2weight.py
spkgraph.py
winflag.txt
                            
import numpy as np
import bulbdef


# compress data eliminate consecutive repetition
def compress(t, colorindex):
  data = [ (t[0], int(colorindex[0])) ]
  data += [ (t[i], int(colorindex[i])) for i in range(1, len(t)) if colorindex[i] != colorindex[i-1] ]
  return data


# binary search for data
def specialBinarySearch(data, t):
  i = 0
  j = len(data)-1
  
  k = (i+j)/2
  while i <= j:
    if data[k][0] > t:
      j = k - 1
    elif data[k][0] < t:
      i = k + 1
    else:
      break
    k = (i+j)/2

  # k is the closest to t
  # if t[k] <= t, it is ok
  # otherwise shift left if you can
  if data[k][0] > t and k > 0:
    k -= 1
    
  return k
  
class iSceneObjectStory:

  
  def __init__(self, obj, spkr, dt=25.0, MinFR=0, MaxFR=200.0, MinW=0, MaxW=1):
    self.obj = obj

    

    def retrieve(func, gid, Tvals, tstop):
      try:
        t, y = func(gid)
      except KeyError:
        t = [0]
        y = [0]
      t.append(tstop)
      y.append(y[-1])
      return np.interp(Tvals, t, y)

    

    def normalize(y, miny, maxy):
      y = np.divide(np.subtract(y, miny), maxy - miny)
      y = np.floor(np.multiply(y, len(self.obj.palette)))
      y[np.where(y < 0)] = 0
      y[np.where(y > (len(self.obj.palette)-1))] = len(self.obj.palette)-1
      return y
      


    from bulbvis import GC, Segment, Soma
    # time to visualize
    Tvals = np.linspace(0, spkr.tstop, int(spkr.tstop/dt)+1)
    
    if len(self.obj.gids) == 0:
      self.Wexc_data = [ (0, 0) ]
      self.Winh_data = [ (0, 0) ]
      self.FRdata = [ (0, 0) ]
    elif isinstance(self.obj, Soma):
      self.Wexc_data = [ (0, 0) ]
      self.Winh_data = [ (0, 0) ]
      #print normalize(retrieve(spkr.frequency, self.obj.gids[0], Tvals, spkr.tstop),MinFR, MaxFR)
      self.FRdata = compress(Tvals,
                             normalize(retrieve(spkr.frequency, self.obj.gids[0], Tvals, spkr.tstop), \
                             MinFR, MaxFR))
    else:
      # interpolated weight
      Wexc_interp = []
      Winh_interp = []
      
      # interpolated frequencies
      FRinterp = []        
        
      # gather all data
      for gid in self.obj.gids:
        # don't show weights for somas
        if bulbdef.gid_is_mitral(gid) or \
            bulbdef.gid_is_mtufted(gid) or \
            bulbdef.gid_is_granule(gid):
          continue

        # FR interp
        FRinterp.append(retrieve(spkr.frequency, gid, Tvals, spkr.tstop))
        # excitatory
        Wexc_interp.append(retrieve(spkr.weight, gid, Tvals, spkr.tstop))

        # if it is granule do not visualize WExc inverted
        if isinstance(self.obj, GC):
          Winh_interp.append(Wexc_interp[-1])
        else:
          Winh_interp.append(retrieve(spkr.weight, gid-1, Tvals, spkr.tstop))



      # get max for granule cell
      # avg for mitral cell segment
      if isinstance(self.obj, GC):
        Wexc_interp = np.matrix(Wexc_interp).max(0)
        Winh_interp = np.matrix(Winh_interp).max(0)
      else:
        Wexc_interp = np.matrix(Wexc_interp).mean(0)
        Winh_interp = np.matrix(Winh_interp).mean(0)

      # clean
      Wexc_interp = np.array(Wexc_interp)[0]
      Winh_interp = np.array(Winh_interp)[0]
      FRinterp = np.array(np.matrix(FRinterp).mean(0))[0]
      
      # normalizations
      Wexc_interp = normalize(Wexc_interp, MinW, MaxW)
      Winh_interp = normalize(Winh_interp, MinW, MaxW)
      FRinterp = normalize(FRinterp, MinFR, MaxFR)

      # compress
      self.Wexc_data = compress(Tvals, Wexc_interp)
      self.Winh_data = compress(Tvals, Winh_interp)
      self.FRdata = compress(Tvals, FRinterp)


  

  def __set_data_color(self, data, t):
    k = specialBinarySearch(data, t)
    ci = data[k][1]
    self.obj.datacolor = self.obj.palette[ci]
    self.obj.actor.property.color = self.obj.datacolor
    

  def weight(self, excit, t):
    if excit:
      self.__set_data_color(self.Wexc_data, t)
    else:
      self.__set_data_color(self.Winh_data, t)
    

  def firing(self, t):
    self.__set_data_color(self.FRdata, t)
  



class iBulb:
  def __init__(self, bulb, spkr, dt=25.0, MinFR=0, MaxFR=200.0, MinW=0, MaxW=1):
    self.gc = [ iSceneObjectStory(o, spkr, dt, MinFR, MaxFR, MinW, MaxW) for o in bulb.gc.objs ]
    
    from bulbvis import Segment, Soma    
    self.cell = [ ]
    for c in bulb.cell.values():
      self.cell.append([])
      
      index_soma = 0
      index_apic = []

      for o in c.objs:
        self.cell[-1].append(iSceneObjectStory(o, spkr, dt, MinFR, MaxFR, MinW, MaxW))
        if isinstance(o, Soma):
          index_soma = len(self.cell[-1])-1
        elif isinstance(o, Segment) and len(o.gids) == 0:
          index_apic.append(len(self.cell[-1])-1)

      for i in index_apic:
        self.cell[-1][i].Wexc_data = self.cell[-1][index_soma].Wexc_data
        self.cell[-1][i].Winh_data = self.cell[-1][index_soma].Winh_data
        self.cell[-1][i].FRdata = self.cell[-1][index_soma].FRdata
        

  def weight(self, excit, t):
    for objs in [self.gc]+self.cell:
      for o in objs:
        o.weight(excit, t)

  def firing(self, t):
    for objs in [self.gc]+self.cell:
      for o in objs:
        o.firing(t)
          
    
if __name__ == '__main__':
  t = 50
  x = [ (0, 1), (25, 2), (90, 1) ]
  k = specialBinarySearch(x, t)
  print x, t, k

Loading data, please wait...