Synchrony by synapse location (McTavish et al. 2012)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:144054
This model considers synchrony between mitral cells induced via shared granule cell interneurons while taking into account the spatial constraints of the system. In particular, since inhibitory inputs decay passively along the lateral dendrites, this model demonstrates that an optimal arrangement of the inhibitory synapses will be near the cell bodies of the relevant mitral cells.
Reference:
1 . McTavish TS, Migliore M, Shepherd GM, Hines ML (2012) Mitral cell spike synchrony modulated by dendrodendritic synapse location. Front Comput Neurosci 6:3 [PubMed]
Citations  Citation Browser
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network; Neuron or other electrically excitable cell;
Brain Region(s)/Organism: Olfactory bulb;
Cell Type(s): Olfactory bulb main mitral GLU cell; Olfactory bulb main interneuron granule MC GABA cell;
Channel(s): I Na,t; I A; I K;
Gap Junctions:
Receptor(s): GabaB; AMPA; NMDA;
Gene(s):
Transmitter(s):
Simulation Environment: NEURON;
Model Concept(s): Synchronization; Olfaction;
Implementer(s): McTavish, Thomas S [thomas.mctavish at yale.edu];
Search NeuronDB for information about:  Olfactory bulb main mitral GLU cell; Olfactory bulb main interneuron granule MC GABA cell; GabaB; AMPA; NMDA; I Na,t; I A; I K;
/
mctavish_syncbylocation
src
ampanmda.mod
fi.mod
kamt.mod
kdrmt.mod
naxn.mod
ThreshDetect.mod *
allsynhinton.hoc *
analysis.py
animtest.py
antest.ses *
bulbspikes.py
clear.hoc
connect.hoc
control.ses
default.hoc
granule.hoc *
hinton.hoc
init.hoc *
iterator.hoc *
lptiter.hoc
mgrs.hoc
michele_movie.hoc
mitral.hoc
mosinit.hoc
net.hoc
param.hoc
params.py
parinit.hoc
pattern.hoc
perfrun.hoc
show.hoc
showw.hoc
somesyn.hoc *
sortspike *
split.hoc
start.hoc
start.ses
stimodors.hoc
subset.hoc
subset_control.ses *
synweightsnapshot.py
viewspikes.hoc
viewspikes1.hoc
weight_movie.hoc
weightsave.hoc
                            
# -*- coding: utf-8 -*-
import sys
import pylab
import numpy
import math
#from matplotlib import pyplot as plt 
from matplotlib import pylab
from matplotlib import rc # To possibly render in LaTeX
from matplotlib.backends.backend_pdf import PdfPages
from matplotlib import lines
import os

class RawLine:
    def __init__(self,src,tgt,sigidx,w):
        self.src=src
        self.tgt=tgt
        self.sigidx=sigidx
        self.w=w

class LoadError(Exception):
    def __init__(self, value='The data has not yet been loaded. Load the data file first.'):
        self.value = value
    def __str__(self):
        return repr(self.value)

