birdnet-analyzer 2.0.1__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/PKG-INFO +18 -9
  2. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/SOURCES.txt +3 -2
  3. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/requires.txt +15 -5
  4. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/PKG-INFO +18 -9
  5. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/README.md +4 -1
  6. birdnet_analyzer-2.1.0/birdnet_analyzer/analyze/__init__.py +19 -0
  7. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/analyze/cli.py +5 -0
  8. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/analyze/core.py +6 -1
  9. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/analyze/utils.py +42 -40
  10. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/audio.py +2 -2
  11. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/cli.py +41 -18
  12. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/config.py +4 -3
  13. birdnet_analyzer-2.1.0/birdnet_analyzer/eBird_taxonomy_codes_2024E.json +13046 -0
  14. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/embeddings/core.py +2 -1
  15. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/embeddings/utils.py +42 -1
  16. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/__init__.py +6 -13
  17. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/assessment/performance_assessor.py +12 -57
  18. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/assessment/plotting.py +61 -62
  19. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/preprocessing/data_processor.py +1 -1
  20. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/analysis.py +5 -1
  21. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/gui.css +8 -0
  22. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/embeddings.py +37 -18
  23. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/evaluation.py +14 -8
  24. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/multi_file.py +25 -5
  25. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/review.py +16 -63
  26. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/settings.py +25 -4
  27. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/single_file.py +14 -17
  28. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/train.py +7 -16
  29. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/utils.py +42 -55
  30. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ca.txt +1 -1
  31. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pl.txt +1 -1
  32. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sr.txt +108 -108
  33. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_zh.txt +1 -1
  34. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/de.json +7 -0
  35. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/en.json +7 -0
  36. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/fi.json +7 -0
  37. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/fr.json +7 -0
  38. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/id.json +7 -0
  39. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/pt-br.json +7 -0
  40. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/ru.json +36 -29
  41. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/se.json +7 -0
  42. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/tlh.json +7 -0
  43. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/lang/zh_TW.json +7 -0
  44. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/model.py +21 -21
  45. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/search/core.py +1 -1
  46. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/utils.py +3 -4
  47. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/pyproject.toml +11 -7
  48. birdnet_analyzer-2.1.0/tests/test_utils.py +28 -0
  49. birdnet_analyzer-2.0.1/birdnet_analyzer/analyze/__init__.py +0 -5
  50. birdnet_analyzer-2.0.1/birdnet_analyzer/eBird_taxonomy_codes_2021E.json +0 -25280
  51. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/dependency_links.txt +0 -0
  52. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/entry_points.txt +0 -0
  53. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/BirdNET_Analyzer.egg-info/top_level.txt +0 -0
  54. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/LICENSE +0 -0
  55. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/__init__.py +0 -0
  56. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/analyze/__main__.py +0 -0
  57. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/embeddings/__init__.py +0 -0
  58. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/embeddings/__main__.py +0 -0
  59. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/embeddings/cli.py +0 -0
  60. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/__main__.py +0 -0
  61. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/assessment/__init__.py +0 -0
  62. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/assessment/metrics.py +0 -0
  63. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/preprocessing/__init__.py +0 -0
  64. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/evaluation/preprocessing/utils.py +0 -0
  65. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/__init__.py +0 -0
  66. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/__main__.py +0 -0
  67. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/arrow_down.svg +0 -0
  68. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/arrow_left.svg +0 -0
  69. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/arrow_right.svg +0 -0
  70. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/arrow_up.svg +0 -0
  71. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/gui.js +0 -0
  72. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/img/birdnet-icon.ico +0 -0
  73. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/img/birdnet_logo.png +0 -0
  74. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/img/birdnet_logo_no_transparent.png +0 -0
  75. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/assets/img/clo-logo-bird.svg +0 -0
  76. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/localization.py +0 -0
  77. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/segments.py +0 -0
  78. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/gui/species.py +0 -0
  79. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_af.txt +0 -0
  80. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ar.txt +0 -0
  81. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_bg.txt +0 -0
  82. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_cs.txt +0 -0
  83. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_da.txt +0 -0
  84. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_de.txt +0 -0
  85. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_el.txt +0 -0
  86. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_en_uk.txt +0 -0
  87. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_es.txt +0 -0
  88. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_fi.txt +0 -0
  89. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_fr.txt +0 -0
  90. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_he.txt +0 -0
  91. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_hr.txt +0 -0
  92. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_hu.txt +0 -0
  93. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_in.txt +0 -0
  94. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_is.txt +0 -0
  95. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_it.txt +0 -0
  96. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ja.txt +0 -0
  97. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ko.txt +0 -0
  98. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_lt.txt +0 -0
  99. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ml.txt +0 -0
  100. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_nl.txt +0 -0
  101. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_no.txt +0 -0
  102. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pt_BR.txt +0 -0
  103. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pt_PT.txt +0 -0
  104. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ro.txt +0 -0
  105. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ru.txt +0 -0
  106. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sk.txt +0 -0
  107. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sl.txt +0 -0
  108. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sv.txt +0 -0
  109. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_th.txt +0 -0
  110. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_tr.txt +0 -0
  111. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_uk.txt +0 -0
  112. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/playground.py +0 -0
  113. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/search/__init__.py +0 -0
  114. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/search/__main__.py +0 -0
  115. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/search/cli.py +0 -0
  116. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/search/utils.py +0 -0
  117. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/segments/__init__.py +0 -0
  118. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/segments/__main__.py +0 -0
  119. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/segments/cli.py +0 -0
  120. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/segments/core.py +0 -0
  121. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/segments/utils.py +0 -0
  122. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/species/__init__.py +0 -0
  123. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/species/__main__.py +0 -0
  124. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/species/cli.py +0 -0
  125. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/species/core.py +0 -0
  126. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/species/utils.py +0 -0
  127. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/train/__init__.py +0 -0
  128. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/train/__main__.py +0 -0
  129. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/train/cli.py +0 -0
  130. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/train/core.py +0 -0
  131. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/train/utils.py +0 -0
  132. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/birdnet_analyzer/translate.py +0 -0
  133. {birdnet_analyzer-2.0.1 → birdnet_analyzer-2.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: birdnet_analyzer
3
- Version: 2.0.1
3
+ Version: 2.1.0
4
4
  Summary: BirdNET analyzer for scientific audio data processing and bird classification.
5
5
  Author: Stefan Kahl
6
6
  Maintainer: Josef Haupt, Max Mauermann
@@ -25,6 +25,8 @@ Requires-Dist: resampy
25
25
  Requires-Dist: tensorflow==2.15.1
26
26
  Requires-Dist: scikit-learn==1.6.1
27
27
  Requires-Dist: tqdm
28
+ Requires-Dist: pandas
29
+ Requires-Dist: matplotlib
28
30
  Provides-Extra: train
29
31
  Requires-Dist: keras-tuner; extra == "train"
30
32
  Provides-Extra: server
@@ -32,21 +34,25 @@ Requires-Dist: bottle; extra == "server"
32
34
  Requires-Dist: requests; extra == "server"
33
35
  Provides-Extra: gui
34
36
  Requires-Dist: birdnet-analyzer[embeddings,train]; extra == "gui"
35
- Requires-Dist: gradio==5.25.2; extra == "gui"
37
+ Requires-Dist: gradio==5.32.1; extra == "gui"
36
38
  Requires-Dist: pywebview; extra == "gui"
37
- Requires-Dist: matplotlib; extra == "gui"
38
39
  Requires-Dist: plotly[express]; extra == "gui"
39
- Requires-Dist: seaborn; extra == "gui"
40
40
  Requires-Dist: pywin32; platform_system == "Windows" and extra == "gui"
41
+ Requires-Dist: qtpy; platform_system == "Linux" and extra == "gui"
42
+ Requires-Dist: PyGObject; platform_system == "Linux" and extra == "gui"
41
43
  Provides-Extra: embeddings
42
44
  Requires-Dist: perch-hoplite; extra == "embeddings"
43
45
  Provides-Extra: all
44
46
  Requires-Dist: birdnet-analyzer[gui,server]; extra == "all"
47
+ Provides-Extra: docs
48
+ Requires-Dist: sphinx; extra == "docs"
49
+ Requires-Dist: sphinx-rtd-theme; extra == "docs"
50
+ Requires-Dist: sphinx-argparse; extra == "docs"
51
+ Provides-Extra: tests
52
+ Requires-Dist: pytest; extra == "tests"
45
53
  Provides-Extra: dev
46
- Requires-Dist: sphinx; extra == "dev"
47
- Requires-Dist: sphinx-rtd-theme; extra == "dev"
48
- Requires-Dist: sphinx-argparse; extra == "dev"
49
- Requires-Dist: pytest; extra == "dev"
54
+ Requires-Dist: birdnet_analyzer[tests]; extra == "dev"
55
+ Requires-Dist: birdnet_analyzer[docs]; extra == "dev"
50
56
  Requires-Dist: ruff; extra == "dev"
51
57
  Dynamic: license-file
52
58
 
@@ -72,9 +78,11 @@ Dynamic: license-file
72
78
  [![GitHub release](https://img.shields.io/github/v/release/birdnet-team/BirdNET-Analyzer)](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest)
73
79
  [![PyPI - Version](https://img.shields.io/pypi/v/birdnet_analyzer?logo=pypi)](https://pypi.org/project/birdnet-analyzer/)
74
80
 
81
+ [![Sponsor](https://img.shields.io/badge/Support%20our%20work-8A2BE2?logo=data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE2IiBkYXRhLXZpZXctY29tcG9uZW50PSJ0cnVlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgIDxwYXRoIGQ9Im04IDE0LjI1LjM0NS42NjZhLjc1Ljc1IDAgMCAxLS42OSAwbC0uMDA4LS4wMDQtLjAxOC0uMDFhNy4xNTIgNy4xNTIgMCAwIDEtLjMxLS4xNyAyMi4wNTUgMjIuMDU1IDAgMCAxLTMuNDM0LTIuNDE0QzIuMDQ1IDEwLjczMSAwIDguMzUgMCA1LjUgMCAyLjgzNiAyLjA4NiAxIDQuMjUgMSA1Ljc5NyAxIDcuMTUzIDEuODAyIDggMy4wMiA4Ljg0NyAxLjgwMiAxMC4yMDMgMSAxMS43NSAxIDEzLjkxNCAxIDE2IDIuODM2IDE2IDUuNWMwIDIuODUtMi4wNDUgNS4yMzEtMy44ODUgNi44MThhMjIuMDY2IDIyLjA2NiAwIDAgMS0zLjc0NCAyLjU4NGwtLjAxOC4wMS0uMDA2LjAwM2gtLjAwMlpNNC4yNSAyLjVjLTEuMzM2IDAtMi43NSAxLjE2NC0yLjc1IDMgMCAyLjE1IDEuNTggNC4xNDQgMy4zNjUgNS42ODJBMjAuNTggMjAuNTggMCAwIDAgOCAxMy4zOTNhMjAuNTggMjAuNTggMCAwIDAgMy4xMzUtMi4yMTFDMTIuOTIgOS42NDQgMTQuNSA3LjY1IDE0LjUgNS41YzAtMS44MzYtMS40MTQtMy0yLjc1LTMtMS4zNzMgMC0yLjYwOS45ODYtMy4wMjkgMi40NTZhLjc0OS43NDkgMCAwIDEtMS40NDIgMEM2Ljg1OSAzLjQ4NiA1LjYyMyAyLjUgNC4yNSAyLjVaIj48L3BhdGg+DQo8L3N2Zz4=)](https://give.birds.cornell.edu/page/132162/donate/1)
82
+
75
83
  </div>
76
84
 
77
- This repo contains BirdNET models and scripts for processing large amounts of audio data or single audio files.
85
+ This repo contains BirdNET scripts for processing large amounts of audio data or single audio files.
78
86
  This is the most advanced version of BirdNET for acoustic analyses and we will keep this repository up-to-date with new models and improved interfaces to enable scientists with no CS background to run the analysis.
79
87
 
80
88
  Feel free to use BirdNET for your acoustic analyses and research.
@@ -99,6 +107,7 @@ You can access documentation for this project [here](https://birdnet-team.github
99
107
  ## Download
100
108
 
101
109
  You can download installers for Windows and macOS from the [releases page](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest).
110
+ Models can be found on [Zenodo](https://zenodo.org/records/15050749).
102
111
 
103
112
  ## About
104
113
 
@@ -11,7 +11,7 @@ birdnet_analyzer/__init__.py
11
11
  birdnet_analyzer/audio.py
12
12
  birdnet_analyzer/cli.py
13
13
  birdnet_analyzer/config.py
14
- birdnet_analyzer/eBird_taxonomy_codes_2021E.json
14
+ birdnet_analyzer/eBird_taxonomy_codes_2024E.json
15
15
  birdnet_analyzer/model.py
16
16
  birdnet_analyzer/playground.py
17
17
  birdnet_analyzer/translate.py
@@ -131,4 +131,5 @@ birdnet_analyzer/train/__init__.py
131
131
  birdnet_analyzer/train/__main__.py
132
132
  birdnet_analyzer/train/cli.py
133
133
  birdnet_analyzer/train/core.py
134
- birdnet_analyzer/train/utils.py
134
+ birdnet_analyzer/train/utils.py
135
+ tests/test_utils.py
@@ -3,27 +3,34 @@ resampy
3
3
  tensorflow==2.15.1
4
4
  scikit-learn==1.6.1
5
5
  tqdm
6
+ pandas
7
+ matplotlib
6
8
 
7
9
  [all]
8
10
  birdnet-analyzer[gui,server]
9
11
 
10
12
  [dev]
13
+ birdnet_analyzer[tests]
14
+ birdnet_analyzer[docs]
15
+ ruff
16
+
17
+ [docs]
11
18
  sphinx
12
19
  sphinx-rtd-theme
13
20
  sphinx-argparse
14
- pytest
15
- ruff
16
21
 
17
22
  [embeddings]
18
23
  perch-hoplite
19
24
 
20
25
  [gui]
21
26
  birdnet-analyzer[embeddings,train]
22
- gradio==5.25.2
27
+ gradio==5.32.1
23
28
  pywebview
24
- matplotlib
25
29
  plotly[express]
26
- seaborn
30
+
31
+ [gui:platform_system == "Linux"]
32
+ qtpy
33
+ PyGObject
27
34
 
28
35
  [gui:platform_system == "Windows"]
29
36
  pywin32
@@ -32,5 +39,8 @@ pywin32
32
39
  bottle
33
40
  requests
34
41
 
42
+ [tests]
43
+ pytest
44
+
35
45
  [train]
36
46
  keras-tuner
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: birdnet_analyzer
3
- Version: 2.0.1
3
+ Version: 2.1.0
4
4
  Summary: BirdNET analyzer for scientific audio data processing and bird classification.
5
5
  Author: Stefan Kahl
6
6
  Maintainer: Josef Haupt, Max Mauermann
@@ -25,6 +25,8 @@ Requires-Dist: resampy
25
25
  Requires-Dist: tensorflow==2.15.1
26
26
  Requires-Dist: scikit-learn==1.6.1
27
27
  Requires-Dist: tqdm
28
+ Requires-Dist: pandas
29
+ Requires-Dist: matplotlib
28
30
  Provides-Extra: train
29
31
  Requires-Dist: keras-tuner; extra == "train"
30
32
  Provides-Extra: server
@@ -32,21 +34,25 @@ Requires-Dist: bottle; extra == "server"
32
34
  Requires-Dist: requests; extra == "server"
33
35
  Provides-Extra: gui
34
36
  Requires-Dist: birdnet-analyzer[embeddings,train]; extra == "gui"
35
- Requires-Dist: gradio==5.25.2; extra == "gui"
37
+ Requires-Dist: gradio==5.32.1; extra == "gui"
36
38
  Requires-Dist: pywebview; extra == "gui"
37
- Requires-Dist: matplotlib; extra == "gui"
38
39
  Requires-Dist: plotly[express]; extra == "gui"
39
- Requires-Dist: seaborn; extra == "gui"
40
40
  Requires-Dist: pywin32; platform_system == "Windows" and extra == "gui"
41
+ Requires-Dist: qtpy; platform_system == "Linux" and extra == "gui"
42
+ Requires-Dist: PyGObject; platform_system == "Linux" and extra == "gui"
41
43
  Provides-Extra: embeddings
42
44
  Requires-Dist: perch-hoplite; extra == "embeddings"
43
45
  Provides-Extra: all
44
46
  Requires-Dist: birdnet-analyzer[gui,server]; extra == "all"
47
+ Provides-Extra: docs
48
+ Requires-Dist: sphinx; extra == "docs"
49
+ Requires-Dist: sphinx-rtd-theme; extra == "docs"
50
+ Requires-Dist: sphinx-argparse; extra == "docs"
51
+ Provides-Extra: tests
52
+ Requires-Dist: pytest; extra == "tests"
45
53
  Provides-Extra: dev
46
- Requires-Dist: sphinx; extra == "dev"
47
- Requires-Dist: sphinx-rtd-theme; extra == "dev"
48
- Requires-Dist: sphinx-argparse; extra == "dev"
49
- Requires-Dist: pytest; extra == "dev"
54
+ Requires-Dist: birdnet_analyzer[tests]; extra == "dev"
55
+ Requires-Dist: birdnet_analyzer[docs]; extra == "dev"
50
56
  Requires-Dist: ruff; extra == "dev"
51
57
  Dynamic: license-file
52
58
 
@@ -72,9 +78,11 @@ Dynamic: license-file
72
78
  [![GitHub release](https://img.shields.io/github/v/release/birdnet-team/BirdNET-Analyzer)](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest)
73
79
  [![PyPI - Version](https://img.shields.io/pypi/v/birdnet_analyzer?logo=pypi)](https://pypi.org/project/birdnet-analyzer/)
74
80
 
81
+ [![Sponsor](https://img.shields.io/badge/Support%20our%20work-8A2BE2?logo=data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE2IiBkYXRhLXZpZXctY29tcG9uZW50PSJ0cnVlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgIDxwYXRoIGQ9Im04IDE0LjI1LjM0NS42NjZhLjc1Ljc1IDAgMCAxLS42OSAwbC0uMDA4LS4wMDQtLjAxOC0uMDFhNy4xNTIgNy4xNTIgMCAwIDEtLjMxLS4xNyAyMi4wNTUgMjIuMDU1IDAgMCAxLTMuNDM0LTIuNDE0QzIuMDQ1IDEwLjczMSAwIDguMzUgMCA1LjUgMCAyLjgzNiAyLjA4NiAxIDQuMjUgMSA1Ljc5NyAxIDcuMTUzIDEuODAyIDggMy4wMiA4Ljg0NyAxLjgwMiAxMC4yMDMgMSAxMS43NSAxIDEzLjkxNCAxIDE2IDIuODM2IDE2IDUuNWMwIDIuODUtMi4wNDUgNS4yMzEtMy44ODUgNi44MThhMjIuMDY2IDIyLjA2NiAwIDAgMS0zLjc0NCAyLjU4NGwtLjAxOC4wMS0uMDA2LjAwM2gtLjAwMlpNNC4yNSAyLjVjLTEuMzM2IDAtMi43NSAxLjE2NC0yLjc1IDMgMCAyLjE1IDEuNTggNC4xNDQgMy4zNjUgNS42ODJBMjAuNTggMjAuNTggMCAwIDAgOCAxMy4zOTNhMjAuNTggMjAuNTggMCAwIDAgMy4xMzUtMi4yMTFDMTIuOTIgOS42NDQgMTQuNSA3LjY1IDE0LjUgNS41YzAtMS44MzYtMS40MTQtMy0yLjc1LTMtMS4zNzMgMC0yLjYwOS45ODYtMy4wMjkgMi40NTZhLjc0OS43NDkgMCAwIDEtMS40NDIgMEM2Ljg1OSAzLjQ4NiA1LjYyMyAyLjUgNC4yNSAyLjVaIj48L3BhdGg+DQo8L3N2Zz4=)](https://give.birds.cornell.edu/page/132162/donate/1)
82
+
75
83
  </div>
76
84
 
77
- This repo contains BirdNET models and scripts for processing large amounts of audio data or single audio files.
85
+ This repo contains BirdNET scripts for processing large amounts of audio data or single audio files.
78
86
  This is the most advanced version of BirdNET for acoustic analyses and we will keep this repository up-to-date with new models and improved interfaces to enable scientists with no CS background to run the analysis.
79
87
 
80
88
  Feel free to use BirdNET for your acoustic analyses and research.
@@ -99,6 +107,7 @@ You can access documentation for this project [here](https://birdnet-team.github
99
107
  ## Download
100
108
 
101
109
  You can download installers for Windows and macOS from the [releases page](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest).
110
+ Models can be found on [Zenodo](https://zenodo.org/records/15050749).
102
111
 
103
112
  ## About
104
113
 
@@ -20,9 +20,11 @@
20
20
  [![GitHub release](https://img.shields.io/github/v/release/birdnet-team/BirdNET-Analyzer)](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest)
21
21
  [![PyPI - Version](https://img.shields.io/pypi/v/birdnet_analyzer?logo=pypi)](https://pypi.org/project/birdnet-analyzer/)
22
22
 
23
+ [![Sponsor](https://img.shields.io/badge/Support%20our%20work-8A2BE2?logo=data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE2IiBkYXRhLXZpZXctY29tcG9uZW50PSJ0cnVlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgIDxwYXRoIGQ9Im04IDE0LjI1LjM0NS42NjZhLjc1Ljc1IDAgMCAxLS42OSAwbC0uMDA4LS4wMDQtLjAxOC0uMDFhNy4xNTIgNy4xNTIgMCAwIDEtLjMxLS4xNyAyMi4wNTUgMjIuMDU1IDAgMCAxLTMuNDM0LTIuNDE0QzIuMDQ1IDEwLjczMSAwIDguMzUgMCA1LjUgMCAyLjgzNiAyLjA4NiAxIDQuMjUgMSA1Ljc5NyAxIDcuMTUzIDEuODAyIDggMy4wMiA4Ljg0NyAxLjgwMiAxMC4yMDMgMSAxMS43NSAxIDEzLjkxNCAxIDE2IDIuODM2IDE2IDUuNWMwIDIuODUtMi4wNDUgNS4yMzEtMy44ODUgNi44MThhMjIuMDY2IDIyLjA2NiAwIDAgMS0zLjc0NCAyLjU4NGwtLjAxOC4wMS0uMDA2LjAwM2gtLjAwMlpNNC4yNSAyLjVjLTEuMzM2IDAtMi43NSAxLjE2NC0yLjc1IDMgMCAyLjE1IDEuNTggNC4xNDQgMy4zNjUgNS42ODJBMjAuNTggMjAuNTggMCAwIDAgOCAxMy4zOTNhMjAuNTggMjAuNTggMCAwIDAgMy4xMzUtMi4yMTFDMTIuOTIgOS42NDQgMTQuNSA3LjY1IDE0LjUgNS41YzAtMS44MzYtMS40MTQtMy0yLjc1LTMtMS4zNzMgMC0yLjYwOS45ODYtMy4wMjkgMi40NTZhLjc0OS43NDkgMCAwIDEtMS40NDIgMEM2Ljg1OSAzLjQ4NiA1LjYyMyAyLjUgNC4yNSAyLjVaIj48L3BhdGg+DQo8L3N2Zz4=)](https://give.birds.cornell.edu/page/132162/donate/1)
24
+
23
25
  </div>
24
26
 
25
- This repo contains BirdNET models and scripts for processing large amounts of audio data or single audio files.
27
+ This repo contains BirdNET scripts for processing large amounts of audio data or single audio files.
26
28
  This is the most advanced version of BirdNET for acoustic analyses and we will keep this repository up-to-date with new models and improved interfaces to enable scientists with no CS background to run the analysis.
27
29
 
28
30
  Feel free to use BirdNET for your acoustic analyses and research.
@@ -47,6 +49,7 @@ You can access documentation for this project [here](https://birdnet-team.github
47
49
  ## Download
48
50
 
49
51
  You can download installers for Windows and macOS from the [releases page](https://github.com/birdnet-team/BirdNET-Analyzer/releases/latest).
52
+ Models can be found on [Zenodo](https://zenodo.org/records/15050749).
50
53
 
51
54
  ## About
52
55
 
@@ -0,0 +1,19 @@
1
+ import os
2
+
3
+ import birdnet_analyzer.config as cfg
4
+ from birdnet_analyzer.analyze.core import analyze
5
+
6
+ POSSIBLE_ADDITIONAL_COLUMNS_MAP = {
7
+ "lat": lambda: cfg.LATITUDE,
8
+ "lon": lambda: cfg.LONGITUDE,
9
+ "week": lambda: cfg.WEEK,
10
+ "overlap": lambda: cfg.SIG_OVERLAP,
11
+ "sensitivity": lambda: cfg.SIGMOID_SENSITIVITY,
12
+ "min_conf": lambda: cfg.MIN_CONFIDENCE,
13
+ "species_list": lambda: cfg.SPECIES_LIST_FILE or "",
14
+ "model": lambda: os.path.basename(cfg.MODEL_PATH),
15
+ }
16
+
17
+ __all__ = [
18
+ "analyze",
19
+ ]
@@ -22,4 +22,9 @@ def main():
22
22
  except Exception:
23
23
  pass
24
24
 
25
+ if "additional_columns" in args and args.additional_columns and "csv" not in args.rtype:
26
+ import warnings
27
+
28
+ warnings.warn("The --additional_columns argument is only valid for CSV output. It will be ignored.", stacklevel=1)
29
+
25
30
  analyze(**vars(args))
@@ -26,6 +26,7 @@ def analyze(
26
26
  merge_consecutive: int = 1,
27
27
  threads: int = 8,
28
28
  locale: str = "en",
29
+ additional_columns: list[str] | None = None,
29
30
  ):
30
31
  """
31
32
  Analyzes audio files for bird species detection using the BirdNET-Analyzer.
@@ -53,6 +54,7 @@ def analyze(
53
54
  merge_consecutive (int, optional): Merge consecutive detections within this time window in seconds. Defaults to 1.
54
55
  threads (int, optional): Number of CPU threads to use for analysis. Defaults to 8.
55
56
  locale (str, optional): Locale for species names and output. Defaults to "en".
57
+ additional_columns (list[str] | None, optional): Additional columns to include in the output. Defaults to None.
56
58
  Returns:
57
59
  None
58
60
  Raises:
@@ -95,6 +97,7 @@ def analyze(
95
97
  skip_existing_results=skip_existing_results,
96
98
  threads=threads,
97
99
  labels_file=cfg.LABELS_FILE,
100
+ additional_columns=additional_columns,
98
101
  )
99
102
 
100
103
  print(f"Found {len(cfg.FILE_LIST)} files to analyze")
@@ -150,6 +153,7 @@ def _set_params(
150
153
  merge_consecutive,
151
154
  threads,
152
155
  labels_file=None,
156
+ additional_columns=None,
153
157
  ):
154
158
  import birdnet_analyzer.config as cfg
155
159
  from birdnet_analyzer.analyze.utils import load_codes
@@ -162,7 +166,7 @@ def _set_params(
162
166
  cfg.LOCATION_FILTER_THRESHOLD = sf_thresh
163
167
  cfg.TOP_N = top_n
164
168
  cfg.MERGE_CONSECUTIVE = merge_consecutive
165
- cfg.INPUT_PATH = audio_input
169
+ cfg.INPUT_PATH = audio_input.replace("/", os.sep)
166
170
  cfg.MIN_CONFIDENCE = min_conf
167
171
  cfg.SIGMOID_SENSITIVITY = sensitivity
168
172
  cfg.SIG_OVERLAP = overlap
@@ -172,6 +176,7 @@ def _set_params(
172
176
  cfg.RESULT_TYPES = rtype
173
177
  cfg.COMBINE_RESULTS = combine_results
174
178
  cfg.BATCH_SIZE = bs
179
+ cfg.ADDITIONAL_COLUMNS = additional_columns
175
180
 
176
181
  if not output:
177
182
  if os.path.isfile(cfg.INPUT_PATH):
@@ -4,17 +4,17 @@ import datetime
4
4
  import json
5
5
  import operator
6
6
  import os
7
+ from collections.abc import Sequence
7
8
 
8
9
  import numpy as np
9
10
 
10
11
  import birdnet_analyzer.config as cfg
11
12
  from birdnet_analyzer import audio, model, utils
12
13
 
13
- RAVEN_TABLE_HEADER = "Selection\tView\tChannel\tBegin Time (s)\tEnd Time (s)\tLow Freq (Hz)\tHigh Freq (Hz)\tCommon Name\tSpecies Code\tConfidence\tBegin Path\tFile Offset (s)\n" # noqa: E501
14
- RTABLE_HEADER = "filepath,start,end,scientific_name,common_name,confidence,lat,lon,week,overlap,sensitivity,min_conf,species_list,model\n"
15
- KALEIDOSCOPE_HEADER = (
16
- "INDIR,FOLDER,IN FILE,OFFSET,DURATION,scientific_name,common_name,confidence,lat,lon,week,overlap,sensitivity\n"
14
+ RAVEN_TABLE_HEADER = (
15
+ "Selection\tView\tChannel\tBegin Time (s)\tEnd Time (s)\tLow Freq (Hz)\tHigh Freq (Hz)\tCommon Name\tSpecies Code\tConfidence\tBegin Path\tFile Offset (s)\n"
17
16
  )
17
+ KALEIDOSCOPE_HEADER = "INDIR,FOLDER,IN FILE,OFFSET,DURATION,scientific_name,common_name,confidence,lat,lon,week,overlap,sensitivity\n"
18
18
  CSV_HEADER = "Start (s),End (s),Scientific name,Common name,Confidence,File\n"
19
19
  SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
20
20
 
@@ -80,7 +80,7 @@ def generate_raven_table(timestamps: list[str], result: dict[str, list], afile_p
80
80
 
81
81
  high_freq = min(high_freq, int(cfg.SIG_FMAX / cfg.AUDIO_SPEED))
82
82
 
83
- high_freq = min(high_freq, int(cfg.BANDPASS_FMAX / cfg.AUDIO_SPEED))
83
+ high_freq = int(min(high_freq, int(cfg.BANDPASS_FMAX / cfg.AUDIO_SPEED)))
84
84
  low_freq = max(cfg.SIG_FMIN, int(cfg.BANDPASS_FMIN / cfg.AUDIO_SPEED))
85
85
 
86
86
  # Extract valid predictions for every timestamp
@@ -92,7 +92,9 @@ def generate_raven_table(timestamps: list[str], result: dict[str, list], afile_p
92
92
  selection_id += 1
93
93
  label = cfg.TRANSLATED_LABELS[cfg.LABELS.index(c[0])]
94
94
  code = cfg.CODES[c[0]] if c[0] in cfg.CODES else c[0]
95
- rstring += f"{selection_id}\tSpectrogram 1\t1\t{start}\t{end}\t{low_freq}\t{high_freq}\t{label.split('_', 1)[-1]}\t{code}\t{c[1]:.4f}\t{afile_path}\t{start}\n" # noqa: E501
95
+ rstring += (
96
+ f"{selection_id}\tSpectrogram 1\t1\t{start}\t{end}\t{low_freq}\t{high_freq}\t{label.split('_', 1)[-1]}\t{code}\t{c[1]:.4f}\t{afile_path}\t{start}\n"
97
+ )
96
98
 
97
99
  # Write result string to file
98
100
  out_string += rstring
@@ -103,9 +105,7 @@ def generate_raven_table(timestamps: list[str], result: dict[str, list], afile_p
103
105
  # of file durations during the analysis.
104
106
  if len(out_string) == len(RAVEN_TABLE_HEADER) and cfg.OUTPUT_PATH is not None:
105
107
  selection_id += 1
106
- out_string += (
107
- f"{selection_id}\tSpectrogram 1\t1\t0\t3\t{low_freq}\t{high_freq}\tnocall\tnocall\t1.0\t{afile_path}\t0\n"
108
- )
108
+ out_string += f"{selection_id}\tSpectrogram 1\t1\t0\t3\t{low_freq}\t{high_freq}\tnocall\tnocall\t1.0\t{afile_path}\t0\n"
109
109
 
110
110
  utils.save_result_file(result_path, out_string)
111
111
 
@@ -202,7 +202,18 @@ def generate_csv(timestamps: list[str], result: dict[str, list], afile_path: str
202
202
  Returns:
203
203
  None
204
204
  """
205
+ from birdnet_analyzer.analyze import POSSIBLE_ADDITIONAL_COLUMNS_MAP
206
+
205
207
  out_string = CSV_HEADER
208
+ columns_map = {}
209
+
210
+ if cfg.ADDITIONAL_COLUMNS:
211
+ for col in cfg.ADDITIONAL_COLUMNS:
212
+ if col in POSSIBLE_ADDITIONAL_COLUMNS_MAP:
213
+ columns_map[col] = POSSIBLE_ADDITIONAL_COLUMNS_MAP[col]()
214
+
215
+ if columns_map:
216
+ out_string = out_string[:-1] + "," + ",".join(columns_map) + "\n"
206
217
 
207
218
  for timestamp in timestamps:
208
219
  rstring = ""
@@ -210,7 +221,12 @@ def generate_csv(timestamps: list[str], result: dict[str, list], afile_path: str
210
221
  for c in result[timestamp]:
211
222
  start, end = timestamp.split("-", 1)
212
223
  label = cfg.TRANSLATED_LABELS[cfg.LABELS.index(c[0])]
213
- rstring += f"{start},{end},{label.split('_', 1)[0]},{label.split('_', 1)[-1]},{c[1]:.4f},{afile_path}\n"
224
+ rstring += f"{start},{end},{label.split('_', 1)[0]},{label.split('_', 1)[-1]},{c[1]:.4f},{afile_path}"
225
+
226
+ if columns_map:
227
+ rstring += "," + ",".join(str(val) for val in columns_map.values())
228
+
229
+ rstring += "\n"
214
230
 
215
231
  # Write result string to file
216
232
  out_string += rstring
@@ -364,29 +380,23 @@ def combine_csv_files(saved_results: list[str]):
364
380
  Args:
365
381
  saved_results (list[str]): A list of file paths to the CSV files to be combined.
366
382
  """
367
- # Combine all files
368
- with open(os.path.join(cfg.OUTPUT_PATH, cfg.OUTPUT_CSV_FILENAME), "w", encoding="utf-8") as f:
369
- f.write(CSV_HEADER)
383
+ out_string = ""
370
384
 
371
- for rfile in saved_results:
385
+ for rfile in saved_results:
386
+ try:
372
387
  with open(rfile, encoding="utf-8") as rf:
373
- try:
374
- lines = rf.readlines()
388
+ lines = rf.readlines()
389
+ out_string += "".join(lines[1:] if out_string else lines)
375
390
 
376
- # make sure it's a selection table
377
- if "Start (s)" not in lines[0] or "Confidence" not in lines[0]:
378
- continue
379
-
380
- # skip header and add to file
381
- for line in lines[1:]:
382
- f.write(line)
391
+ except Exception as ex:
392
+ print(f"Error: Cannot combine results from {rfile}.\n", flush=True)
393
+ utils.write_error_log(ex)
383
394
 
384
- except Exception as ex:
385
- print(f"Error: Cannot combine results from {rfile}.\n", flush=True)
386
- utils.write_error_log(ex)
395
+ with open(os.path.join(cfg.OUTPUT_PATH, cfg.OUTPUT_CSV_FILENAME), "w", encoding="utf-8") as f:
396
+ f.write(out_string)
387
397
 
388
398
 
389
- def combine_results(saved_results: list[dict[str, str]]):
399
+ def combine_results(saved_results: Sequence[dict[str, str]| None]):
390
400
  """
391
401
  Combines various types of result files based on the configuration settings.
392
402
  This function checks the types of results specified in the configuration
@@ -403,9 +413,6 @@ def combine_results(saved_results: list[dict[str, str]]):
403
413
  if "table" in cfg.RESULT_TYPES:
404
414
  combine_raven_tables([f["table"] for f in saved_results if f])
405
415
 
406
- # if "r" in cfg.RESULT_TYPES:
407
- # combine_rtable_files([f["r"] for f in saved_results if f])
408
-
409
416
  if "kaleidoscope" in cfg.RESULT_TYPES:
410
417
  combine_kaleidoscope_files([f["kaleidoscope"] for f in saved_results if f])
411
418
 
@@ -509,9 +516,7 @@ def get_raw_audio_from_file(fpath: str, offset, duration):
509
516
  The signal split into a list of chunks.
510
517
  """
511
518
  # Open file
512
- sig, rate = audio.open_audio_file(
513
- fpath, cfg.SAMPLE_RATE, offset, duration, cfg.BANDPASS_FMIN, cfg.BANDPASS_FMAX, cfg.AUDIO_SPEED
514
- )
519
+ sig, rate = audio.open_audio_file(fpath, cfg.SAMPLE_RATE, offset, duration, cfg.BANDPASS_FMIN, cfg.BANDPASS_FMAX, cfg.AUDIO_SPEED)
515
520
 
516
521
  # Split into raw audio chunks
517
522
  return audio.split_signal(sig, rate, cfg.SIG_LENGTH, cfg.SIG_OVERLAP, cfg.SIG_MINLEN)
@@ -563,16 +568,14 @@ def get_result_file_names(fpath: str):
563
568
  # if "r" in cfg.RESULT_TYPES:
564
569
  # result_names["r"] = os.path.join(cfg.OUTPUT_PATH, file_shorthand + ".BirdNET.results.r.csv")
565
570
  if "kaleidoscope" in cfg.RESULT_TYPES:
566
- result_names["kaleidoscope"] = os.path.join(
567
- cfg.OUTPUT_PATH, file_shorthand + ".BirdNET.results.kaleidoscope.csv"
568
- )
571
+ result_names["kaleidoscope"] = os.path.join(cfg.OUTPUT_PATH, file_shorthand + ".BirdNET.results.kaleidoscope.csv")
569
572
  if "csv" in cfg.RESULT_TYPES:
570
573
  result_names["csv"] = os.path.join(cfg.OUTPUT_PATH, file_shorthand + ".BirdNET.results.csv")
571
574
 
572
575
  return result_names
573
576
 
574
577
 
575
- def analyze_file(item):
578
+ def analyze_file(item) -> dict[str, str] | None:
576
579
  """
577
580
  Analyzes an audio file and generates prediction results.
578
581
 
@@ -606,7 +609,7 @@ def analyze_file(item):
606
609
  print(f"Analyzing {fpath}", flush=True)
607
610
 
608
611
  try:
609
- fileLengthSeconds = int(audio.get_audio_file_length(fpath) / cfg.AUDIO_SPEED)
612
+ fileLengthSeconds = audio.get_audio_file_length(fpath)
610
613
  except Exception as ex:
611
614
  # Write error log
612
615
  print(f"Error: Cannot analyze audio file {fpath}. File corrupt?\n", flush=True)
@@ -649,8 +652,7 @@ def analyze_file(item):
649
652
  p_labels = [
650
653
  p
651
654
  for p in zip(cfg.LABELS, pred, strict=True)
652
- if (cfg.TOP_N or p[1] >= cfg.MIN_CONFIDENCE)
653
- and (not cfg.SPECIES_LIST or p[0] in cfg.SPECIES_LIST)
655
+ if (cfg.TOP_N or p[1] >= cfg.MIN_CONFIDENCE) and (not cfg.SPECIES_LIST or p[0] in cfg.SPECIES_LIST)
654
656
  ]
655
657
 
656
658
  # Sort by score
@@ -61,7 +61,7 @@ def get_audio_file_length(path):
61
61
  """
62
62
  # Open file with librosa (uses ffmpeg or libav)
63
63
 
64
- return librosa.get_duration(filename=path, sr=None)
64
+ return librosa.get_duration(path=path, sr=None)
65
65
 
66
66
 
67
67
  def get_sample_rate(path: str):
@@ -184,7 +184,7 @@ def split_signal(sig, rate, seconds, overlap, minlen, amount=None):
184
184
 
185
185
  # Split signal with overlap
186
186
  sig_splits = []
187
- sig_splits.extend(data[i : i + chunksize] for i in range(0, lastchunkpos, stepsize))
187
+ sig_splits.extend(data[i : i + chunksize] for i in range(0, lastchunkpos + 1, stepsize))
188
188
 
189
189
  return sig_splits
190
190
 
@@ -31,7 +31,7 @@ ASCII_LOGO = r"""
31
31
  **=====
32
32
  ***+==
33
33
  ****+
34
- """ # noqa: W291
34
+ """ # noqa: W291
35
35
 
36
36
 
37
37
  def io_args():
@@ -80,10 +80,9 @@ def bandpass_args():
80
80
 
81
81
  return p
82
82
 
83
-
84
- def species_args():
83
+ def species_list_args():
85
84
  """
86
- Creates an argument parser for species-related arguments.
85
+ Creates an argument parser for species-list arguments.
87
86
  Returns:
88
87
  argparse.ArgumentParser: The argument parser with the following arguments:
89
88
  --lat (float): Recording location latitude. Set -1 to ignore. Default is -1.
@@ -104,17 +103,33 @@ def species_args():
104
103
  default=-1,
105
104
  help="Week of the year when the recording was made. Values in [1, 48] (4 weeks per month). Set -1 for year-round species list.",
106
105
  )
107
- p.add_argument(
108
- "--slist",
109
- help='Path to species list file or folder. If folder is provided, species list needs to be named "species_list.txt". If lat and lon are provided, this list will be ignored.',
110
- )
111
106
  p.add_argument(
112
107
  "--sf_thresh",
113
108
  type=lambda a: max(0.0001, min(0.99, float(a))),
114
109
  default=cfg.LOCATION_FILTER_THRESHOLD,
115
110
  help="Minimum species occurrence frequency threshold for location filter. Values in [0.0001, 0.99].",
116
111
  )
112
+ return p
117
113
 
114
+ def species_args():
115
+ """
116
+ Creates an argument parser for species-related arguments including the species-list arguments.
117
+ Returns:
118
+ argparse.ArgumentParser: The argument parser with the following arguments:
119
+ --lat (float): Recording location latitude. Set -1 to ignore. Default is -1.
120
+ --lon (float): Recording location longitude. Set -1 to ignore. Default is -1.
121
+ --week (int): Week of the year when the recording was made. Values in [1, 48] (4 weeks per month).
122
+ Set -1 for year-round species list. Default is -1.
123
+ --sf_thresh (float): Minimum species occurrence frequency threshold for location filter. Values in [0.01, 0.99].
124
+ Defaults to cfg.LOCATION_FILTER_THRESHOLD.
125
+ --slist (str): Path to species list file or folder. If folder is provided, species list needs to be named
126
+ "species_list.txt". If lat and lon are provided, this list will be ignored.
127
+ """
128
+ p = species_list_args()
129
+ p.add_argument(
130
+ "--slist",
131
+ help='Path to species list file or folder. If folder is provided, species list needs to be named "species_list.txt". If lat and lon are provided, this list will be ignored.',
132
+ )
118
133
  return p
119
134
 
120
135
 
@@ -309,6 +324,7 @@ def analyzer_parser():
309
324
  Returns:
310
325
  argparse.ArgumentParser: Configured argument parser for the BirdNET Analyzer CLI.
311
326
  """
327
+ from birdnet_analyzer.analyze import POSSIBLE_ADDITIONAL_COLUMNS_MAP
312
328
  parents = [
313
329
  io_args(),
314
330
  bandpass_args(),
@@ -339,6 +355,14 @@ def analyzer_parser():
339
355
  help="Specifies output format. Values in `['table', 'audacity', 'kaleidoscope', 'csv']`.",
340
356
  action=UniqueSetAction,
341
357
  )
358
+ parser.add_argument(
359
+ "--additional_columns",
360
+ choices=POSSIBLE_ADDITIONAL_COLUMNS_MAP.keys(),
361
+ nargs="+",
362
+ help="Additional columns to include in the output, only applied to the csv output format. "
363
+ + f"Values in [{','.join(POSSIBLE_ADDITIONAL_COLUMNS_MAP.keys())}].",
364
+ action=UniqueSetAction,
365
+ )
342
366
  parser.add_argument(
343
367
  "--combine_results",
344
368
  help="Also outputs a combined file for all the selected result types. If not set combined tables will be generated.",
@@ -404,6 +428,10 @@ def embeddings_parser():
404
428
  help="Path to input file or folder.",
405
429
  )
406
430
 
431
+ parser.add_argument(
432
+ "--file_output",
433
+ )
434
+
407
435
  return parser
408
436
 
409
437
 
@@ -498,9 +526,7 @@ def segments_parser():
498
526
  )
499
527
  parser.add_argument("audio_input", metavar="INPUT", help="Path to folder containing audio files.")
500
528
  parser.add_argument("-r", "--results", help="Path to folder containing result files. Defaults to the `input` path.")
501
- parser.add_argument(
502
- "-o", "--output", help="Output folder path for extracted segments. Defaults to the `input` path."
503
- )
529
+ parser.add_argument("-o", "--output", help="Output folder path for extracted segments. Defaults to the `input` path.")
504
530
  parser.add_argument(
505
531
  "--max_segments",
506
532
  type=lambda a: max(1, int(a)),
@@ -535,9 +561,7 @@ def server_parser():
535
561
  parser.add_argument("-p", "--port", type=int, default=8080, help="Port of API endpoint server.")
536
562
  parser.add_argument(
537
563
  "--spath",
538
- default="uploads/"
539
- if os.environ.get("IS_GITHUB_RUNNER", "false").lower() == "true"
540
- else os.path.join(SCRIPT_DIR, "uploads"),
564
+ default="uploads/" if os.environ.get("IS_GITHUB_RUNNER", "false").lower() == "true" else os.path.join(SCRIPT_DIR, "uploads"),
541
565
  help="Path to folder where uploaded files should be stored.",
542
566
  )
543
567
 
@@ -555,7 +579,7 @@ def species_parser():
555
579
  """
556
580
  parser = argparse.ArgumentParser(
557
581
  formatter_class=argparse.ArgumentDefaultsHelpFormatter,
558
- parents=[species_args()],
582
+ parents=[species_list_args()],
559
583
  )
560
584
  parser.add_argument(
561
585
  "output",
@@ -603,9 +627,7 @@ def train_parser():
603
627
  metavar="INPUT",
604
628
  help="Path to training data folder. Subfolder names are used as labels.",
605
629
  )
606
- parser.add_argument(
607
- "--test_data", help="Path to test data folder. If not specified, a random validation split will be used."
608
- )
630
+ parser.add_argument("--test_data", help="Path to test data folder. If not specified, a random validation split will be used.")
609
631
  parser.add_argument(
610
632
  "--crop_mode",
611
633
  default=cfg.SAMPLE_CROP_MODE,
@@ -633,6 +655,7 @@ def train_parser():
633
655
  )
634
656
  parser.add_argument(
635
657
  "--focal-loss",
658
+ dest="use_focal_loss",
636
659
  action="store_true",
637
660
  help="Use focal loss for training (helps with imbalanced classes and hard examples).",
638
661
  )