forcingkit 0.3.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.agents/forcingkit.md +4 -4
- forcingkit-0.5.0/.env.template +20 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/AGENTS.md +4 -3
- {forcingkit-0.3.0 → forcingkit-0.5.0}/PKG-INFO +1 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/atmospheric_forcing.rst +10 -5
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/conf.py +1 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/fetchers.rst +19 -10
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/hycom.rst +76 -16
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/index.rst +13 -5
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/necofs.rst +2 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/nyofs.rst +4 -2
- forcingkit-0.5.0/docs/source/rivers.rst +177 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/roadmap.rst +61 -15
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/sources.rst +23 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/pyproject.toml +1 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/main.py +220 -0
- forcingkit-0.5.0/src/forcingkit/data/rivers/northeast_us.json +29 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/dispatcher.py +186 -3
- forcingkit-0.5.0/src/forcingkit/fetchers/coastwatch.py +487 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/erddap.py +3 -2
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/hycom.py +44 -11
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/necofs.py +118 -1
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/noaa.py +1 -1
- forcingkit-0.5.0/src/forcingkit/fetchers/usgs.py +347 -0
- forcingkit-0.5.0/src/forcingkit/fetchers/usgs_rivers.py +625 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/settings.py +2 -3
- forcingkit-0.3.0/tests/integration/test_obc_mab.py → forcingkit-0.5.0/tests/integration/test_obc_offshore_nj.py +4 -4
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/scripts/inspect_dem.py +12 -5
- forcingkit-0.5.0/tests/unit/test_coastwatch.py +222 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_hycom.py +111 -6
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_necofs_parent.py +9 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_settings.py +4 -7
- forcingkit-0.5.0/tests/unit/test_usgs.py +110 -0
- forcingkit-0.5.0/tests/unit/test_usgs_rivers.py +490 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/uv.lock +1 -1
- forcingkit-0.3.0/.env.template +0 -17
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.claude/CLAUDE.md +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.github/copilot-instructions.md +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.github/workflows/docs.yml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.github/workflows/publish.yml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.github/workflows/tests.yml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.gitignore +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.markdownlint.yaml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.pre-commit-config.yaml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/.python-version +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/CONTRIBUTING.md +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/Dockerfile +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/LICENSE +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/README.md +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docker-compose.yml +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/Makefile +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/make.bat +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/requirements-docs.txt +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/_extra/CNAME +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/_static/custom.css +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/docs/source/_static/forcingkit-noreaster-wind.gif +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/main.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/__init__.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/__init__.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/routers/bathymetry.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/routers/plotly_api.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/routers/removed.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/forcingkit_serve/routers/viewer.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/service/run_server.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/__init__.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/dbofs.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/hrrr.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/hrrr_atmosphere.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/hydrography.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/ndbc.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/fetchers/nyofs.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/src/forcingkit/zarr_stream.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/app.js +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/favicon.ico +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/favicon.svg +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/index.html +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/logo.svg +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/preview3d.js +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/static/styles.css +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/__init__.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/integration/test_auth.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/integration/test_erddap_fetch.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/integration/test_nyofs_obc_fetch.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/integration/test_ofs_archive_paths.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/integration/test_s3_roms_fetchers.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/scripts/inspect_grib.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/scripts/inspect_zarr.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_dbofs.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_dispatcher.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_hrrr_atm.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_hrrr_idx.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_main.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_ndbc.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_noaa_currents.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_noaa_datum.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_nyofs.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_obc_donor_report.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_obc_pipeline.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_removed_routes.py +0 -0
- {forcingkit-0.3.0 → forcingkit-0.5.0}/tests/unit/test_zarr_stream.py +0 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
## Mission
|
|
4
4
|
|
|
5
5
|
Python microservice providing real-time and historical forcing (the parent ocean and
|
|
6
|
-
the HRRR atmosphere) and validation observations to
|
|
7
|
-
|
|
6
|
+
the HRRR atmosphere) and validation observations to downstream ocean models, for
|
|
7
|
+
example ones built on Oceananigans.jl or NumericalEarth.
|
|
8
8
|
|
|
9
9
|
## Environment
|
|
10
10
|
|
|
@@ -41,7 +41,7 @@ HTTP Request → service/forcingkit_serve/main.py
|
|
|
41
41
|
*Note: Because the architecture is modular, a future roadmap item includes the integration of TPXO (via `tpxo.py`) given usage rights.*
|
|
42
42
|
|
|
43
43
|
Atmospheric forcing: HRRR from 2014-07-30 (`hrrr_atmosphere.py`, `/api/v1/atmosphere`).
|
|
44
|
-
Earlier runs use ERA5 through NumericalEarth in
|
|
44
|
+
Earlier runs use ERA5 through NumericalEarth in the model, not this service.
|
|
45
45
|
|
|
46
46
|
## Testing
|
|
47
47
|
|
|
@@ -89,7 +89,7 @@ uv run python -c "from forcingkit.fetchers import nyofs; print(nyofs.get_metadat
|
|
|
89
89
|
- **Mocking strategy**: Dispatcher unit tests check tuple/dict return
|
|
90
90
|
boundaries carefully. When modifying mocked fetchers, track
|
|
91
91
|
keyword-argument vs positional argument boundaries.
|
|
92
|
-
- **Grid normalization**:
|
|
92
|
+
- **Grid normalization**: downstream models expect elevations positive
|
|
93
93
|
up (LMSL/NAVD88). Normalize any inverted datasets in the fetcher
|
|
94
94
|
tier before the dispatcher sees them.
|
|
95
95
|
- **Cache keys**: Cache Zarr keys are deterministic hashes of bbox
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# forcingkit environment variables
|
|
2
|
+
# Copy this file to .env and fill in your credentials.
|
|
3
|
+
# A docker-compose service can load it with env_file.
|
|
4
|
+
|
|
5
|
+
# No credentials are required: HRRR, NOAA OFS, NECOFS, HYCOM, NDBC, CO-OPS and the
|
|
6
|
+
# USGS Water Data APIs are all served without authentication.
|
|
7
|
+
|
|
8
|
+
# Optional USGS Water Data API key (free from https://api.waterdata.usgs.gov/signup/).
|
|
9
|
+
# Without it, river discharge requests still work at a lower hourly rate limit.
|
|
10
|
+
# USGS_API_KEY=
|
|
11
|
+
|
|
12
|
+
# Cache root for every store (default ~/.cache/forcingkit). The old name
|
|
13
|
+
# ECODATA_CACHE_CACHE_DIR is still read, with a warning, until the next release.
|
|
14
|
+
# FORCINGKIT_CACHE_DIR=~/.cache/forcingkit
|
|
15
|
+
|
|
16
|
+
# Threads for parallel OPeNDAP reads (default 4; was ECODATA_CACHE_MAX_WORKERS).
|
|
17
|
+
# FORCINGKIT_MAX_WORKERS=4
|
|
18
|
+
|
|
19
|
+
# The topobathykit elevation service (default http://localhost:9595; was TOPOBATHYSIM_URL).
|
|
20
|
+
# TOPOBATHYKIT_URL=http://localhost:9595
|
|
@@ -22,9 +22,10 @@ guidance in this repository.
|
|
|
22
22
|
## Repository Focus
|
|
23
23
|
|
|
24
24
|
forcingkit is a Python microservice that fetches, harmonizes, regrids, and serves
|
|
25
|
-
real-time and historical forcing to
|
|
26
|
-
ocean (`/api/v1/obc`, schema z-
|
|
27
|
-
and station telemetry and NDBC
|
|
25
|
+
real-time and historical forcing to downstream ocean models (for example ones built on
|
|
26
|
+
Oceananigans.jl or NumericalEarth): the parent ocean (`/api/v1/obc`, schema z-v3), the
|
|
27
|
+
HRRR atmosphere (`/api/v1/atmosphere`), tides, and station telemetry and NDBC
|
|
28
|
+
observations for validation.
|
|
28
29
|
|
|
29
30
|
## Core Rules
|
|
30
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: forcingkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Spatiotemporal forcing for computational Earth-system models: selects, regrids and serves model-ready time series with provenance.
|
|
5
5
|
Project-URL: Documentation, https://forcingkit.docs.lhzn.io
|
|
6
6
|
Project-URL: Issues, https://github.com/lhzn-io/forcingkit/issues
|
|
@@ -2,7 +2,8 @@ Atmospheric Forcing Datasets
|
|
|
2
2
|
============================
|
|
3
3
|
|
|
4
4
|
As of 2026-10-04. Which atmospheric datasets can force a coastal ocean model through this service
|
|
5
|
-
or through `NumericalEarth <https://github.com/NumericalEarth/NumericalEarth.jl>`__, how they
|
|
5
|
+
or through `NumericalEarth <https://github.com/NumericalEarth/NumericalEarth.jl>`__, how they
|
|
6
|
+
compare, and which to choose.
|
|
6
7
|
|
|
7
8
|
An ocean model's surface fluxes need, at every hour of the run: 10 m wind (eastward and
|
|
8
9
|
northward), 2 m air temperature and specific humidity, surface pressure, precipitation, and
|
|
@@ -151,9 +152,11 @@ ERA5 (fallback)
|
|
|
151
152
|
|
|
152
153
|
*Provenance.* `ECMWF <https://www.ecmwf.int/>`__'s fifth-generation global reanalysis for the
|
|
153
154
|
`Copernicus Climate Change Service <https://climate.copernicus.eu/>`__ (`Hersbach et al., 2020
|
|
154
|
-
<https://doi.org/10.1002/qj.3803>`__): 0.25 degree grid (about 31 km), hourly, 1940 to the present.
|
|
155
|
+
<https://doi.org/10.1002/qj.3803>`__): 0.25 degree grid (about 31 km), hourly, 1940 to the present.
|
|
156
|
+
ERA5T, the initial release,
|
|
155
157
|
appears about five days behind real time and is overwritten by the final ERA5 two to three months
|
|
156
|
-
later. Requires a free `Copernicus Climate Data Store <https://cds.climate.copernicus.eu/>`__
|
|
158
|
+
later. Requires a free `Copernicus Climate Data Store <https://cds.climate.copernicus.eu/>`__
|
|
159
|
+
account (credentials in ``~/.cdsapirc``);
|
|
157
160
|
Copernicus licence, attribution required.
|
|
158
161
|
|
|
159
162
|
*How it is used.* A model reads it through NumericalEarth's ``ERA5PrescribedAtmosphere`` and
|
|
@@ -167,7 +170,8 @@ standard against which forcing biases are judged.
|
|
|
167
170
|
|
|
168
171
|
*Limits.* At 31 km a 15 km coastal domain spans one or two ERA5 cells, so the forcing is nearly
|
|
169
172
|
uniform and smears the coast: in the first hours of 2026-04-02 over such a domain off New Jersey,
|
|
170
|
-
the ERA5 box (which includes New Jersey land) was about 3 K warmer at 2 m and had about half HRRR's
|
|
173
|
+
the ERA5 box (which includes New Jersey land) was about 3 K warmer at 2 m and had about half HRRR's
|
|
174
|
+
wind speed. Latency rules out
|
|
171
175
|
anything closer than five days to the present.
|
|
172
176
|
|
|
173
177
|
Choosing
|
|
@@ -220,6 +224,7 @@ Links
|
|
|
220
224
|
- NOAA HRRR on AWS: https://registry.opendata.aws/noaa-hrrr-pds/
|
|
221
225
|
- NOAA RRFS: https://gsl.noaa.gov/rrfs/ ; operational date and retirements:
|
|
222
226
|
https://gribstream.com/blog/noaa-rrfs-refs-operational-august-2026
|
|
223
|
-
- ERA5T latency:
|
|
227
|
+
- ERA5T latency:
|
|
228
|
+
https://climate.copernicus.eu/key-update-climate-dataset-brings-data-five-days-behind-real-time
|
|
224
229
|
- ECMWF open data: https://www.ecmwf.int/en/forecasts/datasets/open-data
|
|
225
230
|
- JRA55-do: https://climate.mri-jma.go.jp/pub/ocean/JRA55-do/
|
|
@@ -19,11 +19,12 @@ Atmospheric forcing (``/api/v1/atmosphere``)
|
|
|
19
19
|
- NOAA `High-Resolution Rapid Refresh <https://rapidrefresh.noaa.gov/hrrr/>`__ (developed by
|
|
20
20
|
the `NOAA Global Systems Laboratory <https://gsl.noaa.gov/>`__, run operationally by
|
|
21
21
|
`NCEP <https://www.nco.ncep.noaa.gov/>`__), 3 km, from the anonymous AWS S3 bucket
|
|
22
|
-
`noaa-hrrr-bdp-pds <https://registry.opendata.aws/noaa-hrrr-pds/>`__; the archive starts
|
|
23
|
-
regular 0.03 degree grid and streamed hour
|
|
24
|
-
use `ERA5
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
`noaa-hrrr-bdp-pds <https://registry.opendata.aws/noaa-hrrr-pds/>`__; the archive starts
|
|
23
|
+
2014-07-30. Surface fields are interpolated to a regular 0.03 degree grid and streamed hour
|
|
24
|
+
by hour (schema ``hrrr-atm-v1``). Earlier dates use `ERA5
|
|
25
|
+
<https://cds.climate.copernicus.eu/>`__ through `NumericalEarth
|
|
26
|
+
<https://github.com/NumericalEarth/NumericalEarth.jl>`__ in the model, outside this
|
|
27
|
+
service. See :doc:`atmospheric_forcing`.
|
|
27
28
|
|
|
28
29
|
Parent ocean (``/api/v1/obc``)
|
|
29
30
|
------------------------------
|
|
@@ -37,7 +38,8 @@ Parent ocean (``/api/v1/obc``)
|
|
|
37
38
|
* - **NECOFS**
|
|
38
39
|
- `Northeast Coastal Ocean Forecast System <https://fvcom.smast.umassd.edu/?p=20>`__, `FVCOM
|
|
39
40
|
<https://fvcom.smast.umassd.edu/>`__ GOM7 (`UMass Dartmouth SMAST
|
|
40
|
-
<https://www.umassd.edu/smast/>`__ and `WHOI <https://www.whoi.edu/>`__), unstructured mesh
|
|
41
|
+
<https://www.umassd.edu/smast/>`__ and `WHOI <https://www.whoi.edu/>`__), unstructured mesh
|
|
42
|
+
with 45 sigma layers. Daily history files from 2025-01-01, then the rolling forecast.
|
|
41
43
|
The only donor that streams the ``z-v3`` parent store. See :doc:`necofs`.
|
|
42
44
|
* - **NYOFS**
|
|
43
45
|
- `NOAA New York/New Jersey Operational Forecast System
|
|
@@ -58,12 +60,16 @@ Parent ocean (``/api/v1/obc``)
|
|
|
58
60
|
the present. The experiment follows the date: GLBv0.08 ``expt_53.X`` (reanalysis) to
|
|
59
61
|
2015, a chain of GLBv0.08 analysis experiments to 2018-12-04, GLBy0.08 ``expt_93.0`` to
|
|
60
62
|
2024-09-05, then ESPC-D-V02. A window that spans a switch is stitched; if any piece fails,
|
|
61
|
-
the whole window fails.
|
|
63
|
+
the whole window fails. Tidal only from 2024-09-05, recorded in the store's ``tides``
|
|
64
|
+
attribute (``"none"``, ``"included"`` or ``"mixed"``). Last-resort fallback; legacy
|
|
65
|
+
output layout.
|
|
62
66
|
|
|
63
67
|
`TPXO10 <https://www.tpxo.net/>`__ tidal harmonics are a roadmap item, not integrated; the
|
|
64
68
|
`pyTMD <https://github.com/pyTMD/pyTMD>`__ dependency was removed on
|
|
65
69
|
2026-10-05. The ``include_tides`` and ``tidal_model`` request fields
|
|
66
70
|
are still accepted and form part of the cache key, but no tide is added to the parent store.
|
|
71
|
+
A parent that already contains the tide (a HYCOM store with ``tides = "included"``) should not
|
|
72
|
+
have tides added again downstream; see :doc:`hycom`.
|
|
67
73
|
|
|
68
74
|
Donor selection
|
|
69
75
|
~~~~~~~~~~~~~~~
|
|
@@ -149,8 +155,9 @@ As checked on 2026-10-06, NYOFS and DBOFS output is available from three places:
|
|
|
149
155
|
- From 2024-11-19, one directory per day, ``<ofs>/netcdf/{yyyy}/{mm}/{dd}/``; the first day
|
|
150
156
|
holds only its last cycle. Before that, one flat directory per month,
|
|
151
157
|
``<ofs>/netcdf/{yyyymm}/``, with a mix of file names (NYOFS 2024-07 uses the older names,
|
|
152
|
-
DBOFS 2024-07 the newer ones); several of those months are partial and some are absent
|
|
153
|
-
and 2024-06; DBOFS lacks 2024-02 and starts
|
|
158
|
+
DBOFS 2024-07 the newer ones); several of those months are partial and some are absent
|
|
159
|
+
(NYOFS lacks 2024-01 to 2024-03, 2024-05 and 2024-06; DBOFS lacks 2024-02 and starts
|
|
160
|
+
2024-01 on the 29th).
|
|
154
161
|
|
|
155
162
|
.. note::
|
|
156
163
|
An earlier version of this page said that NCEI stopped archiving at the end of November 2023,
|
|
@@ -181,7 +188,9 @@ Common processing
|
|
|
181
188
|
-----------------
|
|
182
189
|
|
|
183
190
|
- **Hourly time axis.** Non-streaming donors are resampled to a strict hourly index by linear
|
|
184
|
-
interpolation. Streaming donors deliver hourly records directly.
|
|
191
|
+
interpolation. Streaming donors deliver hourly records directly. HYCOM steps are 3 hours apart
|
|
192
|
+
with occasional gaps of up to 51 hours, which this bridges with a straight line; a store does
|
|
193
|
+
not yet record the longest gap it filled (:doc:`hycom`).
|
|
185
194
|
- **Float32 fields, full-precision coordinates.** Data variables are cast to Float32 for the
|
|
186
195
|
model; ``lat``, ``lon``, ``z`` and ``z_face`` keep full precision, since Float32 longitudes near
|
|
187
196
|
-74 resolve only about 8e-6 degrees.
|
|
@@ -8,7 +8,9 @@ live against it on the same day.
|
|
|
8
8
|
HYCOM is forcingkit's global parent ocean and the dispatcher's last-resort donor: it accepts any
|
|
9
9
|
box and is tried after NYOFS, DBOFS and NECOFS (:doc:`fetchers`). It covers 1994 to the present
|
|
10
10
|
by switching between several experiments, and delivers the legacy output layout rather than the
|
|
11
|
-
``z-v3`` parent store.
|
|
11
|
+
``z-v3`` parent store. Its fields are already on a regular longitude/latitude grid at fixed
|
|
12
|
+
depths in metres, with temperature and salinity, so it is the donor closest to ``z-v3``
|
|
13
|
+
(:doc:`roadmap`).
|
|
12
14
|
|
|
13
15
|
System overview
|
|
14
16
|
---------------
|
|
@@ -73,6 +75,7 @@ Experiments forcingkit reads
|
|
|
73
75
|
Each experiment serves from the time in the third column until the next one starts. Where two
|
|
74
76
|
overlap, the switch is at the newer one's first time step, with one exception: GLBy0.08
|
|
75
77
|
``expt_93.0`` is kept to its last step on 2024-09-05 although ESPC-D-V02 begins on 2024-08-10.
|
|
78
|
+
The GLB experiments carry no tides; ESPC-D-V02 does (see `Tides`_).
|
|
76
79
|
Times before 1994-01-01 are not served.
|
|
77
80
|
|
|
78
81
|
Grids
|
|
@@ -105,6 +108,48 @@ experiments carry all five in one dataset, 3-hourly, plus ``tau`` (analysis time
|
|
|
105
108
|
field: ``u3z``, ``v3z``, ``t3z`` and ``s3z`` are 3-hourly; ``ssh`` is hourly. All use the time
|
|
106
109
|
unit "hours since 2000-01-01 00:00:00".
|
|
107
110
|
|
|
111
|
+
Tides
|
|
112
|
+
~~~~~
|
|
113
|
+
|
|
114
|
+
The record changes character at 2024-09-05. Sea surface height sampled on 2026-10-06 at
|
|
115
|
+
40.40 N, 72.48 W (open water south of Long Island) shows:
|
|
116
|
+
|
|
117
|
+
- **ESPC-D-V02** (hourly ``ssh``): a semidiurnal tide of about 0.43 m amplitude with a period
|
|
118
|
+
near 12.4 hours.
|
|
119
|
+
- **GLBy0.08** ``expt_93.0`` (3-hourly): variations within about 5 cm and no tidal period. The
|
|
120
|
+
GLB experiments are run without tidal forcing.
|
|
121
|
+
|
|
122
|
+
So a window before 2024-09-05 is a non-tidal ocean and a window after it is a tidal one, and a
|
|
123
|
+
window across the date changes from one to the other. The fetcher records which in the
|
|
124
|
+
``tides`` attribute of the output, which the dispatcher carries into the store:
|
|
125
|
+
|
|
126
|
+
.. list-table::
|
|
127
|
+
:header-rows: 1
|
|
128
|
+
:widths: 20 80
|
|
129
|
+
|
|
130
|
+
* - ``tides``
|
|
131
|
+
- Window
|
|
132
|
+
* - ``"none"``
|
|
133
|
+
- Entirely before 2024-09-05 (GLB experiments).
|
|
134
|
+
* - ``"included"``
|
|
135
|
+
- Entirely from 2024-09-05 (ESPC-D-V02).
|
|
136
|
+
* - ``"mixed"``
|
|
137
|
+
- Spans 2024-09-05: non-tidal before the switch, tidal after it. The fetcher also logs a
|
|
138
|
+
warning.
|
|
139
|
+
|
|
140
|
+
Two consequences:
|
|
141
|
+
|
|
142
|
+
- **Do not add tides twice.** A tidal parent (``tides = "included"``) already carries the tide
|
|
143
|
+
in ``zeta`` and in the currents. A downstream model that adds its own tidal boundary forcing
|
|
144
|
+
(harmonic constituents from TPXO, FES or similar) should do so only when ``tides`` is
|
|
145
|
+
``"none"``; adding it to a tidal parent doubles the tide. A ``"mixed"`` window has no single
|
|
146
|
+
correct treatment and is best split at 2024-09-05 or avoided.
|
|
147
|
+
- **Tidal sampling.** ESPC-D-V02's ``zeta`` is kept at its native hourly steps (step 3 below),
|
|
148
|
+
and the dispatcher's hourly resample leaves those values unchanged. Velocities, temperature
|
|
149
|
+
and salinity are published only 3-hourly, so the tidal currents are sampled four times per
|
|
150
|
+
semidiurnal cycle and linearly interpolated to hourly in between, which flattens their peaks
|
|
151
|
+
by up to about 30 percent.
|
|
152
|
+
|
|
108
153
|
Where the data lives
|
|
109
154
|
--------------------
|
|
110
155
|
|
|
@@ -127,9 +172,13 @@ How forcingkit reads it
|
|
|
127
172
|
dataset's own convention (-180..180 or 0..360, detected per dataset); a box that crosses the
|
|
128
173
|
dataset's seam is read in two parts. Only the five fields above are downloaded.
|
|
129
174
|
3. **ESPC-D-V02 merge.** The five per-field datasets are read separately and merged on the
|
|
130
|
-
|
|
175
|
+
union of their times, so ``zeta`` keeps its hourly steps and ``u``, ``v``, ``temp`` and
|
|
176
|
+
``salt`` are NaN at the two hours between their 3-hourly steps. Times outside the span that
|
|
177
|
+
all five fields share are dropped, so no field begins or ends on a step it has no data for.
|
|
131
178
|
4. **Clean-up.** Longitudes are returned on 0..360 for every experiment. Times are sorted,
|
|
132
|
-
duplicates dropped, and
|
|
179
|
+
duplicates dropped, decoded to datetimes and rounded to the second (ESPC-D-V02 ``ssh``
|
|
180
|
+
decodes a few hundred nanoseconds off the hour, which would otherwise keep its steps apart
|
|
181
|
+
from those of the other fields in step 3).
|
|
133
182
|
5. **Stitch.** Pieces from different experiments are concatenated in time. A piece on a
|
|
134
183
|
different grid is interpolated (bilinear) onto the grid of the first piece. The step at a
|
|
135
184
|
switch is read from both experiments; the newer one's copy is kept.
|
|
@@ -139,9 +188,12 @@ How forcingkit reads it
|
|
|
139
188
|
data in a dataset's time range is not retried.
|
|
140
189
|
|
|
141
190
|
Output is a Dataset with ``u``, ``v``, ``temp``, ``salt`` (``time, depth, lat, lon``) and
|
|
142
|
-
``zeta`` (``time, lat, lon``)
|
|
143
|
-
|
|
144
|
-
``
|
|
191
|
+
``zeta`` (``time, lat, lon``), and the ``tides`` attribute (see `Tides`_). Land and cells below
|
|
192
|
+
the sea floor are NaN. The time axis is 3-hourly for GLB experiments and hourly for ESPC-D-V02,
|
|
193
|
+
where only ``zeta`` has data at every step. The dispatcher then resamples to hourly by linear
|
|
194
|
+
interpolation, each variable from the steps at which it has data (so the 3-hourly fields are
|
|
195
|
+
bridged between their own steps and hourly ``zeta`` is kept as is), casts to Float32, and
|
|
196
|
+
writes the store with ``schema = "legacy"``.
|
|
145
197
|
|
|
146
198
|
Known issues
|
|
147
199
|
~~~~~~~~~~~~
|
|
@@ -161,8 +213,8 @@ Known issues
|
|
|
161
213
|
- **GLBv0.08 ``expt_93.0`` steps back.** Its time axis goes from 2018-06-21 09:00 to 06:00,
|
|
162
214
|
repeating 06:00. The fetcher selects by position and drops the duplicate.
|
|
163
215
|
- **Dead path for ``expt_53.X``.** ``GLBy0.08/expt_53.X`` answers HTTP 200 with an empty
|
|
164
|
-
dataset description; the reanalysis lives under ``GLBv0.08
|
|
165
|
-
|
|
216
|
+
dataset description; the reanalysis lives under ``GLBv0.08``, which is the path forcingkit
|
|
217
|
+
reads.
|
|
166
218
|
- **GLBy0.08 ``expt_93.0`` starts at 12:00.** Its first step is 2018-12-04 12:00, not the
|
|
167
219
|
midnight that the catalogue date suggests; the switch from GLBv0.08 ``expt_93.0`` is at
|
|
168
220
|
12:00.
|
|
@@ -186,27 +238,35 @@ these returned all five fields on 10 x 5 cells and 40 depths:
|
|
|
186
238
|
* - 2018-12-03 18:00, 12 h
|
|
187
239
|
- GLBv0.08 ``expt_93.0``
|
|
188
240
|
- 5 steps, in 12 s.
|
|
189
|
-
* - 2026-10-01 00:00,
|
|
241
|
+
* - 2026-10-01 00:00, 24 h
|
|
190
242
|
- ESPC-D-V02 (five datasets)
|
|
191
|
-
-
|
|
243
|
+
- 25 hourly steps, ``zeta`` at all 25 and the other fields at 9, in 547 s (one read
|
|
244
|
+
retried); ``tides = "included"``. After the dispatcher's resample, ``zeta`` was
|
|
245
|
+
unchanged (a tidal range of about 0.8 m at one cell) and the surface ``u`` had no
|
|
246
|
+
gaps.
|
|
192
247
|
* - 2018-12-04 06:00, 12 h
|
|
193
248
|
- GLBv0.08 then GLBy0.08 ``expt_93.0``
|
|
194
249
|
- 5 steps, in 367 s; 12:00 read from both, kept once.
|
|
195
250
|
* - 2024-09-04 18:00, 12 h
|
|
196
251
|
- GLBy0.08 ``expt_93.0`` then ESPC-D-V02
|
|
197
|
-
-
|
|
198
|
-
|
|
252
|
+
- 9 steps (3-hourly to 2024-09-05 00:00, then hourly), 13 after the dispatcher's
|
|
253
|
+
resample, in 623 s (one read retried); ``tides = "mixed"`` and the crossing warning
|
|
254
|
+
logged. An earlier attempt failed after two timeouts on ``v3z``. ESPC-D-V02 marks a
|
|
255
|
+
few more cells as land or below the sea floor than GLBy0.08 in this box.
|
|
199
256
|
|
|
200
|
-
|
|
201
|
-
|
|
257
|
+
The times are for windows of 6 to 12 hours; multi-day windows have not been timed. Most of the
|
|
258
|
+
time goes to per-request latency on the server rather than to data volume, so a longer window
|
|
259
|
+
need not take proportionally longer, but plan for minutes per fetch and see `Known issues`_.
|
|
202
260
|
|
|
203
261
|
Tests
|
|
204
262
|
-----
|
|
205
263
|
|
|
206
264
|
- ``tests/unit/test_hycom.py``: experiment resolution and window splitting at every switch,
|
|
207
265
|
the URLs for GLBv0.08 and the ESPC-D-V02 fields, stitching across 2018-12-04 (regridding and
|
|
208
|
-
the duplicated switch step) and across 2024-09-05 (merged ESPC-D-V02 fields),
|
|
209
|
-
|
|
266
|
+
the duplicated switch step) and across 2024-09-05 (merged ESPC-D-V02 fields), hourly ``zeta``
|
|
267
|
+
in the ESPC-D-V02 merge and through the dispatcher's hourly resample, trimming to the span
|
|
268
|
+
all fields share, rounding decoded times to the second, the ``tides`` attribute and the warning for a window across 2024-09-05, the
|
|
269
|
+
all or nothing rule, the retry after a failed read (and none for an empty time range), both
|
|
210
270
|
longitude conventions and the seam, and the non-monotonic time axis. No network.
|
|
211
271
|
|
|
212
272
|
.. code-block:: bash
|
|
@@ -17,17 +17,20 @@ and serves model-ready time series, with a record of where every value came from
|
|
|
17
17
|
What it does
|
|
18
18
|
------------
|
|
19
19
|
|
|
20
|
-
A regional ocean model needs
|
|
21
|
-
"parent" ocean along its open boundaries,
|
|
20
|
+
A regional ocean model needs three things from outside its own domain: the state of a larger
|
|
21
|
+
"parent" ocean along its open boundaries, the atmosphere above its surface, and the rivers that
|
|
22
|
+
flow into it. The first two come from
|
|
22
23
|
operational and archive systems (NOAA's `HRRR <https://rapidrefresh.noaa.gov/hrrr/>`__, the NOAA
|
|
23
24
|
`Operational Forecast Systems <https://tidesandcurrents.noaa.gov/models.html>`__,
|
|
24
25
|
`NECOFS <https://fvcom.smast.umassd.edu/?p=20>`__, `HYCOM <https://www.hycom.org/>`__) that
|
|
25
26
|
differ in grid type, vertical coordinate, time convention, file layout and access protocol, and
|
|
26
|
-
that change those details without notice.
|
|
27
|
+
that change those details without notice. River discharge comes from stream gauges, which
|
|
28
|
+
measure flow upstream of the head of tide rather than at the mouth.
|
|
27
29
|
|
|
28
30
|
forcingkit is a FastAPI service that sits between those providers and model codes such as
|
|
29
31
|
`Oceananigans.jl <https://github.com/CliMA/Oceananigans.jl>`__ (for example through
|
|
30
|
-
`NumericalEarth <https://github.com/NumericalEarth/NumericalEarth.jl>`__). For a bounding box and a
|
|
32
|
+
`NumericalEarth <https://github.com/NumericalEarth/NumericalEarth.jl>`__). For a bounding box and a
|
|
33
|
+
time window it:
|
|
31
34
|
|
|
32
35
|
1. picks the source (the "donor") best suited to the box, and falls back to the next one if the
|
|
33
36
|
first cannot deliver;
|
|
@@ -60,6 +63,10 @@ What it serves
|
|
|
60
63
|
- HRRR surface fields (10 m wind, 2 m temperature and humidity, pressure, radiation,
|
|
61
64
|
precipitation) on a regular 0.03 degree grid, hourly, as schema ``hrrr-atm-v1``. See
|
|
62
65
|
:doc:`atmospheric_forcing`.
|
|
66
|
+
* - ``POST /api/v1/rivers``
|
|
67
|
+
- Freshwater discharge at each listed river mouth in the box, hourly, from the tide-free
|
|
68
|
+
`USGS <https://waterdata.usgs.gov/>`__ stream gauges upstream (chosen per request) scaled
|
|
69
|
+
to the drainage area at the mouth, as schema ``river-v1``. See :doc:`rivers`.
|
|
63
70
|
* - ``POST /api/v1/tide``
|
|
64
71
|
- Observed water level at a `NOAA CO-OPS <https://tidesandcurrents.noaa.gov/>`__ station, for
|
|
65
72
|
validation.
|
|
@@ -107,7 +114,7 @@ Parent-ocean donors at a glance
|
|
|
107
114
|
- HYCOM GLBv0.08, GLBy0.08 and ESPC-D-V02, regular
|
|
108
115
|
- 1/12 degree (about 9 km)
|
|
109
116
|
- Global; 1994 to the present
|
|
110
|
-
- Legacy output; last-resort fallback
|
|
117
|
+
- Legacy output; last-resort fallback; tidal only from 2024-09-05
|
|
111
118
|
|
|
112
119
|
Quick start
|
|
113
120
|
-----------
|
|
@@ -153,6 +160,7 @@ PyPI as ``forcingkit``.
|
|
|
153
160
|
nyofs
|
|
154
161
|
hycom
|
|
155
162
|
atmospheric_forcing
|
|
163
|
+
rivers
|
|
156
164
|
|
|
157
165
|
.. toctree::
|
|
158
166
|
:maxdepth: 1
|
|
@@ -20,7 +20,8 @@ Regional Association of Coastal Ocean Observing Systems <https://neracoos.org/>`
|
|
|
20
20
|
It is built on `FVCOM <https://fvcom.smast.umassd.edu/>`__, the unstructured-grid, finite-volume,
|
|
21
21
|
free-surface, primitive-equation coastal ocean model introduced by `Chen, Liu and Beardsley
|
|
22
22
|
(2003) <https://doi.org/10.1175/1520-0426(2003)020%3C0159:AUGFVT%3E2.0.CO;2>`__ and developed by
|
|
23
|
-
Changsheng Chen's group at SMAST with Robert C. Beardsley at WHOI. forcingkit reads its **GOM7**
|
|
23
|
+
Changsheng Chen's group at SMAST with Robert C. Beardsley at WHOI. forcingkit reads its **GOM7**
|
|
24
|
+
configuration, which
|
|
24
25
|
spans the Gulf of Maine, Georges Bank, southern New England, Long Island Sound, New York Harbor
|
|
25
26
|
and the Mid-Atlantic Bight shelf.
|
|
26
27
|
|
|
@@ -321,7 +321,9 @@ Institutions and data services
|
|
|
321
321
|
<https://opendap.co-ops.nos.noaa.gov/thredds/catalog/catalog.html>`__
|
|
322
322
|
- `NOAA NCEI <https://www.ncei.noaa.gov/>`__: `NYOFS files
|
|
323
323
|
<https://www.ncei.noaa.gov/thredds/catalog/model-nyofs-files/catalog.html>`__
|
|
324
|
-
- `NOAA Open Data Dissemination
|
|
324
|
+
- `NOAA Open Data Dissemination
|
|
325
|
+
<https://www.noaa.gov/information-technology/open-data-dissemination>`__:
|
|
325
326
|
`OFS on AWS <https://github.com/NOAA-Big-Data-Program/nodd-data-docs/blob/main/OFS/README.md>`__
|
|
326
|
-
- `Stevens Institute of Technology, Davidson Laboratory
|
|
327
|
+
- `Stevens Institute of Technology, Davidson Laboratory
|
|
328
|
+
<https://www.stevens.edu/davidson-laboratory>`__:
|
|
327
329
|
`NYHOPS <https://hudson.dl.stevens-tech.edu/maritimeforecast/>`__
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
River Discharge
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
``POST /api/v1/rivers`` delivers hourly freshwater discharge at the mouth of every listed river
|
|
5
|
+
in a box (or at mouths passed with the request), for point or surface sources in an ocean model. A nested regional model otherwise
|
|
6
|
+
receives river water only through its open boundaries and initial state, so a river that enters
|
|
7
|
+
inside the domain is missing as a source and its freshwater decays over the run.
|
|
8
|
+
|
|
9
|
+
Method
|
|
10
|
+
------
|
|
11
|
+
|
|
12
|
+
The method is common practice for gauge-driven river forcing. The NOAA Operational Forecast
|
|
13
|
+
Systems map US Geological Survey real-time gauges onto model cells with a per-river scale factor
|
|
14
|
+
and fall back to climatology. Regional estuary models scale gauged flow to ungauged area by the
|
|
15
|
+
ratio of drainage areas.
|
|
16
|
+
|
|
17
|
+
1. **Gauges, derived for every request.** Only a river's mouth is listed. From its NHDPlus
|
|
18
|
+
outlet flowline, forcingkit asks the USGS `NLDI <https://waterdata.usgs.gov/blog/nldi-intro/>`__
|
|
19
|
+
for every USGS site upstream, then keeps a site if:
|
|
20
|
+
|
|
21
|
+
- USGS classes it as a stream site (``ST``). Tidal streams (``ST-TS``) and estuaries (``ES``)
|
|
22
|
+
are left out, because their flow reverses with the tide; on the Connecticut River that rules
|
|
23
|
+
out Hartford and Middle Haddam;
|
|
24
|
+
- it has a drainage area, and a discharge record (15-minute or daily) covering the window;
|
|
25
|
+
- it drains at least ``min_share`` of the mouth's area (default 0.01), so headwater brooks
|
|
26
|
+
drop out;
|
|
27
|
+
- no other kept site lies downstream of it, which leaves the lowest gauge on each branch.
|
|
28
|
+
|
|
29
|
+
The kept gauges then measure disjoint parts of the basin. The selection follows the window: a
|
|
30
|
+
gauge that opened in 2010 is used from 2010 on, and one that closed is dropped from then on.
|
|
31
|
+
2. **Discharge at the mouth.** The sum of the river's gauges, scaled by the drainage area at the
|
|
32
|
+
mouth over the gauged area:
|
|
33
|
+
|
|
34
|
+
.. math::
|
|
35
|
+
|
|
36
|
+
Q_\text{mouth} = \frac{A_\text{mouth}}{\sum_k A_k} \sum_k Q_k
|
|
37
|
+
|
|
38
|
+
Gauge areas come from the USGS monitoring-location records; the mouth's area is that of the
|
|
39
|
+
outlet's NLDI basin.
|
|
40
|
+
3. **Time base.** The 15-minute record from the USGS Water Data APIs (``continuous``), averaged to
|
|
41
|
+
hourly values centred on the hour. The store holds ``hours + 1`` records, from ``start_time``
|
|
42
|
+
to ``start_time + hours``.
|
|
43
|
+
4. **Gaps.** A gap of up to ``max_gap_hours`` (default 6) with values on both sides is
|
|
44
|
+
interpolated. A longer gap takes that day's mean from the ``daily`` record. A day with neither
|
|
45
|
+
is an error, unless ``allow_climatology`` is set; then it takes the USGS day-of-year median of
|
|
46
|
+
daily flow. Every filled hour is flagged in ``fill`` (0 measured, 1 interpolated, 2 daily
|
|
47
|
+
mean, 3 climatology median), and the store's ``provenance`` attribute counts them per river.
|
|
48
|
+
5. **Water properties.** Salinity is zero. Water temperature (``temperature``) comes from the first
|
|
49
|
+
gauge on the river that measures it (USGS parameter 00010), and is NaN where none does.
|
|
50
|
+
6. **Provisional data.** USGS values are provisional until approved, typically months later, and
|
|
51
|
+
provisional values are revised. A store containing any provisional value is marked
|
|
52
|
+
``provisional = True`` and is served from the cache for one day only; after that a request
|
|
53
|
+
rebuilds it.
|
|
54
|
+
7. **Travel time.** None by default. A mouth entry may set ``lag_hours``; gauge values are then
|
|
55
|
+
taken that many hours earlier.
|
|
56
|
+
|
|
57
|
+
Mouths
|
|
58
|
+
------
|
|
59
|
+
|
|
60
|
+
Mouths are listed in ``forcingkit/data/rivers/*.json`` and in any ``*.json`` file in the directory
|
|
61
|
+
named by ``FORCINGKIT_RIVER_MOUTHS_DIR``; a later entry with the same name replaces an earlier one.
|
|
62
|
+
A request may instead pass its own ``mouths``. Adding a river needs a mouth entry and no code or
|
|
63
|
+
release:
|
|
64
|
+
|
|
65
|
+
.. code-block:: json
|
|
66
|
+
|
|
67
|
+
{"mouths": [
|
|
68
|
+
{"name": "Connecticut", "lon": -72.3305, "lat": 41.2726, "comid": 7703046},
|
|
69
|
+
{"name": "Saugatuck", "lon": -73.36, "lat": 41.10, "trace_from": "USGS-01208990"}
|
|
70
|
+
]}
|
|
71
|
+
|
|
72
|
+
- ``name``, ``lon``, ``lat`` (required): the point places the mouth for the bbox test.
|
|
73
|
+
- ``comid``: the NHDPlus outlet flowline. Otherwise ``trace_from`` names any NLDI feature on the
|
|
74
|
+
river (a USGS site such as ``USGS-01184000``) and the outlet is the end of its downstream trace.
|
|
75
|
+
Failing both, the point is snapped to the nearest flowline, with a warning: at an estuary the
|
|
76
|
+
nearest flowline can be a short coastal one rather than the river.
|
|
77
|
+
- ``include`` and ``exclude``: USGS site numbers to pin or rule out where judgement beats the rule
|
|
78
|
+
(for example a gauge below a dam whose releases should not drive the forcing). A pinned set that
|
|
79
|
+
drains more than the mouth's area is refused as double counting.
|
|
80
|
+
- ``lag_hours``: travel time from the gauges to the mouth, applied to the gauge window.
|
|
81
|
+
|
|
82
|
+
The id of a store includes the mouth entries and ``min_share``, but not the derived gauges, which
|
|
83
|
+
are recorded in the store instead. NLDI facts about a mouth (its outlet, basin area, upstream sites
|
|
84
|
+
and which sites lie downstream of which) are cached for 30 days under ``usgs/derivations`` in the
|
|
85
|
+
cache directory, so only the first request for a mouth takes long (about a minute for the
|
|
86
|
+
Connecticut, whose basin holds 1,375 USGS sites).
|
|
87
|
+
|
|
88
|
+
The packaged mouths are the rivers into Long Island Sound. For a request over the Sound in April
|
|
89
|
+
2026 the derivation chose:
|
|
90
|
+
|
|
91
|
+
.. list-table::
|
|
92
|
+
:header-rows: 1
|
|
93
|
+
:widths: 16 46 13 13 12
|
|
94
|
+
|
|
95
|
+
* - River
|
|
96
|
+
- USGS gauges kept
|
|
97
|
+
- Gauged (mi²)
|
|
98
|
+
- Mouth (mi²)
|
|
99
|
+
- Scale
|
|
100
|
+
* - Housatonic
|
|
101
|
+
- 01205500 at Stevenson; 01208500 Naugatuck at Beacon Falls
|
|
102
|
+
- 1,804
|
|
103
|
+
- 1,944
|
|
104
|
+
- 1.08
|
|
105
|
+
* - Quinnipiac
|
|
106
|
+
- 01196500 at Wallingford; 01196620 Mill River near Hamden; 01196561 Muddy River near East
|
|
107
|
+
Wallingford
|
|
108
|
+
- 148
|
|
109
|
+
- 204
|
|
110
|
+
- 1.37
|
|
111
|
+
* - Connecticut
|
|
112
|
+
- 01184000 at Thompsonville; 01189995 Farmington at Tariffville
|
|
113
|
+
- 10,237
|
|
114
|
+
- 11,242
|
|
115
|
+
- 1.10
|
|
116
|
+
* - Thames
|
|
117
|
+
- 01127000 Quinebaug at Jewett City; 011230695 Shetucket at Taftville; 01127500 Yantic at
|
|
118
|
+
Yantic
|
|
119
|
+
- 1,314
|
|
120
|
+
- 1,470
|
|
121
|
+
- 1.12
|
|
122
|
+
|
|
123
|
+
The Quinnipiac's outlet basin is New Haven Harbor's, so its scaled flow also stands for the
|
|
124
|
+
harbour's other streams. The Housatonic at Stevenson is below a hydroelectric dam, so its hourly
|
|
125
|
+
flow follows the dam's releases. The Bronx River gauge (01302020) has no record before the 2000s,
|
|
126
|
+
so a request for an earlier window fails unless ``skip_ungauged`` is set, which leaves such a
|
|
127
|
+
river out and lists it in the store's ``skipped_rivers``.
|
|
128
|
+
|
|
129
|
+
Request and store
|
|
130
|
+
-----------------
|
|
131
|
+
|
|
132
|
+
.. code-block:: bash
|
|
133
|
+
|
|
134
|
+
curl -s -X POST localhost:9598/api/v1/rivers -H 'Content-Type: application/json' -d '{
|
|
135
|
+
"bbox": {"min_lon": -73.855, "min_lat": 40.75, "max_lon": -71.9, "max_lat": 41.45},
|
|
136
|
+
"start_time": "2026-04-02T00:00:00Z", "hours": 48}'
|
|
137
|
+
|
|
138
|
+
Optional fields: ``mouths``, ``min_share`` (default 0.01), ``max_gap_hours`` (default 6),
|
|
139
|
+
``allow_climatology`` and ``skip_ungauged`` (both default false), and ``cache_bust``.
|
|
140
|
+
|
|
141
|
+
For that request (four rivers, 49 records), the mean discharges over the 48 hours were 1,553 m³/s
|
|
142
|
+
for the Connecticut, 147 for the Housatonic, 148 for the Thames and 13 for the Quinnipiac.
|
|
143
|
+
|
|
144
|
+
The store (schema ``river-v1``) has a ``river`` dimension:
|
|
145
|
+
|
|
146
|
+
- ``discharge`` (time, river): m³ s⁻¹, ``water_volume_transport_in_river_channel``.
|
|
147
|
+
- ``temperature`` (time, river): °C.
|
|
148
|
+
- ``fill`` (time, river): the flags above.
|
|
149
|
+
- ``mouth_lon``, ``mouth_lat``, ``scale_factor``, ``salinity`` (river).
|
|
150
|
+
- Attributes: ``river_names``; ``provenance`` (JSON: per river, the gauges kept, the areas, the
|
|
151
|
+
scale factor, the outlet, and the dropped candidates counted by reason); ``derivation_dropped``
|
|
152
|
+
(JSON: every dropped candidate with its reason); ``skipped_rivers``; ``provisional``; and
|
|
153
|
+
``built_utc``.
|
|
154
|
+
|
|
155
|
+
A JSON sidecar next to the store repeats the request, the mouths and the derivation. ``GET /api/v1/rivers/download/{zarr_id}``
|
|
156
|
+
returns the store as a zip.
|
|
157
|
+
|
|
158
|
+
Credentials
|
|
159
|
+
-----------
|
|
160
|
+
|
|
161
|
+
None are required. A free USGS Water Data API key (``USGS_API_KEY``, from
|
|
162
|
+
`api.waterdata.usgs.gov/signup <https://api.waterdata.usgs.gov/signup/>`__) raises the hourly rate
|
|
163
|
+
limit; it is sent in the ``X-Api-Key`` header. forcingkit uses the modernized APIs, not the
|
|
164
|
+
legacy ``waterservices.usgs.gov``, which USGS plans to retire in 2027.
|
|
165
|
+
|
|
166
|
+
Limits
|
|
167
|
+
------
|
|
168
|
+
|
|
169
|
+
- Mouths are not found automatically within a box: each river needs a mouth entry. Finding
|
|
170
|
+
coastal outlets from NHDPlus would remove that step.
|
|
171
|
+
- The selection rule cannot tell a regulated gauge from a natural one; use ``exclude`` where dam
|
|
172
|
+
operations should not reach the forcing.
|
|
173
|
+
- Gauges measure surface runoff. Groundwater discharge (most of Long Island's freshwater input) is
|
|
174
|
+
not represented.
|
|
175
|
+
- A model that applies discharge as a surface freshwater flux on fixed levels dilutes salinity
|
|
176
|
+
but adds no volume. Whether the volume is added depends on the model's vertical coordinate, not
|
|
177
|
+
on this store.
|