Major Changes: - NEW: Scripts 09 & 10 for KPI calculation and enhanced reporting - NEW: Shell script wrappers (01-10) for easier execution - NEW: R packages flextable and officer for enhanced Word reports - NEW: DEPLOYMENT_README.md with complete deployment guide - RENAMED: Numbered R scripts (02, 03, 04) for clarity - REMOVED: Old package management scripts (using renv only) - UPDATED: Workflow now uses scripts 09->10 instead of 05 Files Changed: 90+ files New Packages: flextable, officer New Scripts: 09_run_calculate_kpis.sh, 10_run_kpi_report.sh Documentation: DEPLOYMENT_README.md, EMAIL_TO_ADMIN.txt See DEPLOYMENT_README.md for full deployment instructions.
315 lines
9.4 KiB
Plaintext
315 lines
9.4 KiB
Plaintext
|
||
R version 4.4.3 (2025-02-28 ucrt) -- "Trophy Case"
|
||
Copyright (C) 2025 The R Foundation for Statistical Computing
|
||
Platform: x86_64-w64-mingw32/x64
|
||
|
||
R is free software and comes with ABSOLUTELY NO WARRANTY.
|
||
You are welcome to redistribute it under certain conditions.
|
||
Type 'license()' or 'licence()' for distribution details.
|
||
|
||
Natural language support but running in an English locale
|
||
|
||
R is a collaborative project with many contributors.
|
||
Type 'contributors()' for more information and
|
||
'citation()' on how to cite R or R packages in publications.
|
||
|
||
Type 'demo()' for some demos, 'help()' for on-line help, or
|
||
'help.start()' for an HTML browser interface to help.
|
||
Type 'q()' to quit R.
|
||
|
||
- Project 'C:/Users/timon/Resilience BV/4020 SCane ESA DEMO - Documenten/General/4020 SCDEMO Team/4020 TechnicalData/WP3/smartcane_v2/smartcane' loaded. [renv 1.1.4]
|
||
> # 09_CALCULATE_KPIS.R
|
||
> # ===================
|
||
> # This script calculates 6 Key Performance Indicators (KPIs) for sugarcane monitoring:
|
||
> # 1. Field Uniformity Summary
|
||
> # 2. Farm-wide Area Change Summary
|
||
> # 3. TCH Forecasted
|
||
> # 4. Growth Decline Index
|
||
> # 5. Weed Presence Score
|
||
> # 6. Gap Filling Score (placeholder)
|
||
> #
|
||
> # Usage: Rscript 09_calculate_kpis.R [end_date] [offset] [project_dir]
|
||
> # - end_date: End date for KPI calculation (YYYY-MM-DD format), default: today
|
||
> # - offset: Number of days to look back (not currently used for KPIs, but for consistency)
|
||
> # - project_dir: Project directory name (e.g., "aura", "esa")
|
||
>
|
||
> # 1. Load required libraries
|
||
> # -------------------------
|
||
> suppressPackageStartupMessages({
|
||
+ library(here)
|
||
+ library(sf)
|
||
+ library(terra)
|
||
+ library(dplyr)
|
||
+ library(tidyr)
|
||
+ library(lubridate)
|
||
+ library(readr)
|
||
+ library(caret)
|
||
+ library(CAST)
|
||
+ library(randomForest)
|
||
+ })
|
||
>
|
||
> # 2. Main function
|
||
> # --------------
|
||
> main <- function() {
|
||
+ # Process command line arguments
|
||
+ args <- commandArgs(trailingOnly = TRUE)
|
||
+
|
||
+ # Process end_date argument
|
||
+ if (length(args) >= 1 && !is.na(args[1])) {
|
||
+ end_date <- as.Date(args[1])
|
||
+ if (is.na(end_date)) {
|
||
+ warning("Invalid end_date provided. Using default (current date).")
|
||
+ end_date <- Sys.Date()
|
||
+ }
|
||
+ } else {
|
||
+ end_date <- Sys.Date()
|
||
+ }
|
||
+
|
||
+ # Process offset argument (for consistency with other scripts, not currently used)
|
||
+ if (length(args) >= 2 && !is.na(args[2])) {
|
||
+ offset <- as.numeric(args[2])
|
||
+ if (is.na(offset) || offset <= 0) {
|
||
+ warning("Invalid offset provided. Using default (7 days).")
|
||
+ offset <- 7
|
||
+ }
|
||
+ } else {
|
||
+ offset <- 7
|
||
+ }
|
||
+
|
||
+ # Process project_dir argument
|
||
+ if (length(args) >= 3 && !is.na(args[3])) {
|
||
+ project_dir <- as.character(args[3])
|
||
+ } else {
|
||
+ project_dir <- "esa" # Default project
|
||
+ }
|
||
+
|
||
+ # Make project_dir available globally so parameters_project.R can use it
|
||
+ assign("project_dir", project_dir, envir = .GlobalEnv)
|
||
+
|
||
+ # 3. Load utility functions and project configuration
|
||
+ # --------------------------------------------------
|
||
+
|
||
+ tryCatch({
|
||
+ source(here("r_app", "crop_messaging_utils.R"))
|
||
+ }, error = function(e) {
|
||
+ stop("Error loading crop_messaging_utils.R: ", e$message)
|
||
+ })
|
||
+
|
||
+ tryCatch({
|
||
+ source(here("r_app", "kpi_utils.R"))
|
||
+ }, error = function(e) {
|
||
+ stop("Error loading kpi_utils.R: ", e$message)
|
||
+ })
|
||
+
|
||
+ # Load project parameters (this sets up all directory paths and field boundaries)
|
||
+ tryCatch({
|
||
+ source(here("r_app", "parameters_project.R"))
|
||
+ }, error = function(e) {
|
||
+ stop("Error loading parameters_project.R: ", e$message)
|
||
+ })
|
||
+
|
||
+ # Load growth model utils if available (for yield prediction)
|
||
+ tryCatch({
|
||
+ source(here("r_app", "growth_model_utils.R"))
|
||
+ }, error = function(e) {
|
||
+ warning("growth_model_utils.R not found, yield prediction KPI will use placeholder data")
|
||
+ })
|
||
+
|
||
+ # Check if required variables exist
|
||
+ if (!exists("project_dir")) {
|
||
+ stop("project_dir must be set before running this script")
|
||
+ }
|
||
+
|
||
+ if (!exists("field_boundaries_sf") || is.null(field_boundaries_sf)) {
|
||
+ stop("Field boundaries not loaded. Check parameters_project.R initialization.")
|
||
+ }
|
||
+
|
||
+ # 4. Calculate all KPIs
|
||
+ # -------------------
|
||
+ output_dir <- file.path(reports_dir, "kpis")
|
||
+
|
||
+ kpi_results <- calculate_all_kpis(
|
||
+ report_date = end_date,
|
||
+ output_dir = output_dir,
|
||
+ field_boundaries_sf = field_boundaries_sf,
|
||
+ harvesting_data = harvesting_data,
|
||
+ cumulative_CI_vals_dir = cumulative_CI_vals_dir,
|
||
+ weekly_CI_mosaic = weekly_CI_mosaic,
|
||
+ reports_dir = reports_dir,
|
||
+ project_dir = project_dir
|
||
+ )
|
||
+
|
||
+ # 5. Print summary
|
||
+ # --------------
|
||
+ cat("\n=== KPI CALCULATION SUMMARY ===\n")
|
||
+ cat("Report Date:", as.character(kpi_results$metadata$report_date), "\n")
|
||
+ cat("Current Week:", kpi_results$metadata$current_week, "\n")
|
||
+ cat("Previous Week:", kpi_results$metadata$previous_week, "\n")
|
||
+ cat("Total Fields Analyzed:", kpi_results$metadata$total_fields, "\n")
|
||
+ cat("Calculation Time:", as.character(kpi_results$metadata$calculation_time), "\n")
|
||
+
|
||
+ cat("\nField Uniformity Summary:\n")
|
||
+ print(kpi_results$field_uniformity_summary)
|
||
+
|
||
+ cat("\nArea Change Summary:\n")
|
||
+ print(kpi_results$area_change)
|
||
+
|
||
+ cat("\nTCH Forecasted:\n")
|
||
+ print(kpi_results$tch_forecasted)
|
||
+
|
||
+ cat("\nGrowth Decline Index:\n")
|
||
+ print(kpi_results$growth_decline)
|
||
+
|
||
+ cat("\nWeed Presence Score:\n")
|
||
+ print(kpi_results$weed_presence)
|
||
+
|
||
+ cat("\nGap Filling Score:\n")
|
||
+ print(kpi_results$gap_filling)
|
||
+
|
||
+ cat("\n=== KPI CALCULATION COMPLETED ===\n")
|
||
+ }
|
||
>
|
||
> # 6. Script execution
|
||
> # -----------------
|
||
> if (sys.nframe() == 0) {
|
||
+ main()
|
||
+ }
|
||
[INFO] 2025-10-08 15:39:29 - Initializing project with directory: esa
|
||
[1] "model using cumulative_CI,DOY will be trained now..."
|
||
note: only 1 unique complexity parameters in default grid. Truncating the grid to 1 .
|
||
|
||
+ Fold1: mtry=2
|
||
- Fold1: mtry=2
|
||
+ Fold2: mtry=2
|
||
- Fold2: mtry=2
|
||
+ Fold3: mtry=2
|
||
- Fold3: mtry=2
|
||
+ Fold4: mtry=2
|
||
- Fold4: mtry=2
|
||
+ Fold5: mtry=2
|
||
- Fold5: mtry=2
|
||
Aggregating results
|
||
Fitting final model on full training set
|
||
[1] "maximum number of models that still need to be trained: 3"
|
||
[1] "model using cumulative_CI,CI_per_day will be trained now..."
|
||
note: only 1 unique complexity parameters in default grid. Truncating the grid to 1 .
|
||
|
||
+ Fold1: mtry=2
|
||
- Fold1: mtry=2
|
||
+ Fold2: mtry=2
|
||
- Fold2: mtry=2
|
||
+ Fold3: mtry=2
|
||
- Fold3: mtry=2
|
||
+ Fold4: mtry=2
|
||
- Fold4: mtry=2
|
||
+ Fold5: mtry=2
|
||
- Fold5: mtry=2
|
||
Aggregating results
|
||
Fitting final model on full training set
|
||
[1] "maximum number of models that still need to be trained: 2"
|
||
[1] "model using DOY,CI_per_day will be trained now..."
|
||
note: only 1 unique complexity parameters in default grid. Truncating the grid to 1 .
|
||
|
||
+ Fold1: mtry=2
|
||
- Fold1: mtry=2
|
||
+ Fold2: mtry=2
|
||
- Fold2: mtry=2
|
||
+ Fold3: mtry=2
|
||
- Fold3: mtry=2
|
||
+ Fold4: mtry=2
|
||
- Fold4: mtry=2
|
||
+ Fold5: mtry=2
|
||
- Fold5: mtry=2
|
||
Aggregating results
|
||
Fitting final model on full training set
|
||
[1] "maximum number of models that still need to be trained: 1"
|
||
[1] "vars selected: cumulative_CI,DOY with RMSE 24.808"
|
||
[1] "model using additional variable CI_per_day will be trained now..."
|
||
note: only 2 unique complexity parameters in default grid. Truncating the grid to 2 .
|
||
|
||
+ Fold1: mtry=2
|
||
- Fold1: mtry=2
|
||
+ Fold1: mtry=3
|
||
- Fold1: mtry=3
|
||
+ Fold2: mtry=2
|
||
- Fold2: mtry=2
|
||
+ Fold2: mtry=3
|
||
- Fold2: mtry=3
|
||
+ Fold3: mtry=2
|
||
- Fold3: mtry=2
|
||
+ Fold3: mtry=3
|
||
- Fold3: mtry=3
|
||
+ Fold4: mtry=2
|
||
- Fold4: mtry=2
|
||
+ Fold4: mtry=3
|
||
- Fold4: mtry=3
|
||
+ Fold5: mtry=2
|
||
- Fold5: mtry=2
|
||
+ Fold5: mtry=3
|
||
- Fold5: mtry=3
|
||
Aggregating results
|
||
Selecting tuning parameters
|
||
Fitting mtry = 3 on full training set
|
||
[1] "maximum number of models that still need to be trained: 0"
|
||
[1] "vars selected: cumulative_CI,DOY with RMSE 24.808"
|
||
field_groups count value
|
||
75% Top 25% 3 96.2
|
||
50% Average 7 93.0
|
||
25% Lowest 25% 2 84.0
|
||
Total area forecasted 12 219.0
|
||
|
||
=== KPI CALCULATION SUMMARY ===
|
||
Report Date: 2025-10-08
|
||
Current Week: 40
|
||
Previous Week: 39
|
||
Total Fields Analyzed: 12
|
||
Calculation Time: 2025-10-08 15:39:34.583434
|
||
|
||
Field Uniformity Summary:
|
||
uniformity_level count percent
|
||
1 Excellent 0 0
|
||
2 Good 0 0
|
||
3 Moderate 0 0
|
||
4 Poor 0 0
|
||
|
||
Area Change Summary:
|
||
change_type hectares percent
|
||
1 Improving areas 0 0
|
||
2 Stable areas 0 0
|
||
3 Declining areas 0 0
|
||
4 Total area 0 100
|
||
|
||
TCH Forecasted:
|
||
field_groups count value
|
||
75% Top 25% 3 96.2
|
||
50% Average 7 93.0
|
||
25% Lowest 25% 2 84.0
|
||
Total area forecasted 12 219.0
|
||
|
||
Growth Decline Index:
|
||
risk_level count percent
|
||
1 High 0 0
|
||
2 Low 0 0
|
||
3 Moderate 0 0
|
||
4 Very-high 0 0
|
||
|
||
Weed Presence Score:
|
||
weed_risk_level field_count percent
|
||
1 Canopy closed - Low weed risk 4 33.3
|
||
2 High 0 0.0
|
||
3 Low 0 0.0
|
||
4 Moderate 0 0.0
|
||
|
||
Gap Filling Score:
|
||
# A tibble: 1 × 3
|
||
gap_level field_count percent
|
||
<chr> <int> <dbl>
|
||
1 <NA> 12 100
|
||
|
||
=== KPI CALCULATION COMPLETED ===
|
||
There were 50 or more warnings (use warnings() to see the first 50)
|
||
>
|
||
> proc.time()
|
||
user system elapsed
|
||
11.93 0.93 13.45
|