diff --git a/laravel_app/app/Jobs/ProjectDownloadRDSJob.php b/laravel_app/app/Jobs/ProjectDownloadRDSJob.php index 688f77c..7c27b8f 100644 --- a/laravel_app/app/Jobs/ProjectDownloadRDSJob.php +++ b/laravel_app/app/Jobs/ProjectDownloadRDSJob.php @@ -34,7 +34,7 @@ public function handle(): void { $command = [ - sprintf('%sbuild_RDS.sh', base_path('../')), + sprintf('%supdate_RDS.sh', base_path('../')), sprintf('--end_date=%s', $this->date->format('Y-m-d')), sprintf('--offset=%d', $this->offset), sprintf('--project_dir=%s', $this->project->download_path), diff --git a/r_app/2_CI_data_prep.R b/r_app/2_CI_data_prep.R deleted file mode 100644 index 30b436a..0000000 --- a/r_app/2_CI_data_prep.R +++ /dev/null @@ -1,855 +0,0 @@ -# activeer de renv omgeving; - -# renv::activate('~/smartCane/r_app') -# renv::restore() - - - -library(here) -library(sf) -library(terra) -library(tidyverse) -library(lubridate) -library(exactextractr) -library(readxl) -#funcion CI_prep package - -date_list <- function(end_date, offset){ - offset <- as.numeric(offset) - 1 - end_date <- as.Date(end_date) - start_date <- end_date - lubridate::days(offset) - - week <- week(start_date) - year <- year(start_date) - days_filter <- seq(from = start_date, to = end_date, by = "day") - - return(list("week" = week, "year" = year, "days_filter" = days_filter)) -} - -# date_list <- function(weeks_in_the_paste){ -# week <- week(Sys.Date()- weeks(weeks_in_the_paste) ) -# year <- year(Sys.Date()- weeks(weeks_in_the_paste) ) -# days_filter <- Sys.Date() - weeks(weeks_in_the_paste) - days(0:6) -# -# return(c("week" = week, -# "year" = year, -# "days_filter" = list(days_filter))) -# -# } - -CI_func <- function(x, drop_layers = FALSE){ - CI <- x[[4]]/x[[2]]-1 - add(x) <- CI - names(x) <- c("red", "green", "blue","nir", "cloud" ,"CI") - if(drop_layers == FALSE){ - return(x) - }else{ - return(x$CI) - } -} - -mask_raster <- function(raster, fields){ - # x <- rast(filtered_files[1]) - x <- rast(raster) - emtpy_or_full <- global(x, sum) - - if(emtpy_or_full[1,] >= 2000000){ - names(x) <- c("red", "green", "blue","nir", "cloud") - cloud <- x$cloud - - cloud[cloud == 0 ] <- NA - x_masked <- mask(x, cloud, inverse = T) %>% crop(.,fields, mask = TRUE ) - x_masked <- x_masked %>% CI_func() - - message(raster, " masked") - return(x_masked) - } -} - -date_extract <- function(file_path) { - str_extract(file_path, "\\d{4}-\\d{2}-\\d{2}") -} - -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]) %>% CI_func(drop_layers = TRUE) - date <- date_extract(file) - - pivot_stats <- cbind(field_geojson, mean_CI = round(exactextractr::exact_extract(x, 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) -} - -right = function(text, num_char) { - substr(text, nchar(text) - (num_char-1), nchar(text)) -} - -extract_CI_data <- function(field_names, harvesting_data, field_CI_data, season) { - # field_names = "1.2A" - # harvesting_data = harvesting_data - # field_CI_data = pivot_stats_long - # season= 2021 - - filtered_harvesting_data <- harvesting_data %>% - filter(year == season, field %in% field_names) - - filtered_field_CI_data <- field_CI_data %>% - filter(field %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, - field = field_names) - # }) #%>% - #{if (length(field_names) > 0) message("Done!")} - - return(CI) -} - -load_fields <- function(geojson_path) { - field_geojson <- st_read(geojson_path) %>% - select(pivot, pivot_quadrant) %>% - vect() - return(field_geojson) -} - -load_harvest_data <- function(havest_data_path){ - harvest_data <- readRDS(havest_data_path) - return(harvest_data) -} - -load_rasters <- function(raster_path, dates) { - raster_files <- list.files(raster_path, full.names = TRUE, pattern = ".tif") - filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% - compact() %>% - flatten_chr() - - return(filtered_files) -} - -mask_and_set_names <- function(filtered_files, fields) { - rasters_masked <- map(filtered_files, mask_raster, fields = fields) %>% set_names(filtered_files) - rasters_masked[sapply(rasters_masked, is.null)] <- NULL - rasters_masked <- setNames(rasters_masked, map_chr(names(rasters_masked), date_extract)) - - return(rasters_masked) -} - -calculate_total_pix_area <- function(filtered_files, fields_geojson) { - # total_pix_area <- rast(filtered_files[1]) %>% - # subset(1) %>% - # crop(fields_geojson, mask = TRUE)%>% - # global(.data, fun = "notNA") - total_pix_area <- rast(filtered_files[1]) %>% subset(1) %>% crop(fields_geojson, mask = TRUE) %>% freq(., usenames = TRUE) - - return(total_pix_area) -} - -cloud_layer_extract <- function(rasters_masked){ - cloud_layer_rast <- map(rasters_masked, function(spatraster) { - spatraster[[5]] - }) %>% rast() - - return(cloud_layer_rast) -} - -calculate_cloud_coverage <- function(cloud_layer_rast, total_pix_area) { - cloud_perc_list <- freq(cloud_layer_rast, usenames = TRUE) %>% - mutate(cloud_perc = (100 -((count/total_pix_area$count)*100)), - cloud_thres_5perc = as.integer(cloud_perc < 5), - cloud_thres_40perc = as.integer(cloud_perc < 40)) %>% - rename(Date = layer) %>% select(-value, -count) - - cloud_index_5perc <- which(cloud_perc_list$cloud_thres_5perc == max(cloud_perc_list$cloud_thres_5perc)) - cloud_index_40perc <- which(cloud_perc_list$cloud_thres_40perc == max(cloud_perc_list$cloud_thres_40perc)) - - return(list(cloud_perc_list = cloud_perc_list, cloud_index_5perc = cloud_index_5perc, cloud_index_40perc = cloud_index_40perc)) -} - -process_cloud_coverage <- function(cloud_coverage, rasters_masked) { - if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) > 1) { - message("More than 1 raster without clouds (<5%), max mosaic made ") - - cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_5perc] - rsrc <- sprc(cloudy_rasters_list) - x <- mosaic(rsrc) - names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") - - } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) == 1) { - message("Only 1 raster without clouds (<5%)") - - x <- rast(rasters_masked[cloud_coverage$cloud_index_5perc[1]]) - names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") - - } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) > 1) { - message("More than 1 image contains clouds, composite made of <40% cloud cover images") - - cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_40perc] - rsrc <- sprc(cloudy_rasters_list) - x <- mosaic(rsrc) - names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") - - } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) == 0) { - message("No cloud free images available") - x <- rast(rasters_masked[1]) - x[x] <- NA - names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") - } - - return(x) -} - -extract_rasters_daily_func <- function(daily_vals_dir, filtered_files, fields_geojson) { - extracted_files <- walk(filtered_files, extract_rasters_daily, field_geojson = fields_geojson, quadrants = TRUE, daily_vals_dir) - return(extracted_files) -} - -CI_load <- function(daily_vals_dir, grouping_variable){ - extracted_values <- list.files(here(daily_vals_dir), full.names = TRUE) - - field_CI_values <- extracted_values %>% - map_dfr(readRDS) %>% - group_by(.data[[grouping_variable]]) %>% - summarise(across(everything(), ~ first(na.omit(.)))) - return(field_CI_values) -} - -CI_long <- function(field_CI_values, pivot_long_cols){ - field_CI_long <- field_CI_values %>% - gather("Date", value, -pivot_long_cols) %>% - mutate(Date = right(Date, 8), - Date = ymd(Date) - ) %>% - drop_na(c("value","Date")) %>% - mutate(value = as.numeric(value))%>% - filter_all(all_vars(!is.infinite(.)))%>% - rename(field = pivot_quadrant) - - return(field_CI_long) -} - -process_year_data <- function(year, harvest_data, field_CI_long) { - pivots_dates_year <- harvest_data %>% na.omit() %>% filter(year == year) - pivot_select_model_year <- unique(pivots_dates_year$field) - - data <- map_dfr(pivot_select_model_year, ~ extract_CI_data(.x, harvest_data, field_CI_long, season = year)) - - return(data) -} - - - -#functions for CI_data_prep -create_mask_and_crop <- function(file, pivot_sf_q) { - # 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, pivot_sf_q, 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) -} - - -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) -} - -#functions for rmarkdown file - - -create_RGB_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = TRUE, legend_is_portrait = FALSE, week, age, red = TRUE) { - r <- if (red) 1 else 4 # Set r based on the value of red - title <- if (red) paste0("RGB image of the fields") else paste0("False colour image of the fields") - - tm_shape(pivot_raster, unit = "m") + tm_rgb(r = r, g = 2, b = 3, max.value = 255) + - tm_layout(main.title = title, - main.title.size = 1) + - tm_scale_bar(position = c("right", "top"), text.color = "black") + - tm_compass(position = c("right", "top"), text.color = "black") + - tm_shape(pivot_shape) + tm_borders(col = "gray") + - tm_text("sub_field", size = 0.6, col = "gray") + - tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha = 0.5) -} - -create_CI_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = F, legend_is_portrait = F, week, age, legend_only = F){ - tm_shape(pivot_raster, unit = "m")+ - tm_raster(breaks = CI_breaks, palette = "RdYlGn",legend.is.portrait = legend_is_portrait ,midpoint = NA) + - tm_layout(main.title = paste0("Max CI week ", week,"\n", age, " weeks old"), - main.title.size = 1, legend.show = show_legend, legend.only = legend_only) + - tm_shape(pivot_shape) + - tm_borders(lwd = 3) + tm_text("sub_field", size = 1/2) + - tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha=0.5) +tmap_options(check.and.fix = TRUE) -} - -create_CI_diff_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = F, legend_is_portrait = F, week_1, week_2, age){ - tm_shape(pivot_raster, unit = "m")+ - tm_raster(breaks = CI_diff_breaks, palette = "PRGn",legend.is.portrait = legend_is_portrait ,midpoint = 0, title = "CI difference") + - tm_layout(main.title = paste0("CI change week ", week_1, "- week ",week_2, "\n", age," weeks old"), - main.title.size = 1, legend.show = show_legend) + - tm_shape(pivot_shape) + - tm_borders(lwd = 3) + tm_text("sub_field", size = 1/2) + - tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha=0.5) -} - -ci_plot <- function(pivotName){ - # pivotName = "MV2B09" - # pivotName = "1.1" - - pivotShape <- AllPivots_merged %>% terra::subset(field %in% pivotName) %>% st_transform(crs(CI)) - # age <- AllPivots %>% dplyr::filter(field %in% pivotName) %>% st_drop_geometry() %>% dplyr::select(Age) %>% unique() %>% - # mutate(Age = round(Age)) - - age <- AllPivots %>% - group_by(field) %>% - filter(Season == max(Season, na.rm = TRUE), field %in% pivotName) %>% - dplyr::select(Age)%>% st_drop_geometry() %>% unique() - - AllPivots2 <- AllPivots0 %>% dplyr::filter(field %in% pivotName) - - singlePivot <- CI %>% crop(., pivotShape) %>% mask(., pivotShape) - singlePivot_m1 <- CI_m1 %>% crop(., pivotShape) %>% mask(., pivotShape) - singlePivot_m2 <- CI_m2 %>% crop(., pivotShape) %>% mask(., pivotShape) - # singlePivot_m3 <- CI_m3 %>% crop(., pivotShape) %>% mask(., pivotShape) - - singlePivot_RGB <- RGB_raster %>% crop(., pivotShape) %>% mask(., pivotShape) - singlePivot_false <- RGB_raster_stretch %>% crop(., pivotShape) %>% mask(., pivotShape) - - abs_CI_last_week <- last_week_dif_raster_abs %>% crop(., pivotShape) %>% mask(., pivotShape) - abs_CI_three_week <- three_week_dif_raster_abs %>% crop(., pivotShape) %>% mask(., pivotShape) - - # planting_date <- harvesting_data %>% dplyr::filter(field %in% pivotName) %>% ungroup() %>% dplyr::select(planting_date) %>% unique() - - joined_spans2 <- joined_spans %>% st_transform(crs(pivotShape)) %>% dplyr::filter(field %in% pivotName) %>% st_crop(., pivotShape) - - # CImap_m2 <- create_CI_map(singlePivot_m2, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait = T, week = week_minus_2, age = age -2) - Legend_map <- create_CI_map(singlePivot_m1, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait =T, week = week_minus_1, age = age -1, legend_only = T) - CImap_m1 <- create_CI_map(singlePivot_m1, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait =T, week = week_minus_1, age = age -1) - CImap <- create_CI_map(singlePivot, AllPivots2, joined_spans2, show_legend= F, legend_is_portrait = T, week = week, age = age ) - RGBmap <- create_RGB_map(singlePivot_false, AllPivots2, joined_spans2, show_legend= F, week = week, age = age, red =T ) - Falsemap <- create_RGB_map(singlePivot_false, AllPivots2, joined_spans2, show_legend= F, week = week, age = age, red =F ) - - - CI_max_abs_last_week <- create_CI_diff_map(abs_CI_last_week,AllPivots2, joined_spans2, show_legend = T, legend_is_portrait = T, week_1 = week, week_2 = week_minus_1, age = age) - CI_max_abs_three_week <- create_CI_diff_map(abs_CI_three_week, AllPivots2, joined_spans2, show_legend = F, legend_is_portrait = T, week_1 = week, week_2 = week_minus_3, age = age) - - # tst <- tmap_arrange(CImap_m2, CImap_m1, CImap,CI_max_abs_last_week, CI_max_abs_three_week, nrow = 1) - tst <- tmap_arrange(RGBmap,Falsemap, - CImap_m1, CImap, - CI_max_abs_last_week, CI_max_abs_three_week, - ncol = 2) - - cat(paste("## field", pivotName, "-", age$Age[1], "weeks after planting/harvest", "\n")) - # cat("\n") - # cat('

Pivot', pivotName, '- week', week, '-', age$Age, 'weeks after planting/harvest

') - # cat(paste("# Pivot",pivots$pivot[i],"\n")) - print(tst) - -} - - -subchunkify <- function(g, fig_height=7, fig_width=5) { - g_deparsed <- paste0(deparse( - function() {g} - ), collapse = '') - - sub_chunk <- paste0("```{r sub_chunk_", floor(runif(1) * 10000), ", fig.height=", fig_height, ", fig.width=", fig_width, ", echo=FALSE}", - "\n(", - g_deparsed - , ")()", - "\n``` - ") - - cat(knitr::knit(text = knitr::knit_expand(text = sub_chunk), quiet = TRUE)) -} - -cum_ci_plot <- function(pivotName){ - - # pivotName = "2.1" - - # Check if pivotName exists in the data - if (!pivotName %in% unique(CI_quadrant$field)) { - # message("PivotName '", pivotName, "' not found. Plotting empty graph.") - g <- ggplot() + labs(title = "Empty Graph - Yield dates missing") - return( - subchunkify(g, fig_height=2, fig_width = 10) - ) - } else { - # message("PivotName '", pivotName, "' found. Plotting normal graph.") - data_ci <- CI_quadrant %>% filter(field %in% pivotName) - - - - data_ci2 <- data_ci %>% mutate(CI_rate = cumulative_CI/DOY, - week = week(Date))%>% group_by(sub_field) %>% - mutate(mean_rolling10 = rollapplyr(CI_rate , width = 10, FUN = mean, partial = TRUE)) - - # date_preperation_perfect_pivot <- data_ci2 %>% group_by(season) %>% summarise(min_date = min(Date), - # max_date = max(Date), - # days = max_date - min_date) - - # Identify unique seasons - filtered_data <- data_ci2 %>% - group_by(season) %>% - mutate(rank = dense_rank(desc(season))) %>% - filter(rank <= 2) %>% - ungroup() %>% - dplyr::select(-rank) - - - # g <- ggplot(data= data_ci2 %>% filter(season %in% unique_seasons)) + - g <- ggplot(data= filtered_data ) + - # geom_line(aes(Date, mean_rolling10, col = sub_field)) + - geom_line(aes(Date, CI_rate, col = sub_field)) + - facet_wrap(~season, scales = "free_x") + - # geom_line(data= perfect_pivot, aes(Date , mean_rolling10, col = "Model CI (p5.1 Data 2022, \n date x axis is fictive)"), lty="11",size=1) + - labs(title = paste("CI rate - field", pivotName), - y = "CI rate (cumulative CI / Age)")+ - # scale_y_continuous(limits=c(0.5,3), breaks = seq(0.5, 3, 0.5))+ - scale_x_date(date_breaks = "1 month", date_labels = "%m-%Y") + - theme(axis.text.x = element_text(angle = 60, hjust = 1), - legend.justification=c(1,0), legend.position = c(1, 0), - legend.title = element_text(size = 8), - legend.text = element_text(size = 8)) + - guides(color = guide_legend(nrow = 2, byrow = TRUE)) - subchunkify(g, fig_height=6, fig_width = 10) - } -} - - - -# 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 -end_date <- as.Date(args[1]) - - -offset <- as.numeric(args[2]) -# Controleer of weeks_ago een geldig getal is -if (is.na(offset)) { - # stop("Het argument is geen geldig getal") - offset <- 7 -} - -# Converteer het tweede argument naar een string waarde -project_dir <- as.character(args[3]) - -# 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("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) - -week <- week(end_date) - - -#weeks_ago = 0 -# Creating weekly mosaic -#dates <- date_list(weeks_ago) -dates <- date_list(end_date, offset) -print(dates) -#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") - -filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% - compact() %>% - flatten_chr() -head(filtered_files) - -# 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. - - - # Define the path to the file - file_path <- here(cumulative_CI_vals_dir,"combined_CI_data.rds") - - # Check if the file exists - if (!file.exists(file_path)) { - # Create the file with columns "column1" and "column2" - data <- data.frame(sub_field=NA, field=NA) - saveRDS(data, file_path) - } - - 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(sub_field) %>% - 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.") - saveRDS(combined_CI_data, here(cumulative_CI_vals_dir,"combined_CI_data.rds")) #used to save the rest of the data into one file - - -# gather data into long format for easier calculation and visualisation -pivot_stats_long <- pivot_stats2 %>% - tidyr::gather("Date", value, -field, -sub_field ) %>% - 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, - # sub_field = 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) %>% filter(!is.na(season_start)) %>% pull(sub_field) - -pivot_select_model_Data_2024 <- harvesting_data %>% filter(year == 2024)%>% filter(!is.na(season_start)) %>% pull(sub_field) - -# 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 %>% - na.omit() %>% - filter(year == season, sub_field %in% field_names) - - filtered_field_CI_data <- field_CI_data %>% - filter(sub_field %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, - sub_field = 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) -CI_all <- 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') - diff --git a/r_app/ci_extraction.R b/r_app/ci_extraction.R new file mode 100644 index 0000000..0522ce7 --- /dev/null +++ b/r_app/ci_extraction.R @@ -0,0 +1,241 @@ +library(here) +library(sf) +library(terra) +library(tidyverse) +library(lubridate) +library(exactextractr) +library(readxl) + + +# 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 +end_date <- as.Date(args[1]) + + +offset <- as.numeric(args[2]) +# Controleer of weeks_ago een geldig getal is +if (is.na(offset)) { + # stop("Het argument is geen geldig getal") + offset <- 7 +} + +# Converteer het tweede argument naar een string waarde +project_dir <- as.character(args[3]) + +# 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("parameters_project.R") +source("utils_2.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) + +# end_date <- lubridate::dmy("20-6-2024") +week <- week(end_date) + + +#weeks_ago = 0 +# Creating weekly mosaic +#dates <- date_list(weeks_ago) +dates <- date_list(end_date, offset) +print(dates) +#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") + +# filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% +# compact() %>% +# flatten_chr() +# head(filtered_files) + + + +# Extracting CI + + +# 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. + + +# Define the path to the file +file_path <- here(cumulative_CI_vals_dir,"combined_CI_data.rds") + +# Check if the file exists +if (!file.exists(file_path)) { + # Create the file with columns "column1" and "column2" + data <- data.frame(sub_field=NA, field=NA) + saveRDS(data, file_path) +} + +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(sub_field) %>% + 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.") +saveRDS(combined_CI_data, here(cumulative_CI_vals_dir,"combined_CI_data.rds")) #used to save the rest of the data into one file + + +# gather data into long format for easier calculation and visualisation +pivot_stats_long <- pivot_stats2 %>% + tidyr::gather("Date", value, -field, -sub_field ) %>% + 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, + # sub_field = 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) %>% filter(!is.na(season_start)) %>% pull(sub_field) + +pivot_select_model_Data_2024 <- harvesting_data %>% filter(year == 2024)%>% filter(!is.na(season_start)) %>% pull(sub_field) + +# 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 %>% + na.omit() %>% + filter(year == season, sub_field %in% field_names) + + filtered_field_CI_data <- field_CI_data %>% + filter(sub_field %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, + sub_field = 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) +CI_all <- 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') + diff --git a/r_app/ci_extraction_utils.R b/r_app/ci_extraction_utils.R new file mode 100644 index 0000000..f092da4 --- /dev/null +++ b/r_app/ci_extraction_utils.R @@ -0,0 +1,284 @@ +# Utils for ci extraction + +date_list <- function(end_date, offset){ + offset <- as.numeric(offset) - 1 + end_date <- as.Date(end_date) + start_date <- end_date - lubridate::days(offset) + + week <- week(start_date) + year <- year(start_date) + days_filter <- seq(from = start_date, to = end_date, by = "day") + + return(list("week" = week, "year" = year, "days_filter" = days_filter)) +} + +# date_list <- function(weeks_in_the_paste){ +# week <- week(Sys.Date()- weeks(weeks_in_the_paste) ) +# year <- year(Sys.Date()- weeks(weeks_in_the_paste) ) +# days_filter <- Sys.Date() - weeks(weeks_in_the_paste) - days(0:6) +# +# return(c("week" = week, +# "year" = year, +# "days_filter" = list(days_filter))) +# +# } + +CI_func <- function(x, drop_layers = FALSE){ + CI <- x[[4]]/x[[2]]-1 + add(x) <- CI + names(x) <- c("red", "green", "blue","nir", "cloud" ,"CI") + if(drop_layers == FALSE){ + return(x) + }else{ + return(x$CI) + } +} + +mask_raster <- function(raster, fields){ + # x <- rast(filtered_files[1]) + x <- rast(raster) + emtpy_or_full <- global(x, sum) + + if(emtpy_or_full[1,] >= 2000000){ + names(x) <- c("red", "green", "blue","nir", "cloud") + cloud <- x$cloud + + cloud[cloud == 0 ] <- NA + x_masked <- mask(x, cloud, inverse = T) %>% crop(.,fields, mask = TRUE ) + x_masked <- x_masked %>% CI_func() + + message(raster, " masked") + return(x_masked) + } +} + +date_extract <- function(file_path) { + str_extract(file_path, "\\d{4}-\\d{2}-\\d{2}") +} + +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) +} + +right = function(text, num_char) { + substr(text, nchar(text) - (num_char-1), nchar(text)) +} + +extract_CI_data <- function(field_names, harvesting_data, field_CI_data, season) { + # field_names = "1.2A" + # harvesting_data = harvesting_data + # field_CI_data = pivot_stats_long + # season= 2021 + + filtered_harvesting_data <- harvesting_data %>% + filter(year == season, field %in% field_names) + + filtered_field_CI_data <- field_CI_data %>% + filter(field %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, + field = field_names) + # }) #%>% + #{if (length(field_names) > 0) message("Done!")} + + return(CI) +} +# +# load_fields <- function(geojson_path) { +# field_geojson <- st_read(geojson_path) %>% +# select(pivot, pivot_quadrant) %>% +# vect() +# return(field_geojson) +# } +# +# load_harvest_data <- function(havest_data_path){ +# harvest_data <- readRDS(havest_data_path) +# return(harvest_data) +# } +# +# load_rasters <- function(raster_path, dates) { +# raster_files <- list.files(raster_path, full.names = TRUE, pattern = ".tif") +# filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% +# compact() %>% +# flatten_chr() +# +# return(filtered_files) +# } +# +# mask_and_set_names <- function(filtered_files, fields) { +# rasters_masked <- map(filtered_files, mask_raster, fields = fields) %>% set_names(filtered_files) +# rasters_masked[sapply(rasters_masked, is.null)] <- NULL +# rasters_masked <- setNames(rasters_masked, map_chr(names(rasters_masked), date_extract)) +# +# return(rasters_masked) +# } +# +# calculate_total_pix_area <- function(filtered_files, fields_geojson) { +# # total_pix_area <- rast(filtered_files[1]) %>% +# # subset(1) %>% +# # crop(fields_geojson, mask = TRUE)%>% +# # global(.data, fun = "notNA") +# total_pix_area <- rast(filtered_files[1]) %>% subset(1) %>% crop(fields_geojson, mask = TRUE) %>% freq(., usenames = TRUE) +# +# return(total_pix_area) +# } +# +# cloud_layer_extract <- function(rasters_masked){ +# cloud_layer_rast <- map(rasters_masked, function(spatraster) { +# spatraster[[5]] +# }) %>% rast() +# +# return(cloud_layer_rast) +# } +# +# calculate_cloud_coverage <- function(cloud_layer_rast, total_pix_area) { +# cloud_perc_list <- freq(cloud_layer_rast, usenames = TRUE) %>% +# mutate(cloud_perc = (100 -((count/total_pix_area$count)*100)), +# cloud_thres_5perc = as.integer(cloud_perc < 5), +# cloud_thres_40perc = as.integer(cloud_perc < 40)) %>% +# rename(Date = layer) %>% select(-value, -count) +# +# cloud_index_5perc <- which(cloud_perc_list$cloud_thres_5perc == max(cloud_perc_list$cloud_thres_5perc)) +# cloud_index_40perc <- which(cloud_perc_list$cloud_thres_40perc == max(cloud_perc_list$cloud_thres_40perc)) +# +# return(list(cloud_perc_list = cloud_perc_list, cloud_index_5perc = cloud_index_5perc, cloud_index_40perc = cloud_index_40perc)) +# } +# +# process_cloud_coverage <- function(cloud_coverage, rasters_masked) { +# if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) > 1) { +# message("More than 1 raster without clouds (<5%), max mosaic made ") +# +# cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_5perc] +# rsrc <- sprc(cloudy_rasters_list) +# x <- mosaic(rsrc) +# names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") +# +# } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) == 1) { +# message("Only 1 raster without clouds (<5%)") +# +# x <- rast(rasters_masked[cloud_coverage$cloud_index_5perc[1]]) +# names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") +# +# } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) > 1) { +# message("More than 1 image contains clouds, composite made of <40% cloud cover images") +# +# cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_40perc] +# rsrc <- sprc(cloudy_rasters_list) +# x <- mosaic(rsrc) +# names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") +# +# } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) == 0) { +# message("No cloud free images available") +# x <- rast(rasters_masked[1]) +# x[x] <- NA +# names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") +# } +# +# return(x) +# } + +# extract_rasters_daily_func <- function(daily_vals_dir, filtered_files, fields_geojson) { +# extracted_files <- walk(filtered_files, extract_rasters_daily, field_geojson = fields_geojson, quadrants = TRUE, daily_vals_dir) +# return(extracted_files) +# } + +# CI_load <- function(daily_vals_dir, grouping_variable){ +# extracted_values <- list.files(here(daily_vals_dir), full.names = TRUE) +# +# field_CI_values <- extracted_values %>% +# map_dfr(readRDS) %>% +# group_by(.data[[grouping_variable]]) %>% +# summarise(across(everything(), ~ first(na.omit(.)))) +# return(field_CI_values) +# } +# +# CI_long <- function(field_CI_values, pivot_long_cols){ +# field_CI_long <- field_CI_values %>% +# gather("Date", value, -pivot_long_cols) %>% +# mutate(Date = right(Date, 8), +# Date = ymd(Date) +# ) %>% +# drop_na(c("value","Date")) %>% +# mutate(value = as.numeric(value))%>% +# filter_all(all_vars(!is.infinite(.)))%>% +# rename(field = pivot_quadrant) +# +# return(field_CI_long) +# } +# +# process_year_data <- function(year, harvest_data, field_CI_long) { +# pivots_dates_year <- harvest_data %>% na.omit() %>% filter(year == year) +# pivot_select_model_year <- unique(pivots_dates_year$field) +# +# data <- map_dfr(pivot_select_model_year, ~ extract_CI_data(.x, harvest_data, field_CI_long, season = year)) +# +# return(data) +# } + + + +#functions for CI_data_prep +# create_mask_and_crop <- function(file, pivot_sf_q) { +# # 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, pivot_sf_q, 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) +# } + + +# 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) +# } + diff --git a/r_app/mosaic_creation.R b/r_app/mosaic_creation.R new file mode 100644 index 0000000..055604b --- /dev/null +++ b/r_app/mosaic_creation.R @@ -0,0 +1,216 @@ +# activeer de renv omgeving; + +# renv::activate('~/smartCane/r_app') +# renv::restore() + + + +library(here) +library(sf) +library(terra) +library(tidyverse) +library(lubridate) +# library(exactextractr) +library(readxl) +#funcion CI_prep package + + +# 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 +end_date <- as.Date(args[1]) + + +offset <- as.numeric(args[2]) +# Controleer of weeks_ago een geldig getal is +if (is.na(offset)) { + # stop("Het argument is geen geldig getal") + offset <- 7 +} + +# Converteer het tweede argument naar een string waarde +project_dir <- as.character(args[3]) + +# 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("parameters_project.R") +source("utils_1.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) + +# end_date <- lubridate::dmy("20-6-2024") +week <- week(end_date) + + +#weeks_ago = 0 + +# Creating weekly mosaic +#dates <- date_list(weeks_ago) +dates <- date_list(end_date, offset) +print(dates) +#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") + +filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% + compact() %>% + flatten_chr() +head(filtered_files) + +# 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) +# } + + +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) diff --git a/r_app/mosaic_creation_utils.R b/r_app/mosaic_creation_utils.R new file mode 100644 index 0000000..b07176f --- /dev/null +++ b/r_app/mosaic_creation_utils.R @@ -0,0 +1,217 @@ +# utils for mosaic creation + +date_list <- function(end_date, offset){ + offset <- as.numeric(offset) - 1 + end_date <- as.Date(end_date) + start_date <- end_date - lubridate::days(offset) + + week <- week(start_date) + year <- year(start_date) + days_filter <- seq(from = start_date, to = end_date, by = "day") + + return(list("week" = week, "year" = year, "days_filter" = days_filter)) +} + +# date_list <- function(weeks_in_the_paste){ +# week <- week(Sys.Date()- weeks(weeks_in_the_paste) ) +# year <- year(Sys.Date()- weeks(weeks_in_the_paste) ) +# days_filter <- Sys.Date() - weeks(weeks_in_the_paste) - days(0:6) +# +# return(c("week" = week, +# "year" = year, +# "days_filter" = list(days_filter))) +# +# } +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) +} + +CI_func <- function(x, drop_layers = FALSE){ + CI <- x[[4]]/x[[2]]-1 + add(x) <- CI + names(x) <- c("red", "green", "blue","nir", "cloud" ,"CI") + if(drop_layers == FALSE){ + return(x) + }else{ + return(x$CI) + } +} + +mask_raster <- function(raster, fields){ + # x <- rast(filtered_files[1]) + x <- rast(raster) + emtpy_or_full <- global(x, sum) + + if(emtpy_or_full[1,] >= 2000000){ + names(x) <- c("red", "green", "blue","nir", "cloud") + cloud <- x$cloud + + cloud[cloud == 0 ] <- NA + x_masked <- mask(x, cloud, inverse = T) %>% crop(.,fields, mask = TRUE ) + x_masked <- x_masked %>% CI_func() + + message(raster, " masked") + return(x_masked) + } +} + +date_extract <- function(file_path) { + str_extract(file_path, "\\d{4}-\\d{2}-\\d{2}") +} + + + +right = function(text, num_char) { + substr(text, nchar(text) - (num_char-1), nchar(text)) +} + +# load_fields <- function(geojson_path) { +# field_geojson <- st_read(geojson_path) %>% +# select(pivot, pivot_quadrant) %>% +# vect() +# return(field_geojson) +# } +# +# load_harvest_data <- function(havest_data_path){ +# harvest_data <- readRDS(havest_data_path) +# return(harvest_data) +# } + +# load_rasters <- function(raster_path, dates) { +# raster_files <- list.files(raster_path, full.names = TRUE, pattern = ".tif") +# filtered_files <- map(dates$days_filter, ~ raster_files[grepl(pattern = .x, x = raster_files)]) %>% +# compact() %>% +# flatten_chr() +# +# return(filtered_files) +# } + +# mask_and_set_names <- function(filtered_files, fields) { +# rasters_masked <- map(filtered_files, mask_raster, fields = fields) %>% set_names(filtered_files) +# rasters_masked[sapply(rasters_masked, is.null)] <- NULL +# rasters_masked <- setNames(rasters_masked, map_chr(names(rasters_masked), date_extract)) +# +# return(rasters_masked) +# } + +# calculate_total_pix_area <- function(filtered_files, fields_geojson) { +# # total_pix_area <- rast(filtered_files[1]) %>% +# # subset(1) %>% +# # crop(fields_geojson, mask = TRUE)%>% +# # global(.data, fun = "notNA") +# total_pix_area <- rast(filtered_files[1]) %>% subset(1) %>% crop(fields_geojson, mask = TRUE) %>% freq(., usenames = TRUE) +# +# return(total_pix_area) +# } + +# cloud_layer_extract <- function(rasters_masked){ +# cloud_layer_rast <- map(rasters_masked, function(spatraster) { +# spatraster[[5]] +# }) %>% rast() +# +# return(cloud_layer_rast) +# } + +# calculate_cloud_coverage <- function(cloud_layer_rast, total_pix_area) { +# cloud_perc_list <- freq(cloud_layer_rast, usenames = TRUE) %>% +# mutate(cloud_perc = (100 -((count/total_pix_area$count)*100)), +# cloud_thres_5perc = as.integer(cloud_perc < 5), +# cloud_thres_40perc = as.integer(cloud_perc < 40)) %>% +# rename(Date = layer) %>% select(-value, -count) +# +# cloud_index_5perc <- which(cloud_perc_list$cloud_thres_5perc == max(cloud_perc_list$cloud_thres_5perc)) +# cloud_index_40perc <- which(cloud_perc_list$cloud_thres_40perc == max(cloud_perc_list$cloud_thres_40perc)) +# +# return(list(cloud_perc_list = cloud_perc_list, cloud_index_5perc = cloud_index_5perc, cloud_index_40perc = cloud_index_40perc)) +# } + +process_cloud_coverage <- function(cloud_coverage, rasters_masked) { + if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) > 1) { + message("More than 1 raster without clouds (<5%), max mosaic made ") + + cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_5perc] + rsrc <- sprc(cloudy_rasters_list) + x <- mosaic(rsrc) + names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") + + } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_5perc) == 1) { + message("Only 1 raster without clouds (<5%)") + + x <- rast(rasters_masked[cloud_coverage$cloud_index_5perc[1]]) + names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") + + } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) > 1) { + message("More than 1 image contains clouds, composite made of <40% cloud cover images") + + cloudy_rasters_list <- rasters_masked[cloud_coverage$cloud_index_40perc] + rsrc <- sprc(cloudy_rasters_list) + x <- mosaic(rsrc) + names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") + + } else if (sum(cloud_coverage$cloud_perc_list$cloud_thres_40perc) == 0) { + message("No cloud free images available") + x <- rast(rasters_masked[1]) + x[x] <- NA + names(x) <- c("red", "green", "blue", "nir", "cloud", "CI") + } + + return(x) +} + + +#functions for CI_data_prep +# create_mask_and_crop <- function(file, pivot_sf_q) { +# # 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, pivot_sf_q, 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) +# } + + diff --git a/r_app/utils_3.R b/r_app/utils_3.R new file mode 100644 index 0000000..27a4e8e --- /dev/null +++ b/r_app/utils_3.R @@ -0,0 +1,161 @@ +# utils for report +#functions for rmarkdown file + + +create_RGB_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = TRUE, legend_is_portrait = FALSE, week, age, red = TRUE) { + r <- if (red) 1 else 4 # Set r based on the value of red + title <- if (red) paste0("RGB image of the fields") else paste0("False colour image of the fields") + + tm_shape(pivot_raster, unit = "m") + tm_rgb(r = r, g = 2, b = 3, max.value = 255) + + tm_layout(main.title = title, + main.title.size = 1) + + tm_scale_bar(position = c("right", "top"), text.color = "black") + + tm_compass(position = c("right", "top"), text.color = "black") + + tm_shape(pivot_shape) + tm_borders(col = "gray") + + tm_text("sub_field", size = 0.6, col = "gray") + + tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha = 0.5) +} + +create_CI_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = F, legend_is_portrait = F, week, age, legend_only = F){ + tm_shape(pivot_raster, unit = "m")+ + tm_raster(breaks = CI_breaks, palette = "RdYlGn",legend.is.portrait = legend_is_portrait ,midpoint = NA) + + tm_layout(main.title = paste0("Max CI week ", week,"\n", age, " weeks old"), + main.title.size = 1, legend.show = show_legend, legend.only = legend_only) + + tm_shape(pivot_shape) + + tm_borders(lwd = 3) + tm_text("sub_field", size = 1/2) + + tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha=0.5) +tmap_options(check.and.fix = TRUE) +} + +create_CI_diff_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = F, legend_is_portrait = F, week_1, week_2, age){ + tm_shape(pivot_raster, unit = "m")+ + tm_raster(breaks = CI_diff_breaks, palette = "PRGn",legend.is.portrait = legend_is_portrait ,midpoint = 0, title = "CI difference") + + tm_layout(main.title = paste0("CI change week ", week_1, "- week ",week_2, "\n", age," weeks old"), + main.title.size = 1, legend.show = show_legend) + + tm_shape(pivot_shape) + + tm_borders(lwd = 3) + tm_text("sub_field", size = 1/2) + + tm_shape(pivot_spans) + tm_borders(lwd = 0.5, alpha=0.5) +} + +ci_plot <- function(pivotName){ + # pivotName = "MV2B09" + # pivotName = "1.1" + + pivotShape <- AllPivots_merged %>% terra::subset(field %in% pivotName) %>% st_transform(crs(CI)) + # age <- AllPivots %>% dplyr::filter(field %in% pivotName) %>% st_drop_geometry() %>% dplyr::select(Age) %>% unique() %>% + # mutate(Age = round(Age)) + + age <- AllPivots %>% + group_by(field) %>% + filter(Season == max(Season, na.rm = TRUE), field %in% pivotName) %>% + dplyr::select(Age)%>% st_drop_geometry() %>% unique() + + AllPivots2 <- AllPivots0 %>% dplyr::filter(field %in% pivotName) + + singlePivot <- CI %>% crop(., pivotShape) %>% mask(., pivotShape) + singlePivot_m1 <- CI_m1 %>% crop(., pivotShape) %>% mask(., pivotShape) + singlePivot_m2 <- CI_m2 %>% crop(., pivotShape) %>% mask(., pivotShape) + # singlePivot_m3 <- CI_m3 %>% crop(., pivotShape) %>% mask(., pivotShape) + + singlePivot_RGB <- RGB_raster %>% crop(., pivotShape) %>% mask(., pivotShape) + singlePivot_false <- RGB_raster_stretch %>% crop(., pivotShape) %>% mask(., pivotShape) + + abs_CI_last_week <- last_week_dif_raster_abs %>% crop(., pivotShape) %>% mask(., pivotShape) + abs_CI_three_week <- three_week_dif_raster_abs %>% crop(., pivotShape) %>% mask(., pivotShape) + + # planting_date <- harvesting_data %>% dplyr::filter(field %in% pivotName) %>% ungroup() %>% dplyr::select(planting_date) %>% unique() + + joined_spans2 <- joined_spans %>% st_transform(crs(pivotShape)) %>% dplyr::filter(field %in% pivotName) %>% st_crop(., pivotShape) + + # CImap_m2 <- create_CI_map(singlePivot_m2, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait = T, week = week_minus_2, age = age -2) + Legend_map <- create_CI_map(singlePivot_m1, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait =T, week = week_minus_1, age = age -1, legend_only = T) + CImap_m1 <- create_CI_map(singlePivot_m1, AllPivots2, joined_spans2, show_legend= T, legend_is_portrait =T, week = week_minus_1, age = age -1) + CImap <- create_CI_map(singlePivot, AllPivots2, joined_spans2, show_legend= F, legend_is_portrait = T, week = week, age = age ) + RGBmap <- create_RGB_map(singlePivot_false, AllPivots2, joined_spans2, show_legend= F, week = week, age = age, red =T ) + Falsemap <- create_RGB_map(singlePivot_false, AllPivots2, joined_spans2, show_legend= F, week = week, age = age, red =F ) + + + CI_max_abs_last_week <- create_CI_diff_map(abs_CI_last_week,AllPivots2, joined_spans2, show_legend = T, legend_is_portrait = T, week_1 = week, week_2 = week_minus_1, age = age) + CI_max_abs_three_week <- create_CI_diff_map(abs_CI_three_week, AllPivots2, joined_spans2, show_legend = F, legend_is_portrait = T, week_1 = week, week_2 = week_minus_3, age = age) + + # tst <- tmap_arrange(CImap_m2, CImap_m1, CImap,CI_max_abs_last_week, CI_max_abs_three_week, nrow = 1) + tst <- tmap_arrange(RGBmap,Falsemap, + CImap_m1, CImap, + CI_max_abs_last_week, CI_max_abs_three_week, + ncol = 2) + + cat(paste("## field", pivotName, "-", age$Age[1], "weeks after planting/harvest", "\n")) + # cat("\n") + # cat('

Pivot', pivotName, '- week', week, '-', age$Age, 'weeks after planting/harvest

') + # cat(paste("# Pivot",pivots$pivot[i],"\n")) + print(tst) + +} + + +subchunkify <- function(g, fig_height=7, fig_width=5) { + g_deparsed <- paste0(deparse( + function() {g} + ), collapse = '') + + sub_chunk <- paste0("```{r sub_chunk_", floor(runif(1) * 10000), ", fig.height=", fig_height, ", fig.width=", fig_width, ", echo=FALSE}", + "\n(", + g_deparsed + , ")()", + "\n``` + ") + + cat(knitr::knit(text = knitr::knit_expand(text = sub_chunk), quiet = TRUE)) +} + +cum_ci_plot <- function(pivotName){ + + # pivotName = "2.1" + + # Check if pivotName exists in the data + if (!pivotName %in% unique(CI_quadrant$field)) { + # message("PivotName '", pivotName, "' not found. Plotting empty graph.") + g <- ggplot() + labs(title = "Empty Graph - Yield dates missing") + return( + subchunkify(g, fig_height=2, fig_width = 10) + ) + } else { + # message("PivotName '", pivotName, "' found. Plotting normal graph.") + data_ci <- CI_quadrant %>% filter(field %in% pivotName) + + + + data_ci2 <- data_ci %>% mutate(CI_rate = cumulative_CI/DOY, + week = week(Date))%>% group_by(sub_field) %>% + mutate(mean_rolling10 = rollapplyr(CI_rate , width = 10, FUN = mean, partial = TRUE)) + + # date_preperation_perfect_pivot <- data_ci2 %>% group_by(season) %>% summarise(min_date = min(Date), + # max_date = max(Date), + # days = max_date - min_date) + + # Identify unique seasons + filtered_data <- data_ci2 %>% + group_by(season) %>% + mutate(rank = dense_rank(desc(season))) %>% + filter(rank <= 2) %>% + ungroup() %>% + dplyr::select(-rank) + + + # g <- ggplot(data= data_ci2 %>% filter(season %in% unique_seasons)) + + g <- ggplot(data= filtered_data ) + + # geom_line(aes(Date, mean_rolling10, col = sub_field)) + + geom_line(aes(Date, CI_rate, col = sub_field)) + + facet_wrap(~season, scales = "free_x") + + # geom_line(data= perfect_pivot, aes(Date , mean_rolling10, col = "Model CI (p5.1 Data 2022, \n date x axis is fictive)"), lty="11",size=1) + + labs(title = paste("CI rate - field", pivotName), + y = "CI rate (cumulative CI / Age)")+ + # scale_y_continuous(limits=c(0.5,3), breaks = seq(0.5, 3, 0.5))+ + scale_x_date(date_breaks = "1 month", date_labels = "%m-%Y") + + theme(axis.text.x = element_text(angle = 60, hjust = 1), + legend.justification=c(1,0), legend.position = c(1, 0), + legend.title = element_text(size = 8), + legend.text = element_text(size = 8)) + + guides(color = guide_legend(nrow = 2, byrow = TRUE)) + subchunkify(g, fig_height=6, fig_width = 10) + } +} \ No newline at end of file diff --git a/update_RDS.sh b/update_RDS.sh new file mode 100755 index 0000000..6d74327 --- /dev/null +++ b/update_RDS.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +end_date=$(date +'%Y-%m-%d') +offset=7 +project_dir="chemba" + +# Parse command line arguments +for arg in "$@"; do + case $arg in + --end_date=*) + end_date="${arg#*=}" + ;; + --offset=*) + offset="${arg#*=}" + ;; + --project_dir=*) + project_dir="${arg#*=}" + ;; + *) + echo "Unknown option: $arg" + exit 1 + ;; + esac + shift +done + +echo "end_date: $end_date" +echo "offset: $offset" + +# Check if required arguments are set +if [ -z "$end_date" ] || [ -z "$project_dir" ] || [ -z "$offset" ]; then + echo "Missing arguments. Use: build_RDS.sh --end_date=2024-01-01 --offset=7 --project_dir=chemba" + exit 1 +fi + +echo ci_extraction.R $end_date $offset $project_dir + +cd ../r_app +Rscript ci_extraction.R $end_date $offset $project_dir \ No newline at end of file