Organización jerárquica de sonidos animales

Las vocalizaciones animales se pueden estructurar jerárquicamente: los elementos se agrupan en sílabas, sílabas en cantos, cantos en tandas de canto, etc:

 

viewSpec

 

Las unidades mas básicas, generalmente llamadas notas o elementos, corresponden a trazas continuas de amplitud en el espectrograma. Los niveles por encima de los elementos identifican secuencias de unidades a una menor escala jerárquica cuya secuencia se repite a lo largo del canto.

Muchos patrones biológicos importantes de variación vocal se describen mejor en niveles estructurales más altos, por lo que a menudo nos interesa caracterizar las vocalizaciones en esos niveles. Hay varias herramientas en warbleR para explorar y medir características por encima del nivel de elementos. Para simplificar, cualquier nivel por encima de ‘elemento’ se denominará ‘canto’ , así como en las funciones warbleR que se describen aquí (‘song’).

Tomemos como ejemplo el canto de Phaethornis eurynome:

 

 

Este es un canto muy sencillo con solo un par de elementos. La agrupación de los elementos en pares es clara tanto en el espectrograma como cuando escuchamos el canto.

La literatura científica no es consistente en el uso de términos para referirse a los niveles de organización estructural de sonidos animales. Por lo tanto, es importante definir explicitamente cualquier categoría que se utilice para organizar la estructura de estos.

Medir parámetros a otros niveles jerárquicos

El archivo ‘P. eurynome selection table.csv’ con las anotaciones se encuentra en la carpeta ‘ejemplos’. El archivo con anotaciones tiene un par de columnas que contienen las etiquetas de elementos y cantos:

Podemos hacer espectrogramas de la grabación completa con cuadros en los elementos y líneas naranjas sobre los elementos, destacando aquellos que pertenecen al mismo canto. Esto se puede hacer usando el argumento ‘song’ en lspec(). El argumento simplemente toma el nombre de la columna con las etiquetas de la canto:

# cargar warbleR 
library(warbleR)

# parametros globales
warbleR_options(flim = c(2.5, 14), wl = 200, ovlp = 90, wav.path = "PONER RUTA A 'ejemplos' AQUI")

# leer anotaciones
pe_st <- read.csv("./ejemplos/P. eurynome selection table.csv")

# crear espectrogramas completos
lspec(pe_st, sxrow = 2.5, rows = 7, fast.spec = TRUE, 
      horizontal = TRUE, song = "song")

 

Podemos trazar espectrogramas individuales de cada canto utilizando el argumento ‘song’ en specreator(). La función etiquetará cada elemento usando la etiqueta de la columna ‘selec’:

specreator(pe_st, by.song = "song")

 

Luego, la función realiza un único espectrograma por canto en lugar de uno por elemento, como es el caso cuando no se declara una columna de canto.

También podemos utilizar nuestras propias etiquetas en los elementos. En este caso, la columna ‘olmo’ tiene las etiquetas que usé para clasificar los 2 elementos del canto:

specreator(pe_st, by.song = "song", sel.labels = "elm")

 

Las características del canto se pueden medir utilizando song_param(). La función calcula varias características descriptivas de los cantos, incluidos el tiempo inicial y final, la frecuencia superior e inferior (la frecuencia inferior más baja y la más alta más alta de todos los elementos), la duración media de los elementos, la duración del canto, el número de elementos, el rango de frecuencia, la tasa de canto (elementos por segundo) y duración de los intervalos entre elementos:

song_feat <- song_param(pe_st, song_colm = "song")

