Groundwater Chemistry API#
The groundwater chemistry API provides access to water quality measurements from monitoring stations, including chemical composition, pH, conductivity, and other parameters.
Overview#
The chemistry API is accessed through client.chemistry and provides methods to query chemical measurements from groundwater monitoring stations.
Quick Example:
from sgu_client import SGUClient
client = SGUClient()
# Get chemistry measurements
measurements = client.chemistry.get_measurements(
bbox=[12.0, 55.0, 16.0, 58.0],
datetime="2023-01-01/2024-01-01",
limit=100
)
# Get stations with chemistry data
stations = client.chemistry.get_stations(limit=50)
# Convert to pandas DataFrame for analysis
df = measurements.to_dataframe()
print(df[['observation_date', 'parameter', 'value', 'unit']].head())
Chemistry Client#
The GroundwaterChemistryClient provides methods to query groundwater chemistry data.
Key Methods:
get_measurements()- Retrieve chemistry measurementsget_stations()- Retrieve stations with chemistry dataget_measurement_by_name()- Find measurements for a specific station
Filtering Options:
bbox: Spatial filter (bounding box)
datetime: Temporal filter (ISO 8601 datetime or interval)
filter: CQL filter expression for parameter-specific queries
limit: Maximum number of results to return
Common Parameters:
The chemistry API tracks various water quality parameters including:
pH levels
Electrical conductivity
Major ions (Ca, Mg, Na, K, Cl, SO4, HCO3)
Nutrients (NO3, NH4, PO4)
Trace elements
Dissolved gases
Groundwater chemistry client endpoints.
- class sgu_client.client.chemistry.chemistry.GroundwaterChemistryClient(base_client)[source]#
Bases:
objectClient for groundwater chemistry-related SGU API endpoints.
- Parameters:
base_client (
BaseClient)
- BASE_PATH = 'collections'#
- CHEMISTRY_BASE_URL = 'https://api.sgu.se/oppnadata/grundvattenkvalitet-analysresultat-provplatser/ogc/features/v1/'#
- __init__(base_client)[source]#
Initialize groundwater chemistry client.
- Parameters:
base_client (
BaseClient) – Base HTTP client instance
- get_sampling_sites(bbox=None, datetime=None, limit=None, filter_expr=None, sortby=None, **kwargs)[source]#
Get groundwater chemistry sampling sites. This method is used internally by convenience functions like `get_sampling_site_by_name() by constructing filter expressions. A user may also do this, but readability is greater when using the built-in convenience functions.
- Parameters:
bbox (
list[float] |None) – Bounding box as [min_lon, min_lat, max_lon, max_lat]datetime (
str|None) – Date/time filter (RFC 3339 format or interval)limit (
int|None) – Maximum number of features to return (automatically paginated if needed)filter_expr (
str|None) – CQL filter expressionsortby (
list[str] |None) – List of sort expressions (e.g., [‘+name’, ‘-date’])**kwargs (
Any) – Additional query parameters
- Return type:
- Returns:
Typed collection of groundwater chemistry sampling sites
- get_sampling_site(site_id)[source]#
Get a specific groundwater chemistry sampling site by ID. This endpoint is provided by the OGC API but likely not used by any user.
- Parameters:
site_id (
str) – Site identifier- Return type:
- Returns:
Typed groundwater chemistry sampling site
- Raises:
ValueError – If site not found or multiple sites returned
- get_sampling_site_by_name(site_id=None, site_name=None, **kwargs)[source]#
Convenience function to get a sampling site by name (‘site_id’ or ‘site_name’).
- Parameters:
site_id (
str|None) – Site identifier (maps to ‘platsbeteckning’ in API)site_name (
str|None) – Site name (maps to ‘provplatsnamn’ in API)**kwargs (
Any) – Additional query parameters (e.g., limit)
- Return type:
- Returns:
Typed groundwater chemistry sampling site
- Raises:
ValueError – If neither parameter is provided, both are provided, or if multiple sites are found
Example
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> # find site by id >>> site = client.chemistry.get_sampling_site_by_name(site_id="10001_1") >>> >>> # find site by name >>> site = client.chemistry.get_sampling_site_by_name( ... site_name="Ringarum_1" ... ) >>> print(site.properties.municipality)
- get_sampling_sites_by_names(site_id=None, site_name=None, **kwargs)[source]#
Convenience function to get multiple sampling sites by name (‘site_id’ or ‘site_name’).
- Parameters:
site_id (
list[str] |None) – List of site identifiers (maps to ‘platsbeteckning’ in API)site_name (
list[str] |None) – List of site names (maps to ‘provplatsnamn’ in API)**kwargs (
Any) – Additional query parameters (e.g., limit)
- Return type:
- Returns:
Typed collection of groundwater chemistry sampling sites
- Raises:
ValueError – If neither parameter is provided or both are provided
Example
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> # get multiple sampling sites by their IDs >>> sites = client.chemistry.get_sampling_sites_by_names( ... site_id=["10001_1", "10002_1", "10003_1"] ... ) >>> for site in sites.features: ... print(f"{site.properties.station_id}: {site.properties.municipality}")
- get_analysis_results(bbox=None, datetime=None, limit=None, filter_expr=None, sortby=None, **kwargs)[source]#
Get groundwater chemistry analysis results. This method is used internally by convenience functions like `get_results_by_site() by constructing filter expressions. A user may also do this, but readability is greater when using the built-in convenience functions.
- Parameters:
bbox (
list[float] |None) – Bounding box as [min_lon, min_lat, max_lon, max_lat]datetime (
str|None) – Date/time filter (RFC 3339 format or interval)limit (
int|None) – Maximum number of features to return (automatically paginated if needed)filter_expr (
str|None) – CQL filter expressionsortby (
list[str] |None) – List of sort expressions (e.g., [‘+date’, ‘-value’])**kwargs (
Any) – Additional query parameters
- Return type:
- Returns:
Typed collection of groundwater chemistry analysis results
- get_analysis_result(result_id)[source]#
Get a specific groundwater chemistry analysis result by ID. This endpoint is provided by the OGC API but likely not used by any user.
- Parameters:
result_id (
str) – Result identifier- Return type:
- Returns:
Typed groundwater chemistry analysis result
- Raises:
ValueError – If result not found or multiple results returned
- get_results_by_site(site_id=None, site_name=None, tmin=None, tmax=None, limit=None, **kwargs)[source]#
Get analysis results for a specific site by name with optional time filtering.
- Parameters:
site_id (
str|None) – Site identifier (maps to ‘platsbeteckning’ in API)site_name (
str|None) – Site name (maps to ‘provplatsnamn’ in API)tmin (
str|datetime|None) – Start time (ISO string or datetime object)tmax (
str|datetime|None) – End time (ISO string or datetime object)limit (
int|None) – Maximum number of results to return**kwargs (
Any) – Additional query parameters
- Return type:
- Returns:
Typed collection of groundwater chemistry analysis results
- Raises:
ValueError – If neither or both name parameters are provided, or if site lookup fails
Example
>>> from sgu_client import SGUClient >>> from datetime import datetime, timezone >>> client = SGUClient() >>> >>> # get all results for a site >>> results = client.chemistry.get_results_by_site( ... site_id="10001_1", ... limit=100 ... ) >>> >>> # get results with time filtering >>> results = client.chemistry.get_results_by_site( ... site_id="10001_1", ... tmin=datetime(2020, 1, 1, tzinfo=timezone.utc), ... tmax=datetime(2021, 1, 1, tzinfo=timezone.utc) ... )
- get_results_by_sites(site_id=None, site_name=None, tmin=None, tmax=None, limit=None, **kwargs)[source]#
Get analysis results for multiple sites by name with optional time filtering.
- Parameters:
site_id (
list[str] |None) – List of station identifiers (maps to ‘platsbeteckning’ in API)site_name (
list[str] |None) – List of site names (maps to ‘provplatsnamn’ in API)tmin (
str|datetime|None) – Start time (ISO string or datetime object)tmax (
str|datetime|None) – End time (ISO string or datetime object)limit (
int|None) – Maximum number of results to return**kwargs (
Any) – Additional query parameters
- Return type:
- Returns:
Typed collection of groundwater chemistry analysis results
- Raises:
ValueError – If neither or both name parameters are provided, or if site lookup fails
Example
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> # get results for multiple sites >>> results = client.chemistry.get_results_by_sites( ... station_id=["10001_1", "10002_1"], ... tmin="2020-01-01T00:00:00Z", ... tmax="2021-01-01T00:00:00Z", ... limit=1000 ... ) >>> print(f"Found {len(results.features)} analysis results")
- get_results_by_parameter(parameter, site_id=None, tmin=None, tmax=None, limit=None, **kwargs)[source]#
Get analysis results filtered by chemical parameter (e.g., pH, nitrate).
This convenience method makes it easy to retrieve all measurements for a specific chemical parameter, optionally filtered by site and time range.
- Parameters:
parameter (
str) – Parameter short name (e.g., ‘PH’, ‘NITRATE’, ‘KLORID’)site_id (
str|list[str] |None) – Optional station identifier(s) to filter bytmin (
str|datetime|None) – Start time (ISO string or datetime object)tmax (
str|datetime|None) – End time (ISO string or datetime object)limit (
int|None) – Maximum number of results to return**kwargs (
Any) – Additional query parameters
- Return type:
- Returns:
Typed collection of groundwater chemistry analysis results
Example
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> # get all pH measurements >>> results = client.chemistry.get_results_by_parameter( ... parameter="PH", ... limit=1000 ... ) >>> >>> # get pH measurements for a specific site >>> results = client.chemistry.get_results_by_parameter( ... parameter="PH", ... site_id="10001_1", ... tmin="2020-01-01", ... tmax="2021-01-01" ... ) >>> >>> # ... or multiple sites >>> results = client.chemistry.get_results_by_parameter( ... parameter="PH", ... site_id=["10001_1", "10002_1"] ... )
Chemistry Data Models#
The chemistry data uses typed Pydantic models for measurements and station metadata.
Pydantic models for groundwater chemistry data from SGU API.
- class sgu_client.models.chemistry.SamplingSiteProperties(**data)[source]#
Bases:
SGUBaseModelProperties for a groundwater chemistry sampling site.
- Parameters:
data (
Any)
-
station_id:
str|None#
-
site_name:
str|None#
-
national_site_id:
int|None#
-
eu_station_code:
str|None#
-
eu_groundwater_body:
str|None#
-
site_type_code:
str|None#
-
site_type_description:
str|None#
-
site_category_code:
str|None#
-
site_category_description:
str|None#
-
north_coordinate:
float|None#
-
east_coordinate:
float|None#
-
positioning_method_code:
str|None#
-
positioning_method_description:
str|None#
-
position_quality_code:
str|None#
-
position_quality_description:
str|None#
-
county_code:
str|None#
-
county:
str|None#
-
municipality_code:
str|None#
-
municipality:
str|None#
-
region_code:
str|None#
-
region_description:
str|None#
-
water_district_code:
str|None#
-
water_district_description:
str|None#
-
reference_level:
float|None#
-
elevation_system:
str|None#
-
well_depth:
float|None#
-
well_depth_qualifier:
str|None#
-
filter_depth_top:
float|None#
-
filter_depth_bottom:
float|None#
-
filter_depth_qualifier:
str|None#
-
aquifer_code:
str|None#
-
aquifer_description:
str|None#
-
soil_genesis_code:
str|None#
-
soil_genesis_description:
str|None#
-
rock_type_code:
str|None#
-
rock_type_description:
str|None#
-
established_date:
str|None#
-
decommissioned_date:
str|None#
-
sample_count:
int|None#
-
program_affiliation:
str|None#
-
national_monitoring:
str|None#
-
regional_monitoring:
str|None#
-
local_monitoring:
str|None#
-
symbol:
str|None#
-
analyses_csv_url:
str|None#
-
analyses_json_url:
str|None#
- property established_datetime: datetime | None#
Parse establishment date as datetime object.
- property decommissioned_datetime: datetime | None#
Parse decommissioning date as datetime object.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class sgu_client.models.chemistry.SamplingSite(**data)[source]#
Bases:
SGUBaseModelA groundwater chemistry sampling site (GeoJSON Feature).
- Parameters:
data (
Any)
-
type:
Literal['Feature']#
-
id:
str#
-
geometry:
Point|MultiPoint|LineString|Polygon|MultiPolygon|None#
-
properties:
SamplingSiteProperties#
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class sgu_client.models.chemistry.AnalysisResultProperties(**data)[source]#
Bases:
SGUBaseModelProperties for a groundwater chemistry analysis result.
- Parameters:
data (
Any)
-
station_id:
str|None#
-
national_site_id:
int|None#
-
county_code:
str|None#
-
sample_id:
str|None#
-
sample_type:
str|None#
-
delivery_id:
str|None#
-
program_name:
str|None#
-
program_id:
str|None#
-
monitoring_manual:
str|None#
-
sampling_date:
str|None#
-
submission_date:
str|None#
-
parameter_name:
str|None#
-
parameter_short_name:
str|None#
-
parameter_sequence_number:
int|None#
-
water_preparation:
str|None#
-
sample_preparation:
str|None#
-
laboratory:
str|None#
-
method:
str|None#
-
reporting_limit:
float|None#
-
detection_limit:
float|None#
-
measurement_value_annotation:
str|None#
-
measurement_value:
float|None#
-
measurement_value_span:
str|None#
-
measurement_value_text:
str|None#
-
unit:
str|None#
-
measurement_uncertainty:
str|None#
-
last_updated:
str|None#
-
row_number:
int|None#
- property sampling_datetime: datetime | None#
Parse sampling date as datetime object.
- property submission_datetime: datetime | None#
Parse submission date as datetime object.
- property last_updated_datetime: datetime | None#
Parse last update as datetime object.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class sgu_client.models.chemistry.AnalysisResult(**data)[source]#
Bases:
SGUBaseModelA groundwater chemistry analysis result (GeoJSON Feature).
- Parameters:
data (
Any)
-
type:
Literal['Feature']#
-
id:
str#
-
geometry:
Point|MultiPoint|LineString|Polygon|MultiPolygon|None#
-
properties:
AnalysisResultProperties#
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class sgu_client.models.chemistry.SamplingSiteCollection(**data)[source]#
Bases:
SGUResponseCollection of groundwater chemistry sampling sites (GeoJSON FeatureCollection).
- Parameters:
data (
Any)
-
type:
Literal['FeatureCollection']#
-
features:
list[SamplingSite]#
-
totalFeatures:
int|None#
-
numberMatched:
int|None#
-
numberReturned:
int|None#
-
timeStamp:
str|None#
- to_dataframe(**kwargs) pd.DataFrame#
Convert to pandas DataFrame with flattened sampling site properties.
- Returns:
DataFrame containing sampling site data with parsed datetime columns.
Examples
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> sites = client.chemistry.get_sampling_sites(limit=10) >>> df = sites.to_dataframe() >>> >>> # dataFrame includes site properties with datetime parsing >>> print(df[['station_id', 'site_name', 'municipality', 'established_date', 'sample_count']].head()) >>> # established_date and decommissioned_date are parsed as datetime objects
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class sgu_client.models.chemistry.AnalysisResultCollection(**data)[source]#
Bases:
SGUResponseCollection of groundwater chemistry analysis results (GeoJSON FeatureCollection).
- Parameters:
data (
Any)
-
type:
Literal['FeatureCollection']#
-
features:
list[AnalysisResult]#
-
totalFeatures:
int|None#
-
numberMatched:
int|None#
-
numberReturned:
int|None#
-
timeStamp:
str|None#
- to_dataframe(**kwargs) pd.DataFrame#
Convert to pandas DataFrame with analysis result data.
- Parameters:
sort_by_date – Whether to sort the DataFrame by sampling date.
- Returns:
DataFrame containing analysis result data.
Examples
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> >>> results = client.chemistry.get_results_by_site(site_id="10001_1", limit=100) >>> df = results.to_dataframe() >>> >>> # dataFrame includes chemical analysis results with multiple datetime columns >>> print(df[['sampling_date', 'parameter_short_name', 'measurement_value', 'unit']].head()) >>> # sampling_date, submission_date, and last_update are all parsed as datetime objects
- to_series(**kwargs) pd.Series#
Convert to pandas Series with analysis result data.
- Parameters:
index – Column name to use as index. If None, sampling_date is used.
data – Column name to use as data. If None, measurement_value is used.
sort_by_date – Whether to sort the data by sampling date before creating the Series.
- Returns:
Series containing analysis result data.
Examples
>>> from sgu_client import SGUClient >>> client = SGUClient() >>> results = client.chemistry.get_results_by_site(site_id="10001_1", limit=100) >>> >>> # create time series with default columns (sampling_date, measurement_value) >>> series = results.to_series() >>> print(series.head()) >>> >>> # use custom columns - e.g., parameter names as data >>> series_params = results.to_series( ... index="sampling_date", ... data="parameter_short_name" ... )
- pivot_by_parameter(**kwargs) pd.DataFrame#
Pivot analysis results by parameter for easier time series analysis.
This creates a wide-format DataFrame where each chemical parameter becomes a column, making it easy to analyze multiple parameters over time.
- Parameters:
values – Column to use for values (default: ‘measurement_value’)
index – Column to use as index (default: ‘sampling_date’)
columns – Column to pivot into columns (default: ‘parameter_short_name’)
aggfunc – Aggregation function if there are duplicate index/column pairs (default: ‘mean’). Can be ‘mean’, ‘median’, ‘first’, ‘last’, etc.
- Returns:
Pivoted DataFrame with parameters as columns.
Example
>>> from sgu_client import SGUClient() >>> client = SGUClient() >>> >>> results = client.chemistry.get_results_by_site(site_id="10001_1") >>> df_pivot = results.pivot_by_parameter() >>> # now df_pivot has columns like 'PH', 'NITRATE', 'CHLORIDE', etc.
- model_config: ClassVar[ConfigDict] = {'extra': 'allow', 'use_enum_values': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
See Also#
Core API - Core client and configuration
Data Models - Base model infrastructure
Utilities - DataFrame conversion for chemistry analysis