aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2023-09-27 15:20:16 +0200
committerGuilhem Moulin <guilhem@fripost.org>2023-09-27 18:09:54 +0200
commitccb73fbe98ccc2f54197372ff8f047b535a77bc8 (patch)
treebe7b37db16137579981d976623d3e5801ec7f4ef
parent70807f9c3d2932cdcd73b2025fdcf25a32dae76e (diff)
Get Observations from ArtDataBanken.
-rwxr-xr-xgis-observation-map168
1 files changed, 167 insertions, 1 deletions
diff --git a/gis-observation-map b/gis-observation-map
index 4fe06cf..551a8af 100755
--- a/gis-observation-map
+++ b/gis-observation-map
@@ -322,6 +322,78 @@ artDataBankenHeaders = {
# https://github.com/biodiversitydata-se/SOS/blob/master/Docs/Authentication.md
'Ocp-Apim-Subscription-Key': config['ArtDataBanken']['Subscription-Key']
}
+
+def getObservations(taxonLists, taxonRedlistCategories, data):
+ # https://api-portal.artdatabanken.se/docs/services/sos-api-v1/operations/Exports_DownloadGeoJson
+ headers = artDataBankenHeaders.copy()
+ headers['Content-Type'] = 'application/json'
+ headers['Authorization'] = config['ArtDataBanken']['Authorization']
+ params = {
+ 'cultureCode': 'sv-SE',
+ 'flat': 'true',
+ 'excludeNullValues': 'true',
+ 'gzip': 'false',
+ #'sensitiveObservations': 'true',
+ 'validateSearchFilter': 'true',
+ }
+ resp = requests.post(
+ artDataBankenURL + '/species-observation-system/v1/Exports/Download/GeoJson',
+ headers=headers,
+ params=params,
+ data=json.dumps(data)
+ )
+
+ resp.raise_for_status()
+ obs = resp.json()
+
+ # https://www.rfc-editor.org/rfc/rfc7946
+ if obs is None or type(obs) != dict or 'type' not in obs.keys():
+ raise Exception('invalid GeoJSON output')
+ if 'crs' not in obs.keys():
+ print('WARN: GeoJSON output lacks CRS', file=sys.stderr)
+
+ if obs['type'] == 'FeatureCollection' and 'features' in obs.keys() and type(obs['features']) == list:
+ for feat in obs['features']:
+ if (type(feat) != dict or 'type' not in feat.keys() or feat['type'] != 'Feature'
+ or 'properties' not in feat.keys() or type(feat['properties']) != dict):
+ print('WARN: Invalid feature in GeoJSON output', file=sys.stderr)
+ continue
+ properties = feat['properties']
+ if 'DyntaxaTaxonId' not in properties.keys() or properties['DyntaxaTaxonId'] is None:
+ print('WARN: Feature lacks taxon ID', file=sys.stderr)
+ continue
+
+ tid = properties['DyntaxaTaxonId']
+ for k, taxonList in taxonLists.items():
+ v = (tid in taxonList)
+ if k in properties.keys() and properties[k] != v:
+ print(f'WARN: #{tid} {k}: {properties[k]} → {v}', file=sys.stderr)
+ properties[k] = v
+
+ if tid in taxonRedlistCategories.keys():
+ k = 'RedlistCategory'
+ v = taxonRedlistCategories[tid]
+ if k in properties.keys() and properties[k] != v:
+ print(f'WARN: #{tid} {k}: {properties[k]} → {v}', file=sys.stderr)
+ properties[k] = v
+
+ # TODO generate GPKG instead and reproject to EPSG:3006
+ path = projectHome.joinpath('fynd.geojson')
+ with path.open(mode='w') as fp:
+ json.dump(obs, fp, indent=2, ensure_ascii=False)
+
+ if projectInstance is not None:
+ layer = QgsVectorLayer(path.as_posix() + '''|subset="Kingdom" IN ('Fungi', 'Plantae') AND "IsPositiveObservation" AND "IsNaturalOccurrence" AND "CoordinateUncertaintyInMeters" <= 250''', path.stem, 'ogr')
+ if not layer.isValid():
+ raise Exception(f'ERROR: {path}: failed to load in QGIS')
+ if 'QGIS' in config.keys() and 'style' in config['QGIS']:
+ style = Path(config['QGIS']['style']).expanduser()
+ layer.loadNamedStyle(style.as_posix())
+ layer.setReadOnly(True)
+ layer.setFlags(QgsMapLayer.Identifiable | QgsMapLayer.Searchable)
+ projectInstance.addMapLayer(layer)
+ layerTreeRoot.findLayer(layer.id()).setItemVisibilityChecked(True)
+
def getTaxonLists():
resp = requests.get(
artDataBankenURL + '/species-observation-system/v1/TaxonLists?cultureCode=en-US',
@@ -442,7 +514,101 @@ geograficsFilter = {
'considerDisturbanceRadius': True
}
taxonLists, taxonRedlistCategories = getTaxonLists()
-exit()
+
+# https://github.com/biodiversitydata-se/SOS/blob/master/Docs/SearchFilter.md
+searchFilter = {
+ 'geographics': geograficsFilter,
+ 'determinationFilter': 'NoFilter',
+ 'notRecoveredFilter': 'NoFilter',
+ 'occurrenceStatus': 'BothPresentAndAbsent',
+ 'verificationStatus': 'BothVerifiedAndNotVerified',
+ 'output': {
+ 'fields': [
+ # https://github.com/biodiversitydata-se/SOS/blob/master/Docs/SearchFilter.md#fields
+ # https://github.com/biodiversitydata-se/SOS/blob/master/Docs/Observation.md
+ 'dataProviderId',
+ 'datasetName',
+ #'basisOfRecord',
+ 'rightsHolder',
+
+ 'modified',
+ 'sensitive',
+ 'measurementOrFacts',
+ 'projects',
+
+ 'occurrence.occurrenceId',
+ 'occurrence.occurrenceRemarks',
+ 'occurrence.recordedBy',
+ 'occurrence.reportedBy',
+ 'occurrence.reportedDate',
+ 'occurrence.occurrenceStatus',
+ 'occurrence.activity',
+ 'occurrence.behavior',
+ 'occurrence.biotope',
+ 'occurrence.biotopeDescription',
+ 'occurrence.lifeStage',
+ 'occurrence.reproductiveCondition',
+ 'occurrence.sex',
+ 'occurrence.associatedMedia',
+ 'occurrence.associatedReferences',
+ 'occurrence.individualCount',
+ 'occurrence.organismQuantityInt',
+ 'occurrence.organismQuantityUnit',
+ 'occurrence.sensitivityCategory',
+ 'occurrence.isNaturalOccurrence',
+ 'occurrence.isNeverFoundObservation',
+ 'occurrence.isNotRediscoveredObservation',
+ 'occurrence.isPositiveObservation',
+ 'occurrence.substrate.description',
+ 'occurrence.substrate.name',
+ 'occurrence.length',
+ 'occurrence.weight',
+ 'occurrence.url',
+
+ 'event.startDate',
+ 'event.endDate',
+ 'event.habitat',
+ 'event.eventRemarks',
+ 'event.discoveryMethod',
+ 'event.measurementOrFacts',
+ 'event.fieldNotes',
+
+ 'identification.verified',
+ 'identification.uncertainIdentification',
+ 'identification.verificationStatus',
+ 'identification.confirmedBy',
+ 'identification.confirmedDate',
+ 'identification.identifiedBy',
+ 'identification.dateIdentified',
+ 'identification.verifiedBy',
+ 'identification.determinationMethod',
+ 'identification.identificationRemarks',
+
+ 'location.locality',
+ 'location.county',
+ 'location.municipality',
+ 'location.coordinateUncertaintyInMeters',
+
+ 'taxon.id',
+ 'taxon.scientificName',
+ 'taxon.scientificNameAuthorship',
+ 'taxon.vernacularName',
+ 'taxon.genus',
+ 'taxon.family',
+ 'taxon.order',
+ 'taxon.class',
+ 'taxon.phylum',
+ 'taxon.kingdom',
+
+ 'taxon.attributes.taxonCategory',
+ 'taxon.attributes.organismGroup',
+
+ 'taxon.attributes.redlistCategory',
+ ]
+ }
+}
+
+getObservations(taxonLists, taxonRedlistCategories, searchFilter)
topo_maps = ['Topografi 10', 'Topografi 50', 'Topografi 100']
if projectInstance is not None: