Inside the Station Catalog
Comparing a satellite pass against a tide gauge starts with knowing where the gauge sits and what measures the water there, and Tidemark holds both in a table the package ships, src/tidemark/gauges/stations.parquet, carrying every gauge the comparison reads. This page follows that table from the services it is built from, through the filters and the keys that decide which gauges reach it, to its columns.
The Services
The gauges this project serves are the network the Gulf of Maine Research Institute and NERACOOS operate along the Maine coast, built from gauges by two makers, Hohonu and Greenstream. NERACOOS publishes one dataset per gauge on its ERDDAP server1, and that server carries gauges from other operators beside them, including the four the USGS runs up the Kennebec at Augusta, Gardiner, and Hallowell and on the Saco at Camp Ellis2 and the two Brown University runs at Rockland, so the catalog reads each USGS gauge's position and datum from the ERDDAP and asks the USGS Water Data API only for the monitoring location its series is read from.
The stations NOAA operates come from its Center for Operational Oceanographic Products and Services (CO-OPS), whose metadata API3 lists its water level stations and, for a station it has removed, the first and last dates of its series. The same answer carries each station's datum table, from which the catalog keeps the heights of NAVD 88 and of mean lower low water above the station datum, their epoch, and the date CO-OPS accepted them, so mise run data:catalog writes a revision of any of them into the table. A station's datum reads NAVD 88 wherever that table lists NAVD88 and mean lower low water otherwise, which leaves Bar Harbor, whose table lists no NAVD 88 tie, on mean lower low water, measured onto NAVD 88 as The NAVD 88 Offset sets out, and A NOAA Station's Reading sets out how its series reads each height on that datum.
The Vendors
Each dataset id opens on the name of the gauge's maker or of the network running it, and the vendor the catalog declares under that name sets whether the gauge arrives as an anchor or a target. mise run docs:render writes the table below from Vendor.known in src/tidemark/gauges/vendors.py and from the station catalog.
| Prefix | Vendor | Its Gauges | Gauges in the Table |
|---|---|---|---|
brown | Brown University | Targets | 2 |
greenstream | Greenstream | Targets | 5 |
hohonu | Hohonu | Targets | 15 |
usgs | USGS | Anchors | 4 |
Reading the Sensor Type
The catalog holds the instrument a gauge measures the water with where a source states it, a difference that matters for the reasons The Gauge’s Reading gives. The NERACOOS ERDDAP states it for the two datasets at Machias, in each dataset's title and summary, so sensor reads radar and ultrasonic there. Each NOAA station's sensor listing names its water level instrument, and sensor keeps NOAA's word for it, acoustic for Acoustic WL and microwave for Microwave WL, reading only the enabled sensors and leaving out Tsunami WL, a name stating what the channel serves rather than how it measures. The listing names none at Wells, whose sensor stays empty as a notice reports. Every other gauge's stays empty as well, since no source the catalog reads states it.
The Two Filters
Two filters decide which gauges the catalog reads:
- The catalog searches the ERDDAP for every dataset publishing
sea_surface_height_above_geopotential_datum, the CF standard name every water level on that server carries, so a gauge from any maker or operator is found, whatever pattern its dataset id follows. - Of those, the catalog keeps the gauges in Maine, reading the state out of the dataset's id and its title together, since the server publishes no field naming it:
- Neither field carries the state for every gauge, in that the two Machias datasets name Maine only in the title, while the Squamscott River dataset names New Hampshire only in the id.
- A dataset naming no state, and one naming two different states, are both left out.
The catalog then writes a gauge it reads only where it declares the vendor its dataset id opens on, as The Vendors sets out, and leaves any other out of the table. Each gauge it writes from the ERDDAP reports the datum its own water level sits on, read from the attribute the ERDDAP publishes on that variable, so the table records a verified reference rather than an assumed one. Every Maine gauge on that server names the North American Vertical Datum of 1988.
The map below sets every gauge the catalog keeps, each NOAA station where CO-OPS places it3, on a coast cut from the provinces' boundary file Statistics Canada publishes4 and the states' file the U.S. Census Bureau publishes5, as every map on the site does.
Anchor
Target
Retired
32 gauges at 31 places along the Maine coast
The Machias Pair
Two datasets sit at Machias, Hohonu_tide_Machias_radar and Hohonu_tide_Machias_ultrasonic, at the same position and under the same place name, differing only in the sensor each one reads, so a disagreement between them comes from the sensors rather than from the water, making the pair the side-by-side test The Gauge’s Reading names.
The NOAA Stations
The CO-OPS listing returns every Maine water level station NOAA still operates, meaning Eastport, Cutler Farris Wharf, Bar Harbor, Portland, and Seavey Island, and the next rebuild writes any station NOAA adds or removes into the table. The listing never returns Wells, which NOAA removed on 2022-08-03, yet the low-cost network's own history reaches back past that date, so the catalog requests Wells by station id and records the removal date the API reports.
A NOAA station's key follows from whether NOAA still operates it:
- A station NOAA operates takes
NWLON_<id>, the id the NERACOOS ERDDAP uses for the dataset it serves that station under, so a NOAA row and a low-cost row read alike. The catalog builds that key rather than reading the dataset back, since the mirror publishes its height under a different variable name and names no datum. - A station NOAA has removed takes its bare station id, because that server carries no dataset for a station it no longer receives.
Anchors and Targets
The anchor column marks each gauge an agency operates, meaning the NOAA stations and the USGS gauges, which arrive with the vertical reference that agency established. No service publishes it, so the catalog reads every NOAA station as an anchor, and a gauge on the ERDDAP as one wherever its vendor is declared an agency. Every other gauge is a target, a low-cost gauge the Gulf of Maine Research Institute or Brown University runs, whose sensor elevation the comparison estimates.
The NAVD 88 Offset
Every comparison reads a gauge's water surface elevation on NAVD 88, whereas Bar Harbor and Camp Ellis, both anchors, publish no surveyed tie to it. Bar Harbor's datum table lists no NAVD 88 at all, since CO-OPS lists NAVD 88 among a station's datums only where two or more of the marks on its bench mark sheet carry a height on it, and only one of Bar Harbor's does3. USGS records Camp Ellis's gage datum at 0.0 ft above NAVD 88, give or take 4.3 ft, as interpolated from an elevation model2. For each such gauge, a rebuild measures the height of the datum the gauge publishes on above NAVD 88, its NAVD 88 offset, which a height on that datum adds to reach NAVD 88, through the first of the routes below that reaches it:
- A bench mark on the station's own sheet whose NGS datasheet carries an adjusted height on NAVD 88, the offset being that height less the mark's height on the sheet above the datum the gauge publishes on6. NGS's documentation of its datasheet gives a leveled height's order and class as its only measure of accuracy and states a tolerance for class 0 alone, 8.4 mm for second order. VDatum's estimation of its uncertainties gives the tidal datums of the Gulf of Maine's tide stations a standard deviation of 1.6 cm, so an offset from a mark carries the two as the root of the sum of their squares, the way VDatum combines its own.
- NOAA's VDatum, between the gauge's tidal datum and NAVD 88 at the gauge, at the uncertainty VDatum gives, wherever no such mark reaches a gauge publishing on a tidal datum7. At the Bath gauge, on a tidal river, the observation-based offset was 32 cm less than the modeled VDatum offset, and Baranes et al. report on page 10 that it remains uncertain whether river influence, insufficient model resolution, or some other cause explains the discrepancy8.
- The altitude the gauge's agency records for its datum, at the accuracy the agency states, for a gauge neither route reaches, which is how Camp Ellis enters the comparison carrying its 4.3 ft.
A rebuild asks VDatum at every NOAA station without a NAVD 88 tie whatever route reaches it, so the two routes can be compared wherever both do. mise run docs:render writes the table below from the station catalog, every height in meters, beside the PID of the mark each offset from a mark is measured from and the offset less VDatum's. At Bar Harbor, the offset from K 22 differs from VDatum's by far less than the uncertainty VDatum gives its own, and each series reads on NAVD 88 through its gauge's offset, as A NOAA Station's Reading and A USGS Gauge's Windows set out.
Bar Harbor’s tide gauge counts from a low-water line 1.821 m below the land survey’s national zero, NAVD 88, so every reading it takes reads 1.821 m lower on NAVD 88.
Point at a part of the drawing, or move to it with the Tab key, to read what it shows. Press the reading to watch it carried onto NAVD 88 again.
NAVD 88, the North American Vertical Datum of 1988, is the zero the National Geodetic Survey keeps for heights on land, fixed by leveling between its survey marks, and every comparison here reads on it.
Mean lower low water is the mean of each tidal day’s lower low water at Bar Harbor over 1983–2001, which NOAA CO-OPS computes for the station, and the zero its tide gauge counts each reading from.
Bench mark PE0281 carries one height measured from each zero, on NAVD 88 on its NGS datasheet and above the low-water line on the tide station’s bench mark sheet.
The mark’s two heights differ by the gap between the zeros, which puts the low-water line 1.821 m below NAVD 88, give or take 0.018 m.
NOAA’s VDatum model puts the low-water line at −1.812 m on NAVD 88, give or take 0.117 m, which is 0.009 m from where the mark puts it.
Where the gauge reads 1.000 m above the low-water line, adding the offset of −1.821 m puts the same water at −0.821 m on NAVD 88.
Every value as a table
| Station | Gauge | Route | Offset | VDatum | Less VDatum's |
|---|---|---|---|---|---|
NWLON_8413320 | Bar Harbor | mark at PE0281 | -1.821 ± 0.018 | -1.812 ± 0.117 | -0.009 |
USGS_tide_Saco_ME | Saco River at Camp Ellis near Saco, ME | agency | 0.000 ± 1.311 | None given | None given |
The Surveyed Elevation
No service publishes the surveyed elevation of a sensor, which the stakeholder holds from the surveys The Unsurveyed Gauge describes. The distance d at a surveyed gauge is that elevation less the published water surface elevation.
Rebuilding the Table
The package ships the catalog rather than fetching it, since every step looks a gauge up by the one key the table indexes it under. mise run data:catalog rebuilds it from the services through tidemark catalog, reading each answer through its record on The Service Records. A rebuild sends its requests one at a time, reading the ERDDAP's search, its dataset listing, and the CO-OPS station listing once each, then the information table of each gauge it writes from the ERDDAP for its datum, one answer for each NOAA station, which carries its bench marks and its datum table, its sensor listing, and the USGS monitoring locations within a thousandth of a degree of each USGS gauge, of which the one on a tidal stream or an estuary becomes its usgs_id. A NOAA station whose datum table lists no NAVD 88 then sends three more at once, for its bench mark sheet, for the NGS datasheet of each published mark it lists a PID for, and for VDatum's offset at the station.
A rebuild records what each service answered under data/gauges/catalog/, and parts.json names those answers beside the release that ships them. Each weekly release carries them as catalog.tar.zst, whose bytes stand until a rebuild records other answers, since the answers leave out what moves while an answer stands, the actual_range and ancillary_variables rows of an ERDDAP information table, the self links and stormsurge flags of a CO-OPS answer, and the timeStamp on a USGS answer. mise run data:catalog -- --check seeds any answer data/ lacks from that release and rebuilds the table from them, asking no service, so it reports where the code no longer rebuilds the table the package ships. A rebuild and a check both refuse a shipped table that fails StationSchema, printing the fault and exiting 1.
Every request goes through one session per thread, which names this project in its User-Agent, and a rebuild reads every gauge and every station at once. A request the service never answered, answered with a server error, or refused as too many requests is sent again once its host reopens, at the pace that host's refusals set, as is the 403 the CO-OPS throttle answers with, as The CO-OPS Throttle sets out, whereas a USGS lookup fails at once past the API's hourly limit, as USGS Request Limits sets out.
Rebuild Notices
A rebuild and a check both print a notice for anything the services left unread or a gauge the table leaves out, and a notice is information rather than a failure, so a rebuild writes the table from every gauge it can read, whatever it found:
- A gauge the catalog writes from the ERDDAP names a datum other than NAVD 88 for its own water level, or names none.
- A USGS gauge sits within a thousandth of a degree of no single USGS monitoring location on a tidal stream or an estuary, or of more than one, so its
usgs_idstays empty. - A NOAA station whose datum table lists no NAVD 88 is reached by neither a bench mark nor VDatum, so its NAVD 88 offset stays empty.
- A NOAA station's sensor listing names no single water level instrument, so its
sensorstays empty. - A column no service publishes has gone missing from the table, so every gauge would read it as empty.
- A gauge's dataset id opens on a prefix the catalog declares no vendor under, so the table leaves it out, and a check lists it among the stations the rebuild adds until
Vendor.knowndeclares its vendor.
The Station Table
One row per
gauge
station
Shares station with 4 other tables.
station also keys The Series Table, counts.parquet, distances.parquet, and looks.parquet.
29columns
mise run docs:render writes the table below from StationSchema, each column beside the service that fills it, whether the NERACOOS ERDDAP1 or CO-OPS3. The columns no service publishes are read from the table a rebuild is about to replace, so a low-cost gauge's sensor type and the stakeholder's survey values survive one. Since vendor comes from the ERDDAP alone, it stays empty on a row that reached the table from CO-OPS, whereas datum takes the one spelling Datum declares for both services, navd for NAVD 88 and mllw for mean lower low water.
EitherEither
datum_vdatum_navd88_survey_Each bar is a column’s share of the 32 gauges · point at a gauge for its row
stationERDDAPCO-OPS
anchorVendor
coops_idCO-OPS
datumERDDAPCO-OPS
datum_acceptedCO-OPS
datum_epochCO-OPS
latitudeERDDAPCO-OPS
longitudeERDDAPCO-OPS
mllw_stnd_mCO-OPS
nameERDDAPCO-OPS
navd88_offset_mOffset
navd88_offset_markNGS
navd88_offset_routeOffset
navd88_offset_uncertainty_mOffset
navd88_stnd_mCO-OPS
operatorERDDAPCO-OPS
retiredCO-OPS
sensorPrevious tableCO-OPS
sensor_navd88_mPrevious table
sourceERDDAPCO-OPS
survey_datePrevious table
survey_framePrevious table
survey_geoidPrevious table
survey_methodPrevious table
survey_uncertainty_mPrevious table
usgs_idUSGS
vdatum_offset_mVDatum
vdatum_uncertainty_mVDatum
vendorERDDAP
The key every step reads a gauge by.
Whether an agency has already established this gauge's vertical reference.
The NOAA station id, which stays empty on a gauge NOAA does not operate.
The vertical datum this gauge's water levels are read on, meaning the surface that counts as zero height.
The date CO-OPS accepted the NOAA station's datum heights, which stays empty on a gauge NOAA does not operate.
The years the NOAA station's tidal datums average over, which stays empty on a gauge NOAA does not operate.
Where the gauge sits in degrees north, inside Maine's extent.
Where the gauge sits in degrees east, inside Maine's extent.
The height of mean lower low water in meters above the NOAA station's station datum.
The place the gauge sits.
The height in meters above NAVD 88 of the datum a gauge without a surveyed NAVD 88 tie publishes on, which a height on that datum adds to reach NAVD 88, and which stays empty on every other gauge.
The NGS PID of the bench mark that offset is measured from, which stays empty on every other route.
The route that offset reaches NAVD 88 by, from a bench mark NGS levels on it as `mark`, through NOAA's VDatum as `vdatum`, or as the gauge's agency records it as `agency`.
The uncertainty of that offset in meters, a standard deviation.
The height of NAVD 88 in meters above the NOAA station's station datum, which stays empty where the station has no NAVD 88 tie.
Who runs the gauge.
The date NOAA removed the station, which stays empty while it operates.
The instrument the gauge measures the water with, in the word its source uses, which stays empty where no source states it.
The surveyed elevation of the sensor in meters above NAVD 88, empty where the table carries no survey.
Which service supplied the row, either the NERACOOS ERDDAP or NOAA CO-OPS.
The date the survey ran, empty where the table carries no survey.
The reference frame the survey worked in, empty where the table carries no survey.
The geoid model the survey read its height above sea level from, empty where the table carries no survey.
How the survey established the elevation, empty where the table carries no survey.
The vertical uncertainty the survey reports in meters, empty where the table carries no survey.
The USGS monitoring location a USGS gauge's series is read from, which stays empty on every other gauge.
The NAVD 88 offset NOAA's VDatum gives at a NOAA station without a NAVD 88 tie, in meters, which stays empty where its grids do not reach the station.
The vertical uncertainty VDatum gives that offset in meters.
The gauge's maker or the network running it, read from the dataset id's prefix.
WestEast
All 26 gauges the ERDDAP lists hold it, and none of the six CO-OPS stations does.
RocklandGreenstream
HeldRocklandGreenstream
ArrowsicGreenstream
HeldArrowsicGreenstream
Bar Harborempty
HeldBar Harborempty
BowdoinhamGreenstream
HeldBowdoinhamGreenstream
YorkHohonu
HeldYorkHohonu
Chebeague IslandHohonu
HeldChebeague IslandHohonu
Cutler Farris Wharfempty
HeldCutler Farris Wharfempty
East BoothbayHohonu
HeldEast BoothbayHohonu
Boothbay HarborHohonu
HeldBoothbay HarborHohonu
Eastportempty
HeldEastportempty
PortlandHohonu
HeldPortlandHohonu
PhippsburgGreenstream
HeldPhippsburgGreenstream
PortlandHohonu
HeldPortlandHohonu
MilbridgeHohonu
HeldMilbridgeHohonu
Kennebec River at Calumet Bridge at AugustaUSGS
HeldKennebec River at Calumet Bridge at AugustaUSGS
Kennebec River at GardinerUSGS
HeldKennebec River at GardinerUSGS
Kennebec River at HallowellUSGS
HeldKennebec River at HallowellUSGS
KennebunkportHohonu
HeldKennebunkportHohonu
RocklandBrown University
HeldRocklandBrown University
MachiasHohonuHohonu
HeldMachiasHohonuHohonu
BathHohonu
HeldBathHohonu
St. GeorgeHohonu
HeldSt. GeorgeHohonu
Portlandempty
HeldPortlandempty
RocklandBrown University
HeldRocklandBrown University
Saco River at Camp Ellis near SacoUSGS
HeldSaco River at Camp Ellis near SacoUSGS
Scarborough RiverHohonu
HeldScarborough RiverHohonu
Seavey Islandempty
HeldSeavey Islandempty
Stonington HarborHohonu
HeldStonington HarborHohonu
JonesportHohonu
HeldJonesportHohonu
BucksportGreenstream
HeldBucksportGreenstream
Wellsempty
HeldWellsempty
Every value as a table
| Column | Holds | Filled From |
|---|---|---|
station | A shared key the tables join on | The ERDDAP and CO-OPS |
anchor | Whether an agency has already established this gauge's vertical reference | The vendor and CO-OPS |
coops_id | The NOAA station id, which stays empty on a gauge NOAA does not operate | CO-OPS |
datum | The vertical datum this gauge's water levels are read on, meaning the surface that counts as zero height | The ERDDAP and CO-OPS |
datum_accepted | The date CO-OPS accepted the NOAA station's datum heights, which stays empty on a gauge NOAA does not operate | CO-OPS |
datum_epoch | The years the NOAA station's tidal datums average over, which stays empty on a gauge NOAA does not operate | CO-OPS |
latitude | Where the gauge sits in degrees north, inside Maine's extent | The ERDDAP and CO-OPS |
longitude | Where the gauge sits in degrees east, inside Maine's extent | The ERDDAP and CO-OPS |
mllw_stnd_m | The height of mean lower low water in meters above the NOAA station's station datum | CO-OPS |
name | The place the gauge sits | The ERDDAP and CO-OPS |
navd88_offset_m | The height in meters above NAVD 88 of the datum a gauge without a surveyed NAVD 88 tie publishes on, which a height on that datum adds to reach NAVD 88, and which stays empty on every other gauge | CO-OPS, NGS, VDatum, and USGS |
navd88_offset_mark | The NGS PID of the bench mark that offset is measured from, which stays empty on every other route | NGS |
navd88_offset_route | The route that offset reaches NAVD 88 by, from a bench mark NGS levels on it as mark, through NOAA's VDatum as vdatum, or as the gauge's agency records it as agency | CO-OPS, NGS, VDatum, and USGS |
navd88_offset_uncertainty_m | The uncertainty of that offset in meters, a standard deviation | CO-OPS, NGS, VDatum, and USGS |
navd88_stnd_m | The height of NAVD 88 in meters above the NOAA station's station datum, which stays empty where the station has no NAVD 88 tie | CO-OPS |
operator | Who runs the gauge | The ERDDAP and CO-OPS |
retired | The date NOAA removed the station, which stays empty while it operates | CO-OPS |
sensor | The instrument the gauge measures the water with, in the word its source uses, which stays empty where no source states it | The previous table and CO-OPS |
sensor_navd88_m | The surveyed elevation of the sensor in meters above NAVD 88, empty where the table carries no survey | The previous table |
source | Which service supplied the row, either the NERACOOS ERDDAP or NOAA CO-OPS | The ERDDAP and CO-OPS |
survey_date | The date the survey ran, empty where the table carries no survey | The previous table |
survey_frame | The reference frame the survey worked in, empty where the table carries no survey | The previous table |
survey_geoid | The geoid model the survey read its height above sea level from, empty where the table carries no survey | The previous table |
survey_method | How the survey established the elevation, empty where the table carries no survey | The previous table |
survey_uncertainty_m | The vertical uncertainty the survey reports in meters, empty where the table carries no survey | The previous table |
usgs_id | The USGS monitoring location a USGS gauge's series is read from, which stays empty on every other gauge | The USGS Water Data API |
vdatum_offset_m | The NAVD 88 offset NOAA's VDatum gives at a NOAA station without a NAVD 88 tie, in meters, which stays empty where its grids do not reach the station | VDatum |
vdatum_uncertainty_m | The vertical uncertainty VDatum gives that offset in meters | VDatum |
vendor | The gauge's maker or the network running it, read from the dataset id's prefix | The ERDDAP |
The first steps of the analysis graph read the table the package ships and hold its anchors and its targets apart.
1Gulf of Maine Research Institute & Brown University 2026. "NERACOOS ERDDAP." Northeastern Regional Association of Coastal Ocean Observing Systems. https://data.neracoos.org/
erddap/ .↩︎ ↩︎2United States Geological Survey 1994. "USGS Water Data for the Nation." https://doi.org/
10.5066/ .↩︎ ↩︎F7P55KJN 3NOAA CO-OPS 2026. "CO-OPS Data Retrieval API and Metadata API." https://tidesandcurrents.noaa.gov/
web_services_info.html .↩︎ ↩︎ ↩︎ ↩︎4Statistics Canada 2021. "Provinces/Territories, Cartographic Boundary File, 2021 Census." https://www12.statcan.gc.ca/
census-recensement/ .↩︎2021/ geo/ sip-pis/ boundary-limites/ files-fichiers/ lpr_000b21a_e.zip 5U.S. Census Bureau 2024. "2024 Cartographic Boundary File (SHP), State and Equivalent Entities for United States, 1:500,000." https://www2.census.gov/
geo/ .↩︎tiger/ GENZ2024/ shp/ cb_2024_us_state_500k.zip 6National Geodetic Survey 2026. "NGS Data Explorer API." https://geodesy.noaa.gov/
web_services/ .↩︎data-explorer.shtml 7NOAA National Ocean Service 2026. "VDatum." https://vdatum.noaa.gov/.↩︎
8Baranes et al. 2026. "Supporting Coastal Flood Forecasting and Community-Led Adaptation With Tide Gauges, Community Science and Youth Engagement." Frontiers in Climate 8: 1757212. https://doi.org/
10.3389/ ↩︎fclim.2026.1757212