SmartCane/r_app/2_CI_data_prep.R
2024-03-14 13:00:02 +01:00

404 lines
14 KiB
R

# activeer de renv omgeving;
renv::activate('~/smartCane/r_app')
renv::restore()
library(here)
library(sf)
library(terra)
library(tidyverse)
library(lubridate)
library(exactextractr)
library(CIprep)
# Vang alle command line argumenten op
args <- commandArgs(trailingOnly = TRUE)
# Controleer of er ten minste één argument is doorgegeven
if (length(args) == 0) {
stop("Geen argumenten doorgegeven aan het script")
}
# Converteer het eerste argument naar een numerieke waarde
weeks_ago <- as.numeric(args[1])
# Controleer of weeks_ago een geldig getal is
if (is.na(weeks_ago)) {
# stop("Het argument is geen geldig getal")
weeks_ago <- 0
}
# Converteer het tweede argument naar een string waarde
project_dir <- as.character(args[2])
# Controleer of data_dir een geldige waarde is
if (!is.character(project_dir)) {
project_dir <- "chemba"
}
laravel_storage_dir <- here("laravel_app/storage/app", project_dir)
#preparing directories
planet_tif_folder <- here(laravel_storage_dir, "merged_tif")
merged_final <- here(laravel_storage_dir, "merged_final_tif")
new_project_question = FALSE
planet_tif_folder <- here(laravel_storage_dir, "merged_tif")
merged_final <- here(laravel_storage_dir, "merged_final_tif")
data_dir <- here(laravel_storage_dir, "Data")
extracted_CI_dir <- here(data_dir, "extracted_ci")
daily_CI_vals_dir <- here(extracted_CI_dir, "daily_vals")
cumulative_CI_vals_dir <- here(extracted_CI_dir, "cumulative_vals")
weekly_CI_mosaic <- here(laravel_storage_dir, "weekly_mosaic")
daily_vrt <- here(data_dir, "vrt")
harvest_dir <- here(data_dir, "HarvestData")
source(here("r_app", "parameters_project.R"))
dir.create(here(laravel_storage_dir))
dir.create(here(data_dir))
dir.create(here(extracted_CI_dir))
dir.create(here(daily_CI_vals_dir))
dir.create(here(cumulative_CI_vals_dir))
dir.create(here(weekly_CI_mosaic))
dir.create(here(daily_vrt))
dir.create(merged_final)
dir.create(harvest_dir)
# Creating weekly mosaic
dates <- date_list(weeks_ago)
#load pivot geojson
# pivot_sf_q <- st_read(here(data_dir, "pivot.geojson")) %>% dplyr::select(pivot, pivot_quadrant) %>% vect()
raster_files <- list.files(planet_tif_folder,full.names = T, pattern = ".tif")
head(raster_files)
filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>%
compact() %>%
flatten_chr()
# filtered_files <- raster_files #for first CI extraction
# create_mask_and_crop <- function(file, field_boundaries) {
# message("starting ", file)
# CI <- rast(file)
# # names(CI) <- c("green","nir")
# message("raster loaded")
#
# CI <- CI[[2]]/CI[[1]]-1
# # CI <- CI$nir/CI$green-1
# message("CI calculated")
# CI <- terra::crop(CI, field_boundaries, mask = TRUE) #%>% CI_func()
#
# new_file <- here(merged_final, paste0(tools::file_path_sans_ext(basename(file)), ".tif"))
# writeRaster(CI, new_file, overwrite = TRUE)
#
# vrt_file <- here(daily_vrt, paste0(tools::file_path_sans_ext(basename(file)), ".vrt"))
# terra::vrt(new_file, vrt_file, overwrite = TRUE)
#
# return(CI)
# }
create_mask_and_crop <- function(file, field_boundaries) {
# file <- filtered_files[5]
message("starting ", file)
loaded_raster <- rast(file)
names(loaded_raster) <- c("Red", "Green", "Blue", "NIR")
# names(CI) <- c("green","nir")
message("raster loaded")
# CI <- CI[[2]] / CI[[1]] - 1
CI <- loaded_raster$NIR / loaded_raster$Green - 1
loaded_raster$CI <- CI
# CI <- CI$nir/CI$green-1
message("CI calculated")
loaded_raster <- terra::crop(loaded_raster, field_boundaries, mask = TRUE) #%>% CI_func()
loaded_raster[loaded_raster == 0] <- NA
# names(v_crop) <- c("red", "green", "blue","nir", "cloud" ,"CI")
# v_crop$CI <- v_crop$CI - 1
new_file <- here(merged_final, paste0(tools::file_path_sans_ext(basename(file)), ".tif"))
writeRaster(loaded_raster, new_file, overwrite = TRUE)
vrt_file <- here(daily_vrt, paste0(tools::file_path_sans_ext(basename(file)), ".vrt"))
terra::vrt(new_file, vrt_file, overwrite = TRUE)
# v_crop <- mask_raster(v, pivot_sf_q)
return(loaded_raster)
}
vrt_list <- list()
# for (file in raster_files) {
# v_crop <- create_mask_and_crop(file, field_boundaries)
# message(file, " processed")
# gc()
# }
for (file in filtered_files) {
v_crop <- create_mask_and_crop(file, field_boundaries)
emtpy_or_full <- global(v_crop, "notNA")
vrt_file <- here(daily_vrt, paste0(tools::file_path_sans_ext(basename(file)), ".vrt"))
if(emtpy_or_full[1,] > 10000){
vrt_list[vrt_file] <- vrt_file
}else{
file.remove(vrt_file)
}
message(file, " processed")
gc()
}
# list_global <- list_global %>% flatten_chr()
vrt_list <- vrt_list %>% flatten_chr()
total_pix_area <- rast(vrt_list[1]) %>% terra::subset(1) %>% setValues(1) %>%
crop(field_boundaries, mask = TRUE) %>%
global(., fun="notNA") #%>%
layer_5_list <- purrr::map(vrt_list, function(vrt_list) {
rast(vrt_list[1]) %>% terra::subset(1)
}) %>% rast()
missing_pixels_count <- layer_5_list %>% global(., fun="notNA") %>%
mutate(
total_pixels = total_pix_area$notNA,
missing_pixels_percentage = round(100 -((notNA/total_pix_area$notNA)*100)),
thres_5perc = as.integer(missing_pixels_percentage < 5),
thres_40perc = as.integer(missing_pixels_percentage < 45)
)
index_5perc <- which(missing_pixels_count$thres_5perc == max(missing_pixels_count$thres_5perc) )
index_40perc <- which(missing_pixels_count$thres_40perc == max(missing_pixels_count$thres_40perc))
## Create mosaic
if(sum(missing_pixels_count$thres_5perc)>1){
message("More than 1 raster without clouds (<5%), max composite made")
cloudy_rasters_list <- vrt_list[index_5perc]
rsrc <- sprc(cloudy_rasters_list)
x <- mosaic(rsrc, fun = "max")
# names(x) <- "CI"
names(x) <- c("Red", "Green", "Blue", "NIR", "CI")
}else if(sum(missing_pixels_count$thres_5perc)==1){
message("Only 1 raster without clouds (<5%)")
x <- rast(vrt_list[index_5perc[1]])
# names(x) <- c("CI")
names(x) <- c("Red", "Green", "Blue", "NIR", "CI")
}else if(sum(missing_pixels_count$thres_40perc)>1){
message("More than 1 image contains clouds, composite made of <40% cloud cover images")
cloudy_rasters_list <- vrt_list[index_40perc]
rsrc <- sprc(cloudy_rasters_list)
x <- mosaic(rsrc, fun = "max")
# names(x) <- "CI"
names(x) <- c("Red", "Green", "Blue", "NIR", "CI")
}else if(sum(missing_pixels_count$thres_40perc)==1){
message("Only 1 image available but contains clouds")
x <- rast(vrt_list[index_40perc[1]])
# names(x) <- c("CI")
names(x) <- c("Red", "Green", "Blue", "NIR", "CI")
}else{
message("No cloud free images available, all images combined")
rsrc <- sprc(vrt_list)
x <- mosaic(rsrc, fun = "max")
# x <- rast(vrt_list[1]) %>% setValues(NA)
# names(x) <- c("CI")
names(x) <- c("Red", "Green", "Blue", "NIR", "CI")
}
plot(x$CI, main = paste("CI map ", dates$week))
plotRGB(x, main = paste("RGB map ", dates$week))
file_path_tif <- here(weekly_CI_mosaic ,paste0("week_", sprintf("%02d", dates$week), "_", dates$year, ".tif"))
writeRaster(x, file_path_tif, overwrite=TRUE)
message("Raster written/made at: ", file_path_tif)
# Extracting CI
extract_rasters_daily <- function(file, field_geojson, quadrants = TRUE, save_dir) {
# x <- rast(filtered_files[1])%>% CI_func(drop_layers = TRUE)
# date <- date_extract(filtered_files[1])
# field_geojson <- sf::st_as_sf(pivot_sf_q)
field_geojson <- sf::st_as_sf(field_geojson)
x <- rast(file[1])
date <- date_extract(file)
pivot_stats <- cbind(field_geojson, mean_CI = round(exactextractr::exact_extract(x$CI, field_geojson, fun = "mean"), 2)) %>%
st_drop_geometry() %>% rename("{date}" := mean_CI)
save_suffix <- if (quadrants){"quadrant"} else {"whole_field"}
save_path <- here(save_dir, paste0("extracted_", date, "_", save_suffix, ".rds"))
saveRDS(pivot_stats, save_path)
}
# pivot_sf_q <- st_read(here("..", "Data", "pivot_20210625.geojson")) %>% dplyr::select(pivot, pivot_quadrant) %>% vect()
# pivot_sf <- st_read(here(data_dir, "pivot.geojson")) %>% dplyr::select(pivot, pivot_quadrant) %>% group_by(pivot) %>% summarise() %>% vect()
# message("pivot loaded")
raster_files_NEW <- list.files(merged_final,full.names = T, pattern = ".tif")
# pivots_dates0 <- readRDS(here(harvest_dir, "harvest_data_new")) %>% filter(
# pivot %in% c("1.1", "1.2", "1.3", "1.4", "1.6", "1.7", "1.8", "1.9", "1.10", "1.11", "1.12", "1.13",
# "1.14" , "1.16" , "1.17" , "1.18" ,"2.1", "2.2", "2.3" , "2.4", "2.5", "3.1", "3.2", "3.3",
# "4.1", "4.2", "4.3", "4.4", "4.5", "4.6", "5.1" ,"5.2", "5.3", "5.4", "6.1", "6.2", "DL1.1", "DL1.3")
# )
# harvesting_data <- pivots_dates0 %>%
# select(c("pivot_quadrant", "season_start_2021", "season_end_2021", "season_start_2022", "season_end_2022", "season_start_2023", "season_end_2023", "season_start_2024", "season_end_2024")) %>%
# pivot_longer(cols = starts_with("season"), names_to = "Year", values_to = "value") %>%
# separate(Year, into = c("name", "Year"), sep = "(?<=season_start|season_end)\\_", remove = FALSE) %>%
# mutate(name = str_to_title(name)) %>%
# pivot_wider(names_from = name, values_from = value) %>%
# rename(Field = pivot_quadrant)
#If run for the firsttime, it will extract all data since the start and put into a table.rds. otherwise it will only add on to the existing table.
if (new_project_question == TRUE) {
print("combined_CI_data.rds does not exist. Preparing combined_CI_data.rds file for all available images.")
walk(raster_files_NEW, extract_rasters_daily, field_geojson= field_boundaries, quadrants = F, daily_CI_vals_dir)
extracted_values <- list.files(here(daily_CI_vals_dir), full.names = TRUE)
pivot_stats <- extracted_values %>%
map(readRDS) %>% list_rbind() %>%
group_by(subField) %>%
summarise(across(everything(), ~ first(na.omit(.))))
saveRDS(pivot_stats, here(cumulative_CI_vals_dir,"combined_CI_data.rds")) #used to save the rest of the data into one file
pivot_stats2 <- pivot_stats
print("All CI values extracted from all historic images")
} else {
print("combined_CI_data.rds exists, adding the latest image data to the table.")
filtered_files <- map(dates$days_filter, ~ raster_files_NEW[grepl(pattern = .x, x = raster_files_NEW)]) %>%
compact() %>%
flatten_chr()
walk(filtered_files, extract_rasters_daily, field_geojson= field_boundaries, quadrants = TRUE, daily_CI_vals_dir)
extracted_values <- list.files(daily_CI_vals_dir, full.names = TRUE)
extracted_values <- map(dates$days_filter, ~ extracted_values[grepl(pattern = .x, x = extracted_values)]) %>%
compact() %>%
flatten_chr()
pivot_stats <- extracted_values %>%
map(readRDS) %>% list_rbind() %>%
group_by(pivot_quadrant) %>%
summarise(across(everything(), ~ first(na.omit(.))))
combined_CI_data <- readRDS(here(cumulative_CI_vals_dir,"combined_CI_data.rds")) #%>% drop_na(pivot_quadrant)
pivot_stats2 <- bind_rows(pivot_stats, combined_CI_data)
# pivot_stats2 <- combined_CI_data
print("All CI values extracted from latest 7 images.")
}
# gather data into long format for easier calculation and visualisation
pivot_stats_long <- pivot_stats2 %>%
tidyr::gather("Date", value, -Field, -subField, -sub_area ) %>%
mutate(Date = right(Date, 8),
Date = lubridate::ymd(Date)
) %>%
drop_na(c("value","Date")) %>%
mutate(value = as.numeric(value))%>%
filter_all(all_vars(!is.infinite(.))) %>%
# rename(Field = pivot_quadrant,
# subField = Field) %>%
unique()
# #2021
# pivot_select_model_Data_2021 <- harvesting_data %>% filter(Year == 2021) %>% pull(Field)
#
# pivot_select_model_Data_2022 <- harvesting_data %>% filter(Year == 2022) %>% pull(Field)
pivot_select_model_Data_2023 <- harvesting_data %>% filter(Year == 2023) %>% pull(subField)
pivot_select_model_Data_2024 <- harvesting_data %>% filter(Year == 2024) %>% pull(subField)
# pivots_dates_Data_2022 <- pivots_dates0 %>% filter(!is.na(season_end_2022))
# pivot_select_model_Data_2022 <- unique(pivots_dates_Data_2022$pivot_quadrant )
#
# pivots_dates_Data_2023 <- pivots_dates0 %>% filter(!is.na(season_start_2023))
# pivot_select_model_Data_2023 <- unique(pivots_dates_Data_2023$pivot_quadrant)
#
# pivots_dates_Data_2024 <- pivots_dates0 %>% filter(!is.na(season_start_2024))
# pivot_select_model_Data_2024 <- unique(pivots_dates_Data_2024$pivot_quadrant)
extract_CI_data <- function(field_names, harvesting_data, field_CI_data, season) {
# field_names = "AG1D06P"
# field_names = "1.13A"
# harvesting_data = harvesting_data
# field_CI_data = pivot_stats_long
# season= 2023
filtered_harvesting_data <- harvesting_data %>%
filter(Year == season, subField %in% field_names)
filtered_field_CI_data <- field_CI_data %>%
filter(subField %in% field_names)
# CI <- map_df(field_names, ~ {
ApproxFun <- approxfun(x = filtered_field_CI_data$Date, y = filtered_field_CI_data$value)
Dates <- seq.Date(ymd(min(filtered_field_CI_data$Date)), ymd(max(filtered_field_CI_data$Date)), by = 1)
LinearFit <- ApproxFun(Dates)
CI <- data.frame(Date = Dates, FitData = LinearFit) %>%
left_join(., filtered_field_CI_data, by = "Date") %>%
filter(Date > filtered_harvesting_data$Season_start & Date < filtered_harvesting_data$Season_end) %>%
mutate(DOY = seq(1, n(), 1),
model = paste0("Data", season, " : ", field_names),
season = season,
subField = field_names)
# }) #%>%
#{if (length(field_names) > 0) message("Done!")}
return(CI)
}
## Extracting the correct CI values
# Data_2021 <- map(pivot_select_model_Data_2021, ~ extract_CI_data(.x, harvesting_data = harvesting_data, field_CI_data = pivot_stats_long, season = 2021)) %>% list_rbind()
# message('2021')
# Data_2022 <- map(pivot_select_model_Data_2022, ~ extract_CI_data(.x, harvesting_data = harvesting_data, field_CI_data = pivot_stats_long, season = 2022)) %>% list_rbind()
# message('2022')
Data_2023 <- map(pivot_select_model_Data_2023, ~ extract_CI_data(.x, harvesting_data = harvesting_data, field_CI_data = pivot_stats_long, season = 2023)) %>% list_rbind()
message('2023')
Data_2024 <- map(pivot_select_model_Data_2024, ~ extract_CI_data(.x, harvesting_data = harvesting_data, field_CI_data = pivot_stats_long, season = 2024)) %>% list_rbind()
message('2024')
CI_all <- rbind(Data_2023, Data_2024)
message('CI_all created')
#CI_all <- Data_2023
CI_all <- CI_all %>% group_by(model) %>% mutate(CI_per_day = FitData - lag(FitData),
cumulative_CI = cumsum(FitData))
message('CI_all cumulative')
head(CI_all)
message('show head')
saveRDS(CI_all, here(cumulative_CI_vals_dir,"All_pivots_Cumulative_CI_quadrant_year_v2.rds"))
message('rds saved')