This package combines a set of functions for analysing multisensor geolocator data such as Pressure, Activity, Magnetism, Temperature or Light. This includes functions for importing and visualising any or all of these sensor data, formatting the data for analysis (with some functions already setup for birds), deriving classifications (using cluster analysis or hidden markove models), and finally for comparing classification accuracy between different models.
The manual is the best way to get started with the package, and can be found at the following link: https://kiranlda.github.io/PAMLrManual/index.html
To install this package from github, make sure the user first have devtools
installed.
install.packages("devtools")
Then the package can be installed from github:
devtools::install_github("KiranLDA/PAMLr")
Data can be imported as follows:
library(PAMLr) PAM_data = importPAM(pathname = "C:/Put/your/path/here", measurements = c(".pressure", ".glf", ".acceleration", ".temperature", ".magnetic")`
An example dataset is
data(hoopoe)
Note that very often, a logger continues to record data before and after it is removed from a bird. For example, it might be transported in a rucksack or left in a laboratory until data are downloaded. It's therefore important to remove these incorrect datapoints. This can be done using cutPAM
.
# make sure the cropping period is in the correct date format start = as.POSIXct("2016-07-01","%Y-%m-%d", tz="UTC") end = as.POSIXct("2017-06-01","%Y-%m-%d", tz="UTC") # Crop the data PAM_data= cutPAM(hoopoe,start,end)
For a quick look at the data, it's possible to use quickPLOT
. The user can specify which arguments to use, using measurements
. There's a choice between different combinations of "pressure"
, "light"
, "acceleration"
, "temperature"
and "magnetic"
. You can add any parameters from ?plot
, here I illustrate it with col="cornflowerblue"
and by showing how to restrict the x-axis limits xlim
with the date format, to zoom into the post breeding mihration period of a hoopoe
par(mar=c(3,4,0.5,0.5)) quickPLOT(hoopoe, col="cornflowerblue", measurements = c("pressure", "light", "acceleration"), xlim=c(as.POSIXct("2016-08-20","%Y-%m-%d", tz="UTC"), as.POSIXct("2016-09-01","%Y-%m-%d", tz="UTC")))
To have a better overview of the data, it is possible to create interactive dygraphPAM()
plots which allow the user to compare different measurements recorded by the logger. These might for instance include light, temperature, pressure, activity, pitch and magnetism.
If you are working from Rstudio, this bit of code should be run:
# In Rstudio, it will display in the viewer by default and use a lot of ram, and is better in html backup_options <- options() options(viewer=NULL) # ensure it is viewed in internet browser dygraphPAM(dta = PAM_data) # plot options(backup_options) # restore previous viewer settings
If you are working from base R use this instead:
To save space here we only plot only one variable - pressure .
dygraphPAM(dta = PAM_data, toPLOT = c("pressure"))
The reason there is additional code for Rstudio, is that by default it will open this graphic in the viewer pane and use up a lot of ram. This additional code allows the user to open this window in a browser instead of r studio, and the file can later be saved as an html file.
With this interactive plot, the user can then zoom in and out of different plots to help get a feel for the data. For instance, this is a great way of seeing changes in the data which might be due to a logger being in a rucksack and no longer on the birds, or to look at how acticity or pressure might look during migration periods.
It is possible to select areas to zoom into by right clicking and highighting certain regions, and to double click to zoom out. All plots are synched to the same time period and have a timeline at the bottom to increase or decrease the time over which the data is observed.
Actograms are often used to plot activity over time at different hours of the day. However, the same approach can be used to plot any sensor data, not just activity. For simplicity, we name these “sensor images”. Plotting all sensors side by side is an important step for visualising data and developing an understanding of data patterns, and to start thinking about the behaviours that may be driving the observed patterns. PAMLr offers a function sensorIMG()
for plotting sensor images, which can be implemented as follows.
# Create plots with 3 together (mfrow) par( mfrow= c(1,3), oma=c(0,2,0,6)) par(mar = c(4,2,4,2)) sensorIMG(PAM_data$acceleration$date, ploty=FALSE, PAM_data$acceleration$act, main = "Activity", col=c("black",viridis::cividis(90)), cex=1.2, cex.main = 2) par(mar = c(4,2,4,2)) sensorIMG(PAM_data$pressure$date, plotx=TRUE, ploty=FALSE, labely=FALSE, PAM_data$pressure$obs, main="Pressure", col=c("black",viridis::cividis(90)), cex=1.2, cex.main = 2) par(mar = c(4,2,4,2)) sensorIMG(PAM_data$temperature$date, labely=FALSE, PAM_data$temperature$obs, main="Temperature", col=c("black",viridis::cividis(90)), cex=1.2, cex.main = 2)
Histograms can provide a first impression of whether some of the data may be aggregated and therefore clustered. Indeed, sensor images may not always well-suited for visualising tri-axial data, such as magnetic field or acceleration. By plotting data in three dimensions (hereafter “3D”) using the function pam3D
it’s possible to find patterns or clusters of datapoints which would not otherwise be apparent in the data. Here we plot magnetic data.
pam3D(PAM_data$magnetic$gX, PAM_data$magnetic$gY, PAM_data$magnetic$gZ, xlab= "X", ylab= "Y", zlab= "Z", xlim=c(-3000,3000), ylim=c(-3000,3000), zlim=c(-3000,3000))
A g-sphere is a method of visualising tri-axial acceleration data. This involves centering the data and plotting it on a sphere.The function triACC
allows the user to center this data (as well as calculating pitch, roll and yaw from the data)
# plot an g-phere calibration = triACC(dta = PAM_data$magnetic) pamSPHERE(x = calibration$centered_accx, y = calibration$centered_accy, z = calibration$centered_accz, ptcol = "royalblue", ptsize = 0.03, linecolor ="orange", spherecolor="orange", arrows=TRUE)
An m-sphere is a method of visualising tri-axial magnetometer data. This involves centering the data and correcting the data, before plotting it on a sphere.The function triMAG
calibrates the data. This provides the animal's bearing.
# plot a m-phere calibration = triMAG(dta = PAM_data$magnetic) pamSPHERE(x = calibration$calib_magx, y = calibration$calib_magy, z = calibration$calib_magz, ptcol = "orange", ptsize = 0.03, linecolor ="royalblue", spherecolor="royalblue", arrows=TRUE, cex=2)
Because flapping is widespread in birds, PAMLr integrates a pre-defined function classifyFLAP()
to classify this behaviour.
This function assumes that if the bird has displayed high activity for x number of consecutive minutes, then it is flapping. It is therefore important to think about what constitutes high activity and how long this period should be. At the moment, the function uses k-means clustering to identify the threshold between high and low activity. Using toPLOT = TRUE
then allows the user to see where that threshold was drawn. The period of high activity is set by default to period = 3
. This is because activity is recorded (on this logger) every 5 minutes and we assume that after an hour of high activity, the bird must be flapping.
Thus "high activity duration" / "data resolution" = "period" and 60 minutes / 5 minutes = period of 12.
# Classify behaviour behaviour = classifyFLAP(dta = PAM_data$acceleration, period = 12) str(behaviour)
This classification therefore provides different pieces of infomration.
Using these information, it's therefore possible to plot the classification:
#Plot behaviour col=col=c("black","royalblue4","brown","gold") index= 7300:8000 plot(PAM_data$acceleration$date[index],PAM_data$acceleration$act[index], type="l", xlab="Date", ylab="Activity") points(PAM_data$acceleration$date[index],PAM_data$acceleration$act[index], col=col[behaviour$classification+1][index], pch=16,) legend( PAM_data$acceleration$date[index[1]],60 , c("No activity", "Low activity", "High activity", "Migration" ) , col = col[c(behaviour$no_movement, behaviour$low_movement, behaviour$high_movement, behaviour$migration)+1], pch=20)
Another way of looking at a classification is to use a sensor image of the results and to plot it side by side with the raw data to see if the same patterns are being picked out. We can also add (for instance sunset and sunrise events)
par(mfrow= c(1,3), # number of panels oma=c(0,2,0,6), # outer margin around all panels mar = c(4,1,4,1)) # inner margin around individual fivure sensorIMG(PAM_data$acceleration$date, ploty=FALSE, PAM_data$acceleration$act, main = "Activity", col=c("black",viridis::cividis(90)), cex=1.2, cex.main = 2) legend("bottomright",cex=1.2, c("No Activity", "Low Activity", "High Activity" ) , fill = c("black","royalblue3", "orange"), xpd = NA) sensorIMG(PAM_data$pressure$date, plotx=TRUE, ploty=FALSE, labely=FALSE, PAM_data$pressure$obs, main="Pressure", col=c("black",viridis::cividis(90)), cex=1.2, cex.main = 2) legend("bottomright",cex=1.2, c("Low Pressure", "High Pressure" ) , fill = c("royalblue3", "orange"), xpd = NA) sensorIMG(PAM_data$acceleration$date, labely=FALSE, behaviour$classification, main="Classification", col=col, cex=1.2, cex.main = 2) legend("bottomright",cex=1.2, # grconvertX(1, "device"), grconvertY(1, "device"), c("Resting", "Active", "Flapping", "Migrating" ) , fill = col, xpd = NA)
Kiran Dhanjal-Adams
Dhanjal-Adams, K.L., Bauer, S., Emmenegger, T., Hahn, S., Lisovski, S., & Liechti, F. (2018) Spatiotemporal Group Dynamics in a Long-Distance Migratory Bird. Current Biology, 28, 2824–2830.e3.
Liechti, F., Bauer, S., Dhanjal-Adams, K.L., Emmenegger, T., Zehtindjiev, P., & Hahn, S. (2018) Miniaturized multi-sensor loggers provide new insight into year-round flight behaviour of small trans-Sahara avian migrants. Movement Ecology, 6, 19.
This project is licensed under the GNU General Public License version 3 - see the LICENSE file for details
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.