P2 client w-volume-conduction-sim

Volume Conduction Sim

Put one or two sources inside a conducting sphere, watch them arrive at every electrode at once, and read the coherence matrix that produces.

2 claims on this page are unverified. TODO(confirm) marks a specific statement the author has not yet checked against a primary source. Everything else on this page has been reviewed. Treat a marked claim as provisional and go to the cited source rather than quoting the sentence.

Modes: default — the widget below runs in default. Use Share state to put the exact view in the URL.

Volume Conduction Sim

mode: default
Loading Volume Conduction Sim…

Data provenance is recorded in each asset's sidecar under /data/widgets/w-volume-conduction-sim/.

What it does

A homogeneous conducting sphere — 9 cm radius, conductivity 0.33 S/m — with 21 electrodes on its surface: the classic 19 of the 10-20 system plus Fpz and Oz, taken from a standard template montage and projected onto the sphere. You place one or two current dipoles inside it, choose how each one oscillates, add a background, and the widget simulates the sensor time series through an analytic forward model and computes the coherence matrix over every pair of electrodes, live.

Everything is computed in the browser from a seeded simulation: there is no recording anywhere in this lab, and the shipped fixtures.json supplies the sphere, the montage, four named source configurations and a set of MNE-computed potentials used to check the widget’s own physics.

The one number the widget exists to show is that with a single source and no noise, the coherence between every pair of sensors is exactly 1 — including the two furthest apart on the head. That is not a simulation artifact and not a property of this montage; L5.1 derives it. Everything else in the widget is about what happens when you try to make it go away.

Controls

ControlWhat it sets
Number of sourcesOne or two dipoles inside the sphere
ConfigurationApplies one of the named presets from fixtures.json — one superficial source, one deep source, two independent sources, two sources with a true lag
Source waveformA pure tone, or seeded narrowband noise with an adjustable bandwidth. Narrowband draws an independent waveform per source, which is what makes a genuine two-source comparison possible
Per sourcePosition (depth below the scalp, azimuth, elevation), orientation (radial to tangential, and the direction of the tangential component), dipole moment in nA·m, frequency, phase
BackgroundIndependent sensor noise in µV, or a set of independent dipoles placed inside the sphere and scaled to a requested mean sensor RMS
SeedThe seeded PRNG behind every random draw, so any view is reproducible
Record length, segment lengthThe simulated duration and the Welch segment length. Segments are non-overlapping, so K, the number of averaged segments, is their ratio — and K sets the independence floor
Analysis frequencyThe frequency the matrix is read at (0 means the first source’s frequency)
Matrix viewMagnitude-squared coherence, or the magnitude of the imaginary part of coherency
Sensor pairThe highlighted pair, chosen from two selects or by clicking a cell
Show tracesThe two highlighted sensors’ time series above the matrix

The simulation runs at a fixed 250 Hz: this widget is about mixing, not about sampling. The whole matrix is also available as a table, and so are the per-sensor amplitudes, so nothing here depends on reading colours.

What to look for

default

  • With one source and the noise at zero, every cell is 1.000 — including the pair of sensors furthest apart on the head. One generator, seen by every sensor, looks like a head full of perfectly connected sites.
  • The two traces above the matrix have very different amplitudes. The sensor near the source gets much more of it than the sensor across the head; coherence does not care about amplitude, only about whether the two move together.
  • This is not about sinusoids. Every sensor is a scaled copy of the same waveform, so the coherence is 1 whatever that waveform is; the tone is only there so the analysis frequency is somewhere definite.
  • Raise the sensor noise and the coherence falls, faster at the sensor that was getting less signal. The prediction printed beside the estimate is the share of each sensor’s power that came from the source, multiplied together — so a lower value here means worse signal-to-noise, not less connection.
  • Watch the independence floor in the read-out. With K averaged segments, two unrelated signals give about 1/K, not 0. Shorten the record or lengthen the segments and the floor rises; a coherence of 0.2 measured from five segments is what nothing looks like.
  • Switch the background to independent brain sources. They are independent where they are generated and still arrive mixed at the scalp, so the sensor coherence stays well above the floor. You cannot assume the background away.
  • Switch the matrix to the imaginary part of coherency. With one source it is zero everywhere, because instantaneous mixing has no lag to find. Give a second source at the same frequency a phase difference and the imaginary part comes alive while the magnitude stays at 1.
  • Two noiseless tones at one frequency are perfectly coherent by construction, so that configuration cannot show independence. Switch the waveform to narrowband for a real two-source comparison: the two most distant sensors still agree strongly, from two generators that share nothing.

Used in

  • L5.1 Volume conduction: the central problem (default)

Data provenance

No recorded data. fixtures.json is a JSON-only synthetic asset generated by data/scripts/make_vc_fixtures.py with MNE 1.10.2. It carries the sphere parameters, the 21-site montage (electrode positions from MNE’s standard_1005, re-centred on a least-squares sphere fitted to all of its electrodes, normalised and scaled), four named source configurations, the simulation and coherence defaults, and MNE-computed potentials for four dipoles used as a cross-check. It declares synthetic: true with derived_from and modifications, carries generated_by, generated_at and license at the top level, and is listed in the asset manifest with its SHA-256 and size, under the site’s own CC BY 4.0 terms.

Two honest limits on what the simulation represents:

  • The sphere is homogeneous: no skull, no CSF, no scalp layer. A real head attenuates and blurs more than this, so the mixing shown here is, if anything, an understatement. The four-shell comparison is in w-dipole-to-scalp’s forward mode and in L5.4.
  • The dipole moments are chosen for legibility, not physiology. The defaults put scalp amplitudes in the tens of microvolts, which is the range a learner recognises. TODO(confirm): the moment a cortical patch of a given size actually carries is a physiological number this site has not sourced, and a skull-free sphere produces a larger scalp potential per unit moment than a real head would.

The widget’s forward model is the same module w-dipole-to-scalp uses rather than a second implementation, and its unit tests reproduce the MNE-computed potentials in fixtures.json to a worst case of 0.016 % of each row’s peak.

Open the code

site/src/components/widgets/w-volume-conduction-sim/Widget.svelte, index.ts, meta.ts, the physics and coherence modules, README.md, and the test suite that pins every number quoted in L5.1. Repository link: TODO(confirm) (GitHub org/repo).