Regional aftershock sequence¶
Pull a mainshock and its aftershock sequence (the 2019 Ridgecrest, California events) in a tight bounding box over the following month, and plot magnitude against time to show the Omori-law decay.
Setup¶
The imports up front: EarthLens is the unified entry point, matplotlib draws the magnitude-vs-time scatter, and Path prepares the output directory FDSN writes its QuakeML into.
from pathlib import Path
import matplotlib.pyplot as plt
from earthlens import EarthLens
OUT_DIR = Path('fdsn_output')
OUT_DIR.mkdir(exist_ok=True)
Query the sequence¶
Build the FDSN request first: a tight bounding box around the 2019 Ridgecrest, California sequence over the month that follows the mainshock, keeping only events at or above magnitude 2.5.
# A mainshock + its aftershock sequence: a tight box around the 2019
# Ridgecrest, California sequence over the following month.
quake = EarthLens(
variables=['USGS'],
data_source='fdsn',
start='2019-07-04',
end='2019-08-04',
aoi=[-117.9, 35.4, -117.2, 36.1],
min_magnitude=2.5,
path=str(OUT_DIR),
)
Run the download as its own step. FDSN is a live network query, so it is wrapped in a try/except that prints a friendly message and leaves events as None when the notebook runs offline.
events = None
try:
events = quake.download()
print(f'{len(events)} events in the sequence')
except Exception as exc:
print(f'live FDSN query skipped (offline?): {type(exc).__name__}: {exc}')
Magnitude vs time¶
Sort the events chronologically and scatter magnitude against time. The tail of small aftershocks decaying after the mainshock is the visual signature of Omori-law decay. The plot is skipped when the query above returned no events.
if events is not None and len(events):
df = events.sort_values('time')
fig, ax = plt.subplots(figsize=(11, 5))
ax.scatter(df['time'], df['magnitude'], s=12, alpha=0.6, color='darkorange')
ax.set_title('Ridgecrest 2019 — magnitude vs time (aftershock decay)')
ax.set_xlabel('time')
ax.set_ylabel('magnitude')
fig.autofmt_xdate()