r-spatialecology/landscapemetrics

Check lansdcape

Closed this issue · 8 comments

All functions that use calculate_lsm() return the warning to check the landscape multiple times

library(landscapemetrics)

sample_points <- matrix(c(10, 5, 25, 15, 5, 25), ncol = 2, byrow = TRUE)

sample_lsm(landscape, y = sample_points, size = 15, what = "lsm_l_np")
#> # A tibble: 3 x 8
#>   layer level     class    id metric value plot_id percentage_inside
#>   <int> <chr>     <int> <int> <chr>  <dbl>   <int>             <dbl>
#> 1     1 landscape    NA    NA np        18       1              55.6
#> 2     1 landscape    NA    NA np        17       2              66.7
#> 3     1 landscape    NA    NA np        13       3              44.4

#> Warning: Please use check_landscape() to ensure the input data is valid.
#> Warning: Please use check_landscape() to ensure the input data is valid.
#> Warning: Please use check_landscape() to ensure the input data is valid.
#> Warning: Some of buffers extend over the landscape border. Consider decreasing the size argument value.

Created on 2019-09-09 by the reprex package (v0.3.0)

It's possible to redirect the messages (e.g., warnings) to a variable. We could do that during the loop in sample_lsm(), filter out the unwanted stuff, and print the remaining warnings.

Here is a proof-of-concept:

library(landscapemetrics)

sample_points <- matrix(c(10, 5, 25, 15, 5, 25), ncol = 2, byrow = TRUE)

# this should happen just before the loop starts
# (thanks to MrFlick for a useful code snippet https://stackoverflow.com/a/24397137/7273230)

tc <- textConnection("messages","w") 
sink(tc, type="message")

# the "loop"
sample_lsm(landscape, y = sample_points, size = 15, what = "lsm_l_np")

# and this just after the loop has ended
sink(NULL, type="message")
close(tc)

# sort and print the warnings
messages <- gsub("^.*:","",messages)
messages <- unique(messages)
invisible(lapply(messages, function(x){ warning(x, call. = FALSE)}))

Not pretty yet, and I have no clue where the code would need to go. But I think this would be a way to do it.

I just recognized that our current solution is not very stable and there are problems if errors occur before the connection can be closed.

I'm working on a much better solution using withCallingHandlers(), which is what is normally done for such problems.

Okay, this should do the trick: 64aa4e0

Interestingly, this leads to a new warning message we didn't get before (the non-missing stuff).

library(landscapemetrics)
s <- spatialize_lsm(landscape, what = "lsm_p_area")
#> Warning: Please use 'check_landscape()' to ensure the input data is valid.
#> Warning: no non-missing arguments to min; returning Inf
#> Warning: no non-missing arguments to max; returning -Inf

Created on 2020-02-20 by the reprex package (v0.3.0)

The warnings comes from raster::rasterFromXYZ(fill_value[, c(2,3, 8)], crs = crs_input) and can can be reproduced by using the min() or max() on an empty vector, e.g. min(numeric(0)). I tried to find exactly where this is happening within raster, but couldn't find it. Also, I don't understand yet why the warning wasn't thrown before.

Still not sure where exactly this is happening, but I think it is happening because raster firstly sets up an empty raster and then adds the values to it. During the setting up, the min/max values can't be identified by raster (...because they are not there yet...). I don't understand how raster suppresses the warning normally and why withCallingHandlers() picks it up now.

However, shouldn't be a big deal to just remove it from the list with all thrown errors we filter for unique messages anyways. A bit of a dirty hack though.

Asked for help: rspatial/raster#96

50b7f5d

Seemed to be an error in raster which is now solved. So I removed the part which removed the no non-missing arguments to max; returning -Inf.