# AGENTS.md — Ocean Metrics gazetteer

Guidance for AI agents and LLMs working with this catalog. Two patterns cover most needs.

## 1. Find a place

```sql
SELECT * FROM read_parquet('https://storage.oceanmetrics.io/gazetteer/places/places.parquet')
WHERE place_id = 'NMS:HIHWNMS';
```

`place_id` is a prefixed id: `NMS:<code>` (sanctuary), `MRGID:<id>` (MarineRegions), or
`PSGID:<id>` (ProtectedSeas). See [`places/AGENTS.md`](places/AGENTS.md).

## 2. Statistics for a place, precomputed

If the (dataset, variable, place) you want is in [`stats/`](stats/collection.json), read it and stop
— one range-read instead of a minute of griddap:

```sql
SELECT * FROM read_parquet('https://storage.oceanmetrics.io/gazetteer/stats/dhw_5km/CRW_SST/NMS:HIHWNMS.parquet')
ORDER BY date;
```

The dataset's full record, refreshed daily, `place_id` colon and all. See [`stats/AGENTS.md`](stats/AGENTS.md).

## 3. Fresh statistics for a place

1. Read an `erddap/*/collection.json` (e.g. [`erddap/dhw_5km/`](erddap/dhw_5km/collection.json)).
2. Take the place's bbox per polygon lobe (from `places.parquet`'s `bbox` column — a place can
   have multiple lobes, e.g. antimeridian-crossing `NMS:PMNM`).
3. Build the griddap URL from the collection's `griddap` asset href template, substituting
   `{variable}`, `{t0}`, `{t1}`, `{lat_min}`, `{lat_max}`, `{lon_min}`, `{lon_max}` — percent-encode
   each `[(...)...]` constraint separately.
4. `read_parquet(url)` (DuckDB or duckdb-wasm in-browser; both datasets are CORS-enabled).
5. Mask to grid cells whose centre falls inside the polygon lobe, aggregate per day.

Full walkthrough: [`erddap/AGENTS.md`](erddap/AGENTS.md).

## 4. Then vs Now: decades of daily SST for a sanctuary

- daily area means 1985–now: `read_parquet('https://storage.oceanmetrics.io/gazetteer/series/dhw_5km/CRW_SST/NMS:FKNMS.parquet')`
- a day's map: band `dayofyear(make_date(2000, month(d), day(d)))` of
  `rasters/dhw_5km/CRW_SST/<place_id>/<year>.tif` (366 bands, band 60 = 29 Feb)
- the baseline map for that day: the same band of `climatology/dhw_5km/CRW_SST/<place_id>/1985-2005_mean.tif`

See [`rasters/AGENTS.md`](rasters/AGENTS.md), [`climatology/AGENTS.md`](climatology/AGENTS.md),
[`series/AGENTS.md`](series/AGENTS.md).

## Bounding boxes across ±180

Geometries are stored split at ±180, so `NMS:PMNM` has parts on both sides. Every **STAC bbox**
(Item `bbox`, collection `extent.spatial.bbox`) and the **file-level GeoParquet `geo` bbox** cross
the antimeridian with west > east (RFC 7946 §5): PMNM is about `[177.8, 19.2, -161.0, 31.8]`. The
**per-row `bbox` column** of `places.parquet` stays plain min/max (PMNM: `-180 … 180`), so
`xmin <= x AND x <= xmax` filters keep working. Fetch data per lobe (one per side), never one box.

## Collections

- [`places/`](places/) — the gazetteer (GeoParquet + PMTiles).
- [`erddap/dhw_5km/`](erddap/dhw_5km/) — NOAA Coral Reef Watch SST + DHW (live).
- [`erddap/jplMURSST41/`](erddap/jplMURSST41/) — JPL MUR SST v4.1 (mirror not yet live; use the
  `griddap_upstream` asset).
- `erddap/cmems_*`, `erddap/CMEMS_PHY_MONTHLY`, `erddap/IMERG_monthly_global_precip`,
  `erddap/moda_npp_mo_glob` — USF IMaRS datasets re-served on erddap.oceanmetrics.io (monthly
  CMEMS biogeochemistry/physics, precipitation, NPP); `erddap/jplMURSST41mday`,
  `erddap/jplMURSST41anom1day` are pending. See [`erddap/README.md`](erddap/README.md).
- [`stats/`](stats/) — precomputed place statistics (Parquet + STAC Items).
- [`rasters/`](rasters/), [`climatology/`](climatology/), [`series/`](series/) — Then vs Now:
  sanctuary SST since 1985 as day-of-year COGs, baselines and area series.

## License

CC-BY-4.0 for our derived `places/` files. ERDDAP collections describe upstream services under
their own licenses (see each collection's README).
