Working with Lidar

This chapter documents lidar workflows in WbW-R, including file-backed processing, metadata checks, and output control patterns.

Lidar workflows are strongly shaped by dataset size and I/O cost. The guiding pattern here is to use file-backed objects and vectorized matrix operations for normal workloads, then switch to chunked processing when point counts exceed comfortable memory limits.

Baseline Workflow

Use this as a first-run validation before introducing matrix edits or chunked processing.

library(whiteboxworkflows)

l <- wbw_read_lidar('survey.las')
print(l$metadata())

copy <- l$deep_copy('survey_copy.las', overwrite = TRUE)
print(copy$metadata())

Memory-Backed Lidar for Pipeline Efficiency

For workflows that chain multiple lidar operations, memory-backed lidar objects eliminate disk I/O between steps. This is valuable when processing large point clouds through sequential filtering or classification steps.

Load a point cloud into memory with file_mode = "m":

library(whiteboxworkflows)

# Read directly into memory
survey <- wbw_read_lidar('survey.las', file_mode = "m")
print(survey$file_path())  # prints: memory://lidar/...

Memory-backed lidar objects support the full matrix/data-frame API and all downstream operations:

library(whiteboxworkflows)

# Read into memory
survey <- wbw_read_lidar('survey.las', file_mode = "m")

# Inspect and process
meta <- survey$metadata()
cat('Points:', meta$point_count, '\n')

# Extract and edit points
pts <- survey$to_matrix(fields = c('x', 'y', 'z', 'classification'))
high <- pts[, 3] > 250
pts[high, 4] <- 6

# Write edits back to disk
edited <- survey$from_matrix(
  pts,
  output_path = 'survey_filtered.laz',
  overwrite = TRUE,
  fields = c('x', 'y', 'z', 'classification')
)

Lidar Memory Lifecycle

Memory-backed lidar objects persist until explicitly removed or cleared. For long-running lidar pipelines, manage memory explicitly:

library(whiteboxworkflows)

# Check current memory
cat('Lidar objects in memory:', wbw_lidar_memory_count(), '\n')

# Read point clouds
survey1 <- wbw_read_lidar('large1.las', file_mode = "m")
survey2 <- wbw_read_lidar('large2.las', file_mode = "m")

cat('After reads:', wbw_lidar_memory_count(), '\n')

# Remove when done
wbw_remove_lidar_from_memory(survey1)
cat('After remove:', wbw_lidar_memory_count(), '\n')

# Or clear all
wbw_clear_lidar_memory()
cat('After clear:', wbw_lidar_memory_count(), '\n')

Implicit Memory Output from Tools

All lidar-output tools store their result in memory automatically when the output argument is omitted (NULL). You do not need to pass file_mode = "m" or choose a temporary path — simply leave output out and the returned wbw_lidar object is already memory-backed:

library(whiteboxworkflows)

wbe <- wbw_make_session()
survey <- wbw_read_lidar('survey.laz')

# No output path — result is stored in memory automatically
filtered <- wbe$filter_lidar_classes(input = survey$path, excluded_classes = list(7L))
cat(filtered$path, '\n')  # prints: memory://lidar/...

# Chain operations without any intermediate files
thinned <- wbe$lidar_thin(input = filtered$path, resolution = 0.5)
cat(thinned$path, '\n')  # also memory://lidar/...

# Persist the final result only
wbw_write_lidar(thinned, 'survey_clean.copc.laz')

This applies to all lidar tools. Providing an explicit output argument writes to disk as before.

Best practices:

  • Use file_mode = "m" for intermediate point cloud processing.
  • Export memory-backed lidar to disk with write() when persisting final outputs.
  • Call remove_lidar_from_memory() after a point cloud is no longer needed.
  • Use clear_lidar_memory() between independent analysis phases.
  • Use wbw_clear_memory() when resetting all in-process raster/vector/lidar stores together.
  • Monitor lidar_memory_count() for large processing jobs.

Iterating Through Lidar Points

Stable WbW-R lidar objects are file-backed and tool-oriented, with explicit columnar point access through matrix/data-frame APIs. Direct point-by-point iteration is still not the primary API path.

Recommended point-level workflow:

  1. Use to_matrix() or to_data_frame() with selected point fields.
  2. Apply vectorized edits in base R/tidy workflows.
  3. Write updates with from_matrix(...) or from_data_frame(...).

The example below uses a simple reclassification rule to illustrate the matrix roundtrip pattern.

library(whiteboxworkflows)

l <- wbw_read_lidar('survey.las')
pts <- l$to_matrix(fields = c('x', 'y', 'z', 'classification'))

ground <- pts[, 4] == 2
pts[ground, 4] <- 6

edited <- l$from_matrix(
  pts,
  output_path = 'survey_reclassified.laz',
  overwrite = TRUE,
  fields = c('x', 'y', 'z', 'classification')
)

print(edited$point_count())

Tool-Driven Lidar Processing

Use tool-driven processing when extracting QA outputs and diagnostics from lidar datasets.

For complete lidar write-option keys and allowed values, see Output Controls.

library(whiteboxworkflows)

s <- wbw_session()
wbw_lidar_info(input = 'survey.las', output = 'survey_info.html')

Chunked Matrix Streaming

For very large point clouds, use chunked matrix streaming to avoid keeping the full point matrix in memory.

Recommended chunked workflow:

  1. Read chunks with to_matrix_chunks(...).
  2. Apply vectorized edits in each chunk.
  3. Write edited chunks with from_matrix_chunks(...).

Use this when full-matrix operations would exceed available memory.

library(whiteboxworkflows)

l <- wbw_read_lidar('survey.las')
fields <- c('x', 'y', 'z', 'classification')

chunks <- l$to_matrix_chunks(chunk_size = 200000, fields = fields)
for (i in seq_along(chunks)) {
  high <- chunks[[i]][, 3] > 250
  chunks[[i]][high, 4] <- 6
}

edited <- l$from_matrix_chunks(
  chunks,
  output_path = 'survey_chunked_reclassified.laz',
  overwrite = TRUE,
  fields = fields
)

print(edited$point_count())

Notes:

  • LAS/LAZ chunk outputs use shared core streaming rewrite.
  • Other output formats currently fall back to non-streaming assembly in this API path.

Best Practices

  • Validate CRS before and after reprojection.
  • Keep source lidar immutable; write derived products to new files.
  • Prefer COPC/LAZ outputs for large cloud workflows.

Lidar Object Method Reference

Metadata and Access

MethodDescription
metadataReturn lidar metadata (bounds, point format, CRS, counts).
point_countReturn total number of points.
file_path, pathReturn backing lidar path.
get_short_filenameReturn basename of lidar file.

Matrix and Data-Frame Conversion

MethodDescription
to_matrixRead selected lidar fields as numeric matrix.
to_data_frameRead selected lidar fields as data frame.
to_matrix_chunksRead selected lidar fields in chunked matrix blocks.

Writing Edited Point Data

MethodDescription
from_matrixWrite edited matrix data to lidar output.
from_data_frameWrite edited data frame fields to lidar output.
from_matrix_chunksWrite chunked matrix edits to lidar output.

Persistence

MethodDescription
deep_copyCopy lidar to a new path with optional write options.
writeWrite lidar to a new output path.