[general]
name=basinkit
qgisMinimumVersion=3.28
qgisMaximumVersion=4.99
description=Click a river anywhere on Earth and get an analysis-ready basin package: elevation, terrain surfaces, land cover, soil, rainfall, surface water, rivers, full Horton-Strahler morphometry, a grade for whether the elevation model can carry any of it, a quality indicator for every other layer, and an eight-page report.
version=0.9.1
author=Pradeepika Kaushik
email=pradeepika.kaushik@gmail.com

about=Click a point on any river in the world and get the basin draining into it, then pull DEM, land cover, soil, rainfall, surface water, rivers and lakes for that basin -- clipped and masked to the polygon, not to its bounding box. No account is needed for any of it. Delineation is validated blind against 2,550 gauges in 99 countries on six continents, whose catchment areas are published by the agencies that operate them, and the plugin reports which accuracy regime an answer falls in rather than quoting a single figure: 0.3 percent median area error above 100,000 square kilometres, 1.7 percent from 2,000 to 10,000. Below about 2,000 square kilometres the DEM backend is the right instrument, and the plugin says so at the moment it matters and switches to it where the evidence supports the switch.
    Other plugins delineate from a clicked point, and Sen Hydro does it well through the same public mghydro service this plugin can use. Three things here are different. The data: elevation, land cover, soil, rainfall, surface water, rivers and lakes come back as layers clipped to the polygon, not as a report. The morphometry: the full Horton-Strahler-Schumm set from one algorithm, with Strahler streams counted as streams rather than as the reaches a river dataset splits them into. And the offline path: the default backend walks the HydroBASINS level-12 graph from a cached local copy, so after the first download it needs no network at all. Every algorithm is a Processing algorithm, so batch mode, the Model Builder and qgis_process all work.
    SETUP: needs QGIS 3.28 or newer, because the package needs Python 3.10 (geopandas 1.0 and rasterio both do) and older QGIS builds ship Python 3.7 or 3.8, where pip cannot install it at all. QGIS 3.34 LTR and 3.40 are both new enough. This plugin runs on the Python package "basinkit", which is installed once with pip into the Python that QGIS itself uses. The plugin detects whether it is present and prints the exact command for your installation, so setup is a single copy and paste. The surest route on every platform is from the QGIS Python Console, which installs into the interpreter QGIS imports from; note that "!pip install" works only in Jupyter, not in the QGIS console. See the plugin homepage for details.
    LICENCE: the plugin is GPL-3.0-or-later. The basinkit Python package it
    calls is Apache-2.0. Neither licence grants the use of the name
    basinkit; a fork must carry its own.

    CITATION: if basinkit contributes to published work, please cite
    Kaushik, P. (2026), basinkit, doi.org/10.5281/zenodo.22181933, and
    the datasets the run used. Every algorithm's help panel prints it.

    THANKS: Vitor Castellar tested the QGIS algorithms against his own
    reference delineations and reported the boundary and CRS failures
    fixed in 0.8.3 and 0.8.4.

tracker=https://github.com/Praddy-GByte/basinkit/issues
repository=https://github.com/Praddy-GByte/basinkit
homepage=https://praddy-gbyte.github.io/basinkit/

category=Vector
icon=icon.png
experimental=False
deprecated=False
hasProcessingProvider=yes

# The pip distribution this plugin runs on. QGIS installs plugins but not
# their Python dependencies, so the plugin detects it at load
# and hands the user a command that works. Declaring it here is what puts it in
# the "External dependencies" field on plugins.qgis.org.
external_deps=basinkit>=0.9.1
server=False

tags=hydrology,watershed,catchment,basin,delineation,dem,terrain,slope,hand,morphometry,remote sensing,satellite,srtm,copernicus,sentinel,landsat,rainfall,soil,stac,processing