head(song_feat)
sound.files selec start end top.freq bottom.freq song num.elms elm.duration freq.range song.duration song.rate gap.duration
Phaethornis-eurynome-15607.wav 1 0.773606 1.151724 9.15075 2.97675 1 2 0.1766441 6.17400 0.3781182 5.289352 0.0248299
Phaethornis-eurynome-15607.wav 1 2.807666 3.184560 10.00000 2.97675 2 2 0.1760545 7.02325 0.3768937 5.306536 0.0247846
Phaethornis-eurynome-15607.wav 1 4.200887 4.571976 10.00000 3.19725 3 2 0.1761566 6.80275 0.3710887 5.389547 0.0187755
Phaethornis-eurynome-15607.wav 1 4.966239 5.344562 9.81225 3.19725 4 2 0.1829026 6.61500 0.3783223 5.286498 0.0125170
Phaethornis-eurynome-15607.wav 1 5.956716 6.323474 10.00000 2.97675 5 2 0.1615874 7.02325 0.3667576 5.453193 0.0435828
Phaethornis-eurynome-15607.wav 1 7.424245 7.796151 8.93025 3.41775 6 2 0.1591724 5.51250 0.3719050 5.377717 0.0535601

 

Si se suministra la columna de etiqueta del elemento, la función también devolverá el número de tipos de elementos únicos (columna ‘elm.types’) y el número medio de veces que se encuentran los tipos de elementos en un canto (‘mean.elm.count’):

song_feat <- song_param(pe_st, song_colm = "song", elm_colm = "elm")

# ver una parte de los datos
head(song_feat[, -c(2:6)])
sound.files elm.duration freq.range song.duration song.rate gap.duration elm.types mean.elm.count
Phaethornis-eurynome-15607.wav 0.1766441 6.17400 0.3781182 5.289352 0.0248299 2 1
Phaethornis-eurynome-15607.wav 0.1760545 7.02325 0.3768937 5.306536 0.0247846 2 1
Phaethornis-eurynome-15607.wav 0.1761566 6.80275 0.3710887 5.389547 0.0187755 2 1
Phaethornis-eurynome-15607.wav 0.1829026 6.61500 0.3783223 5.286498 0.0125170 2 1
Phaethornis-eurynome-15607.wav 0.1615874 7.02325 0.3667576 5.453193 0.0435828 2 1
Phaethornis-eurynome-15607.wav 0.1591724 5.51250 0.3719050 5.377717 0.0535601 2 1

 

Y si los parámetros espectrales se han medido en los elementos, también se pueden promediar por canto de la siguiente manera:

# mmedir parametros acusticos
elm_sp <- specan(pe_st)

# añadir datos de canto
elm_sp <- merge(elm_sp[ , -c(3:4)], pe_st, by = c("sound.files", "selec"))

# calcular kurtosis y entropia
song_feat <- song_param(X = elm_sp, song_colm = "song", 
                        mean_colm = c("kurt", "sp.ent"))

# ver datos
head(song_feat)
sound.files selec start end top.freq bottom.freq song kurt sp.ent num.elms elm.duration freq.range song.duration song.rate gap.duration
Phaethornis-eurynome-15607.wav 1 0.773606 1.151724 9.15075 2.97675 1 9.431925 0.9259725 2 0.1766441 6.17400 0.3781182 5.289352 0.0248299
Phaethornis-eurynome-15607.wav 1 5.956716 6.323474 10.00000 2.97675 5 5.903726 0.9283246 2 0.1615874 7.02325 0.3667576 5.453193 -0.3667576
Phaethornis-eurynome-15607.wav 1 7.424245 7.796151 8.93025 3.41775 6 10.269098 0.9192882 2 0.1591724 5.51250 0.3719050 5.377717 0.0535601
Phaethornis-eurynome-15607.wav 1 8.851344 9.218011 9.37125 3.41775 7 5.396240 0.9283730 2 0.1539684 5.95350 0.3666669 5.454542 0.0587302
Phaethornis-eurynome-15607.wav 1 10.932547 11.307672 8.70975 3.41775 8 8.002969 0.9225578 2 0.1724491 5.29200 0.3751250 5.331556 0.0302268
Phaethornis-eurynome-15607.wav 1 12.159691 12.539737 8.93025 3.41775 9 7.194692 0.9294223 2 0.1790704 5.51250 0.3800456 5.262526 0.0219048

 

EL mínimo, máximo y desviación estándar también pueden devolverse usando los argumentos ‘min_colm’, ‘max_colm’ y ‘sd’ respectivamente.

