diff --git a/laravel_app/app/Http/Controllers/ProjectController.php b/laravel_app/app/Http/Controllers/ProjectController.php index 33b56d8..874ac06 100644 --- a/laravel_app/app/Http/Controllers/ProjectController.php +++ b/laravel_app/app/Http/Controllers/ProjectController.php @@ -15,7 +15,7 @@ public function index() public function show(string $projectName,?string $currentTab = null) { if($project = Project::firstWhere([['name',$projectName]])) { - $availableTabs = ['downloads', 'mosaics', 'reports', 'mailings', 'settings']; + $availableTabs = ['downloads', 'mosaics', 'reports', 'mailings', 'settings', 'exports']; return in_array($currentTab, $availableTabs) ? view('projects.show', compact(['project', 'currentTab'])) : redirect(route('project.show', [$projectName,'downloads'])); } return abort(404); diff --git a/laravel_app/app/Jobs/ProjectInterpolateGrowthModelJob.php b/laravel_app/app/Jobs/ProjectInterpolateGrowthModelJob.php index a9bb916..153aa1c 100644 --- a/laravel_app/app/Jobs/ProjectInterpolateGrowthModelJob.php +++ b/laravel_app/app/Jobs/ProjectInterpolateGrowthModelJob.php @@ -16,9 +16,8 @@ class ProjectInterpolateGrowthModelJob implements ShouldQueue { use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + protected Project $project; - protected Carbon $date; - protected int $offset; public function __construct(Project $project) { diff --git a/laravel_app/app/Jobs/newDownloadsUploaded.php b/laravel_app/app/Jobs/newDownloadsUploaded.php new file mode 100644 index 0000000..ced2e88 --- /dev/null +++ b/laravel_app/app/Jobs/newDownloadsUploaded.php @@ -0,0 +1,32 @@ +project = $project; + } + + /** + * Execute the job. + */ + public function handle(): void + { + $this->project->newDownloadsUploaded(); + } +} diff --git a/laravel_app/app/Livewire/Projects/Tabs/Exports.php b/laravel_app/app/Livewire/Projects/Tabs/Exports.php new file mode 100644 index 0000000..9069f3e --- /dev/null +++ b/laravel_app/app/Livewire/Projects/Tabs/Exports.php @@ -0,0 +1,56 @@ +formData = [ + 'start_date' => now()->subDays(6)->format('Y-m-d'), + 'end_date' => now()->subDay()->format('Y-m-d'), + ]; + } + + + + public function render() + { + return view('livewire.projects.tabs.exports'); + } + + public function downloadRds() + { + return $this->project->getRdsAsDownload(); + } + + public function downloadTifs() + { + $startDate = \Carbon\Carbon::parse($this->formData['start_date']); + $endDate = \Carbon\Carbon::parse($this->formData['end_date']); + $this->showDownloadTifsModal = false; + return $this->project->getTifsAsZip( + $startDate, $endDate + ); + } + + public function downloadMosaics() + { + $startDate = \Carbon\Carbon::parse($this->formData['start_date']); + $endDate = \Carbon\Carbon::parse($this->formData['end_date']); + $this->showDownloadMosaicsModal = false; + return $this->project->getMosaicsAsZip( + $startDate, $endDate + ); + } +} diff --git a/laravel_app/app/Models/Project.php b/laravel_app/app/Models/Project.php index f2d04af..def188c 100644 --- a/laravel_app/app/Models/Project.php +++ b/laravel_app/app/Models/Project.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Jobs\ProjectDownloadRDSJob; use App\Jobs\ProjectDownloadTiffJob; use App\Jobs\ProjectInterpolateGrowthModelJob; use App\Jobs\ProjectMosiacGeneratorJob; @@ -348,7 +349,7 @@ public function getFileDownloadsFor(Carbon $endDate, int $offset = 7): array public function getMosaicsFor(Carbon $endDate, int $offset = 7): array { return collect(range(0, 3)) - ->map(function() use ($endDate, $offset){ + ->map(function () use ($endDate, $offset) { $currentEndDate = $endDate->clone(); if (!$currentEndDate->isDayOfWeek($this->mail_day)) { $endDate->previous($this->mail_day); @@ -402,4 +403,101 @@ private function getMinimumDateFromHarvestExcelFile(): Carbon return min($carry, Carbon::instance(SharedDate::excelToDateTimeObject($value[$season_start_index]))); }, now()); } + + public function newDownloadsUploaded() + { +// $this->createDownloadRecordsInDatabaseAndUpdateStatusForAllDownloadedImages(); + $date = Carbon::parse('2023-01-01'); + $now = Carbon::now(); + + $offset = (int) $date->diffInDays($now); +// dispatch_sync(new ProjectDownloadRDSJob($this, Carbon::yesterday(), 1)); + dispatch_sync(new ProjectInterpolateGrowthModelJob($this)); + } + public function getRdsAsDownload() { + + $path = $this->download_path.'/Data/extracted_ci/cumulative_vals/combined_CI_data.rds'; + + return Storage::download( + $path, 'combined_CI_data.rds' + ); + } + + public function getTifsAsZip(Carbon $startDate, Carbon $endDate) { + $path = $this->download_path.'/merged_final_tif'; + $files = collect(Storage::files($path)) + ->filter(fn($file) => Str::endsWith($file, '.tif')) + ->filter(function ($file) use ($startDate, $endDate) { + $dateString = str_replace('.tif', '', basename($file)); + $date = Carbon::parse($dateString); + return $date->between($startDate, $endDate); + }); + + return $this->createZipArchiveAndReturn($files); + } + + public function getMosaicsAsZip(Carbon $startDate, Carbon $endDate) { + $path = $this->download_path.'/weekly_mosaic'; + + // create a collection of all week numbers and years for given date range + $allowedFiles = collect(CarbonPeriod::create($startDate, $endDate)->toArray()) + ->map(fn($date) => sprintf('week_%s_%s.tif',$date->weekOfYear, $date->year)) + ->unique(); + + + $files = collect(Storage::files($path)) + ->filter(fn($file) => Str::endsWith($file, '.tif')) + ->filter(function ($file) use ($allowedFiles) { + return $allowedFiles->contains(basename($file)); + }); + putenv('TMPDIR='.storage_path('app')); + + return $this->createZipArchiveAndReturn($files); + } + + private function createZipArchiveAndReturn(Collection $files) + { + $zipPath = storage_path('app/'.$this->download_path.'/download.zip'); + $zip = new \ZipArchive(); + $zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); + $files->each(function ($file) use ($zip) { + $zip->addFile(storage_path('app/'.$file), basename($file)); + }); + $zip->close(); + + return response()->download( + $zipPath, 'download.zip' + ); + } + + public function createDownloadRecordsInDatabaseAndUpdateStatusForAllDownloadedImages(): void + { + $merged_tiffs = $this->getMergedTiffList(); + $this->downloads->each(function ($download) use ($merged_tiffs) { + if ($merged_tiffs->contains($download->path) && $download->status !== 'success') { + $download->setStatusSuccess(); + } + }); + + $merged_tiffs->each(function ($path) { + if ($this->downloads()->where('path', $path)->count() === 0) { + $this->downloads()->create([ + 'path' => $path, + 'status' => 'success', + 'name' => explode('/', $path)[count(explode('/', $path)) - 1] + ]); + } + }); + } + + public function createAllMosaicsInDatabaseAndUpdateStatusForAllDownloadedImages() + { + $list_of_desired_mosaics = $this->getMergedTiffList() + ->map(fn($file) => str_replace('.tif', '', basename($file) )) + ->map(function($date) { + $carbon = Carbon::parse($date); + return sprintf('week_%s_%s', $carbon->format('W'), $carbon->year); + }) + ->unique(); + } } diff --git a/laravel_app/public/Sonydownload.zip b/laravel_app/public/Sonydownload.zip new file mode 100644 index 0000000..d4c8f23 Binary files /dev/null and b/laravel_app/public/Sonydownload.zip differ diff --git a/laravel_app/resources/views/components/download-mosaics-as-zip-modal.blade.php b/laravel_app/resources/views/components/download-mosaics-as-zip-modal.blade.php new file mode 100644 index 0000000..79b5809 --- /dev/null +++ b/laravel_app/resources/views/components/download-mosaics-as-zip-modal.blade.php @@ -0,0 +1,47 @@ +@props([ + 'formData', +]) + + + + + {{ __('Download Mosaics') }} + + + + + + + +
+ + + +
+ + + +
+
+ +
+
+ + + + {{ __('Saved.') }} + + + + {{ __('Cancel') }} + + + {{ __('Download') }} + + + +
+
diff --git a/laravel_app/resources/views/components/download-tifs-as-zip-modal.blade.php b/laravel_app/resources/views/components/download-tifs-as-zip-modal.blade.php new file mode 100644 index 0000000..99853d3 --- /dev/null +++ b/laravel_app/resources/views/components/download-tifs-as-zip-modal.blade.php @@ -0,0 +1,47 @@ +@props([ + 'formData', +]) + + + + + {{ __('Download Zip with satelite data') }} + + + + + + + +
+ + + +
+ + + +
+
+ +
+
+ + + + {{ __('Saved.') }} + + + + {{ __('Cancel') }} + + + {{ __('Save') }} + + + +
+
diff --git a/laravel_app/resources/views/livewire/projects/menu.blade.php b/laravel_app/resources/views/livewire/projects/menu.blade.php index a57a26c..9c9c81d 100644 --- a/laravel_app/resources/views/livewire/projects/menu.blade.php +++ b/laravel_app/resources/views/livewire/projects/menu.blade.php @@ -4,4 +4,5 @@ Reports Mailings Settings + Exports diff --git a/laravel_app/resources/views/livewire/projects/tabs/exports.blade.php b/laravel_app/resources/views/livewire/projects/tabs/exports.blade.php new file mode 100644 index 0000000..fad2b6f --- /dev/null +++ b/laravel_app/resources/views/livewire/projects/tabs/exports.blade.php @@ -0,0 +1,56 @@ +
+
+
+
+ {{ __('RDS File') }} +
+
+ {{__('Download the RDS file for this project')}} +
+
+
+ +
+
+
+
+ {{__('Download Tifs')}} +
+ {{ __('Create a zip file with satelite images for a given time series') }} +
+
+
{{-- flex col--}} +
+
+
+ +
+
+
+
+
+
+
+
+ {{__('Download Mosaics')}} +
+ {{ __('Create a zip file with mosaic images for a given time series') }} +
+
+
{{-- flex col--}} +
+
+
+ +
+
+
+
+
+
+
+ + +
diff --git a/laravel_app/resources/views/projects/show.blade.php b/laravel_app/resources/views/projects/show.blade.php index 5ecc990..09b851e 100644 --- a/laravel_app/resources/views/projects/show.blade.php +++ b/laravel_app/resources/views/projects/show.blade.php @@ -24,6 +24,9 @@ @case('settings') @break + @case('exports') + + @break @default
Menu Component not found.
@endswitch diff --git a/laravel_app/tests/Unit/Models/ProjectTest.php b/laravel_app/tests/Unit/Models/ProjectTest.php index ed09151..2db9422 100644 --- a/laravel_app/tests/Unit/Models/ProjectTest.php +++ b/laravel_app/tests/Unit/Models/ProjectTest.php @@ -329,4 +329,5 @@ public static function scheduleDayProvider() ]; } + } diff --git a/r_app/CI_report_dashboard_planet.Rmd b/r_app/CI_report_dashboard_planet.Rmd index 6741d50..ebe8e25 100644 --- a/r_app/CI_report_dashboard_planet.Rmd +++ b/r_app/CI_report_dashboard_planet.Rmd @@ -230,20 +230,20 @@ create_CI_map <- function(pivot_raster, pivot_shape, pivot_spans, show_legend = tm_shape(pivot_raster, unit = "m")+ tm_raster(breaks = c(0,0.5,1,2,3,4,5,6,7,Inf), palette = "RdYlGn",legend.is.portrait = legend_is_portrait ,midpoint = NA) + tm_layout(main.title = paste0("\nMax CI week ", week,"\n", age, " weeks old"), - main.title.size = 0.7, 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) + main.title.size = 0.7, 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) } 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 = c(-3,-2,-1,0,1,2, 3), palette = "RdYlGn",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 = 0.7, 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) + main.title.size = 0.7, 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){ diff --git a/r_app/Rplots.pdf b/r_app/Rplots.pdf index ad6bce6..c264194 100644 Binary files a/r_app/Rplots.pdf and b/r_app/Rplots.pdf differ diff --git a/r_app/interpolate_growth_model.R b/r_app/interpolate_growth_model.R index 9c219ca..20b317a 100644 --- a/r_app/interpolate_growth_model.R +++ b/r_app/interpolate_growth_model.R @@ -27,8 +27,6 @@ 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") @@ -53,7 +51,7 @@ pivot_stats2 <- readRDS(here(cumulative_CI_vals_dir,"combined_CI_data.rds")) %>% # 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), + mutate(#Date = right(Date, 8), Date = lubridate::ymd(Date) ) %>% drop_na(c("value","Date")) %>% @@ -72,7 +70,7 @@ pivot_stats_long <- pivot_stats2 %>% # 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) -print(pivot_select_model_Data_2024) +message(pivot_select_model_Data_2024) # pivots_dates_Data_2022 <- pivots_dates0 %>% filter(!is.na(season_end_2022)) # pivot_select_model_Data_2022 <- unique(pivots_dates_Data_2022$pivot_quadrant ) # @@ -83,14 +81,14 @@ print(pivot_select_model_Data_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 = "4042902" + # field_names = "Nandi A1a" # field_names = "1.13A" # harvesting_data = harvesting_data # field_CI_data = pivot_stats_long # season= 2024 filtered_harvesting_data <- harvesting_data %>% - na.omit() %>% + # na.omit() %>% filter(year == season, sub_field %in% field_names) filtered_field_CI_data <- field_CI_data %>% @@ -125,6 +123,7 @@ extract_CI_data <- function(field_names, harvesting_data, field_CI_data, season) # 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') +head(Data_2024) #CI_all <- rbind(Data_2023, Data_2024) diff --git a/r_app/parameters_project.R b/r_app/parameters_project.R index ce5547e..cbfa024 100644 --- a/r_app/parameters_project.R +++ b/r_app/parameters_project.R @@ -92,7 +92,7 @@ if(project_dir == "chemba"){ names(field_boundaries_sf) <- c("field", "sub_field", "geometry") field_boundaries <- field_boundaries_sf %>% vect() harvesting_data <- read_excel(here(data_dir, "harvest.xlsx"), - col_types = c("numeric", "numeric", "numeric", + col_types = c("text", "text", "numeric", "date", "date", "numeric", "text", "numeric", "numeric")) %>% mutate(season_end = case_when(