You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Status: draft / not committed
Audience: maintainers of the Ocotillo OGC API backend (pygeoapi + PostGIS) at https://ocotillo-api.newmexicowaterdata.org/ogcapi
Related: DIG connector backend/connectors/ocotillo/ (added in branch feature/ocotillo-ogcapi-source)
Purpose
DIG now consumes Ocotillo as a data source intended to replace the legacy NMBGMR AMP API (ampapidev-dot-waterdatainitiative-271000.appspot.com,
DIG source key nmbgmr_amp). As currently published, Ocotillo only exposes
pre-aggregated latest / summary feature collections and no raw
observations. Because of that, the DIG Ocotillo connector is summary-only:
Timeseries output (timeseries_unified, timeseries_separated) produces
nothing for Ocotillo — it is a logged no-op.
Summary output omits several columns that AMP can populate (see below).
This document lists the backend changes required for Ocotillo to reach feature
parity with the AMP API, so the nmbgmr_amp source can be fully retired.
What AMP provides today (the parity target)
The DIG nmbgmr_amp connector uses these AMP endpoints:
paginated list of {DateMeasured, TimeMeasured, DepthToWaterBGS, DepthToWaterBGSUnits, PointID}
waterchemistry
Full analyte time series
per pointid per analyte: list of {SampleValue, Units, AnalyteMeaning, info.CollectionDate}
The two endpoints that matter most are waterlevels/manual and waterchemistry: both return every observation over time, which is what
lets DIG compute summary statistics (count, min, max, mean, earliest, latest) and emit full time series.
What Ocotillo provides today
OGC API - Features, 24 collections. Relevant ones:
Collection
Item type
Content
water_wells
feature (1/well)
name, coords, well_depth, nma_pk_welldata, nma_formation_zone (no elevation/datum/USGS id)
Every collection is one row per well holding a snapshot (latest or
aggregate). None expose per-observation history.
Gaps and required backend changes
Ordered by impact. Items 1–3 are required for parity; 4–5 are correctness/
completeness.
1. Raw observation collections (blocks time series entirely) — REQUIRED
Problem. There is no collection of individual observations, so DIG cannot
produce time series output and cannot compute mean or the earliest
observation for summaries.
Change. Publish per-observation OGC API - Features collections:
depth_to_water_observations — one feature per DTW measurement:
well name/id, observation datetime, depth-to-water value, units.
chemistry_observations — one feature per analyte result:
well name/id, analyte name, value, units, sample/collection datetime.
Requirements.
Filterable by well identifier (queryable name, matching water_wells.name,
e.g. NM-28368) and by datetime (OGC datetime parameter or a queryable
timestamp property).
Support paging (already standard in pygeoapi via limit/offset).
Publish in WGS84 GeoJSON (consistent with existing collections).
DIG impact when available. The connector can be switched from summary-only
to the standard pattern (model on nmbgmr): full timeseries + locally computed
count/min/max/mean/earliest/latest. --output-type timeseries_* starts working.
2. Chemistry history (blocks analyte summary stats) — REQUIRED
Problem.major_chemistry_results / minor_chemistry_wells expose only the
latest value per analyte. DIG therefore reports analyte summaries with only latest_value; nrecords, min, max, mean, earliest_* are blank.
Change. Covered by the chemistry_observations collection in item 1 — it
must include the full history of analyte results, not just the latest. AMP's waterchemistry returns all samples per analyte; match that.
Analyte coverage. At minimum the analytes DIG maps today (see backend/connectors/ocotillo/mappings.py): arsenic, bicarbonate, calcium,
carbonate, chloride, fluoride, magnesium, nitrate, ph, potassium, silica,
sodium, specific_conductance, sulfate, tds, uranium.
3. Site metadata on water_wells (degraded site records) — REQUIRED
Problem.water_wells lacks fields AMP's locations provides. Current DIG
behavior:
DIG site field
AMP source
Ocotillo today
elevation / elevation_units
present
null (not in water_wells)
horizontal_datum
lonlat_datum
defaulted to WGS84
vertical_datum
altitude_datum
blank
aquifer / formation
wells.formation
nma_formation_zone (partial)
usgs_site_id
locations.site_id
blank
alternate_site_id
present
nma_pk_welldata (GUID)
well_depth
wells.well_depth_ftbgs
present
Change. Add elevation (+ units), horizontal_datum, vertical_datum, aquifer/formation, and usgs_site_id to water_wells — or expose a locations-equivalent collection carrying full site metadata that DIG can seed
sites from. Note: water_well_summary already carries elevation, but it is
keyed to wells that have water levels, so it is not a complete site source for
chemistry-only wells.
Coverage note. DIG currently seeds sites from water_wells (all wells).
Wells that have chemistry/water-level data but are absent from water_wells
will not appear. Ensure water_wells (or the chosen site collection) is the
authoritative superset of monitored wells.
4. Nitrate reporting basis (silent value error risk) — REQUIRED for correctness
Problem. AMP reports Nitrate (as N) and DIG applies a 4.427 conversion to
nitrate-as-NO3. The Ocotillo nitrate column basis is undocumented; the
connector currently takes it as-is (factor 1.0). If Ocotillo reports as-N, DIG
will under-report nitrate by ~4.4x.
Change. Document and unit-tag the nitrate basis. Preferably expose the
value with an explicit unit (mg/L as N vs mg/L as NO3) in <analyte>_units / the observation record so DIG's converter can normalize
correctly. Same care for any analyte reported on an alternate basis
(e.g. bicarbonate/carbonate as CaCO3).
5. TDS history — REQUIRED for TDS parity
Problem.latest_tds_wells is latest-only; avg_tds_wells is a single
average. DIG cannot report TDS count/min/max/earliest.
Change. Include TDS in the chemistry_observations history collection (item
1/2), or add an explicit TDS observation collection. Then the latest/avg
snapshot collections become optional conveniences rather than the only source.
Field-mapping reference (post-parity, expected)
Once observation collections exist, the DIG connector would map like AMP:
Ocotillo OGC API — Backend Changes for AMP Parity
Status: draft / not committed
Audience: maintainers of the Ocotillo OGC API backend (pygeoapi + PostGIS) at
https://ocotillo-api.newmexicowaterdata.org/ogcapiRelated: DIG connector
backend/connectors/ocotillo/(added in branchfeature/ocotillo-ogcapi-source)Purpose
DIG now consumes Ocotillo as a data source intended to replace the legacy
NMBGMR AMP API (
ampapidev-dot-waterdatainitiative-271000.appspot.com,DIG source key
nmbgmr_amp). As currently published, Ocotillo only exposespre-aggregated latest / summary feature collections and no raw
observations. Because of that, the DIG Ocotillo connector is summary-only:
timeseries_unified,timeseries_separated) producesnothing for Ocotillo — it is a logged no-op.
This document lists the backend changes required for Ocotillo to reach feature
parity with the AMP API, so the
nmbgmr_ampsource can be fully retired.What AMP provides today (the parity target)
The DIG
nmbgmr_ampconnector uses these AMP endpoints:locationslonlat_datum,altitude_datum,site_id(USGS),alternate_site_idwellsformation,well_depth_ftbgswaterlevels/manual{DateMeasured, TimeMeasured, DepthToWaterBGS, DepthToWaterBGSUnits, PointID}waterchemistry{SampleValue, Units, AnalyteMeaning, info.CollectionDate}The two endpoints that matter most are
waterlevels/manualandwaterchemistry: both return every observation over time, which is whatlets DIG compute summary statistics (count, min, max, mean, earliest, latest)
and emit full time series.
What Ocotillo provides today
OGC API - Features, 24 collections. Relevant ones:
water_wellswell_depth,nma_pk_welldata,nma_formation_zone(no elevation/datum/USGS id)water_well_summarytotal_water_levels,min_water_level,max_water_level,last_water_level+last_water_level_datetime,water_level_trend_ft_per_year,elevation,well_depthlatest_depth_to_water_wellsmajor_chemistry_results<analyte>_units,latest_chemistry_date,analyte_countminor_chemistry_wellslatest_tds_wellslatest_tds_value,latest_tds_units,latest_tds_observation_dateavg_tds_wellsEvery collection is one row per well holding a snapshot (latest or
aggregate). None expose per-observation history.
Gaps and required backend changes
Ordered by impact. Items 1–3 are required for parity; 4–5 are correctness/
completeness.
1. Raw observation collections (blocks time series entirely) — REQUIRED
Problem. There is no collection of individual observations, so DIG cannot
produce time series output and cannot compute
meanor theearliestobservation for summaries.
Change. Publish per-observation OGC API - Features collections:
depth_to_water_observations— one feature per DTW measurement:well name/id, observation datetime, depth-to-water value, units.
chemistry_observations— one feature per analyte result:well name/id, analyte name, value, units, sample/collection datetime.
Requirements.
name, matchingwater_wells.name,e.g.
NM-28368) and bydatetime(OGCdatetimeparameter or a queryabletimestamp property).
limit/offset).DIG impact when available. The connector can be switched from summary-only
to the standard pattern (model on
nmbgmr): full timeseries + locally computedcount/min/max/mean/earliest/latest.
--output-type timeseries_*starts working.2. Chemistry history (blocks analyte summary stats) — REQUIRED
Problem.
major_chemistry_results/minor_chemistry_wellsexpose only thelatest value per analyte. DIG therefore reports analyte summaries with only
latest_value;nrecords,min,max,mean,earliest_*are blank.Change. Covered by the
chemistry_observationscollection in item 1 — itmust include the full history of analyte results, not just the latest. AMP's
waterchemistryreturns all samples per analyte; match that.Analyte coverage. At minimum the analytes DIG maps today (see
backend/connectors/ocotillo/mappings.py): arsenic, bicarbonate, calcium,carbonate, chloride, fluoride, magnesium, nitrate, ph, potassium, silica,
sodium, specific_conductance, sulfate, tds, uranium.
3. Site metadata on
water_wells(degraded site records) — REQUIREDProblem.
water_wellslacks fields AMP'slocationsprovides. Current DIGbehavior:
water_wells)lonlat_datumWGS84altitude_datumwells.formationnma_formation_zone(partial)locations.site_idnma_pk_welldata(GUID)wells.well_depth_ftbgsChange. Add
elevation(+ units),horizontal_datum,vertical_datum,aquifer/formation, andusgs_site_idtowater_wells— or expose alocations-equivalent collection carrying full site metadata that DIG can seedsites from. Note:
water_well_summaryalready carrieselevation, but it iskeyed to wells that have water levels, so it is not a complete site source for
chemistry-only wells.
Coverage note. DIG currently seeds sites from
water_wells(all wells).Wells that have chemistry/water-level data but are absent from
water_wellswill not appear. Ensure
water_wells(or the chosen site collection) is theauthoritative superset of monitored wells.
4. Nitrate reporting basis (silent value error risk) — REQUIRED for correctness
Problem. AMP reports
Nitrate (as N)and DIG applies a 4.427 conversion tonitrate-as-NO3. The Ocotillo
nitratecolumn basis is undocumented; theconnector currently takes it as-is (factor 1.0). If Ocotillo reports as-N, DIG
will under-report nitrate by ~4.4x.
Change. Document and unit-tag the nitrate basis. Preferably expose the
value with an explicit unit (
mg/L as Nvsmg/L as NO3) in<analyte>_units/ the observation record so DIG's converter can normalizecorrectly. Same care for any analyte reported on an alternate basis
(e.g. bicarbonate/carbonate as CaCO3).
5. TDS history — REQUIRED for TDS parity
Problem.
latest_tds_wellsis latest-only;avg_tds_wellsis a singleaverage. DIG cannot report TDS count/min/max/earliest.
Change. Include TDS in the
chemistry_observationshistory collection (item1/2), or add an explicit TDS observation collection. Then the latest/avg
snapshot collections become optional conveniences rather than the only source.
Field-mapping reference (post-parity, expected)
Once observation collections exist, the DIG connector would map like AMP:
Water level (per observation):
depth_to_water_observations.{depth_to_water_bgs, observation_datetime, units, name}→ DIG
{parameter_value, date_measured/time_measured, source_parameter_units, id}.Analyte (per observation):
chemistry_observations.{value, sample_datetime, units, analyte, name}→ DIG
{parameter_value, date_measured, source_parameter_units, source_parameter_name, id}.Summary stats (count/min/max/mean/earliest/latest) are then computed by DIG, as
they are for AMP — the backend need not pre-aggregate.
Acceptance criteria (definition of parity)
depth_to_water_observationsandchemistry_observationscollectionsexist, filterable by well
nameanddatetime, returning full history.--output-type timeseries_unifiedforwaterlevelsproduces anon-empty timeseries file from Ocotillo.
nrecords,min,max,mean,earliest_*,latest_*(no blankstats columns).
where AMP has them.
DIG output matches AMP within rounding for a shared set of wells.
nmbgmr_ampsummary outputs agree(well set, latest values, counts) within expected tolerances.
Until parity lands (current DIG behavior)
nmbgmr_amp(not a replacement). Toggle with--no-ocotillo/--no-nmbgmr-amp.mean,earliest_*(all parameters);additionally
min,max,nrecordsfor chemistry and TDS.elevationblank; datum defaults to WGS84.OCOTILLO_URL.