# ============================================================================ # SCRIPT 10: Create Per-Field TIFFs (Data Organization & Splitting) # ============================================================================ # PURPOSE: # Split full-farm satellite TIFFs into per-field file structure. Supports # two phases: legacy data migration and ongoing new downloads. Transforms # single large-file architecture into per-field directory structure for # clean aggregation in downstream scripts (Script 20, 40, 80/90). # # INPUT DATA: # - Source: laravel_app/storage/app/{project}/merged_tif/ or merged_final_tif/ # - Format: GeoTIFF (4-band RGB+NIR or 5-band with CI) # - Naming: {YYYY-MM-DD}.tif (full farm mosaic) # # OUTPUT DATA: # - Destination: laravel_app/storage/app/{project}/field_tiles/ # - Format: GeoTIFF (4-band RGB+NIR, same as input) # - Structure: field_tiles/{FIELD}/{YYYY-MM-DD}.tif # - Naming: Per-field GeoTIFFs organized by field and date # # USAGE: # Rscript 10_create_per_field_tiffs.R [project] # # Example (Windows PowerShell): # & "C:\Program Files\R\R-4.4.3\bin\x64\Rscript.exe" r_app/10_create_per_field_tiffs.R angata # # PARAMETERS: # - project: Project name (character) - angata, chemba, xinavane, esa, simba # # CLIENT TYPES: # - cane_supply (ANGATA): Yes - primary data organization script # - agronomic_support (AURA): Yes - supports field-level analysis # # DEPENDENCIES: # - Packages: terra, sf, tidyverse # - Utils files: parameters_project.R, 00_common_utils.R, 10_create_per_field_tiffs_utils.R # - External data: Field boundaries (pivot.geojson) # - Data directories: merged_tif/, field_tiles/ (created if missing) # # NOTES: # - Supports two-phase migration: legacy (merged_final_tif) and ongoing (merged_tif) # - Automatically detects and handles field boundaries from pivot.geojson # - Geometry validation and repair applied via st_make_valid() # - Critical for downstream Scripts 20, 40, and KPI calculations # - Creates per-field structure that enables efficient per-field processing # # RELATED ISSUES: # SC-111: Script 10 refactoring and geometry repair # SC-112: Utilities restructuring (uses 00_common_utils.R) # # ============================================================================ library(terra) library(sf) # ============================================================================== # LOAD CENTRALIZED PARAMETERS & PATHS # ============================================================================== source(here::here("r_app", "parameters_project.R")) source(here::here("r_app", "00_common_utils.R")) source(here::here("r_app", "10_create_per_field_tiffs_utils.R")) # Get project parameter from command line args <- commandArgs(trailingOnly = TRUE) if (length(args) == 0) { PROJECT <- "angata" } else { PROJECT <- args[1] } # Load centralized path structure (creates all directories automatically) paths <- setup_project_directories(PROJECT) safe_log(paste("Project:", PROJECT)) safe_log(paste("Base path:", paths$laravel_storage_dir)) safe_log(paste("Data dir:", paths$data_dir)) # Load field boundaries using data_dir (not field_boundaries_path) # load_field_boundaries() expects a directory and builds the file path internally fields_data <- load_field_boundaries(paths$data_dir) fields <- fields_data$field_boundaries_sf # Define input and output directories (from centralized paths) merged_tif_dir <- paths$merged_tif_folder field_tiles_dir <- paths$field_tiles_dir field_tiles_ci_dir <- paths$field_tiles_ci_dir # PHASE 1: Process new downloads (always runs) # Pass field_tiles_ci_dir so it can skip dates already migrated process_result <- process_new_merged_tif(merged_tif_dir, field_tiles_dir, fields, field_tiles_ci_dir) safe_log("\n========================================", "INFO") safe_log("FINAL SUMMARY", "INFO") safe_log("========================================", "INFO") safe_log(paste("Processing: created =", process_result$total_created, ", skipped =", process_result$total_skipped, ", errors =", process_result$total_errors), "INFO") safe_log("Script 10 complete", "INFO") safe_log("========================================\n", "INFO")