<jupyter_start><jupyter_text>CCNSS 2018 Module 1: Neurons, synapses and networks Tutorial 4: Balanced neuronal excitation and inhibition[source](https://colab.research.google.com/drive/1I4b01XubbttyGW1nahCEBM-Yl0K98QrV)Please execute the cell below to initialise the notebook environment.<jupyter_code>%autosave 0

import matplotlib.pyplot as plt    # import matplotlib
import numpy as np                 # import numpy
import random                      # import basic random number generator functions

fig_w, fig_h = (6, 4)
plt.rcParams.update({'figure.figsize': (fig_w, fig_h)})<jupyter_output><empty_output><jupyter_text>ObjectivesIn this tutorial, we will build on the conductance-based model in Tutorial 4 to study E/I balance and fluctuation-drive spiking in a conductance based neuron.**Background paper:*** <NAME>, <NAME> and <NAME> (2000) Competitive Hebbian learning through spike-timing-dependent synaptic plasticity. Nature Neurosci 3.**Extra reading:*** <NAME> and <NAME> (1993) The highly irregular firing of cortical cells is inconsistent with temporal integration of random EPSPs. J Neurosci 13.* Okun M and Lampl I (2009) Balance of excitation and inhibition. Scholarpedia: http://www.scholarpedia.org/article/Balance_of_excitation_and_inhibition  Background<jupyter_code>t_max = 500e-3   # second
dt = 1e-3        # second
tau = 20e-3      # second
el = -60e-3      # volt
e_ex = 0         # volt
e_in = -70e-3    # volt
vr = -70e-3      # volt
vth = -50e-3     # volt
tau_syn = 5e-3   # second<jupyter_output><empty_output><jupyter_text>**Exercise 1:** Fill in in the following functions to generate Poisson spikes and simulate a postsynaptic neuron with both excitatory and inhibitoy conductances (no plasticity). Use the code you wrote in Tutorial 3 and build it up to incorporate inhibition, by adding an inhibitory conductance:\begin{align}&\tau_m\,\frac{dV}{dt}\ = E_{L} - V(t) + g_{ex}(t)(E_{ex}-V(t))+ g_{in}(t)(E_{in}-V(t)) &\text{if }\quad V(t) \leq V_{th}\\&V(t) = V_{r} &\text{otherwise}\\\end{align}Also modify the code to return the spike times of the postsynpatic neuron. Then, simulate a postsynaptic neuron with 800 excitatory inputs and 200 inhibitory inputs at 10 Hz for 500 ms, with peak conductances of $\bar g_{max,ex} = \bar g_{max,in} = 6*10^{-3}$.<jupyter_code>random.seed(0)

def generate_Poisson_spikes(t,rate,n):
  """ Generates poisson spike trains
  
  Arguments:
  t -- time
  rate -- firing rate (Hz)
  n -- number of spike trains
  
  Returns:
  pre_spike_train -- spike train matrix, ith row represents whether 
                     there is a spike in ith spike train over time
                     (1 if spike, 0 otherwise)
  """
  # insert your code here
  return pre_spike_train

def simulate_postsynaptic_neuron(t,pre_spike_train_ex,pre_spike_train_in):
    """ Simulate nonplastic postsynaptic neuron
  
    Arguments:
    t -- time
    pre_spike_train_ex -- excitatory presynaptic spike train matrix, same length as t
    pre_spike_train_in -- inhibitory presynaptic spike train matrix, same length as t
  
    Returns:
    v -- membrane potential
    spike_times -- list of postsynaptic spike times
    """
    # insert your code here
    return v,spike_times

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**```24.0``` **Exercise 2:** Repeat this over 10 trials and make a raster plot showing the spike times for each trial. Calculate the average firing rate over all the trials.<jupyter_code>random.seed(0)

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**```22.6```![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E2.png) **Exercise 3:** Now increase the peak inhibitory conductance to  $\bar g_{max,in} = 8*\bar g_{max,ex}$. To maintain a similar firing rate, you should also increase the peak excitatory conductance: $\bar g_{max,ex} = 17*10^{-3}$. How are the raster plots different? Which one is more regular?<jupyter_code>random.seed(0)

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**```22.2```![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E3.png) **Exercise 4:** To see what's happening, simulate one example with the excitatory and inhibitory conductances from Exercise 1-2, and one example with the conductances from Exercise 3. Use exactly the same presynaptic spike train for each simulation. Plot the membrane potential for each case. How does this difference in $\bar g_{max,ex}$ and $\bar g_{max,in}$ change the subthreshold dynamics? How does this explain the difference in the postsynaptic spike trains?<jupyter_code>random.seed(0)

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E4.png) **Exercise 5:**  By increasing the inhibitory strengths relative to the excitatory strength, the postsynaptic neuron enters an irregular spiking regime in which spikes are drive by fluctuations in the input, rather than the mean input. This is called E/I balance. To quantify the irregularity of spiking, calculate the coefficient of variation (CV) of the inter-spike intervals. The CV is defined as the ratio of the standard deviation to the mean:$$ CV = \frac{\sigma_{ISI}}{\mu_{ISI}}$$Fill in the following function to get the CV. Test it by calculating the CV for both the balanced and unbalanced neurons (increase $t_{max}$ to 5 s). Note that for a poisson process, the CV is 1.<jupyter_code>random.seed(0)


