Loading...
Loading...
Groundwater time series analysis and modelling using transfer function noise models. Use when Claude needs to: (1) Analyze groundwater level time series, (2) Model well responses to precipitation/pumping, (3) Calibrate aquifer parameters from head data, (4) Forecast or hindcast groundwater levels, (5) Decompose hydrological signals into components, (6) Compare response functions, (7) Perform model diagnostics and uncertainty analysis.
npx skill4agent add steadfastasart/geoscience-skills pastasimport pastas as ps
import pandas as pd
# Load data
head = pd.read_csv('well.csv', index_col=0, parse_dates=True).squeeze()
precip = pd.read_csv('precip.csv', index_col=0, parse_dates=True).squeeze()
evap = pd.read_csv('evap.csv', index_col=0, parse_dates=True).squeeze()
# Create model
ml = ps.Model(head, name='Well_001')
# Add recharge stress
sm = ps.RechargeModel(precip, evap, rfunc=ps.Gamma(), name='recharge')
ml.add_stressmodel(sm)
# Solve and plot
ml.solve()
ml.plot()| Class | Purpose |
|---|---|
| Main model container |
| Response to external stress (pumping, river) |
| Recharge from precipitation minus evaporation |
| Gamma distribution response function |
| Simple exponential response function |
ml = ps.Model(head, name='well')
ml.add_stressmodel(ps.RechargeModel(precip, evap, rfunc=ps.Gamma(), name='recharge'))
ml.solve()pumping = pd.read_csv('pumping.csv', index_col=0, parse_dates=True).squeeze()
ml.add_stressmodel(ps.StressModel(pumping, rfunc=ps.Hantush(),
name='pumping', up=False)) # up=False for drawdownprint(f"EVP: {ml.stats.evp():.1f}%") # Explained variance
print(f"RMSE: {ml.stats.rmse():.3f} m") # Root mean square error
print(f"AIC: {ml.stats.aic():.1f}") # Model selection criterion
ml.plots.diagnostics() # Diagnostic plots
ml.plots.acf() # Autocorrelationcontributions = ml.get_contributions()
for name, contrib in contributions.items():
print(f"{name}: mean={contrib.mean():.2f}")step = ml.get_step_response('recharge') # Step response
block = ml.get_block_response('recharge') # Impulse responseml.to_json('model.pas') # Save model
ml_loaded = ps.io.load('model.pas') # Load model
sim = ml.simulate()
sim.to_csv('simulation.csv') # Export results| Statistic | Description | Good Value |
|---|---|---|
| EVP | Explained variance percentage | >70% |
| RMSE | Root mean square error | Low (context-dependent) |
| AIC | Akaike Information Criterion | Lower = better |
| BIC | Bayesian Information Criterion | Lower = better |
for rfunc in [ps.Gamma(), ps.Exponential(), ps.Hantush()]:
ml = ps.Model(head)
ml.add_stressmodel(ps.RechargeModel(precip, evap, rfunc=rfunc, name='r'))
ml.solve(report=False)
print(f"{rfunc.name}: EVP={ml.stats.evp():.1f}%, AIC={ml.stats.aic():.1f}")ml.solve()
forecast = ml.simulate(tmin='2024-01-01', tmax='2025-12-31')
ml.plot(tmax='2025-12-31')river = pd.read_csv('river_stage.csv', index_col=0, parse_dates=True).squeeze()
sm = ps.StressModel(river, rfunc=ps.Exponential(), name='river',
settings='waterlevel')
ml.add_stressmodel(sm)| Use Case | Tool | Why |
|---|---|---|
| Groundwater time series analysis | Pastas | Purpose-built transfer function models |
| Well response to recharge/pumping | Pastas | Built-in stress models and response functions |
| Numerical groundwater flow (MODFLOW) | FloPy | Full 3D finite-difference groundwater model |
| Simple exponential decay fitting | Custom scipy | |
| Regional groundwater flow modelling | FloPy | Spatially distributed parameters and boundaries |
| Aquifer test analysis (pumping tests) | Aqtesolv / custom | Dedicated well test interpretation |
| Multi-well network analysis | Pastas | Model each well independently, compare responses |
| Signal decomposition | Pastas | Separate recharge, pumping, and trend contributions |
ps.Model(head)ps.RechargeModel(precip, evap, rfunc=ps.Gamma())ml.solve()ml.plots.diagnostics()ml.solve(noise=True)ml.plots.diagnostics()| Issue | Solution |
|---|---|
| Poor fit (low EVP) | Try different response functions |
| Residual autocorrelation | Add noise model: |
| Unstable parameters | Set parameter bounds or fix values |
| Missing stress data | Interpolate or use |