Refactor disease prefiltering logic and update documentation
- Updated README.md to clarify the conditions for the `INCUBAZPRIMARIA` rule in the context of disease forecasting. - Modified disease.py to adjust the order of prefilter rules, ensuring `INCUBAZPRIMARIA` is evaluated correctly. - Enhanced product prefiltering logic in products.py to incorporate the new conditions for `incubazprimaria` while removing redundant checks.
This commit is contained in:
parent
1e696405ad
commit
28250d6608
@ -356,11 +356,11 @@ Run once per `(field, disease)` job by `pipeline/job.py::run_job`:
|
||||
| Rule | Predicates |
|
||||
|---|---|
|
||||
| `observation` true on `as_of` or the past 5 days | `systemicity` in `{systemic, mixed}` and `eradicant_action = 1` |
|
||||
| `INCUBAZPRIMARIA` / `INCUBAZPRIMARIA_<value>` today or in the past 5 days | `systemicity` in `{systemic, mixed}` and `curative_action = 1` and `eradicant_action = 0` |
|
||||
| `FASE2` anywhere and no `FASE5` anywhere | `systemicity == contact` and `preventive_action = 1` and `curative_action = 0` and `eradicant_action = 0` |
|
||||
| `FASE5` both past/today and future | `systemicity == mixed` and `preventive_action = 1` and `curative_action = 1` and `eradicant_action = 0` |
|
||||
| `FASE5` in the future only | same predicates as the `FASE2`-only rule |
|
||||
| `FASE5` today or in the past only | `systemicity` in `{contact, mixed}` and `preventive_action = 1` and `curative_action = 0` and `eradicant_action = 0` |
|
||||
| `INCUBAZPRIMARIA` / `INCUBAZPRIMARIA_<value>` today or in the past 5 days | `systemicity` in `{systemic, mixed}` and `curative_action = 1` and `eradicant_action = 0` |
|
||||
| none of the above | no FASE-specific cut; organic/crop/disease gates only |
|
||||
|
||||
9. **Vector search** — Weaviate `near_text` on `ProductProfile`, filtered server-side to the allowlisted `product_id`s
|
||||
|
||||
@ -220,11 +220,11 @@ def select_prefilter_rule(
|
||||
match wins:
|
||||
|
||||
1. `observation` True on as_of or any of the past 5 days -> "observation"
|
||||
2. FASE2 anywhere in the window AND no FASE5 anywhere -> "fase2_only"
|
||||
3. FASE5 present both past/today AND future -> "fase5_both"
|
||||
4. FASE5 present in the future only -> "fase5_future"
|
||||
5. FASE5 present today or in the past only -> "fase5_past"
|
||||
6. INCUBAZPRIMARIA today or in the past 5 days -> "incubazprimaria"
|
||||
2. INCUBAZPRIMARIA today or in the past 5 days -> "incubazprimaria"
|
||||
3. FASE2 anywhere in the window AND no FASE5 anywhere -> "fase2_only"
|
||||
4. FASE5 present both past/today AND future -> "fase5_both"
|
||||
5. FASE5 present in the future only -> "fase5_future"
|
||||
6. FASE5 present today or in the past only -> "fase5_past"
|
||||
7. otherwise -> None
|
||||
|
||||
None means the product prefilter applies only the crop / disease /
|
||||
@ -236,6 +236,9 @@ def select_prefilter_rule(
|
||||
if any(observation_by_day.get(d, False) for d in past_today):
|
||||
return "observation"
|
||||
|
||||
if any(_is_incubazprimaria(forecasts_by_day.get(d)) for d in past_today):
|
||||
return "incubazprimaria"
|
||||
|
||||
fase2_anywhere = any(v == "FASE2" for v in forecasts_by_day.values())
|
||||
fase5_anywhere = any(v == "FASE5" for v in forecasts_by_day.values())
|
||||
|
||||
@ -252,7 +255,4 @@ def select_prefilter_rule(
|
||||
if fase5_past_today:
|
||||
return "fase5_past"
|
||||
|
||||
if any(_is_incubazprimaria(forecasts_by_day.get(d)) for d in past_today):
|
||||
return "incubazprimaria"
|
||||
|
||||
return None
|
||||
|
||||
@ -138,6 +138,8 @@ def prefilter_products(
|
||||
prefilter rule (see pipeline.stages.disease.select_prefilter_rule).
|
||||
|
||||
observation -> systemicity in {systemic, mixed} AND eradicant_action = 1
|
||||
incubazprimaria -> systemicity in {systemic, mixed} AND curative_action = 1
|
||||
AND eradicant_action = 0
|
||||
fase2_only -> systemicity == contact AND preventive_action = 1
|
||||
AND curative_action = 0 AND eradicant_action = 0
|
||||
fase5_both -> systemicity == mixed AND preventive_action = 1
|
||||
@ -145,8 +147,6 @@ def prefilter_products(
|
||||
fase5_future -> same predicates as fase2_only
|
||||
fase5_past -> systemicity in {contact, mixed} AND preventive_action = 1
|
||||
AND curative_action = 0 AND eradicant_action = 0
|
||||
incubazprimaria -> systemicity in {systemic, mixed} AND curative_action = 1
|
||||
AND eradicant_action = 0
|
||||
None -> no FASE-specific cut; crop/disease/organic gates only
|
||||
"""
|
||||
candidates: list[ProductCandidate] = []
|
||||
@ -162,6 +162,13 @@ def prefilter_products(
|
||||
continue
|
||||
if not row.eradicant_action:
|
||||
continue
|
||||
elif rule == "incubazprimaria":
|
||||
if systemicity not in {"systemic", "mixed"}:
|
||||
continue
|
||||
if not row.curative_action:
|
||||
continue
|
||||
if row.eradicant_action:
|
||||
continue
|
||||
elif rule in ("fase2_only", "fase5_future"):
|
||||
if systemicity != "contact":
|
||||
continue
|
||||
@ -189,13 +196,6 @@ def prefilter_products(
|
||||
continue
|
||||
if row.eradicant_action:
|
||||
continue
|
||||
elif rule == "incubazprimaria":
|
||||
if systemicity not in {"systemic", "mixed"}:
|
||||
continue
|
||||
if not row.curative_action:
|
||||
continue
|
||||
if row.eradicant_action:
|
||||
continue
|
||||
# rule is None: no FASE-specific cut, only the gates above apply.
|
||||
|
||||
candidates.append(row.as_candidate())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user