The warbleR package is intended to facilitate the analysis of the structure of animal acoustic signals in R. Users can enter their own data into a workflow that facilitates spectrographic visualization and measurement of acoustic parameters warbleR makes use of the fundamental sound analysis tools of the seewave package, and offers new tools for acoustic structure analysis. These tools are available for batch analysis of acoustic signals.
The main features of the package are:
The package offers functions for:
Most functions allow the parallelization of tasks, which distributes the tasks among several cores to improve computational efficiency. Tools to evaluate the performance of the analysis at each step are also available. All these tools are provided in a standardized workflow for the analysis of the signal structure, making them accessible to a wide range of users, including those without much knowledge of R.
warbleR is a young package (officially published in 2017) currently in a maturation stage:
These objects are created with the selection_table()
function. The function takes data frames containing selection data (name of the sound file, selection, start, end …), verifies if the information is consistent (see the function check_sels()
for details) and saves the ‘diagnostic’ metadata as an attribute. The selection tables are basically data frames in which the information contained has been corroborated so it can be read by other warbleR functions. The selection tables must contain (at least) the following columns:
The sample data “lbh_selec_table” contains these columns:
data("lbh_selec_table")
lbh_selec_table
sound.files | channel | selec | start | end | bottom.freq | top.freq |
---|---|---|---|---|---|---|
Phae.long1.wav | 1 | 1 | 1.169355 | 1.342388 | 2.22011 | 8.60438 |
Phae.long1.wav | 1 | 2 | 2.158408 | 2.321457 | 2.16944 | 8.80705 |
Phae.long1.wav | 1 | 3 | 0.343337 | 0.518255 | 2.21829 | 8.75660 |
Phae.long2.wav | 1 | 1 | 0.159598 | 0.292169 | 2.31686 | 8.82232 |
Phae.long2.wav | 1 | 2 | 1.457058 | 1.583209 | 2.28401 | 8.88803 |
Phae.long3.wav | 1 | 1 | 0.626552 | 0.757771 | 3.00683 | 8.82232 |
Phae.long3.wav | 1 | 2 | 1.974213 | 2.104392 | 2.77684 | 8.88803 |
Phae.long3.wav | 1 | 3 | 0.123364 | 0.254581 | 2.31686 | 9.31515 |
Phae.long4.wav | 1 | 1 | 1.516812 | 1.662236 | 2.51400 | 9.21659 |
Phae.long4.wav | 1 | 2 | 2.932692 | 3.076878 | 2.57971 | 10.23512 |
Phae.long4.wav | 1 | 3 | 0.145398 | 0.290497 | 2.57971 | 9.74228 |
… and can be converted to the selection_table format like this:
# global parameters
warbleR_options(wav.path = "./examples")
st <- selection_table(X = lbh_selec_table, pb = FALSE)
st
Object of class 'selection_table'
* The output of the following call:
selection_table(X = lbh_selec_table, pb = FALSE)
Contains:
* A selection table data frame with 11 rows and 7 columns:
|sound.files | channel| selec| start| end| bottom.freq|
|:--------------|-------:|-----:|------:|------:|-----------:|
|Phae.long1.wav | 1| 1| 1.1694| 1.3424| 2.2201|
|Phae.long1.wav | 1| 2| 2.1584| 2.3215| 2.1694|
|Phae.long1.wav | 1| 3| 0.3433| 0.5183| 2.2183|
|Phae.long2.wav | 1| 1| 0.1596| 0.2922| 2.3169|
|Phae.long2.wav | 1| 2| 1.4571| 1.5832| 2.2840|
|Phae.long3.wav | 1| 1| 0.6266| 0.7578| 3.0068|
... 1 more column(s) (top.freq) and 5 more row(s)
* A data frame (check.results) generated by check_sels() (as attribute)
created by warbleR 1.1.27
Note that the path to the sound files has been provided. This is necessary in order to verify that the data provided conforms to the characteristics of the audio files.
Selection tables have their own class in R:
class(st)
[1] "selection_table" "data.frame"
When the extended = TRUE
argument the function generates an object of the extended_selection_table class that also contains a list of ‘wave’ objects corresponding to each of the selections in the data. Therefore, the function transforms the selection table into self-contained objects since the original sound files are no longer needed to perform most of the acoustic analysis in warbleR. This can greatly facilitate the storage and exchange of (bio)acoustic data. In addition, it also speeds up analysis, since it is not necessary to read the sound files every time the data is analyzed.
Now, as mentioned earlier, you need the selection_table()
function to create an extended selection table. You must also set the argument extended = TRUE
(otherwise, the class would be a selection table). The following code converts the sample data into an extended selection table:
# global parameters
warbleR_options(wav.path = "./examples")
ext_st <- selection_table(X = lbh_selec_table, pb = FALSE,
extended = TRUE, confirm.extended = FALSE)
And that is. Now the acoustic data and the selection data (as well as the additional metadata) are all together in a single R object.
Exercise
Run the example code in the selection_table()
function documentation
What do the arguments “mar”, “by.song” and “whole.recs” do?
Several functions can be used to deal with objects of this class. You can test if the object belongs to the extended_selection_table:
is_extended_selection_table(ext_st)
[1] TRUE
You can subset the selection in the same way that any other data frame and it will still keep its attributes:
ext_st2 <- ext_st[1:2, ]
is_extended_selection_table(ext_st2)
[1] TRUE
There is also a generic version of print()
for this class of objects:
## print
print(ext_st)
Object of class 'extended_selection_table'
* The output of the following call:
selection_table(X = lbh_selec_table, extended = TRUE, confirm.extended = FALSE,
pb = FALSE)
Contains:
* A selection table data frame with 11 row(s) and 7 columns:
|sound.files | channel| selec| start| end| bottom.freq|
|:----------------|-------:|-----:|-----:|------:|-----------:|
|Phae.long1.wav_1 | 1| 1| 0.1| 0.2730| 2.2201|
|Phae.long1.wav_2 | 1| 1| 0.1| 0.2630| 2.1694|
|Phae.long1.wav_3 | 1| 1| 0.1| 0.2749| 2.2183|
|Phae.long2.wav_1 | 1| 1| 0.1| 0.2326| 2.3169|
|Phae.long2.wav_2 | 1| 1| 0.1| 0.2262| 2.2840|
|Phae.long3.wav_1 | 1| 1| 0.1| 0.2312| 3.0068|
... 1 more column(s) (top.freq) and 5 more row(s)
* 11 wave object(s) (as attributes): Phae.long1.wav_1 Phae.long1.wav_2 Phae.long1.wav_3 Phae.long2.wav_1 Phae.long2.wav_2 Phae.long3.wav_1... and 5 more
* A data frame (check.results) generated by check_sels() (as attribute)
The selection table was created by element (see 'class_extended_selection_table')
* 1 sampling rate(s) (in kHz): 22.5
* 1 bit depth(s): 16
* Created by warbleR 1.1.27
… which is equivalent to:
ext_st
Object of class 'extended_selection_table'
* The output of the following call:
selection_table(X = lbh_selec_table, extended = TRUE, confirm.extended = FALSE,
pb = FALSE)
Contains:
* A selection table data frame with 11 row(s) and 7 columns:
|sound.files | channel| selec| start| end| bottom.freq|
|:----------------|-------:|-----:|-----:|------:|-----------:|
|Phae.long1.wav_1 | 1| 1| 0.1| 0.2730| 2.2201|
|Phae.long1.wav_2 | 1| 1| 0.1| 0.2630| 2.1694|
|Phae.long1.wav_3 | 1| 1| 0.1| 0.2749| 2.2183|
|Phae.long2.wav_1 | 1| 1| 0.1| 0.2326| 2.3169|
|Phae.long2.wav_2 | 1| 1| 0.1| 0.2262| 2.2840|
|Phae.long3.wav_1 | 1| 1| 0.1| 0.2312| 3.0068|
... 1 more column(s) (top.freq) and 5 more row(s)
* 11 wave object(s) (as attributes): Phae.long1.wav_1 Phae.long1.wav_2 Phae.long1.wav_3 Phae.long2.wav_1 Phae.long2.wav_2 Phae.long3.wav_1... and 5 more
* A data frame (check.results) generated by check_sels() (as attribute)
The selection table was created by element (see 'class_extended_selection_table')
* 1 sampling rate(s) (in kHz): 22.5
* 1 bit depth(s): 16
* Created by warbleR 1.1.27
You can also join them in rows. Here the original extended_selection_table is divided into 2 and bound again using rbind()
:
ext_st3 <- ext_st[1:5, ]
ext_st4 <- ext_st[6:11, ]
ext_st5 <- rbind(ext_st3, ext_st4)
#print
ext_st5
Object of class 'extended_selection_table'
* The output of the following call:
rbind(deparse.level, ..1, ..2)
Contains:
* A selection table data frame with 11 row(s) and 7 columns:
|sound.files | channel| selec| start| end| bottom.freq|
|:----------------|-------:|-----:|-----:|------:|-----------:|
|Phae.long1.wav_1 | 1| 1| 0.1| 0.2730| 2.2201|
|Phae.long1.wav_2 | 1| 1| 0.1| 0.2630| 2.1694|
|Phae.long1.wav_3 | 1| 1| 0.1| 0.2749| 2.2183|
|Phae.long2.wav_1 | 1| 1| 0.1| 0.2326| 2.3169|
|Phae.long2.wav_2 | 1| 1| 0.1| 0.2262| 2.2840|
|Phae.long3.wav_1 | 1| 1| 0.1| 0.2312| 3.0068|
... 1 more column(s) (top.freq) and 5 more row(s)
* 11 wave object(s) (as attributes): Phae.long1.wav_1 Phae.long1.wav_2 Phae.long1.wav_3 Phae.long2.wav_1 Phae.long2.wav_2 Phae.long3.wav_1... and 5 more
* A data frame (check.results) generated by check_sels() (as attribute)
The selection table was created by element (see 'class_extended_selection_table')
* 1 sampling rate(s) (in kHz): 22.5
* 1 bit depth(s): 16
* Created by warbleR 1.1.27
# are they equal?
all.equal(ext_st, ext_st5)
[1] "Attributes: < Component \"call\": target, current do not match when deparsed >"
The ‘wave’ objects can be read individually using read_wave()
, a wrapper for the readWave()
function of tuneR, which can handle extended selection tables:
wv1 <- read_wave(X = ext_st, index = 3, from = 0, to = 0.37)
These are regular ‘wave’ objects:
class(wv1)
[1] "Wave"
attr(,"package")
[1] "tuneR"
wv1
Wave Object
Number of Samples: 8325
Duration (seconds): 0.37
Samplingrate (Hertz): 22500
Channels (Mono/Stereo): Mono
PCM (integer format): TRUE
Bit (8/16/24/32/64): 16
spectro(wv1, wl = 150, grid = FALSE, scale = FALSE, ovlp = 90)
par(mfrow = c(3, 2), mar = rep(0, 4))
for(i in 1:6){
wv <- read_wave(X = ext_st, index = i, from = 0.05, to = 0.32)
spectro(wv, wl = 150, grid = FALSE, scale = FALSE, axisX = FALSE,
axisY = FALSE, ovlp = 90)
}
The read_wave()
function requires the selection table, as well as the row index (i.e. the row number) to be able to read the ‘wave’ objects. It can also read a regular ‘wave’ file if the path is provided.
Note that other functions that modify data frames are likely to delete the attributes in which the ‘wave’ objects and metadata are stored. For example, the merge and the extended selection box will remove its attributes:
# create new data base
Y <- data.frame(sound.files = ext_st$sound.files, site = "La Selva", lek = c(rep("SUR", 5), rep("CCL", 6)))
# combine
mrg_ext_st <- merge(ext_st, Y, by = "sound.files")
# check class
is_extended_selection_table(mrg_ext_st)
[1] FALSE
In this case, we can use the fix_extended_selection_table()
function to transfer the attributes of the original extended selection table:
# fix
mrg_ext_st <- fix_extended_selection_table(X = mrg_ext_st, Y = ext_st)
# check class
is_extended_selection_table(mrg_ext_st)
[1] TRUE
This works as long as some of the original sound files are retained and no other selections are added.
& nbsp;
The size of the extended selection box will depend on the number of selections, the sampling rate, the duration of the selection and the length of margins (i.e. additional time you want to keep on each side of the selection). In this example, a selection table with 1000 selections is created simply by repeating the sample data frame several times and then is converted to an extended selection table:
lng.selec.table <- do.call(rbind, replicate(100, lbh_selec_table,
simplify = FALSE))[1:1000,]
lng.selec.table$selec <- 1:nrow(lng.selec.table)
nrow(lng.selec.table)
lng_ext_st <- selection_table(X = lng.selec.table, pb = FALSE,
extended = TRUE, confirm.extended = FALSE)
lng_ext_st
Object of class 'extended_selection_table'
* The output of the following call:
selection_table(X = lng.selec.table, extended = TRUE, confirm.extended = FALSE,
pb = FALSE)
Contains:
* A selection table data frame with 1000 row(s) and 7 columns:
|sound.files | channel| selec| start| end| bottom.freq|
|:----------------|-------:|-----:|-----:|------:|-----------:|
|Phae.long1.wav_1 | 1| 1| 0.1| 0.2730| 2.2201|
|Phae.long1.wav_2 | 1| 1| 0.1| 0.2630| 2.1694|
|Phae.long1.wav_3 | 1| 1| 0.1| 0.2749| 2.2183|
|Phae.long2.wav_4 | 1| 1| 0.1| 0.2326| 2.3169|
|Phae.long2.wav_5 | 1| 1| 0.1| 0.2262| 2.2840|
|Phae.long3.wav_6 | 1| 1| 0.1| 0.2312| 3.0068|
... 1 more column(s) (top.freq) and 994 more row(s)
* 1000 wave object(s) (as attributes): Phae.long1.wav_1 Phae.long1.wav_2 Phae.long1.wav_3 Phae.long2.wav_4 Phae.long2.wav_5 Phae.long3.wav_6... and 994 more
* A data frame (check.results) generated by check_sels() (as attribute)
The selection table was created by element (see 'class_extended_selection_table')
* 1 sampling rate(s) (in kHz): 22.5
* 1 bit depth(s): 16
* Created by warbleR 1.1.27
format(object.size(lng_ext_st), units = "auto")
[1] "31.4 Mb"
As you can see, the object size is only ~ 31 MB. Then, as a guide, a selection box with 1000 selections similar to those of ‘lbh_selec_table’ (average duration of ~ 0.15 seconds) at a sampling rate of 22.5 kHz and the default margin (mar = 0.1) will generate an extended selection box ~ 31 MB or ~ 310 MB for a selection table of 10,000 rows.
These objects can be used as input for most warbleR functions. Here are some examples of warbleR functions using extended_selection_table:
# spectrographic parameters
sp <- spectro_analysis(ext_st)
sp
sound.files | selec | duration | meanfreq | sd | freq.median | freq.Q25 | freq.Q75 | freq.IQR | time.median | time.Q25 | time.Q75 | time.IQR | skew | kurt | sp.ent | time.ent | entropy | sfm | meandom | mindom | maxdom | dfrange | modindx | startdom | enddom | dfslope | meanpeakf |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Phae.long1.wav_1 | 1 | 0.173033 | 5.91706 | 1.98509 | 6.33314 | 5.11278 | 6.95778 | 1.84500 | 0.077060 | 0.049435 | 0.117771 | 0.068337 | 2.55569 | 10.19518 | 0.930148 | 0.893591 | 0.831172 | 0.575701 | 6.58500 | 4.3125 | 8.2875 | 3.975 | 4.90566 | 7.1625 | 7.1625 | 0.000000 | 7.13514 |
Phae.long1.wav_2 | 1 | 0.163048 | 5.90489 | 1.96549 | 6.20859 | 5.20859 | 6.95706 | 1.74847 | 0.077165 | 0.045135 | 0.116476 | 0.071342 | 2.39934 | 9.94032 | 0.933989 | 0.897093 | 0.837876 | 0.594429 | 6.76626 | 4.4625 | 8.5125 | 4.050 | 4.07407 | 6.9375 | 7.2375 | 1.839949 | 6.90862 |
Phae.long1.wav_3 | 1 | 0.174919 | 5.94003 | 2.04754 | 6.43225 | 4.89994 | 7.07261 | 2.17267 | 0.089635 | 0.054938 | 0.128670 | 0.073732 | 2.99989 | 14.94906 | 0.932716 | 0.893109 | 0.833017 | 0.592655 | 6.80103 | 3.8625 | 8.6625 | 4.800 | 5.25000 | 7.0875 | 7.2375 | 0.857541 | 6.83311 |
Phae.long2.wav_1 | 1 | 0.132571 | 6.39401 | 1.77094 | 6.66415 | 5.56226 | 7.47170 | 1.90943 | 0.077461 | 0.053627 | 0.104275 | 0.050648 | 2.04464 | 8.05258 | 0.922802 | 0.910264 | 0.839993 | 0.505319 | 6.50014 | 4.9875 | 7.8375 | 2.850 | 6.50000 | 7.1625 | 6.1875 | -7.354555 | 7.36165 |
Phae.long2.wav_2 | 1 | 0.126150 | 6.25484 | 1.80648 | 6.60587 | 5.44806 | 7.31959 | 1.87153 | 0.078083 | 0.054057 | 0.099105 | 0.045048 | 2.96411 | 14.49506 | 0.917199 | 0.913833 | 0.838167 | 0.515082 | 6.29515 | 3.0375 | 7.6125 | 4.575 | 3.80328 | 4.8375 | 6.6375 | 14.268705 | 6.75760 |
Phae.long3.wav_1 | 1 | 0.131220 | 6.48030 | 1.71110 | 6.65904 | 5.97254 | 7.45233 | 1.47979 | 0.062618 | 0.040255 | 0.089455 | 0.049200 | 2.47759 | 10.29901 | 0.906241 | 0.911341 | 0.825894 | 0.465522 | 6.62233 | 4.8375 | 8.0625 | 3.225 | 3.67442 | 7.0125 | 8.0625 | 8.001857 | 6.75760 |
Phae.long3.wav_2 | 1 | 0.130179 | 6.54728 | 1.66118 | 6.67179 | 6.04151 | 7.50961 | 1.46810 | 0.068830 | 0.043393 | 0.094267 | 0.050874 | 2.22587 | 7.92601 | 0.901351 | 0.912495 | 0.822478 | 0.448897 | 6.38352 | 4.6125 | 7.5375 | 2.925 | 4.35897 | 6.7125 | 7.0125 | 2.304520 | 6.68210 |
Phae.long3.wav_3 | 1 | 0.131217 | 6.39641 | 1.74753 | 6.62090 | 5.89626 | 7.42944 | 1.53318 | 0.064109 | 0.038764 | 0.093927 | 0.055164 | 2.31111 | 8.30633 | 0.904421 | 0.912315 | 0.825117 | 0.474448 | 6.24817 | 4.6875 | 7.0125 | 2.325 | 4.06452 | 4.6875 | 6.6375 | 14.860884 | 6.75760 |
Phae.long4.wav_1 | 1 | 0.145425 | 6.00224 | 1.94330 | 6.18294 | 5.16506 | 7.31774 | 2.15268 | 0.083728 | 0.044067 | 0.113106 | 0.069039 | 1.60426 | 5.48360 | 0.944668 | 0.904381 | 0.854339 | 0.624541 | 6.12825 | 3.5625 | 8.2875 | 4.725 | 2.76191 | 5.3625 | 3.5625 | -12.377522 | 6.30456 |
Phae.long4.wav_2 | 1 | 0.144186 | 6.11418 | 1.96027 | 6.21790 | 5.35045 | 7.46010 | 2.10965 | 0.083859 | 0.042665 | 0.108869 | 0.066204 | 1.87987 | 7.22913 | 0.944252 | 0.905089 | 0.854633 | 0.620154 | 6.34508 | 3.6375 | 8.9625 | 5.325 | 5.56338 | 8.0625 | 3.6375 | -30.689430 | 6.22905 |
Phae.long4.wav_3 | 1 | 0.145099 | 5.84222 | 1.93942 | 6.00690 | 4.85517 | 7.20000 | 2.34483 | 0.081440 | 0.044422 | 0.111054 | 0.066633 | 1.37025 | 4.79206 | 0.947509 | 0.905043 | 0.857536 | 0.621575 | 6.12008 | 3.7125 | 8.5875 | 4.875 | 4.76923 | 7.9125 | 3.7125 | -28.945769 | 6.00253 |
snr <- sig2noise(ext_st, mar = 0.05)
snr
sound.files | channel | selec | start | end | bottom.freq | top.freq | SNR |
---|---|---|---|---|---|---|---|
Phae.long1.wav_1 | 1 | 1 | 0.1 | 0.273033 | 2.22011 | 8.60438 | 21.2716 |
Phae.long1.wav_2 | 1 | 1 | 0.1 | 0.263048 | 2.16944 | 8.80705 | 20.0787 |
Phae.long1.wav_3 | 1 | 1 | 0.1 | 0.274919 | 2.21829 | 8.75660 | 18.9644 |
Phae.long2.wav_1 | 1 | 1 | 0.1 | 0.232571 | 2.31686 | 8.82232 | 23.4963 |
Phae.long2.wav_2 | 1 | 1 | 0.1 | 0.226150 | 2.28401 | 8.88803 | 25.9055 |
Phae.long3.wav_1 | 1 | 1 | 0.1 | 0.231220 | 3.00683 | 8.82232 | 26.2175 |
Phae.long3.wav_2 | 1 | 1 | 0.1 | 0.230179 | 2.77684 | 8.88803 | 25.5638 |
Phae.long3.wav_3 | 1 | 1 | 0.1 | 0.231217 | 2.31686 | 9.31515 | 25.5538 |
Phae.long4.wav_1 | 1 | 1 | 0.1 | 0.245425 | 2.51400 | 9.21659 | 27.9043 |
Phae.long4.wav_2 | 1 | 1 | 0.1 | 0.244186 | 2.57971 | 10.23512 | 28.6007 |
Phae.long4.wav_3 | 1 | 1 | 0.1 | 0.245099 | 2.57971 | 9.74228 | 24.4342 |
dtw.dist <- freq_DTW(ext_st, img = FALSE)
dtw.dist
Phae.long1.wav_1-1 | Phae.long1.wav_2-1 | Phae.long1.wav_3-1 | Phae.long2.wav_1-1 | Phae.long2.wav_2-1 | Phae.long3.wav_1-1 | Phae.long3.wav_2-1 | Phae.long3.wav_3-1 | Phae.long4.wav_1-1 | Phae.long4.wav_2-1 | Phae.long4.wav_3-1 | |
---|---|---|---|---|---|---|---|---|---|---|---|
Phae.long1.wav_1-1 | 0.000 | 6.134 | 10.597 | 8.867 | 15.329 | 9.310 | 10.316 | 15.528 | 23.427 | 22.011 | 23.768 |
Phae.long1.wav_2-1 | 6.134 | 0.000 | 9.128 | 11.939 | 21.299 | 13.185 | 13.584 | 22.565 | 25.262 | 24.802 | 26.605 |
Phae.long1.wav_3-1 | 10.597 | 9.128 | 0.000 | 15.535 | 21.041 | 14.604 | 15.380 | 21.831 | 28.276 | 27.814 | 28.204 |
Phae.long2.wav_1-1 | 8.867 | 11.939 | 15.535 | 0.000 | 10.570 | 10.623 | 10.204 | 10.909 | 17.888 | 17.292 | 19.602 |
Phae.long2.wav_2-1 | 15.329 | 21.299 | 21.041 | 10.570 | 0.000 | 7.488 | 7.317 | 4.027 | 18.139 | 24.295 | 23.008 |
Phae.long3.wav_1-1 | 9.310 | 13.185 | 14.604 | 10.623 | 7.488 | 0.000 | 5.940 | 8.833 | 25.193 | 26.461 | 26.199 |
Phae.long3.wav_2-1 | 10.316 | 13.584 | 15.380 | 10.204 | 7.317 | 5.940 | 0.000 | 7.786 | 21.060 | 22.788 | 22.402 |
Phae.long3.wav_3-1 | 15.528 | 22.565 | 21.831 | 10.909 | 4.027 | 8.833 | 7.786 | 0.000 | 18.949 | 24.264 | 23.456 |
Phae.long4.wav_1-1 | 23.427 | 25.262 | 28.276 | 17.888 | 18.139 | 25.193 | 21.060 | 18.949 | 0.000 | 12.639 | 7.574 |
Phae.long4.wav_2-1 | 22.011 | 24.802 | 27.814 | 17.292 | 24.295 | 26.461 | 22.788 | 24.264 | 12.639 | 0.000 | 8.492 |
Phae.long4.wav_3-1 | 23.768 | 26.605 | 28.204 | 19.602 | 23.008 | 26.199 | 22.402 | 23.456 | 7.574 | 8.492 | 0.000 |
The use of extended_selection_table objects can improve performance (in our case, measured as time). Here we use microbenchmark to compare the performance of sig2noise()
and ggplot2 to plot the results:
# load packages
library(microbenchmark)
library(ggplot2)
# take first 100 selections
mbmrk.snr <- microbenchmark(extended = sig2noise(lng_ext_st[1:100, ],
mar = 0.05), regular = sig2noise(lng.selec.table[1:100, ],
mar = 0.05), times = 50)
autoplot(mbmrk.snr) + ggtitle("sig2noise")
The function runs much faster in the extended selection tables. Performance gain is likely to improve when longer recordings and data sets are used (that is, to compensate for computer overload).
The extended selection above were made by element. That is, each sound file within the object contains a single selection (that is, a 1: 1 correspondence between the selections and the ‘wave’ objects). However, extended selection tables can also be created using a higher hierarchical level with the argument by.song
. In this case, “song” represents a higher level that contains one or more selections and that the user may want to keep together for a particular analysis (for example, the duration of the intervals). The by.song
argument takes the name of the column of characters or factors with the IDs of the different” songs “within a sound file (note that the function assumes that a given song can only be found in only one sound file, so the selections with the same song ID, but from different sound files are taken as different ‘songs’).
To create a selection table by song, let’s add an artificial song column to our example data in which each of the sound files has 2 songs:
# add column
lbh_selec_table$song <- c(1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2)
The data looks like this:
sound.files | channel | selec | start | end | bottom.freq | top.freq | song |
---|---|---|---|---|---|---|---|
Phae.long1.wav | 1 | 1 | 1.169355 | 1.342388 | 2.22011 | 8.60438 | 1 |
Phae.long1.wav | 1 | 2 | 2.158408 | 2.321457 | 2.16944 | 8.80705 | 1 |
Phae.long1.wav | 1 | 3 | 0.343337 | 0.518255 | 2.21829 | 8.75660 | 2 |
Phae.long2.wav | 1 | 1 | 0.159598 | 0.292169 | 2.31686 | 8.82232 | 1 |
Phae.long2.wav | 1 | 2 | 1.457058 | 1.583209 | 2.28401 | 8.88803 | 2 |
Phae.long3.wav | 1 | 1 | 0.626552 | 0.757771 | 3.00683 | 8.82232 | 1 |
Phae.long3.wav | 1 | 2 | 1.974213 | 2.104392 | 2.77684 | 8.88803 | 1 |
Phae.long3.wav | 1 | 3 | 0.123364 | 0.254581 | 2.31686 | 9.31515 | 2 |
Phae.long4.wav | 1 | 1 | 1.516812 | 1.662236 | 2.51400 | 9.21659 | 1 |
Phae.long4.wav | 1 | 2 | 2.932692 | 3.076878 | 2.57971 | 10.23512 | 2 |
Phae.long4.wav | 1 | 3 | 0.145398 | 0.290497 | 2.57971 | 9.74228 | 2 |
Now we can create an extended selection table ‘by song’ using the column name ‘song’ as input for the argument by.song
:
bs_ext_st <- selection_table(X = lbh_selec_table, extended = TRUE,
confirm.extended = FALSE, by.song = "song")
In this case, we should only have 8 ‘wave’ objects instead of 11 as when the object was created ‘by selection’:
# by element
length(attr(ext_st, "wave.objects"))
[1] 11
# by song
length(attr(bs_ext_st, "wave.objects"))
[1] 8
Again, these objects can also be used in any analyzes:
# signal to noise ratio
bs_snr <- sig2noise(bs_ext_st, mar = 0.05)
sound.files | channel | selec | start | end | bottom.freq | top.freq | song | SNR |
---|---|---|---|---|---|---|---|---|
Phae.long1.wav-song_1 | 1 | 1 | 0.10000 | 0.273033 | 2.22011 | 8.60438 | 1 | 21.2716 |
Phae.long1.wav-song_1 | 1 | 2 | 1.08905 | 1.252102 | 2.16944 | 8.80705 | 1 | 20.0787 |
Phae.long1.wav-song_2 | 1 | 1 | 0.10000 | 0.274919 | 2.21829 | 8.75660 | 2 | 18.9644 |
Phae.long2.wav-song_1 | 1 | 1 | 0.10000 | 0.232571 | 2.31686 | 8.82232 | 1 | 23.4963 |
Phae.long2.wav-song_2 | 1 | 1 | 0.10000 | 0.226150 | 2.28401 | 8.88803 | 2 | 25.9055 |
Phae.long3.wav-song_1 | 1 | 1 | 0.10000 | 0.231220 | 3.00683 | 8.82232 | 1 | 26.2175 |
Phae.long3.wav-song_1 | 1 | 2 | 1.44766 | 1.577840 | 2.77684 | 8.88803 | 1 | 25.5727 |
Phae.long3.wav-song_2 | 1 | 1 | 0.10000 | 0.231217 | 2.31686 | 9.31515 | 2 | 25.5538 |
Phae.long4.wav-song_1 | 1 | 1 | 0.10000 | 0.245425 | 2.51400 | 9.21659 | 1 | 27.9043 |
Phae.long4.wav-song_2 | 1 | 1 | 2.88729 | 3.031481 | 2.57971 | 10.23512 | 2 | 28.5995 |
Phae.long4.wav-song_2 | 1 | 2 | 0.10000 | 0.245099 | 2.57971 | 9.74228 | 2 | 24.4342 |
Exercise
Bioacoustic analyzes generally follow a specific processing sequence and analysis. This sequence can be represented schematically like this:
We can group warbleR functions according to the bioacoustic analysis stages.
The query_xc()
function allows you to search and download sounds from the free access database Xeno-Canto. You can also convert .mp3 files to .wav, change the sampling rate of the files and correct corrupt files, among other functions.
Function | Description | Works.on | Output |
---|---|---|---|
check_wavs | verify if sound files can be read | multiple wave files | data frame |
consolidate | consolidate sound files in a single folder | multiple wave files | data frame and wave files |
fix_wavs | fix waves that cannot be read in R | multiple wave files | wave files |
mp32wav | convert multiple mp3 files to wav format | multiple mp3 files | wave files |
query_xc | Search and download mp3 files from Xeno-Canto | Scientific names/data frame | mp3 files |
resample_est | resample wave objects in ext. selection tables | extended selection tables | extended selection tables |
remove_channels | remove channels in multiple wave files | multiple wave files | wave files |
remove_silence | remove silences in multiple wave files | multiple wave files | wave files |
duration_wavs | measures duration in multiple wave files | multiple wave files | data frame |
info_wavs | extract recording parameters from multiple wave files | multiple wave files | data frame |
It is recommended to make annotations in other programs and then import them into R (for example in Raven and import them with the Rraven package). However, warbleR offers some functions to facilitate manual or automatic annotation of sound files, as well as the subsequent manipulation:
Function | Description | Works.on | Output |
---|---|---|---|
auto_detec | automatic annotation of wave files | multiple wave files | data frame, images |
optimize_auto_detec | Try different detection settings to optimize auto_detec detections | auto_detec output | data frame |
freq_range | detect frequency range in selection tables | multiple wave files | data frame |
tailor_sels | interactive tailoring of selections | selection tables | selection tables |
Automatic detection can significantly speed up acoustic analysis. warbleR offers two main methods for automatic signal detection (cross-correlation and amplitude threshold filter) as well as functions to explore detections:
Function | Description | Works.on | Output |
---|---|---|---|
auto_detec | automatic annotation of wave files | multiple wave files | data frame, images |
optimize_auto_detec | Try different detection settings to optimize auto_detec detections | auto_detec output | data frame |
freq_range | detect frequency range in selection tables | multiple wave files | data frame |
tailor_sels | interactive tailoring of selections | selection tables | selection tables |
The annotations (or selection tables) can be manipulated and refined with a variety of functions. Selection tables can also be converted into the compact format extended selection tables:
Function | Description | Works.on | Output |
---|---|---|---|
tailor_sels | interactive tailoring of selections | selection tables | selection tables |
sort_colms | order columns in an intuitive way | selection tables | selection tables |
cut_sels | save selections as individual wave files | selection tables | wave files |
filter_sels | subset selection tables based on filtered image files | selection tables, ext. selection tables, images | selection tables, ext. selection tables |
fix_extended_selection_table | add wave objects to extended selection tables | selection tables | extended selection tables |
selection_table | create selection tables and extended selection tables | selection tables | selection tables, ext. selection tables |
song_analysis | measures acoustic parameters at higher structural levels of organization | selection tables, ext. selection tables | data frame, selection tables |
Most warbleR functions are dedicated to quantifying the structure of acoustic signals listed in selection tables using batch processing. For this, 4 main measurement methods are offered:
Most functions gravitate around these methods, or variations of these methods:
Function | Description | Works.on | Output |
---|---|---|---|
freq_range | detect frequency range in selection tables | multiple wave files | data frame |
song_analysis | measures acoustic parameters at higher structural levels of organization | selection tables, ext. selection tables | data frame, selection tables |
compare_methods | compare the performance of methods to measure acoustic structure | selection tables, ext. selection tables | images |
freq_DTW | measures dynamic time warping (DTW) on dominant/fundamental frequency contours | selection tables, ext. selection tables | (di)similarity matrix, images |
freq_ts | mesaures dominant/fundamental frequency contours | selection tables, ext. selection tables | data frame with frequency contours |
inflections | measures number of inflections in frequency contours | data frame with frequency contours | data frame |
mfcc_stats | measures statistical descriptors of Mel cepstral coefficients | selection tables, ext. selection tables | data frame |
multi_DTW | measures dynamic time warping (DTW) on multiple contours | selection tables, ext. selection tables | (di)similarity matrix |
sig2noise | measures signal-to-noise ratio | selection tables, ext. selection tables | selection tables, ext. selection tables |
spectro_analysis | measures spectrographic parameters | selection tables, ext. selection tables | data frame |
cross_correlation | measurec spectrographic cross-correlation | selection tables, ext. selection tables | (di)similarity matrix |
Exercise
spectro_analysis()
on the example ‘lbh_selec_table’ with “the argument ‘fast = TRUE’ vs ‘fast = FALSE’. What does this argument do and which seewave
function might be involved?
Functions are provided to detect inconsistencies in the selection tables or modify selection tables. The package also offers several functions to generate spectrograms showing the annotations, which can be organized by annotation categories. This allows you to verify if the annotations match the previously defined categories, which is particularly useful if the annotations were automatically generated.
Function | Description | Works.on | Output |
---|---|---|---|
check_sels | double-check selection tables | selection tables | selection tables |
overlapping_sels | finds (time) overlapping selections | selection tables, ext. selection tables | selection tables, ext. selection tables |
catalog | creates spectrogram catalog | selection tables, ext. selection tables | images |
catalog2pdf | convert catalogs to .pdf | images | images |
spectrograms | create spectrogram images | selection tables, ext. selection tables | images |
full_spectrograms | create spectrograms of whole sound files | multiple wave files, selection tables, ext. selection tables | images |
full_spectrogram2pdf | convert full spectrograms to .pfg | images | images |
Function | Description | Works.on | Output |
---|---|---|---|
snr_spectrograms | plots spectrograms highlighting areas where signal-to-noise ratio is measured | selection tables, ext. selection tables | images |
spectrograms | create spectrogram images | selection tables, ext. selection tables | images |
track_freqs | create spectrogram images including frequency contours | selection tables, ext. selection tables | images |
plot_coordination | create schematic plots of coordinated signals | data frame | images |
full_spectrograms | create spectrograms of whole sound files | multiple wave files, selection tables, ext. selection tables | images |
Finally, warbleR offers functions to simplify the use of extended selection tables, organize large numbers of images with spectrograms and generate elaborated signal visualizations:
Function | Description | Works.on | Output |
---|---|---|---|
is_extended_selection_table | check if object is extended selection tables | data frame | TRUE/FALSE |
is_selection_table | check if object is selection tables | data frame | TRUE/FALSE |
catalog2pdf | convert catalogs to .pdf | images | images |
move_imgs | moves images among folders | images | images |
harmonic_track | measures harmonics with highest energy | wave object | data frame with frequency contours |
map_xc | created maps from Xeno-Canto recordings | data frame | images |
test_coordination | test statistical significance of vocal coordination | data frame | data frame |
full_spectrogram2pdf | convert full spectrograms to .pfg | images | images |
color_spectro | highlight signals with colors in a spectrogram | wave object | plot in R |
freq_range_detec | detect frequency range in wave objetcs | wave object | data frame, plot in R |
open_wd | open working directory | ||
phylo_spectro | plots phylogenetic trees with spectrograms | selection tables | plot in R |
read_wave | read wave files and wave objects | selection tables, ext. selection tables | wave object |
sim_songs | simulate songs | wave object, wave file and selection table | |
tweak_spectro | creates mosaic plots with spectrograms with different display parameters | selection tables, ext. selection tables | images |
warbleR_options | define global parameters for warbleR functions |
Exercise
Run the examples of the functions phylo_spectro()
and color_spectro()
Use the query_xc()
and map_xc()
functions to explore the geographical distribution of the Xeno-Canto recordings of a species (of bird) of your interest (if any!)
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] ggplot2_3.3.5 microbenchmark_1.4-7 kableExtra_1.3.4 warbleR_1.1.27
[5] NatureSounds_1.0.4 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] ohun_0.1.0 rstudioapi_0.13 proxy_0.4-26 spatstat.data_2.1-2
[9] farver_2.1.0 xaringan_0.22 Deriv_4.1.3 audio_0.1-10
[13] remotes_2.4.0 DT_0.19 fansi_1.0.2 xml2_1.3.2
[17] codetools_0.2-18 splines_4.1.1 baRulho_1.0.6 polyclip_1.10-0
[21] jsonlite_1.7.2 Rraven_1.0.13 cluster_2.1.2 png_0.1-7
[25] bioacoustics_0.2.8 shiny_1.6.0 spatstat.sparse_2.1-0 compiler_4.1.1
[29] httr_1.4.2 assertthat_0.2.1 Matrix_1.3-4 fastmap_1.1.0
[33] cli_3.2.0 later_1.3.0 formatR_1.11 htmltools_0.5.2
[37] tools_4.1.1 gtable_0.3.0 glue_1.6.2 PhenotypeSpace_0.1.0
[41] dplyr_1.0.7 Rcpp_1.0.8 jquerylib_0.1.4 raster_3.5-11
[45] vctrs_0.3.8 svglite_2.0.0 nlme_3.1-152 xfun_0.30
[49] stringr_1.4.0 phonTools_0.2-2.1 rvest_1.0.1 mime_0.11
[53] lifecycle_1.0.1 goftest_1.2-3 terra_1.5-12 zoo_1.8-9
[57] MASS_7.3-54 scales_1.1.1 spatstat.core_2.3-2 promises_1.2.0.1
[61] spatstat.utils_2.3-0 shinyBS_0.61 parallel_4.1.1 Sim.DiffProc_4.8
[65] yaml_2.3.5 pbapply_1.5-0 gridExtra_2.3 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 ]