# Import basic libs import json import time # Import PyQt libs from PyQt5.QtCore import QObject, pyqtSignal, QUrl, Qt, QVariant from PyQt5.QtGui import QColor from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply from PyQt5.QtWidgets import QDialog, QPushButton, QApplication, QVBoxLayout, QHBoxLayout, QButtonGroup, QCheckBox, QLabel # Import PyQgis libs from qgis.utils import iface from qgis.core import QgsProject, QgsFeature, QgsDataSourceUri, QgsRectangle, QgsNetworkAccessManager, QgsVectorLayer, QgsPointXY, QgsWkbTypes, QgsMapLayerProxyModel, QgsGeometry, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsField from qgis.gui import QgsMapTool, QgsMapMouseEvent, QgsRubberBand, QgsMapLayerComboBox class GetTaxrefId(QObject): finished_dl = pyqtSignal() """Get multiples informations from a getcapabilities request. List all layers available, get the maximal extent of all the Wfs' data.""" def __init__(self, network_manager=None, project=None, layer=None, field_name=None, field_rank=None): super().__init__() self.network_manager = network_manager self.project = project self.layer = layer self.field_name = field_name self.field_rank = field_rank self._pending_downloads = 0 self.ids = [] self.names = [] self.rank = [] for obs in self.layer.getFeatures(): self.ids.append(obs.id()) self.names.append(obs[self.field_name]) self.rank.append(obs[self.field_rank]) self._pending_downloads = len(self.names) self._iterate_names = 0 self.download(self.ids[self._iterate_names], self.names[self._iterate_names], self.rank[self._iterate_names]) @property def pending_downloads(self): return self._pending_downloads @property def iterate_names(self): return self._iterate_names def download(self, feature_id, nom, rank): if rank.lower() == 'stateofmatter': self._iterate_names += 1 self.download(self.ids[self._iterate_names], self.names[self._iterate_names], self.rank[self._iterate_names]) else: if rank.lower() == 'complex' or rank.lower() == 'hybrid': rank = 'species' elif rank.lower() == 'epifamily' or rank.lower() == 'section': rank = 'genus' elif rank.lower() == 'subtribe': rank = 'subfamily' url = "https://api.checklistbank.org/nameusage/search?content=SCIENTIFIC_NAME&datasetKey=2008&facet=datasetKey&facet=rank&facet=issue&facet=status&facet=nomStatus&facet=nameType&facet=field&facet=authorship&facet=authorshipYear&facet=extinct&facet=environment&facet=origin&limit=50&offset=0&q={nom}&rank={rank}&type=PREFIX".format(nom=nom.split("(")[0], rank=rank.lower()) print(url) request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") reply = self.network_manager.get(request) reply.finished.connect(lambda: self.handle_finished(reply, feature_id)) self._iterate_names += 1 def handle_finished(self, reply, feature_id): self._pending_downloads -= 1 if reply.error() != QNetworkReply.NoError: print(f"code: {reply.error()} message: {reply.errorString()}") if reply.error() == 403: print("Service down") else: data_request = reply.readAll().data().decode() if data_request != "": res = json.loads(data_request) if "result" in res: taxref_id = res["result"][0]["id"] taxref_name = res["result"][0]["usage"]["label"] self.layer.startEditing() self.layer.changeAttributeValue(feature_id, self.layer.fields().indexFromName("cd_nom"), taxref_id) self.layer.changeAttributeValue(feature_id, self.layer.fields().indexFromName("nom_scien"), taxref_name) self.layer.commitChanges() self.layer.triggerRepaint() if self.pending_downloads == 0: self.project.addMapLayer(self.layer) self.finished_dl.emit() else: self.download(self.ids[self._iterate_names], self.names[self._iterate_names], self.rank[self._iterate_names]) class ImportDataGbif(QObject): finished_dl = pyqtSignal() """Get multiples informations from a getcapabilities request. List all layers available, get the maximal extent of all the Wfs' data.""" def __init__(self, network_manager=None, project=None, geom=None, ): super().__init__() self._pending_downloads = 0 self._pending_pages = 1 self.network_manager = network_manager self.project = project self.layer = self.new_layer() self.geom = geom self.new_features = [] self.max_obs = 0 self.total_pages = 0 self.download() @property def pending_downloads(self): return self._pending_downloads @property def pending_pages(self): return self._pending_pages def new_layer(self): geom_type = "Point" new_layer = QgsVectorLayer(geom_type + "?crs=epsg:4326", "GBIF", "memory") new_layer.startEditing() new_layer.addAttribute(QgsField("id", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("cd_nom", QVariant.Int, "integer", 10)) new_layer.addAttribute(QgsField("niveau", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("nom", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("nom_scien", QVariant.String, "string", 100000)) new_layer.addAttribute(QgsField("observat", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("date", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("projet", QVariant.String, "string", 254)) new_layer.addAttribute(QgsField("effectif", QVariant.Int, "integer", 10)) new_layer.addAttribute(QgsField("url", QVariant.String, "string", 254)) new_layer.commitChanges() new_layer.triggerRepaint() return new_layer def download(self): url = "https://api.gbif.org/v1/occurrence/search?advanced=false&geometry={polygon}&offset={offset}&limit=1000".format( offset=self.pending_pages, polygon=self.geom.asWkt()) url = QUrl(url) self.nb_request = 1 print(url) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") reply = self.network_manager.get(request) reply.finished.connect(lambda: self.handle_finished(reply)) self._pending_downloads += 1 def handle_finished(self, reply): self._pending_downloads -= 1 if reply.error() != QNetworkReply.NoError: print(f"code: {reply.error()} message: {reply.errorString()}") if reply.error() == 403: print("Service down") else: data_request = reply.readAll().data().decode() if self.pending_downloads == 0: res = json.loads(data_request) self.max_obs = res["count"] self.total_pages = int(self.max_obs/20) + 1 for obs in res["results"]: new_geom = QgsGeometry.fromPointXY(QgsPointXY(obs["decimalLongitude"], obs["decimalLatitude"])) new_feature = QgsFeature(self.layer.fields()) new_feature.setGeometry(new_geom) new_feature.setAttribute(0, str(obs["key"])) new_feature.setAttribute(1, 0) new_feature.setAttribute(2, obs["taxonRank"]) if obs["taxonRank"].lower() in ['kingdom', 'phylum', 'order', 'family', 'genus', 'species']: new_feature.setAttribute(3, obs[obs["taxonRank"].lower()]) else: new_feature.setAttribute(3, obs["scientificName"]) new_feature.setAttribute(4, "") new_feature.setAttribute(5, "") new_feature.setAttribute(6, str(obs["eventDate"])) # new_feature.setAttribute(7, obs["_datasetKey"]["title"]) new_feature.setAttribute(7, obs["datasetName"] if "datasetName" in obs.keys() else None ) new_feature.setAttribute(8, 1) new_feature.setAttribute(9, "https://www.gbif.org/fr/occurrence/" + str(obs["key"])) self.new_features.append(new_feature) if self.nb_request == 10: time.sleep(10) if self.pending_pages < self.total_pages: self._pending_pages += 300 self.nb_request += 1 self.download() else: # Add the new feature to the temporary layer self.layer.startEditing() self.layer.dataProvider().addFeatures(self.new_features) self.layer.updateExtents() self.layer.commitChanges() self.layer.triggerRepaint() GetTaxrefId(self.network_manager, self.project, self.layer, "nom", "niveau") self.finished_dl.emit()