def get_CV(spike_times):
  """Calculate the coefficient of variation
  
  Arguments:
  spike_times -- list of spike times
  
  Returns:
  CV -- coefficient of variation for the spike times
  """
  # insert your code here
  return CV

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**```0.774793911740589 0.15577586005132124``` **Exercise 6:** Now repeat the previous exercise while ranging the presynaptic range from 10 to 40 Hz. Plot the CV against the firing rate for both the balanced and unbalanced neurons. Why does the CV decrease with firing rate?<jupyter_code>random.seed(0)

# insert your text here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E6.png) **Exercise 7:** Next we will see how STDP can help E/I balance in a postsynaptic neuron. First, execute the cell below to set the STDP parameters used in Tutorial 2.<jupyter_code>tau_stdp = 20e-3       # second
A_plus = 5e-3  
A_minus = A_plus*1.10

gbar_max_ex = 0.015
gbar_max_in = 0.015<jupyter_output><empty_output><jupyter_text>Then, fill in the functions below to simulate STDP. You can use your code from Tutorial 2, while adding nonplastic inhibitory synaptic inputs. Also fill in the function to simulate a postsynaptic neuron with frozen weights (i.e., with fixed $\bar g_i$). Check that your code works by simulating a plastic postystnaptic neurons receiving input from 300 excitatory cells and 75 inhibitory cells (all firing at 20 Hz) for 5 seconds and plotting the average $\bar g_i(t)$. Then simulate the postsynaptic neuron for 100 ms after freezing the synaptic weights to those at the end of the STDP protocol. Plot the membraine potential.<jupyter_code>random.seed(0)

def generate_P(t,pre_spike_train):
  """ Generate P to track presynaptic spikes
  
  Arguments:
  t -- time
  pre_spike_train -- presynaptic spike train matrix, same length as t
  
  Returns:
  P -- matrix, ith row is P for the ith presynaptic input 
  """
  # insert your code here
  return P

def simulate_postsynaptic_neuron_plastic(t,pre_spike_train_ex,pre_spike_train_in):
    """Simulate a plastic neuron
    
    Arguments:
    t -- time
    pre_spike_train_ex -- excitatory presynaptic spike train matrix, same length as t
    pre_spike_train_in -- inhibitory presynaptic spike train matrix, same length as t
  
    Returns:
    gbar -- matrix, ith row is peak excitatory conductance 
            over time for ith presynaptic neuron
    v -- membrane potential
    spike_times -- list of spike times 
    """
    # insert your code here
    return gbar,v


def simulate_postsynaptic_neuron_frozen(t,pre_spike_train_ex,pre_spike_train_in,gbar):
    """Simulate the postsynaptic neuron after freezing the weights
    
    Arguments:
    t -- time
    pre_spike_train_ex -- excitatory presynaptic spike train matrix, same length as t
    pre_spike_train_in -- inhibitory presynaptic spike train matrix, same length as t
    gbar -- vector, ith element is peak excitatory conductance 
            over time for ith presynaptic neuron
            
    Returns:
    v -- membrane potential
    spike_times -- list of spike times 
    """
    # insert your code here
    return v,spike_times
  
# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E7a.png)![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E7b.png) **Exercise 8:** Now increase $t_{max}$ to 1000 s and simulate STDP by executing the following cell (warning: this is really slow and might kill all your memory).<jupyter_code>random.seed(0)
  
t_max = 1000;
t = np.arange(0,t_max,dt)

n_ex = 300; n_in = 75; rate = 20

pre_spike_train_ex = generate_Poisson_spikes(t,rate,n_ex)
pre_spike_train_in = generate_Poisson_spikes(t,rate,n_in)

gbar, v = simulate_postsynaptic_neuron_plastic(t,pre_spike_train_ex,pre_spike_train_in)<jupyter_output><empty_output><jupyter_text>When it has completed, plot the histograms at the end of learning and 90% of the way through. Has the system converged?<jupyter_code>random.seed(0)

# insert your code here<jupyter_output><empty_output><jupyter_text>**EXPECTED OUTPUT**![](https://github.com/ccnss/ccnss2018_students/raw/master/module1/figures/T4E8.png) **Exercise 9:** Finally, use the weights at the end of STDP (from Exercise 8) to simulate the postsynaptic neuron for  $t_{max}=15 s$ (use  the function ``simulate_postsynaptic_neuron_frozen``).Calculate the CV at the beginning and at the end of STDP.<jupyter_code>random.seed(0)

# insert your code here<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0902987253089423, 'fraction_numerical': 0.024618079205993966, 'mean_word_length': 4.426610348468849, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 58, 'https://': 8, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '109960', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 3521, 'n_tokens_neox': 3116, 'n_words': 1102, 'path': 'module1/4_balanced_neuronal_ei/4_balanced_neuronal_ei.ipynb', 'repo_name': 'ruyuanzhang/ccnss2018_students', 'size': '10281'}