Skip to content
Back to skills

Docs

ASecurity

> **Stage ID**: s3_weather_prep > **Pipeline order**: 3 of 10 > **Depends on**: none

  • 200 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 11, 2026
testingpythonapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 16 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add lzwei196/KISS---Knowledge-Infrastructure-for-Scientific-Simulation --skill docs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Docs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lzwei196-docs-51332647/badge)](https://www.skillsdirectory.com/skills/lzwei196-docs-51332647)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Weather Data Preparation -- Skill Document

> **Stage ID**: s3_weather_prep
> **Pipeline order**: 3 of 10
> **Depends on**: none

## Purpose

Prepare the daily weather DataFrame that drives the AquaCrop simulation. This is the **most error-prone stage** because AquaCrop requires a specific DataFrame format with pre-computed reference evapotranspiration (ET0), which most raw data sources do not provide. Unlike DSSAT (which computes ET internally from radiation/wind/humidity), AquaCrop expects ET0 as an input variable.

## Prerequisites

- [ ] Daily weather data available for the simulation period
- [ ] If ET0 is not in source data: solar radiation, wind speed, and humidity data available for Penman-Monteith computation
- [ ] Latitude and elevation of the site (needed for ET0 computation)

## Inputs

| Input | Type | Source | Description |
|-------|------|--------|-------------|
| weather_source | forcing source / file | CMFD, MSWX, NASA POWER (through `load_daily_forcing`), local station, AquaCrop text file | Daily weather data |
| lat | float | Site location | Latitude in degrees (for ET0 computation) |
| elevation | float | DEM | Elevation in meters (for ET0 computation) |

## Procedure

### Step 1: Determine data source and available variables

| Source | Available Variables | ET0 Available? | Action |
|--------|-------------------|---------------|--------|
| AquaCrop sample files | MinTemp, MaxTemp, Precip, ET0 | Yes | Use `prepare_weather()` directly |
| CMFD/MSWX | Tmin, Tmax, Precip, SWrad, LWrad, Wind, Pressure, Humidity (through `load_daily_forcing`) | No | Compute ET0 via Penman-Monteith |
| Local station | Tmin, Tmax, Precip, possibly SWrad | Maybe | Compute ET0 or use Hargreaves if only T available |
| NASA POWER | Tmin, Tmax, Precip, SWrad, LWrad, Wind, Humidity | No | Compute ET0 via Penman-Monteith |

### Step 2A: Load from AquaCrop text file

```python
from aquacrop.utils import prepare_weather
weather_df = prepare_weather('/path/to/weather.txt')
```

File format: whitespace-separated, 7 columns, no header:
```
Day Month Year MinTemp MaxTemp Precipitation ReferenceET
1   1     2000 2.1     12.5    0.0           1.2
2   1     2000 1.8     11.9    3.2           1.1
```

### Step 2B: Build the DataFrame straight from a forcing source (CMFD / MSWX / NASA POWER)

Read the source through the shared loader; do not extract it from another model's forcing files.

```python
from ki_tools_common.load_forcing import load_daily_forcing
from tools.s3_weather_prep.compute_eto_penman_monteith import compute_et0_fao56   # this KI's ET0 function
import numpy as np
import pandas as pd

fc = load_daily_forcing('nasa_power', lat, lon, y0, y1)        # or 'cmfd' / 'mswx' with forcing_dir=<3-hourly store>
fc = {k: (v if k == 'dates' else np.asarray(v, dtype=float)) for k, v in fc.items()}   # the loader returns lists
dates = pd.to_datetime(fc['dates'])
et0 = compute_et0_fao56(fc['temp_min_c'], fc['temp_max_c'], fc['srad_wm2'] * 0.0864,   # W/m2 -> MJ/m2/day
                        fc['wind_ms'], lat, elevation, dates.dayofyear.values)
weather_df = pd.DataFrame({
    'MinTemp': fc['temp_min_c'],        # deg C
    'MaxTemp': fc['temp_max_c'],        # deg C
    'Precipitation': fc['precip_mm'],   # mm/day (the loader already returns daily totals)
    'ReferenceET': et0,                 # mm/day
    'Date': dates,
})
```

### Step 3: Compute ET0 if not available

Use FAO-56 Penman-Monteith method. Run tool `compute_eto_penman_monteith`.

**Simplified Hargreaves** (if only temperature available):
```python
# Hargreaves-Samani equation (less accurate than PM):
et0 = 0.0023 * (tmax - tmin)**0.5 * ((tmax + tmin)/2 + 17.8) * Ra
# where Ra = extraterrestrial radiation (MJ/m2/day) from latitude and DOY
```

### Step 4: Validate the DataFrame

Run tool `validate_weather_df`. Checks:
- All 5 required columns present: `MinTemp`, `MaxTemp`, `Precipitation`, `ReferenceET`, `Date`
- Column names are EXACTLY as shown (case-sensitive)
- No NaN values
- `MaxTemp >= MinTemp` for all rows
- `Precipitation >= 0` for all rows
- `ReferenceET > 0` for all rows (clipped to 0.1 internally)
- No missing days in the Date column

**If this fails**: See diagnostic triplets dt_001 (missing ET0), dt_007 (wrong column names).

### Step 5: Clip to simulation period

The weather DataFrame must cover at least `sim_start_time` to `sim_end_time`. Extra days are acceptable (AquaCrop will subset internally).

## Expected Outputs

| Output | Path | Verification |
|--------|------|--------------|
| weather_df | in-memory DataFrame | `len(weather_df) >= (end_date - start_date).days`, all 5 columns present |

## Validation Checks

1. **Column presence**: `set(['MinTemp','MaxTemp','Precipitation','ReferenceET','Date']).issubset(df.columns)`
   - If missing column: ValueError at model construction. See dt_007.

2. **ET0 positivity**: `weather_df.ReferenceET.min() >= 0.1`
   - If zero/negative: divide-by-zero errors during simulation. See dt_001.

3. **Temperature range**: `-50 < MinTemp < MaxTemp < 60` for all rows
   - If units are Kelvin (values > 200): convert to Celsius first. See common failure pattern cfp_005.

4. **Date continuity**: `weather_df.Date.diff().dropna().unique()` should be `[timedelta(days=1)]`
   - If gaps: model may produce wrong results for missing days.

## Common Pitfalls

> **PITFALL**: Missing ReferenceET column (most common error)
> AquaCrop REQUIRES pre-computed ET0. Most raw weather data does not include it. The symptom is ValueError: "Check if all the following columns exist (Date MinTemp MaxTemp Precipitation ReferenceET)."
> **Do this instead**: Compute ET0 using FAO Penman-Monteith before creating the DataFrame.
> See diagnostic triplet dt_001.

> **PITFALL**: Column name capitalization mismatch
> AquaCrop expects `MinTemp` not `min_temp`, `ReferenceET` not `ET0` or `ETo` or `ref_et`. Case matters.
> **Do this instead**: Rename columns to exact AquaCrop format: `df.rename(columns={'tmin': 'MinTemp', ...})`
> See diagnostic triplet dt_007.

> **PITFALL**: Precipitation in mm/timestep instead of mm/day
> A sub-daily series gives precipitation per timestep (3-hourly = mm/3hr); it must be summed to daily before passing to AquaCrop. `load_daily_forcing` already returns daily totals.
> **Do this instead**: Resample to daily: `daily_precip = hourly_precip.resample('D').sum()`

---

*This skill document is part of the aquacrop-ospy-knowledge infrastructure.*
*Stage 3 of 10 | Tools used: prepare_weather_df, compute_eto_penman_monteith, validate_weather_df | Related triplets: dt_001, dt_007*

Files in this skill

  • REFERENCES.md1.6 KB
  • format_spec.yaml35.8 KB
  • model_couplings.yaml13.5 KB
  • papers.json4.9 KB
  • s10_water_productivity_skill.md7.1 KB
  • s1_crop_selection_skill.md4.5 KB
  • s2_soil_profile_skill.md4 KB
  • s3_weather_prep_skill.md5.7 KB
  • s4_initial_conditions_skill.md3.4 KB
  • s5_irrigation_skill.md5.7 KB
  • s6_field_management_skill.md2.9 KB
  • s7_model_assembly_skill.md4 KB
  • s8_execution_skill.md3.3 KB
  • s9_output_analysis_skill.md5.3 KB
  • validation_convention.yaml23 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…