class SynWeightSnapshot:
    def __init__(self, nummit=5, numgran=100):
        """Number of dendrodendritic synapses"""
        self.nsyn=0
        
        """Number of mitral cells"""
        self.nummit = nummit
        
        """Number of granule cells"""
        self.numgran = numgran
                
        """Timestamps of each snapshot"""
        self.timestamps=[]
        
        """The mitral-to-granule synaptic weights. Weights are specified in
        3D with rows being the number of mitral cells, columns being the number
        of granule cells, and the z axis is time (that is, a snapshot)."""
        self.m2g=[]
        
        """The granule-to-mitral synaptic weights. Also a 3D structure."""
        self.g2m=[]
        
        """Input data filename, without extension. (Assumes .dat extension)"""
        self.input_filename=None
        
        """Output graphic filename, without the extension."""
        self.output_filename=None
        
        self.data_path=None
        
        """File format"""
        self.file_format='pdf'
        
        """If the output file_format is 'pdf', then this object encapsulates
        multiple pages.
        """
        self.pdf=None

        self.fi_gmax = 0.003

        self.ampa_gmax = 2.
        
    def read_file(self,input_filename,data_path=None,output_filename=None):
        """Read the weight snapshot file and return as a formatted list of line
        objects to be parsed."""
        try:
            fname=''
            if data_path is not None:
                fname=data_path
            if not input_filename.endswith('.dat'):
                input_filename += '.dat'
            filepath = os.path.join(fname, input_filename)
            f=open(filepath,'r') # Open the file
            # The format of the file is such that the first line contains the
            # number of dendrodendritic synapses. The second line contains the
            # timestamp of the first snapshot. 
            # The subsequent lines are formatted as:
            # gid   ->   gid   location_on_sigmoid   value
            # Mitral -> Granule syns will be [0 nummit] in the 1st column, and
            # Granule -> Mitral syns will be [0 nummit] in the second column,
            # with the exception that there will be a timestamp as well that
            # will occur every interval.
            
            raw=[]
            for line in f:
                tosplit=line.split()
                try:
                    c1=int(tosplit[0])
                    c2=int(tosplit[1])
                    c3=int(tosplit[2])
                    c4=float(tosplit[3])
                    raw.append(RawLine(c1,c2,c3,c4))
                except IndexError:
                    # This will occur at the beginning of each snapshot file
                    if self.nsyn==0:
                        self.nsyn=c1
                    else:
                        self.timestamps.append(c1)
                        
                except ValueError:
                    # This will occur if the beginning of the snapshot has a
                    # floating point number as its timestamp.
                    c1=int(math.floor(float(tosplit[0])))
                    self.timestamps.append(c1)

            f.close()
        
        except:
            raise
        
        self.data_path=data_path
        self.input_filename=input_filename[:-4] # Remove '.dat'
        if output_filename is None:
            self.output_filename=self.input_filename+'_img'
        else:
            self.output_filename=output_filename
        return raw

    def parse_data(self,raw):
        """Build the mitral-to-granule 3D volume and the granule to mitral
        3D volume."""
        depth=int(float(len(raw))/float(self.nsyn))
        slice_size=self.nummit*self.numgran*2
        self.m2g=numpy.ndarray(shape=(self.nummit,self.numgran,depth),dtype=float)
        self.g2m=numpy.ndarray(shape=(self.nummit,self.numgran,depth),dtype=float)
        d=0
        count=0
        for r in raw:
            if r.src < self.nummit:
                self.m2g[r.src,r.tgt-self.nummit,d]=r.w
            else:
                self.g2m[r.tgt,r.src-self.nummit,d]=r.w
            count=count+1
            if count % slice_size == 0:
                d=d+1
    
    def get_full_output_path(self,slice=-1):
        fname=''
        if self.data_path is not None:
            fname=self.data_path
        
        if slice==-1 or self.file_format=='pdf':
            fname = os.path.join(fname, '%(a)s.%(c)s' % \
                    {'a':self.output_filename, 'c':self.file_format})
        else:
            fname = os.path.join(fname, '%(a)s%(b)04d.%(c)s' % \
                    {'a':self.output_filename, 'b':slice, 'c':self.file_format})
        return fname
        
    
    def plot_slice(self,slice=0,draw_colorbar=False,space_colorbar=False,cmap='OrRd',figsize=(6,1.5),dpi=144,background_color='gray'):
        # The snapshot slice number to draw, zero-indexed.
        pylab.clf()
        fig=pylab.figure(figsize=figsize) # Make a main figure object
        fig_size=fig.get_size_inches()
        aspect_ratio=float(fig_size[0])/float(fig_size[1])
        # Draw the image such that the excitatory synapses are on top
        # and the inhibitory synapses are on bottom. To do this, we add
        # self.nummit subplots, each subplot containing a subimage
        # containing the excitatory synapse in the first row and the
        # inhibitory synapses in the bottom row.
        m_size=1000 # Won't draw outside, so make it big
        subimg=numpy.zeros((2,self.numgran))
        maxm2g=numpy.max(self.m2g)
        maxg2m=numpy.max(self.g2m)
        ppp=55.    # Short for points per pixel
        tick_label_size=5+int(0.5+sum(fig_size)/aspect_ratio)
        label_font_size=7+int(1.2*sum(fig_size)/aspect_ratio)
        if draw_colorbar is True:
            space_colorbar=True
            
        for i in range(self.nummit):
            ax=fig.add_subplot(self.nummit,1,(i+1)) # Add a new subplot
            subimg[0,:]=self.m2g[i,:,slice]/maxm2g   # Get the mitral-to-granule syn weights
            subimg[1,:]=self.g2m[i,:,slice]/maxg2m   # Get the granule-to-mitral syn weights
            imgplot = ax.imshow(subimg)            # Make an image from the data
            imgplot.set_interpolation('nearest')   # Pixels are not antialiased
            imgplot.set_cmap(cmap)                # Jet colormap
            imgplot.axes.set_aspect('auto')             # Make the pixels taller than wide
            
            # Draw lines between the pixels
            X=range(-1,self.numgran)
            X=numpy.add(X,.5)
            Y=numpy.ones_like(X)*.5
            line=lines.Line2D(X,Y,color=background_color,marker='|',markeredgewidth=1.25,markersize=m_size)
            ax.add_line(line)

            if i<self.nummit-1:                   # Only draw x tick labels on the bottom row
                ax.set_xticklabels([])
            else:
                # Make x labels aligned with where the mitral cells are.
                xticks=numpy.arange(0,self.numgran,float(self.numgran)/float(self.nummit)/2.)
                xticklabels=[]
                for j in range(len(xticks)):
                    if j%2==0:
                        xticklabels.append('')
                    else:
                        xticklabels.append(str(int(round(xticks[j]))))
                ax.set_xticks(xticks)
                ax.set_xticklabels(xticklabels,size=tick_label_size)
            
            # Make 5 y tick marks such that they span correctly to draw the "E" and "I"
            ax.set_yticks(numpy.arange(-.5,2,.5))
            # When horizontally centering, the bounding box of the tick label does not move.
            # position=(-.005,0) moves the text slightly to the left.
            ytick_labels=ax.set_yticklabels(['','E','','I',''], \
            horizontalalignment='center', \
            size=tick_label_size, \
            position=(-.0005*tick_label_size,0))
            ylabel='M'+str(i+1)
            ax.set_ylabel(ylabel, rotation='horizontal', labelpad=label_font_size*.8, size=label_font_size)

            for line in ax.get_yticklines(): # Turn off the Y tickmarks
                line.set_markersize(0)

            imgplot.figure.canvas.draw()    # Command to draw, otherwise the last subimg
                                            #  will be drawn in place of all of them
        left_bound=float(2.5*label_font_size/ppp/fig_size[0])
        
        # Bottom bound will be the height of the font in figure space. 
        # Calculate with 55 points/inch
        bottom_bound=float(1.1*tick_label_size/ppp/fig_size[1])
        top_bound=1-float(1.1*label_font_size/ppp/fig_size[1])
        right_bound=.99
        cb_width=float(.8*tick_label_size/ppp/fig_size[0])
        cb_pad=5./ppp/fig_size[0]
        if space_colorbar is True:
            right_bound-=(cb_width+cb_pad+cb_width)
        fig.subplots_adjust(top=top_bound,bottom=bottom_bound,left=left_bound,right=right_bound)
        
        if draw_colorbar is True:
            cax=fig.add_axes([right_bound+cb_pad,bottom_bound,cb_width,top_bound-bottom_bound])
            a=numpy.outer(numpy.arange(0,1.01,0.01),numpy.ones(1))
            cax.imshow(a,aspect='auto',cmap=cmap,origin="lower")
            yticks=cax.get_ylim()
            cax.set_yticks(yticks)
            # Set position=(2.4,0) because trying to set the position to
            # "right" does not change the font size.
            cax.set_yticklabels(['0','1'],size=tick_label_size,position=(2.4,0))
            cax.set_xticklabels([])
            for line in cax.get_xticklines(): # Turn off the X tickmarks
                line.set_markersize(0)

        titlestr='$t='+str(self.timestamps[slice])+'$' # Make a LaTeX string
        fig.suptitle(titlestr,size=label_font_size)
        fname=self.get_full_output_path(slice)
        #print fname

        if self.file_format=='pdf':
            if self.pdf==None:
                self.pdf=PdfPages(fname)
            fig.savefig(self.pdf, format='pdf', dpi=dpi)
        else:
            fig.savefig(fname,dpi=dpi) 
        pylab.close()
            
    def plot_slices(self,r=[],file_format='pdf',draw_colorbar=False,space_colorbar=False,cmap='OrRd',figsize=(6,1.5),dpi=144,background_color='gray'):
        if len(self.m2g)==0:
            raise LoadError()
        self.file_format=file_format
        self.pdf=None # Let plot_slice() set, if necessary.
        if type(r) is not list:
            r=range(r,r+1) # Assume int, but sage may make it's own integer type.
        if len(r)==0:
            r=range(self.m2g.shape[-1]) # Last parameter of the m2g shape array is the depth
        for i in r:
            self.plot_slice(i,draw_colorbar,space_colorbar,cmap,figsize,dpi,background_color)
            if i%10==0:
                print 'slice '+str(i)
        if self.file_format=='pdf':
            if self.pdf is not None:
                self.pdf.close()
        
        # If using SAGE, the files were probably saved to the DATA folder. 
        # Provide a link in the worksheet to the first and last snapshots for
        # visual output.
        if self.data_path is not None:
            fname=self.get_full_output_path(r[-1])            
            #os.symlink(fname,self.output_filename+'.'+self.file_format)
            #refstr='<a href=\"%(a)s\">%(b)s</a>' % \
            #{'a':fname, 'b':self.output_filename+'.'+self.file_format}
            #html(refstr)
        
sws=SynWeightSnapshot()

def load_file(input_filename,data_path=None,output_filename=None):
    global sws
    raw=sws.read_file(input_filename,data_path,output_filename)
    sws.parse_data(raw)
    
def plot_slices(r=[],file_format='pdf',draw_colorbar=False,space_colorbar=False,cmap='OrRd',figsize=(6,1.5),dpi=144,background_color='gray'):
    global sws
    sws.plot_slices(r,file_format,draw_colorbar,space_colorbar,cmap,figsize,dpi,background_color)