# -*- 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