changelog=0.9.1
    - Basin report ran at ten times the budget 0.9.0 had just set for it. The
      package caps the elevation grid at four megapixels because a larger one
      was killed by the operating system, and inside QGIS that takes QGIS with
      it -- but this algorithm passed a budget of its own, and that default
      stood at forty. Measured on the Juniata (8,805 km2) in QGIS 3.34: 245
      seconds and 5.61 GB at forty, 26 seconds and 1.26 GB at four, for the
      same eight pages within six kilobytes of each other. The larger grid
      bought nothing, because every raster a page draws is decimated to 1,600
      pixels first.
    - Fetch basin data layers asked for a hundred megapixels, about 5.6 GB,
      past the ceiling the elevation guard enforces -- so a large basin was
      refused outright instead of coming back at a coarser resolution. It now
      asks for sixty, as the three other surface algorithms do.
    - Data quality reported a layer it could not measure as a layer that
      measured badly. A rainfall correlation that came back as not-a-number was
      graded LIMITED, and through the worst-of rule that one layer set the whole
      basin's grade: a basin whose rainfall pair agrees at r = 0.949 was
      reported LIMITED overall instead of MODERATE. An unmeasurable layer now
      stays ungraded and says why.
    - The notice shown when QGIS runs a Python too old for the package said to
      update to 3.28, which is the release the reader was already on. It now
      names 3.34. The minimum stays 3.28, because the bundled Python belongs to
      the installer rather than to the QGIS version: the Windows and macOS
      builds of 3.28 shipped Python 3.9, where pip finds no release of basinkit
      at all, while the Debian and Ubuntu packages of the same QGIS run on 3.11,
      where it installs normally.
    - Needs basinkit 0.9.1 or newer.
    
    0.9.0
    - Delineate river basin takes an optional line layer of known channels and
      forces the flow along them. Where a stream runs in a culvert under a city,
      or a road embankment dams a valley in the elevation model, the surface
      carries no channel and the water is sent the wrong way; a line drawn on
      the canvas is enough to correct it. Lowering the cells by a fixed depth
      does nothing -- the trench keeps the terrain's own rises -- so each line
      is walked from its lower end and forced to descend the whole way. The
      provenance records that the path was forced, how deep and over how many
      cells, because a basin that was told where to go and one that was found
      are not the same kind of answer.
    - A basin that disagrees with the river at its outlet is now reported
      instead of printed. The check measured the basin only against the largest
      river within the search radius, which beside a confluence is a different
      and far bigger river: a basin at half of what drains to its own stream
      passed, and one at nine times it passed too. It now tests both directions
      against the river at the outlet, and where two channels meet within a
      metre of the point it says the outlet is ambiguous and names both
      catchments rather than choosing one.
    - The TDX-Hydro backend took the reach whose recorded point was nearest.
      Beside a confluence that is a stub: at one outlet it returned 122 km2 of
      a 228 km2 basin. It now takes the unit catchment that contains the
      outlet, and that basin reads 241 km2, in line with the other backends.
    - Basin morphometry and the terrain surfaces no longer fetch a second
      elevation grid, so one report cannot print two different values for the
      same basin's highest point.
    - Every algorithm's help panel now prints the citation and the DOI.
    - The plugin is GPL-3.0-or-later. The basinkit Python package it calls is
      Apache-2.0. Neither licence grants the use of the name basinkit; a fork
      must carry its own.
    - The plugin now asks for the packages it actually needs. It told people
      to run "pip install basinkit", which does not install pyflwdir -- and
      the DEM backend routes with pyflwdir, which auto uses for every
      catchment below 2,000 km2. Those basins came back as the coarser
      HydroBASINS answer instead, 21.6 percent high on one 259 km2 catchment,
      with nothing on the face of the result to say so. It now names
      basinkit[delineate] and basinkit[viz], says what each is for, and quotes
      the extras so the command survives a shell. On Debian and Ubuntu, where
      QGIS runs on a system Python the distribution marks as externally
      managed, the command now carries --break-system-packages, without which
      it failed outright.
    - Basin report no longer takes QGIS down with it. It read elevation at
      the 100 Mpx default, which on a large basin reached about 5.9 GB and was
      killed by the operating system -- and inside QGIS that kills QGIS. The
      grid is now budgeted to 4 Mpx at the point every caller arrives, which
      on a 54,000 km2 basin is about 186 m and on a 235 km2 one is still its
      native 31 m, and the rasters drawn on the pages are decimated to 1,600
      pixels because an A4 page at 300 dpi cannot show more. The cover states
      the resolution used. Measured on the large basin: 1.33 GB and eighteen
      seconds, against a process that did not finish.
    - Delineate river basin declines a window it cannot route, naming the
      megapixels, the memory estimate and the backend to use instead, rather
      than growing the window until the process is killed with nothing
      written.
    - The log is readable again: a delineation emitted twenty-six copies of
      "Use @ matmul instead of * mul operator", a deprecation inside affine
      that names a file nobody here can change.
    - Asking for a backend by name is now checked the way auto checks itself.
      Before, a backend chosen explicitly skipped every check, and a basin at
      one percent of what drains to the point came back looking like any other
      answer.
    - Needs basinkit 0.9.0 or newer.
    
    0.8.4
    - Landscape form no longer fails on a basin that has knickpoints.
      It asked the output sink for its field list, which QgsFeatureSink
      does not have, so it only survived basins where there was nothing
      to write. Found by running all eleven tools over five small
      sub-catchments of the Koshi; three of the five hit it.
    
    0.8.3
    - A projected basin layer is now reprojected to EPSG:4326 on the way in.
      basinkit works in lon/lat throughout, so a UTM layer used to arrive as
      metres and PROJ rejected a northing of 7,793,981 as a latitude. This
      failed in Fetch basin data layers and in Basin morphometry; all seven
      algorithms share the same entry point and all seven are fixed.
    - Delineate river basin now warns below 2,000 km2 rather than 500, and
      says what the coarse polygon is: whole HydroBASINS level-12 units of
      about 130 km2, not a routed elevation model, so its boundary follows
      unit edges rather than the terrain divide.
    - Needs basinkit 0.8.3 or newer.
    
    0.8.0
    - New algorithm: Landscape form. chi, normalised channel steepness,
      concavity and knickpoints -- whether a river is still adjusting or has
      settled, which the shape indices cannot tell you. Knickpoints come back
      as a point layer carrying the height of each step and how far its local
      gradient stands above the profile's own median. Channel steepness was
      checked cell by cell against TopoToolbox on two basins and agrees to
      within 6 percent at every quantile. The knickpoint count is not that
      stable and the algorithm says so; it is not an uplift rate either.
    - New algorithm: Export for Arc Hydro. Sub-catchments and reaches as
      Catchment and DrainageLine layers carrying HydroID, HydroCode,
      NextDownID and AreaSqKm, so Arc Hydro's own tools read them without
      conversion. A renaming, not a computation: every value written is one
      basinkit already holds, and DrainID is deliberately left for Arc Hydro
      to populate rather than guessed with a spatial join.
    - Eleven algorithms now. Needs basinkit 0.8.2 or newer.

    0.7.0
    - New algorithm: Data quality. A grade for every layer, not only for the
      elevation model, each measured 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 as the suitability grade split by
      terrain class. Suggested by Prof. Dr. B. Mishra.
    - Soil and surface water are reported without a grade, because no published
      threshold exists for either; the output says so rather than inventing a
      cut-off. Every threshold that does exist is printed beside the
      measurement it judged.
    - The ESRI land cover reader now writes an integer nodata value, so a
      comparison against another class raster no longer counts nodata as a
      class.
    0.6.3
    - On QGIS builds older than 3.28 the plugin now says so. basinkit needs
      Python 3.10, which those builds do not ship, so pip cannot install it
      there at all and the old message ('no module named basinkit') sent
      people looking for an installation fault that was not there.
    - The install instructions now lead with the QGIS Python Console route,
      which installs into the interpreter QGIS imports from on every
      platform, and note that '!pip install' works only in Jupyter.
    0.6.2
    - Found by running every analysis on the Ganga above Farakka (934,516
      square kilometres) and on the Potomac, then checking the results
      against GRDC, 190 Nepal gauges, IMD rainfall and USGS records.
    - Sentinel-2, Landsat, Sentinel-1 and land cover change failed on very
      large basins: the basin outline was too big for the catalogue search.
      The search now sends a simplified outline that still contains the
      basin; results are clipped to the full outline as before.
    - The 3D page ran out of memory on large basins and showed a black screen
      for basins wider than 900 km. Both fixed; the page also declares its
      text encoding so symbols render correctly.
    - The river profile reads a capped elevation model; on a 30,000 km2
      basin it used to need more than 6 GB of memory.
    - The 3D page sets its colour balance from the scene, so forested basins
      no longer render nearly black.
    - The report's first page names the elevation product it used.
    - Needs basinkit 0.6.2.
    0.6.1
    - 'Basin statistics' reported mean slope over the whole bounding box, with
      the ground outside the basin filled in as a flat plain. On a catchment
      filling 43 percent of its box that read 7 degrees where the basin's own
      slopes average 16. It now measures inside the basin only.
    - A failed delineation now says why, instead of reporting an
      AttributeError about a missing helper.
    - The check against the river network measures distance on the ground, so
      it no longer misses rivers inside its search radius at high latitude.
    - Needs basinkit 0.6.1, which also requires geopandas 1.0: on installs with
      an older geopandas the first delineation used to fail.
    0.6.0
    - Four new Processing algorithms. 'Terrain surfaces' computes slope,
      aspect, hillshade, curvature, topographic position, ruggedness, local
      relief, slope-position classes, flow accumulation, the channel network,
      the wetness index and height above nearest drainage, all from one
      elevation download rather than one per surface. 'Sub-catchments and their
      routing' returns the pieces a basin is assembled from, each carrying
      NEXT_DOWN, which is the routing graph a distributed model needs without
      inferring anything from geometry. 'Elevation data suitability' grades
      whether the elevation model can carry the terrain analysis at all.
      'Basin report' writes eight A4 pages ready for a thesis or a manuscript.
    - The elevation data suitability grade is the one worth reading first.
      Five measurements against stated thresholds -- how much surface
      depression filling invented, how many slopes fall below the angle at
      which a gradient is only the model's own error, relief against that
      error, the largest level surface, and cells with no elevation -- combined
      into HIGH, MODERATE or LIMITED with a per-cell map of which ground the
      answer rests on. Tested on 133 gauges against an independently produced
      elevation model: where it says HIGH the two models agree about the slope
      field at r = 0.94, where it says LIMITED at r = 0.76.
    - A twelve-metre delineation backend. 'tdx' walks a reach-level graph built
      from TanDEM-X, one catchment per stream reach instead of one per 130
      square kilometre unit. On 360 gauges between 100 and 500 square
      kilometres it cut the median area error from 32.5 percent to 10.5 percent
      and was the better answer on two thirds of them. It is never chosen
      automatically because TDX-Hydro is CC BY-SA, and ShareAlike travels into
      anything derived from it and redistributed.
    - Cell size is taken per row from that row's latitude everywhere in the
      terrain code. Dividing by one assumed width reports a basin at 60 degrees
      north as about twice as steep as it is.

    0.5.0
    - Compatibility across the full supported QGIS range. The provider now
      resolves the Processing source-type enum by asking the API for it, so it
      loads identically on QGIS 3.28 through 4.x. QGIS 3.34, the current
      long-term release, is covered by a continuous integration job that
      installs QGIS and loads every algorithm.
    - Accuracy is now reported by catchment size, from blind validation against
      2,550 gauges in 99 countries whose catchment areas are published by the
      agencies that operate them: 0.3 percent median error above
      100,000 square kilometres, 1.3 percent from 10,000 to 100,000, 1.7
      percent from 2,000 to 10,000. Below about 2,000 square kilometres the
      'dem' backend is the better instrument, and the plugin now says so at the
      moment it matters.
    - Every answer is checked against the river network. When the basin exceeds
      twice the area draining to the largest river within two kilometres of the
      outlet, the plugin reports it: 85 percent of the outlets it flags need
      attention, and it stays quiet on 97 percent of the ones that do not.
      Precision runs from 75 percent in Europe to 93 percent in Africa.
    - The 'auto' backend refines on the elevation model when the river network
      and a 30 metre routing of the same point agree on a smaller catchment.
      Across 300 gauges drawn after the method was fixed and used nowhere else
      in its design, it improved 19 results, left 279 unchanged and reduced
      none. Where it acts, the median error falls from 1,731 percent to 4.3
      percent, at a median cost of 1.6 seconds.
    - Refinement acts only when the river it is judging by lies within a
      kilometre of the outlet. Beyond that distance the point is not on that
      river, so the two sources stop being independent. Every refinement that
      improved a result had its river within 0.91 kilometres.
    - The plugin now names what kind of place the outlet is in. An endorheic
      system, a coastal strip draining straight to the ocean, and an outlet
      with nothing draining into it are each reported, the last being what a
      lake surface and a sub-grid headwater have in common.
    - Messages are matched to the cause and say what to do next: a coordinate
      outside the network's coverage, one beyond the snap distance, and one on
      a hillslope rather than in a channel each get their own guidance.
    - The consistency line now compares the result against the river network
      rather than against the source dataset's own upstream-area field, which
      confirms the traversal rather than the choice of outlet.
    - The river-network check is a checkbox, on by default, and is the only
      thing that downloads the regional rivers file.
    - Against pysheds and WhiteboxTools on identical 30 metre rasters across 59
      catchments under 2,000 square kilometres, the 'dem' backend returned a
      basin for every one, matched the agency figure within 20 percent on 68
      percent of them against 56 and 51, and had the lowest median error.
    - Requires basinkit 0.5 or newer.

    0.4.0
    - New algorithm: Basin morphometry. The full Horton-Strahler-Schumm set
      from one run, with the per-order table showing Strahler streams and
      dataset reaches side by side, and the counts tested against what Strahler
      ordering allows. A bifurcation ratio below 2 and more than one stream of
      the basin's highest order are both impossible, and are now reported
      instead of being handed back as numbers to interpret. Until now
      morphometry was in the Python package but not reachable from QGIS.
    - The plugin description leads with the data package rather than with
      "delineate". QGIS already has
      several delineation plugins, and the old wording put this one in that
      queue while morphometry, which is the part with no equivalent elsewhere,
      went unmentioned.
    - Requires basinkit 0.4 or newer.

    0.3.3
    - Pairs with basinkit 0.3.3, which corrects channel_gradient_m_per_km. Up to
      0.3.0 it divided total basin relief by main channel length, which reports
      a fall the river never makes, because the highest point in a basin is a
      ridge top and not the head of the main stem. It is now read from the bed:
      the DEM is sampled along the main channel and the drop between its ends is
      divided by the channel length. On the Koshi that is 9.6 m/km, not 15.1.
      The Basin statistics algorithm never reported this figure, so nothing in
      the plugin's own output changes; it matters if you called morphometry()
      from the Python Console or a script, where the old value should be
      recomputed.
    - Basin.morphometry() now checks its own stream counts. Two of the checks
      are impossibilities rather than oddities: an order-u+1 stream is formed
      where two order-u streams meet, so N(u) >= 2*N(u+1) and the bifurcation
      ratio can never fall below 2, and a basin with one outlet has exactly one
      stream of its highest order. Counts that break either are reported rather
      than returned as numbers.
    - The plugin description now says plainly what this does that a
      delineate-from-a-click plugin offers, rather than leaving a reader to
      work it out.

    0.3.2
    - Declares its pip dependency in the external_deps metadata field, so it
      shows in the External dependencies box on the plugin page.

    0.3.1
    - Fixed 16 Qt6 compatibility issues found by the plugin repository's own
      checker: every Qt and QGIS enum is now spelled with its full scope
      (QgsWkbTypes.Type.Polygon rather than QgsWkbTypes.Polygon, and so on).
      The scoped spelling works on both PyQt5 and PyQt6, so QGIS 3.28 onwards
      and QGIS 4 are both covered by one code path, with no version guard.
    - A test now scans the plugin for unscoped enums, so they cannot come back.

    0.3.0
    The plugin version now tracks the basinkit package version, so it is clear
    which plugin goes with which package. No algorithm has changed since 0.1.0.
    - Fixed: on macOS the "package missing" notice printed the QGIS application
      binary instead of an interpreter, so the suggested pip command opened a
      second QGIS window and installed nothing. A path is now offered only once
      it is verified to be a python executable, and there is a Python Console
      snippet that needs no path at all
    - New icon: the b is drawn as a river basin with a dendritic stream network
      draining to a single outlet
    - Pairs with basinkit 0.3.0, which adds Basin.morphometry() -- the classical
      Horton-Strahler-Schumm parameters -- to the Python API
    0.1.0
    First release.
    - Delineate a basin from a canvas click, globally, via HydroBASINS graph traversal or DEM flow routing
    - Fetch DEM, land cover, soil, surface water, rivers and lakes clipped to the basin
    - Basin statistics: area, relief, mean slope, land cover fractions, bounding-box efficiency
    - Every algorithm runs in the Processing framework, so batch mode and the Model Builder work
