--- title: "PhysMove: Movement Patterns" author: "Hannah J. Calich, Jorge Rodríguez, Víctor Eguíluz & Ana M. M. Sequeira" date: "Last updated: `r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{PhysMove: Movement Patterns} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(dev = "png", dpi = 120, fig.width = 5, fig.height = 4, out.width = "70%", fig.align = "center", echo = TRUE, collapse = TRUE, comment = "#>") ``` ## Index 1. [Introduction and data preparation](pt1_introduction.html) 2. [Movement patterns](pt2_movement_patterns.html) 3. [Space-use patterns](pt3_space_use_patterns.html) 4. [Intraspecific movements](pt4_intraspecific_movements.html) ## *Movement patterns* *PhysMove* includes 5 metrics for quantifying movement patterns that are based on ten functions, including: * [Scale of movement](pt2_movement_patterns.html#scale-of-movement): `rms()` * [Movement patterns across temporal scales](pt2_movement_patterns.html#movement-patterns-across-temporal-scales): `calcDisp()` and `plotDispPDF()` * [Search patterns](pt2_movement_patterns.html#search-patterns): `fitDist()`, `compDist()`, and `plotDist()` * [Influence of correlations on movement decisions](pt2_movement_patterns.html#influence-of-correlations-on-movement-decisions): `randomise()` and `plotRandomTracks()` * [Turning angles](pt2_movement_patterns.html#turning-angles): `turningAngles()` and `plotAngles()` ```{r load physmove movement vignette, echo=FALSE} # Load PhysMove library(PhysMove) ``` ## Scale of movement The `rms()` function provides insights into how movement scales with time by calculating mean and root-mean-square (RMS) displacements and plotting them over time (Figure V2). `rms()` requires a data frame with telemetry data (see [data formatting](pt1_introduction.html#data-formatting)) and includes four optional parameters: * `timeUnit`: time unit used to calculate the time between locations (`timeUnit= "days"`, by default), * `wBins`: width of the time bins used to calculate how frequently displacements occurred (`wBins=1.1`, by default), * `plot`: create a scatter plot (`plot=TRUE`, by default), and * `lm`: fit a linear model to examine the relationship between root-mean-square displacements and time (`lm=TRUE`, by default). `rms()` results are output as a list. The first list element is a data frame of results with three columns: * *timeWindow*: binned time windows in whatever unit was set using `timeUnit` * *meanDisplacements*: mean displacement values in km that correspond with *timeWindow* * *rmsDisplacements*: root-mean-square displacement values that correspond with *timeWindow* The second list element is a data frame of results from the linear model and is only exported when `lm=TRUE`. The slope of the linear model describes how displacement scales with time. Note that because `rms()` calculates all displacements in each track, this function can take time. Progress updates will appear when calculations are 25%, 50%, 75%, and 100% complete. ```{r calculate_rms} # Calculate RMS values with default parameters rms.result <- rms(tracks) ``` **Figure V2** Scatter plot of mean (grey points; q=1) and root-mean-square (RMS; black points; q=2) displacements (d) in kilometers (km) from `'tracks'` dataset over time (T) in days, fit to a linear model (red line with standard error shaded in grey). Plot created with `rms()` default parameters. ```{r summarise rms results} # Summarise RMS results summary(rms.result[["rmsResults"]]) # Summarise linear model results and identify the scaling exponent RMSlinearModel <- rms.result[["lm"]] print(RMSlinearModel) # Determine the scaling exponent RMSlinearModel$estimate[2] ``` [Back to top](pt2_movement_patterns.html) ## Movement patterns across temporal scales The `calcDisp()` function calculates displacements travelled in kilometres over set time windows. `calcDisp()` requires a data frame with telemetry data (see [data formatting](pt1_introduction.html#data-formatting)) and has four optional parameters that allow you to change different aspects of the time windows: * `min_hr` and `max_hr`: set the minimum and maximum times between location estimates in hours, respectively (`min_hr=24` and `max_hr=240`, by default), * `interval_hr`: set the time interval in hours. This parameter creates a sequence of time windows between the minimum and maximum times over the set time interval (`interval_hr=24`, by default), and * `range_hr`: set the range in hours. This parameter allows the code to identify location estimates that are close to, but not exactly separated by the `interval_hr` input value (`range_hr=6`, by default). For example, by default, `calcDisp()` calculates displacements between location estimates separated by 10 time windows: 24 ± 6 hours, 48 ± 6 hours, 72 ± 6 hours, etc., until 240 ± 6 hours. Note that displacements smaller than 0.001 km (1 m) are excluded to avoid zero or near-zero values arising from duplicated or stationary locations. `calcDisp()` outputs a list where each list element contains the displacements calculated over a time window, such that the first list element contains data from the first time window and so on. For example, by default, the first list element includes displacements calculated over 24 ± 6 hours, and the tenth list element includes displacements calculated over 240 ± 6 hours. ```{r calc disp, eval=FALSE} # Calculate displacements with default parameters dispAll <- calcDisp(tracks) # [1] "15598 displacements in 24 +/- 6 hour(s)" # [1] "15573 displacements in 48 +/- 6 hour(s)" # [1] "15548 displacements in 72 +/- 6 hour(s)" # [1] "15523 displacements in 96 +/- 6 hour(s)" # [1] "15498 displacements in 120 +/- 6 hour(s)" # [1] "15473 displacements in 144 +/- 6 hour(s)" # [1] "15448 displacements in 168 +/- 6 hour(s)" # [1] "15423 displacements in 192 +/- 6 hour(s)" # [1] "15398 displacements in 216 +/- 6 hour(s)" # [1] "15373 displacements in 240 +/- 6 hour(s)" ``` ```{r load example disp data, include=FALSE} # Load example dataset included in the package data("dispAll", package = "PhysMove") ``` ```{r sum disp all} # Summarise displacements calculated over the first time window (24 ± 6 hrs) summary(unlist(dispAll[[1]])) ``` ### Probability density function (pdf) of displacements Probability density functions (pdfs) of displacements describe the probability distribution of the displacements and can be used to calculate the probability of displacements occurring (Figures V3 to Figure V4). The `plotDispPDF()` function requires a list of displacements calculated using `calcDisp()` and includes 3 optional parameters: * `normalise`: normalise the data before plotting, which divides all displacements in a time window by the mean displacement for that time window (`normalise=TRUE`, by default). * `colours`: change the point colours (`colours=rainbow`, by default) and * `legend`: add or remove a legend (`legend=TRUE`, by default). `plotDispPDF()` outputs a data frame of all data used to create the plot, including: * *pdf*: pdf values, * *disp*: binned displacement values (note that if `normalise=TRUE` the displacements are normalised values), and * *timeWindow*: corresponding time windows ```{r plot all norm disp} # Create a probability density function (pdf) plot of normalised # displacements plot.data <- plotDispPDF(dispAll) ``` **Figure V3** Probability density function (pdf) plot of normalised displacements from the `'tracks'` dataset calculated over 10 time windows, 24 to 240 hours at 24 ± 6-hour time intervals with `calcDisp()`. Plot created with `plotDispPDF()` default parameters (i.e., where `normalise=TRUE`). ```{r plot all disp (not norm)} # Create a probability density function (pdf) plot of raw (i.e., not # normalised) displacements plot.data.norm <- plotDispPDF(dispAll, normalise=FALSE) ``` **Figure V4** Probability density function (pdf) plot of displacements from the `'tracks'` dataset calculated over 10 time windows, 24 to 240 hours at 24 ± 6-hour time intervals with `calcDisp()`. Plot created with `plotDispPDF()` where `normalise=FALSE`. [Back to top](pt2_movement_patterns.html) ## Search patterns *PhysMove* can be used to identify the best-fit distribution of displacements, which can provide insights into the search pattern(s) a species may use to locate resources. Determining the best-fit distribution for the displacements involves 3 functions: 1. `fitDist()`: Fits cdfs of continuous power-law, exponential, and lognormal distributions over the full range of displacements (i.e., full distributions) or to displacements truncated by a minimum value (i.e., truncated distributions). The `fitDist()` function requires a list of values (e.g., displacements calculated using `calcDisp()`) and includes four optional parameters: * `dist`: distributions you want to fit to the displacement data. `fitDist()` can fit continuous power-law ("pl"), exponential ("exp"), and lognormal ("lnorm") distributions (`dist=c("pl","exp","lnorm")`, by default). To fit only one or two distributions simply remove the distribution(s) you are not interested in running, e.g., `dist=c("exp","lnorm")`. * `set_dmin`: To limit the fitted distribution to values above a specified value. If your data are going to be normalised this value will have to be a normalised value as well. Default = NULL. * `full`: determines if distributions are fit over the full range of displacement data (`full=TRUE`), or to displacements truncated by a minimum value (`full=FALSE`, by default) * `normalise`: normalise displacements before fitting distributions (`normalise=TRUE`, by default). Displacements should be normalised if they were calculated over multiple temporal periods. `fitDist()` outputs a list including two list elements. The first list element is a data frame that includes: * *distribution*: all distributions fit to the displacement data (pl, exp, or lnorm), * *dmin*: minimum value used to fit each distribution * *parameter 1*: first parameter for each distribution (i.e., α, λ, or μ for pl, exp, and lnorm, respectively) * *parameter 2*: second distribution parameter (i.e., σ, only applicable to lnorm), and * *nTail*: number of values greater than or equal to dmin. The second list element is a logical argument that records if the displacements were normalised (TRUE) or not (FALSE). This information is required for `plotDist()` and `compDist()`. 2. `plotDist()`: Uses the results from `fitDist()` to plot ccdfs of the displacements with fit lines for each distribution. The `plotDist()` function requires a list of values (e.g., calculated using `calcDisp()`) and results from `fitDist()`, and includes four optional parameters: * `fitLines`: add fit lines for each distribution (`fitLines=TRUE`, by default), * `setDist`: plot only specific distributions (`setDist=NULL`, by default, which will plot all distributions), * `colours`: change the colours of the fit lines (`colours=c("red","gold2","blue")`, by default), * `legend`: add a legend (`legend=TRUE`, by default), and * `label`: X axis label. Note that "Normalised" will automatically be added if distributions were fit to normalised data. Default = NULL and will result in x-axis label of "input data". `plotDist()` outputs a plot and a data frame of the displacements (x values) and ccdf values (y values) used in the plot. 3. `compDist()`: Compares distribution fits from `fitDist()` and identifies the best-fit distribution for the displacements. Note that `compDist()` can only be used when all distributions are fit to the same range of data (e.g., when `full=TRUE` or if `set_dmin≠NULL`). See Figure V5 for a methods overview. The `compDist()` function requires a list of displacements calculated using `calcDisp()`, the results from `fitDist()`, and includes one optional parameter: * `force_AICc`: force `compDist()` to calculate an AICc (`force_AICc=FALSE`, by default). By default, `compDist()` compares distribution fits using weighted AICc scores (AIC scores corrected for small sample sizes) when the ratio of sample size (*nTail*) to the number of parameters (K) is ≤ 40, based on the model with the largest K; else, weighted AIC scores are calculated, following Burnham and Anderson (2004). `force_AICc` is used to calculate an AICc instead of an AIC score (if `force_AICc` = TRUE). The highest wAIC or wAICc score from each comparison indicates the best-fit distribution. `compDist()` outputs a data frame that contains the summary statistics for each distribution fit (as described for `fitDist()`) with the corresponding *AICc*/*AIC* scores and weighted AICc/AIC scores (*wAICc*/*wAIC*). The distribution with the highest *wAIC* or *wAICc* score from each comparison is the best-fit distribution. **Figure V5** Diagram outlining the procedure for identifying the best-fit distribution of displacements. ### Search patterns example In the example below we calculate displacements over 24 ± 6 hours, plot a pdf of the displacements, and identify the best-fit distributions for both full and truncated datasets. Using a single time window helps keep run times manageable, while still capturing the overall displacement patterns. In general, we recommend fitting distributions to both full and truncated datasets to gain a comprehensive understanding of displacement patterns. We begin by calculating displacements over 24 ± 6 hours with `calcDisp()` and plotting a pdf of the displacements with `plotDispPDF()` (Figure V6). ```{r calc disp over 24 hours} # Calculate displacements over 24 ± 6 hours disp <- calcDisp(tracks, max_hr=24) # Summarise displacements summary(unlist(disp)) # Plot displacements (as displacements were only calculated over one time window they do not need to be normalised) plot.data.pdf <- plotDispPDF(disp, normalise=FALSE) ``` **Figure V6** Probability density function (pdf) plot of displacements calculated using `calcDisp()` with `max_hr=24`. Plot created with `plotDispPDF()` and `normalise=FALSE`. #### Fitting full distributions We use `fitDist()` to fit the full range of distributions calculated over 24 ± 6 hours to power-law, exponential, and lognormal distributions, and `plotDist()` to visualise the results (Figure V7). ```{r fit full dist} # Fit all distributions to the full range of displacement data distResults <- fitDist(disp, full=TRUE, normalise=FALSE) distResults[["distResults"]] ``` ```{r plot full dist} # Create a ccdf plot of displacements with fit lines illustrating # distributions fit to the full range of displacements plot.data.all.pdf <- plotDist(disp, distResults, label="Displacements (km)") ``` **Figure V7** Complementary cumulative distribution function (ccdf) of displacements (calculated using `calcDisp()` with `max_hr=24`). Plot includes fit lines for power-law (pl), exponential (exp), and lognormal (lnorm) distributions based on results from `fitDist()` with `full=TRUE`. Plot created using `plotDist()` default parameters. Next, we use `compDist()` to compare distribution fits over the full range of displacement data. ```{r comp dist fits} # Identify the best-fit distribution for the full range of displacement data compResults <- compDist(disp, distResults) compResults ``` #### Fitting truncated distributions We use `fitDist()` to identify the best-fit dmin for each distribution and fit truncated power-law, exponential, and lognormal distributions to displacements calculated over 24 ± 6 hours. We visualise results with `plotDist()` (Figure V8). ```{r load example dispTrunc data, include=FALSE} data("distResultsTrunc", package = "PhysMove") ``` ```{r find best-fit dmin for each dist, eval=FALSE} # Fit all distributions and identify the best-fit dmin for each distribution distResultsTrunc <- fitDist(disp, full=FALSE, normalise=FALSE) ``` ``` {r print dist results trunc} print(distResultsTrunc[["distResults"]]) ``` ```{r plot trunc dist} # Create a ccdf plot of displacements with fit lines illustrating # distributions fit to the best-fit dmin for each distribution plot.data.all.trunc <- plotDist(disp, distResultsTrunc, label="Displacements (km)") ``` **Figure V8** Complementary cumulative distribution function (ccdf) of displacements calculated using `calcDisp()` with `max_hr=24` including fit lines for truncated power-law (pl), exponential (exp), and lognormal (lnorm) distributions based on the best-fit dmin results from `fitDist()`. Plot created using `plotDist()` default parameters. Since each distribution was fit to a different range of data (i.e., *nTail* values are different for each distribution), we cannot run `compDist()` directly. Instead, we must make pairwise comparisons where `fitDist()` is re-run three times (once for each of the three distributions) where the `set_dmin` parameter is set to each of the best-fit dmin values in turn. ```{r fit dist with pl} # Fit all distributions using the dmin value for the # power-law distribution dmin <- distResultsTrunc[["distResults"]][1,2] distResultsPl <- fitDist(disp, set_dmin=dmin, normalise=FALSE) ``` ```{r fit dist with exp} # Fit all distributions using the dmin value for the # exponential distribution dmin <- distResultsTrunc[["distResults"]][2,2] distResultsExp <- fitDist(disp, set_dmin=dmin, normalise=FALSE) ``` ```{r fit dist with lnorm} # Fit all distributions using the dmin value for the # lognormal distribution dmin <- distResultsTrunc[["distResults"]][3,2] distResultsLnorm <- fitDist(disp, set_dmin=dmin, normalise=FALSE) ``` Once all distributions are fit using each of the best-fit dmin values, the distribution fits can be compared using `compDist()`. An important consideration for interpreting the `compDist()` results from pairwise comparisons is that if a dmin was set to favour a specific distribution, but the *wAIC* (or *wAICc*) scores do not identify that distribution as the best fit, the distribution corresponding to the dmin value is not the best-fit distribution for the displacements. For example, in the first pairwise comparison below, you'll see the dmin was set to the best-fit dmin for a power-law (20.87); however, the *wAIC* scores identified an exponential distribution as the best fit. Therefore, we conclude that a power-law is not the best-fit distribution for the data. ```{r comp pl} # Compare distribution fits based on the best-fit dmin value for the power-law distribution compResultsPl <- compDist(disp, distResultsPl) compResultsPl ``` ```{r comp exp} # Compare distribution fits based on the best-fit dmin value for the exponential distribution compResultsExp <- compDist(disp, distResultsExp) compResultsExp ``` ```{r comp lnorm} # Compare distribution fits based on the best-fit dmin value for the lognormal distribution compResultsLnorm <- compDist(disp, distResultsLnorm) compResultsLnorm ``` Overall conclusion: The data were best-fit to both full and truncated exponential distributions, when compared with power-law and lognormal distributions. Because the full distribution includes all of the data we will refer to the full distribution when presenting and discussing our final results. [Back to top](pt2_movement_patterns.html) ## Influence of correlations on movement decisions The `randomise()` function can be used to gain insights into how correlations influenced a species' movements and space-use (Figure V9). `randomise()` requires a data frame with telemetry data (see [data formatting](pt1_introduction.html#data-formatting)) and includes four optional parameters: * `randTrack`: change the number of randomised tracks that are created (`randTrack=100`, by default), * `gridCell`: change the grid cell size in degrees (`gridCell=0.25`, by default), * `plot`: create a scatter plot of the results (`plot=TRUE`, by default), and * `lm`: fit a linear model to the average number of grid cells visited by the randomised tracks and the number of grid cells visited by the original tracks (`lm=TRUE`, by default). The slope of this model can be used to discuss how correlations may have influenced interpretations of movement. `randomise()` outputs a list with three list elements. The first list element is a data frame with three columns: * *ref*: the reference ID numbers for each track, * *CellsInOriginalTracks*: the number of grid cells visited by the original tracks, and * *AvgCellsInRandomisedTracks*: the average number of grid cells visited by the randomised tracks. The second and third list elements contain the randomised longitude and latitude values, respectively, which are needed for the `plotRandomTracks()` function ```{r randomise tracks} # randomise() involves random number selection, so setting a seed enables the replication of results set.seed(1) # Randomise tracks from the 'tracks' dataset with default parameters randomise.result <- randomise(tracks) ``` **Figure V9** Scatter plot illustrating the relationship between the number of grid cells visited by the original tracks from the `'tracks'` dataset and the average number of grid cells visited by the randomised tracks. The solid black line represents the linear model fit to this data, the grey shaded area reflects the standard error of the fit, and the dashed black line represents a 1:1 relationship. Plot created with `randomise()` default parameters. ```{r view random results} # Summarise RMS results summary(randomise.result[["resultsDF"]]) # Determine the slope of the linear model RandomiselinearModel <- randomise.result[["lm"]] print(RandomiselinearModel) # Determine the slope without displaying the full linear model summary RandomiselinearModel$estimate[2] ``` ### Plot randomised tracks To visualise the tracks created with `randomise()` you can use `plotRandomTracks()` (Figure V10). `plotRandomTracks()` requires three parameters: 1. data frame with telemetry data (see [data formatting](pt1_introduction.html#data-formatting)), 2. reference ID of the track you want to map (ref must be included in the telemetry data frame), and 3. results from `randomise()`. `plotRandomTracks()` also includes 6 optional parameters: * `numPlot`: the number of randomised tracks to plot (`numPlot=1:5`, by default, which will plot the first 5 randomised versions of each track), * `colours`: the colours of the original and randomised location estimates, respectively (`colours=c("black","grey70")`, by default), * `tracks`: connect points with lines (`tracks=TRUE`, by default), * `startCol` and `endCol`: change the colours of the starting and ending points of each track, respectively (`startCol="red"` and `endCol = "blue"`, by default), and * `legend`: add a legend (`legend=TRUE`, by default). `plotRandomTracks()` outputs the data used to create the map in three columns: * *randTrack*: ID number of the random track, * *lon*: longitude coordinates of the randomised tracks, and * *lat*: latitude coordinates of the randomised tracks. ```{r plot random tracks} # Plot random tracks for 'tracks' dataset reference ID 1 plot.data.random.tracks <- plotRandomTracks(tracks, ref=1, randomise.result) ``` **Figure V10** Map illustrating the original track for reference ID 1 from the `'tracks'` dataset (black points and line) and the first 5 randomised tracks for track reference ID 1 calculated using `randomise()` (grey points and lines). The starting and ending locations are in red and blue, respectively. Plot created with `plotRandomTracks()` default parameters and `ref=1`. [Back to top](pt2_movement_patterns.html) ## Turning angles The `turningAngles()` function calculates turning angles between sets of three consecutive location estimates separated by set time windows to describe how species explore their habitats (Figure V11). `turningAngles()` requires a data frame with telemetry data (see [data formatting](pt1_introduction.html#data-formatting)) and includes 5 optional parameters: * `min_hr` and `max_hr`: set the minimum and maximum times between location estimates in hours (`min_hr=24` and `max_hr=240`, by default), * `interval_hr`: set the time interval in hours, which creates a sequence of time windows between the minimum and maximum times over a set time interval (`interval_hr=24`, by default), * `range_hr`: set the range in hours, which allows the code to identify location estimates that are close to, but not exactly separated by the `interval_hr` input value (`range_hr=6`, by default), and * `histPlot`: output a histogram and control if "all" time windows are plotted or if only a specific time window is plotted, in which case "all" is replaced with a number corresponding to the desired time window, e.g., `histPlot=c(TRUE,1)` will plot the first time window (`histPlot=c(TRUE,"all")`, by default). Results are output in a list where each list element contains the angles calculated over a time window, such that the first list element contains data from the first time window and so on. ```{r load example angle data, include=FALSE} data("angleListAll", package = "PhysMove") ``` ```{r calc turn angles, eval=FALSE} # Calculate turning angles in the 'tracks' dataset using default parameters angleListAll <- turningAngles(tracks) # [1] "15573 angles in 24 +/- 6 hour(s)" # [1] "15523 angles in 48 +/- 6 hour(s)" # [1] "15473 angles in 72 +/- 6 hour(s)" # [1] "15423 angles in 96 +/- 6 hour(s)" # [1] "15373 angles in 120 +/- 6 hour(s)" # [1] "15323 angles in 144 +/- 6 hour(s)" # [1] "15273 angles in 168 +/- 6 hour(s)" # [1] "15223 angles in 192 +/- 6 hour(s)" # [1] "15173 angles in 216 +/- 6 hour(s)" # [1] "15123 angles in 240 +/- 6 hour(s)" ``` ```{r plot histogram from turningAngles, echo=FALSE} # Histogram of all angles combined - directly from turningAngles code bins <- 360 / 45 angleListAll <- angleListAll[lengths(angleList)>0] angles.df <- as.data.frame(unlist(angleListAll)) names(angles.df) <- "Angles" h <- graphics::hist(angles.df$Angles, plot = FALSE, breaks = seq(-180, 180, bins)) # Plot all angles for all time periods from all individuals xlabels <- c("-180", "", "-120", "", "-60", "", "0", "", "60", "", "120", "", "180") hist_plot <- ggplot2::ggplot(angles.df, ggplot2::aes(.data$Angles))+ ggplot2::geom_histogram(breaks=h$breaks, color="black", fill="darkgrey")+ ggplot2::scale_x_continuous("Turning Angles", breaks=seq(-180,180,30), labels=xlabels)+ ggplot2::labs(y="Frequency")+ ggplot2::theme_classic(base_size=12) plot(hist_plot) ``` **Figure V11** Histogram of turning angles from the `'tracks'` dataset over ten time windows (24 to 240 hours at 24 ± 6 hour intervals). Plot created with `turningAngles()` default parameters. ```{r summarise turning angles} # Summarise turning angles calculated over the first time window summary(angleListAll[[1]]) ``` ### Create a circle plot Results from `turningAngles()` can be visualised with the `plotAngles()` function, which creates a circle plot (also known as a spider or radar plot) showing the frequency of turning angles over each time window (Figure V12). `plotAngles()` requires the list of angles output from `turningAngles()` and includes 3 optional parameters: * `timePlot`: control if "all" time windows or only specific windows are plotted (`timePlot="all"`, by default), * `colours`: change line colours (`colours=rainbow`, by default), and * `legend`: add a legend (`legend=TRUE`, by default). `plotAngles()` outputs a data frame of all data used to create the circle plot, including: * *timeWindows*: the time windows * *frequency*: turning angle frequency, and * *angle*: turning angles in degrees ```{r plot angles with a circle plot} # Plot angles with a circle plot plot.data.angles <- plotAngles(angleListAll) ``` **Figure V12** Circle plot of turning angles recorded from the `'tracks'` dataset during ten time windows (24 to 240 hours at 24 ± 6 hour intervals). Plot created with `plotAngles()` default parameters. [Proceed to Space-Use Patterns](pt3_space_use_patterns.html) [Back to top](pt2_movement_patterns.html) ## References & Recommended resources
Burnham, K.P. & Anderson, D.R. (2004) Multimodel Inference: Understanding AIC and BIC in Model Selection. *Sociological Methods & Research*, 33, 261-304. Calich, H.J. *et al*. (2021) Comprehensive analytical approaches reveal species-specific search strategies in sympatric apex predatory sharks. *Ecography*, 44, 1544-1556. Farage, C. *et al*. (2021) Identifying flow modules in ecological networks using Infomap. *Methods in Ecology and Evolution*, 12, 778–786. Méndez, V., *et al*. (2013). Stochastic Foundations in Movement Ecology: Anomalous Diffusion, Front Propagation and Random Searches. Berlin, Heidelberg, Germany, Springer Berlin / Heidelberg. Rodríguez, J.P. *et al*. (2017) Big data analyses reveal patterns and drivers of the movements of southern elephant seals. *Scientific* *Reports*, 7, 1-10. Viswanathan, G. M., *et al*. (2011). The Physics of Foraging: An Introduction to Random Searches and Biological Encounters. Cambridge, Cambridge University Press. Wickham, H. (2016) ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag, New York.