Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small improvements #85

Merged
merged 4 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,68 @@ def create_grid_cd(tile_size, vec1, vec2):
grass.message(_(f"Number of tiles is: {number_tiles}"))

return grid_trees, tiles_list, number_tiles, rm_vectors


def create_nearest_pixel_ndvi(
ndvi, ndvi_threshold, nearest, nprocs, memory, rm_rasters, output
):
"""Creates the raster map with nearest tree peaks based on the NDVI
threshold

Args:
ndvi (str): The name of the NDVI raster map
ndvi_threshold (float): The threshold for the NDVI
nearest (str): The name of nearest tree peaks raster map
nprocs (int): The number of parallel processes
memory (int): The used memory in MB
rm_rasters (list): The list of raster which should be removed in the
cleanup
output (str): The name for the nearest tree peaks based on NDVI
threshold raster map
"""
# mathematical morphology: opening to remove isolated small patches of high ndvi
ndvi_split = ndvi.split("@")[0]
grass.run_command(
"r.neighbors",
input=ndvi,
output=f"{ndvi_split}_min1",
size=3,
method="minimum",
nprocs=nprocs,
memory=memory,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_min1",
output=f"{ndvi_split}_min2",
size=3,
method="minimum",
nprocs=nprocs,
memory=memory,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_min2",
output=f"{ndvi_split}_max1",
size=3,
method="maximum",
nprocs=nprocs,
memory=memory,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_max1",
output=f"{ndvi_split}_max2",
size=3,
method="maximum",
nprocs=nprocs,
memory=memory,
)
rm_rasters.append(f"{ndvi_split}_min1")
rm_rasters.append(f"{ndvi_split}_min2")
rm_rasters.append(f"{ndvi_split}_max1")
rm_rasters.append(f"{ndvi_split}_max2")

grass.mapcalc(
f"{output} = if({ndvi_split}_max2 < {ndvi_threshold}, null(), {nearest})"
)
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,30 @@
# %end

# %option G_OPT_R_INPUT
# % key: trees_pixel_ndvi
# % key: nearest_pixel_ndvi
# % label: raster with trees identified by NDVI value
# % answer: trees_pixel_ndvi
# % required: no
# % answer: nearest_pixel_ndvi
# % guisection: Input
# %end

# %option G_OPT_R_INPUT
# % key: nearest
# % label: Name of raster with nearest peak IDs
# % required: no
# % answer: nearest_tree
# % guisection: Input
# %end

# %option
# % key: ndvi_threshold
# % type: double
# % required: no
# % label: NDVI threshold for potential trees
# % answer: 130
# % guisection: Parameters
# %end

# %option G_OPT_R_INPUT
# % key: ndvi_raster
# % label: Name of the NDVI raster
Expand Down Expand Up @@ -141,9 +159,16 @@
# % guisection: Parallel processing
# %end

# %option G_OPT_MEMORYMB
# % guisection: Parallel processing
# %end

# %rules
# % exclusive: trees_raw_r,trees_raw_v
# % required: trees_raw_r,trees_raw_v
# % required: nearest_pixel_ndvi,nearest
# % excludes: nearest_pixel_ndvi,nearest,ndvi_threshold
# % requires_all: nearest,ndvi_threshold
# %end

import atexit
Expand Down Expand Up @@ -190,7 +215,11 @@ def main():
grass.fatal("Unable to find the analyse trees library directory")
sys.path.append(path)
try:
from analyse_trees_lib import set_nprocs
from analyse_trees_lib import (
create_nearest_pixel_ndvi,
set_nprocs,
test_memory,
)
except Exception:
grass.fatal("m.analyse.trees library is not installed")

Expand All @@ -213,9 +242,17 @@ def main():
group_name = options["group"]
model_file = options["save_model"]
nprocs = int(options["nprocs"])
trees_pixel_ndvi = options["trees_pixel_ndvi"]
nearest_pixel_ndvi = options["nearest_pixel_ndvi"]
nearest = options["nearest"]
ndvi_threshold = options["ndvi_threshold"]

nprocs = set_nprocs(nprocs)
memmb = test_memory(options["memory"])
# for some modules like r.neighbors and r.slope_aspect, there is
# no speed gain by using more than 100 MB RAM
memory_max100mb = 100
if memmb < 100:
memory_max100mb = memmb

grass.use_temp_region()

Expand Down Expand Up @@ -247,17 +284,28 @@ def main():
trees_basemap = options["trees_raw_r"]

# non trees
if not grass.find_file(name=nearest_pixel_ndvi, element="cell")["file"]:
create_nearest_pixel_ndvi(
ndvi,
ndvi_threshold,
nearest,
nprocs,
memory_max100mb,
rm_rasters,
nearest_pixel_ndvi,
)
rm_rasters.append(nearest_pixel_ndvi)

# false trees
# problem areas with high NDVI like shadows on roofs, solar panels
# trees_object_filt_large = NULL and trees_pixel_ndvi != NULL
# trees_object_filt_large = NULL and nearest_pixel_ndvi != NULL
grass.mapcalc(
f"false_trees = if(isnull({trees_pixel_ndvi}), null(), if(isnull({trees_basemap}), 1, null()))"
f"false_trees = if(isnull({nearest_pixel_ndvi}), null(), if(isnull({trees_basemap}), 1, null()))"
)

