P2 client w-phase-clock

Phase Clock

Trial phases as unit vectors on a circle, ITC as the length of their average — with the small-N floor drawn beside it, and an added evoked component raising ITC without any phase reset.

4 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.

Phase Clock

mode: default
Loading Phase Clock…

Data: synthetic · license CC-BY-4.0 · synthetic / modified segment · labels: algorithmic · a cropped, re-referenced or filtered derivative of the source recording.

What it does

Three things this widget exists to make visible:

  1. ITC is a mean resultant length. The clock draws each trial’s phase as a unit vector and the ITC as the length of their average. Nothing more.
  2. Its floor is not zero. With N uniformly random phases the expected ITC is √π / (2√N) — about 0.14 at 40 trials — and the widget draws a seeded Monte-Carlo null beside that closed form, so the floor is something you see rather than something you are told.
  3. An added evoked response raises ITC with no phase resetting at all. Adding a fixed component to every trial pulls their measured phases together, so a high ITC on its own does not choose between the two accounts.

Everything runs in the browser. The clock is a pure derived value drawn as inline SVG, so it renders on the server too: the static fallback is a real clock with real numbers.

Two model choices that change the answer, so both are controls

Where the phases come from. pipeline (the default) synthesises noisy trials, Morlet-transforms each one and takes the angle at the burst centre — the path the data file measured its answers with, and the path a real ITC is computed on. It gives 0.971 ± 0.009 at 40 phase-locked trials, because the wavelet sees the background as well as the burst. phasor is the abstract model the identities are stated for — one unit phasor per trial, no noise, no wavelet — and gives exactly 1. Switching the background off inside the pipeline also gives exactly 1, which is what pins the difference on the background rather than on the transform.

How the jitter slider is read. The data file defines phase_jitter_deg as the full width of a uniform draw, so 360° is an exactly uniform draw and 0° is perfect locking. The widget defaults to that and offers the von Mises circular-standard-deviation reading as a named control, because between them is roughly a factor of three in every jitter number. Under the second reading, 180° is nearly uniform but not quite: its resultant is 0.0072, not 0.

Controls

ControlWhat it sets
Trials (N)2–200; raising it appends trials rather than redrawing the ones on the clock
Redraw phases · 40 random · 40 lockedSeeded redraw, and the two ends of L4.5’s exercise as one click each
Phases come frompipeline or phasor
Jitter is read asuniform full width (default) or von Mises circular SD
Phase jitter0–360°, in steps of 5
Mean phase−180…180°; rotates both the ongoing mean and the evoked component. ITC does not change, which is worth seeing
Added amplitude0–40 µV of evoked component, identical on every trial and never jittered
Ongoing burst · Background0–40 µV each
Clock showsUnit phase vectors (what ITC sees) or the trials at their true complex positions
Surrogates · α500 / 2000 / 10000 surrogates in the Monte-Carlo null; α for its critical value
PanelsThe null distribution; the bias curve

Every number it prints

Read-outDefinition
ITCthe length of (1/N)·Σ exp(iθ) over the trial phases — exactly 1 for identical phases, exactly 0 for phases spread evenly around the circle
Expected ITC of uniformly random phases√π / (2√N), the Rayleigh large-N limit, and labelled as a limit — 0.1401 at N = 40
Exact RMS ITC under the same null1/√N, exact at every N from E[ITC²] = 1/N — 0.1581 at N = 40
Standard deviation of that null√((1 − π/4)/N) — 0.0732 at N = 40, large enough that one draw is not the expectation
Rayleigh critical ITC at p = .05√(−ln 0.05 / N) — 0.2737 at N = 40
Bias-corrected ITC√( max(0, (N·ITC² − 1)/(N − 1)) ), from inverting E[ITC²] = R² + (1 − R²)/N. The estimator of R² is unbiased, its square root is not, and it is clamped at 0 — both facts printed beside it
Rayleigh z, pz = N·ITC², p = exp(−z), printed beside a Monte-Carlo p from surrogates at the same N
Monte-Carlo p(surrogates ≥ observed + 1) / (surrogates + 1)
Mean single-trial powerMeasured, beside the noise-free model’s 1 + ρ² + 2ρR
Amplitude of the complex average|mean z| — the evoked response, which keeps the amplitudes and is therefore not the ITC

