%conda install gdownLidar
Dependencies
Setup
# Import modules
import sys
import subprocess
from pathlib import Path
from contextlib import suppress
import gdown
# Find GRASS Python packages
sys.path.append(
subprocess.check_output(
["grass", "--config", "python_path"],
text=True
).strip()
)
# Import GRASS packages
import grass.script as gs
import grass.jupyter as gj
from grass.tools import Tools
# Create and initialize GRASS project
try:
gj.init("hilltop")
except ValueError:
with suppress(ValueError):
gs.create_project("hilltop", epsg="2801")
gj.init("hilltop")
tools = Tools(overwrite=True)
# Print projection
projection = tools.g_proj(format="shell", flags="p").keyval
print(projection.get("name"))NAD83(HARN) / Louisiana South
Download parcel
# Set url
url = "https://drive.google.com/file/d/1Okkjea42jx4omRXGFFujWadvOjQnDtQO/view?usp=drive_link"
# Set filename
output = "parcel.gpkg"
# Download data
gdown.download(url, output, quiet=False)
# Import parcel
tools.v_import(input="parcel.gpkg", output="parcel")Downloading...
From: https://drive.google.com/uc?id=1Okkjea42jx4omRXGFFujWadvOjQnDtQO
To: /Users/baharmon/academia/computational-ecology/parcel.gpkg
100%|███████████████████████████████████████████████████████████████████████████████████| 98.3k/98.3k [00:00<00:00, 41.7MB/s]
Download lidar
# Set url
url = "https://drive.google.com/file/d/1FQPGd3MNjqB3itYwUBCZqqQjoN2mIz19/view?usp=drive_link"
# Set filename
output = "hilltop.laz"
# Download data
gdown.download(url, output, quiet=False)Downloading...
From (original): https://drive.google.com/uc?id=1FQPGd3MNjqB3itYwUBCZqqQjoN2mIz19
From (redirected): https://drive.google.com/uc?id=1FQPGd3MNjqB3itYwUBCZqqQjoN2mIz19&confirm=t&uuid=09f3a12f-b061-4e95-8aca-e6d944399d84
To: /Users/baharmon/academia/computational-ecology/hilltop.laz
100%|█████████████████████████████████████████████████████████████████████████████████████| 203M/203M [01:03<00:00, 3.20MB/s]
'hilltop.laz'
Set region
# Set region
tools.g_region(vector="parcel", res=0.3)Bin lidar
%%time
# Bin lidar
tools.r_in_pdal(
input="hilltop.laz",
output="surface",
method="max",
resolution=0.3,
flags="oe"
)
# Set color gradient
tools.r_colors(map="surface", color="viridis")
# Visualize
m = gj.Map(width=1600)
m.d_rast(map="surface")
m.d_legend(raster="surface", color="white", at=(75, 95, 2, 4))
m.show()
CPU times: user 13 ms, sys: 385 ms, total: 398 ms
Wall time: 5.68 s
Set region
# Set region
tools.g_region(vector="parcel", res=0.3)Process surface
%%time
# Set mask
with gs.MaskManager():
# Set mask
tools.r_mask(vector="parcel")
# Clip
tools.r_mapcalc(expression="clip = surface")
# Fill nulls
tools.r_fillnulls(input="clip", output="surface", method="rst", tension=40)
# Remove temporary map
tools.g_remove(type="raster", name="clip", flags="f")
# Set color gradient
tools.r_colors(map="surface", color="viridis")
# Visualize
m = gj.Map(width=1600)
m.d_rast(map="surface")
m.d_legend(raster="surface", color="white", at=(75, 95, 2, 4))
m.show()
CPU times: user 16.1 ms, sys: 593 ms, total: 610 ms
Wall time: 58.2 s
Import lidar
%%time
# Import lidar
tools.v_in_pdal(
input="hilltop.laz",
output="lidar",
flags="ro"
)
# Print point count
info = tools.v_info(map="lidar", format="json", flags="gt").json
print(info["points"])15130452
CPU times: user 5.17 ms, sys: 141 ms, total: 146 ms
Wall time: 58.8 s
Decimate lidar
%%time
# Set region
tools.g_region(vector="lidar", res=0.3)
# Decimate lidar
tools.v_decimate(
input="lidar",
output="points",
layer=1,
zdiff=1.0,
flags="gz"
)
# Print point count
info = tools.v_info(map="points", format="json", flags="gt").json
print(info["points"])1813159
CPU times: user 7.98 ms, sys: 359 ms, total: 367 ms
Wall time: 1min 30s
Classify ground
# Install addon
tools.g_extension(extension="v.lidar.mcc")%%time
# Classify lidar
tools.v_lidar_mcc(
input="points",
ground="ground",
nonground="nonground",
nl=3,
t=0.2,
j=0.1,
f=2,
s=15
)CPU times: user 4.75 ms, sys: 72.6 ms, total: 77.3 ms
Wall time: 1min 27s
Interpolate ground
%%time
# Interpolate ground
tools.v_surf_rst(
input="ground",
elevation="interpolation",
nprocs=12
)
# Clip ground
with gs.MaskManager():
# Set mask
tools.r_mask(vector="parcel")
# Clip to region
tools.r_mapcalc(expression="elevation = interpolation")
# Set color gradient
tools.r_colors(map="elevation", color="viridis")
# Visualize
m = gj.Map(width=1600)
m.d_rast(map="elevation")
m.d_legend(raster="elevation", color="white", at=(75, 95, 2, 4))
m.show()
CPU times: user 20.2 ms, sys: 665 ms, total: 685 ms
Wall time: 2min 3s
Calculate canopy height
# Calculate difference
tools.r_mapcalc(expression="canopy = surface - elevation")
# Set color gradient
tools.r_colors(map="canopy", color="viridis")
# Visualize
m = gj.Map(width=1600)
m.d_rast(map="canopy")
m.d_legend(raster="canopy", color="white", at=(75, 95, 2, 4))
m.show()