forked from kahst/BirdNET-Analyzer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
species.py
103 lines (78 loc) · 3.48 KB
/
species.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""Module for predicting a species list.
Can be used to predict a species list using coordinates and weeks.
"""
import argparse
import os
import sys
import config as cfg
import model
import utils
def getSpeciesList(lat: float, lon: float, week: int, threshold=0.05, sort=False) -> list[str]:
"""Predict a species list.
Uses the model to predict the species list for the given coordinates and filters by threshold.
Args:
lat: The latitude.
lon: The longitude.
week: The week of the year [1-48]. Use -1 for year-round.
threshold: Only values above or equal to threshold will be shown.
sort: If the species list should be sorted.
Returns:
A list of all eligible species.
"""
# Extract species from model
pred = model.explore(lat, lon, week)
# Make species list
slist = [p[1] for p in pred if p[0] >= threshold]
return sorted(slist) if sort else slist
def run(output_path, lat, lon, week, threshold, sortby):
# Set paths relative to script path (requested in #3)
cfg.LABELS_FILE = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), cfg.LABELS_FILE)
cfg.MDATA_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), cfg.MDATA_MODEL_PATH)
# Load eBird codes, labels
cfg.LABELS = utils.readLines(cfg.LABELS_FILE)
# Set output path
cfg.OUTPUT_PATH = output_path
if os.path.isdir(cfg.OUTPUT_PATH):
cfg.OUTPUT_PATH = os.path.join(cfg.OUTPUT_PATH, "species_list.txt")
# Set config
cfg.LATITUDE, cfg.LONGITUDE, cfg.WEEK = lat, lon, week
cfg.LOCATION_FILTER_THRESHOLD = threshold
print(f"Getting species list for {cfg.LATITUDE}/{cfg.LONGITUDE}, Week {cfg.WEEK}...", end="", flush=True)
# Get species list
species_list = getSpeciesList(
cfg.LATITUDE, cfg.LONGITUDE, cfg.WEEK, cfg.LOCATION_FILTER_THRESHOLD, False if sortby == "freq" else True
)
print(f"Done. {len(species_list)} species on list.", flush=True)
# Save species list
with open(cfg.OUTPUT_PATH, "w") as f:
for s in species_list:
f.write(s + "\n")
if __name__ == "__main__":
# Parse arguments
parser = argparse.ArgumentParser(
description="Get list of species for a given location with BirdNET. Sorted by occurrence frequency."
)
parser.add_argument(
"--o",
default="example/",
help="Path to output file or folder. If this is a folder, file will be named 'species_list.txt'.",
)
parser.add_argument("--lat", type=float, help="Recording location latitude.")
parser.add_argument("--lon", type=float, help="Recording location longitude.")
parser.add_argument(
"--week",
type=int,
default=-1,
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.",
)
parser.add_argument("--threshold", type=float, default=0.03, help="Occurrence frequency threshold. Defaults to 0.03.")
parser.add_argument(
"--sortby",
default="freq",
help="Sort species by occurrence frequency or alphabetically. Values in ['freq', 'alpha']. Defaults to 'freq'.",
)
args = parser.parse_args()
run(args.o, args.lat, args.lon, args.week, args.threshold, args.sortby)
# A few examples to test
# python3 species.py --o example/ --lat 42.5 --lon -76.45 --week -1
# python3 species.py --o example/species_list.txt --lat 42.5 --lon -76.45 --week 4 --threshold 0.05 --sortby alpha