Refactor risk assessment terminology in reports; replace 'Weed Risk' with 'Patchiness Risk' and update related calculations and alerts for consistency
This commit is contained in:
parent
253ff51ca2
commit
f0a3afad52
|
|
@ -138,28 +138,28 @@ categorize_cv_trend_long_term <- function(cv_slope) {
|
|||
|
||||
#' Determine status alert based on harvest probability and crop health
|
||||
#' Priority order:
|
||||
#' 1. Ready for harvest-check (imminent + mature ≥12 months)
|
||||
#' 2. Strong decline in crop health (drop ≥2 points but still >1.5)
|
||||
#' 3. Harvested/bare (Mean CI < 1.5)
|
||||
#' 1. harvest_ready (imminent + mature ≥12 months)
|
||||
#' 2. decline_stress (drop ≥2 points but still >1.5)
|
||||
#' 3. harvested_bare (Mean CI < 1.5)
|
||||
#' @param imminent_prob Numeric harvest probability
|
||||
#' @param age_week Numeric age in weeks
|
||||
#' @param weekly_ci_change Numeric weekly CI change
|
||||
#' @param mean_ci Numeric mean CI value
|
||||
#' @return Character status alert or NA
|
||||
#' @return Character status alert code or NA
|
||||
calculate_status_alert <- function(imminent_prob, age_week, weekly_ci_change, mean_ci) {
|
||||
# Priority 1: Ready for harvest-check
|
||||
if (!is.na(imminent_prob) && imminent_prob > 0.5 && !is.na(age_week) && age_week >= 52) {
|
||||
return("Ready for harvest-check")
|
||||
return("harvest_ready")
|
||||
}
|
||||
|
||||
# Priority 2: Strong decline
|
||||
if (!is.na(weekly_ci_change) && weekly_ci_change <= -2.0 && !is.na(mean_ci) && mean_ci > 1.5) {
|
||||
return("Strong decline in crop health")
|
||||
return("decline_stress")
|
||||
}
|
||||
|
||||
# Priority 3: Harvested/bare
|
||||
if (!is.na(mean_ci) && mean_ci < 1.5) {
|
||||
return("Harvested/bare")
|
||||
return("harvested_bare")
|
||||
}
|
||||
|
||||
# Fallback: no alert
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ if (dir.exists(kpi_data_dir)) {
|
|||
c("Gap_Score", "Gap_Score"), # Keep as-is
|
||||
c("Growth Uniformity", "Growth_Uniformity"),
|
||||
c("Decline Risk", "Decline_Risk"),
|
||||
c("Weed Risk", "Weed_Risk"),
|
||||
c("Patchiness Risk", "Patchiness_Risk"),
|
||||
c("Moran's I", "Morans_I")
|
||||
)
|
||||
|
||||
|
|
@ -539,15 +539,15 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
}
|
||||
}
|
||||
|
||||
# 4. Weed pressure insights - group by weed_pressure_risk
|
||||
if (!is.null(summary_tables$weed_pressure) && nrow(summary_tables$weed_pressure) > 0) {
|
||||
cat("\n**Weed/Pest Pressure Risk:**\n")
|
||||
weed_counts <- summary_tables$weed_pressure %>%
|
||||
dplyr::select(weed_pressure_risk, count = field_count)
|
||||
# 4. Patchiness insights - group by patchiness_risk
|
||||
if (!is.null(summary_tables$patchiness) && nrow(summary_tables$patchiness) > 0) {
|
||||
cat("\n**Field Patchiness Risk:**\n")
|
||||
patchiness_counts <- summary_tables$patchiness %>%
|
||||
dplyr::select(patchiness_risk, count = field_count)
|
||||
|
||||
for (i in seq_len(nrow(weed_counts))) {
|
||||
risk <- weed_counts$weed_pressure_risk[i]
|
||||
count <- weed_counts$count[i]
|
||||
for (i in seq_len(nrow(patchiness_counts))) {
|
||||
risk <- patchiness_counts$patchiness_risk[i]
|
||||
count <- patchiness_counts$count[i]
|
||||
if (!is.na(risk) && !is.na(count) && count > 0) {
|
||||
cat("- ", count, " field(s) at ", risk, " risk\n", sep="")
|
||||
}
|
||||
|
|
@ -684,7 +684,7 @@ generate_field_alerts <- function(field_details_table) {
|
|||
|
||||
# Check for required columns
|
||||
required_cols <- c("Field", "Field Size (acres)", "Growth Uniformity", "Yield Forecast (t/ha)",
|
||||
"Gap Score", "Decline Risk", "Weed Risk", "Mean CI", "CV Value", "Moran's I")
|
||||
"Gap Score", "Decline Risk", "Patchiness Risk", "Mean CI", "CV Value", "Moran's I")
|
||||
missing_cols <- setdiff(required_cols, colnames(field_details_table))
|
||||
|
||||
if (length(missing_cols) > 0) {
|
||||
|
|
@ -714,10 +714,10 @@ generate_field_alerts <- function(field_details_table) {
|
|||
any(`Decline Risk` == "Low") ~ "Low",
|
||||
TRUE ~ "Unknown"
|
||||
),
|
||||
highest_weed_risk = case_when(
|
||||
any(`Weed Risk` == "High") ~ "High",
|
||||
any(`Weed Risk` == "Moderate") ~ "Moderate",
|
||||
any(`Weed Risk` == "Low") ~ "Low",
|
||||
highest_patchiness_risk = case_when(
|
||||
any(`Patchiness Risk` == "High") ~ "High",
|
||||
any(`Patchiness Risk` == "Medium") ~ "Medium",
|
||||
any(`Patchiness Risk` == "Minimal") ~ "Minimal",
|
||||
TRUE ~ "Unknown"
|
||||
),
|
||||
avg_mean_ci = mean(`Mean CI`, na.rm = TRUE),
|
||||
|
|
@ -743,12 +743,12 @@ generate_field_alerts <- function(field_details_table) {
|
|||
}
|
||||
# Priority 3: No alert (no stress)
|
||||
|
||||
# Keep other alerts for decline risk, weed risk, gap score
|
||||
# Keep other alerts for decline risk, patchiness risk, gap score
|
||||
if (field_summary$highest_decline_risk %in% c("High", "Very-high")) {
|
||||
field_alerts <- c(field_alerts, "Growth decline observed")
|
||||
}
|
||||
if (field_summary$highest_weed_risk == "High") {
|
||||
field_alerts <- c(field_alerts, "Increased weed presence")
|
||||
if (field_summary$highest_patchiness_risk == "High") {
|
||||
field_alerts <- c(field_alerts, "High patchiness detected - recommend scouting")
|
||||
}
|
||||
if (field_summary$max_gap_score > 20) {
|
||||
field_alerts <- c(field_alerts, "Gaps present - recommend review")
|
||||
|
|
@ -859,7 +859,7 @@ if (!exists("field_details_table") || is.null(field_details_table)) {
|
|||
TCH_Forecasted = NA_real_,
|
||||
Gap_Score = NA_real_,
|
||||
Decline_Risk = NA_character_,
|
||||
Weed_Risk = NA_character_,
|
||||
Patchiness_Risk = NA_character_,
|
||||
Mean_CI = NA_real_,
|
||||
CV = NA_real_,
|
||||
Morans_I = NA_real_
|
||||
|
|
@ -1410,7 +1410,7 @@ tryCatch({
|
|||
kpi_parts <- c(
|
||||
kpi_parts,
|
||||
sprintf("**Gap:** %.0f", field_kpi$Gap_Score),
|
||||
sprintf("**Weed:** %s", field_kpi$Weed_Pressure_Risk),
|
||||
sprintf("**Patchiness:** %s", field_kpi$Patchiness_Risk),
|
||||
sprintf("**Decline:** %s", field_kpi$Decline_Severity)
|
||||
)
|
||||
|
||||
|
|
@ -1518,7 +1518,7 @@ if (!exists("field_details_table") || is.null(field_details_table) || nrow(field
|
|||
# Ensure all expected KPI columns exist; add as NA if missing
|
||||
expected_cols <- c("Field_id", "Mean_CI", "CV", "TCH_Forecasted", "Gap_Score",
|
||||
"Trend_Interpretation", "Weekly_CI_Change", "Uniformity_Interpretation",
|
||||
"Decline_Severity", "Weed_Pressure_Risk")
|
||||
"Decline_Severity", "Patchiness_Risk")
|
||||
for (col in expected_cols) {
|
||||
if (!col %in% names(field_details_table)) {
|
||||
field_details_table[[col]] <- NA
|
||||
|
|
@ -1553,7 +1553,7 @@ if (!exists("field_details_table") || is.null(field_details_table) || nrow(field
|
|||
`Yield Forecast (t/ha)` = TCH_Forecasted,
|
||||
`Gap Score` = Gap_Score,
|
||||
`Decline Risk` = Decline_Severity,
|
||||
`Weed Risk` = Weed_Pressure_Risk,
|
||||
`Patchiness Risk` = Patchiness_Risk,
|
||||
`CV Value` = CV
|
||||
)
|
||||
} else {
|
||||
|
|
@ -1566,7 +1566,7 @@ if (!exists("field_details_table") || is.null(field_details_table) || nrow(field
|
|||
`Yield Forecast (t/ha)` = TCH_Forecasted,
|
||||
`Gap Score` = Gap_Score,
|
||||
`Decline Risk` = Decline_Severity,
|
||||
`Weed Risk` = Weed_Pressure_Risk,
|
||||
`Patchiness Risk` = Patchiness_Risk,
|
||||
`CV Value` = CV
|
||||
)
|
||||
}
|
||||
|
|
@ -1634,11 +1634,11 @@ CI values typically range from 0 (bare soil or severely stressed vegetation) to
|
|||
|
||||
- **TCH Forecasted:** Provides yield predictions (tons cane per hectare) for mature fields (typically over 240 days old), using a machine learning model trained on historical CI and yield data. Helps plan harvest timing and logistics.
|
||||
|
||||
- **Weed Presence Score:** Detects rapid CI increases between weeks as a proxy for weed outbreaks in young fields (< 8 months old). After 8 months, canopy closure prevents weed growth. Risk levels based on percentage of pixels showing rapid growth (> 2.0 CI units increase):
|
||||
- **Low:** < 10% of field area (minimal weed presence)
|
||||
- **Moderate:** 10–25% (monitor and scout)
|
||||
- **High:** > 25% (requires immediate intervention)
|
||||
- **Note:** Mature fields (≥ 8 months) show "Canopy closed - Low weed risk" as the closed canopy suppresses weed growth.
|
||||
- **Field Patchiness Score:** Measures field heterogeneity using the Gini coefficient, detecting spatial variation in crop health. High patchiness (Gini > 0.12) may indicate irrigation, pest, or fertility issues requiring targeted scouting:
|
||||
- **Low:** Gini < 0.08 (excellent uniformity, minimal intervention needed)
|
||||
- **Medium:** Gini 0.08–0.12 (acceptable variation, routine monitoring)
|
||||
- **High:** Gini > 0.12 (poor uniformity, recommend field scouting)
|
||||
- **Note:** Young crops (< 3 months) naturally show higher patchiness as they establish; this decreases with canopy closure.
|
||||
|
||||
- **Gap Filling Score:** Indicates the proportion of a field with low CI values (lowest 25% of the distribution), highlighting areas with poor crop establishment or gaps that may need replanting.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue