Automatic call detection analysis

Call activity in strawberry poison-dart frogs

Author
Published

February 19, 2023

Purpose

  • Train model to automate detection of strawberry poison-dart frog calls

  • Detect calls in passive acoustic monitoring recordings

 

Report overview

 

Load packages

Code
# knitr is require for creating html/pdf/word reports formatR is
# used for soft-wrapping code

# install/ load packages
sketchy::load_packages(packages = c("knitr", "formatR", "rprojroot",
    "ohun", "warbleR", "Rraven", "ggplot2", "dynaSpec", "viridis"))

1 Training model

1.1 Prepare data

  • Import annotations
Code
train_path <- "~/Dropbox/oophaga/"

ref <- imp_raven(path = train_path, name.from.file = TRUE, warbler.format = TRUE,
    all.data = FALSE, ext.case = "lower", pb = FALSE)

cs <- check_sels(ref, path = train_path, pb = FALSE)
all selections are OK 
Code
ref$dur <- ref$end - ref$start

ref <- ref[ref$dur > 0.01, ]


nrow(ref)
[1] 1545
Code
max(ref$top.freq)
[1] 6.4834
  • Resample sound files
Code
fix_wavs(samp.rate = 14, path = train_path)

1.2 Find templates

Code
train_path <- "~/Dropbox/oophaga/converted_sound_files/"

# get mean structure template
templates <- get_templates(reference = ref, path = train_path, n.sub.spaces = 5,
    pb = FALSE)
The first 2 principal components explained 0.52 of the variance

Code
templates_est <- selection_table(templates, path = train_path, confirm.extended = FALSE,
    extended = TRUE)
checking selections (step 1 of 2):
saving wave objects into extended selection table (step 2 of 2):
Code
saveRDS(templates_est, "~/Dropbox/oophaga/templates_est.RDS")
Code
corrs <- template_correlator(templates = templates[1:5, ], path = train_path,
    wl = 100, ovlp = 70, cores = 10)

opt_oo <- optimize_template_detector(template.correlations = corrs,
    reference = ref, threshold = seq(0.1, 0.95, 0.05), cores = 15,
    by.sound.file = FALSE)

write.csv(opt_oo, "~/Dropbox/oophaga/optimization_results.csv", row.names = FALSE)
Code
opt_oo <- read.csv("~/Dropbox/oophaga/optimization_results.csv")

sub_oo <- opt_oo[order(opt_oo$f1.score, decreasing = TRUE), ]

kable(sub_oo[1:3, c(1:2, 4:6, 10:11)], digits = 2)
threshold templates true.positives false.positives false.negatives recall precision
37 0.45 ZOOM0002_Tr1-3.wav-92 1957 877 593 0.77 0.69
45 0.50 ZOOM0002_Tr1-2.wav-256 1817 1703 515 0.78 0.52
48 0.55 ZOOM0002_Tr1-5.wav-238 1092 667 702 0.61 0.62

2 Run model on the entire data set

  • Split files into 1 min segments (to improve computation effciency)
Code
split_sound_files("~/Dropbox/oophaga/test/", sgmt.dur = 300)


fix_wavs(samp.rate = 14, path = "~/Dropbox/oophaga/test/1min_clips/")

templates_est <- readRDS("~/Dropbox/oophaga/templates_est.RDS")

corrs <- template_correlator(templates = templates_est[2, ], path = "~/Dropbox/oophaga/test/1min_clips/converted_sound_files/",
    wl = 100, ovlp = 70, cores = 1)

full_detec <- template_detector(template.correlations = corrs, threshold = 0.45,
    cores = 1)

write.csv(full_detec, "~/Dropbox/oophaga/full_detection.csv", row.names = FALSE)

2.1 Vocal activity through time in open and closed habitat

Code
full_detec <- read.csv("~/Dropbox/oophaga/full_detection.csv")

full_detec$site <- ifelse(grepl("arriera_zompopa", full_detec$sound.files),
    "open", "closed")

full_detec$time.block <- as.numeric(gsub(".wav", "", sapply(strsplit(full_detec$sound.files,
    "-"), "[", 2)))

full_detec$time <- ((9 * 60) + (full_detec$time.block * 5))/60

full_detec <- full_detec[!is.na(full_detec$start), ]

2.2 Counts per site

Code
aggregate(sound.files ~ site, full_detec, length)
site sound.files
closed 13650
open 7647
Code
call_count <- aggregate(sound.files ~ time + site, full_detec, length)

