---
title: "Calculating home-range overlaps with `amt`"
author: "Johannes Signer and John Fieberg"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteKeyword{hr-overlap}
  %\VignetteIndexEntry{Calculating home-range overlaps with `amt`}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include=FALSE}
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
```

## Background

Several different indices have been proposed for measuring home-range overlap. These are reviewed
by Fieberg & Kochanny
(2005).
There are two general approaches used to calculate home-range overlap: 1) calculate the percentage overlap at a given isopleth level (this works for geometric and probabilistic home ranges) or 2) calculate an index of
similarity between the two utilization distributions (UD; this only works for
probabilistic estimators)^[For a discussion of geometric vs. probabilistic estimators see here: https://www.biorxiv.org/content/10.1101/2020.08.19.256859v2].

## Implementation in `amt`

`amt` currently implements all methods to calculate overlaps that were reviewed by Fieberg and Kochany (2005). These are: 

- `hr`: That is the proportion of the home range of instance $i$ that overlaps with the home range of instance $j$. This measure does not rely on a UD and is directional (i.e., $HR_{i,j} \ne HR_{j,i}$) and bound between 0 (no overlap) and 1 (complete overlap)
- `phr`: Is the probability of instance $j$ being located in the home range of instance $i$. `phr` is also directional and bounded between 0 (no overlap) and 1 (complete overlap)
- `vi`: The volumetric intersection between two UDs.
- `ba`: The Bhattacharyya's affinity between two UDs. 
- `udoi`: A UD overlap index. 
- `hd`: Hellinger's distance between two UDs. 

These overlap indices can be calculated with the function `hr_overlap`. The type of overlap measure an be controlled with the argument `type`. 

All of these estimators can be calculated for a given home-range level (i.e., using conditional UDs). Whether or not a conditional overlap is desired or not, can be controlled with the argument `conditional`. For `hr`, the argument `conditional` has no effect and the isopleths used for home-range estimation will always be used for the overlap calculation. 

The function `hr_overlap()` can also be provided with a list of home-range estimates in situations when overlap between many different instances are required. Currently, there are three options for calculating overlap among multiple instances: `which = "all"` calculates overlap for each pair of home ranges, `which = "one_to_all"` calculates overlap between the first element in the list and all others, and `which = "consecutive"` will calculate overlap between consecutive elements in the list. 


## Examples

First we need to load the required packages: 

```{r}
library(amt)
library(ggplot2)
library(tidygraph)
library(ggraph)
```

### Two instances

We will use tracking data from Fishers from New York State, USA. 

```{r}
leroy <- amt_fisher |> filter(name == "Leroy")
lupe <- amt_fisher |> filter(name == "Lupe")
```

Create a template raster for the KDE

```{r}
trast <- make_trast(amt_fisher |> filter(name %in% c("Leroy", "Lupe")), res = 50)
```

And estimate home-ranges for both fishers

```{r}
hr_leroy <- hr_kde(leroy, trast = trast, levels = c(0.5, 0.9))
hr_lupe <- hr_kde(lupe, trast = trast, levels = c(0.5, 0.9))
```

`hr` and `phr` are directional, this means the order matters. For all other overlap measures the order does not matter. 

```{r}
hr_overlap(hr_leroy, hr_lupe, type = "hr") 
hr_overlap(hr_lupe, hr_leroy, type = "hr")
```

By default `conditional = FALSE` and the full UD is used.

```{r}
hr_overlap(hr_leroy, hr_lupe, type = "phr", conditional = FALSE) 
hr_overlap(hr_lupe, hr_leroy, type = "phr", conditional = FALSE)
```

If we set `conditional = TRUE`, the overlap is measured at home-range levels that were specified during estimation. 

```{r}
hr_overlap(hr_leroy, hr_lupe, type = "phr", conditional = TRUE) 
hr_overlap(hr_lupe, hr_leroy, type = "phr", conditional = TRUE)
```

Note, for the remaining overlap measures the order does not matter. Below
we show this for the volumnic intersection (`type = "vi"`) as an example. 

```{r}
hr_overlap(hr_lupe, hr_leroy, type = "vi", conditional = FALSE)
hr_overlap(hr_leroy, hr_lupe, type = "vi", conditional = FALSE)
```

### $> 2$ instances

Lets calculate daily ranges for Lupe and then and then see how different
ranges overlap with each other.

We have to use the same template raster in order to make ranges comparable. 

```{r}
trast <- make_trast(lupe, res = 50)
```

Then we add a new column with day and calculate for each day a `KDE` home range. 

```{r}
dat <- lupe |> 
  mutate(week = lubridate::floor_date(t_, "week")) |> 
  nest(data = -week) |> 
  mutate(kde = map(data, hr_kde, trast = trast, levels = c(0.5, 0.95, 0.99)))
