Skip to content

Home

basinkit

There is no basin-native data acquisition layer for South Asia. HyRiver is US-only. rabpro and eodag take bounding boxes. basinkit is that missing layer, and it works everywhere else too: click a river anywhere on Earth and get an analysis-ready basin package. The basin polygon, elevation, land cover, soil, rainfall, surface water and rivers clipped to it, the river's own profile, and the full Horton-Strahler-Schumm morphometry, with no account anywhere in the chain.

import basinkit as bk

basin = bk.Basin.from_point(26.87, 87.15)    # Sapta Koshi at Chatara
print(basin)
# <Basin area=54,497 km2 centroid=(27.974, 87.021) backend='hydrobasins'>
# published area at this gauge: ~54,100 km2

dem   = basin.dem()                          # clipped and masked to the polygon
land  = basin.landcover()
soil  = basin.available_water_capacity()
rain  = basin.precipitation(2000, 2024)      # basin-mean monthly series
water = basin.surface_water()                # 37 years of Landsat, pre-reduced

basin.download_all("koshi/")                 # the whole stack, one call
basin.export_3d("koshi.html")                # an interactive 3D page

Needs Python 3.10 or newer, and QGIS 3.28 or newer for the plugin.

Or without writing any Python at all:

pip install basinkit
basinkit fetch --lat 26.87 --lon 87.15 --out koshi/

Or without a terminal either: there is a QGIS plugin in qgis_plugin/. Click an outlet on the map canvas and the basin and its data land in your project. See its README.

Not affiliated with EPA BASINS or BasinMaker. BASINS is a US EPA desktop modelling system; BasinMaker builds lake-aware routing structures from data you supply. basinkit is a global data-acquisition package: a coordinate goes in, a delineated basin and its open Earth observation data come out.


Why this exists

If you work on a river basin in the United States, this problem is solved: HyRiver and watershed-workflow will hand you a delineated catchment and every layer that goes with it.

Everywhere else, you assemble it by hand. You clone a delineation script, download tens of gigabytes of MERIT tiles, wait half an hour, and then start again from scratch on the data side, because eodag, earthaccess, pystac-client and every other downloader takes a bounding box and returns whole scenes. Nothing joins the two halves, and nothing clips to the basin.

basinkit is that missing join, for the whole planet.

The precise claim, and the four packages that make it non-obvious, are in Related work, including the two that do this better than basinkit within their own scope.

Three things it does that the alternatives do not

It clips to the polygon, not the box. Measured on sixteen major basins spanning 54,000 km2 to the Amazon's 4.67 million, a catchment fills between 42% and 62% of its own bounding box, median 54%. Every Basin exposes bbox_efficiency, so the figure for yours is one attribute away. Roughly half of what a bounding-box download transfers is therefore somebody else's catchment, and those pixels sit inside every "basin average" computed from it.

It needs no account. Not for the DEM, not for Sentinel-2, not for Landsat, not for terrain-corrected radar. Nineteen of the twenty-seven catalogued datasets are fetchable today, and every one of those is anonymous. Compare: MERIT Hydro is behind a Google Form and an emailed Dropbox password; the OpenTopography API allows fifty calls a day on a non-academic key; Earth Engine requires a Google Cloud project and forbids commercial use on the free tier. basinkit routes around all of it.

It tells you what you are allowed to do with the result, and what it cannot get you. basinkit catalog and Basin.license_report() read from the same machine-readable table the fetchers use, so the licence shown is the licence that applied. The seven datasets basinkit documents but cannot download are marked DOC, and asking for one raises an error carrying the access route and the licence rather than quietly pretending to be a feature. Every default layer is CC BY 4.0 or more permissive: redistributable, commercially usable, attribution required. The restricted ones (MERIT Hydro, FABDEM, MSWEP, GRDC) are opt-in and say so before the first byte moves.


Does it work?

Blind validation against 2,740 delineations at 2,550 gauges in 99 countries on six continents, whose catchment areas are published by the national agencies that operate them. The samples were drawn by seed before any result was seen and nothing was dropped afterwards, failures included.

The answer depends almost entirely on catchment size, so it is reported that way rather than as one number:

catchment area median error within 20% within 5%
above 100,000 km2 0.3% 92% 78%
10,000 to 100,000 1.3% 92% 86%
2,000 to 10,000 1.7% 96% 58%
500 to 2,000 8.9% 78% 35%
100 to 500 30% 40% 15%
below 100 181% 22% 0%

And that table is about the population, not about your basin. It says what error to expect across thousands of gauges at a given catchment size. It cannot say whether the one in front of you is a case it was kind to.

