r-spatialecology/landscapemetrics

Bug in AI

Closed this issue · 6 comments

There seems to be a problem if there is only 1 class/patch and NA values. The result should be AI = 100 (same as if all cells have the same value I think)

library(raster)
library(landscapemetrics)

mat <- matrix(data = 1, ncol = 100, nrow = 100)
mat_na <- matrix(data = rep(x = c(1, NA), each = 5000), 
                 ncol = 100, nrow = 100)

input_lsm <- raster::raster(mat, 
                            xmn = 0, xmx = 100, 
                            ymn = 0, ymx = 100)

input_lsm_na <- raster::raster(mat_na, 
                               xmn = 0, xmx = 100, 
                               ymn = 0, ymx = 100)

input_stack <- raster::stack(input_lsm, input_lsm_na)

lsm_c_ai(input_stack)

The problem is probably inside of lsm_c_ai_calc():

ai2 <- landscapemetrics:::lsm_c_ai_calc(input_lsm_na)

It is probably here -

cells_class$max_adj <- ifelse(test = cells_class$m == 0,
, but I do not know what is exactly going on there...

   cells_class$max_adj <- ifelse(test = cells_class$m == 0,
                                  yes = 2 * cells_class$n * (cells_class$n - 1),
                                  no = ifelse(test = cells_class$m <= cells_class$n,
                                              yes = 2 * cells_class$n * (cells_class$n - 1) + 2 * cells_class$m - 1,
                                              no = ifelse(test = cells_class$m > cells_class$n,
                                                          yes = 2 * cells_class$n * (cells_class$n - 1) + 2 * cells_class$m - 2,
                                                          no = NA)))

I tried to measure the non-NA part, only:

library(raster)
library(landscapemetrics)

mat_small <- matrix(data = 1, ncol = 50, nrow = 100)
input_lsm_small <- raster::raster(mat_small, 
                               xmn = 0, xmx = 50, 
                               ymn = 0, ymx = 100)

landscapemetrics:::lsm_c_ai_calc(input_lsm_small)

# A tibble: 1 x 5
  level class    id metric value
  <chr> <int> <int> <chr>  <dbl>
1 class     1    NA ai      99.9

Either I did something wrong, or the bug affecs more than this special case-

It could be just a rounding issue:

cells_class$n <- trunc(sqrt(cells_class$value))

I haven't got the time to look into it yet. But since the difference is just very small, a rouding issue is a good guess. I will have a look next week if nobody else tackles it before.

Looking at it again, I think actually there is not a problem at all. In the example, the value with NAs should be a bit less than AI = 100, because the patch is not maximal compact. AI should reach it's maximum value if only one, compact patch is present, i.e. a square.

library(raster)
#> Loading required package: sp
library(landscapemetrics)

mat <- matrix(data = 1, ncol = 100, nrow = 100)

mat_na_1 <- matrix(data = rep(x = c(1, NA), each = 5000),
                   ncol = 100, nrow = 100)

mat_na_2 <- mat_na_1
mat_na_2[50:100, ] <- NA

input_lsm <- raster::raster(mat, 
                            xmn = 0, xmx = 100, 
                            ymn = 0, ymx = 100)

input_lsm_na_1 <- raster::raster(mat_na_1,
                                 xmn = 0, xmx = 100,
                                 ymn = 0, ymx = 100)

input_lsm_na_2 <- raster::raster(mat_na_2,
                                 xmn = 0, xmx = 100,
                                 ymn = 0, ymx = 100)

input_stack <- raster::stack(input_lsm, 
                             input_lsm_na_1, 
                             input_lsm_na_2)

calculate_lsm(input_stack, what = c("lsm_c_ai", "lsm_l_ai"), 
              verbose = FALSE)
#> # A tibble: 6 x 6
#>   layer level     class    id metric value
#>   <int> <chr>     <int> <int> <chr>  <dbl>
#> 1     1 class         1    NA ai     100  
#> 2     1 landscape    NA    NA ai     100  
#> 3     2 class         1    NA ai      99.9
#> 4     2 landscape    NA    NA ai      99.9
#> 5     3 class         1    NA ai     100  
#> 6     3 landscape    NA    NA ai     100

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

Sorry for the false alarm...