"""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