# other areas clearly not trees
grass.mapcalc(
f"notrees = if(isnull({trees_pixel_ndvi}) && isnull({trees_basemap}), 1, null())"
f"notrees = if(isnull({nearest_pixel_ndvi}) && isnull({trees_basemap}), 1, null())"
)
rm_rasters.append("false_trees")
rm_rasters.append("notrees")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
# %end

# %option G_OPT_R_OUTPUT
# % key: trees_pixel_ndvi
# % key: nearest_pixel_ndvi
# % label: Name of raster with nearest peak IDs filtered by NDVI
# % description: necessary intermediate result for mltrain
# % required: no
Expand Down Expand Up @@ -211,7 +211,11 @@ def main():
grass.fatal("Unable to find the analyse trees library directory")
sys.path.append(path)
try:
from analyse_trees_lib import set_nprocs, test_memory
from analyse_trees_lib import (
create_nearest_pixel_ndvi,
set_nprocs,
test_memory,
)
except Exception:
grass.fatal("m.analyse.trees library is not installed")

Expand All @@ -226,7 +230,6 @@ def main():
blue = options["blue_raster"]
nir = options["nir_raster"]
ndvi = options["ndvi_raster"]
ndvi_split = ndvi.split("@")[0]
ndwi = options["ndwi_raster"]
ndgb = options["ndgb_raster"]
ndsm = options["ndsm"]
Expand Down Expand Up @@ -273,62 +276,26 @@ def main():
# - lower such that trees are kept -> shadow areas are kept

# mathematical morphology: opening to remove isolated small patches of high ndvi
grass.run_command(
"r.neighbors",
input=ndvi,
output=f"{ndvi_split}_min1",
size=3,
method="minimum",
nprocs=nprocs,
memory=memory_max100mb,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_min1",
output=f"{ndvi_split}_min2",
size=3,
method="minimum",
nprocs=nprocs,
memory=memory_max100mb,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_min2",
output=f"{ndvi_split}_max1",
size=3,
method="maximum",
nprocs=nprocs,
memory=memory_max100mb,
)
grass.run_command(
"r.neighbors",
input=f"{ndvi_split}_max1",
output=f"{ndvi_split}_max2",
size=3,
method="maximum",
nprocs=nprocs,
memory=memory_max100mb,
)
rm_rasters.append(f"{ndvi_split}_min1")
rm_rasters.append(f"{ndvi_split}_min2")
rm_rasters.append(f"{ndvi_split}_max1")
rm_rasters.append(f"{ndvi_split}_max2")

if options["trees_pixel_ndvi"]:
trees_pixel_ndvi = options["trees_pixel_ndvi"]
if options["nearest_pixel_ndvi"]:
nearest_pixel_ndvi = options["nearest_pixel_ndvi"]
else:
trees_pixel_ndvi = "trees_pixel_ndvi"
rm_rasters.append(trees_pixel_ndvi)

grass.mapcalc(
f"{trees_pixel_ndvi} = if({ndvi_split}_max2 < {ndvi_threshold}, null(), {nearest})"
nearest_pixel_ndvi = "nearest_pixel_ndvi"
rm_rasters.append(nearest_pixel_ndvi)
create_nearest_pixel_ndvi(
ndvi,
ndvi_threshold,
nearest,
nprocs,
memory_max100mb,
rm_rasters,
nearest_pixel_ndvi,
)

# cut to nir: all pixels below 100 are not vegetation
# removes shadows with high ndvi e.g. on roofs
# needed
grass.mapcalc(
f"trees_pixel_nir = if({nir} < {nir_threshold}, null(), {trees_pixel_ndvi})"
f"trees_pixel_nir = if({nir} < {nir_threshold}, null(), {nearest_pixel_ndvi})"
)
rm_rasters.append("trees_pixel_nir")

Expand Down
15 changes: 11 additions & 4 deletions grass-gis-addons/m.import.rvr/m.import.rvr.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,19 +569,22 @@ def check_data_exists(data, optionname):
grass.fatal(_(f"The data directory <{data}> does not exists."))


def check_addon(addon, url=None):
def check_addon(addon, url=None, multiaddon=None):
"""Check if addon is installed.
Args:
addon (str): Name of the addon
url (str): Url to download the addon
"""
if not grass.find_program(addon, "--help"):
if not multiaddon:
multiaddon = addon
msg = (
f"The '{addon}' module was not found, install it first:\n"
f"g.extension {addon}"
f"The '{addon}' module was not found, install it first:\n"
f"<g.extension {multiaddon}"
)
if url:
msg += f" url={url}"
msg += ">"
grass.fatal(_(msg))


Expand Down Expand Up @@ -1585,7 +1588,11 @@ def main():

# check if needed addons are installed
check_addon("r.import.ndsm_nrw", "/path/to/r.import.ndsm_nrw")
check_addon("r.dem.import", "https://github.com/mundialis/r.dem.import")
check_addon(
"r.dtm.import.nw",
"https://github.com/mundialis/r.dem.import",
"r.dem.import",
)

# check if needed paths to data are set
grass.message(_("Checking input parameters ..."))
Expand Down