<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Neuroscience |</title><link>https://biomedicaldata.science/tags/neuroscience/</link><atom:link href="https://biomedicaldata.science/tags/neuroscience/index.xml" rel="self" type="application/rss+xml"/><description>Neuroscience</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Tue, 08 Sep 2026 00:00:00 +0000</lastBuildDate><image><url>https://biomedicaldata.science/media/icon.svg</url><title>Neuroscience</title><link>https://biomedicaldata.science/tags/neuroscience/</link></image><item><title>A Virtual Electrophysiology Lab, rebuilt for the browser</title><link>https://biomedicaldata.science/blog/virtual-electrophysiology-lab/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://biomedicaldata.science/blog/virtual-electrophysiology-lab/</guid><description>&lt;p&gt;&lt;em&gt;From a 2019 Colab notebook to a validated, zero-install interactive lab&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Back in 2019, teaching Electrophysiology of the Central Nervous System, I built a Google Colab
notebook to give students something to interact with instead of just static slides: adjust ion
concentrations and watch the equilibrium potential update, compare RC charge/discharge curves for
different cell sizes, isolate a noisy signal with a Butterworth filter. It worked, but it needed a
Google account, Colab&amp;rsquo;s &lt;code&gt;#@param&lt;/code&gt; form fields, and a Bokeh widget API that&amp;rsquo;s been deprecated for
several major releases now. It was also entirely in Portuguese.&lt;/p&gt;
&lt;p&gt;This month I rebuilt it properly. Try it below.&lt;/p&gt;
&lt;div style="border:1px solid rgba(128,128,128,0.25); border-radius:10px; overflow:hidden; margin:2rem 0;"&gt;
&lt;iframe src="https://biomedicaldata.science/demos/electrophysiology-lab/" style="width:100%; height:900px; border:0; display:block;" loading="lazy" title="Virtual Electrophysiology Lab"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;h2 id="what-changed"&gt;What changed&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Language and stack.&lt;/strong&gt; Everything is in English now, and there are two independent
implementations of the same three modules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;zero-install browser version&lt;/strong&gt; (embedded above) — vanilla JS and hand-drawn SVG charts, no
frameworks, no build step.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Python package +
app&lt;/strong&gt; — the physics factored out into
small, tested functions with no plotting or widget imports at all, so they&amp;rsquo;re trivial to reuse
or verify independently of the UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both are on GitHub: &lt;strong&gt;
&lt;/strong&gt;.
The original 2019 notebook is kept in the repo&amp;rsquo;s &lt;code&gt;original/&lt;/code&gt; folder, unmodified, for anyone
curious what &amp;ldquo;before&amp;rdquo; looked like.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A from-scratch Butterworth filter, checked against SciPy.&lt;/strong&gt; The signal-filtering module needed
a 6th-order zero-phase Butterworth filter running client-side, in the browser, with no
dependencies. Rather than approximate one, I implemented the actual filter design pipeline —
analog prototype poles, the bilinear transform, &lt;code&gt;filtfilt&lt;/code&gt;&amp;rsquo;s zero-phase forward/backward pass with
proper edge handling — in plain JavaScript, then validated it numerically against
&lt;code&gt;scipy.signal.butter&lt;/code&gt; + &lt;code&gt;filtfilt&lt;/code&gt; on the same test signal. It matches to less than 1e-8 absolute
error across the filter&amp;rsquo;s usable cutoff range. The Python repo runs the real &lt;code&gt;scipy&lt;/code&gt; call, so both
versions agree by construction, not by eyeballing two plots that happen to look similar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Testing.&lt;/strong&gt; The Python package has a small pytest suite checked against the textbook reference
values from the original notebook (Na⁺, K⁺, and Cl⁻ equilibrium potentials; the two reference
cells&amp;rsquo; RC time constants), with CI running on every push.&lt;/p&gt;
&lt;h2 id="the-three-modules"&gt;The three modules&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Equilibrium potential&lt;/strong&gt; — the Nernst potential of an ion as a function of its valence and the
concentration ratio across the membrane, with live-updating bars for Na⁺, K⁺, and Cl⁻ against
their textbook physiological concentrations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Passive membrane properties&lt;/strong&gt; — the RC time constant of the neuronal membrane, comparing
charge/discharge curves between a large and a small reference cell (and a fully custom one, on
log-scale sliders spanning both).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Electronic filters&lt;/strong&gt; — a composite signal made of three sine waves, with low-pass/high-pass
filtering to isolate the low-frequency signal from simulated high-frequency noise, exactly the
kind of thing you actually do to a real electrophysiological recording.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you use this for teaching or reference, both the code (MIT) and the instructional text/exercises
(CC BY-NC 4.0) are free to reuse — the
has the details.&lt;/p&gt;</description></item></channel></rss>