-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Looks like pysheds
is GNU???
#263
Comments
Oh, dang! Yeah, GPLv3 code cannot be shipped with MIT. You either have to change the license or go with |
I was thinking that we might be able to take out the conditioning part of However, it seems that you can get permission from the developer of |
I mean considering #213 I think there is still a desire to move away from |
OK, I thought you're happy with |
The results from |
Can you please try it with the |
Yep will have a look - probably on Tuesday though |
Seems to have a similar issue (at least in this use case) as
|
sounds good - thanks for the detailed look. The CRS was just for speed of reproducability in this example. In |
Oh I misunderstood - yes I had noticed that problem when fiddling with the subbasin delineation. I will make a separate issue for it. #269 OK it could be effects of the buffer there for why |
You can try with the DEM method that I mentioned and see if you get the same results. |
I got curious and when I looked into the This wrapper takes care of getting the Rust binaries and provides a runner. import platform
import requests
import zipfile
import shutil
import tempfile
import stat
from pathlib import Path
import subprocess
def _download_wbt(wbt_root: str | Path = "WBT") -> None:
"""Download the WhiteboxTools executable for the current platform."""
base_url = "https://www.whiteboxgeo.com/WBT_{}/WhiteboxTools_{}.zip"
system = platform.system()
if system not in ("Windows", "Darwin", "Linux"):
raise ValueError(f"Unsupported operating system: {system}")
if system == "Windows":
platform_suffix = "win_amd64"
elif system == "Darwin":
if platform.machine() == "arm64":
platform_suffix = "darwin_m_series"
else:
platform_suffix = "darwin_amd64"
elif system == "Linux":
if "musl" in platform.libc_ver()[0].lower():
platform_suffix = "linux_musl"
else:
platform_suffix = "linux_amd64"
url = base_url.format(system, platform_suffix)
wbt_root = Path(wbt_root)
exe_name = "whitebox_tools.exe" if platform.system() == "Windows" else "whitebox_tools"
if (wbt_root / exe_name).exists():
shutil.rmtree(wbt_root)
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
zip_path = temp_path / "whitebox_tools.zip"
try:
response = requests.get(url)
response.raise_for_status()
zip_path.write_bytes(response.content)
except requests.exceptions.RequestException as e:
raise RuntimeError(f"Failed to download WhiteboxTools: {e!s}") from e
try:
with zipfile.ZipFile(zip_path, "r") as zip_ref:
for file_info in zip_ref.infolist():
if "/WBT/" in file_info.filename:
extracted_path = Path(
*Path(file_info.filename).parts[
Path(file_info.filename).parts.index("WBT") + 1 :
]
)
if extracted_path.parts:
source = zip_ref.extract(file_info, path=temp_dir)
dest = wbt_root / extracted_path
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.move(source, dest)
except zipfile.BadZipFile:
raise RuntimeError("Downloaded file is not a valid zip file.")
# Set executable permissions for non-Windows platforms
if system != "Windows":
executable_names = ["whitebox_tools", "whitebox_runner"]
for exec_name in executable_names:
exec_path = wbt_root / exec_name
if exec_path.exists():
exec_path.chmod(
exec_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
)
def whitebox_tools(
tool_name: str,
args: list[str] | tuple[str, ...],
wbt_root: str | Path = "WBT",
work_dir: str | Path = "",
verbose: bool = False,
compress_rasters: bool = False,
refresh_download: bool = False,
) -> None:
"""Run a WhiteboxTools (not Whitebox Runner) tool with specified arguments.
Parameters
----------
tool_name : str
Name of the WhiteboxTools to run.
args : list or tuple
List of arguments for the tool.
wbt_root : str or Path, optional
Path to the root directory containing the Whitebox executables (default is "WBT").
work_dir : str or Path, optional
Working directory for the tool (default is current directory).
verbose : bool, optional
Whether to print verbose output (default is False).
compress_rasters : bool, optional
Whether to compress output rasters (default is False).
refresh_download : bool, optional
Whether to refresh the download if WhiteboxTools is found (default is False).
Raises
------
subprocess.CalledProcessError
If the tool execution fails.
Exception
For any other unexpected errors.
Notes
-----
This function will run the specified WhiteboxTools tool and handle its output.
If verbose is True, all output will be printed.
"""
wbt_root = Path(wbt_root)
work_dir = Path(work_dir) if work_dir else Path.cwd()
exe_name = "whitebox_tools.exe" if platform.system() == "Windows" else "whitebox_tools"
exe_path = wbt_root / exe_name
if not exe_path.exists() or refresh_download:
_download_wbt(wbt_root)
command = [
str(exe_path),
f"--run={tool_name}",
f"--wd={work_dir}",
"-v" if verbose else "-v=false",
f"--compress_rasters={'true' if compress_rasters else 'false'}",
]
command.extend(args)
if verbose:
print(" ".join(map(str, command)))
try:
process = subprocess.run(command, check=True, text=True, capture_output=True)
if verbose:
print(process.stdout)
except subprocess.CalledProcessError as e:
print(f"Error output: {e.stdout}")
raise Exception(f"Error running tool: {e}")
except Exception as e:
raise Exception(f"Unexpected error: {e}") Then, I was able to reproduce the whole delineation with only WhitboxTools. import shapely
bbox = shapely.box(*dem.rio.bounds())
u, x, y = zip(
*[
(u, float(p["x"]), float(p["y"]))
for u, p in g.nodes(data=True)
if shapely.Point(p["x"], p["y"]).within(bbox)
]
)
gpd.GeoSeries(gpd.points_from_xy(x, y), crs=g.graph["crs"]).to_file("pour_pts.shp")
whitebox_tools("BreachDepressionsLeastCost", ["-i=dem.tif", "-o=dem_corr.tif"])
whitebox_tools("D8Pointer", ["-i=dem_corr.tif", "-o=fdir.tif"])
whitebox_tools("D8FlowAccumulation", ["-i=fdir.tif", "--pntr", "-o=streams.tif"])
whitebox_tools("JensonSnapPourPoints", ["--pour_pts=pour_pts.shp", "--streams=streams.tif", "--snap_dist=15.0", "-o=pour_pts_snapped.shp"])
whitebox_tools("Watershed", ["--d8_pntr=fdir.tif", "--pour_pts=pour_pts_snapped.shp", "-o=watersheds.tif"])
with rasterio.open("watersheds.tif") as src:
gdf_bas = vectorize(
src.read(1).astype(np.int32), 0, src.transform, src.crs, name="basin"
)
gdf_bas = gdf_bas[gdf_bas.basin != src.nodata]
gdf_bas["id"] = [u[x - 1] for x in gdf_bas["basin"]] I highly recommend reading the hydrology part of the WhiteboxTools documentation here, it has lots of good stuff. |
Since it is a requirement... I guess this would make
SWMManywhere
have to be GNU no?ughhhhh - richdem, #137 is too..
pyflwdir
isn't, but I was thrilled with the conditioning results we were seeing from it.Or the really simple option would just be to do a thessian polygon type approach like in: https://doi.org/10.3390/w15010046
The text was updated successfully, but these errors were encountered: