Skip to content

Commit

Permalink
Update course book
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Jul 3, 2023
1 parent 63b3ad9 commit 10aa103
Show file tree
Hide file tree
Showing 34 changed files with 848 additions and 1,036 deletions.
Binary file removed _images/W0D2_Tutorial1_94_0.png
Binary file not shown.
Binary file modified _images/W0D4_Tutorial1_108_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
134 changes: 25 additions & 109 deletions _sources/tutorials/W0D2_PythonWorkshop2/student/W0D2_Tutorial1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
"source": [
"---\n",
"## Tutorial objectives\n",
"\n",
"We learned basic Python and NumPy concepts in the previous tutorial. These new and efficient coding techniques can be applied repeatedly in tutorials from the NMA course, and elsewhere.\n",
"\n",
"In this tutorial, we'll introduce spikes in our LIF neuron and evaluate the refractory period's effect in spiking dynamics!\n"
"In this tutorial, we'll introduce spikes in our LIF neuron and evaluate the refractory period's effect in spiking dynamics!"
]
},
{
Expand Down Expand Up @@ -346,7 +347,7 @@
"\n",
"<br>\n",
"\n",
"Another important statistic is the sample [histogram](https://en.wikipedia.org/wiki/Histogram). For our LIF neuron it provides an approximate representation of the distribution of membrane potential $V_m(t)$ at time $t=t_k\\in[0,t_{max}]$. For $N$ realizations $V\\left(t_k\\right)$ and $J$ bins is given by:\n",
"Another important statistic is the sample [histogram](https://en.wikipedia.org/wiki/Histogram). For our LIF neuron, it provides an approximate representation of the distribution of membrane potential $V_m(t)$ at time $t=t_k\\in[0,t_{max}]$. For $N$ realizations $V\\left(t_k\\right)$ and $J$ bins is given by:\n",
"\n",
"<br>\n",
"\\begin{equation}\n",
Expand Down Expand Up @@ -673,7 +674,7 @@
"execution": {}
},
"source": [
"A spike takes place whenever $V(t)$ crosses $V_{th}$. In that case, a spike is recorded and $V(t)$ resets to $V_{reset}$ value. This is summarized in the *reset condition*:\n",
"A spike occures whenever $V(t)$ crosses $V_{th}$. In that case, a spike is recorded, and $V(t)$ resets to $V_{reset}$ value. This is summarized in the *reset condition*:\n",
"\n",
"\\begin{equation}\n",
"V(t) = V_{reset}\\quad \\text{ if } V(t)\\geq V_{th}\n",
Expand Down Expand Up @@ -855,7 +856,7 @@
"for step, t in enumerate(t_range):\n",
"\n",
" # Skip first iteration\n",
" if step==0:\n",
" if step == 0:\n",
" continue\n",
"\n",
" # Compute v_n\n",
Expand Down Expand Up @@ -915,7 +916,7 @@
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D2_PythonWorkshop2/solutions/W0D2_Tutorial1_Solution_9aaee1d8.py)\n",
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D2_PythonWorkshop2/solutions/W0D2_Tutorial1_Solution_950b2963.py)\n",
"\n"
]
},
Expand Down Expand Up @@ -1047,7 +1048,7 @@
"execution": {}
},
"source": [
"Numpy arrays can be indexed by boolean arrays to select a subset of elements (also works with lists of booleans).\n",
"Boolean arrays can index NumPy arrays to select a subset of elements (also works with lists of booleans).\n",
"\n",
"The boolean array itself can be initiated by a condition, as shown in the example below.\n",
"\n",
Expand Down Expand Up @@ -1251,13 +1252,13 @@
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D2_PythonWorkshop2/solutions/W0D2_Tutorial1_Solution_5061d76b.py)\n",
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D2_PythonWorkshop2/solutions/W0D2_Tutorial1_Solution_c368c1ef.py)\n",
"\n",
"*Example output:*\n",
"\n",
"<img alt='Solution hint' align='left' width=777.0 height=577.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_5061d76b_0.png>\n",
"<img alt='Solution hint' align='left' width=777.0 height=577.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_c368c1ef_0.png>\n",
"\n",
"<img alt='Solution hint' align='left' width=777.0 height=877.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_5061d76b_1.png>\n",
"<img alt='Solution hint' align='left' width=777.0 height=877.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_c368c1ef_1.png>\n",
"\n"
]
},
Expand Down Expand Up @@ -1604,9 +1605,8 @@
},
"source": [
"## Coding Exercise 5: Investigating refactory periods\n",
"Investigate the effect of (absolute) refractory period $t_{ref}$ on the evolution of output rate $\\lambda(t)$. Add refractory period $t_{ref}=10$ ms after each spike, during which $V(t)$ is clamped to $V_{reset}$.\n",
"\n",
"\n"
"Investigate the effect of (absolute) refractory period $t_{ref}$ on the evolution of output rate $\\lambda(t)$. Add refractory period $t_{ref}=10$ ms after each spike, during which $V(t)$ is clamped to $V_{reset}$."
]
},
{
Expand Down Expand Up @@ -1717,13 +1717,13 @@
},
"source": [
"## Interactive Demo 1: Random refractory period\n",
"\n",
"In the following interactive demo, we will investigate the effect of random refractory periods. We will use random refactory periods $t_{ref}$ with\n",
"$t_{ref} = \\mu + \\sigma\\,\\mathcal{N}$, where $\\mathcal{N}$ is the [normal distribution](https://en.wikipedia.org/wiki/Normal_distribution), $\\mu=0.01$ and $\\sigma=0.007$.\n",
"\n",
"Refractory period samples `t_ref` of size `n` is initialized with `np.random.normal`. We clip negative values to `0` with boolean indexes. (Why?) You can double click the cell to see the hidden code.\n",
"Refractory period samples `t_ref` of size `n` is initialized with `np.random.normal`. We clip negative values to `0` with boolean indexes. (Why?) You can double-click the cell to see the hidden code.\n",
"\n",
"You can play with the parameters mu and sigma and visualize the resulting simulation.\n",
"What is the effect of different $\\sigma$ values?\n"
"You can play with the parameters mu and sigma and visualize the resulting simulation. What is the effect of different $\\sigma$ values?"
]
},
{
Expand Down Expand Up @@ -2014,6 +2014,7 @@
},
"source": [
"## Coding Exercise 6: Rewriting code with functions\n",
"\n",
"We will now re-organize parts of the code from the previous exercise with functions. You need to complete the function `spike_clamp()` to update $V(t)$ and deal with spiking and refractoriness"
]
},
Expand All @@ -2033,7 +2034,7 @@
" v (numpy array of floats)\n",
" membrane potential at previous time step of shape (neurons)\n",
"\n",
" v (numpy array of floats)\n",
" i (numpy array of floats)\n",
" synaptic input at current time step of shape (neurons)\n",
"\n",
" dt (float)\n",
Expand All @@ -2047,6 +2048,7 @@
"\n",
" return v\n",
"\n",
"\n",
"def spike_clamp(v, delta_spike):\n",
" \"\"\"\n",
" Resets membrane potential of neurons if v>= vth\n",
Expand Down Expand Up @@ -2124,106 +2126,20 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"outputs": [],
"source": [
"def ode_step(v, i, dt):\n",
" \"\"\"\n",
" Evolves membrane potential by one step of discrete time integration\n",
"\n",
" Args:\n",
" v (numpy array of floats)\n",
" membrane potential at previous time step of shape (neurons)\n",
"\n",
" v (numpy array of floats)\n",
" synaptic input at current time step of shape (neurons)\n",
"\n",
" dt (float)\n",
" time step increment\n",
"\n",
" Returns:\n",
" v (numpy array of floats)\n",
" membrane potential at current time step of shape (neurons)\n",
" \"\"\"\n",
" v = v + dt/tau * (el - v + r*i)\n",
"\n",
" return v\n",
"\n",
"# to_remove solution\n",
"def spike_clamp(v, delta_spike):\n",
" \"\"\"\n",
" Resets membrane potential of neurons if v>= vth\n",
" and clamps to vr if interval of time since last spike < t_ref\n",
"\n",
" Args:\n",
" v (numpy array of floats)\n",
" membrane potential of shape (neurons)\n",
"\n",
" delta_spike (numpy array of floats)\n",
" interval of time since last spike of shape (neurons)\n",
"\n",
" Returns:\n",
" v (numpy array of floats)\n",
" membrane potential of shape (neurons)\n",
" spiked (numpy array of floats)\n",
" boolean array of neurons that spiked of shape (neurons)\n",
" \"\"\"\n",
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D2_PythonWorkshop2/solutions/W0D2_Tutorial1_Solution_bf9f75ab.py)\n",
"\n",
" # Boolean array spiked indexes neurons with v>=vth\n",
" spiked = (v >= vth)\n",
" v[spiked] = vr\n",
"\n",
" # Boolean array clamped indexes refractory neurons\n",
" clamped = (t_ref > delta_spike)\n",
" v[clamped] = vr\n",
"\n",
" return v, spiked\n",
"\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end, t_range, n, v_n and i\n",
"t_range = np.arange(0, t_max, dt)\n",
"step_end = len(t_range)\n",
"n = 500\n",
"v_n = el * np.ones([n, step_end])\n",
"i = i_mean * (1 + 0.1 * (t_max / dt)**(0.5) * (2 * np.random.random([n, step_end]) - 1))\n",
"\n",
"# Initialize binary numpy array for raster plot\n",
"raster = np.zeros([n,step_end])\n",
"\n",
"# Initialize t_ref and last_spike\n",
"mu = 0.01\n",
"sigma = 0.007\n",
"t_ref = mu + sigma*np.random.normal(size=n)\n",
"t_ref[t_ref<0] = 0\n",
"last_spike = -t_ref * np.ones([n])\n",
"\n",
"# Loop over time steps\n",
"for step, t in enumerate(t_range):\n",
"\n",
" # Skip first iteration\n",
" if step==0:\n",
" continue\n",
"\n",
" # Compute v_n\n",
" v_n[:,step] = ode_step(v_n[:,step-1], i[:,step], dt)\n",
"\n",
" # Reset membrane potential and clamp\n",
" v_n[:,step], spiked = spike_clamp(v_n[:,step], t - last_spike)\n",
"*Example output:*\n",
"\n",
" # Update raster and last_spike\n",
" raster[spiked,step] = 1.\n",
" last_spike[spiked] = t\n",
"<img alt='Solution hint' align='left' width=777.0 height=378.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_bf9f75ab_0.png>\n",
"\n",
"# Plot multiple realizations of Vm, spikes and mean spike rate\n",
"with plt.xkcd():\n",
" plot_all(t_range, v_n, raster)"
"<img alt='Solution hint' align='left' width=777.0 height=877.0 src=https://raw.githubusercontent.com/NeuromatchAcademy/precourse/main/tutorials/W0D2_PythonWorkshop2/static/W0D2_Tutorial1_Solution_bf9f75ab_1.png>\n",
"\n"
]
},
{
Expand Down Expand Up @@ -2354,7 +2270,7 @@
"execution": {}
},
"source": [
"Using classes helps with code reuse and reliability. Well-designed classes are like black boxes in that they receive inputs and provide expected outputs. The details of how the class processes inputs and produces outputs are unimportant.\n",
"Using classes helps with code reuse and reliability. Well-designed classes are like black boxes, receiving inputs and providing expected outputs. The details of how the class processes inputs and produces outputs are unimportant.\n",
"\n",
"See additional details here: [A Beginner's Python Tutorial/Classes](https://en.wikibooks.org/wiki/A_Beginner%27s_Python_Tutorial/Classes)\n",
"\n",
Expand Down
Loading

0 comments on commit 10aa103

Please sign in to comment.