A cloud-native workflow for automated seismic phase picking and earthquake detection using deep learning, deployed on AWS with containerized models and managed infrastructure.
Authors: Jannes Munchmeyer (munchmej@univ-grenoble-alpes.fr), Yiyu Ni (niyiyu@uw.edu), and Marine Denolle (mdenolle@uw.edu)
If you use QuakeScope in research, please cite:
- Ni, Y., Denolle, M. A., Münchmeyer, J., Wang, Y., Feng, K. F., Suarez, C. G. J., Thomas, A. M., Trabant, C., Hamilton, A., Mencin, D. (2025). A Review of Cloud Computing and Storage in Seismology. Geophysical Journal International, 243(1), ggaf322. 10.1093/gji/ggaf322
- Ni, Y., Denolle, M. A., Thomas, A. M., Münchmeyer, J., Hamilton, A., Wang, Y., Bachelot, L., Trabant, C., Mencin, D. (2025). A Global-scale Database of Seismic Phases from Cloud-based Picking at Petabyte Scale. Seismica, 4(2). 10.26443/seismica.v4i2.1738
See CITATION.cff for BibTeX and other formats.
Local tutorials (5 min):
git clone https://github.com/SeisSCOPED/QuakeScope.git
cd QuakeScope
pixi install --environment tutorials
pixi run smoke-testCloud deployment: See INSTALL.md
| Link | Purpose |
|---|---|
| INSTALL_TUTORIALS.md | Local setup (pixi + notebooks) |
| INSTALL.md | AWS Batch/Fargate deployment |
| docs/rerun_2026/README.md | Production runbook |
| docs/phasenet_v7_model_description.md | Model architecture & benchmarks |
| docs/smoke_test_workflow.md | Validation workflow |
| docs/rerun_2026/15_monitoring.md | Cost alerts and emergency stop |
| notebooks/5_submit_job_parquet.ipynb | Launch a Fargate campaign with Parquet output (no DocumentDB) |
| notebooks/6_check_parquet.ipynb | Query the Parquet catalogue |
| reports/ | Rendered benchmark reports, published at seisscoped.org/QuakeScope |
| SECURITY_AUDIT.md | Security assessment |
Campaigns run on Spot instances that are easy to leave running. Two layers watch for that; neither is on by default.
What is running right now, from your laptop:
pixi run -e cloud watch # instances, spot vs on-demand, $/hr, $/monthRead-only, and it prints the stop commands for whatever it finds.
Hourly alerts by email, via GitHub Actions
(.github/workflows/aws-watch.yml). Three
things must all be true, and none is automatic:
- The workflow must be on the default branch. GitHub runs
schedule:triggers only from the default branch; on a feature branch it never fires. - Credentials must be set — repository variable
AWS_WATCH_ROLE_ARN(OIDC, preferred, no stored keys) or theAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYsecrets. The IAM policy is describe-only. - You must watch the repo, since the alert is an issue comment and GitHub turns that into email.
Test it without waiting an hour:
gh workflow run aws-watch.ymlIt does not email hourly. One issue is the dashboard, its body updates silently, and a comment — which notifies — is posted only when the state changes: idle → running, a new warning, or all-clear.
Turning it off, at the level you want:
gh workflow disable aws-watch.yml # stop entirely (enable to resume)To keep the dashboard but stop the email, unsubscribe from that one issue. To
silence all repo email, set the repo to Participating and @mentions. To pause,
drop the schedule: block and keep workflow_dispatch.
Add an AWS Budgets daily alert as an independent backstop — it fires even if Actions, the credentials, or the repo are broken. Setup, the IAM policy and the emergency-stop sequence are in docs/rerun_2026/15_monitoring.md.
- 🌩️ Cloud-native: AWS Batch/Fargate for elastic, serverless phase picking
- 🔬 Selectable weights: ships SeisBench models; custom fine-tunes drop in via
--weight - 📊 Scalable database: DocumentDB for catalog storage and querying
- ⏱️ Timing-tuned picker: the v7 fine-tune improves P-MAE to 0.340 s from its parent's 0.374 s, trading recall to get there — see the model notes before choosing it
- 📦 Containerized: Docker-based deployment with custom weights and dependencies
- 🔍 Monitored: CloudWatch dashboards and SNS alerts for job tracking
Two deployment paths are supported, and they differ in more than plumbing:
| v2 — AWS Batch on Fargate Spot | v3 — SkyPilot Spot + S3 queue | |
|---|---|---|
| Proven at | the 2025 petabyte campaign | two shards end to end |
| State | DocumentDB (VPC-bound) | S3 objects, no database |
| Submission from | an EC2 controller inside the VPC | anywhere |
| Notebooks | 3, 4 | 5, 6 |
Both write picks as Parquet on S3. The diagram below is the v2 path; for v3 see 14_skypilot.md, and 16_skypilot_vs_fargate.md for the cost comparison.
Continuous Waveforms (SCEDC/NCEDC S3)
↓
┌─────────────────────────┐
│ AWS Batch/Fargate │
│ • PhaseNet inference │
│ • QuakeXNet classifier │
│ • PyOcto association │
└─────────────────────────┘
↓
┌─────────────────────────┐
│ DocumentDB │
│ • Picks catalog │
│ • Event associations │
│ • Metadata │
└─────────────────────────┘
↓
Analytics & Visualization
QuakeScope/
├── README.md # This file
├── CITATION.cff # Citation metadata
├── AUTHORS # Project authors
├── INSTALL.md # Cloud installation
├── INSTALL_TUTORIALS.md # Tutorial setup
│
├── sb_catalog/
│ ├── models/v3/
│ │ ├── phasenet/ # PhaseNet weights (quakescope2026 = v7)
│ │ └── quakexnet/ # Event classifier weights
│ └── src/
│ ├── picking.py # Inference pipeline
│ ├── s3_helper.py # S3 data loading
│ └── constants.py # Configuration
│
├── notebooks/
│ ├── 1_prepare_compute_env.ipynb # AWS setup
│ ├── 2_prepare_station_metadata.ipynb
│ ├── 3_submit_job.ipynb # Job submission
│ └── 4_check_database.ipynb # Results verification
│
├── tutorials/
│ ├── phasenet_smoke_test_ridgecrest.ipynb
│ ├── compare_phasenet_models.ipynb
│ └── seisbench_pyocto_ncedc.ipynb
│
├── docs/
│ ├── rerun_2026/ # 2026 re-run runbook
│ ├── smoke_test_workflow.md
│ ├── phasenet_v7_model_description.md
│ └── ridgecrest_2019_test_stations.md
│
└── Dockerfile # Container image
- Python 3.9+
- PyTorch 2.0+
- ObsPy, SeisBench, PyOcto (see INSTALL.md or INSTALL_TUTORIALS.md)
- AWS account (for cloud deployment)
Contributions are welcome! Please open an issue or pull request on GitHub.
- Lead Author: Yiyu Ni (niyiyu@uw.edu)
- Project PI: Marine Denolle (mdenolle@uw.edu)
- Infrastructure: Jannes Munchmeyer (munchmej@univ-grenoble-alpes.fr)