AquaScan National Groundwater Depth Model v1
Research baseline that predicts historical depth to water (metres) from documentary and contextual groundwater features across Spain. It is part of the AquaScan Open Science project.
This is not a groundwater detector. It is a tabular regression baseline trained on historical documentary records. It has not been validated in the field and does not classify dry wells, and must not be used as the sole basis for drilling, investment or safety-critical decisions.
This is the canonical AquaScan depth-to-water model in
angellopez/aquascan-open-science-model.
It supersedes the earlier five-domain GeoAI Context v0 baseline, which is
preserved at the
v0-5domain tag.
The five-domain baseline was trained on 563 records from five domains; this
model is trained on the national READY depth-to-water population described
below.
Model summary
| Item | Value |
|---|---|
| Model name | AquaScan National Groundwater Depth Model v1 |
| Task | Tabular regression: TARGET_DEPTH_TO_WATER (metres) |
| Model | RandomForestRegressor(n_estimators=150, max_depth=20, min_samples_leaf=5, random_state=42) |
| Preprocessing | Median imputation + StandardScaler for numeric; most-frequent imputation + OneHotEncoder(handle_unknown="infrequent_if_exist", min_frequency=10) for categorical |
| Inputs | 21 documentary/contextual features |
| Training population | 16,722 READY depth records |
| Geographic scope | Spain — 44 of 48 provinces and 323 of 401 domains present in the 139,697-record national snapshot |
| Phase 0 firewall | Active — 10 sealed San Antonio sites excluded (10 READY records) |
| Framework | scikit-learn 1.9.0 |
| License | Apache-2.0 (code and weights) |
Intended use
- Research baseline for leakage-safe national groundwater contextual modelling.
- Reproducing the AquaScan national depth-to-water evaluation.
- A prior to compare against physical measurements (ERT, seismic) in future experiments.
- Screening and prioritisation, with explicit uncertainty and support flags.
Out-of-scope use
- Claiming groundwater discovery or borehole success.
- Dry-well discrimination: this model does not predict water presence.
- Replacing a hydrogeological study or a field campaign.
- Operational, commercial or safety-critical decisions.
- Treating the prediction as a current water level.
Geographic scope and support
The national snapshot contains 139,697 records, 48 provinces and 401 domains. After requiring a READY depth-to-water target and applying the Phase 0 firewall, the modeling population is 16,722 records from 44 provinces and 323 domains.
This is a national model in coverage, not a uniformly validated model for every province or domain. Of the 323 modeling domains, 122 have at least 30 training records, 201 have 1–29 records, and the domain-holdout evaluation only scores the 21 domains with at least 150 records. Predictions for weak-support domains carry no domain-level validation.
The 10 sealed Phase 0 San Antonio sites are excluded before grouping, evaluation and training. They are not part of the published training population.
Evaluation
All metrics are for TARGET_DEPTH_TO_WATER and use leakage-safe groups. The
same 500 m proximity cluster, province or domain is never split across train
and test.
| Evaluation regime | RF MAE | Dummy (median) MAE | RF RMSE | RF R² |
|---|---|---|---|---|
| Grouped 5-fold CV (500 m proximity) | 11.52 m | 26.34 m | 23.28 m | 0.706 |
| Province holdout (5 folds; 44 provinces) | 16.33 m | 27.26 m | 31.30 m | 0.502 |
| Domain holdout (21 domains ≥150 records; weighted) | 12.82 m | 23.14 m | 25.23 m | median 0.441 |
Figures are medians across folds except the domain-holdout row: MAE and RMSE are weighted by each domain's test-record count, and R² is the median across domains. The RandomForest improves over the median dummy in the grouped, province and domain regimes. The province holdout is the hardest regime: performance depends strongly on the held-out province.
Domain-holdout detail: RandomForest beats the median dummy in
20 of
21 scored domains. The only domain where RandomForest does not beat the median dummy is Vega Media y Baja del Segura.
The highest domain-holdout errors are:
Campo de Cartagena: 36.30 m MAE (n=243, dummy 63.68 m)Madrid- Talavera: 26.91 m MAE (n=174, dummy 34.70 m)Peñón- Montgó- Bernia: 25.67 m MAE (n=164, dummy 58.95 m)Campo de Dalías: 23.98 m MAE (n=972, dummy 48.36 m)Cresta del Gallo: 20.61 m MAE (n=150, dummy 52.10 m)
These are aggregate domain results; they are not site-specific guarantees.
Uncertainty
Split-conformal absolute residual at alpha = 0.1 gives a
±31.62 m 90% interval
(interval_width_m = 63.25 m) with
90.0% empirical coverage on the
out-of-fold predictions. This is a marginal interval over the national
modeling population, not a per-site guarantee. It is wide because the target
spans 0.00–542.50 m and the model is
trained across heterogeneous hydrogeological domains.
The confidence_policy.json gate additionally flags unseen or weak-support
domains and provinces. A RED gate means abstain, not that the point
prediction is valid.
Limitations
- No field validation. No ERT/seismic/GNSS groundwater validation has been performed.
- Historical target. The target is the median of dated observations; it is not the current water level.
- No water-presence or dry-well classification. The model predicts depth only. It must not be used to claim that a well will be productive.
- Uneven support. 201 of 323 domains have fewer than 30 training records, and only 21 domains have a dedicated holdout evaluation.
- High-error domains. Even with support, some domains have large holdout errors (see above), so aggregate national metrics hide local failures.
- Distribution shift. Performance outside Spain is not established.
- Marginal uncertainty. The conformal interval is global and wide; it does not model site-specific uncertainty.
- No physical inputs. The model uses documentary/contextual features only.
- Missing documentary data.
construction_dateis missing for 51.3% of records; imputation is used. Missingness for key source fields:
| Field | Missing |
|---|---|
construction_date |
51.3% |
total_depth_m |
4.4% |
aquifer_system |
0.7% |
watershed |
0.3% |
Features (21)
aquifer_system, construction_date, drilling_method, elevation_m, group_aquifer, group_domain, group_watershed, latitude, longitude, municipality, point_nature, province, pump_type, qa_coordinate_outlier, qa_depth_outlier, qa_duplicate_coordinate, qa_elevation_outlier, qa_flag_count, total_depth_m, water_use, watershed
- Numeric (9):
elevation_m,latitude,longitude, the fourqa_*flags,qa_flag_count,total_depth_m. - Categorical (12): the remaining features.
group_proximity_500m and group_spatial_cell are not model inputs. They
are built only to define leakage-safe evaluation folds. Target-derived columns
(temporal_summary_json, readiness_*, gt_*) are never inputs.
The exact contract is in feature_manifest.json.
Rows must contain all 21 columns; missing columns raise an error.
How to use
pip install -r requirements.txt
python example.py
import json
import joblib
import pandas as pd
model = joblib.load("model.joblib")
preprocessor = joblib.load("preprocessor.joblib")
features = json.load(open("feature_manifest.json"))["features"]
row = {feature: "unknown" for feature in features}
row.update({
"elevation_m": 100.0,
"latitude": 39.5,
"longitude": -3.7,
"qa_coordinate_outlier": 0,
"qa_depth_outlier": 0,
"qa_duplicate_coordinate": 0,
"qa_elevation_outlier": 0,
"qa_flag_count": 0,
"total_depth_m": 100.0,
})
X = pd.DataFrame([row], columns=features)
prediction_m = model.predict(preprocessor.transform(X))[0]
print(f"Predicted historical depth to water: {prediction_m:.2f} m")
print("90% conformal interval: +/- 31.62 m")
The row above is synthetic and only demonstrates the API. It is not a real site and its output has no scientific meaning. For real data, preserve the same feature dtypes used in training and check the support policy before using a prediction.
Files
| File | Description |
|---|---|
model.joblib |
Fitted RandomForestRegressor |
preprocessor.joblib |
Fitted preprocessing pipeline |
feature_manifest.json |
Exact input contract (21 features) |
confidence_policy.json |
GREEN/YELLOW/RED support and interval policy |
uncertainty_calibrator.json |
Split-conformal calibration |
ood_policy_reference.json |
Domain/province support policy |
metrics.json |
Aggregate evaluation metrics |
training_manifest.json |
Provenance, source hashes and hyperparameters |
example.py |
Minimal synthetic example |
requirements.txt |
Pinned runtime versions |
SHA256SUMS |
Artifact checksums |
Data provenance and license
The model was trained on IGME-derived documentary records from the national
AquaScan enrichment (dataset SHA-256
8c69621e05178d2f97ea01a27623c43e759271b7afae74c625ff4f2b33d18fbc). The record-level dataset is not redistributed:
the IGME reuse terms are still under review and the dataset may contain
record-level information. Only aggregate counts, the model card, the policies
and the fitted weights are published.
Code and weights are released under Apache-2.0. This does not grant any rights over the underlying IGME data. Users are responsible for complying with the source-data terms.
Reproducibility
experiment_id:aquascan-national-depth-v1- Random seed:
42 - Dataset SHA-256:
8c69621e05178d2f97ea01a27623c43e759271b7afae74c625ff4f2b33d18fbc - Phase 0 firewall:
10sealed IDs excluded - Created at:
2026-11-08T08:56:18+00:00
The training/evaluation entry point is
scripts/train_national_model.py; the modeling code is
src/aquascan/modeling/national_depth.py. The working tree is not a git
repository, so training_manifest.json records SHA-256 hashes of the exact
source and report files instead of a commit hash.
Synthetic inputs are not field validation. The example row is synthetic and cannot validate real-world performance.