Two functions answer that, and they answer different halves of it. Basin.validation_envelope() says which row of the table above applies to this basin, and whether any of it does: inside, edge or outside, the median error measured at this size with its within-5% and within-20% counts, and the three conditions the validation never recorded -- aridity, flow regulation and karst -- so that no figure above is quoted about a case it was not measured on. It reads the area and nothing else, so it downloads nothing. Hand it a suitability result and it compares the terrain descriptors against the range they covered in the 133 gauges where both were recorded.

Basin.dem_suitability() answers the other half by measuring the basin itself: how much of the surface depression filling had to invent, how many slopes fall below the angle at which a gradient is only the model's vertical error, relief against that error, the largest level surface as a share of the basin, and cells with no elevation at all. Each against a stated threshold, combined into HIGH, MODERATE or LIMITED, with a per-cell raster of which ground the answer rests on.

basin grade what decided it
Koshi at Chatara, 54,497 km2 HIGH every test passed; 90% of cells supported
Koyna Dam, 903 km2 LIMITED the Shivsagar reservoir is 8.6% of the basin
Hillsborough, Florida, 436 km2 LIMITED 53% of cells raised by filling, 94% of slopes below the noise floor, 4% supported

Florida is the one to read twice: it is also the station where the DEM backend's own area error is +99%, so the grade names the case before the number misleads anyone.

And Basin.data_quality() asks the same question of every other layer, each against something produced independently of it: land cover as the agreement between ESA WorldCover and the ESRI annual series, rainfall as CHIRPS against TerraClimate, soil as the width of SoilGrids' own published interval, surface water as the permanent-to-seasonal split, delineation as the network check and the accuracy regime for a basin of this size -- and elevation split by terrain class, because a basin that is part plain and part mountain is not one number. Where no defensible threshold exists, the layer is reported and deliberately not graded. See Data quality.

And one command writes the lot to paper: basin.report("basin.pdf") produces eight A4 pages with the suitability grade on the cover, every morphometric parameter carrying its symbol and original reference, the channel network against Horton's laws, the per-cell support map, and a methods page with the software versions and licences. It is the thing a thesis chapter or a manuscript appendix actually needs, and it takes about a minute.

The default backend walks HydroBASINS level-12 units, which average about 130 km2, so that is the scale it resolves. Below it, an outlet falls inside a unit whose own outlet may be on the trunk river, and the polygon returned is the trunk's catchment. The geometry gives no sign of this by itself, since the traversal reproduces HydroBASINS' own upstream area on 95% of stations either way.

backend="tdx" answers that band directly. TDX-Hydro carries one catchment polygon per stream reach, derived from TanDEM-X at 12 m, so a basin of a few hundred square kilometres is described by its own ground instead of by the 130 km2 unit that happens to contain its outlet. On 360 catchments between 100 and 500 km2, across eight GEOGLOWS regions on four continents, drawn by seed before any result was seen:

backend median error within 20%
hydrobasins 32.5% 38%
tdx 10.5% 58%

It is better on 66% of them, and the gain is where it should be: on catchments of 100-200 km2 the median error falls from 61% to 11%, and by 350-500 km2, as the basin grows past a level-12 unit, the two converge.

It stays opt-in and auto never reaches for it, for one reason: TDX-Hydro is CC BY-SA 4.0, where every other default in this catalogue is CC BY 4.0 or more permissive, and ShareAlike travels into anything derived from it and redistributed. That is a term to accept deliberately rather than to inherit by default. It also needs pip install "basinkit[tdx]" for the Parquet reader, and the GEOGLOWS v2 republication it reads omits twelve of NGA's sixty-two regions, Greenland and much of Arctic North America among them.

So basinkit confirms every answer against the river network. Where that check raises a question, 85% of those outlets need attention, and it stays quiet on 97% of the ones that do not. Where the network and a 30 m elevation model agree on a smaller catchment, the answer is refined on the elevation model: on 300 gauges drawn after all of this was designed and used nowhere else, that improved 19 results, left 279 unchanged, and reduced none.

On 59 catchments under 2,000 km2 the DEM backend was compared against pysheds and WhiteboxTools on identical rasters. All three agree with each other to within 5% on three quarters of stations, which locates the small-catchment limit in the resolution of pre-computed sub-basins rather than in any one implementation. basinkit returned a basin for every station and had the lowest median error of the three.

A quarter of the gauges sit outside what any of the four methods reproduces, at every snapping distance tried. Where four independent methods agree with each other and differ from the reference, the reference is the variable: a coordinate on a neighbouring tributary, or a published area measured at a different structure. About 75% is the ceiling this catalogue supports for any tool.

The Amazon (4.67 million km2, 35,625 sub-basins) takes 43 seconds. Rainfall, reflectance and radar are checked separately: CHIRPS lands inside the published Koshi climatology, a Sentinel-2 July composite gives an NDVI median of 0.82 over temperate farmland, Sentinel-1 RTC gives -9.3 dB over vegetated land.

Full results, including the twelve named rivers this check replaced as the headline, are in Verification.