-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.R
1394 lines (1231 loc) · 56 KB
/
app.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Loading libraries -------------------------------------------------------
library(arrow)
library(shiny)
library(shinyWidgets)
library(shinycustomloader)
library(bslib)
library(tibble)
library(stringr)
library(dplyr)
library(rnaturalearth)
library(tidyr)
library(sf)
library(ggplot2)
library(plotly)
library(RColorBrewer)
library(glue)
library(forcats)
options(scipen = 0)
# Loading supporting files ------------------------------------------------
# Get list of all regions available
region_keys <- read_csv_arrow("www/FishMIP_regions_keys.csv",
col_select = !id) |>
deframe()
# Getting names of environmental variables available with equivalent from WOA
var_metadata <- read_csv_arrow("www/woa_gfdl_var_keys.csv")
# GFDL variables - named vector
gfdl_variables <- var_metadata |>
select(long_name.gfdl, gfdl_name) |>
arrange(long_name.gfdl) |>
deframe()
woa_variables <- var_metadata |>
distinct(standard_name.woa, woa_name_code) |>
drop_na() |>
deframe()
# Shapefile with FishMIP regional model boundaries
fish_reg <- file.path("/rd/gem/private/shared_resources/FishMIP_regional_models",
"FishMIP_regional_models.shp") |>
read_sf() |>
mutate(region = str_to_lower(str_remove_all(region, "'")))
# Load catch and effort data
effort_regional_ts <- read_parquet(
"www/effort_1950-2017_FishMIP_regions.parquet")
catch_regional_ts <- read_parquet("www/catch_1950-2017_FishMIP_regions.parquet")
# Define variables for effort and catch datasets we use
effort_variables <- c("Functional Group", "Sector", "Gear")
catch_variables <- c("Functional Group", "Sector")
# Defining location of relevant data sources ------------------------------
# Folders containing Earth System Model (ESM) data
fishmip_dir <- file.path("/rd/gem/public/fishmip/ISIMIP3a/InputData/climate",
"ocean/obsclim/regional/monthly/historical",
"GFDL-MOM6-COBALT2")
#Get a list of GFDL files available
#For download
download_files <- list.files(file.path(fishmip_dir, "download_data"),
full.names = T)
#For mapping
maps_files <- file.path(fishmip_dir, "maps_data")
#For time series
ts_files <- file.path(fishmip_dir, "ts_data")
#For differences
map_comp_files <- file.path(fishmip_dir, "comp_maps")
ts_comp_files <- file.path(fishmip_dir, "comp_ts")
# Getting list of all files within folders
woa_maps <- "/rd/gem/public/fishmip/WOA_data/regional/climatology"
woa_ts <- "/rd/gem/public/fishmip/WOA_data/regional/monthly/ts"
# Loading map of the world
world <- ne_countries(returnclass = "sf", scale = "medium")
#Defining palette to be used with effort and catch data
mypal <- c(brewer.pal(n = 9, name = "Set1"), brewer.pal(n = 12, name = "Set3"),
brewer.pal(n = 8, name = "Accent"))
#Defining plot themes
prettymap_theme <- list(geom_tile(),
theme_classic(),
scale_fill_viridis_c(na.value = NA),
geom_sf(inherit.aes = F, data = world, lwd = 0.25,
color = "black", show.legend = F),
theme(text = element_text(colour = "black", size = 15),
legend.position = "bottom",
axis.title = element_blank(),
legend.key.width = unit(3.5, "cm"),
legend.key.height = unit(1, "cm"),
plot.title = element_text(size = 18, hjust = 0.5),
axis.text.y = element_text(hjust = 0.5,
vjust = 0.5,
size = 15),
axis.text.x = element_text(angle = 45,
hjust = 0.5,
vjust = 0.5,
size = 15),
legend.ticks = element_line(linewidth = 0.75,
colour = "gray"),
legend.frame = element_rect(linewidth = 0.75,
colour = "dark gray"),
legend.text = element_text(size = 15),
legend.title = element_text(size = 15)))
prettyts_theme <- list(theme_bw(),
theme(axis.text.y = element_text(size = 14),
axis.text.x = element_text(angle = 45, vjust = 1,
hjust = 1, size = 14),
axis.title.y = element_text(size = 15),
axis.title.x = element_blank(),
plot.title = element_text(hjust = 0.5, size = 18),
legend.position = "bottom",
legend.text = element_text(size = 18)))
fishing_theme <- list(geom_area(stat = "identity", alpha = 0.85,
position = "stack"),
scale_x_continuous(breaks = seq(1950, 2017, 5)),
scale_fill_manual(values = mypal),
theme_bw(),
guides(fill = guide_legend(title.position = "top",
title.hjust = 0.5)),
theme(axis.text.y = element_text(size = 12),
axis.text.x = element_text(angle = 45, vjust = 1,
hjust = 1, size = 12),
axis.title.y = element_text(size = 12),
axis.title.x = element_blank(),
legend.position = "bottom",
legend.direction = "horizontal",
legend.title = element_text(size = 12,
face = "bold"),
legend.text = element_text(size = 12)))
# Defining functions ------------------------------------------------------
# Function to improve map ratios for plotting
scaler <- function(x, type, ratio = F){
if((x > 0 & type == "min") | (x < 0 & type == "min")){
x <- ifelse(ratio == T, x-3, x-5)
}else if((x < 0 & type == "max") | (x > 0 & type == "max")){
x <- ifelse(ratio == T, x+2, x+4)
}else if(x == 0 & type == "min"){
x <- ifelse(ratio == T, x-1, x-2)
}else{
x <- ifelse(ratio == T, x+1, x+2)
}
return(x)
}
range_map <- function(df, region){
minx <- min(df$lon)
maxx <- max(df$lon)
miny <- min(df$lat)
maxy <- max(df$lat)
# Calculate range
rangex <- abs(abs(maxx)-abs(minx))
rangey <- abs(abs(maxy)-abs(miny))
# Check if map crosses international date line
if(rangex == 0 & str_detect(region, "southern-ocean", negate = T)){
df <- df |>
mutate(lon = lon%%360)
minx <- min(df$lon)
maxx <- max(df$lon)
}
if(rangex >= 1.1*rangey){
ylims <- c(scaler(miny, "min"),
scaler(maxy, "max"))
xlims <- c(scaler(minx, "min", ratio = T),
scaler(maxx, "max", ratio = T))
}else if(rangey >= 1.1*rangex){
xlims <- c(scaler(minx, "min"),
scaler(maxx, "max"))
ylims <- c(scaler(miny, "min", ratio = T),
scaler(maxy, "max", ratio = T))
}else{
xlims <- c(scaler(minx, "min"),
scaler(maxx, "max"))
ylims <- c(scaler(miny, "min"),
scaler(maxy, "max"))
}
return(list(df = df,
xlims = xlims,
ylims = ylims))
}
# Defining user interface ------------------------------------------------------
## Global UI -------------------------------------------------------------------
ui <- fluidPage(
theme = bs_theme(bootswatch = "materia"),
titlePanel(title = span(img(src = "FishMIP_logo.jpg",
height = 100, width = 300,
style = "display: block; margin-left: auto;
margin-right:auto"),
h1("Regional Climate Forcing Data Explorer",
style = "color: #095c9e; background-color:#f3f3f3;
border:1.5px solid #c9d5ea;
padding-left: 15px; padding-bottom: 10px;
padding-top: 10px;
text-align: center; font-weight: bold")),
windowTitle = "FishMIP Regional Climate Forcing Data Explorer"),
## Model tab -----------------------------------------------------------------
tabsetPanel(
tabPanel("GFDL model outputs",
sidebarLayout(
sidebarPanel(
h4(strong("Instructions:")),
# Choose region of interest
p("1. Select a FishMIP regional model:"),
selectInput(inputId = "region_gfdl", label = NULL,
choices = region_keys,
selected = "east-bass-strait"),
# Choose variable of interest
p("2. Select an environmental variable:"),
selectInput(inputId = "variable_gfdl",
label = NULL,
choices = gfdl_variables,
selected = "tos"),
# Depth drop down only appears for variables that contain this
# information
conditionalPanel(
condition = "['o2', 'chl', 'zmeso', 'zmicro', 'phydiat',
'phydiaz', 'phypico', 'phyc', 'thetao', 'so', 'uo', 'vo',
'zooc', 'ph'].includes(input.variable_gfdl)",
selectizeInput(inputId = "depth_gfdl",
label = "Choose depth you want to visualise:",
choices = NULL)),
p("3a. Click on the ", strong('Climatological map'),
" tab on the right to see a map of the
climatological mean (1961-2010)."),
p("3b. Click on the ", strong('Time series plot'),
" tab to see a time series of the area-weighted monthly
mean and the linear temporal trend."),
p(em("Optional: "), "Get a copy of the data used to create
these plots by clicking the 'Download' button below."),
# Download option
downloadButton(outputId = "download_gfdl",
label = "Download")
),
mainPanel(
br(),
"All figures shown in this tab are based on the ",
em("Observation-based climate related forcing"), " (obsclim)
outputs from the GFDL-MOM6-COBALT2 model. These data were
originally obtained from the ",
tags$a(href = paste0("https://data.isimip.org/search/tree/",
"ISIMIP3a/InputData/climate/ocean/",
"gfdl-mom6-cobalt2/obsclim/"),
"ISIMIP Data Repository."),
br(), br(),
"The ", em("Climatological map"), " tab below shows the mean
climatology (1961-2010) for the environmental variable and
within the boundaries of the regional model of interest
selected on the left.",
br(), br(),
"The ", em("Time series plot"), "tab below shows the
area-weighted monthly mean between 1961 and 2010.",
br(), br(),
strong("Note: "), "The variable names and units shown in the
dropdown list and plots come from the GFDL-MOM6-COBALT2 model.
We have chosen not apply any transformation to the original
model outputs. Instead, we summarised data so we could create
the map and time series plots within the limits of all FishMIP
regional models. If your model requires environmental data to
be in a unit or grid that is different to the one available in
the GFDL-MOM6-COBALT2 model, you can download the data from
this website and post-process it to meet your needs.",
br(), br(),
tabsetPanel(
tabPanel("Climatological map",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "map_gfdl",
width = "100%"),
type = "html",
loader = "myloader"))
),
tabPanel("Time series plot",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "ts_gfdl",
width = "100%"),
type = "html",
loader = "myloader"))
)
)
)
)
),
## Observations tab --------------------------------------------------------
tabPanel("World Ocean Atlas 2023 data",
sidebarLayout(
sidebarPanel(
h4(strong("Instructions:")),
# Choose region of interest
p("1. Select a FishMIP regional model:"),
selectInput(inputId = "region_WOA", label = NULL,
choices = region_keys,
selected = "east-bass-strait"),
# Choose variable of interest
p("2. Select an environmental variable:"),
selectInput(inputId = "variable_WOA", label = NULL,
choices = woa_variables,
selected = "temp"),
# Select depth (if available)
selectizeInput(inputId = "depth_woa",
label = "Choose depth you want to visualise:",
choices = NULL),
p("3a. Click on the ", strong('Climatological map'),
" tab on the right to see a map of the climatological
mean (1981-2010) of observations."),
p("3b. Click on the ", strong('Time series plot'),
" tab to see a time series of area-weighted
monthly mean of observations."),
#Optional download
p(em("Optional: "), "Get a copy of the data used to create
climatological maps as a csv file by clicking the 'Download'
button below."),
# Download option
downloadButton(outputId = "download_WOA", label = "Download")
),
mainPanel(
br(),
"Figures shown in this tab use data from the ",
tags$a(href =
"https://www.ncei.noaa.gov/products/world-ocean-atlas",
"World Ocean Atlas 2023 (WOA23)"),
". We used the ", em("objectively analysed climatologies"),
"field to create the climatological maps and area-weighted
monthly climatology time series plot. While, the ",
em("number of observations "), "variable was used to create the
maps shown in the sub-tab under the same name.",
br(), br(),
strong("Note: "), "The variable names and units shown in the
dropdown list and plots come from the WOA23. We have chosen not
apply any transformation to the original data. Instead, we
summarised data so we could create maps and time series plots
within the limits of all FishMIP regional models. If your model
requires environmental data to be in a unit or grid that is
different to the one available in the WOA23a you can download
the data from this website and post-process it to meet your
needs.",
br(), br(),
"For some regions, the WOA23 dataset may have a very limited
number of observations and so it may not offer the most
realistic representation of your area of interest. In this
case, you may choose to use a different observational product
to assess the performance of GFDL-MOM6-COBALT2 outputs. We have
an ", tags$a(href =
paste0("https://github.com/Fish-MIP/",
"processing_WOA_data/blob/main/scripts/",
"P_regridding_woa_data.ipynb"),
"example notebook"), " showing how you can regrid this
data to match the grid used by the GFDL-MOM6-COBALT2 model.",
br(), br(),
tabsetPanel(
tabPanel("Climatological map",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "map_WOA",
width = "100%"),
type = "html",
loader = "myloader"))
),
tabPanel("Time series plot",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "ts_WOA",
width = "100%"),
type = "html",
loader = "myloader")),
br(),
br(),
br(),
br(),
strong("Note: "), "The grey ribbon in the plot
above shows the spatial variance in the variable
of interest.",
br(),
br(),
br()
),
tabPanel("Number of in-situ observations",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "count_WOA",
width = "100%"),
type = "html",
loader = "myloader")
)),
)
)
)
),
## Comparison tab ----------------------------------------------------------
tabPanel("Model outputs against observations",
sidebarLayout(
sidebarPanel(
h4(strong("Instructions:")),
# Choose region of interest
p("1. Select a FishMIP regional model:"),
selectInput(inputId = "region_compare", label = NULL,
choices = region_keys,
selected = "east-bass-strait"),
# Choose variable of interest
p("2. Select an environmental variable:"),
selectInput(inputId = "variable_compare", label = NULL,
choices = woa_variables,
selected = "temp"),
# Select depth (if available)
selectizeInput(inputId = "depth_comp",
label = "Choose depth you want to visualise:",
choices = NULL),
p("3a. Click on the ", strong('Climatological map'),
" tab on the right to see a map of the differences
in the climatological mean (1981-2010) from the model output
and observations."),
p("3b. Click on the ", strong('Time series plot'),
" tab to see the difference in climatological monthly
area-weighted mean (1981-2010) between the model output and
observations."),
#Optional download
p(em("Optional: "), "Get a copy of the data for bias correction
(if needed) as a compressed folder by clicking the 'Download'
button below."),
# Download option
downloadButton(outputId = "download_comp",
label = "Download")
),
mainPanel(
br(),
"The following processing steps were taken before comparing
GFDL model outputs and WOA data:", br(),
"1. Climatological mean was calculated using GFDL outputs
between 1981 and 2010.", br(),
"2. WOA data was regridded to match the GFDL outputs.", br(),
"3. Difference was calculated by substracting WOA data from
GFDL model outputs.", br(),
br(),
"This means that positive values in the maps identify areas
where GFDL overestimated mean conditions.",
br(), br(),
tabsetPanel(
tabPanel("Climatological maps",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "map_compare",
width = "140%"),
type = "html",
loader = "myloader"))
),
tabPanel("Time series plot",
mainPanel(
br(),
withLoader(
plotOutput(outputId = "ts_compare",
width = "100%"),
type = "html",
loader = "myloader"))
)
)
)
)
),
## Catch and effort tab ----------------------------------------------------
tabPanel("Fishing effort and catch data",
sidebarLayout(
sidebarPanel(
h4(strong("Instructions:")),
# Choose region of interest
p("1. Select a FishMIP regional model:"),
selectInput(inputId = "region_effort", label = NULL,
choices = names(region_keys),
selected = "East Bass Strait"),
# Choose catch or effort data
p("2. Select dataset to visualise:"),
radioButtons(inputId = "catch_effort_select", label = NULL,
choiceNames = c("Fishing Effort",
"Fisheries Catch"),
choiceValues = c("effort", "catch"),
selected = "effort"),
# Choose variable of interest
p("3. Select how data should be classified in the plot:"),
selectInput(inputId = "variable_effort",
label = NULL,
choices = effort_variables,
selected = "Functional Group"),
# Inline layout for download button
p(em("Optional: "), "Get a copy of the data used to create
these plots by clicking the 'Download' button below. Note
that the compressed downloaded folder also includes a
dictionary to interpret the column names in the fishing data
and keys to interpret country codes."),
downloadButton(outputId = "download_data", label = "Download")
),
mainPanel(
br(),
"The fishing effort and catch data used to create plots in this
tab were obtained from 'ISIMIP3a reconstructed fishing activity
data (v1.0)'",
tags$a(href = "https://data.isimip.org/10.48364/ISIMIP.240282",
"(Novaglio et al. 2024)."),
br(),
br(),
"The fishing effort and catch data start in 1950, but the
fishing effort forcing was reconstructed starting in 1841,
which is available for download on the left panel.",
br(),
tabPanel("",
mainPanel(
br(),
withLoader(plotlyOutput(outputId = "ts_effort",
width = "100%",
height = "500px"),
type = "html", loader = "myloader")
))
)
)
),
## About tab ---------------------------------------------------------------
tabPanel(title = "About",
mainPanel(
br(),
h3(strong("About this website")),
p("This tool allows regional modellers to visualise
environmental data from GFDL-MOM6-COBALT2 and from
observations to determine if bias correction (Step 3 below)
needs to be applied to the data prior to its use as forcings of
a regional marine ecosystem model."),
br(),
img(src = "FishMIP_regional_model_workflow.png", height = 600,
width = 715, style = "display: block;
margin-left: auto;
margin-right: auto"),
br(),
h3(strong("Who is FishMIP?")),
p("The Fisheries and Marine Ecosystem Model Intercomparison
Project (FishMIP) is an network of more than 100 marine ecosystem
modellers and researchers from around the world. Our goal is to
bring together our collective understanding to help better
project the long-term impacts of climate change on fisheries and
marine ecosystems, and to use our findings to help inform policy.
You can find more information about FishMIP on our ",
tags$a(href="https://fishmip.org/", "website.")),
br(),
img(src = "FishMIP_regional_models.png", height = 590,
width = 775, style = "display: block;
margin-left: auto;
margin-right: auto"),
br(),
h3(strong("How should I use this tool?")),
p("This site has three main tabs:"),
p("1.", em(strong("GFDL model outputs"))),
p("2.", em(strong("World Ocean Atlas 2023 data"))),
p("3.", em(strong("Model outputs against observations"))),
p("You can download data that has been subsetted for the
regional model of your interest in the first two tabs. Note
that all WOA 2023 data are available for download as ",
em("csv"), " files. GFDL outputs that do not have a depth
component (i.e., surface or bottom data) are also available as
", em("csv"), " files."),
p("However, due to the size of GFDL outputs with a depth
component (e.g. temperature of the water column), these data
are only available for download as ", em("zip"), " (i.e.,
compressed) folders containing ", em("Zarr"), " files
to speed up download times. A ", em("Zarr"), " file is a cloud
optimised gridded data file format similar to ", em("netcdf"),
" files. If you use Python, we recommend you use the ",
em("xarray"), " library to open these files. If you use R, we
recommend the ", em("Rarrr"), " library. For instructions on
how to load these files in R, refer to ",
tags$a(href =
"https://github.com/Fish-MIP/FishMIP_extracting-data/blob/main/scripts/loading_zarr_files.md",
"this example.")),
br(),
h3(strong("How should I cite data from this site?")),
p("You can download the data used to create the plots shown in
this interactive tool using the 'Download' button included
under each tab. As a condition of this tool to access data,
you must cite its use. Please use the following citations:"),
p("- Fierro-Arcos, D., Blanchard, J. L., Clawson, G., Flynn, C.,
Ortega Cisneros, K., Reimer, T. (2024). FishMIP input explorer
for regional ecosystem modellers. ",
tags$a(href = "https://rstudio.global-ecosystem-model.cloud.edu.au/shiny/FishMIP_Input_Explorer/")),
p("When using the data products in a publication, please include
the following citation in addition to the data product citation
provided above:"),
p("- Ortega-Cisneros, K., Fierro-Arcos, D. Lindmark, M., et al.
(Preprint). An Integrated Global-to-Regional Scale Workflow for
Simulating Climate Change Impacts on Marine Ecosystems. ESS
Open Archive. DOI:",
tags$a(href ="http://dx.doi.org/10.22541/essoar.171587234.44707846/v1",
"10.22541/essoar.171587234.44707846/v1")),
p("When using GFDL-MOM6-COBALT2 model outputs, you
also need to include the following citation:"),
p("- Xiao Liu, Charles Stock, John Dunne, Minjin Lee, Elena
Shevliakova, Sergey Malyshev, Paul C.D. Milly, Matthias Büchner
(2022): ISIMIP3a ocean physical and biogeochemical input data
[GFDL-MOM6-COBALT2 dataset] (v1.0). ISIMIP Repository. DOI:",
tags$a(href = "https://doi.org/10.48364/ISIMIP.920945",
"10.48364/ISIMIP.920945")),
p("If using WOA23 data, please refer to their ",
tags$a(href =
"https://www.ncei.noaa.gov/products/world-ocean-atlas",
"product documentation"), " for the most appropriate citation."),
p("The fishing and catch data should be cited as follows:"),
p("- Camilla Novaglio, Yannick Rousseau, Reg A. Watson, Julia L.
Blanchard (2024): ISIMIP3a reconstructed fishing activity data
(v1.0). ISIMIP Repository. DOI: ",
tags$a(href = "https://doi.org/10.48364/ISIMIP.240282",
"10.48364/ISIMIP.240282")),
br(),
h3(strong("How can I contact you?")),
p("If you are interested in our regional modelling work and would like to be
part of the FishMIP community, you can head to the ",
tags$a(href = "https://fishmip.org/joinus.html", "'Join us'"),
" section of our website for more information."),
p("If you would like to suggest changes or have spotted an
issue with this app, you can create an issue in our ",
tags$a(href = "https://github.com/Fish-MIP/FishMIP_Input_Explorer/issues",
"GitHub repository.")),
br(),
h4(strong("Acknowledgments")),
p("The development of this tool was funded by the Australian
Government through the Australian Research Council (ARC)
Future Fellowship Project FT210100798. We gratefully
acknowledge contributions
from coordinators and contributing modellers of the FishMIP
and ISIMIP communities. We would also like to acknowledge
OceanHackWeek participants for contributing to the development
of this tool. Finally, we would also like to acknowledge the
use of computing facilities provided by Digital Research
Services, IT Services at the University of Tasmania."),
br(),
br(),
fluidRow(
column(4, img(src = "IMAS_logo.png", height = 150, width = 300,
style = "display: block; margin-left: auto;
margin-right: auto")),
column(4, br(),
img(src = "FishMIP_logo.jpg", height = 125,
width = 350,
style = "display: block; margin-left: auto;
margin-right: auto")),
column(4, img(src = "UN_OceanDecadeLogo_cropped.png",
height = 150, width = 300,
style = "display: block; margin-left: auto;
margin-right: auto"))),
br()
)
)
)
)
# Define actions ---------------------------------------------------------------
server <- function(input, output, session) {
## Model tab -----------------------------------------------------------------
# Merging region and variable information to filter files
lookup_file <- reactive({
#Get variable metadata
var_meta <- var_metadata |>
filter(gfdl_name == input$variable_gfdl)
#Variable long name
var <- var_meta$long_name.gfdl
## Create title for colour bar
unit <- var_meta$units.gfdl
if(unit == "1"){
unit <- "unitless"
}else if(unit == "0.001"){
unit <- "parts per thousand"
}
cb_lab <- paste0(var, " (", unit, ")")
#Create keywords to search files
search_file <- paste0("_", input$variable_gfdl, "_.*_", input$region_gfdl)
#Return items
return(list(search_file = search_file,
long_name = var,
cb_lab = cb_lab))
})
# Loading relevant data
gfdl_data <- reactive({
#Loading maps dataset
df_map <- list.files(maps_files, pattern = lookup_file()$search_file,
full.names = T) |>
read_parquet(col_select = lat:vals)
#Loading time series dataset
df_ts <- tryCatch({
list.files(ts_files, pattern = lookup_file()$search_file,
full.names = T) |>
read_parquet(col_select = time:vals)
},
error = function(cond){
NA
})
#Loading region boundaries
shp_map <- fish_reg |>
filter(region == str_replace_all(input$region_gfdl, "-", " "))
return(list(df_map = df_map,
df_ts = df_ts,
shp_map = shp_map))
})
observeEvent(gfdl_data(), {
#Getting depth information
if("depth_bin_m" %in% colnames(gfdl_data()$df_map)){
depths <- unique(gfdl_data()$df_map$depth_bin_m)
}else{
depths <- NULL
}
updateSelectizeInput(session, "depth_gfdl",
choices = depths, server = T)
})
gfdl_maps_df <- reactive({
df <- gfdl_data()$df_map
if("depth_bin_m" %in% colnames(df)){
df <- df |>
filter(depth_bin_m == input$depth_gfdl)
}
validate(
need(df$lon != "",
"Rendering map"))
range_map <- range_map(df, input$region_gfdl)
if(max(range_map$df$lon) > 180){
shp_map <- gfdl_data()$shp_map |>
st_shift_longitude()
}else{
shp_map <- gfdl_data()$shp_map
}
title <- paste0("Climatological mean (1961-2010) ",
lookup_file()$long_name) |>
str_to_sentence()
return(list(df = range_map$df,
shp_map = shp_map,
ylim = range_map$ylims,
xlim = range_map$xlims,
title = title))
})
# Creating first plot
output$map_gfdl <- renderPlot({
df <- gfdl_maps_df()$df
shp_map <- gfdl_maps_df()$shp_map
# Plotting map
ggplot(df, aes(x = lon, y = lat, fill = vals)) +
prettymap_theme +
geom_sf(inherit.aes = F, data = shp_map, colour = "red", fill = NA,
linewidth = 0.75)+
coord_sf(ylim = gfdl_maps_df()$ylim, xlim = gfdl_maps_df()$xlim,
expand = F) +
guides(fill = guide_colorbar(title = lookup_file()$cb_lab,
title.position = "top", title.hjust = 0.5))+
labs(title = str_wrap(gfdl_maps_df()$title, 65))
},
height = 600, width = 750)
gfdl_ts_df <- reactive({
df <- gfdl_data()$df_ts
if("depth" %in% colnames(df)){
df <- df |>
filter(depth == input$depth_gfdl)
}
title <- paste0("Area weighted mean (1961-2010) for ",
lookup_file()$long_name) |>
str_to_sentence()
return(list(df = df,
title = title))
})
output$ts_gfdl <- renderPlot({
df <- gfdl_ts_df()$df
validate(
need(!is.na(df),
paste0("Fixed variable selected from dropdown list.\n",
"Time series is not available for this variable.")))
# Calculate spatially weighted average of variables selected
ggplot(df, aes(x = time, y = vals)) +
geom_line(aes(color = "area weighted monthly mean")) +
geom_smooth(aes(color = "linear temporal trend")) +
scale_color_manual(breaks = c("area weighted monthly mean",
"linear temporal trend"),
values = c("#004488", "#bb5566")) +
scale_x_date(date_labels = "%b-%Y", date_breaks = "24 months",
expand = expansion(0.02)) +
guides(color = guide_legend(title = element_blank())) +
prettyts_theme +
labs(title = str_wrap(gfdl_ts_df()$title, 60),
y = str_wrap(lookup_file()$cb_lab, 50))
}, height = 500, width = 800)
#Loading download dataset
gfdl_down_path <- reactive({
file_path <- str_subset(download_files, lookup_file()$search_file)
if(str_detect(file_path, "parquet$")){
file_out <- basename(file_path) |>
str_replace(".parquet", ".csv")
}else{
file_out <- basename(file_path)
}
return(list(file_path = file_path,
file_out = file_out))
})
gfdl_down_data <- reactive({
file_path <- gfdl_down_path()$file_path
if(str_detect(file_path, "parquet$")){
df <- read_parquet(file_path)
}else{
df <- file_path
}
return(df)
})
output$download_gfdl <- downloadHandler(
filename = function(){
gfdl_down_path()$file_out
},
# Creating name of download file based on original file name
content = function(file){
id <- showNotification("Preparing Download...", type = "message",
duration = NULL, closeButton = F)
df <- gfdl_down_data()
if(str_detect(file, "csv$")){
write_csv(df, file)
}else{
file.copy(df, file)
}
on.exit(removeNotification(id), add = TRUE)
}
)
# output$test <- renderPrint({
# c(head(gfdl_down_data()),
# gfdl_down_path()$file_out)
# })
## Observations tab ----------------------------------------------------------
# Select correct file based on inputs from region and variable selected
lookup_woa <- reactive({
#Get variable metadata
var_meta <- var_metadata |>
select(contains("woa")) |>
distinct() |>
filter(woa_name_code == input$variable_WOA)
## Create title for colour bar
var <- var_meta$standard_name.woa
unit <- var_meta$units.woa
if(unit == "1"){
unit <- "unitless"
}
cb_lab <- paste0(var, " (", unit, ")")
#Create keywords to search files
search_file <- paste0("_", input$region_WOA, "_.*mean.*_",
input$variable_WOA)
count_file <- paste0("_", input$region_WOA, "_number_obs_",
input$variable_WOA)
#Return items
return(list(search_file = search_file,
count_file = count_file,
long_name = var,
cb_lab = cb_lab))
})
woa_data <- reactive({
#Loading maps dataset
df_map <- list.files(woa_maps, pattern = lookup_woa()$search_file,
full.names = T) |>
read_parquet(col_select = lat:vals) |>
drop_na(vals)
#Loading time series dataset
df_ts <- list.files(woa_ts, pattern = lookup_woa()$search_file,
full.names = T) |>
read_parquet(col_select = month:weighted_sd) |>
mutate(month = factor(month, levels = month.name, ordered = T))
#Loading region boundaries
shp_map <- fish_reg |>
filter(region == str_replace_all(input$region_WOA, "-", " "))
#Getting depth information
depths <- unique(df_map$depth)
return(list(df_map = df_map,
df_ts = df_ts,
depths = depths,
shp_map = shp_map))
})
observeEvent(woa_data(), {
updateSelectizeInput(session, "depth_woa",
choices = woa_data()$depths, server = T)
})
woa_maps_df <- reactive({
df <- woa_data()$df_map |>
filter(depth == input$depth_woa)
validate(
need(df$lon != "",
"Rendering map"))
# Adjusting map proportions
range_map <- range_map(df, input$region_WOA)
if(max(range_map$df$lon) > 180){
shp_map <- woa_data()$shp_map |>
st_shift_longitude()
}else{
shp_map <- woa_data()$shp_map
}
title <- paste0("Climatological mean (1981-2010) ",
lookup_woa()$long_name) |>
str_to_sentence()
return(list(df = range_map$df,
shp_map = shp_map,
ylim = range_map$ylims,
xlim = range_map$xlims,
title = title))
})
# Creating first plot
output$map_WOA <- renderPlot({
df <- woa_maps_df()$df
shp_map <- woa_maps_df()$shp_map
# Plotting map
ggplot(df, aes(x = lon, y = lat, fill = vals)) +
prettymap_theme +
geom_sf(inherit.aes = F, data = shp_map, colour = "red", fill = NA,
linewidth = 0.75)+
coord_sf(ylim = woa_maps_df()$ylim, xlim = woa_maps_df()$xlim,
expand = F) +