Merge branch 'code-improvements' into SC-204
This commit is contained in:
commit
573733cfb4
|
|
@ -9,7 +9,8 @@
|
|||
"Bash(/c/Users/timon/AppData/Local/r-miniconda/python.exe -c \":*)",
|
||||
"Bash(python3 -c \":*)",
|
||||
"Bash(Rscript -e \":*)",
|
||||
"Bash(\"/c/Program Files/R/R-4.4.3/bin/x64/Rscript.exe\" -e \":*)"
|
||||
"Bash(\"/c/Program Files/R/R-4.4.3/bin/x64/Rscript.exe\" -e \":*)",
|
||||
"Read(//c/Users/timon/Documents/SmartCane_code/r_app/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
186
create_field_checklist.R
Normal file
186
create_field_checklist.R
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
# Creates an Excel checklist from pivot.geojson
|
||||
# Fields sorted largest to smallest, split across Timon/Joey/Dimitra side-by-side
|
||||
|
||||
# Install packages if needed
|
||||
if (!requireNamespace("jsonlite", quietly = TRUE)) install.packages("jsonlite", repos = "https://cloud.r-project.org")
|
||||
if (!requireNamespace("openxlsx", quietly = TRUE)) install.packages("openxlsx", repos = "https://cloud.r-project.org")
|
||||
|
||||
library(jsonlite)
|
||||
library(openxlsx)
|
||||
|
||||
# ---- Load GeoJSON ----
|
||||
geojson_path <- "laravel_app/storage/app/angata/pivot.geojson"
|
||||
gj <- fromJSON(geojson_path, simplifyVector = FALSE)
|
||||
features <- gj$features
|
||||
cat(sprintf("Total features: %d\n", length(features)))
|
||||
|
||||
# ---- Shoelace area (degrees²) ----
|
||||
shoelace <- function(ring) {
|
||||
n <- length(ring)
|
||||
lons <- sapply(ring, `[[`, 1)
|
||||
lats <- sapply(ring, `[[`, 2)
|
||||
area <- 0
|
||||
for (i in seq_len(n)) {
|
||||
j <- (i %% n) + 1
|
||||
area <- area + lons[i] * lats[j] - lons[j] * lats[i]
|
||||
}
|
||||
abs(area) / 2
|
||||
}
|
||||
|
||||
# ---- Approx area in m² ----
|
||||
area_m2 <- function(ring) {
|
||||
R <- 6371000
|
||||
lats <- sapply(ring, `[[`, 2)
|
||||
mean_lat <- mean(lats)
|
||||
lat_rad <- mean_lat * pi / 180
|
||||
m_per_deg_lat <- R * pi / 180
|
||||
m_per_deg_lon <- R * cos(lat_rad) * pi / 180
|
||||
shoelace(ring) * m_per_deg_lat * m_per_deg_lon
|
||||
}
|
||||
|
||||
# ---- Compute feature areas ----
|
||||
compute_area <- function(feat) {
|
||||
geom <- feat$geometry
|
||||
total <- 0
|
||||
if (geom$type == "MultiPolygon") {
|
||||
for (polygon in geom$coordinates) {
|
||||
total <- total + area_m2(polygon[[1]]) # outer ring
|
||||
}
|
||||
} else if (geom$type == "Polygon") {
|
||||
total <- total + area_m2(geom$coordinates[[1]])
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
field_names <- sapply(features, function(f) f$properties$field)
|
||||
areas_m2 <- sapply(features, compute_area)
|
||||
areas_ha <- areas_m2 / 10000
|
||||
|
||||
df <- data.frame(
|
||||
field = field_names,
|
||||
area_ha = round(areas_ha, 2),
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
|
||||
# Sort largest to smallest
|
||||
df <- df[order(df$area_ha, decreasing = TRUE), ]
|
||||
df$rank <- seq_len(nrow(df))
|
||||
|
||||
cat("\nTop 10 fields by area:\n")
|
||||
print(head(df[, c("rank", "field", "area_ha")], 10))
|
||||
|
||||
# ---- Split: Timon=1st, Joey=2nd, Dimitra=3rd ----
|
||||
idx <- seq_len(nrow(df))
|
||||
timon <- df[idx %% 3 == 1, ]
|
||||
joey <- df[idx %% 3 == 2, ]
|
||||
dimitra <- df[idx %% 3 == 0, ]
|
||||
|
||||
cat(sprintf("\nSplit: Timon=%d, Joey=%d, Dimitra=%d\n",
|
||||
nrow(timon), nrow(joey), nrow(dimitra)))
|
||||
|
||||
# ---- Build Excel ----
|
||||
wb <- createWorkbook()
|
||||
addWorksheet(wb, "Field Checklist")
|
||||
|
||||
# Header colors
|
||||
col_timon <- "1F6AA5"
|
||||
col_joey <- "2E7D32"
|
||||
col_dimitra <- "7B1FA2"
|
||||
alt_timon <- "D6E4F0"
|
||||
alt_joey <- "D7F0D8"
|
||||
alt_dimitra <- "EDD7F0"
|
||||
|
||||
header_font <- createStyle(fontName = "Calibri", fontSize = 11, fontColour = "FFFFFF",
|
||||
halign = "CENTER", valign = "center", textDecoration = "bold",
|
||||
border = "TopBottomLeftRight")
|
||||
sub_font <- createStyle(fontName = "Calibri", fontSize = 10, fontColour = "FFFFFF",
|
||||
halign = "CENTER", valign = "center", textDecoration = "bold",
|
||||
border = "TopBottomLeftRight")
|
||||
|
||||
# Title row
|
||||
writeData(wb, "Field Checklist",
|
||||
"Angata Pivot Field Checklist — sorted largest to smallest",
|
||||
startRow = 1, startCol = 1)
|
||||
mergeCells(wb, "Field Checklist", cols = 1:14, rows = 1)
|
||||
addStyle(wb, "Field Checklist",
|
||||
createStyle(fontName = "Calibri", fontSize = 13, textDecoration = "bold",
|
||||
halign = "CENTER", valign = "center",
|
||||
fgFill = "F0F0F0"),
|
||||
rows = 1, cols = 1)
|
||||
setRowHeights(wb, "Field Checklist", rows = 1, heights = 28)
|
||||
|
||||
# Person block writer
|
||||
write_person_block <- function(wb, ws_name, data, start_col, hdr_color, alt_color, person_name) {
|
||||
end_col <- start_col + 3
|
||||
|
||||
# Person name header (row 2)
|
||||
mergeCells(wb, ws_name, cols = start_col:end_col, rows = 2)
|
||||
writeData(wb, ws_name, person_name, startRow = 2, startCol = start_col)
|
||||
addStyle(wb, ws_name,
|
||||
createStyle(fontName = "Calibri", fontSize = 12, fontColour = "FFFFFF",
|
||||
textDecoration = "bold", halign = "CENTER", valign = "center",
|
||||
fgFill = hdr_color, border = "TopBottomLeftRight",
|
||||
borderColour = "999999"),
|
||||
rows = 2, cols = start_col:end_col)
|
||||
|
||||
# Sub-headers (row 3)
|
||||
sub_headers <- c("#", "Field", "Area (ha)", "Checked \u2713")
|
||||
writeData(wb, ws_name, as.data.frame(t(sub_headers)),
|
||||
startRow = 3, startCol = start_col, colNames = FALSE)
|
||||
addStyle(wb, ws_name,
|
||||
createStyle(fontName = "Calibri", fontSize = 10, fontColour = "FFFFFF",
|
||||
textDecoration = "bold", halign = "CENTER", valign = "center",
|
||||
fgFill = hdr_color, border = "TopBottomLeftRight",
|
||||
borderColour = "999999"),
|
||||
rows = 3, cols = start_col:end_col)
|
||||
|
||||
# Data rows (starting row 4)
|
||||
n <- nrow(data)
|
||||
for (i in seq_len(n)) {
|
||||
row_num <- i + 3
|
||||
bg <- if (i %% 2 == 0) alt_color else "FFFFFF"
|
||||
# Rank
|
||||
writeData(wb, ws_name, i, startRow = row_num, startCol = start_col)
|
||||
# Field name
|
||||
writeData(wb, ws_name, data$field[i], startRow = row_num, startCol = start_col + 1)
|
||||
# Area
|
||||
writeData(wb, ws_name, data$area_ha[i], startRow = row_num, startCol = start_col + 2)
|
||||
# Checked (empty)
|
||||
writeData(wb, ws_name, "", startRow = row_num, startCol = start_col + 3)
|
||||
|
||||
row_style <- createStyle(fontName = "Calibri", fontSize = 10, halign = "center",
|
||||
fgFill = bg, border = "TopBottomLeftRight",
|
||||
borderColour = "CCCCCC")
|
||||
field_style <- createStyle(fontName = "Calibri", fontSize = 10, halign = "left",
|
||||
fgFill = bg, border = "TopBottomLeftRight",
|
||||
borderColour = "CCCCCC")
|
||||
addStyle(wb, ws_name, row_style, rows = row_num, cols = start_col)
|
||||
addStyle(wb, ws_name, field_style, rows = row_num, cols = start_col + 1)
|
||||
addStyle(wb, ws_name, row_style, rows = row_num, cols = start_col + 2)
|
||||
addStyle(wb, ws_name, row_style, rows = row_num, cols = start_col + 3)
|
||||
}
|
||||
}
|
||||
|
||||
write_person_block(wb, "Field Checklist", timon, 1, col_timon, alt_timon, "Timon")
|
||||
write_person_block(wb, "Field Checklist", joey, 6, col_joey, alt_joey, "Joey")
|
||||
write_person_block(wb, "Field Checklist", dimitra, 11, col_dimitra, alt_dimitra, "Dimitra")
|
||||
|
||||
# Column widths (col 5 and 10 = spacers)
|
||||
setColWidths(wb, "Field Checklist",
|
||||
cols = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14),
|
||||
widths = c(5, 14, 10, 12, 2, 5, 14, 10, 12, 2, 5, 14, 10, 12))
|
||||
|
||||
# Row heights
|
||||
setRowHeights(wb, "Field Checklist", rows = 2:3, heights = c(22, 18))
|
||||
max_rows <- max(nrow(timon), nrow(joey), nrow(dimitra))
|
||||
setRowHeights(wb, "Field Checklist", rows = 4:(max_rows + 3), heights = 16)
|
||||
|
||||
# Freeze panes below header
|
||||
freezePane(wb, "Field Checklist", firstActiveRow = 4)
|
||||
|
||||
# Save
|
||||
out_path <- "angata_field_checklist.xlsx"
|
||||
saveWorkbook(wb, out_path, overwrite = TRUE)
|
||||
cat(sprintf("\nExcel saved to: %s\n", out_path))
|
||||
cat(sprintf("Total: %d fields — Timon: %d, Joey: %d, Dimitra: %d\n",
|
||||
nrow(df), nrow(timon), nrow(joey), nrow(dimitra)))
|
||||
194
create_field_checklist.py
Normal file
194
create_field_checklist.py
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
"""
|
||||
Creates an Excel checklist from pivot.geojson, with fields sorted largest to smallest,
|
||||
split across Timon (1st), Joey (2nd), Dimitra (3rd) in a single sheet side-by-side.
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
|
||||
try:
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
except ImportError:
|
||||
print("Installing openpyxl...")
|
||||
import subprocess, sys
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "openpyxl"])
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
||||
from openpyxl.utils import get_column_letter
|
||||
|
||||
|
||||
def shoelace_area(coords):
|
||||
"""Compute area in square degrees using the shoelace formula."""
|
||||
n = len(coords)
|
||||
area = 0.0
|
||||
for i in range(n):
|
||||
j = (i + 1) % n
|
||||
area += coords[i][0] * coords[j][1]
|
||||
area -= coords[j][0] * coords[i][1]
|
||||
return abs(area) / 2.0
|
||||
|
||||
|
||||
def polygon_area_m2(ring):
|
||||
"""
|
||||
Approximate polygon area in m² using spherical coordinates.
|
||||
ring: list of [lon, lat] pairs
|
||||
"""
|
||||
R = 6371000 # Earth radius in meters
|
||||
area_deg2 = shoelace_area(ring)
|
||||
# Convert to m² using mean latitude
|
||||
mean_lat = sum(p[1] for p in ring) / len(ring)
|
||||
lat_rad = math.radians(mean_lat)
|
||||
# 1 degree lat ≈ R * pi/180 meters, 1 degree lon ≈ R * cos(lat) * pi/180 meters
|
||||
m_per_deg_lat = R * math.pi / 180
|
||||
m_per_deg_lon = R * math.cos(lat_rad) * math.pi / 180
|
||||
return area_deg2 * m_per_deg_lat * m_per_deg_lon
|
||||
|
||||
|
||||
def feature_area(feature):
|
||||
"""Compute total area of a feature (MultiPolygon or Polygon) in m²."""
|
||||
geom = feature["geometry"]
|
||||
total = 0.0
|
||||
if geom["type"] == "MultiPolygon":
|
||||
for polygon in geom["coordinates"]:
|
||||
# First ring is outer boundary
|
||||
total += polygon_area_m2(polygon[0])
|
||||
elif geom["type"] == "Polygon":
|
||||
total += polygon_area_m2(geom["coordinates"][0])
|
||||
return total
|
||||
|
||||
|
||||
# Load GeoJSON
|
||||
geojson_path = r"C:\Users\timon\Documents\SmartCane_code\laravel_app\storage\app\angata\pivot.geojson"
|
||||
with open(geojson_path, "r", encoding="utf-8") as f:
|
||||
gj = json.load(f)
|
||||
|
||||
features = gj["features"]
|
||||
print(f"Total features: {len(features)}")
|
||||
|
||||
# Compute areas and sort
|
||||
fields = []
|
||||
for feat in features:
|
||||
field_name = feat["properties"].get("field", "?")
|
||||
area = feature_area(feat)
|
||||
fields.append({"field": field_name, "area_m2": area, "area_ha": area / 10000})
|
||||
|
||||
fields.sort(key=lambda x: x["area_m2"], reverse=True)
|
||||
|
||||
# Print top 10 for verification
|
||||
print("\nTop 10 fields by area:")
|
||||
for i, f in enumerate(fields[:10]):
|
||||
print(f" {i+1:3d}. Field {f['field']:15s} {f['area_ha']:.2f} ha")
|
||||
|
||||
# Split: index 0,3,6,... → Timon; 1,4,7,... → Joey; 2,5,8,... → Dimitra
|
||||
timon = [f for i, f in enumerate(fields) if i % 3 == 0]
|
||||
joey = [f for i, f in enumerate(fields) if i % 3 == 1]
|
||||
dimitra = [f for i, f in enumerate(fields) if i % 3 == 2]
|
||||
|
||||
print(f"\nSplit: Timon={len(timon)}, Joey={len(joey)}, Dimitra={len(dimitra)}")
|
||||
|
||||
# Create Excel
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "Field Checklist"
|
||||
|
||||
# Color palette
|
||||
colors = {
|
||||
"timon": {"header_bg": "1F6AA5", "alt_bg": "D6E4F0"},
|
||||
"joey": {"header_bg": "2E7D32", "alt_bg": "D7F0D8"},
|
||||
"dimitra": {"header_bg": "7B1FA2", "alt_bg": "EDD7F0"},
|
||||
}
|
||||
|
||||
white_font = Font(name="Calibri", bold=True, color="FFFFFF", size=11)
|
||||
black_font = Font(name="Calibri", size=10)
|
||||
bold_black = Font(name="Calibri", bold=True, size=10)
|
||||
center_align = Alignment(horizontal="center", vertical="center", wrap_text=True)
|
||||
|
||||
thin = Side(style="thin", color="CCCCCC")
|
||||
border = Border(left=thin, right=thin, top=thin, bottom=thin)
|
||||
|
||||
# Column layout: each person gets 3 columns (Rank, Field, Area ha, Checked)
|
||||
# Spacing: col 1-4 = Timon, col 5 = spacer, col 6-9 = Joey, col 10 = spacer, col 11-14 = Dimitra
|
||||
persons = [
|
||||
("Timon", timon, 1),
|
||||
("Joey", joey, 6),
|
||||
("Dimitra", dimitra, 11),
|
||||
]
|
||||
|
||||
# Row 1: Person name header (merged across 4 cols)
|
||||
ws.row_dimensions[1].height = 25
|
||||
ws.row_dimensions[2].height = 20
|
||||
|
||||
for name, data, start_col in persons:
|
||||
c = colors[name.lower()]
|
||||
# Merge cells for person name
|
||||
end_col = start_col + 3
|
||||
ws.merge_cells(
|
||||
start_row=1, start_column=start_col,
|
||||
end_row=1, end_column=end_col
|
||||
)
|
||||
cell = ws.cell(row=1, column=start_col, value=name)
|
||||
cell.font = white_font
|
||||
cell.fill = PatternFill("solid", fgColor=c["header_bg"])
|
||||
cell.alignment = center_align
|
||||
cell.border = border
|
||||
|
||||
# Sub-headers
|
||||
sub_headers = ["#", "Field", "Area (ha)", "Checked ✓"]
|
||||
for i, hdr in enumerate(sub_headers):
|
||||
cell = ws.cell(row=2, column=start_col + i, value=hdr)
|
||||
cell.font = white_font
|
||||
cell.fill = PatternFill("solid", fgColor=c["header_bg"])
|
||||
cell.alignment = center_align
|
||||
cell.border = border
|
||||
|
||||
# Data rows
|
||||
for row_i, field in enumerate(data):
|
||||
row_num = row_i + 3
|
||||
ws.row_dimensions[row_num].height = 16
|
||||
alt = row_i % 2 == 1
|
||||
bg = c["alt_bg"] if alt else "FFFFFF"
|
||||
fill = PatternFill("solid", fgColor=bg)
|
||||
|
||||
values = [row_i + 1, field["field"], round(field["area_ha"], 2), ""]
|
||||
for col_i, val in enumerate(values):
|
||||
cell = ws.cell(row=row_num, column=start_col + col_i, value=val)
|
||||
cell.font = black_font
|
||||
cell.fill = fill
|
||||
cell.border = border
|
||||
cell.alignment = Alignment(horizontal="center" if col_i != 1 else "left",
|
||||
vertical="center")
|
||||
|
||||
# Column widths
|
||||
col_widths = {1: 5, 2: 14, 3: 10, 4: 12, # Timon
|
||||
5: 2, # spacer
|
||||
6: 5, 7: 14, 8: 10, 9: 12, # Joey
|
||||
10: 2, # spacer
|
||||
11: 5, 12: 14, 13: 10, 14: 12} # Dimitra
|
||||
|
||||
for col, width in col_widths.items():
|
||||
ws.column_dimensions[get_column_letter(col)].width = width
|
||||
|
||||
# Freeze header rows
|
||||
ws.freeze_panes = "A3"
|
||||
|
||||
# Title row above everything — insert a title row
|
||||
ws.insert_rows(1)
|
||||
ws.merge_cells("A1:N1")
|
||||
title_cell = ws.cell(row=1, column=1, value="Angata Pivot Field Checklist — sorted largest to smallest")
|
||||
title_cell.font = Font(name="Calibri", bold=True, size=13, color="1A1A1A")
|
||||
title_cell.alignment = Alignment(horizontal="center", vertical="center")
|
||||
title_cell.fill = PatternFill("solid", fgColor="F0F0F0")
|
||||
ws.row_dimensions[1].height = 28
|
||||
|
||||
# Re-freeze after insert
|
||||
ws.freeze_panes = "A4"
|
||||
|
||||
out_path = r"C:\Users\timon\Documents\SmartCane_code\angata_field_checklist.xlsx"
|
||||
wb.save(out_path)
|
||||
print(f"\nExcel saved to: {out_path}")
|
||||
print(f"Total fields: {len(fields)}")
|
||||
print(f" Timon: {len(timon)} fields")
|
||||
print(f" Joey: {len(joey)} fields")
|
||||
print(f" Dimitra: {len(dimitra)} fields")
|
||||
|
|
@ -170,7 +170,7 @@ calculate_status_alert <- function(imminent_prob, age_week, mean_ci,
|
|||
|
||||
# Priority 1: HARVEST READY - highest business priority
|
||||
# Field is mature (≥12 months) AND harvest model predicts imminent harvest
|
||||
if (!is.na(imminent_prob) && imminent_prob > 0.5 && !is.na(age_week) && age_week >= 52) {
|
||||
if (!is.na(imminent_prob) && imminent_prob > 0.3 && !is.na(age_week) && age_week >= 52) {
|
||||
return("harvest_ready")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -650,48 +650,6 @@ get_phase_by_age <- function(age_weeks) {
|
|||
return("Unknown")
|
||||
}
|
||||
|
||||
#' Get status trigger based on CI values and field age
|
||||
get_status_trigger <- function(ci_values, ci_change, age_weeks) {
|
||||
if (is.na(age_weeks) || length(ci_values) == 0) return(NA_character_)
|
||||
|
||||
ci_values <- ci_values[!is.na(ci_values)]
|
||||
if (length(ci_values) == 0) return(NA_character_)
|
||||
|
||||
pct_above_2 <- sum(ci_values > 2) / length(ci_values) * 100
|
||||
pct_at_or_above_2 <- sum(ci_values >= 2) / length(ci_values) * 100
|
||||
ci_cv <- if (mean(ci_values, na.rm = TRUE) > 0) sd(ci_values) / mean(ci_values, na.rm = TRUE) else 0
|
||||
mean_ci <- mean(ci_values, na.rm = TRUE)
|
||||
|
||||
if (age_weeks >= 0 && age_weeks <= 6) {
|
||||
if (pct_at_or_above_2 >= 70) {
|
||||
return("germination_complete")
|
||||
} else if (pct_above_2 > 10) {
|
||||
return("germination_started")
|
||||
}
|
||||
}
|
||||
|
||||
if (age_weeks >= 45) {
|
||||
return("harvest_ready")
|
||||
}
|
||||
|
||||
if (age_weeks > 6 && !is.na(ci_change) && ci_change < -1.5 && ci_cv < 0.25) {
|
||||
return("stress_detected_whole_field")
|
||||
}
|
||||
|
||||
if (age_weeks > 6 && !is.na(ci_change) && ci_change > 1.5) {
|
||||
return("strong_recovery")
|
||||
}
|
||||
|
||||
if (age_weeks >= 4 && age_weeks < 39 && !is.na(ci_change) && ci_change > 0.2) {
|
||||
return("growth_on_track")
|
||||
}
|
||||
|
||||
if (age_weeks >= 39 && age_weeks < 45 && mean_ci > 3.5) {
|
||||
return("maturation_progressing")
|
||||
}
|
||||
|
||||
return(NA_character_)
|
||||
}
|
||||
|
||||
#' Extract planting dates from harvesting data
|
||||
extract_planting_dates <- function(harvesting_data, field_boundaries_sf = NULL) {
|
||||
|
|
|
|||
|
|
@ -600,6 +600,16 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
cat("\n\n", tr_key("tot_fields_analyzed"))
|
||||
}
|
||||
|
||||
# Total area analyzed
|
||||
if (exists("field_details_table") && !is.null(field_details_table)) {
|
||||
area_col_name <- paste0("Area_", get_area_unit_label(AREA_UNIT_PREFERENCE))
|
||||
unit_label <- get_area_unit_label(AREA_UNIT_PREFERENCE)
|
||||
if (area_col_name %in% names(field_details_table)) {
|
||||
total_area <- sum(field_details_table[[area_col_name]], na.rm = TRUE)
|
||||
cat("\n\n", tr_key("tot_area_analyzed"))
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
cat(tr_key("kpi_na"))
|
||||
}
|
||||
|
|
@ -618,15 +628,89 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
tryCatch({
|
||||
# KPI metadata for display
|
||||
kpi_display_order <- list(
|
||||
uniformity = list(display = "Field Uniformity", level_col = "interpretation", count_col = "field_count"),
|
||||
area_change = list(display = "Area Change", level_col = "interpretation", count_col = "field_count"),
|
||||
growth_decline = list(display = "4-Week Trend", level_col = "trend_interpretation", count_col = "field_count"),
|
||||
patchiness = list(display = "Field Patchiness", level_col = "gini_category", count_col = "field_count", detail_col = "patchiness_risk"),
|
||||
tch_forecast = list(display = "TCH Forecasted", level_col = "tch_category", detail_col = "range", count_col = "field_count"),
|
||||
gap_filling = list(display = "Gaps", level_col = "gap_level", count_col = "field_count")
|
||||
uniformity = list(display = "Field Uniformity", level_col = "interpretation", count_col = "field_count", area_col = "area_sum"),
|
||||
area_change = list(display = "Area Change", level_col = "interpretation", count_col = "field_count", area_col = "area_sum"),
|
||||
growth_decline = list(display = "4-Week Trend", level_col = "trend_interpretation", count_col = "field_count", area_col = "area_sum"),
|
||||
patchiness = list(display = "Field Patchiness", level_col = "gini_category", count_col = "field_count", detail_col = "patchiness_risk", area_col = "area_sum"),
|
||||
tch_forecast = list(display = "TCH Forecasted", level_col = "tch_category", count_col = "field_count", detail_col = "range", area_col = "area_sum"),
|
||||
gap_filling = list(display = "Gaps", level_col = "gap_level", count_col = "field_count", area_col = "area_sum")
|
||||
)
|
||||
|
||||
standardize_kpi <- function(df, level_col, count_col, detail_col = NULL) {
|
||||
# Enrich summary_tables with area_sum from field_details_table (mirrors script 91 pattern)
|
||||
area_col_name <- paste0("Area_", get_area_unit_label(AREA_UNIT_PREFERENCE))
|
||||
unit_label <- get_area_unit_label(AREA_UNIT_PREFERENCE)
|
||||
has_area <- exists("field_details_table") && !is.null(field_details_table) &&
|
||||
area_col_name %in% names(field_details_table)
|
||||
if (has_area) {
|
||||
fdt <- field_details_table
|
||||
if (!is.null(summary_tables$uniformity) && "Uniformity_Category" %in% names(fdt)) {
|
||||
summary_tables$uniformity <- summary_tables$uniformity %>%
|
||||
left_join(fdt %>% group_by(interpretation = Uniformity_Category) %>%
|
||||
summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop"),
|
||||
by = "interpretation")
|
||||
}
|
||||
if (!is.null(summary_tables$area_change) && "Area_Change_Interpretation" %in% names(fdt)) {
|
||||
summary_tables$area_change <- summary_tables$area_change %>%
|
||||
left_join(fdt %>% group_by(interpretation = Area_Change_Interpretation) %>%
|
||||
summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop"),
|
||||
by = "interpretation")
|
||||
}
|
||||
if (!is.null(summary_tables$growth_decline) && "Trend_Interpretation" %in% names(fdt)) {
|
||||
summary_tables$growth_decline <- summary_tables$growth_decline %>%
|
||||
left_join(fdt %>% group_by(trend_interpretation = Trend_Interpretation) %>%
|
||||
summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop"),
|
||||
by = "trend_interpretation")
|
||||
}
|
||||
if (!is.null(summary_tables$patchiness) && all(c("Patchiness_Risk", "Gini_Coefficient") %in% names(fdt))) {
|
||||
summary_tables$patchiness <- summary_tables$patchiness %>%
|
||||
left_join(
|
||||
fdt %>%
|
||||
mutate(gini_category = case_when(
|
||||
Gini_Coefficient < 0.2 ~ "Uniform (Gini<0.2)",
|
||||
Gini_Coefficient < 0.4 ~ "Moderate (Gini 0.2-0.4)",
|
||||
TRUE ~ "High (Gini≥0.4)"
|
||||
)) %>%
|
||||
group_by(gini_category, patchiness_risk = Patchiness_Risk) %>%
|
||||
summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop"),
|
||||
by = c("gini_category", "patchiness_risk")
|
||||
)
|
||||
}
|
||||
if (!is.null(summary_tables$gap_filling) && "Gap_Level" %in% names(fdt)) {
|
||||
summary_tables$gap_filling <- summary_tables$gap_filling %>%
|
||||
left_join(fdt %>% group_by(gap_level = Gap_Level) %>%
|
||||
summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop"),
|
||||
by = "gap_level")
|
||||
}
|
||||
# TCH forecast: reproduce the same quartile logic used when building summary_tables so we
|
||||
# can assign each field to a tch_category and sum its area
|
||||
if (!is.null(summary_tables$tch_forecast) && "TCH_Forecasted" %in% names(fdt)) {
|
||||
tch_vals <- fdt %>% dplyr::filter(!is.na(TCH_Forecasted)) %>% dplyr::pull(TCH_Forecasted)
|
||||
if (length(tch_vals) > 0) {
|
||||
if (length(unique(tch_vals)) == 1) {
|
||||
area_tch <- fdt %>%
|
||||
dplyr::filter(!is.na(TCH_Forecasted)) %>%
|
||||
dplyr::summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE)) %>%
|
||||
dplyr::mutate(tch_category = "All equal")
|
||||
} else {
|
||||
q25 <- quantile(tch_vals, 0.25, na.rm = TRUE)
|
||||
q75 <- quantile(tch_vals, 0.75, na.rm = TRUE)
|
||||
area_tch <- fdt %>%
|
||||
dplyr::filter(!is.na(TCH_Forecasted)) %>%
|
||||
dplyr::mutate(tch_category = dplyr::case_when(
|
||||
TCH_Forecasted >= q75 ~ "Top 25%",
|
||||
TCH_Forecasted >= q25 ~ "Middle 50%",
|
||||
TRUE ~ "Bottom 25%"
|
||||
)) %>%
|
||||
dplyr::group_by(tch_category) %>%
|
||||
dplyr::summarise(area_sum = sum(.data[[area_col_name]], na.rm = TRUE), .groups = "drop")
|
||||
}
|
||||
summary_tables$tch_forecast <- summary_tables$tch_forecast %>%
|
||||
left_join(area_tch, by = "tch_category")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
standardize_kpi <- function(df, level_col, count_col, detail_col = NULL, area_col = NULL) {
|
||||
if (is.null(level_col) || !(level_col %in% names(df)) || is.null(count_col) || !(count_col %in% names(df))) {
|
||||
return(NULL)
|
||||
}
|
||||
|
|
@ -640,10 +724,16 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
display_level <- df[[level_col]]
|
||||
}
|
||||
|
||||
area_vals <- if (!is.null(area_col) && area_col %in% names(df))
|
||||
round(df[[area_col]], 1)
|
||||
else
|
||||
rep(NA_real_, nrow(df))
|
||||
|
||||
df %>%
|
||||
dplyr::transmute(
|
||||
Level = if (level_col == "trend_interpretation") map_trend_to_arrow(display_level, include_text = TRUE) else as.character(display_level),
|
||||
Count = as.integer(round(as.numeric(.data[[count_col]]))),
|
||||
Area = area_vals,
|
||||
Percent = if (is.na(total)) {
|
||||
NA_real_
|
||||
} else {
|
||||
|
|
@ -661,9 +751,10 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
kpi_df <- summary_tables[[kpi_key]]
|
||||
if (is.null(kpi_df) || !is.data.frame(kpi_df) || nrow(kpi_df) == 0) next
|
||||
|
||||
# Pass detail_col if it exists in config
|
||||
# Pass detail_col and area_col if present in config
|
||||
detail_col <- if (!is.null(config$detail_col)) config$detail_col else NULL
|
||||
kpi_rows <- standardize_kpi(kpi_df, config$level_col, config$count_col, detail_col)
|
||||
kpi_rows <- standardize_kpi(kpi_df, config$level_col, config$count_col, detail_col,
|
||||
config[["area_col"]])
|
||||
|
||||
if (!is.null(kpi_rows)) {
|
||||
kpi_rows$KPI <- config$display
|
||||
|
|
@ -685,10 +776,14 @@ if (exists("summary_tables") && !is.null(summary_tables) && length(summary_table
|
|||
kpi_group_sizes <- rle(combined_df$KPI_group)$lengths
|
||||
|
||||
display_df <- combined_df %>%
|
||||
dplyr::select(KPI = KPI_display, Level, Count, Percent)
|
||||
dplyr::select(KPI = KPI_display, Level, Count, Area, Percent)
|
||||
|
||||
# Translate the table for visualization
|
||||
names(display_df) <- c(tr_key("KPI"), tr_key("Level"), tr_key("Count"), tr_key("Percent"))
|
||||
names(display_df) <- c(
|
||||
tr_key("KPI"), tr_key("Level"), tr_key("Count"),
|
||||
paste0(tr_key("Area"), " (", unit_label, ")"),
|
||||
tr_key("Percent")
|
||||
)
|
||||
display_df[, 1:2] <- lapply(display_df[, 1:2], function(col) sapply(col, tr_key))
|
||||
ft <- flextable(display_df) %>%
|
||||
merge_v(j = tr_key("KPI")) %>%
|
||||
|
|
@ -1188,9 +1283,11 @@ tryCatch({
|
|||
minus_2_ww <- get_week_year(as.Date(today) - lubridate::weeks(2))
|
||||
minus_3_ww <- get_week_year(as.Date(today) - lubridate::weeks(3))
|
||||
|
||||
message(paste("Processing", nrow(AllPivots_merged), "fields for weeks:",
|
||||
message(paste("Processing", nrow(AllPivots_merged), "fields for weeks:",
|
||||
current_ww$week, minus_1_ww$week, minus_2_ww$week, minus_3_ww$week))
|
||||
|
||||
|
||||
# load_per_field_mosaic() is defined in 90_report_utils.R (sourced above)
|
||||
|
||||
# --- Fetch rain for all fields (one API call per 0.25° tile) ---
|
||||
|
|
@ -1334,6 +1431,14 @@ tryCatch({
|
|||
sprintf("**%s:** %.2f", tr_key("mean_ci"), field_kpi$Mean_CI)
|
||||
)
|
||||
|
||||
# Prepend area as first item (static field attribute)
|
||||
if (area_col_name %in% names(field_kpi) && !is.na(field_kpi[[area_col_name]])) {
|
||||
kpi_parts <- c(
|
||||
sprintf("**%s:** %.1f %s", tr_key("Area"), field_kpi[[area_col_name]], unit_label),
|
||||
kpi_parts
|
||||
)
|
||||
}
|
||||
|
||||
# Add Weekly_CI_Change if available (note: capital C and I)
|
||||
if (!is.null(field_kpi$Weekly_CI_Change) && !is.na(field_kpi$Weekly_CI_Change)) {
|
||||
change_sign <- ifelse(field_kpi$Weekly_CI_Change >= 0, "+", "")
|
||||
|
|
|
|||
|
|
@ -544,9 +544,11 @@ if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% na
|
|||
tryCatch({
|
||||
# Use per-field field_analysis data from RDS (already loaded in load_kpi_data chunk)
|
||||
if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% names(summary_data)) {
|
||||
analysis_data <- summary_data$field_analysis %>%
|
||||
select(Field_id, Status_Alert) %>%
|
||||
rename(Status_trigger = Status_Alert) # Rename to Status_trigger for compatibility with hexbin logic
|
||||
fa <- summary_data$field_analysis
|
||||
status_col <- intersect(c("Status_Alert", "Status_trigger"), names(fa))[1]
|
||||
analysis_data <- fa %>%
|
||||
select(Field_id, all_of(status_col)) %>%
|
||||
rename(Status_trigger = all_of(status_col))
|
||||
} else {
|
||||
analysis_data <- tibble(Field_id = character(), Status_trigger = character())
|
||||
}
|
||||
|
|
@ -619,10 +621,9 @@ tryCatch({
|
|||
filter(Status_trigger != "harvest_ready" | is.na(Status_trigger))
|
||||
|
||||
# Generate breaks for color gradients
|
||||
breaks_vec <- c(0, 5, 10, 15, 20, 30, 35)
|
||||
breaks_vec <- c(5, 10, 15, 20, 30, 35)
|
||||
labels_vec <- as.character(breaks_vec)
|
||||
labels_vec[length(labels_vec)] <- ">30"
|
||||
labels_vec[1] <- "0.1"
|
||||
|
||||
# Calculate data bounds for coordinate limits (prevents basemap scale conflicts)
|
||||
# Use actual data bounds without dummy points to avoid column mismatch
|
||||
|
|
@ -635,36 +636,45 @@ tryCatch({
|
|||
ceiling(max(points_processed$Y, na.rm = TRUE) * 20) / 20
|
||||
)
|
||||
|
||||
# ggplot2's StatBinhex computes the hex grid origin as c(min(x), min(y)) of each layer's
|
||||
# own data. Feeding different subsets (points_ready / points_not_ready) to the two layers
|
||||
# gives different origins → misaligned hexes. Fix: pass points_processed to BOTH layers.
|
||||
# For the coloured layer, use ready_area = area_value for harvest-ready fields, 0 elsewhere.
|
||||
# The scale censors 0 → NA → transparent, so non-ready hexes are invisible in that layer.
|
||||
points_processed <- points_processed %>%
|
||||
mutate(ready_area = ifelse(Status_trigger == "harvest_ready", area_value, 0))
|
||||
|
||||
# Create hexbin map with enhanced aesthetics, basemap, and proper legend
|
||||
ggplot() +
|
||||
# OpenStreetMap basemap (zoom=11 appropriate for agricultural fields)
|
||||
ggspatial::annotation_map_tile(type = "osm", zoom = 11, progress = "none", alpha = 0.5) +
|
||||
# Hexbin for NOT ready fields (light background)
|
||||
# Hexbin background: ALL fields as white hexes (anchors the hex grid to the full extent)
|
||||
geom_hex(
|
||||
data = points_not_ready,
|
||||
data = points_processed,
|
||||
aes(x = X, y = Y, weight = area_value, alpha = tr_key("hexbin_not_ready")),
|
||||
binwidth = c(0.012, 0.012),
|
||||
fill = "#ffffff",
|
||||
colour = "#0000009a",
|
||||
linewidth = 0.1
|
||||
) +
|
||||
# Hexbin for READY fields (colored gradient)
|
||||
# Hexbin overlay: same grid (same data), coloured only where ready_area > 0
|
||||
geom_hex(
|
||||
data = points_ready,
|
||||
aes(x = X, y = Y, weight = area_value),
|
||||
data = points_processed,
|
||||
aes(x = X, y = Y, weight = ready_area),
|
||||
binwidth = c(0.012, 0.012),
|
||||
alpha = 0.9,
|
||||
colour = "#0000009a",
|
||||
linewidth = 0.1
|
||||
) +
|
||||
# Color gradient scale for area
|
||||
# Color gradient scale — values of 0 (non-ready hexes) are censored → NA → transparent
|
||||
scale_fill_viridis_b(
|
||||
option = "viridis",
|
||||
direction = -1,
|
||||
breaks = breaks_vec,
|
||||
labels = labels_vec,
|
||||
limits = c(0, 35),
|
||||
oob = scales::squish,
|
||||
limits = c(0.001, 35),
|
||||
oob = scales::oob_censor,
|
||||
na.value = "transparent",
|
||||
name = tr_key("hexbin_legend_acres")
|
||||
) +
|
||||
# Alpha scale for "not ready" status indication
|
||||
|
|
@ -722,7 +732,10 @@ if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% na
|
|||
if (is.null(summary_data$field_analysis_summary) || !("field_analysis_summary" %in% names(summary_data)) ||
|
||||
!is.data.frame(summary_data$field_analysis_summary)) {
|
||||
|
||||
# Create summary by aggregating by Status_Alert and Phase categories
|
||||
# Detect which status column is present (Status_Alert from cane_supply, Status_trigger from others)
|
||||
status_col <- intersect(c("Status_Alert", "Status_trigger"), names(field_analysis_df))[1]
|
||||
|
||||
# Create summary by aggregating by status and Phase categories
|
||||
phase_summary <- field_analysis_df %>%
|
||||
filter(!is.na(Phase)) %>%
|
||||
group_by(Phase) %>%
|
||||
|
|
@ -736,21 +749,21 @@ if (exists("summary_data") && !is.null(summary_data) && "field_analysis" %in% na
|
|||
|
||||
# Create Status trigger summary - includes both active alerts and "No active triggers"
|
||||
trigger_summary <- tryCatch({
|
||||
# Active alerts (fields with non-NA Status_Alert)
|
||||
# Active alerts (fields with non-NA status)
|
||||
active_alerts <- field_analysis_df %>%
|
||||
filter(!is.na(Status_Alert), Status_Alert != "") %>%
|
||||
group_by(Status_Alert) %>%
|
||||
filter(!is.na(.data[[status_col]]), .data[[status_col]] != "") %>%
|
||||
group_by(across(all_of(status_col))) %>%
|
||||
summarise(
|
||||
Acreage = sum(Acreage, na.rm = TRUE),
|
||||
Field_count = n_distinct(Field_id),
|
||||
.groups = "drop"
|
||||
) %>%
|
||||
mutate(Category = Status_Alert) %>%
|
||||
mutate(Category = .data[[status_col]]) %>%
|
||||
select(Category, Acreage, Field_count)
|
||||
|
||||
# No active triggers (fields with NA Status_Alert)
|
||||
# No active triggers (fields with NA status)
|
||||
no_alerts <- field_analysis_df %>%
|
||||
filter(is.na(Status_Alert) | Status_Alert == "") %>%
|
||||
filter(is.na(.data[[status_col]]) | .data[[status_col]] == "") %>%
|
||||
summarise(
|
||||
Acreage = sum(Acreage, na.rm = TRUE),
|
||||
Field_count = n_distinct(Field_id),
|
||||
|
|
|
|||
|
|
@ -456,8 +456,8 @@ rmarkdown::render(
|
|||
# rmarkdown::render(
|
||||
rmarkdown::render(
|
||||
"r_app/91_CI_report_with_kpis_cane_supply.Rmd",
|
||||
params = list(data_dir = "angata", report_date = as.Date("2026-02-23")),
|
||||
output_file = "SmartCane_Report_cane_supply_angata_2026-02-23_en.docx",
|
||||
params = list(data_dir = "angata", report_date = as.Date("2026-03-17")),
|
||||
output_file = "SmartCane_Report_cane_supply_angata_2026-03-17_en.docx",
|
||||
output_dir = "laravel_app/storage/app/angata/reports"
|
||||
)
|
||||
#
|
||||
|
|
|
|||
|
|
@ -512,6 +512,16 @@
|
|||
"es-mx": "**Total de parcelas analizadas:** {total_fields}",
|
||||
"pt-br": "**Total de campos analisados:** {total_fields}"
|
||||
},
|
||||
"tot_area_analyzed": {
|
||||
"en": "**Total Area Analyzed:** {round(total_area, 1)} {unit_label}",
|
||||
"es-mx": "**Área total analizada:** {round(total_area, 1)} {unit_label}",
|
||||
"pt-br": "**Área total analisada:** {round(total_area, 1)} {unit_label}"
|
||||
},
|
||||
"Area": {
|
||||
"en": "Area",
|
||||
"es-mx": "Área",
|
||||
"pt-br": "Área"
|
||||
},
|
||||
"Medium": {
|
||||
"en": "Medium",
|
||||
"es-mx": "Medio",
|
||||
|
|
|
|||
|
|
@ -2,541 +2,541 @@
|
|||
"main_translations": {
|
||||
"cover_title": {
|
||||
"en": "Satellite Based Field Reporting",
|
||||
"es-mx": "",
|
||||
"es-mx": "Reportes de Campo Basados en Satélite",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"cover_subtitle": {
|
||||
"en": "Cane Supply Office\n\nChlorophyll Index (CI) Monitoring Report — {toupper(params$data_dir)} Estate (Week {if (!is.null(params$week)) params$week else format(as.Date(params$report_date), '%V')}, {format(as.Date(params$report_date), '%Y')})",
|
||||
"es-mx": "",
|
||||
"es-mx": "Oficina de Abastecimiento de Caña\n\nReporte de Monitoreo del Índice de Clorofila (IC) — Finca {toupper(params$data_dir)} (Semana {if (!is.null(params$week)) params$week else format(as.Date(params$report_date), '%V')}, {format(as.Date(params$report_date), '%Y')})",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_summary_heading": {
|
||||
"en": "## Report Generated",
|
||||
"es-mx": "",
|
||||
"es-mx": "## Reporte Generado",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_farm_location": {
|
||||
"en": "**Farm Location:**",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Ubicación de la Finca:**",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_period_label": {
|
||||
"en": "**Report Period:** Week {current_week} of {year}",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Período del Reporte:** Semana {current_week} de {year}",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_generated_on": {
|
||||
"en": "**Report Generated on:**",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Reporte Generado el:**",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_farm_size": {
|
||||
"en": "**Farm Size Included in Analysis:** {formatC(total_acreage, format='f', digits=1)} acres",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Tamaño de Finca Incluido en el Análisis:** {formatC(total_acreage, format='f', digits=1)} acres",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_data_source": {
|
||||
"en": "**Data Source:** Planet Labs Satellite Imagery",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Fuente de Datos:** Imágenes Satelitales de Planet Labs",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_analysis_type": {
|
||||
"en": "**Analysis Type:** Chlorophyll Index (CI) Monitoring",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Tipo de Análisis:** Monitoreo del Índice de Clorofila (IC)",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"key_insights": {
|
||||
"en": "## Key Insights",
|
||||
"es-mx": "",
|
||||
"es-mx": "## Hallazgos Clave",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"insight_excellent_unif": {
|
||||
"en": "- {excellent_pct}% of fields have excellent uniformity (CV < 0.08)",
|
||||
"es-mx": "",
|
||||
"es-mx": "- {excellent_pct}% de los campos tienen uniformidad excelente (CV < 0.08)",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"insight_good_unif": {
|
||||
"en": "- {good_pct}% of fields have good uniformity (CV < 0.15)",
|
||||
"es-mx": "",
|
||||
"es-mx": "- {good_pct}% de los campos tienen buena uniformidad (CV < 0.15)",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"insight_improving": {
|
||||
"en": "- {round(improving_acreage, 1)} acres ({improving_pct}%) of farm area is improving week-over-week",
|
||||
"es-mx": "",
|
||||
"es-mx": "- {round(improving_acreage, 1)} acres ({improving_pct}%) del área de la finca está mejorando semana a semana",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"insight_declining": {
|
||||
"en": "- {round(declining_acreage, 1)} acres ({declining_pct}%) of farm area is declining week-over-week",
|
||||
"es-mx": "",
|
||||
"es-mx": "- {round(declining_acreage, 1)} acres ({declining_pct}%) del área de la finca está en declive semana a semana",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_na_insights": {
|
||||
"en": "KPI data not available for key insights.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Datos de KPI no disponibles para hallazgos clave.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_structure_heading": {
|
||||
"en": "## Report Structure",
|
||||
"es-mx": "",
|
||||
"es-mx": "## Estructura del Reporte",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_structure_body": {
|
||||
"en": "**Section 1:** Cane supply zone analyses, summaries and Key Performance Indicators (KPIs)\n**Section 2:** Explanation of the report, definitions, methodology, and CSV export structure",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Sección 1:** Análisis de zonas de abastecimiento de caña, resúmenes e Indicadores Clave de Desempeño (KPIs)\n**Sección 2:** Explicación del reporte, definiciones, metodología y estructura de exportación CSV",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"section_i": {
|
||||
"en": "# Section 1: Farm-wide Analyses and KPIs",
|
||||
"es-mx": "",
|
||||
"es-mx": "# Sección 1: Análisis General de la Finca y KPIs",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"section_1_1": {
|
||||
"en": "## 1.1 Overview of cane supply area, showing zones with number of acres being harvest ready",
|
||||
"es-mx": "",
|
||||
"es-mx": "## 1.1 Panorama del área de abastecimiento de caña, mostrando zonas con número de acres listos para cosecha",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"section_1_2": {
|
||||
"en": "## 1.2 Key Performance Indicators",
|
||||
"es-mx": "",
|
||||
"es-mx": "## 1.2 Indicadores Clave de Desempeño",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_empty": {
|
||||
"en": "KPI summary data available but is empty/invalid.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Datos de resumen de KPI disponibles pero vacíos/inválidos.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_unavailable": {
|
||||
"en": "KPI summary data not available.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Datos de resumen de KPI no disponibles.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"metadata": {
|
||||
"en": "## Report Metadata",
|
||||
"es-mx": "",
|
||||
"es-mx": "## Metadatos del Reporte",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"disclaimer": {
|
||||
"en": "*This report was automatically generated by the SmartCane monitoring system. For questions or additional analysis, please contact the technical team at info@smartcane.ag.*",
|
||||
"es-mx": "",
|
||||
"es-mx": "*Este reporte fue generado automáticamente por el sistema de monitoreo SmartCane. Para preguntas o análisis adicionales, por favor contacte al equipo técnico en info@smartcane.ag.*",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"section_2_heading": {
|
||||
"en": "# Section 2: Support Document for weekly SmartCane data package.",
|
||||
"es-mx": "",
|
||||
"es-mx": "# Sección 2: Documento de Soporte para el paquete de datos semanal de SmartCane.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_doc_heading": {
|
||||
"en": "## 1. About This Document",
|
||||
"es-mx": "",
|
||||
"es-mx": "## 1. Acerca de Este Documento",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_doc_body": {
|
||||
"en": "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.ag.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Este documento es el documento de soporte del archivo de datos SmartCane. Incluye las definiciones, cálculos explicativos y sugerencias para la interpretación de los datos proporcionados. Para preguntas adicionales, no dude en contactar al soporte de SmartCane, a través de su persona de contacto o vía info@smartcane.ag.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_heading": {
|
||||
"en": "## 2. About the Data File",
|
||||
"es-mx": "",
|
||||
"es-mx": "## 2. Acerca del Archivo de Datos",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_body": {
|
||||
"en": "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:",
|
||||
"es-mx": "",
|
||||
"es-mx": "El archivo de datos se genera automáticamente a partir de imágenes de teledetección normalizadas e indexadas de los polígonos proporcionados. Los algoritmos específicos de SmartCane proporcionan resultados de cálculo personalizados desarrollados para apoyar las operaciones de caña de azúcar mediante:",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_bullet_harvest": {
|
||||
"en": "Supporting harvest planning mill-field logistics to ensure optimal tonnage and sucrose levels",
|
||||
"es-mx": "",
|
||||
"es-mx": "Apoyo a la planificación de cosecha y logística ingenio-campo para asegurar niveles óptimos de tonelaje y sacarosa",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_bullet_monitoring": {
|
||||
"en": "Monitoring of the crop growth rates on the farm, providing evidence of performance",
|
||||
"es-mx": "",
|
||||
"es-mx": "Monitoreo de las tasas de crecimiento del cultivo en la finca, proporcionando evidencia de rendimiento",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_bullet_identifying": {
|
||||
"en": "Identifying growth-related issues that are in need of attention",
|
||||
"es-mx": "",
|
||||
"es-mx": "Identificación de problemas relacionados con el crecimiento que requieren atención",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_bullet_enabling": {
|
||||
"en": "Enabling timely actions to minimize negative impact",
|
||||
"es-mx": "",
|
||||
"es-mx": "Habilitación de acciones oportunas para minimizar el impacto negativo",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"about_data_key_features": {
|
||||
"en": "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.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Características principales del archivo de datos: - Análisis de imágenes satelitales de alta resolución - Detección de cambios semana a semana - Métricas de rendimiento por campo individual - Información accionable para el manejo del cultivo.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_section_heading": {
|
||||
"en": "#### *What is the Chlorophyll Index (CI)?*",
|
||||
"es-mx": "",
|
||||
"es-mx": "#### *¿Qué es el Índice de Clorofila (IC)?*",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_intro_body": {
|
||||
"en": "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:",
|
||||
"es-mx": "",
|
||||
"es-mx": "El Índice de Clorofila (IC) es un índice de vegetación que mide la cantidad relativa de clorofila en las hojas de las plantas. La clorofila es el pigmento verde responsable de la fotosíntesis en las plantas. Valores más altos de IC indican:",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_bullet_photosynthetic": {
|
||||
"en": "Greater photosynthetic activity",
|
||||
"es-mx": "",
|
||||
"es-mx": "Mayor actividad fotosintética",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_bullet_healthy": {
|
||||
"en": "Healthier plant tissue",
|
||||
"es-mx": "",
|
||||
"es-mx": "Tejido vegetal más saludable",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_bullet_nitrogen": {
|
||||
"en": "Better nitrogen uptake",
|
||||
"es-mx": "",
|
||||
"es-mx": "Mejor absorción de nitrógeno",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_bullet_vigorous": {
|
||||
"en": "More vigorous crop growth",
|
||||
"es-mx": "",
|
||||
"es-mx": "Crecimiento más vigoroso del cultivo",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"ci_range_body": {
|
||||
"en": "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.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Los valores de IC generalmente varían de 0 (suelo descubierto o vegetación severamente estresada) a 7+ (vegetación muy saludable y densa). Para la caña de azúcar, valores entre 3-7 generalmente indican buena salud del cultivo, dependiendo de la etapa de crecimiento.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"data_structure_heading": {
|
||||
"en": "### Data File Structure and Columns",
|
||||
"es-mx": "",
|
||||
"es-mx": "### Estructura del Archivo de Datos y Columnas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"data_structure_intro": {
|
||||
"en": "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 integrated with existing farm management systems for further analysis. Each column is described hereunder:",
|
||||
"es-mx": "",
|
||||
"es-mx": "El archivo de datos está organizado en filas, una fila por campo agrícola (polígono), y columnas, proporcionando datos del campo, mediciones reales, resultados de cálculos y descripciones. El archivo de datos puede integrarse directamente con los sistemas de gestión agrícola existentes para análisis adicional. Cada columna se describe a continuación:",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_field_id_desc": {
|
||||
"en": "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.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Identificador único para un campo de caña que combina el nombre del campo y el número de subcampo. Puede ser igual que Field_Name pero también es útil para dar seguimiento a los campos de caña en caso de cambios, divisiones o fusiones.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_farm_section_desc": {
|
||||
"en": "Sub-area or section name",
|
||||
"es-mx": "",
|
||||
"es-mx": "Nombre de subárea o sección",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_field_name_desc": {
|
||||
"en": "Client name or label assigned to a cane field.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Nombre o etiqueta del cliente asignado a un campo de caña.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_acreage_desc": {
|
||||
"en": "Field size in acres",
|
||||
"es-mx": "",
|
||||
"es-mx": "Tamaño del campo en acres",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_status_trigger_desc": {
|
||||
"en": "Shows changes in crop status worth alerting. More detailed explanation of the possible alerts is written down under key concepts.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Muestra cambios en el estado del cultivo que ameritan alerta. Una explicación más detallada de las alertas posibles se encuentra en conceptos clave.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_last_harvest_desc": {
|
||||
"en": "Date of most recent harvest as per satellite detection algorithm / or manual entry",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fecha de la cosecha más reciente según el algoritmo de detección satelital / o ingreso manual",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_age_week_desc": {
|
||||
"en": "Time elapsed since planting/harvest in weeks; used to predict expected growth phases. Reflects planting/harvest date.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Tiempo transcurrido desde la siembra/cosecha en semanas; utilizado para predecir fases de crecimiento esperadas. Refleja la fecha de siembra/cosecha.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_phase_desc": {
|
||||
"en": "Current growth phase (e.g., germination, tillering, stem elongation, grain fill, mature) inferred from crop age",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fase de crecimiento actual (ej., germinación, macollamiento, elongación del tallo, llenado de grano, madurez) inferida de la edad del cultivo",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_germination_progress_desc": {
|
||||
"en": "Estimated percentage or stage of germination/emergence based on CI patterns and age. This goes for young fields (age < 4 months). Remains at 100% when finished.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Porcentaje estimado o etapa de germinación/emergencia basado en patrones de IC y edad. Aplica para campos jóvenes (edad < 4 meses). Permanece en 100% al completarse.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_mean_ci_desc": {
|
||||
"en": "Average Chlorophyll Index value across the field; higher values indicate healthier, greener vegetation. Calculated on a 7-day merged weekly image.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Valor promedio del Índice de Clorofila en todo el campo; valores más altos indican vegetación más saludable y verde. Calculado sobre una imagen semanal fusionada de 7 días.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_weekly_ci_change_desc": {
|
||||
"en": "Week-over-week change in Mean_CI; positive values indicate greening/growth, negative values indicate yellowing/decline",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cambio semanal en Mean_CI; valores positivos indican reverdecimiento/crecimiento, valores negativos indican amarillamiento/declive",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_four_week_trend_desc": {
|
||||
"en": "Long term change in mean CI; smoothed trend (strong growth, growth, no growth, decline, strong decline)",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cambio a largo plazo en el IC promedio; tendencia suavizada (crecimiento fuerte, crecimiento, sin crecimiento, declive, declive fuerte)",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_ci_range_desc": {
|
||||
"en": "Min-max Chlorophyll Index values within the field; wide ranges indicate spatial heterogeneity/patches. Derived from week mosaic.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Valores mínimo-máximo del Índice de Clorofila dentro del campo; rangos amplios indican heterogeneidad espacial/parches. Derivado del mosaico semanal.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_ci_percentiles_desc": {
|
||||
"en": "The CI-range without border effects",
|
||||
"es-mx": "",
|
||||
"es-mx": "El rango de IC sin efectos de borde",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_cv_desc": {
|
||||
"en": "Coefficient of variation of CI; measures field uniformity (lower = more uniform, >0.25 = poor uniformity). Derived from week mosaic. In percentages.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Coeficiente de variación del IC; mide la uniformidad del campo (menor = más uniforme, >0.25 = uniformidad deficiente). Derivado del mosaico semanal. En porcentajes.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_cv_trend_short_desc": {
|
||||
"en": "Trend of CV over two weeks. Indicating short-term heterogeneity.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Tendencia del CV en dos semanas. Indica heterogeneidad a corto plazo.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_cv_trend_long_desc": {
|
||||
"en": "Slope of 8-week trend line.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Pendiente de la línea de tendencia de 8 semanas.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_imminent_prob_desc": {
|
||||
"en": "Probability (0-1) that the field is ready for harvest based on LSTM harvest model predictions",
|
||||
"es-mx": "",
|
||||
"es-mx": "Probabilidad (0-1) de que el campo esté listo para cosecha basado en predicciones del modelo de cosecha LSTM",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_cloud_pct_desc": {
|
||||
"en": "Percentage of field visible in the satellite image (unobstructed by clouds); lower values indicate poor data quality",
|
||||
"es-mx": "",
|
||||
"es-mx": "Porcentaje del campo visible en la imagen satelital (sin obstrucción de nubes); valores más bajos indican calidad de datos deficiente",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"col_cloud_category_desc": {
|
||||
"en": "Classification of cloud cover level (e.g., clear, partial, heavy); indicates confidence in CI measurements",
|
||||
"es-mx": "",
|
||||
"es-mx": "Clasificación del nivel de cobertura de nubes (ej., despejado, parcial, denso); indica confianza en las mediciones de IC",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"key_concepts_heading": {
|
||||
"en": "# 3. Key Concepts",
|
||||
"es-mx": "",
|
||||
"es-mx": "# 3. Conceptos Clave",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"growth_phases_heading": {
|
||||
"en": "#### *Growth Phases (Age-Based)*",
|
||||
"es-mx": "",
|
||||
"es-mx": "#### *Fases de Crecimiento (Basadas en Edad)*",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"growth_phases_intro": {
|
||||
"en": "Each field is assigned to one of four growth phases based on age in weeks since planting:",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cada campo se asigna a una de cuatro fases de crecimiento según la edad en semanas desde la siembra:",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"germination_age_range": {
|
||||
"en": "0-6 weeks",
|
||||
"es-mx": "",
|
||||
"es-mx": "0-6 semanas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"tillering_age_range": {
|
||||
"en": "4-16 weeks",
|
||||
"es-mx": "",
|
||||
"es-mx": "4-16 semanas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"grand_growth_age_range": {
|
||||
"en": "17-39 weeks",
|
||||
"es-mx": "",
|
||||
"es-mx": "17-39 semanas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"maturation_age_range": {
|
||||
"en": "39+ weeks",
|
||||
"es-mx": "",
|
||||
"es-mx": "39+ semanas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"germination_characteristics": {
|
||||
"en": "Crop emergence and early establishment; high variability expected",
|
||||
"es-mx": "",
|
||||
"es-mx": "Emergencia del cultivo y establecimiento temprano; alta variabilidad esperada",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"tillering_characteristics": {
|
||||
"en": "Shoot multiplication and plant establishment; rapid growth phase",
|
||||
"es-mx": "",
|
||||
"es-mx": "Multiplicación de brotes y establecimiento de la planta; fase de crecimiento rápido",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"grand_growth_characteristics": {
|
||||
"en": "Peak vegetative growth; maximum height and biomass accumulation",
|
||||
"es-mx": "",
|
||||
"es-mx": "Pico de crecimiento vegetativo; máxima altura y acumulación de biomasa",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"maturation_characteristics": {
|
||||
"en": "Ripening phase; sugar accumulation and preparation for harvest",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fase de maduración; acumulación de azúcar y preparación para la cosecha",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"status_alert_heading": {
|
||||
"en": "#### *Status Alert*",
|
||||
"es-mx": "",
|
||||
"es-mx": "#### *Alerta de Estado*",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"status_alert_intro": {
|
||||
"en": "Status alerts indicate the current field condition based on CI and age-related patterns. Each field receives **one alert** reflecting its most relevant status:",
|
||||
"es-mx": "",
|
||||
"es-mx": "Las alertas de estado indican la condición actual del campo basada en patrones de IC y edad. Cada campo recibe **una alerta** que refleja su estado más relevante:",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_ready_condition": {
|
||||
"en": "Harvest model > 0.50 and crop is mature",
|
||||
"es-mx": "",
|
||||
"es-mx": "Modelo de cosecha > 0.50 y el cultivo está maduro",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_ready_phase_info": {
|
||||
"en": "Active from 52 weeks onwards",
|
||||
"es-mx": "",
|
||||
"es-mx": "Activo a partir de las 52 semanas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_ready_msg": {
|
||||
"en": "Ready for harvest-check",
|
||||
"es-mx": "",
|
||||
"es-mx": "Listo para verificación de cosecha",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvested_bare_condition": {
|
||||
"en": "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",
|
||||
"es-mx": "",
|
||||
"es-mx": "Campo de 50 semanas o más que muestra valores promedio de IC menores a 1.5 (por un máximo de tres semanas) O que cae de un IC mayor a menor de 1.5. La alerta se desactiva si el IC sube y supera 1.5 nuevamente",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvested_bare_phase_info": {
|
||||
"en": "Maturation (39+)",
|
||||
"es-mx": "",
|
||||
"es-mx": "Maduración (39+)",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvested_bare_msg": {
|
||||
"en": "Harvested or bare field",
|
||||
"es-mx": "",
|
||||
"es-mx": "Campo cosechado o descubierto",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"stress_condition": {
|
||||
"en": "Mean CI on field drops by 2+ points but field mean CI remains higher than 1.5",
|
||||
"es-mx": "",
|
||||
"es-mx": "El IC promedio del campo cae 2+ puntos pero el IC promedio del campo permanece mayor a 1.5",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"stress_phase_info": {
|
||||
"en": "Any",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cualquiera",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"stress_msg": {
|
||||
"en": "Strong decline in crop health",
|
||||
"es-mx": "",
|
||||
"es-mx": "Declive fuerte en la salud del cultivo",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_date_heading": {
|
||||
"en": "#### *Harvest Date and Harvest Imminent*",
|
||||
"es-mx": "",
|
||||
"es-mx": "#### *Fecha de Cosecha y Cosecha Inminente*",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_date_body_1": {
|
||||
"en": "The SmartCane algorithm calculates the last harvest date and the probability of harvest approaching in the next 4 weeks. Two different algorithms are used.",
|
||||
"es-mx": "",
|
||||
"es-mx": "El algoritmo de SmartCane calcula la última fecha de cosecha y la probabilidad de que la cosecha se aproxime en las próximas 4 semanas. Se utilizan dos algoritmos diferentes.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_date_body_2": {
|
||||
"en": "The **last harvest date** is a timeseries analysis 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.",
|
||||
"es-mx": "",
|
||||
"es-mx": "La **última fecha de cosecha** es un análisis de series de tiempo de los niveles de IC de años anteriores, basado en campos limpios administrados por la fábrica como conjunto de datos para el aprendizaje automático, se ha alcanzado una confiabilidad superior al 90%. Los campos pequeños administrados por pequeños productores (0.3 acres) tienen efectos secundarios específicos y características de manejo que influyen en los resultados del modelo.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_date_body_3": {
|
||||
"en": "**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 leaf tissue.",
|
||||
"es-mx": "",
|
||||
"es-mx": "**Imminent_probability** de cosecha es un algoritmo de predicción que estima la probabilidad de que un cultivo esté listo para ser cosechado en el futuro cercano. Esta predicción toma en cuenta los niveles de IC, basándose en el desarrollo vegetativo de la caña de azúcar en la última etapa de Maduración, donde toda la sacarosa se concentra en el tallo, agotando la energía y función productiva de las hojas, reduciendo los niveles de IC en el tejido foliar.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_date_body_4": {
|
||||
"en": "Both algorithms are not always in sync, and can have contradictory results. Wider field characteristics analysis is suggested if such contradictory calculation results occur.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Ambos algoritmos no siempre están sincronizados y pueden tener resultados contradictorios. Se sugiere un análisis más amplio de las características del campo si se presentan resultados de cálculo contradictorios.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
}
|
||||
|
|
@ -544,127 +544,127 @@
|
|||
"status_translations": {
|
||||
"PHASE DISTRIBUTION": {
|
||||
"en": "Phase Distribution",
|
||||
"es-mx": "",
|
||||
"es-mx": "Distribución de Fases",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"OPERATIONAL ALERTS": {
|
||||
"en": "Operational Alerts",
|
||||
"es-mx": "",
|
||||
"es-mx": "Alertas Operativas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"AREA CHANGE": {
|
||||
"en": "Area Change",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cambio de Área",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"CLOUD INFLUENCE": {
|
||||
"en": "Cloud Influence",
|
||||
"es-mx": "",
|
||||
"es-mx": "Influencia de Nubes",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"TOTAL FARM": {
|
||||
"en": "Total Farm",
|
||||
"es-mx": "",
|
||||
"es-mx": "Total de la Finca",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Germination": {
|
||||
"en": "Germination",
|
||||
"es-mx": "",
|
||||
"es-mx": "Germinación",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Tillering": {
|
||||
"en": "Tillering",
|
||||
"es-mx": "",
|
||||
"es-mx": "Macollamiento",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Grand Growth": {
|
||||
"en": "Grand Growth",
|
||||
"es-mx": "",
|
||||
"es-mx": "Gran Crecimiento",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Maturation": {
|
||||
"en": "Maturation",
|
||||
"es-mx": "",
|
||||
"es-mx": "Maduración",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Unknown Phase": {
|
||||
"en": "Unknown Phase",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fase Desconocida",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvest_ready": {
|
||||
"en": "Ready for Harvest-Check",
|
||||
"es-mx": "",
|
||||
"es-mx": "Listo para Verificación de Cosecha",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"harvested_bare": {
|
||||
"en": "Harvested / Bare Field",
|
||||
"es-mx": "",
|
||||
"es-mx": "Cosechado / Campo Descubierto",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"stress_detected": {
|
||||
"en": "Stress Detected",
|
||||
"es-mx": "",
|
||||
"es-mx": "Estrés Detectado",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"germination_delayed": {
|
||||
"en": "Germination Delayed",
|
||||
"es-mx": "",
|
||||
"es-mx": "Germinación Retrasada",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"growth_on_track": {
|
||||
"en": "Growth on Track",
|
||||
"es-mx": "",
|
||||
"es-mx": "Crecimiento en Curso",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"No active triggers": {
|
||||
"en": "No Active Triggers",
|
||||
"es-mx": "",
|
||||
"es-mx": "Sin Alertas Activas",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Improving": {
|
||||
"en": "Improving",
|
||||
"es-mx": "",
|
||||
"es-mx": "Mejorando",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Stable": {
|
||||
"en": "Stable",
|
||||
"es-mx": "",
|
||||
"es-mx": "Estable",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Declining": {
|
||||
"en": "Declining",
|
||||
"es-mx": "",
|
||||
"es-mx": "En Declive",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"Total Acreage": {
|
||||
"en": "Total Acreage",
|
||||
"es-mx": "",
|
||||
"es-mx": "Superficie Total",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_na": {
|
||||
"en": "KPI data not available for {project_dir} on this date.",
|
||||
"es-mx": "",
|
||||
"es-mx": "Datos de KPI no disponibles para {project_dir} en esta fecha.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
}
|
||||
|
|
@ -672,157 +672,157 @@
|
|||
"figure_translations": {
|
||||
"kpi_col_category": {
|
||||
"en": "KPI Category",
|
||||
"es-mx": "",
|
||||
"es-mx": "Categoría de KPI",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_col_item": {
|
||||
"en": "Item",
|
||||
"es-mx": "",
|
||||
"es-mx": "Elemento",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_col_acreage": {
|
||||
"en": "Acreage",
|
||||
"es-mx": "",
|
||||
"es-mx": "Superficie",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_col_percent": {
|
||||
"en": "Percentage of Total Fields",
|
||||
"es-mx": "",
|
||||
"es-mx": "Porcentaje del Total de Campos",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"kpi_col_fields": {
|
||||
"en": "# Fields",
|
||||
"es-mx": "",
|
||||
"es-mx": "# Campos",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"hexbin_legend_acres": {
|
||||
"en": "Total Acres",
|
||||
"es-mx": "",
|
||||
"es-mx": "Acres Totales",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"hexbin_subtitle": {
|
||||
"en": "Acres of fields 'harvest ready within a month'",
|
||||
"es-mx": "",
|
||||
"es-mx": "Acres de campos listos para cosecha dentro de un mes",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"hexbin_not_ready": {
|
||||
"en": "Not harvest ready",
|
||||
"es-mx": "",
|
||||
"es-mx": "No listo para cosecha",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"metadata_caption": {
|
||||
"en": "Report Metadata",
|
||||
"es-mx": "",
|
||||
"es-mx": "Metadatos del Reporte",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"metric": {
|
||||
"en": "Metric",
|
||||
"es-mx": "",
|
||||
"es-mx": "Métrica",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"value": {
|
||||
"en": "Value",
|
||||
"es-mx": "",
|
||||
"es-mx": "Valor",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"report_gen": {
|
||||
"en": "Report Generated",
|
||||
"es-mx": "",
|
||||
"es-mx": "Reporte Generado",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"data_source": {
|
||||
"en": "Data Source",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fuente de Datos",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"analysis_period": {
|
||||
"en": "Analysis Period",
|
||||
"es-mx": "",
|
||||
"es-mx": "Período de Análisis",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"tot_fields_number": {
|
||||
"en": "Total Fields [number]",
|
||||
"es-mx": "",
|
||||
"es-mx": "Total de Campos [número]",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"tot_area_acres": {
|
||||
"en": "Total Area [acres]",
|
||||
"es-mx": "",
|
||||
"es-mx": "Área Total [acres]",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"next_update": {
|
||||
"en": "Next Update",
|
||||
"es-mx": "",
|
||||
"es-mx": "Próxima Actualización",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"service_provided": {
|
||||
"en": "Service provided",
|
||||
"es-mx": "",
|
||||
"es-mx": "Servicio proporcionado",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"service_start": {
|
||||
"en": "Starting date service",
|
||||
"es-mx": "",
|
||||
"es-mx": "Fecha de inicio del servicio",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"next_wed": {
|
||||
"en": "Next Wednesday",
|
||||
"es-mx": "",
|
||||
"es-mx": "Próximo miércoles",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"week": {
|
||||
"en": "Week",
|
||||
"es-mx": "",
|
||||
"es-mx": "Semana",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"of": {
|
||||
"en": "of",
|
||||
"es-mx": "",
|
||||
"es-mx": "de",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"project": {
|
||||
"en": "Project",
|
||||
"es-mx": "",
|
||||
"es-mx": "Proyecto",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"cane_supply_service": {
|
||||
"en": "Cane Supply Office - Weekly",
|
||||
"es-mx": "",
|
||||
"es-mx": "Oficina de Abastecimiento de Caña - Semanal",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"unknown": {
|
||||
"en": "Unknown",
|
||||
"es-mx": "",
|
||||
"es-mx": "Desconocido",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
},
|
||||
"no_field_data": {
|
||||
"en": "No field-level KPI data available for this report period.",
|
||||
"es-mx": "",
|
||||
"es-mx": "No hay datos de KPI a nivel de campo disponibles para este período de reporte.",
|
||||
"pt-br": "",
|
||||
"sw": ""
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue