r-spatialecology/landscapemetrics

How do I see patch Ids (without show_patches)

Closed this issue · 14 comments

Hello, I am really enjoying the package and currently useing extract_lsm for all patch metrics for 31 sites in a 6200sq km landscape. I am having trouble matching the patch Id that I get in the output tibble with the patches spatially (which I have site names for). How can I see these patches highlighted and labelled in the map?

I tried with show_patches but it takes forever and never showed me the landscape with the patches. I have a point file with the patch names I would like the script to use, but was not able to input them as patch IDs in extract_lsm

I appreciate any help

Hello,

Good to hear you enjoy the package :)

Maybe have a look at the spatialize_lsm()-function. The function returns the visual output of the show_patches() function as a RasterLayer. The raster-plotting function or other packages such as RasterVis are way faster than our show_patches() function which is based on ggplot2().

If you need more help, it would be great if you could share some of your data, so I can reproduce the problem.

Thanks for the suggestion. I used spatialize_lsm() but have not succeeded in displaying the result! I tried with all sort of raster tools.

I attach a TIF raster file with the patches I am interested in. I would like to have all the patch level statistics for each patch, knowing which ones correspond to each patch spatially, or at least being able to display the patchID in an image so that I can match it with the names of my field sites.

I appreciate any help you can provide!

patch data.zip

Hi @ocamponata ,
I cannot think of a simple solution to your question right now. One sub-optimal solution is to calculate a few metrics using spatialize_lsm() and next trying to connect it visually to the names of your field sites...

library(landscapemetrics)
library(raster)

r = raster("patches_sites.tif")
sr = spatialize_lsm(r, what = "lsm_p_area")
plot(sr)

@mhesselbarth would it be possible to add an option in spatialize_lsm() to return an id of a patch? E.g., `spatialize_lsm(r, what = "id")?

Wait... @ocamponata would the get_patches() function solve your question?

library(landscapemetrics)
library(raster)

r = raster("patches_sites.tif")
plot(r)

patched_raster = get_patches(r, class = 1)
plot(patched_raster[[1]])

I will close this for now. Please feel free to re-open at any time.

I am jumping into this conversation because I have the same problem. So as I understand it get_patches() "desintegrates" the landscape into separate class rasters with IDs 1:npatches(class), whereas the lsm_ metrics assign the ID into the tibble as 1:nrow(tibble). So it would be nice to either create a spatialize_lsm(r, what = "id") as @Nowosad was suggesting or have the ID from the "desintegrated" raster into the tibble.

I still think that is was get_patches() does?

Here is a reprex. Notice that get_patches() starts counting patches from 1 for each class, whereas the id column in any lsm_* is essentialy the same as saying tibble::rowid_to_column(var = 'id'). So basically there are two concurrent IDs.

  > library(landscapemetrics)
  > library(tidyverse)
  > library(raster)
  > 
  > get_patches(landscape) %>% 
  +     unlist() %>% 
  +     map(unique)
  $layer_1.class_1
  [1] 1 2 3 4 5 6 7 8 9
  
  $layer_1.class_2
   [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14
  
  $layer_1.class_3
  [1] 1 2 3 4
  
  > 
  > 
  > lsm_p_area(landscape) %>%
  +     group_by(class) %>%
  +     nest() %>% 
  +     mutate(unique = map(data, pull, id)) %>% 
  +     pull(unique)
  [[1]]
  [1] 1 2 3 4 5 6 7 8 9
  
  [[2]]
   [1] 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  
  [[3]]
  [1] 24 25 26 27

I thought we had fixed this at some point? But apparently not. It would be nice to have just one unique ID if possible.

I looked a little bit into this. In order to get a unique patch id during get_patches we would need to first label all present classes in order to get the lowest id value of the second, third, etc. class. However, this would require some fundamental changes to all metrics that use get_patches.

So I think, a quick-and-dirty fix for now is @Nowosad idea to allow what = "id" in spatialize_lsm(). I added this on the "unique_id" branch.

remotes::install_github(repo = "r-spatialecology/landscapemetrics", ref = "unique_id")
library(landscapemetrics)

spatialize_lsm(landscape = landscape, what = "id")
#> $layer_1
#> $layer_1$id
#> class      : RasterLayer 
#> dimensions : 30, 30, 900  (nrow, ncol, ncell)
#> resolution : 1, 1  (x, y)
#> extent     : 0, 30, 0, 30  (xmin, xmax, ymin, ymax)
#> crs        : NA 
#> source     : memory
#> names      : layer 
#> values     : 1, 27  (min, max)

Created on 2021-11-04 by the reprex package (v2.0.1)

Edit: However, I am not really happy with this. It basically is the same functionality of get_patches. So maybe it does make sense to deal with the problem directly within the get_patches function even though that might be a bit more effort.

d07ea9b
#247

Okay...I think I came up with an idea how to deal with this directly in get_patches:

library(landscapemetrics)
library(tidyverse)
library(raster)

get_patches(landscape) %>% unlist() %>% map(unique)
#> $layer_1.class_1
#> [1] 1 2 3 4 5 6 7 8 9
#> 
#> $layer_1.class_2
#>  [1] 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#> 
#> $layer_1.class_3
#> [1] 24 25 26 27

lsm_p_area(landscape) %>%
    group_by(class) %>%
    nest() %>% 
    mutate(unique = map(data, pull, id)) %>% 
    pull(unique)
#> [[1]]
#> [1] 1 2 3 4 5 6 7 8 9
#> 
#> [[2]]
#>  [1] 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#> 
#> [[3]]
#> [1] 24 25 26 27

Created on 2021-11-05 by the reprex package (v2.0.1)

@Nowosad @bitbacchus Could you please play around with this a little bit and see if that breaks any other labeling, ordering etc.?

I tried it on several datasets, and also took a look at the code changes. Look good, in my opinion.

The only "disadvantage" is that in get_patches() now all classes are labelled first, even if only e.g. class 2 is required. However, in all lsm_ metrics, we use get_patches_int() where this is not the case. So personally, I don't think this is a problem

Merged into main. Will close this. Please re-open if needed