Here we present examples regarding how to begin the warbleR
workflow by downloading recordings from xeno-canto, importing your own recordings, making spectrograms of whole recordings, selecting signals within recordings or importing selections already made in Raven and Syrinx. For more details about function arguments, input or output, read the documentation for the function in question (e.g. ?querxc
). warbleR
is available on both CRAN and GitHub. The GitHub repository will always contain the latest functions and updates. We also published an article on warbleR
documenting the package workflow [1].
Please note that most tools in warbleR
use functions from the seewave, monitoR, tuneR and dtw
packages internally. warbleR
has been designed to make the analyses more accessible to average R-users. However, acoustic analysis with warbleR
would not be possible without the tools provided by these additional packages. These packages should be given credit when using warbleR
by including the appropriate citations in publications (e.g. citation("seewave")
).
Nearly all warbleR
functions contain options for parallel processing, which can greatly speed up analyses. See [1] for more details about parallel processing performance. Use parallel processing with caution, particularly if you use a Windows operating system. warbleR
dependencies for parallel processing have not yet been optimized for Windows.
This vignette can be run without an advanced understanding of R, as long as you know how to run code in your R console. However, knowing more about basic R coding would be very helpful to modify the code for your research questions.
First, we need to install and load warbleR
. Install the package from its GitHub repository to access the latest functions presented in this vignette series. You will need an R version ≥ 2.10 and seewave package version ≥ 2.0.1. Also, users using UNIX machines (Mac OSX or Linux), will need to install fftw3
, pkg-config
and libsndfile
on their machines prior to installing warbleR
. These external packages will need to be installed through a UNIX terminal. Installing these packages lies outside the scope of this vignette, but more details can be found using Google.
# install warbleR from CRAN
# install.packages("warbleR")
# install warbleR from GitHub repository, which contains the latest updates
# install.packages("devtools") # run this if devtools is not already installed
library(devtools)
install_github("maRce10/warbleR")
library(warbleR) # load warbleR into your global environment
Set up a working directory
# Create a new directory and set your working directory
dir.create(file.path(getwd(),"warbleR_example"))
setwd(file.path(getwd(),"warbleR_example"))
# Check your location
getwd()
Bioacoustics research encompasses a wide range of questions, species, geographic areas and methods, including software used for analysis. warbleR accounts for this diversity by offering a variety of ways to import data for analysis. Regardless of the research question(s), warbleR relies on the following two types of data:
Sound files: Recordings in wav or mp3 format, either from your own research or open-access databases like xeno-canto
Selections: Selections are temporal coordinates (start and end points) of selected acoustic signals within recordings, often organized within a data frame called a selection table
Below we will give different examples of how to obtain recordings from the open-access database xeno-canto, import recordings or selections other bioacoustics software, such as Raven and Syrinx, as well as how to make selections using warbleR functions.
The open-access xeno-canto database is an excellent source of sound files across a broad selection of avian species. We can query this database for a species or genus of interest. The function querxc
has two types of output:
Metadata of recordings: geographic coordinates, recording quality, recorder, type of signal, etc.
Sound files: Sound files in mp3 format are returned if the argument download
is set to TRUE
(default is FALSE
).
We recommend downloading metadata first from xeno-canto, as this data can be filtered in R to more efficiently download only the recordings important for your question.
You can query xeno-canto by genus:
# Query xeno-canto for all recordings of the hummingbird genus Phaethornis
Phae <- querxc(qword = "Phaethornis", download = FALSE)
## Obtaining recording list...806 recordings found!
# Print column names of data frame to explore metadata
names(Phae)
## [1] "Recording_ID" "Genus" "Specific_epithet"
## [4] "Subspecies" "English_name" "Recordist"
## [7] "Country" "Locality" "Latitude"
## [10] "Longitude" "Vocalization_type" "Audio_file"
## [13] "License" "Url" "Quality"
## [16] "Time" "Date"
# Check out the structure of the data frame
str(Phae)
Or you can query by species:
# Query xeno-canto for all recordings of the species Phaethornis longirostris
Phae.lon <- querxc(qword = "Phaethornis longirostris", download = FALSE)
str(Phae.lon)
## Obtaining recording list...76 recordings found!
If you’re interested in the geographic spread of the recording locations, you can use the function xcmaps
to visualize locations. xcmaps
will create an image file of a map per species in your current directory if img = TRUE
. If img = FALSE
, maps will be displayed in the graphic device.
# Image type default is jpeg, but tiff files have better resolution
# When the data frame contains multiple species,
# you will have one map per species
xcmaps(X = Phae, img = TRUE, it = "tiff")
xcmaps(X = Phae.lon, img = FALSE)
In most cases, you will need to filter the xeno-canto metadata by type of signal you want to analyze. When you subset the metadata, you can input the filtered metadata back into querxc
to download only the selected recordings. There are many ways to filter data in R, and the example below can be modified to fit your own data.
Some of the metadata is not quite consistent across recordings, such as signal type or recording quality. These are characteristics of the recordings that you will need to explore with downstream functions before proceeding with signal selection and analysis. However, if you are working with many recordings, we advise removing the lowest quality recordings (D quality) or selecting specific vocalization types.
For example, we are interested in assessing the microgeographic variation of long-billed hermit songs, Phaethornis longirostris. Variation at small geographic scales has been already described in this species [2]. We should proceed by looking for a site with the highest number of songs. Our goal is to search for visible differences in song structure within a site, and then determine whether underlying differences in acoustic parameters are representative of spectrographic distinctiveness.
# Find out number of available recordings
nrow(Phae.lon)
## [1] 76
# Find out how many types of signal descriptions exist in the xeno-canto metadata
levels(Phae.lon$Vocalization_type)
## [1] "alarm call" "flight call" "song" "song at lek" "calls"
## [6] "call" "lekking" "300"
# How many recordings per signal type?
table(Phae.lon$Vocalization_type)
##
## alarm call flight call song song at lek calls call
## 1 2 63 2 1 5
## lekking 300
## 1 1
# There are many levels to the Vocalization_type variable.
# Some are biologically relevant signals, but most just
# reflect variation in data entry.
# Select just the signals we want
# Regular expression is always a good filtering option
Phae.lon.song <- Phae.lon[grep("song", Phae.lon$Vocalization_type,
ignore.case = TRUE), ]
# Check resulting data frame
str(Phae.lon.song)
## 'data.frame': 65 obs. of 17 variables:
## $ Recording_ID : Factor w/ 76 levels "402755","402754",..: 3 4 5 6 7 8 9 12 13 14 ...
## $ Genus : Factor w/ 1 level "Phaethornis": 1 1 1 1 1 1 1 1 1 1 ...
## $ Specific_epithet : Factor w/ 1 level "longirostris": 1 1 1 1 1 1 1 1 1 1 ...
## $ Subspecies : Factor w/ 3 levels "","baroni","cephalus": 1 1 1 2 1 1 2 1 1 1 ...
## $ English_name : Factor w/ 1 level "Long-billed Hermit": 1 1 1 1 1 1 1 1 1 1 ...
## $ Recordist : Factor w/ 16 levels "Marilyn Castillo",..: 2 2 3 4 5 5 6 9 9 9 ...
## $ Country : Factor w/ 7 levels "Mexico","Panama",..: 2 2 3 4 5 2 4 5 5 5 ...
## $ Locality : Factor w/ 23 levels "Boca de Chajul, Marqués de Comillas, Chiapas",..: 3 3 4 5 6 7 8 10 10 10 ...
## $ Latitude : Factor w/ 22 levels "16.1332","16.1696",..: 3 3 4 5 6 7 8 10 10 10 ...
## $ Longitude : Factor w/ 21 levels "-90.9381","-90.9035",..: 3 3 4 5 6 7 8 10 10 10 ...
## $ Vocalization_type: Factor w/ 8 levels "alarm call","flight call",..: 3 3 3 4 3 3 4 3 3 3 ...
## $ Audio_file : Factor w/ 76 levels "//www.xeno-canto.org/402755/download",..: 3 4 5 6 7 8 9 12 13 14 ...
## $ License : Factor w/ 5 levels "//creativecommons.org/licenses/by-nc-nd/4.0/",..: 2 2 2 2 1 1 2 3 3 3 ...
## $ Url : Factor w/ 76 levels "https://www.xeno-canto.org/402755",..: 3 4 5 6 7 8 9 12 13 14 ...
## $ Quality : Factor w/ 4 levels "A","B","C","D": 1 1 1 1 1 1 1 1 1 1 ...
## $ Time : Factor w/ 60 levels "07:30","07:00",..: 3 4 1 5 6 7 8 11 12 13 ...
## $ Date : Factor w/ 33 levels "2016-01-18","2017-02-09",..: 2 2 3 4 5 6 7 10 11 11 ...
# In case you want more than one type of signals:
Phae.lon.sc <- Phae.lon[grep("song|call", Phae.lon$Vocalization_type,ignore.case = TRUE), ]
# How many recordings per locatity?
table(Phae.lon.song$Locality)
Focus on high quality song recordings from La Selva Biological Station:
# Filter by location
Phae.lon.LS <- Phae.lon.song[grep("La Selva Biological Station, Sarapiqui, Heredia", Phae.lon.song$Locality,
ignore.case = FALSE), ]
# Select highest quality recordings
Phae.lon.LS <- Phae.lon.LS[Phae.lon.LS$Quality == "A", ]
We can check if the location coordinates make sense (all recordings should be from a single place in Costa Rica) by making a map of these recordings using xcmaps
.
# map in the RStudio graphics device (img = FALSE)
xcmaps(Phae.lon.LS, img = FALSE)
Once you’re sure you want the recordings, use querxc
to download the files. It’s also a good idea to save the metadata as .csv files.
# Download sound files
querxc(X = Phae.lon.LS)
# Save each data frame object as a .csv file
write.csv(Phae.lon.LS, "Phae_lon.LS.csv", row.names = FALSE)
xeno-canto maintains recordings in mp3 format due to file size restrictions. However, we require wav format for all downstream analyses. Compression from wav to mp3 and back involves information losses, but recordings that have undergone this transformation have been successfully used in research [3].
To convert mp3 to wav, we can use the warbleR function mp32wav
, which relies on a underlying function from the tuneR
package. This function does not always work (and it remains unclear as to why!). This bug should be fixed in future versions of tuneR
. If RStudio aborts when running mp32wav
, use an mp3 to wav converter online, or download the open source software Audacity
(available for Mac, Linux and Windows users). We have made the selected wav files available for download (see next section).
After mp3 files have been converted, we need to check that the wav files are not corrupted and can be read into RStudio (some wav files can’t be read due to format or permission issues).
# Neither of these functions requires arguments
# Always check you're in the right directory beforehand
# getwd()
mp32wav()
# Use checkwavs to see if wav files can be read
checkwavs()
# Create a list of all the recordings in the directory
wavs <- list.files(pattern = "wav$")
# Downsample the wav files and speed up downstream analyses
invisible(lapply(wavs, function(x) writeWave(downsample(readWave(x), samp.rate = 22050),
filename = x)))
The function lspec
produces image files with spectrograms of whole sound files split into multiple rows. It is a useful tool for filtering by visual inspection.
lspec
allows you to visually inspect the quality of the recording (e.g. amount of background noise) or the type, number, and completeness of the vocalizations of interest. You can discard the image files and recordings that you no longer want to analyze.
We should first adjust the function arguments to fit our recording characteristics. We can work on a subset of the recordings by specifying their names with the flist
argument.
# Create a list of all the recordings in the directory
wavs <- list.files(pattern = "wav$")
# Select a subset of recordings to explore lspec() arguments
# Based on the list of wav files we created above
sub <- wavs[c(1,3)]
# How long are these files? will determine number of pages returned by lspec
wavdur(sub)
# ovlp = 10 to speed up function
# tiff image files are better quality and are faster to produce
lspec(flist = sub, ovlp = 10, it = "tiff")
# We can zoom in on the frequency axis by changing flim,
# the number of seconds per row, and number of rows
lspec(flist = sub, flim = c(2, 10), sxrow = 6, rows = 15, ovlp = 10, it = "tiff")
Once satisfied with the argument settings we can run all files.
lspec(flim = c(2, 10), ovlp = 10, sxrow = 6, rows = 15, it = "jpeg")
# concatenate lspec image files into a single PDF per recording
# lspec images must be jpegs
lspec2pdf(keep.img = FALSE, overwrite = TRUE)
The pdf image file (in the working directory) should look like this:
Note that the sound file name and page number are placed in the top right corner. Also, the dimensions of the image are made to letter paper size for printing and subsequent visual inspection.
Recording 154123 has a lot of background noise. Delete the wav file for this recording to remove it from subsequent analyses.
warbleR has two main functions for selecting acoustic signals within recordings: + autodetec
- automatically detects the start and end of signals in sound files based on amplitude, duration, and frequency range attributes + manualoc
- provides an interactive interface in the RStudio graphics device to manually select signals
Both functions work fastest with shorter recordings, but there are ways to deal with larger recordings (an hour long or more). In this section we have expanded on some important function arguments, but check out the function documentation for more information.
autodetec
Keep these points in mind when using autodetec
:
autodetec
has 2 types of output:
ls = TRUE
). For shorter recordings, spectrograms of individual selections may work better (ls = FALSE
). threshold
controls detection by relative amplitude (%)bp
serves as a frequency bandpass filterssmooth
controls combination of window length and overlap to smooth signals that have many peaks and would otherwise be detected as multiple signalsmindur
& maxdur
determine the minimum and maximum duration of the signals to be detectedset
dictates whether settings of the autodetection process are included in the image file name. If set = TRUE
, threshold (th), envelope (envt), bandpass (bp), power (pw), smooth (smo), maxdur (mxdu), and mindur (midu) are included in image file names. This helps compare the performance of different detection setttings.To set detection parameters we need to know the frequency range and duration of the signals we want to detect. Phaenthornis longirostris songs have frequencies between 2 and 10 kHz and durations between 0.05 and 0.5 s. Detecting signals is not a linear process. You will often need to run detection functions several times, and in the process you will get to know your signals better (if you don’t already).
If you need to detect all or most of the signals within the recording, play around with different arguments to increase detection accuracy. Since you may need to do several rounds of optimization, we recommend using subsets of your recordings to speed up the process. If the species you study produces stereotyped signals, like Phaethornis longirostris, just a few signals are needed per recording, and a low-accuracy detection could yield enough selections.
Finally, although autodetec
performs automatic signal detection, it does not replace visual inspection of selected signals. Ensure that you set aside the time to inspect all selected signals for accuracy.
# Select a subset of the recordings
wavs <- list.files(pattern = ".wav$", ignore.case = TRUE)
# Set a seed so we all have the same results
set.seed(1)
sub <- wavs[sample(1:length(wavs), 3)]
# Run autodetec() on subset of recordings
autodetec(flist = sub, bp = c(1, 10), threshold = 10, mindur = 0.05, maxdur = 0.5, envt="abs",
ssmooth = 300, ls = TRUE, res = 100,
flim = c(1, 12), wl = 300, set =TRUE, sxrow = 6, rows = 15,
redo = FALSE, it = "tiff")
The image files (in the working directory) should look like this (shown below is recording ID 154161):
Note that some songs were correctly detected but other undersired sounds were also detected. In most cases, the undesired selections have a shorter duration than our target signals.
We won’t save the autodetec
ouput in an object until we’re satisfied with the detection. To improve our detection we should play around with argument values. Below are some detection parameters that work well for these Phaethornis longirotris recordings:
autodetec(flist = sub, bp = c(2, 10), threshold = 20, mindur = 0.09, maxdur = 0.22,
envt = "abs", ssmooth = 900, ls = TRUE, res = 100,
flim= c(1, 12), wl = 300, set =TRUE, sxrow = 6, rows = 15,
redo = TRUE, it = "tiff", img = TRUE, smadj = "end")
This seems to provide a good detection for most recordings (recording ID 154161):
Once we’re satisfied with the detection, we can run the autodetec
on all the recordings, removing the argument flist
(so autodetec
runs over all wav files in the working directory). We will also save the temporal output in an object.
Phae.ad <- autodetec(bp = c(2, 10), threshold = 20, mindur = 0.09, maxdur = 0.22,
envt = "abs", ssmooth = 900, ls = TRUE, res = 100,
flim = c(2, 10), wl = 300, set =TRUE, sxrow = 6, rows = 15,
redo = TRUE, it = "tiff", img = TRUE, smadj = "end")
Let’s look at the number of selections per sound file:
table(Phae.ad$sound.files)
Signal-to-noise ratio (SNR) can be a useful filter for automated signal detection. When background noise is detected as a signal it will have a low SNR, and this characteristic can be used to remove background noise from the autodetec
selection table. SNR = 1 means the signal and background noise have the same amplitude, so signals with SNR <= 1 are poor quality. SNR calculations can also be used for different purposes throughout your analysis workflow.
snrspecs
to optimize SNR measurementssnrspecs
is another function in the family of spectrogram creators that allows you to pick a margin for measuring noise. These margins are very important for calculating SNR, especially when working with signals separated by short gaps (e.g. duets).
# A margin that's too large causes other signals to be included in the noise measurement
# Re-initialize X as needed, for either autodetec or manualoc output
# Try this with 10% of the selections first
# Set a seed first, so we all have the same results
set.seed(5)
X <- Phae.ad[sample(1:nrow(Phae.ad),(nrow(Phae.ad)*0.1)), ]
snrspecs(X = X, flim = c(2, 10), snrmar = 0.5, mar = 0.7, it = "tiff")
The image files should look like this:
This margin overlaps signals, a smaller margin would be better.
# This smaller margin is better
snrspecs(X = X, flim = c(2, 10), snrmar = 0.04, mar = 0.7, it = "tiff")
Once we’ve picked an SNR margin we can move forward with the SNR calculation. We will measure SNR on every other selection to speed up the process.
Phae.snr <- sig2noise(X = Phae.ad[seq(1, nrow(Phae.ad), 2), ], mar = 0.04)
As we just need a few songs to characterize each sound file and individual, we can choose selections with the highest SNR per sound file. In this example, we will choose 5 selections per recording with the highest SNRs.
Phae.hisnr <- Phae.snr[ave(-Phae.snr$SNR, Phae.snr$sound.files, FUN = rank) <= 5, ]
# save the selections as a physical file
write.csv(Phae.hisnr, "Phae_hisnr.csv", row.names = FALSE)
# Double check the number of selection per sound files
table(Phae.hisnr$sound.files)
##
## Phaethornis-longirostris-154070.wav Phaethornis-longirostris-154072.wav
## 5 5
## Phaethornis-longirostris-154129.wav Phaethornis-longirostris-154138.wav
## 5 5
## Phaethornis-longirostris-154161.wav
## 5
manualoc
manualoc
is a function that provides an interactive interface to select signals. We recommend reading the documentation for manualoc
prior to running this example. Once you’ve done so, here are some points to keep in mind:
manualoc
to failmanualoc
starts responding to single clicksmanualoc
with Stop
buttonmanualoc
retains all previous selections in the .csv file and will start up where you left offmanualoc
interface
Del-sel
buttonmanualoc_output.csv
manualoc
, open the .csvmanualoc
againmanualoc
within the expected frequency range for your species
flim
to facilitate signal selectionmanualoc
with oscillograms enabled to improve signal selection
osci = TRUE
, the oscillogram or waveform serves as a visual aidseltime
argument)seltime
determines the time interval in seconds at which the spectrograms are produced with higher resolution and oscillogramsSome other uses for manualoc
:
manualoc
can be used in combination with autodetec
if you have large recordings:
autodetec
autodetec
using the data frame argument X
manualoc
can also be used for visual classification:
manualoc
with selcomm = TRUE
selcomm
specreator
to create spectrograms with selcomm
text and check visual classificationsYou can stop the function at any point by clicking twice on the stop
button.
# Run manualoc() with frequency range set for Phaethornis longirostris
# Recording comments are enabled to mark recording quality
# Selection comments enabled to include visual classifications
manualoc(flim = c(2, 10), reccomm = TRUE, selcomm = TRUE, osci = TRUE, seltime = 2)
# Read manualoc() output back into RStudio as an object
# This data frame object can be used as input for later functions
manualoc_out <- read.csv("manualoc_output.csv", header = TRUE)
The graphics device will look similar to this:
warbleR is compatible with Raven and Syrinx. You may already work with these bioacoustics programs, and they are a valuable subset of the software available to a wide user base. One of the most difficult part of any biological analysis is transitioning between software, as this often involves writing customized code, or relying on yet other programs, to translate file formats. warbleR now contains functions that allow you to start an analysis outside of R, or take the analysis outside of R when necessary. Check out the following functions:
exp_raven
- export selections made in warbleR to Ravenimp.raven
- import selection tables from Ravenimp.syrinx
- import selection tables from Syrinxrun_raven
- open sound files in Raven from the R interfaceThe function exp_raven
lets you take the analysis outside of R after making selections in warbleR.
Phae.hisnr <- read.csv("Phae_hisnr.csv", header = TRUE)
# remove SNR column and select the first sound file
sub <- droplevels(Phae.hisnr[Phae.hisnr$sound.files == levels(Phae.hisnr$sound.files)[1], -grep("SNR", names(Phae.hisnr))])
str(sub)
# extract recording name without ".wav" extension
# save filtered autodetec output as a Raven selection file
exp_raven(X = sub, file.name = paste(strsplit(unique(as.character(sub$sound.files)), split = ".w")[[1]][1], "hisnr", sep = "_"))
The function run_raven
is particularly useful. It allows you to call Raven from warbleR and import selections you make in Raven directly back to warbleR as a data frame.
# the object sels will contain selections you made in the target recordings
# use arguments from imp.raven to return selection table in correct format for warbleR functions
sels <- run_raven(raven.path = "~/opt/Raven-1.5.0.0035/", sound.files = c("Phaethornis-longirostris-154072.wav", "Phaethornis-longirostris-154070.wav"), at.the.time = 2, import = TRUE, all.data = FALSE, name.from.file = TRUE, ext.case = "lower", freq.cols = FALSE)
str(sels)
# write the imported selections as a .csv for later use
write.csv(sels, "Raven_sels.csv", row.names = FALSE)
## 'data.frame': 8 obs. of 6 variables:
## $ sound.files: Factor w/ 2 levels "Phaethornis-longirostris-154070.wav",..: 1 1 1 1 2 2 2 2
## $ selec.file : Factor w/ 2 levels "Phaethornis-longirostris-154070.Table.1.selections.txt",..: 1 1 1 1 2 2 2 2
## $ channel : int 1 1 1 1 1 1 1 1
## $ selec : int 1 2 3 4 1 2 3 4
## $ start : num 0.791 1.479 2.125 2.227 0.706 ...
## $ end : num 0.951 1.63 2.276 2.227 0.848 ...
Here we have given examples of how to begin the warbleR
workflow. Note that there are many different ways to begin the workflow, depending on your question and source of data. After running the code in this first vignette, you should now have an idea of:
warbleR
interface with other bioacoustics programs, Raven and SyrinxThe next vignette will cover the second phase of the warbleR workflow, which includes methods to visualize signals for quality control and classification.
Araya-Salas, M. and G. Smith-Vidaurre. 2016. warbleR: an R package to streamline analysis of animal acoustic signals. Methods in Ecology and Evolution. doi: 10.1111/2041-210X.12624
Araya-Salas, M. and T. Wright. 2013. Open-ended song learning in a hummingbird. Biology Letters. 9 (5). doi: 10.1098/rsbl.2013.0625
Medina‐García, Angela, M. Araya‐Salas, and T. Wright. 2015. Does vocal learning accelerate acoustic diversification? Evolution of contact calls in Neotropical parrots. Journal of Evolutionary Biology. doi: 10.1111/jeb.12694