ggplot(call_count, aes(x = time, y = sound.files, fill = site, color = site)) +
    geom_point(size = 4, pch = 21) + geom_smooth(method = "lm") +
    scale_fill_viridis_d(alpha = 0.5, begin = 0.2, end = 0.8) + scale_color_viridis_d(alpha = 0.3,
    begin = 0.2, end = 0.8) + theme_classic(base_size = 20) + labs(x = "Time (h)",
    y = "Call count", color = "Habitat", fill = "Habitat") + theme(legend.position = c(0.9,
    0.9))

Takeaways

  • Fair performance of automatic detection model
  • Prediction on test data shows expected pattern of decrease in activity through time during morning hours

  # Example images

3 Spectro + oscillo

Code
wv <- read_sound_file("/home/m/Dropbox/oophaga/example_inaturalist/clip.wav")

anns <- imp_raven(path = "/home/m/Dropbox/oophaga/example_inaturalist/",
    warbler.format = TRUE, all.data = FALSE)

spectro(wv, scale = FALSE, wl = 76, collevels = seq(-100, 0, 5), palette = viridis::viridis,
    ovlp = 9, grid = FALSE, flim = c(1, 6.5), zp = 1000, osc = TRUE,
    heights = c(2, 1))

3.1 Perfect detection

Code
diagnose_detection(reference = anns, detection = anns)[, c(2:4, 8:10)]
true.positives false.positives false.negatives recall precision f1.score
10 0 0 1 1 1
Code
label_spectro(wave = wv, reference = anns, detection = anns, wl = 76,
    ovlp = 99, flim = c(1, 6.5))

3.2 Precision 1, recall 0.7

Code
diagnose_detection(reference = anns, detection = anns[1:7, ])[, c(2:4,
    8:10)]
true.positives false.positives false.negatives recall precision f1.score
7 0 3 0.7 1 0.823529
Code
label_spectro(wave = wv, reference = anns, detection = anns[1:7, ],
    wl = 76, ovlp = 99, flim = c(1, 6))

3.3 Precision 0.7, recall 1

Code
diagnose_detection(reference = anns[1:7, ], detection = anns)[, c(2:4,
    8:10)]
true.positives false.positives false.negatives recall precision f1.score
7 3 0 1 0.7 0.823529
Code
label_spectro(wave = wv, reference = anns[1:7, ], detection = anns,
    wl = 76, ovlp = 99, flim = c(1, 6))


 

Session information

R version 4.1.0 (2021-05-18)
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/atlas/libblas.so.3.10.3
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3

locale:
 [1] LC_CTYPE=pt_BR.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=pt_BR.UTF-8    
 [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=pt_BR.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] viridis_0.6.2      viridisLite_0.4.1  dynaSpec_1.0.1     ggplot2_3.4.0     
 [5] Rraven_1.0.13      ohun_0.1.0         warbleR_1.1.28     NatureSounds_1.0.4
 [9] seewave_2.2.0      tuneR_1.4.1        rprojroot_2.0.3    formatR_1.11      
[13] knitr_1.42        

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.9          lattice_0.20-44     fftw_1.0-7         
 [4] assertthat_0.2.1    digest_0.6.31       packrat_0.9.0      
 [7] utf8_1.2.2          R6_2.5.1            Sim.DiffProc_4.8   
[10] signal_0.7-7        evaluate_0.20       pillar_1.8.1       
[13] rlang_1.0.6         rstudioapi_0.14     Matrix_1.5-1       
[16] rmarkdown_2.20      labeling_0.4.2      splines_4.1.0      
[19] sketchy_1.0.2       xaringanExtra_0.7.0 htmlwidgets_1.5.4  
[22] igraph_1.3.5        RCurl_1.98-1.9      munsell_0.5.0      
[25] proxy_0.4-27        compiler_4.1.0      Deriv_4.1.3        
[28] xfun_0.36           pkgconfig_2.0.3     mgcv_1.8-36        
[31] htmltools_0.5.4     tidyselect_1.2.0    tibble_3.1.8       
[34] gridExtra_2.3       dtw_1.23-1          fansi_1.0.3        
[37] crayon_1.5.2        dplyr_1.0.10        withr_2.5.0        
[40] shinyBS_0.61        MASS_7.3-54         bitops_1.0-7       
[43] grid_4.1.0          nlme_3.1-152        jsonlite_1.8.4     
[46] gtable_0.3.1        lifecycle_1.0.3     DBI_1.1.1          
[49] magrittr_2.0.3      scales_1.2.1        cli_3.6.0          
[52] stringi_1.7.12      pbapply_1.6-0       farver_2.1.1       
[55] remotes_2.4.2       sp_1.5-1            vctrs_0.5.2        
[58] generics_0.1.3      rjson_0.2.21        tools_4.1.0        
[61] glue_1.6.2          parallel_4.1.0      fastmap_1.1.0      
[64] yaml_2.3.7          colorspace_2.0-3    soundgen_2.1.0