ingv-shakemap
How hard did the ground shake here? INGV's earthquakes and ShakeMap grids, read into numbers you can sample at any point in Italy.
grid = await IngvClient().shakemap(47606532)
grid.pga_g(15.55, 38.19) # 0.0029 g in Messina, from the Mw 5.5 of 23 October 2026
docs/make_images.py with this package: 542 × 362 points, peak 0.33 g.
- What is it, in 30 seconds
- Who is it for
- Quick start
- How it works
- Recipes
- The traps we already fell into
- API at a glance
- Data licence and credits
What is it, in 30 seconds
After every significant earthquake INGV publishes a ShakeMap: its estimate
of how strongly the ground shook at every point around the epicentre, built from
the stations that recorded it and from ground-motion models where there are
none. The map is a grid.xml of up to 12 MB of text. This package turns it into
arrays and answers questions about a point.
| What you get | |
|---|---|
| 🌍 | Earthquakes from the INGV FDSN catalogue: id, time (UTC), magnitude and its type, epicentre, depth, place |
| 📈 | The ShakeMap grid of an event: PGA, PGV, MMI, spectral accelerations, Vs30, as numpy arrays |
| 📍 | The value at a point: pga_g(lon, lat) in g, pgv_cm_s, mmi, or any column with value_at |
| 🧾 | The map's own metadata: version, map_status (automatic until reviewed), processing time |
| 🔌 | Your HTTP layer: inject an httpx.AsyncClient, or route every call through your own send |
| 🧪 | Pure parsers: parse_grid and parse_events do no I/O, so you can test them on a file |
Who is it for
- Anyone who needs shaking at a site, not just a magnitude: a building, a dam, a road, the cells of a hazard model. Magnitude says how big the earthquake was; PGA says how hard it hit here.
- Landslide and multi-hazard models: earthquake-triggered landslides scale with ground acceleration, which this gives per point.
- Researchers and journalists who want INGV's own estimate rather than a distance-based guess.
It was extracted from Limen, the landslide, flood and wildfire monitor for Italy, where it reads the ShakeMap of every earthquake above magnitude 3.5 onto a 1 km grid. On three real grids its PGA matches Limen's own parser value for value.
Quick start
pip install ingv-shakemap
import asyncio
from datetime import UTC, datetime
from ingv_shakemap import IngvClient
async def main() -> None:
async with IngvClient() as ingv:
quakes = await ingv.events(
datetime(2026, 10, 23, tzinfo=UTC),
datetime(2026, 10, 24, tzinfo=UTC),
min_magnitude=4.5,
)
for q in quakes:
print(q.id, q.time, q.magnitude, q.magnitude_type, q.place)
grid = await ingv.shakemap(quakes[1].id) # None if INGV published no map
if grid is not None:
print(grid.map_status, grid.pga_g(15.55, 38.19), grid.mmi(15.55, 38.19))
asyncio.run(main())
47611152 2026-10-23 13:55:34.920000+00:00 5.0 Mw Tirreno Meridionale [Mare]
47606532 2026-10-23 10:19:15.470000+00:00 5.5 Mw Tirreno Meridionale [Mare]
47605832 2026-10-23 09:51:38.850000+00:00 4.8 Mw Tirreno Meridionale [Mare]
automatic 0.002939 3.4
How it works
flowchart LR
F["INGV FDSN<br/>webservices.ingv.it"] -->|GeoJSON| E["parse_events<br/>Event"]
E -->|event id| S["shakemap.ingv.it<br/>/data/{id}/current/products/grid.xml"]
S -->|up to 12 MB of XML| G["parse_grid<br/>ShakeGrid"]
G --> P["pga_g · pgv_cm_s · mmi<br/>value_at · column"]
The FDSN event id is the ShakeMap id: the same integer joins the two services.
Recipes
The shaking on many points at once. column gives the whole grid as an
(nlat, nlon) array, north row first; index it yourself for thousands of points:
pga = grid.column("PGA") / 100.0 # percent of g -> g
west, south, east, north = grid.bbox
Parse in a thread. A big grid takes about a quarter of a second to parse.
IngvClient.shakemap already runs it in asyncio.to_thread; when you parse
yourself, do the same:
xml = await ingv.shakemap_xml(event_id)
grid = await asyncio.to_thread(parse_grid, xml)
Your own HTTP layer. Pass send, and the client uses it for every request
and does no retrying of its own:
async def send(method: str, url: str, **kwargs):
return await my_shared_policy(method, url, **kwargs)
ingv = IngvClient(send=send)
No network at all. parse_grid(Path("grid.xml").read_bytes()) and
parse_events(json.loads(text)) work on files.
The traps we already fell into
- PGA is in percent of g, not in g. The
grid.xmlwritesunits="%g":0.11is 0.0011 g, barely felt.pga_gconverts;value_at("PGA", ...)andcolumn("PGA")return the file's own unit. - The row order is a convention, not a statement. Rows go from the north
edge southwards, longitude fastest.
parse_gridchecks this on the first rows and refuses a file in another order, because a wrong guess would move every value without raising. - The grid step changes from event to event: about 90 m at Campi Flegrei,
0.0083° (about 900 m) for the 23 October 2026 sequence. Never hard-code it;
read
lon_stepandlat_step. - An empty week is a 204, an outage is not. The FDSN service answers
204 No Contentto a window without earthquakes. A 5xx, even with no body, is a failure:eventsraisesIngvErrorfor it and returns[]only for the 204, so an unreachable catalogue never looks like a quiet week. - No ShakeMap is a 404, and it is normal. Small or very recent events
have none:
shakemapreturnsNone. Any other error raises. automaticcan last. The maps of the 23 October 2026 sequence still saidmap_status="automatic"twelve days later. Readmap_statusandprocess_timeif you need a reviewed map, and fetch it again later.- The old URL is dead. The
/shake4/prefix answered 404 for every event on 19 October 2026; the grid lives under/data/{id}/current/products/. - No top-level id in the GeoJSON. INGV puts the event id in
properties.eventId, as an integer.parse_eventreads it from there. - Times are UTC without an offset, both ways. The package sends
2026-10-23T10:19:15and gives back aware UTC datetimes.
API at a glance
| Name | What it does |
|---|---|
IngvClient(client=None, *, send=None, retries=3, backoff_s=2.0, timeout_s=60.0) |
async client; retries transport errors, 429 and 5xx |
IngvClient.events(start, end, *, bbox=ITALY, min_magnitude=None, max_depth_km=None, limit=None) |
earthquakes, newest first |
IngvClient.shakemap(event_id) / .shakemap_xml(event_id) |
the parsed grid, or the raw bytes; None if there is no map |
parse_grid(xml) → ShakeGrid |
pure parser; raises only GridError |
ShakeGrid.pga_g / .pgv_cm_s / .mmi / .value_at / .column / .bbox |
values at a point, or as arrays |
ShakeGrid.event, .map_status, .version, .process_time, .fields |
the map's metadata |
parse_events(geojson) / parse_event(feature) → Event |
pure parsers of the FDSN answer |
event_query(...), shakemap_grid_url(id) |
the requests, without sending them |
IngvError, GridError |
the only exceptions; GridError is also a ValueError |
The full reference is on the documentation site.
Development
uv sync
make check # ruff, mypy --strict, pytest with coverage
make docs # the documentation site, built with --strict
Data licence and credits
- Earthquake catalogue: © Istituto Nazionale di Geofisica e Vulcanologia (INGV). The data and results published on terremoti.ingv.it are under CC BY 4.0: credit INGV.
- ShakeMap: computed and published by INGV at shakemap.ingv.it. That site states no licence of its own (checked on 4 November 2026); credit INGV as for the catalogue.
- ShakeMap is software by the USGS; the
grid.xmlformat is ShakeMap 4's.
This package is not affiliated with INGV or the USGS. Code under Apache-2.0.
Metadata
Release files for ingv-shakemap 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ingv_shakemap-0.1.0.tar.gz | 20.5 kB | With provenance | Details for ingv_shakemap-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ingv_shakemap-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ingv_shakemap-0.1.0-py3-none-any.whl |
Total release size: 39.4 kB
Release files / ingv_shakemap-0.1.0.tar.gz
| Download URL | ingv_shakemap-0.1.0.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6bfa5195bf7423f18ac1a88fcfe5cc1d2288979530563a503d7d4f3a6c45cf30
|
|
BLAKE2b-256 checksum How to use checksums |
5ad15b4a966a54c6e9a88f60968fafa7044c2c0711d35d513f4462bf27048d6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / ingv_shakemap-0.1.0-py3-none-any.whl
| Download URL | ingv_shakemap-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d1fed33c821fbd18bfb26bdaaef8e9e14f69e310db21ce14b81e96fbdeab7521
|
|
BLAKE2b-256 checksum How to use checksums |
7198f635da76d3e9ddbe458866d260dcf54dfc6c0fac574c1723f488ab2642c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logSecurity for ingv-shakemap 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ingv_shakemap-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.