Machine-learning inference of identifiable transport parameters from six-sensor ADR1D concentration histories.
A locked, reproducible model bundle for effective velocity, effective dispersion, and sensor-resolvable first-order decay.
- Overview
- Repository Structure
- Installation
- Quick Start
- Input Contract
- Prediction Contract
- Scientific Formulation
- Model Components
- Training Protocol
- Locked Test Results
- Simulation Results
- Numerical Integration
- Validation and Reproducibility
- Data Provenance
- File Integrity
- Limitations
- How to Cite
- Research Team
- Industry Partners
- License and Rights
- Acknowledgments
- Contact and Support
- FAQ
ADR1D-ML is an initial machine-learning model for inverse estimation of transport parameters from noisy concentration histories. It was developed from the public ADR1D benchmark, which provides 300 analytical one-dimensional advection-dispersion-reaction scenarios with fixed train, validation, and test partitions.
The repository distributes:
- a serialized bundle containing four scikit-learn pipelines;
- a feature extractor for raw six-sensor ADR1D-format observations;
- a command-line inference interface that does not require target labels;
- the locked training protocol and final evaluation artifacts;
- the two compact modeling tables needed to reproduce training;
- exact dependency versions, integrity metadata, licenses, and technical notes.
| Output | Symbol | Unit | Interpretation |
|---|---|---|---|
| Effective velocity | m s-1 | Advective coefficient in the normalized ADR equation | |
| Effective dispersion | m2 s-1 | Dispersive coefficient in the normalized ADR equation | |
| Decay resolvability | dimensionless | Probability that decay exceeds the modeled sensor resolution | |
| Conditional decay rate | s-1 | Reported only when decay is classified as resolvable |
The model does not recover
| Item | Value |
|---|---|
| ADR1D scenarios | 300 |
| Training / validation / test | 210 / 45 / 45 |
| Sensor locations | 6 |
| Time samples per sensor | 49 |
| Base features | 69 |
| Physics-derived features | 17 |
| Development scenarios used for final fitting | 255 |
| Locked test scenarios | 45 |
| Bundle version | 1.0.0 |
| Random seed | 20260720 |
| Scheduled development period | January--February 2025 |
| Initial code release | January 2025 |
| Last documentation update | July 2026 |
The scheduled development period and the execution record describe different parts of the project history. Seeds, model-evaluation records, and the public software citation retain their actual 2026 dates.
.
|-- README.md
|-- CITATION.cff
|-- LICENSE
|-- LICENSE-DATA
|-- requirements.txt
|-- data/
| |-- adr1d_modeling_table.csv
| |-- adr1d_decay_detectability_table.csv
| |-- example_sources.csv
| |-- example_sensor_observations.csv
| `-- example_features.csv
|-- models/
| |-- adr1d_parameter_models.joblib
| `-- model_manifest.json
|-- scripts/
| |-- __init__.py
| |-- extract_sensor_features.py
| |-- predict_parameters.py
| |-- train_and_evaluate_final_models.py
| |-- validate_final_models.py
| |-- validate_release.py
| |-- plot_final_test_results.py
| `-- plot_simulation_results.py
|-- results/
| |-- final_model_protocol.json
| |-- final_test_metrics.json
| |-- final_test_predictions.csv
| |-- final_model_validation.json
| |-- baseline_validation_summary.json
| |-- decay_detectability_validation_summary.json
| |-- example_predictions.csv
| `-- simulation_reconstruction_metrics.csv
`-- docs/
|-- final_test_diagnostics.png
|-- simulation_examples.png
|-- simulation_reconstructions.png
`-- team/
The repository is self-contained for inference, locked-model validation, and retraining. The larger ADR1D analytical field and raw sensor release remain in the upstream data repository to avoid unnecessary duplication.
| Component | Supported configuration |
|---|---|
| Python | 3.12 |
| Operating system | Linux, macOS, or Windows |
| RAM | 2 GB minimum; 4 GB recommended for retraining |
| Storage | Approximately 20 MB plus the virtual environment |
git clone https://github.com/gstinoco/ADR1D-ML.git
cd ADR1D-ML
python3 -m venv .venv
source .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txtExact versions are pinned because scikit-learn's Joblib persistence format is not guaranteed to remain compatible across library versions.
python scripts/validate_final_models.py
python scripts/validate_release.pyA successful check ends with:
{
"model_bundle_loaded": true,
"reproduced_prediction_arrays": 5,
"recomputed_metric_checks": 4,
"status": "ok",
"test_rows": 45
}The second command independently exercises the complete public path from raw sensor CSV files through feature extraction and in-memory parameter inference.
python scripts/predict_parameters.py \
--input-csv data/example_features.csv \
--output-csv results/my_predictions.csvThis path is appropriate when the 86 input features have already been calculated.
import pandas as pd
from scripts.predict_parameters import load_verified_bundle, predict_feature_table
features = pd.read_csv("data/example_features.csv")
bundle, manifest = load_verified_bundle()
parameters = predict_feature_table(features, bundle)parameters can be passed directly to a numerical workflow. The loader checks
the model against its manifest before deserialization.
python scripts/extract_sensor_features.py \
--sources-csv data/example_sources.csv \
--observations-csv data/example_sensor_observations.csv \
--output-csv results/my_features.csv
python scripts/predict_parameters.py \
--input-csv results/my_features.csv \
--output-csv results/my_predictions.csvThe included example contains three validation scenarios representing zero, below-resolution, and resolvable decay. Target parameters are deliberately absent from the example input files.
python scripts/train_and_evaluate_final_models.py
python scripts/validate_final_models.py
python scripts/plot_final_test_results.py
python scripts/plot_simulation_results.pyRetraining uses the protocol and tables distributed in this release. It should reproduce the published bundle, metrics, predictions, and figures when the pinned environment is used. The test set is public after release and must not be used for additional tuning while claiming the original locked evaluation.
extract_sensor_features.py expects one row per scenario:
| Column | Type | Unit | Description |
|---|---|---|---|
scenario_id |
string | - | Unique scenario identifier |
source_concentration_mg_L |
float | mg L-1 | Inlet pulse concentration |
source_start_s |
float | s | Pulse start time |
source_duration_s |
float | s | Positive pulse duration |
The observation table must contain 49 ordered samples for each of the six fixed sensors and each scenario:
| Column | Type | Unit | Description |
|---|---|---|---|
scenario_id |
string | - | Link to the source table |
sensor_id |
string | - | One of S01 through S06 |
x_m |
float | m | Sensor coordinate |
time_s |
float | s | Observation time |
concentration_observed_mg_L |
float | mg L-1 | Noisy observed concentration |
is_below_detection_limit |
boolean | - | true for a censored observation |
The trained sensor geometry is fixed:
| Sensor | Position (m) |
|---|---|
S01 |
100 |
S02 |
250 |
S03 |
400 |
S04 |
600 |
S05 |
800 |
S06 |
1000 |
The time grid is also fixed at 0 through 86,400 s in increments of 1,800 s.
The extractor validates identifiers, positions, the exact time grid, row counts, unique time values, finite detected concentrations, and positive source concentration and duration. Changing the geometry or temporal sampling places the input outside the tested model contract.
predict_parameters.py can alternatively receive any CSV containing all
feature columns declared in the model bundle. Extra metadata columns are
allowed. scenario_id is propagated to the prediction output when present.
The 86 predictors comprise:
- three known source descriptors;
- eleven concentration-history descriptors at each of six sensors;
- seventeen cross-sensor attenuation, travel-time, spread, velocity, dispersion, and decay proxies.
The feature extraction excludes analytical true concentration, injected noise standard deviation, and target transport parameters.
The inference script produces:
| Column | Unit | Meaning |
|---|---|---|
scenario_id |
- | Input identifier, when provided |
effective_velocity_m_s |
m s-1 | Predicted |
effective_dispersion_m2_s |
m2 s-1 | Predicted |
decay_resolvable_probability |
- | Probability assigned by the classifier |
decay_resolvable |
- | Binary decision at threshold 0.19 |
decay_status |
- |
resolvable or below_sensor_resolution
|
decay_rate_if_resolvable_s_1 |
s-1 | Raw conditional-model output |
reported_decay_rate_s_1 |
s-1 | Populated only for resolvable decay |
decay_rate_if_resolvable_s_1 is exposed for auditing and sensitivity work.
It must not be interpreted as a measured decay rate when decay_resolvable=0.
The operational output for that case is a missing
reported_decay_rate_s_1, not zero.
ADR1D represents one-dimensional transport in a homogeneous medium:
After division by
Concentration histories therefore identify
If an independent measurement supplies
The benchmark uses 3% relative Gaussian sensor noise. Decay is labeled resolvable when the attenuation over one advective domain crossing is at least that relative noise level:
or equivalently
This operational label separates three physical states: exactly zero decay, positive decay below sensor resolution, and sensor-resolvable decay.
The bundle contains four independently fitted pipelines:
| Component | Estimator | Features | Training target |
|---|---|---|---|
| Effective velocity | Extra Trees, 300 trees | 69 | |
| Effective dispersion | Extra Trees, 300 trees | 69 | |
| Decay resolvability | Balanced logistic regression | 86 | Resolvable / not resolvable |
| Conditional decay rate | Extra Trees, 300 trees | 12 |
|
All pipelines use median imputation. Logistic regression additionally uses
standard scaling. Hyperparameters and the complete 12-variable conditional
decay subset are recorded in results/final_model_protocol.json.
Tree regressors were selected because they substantially improved upon median baselines for the effective parameters while handling nonlinear interactions among arrival, peak, area, and temporal-spread descriptors. Logistic regression was retained for resolvability because training-only repeated validation supported a stable probability model and an explicit operating threshold.
ADR1D defines fixed scenario-level partitions. No time row or sensor row from a scenario appears in more than one partition.
- Candidate development used the 210 training scenarios.
- Configuration checks used the 45 validation scenarios.
- The final protocol was serialized and locked before opening the test split.
- Locked pipelines were fitted on training plus validation, totaling 255 development scenarios.
- Final metrics were computed once on the 45 test scenarios.
- No feature, model, threshold, or hyperparameter was changed after testing.
The locked protocol is distributed as configs/final_model_protocol.json.
Its relationship to the trained bundle and evaluation artifacts is recorded in
models/model_manifest.json.
The development process compared simple medians, regularized linear models, logistic regression, and Extra Trees baselines. Physics-derived features were also evaluated for decay. Their first formulation improved ranking but not the classification operating point or conditional decay regression, which led to the sensor-resolution-aware target used in the final protocol.
| Output | Metric | Test result |
|---|---|---|
| Effective velocity | Median absolute percentage error | 4.40% |
| Effective velocity | Physical-scale |
0.9840 |
| Effective dispersion | Median absolute percentage error | 27.65% |
| Effective dispersion | Physical-scale |
0.6916 |
| Decay resolvability | Balanced accuracy | 0.7564 |
| Decay resolvability | ROC AUC | 0.8120 |
| Decay resolvability | Recall | 0.6667 |
| Conditional decay rate | Median absolute percentage error | 69.01% |
| Conditional decay rate | Log-scale |
0.4250 |
The conditional decay-rate result is based on only six resolvable test cases. It is distributed to preserve the complete locked experiment, but it should be treated as a high-uncertainty estimate rather than a precise measurement.
Locked test predictions. Dashed diagonals denote perfect regression agreement; the horizontal dashed line is the fixed decay-resolvability threshold.
| Regime | Test rows | Velocity MdAPE | Dispersion MdAPE |
|---|---|---|---|
| Conservative | 11 | 5.86% | 28.42% |
| Decay only | 11 | 5.81% | 21.99% |
| Retardation and decay | 12 | 2.65% | 30.22% |
| Retardation only | 11 | 3.47% | 15.73% |
Parameter errors are also examined in simulation space. The public plotting script reconstructs analytical ADR1D concentration fields from the compact scenario tables, so the full 749,700-row benchmark field does not need to be duplicated in this repository.
Three illustrative validation scenarios spanning the modeled decay states. Lines are noise-free analytical responses, points are virtual observations, and crosses indicate values censored by the detection-limit rule.
These examples expose the simulated plume motion before reducing each sensor history to machine-learning features. They belong to the final development set and are presented for interpretation, not as independent performance evidence.
Reference and ML-driven fields for all four resolvable test scenarios classified correctly. No case was selected according to visual quality.
| Scenario | Physical regime | Field RMSE | Maximum absolute error |
|---|---|---|---|
| ADR1D-0130 | Decay only | 0.040 |
0.426 |
| ADR1D-0240 | Retardation and decay | 0.016 |
0.099 |
| ADR1D-0244 | Retardation and decay | 0.031 |
0.142 |
| ADR1D-0279 | Retardation and decay | 0.027 |
0.098 |
The comparison uses a common grid of 201 spatial positions and 121 times. The
complete values are stored in
results/simulation_reconstruction_metrics.csv. Cases classified as
unresolved are intentionally absent because the model contract does not assign
them a single decay rate. These post-test visual diagnostics were not used to
change features, thresholds, estimators, or hyperparameters.
Reproduce both figures from the repository root with:
python scripts/plot_simulation_results.pyThe effective predictions can be inserted directly into the normalized one-dimensional model:
Recommended integration logic:
- Extract features from a sensor window matching the published geometry and temporal grid.
- Predict
$u_{eff}$ ,$D_{eff}$ , and decay resolvability. - Use
$u_{eff}$ and$D_{eff}$ directly in the normalized solver. - Use the conditional
$\lambda$ prediction only whendecay_resolvable=1. - For unresolved decay, propagate a sensitivity range rather than replacing
$\lambda$ automatically with zero.
Under the same ADR1D detectability definition, an unresolved result implies approximately
The model estimates coefficients; it does not replace conservation checks, boundary-condition treatment, mesh or time-step convergence studies, or solver verification.
python scripts/validate_final_models.py
python scripts/validate_release.pyThe validator performs all of the following:
- checks the model, protocol, metrics, and predictions against the manifest;
- loads the four pipelines from the trusted bundle;
- reproduces effective-velocity and effective-dispersion predictions;
- reproduces decay probabilities, binary decisions, and conditional rates;
- recomputes four headline test metrics;
- confirms that unresolved rows do not report a decay rate;
- confirms that the manifest records no post-test tuning.
The release validator additionally rebuilds all 86 features from the raw three-scenario example, loads the verified bundle through the public API, and reproduces all eight prediction columns.
python scripts/plot_final_test_results.py
python scripts/plot_simulation_results.pypython scripts/train_and_evaluate_final_models.py
python scripts/validate_final_models.pyThe standalone public distribution was tested in a clean Python 3.12.2 virtual
environment using the versions in requirements.txt. The complete fit
reproduced the original model, metrics, and predictions byte for byte.
The modeling tables derive exclusively from ADR1D version 1.0.0 (GitHub source), a public analytical benchmark created by the same research group. ADR1D supplies physical parameters, source conditions, analytical fields, noisy virtual sensors, and fixed scenario partitions.
| Public modeling file | Rows | Purpose |
|---|---|---|
data/adr1d_modeling_table.csv |
300 | Base 69-feature table for effective parameters |
data/adr1d_decay_detectability_table.csv |
300 | 86-feature table with sensor-resolution-aware decay targets |
data/example_sources.csv |
3 | Unlabeled source metadata for quick-start inference |
data/example_sensor_observations.csv |
882 | Unlabeled six-sensor histories for quick-start inference |
data/example_features.csv |
3 | Features reproduced from the quick-start sensor histories |
The field solution and complete 88,200-row sensor table are not duplicated here. They remain available upstream with the generation methodology, data dictionary, rights statement, and validation record.
Water Quality Portal observations are not used to train or validate this parameter model because they do not provide equivalent ground-truth transport coefficients and boundary conditions.
The machine-readable model manifest records the identity of the locked model, protocol, metrics, predictions, and modeling tables. The inference interface checks the bundle against that manifest before deserialization, while the release validator extends the check to the remaining artifacts. Detailed integrity values remain in the manifest instead of being duplicated here.
Users should never load an untrusted Joblib or pickle artifact.
- Validation covers the parameter ranges sampled by ADR1D 1.0.0; no out-of-distribution extrapolation claim is made.
- Geometry, time window, sampling interval, noise, censoring, and source type follow the ADR1D six-sensor benchmark.
- The underlying medium is one-dimensional, homogeneous, and constant within each scenario.
- Effective coefficients
$v/R$ and$D/R$ are identifiable;$v$ ,$D$ , and$R$ are not separately identifiable without independent information. - Effective dispersion is less accurate than effective velocity.
- Decay classification missed two of six resolvable test cases and produced six false positives.
- Conditional decay magnitude has high uncertainty and only six resolvable test cases.
- A below-resolution result does not establish that physical decay is zero.
- No field-site validation, uncertainty calibration, multi-dimensional flow, heterogeneous medium, variable boundary condition, or sensor-placement transfer has been demonstrated.
- The bundle is a research artifact, not a substitute for site-specific hydrogeological assessment or regulatory decision procedures.
Please cite the software release as:
Tinoco-Guerrero, G., Domínguez-Mota, F. J., and Guzmán-Torres, J. A. (2026). ADR1D-ML: Identifiable Parameter Inference for One-Dimensional Reactive Transport (Version 1.0.0) [Computer software]. Universidad Michoacana de San Nicolás de Hidalgo. https://github.com/gstinoco/ADR1D-ML
BibTeX:
@software{TinocoGuerrero2026ADR1DML,
author = {Tinoco-Guerrero, Gerardo and
Domínguez-Mota, Francisco J. and
Guzmán-Torres, J. Alberto},
title = {{ADR1D-ML}: Identifiable Parameter Inference for
One-Dimensional Reactive Transport},
version = {1.0.0},
year = {2026},
publisher = {Universidad Michoacana de San Nicolás de Hidalgo},
url = {https://github.com/gstinoco/ADR1D-ML}
}When using the distributed training tables, also cite the upstream ADR1D data release:
Tinoco-Guerrero, G., Domínguez-Mota, F. J., and Guzmán-Torres, J. A. (2026). ADR1D and WQP-NM-Nutrients: A Reproducible Contaminant-Transport Benchmark and Curated Water-Quality Snapshot (Version 1.0.0) [Data set]. Universidad Michoacana de San Nicolás de Hidalgo. https://doi.org/10.5281/zenodo.21499528
- Ogata, A., and Banks, R. B. (1961). A solution of the differential equation of longitudinal dispersion in porous media. U.S. Geological Survey Professional Paper 411-A. https://doi.org/10.3133/pp411A
- McKay, M. D., Beckman, R. J., and Conover, W. J. (1979). Comparison of three methods for selecting values of input variables in the analysis of output from a computer code. Technometrics, 21(2), 239-245. https://doi.org/10.1080/00401706.1979.10489755
GitHub can also generate citation metadata directly from CITATION.cff.
Researchers and students advancing reproducible contaminant-transport modeling and scientific machine learning
| Photo | Student | Institution | Contact |
|---|---|---|---|
![]() |
Gabriela Pedraza-Jiménez |
||
![]() |
Eli Chagolla-Inzunza |
| Photo | Student | Institution | Contact |
|---|---|---|---|
![]() |
Jorge L. González-Figueroa |
||
![]() |
Christopher N. Magaña-Barocio |
| Photo | Student | Institution | Contact |
|---|---|---|---|
![]() |
Maria Goretti Fraga-Lopez |
Student contributors are recognized for their participation in the broader
research program. Formal software citation and copyright attribution remain
limited to the three principal researchers listed in CITATION.cff and the
license files.
Connecting scientific machine learning with applied engineering and technology transfer
|
Focus areas
|
ADR1D-ML uses a component-specific licensing scheme:
- Source code and serialized model bundle: MIT License, provided in
LICENSE. - CSV training and example data: Creative Commons Attribution 4.0
International, provided in
LICENSE-DATA. - ADR1D upstream content: remains subject to the rights and attribution statement in the ADR1D repository.
- Third-party libraries: retain their respective licenses; their names in this repository do not imply redistribution of their source code.
- Institutional emblems and logos: files under
docs/partners/remain the property of their respective organizations. They are used solely for identification and acknowledgment and are not covered by the MIT orCC BY 4.0licenses.
The model and code are provided without warranty. Attribution must not imply endorsement by the authors, UMSNH, SECIHTI, CIMNE, Aula CIMNE Morelia, or SIIIA MATH.
We thank the institutions and partners whose continuing institutional and financial support made the model development, validation, documentation, and student participation possible.
|
Collaboration highlights
|
Collaboration highlights
|
|
Primary Research Contact
Scientific coordination and model integration Gerardo Tinoco-Guerrero Universidad Michoacana de San Nicolás de Hidalgo Morelia, Michoacán, Mexico |
Repository Support
Questions, reproducibility reports, and integration problems
|
Why does the model predict v/R and D/R instead of v, D, and R?
The normalized concentration equation contains only the ratios
Does below sensor resolution mean lambda is zero?
No. It means the modeled decay effect is too small relative to the 3% sensor
noise used by ADR1D. The numerical solver should use sensitivity analysis or
additional observations rather than automatically setting
Can I use a different sensor layout?
Not without retraining and new validation. Version 1.0.0 was evaluated only for six sensors at 100, 250, 400, 600, 800, and 1000 m with 49 temporal samples.
Can the model be used directly with Water Quality Portal records?
No. Those observations generally lack equivalent parameter labels, controlled source conditions, and complete boundary information. They were not used to train this release.
Why are exact package versions required?
The bundle uses Joblib serialization of scikit-learn estimators. Exact versions reduce persistence incompatibilities and support byte-for-byte reproduction of the locked release.
Is the conditional decay estimate reliable?
Its error remains high and only six resolvable cases occur in the test split. The output is useful for research and sensitivity studies, but it is not a precise field measurement.











