{"id":421,"date":"2017-08-02T03:16:25","date_gmt":"2017-08-02T02:16:25","guid":{"rendered":"http:\/\/www.billconnelly.net\/?p=421"},"modified":"2025-07-05T04:15:09","modified_gmt":"2025-07-05T03:15:09","slug":"neuronal-modelling-the-very-basics-part-1","status":"publish","type":"post","link":"https:\/\/www.billconnelly.net\/?p=421","title":{"rendered":"Neuronal Modelling &#8211; The very basics. Part 1."},"content":{"rendered":"<p>I think a lot of people are confused about neuronal modelling. I think a lot of people think it is more complex than it is. I think too many people think you have to be a mathematical or computational wizard to understand it, and I think that leads to a lot of good modelling being discounted and a lot of bad modelling being let through peer-review. I&#8217;m here to tell you that biophysical models on neurons don&#8217;t have to be hard to implement, or understand. I&#8217;m going to start you off on the ground floor, in fact, below the ground floor, this is the basement level. All you need to know is a little coding (I&#8217;m going to do both Matlab and Python to start). But I should temper your expectations. When we are done, you&#8217;re not going to be ready to publish fully fledged multi-compartment models of neurons, but at least you will understand the fundamental principles of what is happening. And the most fundamental of all is this&#8230;<\/p>\n<div align=\"center\">$latex \\frac{\\mathrm{d}v}{\\mathrm{d}t} = \\frac{i}{C} &#038;s=4$<\/div>\n<p><!--more--><\/p>\n<p>Before I get started, I just want to say, that if you know what a Jacobian Matrix is, or what Runge\u2013Kutta methods are, this post is not for you. This is neuronal modelling for people at the back of the class.<\/p>\n<p>As I said above, the most fundamental equation in all of this is this:<\/p>\n<div align=\"center\">$latex \\frac{\\mathrm{d}v}{\\mathrm{d}t} = \\frac{i}{C} &#038;s=1$<\/div>\n<p>Which is saying &#8220;The rate at which the membrane potential changes is equal to the current flowing, divided by the capacitance of the cell&#8221;. But to make it even more clear, let&#8217;s look into the left part of the equation: $latex \\frac{\\mathrm{d}v}{\\mathrm{d}t} $ which may already be scaring you. I want you to treat this as just a normal fraction, just like $latex \\frac{1}{2} $ where the symbol $latex \\mathrm{d} $ just means &#8220;a little bit of&#8221; so  $latex \\frac{\\mathrm{d}v}{\\mathrm{d}t} $ means &#8220;a little bit of v divided by a little bit of t&#8221;, where v is voltage and t is time. So what we&#8217;re saying is, in a little bit of time, how much does v change? Because we&#8217;re treating $latex \\frac{\\mathrm{d}v}{\\mathrm{d}t} $ as a simple fraction, we can just multiply each side by $latex \\mathrm{d}t $ and get the equation<\/p>\n<div align=\"center\">$latex \\mathrm{d}v = \\frac{i}{C} \\times \\mathrm{d}t &#038;s=1$<\/div>\n<p>So what we are saying is: &#8220;The amount that the membrane potential changes (in a small amount of time) is equal to the current flowing, divided by the capacitance of the cell multiplied by that small amount of time. And THAT is basically what all neuronal models perform: for each compartment of the cell, it calculates what i is, then performs that computation. What you might notice is that we&#8217;re only talking about how the membrane potential <strong>changes<\/strong>, not what it actually <strong>is<\/strong>. And because of that, we need to choose where the membrane potential begins or what is called &#8220;the initial conditions&#8221;.<\/p>\n<p>With that knowledge in mind, let&#8217;s convert this mathematics to code and get started with becoming computational neuroscientists.<br \/>\n<br \/>\n<strong>Matlab<\/strong><\/p>\n<pre class=\"prettyprint linenums\">\r\n% Basic simulation Properties\r\ndt     = 10E-6;     % 10 us timestep\r\n\r\n% Basic Cell Properties\r\nCm     = 100E-12;   % Membrane Capacitance = 100 pF\r\nv_init = -70E-3;    % Initial membrane potential -70 mV\r\n\r\n% Injected Current step\r\ncurrent_magnitude = 100E-12; % 100 pA \r\n\r\n%Injected current, 0.2 seconds of 0 current, 0.3 seconds of some current,\r\n%and 0.5 seconds of no current\r\ni_inj = &#91;zeros(round(0.2&#47;dt),1);\r\n         current_magnitude*ones(round(0.3&#47;dt), 1);\r\n         zeros(round(0.5&#47;dt), 1)&#93;;\r\n\r\n%Preallocate the voltage output\r\nv_out = zeros(size(i_inj));\r\n\r\n%The real computational meat\r\nfor t = 1:length(v_out)\r\n    if t == 1\r\n        v_out(t) = v_init; %At the first time step, set voltage to the initial condition\r\n    else\r\n        i_cap = i_inj(t);       %Calculate what i is\r\n        dv = i_cap&#47;Cm * dt;     %Calculate dv, using our favourite equation\r\n        v_out(t) = v_out(t-1) + dv;     %add dv on to our last known voltage\r\n    end\r\nend\r\n\r\n%Make the graph\r\nt_vec = dt*&#91;1:length(v_out)&#93;;\r\nplot(t_vec,v_out);\r\nxlabel(&#39;Time (s)&#39;)\r\nylabel(&#39;Membrane Potential (V)&#39;)\r\n<\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre class=\"prettyprint linenums\">\r\nimport matplotlib.pyplot as plt\r\nimport numpy as np\r\n\r\n# Basic simulation Properties\r\ndt     = 10E-6;     # 10 us timestep\r\n\r\n# Basic Cell Properties\r\nCm     = 100E-12;   # Membrane Capacitance = 100 pF\r\nv_init = -70E-3;    # Initial membrane potential -70 mV\r\n\r\n# Injected Current step\r\ncurrent_magnitude = 100E-12; # 100 pA\r\n\r\n#Injected current, 0.2 seconds of 0 current, 0.3 seconds of some current,\r\n#and 0.5 seconds of no current\r\ni_inj = np.concatenate( (np.zeros(&#91;round(0.2&#47;dt),1&#93;),\r\n                         current_magnitude*np.ones(&#91;round(0.3&#47;dt), 1&#93;),\r\n                         np.zeros(&#91;round(0.5&#47;dt), 1&#93;)) )\r\n\r\n#Preallocate the voltage output\r\nv_out = np.zeros(np.size(i_inj))\r\n\r\n#The real computational meat\r\nfor t in range(np.size(v_out)):\r\n    if t == 0:\r\n        v_out&#91;t&#93; = v_init; #At the first time step, set voltage to the initial condition\r\n    else:\r\n        i_cap = i_inj&#91;t&#93;;       #Calculate what i is\r\n        dv = i_cap&#47;Cm * dt;     #Calculate dv, using our favourite equation\r\n        v_out&#91;t&#93; = v_out&#91;t-1&#93; + dv;     #add dv on to our last known voltage\r\n\r\n#Make the graph\r\nt_vec = np.linspace(0, 1, np.size(v_out))\r\nplt.plot(t_vec, v_out)\r\nplt.xlabel(&#39;Time (s)&#39;)\r\nplt.ylabel(&#39;Membrane Potential (V)&#39;)\r\nplt.show()\r\n<\/pre>\n<p><a href=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation1-300x267.png\" alt=\"simulation1\" width=\"300\" height=\"267\" class=\"alignright size-medium wp-image-428\" srcset=\"https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation1-300x267.png 300w, https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation1.png 576w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Despite the length of that code, all the import stuff is happening in the for loop. At the first time point we set the voltage equal to the initial voltage, and from then on at each time point we calculate the new voltage by adding something (dv) onto the previous voltage. Now you may be looking at the voltage trace and thinking that it doesn&#8217;t look very neuronal. Well that is because we have no ion channels. In order to include ion channels, we need to know how they behave. The standard model for an ion channel starts with this simple formula:<\/p>\n<div align=\"center\"> $latex I_X = G_X \\times (V_M &#8211; E_X)  &#038;s=2$<\/div>\n<p><a href=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/Icap-Iion.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/Icap-Iion-300x228.png\" alt=\"Icap-Iion\" width=\"300\" height=\"228\" class=\"alignright size-medium wp-image-432\" srcset=\"https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/Icap-Iion-300x228.png 300w, https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/Icap-Iion.png 623w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Where we are saying the ionic current for an ion channel X ($latex I_X$), is equal to the conductance of the ion channel ($latex G_X$), multiplied by the driving force, where the driving force is the membrane potential ($latex V_M$) minus the reversal potential of that ion channel ($latex E_X$). To include this into our model, we need to think very carefully about the direction of that current. That is to say, when $latex I_X$ is positive, is that current going to make the membrane potential more positive, or more negative? Well let&#8217;s think about it, let&#8217;s imagine an EPSP: if Vm is -70 mV and the reversal potential is 0 mV, and lets say the conductance is 1 nS. So the current will be -70 nA. Now we know an EPSP must depolarize a cell, but if we plug a negative current into our favourite equation $latex \\mathrm{d}v = \\frac{i}{C} \\times \\mathrm{d}t $ we would get a negative $latex \\mathrm{d}v $, meaning that the current would hyperpolarize the cell. This is due to the fact that $latex I_X = G_X \\times (V_M &#8211; E_X) $ calculates the current through the ion channel, which is equal and opposite to the current going through the membrane capacitor.<\/p>\n<p>So with that understanding of how ion channels behave, let&#8217;s include a leak potassium current (i.e. the conductance doesn&#8217;t vary over time or voltage).<br \/>\n<br \/>\n<strong>Python<\/strong> Important additions on lines 30 and 31<\/p>\n<pre class=\"prettyprint linenums\">\r\nimport matplotlib.pyplot as plt\r\nimport numpy as np\r\n\r\n# Basic simulation Properties\r\ndt     = 10E-6;     # 10 us timestep\r\n\r\n# Basic Cell Properties\r\nCm     = 100E-12;   # Membrane Capacitance = 100 pF\r\nv_init = -70E-3;    # Initial membrane potential -70 mV\r\nGk     = 5E-9       # 5 nS conductance\r\nEk     = -90E-3     # Reversal potential of -90 mV\r\n\r\n# Injected Current step\r\ncurrent_magnitude = 100E-12; # 100 pA\r\n\r\n#Injected current, 0.2 seconds of 0 current, 0.3 seconds of some current,\r\n#and 0.5 seconds of no current\r\ni_inj = np.concatenate( (np.zeros(&#91;round(0.2&#47;dt),1&#93;),\r\n                         current_magnitude*np.ones(&#91;round(0.3&#47;dt), 1&#93;),\r\n                         np.zeros(&#91;round(0.5&#47;dt), 1&#93;)) )\r\n\r\n#Preallocate the voltage output\r\nv_out = np.zeros(np.size(i_inj))\r\n\r\n#The real computational meat\r\nfor t in range(np.size(v_out)):\r\n    if t == 1:\r\n        v_out&#91;t&#93; = v_init; #At the first time step, set voltage to the initial condition\r\n    else:\r\n        i_ion = Gk * (v_out&#91;t-1&#93; - Ek)  #Calculate the current through ion channels\r\n        i_cap = i_inj&#91;t&#93; - i_ion;       #Calculate what i is\r\n        dv = i_cap&#47;Cm * dt;     #Calculate dv, using our favourite equation\r\n        v_out&#91;t&#93; = v_out&#91;t-1&#93; + dv;     #add dv on to our last known voltage\r\n\r\n#Make the graph\r\nt_vec = np.linspace(0, 1, np.size(v_out))\r\nplt.plot(t_vec, v_out)\r\nplt.xlabel(&#39;Time (s)&#39;)\r\nplt.ylabel(&#39;Membrane Potential (V)&#39;)\r\nplt.show()\r\n<\/pre>\n<p><strong>Matlab<\/strong> Important additions on lines 25 and 26<\/p>\n<pre class=\"prettyprint linenums\">\r\n% Basic simulation Properties\r\ndt     = 10E-6;     % 10 us timestep\r\n\r\n% Basic Cell Properties\r\nCm     = 100E-12;   % Membrane Capacitance = 100 pF\r\nv_init = -70E-3;    % Initial membrane potential -70 mV\r\nGk     = 5E-9;       % 5 nS conductance\r\nEk     = -90E-3;     % Reversal potential of -90 mV\r\n\r\n% Injected Current step\r\ncurrent_magnitude = 100E-12; % 100 pA \r\n\r\n%Injected current, 0.2 seconds of 0 current, 0.3 seconds of some current,\r\n%and 0.5 seconds of no current\r\ni_inj = &#91;zeros(round(0.2&#47;dt),1); current_magnitude*ones(round(0.3&#47;dt), 1); zeros(round(0.5&#47;dt), 1)&#93;;\r\n\r\n%Preallocate the voltage output\r\nv_out = zeros(size(i_inj));\r\n\r\n%The real computational meat\r\nfor t = 1:length(v_out)\r\n    if t == 1\r\n        v_out(t) = v_init; %At the first time step, set voltage to the initial condition\r\n    else\r\n        i_ion = Gk * (v_out(t-1) - Ek); %Calculate the current through ion channels\r\n        i_cap = i_inj(t) - i_ion;       %Calculate what i is\r\n        dv = i_cap&#47;Cm * dt;     %Calculate dv, using our favourite equation\r\n        v_out(t) = v_out(t-1) + dv;     %add dv on to our last known voltage\r\n    end\r\nend\r\n\r\n%Make the graph\r\nt_vec = dt*&#91;1:length(v_out)&#93;;\r\nplot(t_vec,v_out);\r\nxlabel(&#39;Time (s)&#39;)\r\nylabel(&#39;Membrane Potential (V)&#39;)\r\n<\/pre>\n<p><a href=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation21.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation21.png\" alt=\"simulation2\" width=\"668\" height=\"564\" class=\"aligncenter size-full wp-image-460\" srcset=\"https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation21.png 668w, https:\/\/www.billconnelly.net\/wp-content\/uploads\/2017\/08\/simulation21-300x253.png 300w\" sizes=\"(max-width: 668px) 100vw, 668px\" \/><\/a> Now <em>that<\/em> looks more like a neuron. A pretty dull neuron, with no action potentials, but at least we&#8217;re getting there. And how do we put in action potentials? Well we have to go and talk to two people: Hodgkin and Huxley. And we&#8217;re going to talk to them in <a href=\"http:\/\/www.billconnelly.net\/?p=440\">part 2<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I think a lot of people are confused about neuronal modelling. I think a lot of people think it is more complex than it is. I think too many people think you have to be a mathematical or computational wizard to understand it, and I think that leads to a lot of good modelling being&hellip;<a href=\"https:\/\/www.billconnelly.net\/?p=421\">Read more <span class=\"screen-reader-text\">Neuronal Modelling &#8211; The very basics. Part 1.<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[7,6],"tags":[],"_links":{"self":[{"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/posts\/421"}],"collection":[{"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=421"}],"version-history":[{"count":21,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/posts\/421\/revisions"}],"predecessor-version":[{"id":458,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=\/wp\/v2\/posts\/421\/revisions\/458"}],"wp:attachment":[{"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.billconnelly.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}