```
  
Now we can use the list column with the home-range estimates to calculate
overlap between the different home-ranges. By default `which = "consecutive"`, this means for each list entry (= home-range estimate) the overlap to the next entry will be calculated.

```{r}
hr_overlap(dat$kde, type = "vi")
```

This works as well, if we set `conditional = TRUE`:

```{r}
hr_overlap(dat$kde, type = "vi", conditional = TRUE)
```

Sometimes it can be useful to provide meaningful labels. We can do this with
the `labels` argument.

```{r}
hr_overlap(dat$kde, type = "vi", labels = dat$week)
```

Different options exist for the argument `which`. For example, `which = "one_to_all"` calculates the overlap between the first and all other home ranges. 

<!--
Finally, we can calculate the overlap between all elements inside a list (use
`which = "all"` for this). We will use the `puechcir` from the `adehabitatLT` package to illustrate this. 


```{r, eval = FALSE}
data("puechabon", package = "adehabitatLT")
dat <- puechabonsp$relocs |> as.data.frame() |> 
  make_track(X, Y, id = Name)
trast <- make_trast(dat, res = 50)
dat1 <- dat |> nest(data = -id) |> 
  mutate(kde = map(data, ~ hr_kde(., trast = trast, level = c(0.5, 0.9, 0.99))))
```

Now we can calculate the overlaps between animals: 

```{r, fig.width=7, fig.height=7, eval = FALSE}
ov2 <- hr_overlap(dat1$kde, type = "hr", labels = dat1$id, which = "all", 
                  conditional = TRUE) |> 
  filter(overlap > 0)
graph <- as_tbl_graph(ov2) |> 
  mutate(Popularity = centrality_degree(mode = 'in')) 

ggraph(graph, layout = 'stress') + 
  #geom_edge_fan(aes(col = overlap), show.legend = TRUE, arrow = arrow()) + 
  geom_edge_arc(aes(col = overlap), arrow = arrow(length = unit(4, 'mm'), type = "closed"), 
                start_cap = circle(3, 'mm'),
                end_cap = circle(3, 'mm')) + 
  geom_node_point(size = 4) + 
  geom_node_label(aes(label = name), repel = TRUE, alpha = 0.7) +
  facet_edges(~ levels, ncol = 2) + 
  theme_light() +
  scale_edge_color_gradient(low = "blue", high = "red")
```
-->
  
## Overlap between a home range and a simple feature

The function `hr_overlap_feature` allows to calculate percentage overlap ($HR$ index) between a home. To illustrate this feature, we will use again the data from `lupe` and calculate the intersection with an arbitrary polygon. 

```{r}
poly <- amt::bbox(lupe, buffer = -500, sf = TRUE)
poly1 <- amt::bbox(lupe, sf = TRUE)
hr <- hr_mcp(lupe)
ggplot() + geom_sf(data = hr_isopleths(hr)) + 
  geom_sf(data = poly, fill = NA, col = "red") +
  geom_sf(data = poly1, fill = NA, col = "blue")
```
```{r}
hr_overlap_feature(hr, poly, direction = "hr_with_feature")
hr_overlap_feature(hr, poly1, direction = "hr_with_feature")

hr_overlap_feature(hr, poly, direction = "feature_with_hr")
hr_overlap_feature(hr, poly1, direction = "feature_with_hr")
```

The same work with several home-range levels:

```{r}
hr <- hr_mcp(lupe, levels = c(0.5, 0.9, 0.95))
hr_overlap_feature(hr, poly, direction = "hr_with_feature")
```


## References
- Fieberg, J., & Kochanny, C. O. (2005). Quantifying home‐range overlap: the importance of the utilization distribution. The Journal of Wildlife Management, 69(4), 1346-1359.


## Session
```{r}
sessioninfo::session_info()
```

