mdbartos / pysheds

:earth_americas: Simple and fast watershed delineation in python.
GNU General Public License v3.0
706 stars 191 forks source link

The extent of delineated watershed is not correct in most of the cases for given pour points/outlets. #126

Closed saikirankuntla closed 2 years ago

saikirankuntla commented 4 years ago

I delineated watersheds using pysheds library with the help of Hydrosheds flow direction map of Asia, which can be downloaded from here. It's flow direction coding scheme is (64, 128, 1, 2, 4, 8, 16, 32). Unfortunately, most of the time, though the given pour point is falling on the streamline, the library is not able to delineate its catchment correctly.

The code I am using:

import matplotlib.pyplot as plt
from pysheds.grid import Grid

grid = Grid.from_raster(r'E:\hydrosense\as_dir_30s.tif', data_name='dir')

x, y = 80.8875, 15.9858

grid.catchment(data='dir', x=x, y=y, out_name='catch', recursionlimit=15000, xytype='label')

grid.clip_to('catch')
catchh = grid.view('catch')
plt.imshow(catchh)

Detailed explanation with an example:

github_example

In the above figure (a subset of Asian continent), the red line shows the streamline in vector form and the square boxes below it show the streamline in pixel form whose spatial resolution is the same as the flow direction map from Hydrosheds (900 meters/30 sec).

When I use pixel with yellow border (1) as pour point (coordinates = 80. 8875, 15.9958; flow direction = 2; flow accumulation = 313952) the pysheds delineated the cathemnet as:

github_example1

In the above case, the spatial extent of catchment delineated is not correct.

However, when I use pixel with orange border (2) (coordinates = 80.8875, 16.0049; flow direction = 4; flow accumulation = 313946) and blue border (3) (coordinates = 80.8955, 15.9878; flow direction = 4; flow accumulation = 313956) as pour point/outlet, the extent of catchment delineated by pysheds is correct. It looks like:

github_example2

Kindly let me know why the pysheds could not delineate the catchment correctly when the pixel 1 with yellow boundary is chosen as pour point though the pixel is in the same streamline as pixel 2 and 3, and flow accumulation of pixel 1 is in the same range of pixels 2 and 3.

I faced similar issues with many pour points/outlets. Any help in this regard is much appreciated.

saikirankuntla commented 4 years ago

Strangely, I observed that the coordinates within the pixel are giving different catchment outputs. For example, coordinates (80.8955, 15.9878) at the center of the pixel 3 with the blue border in the above figure are delineating the catchment correctly, whereas, basin delineated with other coordinates (80.8960, 15.9866) in the same pixel is not correct. How is it possible? Since the flow accumulation value will be only one throughout the pixel.

Does grid.catchment() create any shift in the raster image internally while processing?

gzhaowater commented 3 years ago

I had the same issue as @saikirankuntla when using hydrosheds flow direction data. And figured out a solution by using snap='center' in the catchment function. It seems that the default value of snap (i.e. corner) will find the nearest top-left pixel of given x,y. Here is the explanation of snap from the nearest_cell function: https://github.com/mdbartos/pysheds/blob/dbb1519570719e0990504857c0aac1ddd6373876/pysheds/grid.py#L562 Indicates the cell indexing method. If "corner", will resolve to snapping the (x,y) geometry to the index of the nearest top-left cell corner. If "center", will return the index of the cell that the geometry falls within.

mdbartos commented 2 years ago

It seems this issue has been resolved so I will close it. Please reopen if this issue reoccurs.

iamaxy81 commented 2 years ago

I have the same problem and the proposed solution doesn't work for me. Even if I use: grid.catchment(data='dir', x=x, y=y, out_name='catch', recursionlimit=15000, xytype='label', snap='center')

I got wrong results for some arbitrary points directly located on the streamline, and correct results if I move just a few meters away both on the streamline and out of it.