Dado que el tiempo de inicio y final y las frecuencias inferior y superior de los cantos son calculadas por song_param(), el cuadro de datos que genera puede usarse como una tabla de selección para medir o comparar los cantos. Por ejemplo, podemos ejecutar la correlación cruzada entre cantos, tal vez como una métrica de la consistencia de los cantos, de la siguiente manera:

song_feat <- song_param(X = elm_sp, song_colm = "song")

# correr correlacion cruzada
xc <- xcorr(song_feat[1:10, ])

head(xc)
Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1 Phaethornis-eurynome-15607.wav-1
Phaethornis-eurynome-15607.wav-1 1.0000000 0.8471482 0.8234709 0.8162339 0.7400943 0.8435275 0.8017136 0.7437771 0.8142170 0.8027811
Phaethornis-eurynome-15607.wav-1 0.8471482 1.0000000 0.8471482 0.8234709 0.8162339 0.7400943 0.8435275 0.8017136 0.7437771 0.8142170
Phaethornis-eurynome-15607.wav-1 0.8234709 0.8471482 1.0000000 0.8027811 0.8471482 0.8234709 0.8162339 0.7400943 0.8435275 0.8017136
Phaethornis-eurynome-15607.wav-1 0.8162339 0.8234709 0.8027811 1.0000000 0.7437771 0.8142170 0.8027811 0.8471482 0.8234709 0.8162339
Phaethornis-eurynome-15607.wav-1 0.7400943 0.8162339 0.8471482 0.7437771 1.0000000 0.7400943 0.8435275 0.8017136 0.7437771 0.8142170
Phaethornis-eurynome-15607.wav-1 0.8435275 0.7400943 0.8234709 0.8142170 0.7400943 1.0000000 0.8027811 0.8471482 0.8234709 0.8162339
Phaethornis-eurynome-15607.wav-1 0.8017136 0.8435275 0.8162339 0.8027811 0.8435275 0.8027811 1.0000000 0.7400943 0.8435275 0.8017136
Phaethornis-eurynome-15607.wav-1 0.7437771 0.8017136 0.7400943 0.8471482 0.8017136 0.8471482 0.7400943 1.0000000 0.7437771 0.8142170
Phaethornis-eurynome-15607.wav-1 0.8142170 0.7437771 0.8435275 0.8234709 0.7437771 0.8234709 0.8435275 0.7437771 1.0000000 0.8027811
Phaethornis-eurynome-15607.wav-1 0.8027811 0.8142170 0.8017136 0.8162339 0.8142170 0.8162339 0.8017136 0.8142170 0.8027811 1.0000000

 

Finalmente, se pueden crear tablas de selección extendida al nivel del canto. Esto significa que todos los elementos de un canto estarán contenidos en un objeto ‘wave’ único dentro de la tabla de selección. Esto permite a los usuarios tomar métricas a nivel del canto como las descritas anteriormente usando este tipo de objetos (esto no es posible cuando se crean en base a elementos, que es el comportamiento predeterminado).

La tabla de selección extendida de nivel de cantos se puede crear usando el argumento ‘by.song’, que toma la columna de la etiqueta de cantos, de la siguiente manera:

pe_est <- selection_table(pe_st, extended = TRUE, 
              confirm.extended = FALSE, by.song = "song")

pe_est
## all selections are OK
## object of class 'extended_selection_table' 
##  contains a selection table data frame with 46 rows and 8 columns: 
##                             sound.files selec     start       end
## 1 Phaethornis-eurynome-15607.wav-song_1     1 0.1000000 0.2779820
## 2 Phaethornis-eurynome-15607.wav-song_1     2 0.3028119 0.4781182
## 3 Phaethornis-eurynome-15607.wav-song_2     1 0.1000000 0.2761906
## 4 Phaethornis-eurynome-15607.wav-song_2     2 0.3009752 0.4768937
## 5 Phaethornis-eurynome-15607.wav-song_3     1 0.1000000 0.2809979
## 6 Phaethornis-eurynome-15607.wav-song_3     2 0.2997734 0.4710887
##   bottom.freq top.freq song elm
## 1     4.07925  8.48925    1   a
## 2     2.97675  9.15075    1   b
## 3     4.29975  6.94575    2   a
## 4     2.97675 10.00000    2   b
## 5     4.07925  6.94575    3   a
## 6     3.19725 10.00000    3   b
## ... and 40 more rows 
## 23 wave objects (as attributes): 
## [1] "Phaethornis-eurynome-15607.wav-song_1"
## [2] "Phaethornis-eurynome-15607.wav-song_2"
## [3] "Phaethornis-eurynome-15607.wav-song_3"
## [4] "Phaethornis-eurynome-15607.wav-song_4"
## [5] "Phaethornis-eurynome-15607.wav-song_5"
## [6] "Phaethornis-eurynome-15607.wav-song_6"
## ... and 17 more 
## and a data frame (check.results) generated by checkres() (as attribute) 
## the selection table was created by song (see 'class_extended_selection_table')

 

