#!/usr/bin/python3.10 # -*- coding: utf-8 -*- """************************ AnkIdentification - A project to improve your plant identifcation skills through Anki. Aurélien VALENTIN - from 06/11/2022 to 29/12/2022 ************************""" # Default parameters, feel free to change them as you want. NB_SPECIES = 100 # Number of species wanted by the user. Can't exceed 100 with the GBIF method. LANGUAGE = "fr" # Please choose "fr" or "en" to get respectively French or English vernacular names. SPECIE_LIST_PATH_IF_GBIF_METHOD = "" # A csv file from https://identify.plantnet.org/prediction. Only if you've chosen the GBIF method. MY_OWN_LIST_PATH = "" # A txt file with one specie by line. Be careful to write the scientific name used in Pl@ntNet and change NB_SPECIES if needed. # Importation and other initialisations import json, sys import genanki #https://github.com/kerrickstaley/genanki.git from random import shuffle dict_common_plants = {} with open("_dict_species.json", "r") as fpi : dict_common_names = json.load(fpi) # From the 3-1 and 3-2 supplementary codes # Definition of the progressbar function, from https://gist.github.com/ChesterChowWOV/2b35c551b339adbf459363322aac5b4b def progressbar(it, prefix = "", size = 60, file = sys.stdout): count = len(it) def show(j): x = int(size*j/count) file.write("{}[{}{}] {}/{} {}%\r".format(prefix, "█"*x, "."*(size-x), j, count, round(j / count * 100, 2))) file.flush() show(0) for i, item in enumerate(it): yield item show(i + 1) file.write("\n") file.flush() """************************ Step 1 : Listing the most common species (if without a manual list or a GBIF file). ************************""" if SPECIE_LIST_PATH_IF_GBIF_METHOD == MY_OWN_LIST_PATH: print("Listing the most common species") # Loading of the whole list with open("_dict_species_by_rarety.json") as fpi : dict_plants_sorted = json.load(fpi) # From the first supplementary code # Writing of the user's list with open("Selected_species.txt", "w") as fpo: for species in list(dict_plants_sorted.keys())[:NB_SPECIES]: fpo.write(species + "\n") """************************ Step 2 : Parsing data for each species. ************************""" # Initialisation of the dictionary (and addition of the family) from a file from the step 1... if SPECIE_LIST_PATH_IF_GBIF_METHOD == "": with open("_dict_classification.json", "r") as fpi : dict_classification = json.load(fpi) # From the second supplementary code try: fpi = open(MY_OWN_LIST_PATH) except : fpi = open("Selected_species.txt") for line in progressbar(fpi.readlines(), "Adding families", 40): specie = line.split(" ")[0] + " " + line.split(" ")[1].lower().strip() dict_common_plants[specie] = {"Occurrence": {"leaf": 0, "flower": 0, "fruit": 0, "bark": 0}} try: dict_common_plants[specie]["Family"] = dict_classification[specie] except: dict_common_plants[specie]["Family"] = "Family_not_found" dict_common_plants[specie]["Links"] = {"leaf": "", "flower": "", "fruit": "", "bark": ""} dict_common_plants[specie]["Authors"] = {"leaf": "", "flower": "", "fruit": "", "bark": ""} # ...or from a GBIF file from here : https://identify.plantnet.org/prediction else: with open(SPECIE_LIST_PATH_IF_GBIF_METHOD) as fpi: fpi.readline() for line in progressbar(fpi.readlines(), "Adding families", 40): specie = line.split(",")[1].split(" ")[0] + " " + line.split(",")[1].split(" ")[1] dict_common_plants[specie] = {"Occurrence": {"leaf": 0, "flower": 0, "fruit": 0, "bark": 0}} dict_common_plants[specie]["Family"] = line.split(",")[2] dict_common_plants[specie]["Links"] = {"leaf": "", "flower": "", "fruit": "", "bark": ""} dict_common_plants[specie]["Authors"] = {"leaf": "", "flower": "", "fruit": "", "bark": ""} # Addition of vernacular name(s) for specie in progressbar(dict_common_plants.keys(), "Adding common names", 40): try: dict_common_plants[specie]["Common names"] = dict_common_names[specie][LANGUAGE] except: dict_common_plants[specie]["Common names"] = "No common name found." # Addition of photo links and author names with open("multimedia.txt", encoding="utf-8") as fpi: fpi.readline() for line in progressbar(fpi.readlines(), "Adding links and common names", 40): line_split = line.split("\t") specie = line_split[5].split(" ")[0] + " " + line_split[5].split(" ")[1] link = line_split[3].strip(" ").split("o/")[1] type = line_split[5].split(":")[1].strip(" ") author = line_split[len(line_split) - 1].strip() if specie in dict_common_plants.keys() and type in ["leaf", "flower", "fruit", "bark"]: if dict_common_plants[specie]["Occurrence"][type] == 0: dict_common_plants[specie]["Links"][type] += link dict_common_plants[specie]["Authors"][type] += author dict_common_plants[specie]["Occurrence"][type] += 1 elif dict_common_plants[specie]["Occurrence"][type] < 101: dict_common_plants[specie]["Links"][type] += "," + link dict_common_plants[specie]["Authors"][type] += "," + author dict_common_plants[specie]["Occurrence"][type] += 1 """************************ Step 3 : Generation of the Anki deck. ************************""" print("Preparing the Anki deck") # Definition of the Anki card model my_model = genanki.Model( 1091735104, 'Model for AnkIdentification', fields=[ {'name': 'Name'}, {'name': 'Common names'}, {'name': 'Family'}, {'name': 'Leaf'}, {'name': 'Flower'}, {'name': 'Fruit'}, {'name': 'Bark'}, {'name': 'Leaf authors'}, {'name': 'Flower authors'}, {'name': 'Fruit authors'}, {'name': 'Bark authors'} ], templates=[ { 'name': 'Card 1', 'qfmt': """
""", 'afmt': """