Files
API-python-snacks/get_obs_from_artsdatabank.py
T

83 lines
2.1 KiB
Python

import requests
import pandas as pd
import numpy as np
from pyproj import Transformer
# create transformer once (faster if used repeatedly)
_transformer = Transformer.from_crs("EPSG:4326", "EPSG:3857", always_xy=True)
def main(lat, lon, radius_m,
n_vertices=15,
page_size=10000,
species_summary=False):
"""
Fetch Artsdatabanken observations inside a semicircular polygon.
Parameters
----------
lat : float
lon : float
radius_m : float
Radius in meters
n_vertices : int
Polygon vertices approximating the circle
page_size : int
species_summary : bool
If True, also return species counts
Returns
-------
pandas.DataFrame
(optional) pandas.Series with species counts
"""
# -------------------
# Build polygon
# -------------------
cx, cy = _transformer.transform(lon, lat)
angles = np.linspace(0, 2*np.pi, n_vertices, endpoint=False)
x = np.float32(cx + radius_m * np.cos(angles))
y = np.float32(cy + radius_m * np.sin(angles))
points = [f"{xi}+{yi}" for xi, yi in zip(x, y)]
points.append(points[0]) # close polygon
polygon = "POLYGON((" + ",".join(points) + "))"
# -------------------
# API request
# -------------------
url = (
"https://artskart.artsdatabanken.no/publicapi/api/observations/list/"
f"?gmWktPolygon={polygon}&page=0&pageSize={page_size}"
)
r = requests.get(url)
r.raise_for_status()
data = r.json()
if "Observations" not in data:
return pd.DataFrame()
# -------------------
# Dataframe creation
# -------------------
df = pd.json_normalize(data["Observations"])[
["Latitude", "Longitude", "Notes", "ScientificName", "ScientificNameId"]
]
df["Latitude"] = df["Latitude"].str.replace(",", ".").astype(float)
df["Longitude"] = df["Longitude"].str.replace(",", ".").astype(float)
if species_summary:
return df, df["ScientificName"].value_counts()
return df