Changed the generated doc to match the one in Linear (SC-20) BUT i cannot run the coded parts.
This commit is contained in:
parent
f94a6317bd
commit
9f217df98a
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
params:
|
params:
|
||||||
ref: "word-styles-reference-var1.docx"
|
ref: "word-styles-reference-var1.docx"
|
||||||
output_file: CI_report.docx
|
output_file: CI_report.docx
|
||||||
report_date: "2025-09-30"
|
report_date: "2026-01-25"
|
||||||
data_dir: "aura"
|
data_dir: "angata"
|
||||||
mail_day: "Wednesday"
|
mail_day: "Wednesday"
|
||||||
borders: FALSE
|
borders: FALSE
|
||||||
ci_plot_type: "both" # options: "absolute", "cumulative", "both"
|
ci_plot_type: "both" # options: "absolute", "cumulative", "both"
|
||||||
|
|
@ -56,7 +56,7 @@ suppressPackageStartupMessages({
|
||||||
|
|
||||||
# Load custom utility functions
|
# Load custom utility functions
|
||||||
tryCatch({
|
tryCatch({
|
||||||
source("report_utils.R")
|
source("r_app/report_utils.R")
|
||||||
}, error = function(e) {
|
}, error = function(e) {
|
||||||
message(paste("Error loading report_utils.R:", e$message))
|
message(paste("Error loading report_utils.R:", e$message))
|
||||||
# Try alternative path if the first one fails
|
# Try alternative path if the first one fails
|
||||||
|
|
@ -112,7 +112,7 @@ safe_log(paste("report_date params:", params$report_date))
|
||||||
safe_log(paste("mail_day variable:", mail_day))
|
safe_log(paste("mail_day variable:", mail_day))
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r load_kpi_data, message=FALSE, warning=FALSE, include=FALSE}
|
```{r load_kpi_data, eval=TRUE, message=FALSE, warning=FALSE, include=FALSE}
|
||||||
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
||||||
# Primary expected directory inside the laravel storage
|
# Primary expected directory inside the laravel storage
|
||||||
kpi_data_dir <- file.path("..", "laravel_app", "storage", "app", project_dir, "reports", "kpis")
|
kpi_data_dir <- file.path("..", "laravel_app", "storage", "app", project_dir, "reports", "kpis")
|
||||||
|
|
@ -218,7 +218,7 @@ if (kpi_files_exist) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r load_cloud_coverage_data, message=FALSE, warning=FALSE, include=FALSE}
|
```{r load_cloud_coverage_data, eval=TRUE, message=FALSE, warning=FALSE, include=FALSE}
|
||||||
## LOAD PER-FIELD CLOUD COVERAGE DATA
|
## LOAD PER-FIELD CLOUD COVERAGE DATA
|
||||||
# Cloud coverage calculated from the mosaic by script 09
|
# Cloud coverage calculated from the mosaic by script 09
|
||||||
# Expected filename pattern: [project_dir]_cloud_coverage_week[N].rds or _cloud_coverage_[date].rds
|
# Expected filename pattern: [project_dir]_cloud_coverage_week[N].rds or _cloud_coverage_[date].rds
|
||||||
|
|
@ -266,6 +266,7 @@ if (!is.null(cloud_file) && file.exists(cloud_file)) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```{r generate_field_kpi_summary_function, include=FALSE, eval=TRUE}
|
||||||
#' Generate field-specific KPI summary for display in reports
|
#' Generate field-specific KPI summary for display in reports
|
||||||
#' @param field_name Name of the field to summarize
|
#' @param field_name Name of the field to summarize
|
||||||
#' @param field_details_table Data frame with field-level KPI details
|
#' @param field_details_table Data frame with field-level KPI details
|
||||||
|
|
@ -372,7 +373,7 @@ generate_field_kpi_summary <- function(field_name, field_details_table, CI_quadr
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r calculate_dates_and_weeks, message=FALSE, warning=FALSE, include=FALSE}
|
```{r calculate_dates_and_weeks, message=FALSE, warning=FALSE, include=FALSE, eval=TRUE}
|
||||||
# Set locale for consistent date formatting
|
# Set locale for consistent date formatting
|
||||||
Sys.setlocale("LC_TIME", "C")
|
Sys.setlocale("LC_TIME", "C")
|
||||||
|
|
||||||
|
|
@ -423,7 +424,7 @@ safe_log(paste("Report week:", current_week, "Year:", year))
|
||||||
safe_log(paste("Week range:", week_start, "to", week_end))
|
safe_log(paste("Week range:", week_start, "to", week_end))
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r load_ci_data, message=FALSE, warning=FALSE, include=FALSE}
|
```{r load_ci_data, message=FALSE, warning=FALSE, include=FALSE, eval=TRUE}
|
||||||
# Load CI index data with error handling
|
# Load CI index data with error handling
|
||||||
tryCatch({
|
tryCatch({
|
||||||
CI_quadrant <- readRDS(here::here(cumulative_CI_vals_dir, "All_pivots_Cumulative_CI_quadrant_year_v2.rds"))
|
CI_quadrant <- readRDS(here::here(cumulative_CI_vals_dir, "All_pivots_Cumulative_CI_quadrant_year_v2.rds"))
|
||||||
|
|
@ -434,7 +435,7 @@ tryCatch({
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r compute_benchmarks_once, include=FALSE}
|
```{r compute_benchmarks_once, include=FALSE, eval=TRUE}
|
||||||
# Compute CI benchmarks once for the entire estate
|
# Compute CI benchmarks once for the entire estate
|
||||||
benchmarks <- compute_ci_benchmarks(CI_quadrant, project_dir, c(10, 50, 90))
|
benchmarks <- compute_ci_benchmarks(CI_quadrant, project_dir, c(10, 50, 90))
|
||||||
if (!is.null(benchmarks)) {
|
if (!is.null(benchmarks)) {
|
||||||
|
|
@ -444,24 +445,34 @@ if (!is.null(benchmarks)) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Report Summary
|
|
||||||
|
<!-- Dynamic cover page -->
|
||||||
|
::: {custom-style="Cover_title" style="text-align:center; margin-top:120px;"}
|
||||||
|
<span style="font-size:100pt; line-height:1.0; font-weight:700;">Satellite Based Field Reporting</span>
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: {custom-style="Cover_subtitle" style="text-align:center; margin-top:18px;"}
|
||||||
|
<span style="font-size:20pt; font-weight:600;">Chlorophyll Index (CI) Monitoring Report — `r toupper(params$data_dir)` Estate (Week `r (if (!is.null(params$week)) params$week else format(as.Date(params$report_date), '%V'))`, `r format(as.Date(params$report_date), '%Y')`)</span>
|
||||||
|
:::
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Report Generated
|
||||||
|
|
||||||
**Farm Location:** `r toupper(project_dir)` Estate
|
**Farm Location:** `r toupper(project_dir)` Estate
|
||||||
**Report Period:** Week `r current_week` of `r year`
|
**Report Period:** Week `r current_week` of `r year`
|
||||||
|
**Report Generated on:** `r format(Sys.time(), "%B %d, %Y at %H:%M")`
|
||||||
|
**Farm Size Included in Analysis:**
|
||||||
**Data Source:** Planet Labs Satellite Imagery
|
**Data Source:** Planet Labs Satellite Imagery
|
||||||
**Analysis Type:** Chlorophyll Index (CI) Monitoring
|
**Analysis Type:** Chlorophyll Index (CI) Monitoring
|
||||||
**Report Generated on:** `r format(Sys.time(), "%B %d, %Y at %H:%M")`
|
|
||||||
|
|
||||||
## Report Structure
|
|
||||||
|
|
||||||
**Section 1:** Farm-wide analyses, summaries and Key Performance Indicators (KPIs)
|
|
||||||
**Section 3:** Explanation of the report, definitions, methodology, and CSV export structure
|
|
||||||
|
|
||||||
**Bonus:** Weekly field-level CSV export with per-field analysis and summary statistics (generated alongside this report)
|
|
||||||
|
|
||||||
## Key Insights
|
## Key Insights
|
||||||
|
|
||||||
```{r key_insights, echo=FALSE, results='asis'}
|
```{r key_insights, echo=FALSE, results='asis', eval=TRUE}
|
||||||
# Calculate key insights from KPI data
|
# Calculate key insights from KPI data
|
||||||
if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% names(summary_data)) {
|
if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% names(summary_data)) {
|
||||||
field_analysis_df <- summary_data$field_analysis
|
field_analysis_df <- summary_data$field_analysis
|
||||||
|
|
@ -502,13 +513,177 @@ if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% na
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Report Structure
|
||||||
|
|
||||||
|
**Section 1:** Cane supply zone analyses, summaries and Key Performance Indicators (KPIs)
|
||||||
|
**Section 2:** Explanation of the report, definitions, methodology, and CSV export structure
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
|
|
||||||
# Section 1: Farm-wide Analyses and KPIs
|
# Section 1: Farm-wide Analyses and KPIs
|
||||||
|
|
||||||
## Executive Summary - Key Performance Indicators
|
## 1.1 Overview of cane supply area, showing zones with number of acres being harvest ready
|
||||||
|
|
||||||
```{r combined_kpi_table, echo=FALSE}
|
```{r overview_map, fig.width=9, fig.height=7, fig.align="center", echo=FALSE}
|
||||||
|
# Create a hexbin overview map with ggplot
|
||||||
|
tryCatch({
|
||||||
|
# Try to load in the field analysis from this week
|
||||||
|
tryCatch({
|
||||||
|
# Ensure week is zero-padded (e.g., 04) to match filenames like *_week04_2026.xlsx
|
||||||
|
week_padded <- sprintf("%02d", as.numeric(current_week))
|
||||||
|
analysis_path <- file.path("laravel_app", "storage", "app", project_dir, "reports", "kpis", "field_analysis", paste0(params$data_dir, "_field_analysis_week", week_padded, "_", year, ".xlsx"))
|
||||||
|
analysis_data <- read_excel(analysis_path)
|
||||||
|
}, error = function(e) {
|
||||||
|
warning("Error loading field analysis data:", e$message)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Define constants
|
||||||
|
ACRE_CONV <- 4046.856
|
||||||
|
TARGET_CRS <- 32736
|
||||||
|
|
||||||
|
# Process polygons into points
|
||||||
|
points_processed <- field_boundaries_sf %>%
|
||||||
|
st_make_valid() %>%
|
||||||
|
mutate(
|
||||||
|
# Calculate area, convert to numeric to strip units, divide by conversion factor
|
||||||
|
area_ac = round(as.numeric(st_area(geometry)) / ACRE_CONV, 2)
|
||||||
|
) %>%
|
||||||
|
filter(
|
||||||
|
# Filter polygons with no surface area
|
||||||
|
!is.na(area_ac), area_ac > 0
|
||||||
|
) %>%
|
||||||
|
left_join (
|
||||||
|
# Add the status_trigger information
|
||||||
|
analysis_data %>% select(Field_id, Status_trigger),
|
||||||
|
by = c("field" = "Field_id")
|
||||||
|
) %>%
|
||||||
|
st_transform(crs = TARGET_CRS) %>%
|
||||||
|
st_centroid() %>%
|
||||||
|
bind_cols(st_coordinates(.))
|
||||||
|
|
||||||
|
# Subsetting
|
||||||
|
points_ready <- points_processed %>%
|
||||||
|
filter(Status_trigger == "harvest_ready")
|
||||||
|
points_not_ready <- points_processed %>%
|
||||||
|
filter(Status_trigger != "harvest_ready" | is.na(Status_trigger))
|
||||||
|
|
||||||
|
# Generate breaks for the plotting
|
||||||
|
breaks_vec <- c(0, 5, 10, 15, 20, 30, 35)
|
||||||
|
labels_vec <- as.character(breaks_vec)
|
||||||
|
labels_vec[length(labels_vec)] <- ">30"
|
||||||
|
labels_vec[1] <- "0.1"
|
||||||
|
|
||||||
|
# Set CRS
|
||||||
|
map_crs <- st_crs(points_processed)
|
||||||
|
|
||||||
|
# Create dummy point to anchor hexbin grids
|
||||||
|
dummy_point <- data.frame(
|
||||||
|
field = NA,
|
||||||
|
sub_field = NA,
|
||||||
|
area_ac = 0,
|
||||||
|
Status_trigger = NA,
|
||||||
|
X = min(points_processed$X, na.rm = TRUE),
|
||||||
|
Y = min(points_processed$Y, na.rm = TRUE),
|
||||||
|
geometry = NA
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add dummy point
|
||||||
|
dummy_point <- st_as_sf(dummy_point, coords = c("X", "Y"), crs = st_crs(points_ready))
|
||||||
|
dummy_point <- cbind(dummy_point, st_coordinates(dummy_point))
|
||||||
|
points_ready <- rbind(points_ready, dummy_point)
|
||||||
|
points_not_ready <- rbind(points_not_ready, dummy_point)
|
||||||
|
|
||||||
|
# Create the plot
|
||||||
|
hexbin <- ggplot() +
|
||||||
|
# Add OSM basemap
|
||||||
|
annotation_map_tile(type = "osm", zoom = 11, progress = "none", alpha = 0.5) +
|
||||||
|
# Add the hexbins for not ready points
|
||||||
|
geom_hex(
|
||||||
|
data = points_not_ready,
|
||||||
|
aes(x = X, y = Y, weight = area_ac, alpha = "Not harvest ready within 1 month."),
|
||||||
|
binwidth = c(1500, 1500),
|
||||||
|
fill = "#ffffff",
|
||||||
|
colour = "#0000009a",
|
||||||
|
linewidth = 0.1
|
||||||
|
) +
|
||||||
|
# Add the hexbins for ready points
|
||||||
|
geom_hex(
|
||||||
|
data = points_ready,
|
||||||
|
aes(x = X, y = Y, weight = area_ac),
|
||||||
|
binwidth = c(1500, 1500),
|
||||||
|
alpha = 0.9,
|
||||||
|
colour = "#0000009a",
|
||||||
|
linewidth = 0.1
|
||||||
|
) +
|
||||||
|
# Create colour bins
|
||||||
|
scale_fill_viridis_b(
|
||||||
|
option = "viridis",
|
||||||
|
direction = -1,
|
||||||
|
breaks = breaks_vec, # Use our 0-50 sequence
|
||||||
|
labels = labels_vec, # Use our custom ">50" labels
|
||||||
|
limits = c(0, 35), # Limit the scale
|
||||||
|
oob = scales::squish, # Squish higher values into the top bin
|
||||||
|
name = "Total Acres"
|
||||||
|
) +
|
||||||
|
# Titles
|
||||||
|
labs(
|
||||||
|
subtitle = "Acres of fields 'harvest ready within a month'"
|
||||||
|
) +
|
||||||
|
# Set the CRS
|
||||||
|
coord_sf(crs = map_crs) +
|
||||||
|
theme_minimal() +
|
||||||
|
# Legend trick to add the gray colours
|
||||||
|
scale_alpha_manual(
|
||||||
|
name = NULL, # No title needed for this specific legend item
|
||||||
|
values = 0.8 # This sets the actual transparency for the map
|
||||||
|
) +
|
||||||
|
# Legend customisation
|
||||||
|
theme(
|
||||||
|
legend.position = "right",
|
||||||
|
legend.box = "vertical",
|
||||||
|
legend.title.align = 0.5, # Center the legend title
|
||||||
|
plot.title = element_text(face = "bold", size = 16),
|
||||||
|
plot.subtitle = element_text(size = 11)
|
||||||
|
) +
|
||||||
|
# Customise the look of the horizontal bar
|
||||||
|
guides(
|
||||||
|
# The colour bar
|
||||||
|
fill = guide_coloursteps(
|
||||||
|
barwidth = 1,
|
||||||
|
barheight = 20,
|
||||||
|
title.position = "top",
|
||||||
|
order = 1
|
||||||
|
),
|
||||||
|
# The not ready box
|
||||||
|
alpha = guide_legend(
|
||||||
|
override.aes = list(
|
||||||
|
fill = "#ffffff",
|
||||||
|
colour = "#0000009a",
|
||||||
|
shape = 22
|
||||||
|
),
|
||||||
|
order = 2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
hexbin
|
||||||
|
|
||||||
|
}, error = function(e) {
|
||||||
|
warning("Error creating hexbin map:", e$message)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
## 1.2 Key Performance Indicators
|
||||||
|
|
||||||
|
```{r combined_kpi_table, echo=FALSE, eval=TRUE}
|
||||||
# Create summary KPI table from field_analysis_summary data
|
# Create summary KPI table from field_analysis_summary data
|
||||||
# This shows: Phases, Triggers, Area Change, and Total Farm acreage
|
# This shows: Phases, Triggers, Area Change, and Total Farm acreage
|
||||||
|
|
||||||
|
|
@ -717,8 +892,9 @@ if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% na
|
||||||
# The report renders KPI tables and field summaries from that data
|
# The report renders KPI tables and field summaries from that data
|
||||||
```
|
```
|
||||||
|
|
||||||
```{r load_field_boundaries, message=TRUE, warning=TRUE, include=FALSE}
|
```{r load_field_boundaries, message=TRUE, warning=TRUE, include=FALSE, eval=TRUE}
|
||||||
# Load field boundaries from parameters
|
# Load field boundaries from parameters
|
||||||
|
field_boundaries_sf <- sf::st_make_valid(field_boundaries_sf)
|
||||||
tryCatch({
|
tryCatch({
|
||||||
AllPivots0 <- field_boundaries_sf %>%
|
AllPivots0 <- field_boundaries_sf %>%
|
||||||
dplyr::filter(!is.na(field), !is.na(sub_field)) # Filter out NA field names
|
dplyr::filter(!is.na(field), !is.na(sub_field)) # Filter out NA field names
|
||||||
|
|
@ -736,29 +912,27 @@ tryCatch({
|
||||||
```
|
```
|
||||||
\newpage
|
\newpage
|
||||||
|
|
||||||
# Section 2: Methodology and Definitions
|
# Section 2: Support Document for weekly SmartCane data package.
|
||||||
|
|
||||||
## About This Report
|
## 1. About This Document
|
||||||
|
|
||||||
This automated report provides weekly analysis of sugarcane crop health using satellite-derived Chlorophyll Index (CI) measurements. The analysis supports:
|
This document is the support document to the SmartCane data file. It includes the definitions, explanatory calculations and suggestions for interpretations of the data as provided. For additional questions please feel free to contact SmartCane support, through your contact person, or via info@smartcane.org.
|
||||||
|
|
||||||
• Scouting of growth related issues that are in need of attention
|
|
||||||
• Timely actions can be taken such that negative impact is reduced
|
|
||||||
• Monitoring of the crop growth rates on the farms, providing evidence of performance
|
|
||||||
• Planning of harvest moment and mill logistics is supported such that optimal tonnage and sucrose levels can be harvested.
|
|
||||||
|
|
||||||
The base of the report is the Chlorophyll Index. The chlorophyll index identifies:
|
## 2. About the Data File
|
||||||
• Field-level crop health variations => target problem areas
|
|
||||||
• Weekly changes in crop vigor => scout for diseases and stress
|
|
||||||
• Areas requiring attention by the agricultural field teams
|
|
||||||
|
|
||||||
Key Features: - High-resolution satellite imagery analysis - Week-over-week change detection - Individual field performance metrics - Actionable insights for crop management
|
The data file is automatically populated based on normalized and indexed remote sensing images of provided polygons. Specific SmartCane algorithms provide tailored calculation results developed to support the sugarcane operations by:
|
||||||
|
|
||||||
### Explanation of the Report
|
• Supporting harvest planning mill-field logistics to ensure optimal tonnage and sucrose levels
|
||||||
|
• Monitoring of the crop growth rates on the farm, providing evidence of performance
|
||||||
|
• Identifying growth-related issues that are in need of attention
|
||||||
|
• Enabling timely actions to minimize negative impact
|
||||||
|
|
||||||
This report provides a detailed analysis (3x3m of resolution) of sugarcane fields based on satellite imagery. It supports you monitor crop health and development throughout the growing season. The data is processed weekly to give timely insights for optimal decisions.
|
Key Features of the data file: - High-resolution satellite imagery analysis - Week-over-week change detection - Individual field performance metrics - Actionable insights for crop management.
|
||||||
|
|
||||||
### What is the Chlorophyll Index (CI)?
|
|
||||||
|
|
||||||
|
#### *What is the Chlorophyll Index (CI)?*
|
||||||
|
|
||||||
The Chlorophyll Index (CI) is a vegetation index that measures the relative amount of chlorophyll in plant leaves. Chlorophyll is the green pigment responsible for photosynthesis in plants. Higher CI values indicate:
|
The Chlorophyll Index (CI) is a vegetation index that measures the relative amount of chlorophyll in plant leaves. Chlorophyll is the green pigment responsible for photosynthesis in plants. Higher CI values indicate:
|
||||||
• Greater photosynthetic activity
|
• Greater photosynthetic activity
|
||||||
|
|
@ -768,117 +942,77 @@ The Chlorophyll Index (CI) is a vegetation index that measures the relative amou
|
||||||
|
|
||||||
CI values typically range from 0 (bare soil or severely stressed vegetation) to 7+ (very healthy, dense vegetation). For sugarcane, values between 3-7 generally indicate good crop health, depending on the growth stage.
|
CI values typically range from 0 (bare soil or severely stressed vegetation) to 7+ (very healthy, dense vegetation). For sugarcane, values between 3-7 generally indicate good crop health, depending on the growth stage.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### What's Reported
|
```{r ci_fig, echo=FALSE, fig.align='right', out.width='40%', fig.cap="Chlorophyll Index Example"}
|
||||||
1. **Key Performance Indicators (KPIs):**
|
knitr::include_graphics("CI_graph_example.png")
|
||||||
The report provides a farm-wide analysis based on the Chlorophyll Index (CI) changes. KPIs are calculated field by field and summarized in tables.
|
```
|
||||||
|
|
||||||
- **Area Change:** Summarizes the proportion of field area that is improving, stable, or declining week-over-week, based on CI changes. Helps identify fields requiring immediate attention.
|
|
||||||
- **Improving areas:** Mean CI change > +0.5 CI units (positive growth trend)
|
|
||||||
- **Stable areas:** Mean CI change between -0.5 and +0.5 CI units (minimal change)
|
|
||||||
- **Declining areas:** Mean CI change < -0.5 CI units (negative growth trend)
|
|
||||||
|
|
||||||
- **Germination Acreage (CI-based):** Tracks the crop development phase based on CI values:
|
|
||||||
- **In Germination:** When 10% of field's CI > 2 AND less than 70% reaches CI ≥ 2
|
|
||||||
- **Post-Germination:** When 70% or more of field's CI ≥ 2 (crop has emerged and established)
|
|
||||||
- Reports total acres and number of fields in each phase
|
|
||||||
|
|
||||||
- **Harvested Acreage:** ⚠️ **DUMMY DATA** - Currently returns zero values as harvesting detection method is under development
|
|
||||||
- Future implementation will detect harvested fields based on CI drops, backscatter changes, and temporal patterns
|
|
||||||
|
|
||||||
- **Mature Acreage:** ⚠️ **DUMMY DATA** - Currently returns zero values as maturity definition is under development
|
|
||||||
- Future implementation will identify mature fields based on stable high CI over multiple weeks (relative to field's maximum)
|
|
||||||
- Stability assessment accounts for field-specific CI ranges rather than absolute thresholds
|
|
||||||
|
|
||||||
2. **Farm Overview Table:**
|
|
||||||
Presents numerical field-level results for all KPIs.
|
|
||||||
|
|
||||||
---
|
### Data File Structure and Columns
|
||||||
|
The data file is organized in rows, one row per agricultural field (polygon), and columns, providing field data, actual measurements, calculation results and descriptions. The data file can be directly integration with existing farm management systems for further analysis. Each column is described hereunder:
|
||||||
|
|
||||||
## Weekly Field Analysis CSV Export
|
| **Nr.** | **Column** | **Description** | **Example** |
|
||||||
|
|-----|---------------|----------------------------------------------------------------------------|-------------|
|
||||||
|
|-----|---------------|----------------------------------------------------------------------------|-------------|
|
||||||
|
| **1** | **Field_id** | Unique identifier for a cane field combining field name and sub-field number. This can be the same as Field_Name but is also helpful in keeping track of cane fields should they change, split or merge. | "00110" |
|
||||||
|
| **2** | **Farm_Section** | Sub-area or section name | "Section a" |
|
||||||
|
| **3** | **Field_name** | Client Name or label assigned to a cane field. | "Tinga1" |
|
||||||
|
| **4** | **Acreage** | Field size in acres | "4.5" |
|
||||||
|
| **5** | **Status_trigger** | Shows changes in crop status worth alerting. More detailed explanation of the possible alerts is written down under key concepts. | "Harvest_ready" |
|
||||||
|
| **6** | **Last_harvest_or_planting_date** | Date of most recent harvest as per satellite detection algorithm / or manual entry | “2025-03-14” |
|
||||||
|
| **7** |**Age_week** | Time elapsed since planting/harvest in weeks; used to predict expected growth phases. Reflects planting/harvest date (left). | "40" |
|
||||||
|
| **8** | **Phase (age based)** | Current growth phase (e.g., germination, tillering, stem elongation, grain fill, mature) inferred from crop age | "Maturation" |
|
||||||
|
| **9** | **Germination_progress** | Estimated percentage or stage of germination/emergence based on CI patterns and age. This goes for young fields (age < 4 months). Remain at 100% when finished. | "maturation_progressing" |
|
||||||
|
| **10** | **Mean_CI** | Average Chlorophyll Index value across the field; higher values indicate healthier, greener vegetation. Calculated on a 7-day merged weekly image | "3.95" |
|
||||||
|
| **11** | **Weekly CI Change** | Week-over-week change in Mean_CI; positive values indicate greening/growth, negative values indicate yellowing/decline | "0.79" |
|
||||||
|
| **12** | **Four_week_trend** | Long term change in mean CI; smoothed trend (strong growth, growth, no growth, decline, strong decline) | "0.87" |
|
||||||
|
| **13** | **CI_range** | Min-max Chlorophyll Index values within the field; wide ranges indicate spatial heterogeneity/patches. Derived from week mosaic | "3.6-5.6" |
|
||||||
|
| **14** | **CI_Percentiles** | The CI-range without border effects | "3.5-4.4" |
|
||||||
|
| **15** | **CV** | Coefficient of variation of CI; measures field uniformity (lower = more uniform, >0.25 = poor uniformity). Derived from week mosaic. In percentages | "10.01%" |
|
||||||
|
| **16** | **CV_Trend_Short_Term** | Trend of CV over two weeks. Indicating short-term heterogeneity | "0.15" |
|
||||||
|
| **17** | **CV_Trend_Long_Term** | Slope of 8-week trend line. | "0.32" |
|
||||||
|
| **18** | **Imminent_prob** | Probability (0-1) that the field is ready for harvest based on LSTM harvest model predictions | "0.8" |
|
||||||
|
| **19** | **Cloud_pct_clear** | Percentage of field visible in the satellite image (unobstructed by clouds); lower values indicate poor data quality | "70%" |
|
||||||
|
| **20** | **Cloud_category** | Classification of cloud cover level (e.g., clear, partial, heavy); indicates confidence in CI measurements | "Partial Coverage" |
|
||||||
|
|
||||||
In addition to this Word report, a detailed **field-level CSV export** is generated each week for direct integration with farm management systems and further analysis.
|
|
||||||
|
|
||||||
### CSV Structure and Columns
|
|
||||||
|
|
||||||
The CSV contains per-field analysis followed by summary statistics:
|
\newpage
|
||||||
|
# 3. Key Concepts
|
||||||
|
|
||||||
**Per-Field Rows** (one row per field):
|
#### *Growth Phases (Age-Based)*
|
||||||
|
|
||||||
| Column | Description | Example |
|
|
||||||
|--------|-------------|---------|
|
|
||||||
| **Field_id** | Unique field identifier | "00110" |
|
|
||||||
| **Farm_Section** | Sub-area or section name | "a" |
|
|
||||||
| **Field_name** | Field name for reference | "Tinga1" |
|
|
||||||
| **Acreage** | Field size in acres | 40.5 |
|
|
||||||
| **Weekly_ci_change** | CI change from previous week with range; format: `±change (min-max)` | "+2.1 ± 0.15" |
|
|
||||||
| **Age_week** | Field age in weeks since planting | 40 |
|
|
||||||
| **Phase (age based)** | Age-based growth phase | "Maturation" |
|
|
||||||
| **nmr_weeks_in_this_phase** | Number of consecutive weeks in current phase | 2 |
|
|
||||||
| **Status_trigger** | Current field status (one per field) | "maturation_progressing" |
|
|
||||||
| **CI_range** | Min-max CI values across field pixels | "3.1-5.2" |
|
|
||||||
| **CV** | Coefficient of Variation (field uniformity) | 0.158 |
|
|
||||||
|
|
||||||
**Summary Statistic Rows** (at end of CSV):
|
|
||||||
|
|
||||||
| Field_id | Description | Acreage | Notes |
|
|
||||||
|----------|-------------|---------|-------|
|
|
||||||
| `Total_acreage_weekly_change(+)` | Fields improving week-over-week (CI increase > 0.2) | numeric | Sum of improving field acres |
|
|
||||||
| `Total_acreage_weekly_change(-)` | Fields declining week-over-week (CI decrease < -0.2) | numeric | Sum of declining field acres |
|
|
||||||
| `Total_acreage_weekly_stable` | Fields with stable CI (±0.2) | numeric | Sum of stable field acres |
|
|
||||||
| `Total_acreage_weekly_germinated` | Total acreage in Germination phase | numeric | Age 0-6 weeks |
|
|
||||||
| `Total_acreage_weekly_harvested` | Total acreage ready for harvest | numeric | Age 45+ weeks or `harvest_ready` trigger |
|
|
||||||
| `Total_acreage_weekly_mature` | Total acreage in Maturation phase | numeric | Age 39+ weeks |
|
|
||||||
|
|
||||||
### Key Concepts
|
|
||||||
|
|
||||||
#### 1. **Growth Phases (Age-Based)**
|
|
||||||
|
|
||||||
Each field is assigned to one of four growth phases based on age in weeks since planting:
|
Each field is assigned to one of four growth phases based on age in weeks since planting:
|
||||||
|
|
||||||
| Phase | Age Range | Characteristics |
|
| **Phase** | **Age Range** | **Characteristics** |
|
||||||
|-------|-----------|-----------------|
|
|-------|-----------|-----------------|
|
||||||
| **Germination** | 0-6 weeks | Crop emergence and early establishment; high variability expected |
|
| Germination | 0-6 weeks | Crop emergence and early establishment; high variability expected |
|
||||||
| **Tillering** | 4-16 weeks | Shoot multiplication and plant establishment; rapid growth phase |
|
| Tillering | 4-16 weeks | Shoot multiplication and plant establishment; rapid growth phase |
|
||||||
| **Grand Growth** | 17-39 weeks | Peak vegetative growth; maximum height and biomass accumulation |
|
| Grand Growth | 17-39 weeks | Peak vegetative growth; maximum height and biomass accumulation |
|
||||||
| **Maturation** | 39+ weeks | Ripening phase; sugar accumulation and preparation for harvest |
|
| Maturation | 39+ weeks | Ripening phase; sugar accumulation and preparation for harvest |
|
||||||
|
|
||||||
*Note: Phase overlaps at boundaries (e.g., weeks 4 and 39) are assigned to the earlier phase.*
|
|
||||||
|
|
||||||
#### 2. **Status Triggers (Non-Exclusive)**
|
|
||||||
|
|
||||||
Status triggers indicate the current field condition based on CI and age-related patterns. Each field receives **one trigger** reflecting its most relevant status:
|
#### *Status Alert*
|
||||||
|
|
||||||
| Trigger | Condition | Phase | Messaging |
|
Status alerts indicate the current field condition based on CI and age-related patterns. Each field receives **one alert** reflecting its most relevant status:
|
||||||
|
|
||||||
|
| **Alert** | **Condition** | **Phase** | **Messaging** |
|
||||||
|---------|-----------|-------|-----------|
|
|---------|-----------|-------|-----------|
|
||||||
| `germination_started` | 10% of field CI > 2 | Germination (0-6) | Crop emerging |
|
| Ready for harvest-check | Harvest model > 0.50 and crop is mature | Active from 52 weeks onwards | Ready for harvest-check |
|
||||||
| `germination_complete` | 70% of field CI ≥ 2 | Germination (0-6) | Germination finished |
|
| harvested/bare | Field of 50 weeks or older either shows mean CI values lower than 1.5 (for a maximum of three weeks) OR drops from higher CI to lower than 1.5. Alert drops if CI rises and passes 1.5 again | Maturation (39+) | Harvested or bare field |
|
||||||
| `stress_detected_whole_field` | CI decline > -1.5 + low CV | Any | Check irrigation/disease/weeding |
|
| stress_detected_whole_field | Mean CI on field drops by 2+ points but field mean CI remains higher than 1.5 | Any | Strong decline in crop health |
|
||||||
| `strong_recovery` | CI increase > +1.5 | Any | Growth accelerating |
|
|
||||||
| `growth_on_track` | CI consistently increasing | Tillering/Grand Growth (4-39) | Normal progression |
|
|
||||||
| `maturation_progressing` | High CI, stable/declining | Maturation (39-45) | Ripening phase |
|
|
||||||
| `harvest_ready` | Age ≥ 45 weeks | Maturation (45+) | Ready to harvest |
|
|
||||||
|
|
||||||
#### 3. **Phase Transition Tracking**
|
|
||||||
|
|
||||||
The `nmr_weeks_in_this_phase` column tracks how long a field has been in its current phase:
|
#### *Harvest Date and Harvest Imminent*
|
||||||
|
The SmartCane algorithm calculates the last harvest date and the probability of harvest approaching in the next 4 weeks. Two different algorithms are used.
|
||||||
|
The **last harvest date** is a timeseries analyses of the CI levels of the past years, based on clean factory managed fields as data set for the machine learning, a reliability of over 90% has been reached. Smallholder managed fields of small size (0.3 acres) have specific side effects and field management characteristics, that influence the model results.
|
||||||
|
**Imminent_probability** of harvest is a prediction algorithm, estimating the likelihood of a crop ready to be harvested in the near future. This prediction takes the CI-levels into consideration, building on the vegetative development of sugarcane in the last stage of Maturation, where all sucrose is pulled into the stalk, depleting the leaves from energy and productive function, reducing the levels of CI in the leave tissue.
|
||||||
|
Both algorithms are not always in sync, and can have contradictory results. Wider field characteristics analyses is suggested if such contradictory calculation results occur.
|
||||||
|
|
||||||
- **Initialization:** First time seeing a field = 1 week
|
|
||||||
- **Same phase:** Increments by 1 each week
|
|
||||||
- **Phase change:** Resets to 1 when age-based phase changes
|
|
||||||
|
|
||||||
This is achieved by comparing current week's phase assignment to the previous week's CSV. The script loads `[project]_field_analysis_week[XX-1].csv` to detect transitions.
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```
|
|
||||||
Week 29: Field Tinga1 enters Maturation phase (age 39) → nmr_weeks_in_this_phase = 1
|
|
||||||
Week 30: Field Tinga1 still in Maturation (age 40) → nmr_weeks_in_this_phase = 2
|
|
||||||
Week 31: Field Tinga1 still in Maturation (age 41) → nmr_weeks_in_this_phase = 3
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
## Report Metadata
|
## Report Metadata
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue