BirdNet / species.py
BilalSardar's picture
Upload 2 files
6b3d53a
"""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
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.05, help="Occurrence frequency threshold. Defaults to 0.05.")
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()
# 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 = args.o
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 = args.lat, args.lon, args.week
cfg.LOCATION_FILTER_THRESHOLD = args.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 args.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")
# 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