Saturday, August 16, 2014

GSoC Open Source Brain: Arbitrary Spike-trains in PyNN

Arbitrary Spikes in PyNN

Arbitrary Spike-trains in PyNN

In this example we are going to create a population of cells with arbitrary spike trains. We will load the spike train from a file where they are stored as a list of arrays with the times at which they occurred. In order to so we are going to use the SpikeSourceArray class model of PyNN

First we start importing PyNN in with nest and all the other required libraries. Furthermore we start the simulators and given some general parameters. We assume that we already have produced spikes for the cells with 0.50 contrast:

      import numpy as np
      import matplotlib.pyplot as plt
      import cPickle
      import pyNN.nest as simulator

      contrast = 0.50
      Nside_lgn = 30
      Ncell_lgn = Nside_lgn * Nside_lgn
      N_lgn_layers = 4
      t = 1000  # ms

      simulator.setup(timestep=0.1, min_delay=0.1, max_delay=5.0)
    

So we are going to suppose that we have our data stored in './data'. The spike-trains are lists as long as the cell population that contain for each element an array with the times at which the spikes occurred for that particular neuron. In order to load them we will use the following code

      directory = './data/'
      format = '.cpickle'

      spikes_on = []
      spikes_off = []

      for layer in xrange(N_lgn_layers):

      #  Layer 1
      layer = '_layer' + str(layer)

      polarity = '_on'
      contrast_mark = str(contrast)
      mark = '_spike_train'
      spikes_filename = directory + contrast_mark + mark + polarity + layer + format
      f2 = open(spikes_filename, 'rb')
      spikes_on.append(cPickle.load(f2))
      f2.close()

      polarity = '_off'
      contrast_mark = str(contrast)
      mark = '_spike_train'
      spikes_filename = directory + contrast_mark + mark + polarity + layer + format
      f2 = open(spikes_filename, 'rb')
      spikes_off.append(cPickle.load(f2))
      f2.close()

    

Now this is the crucial part. If we want to utilize the SpikeSourceArray model for a cell in PyNN we can define a function that pass the spike-train for each cell in the population. In order to so we use the following code:

      def spike_times(simulator, layer, spikes_file):
         return [simulator.Sequence(x) for x in spikes_file[layer]]
    

Note that we have to change every spike-train array to a sequence before using it as a spike-train. After defining this function we can create the LGN models:

      # Cells models for the LGN spikes (SpikeSourceArray)
      lgn_spikes_on_models = []
      lgn_spikes_off_models = []


      for layer in xrange(N_lgn_layers):
         model = simulator.SpikeSourceArray(spike_times=spike_times(simulator, layer, spikes_on))
         lgn_spikes_on_models.append(model)
         model = simulator.SpikeSourceArray(spike_times=spike_times(simulator, layer, spikes_off))
         lgn_spikes_off_models.append(model)
    

Now that we have the corresponding model for the cells we can create the populations in the usual way:

 # LGN Popluations

 lgn_on_populations = []
 lgn_off_populations = []

 for layer in xrange(N_lgn_layers):
 population = simulator.Population(Ncell_lgn, lgn_spikes_on_models[layer], label='LGN_on_layer_' + str(layer))
 lgn_on_populations.append(population)
 population = simulator.Population(Ncell_lgn, lgn_spikes_off_models[layer], label='LGN_off_layer_' + str(layer))
 lgn_off_populations.append(population)
      

In order to analyze the spike-trains patterns for each population we need to declare a recorder for each population:

 
      layer = 0  # We declare here the layer of our interest 

      population_on = lgn_on_populations[layer]
      population_off = lgn_off_populations[layer]

      population_on.record('spikes')
      population_off.record('spikes')
    

Note here that we can chose the layer of our interest by modifying the value of the layer variable. Finally we run the model with the usual instructions and extract the spikes:

      #############################
      # Run model
      #############################

      simulator.run(t)  # Run the simulations for t ms
      simulator.end()

      #############################
      # Extract the data
      #############################
      data_on = population_on.get_data()  # Creates a Neo Block
      data_off = population_off.get_data()

      segment_on = data_on.segments[0]  # Takes the first segment
      segment_off = data_off.segments[0]
    

In order to visualize the spikes we use the following function:

 
      # Plot spike trains
      def plot_spiketrains(segment):
          """
          Plots the spikes of all the cells in the given segments
          """
          for spiketrain in segment.spiketrains:
              y = np.ones_like(spiketrain) * spiketrain.annotations['source_id']
              plt.plot(spiketrain, y, '*b')
              plt.ylabel('Neuron number')
              plt.xlabel('Spikes')
    

Here the spiketrain variable contains the spike-train for each cell, that is, an array with the times at which the action potentials happened for each cell. In order to tell them apart we assigned them the value of the cell id. Finally we can plot the spikes of the on and off cells with the following code:


      plt.subplot(2, 1, 1)
      plt.title('On cells ')
      plot_spiketrains(segment_on)

      plt.subplot(2, 1, 2)
      plt.title('Off cells ')
      plot_spiketrains(segment_off)

      plt.show()
    

We now show the plot produced by the code above. Note that the on and off cells are off-phase by 180.

No comments: