Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data GBIF/iNaturalist => Synthese ? #2775

Open
sylvain-m opened this issue Oct 30, 2023 · 23 comments
Open

Data GBIF/iNaturalist => Synthese ? #2775

sylvain-m opened this issue Oct 30, 2023 · 23 comments

Comments

@sylvain-m
Copy link
Contributor

Salut la Team GeoNature 😀

Longtemps que je ne suis pas passé ici, et désolé par avance si le sujet a déjà été évoqué.

Je n'administre plus aucune base GeoNature, mais je reste naturaliste et animé de la passion de saisir/valoriser mes observations, et à ce titre il m'arrive encore de saisir des observations sur plusieurs instances GeoNature.

Cependant, je dois avouer qu'en tant que photographe naturaliste, j'ai aussi été séduit par l'ergonomie et surtout la philosophie d'iNaturalist, qui selon moi est une révolution en la matière (je pourrai en parler des heures, mais ce n'est pas le lieu).

Finalement, que ce soit iNaturalist, le GBIF (ou d'autres plateformes que je ne connaitrais pas), il y a aujourd'hui un certain nombre de données naturalistes de qualité, librement accessibles (dans le cas d'iNaturalist ou GBIF, via une API par exemple).

De mon point de vue (mais j'accepte d'être contredit), ces données devraient être intégrées dans la synthèse d'une instance GeoNature, selon le périmètre de cette instance (géographique, taxonomique, ...).

La synthèse pouvant alimenter un ou des Atlas, il serait dommage de se priver de données libres pour compléter la répartition ou la phénologie des fiches espèces de cet Atlas.

J'ouvre donc cette issue pour

  • savoir si d'autres personnes partagent ce point de vue ?
  • savoir si certains ont déjà réalisé ce genre de connexion ?
  • (si oui) savoir s'ils partageraient leurs expériences/scripts, pour aider ceux qui souhaiteraient réaliser ce genre de connexion dans leur instance ?

Merci à vous !

Sylvain

@sylvain-m
Copy link
Contributor Author

@nleguillarme et @DonovanMaillard, je vois ici que vous vous êtes déjà penchés sur la question :

Nous avons développé de notre côté des pipelines d'acquisition de données depuis iNaturalist et Pl@ntNet [...] Ces pipelines sont destinés à être diffusés plus largement. Je sais que @DonovanMaillard notamment est potentiellement intéressé.

@DonovanMaillard
Copy link
Contributor

Salut Sylvain,

C'est touours prévu de mon coté, tant pour le GBIF que pour iNaturalist. Mais question de temps, je n'ai toujours pas pu m'y atteler. Mes espoirs pour fin 2023 s'amenuisent peu à peu ;)

@TheoLechemia
Copy link
Member

Salut Sylvain,

Oui c'est toujours une idée qui est dans les tuyaux.
J'ai commencé à développer un module GeoNature permettant de "parser" des API externes. Il est fonctionnel pour se connecter à d'autres GeoNature et également des flux XML. On a pour ambition de développer un nouveau "parser" pour se connecter à l'API du GBIF.
Le code est ici : https://github.com/PnX-SI/api2GN . C'est écrit en Python. N'hésite pas à y contribuer si ça t'inspire.

à bientôt

@camillemonchicourt
Copy link
Member

Pour moi iNaturalist est un outil et une communauté de contribution au GBIF (parmi plein d'autres dont l'INPN).
Donc il s'agirait bien de pouvoir récupérer les données du GBIF dans GeoNature et non pas de iNaturalist (car elles sont intégrées dans le GBIF), il me semble.

Attention aussi au fait que les données de l'INPN sont versées régulièrement dans le GBIF donc on pourrait récupérer des données qu'on a déjà.
Mais ça c'est classique quand on récupère des données dans une BDD agglomératrice.

De la même manière, il est souhaité pouvoir importer des données depuis l'INPN en interrogeant l'API d'OpenObs.

@sylvain-m
Copy link
Contributor Author

Donc il s'agirait bien de pouvoir récupérer les données du GBIF dans GeoNature et non pas de iNaturalist

On est d'accord ! (et c'est pour ça que je l'ai mis en premier dans le titre)

donc on pourrait récupérer des données qu'on a déjà

Oui, c'est un point d'attention à avoir, et je sais que le GBIF a développé des outils avancés de détection de doublons.
Et sinon, ce sujet serait grandement simplifié avec l'implémentation de la notion d'identifiant unique observateur (ORCID) évoqué dans cette issue :
#1393

De la même manière, il est souhaité pouvoir importer des données depuis l'INPN en interrogeant l'API d'OpenObs.

👍👍👍

J'ai commencé à développer un module GeoNature permettant de "parser" des API externes. [...] Le code est ici : https://github.com/PnX-SI/api2GN .

Super !!! Merci @TheoLechemia 👍👍👍
Je vais regarder ça (mais je ne suis toujours pas développeur, donc pas sûr de pouvoir aider)

Content de voir que le sujet ne déclenche pas de polémique 😀

Vive l'OpenData et les communs numériques 💚

@DonovanMaillard
Copy link
Contributor

De la même manière, il est souhaité pouvoir importer des données depuis l'INPN en interrogeant l'API d'OpenObs.

Je me suis penché sur la question, et pour le moment je ne trouve aucune API qui retourne les obs complètes dans la doc des API d'OpenObs...

@camillemonchicourt
Copy link
Member

Oui l'API INPN d'OpenObs n'est pas documentée actuellement et donc pas forcément prévue pour le moment pour être interroger directement pas des outils tiers ?

Mais Amandine avait aussi commencé des tests et noté cela mais avec des mailles 10km - https://github.com/PnX-SI/Ressources-techniques/tree/master/SINP/open_obs

@sylvain-m
Copy link
Contributor Author

Mais Amandine avait aussi commencé des tests et noté cela mais avec des mailles 10km

Pas vraiment "open", "OpenObs" ? 😉

Dans tous les cas, il est préférable de pointer directement sur le GBIF, les données "Open" y seront dispo "brutes".
J'ai testé, avec les miennes, c'est bon elles remontent bien.
Exemple :
https://www.inaturalist.org/observations/129881560 => https://www.gbif.org/occurrence/4145546442

Autant pointer sur le plus haut niveau, puis effectivement appliquer un filtre pour supprimer les données qui proviendraient de cette instance GeoNature, ou qui y auraient déjà été intégrées.

@orovellotti
Copy link

Vous aviez pas déjà fait ca pour la Jamaïque ?

Sinon oui, très preneur pour les territoire qui font un ABC, ils veulent des données.

@camillemonchicourt
Copy link
Member

Pas vraiment "open", "OpenObs" ? 😉

Si car c'est de l'opendata et on peut télécharger les données précises (non sensibles) comme prévu dans le SINP, donc c'est un super outil et une super avancée.
C'est juste que l'API n'est pas encore documentée à ma connaissance, et peut-être pas encore prévue pour être utilisée directement, mais c'est en cours.
Tout ça prend du temps, de l'argent et des gens.


Oui les données de iNaturalist remontent directement et bien dans le GBIF, mais ce qui est saisi dans un GeoNature ou les outils français, ou est intégré dans l'INPN ne remonte pas aussi simplement et rapidement dans le GBIF.
Et il faut voir si la précision des données et leur qualité dans l'INPN est la même quand ça remonte dans l'INPN, etc...
Donc pas mal de choses à voir, vérifier et analyser car la chaine de travail et les remontées de données ont de nombreux intermédiaires qui ne sont pas encore si simples ni automatisés.


Ensuite sur le fait d'intégrer les données de l'INPN ou du GBIF dans un GeoNature d'un parc, je ne pense pas qu'il y ait de règle ou de réponse unique.
Notre objectif est de le prévoir techniquement, ensuite libre à chacun de le faire ou non.

Pour ma part, je ne suis pas convaincu qu'un GeoNature territorial d'un parc national ou régional nécessite de réintégrer toutes les données existantes sur son territoire, tant qu'elles sont disponibles quelque part d'accessible et ouvert.
De notre côté, je pense qu'un GeoNature d'un territoire est avant tout une instance de production de données pour les utiliser et les diffuser localement, puis régionalement, puis nationalement, puis internationalement.

Mais à terme, quand les flux, les API et les outils d'import automatiques seront disponibles, libre à chacun d'enrichir son GeoNature avec des données nationales ou internationales.


Vous aviez pas déjà fait ça pour la Jamaïque ?

On avait fait un projet expérimental pour tester de récupérer toutes les données GBIF d'un pays (Jamaïque pour l'exemple) et d'une ville (Copenhague en complément) et de monter un GeoNature-atlas sur ces données.
Et oui, ça avait fonctionné, même si c'était un export et import manuel à un instant T, pour le test.
Et on avait documenté ça ici - https://si.ecrins-parcnational.com/blog/2019-05-geonature-atlas-gbif-jamaica.html
Ce projet expérimental avait gagné un prix du GBIF - https://www.ecrins-parcnational.fr/breve/geonature-podium

Les atlas GeoNature basés sur les données GBIF de Jamaïque et de Copenhague sont malheureusement éteints actuellement, car on avait besoin de ressources serveurs pour d'autres projet. :-)

@sylvain-m
Copy link
Contributor Author

sylvain-m commented Nov 2, 2023

Tout ça prend du temps, de l'argent et des gens.

Oui oui, c'est évident : je lance le sujet, car je trouve que c'est important d'y réfléchir, mais je n'attends pas à ce que ce soit en place rapidement. Mais au moins, le débat est lancé (et justement, c'est important de le lancer puisque je lis quelques appréciations différentes dans la suite de ton message 😀)

Pour ma part, je ne suis pas convaincu qu'un GeoNature territorial d'un parc national ou régional nécessite de réintégrer toutes les données existantes sur son territoire, tant qu'elles sont disponibles quelque part d'accessible et ouvert.

Là, je suis moins d'accord, mais bien entendu, je ne suis qu'un "simple utilisateur" de GeoNature, avec la vision d'un naturaliste et/ou gestionnaire d'espace naturels.

Pour un "gestionnaire d'espace naturels" il est utile d'avoir un outil de "monitoring" de son territoire d'étude.
Et c'est quand même une des fonctions de GeoNature non ?

Ensuite, présenter un Atlas de la Biodiversité du PNR de Tartempion, avec des cartes de fiches espèces qui ne reflètent qu'une partie de la connaissance, alors que cette dernière est accessible, c'est quand même bien dommage (j'ai plusieurs observations sous iNaturalist de nouvelles espèces pour le territoire du PNR concerné, qui n'apparaissent donc pas dans les listings/cartes, alors qu'elles le devraient).

Je pense, pour participer à de nombreux réseaux naturalistes, que de plus en plus de données viendront de cette plateforme (iNaturalist), et que les ignorer serait une "faute stratégique".

Et comme ces données sont dans le GBIF (c'est une des raisons, après l'ergonomie, pour laquelle j'utilise iNaturalist), autant se connecter au GBIF directement, c'est la logique pour éviter d'avoir à multiplier les connexions à la multiplicités des instances/plateformes productrices.

Non ?

@DonovanMaillard
Copy link
Contributor

DonovanMaillard commented Nov 2, 2023

C'est juste que l'API n'est pas encore documentée à ma connaissance, et peut-être pas encore prévue pour être utilisée directement, mais c'est en cours.

Il y a bien une doc développeurs avec certaines API, des exemples avec une doc swagger téléchargeables etc, mais seulement pour des routes qui synthétisent des données : statistiques, infos d'un taxon, statistiques par années etc :
https://openobs.mnhn.fr/developer

Pour le moment je n'ai pas trouvé d'API qui retourne des objets "occurrences" mais c'est peut être à venir. A voir aussi sur le projet source, open obs est basé sur un outil déployé dans d'autres pays.

Pour un "gestionnaire d'espace naturels" il est utile d'avoir un outil de "monitoring" de son territoire d'étude.

Ca c'est des questions de positionnements qui dépendent des utilisateurs et des gestionnaires. Je gère plusieurs instances, certains ont besoin d'avoir leurs données dans une boite isolée pour leurs rendus, analyses etc, et d'avoir accès aux données des autres dans des outils distincts. D'autres veulent tout dans leur base pour avour tout au même endroit. Et certains sites protégés ne sont prospectés que par ou pour le gestionnaire puisque interdit aux autres. Les contextes et les besoins sont très variables et l'outil ne doit pas faire le choix à la place de son administrateur :)

@sylvain-m
Copy link
Contributor Author

Les contextes et les besoins sont très variables

On est bien d'accord ! 😀

et l'outil ne doit pas faire le choix à la place de son administrateur :)

On donc, si l'administrateur d'une instance souhaite que son outil affiche les données OpenData, il faut anticiper cette demande.

certains ont besoin d'avoir leurs données dans une boite isolée

Il va de soit que les données en OpenData externes ne doivent pas être mélangée avec les données de l'administrateur de l'instance.
C'est pour ça que l'on parle d'import en Synthèse, avec possibilité de connexion, et d'affichage optionnel.

@DonovanMaillard
Copy link
Contributor

Oui oui, mais du coup on est plusieurs à s'y intéresser, et à le prévoir pour le GBif. Le soucis pour beaucoup d'entre nous c'est de trouver le temps de faire un truc qui fonctionne bien, qui soit facile à utiliser, et qui gère bien les questions des métadonnées, des doublons avec les données qu'on récupère localement etc :) Mais ça reste au programme !

@sylvain-m
Copy link
Contributor Author

Salut à tous,
Je reviens aux nouvelles sur ce sujet.
Même si c'est brouillon et pas générique, je suis intéressé si quelqu'un a déjà quelques bouts de codes à partager 😉
J'ai vu sur plusieurs autres discussions que certains ont déjà fait ce travail : ce serait sympa de le partager ? (même si c'est imparfait !)

@camillemonchicourt
Copy link
Member

On a discuté récemment ici d'intégrer le référentiel taxonomique du GBIF à la place de Taxref : PnX-SI/TaxHub#318
Mais pas d'intégrer des données GBIF dans la synthèse de GeoNature, même si c'est ce que j'avais fait et expliqué dans l'article référencé dans cette même discussion sur l'intégration de données GBIF à Copenhague ou en Jamaïque.

En terme d'automatisation de cela il n'y a rien de nouveau à m connaissance.

@sylvain-m
Copy link
Contributor Author

Merci Camille pour ta réponse.

intégrer le référentiel taxonomique du GBIF à la place de Taxref : PnX-SI/TaxHub#318

Cela ne me semble pas pertinent pour le besoin identifié d'import dans une instance française/SINP.
(dans le cas précis du ticket référencé, pourquoi pas, puisque ce ne sont pas des espèces sauvages/françaises)

Le lien entre TAXREF et GBIF est déjà opérationnel à 96% :
https://www.gbif.org/fr/dataset/0e61f8fe-7d25-4f81-ada7-d970bbb2c6d6
image

Il ne faut donc pas intégrer le référentiel du GBIF "à la place de Taxref", mais "en complément de TaxRef", en ajoutant par exemple à TaxHub un champ id_gbif, ce qui permettra de faire la correspondance pour 96% des taxons (et sans doute encore plus de pourcentage d'occurrences)

@sylvain-m
Copy link
Contributor Author

Je me permets à nouveau de relancer ce sujet.

De mon côté, j'ai finalement découvert que la correspondance TAXREF <=> GBIF est déjà disponible "en dur" dans TAXREF (v17), via la table TAXREF_LIENS, dont voici un extrait :
image
(au total, 616463 cd_nom ont un lien GBIF)

Par ailleurs, le GBIF dispose d'une API, et un module Python dédié : PyGBIF : https://github.com/gbif/pygbif

De manière assez simple, j'ai pu récupérer via ce module les occurrences, en filtrant par exemple selon une emprise (bounding-box) et un jeu de donnée (Dataset "iNaturalist Research-grade Observations")
Mais n'ayant pour l'instant pas accès à l'administration d'une instance GeoNature, je ne peux aller plus loin dans mes tests.

Il me semble que tout est réuni pour que ce travail soit relativement "simple", si l'objectif est "juste" d'ajouter un jeu de données "GBIF" répondant à quelques filtres (spatiaux, taxonomiques, sources, ...). Reste quand même le gros travail de mise en correspondance des champs des occurrences, mais ce travail n'a pas besoin d'être exhaustif, puisque le lien vers la source permet d'avoir toutes les infos.

Avant que je n'aille plus loin, n'étant pas véritablement développeur, je me permets de relancer la bouteille à la mer pour savoir si certains auraient déjà fait ce travail, et des bouts de code à partager ? Ou si ceux qui se seraient frottés à ce sujet ne voudraient pas profiter de ce fil pour partager les éventuelles difficultés rencontrés ?

@DonovanMaillard
Copy link
Contributor

Merci, en effet il y a matière à regarder tout ça.

Pour ma part, je ne peux et ne veux pas récupérer les données seules sans les métadonnées, ce qui complique un peu les choses. Je ne me suis pas repenché sur ce sujet pour le moment, je n'ai pas de deadline pour ça donc ça ne sera pas pour les prochaines semaines,

@sylvain-m
Copy link
Contributor Author

sylvain-m commented Jul 2, 2024

Pour ce qui concerne les métadonnées, je pensais créer manuellement un jeu de donnée dédiée au Dataset "iNaturalist Research-grade Observations"
Les métadonnées de ce jeu de données ne sont donc à saisir qu'une seule fois.

Sinon, pour ceux que cela intéresse, voici déjà un code fonctionnel, basé sur une liste d'Observateurs "en dur".
Ce qui serait mieux, c'est une table de correspondance entre l'identifiant de l'utilisateur GeoNature (userhub si je me souviens bien 😉 ) et l'identifiant utilisateur dans la base externe, selon le Dataset.
Et l'idéal étant à terme de se baser sur ORCID (cf. #1393), mais ça marche pour l'instant très bien avec le champ 'RecordBy'.

import csv
from pygbif import occurrences as occ
from datetime import datetime

# Export name for naming export file
exportname = 'iNaturalist_gbif_observers_list_ornearea'

# Bounding box (latitude/longitude) to limit area
min_latitude = 48.175391
max_latitude = 48.977037
min_longitude = -0.867335
max_longitude = 0.98335

# List of observers
observer_list = ['User1', 'User Toto', 'Sylvain Montagner'] # based on recordedBy field

# Search params
search_params = {
    'country': 'FR',         # France
    'decimalLatitude': f'{min_latitude},{max_latitude}',
    'decimalLongitude': f'{min_longitude},{max_longitude}',
    'datasetKey': '50c9509d-22c7-4a22-a47d-8c48425ef4a7', # iNaturalist dataset
    'limit': 300,            # Limit of 300 occurrences per request
}

# Function to retrieve all occurrences with pagination
def get_all_occurrences(params, observers):
    all_occurrences = []
    for observer in observers:
        offset = 0
        params['recordedBy'] = observer
        while True:
            params['offset'] = offset
            occurrences = occ.search(**params)
            results = occurrences['results']
            if not results:
                break
            all_occurrences.extend(results)
            offset += len(results)
            print(f"{offset} occurrences retrieved for observer {observer} ...")
    return all_occurrences

# Retrieve all occurrences
all_occurrences = get_all_occurrences(search_params, observer_list)


# List all available fields
all_fields = set()
for occurrence in all_occurrences:
    all_fields.update(occurrence.keys())

# Get current date and time for export name
current_datetime = datetime.now().strftime("%Y%m%d_%H%M%S")

# Save occurrences in a CSV file
output_file = f"occurrences_{exportname}_{current_datetime}.csv"

with open(output_file, mode='w', newline='', encoding='utf-8') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=list(all_fields))
    writer.writeheader()
    for occurrence in all_occurrences:
        writer.writerow({field: occurrence.get(field, '') for field in all_fields})

print(f"occurrences have been recorded in the {output_file} file.")

@pierre56
Copy link
Contributor

pierre56 commented Jul 2, 2024

Via API2GN

J'ai commencé a bricoler un truc suite aux rencontres geonature, pour utiliser https://github.com/PnX-SI/api2GN
afin de faire l'intégration des données.

gbif_parser.py

from pygbif import occurrences , registry , species
from geojson import Feature
from shapely import wkt
from geoalchemy2.shape import from_shape
from api2gn.parsers import JSONParser

class GBIFParser(JSONParser):
    srid = 4326
    progress_bar = False  # Assuming no progress bar is needed for a single request

    def __init__(self, occurrence_id):
        # Initialize the parent class
        super().__init__()
        self.occurrence_id = occurrence_id
        self.data = self.fetch_data()
        self.validate_mapping()

    def fetch_data(self):
        # Using pygbif to fetch occurrence data
        response = occurrences.get(self.occurrence_id)
        if response.get('status') == 'success':
            return response['data']
        else:
            raise ValueError(f"Failed to fetch data for occurrence ID {self.occurrence_id}")

    @property
    def items(self):
        return [self.data]  # Return data as a list with a single item

    @property
    def total(self):
        return 1  # Only one item in this case

    def get_geom(self, row):
        if 'decimalLatitude' in row and 'decimalLongitude' in row:
            point = f"POINT({row['decimalLongitude']} {row['decimalLatitude']})"
            geom = wkt.loads(point)
            return from_shape(geom, srid=4326)
        return None

    mapping = {
        # "unique_id_sinp": 
        "eventDate": "date_min",  
        "scientificName": "cd_nom",
        "decimalLatitude": "latitude",
        "decimalLongitude": "longitude",
        "species": "species",
        "recordedBy": "observers",
        "identifiedBy": "determiner",
        "locality": "place_name",
        "habitat": "cd_hab",
        "occurrenceRemarks": "comment_context",
        # Add more fields as necessary
    }

Pour le moment, je suis que a l'étape du POC
mais j'ai repère la lib python pygbif
et je me suis dit qu'il y avait moyen de récupérer les métadonnées en complément.

https://api.gbif.org/v1/organization/28eb1a3f-1c15-4a95-931a-4af90ecb574d
https://api.gbif.org/v1/dataset/50c9509d-22c7-4a22-a47d-8c48425ef4a7
https://api.gbif.org/v1/geocode/gadm/FRA.3_1/subdivisions (Bretagne mais ils ont oublié le 44)

par contre je n'arrive pas a trouver l'uuid de l'observation et d'après les discutions c'était disponible 🤔
ex : https://api.gbif.org/v1/occurrence/4407389321

Avec ton exemple, je vais essayer de creuser dans les semaines qui viennent pour avoir un truc fonctionnel sur un secteur et les données provenant de Inaturalist. On a des conservateurs bénévoles qui préfèrent saisir sur cet outil et on voit jamais les données...

je vais créer une branche dédiée bientôt.
Merci pour le partage 👍

@TheoLechemia
Copy link
Member

Trop bien ! Hésite pas à faire une PR sur le repo API2GN. J'ai hâte de tester ça

@sylvain-m
Copy link
Contributor Author

sylvain-m commented Jul 2, 2024

Super : bravo @pierre56 😃
Je suis de très très loin les évolutions de GN depuis quelques années, mais du coup, si ça marche, la question qui devra être posée sera : quelles données intègre-t-on via cet outil.
Pour ce que j'imaginais concernant notre instance, j'aurais bien vu pouvoir choisir le/les jeux de données à importer (et commencer par "iNaturalist Research-grade Observations" ), et que les données ne soient récupérées que pour une certaine liste d'utilisateurs qui auraient donné leur accord.

Même si la licence des données permettrait d'intégrer la totalité du jeu de données, l'intérêt, c'est que cela donne à l'observateur le choix d'intégrer ou non ses données d'autres plateforme dans son instance de saisie.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants