{"id":31531507,"url":"https://github.com/hyriver/pynhd","last_synced_at":"2026-04-06T01:04:40.844Z","repository":{"id":38020812,"uuid":"280796465","full_name":"hyriver/pynhd","owner":"hyriver","description":"A part of HyRiver software stack that provides access to NHDPlus data through web services","archived":false,"fork":false,"pushed_at":"2025-06-25T20:11:03.000Z","size":769,"stargazers_count":40,"open_issues_count":7,"forks_count":10,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-20T06:47:58.718Z","etag":null,"topics":["hydrology","nhdplus","nldi","python","waterdata","webservices","wfs-service"],"latest_commit_sha":null,"homepage":"https://docs.hyriver.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyriver.png","metadata":{"files":{"readme":"README.rst","changelog":"HISTORY.rst","contributing":"CONTRIBUTING.rst","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.rst","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["cheginit"]}},"created_at":"2020-07-19T05:12:07.000Z","updated_at":"2026-01-14T07:35:34.000Z","dependencies_parsed_at":"2023-11-26T00:24:26.049Z","dependency_job_id":"93ec057a-867e-49c7-a76a-dc0592f3142f","html_url":"https://github.com/hyriver/pynhd","commit_stats":{"total_commits":997,"total_committers":4,"mean_commits":249.25,"dds":"0.11735205616850553","last_synced_commit":"274cfd3c7067a131598fc47bd641ddb15d5cc0ba"},"previous_names":["cheginit/pynhd"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/hyriver/pynhd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyriver%2Fpynhd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyriver%2Fpynhd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyriver%2Fpynhd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyriver%2Fpynhd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyriver","download_url":"https://codeload.github.com/hyriver/pynhd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyriver%2Fpynhd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31455474,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"ssl_error","status_checked_at":"2026-04-05T21:22:51.943Z","response_time":75,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hydrology","nhdplus","nldi","python","waterdata","webservices","wfs-service"],"created_at":"2025-10-04T02:12:57.542Z","updated_at":"2026-04-06T01:04:40.826Z","avatar_url":"https://github.com/hyriver.png","language":"Python","funding_links":["https://github.com/sponsors/cheginit"],"categories":[],"sub_categories":[],"readme":".. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/pynhd_logo.png\n    :target: https://github.com/hyriver/HyRiver\n\n|\n\n.. image:: https://joss.theoj.org/papers/b0df2f6192f0a18b9e622a3edff52e77/status.svg\n    :target: https://joss.theoj.org/papers/b0df2f6192f0a18b9e622a3edff52e77\n    :alt: JOSS\n\n|\n\n.. |pygeohydro| image:: https://github.com/hyriver/pygeohydro/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pygeohydro/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pygeoogc| image:: https://github.com/hyriver/pygeoogc/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pygeoogc/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pygeoutils| image:: https://github.com/hyriver/pygeoutils/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pygeoutils/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pynhd| image:: https://github.com/hyriver/pynhd/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pynhd/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |py3dep| image:: https://github.com/hyriver/py3dep/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/py3dep/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pydaymet| image:: https://github.com/hyriver/pydaymet/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pydaymet/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pygridmet| image:: https://github.com/hyriver/pygridmet/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pygridmet/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |pynldas2| image:: https://github.com/hyriver/pynldas2/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/pynldas2/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |async| image:: https://github.com/hyriver/async-retriever/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/async-retriever/actions/workflows/test.yml\n    :alt: Github Actions\n\n.. |signatures| image:: https://github.com/hyriver/hydrosignatures/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/hyriver/hydrosignatures/actions/workflows/test.yml\n    :alt: Github Actions\n\n================ ====================================================================\nPackage          Description\n================ ====================================================================\nPyNHD_           Navigate and subset NHDPlus (MR and HR) using web services\nPy3DEP_          Access topographic data through National Map's 3DEP web service\nPyGeoHydro_      Access NWIS, NID, WQP, eHydro, NLCD, CAMELS, and SSEBop databases\nPyDaymet_        Access daily, monthly, and annual climate data via Daymet\nPyGridMET_       Access daily climate data via GridMET\nPyNLDAS2_        Access hourly NLDAS-2 data via web services\nHydroSignatures_ A collection of tools for computing hydrological signatures\nAsyncRetriever_  High-level API for asynchronous requests with persistent caching\nPyGeoOGC_        Send queries to any ArcGIS RESTful-, WMS-, and WFS-based services\nPyGeoUtils_      Utilities for manipulating geospatial, (Geo)JSON, and (Geo)TIFF data\n================ ====================================================================\n\n.. _PyGeoHydro: https://github.com/hyriver/pygeohydro\n.. _AsyncRetriever: https://github.com/hyriver/async-retriever\n.. _PyGeoOGC: https://github.com/hyriver/pygeoogc\n.. _PyGeoUtils: https://github.com/hyriver/pygeoutils\n.. _PyNHD: https://github.com/hyriver/pynhd\n.. _Py3DEP: https://github.com/hyriver/py3dep\n.. _PyDaymet: https://github.com/hyriver/pydaymet\n.. _PyGridMET: https://github.com/hyriver/pygridmet\n.. _PyNLDAS2: https://github.com/hyriver/pynldas2\n.. _HydroSignatures: https://github.com/hyriver/hydrosignatures\n\nPyNHD: Navigate and subset NHDPlus database\n-------------------------------------------\n\n.. image:: https://img.shields.io/pypi/v/pynhd.svg\n    :target: https://pypi.python.org/pypi/pynhd\n    :alt: PyPi\n\n.. image:: https://img.shields.io/conda/vn/conda-forge/pynhd.svg\n    :target: https://anaconda.org/conda-forge/pynhd\n    :alt: Conda Version\n\n.. image:: https://codecov.io/gh/hyriver/pynhd/branch/main/graph/badge.svg\n    :target: https://codecov.io/gh/hyriver/pynhd\n    :alt: CodeCov\n\n.. image:: https://img.shields.io/pypi/pyversions/pynhd.svg\n    :target: https://pypi.python.org/pypi/pynhd\n    :alt: Python Versions\n\n.. image:: https://static.pepy.tech/badge/pynhd\n    :target: https://pepy.tech/project/pynhd\n    :alt: Downloads\n\n|\n\n.. image:: https://www.codefactor.io/repository/github/hyriver/pynhd/badge\n   :target: https://www.codefactor.io/repository/github/hyriver/pynhd\n   :alt: CodeFactor\n\n.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\n    :target: https://github.com/astral-sh/ruff\n    :alt: Ruff\n\n.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white\n    :target: https://github.com/pre-commit/pre-commit\n    :alt: pre-commit\n\n.. image:: https://mybinder.org/badge_logo.svg\n    :target: https://mybinder.org/v2/gh/hyriver/HyRiver-examples/main?urlpath=lab/tree/notebooks\n    :alt: Binder\n\n|\n\nFeatures\n--------\n\nPyNHD is a part of `HyRiver \u003chttps://github.com/hyriver/HyRiver\u003e`__ software stack that\nis designed to aid in hydroclimate analysis through web services.\n\nThis package provides access to several hydro-linked datasets:\n\n- `StreamCat \u003chttps://www.epa.gov/national-aquatic-resource-surveys/streamcat-dataset\u003e`__\n- `WaterData \u003chttps://api.water.usgs.gov/\u003e`__\n- `NHDPlus MR \u003chttps://hydro.nationalmap.gov/arcgis/rest/services/nhd/MapServer\u003e`__\n- `NHDPlus HR \u003chttps://hydro.nationalmap.gov/arcgis/rest/services/NHDPlus_HR/MapServer\u003e`__\n- `NLDI \u003chttps://api.water.usgs.gov/\u003e`__\n- `PyGeoAPI \u003chttps://api.water.usgs.gov/\u003e`__\n- `GeoConnex \u003chttps://geoconnex.internetofwater.dev/\u003e`__\n- `Mainstems \u003chttps://www.sciencebase.gov/catalog/item/63cb38b2d34e06fef14f40ad\u003e`__\n- `HUC12 Pour Points \u003chttps://www.sciencebase.gov/catalog/item/60cb5edfd34e86b938a373f4\u003e`__\n\nThese web services can be used to navigate and extract vector data from NHDPlus V2 (both mid-\nand high-resolution) database such as catchments, HUC8, HUC12, GagesII, flowlines, and water\nbodies.\n\nMoreover, the PyGeoAPI service provides four functionalities:\n\n1. ``flow_trace``: Trace flow from a starting point to up/downstream direction.\n2. ``split_catchment``: Split the local catchment of a point of interest at the point's\n   location.\n3. ``elevation_profile``: Extract elevation profile along a flow path between two points.\n4. ``cross_section``: Extract cross-section at a point of interest along a flow line.\n\nPyNHD also provides access to the entire NHDPlus dataset for CONUS (L48) via\n``nhdplus_l48`` function. You can get any of the 31 layers that are available in the\nNHDPlus dataset. You can also get NHDPlus Value Added Attributes on\n`Hydroshare \u003chttps://www.hydroshare.org/resource/6092c8a62fac45be97a09bfd0b0bf726/\u003e`__\nand `ENHD \u003chttps://www.sciencebase.gov/catalog/item/60c92503d34e86b9389df1c9\u003e`__.\nThese datasets that do not have geometries, include slope and roughness, among other\nattributes, for all NHD flowlines. You can use ``nhdplus_vaa`` and ``enhd_attrs``\nfunctions to get these datasets.\n\nAdditionally, you can get many more derived attributes at NHD catchment-level\nthrough two sources:\n\n- Select Attributes for NHDPlus Version 2.1 Reach Catchments from an item on\n  `ScienceBase \u003chttps://sciencebase.usgs.gov\u003e`__\n- EPA's `StreamCat \u003chttps://www.epa.gov/national-aquatic-resource-surveys/streamcat-dataset\u003e`__\n  dataset.\n\nThey both include hundreds of attributes such as hydroclimate properties, water quality,\nurbanization, and population. In addition to NHD catchment summaries, they also have\ntheir network-accumulated values (both upstream and divergence-routed). You can use\n``nhdplus_attrs``, ``epa_nhd_catchments``, ``streamcat`` functions to get these datasets.\n\nAdditionally, PyNHD offers some extra utilities for processing the NHD flowlines:\n\n- ``flowline_xsection`` and ``network_xsection``: Get cross-section lines along a flowline\n  at a given spacing or a network of flowlines at a given spacing.\n- ``flowline_resample`` and ``network_resample``:\n  Resample a flowline or network of flowlines based on a given spacing. This is\n  useful for smoothing jagged flowlines similar to those in the NHDPlus database.\n- ``prepare_nhdplus``: For cleaning up the data frame by, for example, removing tiny networks,\n  adding a ``to_comid`` column, and finding terminal flowlines if it doesn't exist.\n- ``topoogical_sort``: For sorting the river network topologically which is useful for routing\n  and flow accumulation.\n- ``vector_accumulation``: For computing flow accumulation in a river network. This function\n  is generic, and any routing method can be plugged in.\n\nThese utilities are developed based on an R package called\n`nhdplusTools \u003chttps://github.com/USGS-R/nhdplusTools\u003e`__ and a Python package\ncalled `nldi-xstool \u003chttps://code.usgs.gov/wma/nhgf/toolsteam/nldi-xstool\u003e`__.\n\nAll functions and classes that request data from web services use ``async-retriever``\nthat offers response caching. By default, the expiration time is set to never expire.\nAll these functions and classes have two optional parameters for controlling the cache:\n``expire_after`` and ``disable_caching``. You can use ``expire_after`` to set the expiration\ntime in seconds. If ``expire_after`` is set to ``-1``, the cache will never expire (default).\nYou can use ``disable_caching`` if you don't want to use the cached responses. The cached\nresponses are stored in the ``./cache/aiohttp_cache.sqlite`` file.\n\nYou can find some example notebooks `here \u003chttps://github.com/hyriver/HyRiver-examples\u003e`__.\n\nMoreover, under the hood, PyNHD uses\n`PyGeoOGC \u003chttps://github.com/hyriver/pygeoogc\u003e`__ and\n`AsyncRetriever \u003chttps://github.com/hyriver/async-retriever\u003e`__ packages\nfor making requests in parallel and storing responses in chunks. This improves the\nreliability and speed of data retrieval significantly.\n\nYou can control the request/response caching behavior and verbosity of the package\nby setting the following environment variables:\n\n* ``HYRIVER_CACHE_NAME``: Path to the caching SQLite database for asynchronous HTTP\n  requests. It defaults to ``./cache/aiohttp_cache.sqlite``\n* ``HYRIVER_CACHE_NAME_HTTP``: Path to the caching SQLite database for HTTP requests.\n  It defaults to ``./cache/http_cache.sqlite``\n* ``HYRIVER_CACHE_EXPIRE``: Expiration time for cached requests in seconds. It defaults to\n  one week.\n* ``HYRIVER_CACHE_DISABLE``: Disable reading/writing from/to the cache. The default is false.\n* ``HYRIVER_SSL_CERT``: Path to a SSL certificate file.\n\nFor example, in your code before making any requests you can do:\n\n.. code-block:: python\n\n    import os\n\n    os.environ[\"HYRIVER_CACHE_NAME\"] = \"path/to/aiohttp_cache.sqlite\"\n    os.environ[\"HYRIVER_CACHE_NAME_HTTP\"] = \"path/to/http_cache.sqlite\"\n    os.environ[\"HYRIVER_CACHE_EXPIRE\"] = \"3600\"\n    os.environ[\"HYRIVER_CACHE_DISABLE\"] = \"true\"\n    os.environ[\"HYRIVER_SSL_CERT\"] = \"path/to/cert.pem\"\n\nYou can also try using PyNHD without installing\nit on your system by clicking on the binder badge. A Jupyter Lab\ninstance with the HyRiver stack pre-installed will be launched in your web browser, and you\ncan start coding!\n\nMoreover, requests for additional functionalities can be submitted via\n`issue tracker \u003chttps://github.com/hyriver/pynhd/issues\u003e`__.\n\nCitation\n--------\nIf you use any of HyRiver packages in your research, we appreciate citations:\n\n.. code-block:: bibtex\n\n    @article{Chegini_2021,\n        author = {Chegini, Taher and Li, Hong-Yi and Leung, L. Ruby},\n        doi = {10.21105/joss.03175},\n        journal = {Journal of Open Source Software},\n        month = {10},\n        number = {66},\n        pages = {1--3},\n        title = {{HyRiver: Hydroclimate Data Retriever}},\n        volume = {6},\n        year = {2021}\n    }\n\nInstallation\n------------\n\nYou can install PyNHD using ``pip`` after installing ``libgdal`` on your system\n(for example, in Ubuntu run ``sudo apt install libgdal-dev``):\n\n.. code-block:: console\n\n    $ pip install pynhd\n\nAlternatively, PyNHD can be installed from the ``conda-forge`` repository\nusing `Conda \u003chttps://docs.conda.io/en/latest/\u003e`__\nor `Mamba \u003chttps://github.com/conda-forge/miniforge\u003e`__:\n\n.. code-block:: console\n\n    $ conda install -c conda-forge pynhd\n\nQuick start\n-----------\n\nLet's explore the capabilities of ``NLDI``. We need to instantiate the class first:\n\n.. code-block:: python\n\n    from pynhd import NLDI, WaterData, NHDPlusHR\n    import pynhd as nhd\n\nFirst, let's get the watershed geometry of the contributing basin of a\nUSGS station using ``NLDI``:\n\n.. code-block:: python\n\n    nldi = NLDI()\n    station_id = \"01031500\"\n\n    basin = nldi.get_basins(station_id)\n\nThe ``navigate_byid`` class method can be used to navigate NHDPlus in\nboth upstream and downstream of any point in the database. Let's get the ComIDs and flowlines\nof the tributaries and the main river channel upstream of the station.\n\n.. code-block:: python\n\n    flw_main = nldi.navigate_byid(\n        fsource=\"nwissite\",\n        fid=f\"USGS-{station_id}\",\n        navigation=\"upstreamMain\",\n        source=\"flowlines\",\n        distance=1000,\n    )\n\n    flw_trib = nldi.navigate_byid(\n        fsource=\"nwissite\",\n        fid=f\"USGS-{station_id}\",\n        navigation=\"upstreamTributaries\",\n        source=\"flowlines\",\n        distance=1000,\n    )\n\nWe can get other USGS stations upstream (or downstream) of the station\nand even set a distance limit (in km):\n\n.. code-block:: python\n\n    st_all = nldi.navigate_byid(\n        fsource=\"nwissite\",\n        fid=f\"USGS-{station_id}\",\n        navigation=\"upstreamTributaries\",\n        source=\"nwissite\",\n        distance=1000,\n    )\n\n    st_d20 = nldi.navigate_byid(\n        fsource=\"nwissite\",\n        fid=f\"USGS-{station_id}\",\n        navigation=\"upstreamTributaries\",\n        source=\"nwissite\",\n        distance=20,\n    )\n\nWe can get more information about these stations using GeoConnex:\n\n.. code-block:: python\n\n    gcx = GeoConnex(\"gauges\")\n    stations = st_all.identifier.str.split(\"-\").str[1].unique()\n    gauges = gpd.GeoDataFrame(\n        pd.concat(gcx.query({\"provider_id\": sid}) for sid in stations),\n        crs=4326,\n    )\n\nInstead, we can carry out a spatial query within the basin of interest:\n\n.. code-block:: python\n\n    gauges = pynhd.geoconnex(\n        item=\"gauges\",\n        query={\"geometry\": basin.geometry.iloc[0]},\n    )\n\nNow, let's get the\n`HUC12 pour points \u003chttps://www.sciencebase.gov/catalog/item/5762b664e4b07657d19a71ea\u003e`__:\n\n.. code-block:: python\n\n    pp = nldi.navigate_byid(\n        fsource=\"nwissite\",\n        fid=f\"USGS-{station_id}\",\n        navigation=\"upstreamTributaries\",\n        source=\"huc12pp\",\n        distance=1000,\n    )\n\n.. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/nhdplus_navigation.png\n    :target: https://github.com/hyriver/HyRiver-examples/blob/main/notebooks/nhdplus.ipynb\n    :align: center\n\nAlso, we can get the slope data for each river segment from the NHDPlus VAA database:\n\n.. code-block:: python\n\n    vaa = nhd.nhdplus_vaa(\"input_data/nhdplus_vaa.parquet\")\n\n    flw_trib[\"comid\"] = pd.to_numeric(flw_trib.nhdplus_comid)\n    slope = gpd.GeoDataFrame(\n        pd.merge(flw_trib, vaa[[\"comid\", \"slope\"]], left_on=\"comid\", right_on=\"comid\"),\n        crs=flw_trib.crs,\n    )\n    slope[slope.slope \u003c 0] = np.nan\n\nAdditionally, we can obtain cross-section lines along the main river channel with 4 km spacing\nand width of 2 km using ``network_xsection`` as follows:\n\n.. code-block:: python\n\n    from pynhd import NHD\n\n    distance = 4000  # in meters\n    width = 2000  # in meters\n    nhd = NHD(\"flowline_mr\")\n    main_nhd = nhd.byids(\"COMID\", flw_main.index)\n    main_nhd = pynhd.prepare_nhdplus(main_nhd, 0, 0, 0, purge_non_dendritic=True)\n    main_nhd = main_nhd.to_crs(\"ESRI:102003\")\n    cs = pynhd.network_xsection(main_nhd, distance, width)\n\nThen, we can use `Py3DEP \u003chttps://github.com/hyriver/py3dep\u003e`__\nto obtain the elevation profile along the cross-section lines.\n\nNow, let's explore the PyGeoAPI capabilities. There are two ways that you can access\nPyGeoAPI: ``PyGeoAPI`` class and ``pygeoapi`` function. The ``PyGeoAPI`` class\nis for querying the database for a single location using tuples and list while the\n``pygeoapi`` function is for querying the database for multiple locations at once\nand accepts a ``geopandas.GeoDataFrame`` as input. The ``pygeoapi`` function\nis more efficient than the ``PyGeoAPI`` class and has a simpler interface. In future\nversions, the ``PyGeoAPI`` class will be deprecated and the ``pygeoapi`` function\nwill be the only way to access the database. Let's compare the two, starting by\n``PyGeoAPI``:\n\n.. code-block:: python\n\n    pygeoapi = PyGeoAPI()\n\n    trace = pygeoapi.flow_trace((1774209.63, 856381.68), crs=\"ESRI:102003\", direction=\"none\")\n\n    split = pygeoapi.split_catchment((-73.82705, 43.29139), crs=4326, upstream=False)\n\n    profile = pygeoapi.elevation_profile(\n        [(-103.801086, 40.26772), (-103.80097, 40.270568)],\n        numpts=101,\n        dem_res=1,\n        crs=4326,\n    )\n\n    section = pygeoapi.cross_section((-103.80119, 40.2684), width=1000.0, numpts=101, crs=4326)\n\nNow, let's do the same operations using ``pygeoapi``:\n\n.. code-block:: python\n\n    import geopandas as gpd\n    import shapely.geometry as sgeom\n    import pynhd as nhd\n\n    coords = gpd.GeoDataFrame(\n        {\n            \"direction\": [\"up\", \"down\"],\n            \"upstream\": [True, False],\n            \"width\": [1000.0, 500.0],\n            \"numpts\": [101, 55],\n        },\n        geometry=[\n            sgeom.Point(-73.82705, 43.29139),\n            sgeom.Point(-103.801086, 40.26772),\n        ],\n        crs=4326,\n    )\n    trace = nhd.pygeoapi(coords, \"flow_trace\")\n    split = nhd.pygeoapi(coords, \"split_catchment\")\n    section = nhd.pygeoapi(coords, \"cross_section\")\n\n    coords = gpd.GeoDataFrame(\n        {\n            \"direction\": [\"up\", \"down\"],\n            \"upstream\": [True, False],\n            \"width\": [1000.0, 500.0],\n            \"numpts\": [101, 55],\n            \"dem_res\": [1, 10],\n        },\n        geometry=[\n            sgeom.MultiPoint([(-103.801086, 40.26772), (-103.80097, 40.270568)]),\n            sgeom.MultiPoint([(-102.801086, 39.26772), (-102.80097, 39.270568)]),\n        ],\n        crs=4326,\n    )\n    profile = nhd.pygeoapi(coords, \"elevation_profile\")\n\n.. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/split_catchment.png\n    :target: https://github.com/hyriver/HyRiver-examples/blob/main/notebooks/pygeoapi.ipynb\n    :align: center\n\nNext, we retrieve mid- and high-resolution flowlines within the bounding box of our\nwatershed and compare them using ``WaterData`` for mid-resolution, ``NHDPlusHR`` for\nhigh-resolution.\n\n.. code-block:: python\n\n    mr = WaterData(\"nhdflowline_network\")\n    nhdp_mr = mr.bybox(basin.geometry[0].bounds)\n\n    hr = NHDPlusHR(\"flowline\")\n    nhdp_hr = hr.bygeom(basin.geometry[0].bounds)\n\n.. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/hr_mr.png\n    :target: https://github.com/hyriver/HyRiver-examples/blob/main/notebooks/nhdplus.ipynb\n    :align: center\n\nAn alternative to ``WaterData`` and ``NHDPlusHR`` is the ``NHD`` class that\nsupports both the mid- and high-resolution NHDPlus V2 data:\n\n.. code-block:: python\n\n    mr = NHD(\"flowline_mr\")\n    nhdp_mr = mr.bygeom(basin.geometry[0].bounds)\n\n    hr = NHD(\"flowline_hr\")\n    nhdp_hr = hr.bygeom(basin.geometry[0].bounds)\n\nMoreover, ``WaterData`` can find features within a given radius (in meters) of a point:\n\n.. code-block:: python\n\n    eck4 = \"+proj=eck4 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs\"\n    coords = (-5727797.427596455, 5584066.49330473)\n    rad = 5e3\n    flw_rad = mr.bydistance(coords, rad, loc_crs=eck4)\n    flw_rad = flw_rad.to_crs(eck4)\n\nInstead of getting all features within a radius of the coordinate, we can snap to the closest\nfeature ID using NLDI:\n\n.. code-block:: python\n\n    comid_closest = nldi.comid_byloc((x, y), eck4)\n    flw_closest = nhdp_mr.byid(\"comid\", comid_closest.comid.values[0])\n\n.. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/nhdplus_radius.png\n    :target: https://github.com/hyriver/HyRiver-examples/blob/main/notebooks/nhdplus.ipynb\n    :align: center\n\nSince NHDPlus HR is still at the pre-release stage let's use the MR flowlines to\ndemonstrate the vector-based accumulation. Based on a topological sorted river network\n``pynhd.vector_accumulation`` computes flow accumulation in the network.\nIt returns a data frame that is sorted from upstream to downstream that\nshows the accumulated flow in each node.\n\nPyNHD has a utility called ``prepare_nhdplus`` that identifies such\nrelationships among other things such as fixing some common issues with\nNHDPlus flowlines. But first, we need to get all the NHDPlus attributes\nfor each ComID since ``NLDI`` only provides the flowlines' geometries\nand ComIDs which is useful for navigating the vector river network data.\nFor getting the NHDPlus database we use ``WaterData``. Let's use the\n``nhdflowline_network`` layer to get required info.\n\n.. code-block:: python\n\n    wd = WaterData(\"nhdflowline_network\")\n\n    comids = flw_trib.nhdplus_comid.to_list()\n    nhdp_trib = wd.byid(\"comid\", comids)\n    flw = nhd.prepare_nhdplus(nhdp_trib, 0, 0, purge_non_dendritic=False)\n\nTo demonstrate the use of routing, let's use ``nhdplus_attrs`` function to get a list of available\nNHDPlus attributes\n\n.. code-block:: python\n\n    char = \"CAT_RECHG\"\n    area = \"areasqkm\"\n\n    local = nldi.getcharacteristic_byid(comids, \"local\", char_ids=char)\n    flw = flw.merge(local[char], left_on=\"comid\", right_index=True)\n\n\n    def runoff_acc(qin, q, a):\n        return qin + q * a\n\n\n    flw_r = flw[[\"comid\", \"tocomid\", char, area]]\n    runoff = nhd.vector_accumulation(flw_r, runoff_acc, char, [char, area])\n\n\n    def area_acc(ain, a):\n        return ain + a\n\n\n    flw_a = flw[[\"comid\", \"tocomid\", area]]\n    areasqkm = nhd.vector_accumulation(flw_a, area_acc, area, [area])\n\n    runoff /= areasqkm\n\nSince these are catchment-scale characteristics, let's get the catchments\nthen add the accumulated characteristic as a new column and plot the\nresults.\n\n.. code-block:: python\n\n    wd = WaterData(\"catchmentsp\")\n    catchments = wd.byid(\"featureid\", comids)\n\n    c_local = catchments.merge(local, left_on=\"featureid\", right_index=True)\n    c_acc = catchments.merge(runoff, left_on=\"featureid\", right_index=True)\n\n.. image:: https://raw.githubusercontent.com/hyriver/HyRiver-examples/main/notebooks/_static/flow_accumulation.png\n    :target: https://github.com/hyriver/HyRiver-examples/blob/main/notebooks/nhdplus.ipynb\n    :align: center\n\nMore examples can be found `here \u003chttps://pygeohydro.readthedocs.io/en/latest/examples.html\u003e`__.\n\nContributing\n------------\n\nContributions are very welcomed. Please read\n`CONTRIBUTING.rst \u003chttps://github.com/hyriver/pynhd/blob/main/CONTRIBUTING.rst\u003e`__\nfile for instructions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyriver%2Fpynhd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyriver%2Fpynhd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyriver%2Fpynhd/lists"}