What to look for

  • Open on the default — 40 trials, uniform phase, no evoked component — and read the ITC. It is not 0; it is around 0.14, and the opening draw is whatever it is. That is not a bug and not a weak effect: it is what chance looks like at 40 trials.
  • Press Redraw a few times and watch the value move. The null has a standard deviation of 0.073 at this N, so a first look near 0.06 or near 0.22 is ordinary scatter. This is exactly why L4.5 asks what ITC you expect rather than what the widget shows.
  • Drag the trial count and watch the floor move against the law drawn beside it. The expected ITC of random phases falls as 1/√N, so it halves only when N quadruples. Any ITC you report has to be read against the floor for the N you had.
  • Switch to a von Mises distribution and pull the jitter to zero. Every arrow lands on the same spot and the ITC is exactly 1 in the phasor model; in the pipeline it stops at about 0.97, because the wavelet also sees the background. The bias-corrected read-out barely moves here — at high coherence there is almost nothing to correct.
  • Now the important one: go back to uniform phase and raise the evoked amplitude. No trial has had its phase reset — the ongoing oscillation is as random as it was — and yet the arrows swing toward the evoked vector and ITC climbs, from 0.137 at 0 µV to 0.626 at 20 µV. A high ITC does not tell you a phase reset happened.
  • Watch the mean single-trial power while you do it. It rises too, because a fixed vector was added; under a pure phase reset it would not. That difference is the usual argument for telling the two accounts apart — and it is an argument, not a proof, which is why the panel says so.

Used in

  • L4.5 Phase, ITC and cross-frequency coupling (default)

Data provenance

Synthetic. /data/widgets/w-phase-clock/fixtures.json, written by data/scripts/make_phase_fixtures.py, carries parameters only and is marked synthetic: true with derived_from: "none (generated)" and a full modifications list. The generative model is the same as w-evoked-vs-induced’s: 250 Hz, epoch −1.0 … 1.5 s, a 20 µV burst at 10 Hz with 7 cycles (σ = 0.111408 s) centred at 0.3 s, a 1/f^1.343 background at 19.8 µV standard deviation, seed 20260918, plus an evoked block — a fixed, identical 10 Hz burst added to every trial with no jitter, which is the additive-evoked account of L4.5. ITC is read at 10 Hz with 7 cycles at the burst centre.

The background’s exponent and amplitude are medians read at build time from the shipped widgets/w-aperiodic-explorer/psds.json (12 ds-eegbci subjects at O1, eyes-open, specparam 2.0.0rc4), not invented.

The file records its own measurements with their spreads — 0.140 ± 0.074 for random phase over 2000 direct phase draws, 0.97 ± 0.008 for phase-locked over 400 pipeline runs, and the additive sweep 0.137 / 0.151 / 0.184 / 0.229 / 0.306 / 0.453 / 0.626 at 0, 2.5, 5, 7.5, 10, 15 and 20 µV of added component with the jitter held at 360°. Because the browser uses its own seeded generator, the widget reproduces those distributions rather than the script’s individual realisations, which is why the answer key is set against the distribution.

The claim that carries a TODO(confirm)

Adding a fixed component to every trial raises ITC with no phase resetting whatever. That is arithmetic, and the widget computes it. It also raises the mean single-trial power, while a pure phase reset would not — and whether that difference is usable as evidence in real recordings is argued about in the literature rather than settled. The widget says so in the panel, with a literal TODO(confirm) on the inference and not on the numbers.

Open the code

site/src/components/widgets/w-phase-clock/Widget.svelte, circular.ts (both jitter laws, von Mises sampling, and the ITC identities including E[ITC²] = R² + (1 − R²)/N and the de-biasing inverse), pipeline.ts, morlet.ts, compute.ts, data.ts, synthetic.ts, state.ts, plots.ts, and 69 tests. Repository link: TODO(confirm) (GitHub org/repo, §13 item 3).

TODO(confirm): screenshot.png is not yet a real capture of the running widget.