aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2023-09-27 14:29:31 +0200
committerGuilhem Moulin <guilhem@fripost.org>2023-09-27 14:55:58 +0200
commit06dc49bc98e988cfa13c9ce66655fb10813db09f (patch)
treec431cbd0394fcb9eca339f1fd5b2e300c765101e
parent264da16bce66c6be8893cb972edf712e9f514eaa (diff)
Get taxon lists.
-rwxr-xr-xgis-observation-map99
1 files changed, 99 insertions, 0 deletions
diff --git a/gis-observation-map b/gis-observation-map
index 7e97fb9..9c478c7 100755
--- a/gis-observation-map
+++ b/gis-observation-map
@@ -21,6 +21,10 @@
import argparse
import sys
import json
+import requests
+import configparser
+from requests.exceptions import HTTPError
+from xdg import xdg_config_home
from pathlib import Path
from osgeo import gdal, ogr, osr
gdal.UseExceptions()
@@ -46,8 +50,10 @@ target_srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)
gpkg_drv = ogr.GetDriverByName('GPKG')
geojson_drv = ogr.GetDriverByName('GeoJSON')
+programName = 'gis-observation-map'
parser = argparse.ArgumentParser(
description='Create a QGIS project with observations from Artdatabanken.',
+ prog = programName,
usage='''%(prog)s --project-home=DIR --project-name=NAME {--geometry=FILE|--point=X,Y} ...
%(prog)s {--geometry=FILE|--point=X,Y} ...'''
)
@@ -60,6 +66,9 @@ parser.add_argument('--point', nargs='*', default=[], help=f'Coordinates of inte
args = parser.parse_args()
+config = configparser.ConfigParser()
+config.read(Path(xdg_config_home()).joinpath(programName).joinpath('config'))
+
if args.project_home is not None and args.project_name is not None:
QgsApplication.setPrefixPath('/usr/bin/qgis', True)
qgs = QgsApplication([], False)
@@ -305,6 +314,96 @@ def geometricFilter(geometries):
return myGeometries
+artDataBankenURL = 'https://api.artdatabanken.se'
+artDataBankenHeaders = {
+ 'X-Api-Version': '1.5',
+ 'X-Requesting-System': '',
+ # https://github.com/biodiversitydata-se/SOS/blob/master/Docs/Authentication.md
+ 'Ocp-Apim-Subscription-Key': config['ArtDataBanken']['Subscription-Key']
+}
+def getTaxonLists():
+ resp = requests.get(
+ artDataBankenURL + '/species-observation-system/v1/TaxonLists?cultureCode=en-US',
+ headers=artDataBankenHeaders
+ )
+ resp.raise_for_status()
+ taxonLists = resp.json()
+ #print(json.dumps(taxonLists, indent=2))
+ taxonLists2 = {}
+
+ # https://github.com/biodiversitydata-se/SOS/blob/master/Src/SOS.lib/Resources/TaxonLists.json
+ # https://artfakta.se/artinformation/taxa
+ getTaxonList(taxonLists, taxonLists2, 'ProtectedByLaw', 'Protected by law species')
+ getTaxonList(taxonLists, taxonLists2, 'TaxonIsSignalSpecie', 'Signal species')
+
+ getTaxonList(taxonLists, taxonLists2, 'TaxonIsInvasive', 'Invasive species')
+ getTaxonList(taxonLists, taxonLists2, 'TaxonIsInvasiveInSweden', 'Invasive species in Sweden')
+ getTaxonList(taxonLists, taxonLists2, 'TaxonIsInvasiveEuRegulation', 'EU regulation 1143/2014')
+
+ getTaxonList(taxonLists, taxonLists2, 'Natura2000HabitatsDirective', 'Habitats directive species')
+ getTaxonList(taxonLists, taxonLists2, 'Natura2000HabitatsDirectiveArticle2', 'Habitats directive Annex 2')
+ getTaxonList(taxonLists, taxonLists2, 'Natura2000HabitatsDirectiveArticle2PrioritySpecie', 'Habitats directive Annex 2, priority species')
+ getTaxonList(taxonLists, taxonLists2, 'Natura2000HabitatsDirectiveArticle4', 'Habitats directive Annex 4')
+ getTaxonList(taxonLists, taxonLists2, 'Natura2000HabitatsDirectiveArticle5', 'Habitats directive Annex 5')
+
+ # sanity check
+ directives = [
+ 'Natura2000HabitatsDirectiveArticle2',
+ 'Natura2000HabitatsDirectiveArticle2PrioritySpecie',
+ 'Natura2000HabitatsDirectiveArticle4',
+ 'Natura2000HabitatsDirectiveArticle5'
+ ]
+ d0 = 'Natura2000HabitatsDirective'
+ for i in taxonLists2[d0]:
+ if not any(map(lambda d: i in taxonLists2[d], directives)):
+ raise Exception(f'missing taxon #{i} (in {d0}) from directives {",".join(directives)}')
+ for d in directives:
+ for i in taxonLists2[d]:
+ if not i in taxonLists2[d0]:
+ raise Exception(f'missing taxon #{i} (in {d}) from {d0}')
+ for i in taxonLists2['Natura2000HabitatsDirectiveArticle2PrioritySpecie']:
+ if not i in taxonLists2['Natura2000HabitatsDirectiveArticle2']:
+ raise Exception(f'missing taxon #{i} (in Natura2000HabitatsDirectiveArticle2PrioritySpecie) from Natura2000HabitatsDirectiveArticle2')
+
+ getTaxonList(taxonLists, taxonLists2, 'BirdDirective', 'Birds Directive')
+ getTaxonList(taxonLists, taxonLists2, 'BirdDirectiveArticle1', 'Birds directive - Annex 1')
+ getTaxonList(taxonLists, taxonLists2, 'BirdDirectiveArticle2', 'Birds directive - Annex 2')
+ getTaxonList(taxonLists, taxonLists2, 'TaxonIsPriorityBird', 'Priority birds')
+
+ directives = ['BirdDirectiveArticle1', 'BirdDirectiveArticle2']
+ d0 = 'BirdDirective'
+ #for i in taxonLists2[d0]:
+ # if not any(map(lambda d: i in taxonLists2[d], directives)):
+ # raise Exception(f'missing taxon #{i} (in {d0}) from directives {",".join(directives)}')
+ for d in directives:
+ for i in taxonLists2[d]:
+ if not i in taxonLists2[d0]:
+ raise Exception(f'missing taxon #{i} (in {d}) from {d0}')
+
+ return taxonLists2
+
+def getTaxonList(taxonLists, taxonLists2, key, name):
+ i = None
+ for t in taxonLists:
+ if t['name'] == name:
+ if i is not None:
+ raise Exception(f'multiple results found for taxon list "{name}"')
+ i = t['id']
+ if i is None:
+ raise Exception(f'no found for taxon list "{name}"')
+
+ resp = requests.get(
+ artDataBankenURL + f'/species-observation-system/v1/TaxonLists/{i}/Taxa',
+ headers=artDataBankenHeaders
+ )
+ resp.raise_for_status()
+ resp = resp.json()
+ if type(resp) != list:
+ raise Exception(f'expected list, got {type(resp)}')
+ taxonLists2[key] = {r['id'] for r in resp}
+
+taxonLists = getTaxonLists()
+
geograficsFilter = {
'geometries': geometricFilter(geometries),
#'maxAccuracy': 5000,