Improve phase wheel averaging

This commit is contained in:
Mikei386
2026-07-22 09:40:49 +02:00
parent 4379b78b8f
commit 97352ecfce
2 changed files with 91 additions and 6 deletions
+44
View File
@@ -0,0 +1,44 @@
import assert from 'node:assert/strict';
import fs from 'node:fs';
import vm from 'node:vm';
const source = fs.readFileSync(new URL('../www/views/phase_wheel.js', import.meta.url), 'utf8');
const functionSource = source.match(/export function summarizeWeightedPhase[\s\S]*?\n\}/)?.[0];
assert.ok(functionSource, 'weighted phase summary must remain testable');
const context = vm.createContext({ Number, Math });
vm.runInContext(functionSource.replace('export function', 'function'), context);
const dominant = context.summarizeWeightedPhase(
new Float32Array([0, Math.PI / 2]),
new Float32Array([100, 1]),
2,
);
assert.ok(dominant, 'valid weighted phases must produce a summary');
assert.ok(Math.abs(dominant.angle) < 0.02,
'a quiet phase component must not pull a dominant component toward an unweighted mean');
const wrapped = context.summarizeWeightedPhase(
new Float32Array([179 * Math.PI / 180, -179 * Math.PI / 180]),
new Float32Array([1, 1]),
2,
);
assert.ok(Math.abs(Math.abs(wrapped.angle) - Math.PI) < 0.02,
'circular averaging must preserve the wrap around at 180 degrees');
assert.ok(wrapped.coherence > 0.99,
'nearly aligned phase observations must report high coherence');
const opposed = context.summarizeWeightedPhase(
new Float32Array([0, Math.PI]),
new Float32Array([1, 1]),
2,
);
assert.ok(opposed.coherence < 1e-6,
'opposing phase observations must report that their mean direction is ambiguous');
assert.equal(context.summarizeWeightedPhase(
new Float32Array([0]),
new Float32Array([0]),
1,
), null, 'samples without common L/R energy must not invent a phase angle');
console.log('phase wheel regression tests passed');