{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"id": "view-in-github"
},
"source": [
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial: LIF Neuron Part I\n",
"\n",
"**Week 0, Day 1: Python Workshop 1**\n",
"\n",
"**By Neuromatch Academy**\n",
"\n",
"__Content creators:__ Marco Brigham and the [CCNSS](https://www.ccnss.org/) team\n",
"\n",
"__Content reviewers:__ Michael Waskom, Karolina Stosio, Spiros Chavlis\n",
"\n",
"__Production editors:__ Ella Batty, Spiros Chavlis\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Tutorial objectives\n",
"\n",
"During NMA, you will be using code to learn computational neuroscience in an interactive (and hopefully fun) way. This tutorial and the next are to help you get up to speed on Python before the course, so that during the course you can focus on the computational neuroscience concepts.\n",
"\n",
"\n",
"In this notebook, we'll practice basic operations with Python variables, control flow, plotting, and take a sneak peek at `np.array`, the workhorse of scientific computation in Python.\n",
"\n",
"Each new concept in Python will unlock a different aspect of our implementation of a **Leaky Integrate-and-Fire (LIF)** neuron. And as if it couldn't get any better, we'll visualize the evolution of its membrane potential in time, and extract its statistical properties!\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Setup\n",
"\n",
"Please execute the cell(s) below to initialize the notebook environment."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install and import feedback gadget\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Install and import feedback gadget\n",
"\n",
"!pip3 install vibecheck datatops --quiet\n",
"\n",
"from vibecheck import DatatopsContentReviewContainer\n",
"def content_review(notebook_section: str):\n",
" return DatatopsContentReviewContainer(\n",
" \"\", # No text prompt\n",
" notebook_section,\n",
" {\n",
" \"url\": \"https://pmyvdlilci.execute-api.us-east-1.amazonaws.com/klab\",\n",
" \"name\": \"neuromatch-precourse\",\n",
" \"user_key\": \"8zxfvwxw\",\n",
" },\n",
" ).render()\n",
"\n",
"\n",
"feedback_prefix = \"W0D1_T1\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "both",
"execution": {}
},
"outputs": [],
"source": [
"# Imports\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Figure settings\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Figure settings\n",
"import logging\n",
"logging.getLogger('matplotlib.font_manager').disabled = True\n",
"import ipywidgets as widgets # interactive display\n",
"%config InlineBackend.figure_format = 'retina'\n",
"plt.style.use(\"https://raw.githubusercontent.com/NeuromatchAcademy/course-content/master/nma.mplstyle\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 1: Python basics & the LIF model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 1: Python basics & the LIF model\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 1: Python basics & the LIF model\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'Bwm6rjRpVw8'), ('Bilibili', 'BV1vV41167T1')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Python_basics_and_the_LIF_model_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.1: The LIF Model"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"A *membrane equation* and a *reset condition* define our *leaky-integrate-and-fire (LIF)* neuron:\n",
"\n",
"\\begin{align}\n",
"\\tau_m\\,\\frac{d}{dt}\\,V(t) &= E_{L} - V(t) + R\\,I(t) &\\text{if }\\quad V(t) \\leq V_{th} \\\\ \\\\\n",
"V(t) &= V_{reset} &\\text{otherwise}\n",
"\\end{align}\n",
"\n",
"
\n",
"where $V(t)$ is the membrane potential, $\\tau_m$ is the membrane time constant, $E_{L}$ is the leak potential, $R$ is the membrane resistance, $I(t)$ is the synaptic input current, $V_{th}$ is the firing threshold, and $V_{reset}$ is the reset voltage. We can also write $V_m$ for membrane potential, which is more convenient for plot labels.\n",
"\n",
"The membrane equation describes the time evolution of membrane potential $V(t)$ in response to synaptic input and leaking of charge across the cell membrane. This is an *ordinary differential equation (ODE)*, a concept we will learn more about in future days.\n",
"\n",
"**Note that, in this tutorial the neuron model will not implement a spiking mechanism.**"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.2: Comments in code"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Video 2: Nano recap of comments and strings\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 2: Nano recap of comments and strings\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'UP8rD2AwceM'), ('Bilibili', 'BV1fg4y1v7P3')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_comments_and_strings_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercise 1: Defining parameters\n",
"We start by defining and initializing the main simulation variables for our LIF neuron.\n",
"\n",
"In the code cell below, please modify the code to print the simulation parameters."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# t_max = 150e-3 # second\n",
"# dt = 1e-3 # second\n",
"# tau = 20e-3 # second\n",
"# el = -60e-3 # milivolt\n",
"# vr = -70e-3 # milivolt\n",
"# vth = -50e-3 # milivolt\n",
"# r = 100e6 # ohm\n",
"# i_mean = 25e-11 # ampere\n",
"\n",
"# print(t_max, dt, tau, el, vr, vth, r, i_mean)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"**SAMPLE OUTPUT**\n",
"\n",
"```\n",
"0.15 0.001 0.02 -0.06 -0.07 -0.05 100000000.0 2.5e-10\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"cellView": "code",
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_4adeccd3.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Defining_Parameters_Ecercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We needed to remove the #'s at the start of each line - otherwise the code is read as comments and not actually run. Sometimes when you're writing code, you may want to \"comment out\" sections of code for debugging purposes. Note that we tried to use descriptive variable names, in this case that correspond to the math notation we use. We also used comments to denote units within the code - this makes it much easier to understand!"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.3: Math operations\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercise 2: Simulating an input current\n",
"![synaptic input](https://github.com/mpbrigham/colaboratory-figures/raw/master/nma/python-for-nma/synaptic_input.png)\n",
"\n",
"We need to simulate the synaptic input $I(t)$ that goes into our model neuron. We will start with a sinusoidal model to simulate this input (visualized above), using the equation:\n",
"\n",
"\\begin{equation}\n",
"I(t)=I_{mean}\\left(1+\\sin\\left(\\frac{2 \\pi}{0.01}\\,t\\right)\\right)\n",
"\\end{equation}\n",
"\n",
"where $I_{mean}$ is the mean current input and $t$ is the time.\n",
"\n",
"In the next cell, you will compute the values of synaptic input $I(t)$ between $t=0$ and $t=0.009$ with step $\\Delta t=0.001$.\n",
"\n",
"
\n",
"\n",
"**New coding concepts**:\n",
"\n",
"- We use a **for loop** in the code below. We will dive deeper into for loops later, but essentially for loops allow us to run the same code block multiple times. In this case, we loop over steps so the variable *step* equals something new each time. We use the following syntax:\n",
"\n",
" ```python\n",
" for step in range(10):\n",
" ```\n",
"\n",
" This means that `step` will take each integer value between 0 and 9.\n",
"\n",
"- You can use `np.pi` as the value of $\\pi$ and `np.sin(x)` to get the sine of x. These come from a package called numpy, which we'll learn about later.\n",
"\n",
"
\n",
"\n",
"$^{\\dagger}$Generally, the `range` python function returns a sequence of numbers, starting from 0 (by default), and increments by 1 (by default), and stops before a specified number.\n",
"\n",
"Syntax:\n",
"\n",
"```python\n",
"range(start, stop, step)\n",
"```\n",
"\n",
"Parameters:\n",
"\n",
"- *start*: Optional. An integer number specifying at which position to start. Default is 0\n",
"- *stop*: Required. An integer number specifying at which position to stop (not included).\n",
"- *step*: Optional. An integer number specifying the incrementation. Default is 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# Loop for 10 steps, variable 'step' takes values from 0 to 9\n",
"for step in range(10):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Compute value of i at this time step\n",
" i = ...\n",
"\n",
" # Print value of i\n",
" print(i)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"**SAMPLE OUTPUT**\n",
"\n",
"```\n",
"2.5e-10\n",
"3.969463130731183e-10\n",
"4.877641290737885e-10\n",
"4.877641290737885e-10\n",
"3.9694631307311837e-10\n",
"2.5000000000000007e-10\n",
"1.0305368692688176e-10\n",
"1.2235870926211617e-11\n",
"1.223587092621159e-11\n",
"1.0305368692688186e-10\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_0833b67f.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Simulating_an_Input_Current_Ecercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.4: Print formatting\n",
"\n",
"Print formatting is handy for displaying simulation parameters in a clean and organized form. Python 3.6 introduced the new string formatting [f-strings](https://www.python.org/dev/peps/pep-0498). Since we are dealing with type `float` variables, we use `f'{x:.3f}'` for formatting `x` to three decimal points, and `f'{x:.4e}'` for four decimal points but in exponential notation.\n",
"```\n",
"x = 3.14159265e-1\n",
"print(f'{x:.3f}')\n",
"--> 0.314\n",
"\n",
"print(f'{x:.4e}')\n",
"--> 3.1416e-01\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercise 3: Printing pretty numbers\n",
"\n",
"\n",
"Repeat the loop from the previous exercise and print the `t` values with three decimal points, and synaptic input $I(t)$ with four decimal points in exponential notation.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# Initialize step_end\n",
"step_end = 10\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + np.sin((t * 2 * np.pi) / 0.01))\n",
"\n",
" # Print value of t and i\n",
" print(...)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"**SAMPLE OUTPUT**\n",
"\n",
"```\n",
"0.000 2.5000e-10\n",
"0.001 3.9695e-10\n",
"0.002 4.8776e-10\n",
"0.003 4.8776e-10\n",
"0.004 3.9695e-10\n",
"0.005 2.5000e-10\n",
"0.006 1.0305e-10\n",
"0.007 1.2236e-11\n",
"0.008 1.2236e-11\n",
"0.009 1.0305e-10\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_b2d23280.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Printing_Pretty_Numbers_Ecercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 2: For loops & discrete time integration\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 3: For loops & discrete time integration\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 3: For loops & discrete time integration\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'JkxgotYwu4Q'), ('Bilibili', 'BV1nt4y1Q7Z5')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_For_Loops_and_Discrete_time_integration_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 2.1: For Loops\n",
"\n",
"A for loop implements the indented code block multiple times (with the variable being looped over equaling something new each time). The following three formulations are all equivalent and loop for three steps:\n",
"```\n",
"for step in [0, 1, 2]:\n",
" print(step)\n",
"\n",
"for step in range(3):\n",
" print(step)\n",
"\n",
"start = 0\n",
"end = 3\n",
"stepsize = 1\n",
"\n",
"for step in range(start, end, stepsize):\n",
" print(step)\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 2.2: Discrete time integration with spikes\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Video 4: Nano recap of discrete time integration\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 4: Nano recap of discrete time integration\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'kyCbeR28AYQ'), ('Bilibili', 'BV1mt4y1Q7Ls')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_Discrete_time_integration_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"In the next exercises, we will simulate the evolution of the membrane equation in discrete time steps, with a sufficiently small $\\Delta t$.\n",
"\n",
"We start by writing the time derivative $d/dt\\,V(t)$ in the membrane equation without taking the limit $\\Delta t \\to 0$:\n",
"\n",
"\\begin{equation}\n",
"\\tau_m\\,\\frac{V\\left(t+\\Delta t\\right)-V\\left(t\\right)}{\\Delta t} = E_{L} - V(t) + R\\,I(t) \\qquad\\qquad (1)\n",
"\\end{equation}\n",
"\n",
"The value of membrane potential $V\\left(t+\\Delta t\\right)$ can be expressed in terms of its previous value $V(t)$ by simple algebraic manipulation. For *small enough* values of $\\Delta t$, this provides a good approximation of the continuous-time integration.\n",
"\n",
"This operation is an integration since we obtain a sequence $\\{V(t), V(t+\\Delta t), V(t+2\\Delta t),...\\}$ starting from the ODE. Notice how the ODE describes the evolution of $\\frac{d}{dt}\\,V(t)$, the derivative of $V(t)$, but not directly the evolution of $V(t)$. For the evolution of $V(t)$ we need to integrate the ODE, and in this tutorial, we will do a discrete-time integration using the Euler method. See [Numerical methods for ordinary differential equations](https://en.wikipedia.org/wiki/Numerical_methods_for_ordinary_differential_equations) for additional details."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercise 4: Simulating membrane potential\n",
"Compute the values of $V(t)$ between $t=0$ and $t=0.01$ with step $\\Delta t=0.001$ and $V(0)=E_L$.\n",
"\n",
"\n",
"We need to reorganize the Eq. (1) to isolate $V\\left( t+\\Delta t \\right)$ on the left side, and express it as function of $V(t)$ and the other terms:\n",
"\n",
"\\begin{equation}\n",
"V(t + \\Delta t) = V(t) + \\frac{\\Delta t}{\\tau_m}\\left( E_L -V(t) + R I(t) \\right)\n",
"\\end{equation}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out compute v code ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to fill out code to compute v\")\n",
"#################################################\n",
"\n",
"# Initialize step_end and v0\n",
"step_end = 10\n",
"v = el\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + np.sin((t * 2 * np.pi) / 0.01))\n",
"\n",
" # Compute v\n",
" v = ...\n",
"\n",
" # Print value of t and v\n",
" print(f\"{t:.3f} {v:.4e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"**SAMPLE OUTPUT**\n",
"\n",
"```\n",
"0.000 -5.8750e-02\n",
"0.001 -5.6828e-02\n",
"0.002 -5.4548e-02\n",
"0.003 -5.2381e-02\n",
"0.004 -5.0778e-02\n",
"0.005 -4.9989e-02\n",
"0.006 -4.9974e-02\n",
"0.007 -5.0414e-02\n",
"0.008 -5.0832e-02\n",
"0.009 -5.0775e-02\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_6477ecbb.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Simulating_membrane_potential_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 3: Plotting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 5: Intro to plotting\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 5: Intro to plotting\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'RmdPBHn9kjk'), ('Bilibili', 'BV1MC4y1h77q')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Intro_to_Plotting_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 6: Nano recap of plotting\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 6: Nano recap of plotting\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'BOh8CsuTFkY'), ('Bilibili', 'BV1BA411e7eH')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_Plotting_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 5: Plotting current\n",
"\n",
"In this exercise, we will plot the values of $I(t)$ between $t=0$ and $t=0.024$.\n",
"\n",
"You will first need to set the title and axis labels of the plot. Label these descriptively! You will then need to fill out the code to actually create the plot.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out the figure initialization and plotting code below ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to fill out current figure code\")\n",
"#################################################\n",
"\n",
"# Initialize step_end\n",
"step_end = 25\n",
"\n",
"# Initialize the figure\n",
"plt.figure()\n",
"plt.title(...)\n",
"plt.xlabel(...)\n",
"plt.ylabel(...)\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + np.sin((t * 2 * np.pi) / 0.01))\n",
"\n",
" # Plot i (use 'ko' to get small black dots (short for color='k' and marker = 'o'))\n",
" plt.plot(...)\n",
"\n",
"# Display the plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_c15c544f.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We are plotting the curent input at discrete steps only. If we plotted the current continuously, it would resemble the blue line below."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"![synaptic input discrete](https://github.com/mpbrigham/colaboratory-figures/raw/master/nma/python-for-nma/synaptic_input_discrete.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Plotting_current_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 6: Plotting membrane potential\n",
"Plot the values of $V(t)$ between $t=0$ and $t=t_{max}$. We can compute the number of steps required to get to $t=t_{max}$ given $\\Delta t$ as `int(t_max/dt)` where `int` gets the nearest integer.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out the figure initialization and plotting code below ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to fill out membrane potential figure code\")\n",
"#################################################\n",
"\n",
"# Initialize step_end\n",
"step_end = int(t_max / dt)\n",
"\n",
"# Initialize v0\n",
"v = el\n",
"\n",
"# Initialize the figure\n",
"plt.figure()\n",
"plt.title('$V_m$ with sinusoidal I(t)')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)');\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + np.sin((t * 2 * np.pi) / 0.01))\n",
"\n",
" # Compute v\n",
" v = v + dt/tau * (el - v + r*i)\n",
"\n",
" # Plot v (using 'k.' to get even smaller markers)\n",
" plt.plot(...)\n",
"\n",
"# Display plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_70f05c19.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Plotting_membrane_potential_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 4: Random synaptic input\n",
"\n",
"From the perspective of neurons, synaptic input is random (or stochastic). We'll improve the synaptic input model by introducing random input current with statistical properties similar to the previous exercise:\n",
"\n",
"\\begin{equation}\n",
"I(t) = I_{mean}\\left(1+0.1\\sqrt{\\frac{t_{max}}{\\Delta t}}\\,\\xi(t)\\right)\\qquad\\text{with }\\xi(t)\\sim \\mathcal{U}(-1,1)\n",
"\\end{equation}\n",
"\n",
"where $\\mathcal{U}(-1,1)$ is the [uniform distribution](https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)) with support $x\\in[-1,1]$.\n",
"\n",
"We can approximate randomness in code using a pseudo random number generator. The function `np.random.seed()` initializes the RNG. If we initialize this with a number (e.x. `np.random.seed(2)`), we will get the same random number draws each time we run the code. Basically, we are making the random number generation replicable. We do this here so you can get a figure that exactly matches the solution. The function `np.random.random()` generates samples from the uniform distribution between `0` and `1`."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 7: Adding randomness\n",
"\n",
"Plot the values of $V(t)$ between $t=0$ and $t=t_{max}-\\Delta t$ with random input $I(t)$.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to get random input ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to fill out random input code\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end and v\n",
"step_end = int(t_max / dt)\n",
"v = el\n",
"\n",
"# Initialize the figure\n",
"plt.figure()\n",
"plt.title('$V_m$ with random I(t)')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"# loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Get random number in correct range of -1 to 1 (will need to adjust output of np.random.random)\n",
" random_num = ...\n",
"\n",
" # Compute value of i at this time step\n",
" i = ...\n",
"\n",
" # Compute v\n",
" v = v + dt/tau * (el - v + r*i)\n",
"\n",
" # Plot v (using 'k.' to get even smaller markers)\n",
" plt.plot(t, v, 'k.')\n",
"\n",
"\n",
"# Display plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_413e2a3c.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Random synaptic input $I(t)$ results in random time course for $V(t)$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Adding_randomness_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 5: Lists & ensemble statistics\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 7: Lists & ensemble statistics\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 7: Lists & ensemble statistics\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'A2foheo44h4'), ('Bilibili', 'BV1ff4y197Hx')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Lists_&_ensemble_statistics_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 8: Nano recap of ensemble statistics & lists\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 8: Nano recap of ensemble statistics & lists\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', '4nIAS2oPEFI'), ('Bilibili', 'BV1UZ4y1u7sV')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_ensemble_statistics_&_lists_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Multiple runs of the previous exercise may give the impression of periodic regularity in the evolution of $V(t)$. We'll collect the sample mean over $N=50$ realizations of $V(t)$ with random input to test such a hypothesis. The sample mean, sample variance and sample autocovariance at times $\\left\\{t, s\\right\\}\\in[0,t_{max}]$, and for $N$ realizations $V_n(t)$ are given by:\n",
"\n",
"\\begin{align}\n",
"\\\\\n",
"\\left\\langle V(t)\\right\\rangle &= \\frac{1}{N}\\sum_{n=1}^N V_n(t) & & \\text{sample mean}\\\\\n",
"\\left\\langle (V(t)-\\left\\langle V(t)\\right\\rangle)^2\\right\\rangle &= \\frac{1}{N-1} \\sum_{n=1}^N \\left(V_n(t)-\\left\\langle V(t)\\right\\rangle\\right)^2 & & \\text{sample variance} \\\\\n",
"\\left\\langle \\left(V(t)-\\left\\langle V(t)\\right\\rangle\\right)\\left(V(s)-\\left\\langle V(s)\\right\\rangle\\right)\\right\\rangle\n",
"&= \\frac{1}{N-1} \\sum_{n=1}^N \\left(V_n(t)-\\left\\langle V(t)\\right\\rangle\\right)\\left(V_n(s)-\\left\\langle V(s)\\right\\rangle\\right) & & \\text{sample autocovariance}\n",
"\\end{align}"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 8: Storing simulations in lists\n",
"Plot multiple simulations ($N=50$) of $V(t)$ by storing in a list the voltage of each neuron at time $t$.\n",
"\n",
"Keep in mind that the plotting command `plt.plot(x, y)` requires `x` to have the same number of elements as `y`.\n",
"\n",
"Mathematical symbols such as $\\alpha$ and $\\beta$ are specified as `$\\alpha$` and `$\\beta$` in [TeX markup](https://en.wikipedia.org/wiki/TeX). See additional details in [Writing mathematical expressions](https://matplotlib.org/3.2.2/tutorials/text/mathtext.html) in Matplotlib.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to store v in list ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to store v in list\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end and n\n",
"step_end = int(t_max / dt)\n",
"n = 50\n",
"\n",
"# Intiatialize the list v_n with 50 values of membrane leak potential el\n",
"v_n = ...\n",
"\n",
"with plt.xkcd():\n",
" # Initialize the figure\n",
" plt.figure()\n",
" plt.title('Multiple realizations of $V_m$')\n",
" plt.xlabel('time (s)')\n",
" plt.ylabel('$V_m$ (V)')\n",
"\n",
" # Loop for step_end steps\n",
" for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Loop for n simulations\n",
" for j in range(0, n):\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + 0.1 * (t_max/dt)**(0.5) * (2* np.random.random() - 1))\n",
"\n",
" # Compute value of v for this simulation\n",
" v_n[j] = ...\n",
"\n",
" # Plot all simulations (use alpha = 0.1 to make each marker slightly transparent)\n",
" plt.plot(...)\n",
"\n",
" # Display plot\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_04e56444.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Storing_simulations_in_lists_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 9: Plotting sample mean\n",
"\n",
"Add the sample mean $\\left\\langle V(t)\\right\\rangle=\\frac{1}{N}\\sum_{n=1}^N V_n(t)$ to the plot.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to plot sample mean ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to plot the sample mean\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end and n\n",
"step_end = int(t_max / dt)\n",
"n = 50\n",
"\n",
"# Intiatialize the list v_n with 50 values of membrane leak potential el\n",
"v_n = [el] * n\n",
"\n",
"# Initialize the figure\n",
"plt.figure()\n",
"plt.title('Multiple realizations of $V_m$')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Loop for n simulations\n",
" for j in range(0, n):\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + 0.1 * (t_max/dt)**(0.5) * (2* np.random.random() - 1))\n",
"\n",
" # Compute value of v for this simulation\n",
" v_n[j] = v_n[j] + (dt / tau) * (el - v_n[j] + r*i)\n",
"\n",
" # Compute sample mean by summing list of v_n using sum, and dividing by n\n",
" v_mean = ...\n",
"\n",
" # Plot simulations\n",
" plt.plot(n*[t], v_n, 'k.', alpha=0.1)\n",
"\n",
" # Plot sample mean using alpha=0.8 and'C0.' for blue\n",
" plt.plot(...)\n",
"\n",
"# Display plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_684b683f.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Plotting_sample_mean_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 10: Plotting sample standard deviation\n",
"\n",
"Add the sample standard deviation $\\sigma(t)\\equiv\\sqrt{\\text{Var}\\left(t\\right)}$ to the plot, with sample variance $\\text{Var}(t) = \\frac{1}{N-1} \\sum_{n=1}^N \\left(V_n(t)-\\left\\langle V(t)\\right\\rangle\\right)^2$.\n",
"\n",
"Use a list comprehension to collect the sample variance `v_var`. Here's an example to initialize a list with squares of `0` to `9`:\n",
"```\n",
"squares = [x**2 for x in range(10)]\n",
"print(squares)\n",
"--> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n",
"```\n",
"\n",
"Think: Why are we plotting $\\sigma(t)$ rather than the $\\text{Var}(t)$? What are the units of each and the units of $\\left\\langle V(t)\\right\\rangle$?\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to plot sample standard deviation ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to plot the sample standard deviation\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end and n\n",
"step_end = int(t_max / dt)\n",
"n = 50\n",
"\n",
"# Intiatialize the list v_n with 50 values of membrane leak potential el\n",
"v_n = [el] * n\n",
"\n",
"# Initialize the figure\n",
"plt.figure()\n",
"plt.title('Multiple realizations of $V_m$')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(step_end):\n",
"\n",
" # Compute value of t\n",
" t = step * dt\n",
"\n",
" # Loop for n simulations\n",
" for j in range(0, n):\n",
"\n",
" # Compute value of i at this time step\n",
" i = i_mean * (1 + 0.1 * (t_max/dt)**(0.5) * (2* np.random.random() - 1))\n",
"\n",
" # Compute value of v for this simulation\n",
" v_n[j] = v_n[j] + (dt / tau) * (el - v_n[j] + r*i)\n",
"\n",
" # Compute sample mean\n",
" v_mean = sum(v_n) / n\n",
"\n",
" # Initialize a list `v_var_n` with the contribution of each V_n(t) to\n",
" # Var(t) with a list comprehension over values of v_n\n",
" v_var_n = ...\n",
"\n",
" # Compute sample variance v_var by summing the values of v_var_n with sum and dividing by n-1\n",
" v_var = ...\n",
"\n",
" # Compute the standard deviation v_std with the function np.sqrt\n",
" v_std = ...\n",
"\n",
" # Plot simulations\n",
" plt.plot(n*[t], v_n, 'k.', alpha=0.1)\n",
"\n",
" # Plot sample mean using alpha=0.8 and'C0.' for blue\n",
" plt.plot(t, v_mean, 'C0.', alpha=0.8, markersize=10)\n",
"\n",
" # Plot mean + standard deviation with alpha=0.8 and argument 'C7.'\n",
" plt.plot(...)\n",
"\n",
" # Plot mean - standard deviation with alpha=0.8 and argument 'C7.'\n",
" plt.plot(...)\n",
"\n",
"\n",
"# Display plot\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_c05a930d.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Plotting_sample_standard_deviation_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 6: Using NumPy\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 9: Using NumPy\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 9: Using NumPy\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'OIzSQvMbe2k'), ('Bilibili', 'BV1wa4y1a7Xq')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Using_NumPy_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"![NumPy package](https://github.com/NeuromatchAcademy/precourse/blob/main/tutorials/W0D1_PythonWorkshop1/static/numpy_logo_small.png?raw=True)\n",
"\n",
"
\n",
"\n",
"The next set of exercises introduces `np.array`, the workhorse from the scientific computation package [NumPy](https://numpy.org). Numpy arrays the default for numerical data storage and computation and will separate computing steps from plotting.\n",
"\n",
"We updated plots inside the main loop in the previous exercises and stored intermediate results in lists for plotting them. The purpose was to simplify earlier exercises as much as possible. However, there are very few scenarios where this technique is necessary, and you should avoid it in the future. Using numpy arrays will significantly simplify our coding narrative by computing inside the main loop and plotting afterward.\n",
"\n",
"Lists are much more natural for storing data for other purposes than computation. For example, lists are handy for storing numerical indexes and text."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 10: Nano recap of using NumPy\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 10: Nano recap of using NumPy\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'ewyHKKa2_OU'), ('Bilibili', 'BV1of4y197jo')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_using_NumPy_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 11: Rewriting with NumPy\n",
"\n",
"Rewrite the single neuron plot with random input from _Exercise 7_ with numpy arrays.\n",
"\n",
"The time range, voltage values, and synaptic current are initialized or pre-computed as numpy arrays before numerical integration. We use `np.linspace` to initialize a numpy array `t_range` with `num=step_end=150` values from `0` to `t_max`\n",
"We use `np.ones` to initialize a numpy array `v` with `step_end + 1` leak potential values `el`. You will pre-compute `step_end` synaptic current values in numpy array `i` with `np.random.random(step_end)` for `step_end` random numbers. Since `v[0]=el`, we should iterate for `step_end` steps but skip `step=0`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to rewrite simulation in numpy##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to rewrite simulation in numpy\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end, t_range, v\n",
"step_end = int(t_max / dt) - 1\n",
"t_range = np.linspace(0, t_max, num=step_end, endpoint=False)\n",
"v = el * np.ones(step_end)\n",
"\n",
"# Simulate current over time\n",
"i = ...\n",
"\n",
"# Loop for step_end steps\n",
"for step in range(1, step_end):\n",
"\n",
" # Compute v as function of i\n",
" v[step] = ...\n",
"\n",
"\n",
"# Plot membrane potential\n",
"plt.figure()\n",
"plt.title('$V_m$ with random I(t)')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"plt.plot(t_range, v, 'k.')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_66c71ad3.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Rewriting_with_NumPy_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 12: Using enumerate & indexing\n",
"Let's practice using `enumerate` to iterate over the indexes and values of the synaptic current array `i`. We want to get the step and the value of i at that step `i_step`\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to rewrite simulation in numpy##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to rewrite simulation in numpy\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end, t_range, v\n",
"step_end = int(t_max / dt) - 1\n",
"t_range = np.linspace(0, t_max, num=step_end, endpoint=False)\n",
"v = el * np.ones(step_end)\n",
"\n",
"# Simulate current over time\n",
"i = i_mean * (1 + 0.1 * (t_max/dt) ** (0.5) * (2 * np.random.random(step_end) - 1))\n",
"\n",
"# Loop for step_end values of i using enumerate\n",
"for step, i_step in enumerate(i):\n",
"\n",
" # Skip first iteration\n",
" if step==0:\n",
" continue\n",
"\n",
" # Compute v as function of i using i_step\n",
" v[step] = ...\n",
"\n",
"# Plot figure\n",
"plt.figure()\n",
"plt.title('$V_m$ with random I(t)')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"plt.plot(t_range, v, 'k')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_40b5ed28.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Using_enumerate_and_indexing_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Section 7: Aggregation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 11: Aggregation\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 11: Aggregation\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'E6FyhSsO4Vg'), ('Bilibili', 'BV1Uk4y1q76p')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Aggregation_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 12: Nano recap of aggregation\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 12: Nano recap of aggregation\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', '1ME-0rJXLFg'), ('Bilibili', 'BV1vA411e7w4')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Nano_recap_of_aggregation_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 13: Using 2D arrays\n",
"\n",
"Plot multiple realizations ($N=50$) of $V(t)$ by storing the voltage of each neuron at time $t$ in a numpy array.\n",
"\n",
"We first initialize a numpy array `v_n` of shape `(n, step_end)` with membrane leak potential values `el`. We pre-compute synaptic current values in numpy array `i` of shape `(n, step_end)`. After computing v, we plot results with a single plot command, by providing `v_n.T` to the plot function. `v_n.T` is the transposed version of `v_n` (with rows and columns swapped)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to use 2d arrays ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to rewrite code to use 2d arrays\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end, n, t_range, v and i\n",
"step_end = int(t_max / dt)\n",
"n = 50\n",
"t_range = np.linspace(0, t_max, num=step_end)\n",
"v_n = el * np.ones([n, step_end])\n",
"i = ...\n",
"\n",
"# Loop for step_end - 1 steps\n",
"for step in range(1, step_end):\n",
"\n",
" # Compute v_n\n",
" v_n[:, step] = ...\n",
"\n",
"# Plot figure\n",
"plt.figure()\n",
"plt.title('Multiple realizations of $V_m$')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"plt.plot(...)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_93456241.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Using_2D_arrays_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Coding Exercise 14: Plotting sample mean and standard deviation\n",
"\n",
"Add sample mean $\\left\\langle V(t)\\right\\rangle$ and standard deviation $\\sigma(t)\\equiv\\sqrt{\\text{Var}\\left(t\\right)}$ to the plot.\n",
"\n",
"`np.mean(v_n, axis=0)` computes mean over rows, i.e. mean for each neuron\n",
"\n",
"`np.mean(v_n, axis=1)` computes mean over columns (axis `1`), i.e. mean for each time step\n",
"\n",
"We will use label argument in plt.plot to specify labels in each trace. We label only the last voltage trace to avoid labeling all N of them."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"#################################################\n",
"## TODO for students: fill out code to compute sample mean and standard deviation ##\n",
"# Fill out code and comment or remove the next line\n",
"raise NotImplementedError(\"Student exercise: You need to fill out code to compute sample mean and standard deviation\")\n",
"#################################################\n",
"\n",
"# Set random number generator\n",
"np.random.seed(2020)\n",
"\n",
"# Initialize step_end, n, t_range, v and i\n",
"step_end = int(t_max / dt)\n",
"n = 50\n",
"t_range = np.linspace(0, t_max, num=step_end)\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",
"# Loop for step_end - 1 steps\n",
"for step in range(1, step_end):\n",
"\n",
" # Compute v_n\n",
" v_n[:, step] = v_n[:, step - 1] + (dt / tau) * (el - v_n[:, step - 1] + r * i[:, step])\n",
"\n",
"# Compute sample mean (use np.mean)\n",
"v_mean = ...\n",
"\n",
"# Compute sample standard deviation (use np.std)\n",
"v_std = ...\n",
"\n",
"# Plot figure\n",
"plt.figure()\n",
"plt.title('Multiple realizations of $V_m$')\n",
"plt.xlabel('time (s)')\n",
"plt.ylabel('$V_m$ (V)')\n",
"\n",
"plt.plot(t_range, v_n.T, 'k', alpha=0.3)\n",
"\n",
"plt.plot(t_range, v_n[-1], 'k', alpha=0.3, label='V(t)')\n",
"plt.plot(t_range, v_mean, 'C0', alpha=0.8, label='mean')\n",
"plt.plot(t_range, v_mean+v_std, 'C7', alpha=0.8)\n",
"plt.plot(t_range, v_mean-v_std, 'C7', alpha=0.8, label='mean $\\pm$ std')\n",
"\n",
"plt.legend()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/NeuromatchAcademy/precourse/tree/main/tutorials/W0D1_PythonWorkshop1/solutions/W0D1_Tutorial1_Solution_3c8e55c9.py)\n",
"\n",
"*Example output:*\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Plotting_sample_mean_and_standard_deviation_Exercise\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"---\n",
"# Summary\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 13: Overview\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 13: Overview\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'VqAznnSAqmM'), ('Bilibili', 'BV1Fv411q7tE')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Overview_Video\")"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"include_colab_link": true,
"name": "W0D1_Tutorial1",
"provenance": [],
"toc_visible": true
},
"kernel": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.17"
}
},
"nbformat": 4,
"nbformat_minor": 0
}