I am using catalog_apply() to normalize las points using lasnormalize() and segment individual trees using lastrees(). This is modified from the catalog_apply() lidR documentation (p.10):


my_tree_detection_method <- function(cluster, ws)
  las <- readLAS(cluster)
  if (is.empty(las)) return(NULL)
  las_n = lasnormalize(las, tin())
  ttops <- lastrees(las_n, li2012(R = 3, speed_up = 5))
  # ttops is a SpatialPointsDataFrame that contains the tree tops in our region of interest
  # plus the trees tops in the buffered area. We need to remove the buffer otherwise we will get
  # some trees more than once.
  # bbox <- raster::extent(cluster)
  # ttops <- raster::crop(ttops, bbox)

ws <- "/path/to/my/las/data"
ctg <- readLAScatalog(ws)
lidR:::catalog_laxindex(ctg) # Build index

opt_chunk_buffer(ctg) <- 10
opt_chunk_size(ctg) <- 1000

opt <- list(need_buffer = TRUE) # catalog_apply will throw an error if buffer = 0
output <- catalog_apply(ctg, my_tree_detection_method, ws = 5, .options = opt)

The example uses the following to remove the processing buffer:

# bbox <- raster::extent(cluster)
# ttops <- raster::crop(ttops, bbox)

However, my modified example using lastrees() is not a SpatialPointsDataFrame and, I believe, cannot utilize extent() and crop() to remove the processing buffer.

What is the preferred way to remove the buffer used for processing in catalog_apply()?

1 Answer 1


Your case is covered by this vignette. The documentation of catalog_apply says:

Buffered data

The LAS objects read by the user function have a special attribute called buffer that indicates, for each point, if it comes from a buffered area or not. Points from non-buffered areas have a 'buffer' value of 0, while points from buffered areas have a 'buffer' value of 1, 2, 3 or 4, where 1 is the bottom buffer and 2, 3 and 4 are the left, top and right buffers, respectively. This allows for filtering of buffer points if required.

Consequently you can do

ttops <- lasfilter(ttops, buffer == 0)
  • In my case, would I apply the buffer removal to the ttops variable inside the function?: las_no_buffer <- lasfilter(ttops, buffer == 0)
    – Aaron
    Dec 12, 2019 at 15:01
  • 1
    Yes you're right. Be aware that it creates a copy of the point cloud and thus requires memory. But this is how R works...
    – JRR
    Dec 12, 2019 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.