Skip to content

Stem_diameter_profile() issue when detect_stem() outputs are written to disk first... #1

@Robin-hartley

Description

@Robin-hartley

Kia ora Team,

just spotted this issue - as the detect_stem() can fail when running through a large list of individual tree point clouds, its best to write to disk. When the next phase is to derive profiles using stem_diameter_profile(), however, this relies on point clouds that have a "Stem" binary attribute, and the TreeLS package that is used in the background here doesn't natively write the Stem attribute as its not binary.

Here is an example:

list input clouds

itc_list <- list.files(file.path(getwd(), "Input_PCs"), pattern = ".laz$",
full.names = TRUE)

Sequential processing loop

results <- list()
error_log <- file.path(getwd(), "stem_errors_seq.txt")

Sequential processing loop

for (i in seq_along(itc_list )) {
file <- itc_list [i]
message("▶️ Processing file ", i, "/", length(itc_list ), ": ", basename(file))

tryCatch({
stem_las <- detect_stem(file, min_ht = 0.1, max_diameter = 0.8)

if (is.null(stem_las) || npoints(stem_las) == 0) {
  results[[file]] <- list(file = file, status = "empty", out_path = NA,
                          message = "No stem points")
} else {
  out_path <- file.path(out_path_stem,
                        paste0(tools::file_path_sans_ext(basename(file)), "_stem.laz"))
  lidR::writeLAS(stem_las, out_path)
  
  results[[file]] <- list(file = file, status = "ok", out_path = out_path, message = NA)
}

}, error = function(e) {
msg <- paste0("❌ Error with file: ", file, " | ", e$message, "\n")
cat(msg, file = error_log, append = TRUE)
results[[file]] <- list(file = file, status = "error", out_path = NA, message = e$message)
})
}

################# Diameter profiles #################

List all files.

pc_list <- list.files(file.path(getwd(), "Stem_PCs_treenotypR"),
pattern = ".laz$",
full.names = TRUE)

Sequential processing loop

results_2 <- list()
error_log2 <- file.path(getwd(), "seg_errors_seq.txt")

Sequential processing loop

for (i in seq_along(pc_list)) {
file <- pc_list[1]
message("▶️ Processing file ", i, "/", length(pc_list), ": ", basename(file))

tryCatch({
las <- lidR::readLAS(file)

profile <- stem_diameter_profile(las, 
                                 min_ht = 0.1, 
                                 max_diameter = 0.8,
                                 seg_ht = 0.2)

if (is.null(profile) || nrow(profile) == 0) {
  results_2[[las]] <- list(file = file, status = "empty", out_path = NA,
                            message = "No diameter profile generated")
} else {
  out_path_p <- file.path(out_path_profile,
                        paste0(tools::file_path_sans_ext(basename(file)), "_d_profile.csv"))
  
  write.csv(profile, out_path_p, row.names = FALSE)
  
  results_2[[file]] <- list(file = file, status = "ok", out_path = out_path_p, message = NA)
}

}, error = function(e) {
msg <- paste0("❌ Error with file: ", file, " | ", e$message, "\n")
cat(msg, file = error_log2, append = TRUE)
results_2[[file]] <- list(file = file, status = "error", out_path = NA, message = e$message)
})
}

De-bugging found the following error:

Error in validate_las(stem_las, required_cols = c("X", "Y", "Z", "Stem")) :
Invalid input: stem_las LAS object is missing required columns: Stem

I have some code to fix this up, so i will propse a change.

Cheers

RJLH

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions