Skip to content

Commit

Permalink
Add Identifyflats (TopoToolbox#24)
Browse files Browse the repository at this point in the history
Implements identifyflats for the GridObject
  • Loading branch information
Teschl authored May 24, 2024
1 parent 981428e commit 8f19d08
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 8 deletions.
48 changes: 41 additions & 7 deletions examples/test_GridObject.ipynb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{
"cells": [
{
"cell_type": "markdown",
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"## TopoToolbox for Python\n",
"import topotoolbox as topo\n",
"\n",
"This file contains a few examples on how to use the python version of TopoToolbox. Follow the instructions in the README.md on how to install. Download some example GeoFIFFs (that are used here) from https://github.com/wschwanghart/DEMs"
"import matplotlib.pyplot as plt"
]
},
{
Expand All @@ -15,12 +17,44 @@
"metadata": {},
"outputs": [],
"source": [
"import topotoolbox as topo\n",
"dem = topo.GridObject.gen_random()\n",
"dem.info()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"filled = dem.fillsinks()\n",
"\n",
"flats, sills = filled.identifyflats()\n",
"\n",
"# plotting:\n",
"fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12,4))\n",
"ax1.imshow(dem, cmap='terrain')\n",
"ax1.set_title('dem')\n",
"ax2.imshow(filled, cmap='terrain')\n",
"ax2.set_title('filled')\n",
"\n",
"dem = topo.GridObject(\"perfectworld.tif\")\n",
"dem.info()\n",
"ax3.imshow(flats, cmap='Reds', alpha=0.5)\n",
"ax3.imshow(sills, cmap='Blues', alpha=0.5)\n",
"ax3.set_title('flats and sills')\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"raw = filled.identifyflats(raw=True)\n",
"\n",
"dem = dem.fillsinks()"
"img = plt.imshow(raw, cmap='binary')\n",
"plt.show()"
]
}
],
Expand Down
18 changes: 17 additions & 1 deletion src/lib/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,24 @@ void wrap_fillsinks(py::array_t<float> output, py::array_t<float> dem, ptrdiff_t
fillsinks(output_ptr, dem_ptr, nrows, ncols);
}

// Make wrap_fillsinks() function available as grid_fillsinks() to be used by
// wrap_identifyflats:
// Parameters:
// output: A NumPy array to store the output, where flats, sill amd presills will be marked.
// dem: A NumPy array representing the digital elevation model.
// nrows: Number of rows in the input DEM.
// ncols: Number of columns in the input DEM.

void wrap_identifyflats(py::array_t<int32_t> output, py::array_t<float> dem, ptrdiff_t nrows, ptrdiff_t ncols){
int32_t *output_ptr = output.mutable_data();
float *dem_ptr = dem.mutable_data();

identifyflats(output_ptr, dem_ptr, nrows, ncols);
}

// Make wrap_funcname() function available as grid_funcname() to be used by
// by functions in the pytopotoolbox package

PYBIND11_MODULE(_grid, m) {
m.def("grid_fillsinks", &wrap_fillsinks);
m.def("grid_identifyflats", &wrap_identifyflats);
}
2 changes: 2 additions & 0 deletions src/topotoolbox/grid_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
from .gridmixins.fillsinks import FillsinksMixin
from .gridmixins.info import InfoMixin
from .gridmixins.magic import MagicMixin
from .gridmixins.identifyflats import IdentifyflatsMixin


class GridObject(
InfoMixin,
FillsinksMixin,
IdentifyflatsMixin,
MagicMixin
):
"""A class containing all information of a Digital Elevation Model (DEM).
Expand Down
49 changes: 49 additions & 0 deletions src/topotoolbox/gridmixins/identifyflats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import copy

import numpy as np

from .._grid import grid_identifyflats # pylint: disable=import-error


class IdentifyflatsMixin():

def identifyflats(self, raw=False, output=['sills', 'flats']) -> tuple:
"""
Identifies flats and sills in a digital elevation model (DEM).
Args:
raw (bool): If True, returns the raw output grid as np.ndarray.
Defaults to False.
output (list): List of strings indicating desired output types.
Possible values are 'sills', 'flats'. Defaults to ['sills', 'flats'].
Returns:
tuple: A tuple containing copies of the DEM with identified flats and/or sills.
Note:
Flats are identified as 1s, sills as 2s and presills as 5s (since they are also flats)
in the output grid. Only relevant when using raw=True.
"""

dem = self.z.astype(np.float32)
output_grid = np.zeros_like(dem).astype(np.int32)

grid_identifyflats(output_grid, dem, self.rows, self.columns)

if raw:
return output_grid

result = []
if 'flats' in output:
flats = copy.copy(self)
flats.z = np.zeros_like(flats.z)
flats.z = np.where((output_grid & 1) == 1, 1, flats.z)
result.append(flats)

if 'sills' in output:
sills = copy.copy(self)
sills.z = np.zeros_like(sills.z)
sills.z = np.where((output_grid & 2) == 2, 1, sills.z)
result.append(sills)

return tuple(result)

0 comments on commit 8f19d08

Please sign in to comment.