Enhance weather metrics handling and phenology logic
- Introduced a new function to round specific weather metric values to two decimal places in assemble.py. - Updated the JSON entry construction in assemble.py to utilize the new rounding function for weather metrics. - Modified the phenology loading logic in phenology.py to use yesterday's phase if today's phase is null after carry-forward. - Clarified documentation in README.md regarding the phenology phase handling.
This commit is contained in:
parent
e588d97e0f
commit
21927133a4
@ -346,7 +346,7 @@ Run once per `(field, disease)` job by `pipeline/job.py::run_job`:
|
||||
1. **Worklist** — crop → fields (`AI_agrosupport_an_colture` + `AI_agrosupport_cmp_layers`) → disease model (`AI_agrosupport_agro_models`); organic flag is `cmplay_imp == 3` (`pipeline/worklist.py`, run once per batch, not per job)
|
||||
2. **Disease model** — per-day `FASE5` > `FASE2` resolution over as_of±5, from the worklist's known `anmod_id`
|
||||
3. **Weather** — `TDatiMeteo_D` for past days, `TDatiMeteo_D_FRC` for today/future
|
||||
4. **Phenology** — carry-forward of latest observation ≤ day; future days null
|
||||
4. **Phenology** — carry-forward of latest observation ≤ day; future days null; if today's phase is missing, use yesterday's
|
||||
5. **Applied treatments** — products sprayed over `as_of-5 .. as_of`, from `AI_agrosupport_agro_ril_operations*` with `rilop_operation = 10`
|
||||
6. **LLM** — synthesise 1–2 anonymised search queries from the subset
|
||||
7. **Product prefilter** — organic / crop / disease / FASE rules against the batch-wide, in-memory `products` index
|
||||
|
||||
@ -20,6 +20,20 @@ METRIC_KEYS = (
|
||||
"potential_evapotranspiration_mm",
|
||||
)
|
||||
|
||||
_TWO_DECIMAL_KEYS = frozenset({
|
||||
"min_air_temperature_c",
|
||||
"max_air_temperature_c",
|
||||
"average_air_temperature_c",
|
||||
"rainfall_mm",
|
||||
"potential_evapotranspiration_mm",
|
||||
})
|
||||
|
||||
|
||||
def _metric_value(key: str, value: Any) -> Any:
|
||||
if value is None or key not in _TWO_DECIMAL_KEYS:
|
||||
return value
|
||||
return round(float(value), 2)
|
||||
|
||||
|
||||
def _day_entry(
|
||||
day: date,
|
||||
@ -32,7 +46,7 @@ def _day_entry(
|
||||
metrics = weather.get(day, {})
|
||||
entry: dict[str, Any] = {"date": format_date(day)}
|
||||
for key in METRIC_KEYS:
|
||||
entry[key] = metrics.get(key)
|
||||
entry[key] = _metric_value(key, metrics.get(key))
|
||||
entry["phenology_phase"] = phenology.get(day)
|
||||
entry["disease_forecast"] = forecasts.get(day)
|
||||
# Treatments can only have been applied on or before as_of; future days
|
||||
@ -93,7 +107,7 @@ def build_json_for_query_synthesis(
|
||||
metrics = weather.get(day, {})
|
||||
entry: dict[str, Any] = {"date": format_date(day)}
|
||||
for key in METRIC_KEYS:
|
||||
entry[key] = metrics.get(key)
|
||||
entry[key] = _metric_value(key, metrics.get(key))
|
||||
weather_forecasts.append(entry)
|
||||
|
||||
return {
|
||||
|
||||
@ -56,8 +56,7 @@ def load_phenology(
|
||||
|
||||
Observations with rilfeno_date <= as_of are carried forward to each day
|
||||
(latest observation at or before that day). Future days are always null.
|
||||
Today's phase equals yesterday's (which, under carry-forward, is the same
|
||||
observation as of as_of-1, or the latest available before as_of).
|
||||
If today's phase is null after carry-forward, yesterday's phase is used.
|
||||
"""
|
||||
window = build_window(as_of)
|
||||
rows = fetch_all(conn, _FENO_SQL, (field_id, as_of))
|
||||
@ -92,9 +91,9 @@ def load_phenology(
|
||||
_, ff_id = applicable[-1]
|
||||
result[day] = name_by_id.get(ff_id)
|
||||
|
||||
# Explicit rule: today's phase equals yesterday's.
|
||||
# If today's phase is missing, fall back to yesterday's.
|
||||
yesterday = as_of.fromordinal(as_of.toordinal() - 1)
|
||||
if yesterday in result:
|
||||
if result[as_of] is None and yesterday in result:
|
||||
result[as_of] = result[yesterday]
|
||||
|
||||
return result
|
||||
|
||||
Loading…
Reference in New Issue
Block a user