Cuenta con 23 objetos ‘wave’, uno por cada canto.

Ahora podemos medir cosas sobre los cantos sin tener que mantener el archivo de sonido original. El siguiente código elimina el archivo de sonido y mide los parámetros de nivel de cantos usando la tabla de selección extendida:

# eliminar
# unlink("Phaethornis-eurynome-15607.wav")

# measure song features
song_feat <- song_param(pe_est, song_colm = "song")
sound.files selec start end top.freq bottom.freq song num.elms elm.duration freq.range song.duration song.rate gap.duration
Phaethornis-eurynome-15607.wav 1 0.773606 1.151724 9.15075 2.97675 1 2 0.1766441 6.17400 0.3781182 5.289352 0.0248299
Phaethornis-eurynome-15607.wav 1 2.807666 3.184560 10.00000 2.97675 2 2 0.1760545 7.02325 0.3768937 5.306536 0.0247846
Phaethornis-eurynome-15607.wav 1 4.200887 4.571976 10.00000 3.19725 3 2 0.1761566 6.80275 0.3710887 5.389547 0.0187755
Phaethornis-eurynome-15607.wav 1 4.966239 5.344562 9.81225 3.19725 4 2 0.1829026 6.61500 0.3783223 5.286498 0.0125170
Phaethornis-eurynome-15607.wav 1 5.956716 6.323474 10.00000 2.97675 5 2 0.1615874 7.02325 0.3667576 5.453193 0.0435828
Phaethornis-eurynome-15607.wav 1 7.424245 7.796151 8.93025 3.41775 6 2 0.1591724 5.51250 0.3719050 5.377717 0.0535601

 


Información de la sesión

## R version 3.5.3 (2019-03-11)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.2 LTS
## 
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] kableExtra_1.1.0   warbleR_1.1.16     NatureSounds_1.0.1
## [4] seewave_2.1.3      tuneR_1.3.3        maps_3.3.0        
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.1        pracma_2.2.5      highr_0.8        
##  [4] pillar_1.3.1      compiler_3.5.3    bitops_1.0-6     
##  [7] iterators_1.0.10  tools_3.5.3       Sim.DiffProc_4.3 
## [10] digest_0.6.18     viridisLite_0.3.0 evaluate_0.13    
## [13] tibble_2.1.1      fftw_1.0-5        pkgconfig_2.0.2  
## [16] rlang_0.3.4       rstudioapi_0.10   yaml_2.2.0       
## [19] parallel_3.5.3    xfun_0.6          xml2_1.2.0       
## [22] httr_1.4.0        stringr_1.4.0     knitr_1.22       
## [25] hms_0.4.2         webshot_0.5.1     glue_1.3.1       
## [28] R6_2.4.0          dtw_1.20-1        jpeg_0.1-8       
## [31] pbapply_1.4-0     rmarkdown_1.12    soundgen_1.4.0   
## [34] readr_1.3.1       magrittr_1.5      scales_1.0.0     
## [37] htmltools_0.3.6   MASS_7.3-51.1     rvest_0.3.3      
## [40] colorspace_1.4-1  Deriv_3.8.5       stringi_1.4.3    
## [43] proxy_0.4-23      munsell_0.5.0     signal_0.7-6     
## [46] RCurl_1.95-4.12   crayon_1.3.4      rjson_0.2.20