Bioacoustic research is based on quantifying the structure of acoustic signals and comparing that structure between different behavioral / social / ecological contexts, groups or species. However, measuring the signal structure in a way that takes into account the most relevant variation in signal structure could be a difficult task. Some of the differences that are evident by visual inspection of spectrograms may not be detected by some analyzes. Therefore, choosing the most appropriate analytical approach is a critical step.
The compare_methods()
function from warbleR attempts to facilitate the selection of the method. This function produces graphics (such as image files in the working directory) with spectrograms of 4 signals at a time, which allow visual inspection of the performance of acoustic analysis methods when comparing those signals. The signals are chosen randomly from the data frame or selection table provided (argument ‘X’). The function compares 2 methods at a time. The available methods are:
cross_correlation()
function)freq_DTW()
) and fundamental frequency (using freq_DTW()
)spectro_analysis()
)mfcc_stats()
)The graphs also contain 2 scatter plots (1 for each method) of the acoustic space of all the signals in the input data frame ‘X’. The position of the 4 signals in the spectrograms is highlighted in the acoustic space plots. In this way, users can directly assess whether the distances between the signals in the acoustic space accurately represent the spectrographic similarity (i.e. how similar its structure looks on the spectrograms).
This is a brief example of how to use the function using the data files included in the package (and in the examples folder). Simply execute the function by selecting the 2 methods you want to compare. The following code compares spectrographic cross correlation (XCORR
) and dynamic time warping in the dominant frequency contours (freq_DTW
). The compared selections are randomly selected from the set of selections in the input data frame. The argument ‘n’ defines the number of comparisons (that is, graphs) that must be created:
library(warbleR)
data("lbh_selec_table")
# global parameters
warbleR_options(wav.path = "./examples", flim = c(0, 10), bp = c(0, 10), wl = 300, n = 12)
compare_methods(X = lbh_selec_table, methods = c("XCORR", "dfDTW"))
It must produce 12 image files (in the working directory) that look like this one:
Looking at several iterations of the comparison, you can have a better idea of which method works best for the signals being analyzed:
The distance of the acoustic pair between the signals is shown next to the arrows that link them. The font color of a distance value corresponds to the font color of the method that generated it, as shown in the scatter diagrams (in this case, the black font represents the XCORR distances). The distances are standardized, being 0 the distance of a signal to itself and 1 the distance in pairs farthest in the set of signals. The principal component analysis (function prcomp()
) is applied to calculate distances when spectral parameters (SP) are used. In that case the first 2 components are used. Classic multidimensional scaling, also known as principal coordinate analysis, function cmdscale()
) is used for all other methods. The file name contains the methods that are compared and the row number of the selections. This function internally uses a modified version of the spectro()
function of the seewave package to create spectrograms. Note that all spectrograms are plotted with the same frequency and time scale.
compare_methods(X = lbh_selec_table, methods = c("XCORR", "SP"))
Exercise
Use the compare_methods()
function to compare the following methods:
Which method better represents the variation in signal structure for each comparison?
Compare the best methods from the two comparison above
Alternatively, you can provide your own data. This could be useful to eliminate unwanted parameters or to enter parameters obtained with other programs (for example, from Raven). To do this, enter your data with the argument custom1
. The following example 1) calculate the spectral parameters with the spectro_analysis()
function, 2) select only the first 7 columns of the output, and 3) enter this data in compare_methods()
:
# measure parameters
Y <- spectro_analysis(lbh_selec_table)
# selec a subset
Y <- Y[, 1:7]
# PCA
Y <- prcomp(Y[, 3:ncol(Y)])$x
# add sound files and selec columns
Y <- data.frame(lbh_selec_table[, c(1, 3)], Y[, 1:2])
compare_methods(X = lbh_selec_table, methods = c("dfDTW"), custom1 = Y)
Note that there is also a custom2
argument for entering another custom data. The function has many other arguments for specifying methods (for example bandpass, overlap) and spectrogram settings (margin, grid, frequency limits, etc).
Session information
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.2 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
##
## locale:
## [1] LC_CTYPE=es_ES.UTF-8 LC_NUMERIC=C LC_TIME=es_CR.UTF-8
## [4] LC_COLLATE=es_ES.UTF-8 LC_MONETARY=es_CR.UTF-8 LC_MESSAGES=es_ES.UTF-8
## [7] LC_PAPER=es_CR.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] Rraven_1.0.13 ohun_0.1.0 kableExtra_1.3.4 warbleR_1.1.27 NatureSounds_1.0.4
## [6] knitr_1.37 seewave_2.2.0 tuneR_1.3.3.1
##
## loaded via a namespace (and not attached):
## [1] colorspace_2.0-3 rjson_0.2.21 deldir_1.0-6 ellipsis_0.3.2
## [5] rstudioapi_0.13 proxy_0.4-26 spatstat.data_2.1-2 farver_2.1.0
## [9] xaringan_0.22 Deriv_4.1.3 audio_0.1-10 remotes_2.4.0
## [13] DT_0.19 fansi_1.0.2 xml2_1.3.2 codetools_0.2-18
## [17] splines_4.1.1 baRulho_1.0.6 polyclip_1.10-0 jsonlite_1.7.2
## [21] cluster_2.1.2 png_0.1-7 bioacoustics_0.2.8 shiny_1.6.0
## [25] spatstat.sparse_2.1-0 compiler_4.1.1 httr_1.4.2 assertthat_0.2.1
## [29] Matrix_1.3-4 fastmap_1.1.0 cli_3.2.0 later_1.3.0
## [33] formatR_1.11 htmltools_0.5.2 tools_4.1.1 gtable_0.3.0
## [37] glue_1.6.2 PhenotypeSpace_0.1.0 dplyr_1.0.7 Rcpp_1.0.8
## [41] jquerylib_0.1.4 raster_3.5-11 vctrs_0.3.8 svglite_2.0.0
## [45] nlme_3.1-152 xfun_0.30 stringr_1.4.0 phonTools_0.2-2.1
## [49] rvest_1.0.1 mime_0.11 lifecycle_1.0.1 goftest_1.2-3
## [53] terra_1.5-12 zoo_1.8-9 MASS_7.3-54 scales_1.1.1
## [57] microbenchmark_1.4-7 spatstat.core_2.3-2 promises_1.2.0.1 spatstat.utils_2.3-0
## [61] shinyBS_0.61 parallel_4.1.1 Sim.DiffProc_4.8 yaml_2.3.5
## [65] pbapply_1.5-0 gridExtra_2.3 ggplot2_3.3.5 sass_0.4.0
## [69] rpart_4.1-15 stringi_1.7.6 highr_0.9 permute_0.9-5
## [73] soundgen_2.2.0 rlang_1.0.2 pkgconfig_2.0.3 systemfonts_1.0.2
## [77] dtw_1.22-3 moments_0.14 bitops_1.0-7 evaluate_0.15
## [81] lattice_0.20-44 purrr_0.3.4 tensor_1.5 htmlwidgets_1.5.3
## [85] tidyselect_1.1.1 magrittr_2.0.2 xaringanthemer_0.4.1 R6_2.5.1
## [89] fftw_1.0-6.1 generics_0.1.0 DBI_1.1.1 pillar_1.7.0
## [93] whisker_0.4 withr_2.5.0 mgcv_1.8-36 abind_1.4-5
## [97] RCurl_1.98-1.6 sp_1.4-6 tibble_3.1.6 crayon_1.5.0
## [ reached getOption("max.print") -- omitted 15 entries ]