├── docs ├── authors.rst ├── history.rst ├── readme.rst ├── contributing.rst ├── index.rst ├── Makefile ├── usage.rst ├── make.bat ├── installation.rst └── conf.py ├── tests ├── __init__.py └── test_whitebox.py ├── examples ├── testdata.zip ├── testdata │ ├── DEM.tif │ └── DEM.dep └── whitebox.ipynb ├── whitebox ├── img │ ├── open.gif │ ├── open.png │ ├── tool.gif │ ├── tool.png │ ├── closed.gif │ ├── closed.png │ ├── WBRunner.png │ ├── WBT_icon.png │ ├── WhiteboxToolsLogo.png │ ├── WhiteboxToolsLogoBlue.png │ ├── WhiteboxToolsLogoGreen.png │ ├── WhiteboxToolsLogo_vert1.png │ ├── WhiteboxToolsLogo_vert2.png │ ├── WhiteboxToolsLogo_vert3.png │ ├── WhiteboxToolsLogo_vert4.png │ ├── WhiteboxToolsLogo_box_only.svg │ ├── WhiteboxToolsLogo.svg │ └── WhiteboxToolsLogo_vert.svg ├── testdata │ ├── DEM.tif │ └── DEM.dep ├── __init__.py ├── whitebox.py ├── cli.py ├── example.py ├── automation.py ├── whitebox_example.py └── download_wbt.py ├── requirements_dev.txt ├── HISTORY.rst ├── AUTHORS.rst ├── binder ├── environment.yml └── postBuild ├── MANIFEST.in ├── tox.ini ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── workflows │ ├── pypi-publish.yml │ └── py-check.yaml ├── setup.cfg ├── .pre-commit-config.yaml ├── LICENSE ├── setup.py ├── .gitignore ├── Makefile ├── CONTRIBUTING.rst └── README.rst /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../AUTHORS.rst 2 | -------------------------------------------------------------------------------- /docs/history.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../HISTORY.rst 2 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Unit test package for whitebox.""" 4 | -------------------------------------------------------------------------------- /examples/testdata.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/examples/testdata.zip -------------------------------------------------------------------------------- /whitebox/img/open.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/open.gif -------------------------------------------------------------------------------- /whitebox/img/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/open.png -------------------------------------------------------------------------------- /whitebox/img/tool.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/tool.gif -------------------------------------------------------------------------------- /whitebox/img/tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/tool.png -------------------------------------------------------------------------------- /whitebox/img/closed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/closed.gif -------------------------------------------------------------------------------- /whitebox/img/closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/closed.png -------------------------------------------------------------------------------- /examples/testdata/DEM.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/examples/testdata/DEM.tif -------------------------------------------------------------------------------- /whitebox/img/WBRunner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WBRunner.png -------------------------------------------------------------------------------- /whitebox/img/WBT_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WBT_icon.png -------------------------------------------------------------------------------- /whitebox/testdata/DEM.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/testdata/DEM.tif -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogo.png -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogoBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogoBlue.png -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogoGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogoGreen.png -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | pip 2 | bump2version 3 | wheel 4 | watchdog 5 | flake8 6 | tox 7 | coverage 8 | Sphinx 9 | twine 10 | Click 11 | -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_vert1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogo_vert1.png -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_vert2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogo_vert2.png -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_vert3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogo_vert3.png -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_vert4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opengeos/whitebox-python/HEAD/whitebox/img/WhiteboxToolsLogo_vert4.png -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | History 3 | ======= 4 | 0.2.0 (2018-06-08) 5 | ------------------ 6 | 0.1.0 (2018-06-06) 7 | ------------------ 8 | 9 | * First release on PyPI. 10 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Credits 3 | ======= 4 | 5 | Development Lead 6 | ---------------- 7 | 8 | * Qiusheng Wu 9 | 10 | Contributors 11 | ------------ 12 | * John Lindsay 13 | 14 | -------------------------------------------------------------------------------- /binder/environment.yml: -------------------------------------------------------------------------------- 1 | name: wbt 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python 6 | - numpy 7 | - matplotlib 8 | - imageio 9 | - whitebox 10 | - tifffile 11 | - requests 12 | - googledrivedownloader 13 | 14 | -------------------------------------------------------------------------------- /whitebox/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Top-level package for whitebox.""" 4 | 5 | __author__ = """Qiusheng Wu""" 6 | __email__ = 'giswqs@gmail.com' 7 | __version__ = '2.3.6' 8 | 9 | from .whitebox import * 10 | 11 | 12 | -------------------------------------------------------------------------------- /whitebox/whitebox.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Main module.""" 4 | 5 | from .whitebox_tools import download_wbt, WhiteboxTools 6 | 7 | def Runner(clear_app_state=False, callback=None): 8 | wbt = WhiteboxTools() 9 | wbt.launch_wb_runner(clear_app_state, callback) -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS.rst 2 | include CONTRIBUTING.rst 3 | include HISTORY.rst 4 | include LICENSE 5 | include README.rst 6 | 7 | recursive-include tests * 8 | recursive-exclude * __pycache__ 9 | recursive-exclude * *.py[co] 10 | recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif 11 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py34, py35, py36, flake8 3 | 4 | [travis] 5 | python = 6 | 3.6: py36 7 | 3.5: py35 8 | 3.4: py34 9 | 10 | [testenv:flake8] 11 | basepython = python 12 | deps = flake8 13 | commands = flake8 whitebox 14 | 15 | [testenv] 16 | setenv = 17 | PYTHONPATH = {toxinidir} 18 | 19 | commands = python setup.py test 20 | 21 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | charset = utf-8 11 | end_of_line = lf 12 | 13 | [*.bat] 14 | indent_style = tab 15 | end_of_line = crlf 16 | 17 | [LICENSE] 18 | insert_final_newline = false 19 | 20 | [Makefile] 21 | indent_style = tab 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * whitebox version: 2 | * Python version: 3 | * Operating System: 4 | 5 | ### Description 6 | 7 | Describe what you were trying to get done. 8 | Tell us what happened, what went wrong, and what you expected to happen. 9 | 10 | ### What I Did 11 | 12 | ``` 13 | Paste the command(s) you ran and the output. 14 | If there was a crash, please include the traceback here. 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to whitebox's documentation! 2 | ====================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | readme 9 | installation 10 | usage 11 | modules 12 | contributing 13 | authors 14 | history 15 | 16 | Indices and tables 17 | ================== 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /binder/postBuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /srv/conda/lib/python3.6/site-packages/whitebox 3 | wget https://www.whiteboxgeo.com/WBT_Linux/WhiteboxTools_linux_amd64.zip 4 | tar -xvf WhiteboxTools_linux_amd64.tar.xz 5 | mv WBT/whitebox_tools . 6 | mkdir testdata 7 | cd testdata 8 | wget https://github.com/opengeos/whitebox-python/raw/master/examples/testdata/DEM.tif 9 | wget https://github.com/opengeos/whitebox-python/raw/master/examples/testdata/DEM.dep -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 2.3.6 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:setup.py] 7 | search = version='{current_version}' 8 | replace = version='{new_version}' 9 | 10 | [bumpversion:file:whitebox/__init__.py] 11 | search = __version__ = '{current_version}' 12 | replace = __version__ = '{new_version}' 13 | 14 | [bdist_wheel] 15 | universal = 1 16 | 17 | [flake8] 18 | exclude = docs 19 | 20 | [aliases] 21 | -------------------------------------------------------------------------------- /whitebox/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Console script for whitebox.""" 4 | import sys 5 | import click 6 | 7 | 8 | @click.command() 9 | def main(args=None): 10 | """Console script for whitebox.""" 11 | click.echo("Replace this message by putting your code into " "whitebox.cli.main") 12 | click.echo("See click documentation at http://click.pocoo.org/") 13 | return 0 14 | 15 | 16 | if __name__ == "__main__": 17 | sys.exit(main()) # pragma: no cover 18 | -------------------------------------------------------------------------------- /examples/testdata/DEM.dep: -------------------------------------------------------------------------------- 1 | Min: 212.22877502441406 2 | Max: 1233.0966796875 3 | North: 4895782.5891085025 4 | South: 4878858.5400943495 5 | East: 686063.139196986 6 | West: 664737.0507251581 7 | Cols: 237 8 | Rows: 188 9 | Stacks: 1 10 | Data Type: FLOAT 11 | Z Units: not specified 12 | XY Units: metres 13 | Projection: not specified 14 | Data Scale: continuous 15 | Display Min: 212.22877502441406 16 | Display Max: 1233.0966796875 17 | Preferred Palette: high_relief.pal 18 | NoData: -32768.0 19 | Byte Order: LITTLE_ENDIAN 20 | Palette Nonlinearity: 1.0 21 | -------------------------------------------------------------------------------- /whitebox/testdata/DEM.dep: -------------------------------------------------------------------------------- 1 | Min: 212.22877502441406 2 | Max: 1233.0966796875 3 | North: 4895782.5891085025 4 | South: 4878858.5400943495 5 | East: 686063.139196986 6 | West: 664737.0507251581 7 | Cols: 237 8 | Rows: 188 9 | Stacks: 1 10 | Data Type: FLOAT 11 | Z Units: not specified 12 | XY Units: metres 13 | Projection: not specified 14 | Data Scale: continuous 15 | Display Min: 212.22877502441406 16 | Display Max: 1233.0966796875 17 | Preferred Palette: high_relief.pal 18 | NoData: -32768.0 19 | Byte Order: LITTLE_ENDIAN 20 | Palette Nonlinearity: 1.0 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = whitebox 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v6.0.0 4 | hooks: 5 | # - id: check-toml 6 | # - id: check-yaml 7 | # - id: end-of-file-fixer 8 | # types: [python] 9 | # - id: trailing-whitespace 10 | # - id: requirements-txt-fixer 11 | - id: check-added-large-files 12 | args: ["--maxkb=500"] 13 | 14 | # - repo: https://github.com/psf/black 15 | # rev: 24.4.2 16 | # hooks: 17 | # - id: black-jupyter 18 | # language_version: python3.11 19 | 20 | # - repo: https://github.com/kynan/nbstripout 21 | # rev: 0.7.1 22 | # hooks: 23 | # - id: nbstripout 24 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | Usage 3 | ===== 4 | 5 | To use whitebox in a project:: 6 | 7 | import whitebox 8 | 9 | For example: 10 | 11 | .. code:: python 12 | 13 | import os 14 | from importlib_resources import files 15 | import whitebox 16 | 17 | wbt = whitebox.WhiteboxTools() 18 | print(wbt.version()) 19 | print(wbt.help()) 20 | 21 | # identify the sample data directory of the package 22 | data_dir = str(files("whitebox").joinpath("testdata")) 23 | 24 | wbt.set_working_dir(data_dir) 25 | wbt.verbose = False 26 | wbt.feature_preserving_denoise("DEM.tif", "smoothed.tif", filter=9) 27 | wbt.breach_depressions("smoothed.tif", "breached.tif") 28 | wbt.d_inf_flow_accumulation("breached.tif", "flow_accum.tif") 29 | 30 | Check the example.py_ for more details. 31 | 32 | .. _example.py: https://github.com/opengeos/whitebox-python/blob/master/whitebox/example.py -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=whitebox 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 20 | echo.then set the SPHINXBUILD environment variable to point to the full 21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 22 | echo.Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install setuptools wheel twine 25 | - name: Build and publish 26 | env: 27 | TWINE_USERNAME: ${{ secrets.PYPI_USERS }} 28 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 29 | run: | 30 | python setup.py sdist bdist_wheel 31 | twine upload dist/* 32 | -------------------------------------------------------------------------------- /tests/test_whitebox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Tests for `whitebox` package.""" 5 | 6 | 7 | import unittest 8 | from click.testing import CliRunner 9 | 10 | from whitebox import whitebox 11 | from whitebox import cli 12 | 13 | 14 | class TestWhitebox(unittest.TestCase): 15 | """Tests for `whitebox` package.""" 16 | 17 | def setUp(self): 18 | """Set up test fixtures, if any.""" 19 | wbt = whitebox.WhiteboxTools() 20 | print(wbt.version()) 21 | 22 | def tearDown(self): 23 | """Tear down test fixtures, if any.""" 24 | 25 | def test_000_something(self): 26 | """Test something.""" 27 | 28 | # def test_command_line_interface(self): 29 | # """Test the CLI.""" 30 | # runner = CliRunner() 31 | # result = runner.invoke(cli.main) 32 | # assert result.exit_code == 0 33 | # assert 'whitebox.cli.main' in result.output 34 | # help_result = runner.invoke(cli.main, ['--help']) 35 | # assert help_result.exit_code == 0 36 | # assert '--help Show this message and exit.' in help_result.output 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018, Qiusheng Wu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Installation 5 | ============ 6 | 7 | 8 | Stable release 9 | -------------- 10 | 11 | To install whitebox, run this command in your terminal: 12 | 13 | .. code-block:: console 14 | 15 | $ pip install whitebox 16 | 17 | This is the preferred method to install whitebox, as it will always install the most recent stable release. 18 | 19 | If you don't have `pip`_ installed, this `Python installation guide`_ can guide 20 | you through the process. 21 | 22 | .. _pip: https://pip.pypa.io 23 | .. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ 24 | 25 | 26 | From sources 27 | ------------ 28 | 29 | The sources for whitebox can be downloaded from the `Github repo`_. 30 | 31 | You can either clone the public repository: 32 | 33 | .. code-block:: console 34 | 35 | $ git clone git://github.com/opengeos/whitebox 36 | 37 | Or download the `tarball`_: 38 | 39 | .. code-block:: console 40 | 41 | $ curl -OL https://github.com/opengeos/whitebox-python/tarball/master 42 | 43 | Once you have a copy of the source, you can install it with: 44 | 45 | .. code-block:: console 46 | 47 | $ python setup.py install 48 | 49 | 50 | .. _Github repo: https://github.com/opengeos/whitebox 51 | .. _tarball: https://github.com/opengeos/whitebox-python/tarball/master 52 | -------------------------------------------------------------------------------- /.github/workflows/py-check.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | pull_request: 6 | branches: 7 | - master 8 | workflow_dispatch: 9 | schedule: 10 | - cron: "0 6 * * 1" 11 | 12 | name: py-check 13 | jobs: 14 | py-check: 15 | runs-on: ${{ matrix.os }} 16 | name: ${{ matrix.os }} (${{ matrix.python-version }}) 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | os: [ubuntu-latest] 21 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 22 | include: 23 | - os: macos-latest 24 | python-version: "3.12" 25 | - os: windows-latest 26 | python-version: "3.12" 27 | 28 | env: 29 | SDKROOT: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk 30 | steps: 31 | - name: CHECKOUT CODE 32 | uses: actions/checkout@v4 33 | - name: SETUP PYTHON 34 | uses: actions/setup-python@v5 35 | with: 36 | python-version: ${{ matrix.python-version }} 37 | - name: Install dependencies 38 | run: | 39 | python -m pip install --upgrade pip 40 | pip install -U setuptools 41 | pip install --user -r requirements_dev.txt 42 | - name: WBT-TEST 43 | run: | 44 | python -m unittest discover tests/ 45 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """The setup script.""" 5 | 6 | from setuptools import setup, find_packages 7 | 8 | with open("README.rst") as readme_file: 9 | readme = readme_file.read() 10 | 11 | with open("HISTORY.rst") as history_file: 12 | history = history_file.read() 13 | 14 | requirements = [ 15 | "Click>=6.0", 16 | ] 17 | 18 | setup_requirements = [] 19 | 20 | test_requirements = [] 21 | 22 | setup( 23 | author="Qiusheng Wu", 24 | author_email="giswqs@gmail.com", 25 | classifiers=[ 26 | "Development Status :: 2 - Pre-Alpha", 27 | "Intended Audience :: Developers", 28 | "License :: OSI Approved :: MIT License", 29 | "Natural Language :: English", 30 | "Programming Language :: Python :: 3", 31 | "Programming Language :: Python :: 3.4", 32 | "Programming Language :: Python :: 3.5", 33 | "Programming Language :: Python :: 3.6", 34 | ], 35 | description="An advanced geospatial data analysis platform ", 36 | entry_points={ 37 | "console_scripts": [ 38 | "whitebox=whitebox.cli:main", 39 | ], 40 | }, 41 | install_requires=requirements, 42 | license="MIT license", 43 | long_description=readme + "\n\n" + history, 44 | include_package_data=True, 45 | keywords="whitebox", 46 | name="whitebox", 47 | packages=find_packages(include=["whitebox"]), 48 | setup_requires=setup_requirements, 49 | test_suite="tests", 50 | tests_require=test_requirements, 51 | url="https://github.com/opengeos/whitebox-python", 52 | version="2.3.6", 53 | zip_safe=False, 54 | ) 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | .idea/ 6 | whitebox/WBT/ 7 | **/*.tar.xz 8 | **/*.xml 9 | whitebox/img/.DS_Store 10 | whitebox/img/._* 11 | whitebox/plugins 12 | whitebox/testdata/breached.tif 13 | whitebox/testdata/flow_accum.tif 14 | whitebox/testdata/smoothed.tif 15 | whitebox/whitebox_tools 16 | whitebox/whitebox_runner 17 | whitebox/WhiteboxTools_linux_amd64.zip 18 | dev/ 19 | .vscode/ 20 | _build/ 21 | temp/ 22 | whitebox/__MACOSX/ 23 | **/.DS_Store 24 | 25 | # C extensions 26 | *.so 27 | 28 | # Distribution / packaging 29 | .Python 30 | env/ 31 | build/ 32 | develop-eggs/ 33 | dist/ 34 | downloads/ 35 | eggs/ 36 | .eggs/ 37 | lib/ 38 | lib64/ 39 | parts/ 40 | sdist/ 41 | var/ 42 | wheels/ 43 | *.egg-info/ 44 | .installed.cfg 45 | *.egg 46 | 47 | # PyInstaller 48 | # Usually these files are written by a python script from a template 49 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 50 | *.manifest 51 | *.spec 52 | 53 | # Installer logs 54 | pip-log.txt 55 | pip-delete-this-directory.txt 56 | 57 | # Unit test / coverage reports 58 | htmlcov/ 59 | .tox/ 60 | .coverage 61 | .coverage.* 62 | .cache 63 | nosetests.xml 64 | coverage.xml 65 | *.cover 66 | .hypothesis/ 67 | .pytest_cache/ 68 | 69 | # Translations 70 | *.mo 71 | *.pot 72 | 73 | # Django stuff: 74 | *.log 75 | local_settings.py 76 | 77 | # Flask stuff: 78 | instance/ 79 | .webassets-cache 80 | 81 | # Scrapy stuff: 82 | .scrapy 83 | 84 | # Sphinx documentation 85 | docs/_build/ 86 | 87 | # PyBuilder 88 | target/ 89 | 90 | # Jupyter Notebook 91 | .ipynb_checkpoints 92 | examples/.ipynb_checkpoints 93 | 94 | # pyenv 95 | .python-version 96 | 97 | # celery beat schedule file 98 | celerybeat-schedule 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # dotenv 104 | .env 105 | 106 | # virtualenv 107 | .venv 108 | venv/ 109 | ENV/ 110 | 111 | # Spyder project settings 112 | .spyderproject 113 | .spyproject 114 | 115 | # Rope project settings 116 | .ropeproject 117 | 118 | # mkdocs documentation 119 | /site 120 | 121 | # mypy 122 | .mypy_cache/ 123 | whitebox/WhiteboxTools_linux_amd64.zip 124 | whitebox/img/._WhiteboxToolsLogo_box_only.png 125 | whitebox/img/.DS_Store 126 | whitebox/GeneralToolsetExtension_linux.zip 127 | whitebox/settings.json 128 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean clean-test clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | 4 | define BROWSER_PYSCRIPT 5 | import os, webbrowser, sys 6 | 7 | try: 8 | from urllib import pathname2url 9 | except: 10 | from urllib.request import pathname2url 11 | 12 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 13 | endef 14 | export BROWSER_PYSCRIPT 15 | 16 | define PRINT_HELP_PYSCRIPT 17 | import re, sys 18 | 19 | for line in sys.stdin: 20 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 21 | if match: 22 | target, help = match.groups() 23 | print("%-20s %s" % (target, help)) 24 | endef 25 | export PRINT_HELP_PYSCRIPT 26 | 27 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 28 | 29 | help: 30 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 31 | 32 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 33 | 34 | clean-build: ## remove build artifacts 35 | rm -fr build/ 36 | rm -fr dist/ 37 | rm -fr .eggs/ 38 | find . -name '*.egg-info' -exec rm -fr {} + 39 | find . -name '*.egg' -exec rm -f {} + 40 | 41 | clean-pyc: ## remove Python file artifacts 42 | find . -name '*.pyc' -exec rm -f {} + 43 | find . -name '*.pyo' -exec rm -f {} + 44 | find . -name '*~' -exec rm -f {} + 45 | find . -name '__pycache__' -exec rm -fr {} + 46 | 47 | clean-test: ## remove test and coverage artifacts 48 | rm -fr .tox/ 49 | rm -f .coverage 50 | rm -fr htmlcov/ 51 | rm -fr .pytest_cache 52 | 53 | lint: ## check style with flake8 54 | flake8 whitebox tests 55 | 56 | test: ## run tests quickly with the default Python 57 | python setup.py test 58 | 59 | test-all: ## run tests on every Python version with tox 60 | tox 61 | 62 | coverage: ## check code coverage quickly with the default Python 63 | coverage run --source whitebox setup.py test 64 | coverage report -m 65 | coverage html 66 | $(BROWSER) htmlcov/index.html 67 | 68 | docs: ## generate Sphinx HTML documentation, including API docs 69 | rm -f docs/whitebox.rst 70 | rm -f docs/modules.rst 71 | sphinx-apidoc -o docs/ whitebox 72 | $(MAKE) -C docs clean 73 | $(MAKE) -C docs html 74 | $(BROWSER) docs/_build/html/index.html 75 | 76 | servedocs: docs ## compile the docs watching for changes 77 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 78 | 79 | release: dist ## package and upload a release 80 | twine upload dist/* 81 | 82 | dist: clean ## builds source and wheel package 83 | python setup.py sdist 84 | python setup.py bdist_wheel 85 | ls -l dist 86 | 87 | install: clean ## install the package to the active Python's site-packages 88 | python setup.py install 89 | -------------------------------------------------------------------------------- /whitebox/example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | This module provides examples for calling tools/functions in WhiteboxTools library 4 | Only works for Python 3.x 5 | Source: https://jblindsay.github.io/ghrg/WhiteboxTools 6 | GitHub: https://github.com/jblindsay/whitebox-tools 7 | ''' 8 | 9 | import os 10 | import sys 11 | from whitebox_tools import WhiteboxTools 12 | 13 | 14 | if __name__ == '__main__': 15 | try: 16 | wbt = WhiteboxTools() 17 | 18 | root_dir = os.path.dirname(os.path.abspath(__file__)) 19 | # exe_dir = os.path.join(root_dir, "WBT") 20 | exe_dir = os.path.dirname(os.path.abspath(__file__)) 21 | 22 | wbt.set_whitebox_dir(exe_dir) 23 | wbt.work_dir = os.path.join(root_dir, "testdata") 24 | wbt.verbose = False 25 | 26 | # Prints the whitebox-tools version 27 | print("\nVersion information: {}".format(wbt.version())) 28 | # Prints the whitebox-tools license 29 | print(wbt.license()) 30 | # Prints the whitebox-tools help...a listing of available commands 31 | print(wbt.help()) 32 | # List all available tools in whitebox-tools 33 | # Print the help for a specific tool. 34 | print(wbt.tool_help("breach_depressions")) 35 | 36 | # print("ALl available tools: {}\n".format(wbt.list_tools())) 37 | all_tools = wbt.list_tools() 38 | print("\nAll Available Tools:") 39 | for index, tool in enumerate(all_tools): 40 | print( 41 | "{} {}: {} ...".format( 42 | str(index + 1).zfill(3), tool, all_tools[tool][:45] 43 | ) 44 | ) 45 | 46 | # Lists tools with 'lidar' or 'LAS' in tool name or description. 47 | lidar_tools = wbt.list_tools(['lidar', 'LAS']) 48 | print("\nAvailable LiDAR Tools:") 49 | for index, tool in enumerate(lidar_tools): 50 | print( 51 | "{} {}: {} ...".format( 52 | str(index + 1).zfill(3), tool, all_tools[tool][:45] 53 | ) 54 | ) 55 | # print("lidar tools: {}\n".format(wbt.list_tools(['lidar', 'LAS']))) 56 | 57 | # Notice that tool names within WhiteboxTools.exe are CamelCase but 58 | # you can also use snake_case here, e.g. print(wbt.tool_help("breach_depressions")) 59 | 60 | # Call some tools, do some work 61 | wbt.feature_preserving_smoothing("DEM.tif", "smoothed.tif", filter=9) 62 | wbt.breach_depressions("smoothed.tif", "breached.tif") 63 | wbt.d_inf_flow_accumulation("breached.tif", "flow_accum.tif") 64 | 65 | except: 66 | print("Unexpected error:", sys.exc_info()[0]) 67 | raise 68 | # For 'permission denied', you need to ensure that whitebox_tools has executable permission 69 | # cd /path/to/folder/WBT" 70 | # chmod 755 whitebox_tools" 71 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Contributing 5 | ============ 6 | 7 | Contributions are welcome, and they are greatly appreciated! Every little bit 8 | helps, and credit will always be given. 9 | 10 | You can contribute in many ways: 11 | 12 | Types of Contributions 13 | ---------------------- 14 | 15 | Report Bugs 16 | ~~~~~~~~~~~ 17 | 18 | Report bugs at https://github.com/opengeos/whitebox-python/issues. 19 | 20 | If you are reporting a bug, please include: 21 | 22 | * Your operating system name and version. 23 | * Any details about your local setup that might be helpful in troubleshooting. 24 | * Detailed steps to reproduce the bug. 25 | 26 | Fix Bugs 27 | ~~~~~~~~ 28 | 29 | Look through the GitHub issues for bugs. Anything tagged with "bug" and "help 30 | wanted" is open to whoever wants to implement it. 31 | 32 | Implement Features 33 | ~~~~~~~~~~~~~~~~~~ 34 | 35 | Look through the GitHub issues for features. Anything tagged with "enhancement" 36 | and "help wanted" is open to whoever wants to implement it. 37 | 38 | Write Documentation 39 | ~~~~~~~~~~~~~~~~~~~ 40 | 41 | whitebox could always use more documentation, whether as part of the 42 | official whitebox docs, in docstrings, or even on the web in blog posts, 43 | articles, and such. 44 | 45 | Submit Feedback 46 | ~~~~~~~~~~~~~~~ 47 | 48 | The best way to send feedback is to file an issue at https://github.com/opengeos/whitebox-python/issues. 49 | 50 | If you are proposing a feature: 51 | 52 | * Explain in detail how it would work. 53 | * Keep the scope as narrow as possible, to make it easier to implement. 54 | * Remember that this is a volunteer-driven project, and that contributions 55 | are welcome :) 56 | 57 | Get Started! 58 | ------------ 59 | 60 | Ready to contribute? Here's how to set up `whitebox` for local development. 61 | 62 | 1. Fork the `whitebox` repo on GitHub. 63 | 2. Clone your fork locally:: 64 | 65 | $ git clone git@github.com:your_name_here/whitebox.git 66 | 67 | 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: 68 | 69 | $ mkvirtualenv whitebox 70 | $ cd whitebox/ 71 | $ python setup.py develop 72 | 73 | 4. Create a branch for local development:: 74 | 75 | $ git checkout -b name-of-your-bugfix-or-feature 76 | 77 | Now you can make your changes locally. 78 | 79 | 5. When you're done making changes, check that your changes pass flake8 and the 80 | tests, including testing other Python versions with tox:: 81 | 82 | $ flake8 whitebox tests 83 | $ python setup.py test or py.test 84 | $ tox 85 | 86 | To get flake8 and tox, just pip install them into your virtualenv. 87 | 88 | 6. Commit your changes and push your branch to GitHub:: 89 | 90 | $ git add . 91 | $ git commit -m "Your detailed description of your changes." 92 | $ git push origin name-of-your-bugfix-or-feature 93 | 94 | 7. Submit a pull request through the GitHub website. 95 | 96 | Pull Request Guidelines 97 | ----------------------- 98 | 99 | Before you submit a pull request, check that it meets these guidelines: 100 | 101 | 1. The pull request should include tests. 102 | 2. If the pull request adds functionality, the docs should be updated. Put 103 | your new functionality into a function with a docstring, and add the 104 | feature to the list in README.rst. 105 | 106 | Tips 107 | ---- 108 | 109 | To run a subset of tests:: 110 | 111 | 112 | $ python -m unittest tests.test_whitebox 113 | 114 | Deploying 115 | --------- 116 | 117 | A reminder for the maintainers on how to deploy. 118 | Make sure all your changes are committed (including an entry in HISTORY.rst). 119 | Then run:: 120 | 121 | $ bumpversion patch # possible: major / minor / patch 122 | $ git push 123 | $ git push --tags 124 | 125 | Travis will then deploy to PyPI if tests pass. 126 | -------------------------------------------------------------------------------- /whitebox/automation.py: -------------------------------------------------------------------------------- 1 | ################################################################## 2 | # Steps for updating the whitebox Python package 3 | # Step 1 - Delete the existing develop branch: git branch -D develop 4 | # Step 2 - Create a new develop branch: git checkout -b develop 5 | # Step 3 - Delete the old WhiteboxTools_linux_amd64.zip if needed 6 | # Step 4 - Run automation.py 7 | # Step 5 - Create a conda environment: conda create -n wbt python 8 | # Step 6 - Install dependencies: pip install -r requirements_dev.txt 9 | # Step 7 - Install whitebox: pip install -e . 10 | # Step 8 - Run example.py 11 | # Step 9 - Commit and push changes 12 | # Step 10 - Merge pull request on GitHub 13 | # Step 11 - Switch to master branch and pull updates: git checkout master | git pull 14 | # Step 12 - Update version number: bumpversion patch/minor/major | git push --tags | git push 15 | # Step 13 - Create package: python setup.py sdist 16 | # Step 14 - Upload package to PyPI: twine upload dist/whitebox-*.*.*.tar.gz 17 | ################################################################## 18 | 19 | import os 20 | import shutil 21 | import zipfile 22 | import urllib.request 23 | 24 | linux_zip = "WhiteboxTools_linux_amd64.zip" 25 | work_dir = os.path.dirname(__file__) 26 | zip_path = os.path.join(work_dir, linux_zip) 27 | WBT_dir = os.path.join(work_dir, "WBT") 28 | init_img_dir = os.path.join(WBT_dir, "img") 29 | new_img_dir = os.path.join(work_dir, "img") 30 | init_plugin_dir = os.path.join(WBT_dir, "plugins") 31 | new_plugin_dir = os.path.join(work_dir, "plugins") 32 | 33 | if not os.path.exists(zip_path): 34 | print("Downloading WhiteboxTools binary ...") 35 | # url = "https://github.com/opengeos/whitebox-bin/raw/master/WhiteboxTools_linux_amd64.zip" 36 | url = "https://www.whiteboxgeo.com/WBT_Linux/WhiteboxTools_linux_amd64.zip" 37 | urllib.request.urlretrieve(url, zip_path) # Download WhiteboxTools 38 | else: 39 | print("WhiteboxTools binary already exists.") 40 | 41 | if os.path.exists(WBT_dir): 42 | shutil.rmtree(WBT_dir) 43 | 44 | print("Decompressing {} ...".format(linux_zip)) 45 | with zipfile.ZipFile(zip_path, "r") as tar_ref: 46 | tar_ref.extractall(work_dir) 47 | 48 | zip_dir = os.path.join(work_dir, linux_zip.split(".")[0]) 49 | src_dir = os.path.join(zip_dir, "WBT") 50 | shutil.move(src_dir, WBT_dir) 51 | 52 | if os.path.exists(new_img_dir): 53 | shutil.rmtree(new_img_dir) 54 | 55 | if os.path.exists(new_plugin_dir): 56 | shutil.rmtree(new_plugin_dir) 57 | 58 | if os.path.exists(zip_dir): 59 | shutil.rmtree(zip_dir) 60 | 61 | shutil.copytree(init_img_dir, new_img_dir) 62 | shutil.copytree(init_plugin_dir, new_plugin_dir) 63 | 64 | 65 | # print("Generating wb_runner.py ...") 66 | # with open(os.path.join(WBT_dir, "wb_runner.py")) as f_runner: 67 | # lines = f_runner.readlines() 68 | # for index, line in enumerate(lines): 69 | # if line.strip() == "from whitebox_tools import WhiteboxTools, to_camelcase": 70 | # line = "from .whitebox_tools import WhiteboxTools, to_camelcase\n" 71 | # lines[index] = line 72 | # # print("{}: {}".format(index, line)) 73 | # elif line.strip() == "def main():": 74 | # line = "def Runner():\n" 75 | # lines[index] = line 76 | # # print("{}: {}".format(index, line)) 77 | # elif line.strip() == "main()": 78 | # line = " Runner()\n" 79 | # lines[index] = line 80 | # # print("{}: {}".format(index, line)) 81 | 82 | # runner_path = os.path.join(work_dir, "wb_runner.py") 83 | # if os.path.exists(runner_path): 84 | # os.remove(runner_path) 85 | 86 | # with open(runner_path, "w") as f_runner_w: 87 | # f_runner_w.writelines(lines) 88 | 89 | 90 | wbt_path = os.path.join(work_dir, "whitebox_tools.py") 91 | if os.path.exists(wbt_path): 92 | os.remove(wbt_path) 93 | 94 | f = open(wbt_path, "w") 95 | 96 | print("Generating whitebox_tools.py ...") 97 | with open(os.path.join(WBT_dir, "whitebox_tools.py")) as f_wbt: 98 | lines = f_wbt.readlines() 99 | for index, line in enumerate(lines): 100 | if line.strip() == "os.chdir(self.exe_path)": 101 | f.write(" work_dir = os.getcwd()\n") 102 | f.write(line) 103 | 104 | if line.strip() == "from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW": 105 | with open(os.path.join(work_dir, "download_wbt.py")) as f_dl: 106 | dl_lines = f_dl.readlines() 107 | f.write("\n") 108 | f.writelines(dl_lines) 109 | elif line.strip() == "self.__max_procs = -1": 110 | f.write(" download_wbt()\n") 111 | 112 | if line.strip() in ["return 1", "return err"]: 113 | f.write(" finally:\n") 114 | f.write(" os.chdir(work_dir)\n") 115 | 116 | 117 | shutil.move( 118 | os.path.join(WBT_dir, "whitebox_tools"), os.path.join(work_dir, "whitebox_tools") 119 | ) 120 | 121 | # shutil.move( 122 | # os.path.join(WBT_dir, "whitebox_runner"), os.path.join(work_dir, "whitebox_runner") 123 | # ) 124 | 125 | f.close() 126 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # whitebox documentation build configuration file, created by 5 | # sphinx-quickstart on Fri Jun 9 13:47:02 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another 17 | # directory, add these directories to sys.path here. If the directory is 18 | # relative to the documentation root, use os.path.abspath to make it 19 | # absolute, like shown here. 20 | # 21 | import os 22 | import sys 23 | 24 | sys.path.insert(0, os.path.abspath('..')) 25 | 26 | import whitebox 27 | 28 | # -- General configuration --------------------------------------------- 29 | 30 | # If your documentation needs a minimal Sphinx version, state it here. 31 | # 32 | # needs_sphinx = '1.0' 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be 35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 36 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ['_templates'] 40 | 41 | # The suffix(es) of source filenames. 42 | # You can specify multiple suffix as a list of string: 43 | # 44 | # source_suffix = ['.rst', '.md'] 45 | source_suffix = '.rst' 46 | 47 | # The master toctree document. 48 | master_doc = 'index' 49 | 50 | # General information about the project. 51 | project = u'whitebox' 52 | copyright = u"2018, Qiusheng Wu" 53 | author = u"Qiusheng Wu" 54 | 55 | # The version info for the project you're documenting, acts as replacement 56 | # for |version| and |release|, also used in various other places throughout 57 | # the built documents. 58 | # 59 | # The short X.Y version. 60 | version = whitebox.__version__ 61 | # The full version, including alpha/beta/rc tags. 62 | release = whitebox.__version__ 63 | 64 | # The language for content autogenerated by Sphinx. Refer to documentation 65 | # for a list of supported languages. 66 | # 67 | # This is also used if you do content translation via gettext catalogs. 68 | # Usually you set "language" from the command line for these cases. 69 | language = None 70 | 71 | # List of patterns, relative to source directory, that match files and 72 | # directories to ignore when looking for source files. 73 | # This patterns also effect to html_static_path and html_extra_path 74 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 75 | 76 | # The name of the Pygments (syntax highlighting) style to use. 77 | pygments_style = 'sphinx' 78 | 79 | # If true, `todo` and `todoList` produce output, else they produce nothing. 80 | todo_include_todos = False 81 | 82 | 83 | # -- Options for HTML output ------------------------------------------- 84 | 85 | # The theme to use for HTML and HTML Help pages. See the documentation for 86 | # a list of builtin themes. 87 | # 88 | # html_theme = 'alabaster' 89 | 90 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 91 | 92 | if not on_rtd: # only import and set the theme if we're building docs locally 93 | import sphinx_rtd_theme 94 | 95 | html_theme = 'sphinx_rtd_theme' 96 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 97 | 98 | html_context = {'css_files': ['_static/theme_overrides.css']} 99 | else: 100 | html_context = { 101 | 'css_files': [ 102 | '//media.readthedocs.org/css/sphinx_rtd_theme.css', 103 | '//media.readthedocs.org/css/readthedocs-doc-embed.css', 104 | '_static/theme_overrides.css', 105 | ] 106 | } 107 | 108 | # Theme options are theme-specific and customize the look and feel of a 109 | # theme further. For a list of options available for each theme, see the 110 | # documentation. 111 | # 112 | # html_theme_options = {} 113 | 114 | # Add any paths that contain custom static files (such as style sheets) here, 115 | # relative to this directory. They are copied after the builtin static files, 116 | # so a file named "default.css" will overwrite the builtin "default.css". 117 | html_static_path = ['_static'] 118 | 119 | 120 | # -- Options for HTMLHelp output --------------------------------------- 121 | 122 | # Output file base name for HTML help builder. 123 | htmlhelp_basename = 'whiteboxdoc' 124 | 125 | 126 | # -- Options for LaTeX output ------------------------------------------ 127 | 128 | latex_elements = { 129 | # The paper size ('letterpaper' or 'a4paper'). 130 | # 131 | # 'papersize': 'letterpaper', 132 | # The font size ('10pt', '11pt' or '12pt'). 133 | # 134 | # 'pointsize': '10pt', 135 | # Additional stuff for the LaTeX preamble. 136 | # 137 | # 'preamble': '', 138 | # Latex figure (float) alignment 139 | # 140 | # 'figure_align': 'htbp', 141 | } 142 | 143 | # Grouping the document tree into LaTeX files. List of tuples 144 | # (source start file, target name, title, author, documentclass 145 | # [howto, manual, or own class]). 146 | latex_documents = [ 147 | (master_doc, 'whitebox.tex', u'whitebox Documentation', u'Qiusheng Wu', 'manual'), 148 | ] 149 | 150 | 151 | # -- Options for manual page output ------------------------------------ 152 | 153 | # One entry per manual page. List of tuples 154 | # (source start file, name, description, authors, manual section). 155 | man_pages = [(master_doc, 'whitebox', u'whitebox Documentation', [author], 1)] 156 | 157 | 158 | # -- Options for Texinfo output ---------------------------------------- 159 | 160 | # Grouping the document tree into Texinfo files. List of tuples 161 | # (source start file, target name, title, author, 162 | # dir menu entry, description, category) 163 | texinfo_documents = [ 164 | ( 165 | master_doc, 166 | 'whitebox', 167 | u'whitebox Documentation', 168 | author, 169 | 'whitebox', 170 | 'One line description of project.', 171 | 'Miscellaneous', 172 | ), 173 | ] 174 | -------------------------------------------------------------------------------- /whitebox/whitebox_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' This module provides examples of how to call the whitebox_tool script and the 3 | whitebox-tools geospatial analysis library using Python code. 4 | ''' 5 | 6 | # This script is part of the WhiteboxTools geospatial library. 7 | # Authors: Dr. John Lindsay 8 | # Created: November 28, 2017 9 | # Last Modified: Feb. 17, 2018 10 | # License: MIT 11 | 12 | from __future__ import print_function 13 | import os 14 | import sys 15 | from whitebox_tools import WhiteboxTools 16 | import urllib.request 17 | 18 | 19 | def main(): 20 | '''main function''' 21 | try: 22 | wbt = WhiteboxTools() 23 | 24 | # Get the root directory of WhiteboxTools source code or executable file 25 | root_dir = os.path.dirname(os.path.abspath(__file__)) 26 | # WhiteboxTools executable file name for MS Windows 27 | wbt_win_bin = os.path.join(root_dir, "whitebox_tools.exe") 28 | # WhiteboxTools executable file name for MacOS/Linux 29 | wbt_linux_bin = os.path.join(root_dir, "whitebox_tools") 30 | 31 | # If the WhiteboxTools executable file (whitbox_tools.exe) is in the same 32 | # directory as this script, set wbt path to the current directory 33 | # otherwise, set wbt path to (root_dir + "/target/release/") 34 | if os.path.isfile(wbt_win_bin) or os.path.isfile(wbt_linux_bin): 35 | wbt.set_whitebox_dir(root_dir) 36 | else: 37 | # or simply wbt.exe_path = ... 38 | wbt.set_whitebox_dir(root_dir + "/target/release/") 39 | 40 | # Set the working directory. This is the path to the folder containing the data, 41 | # i.e. files sent to tools as input/output parameters. You don't need to set 42 | # the working directory if you specify full path names as tool parameters. 43 | wbt.work_dir = os.path.dirname(os.path.abspath(__file__)) + "/testdata/" 44 | 45 | # If test datasets do not exist, download them from the WhiteboxTools repo 46 | if not os.path.exists(wbt.work_dir): 47 | os.mkdir(wbt.work_dir) 48 | dem_url = "https://github.com/jblindsay/whitebox-tools/raw/master/testdata/DEM.tif" 49 | dep_url = "https://github.com/jblindsay/whitebox-tools/raw/master/testdata/DEM.dep" 50 | urllib.request.urlretrieve(dem_url, "testdata/DEM.tif") 51 | urllib.request.urlretrieve(dep_url, "testdata/DEM.dep") 52 | 53 | # Sets verbose mode (True or False). Most tools will suppress output (e.g. updating 54 | # progress) when verbose mode is False. The default is True 55 | # wbt.set_verbose_mode(False) # or simply, wbt.verbose = False 56 | 57 | # The most convenient way to run a tool is to use its associated method, e.g.: 58 | if wbt.elev_percentile("DEM.tif", "output.tif", 15, 15) != 0: 59 | print("ERROR running tool") 60 | 61 | # You may also provide an optional custom callback for processing output from the 62 | # tool. If you don't provide a callback, and verbose is set to True, tool output 63 | # will simply be printed to the standard output. Also, notice that each tool has a 64 | # convenience method. While internally, whitebox_tools.exe uses CamelCase (MeanFilter) 65 | # to denote tool names, but the Python interface of whitebox_tools.py uses 66 | # snake_case (mean_filter), according to Python style conventions. 67 | 68 | # All of the convenience methods just call the 'run_tool' method, feeding it an 69 | # args array. This is an alternative way of calling tools: 70 | tool_name = "elev_percentile" 71 | args = ["--dem=\"DEM.dep\"", "--output=\"DEV_101.dep\"", "--filterx=101"] 72 | 73 | if wbt.run_tool(tool_name, args, my_callback) != 0: 74 | print("ERROR running {}".format(tool_name)) 75 | 76 | # Prints the whitebox-tools help...a listing of available commands 77 | print(wbt.help()) 78 | 79 | # Prints the whitebox-tools license 80 | print(wbt.license()) 81 | 82 | # Prints the whitebox-tools version 83 | print("Version information: {}".format(wbt.version())) 84 | 85 | # List all available tools in whitebox-tools 86 | print(wbt.list_tools()) 87 | 88 | # Lists tools with 'lidar' or 'LAS' in tool name or description. 89 | print(wbt.list_tools(['lidar', 'LAS'])) 90 | 91 | # Print the help for a specific tool. 92 | print(wbt.tool_help("ElevPercentile")) 93 | # Notice that tool names within WhiteboxTools.exe are CamelCase but 94 | # you can also use snake_case here, e.g. print(wbt.tool_help("elev_percentile")) 95 | 96 | except: 97 | print("Unexpected error:", sys.exc_info()[0]) 98 | raise 99 | 100 | 101 | def my_callback(out_str): 102 | '''Create a custom callback to process the text coming out of the tool. 103 | If a callback is not provided, it will simply print the output stream. 104 | A custom callback allows for processing of the output stream. 105 | ''' 106 | try: 107 | if not hasattr(my_callback, 'prev_line_progress'): 108 | my_callback.prev_line_progress = False 109 | if "%" in out_str: 110 | str_array = out_str.split(" ") 111 | label = out_str.replace(str_array[len(str_array) - 1], "").strip() 112 | progress = int(str_array[len(str_array) - 1].replace("%", "").strip()) 113 | if my_callback.prev_line_progress: 114 | print('{0} {1}%'.format(label, progress), end="\r") 115 | else: 116 | my_callback.prev_line_progress = True 117 | print(out_str) 118 | elif "error" in out_str.lower(): 119 | print("ERROR: {}".format(out_str)) 120 | my_callback.prev_line_progress = False 121 | elif "elapsed time (excluding i/o):" in out_str.lower(): 122 | elapsed_time = ''.join( 123 | ele for ele in out_str if ele.isdigit() or ele == '.' 124 | ) 125 | units = ( 126 | out_str.lower() 127 | .replace("elapsed time (excluding i/o):", "") 128 | .replace(elapsed_time, "") 129 | .strip() 130 | ) 131 | print("Elapsed time: {0}{1}".format(elapsed_time, units)) 132 | my_callback.prev_line_progress = False 133 | else: 134 | if my_callback.prev_line_progress: 135 | print('\n{0}'.format(out_str)) 136 | my_callback.prev_line_progress = False 137 | else: 138 | print(out_str) 139 | 140 | except: 141 | print(out_str) 142 | 143 | 144 | main() 145 | -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_box_only.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | 60 | 66 | 84 | 93 | 102 | 111 | 120 | 129 | 138 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | 60 | 66 | 84 | 93 | 102 | 111 | 120 | 129 | 138 | 147 | 148 | WhiteboxTools 163 | TM 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /whitebox/img/WhiteboxToolsLogo_vert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 57 | 60 | 66 | 84 | 93 | 102 | 111 | 120 | 129 | 138 | 147 | 148 | 151 | WhiteboxTools 166 | TM 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /whitebox/download_wbt.py: -------------------------------------------------------------------------------- 1 | def download_wbt(linux_musl=False, reset=False, verbose=True): 2 | """Downloads WhiteboxTools pre-complied binary for first-time use 3 | 4 | Args: 5 | linux_musl (bool, optional): Whether to download the musl version of WhiteboxTools for Linux. Defaults to False. 6 | reset (bool, optional): Whether to reset the WhiteboxTools installation. Defaults to False. 7 | verbose (bool, optional): Whether to print verbose messages. Defaults to True. 8 | 9 | """ 10 | import glob 11 | import os 12 | import sys 13 | import platform 14 | import zipfile 15 | import tarfile 16 | import shutil 17 | import urllib.request 18 | import importlib.resources 19 | import webbrowser 20 | 21 | if os.environ.get("WBT_PATH", None) is not None: 22 | return 23 | 24 | # print("Your operating system: {}".format(platform.system())) 25 | package_name = "whitebox" 26 | # Get package directory 27 | pkg_dir = os.path.dirname( 28 | importlib.resources.files(package_name) / "whitebox_tools.py" 29 | ) 30 | 31 | exe_dir = os.path.join( 32 | pkg_dir, "WBT" 33 | ) # Get directory of WhiteboxTools executable file 34 | work_dir = os.path.join(pkg_dir, "testdata") # Set working directory 35 | init_img_dir = os.path.join(exe_dir, "img") 36 | new_img_dir = os.path.join(pkg_dir, "img") 37 | init_plugin_dir = os.path.join(exe_dir, "plugins") 38 | new_plugin_dir = os.path.join(pkg_dir, "plugins") 39 | 40 | links = { 41 | "Windows": "https://www.whiteboxgeo.com/WBT_Windows/WhiteboxTools_win_amd64.zip", 42 | "Darwin": "https://www.whiteboxgeo.com/WBT_Darwin/WhiteboxTools_darwin_amd64.zip", 43 | "Darwin-arm": "https://www.whiteboxgeo.com/WBT_Darwin/WhiteboxTools_darwin_m_series.zip", 44 | "Linux": "https://www.whiteboxgeo.com/WBT_Linux/WhiteboxTools_linux_amd64.zip", 45 | "Linux-musl": "https://www.whiteboxgeo.com/WBT_Linux/WhiteboxTools_linux_musl.zip", 46 | } 47 | 48 | if ( 49 | linux_musl 50 | or ("google.colab" in sys.modules) 51 | or (os.environ.get("WBT_LINUX", False) == "MUSL") 52 | ): 53 | links["Linux"] = links["Linux-musl"] 54 | 55 | if platform.system() == "Darwin" and platform.processor() == "arm": 56 | links["Darwin"] = links["Darwin-arm"] 57 | 58 | # These are backup links only used to pass GitHub automated tests. WhiteboxGeo links frequently encounter timeout errors, which fail the automated tests. 59 | backup_links = { 60 | "Windows": "https://github.com/giswqs/whitebox-bin/raw/master/WhiteboxTools_win_amd64.zip", 61 | "Darwin": "https://github.com/giswqs/whitebox-bin/raw/master/WhiteboxTools_darwin_amd64.zip", 62 | "Linux": "https://github.com/giswqs/whitebox-bin/raw/master/WhiteboxTools_linux_amd64.zip", 63 | } 64 | 65 | try: 66 | if reset: 67 | if os.path.exists(exe_dir): 68 | shutil.rmtree(exe_dir) 69 | 70 | if not os.path.exists( 71 | exe_dir 72 | ): # Download WhiteboxTools executable file if non-existent 73 | if verbose: 74 | print( 75 | "Downloading WhiteboxTools pre-compiled binary for first time use ..." 76 | ) 77 | if platform.system() in links.keys(): 78 | url = links[platform.system()] 79 | 80 | else: 81 | print( 82 | "WhiteboxTools is not yet supported on {}!".format( 83 | platform.system() 84 | ) 85 | ) 86 | exit() 87 | 88 | zip_name = os.path.join( 89 | pkg_dir, os.path.basename(url) 90 | ) # Get WhiteboxTools zip file name 91 | # Get downloaded zip file extension 92 | zip_ext = os.path.splitext(zip_name)[1] 93 | # Download WhiteboxTools 94 | try: 95 | request = urllib.request.urlopen(url, timeout=500) 96 | print("Downloading WhiteboxTools binary from {}".format(url)) 97 | except urllib.error.URLError as e: 98 | print(e) 99 | print("Trying backup link ...") 100 | url = backup_links[platform.system()] 101 | print("Downloading WhiteboxTools binary from {}".format(url)) 102 | request = urllib.request.urlopen(url, timeout=500) 103 | 104 | with open(zip_name, "wb") as f: 105 | f.write(request.read()) 106 | 107 | if verbose: 108 | print("Decompressing {} ...".format(os.path.basename(url))) 109 | if zip_ext == ".zip": # Decompress Windows/Mac OS zip file 110 | with zipfile.ZipFile(zip_name, "r") as zip_ref: 111 | zip_ref.extractall(pkg_dir) 112 | else: # Decompress Linux tar file 113 | with tarfile.open(zip_name, "r") as tar_ref: 114 | 115 | def is_within_directory(directory, target): 116 | abs_directory = os.path.abspath(directory) 117 | abs_target = os.path.abspath(target) 118 | 119 | prefix = os.path.commonprefix([abs_directory, abs_target]) 120 | 121 | return prefix == abs_directory 122 | 123 | def safe_extract( 124 | tar, path=".", members=None, *, numeric_owner=False 125 | ): 126 | for member in tar.getmembers(): 127 | member_path = os.path.join(path, member.name) 128 | if not is_within_directory(path, member_path): 129 | raise Exception("Attempted Path Traversal in Tar File") 130 | 131 | tar.extractall(path, members, numeric_owner=numeric_owner) 132 | 133 | safe_extract(tar_ref, pkg_dir) 134 | if verbose: 135 | print("WhiteboxTools package directory: {}".format(pkg_dir)) 136 | 137 | zip_dir = os.path.join( 138 | pkg_dir, os.path.basename(zip_name).replace(".zip", "") 139 | ).replace("musl", "amd64") 140 | src_dir = os.path.join(zip_dir, "WBT") 141 | 142 | if os.path.exists(src_dir): 143 | shutil.move(src_dir, pkg_dir) 144 | 145 | if os.path.exists(new_img_dir): 146 | shutil.rmtree(new_img_dir) 147 | if os.path.exists(new_plugin_dir): 148 | shutil.rmtree(new_plugin_dir) 149 | if os.path.exists(new_plugin_dir): 150 | shutil.rmtree(new_plugin_dir) 151 | 152 | if os.path.exists(init_img_dir): 153 | shutil.copytree(init_img_dir, new_img_dir) 154 | 155 | if os.path.exists(init_plugin_dir): 156 | shutil.copytree(init_plugin_dir, new_plugin_dir) 157 | 158 | if os.path.exists(zip_dir): 159 | shutil.rmtree(zip_dir) 160 | exe_ext = "" # file extension for MacOS/Linux 161 | if platform.system() == "Windows": 162 | exe_ext = ".exe" 163 | exe_name = "whitebox_tools{}".format(exe_ext) 164 | exe_path = os.path.join(exe_dir, exe_name) 165 | runner_name = "whitebox_runner{}".format(exe_ext) 166 | runner_path = os.path.join(exe_dir, runner_name) 167 | 168 | # grant executable permission 169 | if platform.system() != "Windows": 170 | os.system("chmod 755 " + exe_path) 171 | if os.path.exists(runner_path): 172 | os.system("chmod 755 " + runner_path) 173 | plugins = list( 174 | set(glob.glob(os.path.join(new_plugin_dir, "*"))) 175 | - set(glob.glob(os.path.join(new_plugin_dir, "*.json"))) 176 | ) 177 | if platform.system() != "Windows": 178 | for plugin in plugins: 179 | os.system("chmod 755 " + plugin) 180 | 181 | exe_path_new = os.path.join(pkg_dir, exe_name) 182 | shutil.copy(exe_path, exe_path_new) 183 | runner_path_new = os.path.join(pkg_dir, runner_name) 184 | if os.path.exists(runner_path): 185 | shutil.copy(runner_path, runner_path_new) 186 | 187 | try: 188 | os.remove(zip_name) 189 | except: 190 | pass 191 | 192 | # # The official WhiteboxTools Linux binary from whiteboxgeo.com requires GLIBC 2.29, 193 | # # which is incompatible with Google Colab that uses GLIBC 2.27. The following code 194 | # # downloads the binary that is compatible with Google Colab. 195 | if "google.colab" in sys.modules: 196 | # url = "https://github.com/giswqs/whitebox-bin/raw/master/WhiteboxTools_ubuntu_18.04.zip" 197 | url = ( 198 | "https://www.whiteboxgeo.com/WBT_Linux/WhiteboxTools_linux_musl.zip" 199 | ) 200 | 201 | zip_name = os.path.join(pkg_dir, os.path.basename(url)) 202 | try: 203 | request = urllib.request.urlopen(url, timeout=500) 204 | with open(zip_name, "wb") as f: 205 | f.write(request.read()) 206 | os.remove(exe_path) 207 | with zipfile.ZipFile(zip_name, "r") as zip_ref: 208 | zip_ref.extractall(pkg_dir) 209 | os.system("chmod 755 " + exe_path) 210 | plugins = list( 211 | set(glob.glob(os.path.join(new_plugin_dir, "*"))) 212 | - set(glob.glob(os.path.join(new_plugin_dir, "*.json"))) 213 | ) 214 | for plugin in plugins: 215 | os.system("chmod 755 " + plugin) 216 | except Exception as e: 217 | print(e) 218 | 219 | webbrowser.open("https://www.whiteboxgeo.com/", new=2) 220 | 221 | if not os.path.exists(work_dir): 222 | if verbose: 223 | print("Downloading testdata ...") 224 | os.mkdir(work_dir) 225 | dem_url = "https://github.com/opengeos/whitebox-python/raw/master/examples/testdata/DEM.tif" 226 | dep_url = "https://github.com/opengeos/whitebox-python/raw/master/examples/testdata/DEM.dep" 227 | urllib.request.urlretrieve(dem_url, os.path.join(work_dir, "DEM.tif")) 228 | urllib.request.urlretrieve(dep_url, os.path.join(work_dir, "DEM.dep")) 229 | 230 | except: 231 | print("Unexpected error:", sys.exc_info()[0]) 232 | raise 233 | 234 | 235 | if __name__ == "__main__": 236 | download_wbt() 237 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | whitebox-python 3 | =============== 4 | 5 | .. image:: https://colab.research.google.com/assets/colab-badge.svg 6 | :target: https://colab.research.google.com/github/opengeos/whitebox-python/blob/master/examples/whitebox.ipynb 7 | 8 | .. image:: https://mybinder.org/badge_logo.svg 9 | :target: https://gishub.org/whitebox-cloud 10 | 11 | .. image:: https://img.shields.io/pypi/v/whitebox.svg 12 | :target: https://pypi.python.org/pypi/whitebox 13 | 14 | .. image:: https://pepy.tech/badge/whitebox 15 | :target: https://pepy.tech/project/whitebox 16 | 17 | .. image:: https://anaconda.org/conda-forge/whitebox/badges/version.svg 18 | :target: https://anaconda.org/conda-forge/whitebox 19 | 20 | .. image:: https://readthedocs.org/projects/whitebox/badge/?version=latest 21 | :target: https://whitebox.readthedocs.io/en/latest/?badge=latest 22 | :alt: Documentation Status 23 | 24 | .. image:: https://img.shields.io/badge/License-MIT-yellow.svg 25 | :target: https://opensource.org/licenses/MIT 26 | 27 | .. image:: https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-yellowgreen.svg 28 | :target: https://www.buymeacoffee.com/opengeos 29 | 30 | 31 | Important Note 32 | -------------- 33 | .. image:: https://i.imgur.com/Ic8BA7C.png 34 | 35 | This repository is related to the WhiteboxTools Python Frontend only. You can report issues to this repo if you have problems installing this Python package. If you encounter any tool functioning specific errors, please `open an issue`_ on Dr. John Lindsay's WhiteboxTools_ repo. 36 | 37 | **Links** 38 | 39 | * Authors: Dr. John Lindsay (https://jblindsay.github.io/ghrg/index.html) 40 | * Contributors: Dr. Qiusheng Wu (https://wetlands.io) 41 | * GitHub repo: https://github.com/opengeos/whitebox-python 42 | * WhiteboxTools: https://github.com/jblindsay/whitebox-tools 43 | * User Manual: https://www.whiteboxgeo.com/manual/wbt_book/intro.html 44 | * PyPI: https://pypi.org/project/whitebox/ 45 | * conda-forge: https://anaconda.org/conda-forge/whitebox 46 | * Documentation: https://whitebox.readthedocs.io 47 | * Binder: https://gishub.org/whitebox-cloud 48 | * Free software: `MIT license`_ 49 | 50 | 51 | **Contents** 52 | 53 | - `Description`_ 54 | - `Installation`_ 55 | - `whitebox Tutorials`_ 56 | - `whitebox GUI`_ 57 | - `Available Tools`_ 58 | - `Supported Data Formats`_ 59 | - `Contributing`_ 60 | - `License`_ 61 | - `Reporting Bugs`_ 62 | - `Credits`_ 63 | 64 | 65 | 66 | Description 67 | ----------- 68 | The **whitebox** Python package is built on **WhiteboxTools**, an advanced geospatial data analysis platform developed by Prof. John Lindsay (webpage_; jblindsay_) at the University of Guelph's `Geomorphometry and Hydrogeomatics Research Group`_. *WhiteboxTools* can be used to perform common geographical information systems (GIS) analysis operations, such as cost-distance analysis, distance buffering, and raster reclassification. Remote sensing and image processing tasks include image enhancement (e.g. panchromatic sharpening, contrast adjustments), image mosaicing, numerous filtering operations, simple classification (k-means), and common image transformations. *WhiteboxTools* also contains advanced tooling for spatial hydrological analysis (e.g. flow-accumulation, watershed delineation, stream network analysis, sink removal), terrain analysis (e.g. common terrain indices such as slope, curvatures, wetness index, hillshading; hypsometric analysis; multi-scale topographic position analysis), and LiDAR data processing. LiDAR point clouds can be interrogated (LidarInfo, LidarHistogram), segmented, tiled and joined, analyized for outliers, interpolated to rasters (DEMs, intensity images), and ground-points can be classified or filtered. *WhiteboxTools* is not a cartographic or spatial data visualization package; instead it is meant to serve as an analytical backend for other data visualization software, mainly GIS. 69 | 70 | 71 | Installation 72 | ------------ 73 | **whitebox** supports a variety of platforms, including Microsoft Windows, macOS, and Linux operating systems. Note that you will need to have Python 3.x installed. Python 2.x is not supported. The **whitebox** Python package can be installed using the following command: 74 | 75 | .. code:: python 76 | 77 | pip install whitebox 78 | 79 | 80 | If you have installed **whitebox** Python package before and want to upgrade to the latest version, you can use the following command: 81 | 82 | .. code:: python 83 | 84 | pip install whitebox -U 85 | 86 | 87 | It is recommended that you use a Python virtual environment (e.g., conda) to test the whitebox package. Please follow the `conda user guide`_ to install conda if necessary. Once you have conda installed, you can use Terminal or an Anaconda Prompt to create a Python virtual environment. Check `managing Python environment`_ for more information. 88 | 89 | .. code:: python 90 | 91 | conda create -n wbt python 92 | source activate wbt 93 | conda install whitebox -c conda-forge 94 | 95 | If you encounter an GLIBC errors when installing the whitebox package, you can try the following command: 96 | 97 | .. code:: python 98 | 99 | import whitebox 100 | whitebox.download_wbt(linux_musl=True, reset=True) 101 | 102 | 103 | Alternatively, you can set the environment variable ``WBT_LINUX`` to ``MUSL`` before installing the whitebox package. It will automatically download the MUSL version of WhiteboxTools. 104 | 105 | .. code:: python 106 | 107 | import os 108 | os.environ["WBT_LINUX"] = "MUSL" 109 | 110 | whitebox Tutorials 111 | ------------------ 112 | 113 | Launch the whitebox tutorial notebook directly with **mybinder.org** now: 114 | 115 | .. image:: https://mybinder.org/badge_logo.svg 116 | :target: https://gishub.org/whitebox-cloud 117 | 118 | Quick Example 119 | ============= 120 | 121 | Tool names in the **whitebox** Python package can be called either using the snake_case or CamelCase convention (e.g. *lidar_info* or *LidarInfo*). See below for an example Python script (example.py_). If you are interested in using the *WhiteboxTools* command-line program, check `WhiteboxTools Usage`_. 122 | 123 | .. code:: python 124 | 125 | import os 126 | from importlib_resources import files 127 | import whitebox 128 | 129 | wbt = whitebox.WhiteboxTools() 130 | print(wbt.version()) 131 | print(wbt.help()) 132 | 133 | # identify the sample data directory of the package 134 | data_dir = str(files("whitebox").joinpath("testdata")) 135 | 136 | wbt.set_working_dir(data_dir) 137 | wbt.verbose = False 138 | wbt.feature_preserving_smoothing("DEM.tif", "smoothed.tif", filter=9) 139 | wbt.breach_depressions("smoothed.tif", "breached.tif") 140 | wbt.d_inf_flow_accumulation("breached.tif", "flow_accum.tif") 141 | 142 | 143 | A Jupyter Notebook Tutorial for whitebox 144 | ======================================== 145 | 146 | This tutorial can be accessed in three ways: 147 | 148 | - HTML version: https://gishub.org/whitebox-html 149 | - Viewable Notebook: https://gishub.org/whitebox-notebook 150 | - Interactive Notebook: https://gishub.org/whitebox-cloud 151 | 152 | Launch this tutorial as an interactive Jupyter Notebook on the cloud - https://gishub.org/whitebox-cloud. 153 | 154 | .. image:: https://i.imgur.com/LF4UE1j.gif 155 | 156 | 157 | whitebox GUI 158 | ------------ 159 | 160 | WhiteboxTools also provides a Graphical User Interface (GUI) - **WhiteboxTools Runner**, which can be invoked using the following Python script: 161 | 162 | .. code:: python 163 | 164 | import whitebox 165 | whitebox.Runner() 166 | 167 | .. image:: https://wetlands.io/file/images/whitebox.png 168 | 169 | 170 | 171 | 172 | 173 | Troubleshooting 174 | --------------- 175 | 176 | Linux 177 | ===== 178 | When using ``import whitebox``, if you get an error that says ``No module named '_tkinter', please install the python3-tk package``, you can try the following solution: 179 | 180 | - For Ubuntu, Linux Mint, etc: ``sudo apt-get install python3-tk`` 181 | - For Manjaro, Arch Linux: ``sudo pacman -S tk`` 182 | 183 | 184 | 185 | 186 | Available Tools 187 | --------------- 188 | The library currently contains **518** tools, which are each grouped based on their main function into one of the following categories: Data Tools, GIS Analysis, Hydrological Analysis, Image Analysis, LiDAR Analysis, Mathematical and Statistical Analysis, Stream Network Analysis, and Terrain Analysis. For a listing of available tools, complete with documentation and usage details, please see the `WhiteboxTools User Manual`_. 189 | 190 | 191 | Supported Data Formats 192 | ---------------------- 193 | 194 | The WhiteboxTools library currently supports read/writing raster data in Whitebox GAT, GeoTIFF, ESRI (ArcGIS) ASCII and binary (.flt & .hdr), GRASS GIS, Idrisi, SAGA GIS (binary and ASCII), and Surfer 7 data formats. At present, there is limited ability in WhiteboxTools to read vector geospatial data. Support for Shapefile (and other common vector formats) will be enhanced within the library soon. 195 | 196 | Contributing 197 | ------------ 198 | 199 | If you would like to contribute to the project as a developer, follow these instructions to get started: 200 | 201 | 1. Fork the whitebox project (https://github.com/opengeos/whitebox-python) 202 | 2. Create your feature branch (git checkout -b my-new-feature) 203 | 3. Commit your changes (git commit -am 'Add some feature') 204 | 4. Push to the branch (git push origin my-new-feature) 205 | 5. Create a new Pull Request 206 | 207 | License 208 | ------- 209 | 210 | The **whitebox** package is distributed under the `MIT license`_, a permissive open-source (free software) license. 211 | 212 | 213 | Reporting Bugs 214 | -------------- 215 | Report bugs at https://github.com/opengeos/whitebox-python/issues. 216 | 217 | If you are reporting a bug, please include: 218 | 219 | * Your operating system name and version. 220 | * Any details about your local setup that might be helpful in troubleshooting. 221 | * Detailed steps to reproduce the bug. 222 | 223 | Credits 224 | ------- 225 | 226 | This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template. 227 | 228 | .. _Cookiecutter: https://github.com/audreyr/cookiecutter 229 | .. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage 230 | .. _example.py: https://github.com/opengeos/whitebox-python/blob/master/whitebox/example.py 231 | .. _WhiteboxTools: https://github.com/jblindsay/whitebox-tools 232 | .. _webpage: https://jblindsay.github.io/ghrg/index.html 233 | .. _jblindsay: https://github.com/jblindsay 234 | .. _`Geomorphometry and Hydrogeomatics Research Group`: https://jblindsay.github.io/ghrg/index.html 235 | .. _`conda user guide`: https://conda.io/docs/user-guide/install/index.html 236 | .. _`managing Python environment`: https://conda.io/docs/user-guide/tasks/manage-environments.html 237 | .. _`WhiteboxTools Usage`: https://github.com/jblindsay/whitebox-tools#3-usage 238 | .. _`MIT license`: https://opensource.org/licenses/MIT 239 | .. _`open an issue`: https://github.com/jblindsay/whitebox-tools/issues 240 | .. _`WhiteboxTools User Manual`: https://www.whiteboxgeo.com/manual/wbt_book/intro.html 241 | -------------------------------------------------------------------------------- /examples/whitebox.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/whitebox-python/blob/master/examples/whitebox.ipynb)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# A tutorial for the whitebox Python package\n", 16 | "\n", 17 | "This notebook demonstrates the usage of the **whitebox** Python package for geospatial analysis, which is built on a stand-alone executable command-line program called [WhiteboxTools](https://github.com/jblindsay/whitebox-tools).\n", 18 | "\n", 19 | "* GitHub repo: https://github.com/opengeos/whitebox-python\n", 20 | "* WhiteboxTools: https://github.com/jblindsay/whitebox-tools\n", 21 | "* WhiteboxGeo: https://www.whiteboxgeo.com\n", 22 | "* User Manual: https://www.whiteboxgeo.com/manual/wbt_book/intro.html\n", 23 | "* PyPI: https://pypi.org/project/whitebox/\n", 24 | "* Documentation: https://whitebox.readthedocs.io\n", 25 | "* Binder: https://gishub.org/whitebox-cloud\n", 26 | "* Free software: [MIT license](https://opensource.org/licenses/MIT)\n", 27 | "\n", 28 | "**Launch this tutorial as an interactive Jupyter Notebook on the cloud - [MyBinder.org](https://gishub.org/whitebox-cloud).**\n", 29 | "\n", 30 | "![whitebox-gif](https://i.imgur.com/LF4UE1j.gif)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## Table of Content\n", 38 | "\n", 39 | "* [Installation](#Installation)\n", 40 | "* [About whitebox](#About-whitebox)\n", 41 | "* [Getting data](#Getting-data)\n", 42 | "* [Using whitebox](#Using-whitebox)\n", 43 | "* [Displaying results](#Displaying-results)\n", 44 | "* [whitebox GUI](#whitebox-GUI)\n", 45 | "* [Citing whitebox](#Citing-whitebox)\n", 46 | "* [Credits](#Credits)\n", 47 | "* [Contact](#Contact)\n" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## Installation\n", 55 | "\n", 56 | "\n", 57 | "**whitebox** supports a variety of platforms, including Microsoft Windows, macOS, and Linux operating systems. Note that you will need to have **Python 3.x** installed. Python 2.x is not supported. The **whitebox** Python package can be installed using the following command:\n", 58 | "\n", 59 | "`pip install whitebox`\n", 60 | "\n", 61 | "If you have installed **whitebox** Python package before and want to upgrade to the latest version, you can use the following command:\n", 62 | "\n", 63 | "`pip install whitebox -U`\n", 64 | "\n", 65 | "If you encounter any installation issues, please check [Troubleshooting](https://github.com/opengeos/whitebox#troubleshooting) on the **whitebox** GitHub page and [Report Bugs](https://github.com/opengeos/whitebox#reporting-bugs)." 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "%pip install whitebox" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "## About whitebox\n", 82 | "\n", 83 | "**import whitebox and call WhiteboxTools()**" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 1, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "import whitebox\n", 93 | "\n", 94 | "wbt = whitebox.WhiteboxTools()" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "**Prints the whitebox-tools help...a listing of available commands**" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 2, 107 | "metadata": { 108 | "scrolled": true 109 | }, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "WhiteboxTools Help\n", 116 | "\n", 117 | "The following commands are recognized:\n", 118 | "--cd, --wd Changes the working directory; used in conjunction with --run flag.\n", 119 | "--compress_rasters Sets the compress_raster option in the settings.json file; determines if newly created rasters are compressed. e.g. --compress_rasters=true\n", 120 | "-h, --help Prints help information.\n", 121 | "-l, --license Prints the whitebox-tools license. Tool names may also be used, --license=\"Slope\"\n", 122 | "--listtools Lists all available tools. Keywords may also be used, --listtools slope.\n", 123 | "--max_procs Sets the maximum number of processors used. -1 = all available processors. e.g. --max_procs=2\n", 124 | "-r, --run Runs a tool; used in conjunction with --wd flag; -r=\"LidarInfo\".\n", 125 | "--toolbox Prints the toolbox associated with a tool; --toolbox=Slope.\n", 126 | "--toolhelp Prints the help associated with a tool; --toolhelp=\"LidarInfo\".\n", 127 | "--toolparameters Prints the parameters (in json form) for a specific tool; --toolparameters=\"LidarInfo\".\n", 128 | "-v Verbose mode. Without this flag, tool outputs will not be printed.\n", 129 | "--viewcode Opens the source code of a tool in a web browser; --viewcode=\"LidarInfo\".\n", 130 | "--version Prints the version information.\n", 131 | "\n", 132 | "Example Usage:\n", 133 | ">> ./whitebox_tools -r=lidar_info --cd=\"/path/to/data/\" -i=input.las --vlr --geokeys\n", 134 | "\n", 135 | "\n" 136 | ] 137 | } 138 | ], 139 | "source": [ 140 | "print(wbt.help())" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "**Prints the whitebox-tools license**" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 3, 153 | "metadata": { 154 | "scrolled": false 155 | }, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "WhiteboxTools License\n", 162 | "Copyright 2017-2023 John Lindsay\n", 163 | "\n", 164 | "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n", 165 | "associated documentation files (the \"Software\"), to deal in the Software without restriction,\n", 166 | "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\n", 167 | "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\n", 168 | "subject to the following conditions:\n", 169 | "\n", 170 | "The above copyright notice and this permission notice shall be included in all copies or substantial\n", 171 | "portions of the Software.\n", 172 | "\n", 173 | "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\n", 174 | "NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", 175 | "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n", 176 | "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n", 177 | "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", 178 | "\n" 179 | ] 180 | } 181 | ], 182 | "source": [ 183 | "print(wbt.license())" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "**Prints the whitebox-tools version**" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 4, 196 | "metadata": {}, 197 | "outputs": [ 198 | { 199 | "name": "stdout", 200 | "output_type": "stream", 201 | "text": [ 202 | "Version information: WhiteboxTools v2.4.0 (c) Dr. John Lindsay 2017-2023\n", 203 | "\n", 204 | "WhiteboxTools is an advanced geospatial data analysis platform developed at\n", 205 | "the University of Guelph's Geomorphometry and Hydrogeomatics Research \n", 206 | "Group (GHRG). See www.whiteboxgeo.com for more details.\n", 207 | "\n" 208 | ] 209 | } 210 | ], 211 | "source": [ 212 | "print(\"Version information: {}\".format(wbt.version()))" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "**Print the help for a specific tool.**" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 16, 225 | "metadata": { 226 | "scrolled": true 227 | }, 228 | "outputs": [ 229 | { 230 | "name": "stdout", 231 | "output_type": "stream", 232 | "text": [ 233 | "thread 'main' panicked at whitebox-tools-app/src/main.rs:72:21:\n", 234 | "Unrecognized tool name Conditionedlatinhypercube.\n", 235 | "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n", 236 | "\n" 237 | ] 238 | } 239 | ], 240 | "source": [ 241 | "print(wbt.tool_help(\"ConditionedLatinHypercube\"))\n", 242 | "print(wbt.tool_help(\"lidar_info\"))" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": {}, 248 | "source": [ 249 | "**Tool names in the whitebox Python package can be called either using the snake_case or CamelCase convention (e.g. lidar_info or LidarInfo). The example below uses snake_case.** " 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": null, 255 | "metadata": { 256 | "scrolled": true 257 | }, 258 | "outputs": [], 259 | "source": [ 260 | "import os\n", 261 | "from importlib_resources import files\n", 262 | "\n", 263 | "# identify the sample data directory of the package\n", 264 | "data_dir = str(files(\"whitebox\").joinpath(\"testdata\"))\n", 265 | "\n", 266 | "# set whitebox working directory\n", 267 | "wbt.set_working_dir(data_dir)\n", 268 | "wbt.verbose = False\n", 269 | "\n", 270 | "# call whiteboxtools\n", 271 | "wbt.feature_preserving_smoothing(\"DEM.tif\", \"smoothed.tif\", filter=9)\n", 272 | "wbt.breach_depressions(\"smoothed.tif\", \"breached.tif\")\n", 273 | "wbt.d_inf_flow_accumulation(\"breached.tif\", \"flow_accum.tif\")" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "**You can search tools using keywords. For example, the script below searches and lists tools with 'lidar' or 'LAS' in tool name or description.**" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "lidar_tools = wbt.list_tools(['lidar', 'LAS'])\n", 290 | "for index, tool in enumerate(lidar_tools):\n", 291 | " print(\"{} {}: {} ...\".format(str(index + 1).zfill(3), tool, lidar_tools[tool][:45]))" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "**List all available tools in whitebox-tools**. Currently, **whitebox** contains 372 tools. More tools will be added as they become available." 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": null, 304 | "metadata": {}, 305 | "outputs": [], 306 | "source": [ 307 | "all_tools = wbt.list_tools()\n", 308 | "for index, tool in enumerate(all_tools):\n", 309 | " print(\"{} {}: {} ...\".format(str(index + 1).zfill(3), tool, all_tools[tool][:45]))" 310 | ] 311 | }, 312 | { 313 | "cell_type": "markdown", 314 | "metadata": {}, 315 | "source": [ 316 | "## Getting data" 317 | ] 318 | }, 319 | { 320 | "cell_type": "markdown", 321 | "metadata": {}, 322 | "source": [ 323 | "This section demonstrates two ways to get data into Binder so that you can test **whitebox** on the cloud using your own data. \n", 324 | "\n", 325 | "* [Getting data from direct URLs](#Getting-data-from-direct-URLs) \n", 326 | "* [Getting data from Google Drive](#Getting-data-from-Google-Drive)" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "### Getting data from direct URLs\n", 334 | "\n", 335 | "If you have data hosted on your own HTTP server or GitHub, you should be able to get direct URLs. With a direct URL, users can automatically download the data when the URL is clicked. For example https://github.com/opengeos/whitebox-python/raw/master/examples/testdata.zip" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "Import the following Python libraries and start getting data from direct URLs." 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": null, 348 | "metadata": {}, 349 | "outputs": [], 350 | "source": [ 351 | "import os\n", 352 | "import zipfile\n", 353 | "import tarfile\n", 354 | "import shutil\n", 355 | "import urllib.request" 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "metadata": {}, 361 | "source": [ 362 | "Create a folder named *whitebox* under the user home folder and set it as the working directory." 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": null, 368 | "metadata": {}, 369 | "outputs": [], 370 | "source": [ 371 | "work_dir = os.path.join(os.path.expanduser(\"~\"), 'whitebox')\n", 372 | "if not os.path.exists(work_dir):\n", 373 | " os.mkdir(work_dir)\n", 374 | "os.chdir(work_dir)\n", 375 | "print(\"Working directory: {}\".format(work_dir))" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "Replace the following URL with your own direct URL hosting your data." 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": null, 388 | "metadata": {}, 389 | "outputs": [], 390 | "source": [ 391 | "url = \"https://github.com/opengeos/whitebox-python/raw/master/examples/testdata.zip\"" 392 | ] 393 | }, 394 | { 395 | "cell_type": "markdown", 396 | "metadata": {}, 397 | "source": [ 398 | "Download data the from the above URL and unzip the file if needed." 399 | ] 400 | }, 401 | { 402 | "cell_type": "code", 403 | "execution_count": null, 404 | "metadata": {}, 405 | "outputs": [], 406 | "source": [ 407 | "# download the file\n", 408 | "zip_name = os.path.basename(url)\n", 409 | "zip_path = os.path.join(work_dir, zip_name)\n", 410 | "\n", 411 | "print('Downloading {} ...'.format(zip_name))\n", 412 | "urllib.request.urlretrieve(url, zip_path)\n", 413 | "print('Downloading done.'.format(zip_name))\n", 414 | "\n", 415 | "# if it is a zip file\n", 416 | "if '.zip' in zip_name:\n", 417 | " print(\"Decompressing {} ...\".format(zip_name))\n", 418 | " with zipfile.ZipFile(zip_name, \"r\") as zip_ref:\n", 419 | " zip_ref.extractall(work_dir)\n", 420 | " print('Decompressing done.')\n", 421 | "\n", 422 | "# if it is a tar file\n", 423 | "if '.tar' in zip_name:\n", 424 | " print(\"Decompressing {} ...\".format(zip_name))\n", 425 | " with tarfile.open(zip_name, \"r\") as tar_ref:\n", 426 | " tar_ref.extractall(work_dir)\n", 427 | " print('Decompressing done.')\n", 428 | "\n", 429 | "print('Data directory: {}'.format(os.path.splitext(zip_path)[0]))" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "You have successfully downloaded data to Binder. Therefore, you can skip to [Using whitebox](#Using-whitebox) and start testing whitebox with your own data. " 437 | ] 438 | }, 439 | { 440 | "cell_type": "markdown", 441 | "metadata": {}, 442 | "source": [ 443 | "### Getting data from Google Drive\n", 444 | "\n", 445 | "Alternatively, you can upload data to [Google Drive](https://www.google.com/drive/) and then [share files publicly from Google Drive](https://support.google.com/drive/answer/2494822?co=GENIE.Platform%3DDesktop&hl=en). Once the file is shared publicly, you should be able to get a shareable URL. For example, https://drive.google.com/file/d/1xgxMLRh_jOLRNq-f3T_LXAaSuv9g_JnV.\n", 446 | " \n", 447 | "To download files from Google Drive to Binder, you can use the Python package called [google-drive-downloader](https://github.com/ndrplz/google-drive-downloader), which can be installed using the following command:\n", 448 | "\n", 449 | "`pip install googledrivedownloader requests`" 450 | ] 451 | }, 452 | { 453 | "cell_type": "markdown", 454 | "metadata": {}, 455 | "source": [ 456 | "**Replace the following URL with your own shareable URL from Google Drive.**" 457 | ] 458 | }, 459 | { 460 | "cell_type": "code", 461 | "execution_count": null, 462 | "metadata": { 463 | "scrolled": true 464 | }, 465 | "outputs": [], 466 | "source": [ 467 | "gfile_url = 'https://drive.google.com/file/d/1xgxMLRh_jOLRNq-f3T_LXAaSuv9g_JnV'" 468 | ] 469 | }, 470 | { 471 | "cell_type": "markdown", 472 | "metadata": {}, 473 | "source": [ 474 | "**Extract the file id from the above URL.**" 475 | ] 476 | }, 477 | { 478 | "cell_type": "code", 479 | "execution_count": null, 480 | "metadata": {}, 481 | "outputs": [], 482 | "source": [ 483 | "file_id = gfile_url.split('/')[5] #'1xgxMLRh_jOLRNq-f3T_LXAaSuv9g_JnV'\n", 484 | "print('Google Drive file id: {}'.format(file_id))" 485 | ] 486 | }, 487 | { 488 | "cell_type": "markdown", 489 | "metadata": {}, 490 | "source": [ 491 | "**Download the shared file from Google Drive.**" 492 | ] 493 | }, 494 | { 495 | "cell_type": "code", 496 | "execution_count": null, 497 | "metadata": {}, 498 | "outputs": [], 499 | "source": [ 500 | "from google_drive_downloader import GoogleDriveDownloader as gdd\n", 501 | "\n", 502 | "dest_path = './testdata.zip' # choose a name for the downloaded file\n", 503 | "gdd.download_file_from_google_drive(file_id, dest_path, unzip=True)" 504 | ] 505 | }, 506 | { 507 | "cell_type": "markdown", 508 | "metadata": {}, 509 | "source": [ 510 | "You have successfully downloaded data from Google Drive to Binder. You can now continue to [Using whitebox](#Using-whitebox) and start testing whitebox with your own data. " 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | "## Using whitebox" 518 | ] 519 | }, 520 | { 521 | "cell_type": "markdown", 522 | "metadata": {}, 523 | "source": [ 524 | "Here you can specify where your data are located. In this example, we will use [DEM.tif](https://github.com/opengeos/whitebox-python/blob/master/examples/testdata/DEM.tif), which has been downloaded to the testdata folder." 525 | ] 526 | }, 527 | { 528 | "cell_type": "markdown", 529 | "metadata": {}, 530 | "source": [ 531 | "**List data under the data folder.**" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": null, 537 | "metadata": {}, 538 | "outputs": [], 539 | "source": [ 540 | "data_dir = './testdata/'\n", 541 | "print(os.listdir(data_dir))" 542 | ] 543 | }, 544 | { 545 | "cell_type": "markdown", 546 | "metadata": {}, 547 | "source": [ 548 | "In this simple example, we smooth [DEM.tif](https://github.com/opengeos/whitebox-python/blob/master/examples/testdata/DEM.tif) using a [feature preserving denoising](https://github.com/jblindsay/whitebox-tools/blob/master/src/tools/terrain_analysis/feature_preserving_denoise.rs) algorithm. Then, we fill depressions in the DEM using a [depression breaching](https://github.com/jblindsay/whitebox-tools/blob/master/src/tools/hydro_analysis/breach_depressions.rs) algorithm. Finally, we calculate [flow accumulation](https://github.com/jblindsay/whitebox-tools/blob/master/src/tools/hydro_analysis/dinf_flow_accum.rs) based on the depressionless DEM." 549 | ] 550 | }, 551 | { 552 | "cell_type": "code", 553 | "execution_count": null, 554 | "metadata": {}, 555 | "outputs": [], 556 | "source": [ 557 | "import whitebox\n", 558 | "\n", 559 | "wbt = whitebox.WhiteboxTools()\n", 560 | "# set whitebox working directory\n", 561 | "wbt.set_working_dir(data_dir)\n", 562 | "wbt.verbose = False\n", 563 | "\n", 564 | "# call whiteboxtool\n", 565 | "wbt.feature_preserving_smoothing(\"DEM.tif\", \"smoothed.tif\", filter=9)\n", 566 | "wbt.breach_depressions(\"smoothed.tif\", \"breached.tif\")\n", 567 | "wbt.d_inf_flow_accumulation(\"breached.tif\", \"flow_accum.tif\")" 568 | ] 569 | }, 570 | { 571 | "cell_type": "markdown", 572 | "metadata": {}, 573 | "source": [ 574 | "## Displaying results\n", 575 | "\n", 576 | "This section demonstrates how to display images on Jupyter Notebook. Three Python packages are used here, including [matplotlib](https://matplotlib.org/), [imageio](https://imageio.readthedocs.io/en/stable/installation.html), and [tifffile](https://pypi.org/project/tifffile/). These three packages can be installed using the following command:\n", 577 | "\n", 578 | "`pip install matplotlib imageio tifffile`\n" 579 | ] 580 | }, 581 | { 582 | "cell_type": "code", 583 | "execution_count": null, 584 | "metadata": {}, 585 | "outputs": [], 586 | "source": [ 587 | "!pip install matplotlib imageio tifffile" 588 | ] 589 | }, 590 | { 591 | "cell_type": "markdown", 592 | "metadata": {}, 593 | "source": [ 594 | "**Import the libraries.**" 595 | ] 596 | }, 597 | { 598 | "cell_type": "code", 599 | "execution_count": null, 600 | "metadata": {}, 601 | "outputs": [], 602 | "source": [ 603 | "# comment out the third line (%matplotlib inline) if you run the tutorial in other IDEs other than Jupyter Notebook\n", 604 | "import matplotlib.pyplot as plt\n", 605 | "import imageio\n", 606 | "\n", 607 | "%matplotlib inline" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": {}, 613 | "source": [ 614 | "**Display one single image.**" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "execution_count": null, 620 | "metadata": {}, 621 | "outputs": [], 622 | "source": [ 623 | "raster = imageio.imread(os.path.join(data_dir, 'DEM.tif'))\n", 624 | "plt.imshow(raster)\n", 625 | "plt.show()" 626 | ] 627 | }, 628 | { 629 | "cell_type": "markdown", 630 | "metadata": {}, 631 | "source": [ 632 | "**Read images as numpy arrays.**" 633 | ] 634 | }, 635 | { 636 | "cell_type": "code", 637 | "execution_count": null, 638 | "metadata": {}, 639 | "outputs": [], 640 | "source": [ 641 | "original = imageio.imread(os.path.join(data_dir, 'DEM.tif'))\n", 642 | "smoothed = imageio.imread(os.path.join(data_dir, 'smoothed.tif'))\n", 643 | "breached = imageio.imread(os.path.join(data_dir, 'breached.tif'))\n", 644 | "flow_accum = imageio.imread(os.path.join(data_dir, 'flow_accum.tif'))" 645 | ] 646 | }, 647 | { 648 | "cell_type": "markdown", 649 | "metadata": {}, 650 | "source": [ 651 | "**Display multiple images in one plot.**" 652 | ] 653 | }, 654 | { 655 | "cell_type": "code", 656 | "execution_count": null, 657 | "metadata": {}, 658 | "outputs": [], 659 | "source": [ 660 | "fig = plt.figure(figsize=(16, 11))\n", 661 | "\n", 662 | "ax1 = fig.add_subplot(2, 2, 1)\n", 663 | "ax1.set_title('Original DEM')\n", 664 | "plt.imshow(original)\n", 665 | "\n", 666 | "ax2 = fig.add_subplot(2, 2, 2)\n", 667 | "ax2.set_title('Smoothed DEM')\n", 668 | "plt.imshow(smoothed)\n", 669 | "\n", 670 | "ax3 = fig.add_subplot(2, 2, 3)\n", 671 | "ax3.set_title('Breached DEM')\n", 672 | "plt.imshow(breached)\n", 673 | "\n", 674 | "ax4 = fig.add_subplot(2, 2, 4)\n", 675 | "ax4.set_title('Flow Accumulation')\n", 676 | "plt.imshow(flow_accum)\n", 677 | "\n", 678 | "plt.show()" 679 | ] 680 | }, 681 | { 682 | "cell_type": "markdown", 683 | "metadata": {}, 684 | "source": [ 685 | "## whitebox GUI\n", 686 | "\n", 687 | "WhiteboxTools also provides a Graphical User Interface (GUI) - **WhiteboxTools Runner**, which can be invoked using the following Python script. *__Note that the GUI might not work in Jupyter notebooks deployed on the cloud (e.g., MyBinder.org), but it should work on Jupyter notebooks on local computers.__*\n", 688 | "\n", 689 | "```python\n", 690 | "import whitebox\n", 691 | "whitebox.Runner()\n", 692 | "\n", 693 | "```\n", 694 | "\n", 695 | "![](https://wetlands.io/file/images/whitebox.png)" 696 | ] 697 | }, 698 | { 699 | "cell_type": "markdown", 700 | "metadata": {}, 701 | "source": [ 702 | "## Citing whitebox\n", 703 | "\n", 704 | "If you use the **whitebox** Python package for your research and publications, please consider citing the following papers to give Prof. [John Lindsay](http://www.uoguelph.ca/~hydrogeo/index.html) credits for his tremendous efforts in developing [Whitebox GAT](https://github.com/jblindsay/whitebox-geospatial-analysis-tools) and [WhiteboxTools](https://github.com/jblindsay/whitebox-tools). Without his work, this **whitebox** Python package would not exist! \n", 705 | "\n", 706 | "* Lindsay, J. B. (2016). Whitebox GAT: A case study in geomorphometric analysis. Computers & Geosciences, 95, 75-84. http://dx.doi.org/10.1016/j.cageo.2016.07.003" 707 | ] 708 | }, 709 | { 710 | "cell_type": "markdown", 711 | "metadata": {}, 712 | "source": [ 713 | "## Credits\n", 714 | "\n", 715 | "This interactive notebook is made possible by [MyBinder.org](https://mybinder.org/). Big thanks to [MyBinder.org](https://mybinder.org/) for developing the amazing binder platform, which is extremely valuable for reproducible research!\n", 716 | "\n", 717 | "This tutorial made use a number of open-source Python packages, including [ Cookiecutter](https://github.com/audreyr/cookiecutter), [numpy](http://www.numpy.org/), [matplotlib](https://matplotlib.org/), [imageio](https://imageio.readthedocs.io/en/stable/installation.html), [tifffile](https://pypi.org/project/tifffile/), and [google-drive-downloader](https://github.com/ndrplz/google-drive-downloader). Thanks to all developers of these wonderful Python packages!\n" 718 | ] 719 | }, 720 | { 721 | "cell_type": "markdown", 722 | "metadata": {}, 723 | "source": [ 724 | "## Contact\n", 725 | "\n", 726 | "If you have any questions regarding this tutorial or the **whitebox** Python package, you can contact me (Qiusheng Wu) at qwu18@utk.edu or https://wetlands.io/#contact" 727 | ] 728 | } 729 | ], 730 | "metadata": { 731 | "kernelspec": { 732 | "display_name": "Python 3 (ipykernel)", 733 | "language": "python", 734 | "name": "python3" 735 | }, 736 | "language_info": { 737 | "codemirror_mode": { 738 | "name": "ipython", 739 | "version": 3 740 | }, 741 | "file_extension": ".py", 742 | "mimetype": "text/x-python", 743 | "name": "python", 744 | "nbconvert_exporter": "python", 745 | "pygments_lexer": "ipython3", 746 | "version": "3.11.9" 747 | } 748 | }, 749 | "nbformat": 4, 750 | "nbformat_minor": 2 751 | } 752 | --------------------------------------------------------------------------------