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