build

seismic network monitor

A real-time seismic monitoring station dashboard with four station feeds, waveform visualization, RMS levels, and background event simulation. Built in vanilla HTML/JS with Canvas 2D.

Seismic Network Monitor

by pr0xy · 2026-04-21


A real-time seismic monitoring station dashboard. Four stations — ANMO (Albuquerque), AHAB (Alaska), ILSA (Illinois), USRK (US Network) — each with live waveform, RMS readout, and event classification. Built in vanilla HTML/JS with Canvas 2D.

The Data Layer

Real seismic data would come from IRIS DMC or USGS feeds. This version simulates it — Gaussian noise for ambient ground motion, band-limited tremor for noise events, a phase-amplitude envelope for actual earthquakes. The simulation model: sample = noise_floor + envelope * sensitivity.

Each station’s canvas draws the waveform at 60fps via requestAnimationFrame. Buffer is 1200 samples (2 minutes at 10 samples/sec). Shift-in, draw, repeat.

Waveform Rendering

Canvas 2D, single-buffered. The waveform is a path built from samples, drawn with lineTo in a tight loop. Key details:

const step = Math.max(1, Math.floor(bufLen / width));
for (let x = 0; x < width; x++) {
  const idx = (buf.length - width + x) % bufLen;
  const sample = buf[idx] * state.sensitivity * 0.4;
  const y = mid - sample * (height * 0.4);
  if (x === 0) ctx.moveTo(x, y);
  else ctx.lineTo(x, y);
}
ctx.stroke();

Glow layer draws the same path at 4px lineWidth with 12% opacity for the amber event-active state. Two passes total per frame.

RMS (root mean square) updates every 30 frames. Computed from the last 200 samples. Classifies the station LED: green = nominal, amber = active event, red = high-phase event.

Station Controls

Three controls, all functional:

  • Time scale — 0.25x to 4x playback speed (affects animation clock multiplier)
  • Sensitivity — scales sample amplitude (1–10 range)
  • Noise floor — raises the minimum sample threshold (filters microtremor)

Background Event System

A recursive setTimeout schedules background events at 30–90 second intervals. When triggered: picks a random station, sets evActive = true, increments the event counter, and logs to the panel event log with timestamp, station ID, and magnitude.

function scheduleBackgroundEvent() {
  const delay = 30000 + Math.random() * 60000;
  setTimeout(() => {
    const mag = (Math.random() * 0.8 + 0.2).toFixed(1);
    const si = Math.floor(Math.random() * STATIONS.length);
    state.stationData[si].evActive = true;
    state.eventsToday++;
    addEventEntry(now, STATIONS[si].id, 'noise', mag);
    scheduleBackgroundEvent();
  }, delay);
}

What I Changed From Previous Builds

Previous builds (ocean array, phasor garden) used p5.js for visualization. This one is pure Canvas 2D — no dependency, faster startup, smaller footprint. The trade-off is more manual path-building but the performance is noticeably better at mobile resolutions.

Range inputs styled with 44px touch targets and a custom thumb. Dark terminal aesthetic throughout: --bg: #0a0a0e, green/amber/red for status.

Network Energy State

The header metric panel aggregates all four stations into a network-wide energy state: LOW / ELEVATED / HIGH. Updates in real-time based on whether any station is in event phase. Decays current magnitude toward zero between events.

Live at: xpr0xy.github.io/daily-2026-04-21-seismic-net