A Machine Learning Diagnostic Framework for Nonstationary ETAS Aftershock Modeling
Giuseppe Petrillo and Luca Dal Zilio — Earth Observatory of Singapore / Nanyang Technological University
This repository provides the complete numerical framework associated with the study:
G. Petrillo and L. Dal Zilio, A Machine Learning Diagnostic Framework for Nonstationary ETAS Aftershock Modeling, submitted (2025).
The framework integrates three independent analytical components:
- Stationary ETAS inference — maximum likelihood estimation of the five standard ETAS parameters from an earthquake catalog.
- Nonstationary ETAS inference — penalized log-spline extension in which the background rate µ(t) and triggering productivity K₀(t) are allowed to vary continuously in time, with ABIC-based smoothing selection.
- Model-agnostic anomaly detection — unsupervised Isolation Forest analysis applied to multivariate catalog features, serving as an independent diagnostic to assess whether statistically inferred parameter transients correspond to observable changes in seismicity properties.
The framework is applied to the aftershock sequence of the 2025 Mw 7.1 Dingri earthquake in southern Tibet (Yao et al. 2025), and validated on a family of semi-synthetic catalogs with injected perturbations of controlled amplitude. While developed for the Dingri sequence, all components are general and directly transferable to any well-recorded aftershock sequence.
etas-diagnostic-framework/
│
├── catalogs/
│ ├── catalog.txt # Original Dingri aftershock catalog
│ ├── decimal_days_mL.txt # Catalog in decimal days + local magnitude
│ ├── modified_decimal_days_mL.txt # Catalog in decimal years + magnitude (ETAS input)
│ ├── fort.10 # Time-dependent completeness Mc(t) estimates
│ ├── catalog_rate_bump2.txt # Semi-synthetic catalog Sim1
│ ├── catalog_rate_bump3.txt # Semi-synthetic catalog Sim2
│ ├── catalog_rate_bump4.txt # Semi-synthetic catalog Sim3
│ ├── catalog_rate_bump5.txt # Semi-synthetic catalog Sim4
│ └── catalog_rate_bump6.txt # Semi-synthetic catalog Sim5
│
├── codes/
│ ├── figure1_catalog.py # Figure 1 — catalog overview and Mc(t)
│ ├── figure2_stat_etas.py # Figure 2 — stationary ETAS fit and residuals
│ ├── nonstat_etas.py # Nonstationary ETAS inference (core engine)
│ ├── figure3_plot_nonstat_etas.py # Figure 3 — nonstationary ETAS results
│ ├── figure4-5_iso_forest.py # Figures 4–5 — Isolation Forest on real catalog
│ ├── simu_bump.py # Semi-synthetic catalog generation
│ └── figure6_isolation_bump.py # Figure 6 — Isolation Forest on synthetic catalogs
│
├── figures/
│ └── [output figures — generated by the scripts above]
│
└── README.md
The temporal ETAS model (Ogata 1988, 1998) represents seismicity as a self-exciting point process. The conditional intensity function is:
where:
| Parameter | Description |
|---|---|
| µ | Stationary background seismicity rate [events/day] |
| K | Triggering productivity |
| α | Magnitude scaling of productivity |
| c | Omori-Utsu time offset [days] |
| p | Omori-Utsu temporal decay exponent |
| m₀ | Reference magnitude (set equal to Mₜ) |
The five parameters θ = (µ, K, α, c, p) are estimated by maximizing the log-likelihood:
The integral decomposes analytically into a background term µ(T − T₀) and a triggering term with closed-form antiderivative:
Model selection uses the Akaike Information Criterion:
Model adequacy is assessed via the time-rescaling theorem (Zhuang and Ogata 2006). Transformed times
should constitute a homogeneous Poisson process with unit rate if the model is correctly specified. The empirical cumulative count N(τ) is compared against the expected relation N(τ) = τ with 95% confidence band ±1.96 √τ.
The nonstationary extension allows µ and K₀ to vary continuously in time while holding the decay parameters (c, α, p) constant:
Time dependence is parameterized via multiplicative anomaly factors relative to fixed reference values (µ_ref, K₀_ref):
where positivity is enforced through an exponential link applied to cubic spline functions:
The splines s_µ(t) and s_K(t) are defined on a uniform set of N_knots = 6 interior knots spanning the observation window [T₀, T], with natural boundary conditions.
To prevent overfitting, the penalized negative log-likelihood is minimized:
where the roughness penalty is based on the integrated squared curvature of the log-anomaly functions:
The smoothing weight w is selected by minimizing the Akaike Bayesian Information Criterion (ABIC) over a candidate grid {w_ℓ}:
where n_hyper = 1 counts the single hyperparameter w. The full nonstationary model has k = 2 × N_knots + 3 = 15 free parameters (12 spline coefficients plus c, α, p), and the corresponding AIC is:
Optimization uses a bound-constrained quasi-Newton algorithm (L-BFGS-B). The log-likelihood is evaluated in vectorized form via a precomputed time-difference matrix, reducing the triggering sum to a single matrix-vector product with O(N²) complexity.
The earthquake catalog is partitioned into non-overlapping temporal windows of width Δt = 0.5 days. For each window k, a 13-dimensional feature vector x_k is constructed:
| Feature index | Description |
|---|---|
| 1 | Event count N_k |
| 2 | Seismicity rate N_k / Δt [events/day] |
| 3 | Mean magnitude |
| 4 | Maximum magnitude |
| 5 | Fraction of events with M ≥ 4.5 |
| 6 | Mean focal depth |
| 7 | Median focal depth |
| 8 | Standard deviation of focal depth |
| 9 | Mean longitude |
| 10 | Standard deviation of longitude |
| 11 | Mean latitude |
| 12 | Standard deviation of latitude |
| 13 | Spatial dispersion proxy σ_lat × σ_lon |
Each feature is standardized using robust Median Absolute Deviation (MAD) normalization:
yielding a robustly standardized feature matrix Z ∈ ℝ^{K × 13}. Missing values (empty bins) are replaced by the column median prior to standardization.
Anomaly detection is performed using the Isolation Forest algorithm (Liu et al. 2008) with T = 500 trees. The anomaly score for observation z_k is:
where E[h(z_k)] is the mean path length over all trees and c(K) = 2H_{K-1} − 2(K−1)/K is the normalization constant based on the harmonic number H_{K-1}. Higher scores indicate greater anomalousness. If scikit-learn is unavailable, a fallback score is used:
Semi-synthetic catalogs are generated by injecting a controlled perturbation into a real catalog within a specified time window [t₁, t₂]. The additional events are drawn from a Poisson process with rate:
where λ_obs is the observed event rate within the window and a (amp) is the amplification factor. Injected events form a spatially compact Gaussian cluster centered at a shifted location relative to the real centroid:
Magnitude and depth of synthetic events are sampled from real events within the window with small additive jitter. Outside [t₁, t₂] the catalog is identical to the original.
Whitespace-separated, one event per line:
yyyy mm dd hh mm ss.ss lat lon depth Ml seqID
Lines beginning with # are treated as comments and ignored.
Two-column format used as direct input to the ETAS fitting scripts:
time_decimal_years magnitude
Output of the time-dependent completeness estimation (CV stabilization method). The last column contains the Mc(t) values used to produce Figure 1.
All scripts require Python 3.8 or later. Dependencies can be installed with:
pip install numpy scipy matplotlib scikit-learnscikit-learn is required for Isolation Forest. If unavailable, the scripts automatically fall back to a MAD-norm-based anomaly score.
All scripts are designed to be run from within the codes/ directory. Input file paths are relative to this location by default and can be overridden via command-line arguments or by editing the path variables at the top of each script.
python figure1_catalog.pyReads catalogs/decimal_days_mL.txt and catalogs/fort.10. Produces a scatter plot of the earthquake catalog with magnitude color-coded by the viridis colormap, marker size scaled quadratically with magnitude, and the smoothed time-dependent completeness magnitude Mc(t) overlaid as a red curve.
Output: figure1.svg, figure1.eps
python figure2_stat_etas.pyReads catalogs/modified_decimal_days_mL.txt. Converts times from decimal years to days, estimates the five ETAS parameters (µ, K, c, α, p) by L-BFGS-B maximization of the log-likelihood, reports AIC, and produces a two-panel figure:
- (a) Conditional intensity λ(t) on a logarithmic scale with the earthquake catalog overlaid.
- (b) Time-rescaling residuals: empirical N(τ) versus transformed time τ, with the expected relation N(τ) = τ and 95% confidence band.
Terminal output includes the optimization status, log-likelihood, AIC, and all estimated parameters.
Output: etas_intensity_and_residuals.svg, etas_intensity_and_residuals.eps
python nonstat_etas.pyReads catalogs/modified_decimal_days_mL.txt. Runs the full nonstationary ETAS pipeline:
- Loads and converts the catalog to days.
- Precomputes the time-difference matrix dt[i,j] = t_i − t_j and the lower-triangular mask.
- Constructs uniform cubic spline knots for s_µ(t) and s_K(t).
- Performs ABIC grid search over the smoothing weight candidates W_GRID = [0.0, 0.05, 0.1].
- Reports the optimal w, ABIC, and estimated parameters (c, α, p).
- Saves all outputs to
output_nonstat_etas/and produces a two-panel summary figure.
Key settings (editable at the top of the script):
Mth = 2.5 # Magnitude of completeness
N_knots_1 = 6 # Number of spline knots for mu(t)
N_knots_2 = 6 # Number of spline knots for K0(t)
W_GRID = [0.0, 0.05, 0.1] # ABIC smoothing grid
mu_ref = 0.01 # Reference background rate [events/day]
K0_ref = 0.02 # Reference productivity [events/day]Output files written to output_nonstat_etas/:
| File | Description |
|---|---|
catalog_used.dat |
Events used for fitting (decimal year, day, magnitude) |
abic_grid_results.dat |
ABIC values for each candidate smoothing weight |
params_optimal_vector.dat |
Full optimal parameter vector |
fit_summary.txt |
Human-readable summary of the fit |
fitted_time_series.dat |
Time series of λ(t), µ(t), K₀(t) on a 600-point grid |
residuals_time_transform.dat |
Transformed times τᵢ and cumulative event count |
python figure3_plot_nonstat_etas.pyReads the output files from output_nonstat_etas/ produced by nonstat_etas.py. Generates a three-panel figure:
- (a) Conditional intensity λ(t) with catalog in background.
- (b) Time-rescaling residuals N(τ) versus τ.
- (c) Time-varying background rate µ(t) and productivity K₀(t) on a logarithmic scale.
Output: output_nonstat_etas/figure_multipanel_nonstat_etas.png, .svg, .eps, .pdf
python "figure4-5_iso_forest.py" --file ../catalogs/catalog.txt --dt 0.5 --mc 2.5 --highlight 8 10Arguments:
| Argument | Default | Description |
|---|---|---|
--file |
../catalogs/catalog.txt |
Path to input catalog |
--dt |
0.5 | Temporal bin width [days] |
--tmin |
auto | Start of analysis window [days] |
--tmax |
auto | End of analysis window [days] |
--mc |
2.5 | Magnitude of completeness |
--highlight |
8 10 | Interval to highlight [days] |
--seed |
0 | Random seed for Isolation Forest |
--no_heatmap |
— | Suppress heatmap figure |
--out_prefix |
anomaly |
Prefix for output figure files |
Output: anomaly_score.png/.svg/.eps (Figure 4) and anomaly_heatmap.png/.svg/.eps (Figure 5).
python simu_bump.py \
--input ../catalogs/catalog.txt \
--output ../catalogs/catalog_rate_bump2.txt \
--t1 8 --t2 10 \
--amp 1.0 \
--new_lat_shift 0.28 --new_lon_shift 0.28 \
--cluster_sigma 0.10 \
--depth_shift -4.0 \
--seed 0Arguments:
| Argument | Default | Description |
|---|---|---|
--input |
../catalogs/catalog.txt |
Input catalog |
--output |
../output_nonstat_etas/catalog_cluster_test.txt |
Output catalog |
--t1 |
8.0 | Start of perturbation window [days] |
--t2 |
10.0 | End of perturbation window [days] |
--amp |
1.5 | Rate amplification factor relative to observed rate |
--dt |
0.01 | Poisson time step [days] |
--new_lat_shift |
0.08 | Spatial shift of injected cluster [degrees latitude] |
--new_lon_shift |
0.08 | Spatial shift of injected cluster [degrees longitude] |
--cluster_sigma |
0.003 | Standard deviation of injected spatial cluster [degrees] |
--depth_shift |
-2.0 | Systematic depth shift [km] |
--mag_jitter |
0.05 | Random magnitude perturbation σ |
--depth_jitter |
0.1 | Random depth perturbation σ [km] |
--seed |
0 | Random seed |
The five semi-synthetic catalogs used in the paper (Sim1–Sim5) correspond to the following perturbation parameters:
| Catalog | amp | Δlat | Δlon | σ_cluster | Δd (km) |
|---|---|---|---|---|---|
| Original | 0.0 | 0.00 | 0.00 | — | 0.0 |
Sim1 (catalog_rate_bump2.txt) |
1.0 | 0.28 | 0.28 | 0.10 | −4.0 |
Sim2 (catalog_rate_bump3.txt) |
1.3 | 0.35 | 0.35 | 0.08 | −5.0 |
Sim3 (catalog_rate_bump4.txt) |
1.6 | 0.42 | 0.42 | 0.06 | −6.0 |
Sim4 (catalog_rate_bump5.txt) |
2.0 | 0.50 | 0.50 | 0.04 | −7.0 |
Sim5 (catalog_rate_bump6.txt) |
2.5 | 0.60 | 0.60 | 0.03 | −8.0 |
python figure6_isolation_bump.py --dt 0.5 --mc 2.5 --highlight 8 10Automatically loads the original catalog and the five semi-synthetic realizations (Sim1–Sim5) from catalogs/. Applies the identical anomaly detection pipeline to each and produces a single comparison figure showing anomaly score time series for all catalogs, with the 8–10 day window highlighted.
Output: anomaly_compare.png/.svg/.eps
- All ETAS fitting routines have O(N²) complexity in the number of catalog events. For the Dingri catalog (~1300 events above Mc = 2.5 within the analysis window), stationary fitting completes in seconds; nonstationary fitting with the ABIC grid search takes on the order of minutes.
- The nonstationary ETAS script precomputes the full N × N time-difference matrix
dt_matonce before optimization. For catalogs with N > 5000 events, memory usage may become significant and the loop-based fallback should be considered. - The Isolation Forest is run with 500 trees (
n_estimators=500) and contamination set to"auto". Results are deterministic for a fixed random seed.
| Package | Version (tested) | Purpose |
|---|---|---|
| numpy | ≥ 1.22 | Array operations, catalog I/O |
| scipy | ≥ 1.8 | Optimization (L-BFGS-B), cubic splines, integration |
| matplotlib | ≥ 3.5 | All figures |
| scikit-learn | ≥ 1.0 | Isolation Forest anomaly detection |
If you use this code or framework in your research, please cite:
@article{petrillo2025etas,
author = {Petrillo, Giuseppe and Dal Zilio, Luca},
title = {A Machine Learning Diagnostic Framework for Nonstationary {ETAS} Aftershock Modeling},
journal = {submitted},
year = {2025}
}G.P. and L.D.Z. were supported by the Earth Observatory of Singapore (EOS), the Singapore Ministry of Education Tier 3b project "Investigating Volcano and Earthquake Science and Technology (InVEST)" (Award No. MOE-MOET32021-0002), and the Nanyang Assistant Professorship (NAP) (Award No. 025244-00001).
- Liu, F.T., Ting, K.M., Zhou, Z.-H. (2008). Isolation forest. Proceedings of the 8th IEEE ICDM, 413–422.
- Ogata, Y. (1988). Statistical models for earthquake occurrences and residual analysis for point processes. Journal of the American Statistical Association, 83(401), 9–27.
- Ogata, Y. (1998). Space-time point-process models for earthquake occurrences. Annals of the Institute of Statistical Mathematics, 50(2), 379–402.
- Utsu, T., Ogata, Y., Matsu'ura, R.S. (1995). The centenary of the Omori formula for a decay law of aftershock activity. Journal of Physics of the Earth, 43(1), 1–33.
- Yao, J., Yao, D., Chen, F., Zhi, M., Sun, L., Wang, D. (2025). A preliminary catalog of early aftershocks following the 7 January 2025 Ms 6.8 Dingri, Xizang earthquake. Journal of Earth Science, 36(2), 856–860.
- Zhuang, J., Ogata, Y. (2006). Properties of the probability distribution associated with the largest event in an earthquake cluster. Physical Review E, 73, 046134.