vannmiljo
Skill6 starsChanged 5 months agoMITView on GitHub
Vannmiljo data pipeline — scrape water monitoring data from vannmiljo.miljodirektoratet.no, build GeoJSON, and ingest into ODP
In this repository9 other files it gives its agents.
- linkedinSkill
- mapbox-odp-mapsSkill
- nmdc-exploreSkill
- odp-data-consumeSkill
- odp-data-explorationSkill
- odp-data-ingestSkill
- odp-dataset-scoutSkill
- odp-stac-apiSkill
- scenario-analystSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 7
Use this skill when working with Vannmiljo (Norwegian water monitoring) data — scraping, GeoJSON building, or ingesting into ODP.
- Very specific: line 35
All Vannmiljo datasets share the same schema.
- Very specific: line 115
All Vannmiljo area ingest scripts follow the same pattern.
- Very specific: line 146
All other properties → cast to str or None
- Very specific: line 191
All Vannmiljo datasets belong to collection: 6a107394-4dfb-4095-96ea-6cd0607cb213
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Vannmiljo Data Pipeline Skill
Use this skill when working with Vannmiljo (Norwegian water monitoring) data — scraping, GeoJSON building, or ingesting into ODP.
Project Overview
The Vannmiljo project extracts water quality monitoring data from Miljodirektoratet's Vannmiljo database and ingests it into the Ocean Data Platform (ODP).
Pipeline: Vannmiljo web scraper → GeoJSON files → ODP datasets
Source: vannmiljo.miljodirektoratet.no Field documentation: vannmiljokoder.miljodirektoratet.no/files/Om_VMS_Registreringsfelt.htm
Project Structure
Vannmiljo/
├── geojson_builder.py # Builds GeoJSON from scraped Vannmiljo data
├── ingest_holmestrandsfjorden.py # Ingest script for Holmestrandsfjorden
├── test_column_metadata.py # Test script for ODP column metadata
├── input_polygons/ # GeoJSON polygons defining areas of interest
│ ├── holmestrandsfjorden.geojson
│ ├── fordefjorden.geojson
│ └── langoya.geojson
└── output/ # Generated GeoJSON files with measurements
└── holmestrandsfjorden_alle_stasjoner.geojsonPyArrow Schema for Vannmiljo Data
All Vannmiljo datasets share the same schema. All columns are pa.string() except water_location_id (int64). The id column is a generated UUID primary key.
import pyarrow as pa
VANNMILJO_SCHEMA = pa.schema([
pa.field("id", pa.string(), nullable=False),
pa.field("water_location_id", pa.int64(), nullable=True,
metadata={"description": "Unik ID for vannlokaliteten i Vannmiljo"}),
pa.field("water_location_code", pa.string(), nullable=True,
metadata={"description": "Kode som knytter registreringen til en bestemt vannlokalitet"}),
pa.field("station_name", pa.string(), nullable=True,
metadata={"description": "Navn på målestasjonen"}),
pa.field("station_description", pa.string(), nullable=True,
metadata={"description": "Beskrivelse av vannlokaliteten"}),
pa.field("act_info", pa.string(), nullable=True,
metadata={"description": "Aktivitetsinformasjon for stasjonen"}),
pa.field("faktaark_url", pa.string(), nullable=True,
metadata={"description": "URL til stasjonens faktaark i Vannmiljo"}),
pa.field("betegnelse", pa.string(), nullable=True,
metadata={"description": "Betegnelse for provetakingsaktiviteten"}),
pa.field("aktivitet", pa.string(), nullable=True,
metadata={"description": "Overvåkings- eller kartleggingsaktivitet registreringen tilhorer"}),
pa.field("oppdragsgiver", pa.string(), nullable=True,
metadata={"description": "Ansvarlig for anskaffelsen av overvåkingsoppdraget"}),
pa.field("oppdragstaker", pa.string(), nullable=True,
metadata={"description": "Utforer av overvåkingen"}),
pa.field("parameter_id", pa.string(), nullable=True,
metadata={"description": "ID for parameteren som er målt eller observert"}),
pa.field("parameter", pa.string(), nullable=True,
metadata={"description": "Navn på parameteren som er målt eller observert"}),
pa.field("cas_nr", pa.string(), nullable=True,
metadata={"description": "CAS-nummer for kjemisk komponent"}),
pa.field("medium", pa.string(), nullable=True,
metadata={"description": "Medium parameteren er målt i (vann, sediment, biota, partikler)"}),
pa.field("vitenskapelig_navn", pa.string(), nullable=True,
metadata={"description": "Vitenskapelig (latinsk) navn på art/takson"}),
pa.field("provetakingsmetode", pa.string(), nullable=True,
metadata={"description": "Standard provetakingsmetode benyttet"}),
pa.field("analysemetode", pa.string(), nullable=True,
metadata={"description": "Standard analysemetode benyttet"}),
pa.field("provenr", pa.string(), nullable=True,
metadata={"description": "Provenummer for replikate prover"}),
pa.field("filtrert_prove", pa.string(), nullable=True,
metadata={"description": "Om vannproven er filtrert gjennom 0,45 um filter"}),
pa.field("opprinnelse", pa.string(), nullable=True,
metadata={"description": "Opprinnelse for registreringen"}),
pa.field("provedato", pa.string(), nullable=True,
metadata={"description": "Tidspunkt for provetaking"}),
pa.field("operator", pa.string(), nullable=True,
metadata={"description": "Verdioperator: = (påvist), < (under grense), > (over område), ND (ikke påvist)"}),
pa.field("verdi", pa.string(), nullable=True,
metadata={"description": "Målt eller observert verdi"}),
pa.field("enhet", pa.string(), nullable=True,
metadata={"description": "Enhet for registrert verdi"}),
pa.field("listenavn", pa.string(), nullable=True,
metadata={"description": "Navn på verdilisten parameteren tilhorer"}),
pa.field("ovre_dyp", pa.string(), nullable=True,
metadata={"description": "Ovre dybdegrense i meter (vann) eller centimeter (sediment)"}),
pa.field("nedre_dyp", pa.string(), nullable=True,
metadata={"description": "Nedre dybdegrense i meter (vann) eller centimeter (sediment)"}),
pa.field("deteksjonsgrense", pa.string(), nullable=True,
metadata={"description": "Deteksjonsgrensen til den aktuelle måleverdi"}),
pa.field("kvantifiseringsgrense", pa.string(), nullable=True,
metadata={"description": "Kvantifiseringsgrensen for den aktuelle måleverdi"}),
pa.field("kommentarer", pa.string(), nullable=True,
metadata={"description": "Kommentarer knyttet til registreringen (maks 2000 tegn)"}),
pa.field("sist_endret", pa.string(), nullable=True,
metadata={"description": "Dato for siste endring av registreringen"}),
pa.field("geometry", pa.string(), nullable=True,
metadata={
"isGeometry": "1",
"index": "1",
"description": "Punkt-geometri for målestasjonen (WKT)",
}),
])Ingest Script Template
All Vannmiljo area ingest scripts follow the same pattern. Use ingest_holmestrandsfjorden.py as the reference implementation.
Steps
- Check for existing dataset via
get_dataset_meta_by_name(), support--cleanflag - Load GeoJSON from
output/<area>_alle_stasjoner.geojson - Create dataset with descriptive name and Norwegian description
- Add to collection
6a107394-4dfb-4095-96ea-6cd0607cb213 - Upload raw GeoJSON as file via
ds.files.upload() - Create table with the shared
VANNMILJO_SCHEMA - Insert rows in batches of 5000, converting geometry to WKT
Geometry Conversion
GeoJSON Point [lon, lat] → WKT POINT (lon lat):
def point_to_wkt(geometry: dict | None) -> str | None:
if not geometry or geometry.get("type") != "Point":
return None
coords = geometry.get("coordinates")
if not coords or len(coords) < 2:
return None
return f"POINT ({coords[0]} {coords[1]})"Row Conversion
Each GeoJSON feature becomes a table row:
- Generate UUID for
id(primary key) water_location_id→ cast toint- All other properties → cast to
strorNone - Geometry → WKT via
point_to_wkt()
Column Descriptions Reference
Descriptions are sourced from Vannmiljo's official field documentation:
vannmiljokoder.miljodirektoratet.no/files/Om_VMS_Registreringsfelt.htm
| Column | Description |
| water_location_id | Unik ID for vannlokaliteten i Vannmiljo |
| water_location_code | Kode som knytter registreringen til en bestemt vannlokalitet |
| station_name | Navn på målestasjonen |
| station_description | Beskrivelse av vannlokaliteten |
| act_info | Aktivitetsinformasjon for stasjonen |
| faktaark_url | URL til stasjonens faktaark i Vannmiljo |
| betegnelse | Betegnelse for provetakingsaktiviteten |
| aktivitet | Overvåkings- eller kartleggingsaktivitet |
| oppdragsgiver | Ansvarlig for anskaffelsen av overvåkingsoppdraget |
| oppdragstaker | Utforer av overvåkingen |
| parameter_id | ID for parameteren som er målt eller observert |
| parameter | Navn på parameteren |
| cas_nr | CAS-nummer for kjemisk komponent |
| medium | Medium parameteren er målt i |
| vitenskapelig_navn | Vitenskapelig (latinsk) navn på art/takson |
| provetakingsmetode | Standard provetakingsmetode |
| analysemetode | Standard analysemetode |
| provenr | Provenummer for replikate prover |
| filtrert_prove | Om vannproven er filtrert gjennom 0,45 um filter |
| opprinnelse | Opprinnelse for registreringen |
| provedato | Tidspunkt for provetaking |
| operator | Verdioperator: =, <, >, ND |
| verdi | Målt eller observert verdi |
| enhet | Enhet for registrert verdi |
| listenavn | Navn på verdilisten |
| ovre_dyp | Ovre dybdegrense i meter/centimeter |
| nedre_dyp | Nedre dybdegrense i meter/centimeter |
| deteksjonsgrense | Deteksjonsgrensen til måleverdi |
| kvantifiseringsgrense | Kvantifiseringsgrensen for måleverdi |
| kommentarer | Kommentarer (maks 2000 tegn) |
| sist_endret | Dato for siste endring |
| geometry | Punkt-geometri (WKT) |
ODP Collection
All Vannmiljo datasets belong to collection: 6a107394-4dfb-4095-96ea-6cd0607cb213
Areas
| Area | Input Polygon | GeoJSON Output | ODP Dataset |
| Holmestrandsfjorden | input_polygons/holmestrandsfjorden.geojson | output/holmestrandsfjorden_alle_stasjoner.geojson | Vannmiljo Holmestrandsfjorden |
| Fordefjorden | input_polygons/fordefjorden.geojson | output/fordefjorden_alle_stasjoner.geojson | (pending) |
| Langoya | input_polygons/langoya.geojson | output/langoya_alle_stasjoner.geojson | (pending) |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

