A modern Python client library for accessing Geological Survey of Sweden groundwater data APIs with type safety and pandas integration
Project description
SGU Client
A modern Python client library for accessing Geological Survey of Sweden (SGU) groundwater data APIs with type safety and pandas integration.
This package is not affiliated with or endorsed by SGU.
Features
- Type-safe: Full type hints with Pydantic validation
- Pandas integration: Convert data to DataFrames or Series with optional pandas dependency
- Friendly shortcuts: Convenience functions to access stations by names, modeled levels by coordinates, and much more.
Get going with your analysis in just a few lines of code:
from sgu_client import SGUClient
with SGUClient() as client:
measurements = client.levels.observed.get_measurements_by_name(station_id="95_2")
df = measurements.to_dataframe()
# ... rest of your awesome workflow
Installation
Using uv
# basic installation
uv add sgu-client
# with pandas support for dataframe conversion
uv add "sgu-client[recommended]"
... or using pip
# basic installation
pip install sgu-client
# with pandas support for dataframe conversion
pip install "sgu-client[recommended]"
Usage
Initializing a client
from sgu_client import SGUClient
client = SGUClient()
# with custom configuration
from sgu_client import SGUConfig
config = SGUConfig(timeout=60, debug=True, max_retries=5)
client = SGUClient(config=config)
# as a context manager
with SGUClient() as client:
stations = client.levels.observed.get_stations(limit=10)
Observed groundwater levels
Access real-time and historical groundwater monitoring data from SGU's network of observation stations.
from sgu_client import SGUClient
from datetime import UTC, datetime
with SGUClient() as client:
# basic API endpoint usage
stations = client.levels.observed.get_stations(limit=50)
# with OGC API filters, like bbox of southern Sweden
stations = client.levels.observed.get_stations(
bbox=[12.0, 55.0, 16.0, 58.0],
limit=100
)
# convenience function to get station by name
station = client.levels.observed.get_station_by_name(
station_id="95_2" # or station_name="Lagga_2"
)
# or multiple stations by names
stations = client.levels.observed.get_stations_by_names(
station_id=["95_2", "101_1"] # or station_name=["Lagga_2", ...]
)
# convenience function to get measurements by station name
measurements = client.levels.observed.get_measurements_by_name(
station_id="95_2", # or station_name="Lagga_2"
limit=100
)
# or multiple stations by names
measurements = client.levels.observed.get_measurements_by_names(
station_id=["95_2", "101_1"], # or station_name=["Lagga_2", ...]
limit=100
)
# filter by datetime for faster responses
tmin = datetime(2020, 1, 1, tzinfo=UTC)
tmax = datetime(2021, 1, 1, tzinfo=UTC)
measurements = client.levels.observed.get_measurements_by_names(
station_id=["95_2"], tmin=tmin, tmax=tmax, limit=10
)
# responses that create lists of features can be converted to pandas DataFrames
measurements = client.levels.observed.get_measurements_by_names(
station_id=["95_2", "101_1"], # or station_name=["Lagga_2", ...]
limit=100
)
df = measurements.to_dataframe()
# or series
series = measurements.to_series() # defaults to 'water_level_masl_m' (head) column with datetime index
Modeled groundwater levels
Access modeled groundwater levels from SGU-HYPE.
from sgu_client import SGUClient
with SGUClient() as client:
# basic API endpoint usage
areas = client.levels.modeled.get_areas(limit=10)
# with OGC API filters, like bbox of southern Sweden
areas = client.levels.modeled.get_areas(
bbox=[12.0, 55.0, 16.0, 58.0],
limit=20
)
# get a specific area by ID
area = client.levels.modeled.get_area("omraden.30125")
print(f"Area ID: {area.properties.area_id}")
print(f"Geometry: {area.geometry.type}")
# convenience function to get levels for a specific area
levels = client.levels.modeled.get_levels_by_area(30125, limit=10)
# or multiple areas by IDs
levels = client.levels.modeled.get_levels_by_areas(
area_ids=[30125, 30126],
limit=50
)
# convenience function to get levels by coordinates
levels = client.levels.modeled.get_levels_by_coords(
lat=57.7089,
lon=11.9746,
limit=10
)
# responses that create lists of features can be converted to pandas DataFrames
levels = client.levels.modeled.get_levels_by_areas(
area_ids=[30125, 30126],
limit=50
)
df = levels.to_dataframe()
# or series
series = levels.to_series() # defaults to 'relative_level_small_resources' column with datetime index
Groundwater Chemistry
Access groundwater chemistry data including sampling sites and chemical analysis results.
from sgu_client import SGUClient
from datetime import UTC, datetime
with SGUClient() as client:
# basic API endpoint usage
sites = client.chemistry.get_sampling_sites(limit=50)
# with OGC API filters, like bbox of southern Sweden
sites = client.chemistry.get_sampling_sites(
bbox=[12.0, 55.0, 16.0, 58.0],
limit=100
)
# convenience function to get site by name
site = client.chemistry.get_sampling_site_by_name(
station_id="10001_1" # or site_name="Västra Kärrstorp"
)
# or multiple sites by names
sites = client.chemistry.get_sampling_sites_by_names(
station_id=["10001_1", "10002_1"] # or site_name=["Västra Kärrstorp", ...]
)
# get chemical analysis results
results = client.chemistry.get_analysis_results(limit=100)
# convenience function to get results for a specific site
results = client.chemistry.get_results_by_site(
station_id="1000_1", # or site_name="Ringarum_1"
limit=100
)
# or multiple sites by names
results = client.chemistry.get_results_by_sites(
station_id=["1000_1", "1001_2"], # or site_name=["Ringarum_1", ...]
limit=100
)
# filter by datetime for faster responses
tmin = datetime(2020, 1, 1, tzinfo=UTC)
tmax = datetime(2021, 1, 1, tzinfo=UTC)
results = client.chemistry.get_results_by_site(
station_id="1000_1", tmin=tmin, tmax=tmax, limit=500
)
# filter by chemical parameter
ph_results = client.chemistry.get_results_by_parameter(
parameter="PH",
station_id="1000_1",
tmin=tmin,
tmax=tmax
)
# responses that create lists of features can be converted to pandas DataFrames
results = client.chemistry.get_results_by_site(
station_id="1000_1",
limit=1000
)
df = results.to_dataframe()
# or series
series = results.to_series() # defaults to 'measurement_value' column with sampling_date index
# or pivot by parameter for multi-parameter analysis
df_pivot = results.pivot_by_parameter() # creates columns like 'PH', 'NITRATE', 'KLORID', etc.
Working with Typed Data
All responses are fully typed with Pydantic models:
from sgu_client import SGUClient
client = SGUClient()
# Get stations with full type safety
stations = client.levels.observed.get_stations(limit=5)
for station in stations.features:
# All properties are typed and documented
print(f"Station: {station.properties.station_name}")
print(f"Municipality: {station.properties.municipality}")
print(f"Coordinates: {station.geometry.coordinates}")
# Get measurements with automatic datetime parsing
measurements = client.levels.observed.get_measurements(limit=5)
for measurement in measurements.features:
props = measurement.properties
print(f"Date: {props.observation_datetime}") # Parsed datetime object
print(f"Level: {props.water_level_masl_m} m above sea level")
API Reference
SGUClient
The main client class providing access to all SGU APIs.
levels.observed- Observed groundwater level measurementslevels.modeled- Modeled groundwater levels from SGU-HYPEchemistry- Groundwater chemistry sampling sites and analysis results
Configuration
from sgu_client import SGUConfig
config = SGUConfig(
timeout=30, # Request timeout in seconds
max_retries=3, # Maximum retry attempts
debug=False # Enable debug logging
)
Development
We recommend using uv for development:
# Clone the repository
git clone https://github.com/officialankan/sgu-client.git
cd sgu-client
# Install dependencies and sync environment
uv sync --all-extras
# Run tests
uv run pytest
# Format and lint code
uv run ruff format
uv run ruff check --fix
Release Process
To release a new version:
- Create PR with your changes + version bump in
pyproject.toml - PR will be tested and published to TestPyPI for verification
- Once merged, the new version is automatically published to PyPI
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Roadmap
- Initial release with observed and modeled groundwater levels
- Add example notebooks and tutorials
- Add support for groundwater chemistry API
- Add support for geological data API
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Sveriges geologiska undersökning (SGU) for providing open access to groundwater data
- Built with uv, Pydantic, and requests
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sgu_client-0.4.0.tar.gz.
File metadata
- Download URL: sgu_client-0.4.0.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93077be04c1d5159de5818a8f4654ddf32de85747725d283042ed9ca3bbdc0c9
|
|
| MD5 |
b08203bd2265fe9f0d54a62cc2863637
|
|
| BLAKE2b-256 |
1156ba13cea181873851e63a8a897dc3ce7d940ff735efd16f873b51f22e58dc
|
Provenance
The following attestation bundles were made for sgu_client-0.4.0.tar.gz:
Publisher:
ci-cd.yml on officialankan/sgu-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sgu_client-0.4.0.tar.gz -
Subject digest:
93077be04c1d5159de5818a8f4654ddf32de85747725d283042ed9ca3bbdc0c9 - Sigstore transparency entry: 697933980
- Sigstore integration time:
-
Permalink:
officialankan/sgu-client@467f4bb44e0504ed478666b40057d644e3282c33 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/officialankan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@467f4bb44e0504ed478666b40057d644e3282c33 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file sgu_client-0.4.0-py3-none-any.whl.
File metadata
- Download URL: sgu_client-0.4.0-py3-none-any.whl
- Upload date:
- Size: 33.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04dc017edda2c348a2f59449ee4b567c47419933e9c9dc6fe488369f618aa987
|
|
| MD5 |
485eba9736123fa2978820df93c08db6
|
|
| BLAKE2b-256 |
3870e429929472d45e766486e1b67386a715cbeeebe47d6d941cfbd579d45e56
|
Provenance
The following attestation bundles were made for sgu_client-0.4.0-py3-none-any.whl:
Publisher:
ci-cd.yml on officialankan/sgu-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sgu_client-0.4.0-py3-none-any.whl -
Subject digest:
04dc017edda2c348a2f59449ee4b567c47419933e9c9dc6fe488369f618aa987 - Sigstore transparency entry: 697934012
- Sigstore integration time:
-
Permalink:
officialankan/sgu-client@467f4bb44e0504ed478666b40057d644e3282c33 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/officialankan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@467f4bb44e0504ed478666b40057d644e3282c33 -
Trigger Event:
pull_request
-
Statement type: