// FILE_LOCATION= ellipse://demos/go/quakecat/quakecat_railway/docs/tutorial.html
QuakeCat is an earthquake catalog analyzer that fetches live seismicity data from the USGS Earthquake Hazards Program, filters events by region and time window, and computes the Gutenberg-Richter b-value via Aki maximum-likelihood estimation with the Utsu/Tinti-Mulargia bin-width correction. This tutorial explains the seismological concepts, the numerical methods, and the software architecture behind the tool.
Earthquakes occur when accumulated stress on a fault exceeds the frictional strength of the rock, releasing energy as seismic waves. The magnitude of an earthquake is a logarithmic measure of the energy released. The most common modern scale is the moment magnitude Mw, though regional networks often report local magnitude ML or duration magnitude Md for smaller events.
The USGS Earthquake Hazards Program operates a global seismic network and publishes earthquake catalogs in real time via two APIs:
| API | Purpose | QuakeCat use |
|---|---|---|
| FDSN Event Web Service | Arbitrary historical queries by region, time, magnitude | POST /api/analyze (historical analysis) |
| GeoJSON Summary Feeds | Cached real-time feeds (1-minute refresh) | GET /api/recent (live map refresh) |
The USGS asks that automated applications use the Summary feeds for real-time display rather than hammering the FDSN endpoint. QuakeCat respects this guidance: the live map polls the Summary feeds; the historical analysis uses FDSN.
In 1944, Gutenberg and Richter observed that earthquake frequency follows a power law with magnitude:
where N(≥M) is the cumulative number of earthquakes with magnitude at or above M, a is a productivity constant (depends on the catalog size and region), and b is the b-value — the slope of the log-linear frequency-magnitude distribution.
The b-value encodes the relative proportion of large to small earthquakes:
Published California regional b-values fall in the range 0.85–1.05 depending on the Mc threshold and time window. QuakeCat's live cross-check asserts the computed value falls within this range.
A seismic network cannot detect every earthquake — very small events are missed because their signals fall below the noise floor of the nearest station. The magnitude of completeness Mc is the lowest magnitude above which the catalog is considered complete (i.e., essentially all earthquakes are detected).
QuakeCat uses the maximum-curvature method (Wiemer & Wyss 2000): Mc is taken as the lower edge of the histogram bin where the non-cumulative magnitude-frequency distribution reaches its peak count.
The b-value is estimated via the Aki (1965) maximum-likelihood estimator with the Utsu (1965) / Tinti & Mulargia (1987) bin-width correction:
where:
Magnitudes in real catalogs are reported with finite precision (0.1 magnitude units for
USGS). When magnitudes are binned at width Δm, the effective lower threshold is
Mc − Δm/2 (the lower edge of the bin centered on Mc), not Mc itself. The naive Aki
estimator b = log10(e) / (m̄ − Mc) is biased upward by approximately
13% on the project's synthetic fixture:
| Formula | Result on synthetic fixture (planted b = 1.0) |
|---|---|
| Uncorrected Aki | b ≈ 1.1309 |
| Corrected Aki (QuakeCat) | b ≈ 1.0007 |
The L4 gate test explicitly asserts that the corrected value is within tolerance of 1.0007 AND that the uncorrected value 1.1309 is NOT reproduced — the "anti-target" regression test.
The standard error of the b-value estimate is computed via the Shi & Bolt (1982) formula:
where N is the number of events at or above Mc and the 2.30 factor is log(10) arising from the conversion between natural-log and log₁₀ in the variance propagation. The (N−1) denominator is Bessel's correction for the unbiased variance estimator.
QuakeCat is structured as a 7-level decomposition where each level validates a single well-defined invariant:
| Level | Module(s) | Invariant validated |
|---|---|---|
| L0 | quaketypes, geojson_fetcher, geojson_parser | Live USGS endpoint contract; GeoJSON schema parsing |
| L1 | region_filter, density_grid | Spatial filtering (haversine); 2D density grid |
| L2 | magfreq | Magnitude-frequency histogram primitive |
| L3 | mc_estimator | Mc reproduction from synthetic catalog |
| L4 | bvalue | b-value MLE with bin-width-correction anti-target |
| L5 | analyzer, exporters, quakecat CLI | Orchestrated pipeline; live California b-value cross-check |
| L6 | quakecat_gui, quakecat_railway | GUI binary contract; cross-binary exporters.ToJSON shape |
Every module's public API names its own types, never its dependencies'. Three vocabulary lifts were driven by anti-corruption violations detected during generation:
MagFreqDistribution lifted from magfreq → quaketypesMcEstimate lifted from mc_estimator → quaketypesBValueEstimate, DensityGrid, GridParams lifted → quaketypes
The result: the CLI (quakecat) and this Railway server both depend on only three modules —
quaketypes, analyzer, exporters — despite the
pipeline composing eight L0-L4 modules internally.
QuakeCat ships two L6 deployments with identical user-facing surfaces but different composition disciplines:
| Deployment | Composition | Target |
|---|---|---|
| quakecat_gui | Subprocess wrapper — invokes the quakecat binary via os/exec; zero Go-level library imports | Developer's local machine alongside the CLI |
| quakecat_railway (this server) | In-process — calls analyzer.Run + exporters.ToJSON directly; no subprocess | Railway container (single static linux/amd64 binary) |
The Recent Seismicity panel polls the USGS GeoJSON Summary feeds every 60 seconds. Select a magnitude threshold and time window, then click Refresh Now to update the map immediately. Markers are scaled by magnitude and colored by depth:
The Historical Analysis panel queries the USGS FDSN Event Web Service
for a historical catalog and runs the full Gutenberg-Richter pipeline. Select a named
region (or enter lat,lon,radius_km for a custom circle), a time window,
and a minimum magnitude, then click Analyze.
Results include:
QuakeCat v1.3.0 · Genthos · ELLIPSE 5.2