Scope freeze — coral_reef_station Locationdex (6th Locationdex kind)
Decided 2026-06-27 (Mike pasted the data.gov record + ruled "build small standalone
Locationdex now"). Source = EPA's 2011 probabilistic coral-reef condition survey along the
southern coast of Puerto Rico. The 6th Locationdex kind (docs/locationdex-framework.md) after
neutron_monitor, tide_gauge, magnetic_observatory, streamgauge, radiation_monitor. The slot is a
PLACE: one reef survey station.
This one broke the session's NARS water-quality pattern (it's coral-reef ecology, not water chemistry; one region; one year), so the shape was an explicit categorization call — Mike chose a standalone Locationdex over parking it.
Slot
One (reef station) slot. Slot id is namespaced by survey: <survey_id>-<station> (e.g.
pr2011-1), so stations from different surveys never collide in the file-per-slot store. Region
- survey year are slot fields, not the slot key.
This is an EXPANDING kind (Mike, 2026-06-27: "this will definitely not be the last coral reef
survey"). The build is a multi-survey registry from the start (SURVEYS dict in the build
script): adding a same-format survey = one registry entry; a survey whose sheets differ in shape
gets its own per-sheet reader feeding the shared aggregators + dossier (written against the real
file, not a guessed schema). build() clears and fully rebuilds the kind dir from source each
run, so renamed/removed slots never linger.
Surveys loaded (2):
pr2011— EPA 2011 probabilistic reef survey, Puerto Rico southern coast, 64 stations.usvi2009— EPA 2009 targeted assessment of 13 stations along an east-west human-disturbance gradient around Charlotte Amalie Port, St. Thomas, USVI (station codes WCA/MCA/ECA = west / mid / east of the port). Added 2026-06-30 from the data.gov2009-usvirecord Mike pasted. Its four core sheets (station + stony coral + fish + rugosity) are the same shape as PR2011, so it reused the default reader with no new code beyond oneSURVEYSentry. Publication: Oliver et al. 2018, Environmental Monitoring and Assessment 190:213.
Source
Data.gov record: https://catalog.data.gov/dataset/2011-pr-survey-data. Seven per-taxon xlsx
workbooks on EPA's pasteur host (10.23719/1407509). v1 carries the three headline
reef-condition layers + station info; secondary taxa deferred.
Measured reality — IN (bright line feedback_measured_reality_only)
Every value carried is a direct field measurement, all IN:
- Stony coral (per colony): % live tissue, bleached / diseased tallies, height, max diameter, colony count, taxa richness, colony density.
- Fish (per species, belt transect): counts by size class → total individuals, species richness, density.
- Rugosity: draped-length / linear-distance transect ratio (structural complexity index).
- Invertebrates (USVI2009, per belt transect): mobile-invert counts (queen conch, spiny / slipper lobster, crabs, Diadema, other sea urchins) → per-category counts + density. A category never recorded at a station is null, kept distinct from a measured zero.
- Sponges + gorgonians (USVI2009, per quadrant): per-colony census, counts by raw type code (G gorgonian / S sponge / N), mean height + diameter, density over the sampled quadrant area.
The survey's design-based regional condition characterization (the probabilistic population estimate) is not in these raw files and is not carried — consistent with holding out the NARS condition estimates.
Held out — FoRAM Index (Mike's bright-line call, 2026-06-30)
The USVI2009 package also ships a FoRAM Index (one formula-derived foraminiferal bioindicator
value per station: a fixed weighted sum of three foram-group proportions). Held out. Unlike the
rugosity index (where the raw draped/linear lengths are in the file and we recompute), the FoRAM
file carries only the final index — the underlying foraminiferal counts are not present, so it
would be a formula output with no measured basis alongside it. Mike ruled it out under
feedback_measured_reality_only (asked as a single decision; the raw-count taxa above were folded
in regardless). The cached workbook is retained, so a future version with the raw counts could
carry the measured assemblage directly.
Per-station aggregation / gotchas frozen here
- Density uses the single transect-area value, not a row sum. Every colony in a station shares the one survey transect's area (25 m² for coral, 100 m² for fish); density = count / that area, not count / (rows × area). Getting this wrong would deflate density by the colony count. If a station ever carries more than one distinct transect area, the build sums the distinct values (one transect per area).
- Fish total = sum across every size-class bin, across all species rows (counts are spread
over 25 size bins
<5 cm…90-95 cm). - Bleached / Diseased / Clionid are "Yes" / blank flags → percent-of-colonies tallies.
- Station ids are integers in the sheets → normalized to a stable string slot key
(
1.0→"1"). USVI2009 ids are already strings (WCA-1), which pass through unchanged. - Rugosity index — surveys disagree on the convention, so recompute it. PR2011 stores
RIas draped/linear (≥1); USVI2009 stores the reciprocal linear/draped (≤1) for the identical draped (6 m) and linear (~3–5 m) field lengths. Trusting each survey's storedRIcolumn would make the sharedmean_rugosity_indexfield mean opposite things. The build instead recomputes the index from the two measured lengths (larger/smaller, always draped/linear physically, ≥1); the storedRIis only a fallback (also flipped to ≥1) when a survey omits the lengths. Both lengths are direct measurements, so this stays inside the measured-reality line. PR2011's numbers are unchanged by the recompute (its storedRIalready equalled draped/linear); only USVI2009 is corrected (e.g. WCA-1 0.60 → 1.66). - xlsx via openpyxl (read-only, data_only); curl cache-first (sandbox urllib hang).
Storage
Locationdex sibling storehouse data/location_storehouse/coral_reef_station/, file-per-slot
(77 slots is negligible for the shared storehouse_index), via the event_storehouse
write-dossier + disk-rebuilt-index machinery (base_dir=location_storehouse). Built by
scripts/build_coral_reef_station_locationdex.py. 77 station slots across 2 surveys (64
PR2011 + 13 USVI2009), all with the coral layer (coral % live ≈ 75–90%, bleaching 0–10%, fish
richness 14–24 spp, rugosity index 1.07–1.66).
Provenance (normalized: pointer + registry + read-time resolver)
Provenance is NOT embedded per slot. Each slot carries only its sources slug pointer(s)
(epa_pr2011_coral_survey / epa_usvi2009_coral_survey); the full metadata (name, url = the
data.gov record, doi, publication, source_files) lives once in the central registry
(terrapulse.monitor.provenance.KNOWN_SOURCES + the datasources table), keyed by slug. The kind's
canonical sources are also in KIND_SOURCES["coral_reef_station"], so a slot resolves even without a
per-slot pointer. Resolve at read/serve time with resolve_for_kind("coral_reef_station", slot.get("sources"), conn=...); never store the resolved block on the record. The exact source
workbooks stay cached byte-for-byte under data/coral_reef_cache/<survey>/, and the committed
registry + SURVEYS dict hold the same URLs/DOIs, so the kind is fully reproducible. This follows
the global provenance model (feedback_provenance_every_datum, Mike 2026-07-01: normalized pointer,
not an embedded copy).
Deferred (not in v1)
- PR2011 secondary taxa: invertebrates, gorgonians/sponges, Palythoa — PR2011's other workbooks (USVI2009's inverts + sponges/gorgonians are now folded in; PR2011's remain deferred, files cached, one reader-wiring away).
- USVI2009 FoRAM Index — held out on the measured-reality line (see the section above), not merely deferred; would need a version carrying the raw foraminiferal counts.
- Further sibling EPA regional reef surveys (other years / jurisdictions) that keep growing this into a multi-region reef-station network. Two surveys in (PR2011 + USVI2009); the registry is proven to accept same-shape surveys with one entry.
- Spatial sweep / cross-match (
swept=false,cross_match="deferred-v2-locationdex"), as with the other Locationdex kinds. - Exact per-transect replication (the v1 density assumes one transect per area value).