-
Notifications
You must be signed in to change notification settings - Fork 4
/
app.R
1744 lines (1483 loc) · 116 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
### COVID-19 vaccine tracker
### Vaccine Centre, London School of Hygiene & Tropical Medicine
### Contact: Edward Parker, [email protected]
### Shiny app code
### LOAD PACKAGES ---------------------------------------------------------------------------------
if(!require(data.table)) install.packages("data.table", repos = "http://cran.us.r-project.org")
if(!require(DT)) install.packages("DT", repos = "http://cran.us.r-project.org")
if(!require(dplyr)) install.packages("dplyr", repos = "http://cran.us.r-project.org")
if(!require(ggplot2)) install.packages("ggplot2", repos = "http://cran.us.r-project.org")
if(!require(plotly)) install.packages("plotly", repos = "http://cran.us.r-project.org")
if(!require(shiny)) install.packages("shiny", repos = "http://cran.us.r-project.org")
if(!require(shinythemes)) install.packages("shinythemes", repos = "http://cran.us.r-project.org")
if(!require(stringr)) install.packages("stringr", repos = "http://cran.us.r-project.org")
if(!require(stringi)) install.packages("stringi", repos = "http://cran.us.r-project.org")
if(!require(timevis)) install.packages("timevis", repos = "http://cran.us.r-project.org")
if(!require(RColorBrewer)) install.packages("RColorBrewer", repos = "http://cran.us.r-project.org")
if(!require(shinydashboard)) install.packages("shinydashboard", repos = "http://cran.us.r-project.org")
if(!require(writexl)) install.packages("writexl", repos = "http://cran.us.r-project.org")
if(!require(tidyverse)) install.packages("tidyverse", repos = "http://cran.us.r-project.org")
if(!require(readxl)) install.packages("readxl", repos = "http://cran.us.r-project.org")
if(!require(shinyWidgets)) install.packages("shinyWidgets", repos = "http://cran.us.r-project.org")
if(!require(cowplot)) install.packages("cowplot", repos = "http://cran.us.r-project.org")
if(!require(BiocManager)) install.packages("BiocManager", repos = "http://cran.us.r-project.org")
if(!require(leaflet)) install.packages("leaflet", repos = "http://cran.us.r-project.org")
if(!require(geojsonio)) install.packages("geojsonio", repos = "http://cran.us.r-project.org")
if(!require(scales)) install.packages("scales", repos = "http://cran.us.r-project.org")
options(repos = BiocManager::repositories())
if(!require(ComplexHeatmap)) BiocManager::install("ComplexHeatmap")
### Generate landscape inputs for each layer -------------------------------------------------------------------------------------
update_full = "11 August 2022"
update_equity = as.Date("2022-08-11")
source("input_code/VaC_landscape.R")
source("input_code/VaC_efficacy_map.R")
source("input_code/VaC_living_review.R")
source("input_code/VaC_implementation.R")
equity_slider = c(seq(as.Date("2021-01-01"), update_equity, by="months"), update_equity)
# additional code to update case counts for weekly updates
#source("input_code/VaC_jhu_daily_cases.R")
# update manual components for ui
table(landscape$Phase)
table(landscape$Platform)
table(landscape$In.use)
### UI -------------------------------------------------------------------------------------
ui <- bootstrapPage(
tags$head(includeHTML("gtag.html")),
navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
HTML('<a style="text-decoration:none;cursor:default;color:#FFFFFF;" class="active" href="#">COVID-19 vaccine tracker</a>'), id="nav",
windowTitle = "COVID-19 vaccine tracker",
#################
### HOME PAGE ###
#################
tabPanel("Home",
tags$div(
"The site is no longer updated. The last update was carried out on 11th August 2022.",tags$br(),tags$br(),
"The COVID-19 pandemic prompted numerous research institutes and companies to develop vaccine candidates targeting this novel disease.",
"First launched in April 2020, this tracker was developed by the", a("Vaccine Centre", href="https://www.lshtm.ac.uk/research/centres/vaccine-centre", target="_blank"),
"at the", a("London School of Hygiene & Tropical Medicine", href="https://www.lshtm.ac.uk", target="_blank"), "to follow candidates as they progressed through the development pipeline.",
"Weekly or monthly updates of the tracker were performed between April 2020 and August 2022.",
"Read our", a("Correspondence", href="https://www.thelancet.com/journals/langlo/article/PIIS2214-109X(21)00043-7/fulltext", target="_blank"),"in",em("Lancet Global Health"),"for further details.",
"All data and code are available via the LSHTM Vaccine Centre's", tags$a(href="https://github.com/vac-lshtm/VaC_tracker", "Github page.", target="_blank"),
tags$br(),tags$br(),
"Citation details: Shrotri, Swinnen, Kampmann, Parker (2021).",
a("An interactive website tracking COVID-19 vaccine development.", href="https://www.thelancet.com/journals/langlo/article/PIIS2214-109X(21)00043-7/fulltext", target="_blank"),tags$i("Lancet Glob Health;"),"9(5):e590-e592.",
tags$br(),tags$br(),
actionButton("twitter_share", label = "Share", icon = icon("twitter"),class = "btn btn-warning",
onclick = sprintf("window.open('%s')",
"https://twitter.com/intent/tweet?text=%20Keep%20up%20with%20the%20latest%20COVID-19%20vaccine%20developments%20with%20the%20@LSHTM_Vaccines%20tracker&url=https://vac-lshtm.shinyapps.io/ncov_vaccine_landscape/")),
tags$br(),
tags$hr(style="border-color: black;"),
fluidRow(
box(width = 4,
h3("Vaccine landscape", align="center"),
HTML('<div class="text-center"><i class="fa fa-syringe fa-4x"></i></div>'),
tags$p("Summary of vaccine candidates and trial timelines", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(1) a').tab('show');\" role=\"button\">View landscape</button></div>"),
tags$br()
),
box(width = 4,
h3("Clinical trials database", align="center"),
HTML("<div class=\"text-center\"><i class=\"fas fa-clipboard-check fa-4x\"></i></div>"),
tags$p("Key attributes of registered COVID-19 vaccine trials", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(2) a').tab('show');\" role=\"button\">View trials</button></div>"),
tags$br()
),
h3("Efficacy trial map", align="center"),
HTML("<div class=\"text-center\"><i class=\"fas fa-globe-africa fa-4x\"></i></div>"),
tags$p("Map of ongoing phase III trials as of Jan 2022", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(3) a').tab('show');\" role=\"button\">View map</button></div>"),
tags$br()
),
fluidRow(
box(width = 4,
h3("Living review", align="center"),
HTML("<div class=\"text-center\"><i class=\"fas fa-chart-line fa-4x\"></i></div>"),
tags$p("Published data on safety, immunogenicity, and efficacy", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(4) a').tab('show');\" role=\"button\">View data</button></div>"),
tags$br()
),
box(width = 4,
h3("Implementation", align="center"),
HTML("<div class=\"text-center\"><i class=\"fas fa-cart-plus fa-4x\"></i></div>"),
tags$p("Summary of vaccine distribution information", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(5) a').tab('show');\" role=\"button\">View summary</button></div>"),
tags$br()
),
box(width = 4,
h3("FAQs", align="center"),
HTML("<div class=\"text-center\"><i class=\"fas fa-question fa-4x\"></i></div>"),
tags$p("More on the vaccine development process", align="center"),
HTML("<div class=\"text-center\"><button class=\"btn btn-primary\" onclick=\"$('li:eq(6) a').tab('show');\" role=\"button\">View FAQs</button></div>"),
tags$br()
)
),
tags$br(),tags$hr(style="border-color: black;"),
tags$br(),tags$br(),
HTML('<center><img src="vac_dark.png" width="150px" height="75px"></center>'),
tags$br(),tags$br(),
HTML('<center><img src="lshtm_dark.png" width="150px" height="75px"></center>'),
tags$br(),tags$br()
)
),
######################
### LANDSCAPE PAGE ###
######################
tabPanel("Landscape",
sidebarLayout(
sidebarPanel(width = 3,
box(width = 6,
h4(total_count, align="center"),
HTML('<div class="text-center"><i class="fa fa-syringe fa-2x"></i></div>'),
tags$p("vaccine candidates", align="center", style="font-size:14px;")
),
box(width = 6,
h4(clinical_count, align="center"),
HTML('<div class="text-center"><i class="fa fa-user-friends fa-2x"></i></div>'),
tags$p("in clinical testing", align="center", style="font-size:14px;")
),
# create space behind boxes
tags$br(),tags$br(),tags$br(),tags$br(),tags$br(),tags$br(),
checkboxGroupInput(inputId = "stage",
label = "Stage of development",
choices = c("Terminated (12)" = "term",
"Pre-clinical (218)" = "preclin",
"Phase I (39)" = "phasei",
"Phase I/II (32)" = "phasei_ii",
"Phase II (18)" = "phaseii",
"Phase III (40)" = "phaseiii",
"Phase IV (9)" = "phaseiv",
"Heterologous" = "phaseheterol"),
selected = c("phasei", "phasei_ii", "phaseii", "phaseiii", "phaseiv", "phaseheterol")),
tags$br(),
checkboxGroupInput(inputId = "in_use",
label = "In use",
choices = c("No (322)" = "not_in_use",
"Yes (34)" = "in_use"),
selected = c("not_in_use", "in_use")),
tags$br(),
checkboxGroupInput(inputId = "vacc",
label = "Vaccine type",
choices = c("RNA (54)" = "rna",
"DNA (28)" = "dna",
"Vector (non-replicating) (40)" = "nrvv",
"Vector (replicating) (25)" = "rvv",
"Inactivated (26)" = "inact",
"Live-attenuated (3)" = "live",
"Protein subunit (115)" = "ps",
"Virus-like particle (28)" = "vlp",
"Other/Unknown (37)" = "unknown",
"Heterologous" = "heterol"),
selected = c("rna", "dna", "inact", "nrvv", "rvv", "live", "ps", "vlp", "unknown", "heterol")),
tags$br(),
tags$b("Colour code for vaccine type"),tags$br(),
span("RNA", style="color:#9ECAE1"),tags$br(),
span("DNA", style="color:#2171B5"),tags$br(),
span("Vector (non-replicating)", style="color:#FDAE6B"),tags$br(),
span("Vector (replicating)", style="color:#D94801"),tags$br(),
span("Inactivated", style="color:#A1D99B"),tags$br(),
span("Live-attenuated", style="color:#238B45"),tags$br(),
span("Protein subunit", style="color:#BCBDDC"),tags$br(),
span("Virus-like particle", style="color:#6A51A3"),tags$br(),
span("Heterologous/Other/Unknown", style="color:#BDBDBD")
),
mainPanel(
"The site is no longer updated. The last update was carried out on 11th August 2022.",tags$br(),tags$br(),
"Our vaccine landscape summarises information from the",
tags$a(href="https://www.who.int/publications/m/item/draft-landscape-of-covid-19-candidate-vaccines", "WHO,", target="_blank"),
"the ",tags$a(href="https://milken-institute-covid-19-tracker.webflow.io", "Milken Institute", target="_blank"),
"and ", tags$a(href="https://clinicaltrials.gov", "clinicaltrials.gov.", target="_blank"),
"We are also grateful for additional information provided directly by vaccine developers.",
tags$br(),tags$br(),
"All data and code are available via the LSHTM Vaccine Centre's", tags$a(href="https://github.com/vac-lshtm/VaC_tracker", "Github page.", target="_blank"),
"Click on trial numbers to access the published protocols.",
tags$br(),tags$br(),
tabsetPanel(
tabPanel("Full pipeline", timevisOutput("vaccine_timeline")),
tabPanel("Summary", plotOutput("summary_plot", height="400px", width="600px"),
"Candidates listed above as being in phase III include several undergoing combined phase II/III trials.")
)
)
)
),
################################
### CLINICAL TRIALS DATABASE ###
################################
tabPanel("Clinical trials",
"The site is no longer updated. The last update was carried out on 11th August 2022.",tags$br(),tags$br(),
"For each update, we searched", tags$a(href="https://clinicaltrials.gov", "clinicaltrials.gov", target="_blank"),
"for studies of COVID-19 vaccine candidates and extracted key attributes from the registered protocols.
Additional trials were identified using the", tags$a(href="https://www.who.int/publications/m/item/draft-landscape-of-covid-19-candidate-vaccines", "WHO COVID-19 vaccine landscape.", target="_blank"),
tags$br(),tags$br(),
"Trials are listed by decreasing size. Only trials with a registered protocol are included. We excluded observational studies as well as intervention trials evaluating the influence of other treatments on COVID-19 vaccine outcome.",
tags$br(),tags$br(),
"From February 2022 onwards, we no longer incorporated protocol modifications that occured after a trial was registered. Details such as sample size, start date, and primary completion date are subject to change.",
"The latest version of the published protocols can be obtained by clicking on the trial number.",
tags$br(),tags$br(),
pickerInput("trial_select_subset", h4("Select subset:"),
choices = c("All trials", "Trials involving pregnant women", "Trials involving <18s", "Heterologous prime-boost trials", "Variant of concern"),
selected = "All trials",
multiple = FALSE),
tags$br(),
DT::dataTableOutput("trial_table", width="100%"),
tags$br(),
tags$b("Abbreviations:"),
tags$p(
"aAPC: artificial antigen presenting cell;
AZLB: Anhui Zhifei Longcom Biopharmaceutical;
BIBP: Beijing Institute of Biological Products;
BWBP: Beijing Wantai Biological Pharmacy;
CAMS: Chinese Academy of Medical Sciences;
CIGB: Center for Genetic Engineering and Biotechnology;
FBRI SRC VB: Federal Budgetary Research Institution State Research Center of Virology and Biotechnology;
KBP: Kentucky BioProcessing;
LV-SMENP-DC: vaccine comprising dendritic cells (DCs) modified with lentivirus (LV) vectors expressing 'SMENP' minigene;
NVSI: National Vaccine and Serum Institute;
ODIR: Organization of Defensive Innovation and Research;
PLA-AMS: People's Liberation Army Academy of Military Science;
SGMI: Shenzhen Geno-Immune Medical Institute;
STRC: Scientific and Technological Research Council of Turkey;
WIBP: Wuhan Institute of Biological Products.", style="font-size:13px;"),
tags$br(),
downloadButton("downloadCsv", "Download data", class="download_button"),
tags$br(),tags$br()
),
######################
### TRIAL MAP PAGE ###
######################
tabPanel("Trial map",
div(class="outer",
tags$head(includeCSS("styles.css")),
leafletOutput("efficacy_map", width="100%", height="100%"),
absolutePanel(id = "controls", class = "panel panel-default",
top = 75, left = 55, width = 260, fixed=TRUE,
draggable = TRUE, height = "auto",
actionButton('plotBtn', HTML('<i class="fa fa-bars fa"></i>'), "class"='btn btn-link btn-sm', "data-toggle"='collapse',
"data-target"="#controls_collapse"),
tags$div(id = 'controls_collapse', class = "collapse in",
tags$i("Phase III trials with N >1000 registered up to",tags$b("07 January 2022"),"are included."), tags$br(),
pickerInput("mapper_vaccine_select", h4("Select vaccine:"),
choices = as.character(unique(trials$Vaccine)),
selected = as.character(unique(trials$Vaccine))[1],
multiple = FALSE),
pickerInput("mapper_location_select", h4("Selection location:"),
choices = as.character(unique(trials$Location[trials$Trial==trials$Trial[1]])),
selected = as.character(trials$Location[1]),
multiple = FALSE),
strong("Protocol:"),htmlOutput("mapper_trial_number", inline = T), tags$br(),
strong("Target N (total):"),textOutput("mapper_trial_n", inline = T), tags$br(),
strong("N doses:"),textOutput("mapper_trial_n_doses", inline = T), tags$br(),
strong("Status:"),htmlOutput("mapper_country_status", inline=T), tags$br(),
strong("Start date:"),textOutput("mapper_trial_start_date", inline=T), tags$br(),
htmlOutput("mapper_trial_status", inline = T),
htmlOutput("mapper_status_update_date", inline = T),
tags$br(),
em("Case counts (rolling 7-day average):"),
plotOutput("mapper_country_plot", height="180px"),
a("Source for case counts", href="https://vac-lshtm.shinyapps.io/ncov_tracker/", target="_blank")
)
)
)
),
##########################
### LIVING REVIEW PAGE ###
##########################
tabPanel("Living review",
sidebarLayout(
sidebarPanel(width = 3,
pickerInput("select_phase", "Primary outcome:",
choices = as.character(c("Immunogenicity", "Efficacy")),
options = list(`actions-box` = TRUE),
selected = "Efficacy",
multiple = FALSE),
pickerInput("select_trial", "Trial:",
choices = as.character(subset(db, Phasegroup=="Efficacy")$Identifier),
options = list(`actions-box` = TRUE),
selected = as.character(subset(db, Phasegroup=="Efficacy")$Identifier)[1],
multiple = FALSE),
tags$strong("Developer(s):"), htmlOutput("trial_developer"), tags$br(),
tags$strong("Vaccine:"), textOutput("trial_vaccine"), tags$br(),
tags$strong("Platform:"), textOutput("trial_platform"), tags$br(),
tags$strong("Phase:"), textOutput("trial_phase", inline = T), tags$br(), tags$br(),
strong("Number(s):"),htmlOutput("trial_number"), tags$br(),
strong("Location(s):"),textOutput("trial_location"), tags$br(),
strong("Primary report:"),htmlOutput("trial_report"), tags$br(),
strong("Publication date:"),textOutput("trial_publication_date"), tags$br()
),
mainPanel(
tabsetPanel(
tabPanel("Methods",
tags$br(),
"The site is no longer updated. The last update was carried out on 11th August 2022.",tags$br(),tags$br(),
tags$h4("Approach"),
"This living review summarises available clinical trial data (phase I to phase III) on different COVID-19 vaccine candidates.
Between 24 August 2020 and 11 August 2022, we performed weekly (up to September 2021) or monthly (September 2021 onwards) searches of",strong(em("medRxiv")),"and",strong("PubMed"),
"(see", tags$b("Search log"),"below) using the R packages",em("medrxivr"),"and",em("easyPubMed."),
"Titles and abstracts were screened to identify articles reporting outcome data from human clinical trials of COVID-19 vaccine candidates.",
"Additional preprints were identified using the", tags$a(href="https://www.who.int/publications/m/item/draft-landscape-of-covid-19-candidate-vaccines", "WHO COVID-19 vaccine landscape.", target="_blank"),
tags$br(),tags$br(),
tags$h4("Search term"),
tags$em('"(coronavirus OR COVID OR SARS*) AND vaccin* AND (trial OR phase)"'),
tags$br(),tags$br(),
tags$h4("Data extraction"),
"We extracted data on the following study attributes:",
tags$ul(
tags$li(strong("Design:"),"location, number and age of individuals enrolled, vaccine dose, etc."),
tags$li(strong("Safety profile:"),"serious adverse events as well as non-serious adverse events with ≥25% prevalence in one or more study groups."),
tags$li(strong("Immunogenicity:"),"pre- and post-vaccination levels of antigen-specific IgG (ELISA), neutralising antibody levels against live SARS-CoV-2 and/or pseudoviruses, and/or T-cell responses.
We present antibody and T-cell outcomes 28 days post-vaccination or the nearest available timepoint."),
tags$li(strong("Efficacy:"),"protective efficacy against COVID-19, severe COVID-19, and/or asymptomatic SARS-CoV-2 infection.
Where available, we present the profile (age, ethnicity, and comorbidity prevalence) of the study population, as well as vaccine efficacy
estimates stratified by relevant covariates (dose regimen, age group, ethnicity, and presence of comorbidities)."),
tags$li(strong("Planned next steps"),"for clinical testing and/or manufacture. See",strong("Implementation"),"tab for additional details.")
),
"Data extraction was performed for all peer-reviewed manuscripts. Links are provided to all preprints.",
tags$br(),tags$br(),
tags$h4("Protocol update"),
"Data extraction was performed for all eligible peer-reviewed manuscripts published up until 31st May 2021 and all efficacy studies published up until 30th June 2021.",
tags$br(),tags$br(),
"New articles published between 1st July 2021 and 11th August 2022 are summarised in the table below, but full data extraction was not performed.",
tags$br(),tags$br(),
tags$h4("Eligible studies"),
"Total number of studies included: ", living_review_study_count,
DT::dataTableOutput("eligible_studies", width="100%"),
tags$br(),
tags$b("Abbreviations:"),
tags$p("AZLB: Anhui Zhifei Longcom Biopharmaceutical; BIBP: Beijing Institute of Biological Products; BWBP: Beijing Wantai Biological Pharmacy Enterprise; CAMS: Chinese Academy of Medical Sciences; GPO: Government Pharmaceutical Organization; IIBR: Israel Institute for Biological Research; nr: non-replicating; IVAC, Institute of Vaccines and Medical Biologicals; r: replicating; RIBSP: Research Institute for Biological Safety Problems; WIBP: Wuhan Institute of Biological Products."), #, style="font-size:13px;"
tags$b("Notes:"),
tags$p("Phase I and phase II data extracted separately for WIBP inactivated vaccine (Xia; JAMA 2020), BBIBP-CorV (Xia; Lancet Infect Dis 2020), Sinovac CoronaVac (Zhang; Lancet Infect Dis 2020), AZLB ZF2001 (Yang; Lancet Infect Dis 2021), and Shenzhen Kangtai KCONVAC (Pan; Chin Med J 2021)."),
tags$br(),
tags$h4("Search log"),
plotlyOutput("search_log", width="100%"),
tags$br(), tags$br()
),
tabPanel("Results",
tags$br(),
tags$h4("Description of vaccine"),
htmlOutput("trial_vaccine_description"),
tags$br(),tags$h4("Trial attributes"),
DT::dataTableOutput("trial_attributes", width="100%"),
conditionalPanel("input.select_phase == 'Efficacy'",
tags$br(),tags$h4("Vaccine efficacy"),
tags$em("We present protective efficacy against symptomatic COVID-19, severe COVID-19, and/or asymptomatic SARS-CoV-2 infection."),
tags$br(),tags$br(),
htmlOutput("efficacy_endpoint_primary", inline = T),
htmlOutput("efficacy_endpoint_asymptomatic", inline = T),
htmlOutput("efficacy_endpoint_severe", inline = T),
tags$br(),
tabsetPanel(
tabPanel("Plot",
tags$br(),
plotOutput("outcome_plot_efficacy", width = "900px", height = "auto"),
tags$br()),
tabPanel("Table",
fluidPage(style = "font-size: 85%; padding: 0px 0px; margin: 0%", DT::dataTableOutput("efficacy_table", width="100%")),
tags$br()
),
tabPanel("Population profile",
DT::dataTableOutput("efficacy_population", width="100%"),
tags$br()
)
),
htmlOutput("efficacy_table_legend", inline = T),
tags$br()
),
tags$br(),tags$h4("Safety profile"),
tags$em("We present data on any",tags$strong("serious adverse events"),"(potentially life-threatening: requires assessment in A&E or hospitalisation) and",
tags$strong("common adverse events"),"(≥25% prevalence in one or more study groups) relating to the test vaccine."),
tags$br(),tags$br(),
tags$strong("Serious adverse events:"),tags$br(),
textOutput("saes"),tags$br(),
tags$strong("Common adverse events (local):"),
htmlOutput("localaes"),tags$br(),
tags$strong("Common adverse events (systemic):"),
htmlOutput("systemicaes"),
htmlOutput("safetyissue"),
tags$br(),tags$br(),
conditionalPanel("input.select_phase == 'Immunogenicity' |
input.select_trial == 'Wuhan-Sinopharm/Beijing-Sinopharm phase III' |
input.select_trial == 'BioNTech BNT162 phase III (report 2 - adolescents; Frenck Jr 2021)' |
input.select_trial == 'Gamaleya Gam-COVID-Vac phase III' |
input.select_trial == 'Oxford ChAdOx1 phase III (report 2; Voysey 2021)' |
input.select_trial == 'Oxford ChAdOx1 phase I/II (report 3 - South Africa; Madhi 2021)' |
input.select_trial == 'Oxford ChAdOx1 phase II/III (report 4 - B.1.1.7; Emary 2021)'",
tags$h4("Antibody response"),
tags$em("We present antibody levels measured 28 days post-vaccination or the nearest available timepoint.
Where multiple types of antibody were measured, we prioritise (i) antigen-specific ELISA (IgG);
(ii) neutralisation of live SARS-CoV-2; and (iii) neutralisation of a pseudovirus modified to express SARS-CoV-2 antigens."),
tags$br(),tags$br(),
pickerInput("select_outcome", "Select outcome:",
choices = as.character(outcome_list),
options = list(`actions-box` = TRUE),
selected = outcome_list[1],
multiple = FALSE),
htmlOutput("outcome_assay", inline = T),
htmlOutput("outcome_timing", inline = T),
htmlOutput("outcome_units", inline = T),
htmlOutput("outcome_binary", inline = T),
htmlOutput("outcome_extraction_flag", inline = T),
htmlOutput("outcome_small_group_flag", inline = T),
tags$br(),
conditionalPanel("input.select_outcome != 'Not applicable'",
tabsetPanel(
tabPanel("Plot", plotOutput("outcome_plot", height = "350px")),
tabPanel("Table",
DT::dataTableOutput("immunogenicity_table", width="100%"),
tags$br()
)
)
),
tags$br(),tags$h4("T cell response"),
pickerInput("select_outcome_T", "Select outcome:",
choices = as.character(outcome_list_T),
options = list(`actions-box` = TRUE),
selected = outcome_list_T[1],
multiple = FALSE),
htmlOutput("outcome_assay_T", inline = T),
htmlOutput("outcome_timing_T", inline = T),
htmlOutput("outcome_units_T", inline = T),
htmlOutput("outcome_binary_T", inline = T),
htmlOutput("outcome_extraction_flag_T", inline = T),
htmlOutput("outcome_small_group_flag_T", inline = T),
tags$br(),
conditionalPanel("input.select_outcome_T != 'Not applicable'",
tabsetPanel(
tabPanel("Plot", plotOutput("outcome_plot_T", height = "350px")),
tabPanel("Table",
DT::dataTableOutput("immunogenicity_table_T", width="100%"),
tags$br()
)
)
),
htmlOutput("outcome_Th1_Th2", inline = T),
conditionalPanel("input.select_outcome_subgroup != 'Not applicable'",
tags$br(),
tags$h4("Subgroup analysis"),
htmlOutput("subgroup_text", inline = T),
pickerInput("select_outcome_subgroup", "Select outcome:",
choices = as.character(outcome_list_subgroup),
options = list(`actions-box` = TRUE),
selected = outcome_list_subgroup[1],
multiple = FALSE),
htmlOutput("outcome_assay_subgroup", inline = T),
htmlOutput("outcome_timing_subgroup", inline = T),
htmlOutput("outcome_units_subgroup", inline = T),
htmlOutput("outcome_binary_subgroup", inline = T),
DT::dataTableOutput("subgroup_table", width="100%"),
htmlOutput("subgroup_conclusion", inline = T),
tags$br()
)
),
htmlOutput("other_cofactors", inline = T),
htmlOutput("other_endpoints"),
tags$br(),tags$h4("Next steps"),
htmlOutput("trial_next_steps"),
tags$br(),tags$br()
)
)
)
)
),
###########################
### IMPLEMENTATION PAGE ###
###########################
tabPanel("Implementation",
"The site is no longer updated. The last update was carried out on 11th August 2022.",tags$br(),tags$br(),
h4("Equity of vaccine roll-out"),
"Vaccines against COVID-19 are now being rolled out across the globe. However, we are falling considerably short of achieving equitable global distribution.
In the plot below, each circle represents a country, with circle size corresponding to population size. Hover over the circles for additional details.",
tags$br(),tags$br(),
sidebarLayout(
sidebarPanel(width = 3,
pickerInput("equity_outcome", h5("Select outcome:"),
choices = c("% vaccinated with at least 1 dose", "% vaccinated with full primary series", "Total vaccines per hundred people"), # "Total vaccines"
selected = c("% vaccinated with full primary series"),
multiple = FALSE),
checkboxGroupInput(inputId = "equity_group",
label = h5("Select income group:"),
choices = c("High income" = "hic",
"Upper middle income" = "umic",
"Lower middle income" = "lmic",
"Low income" = "lic"),
selected = c("hic", "umic", "lmic", "lic")),
sliderTextInput("equity_date",
label = h5("Select date:"),
choices = format(unique(equity_slider), "%d %b %y"),
selected = format(max(equity_slider), "%d %b %y"),
grid = TRUE,
animate=animationOptions(interval = 1200, loop = FALSE))
),
mainPanel(
h4(textOutput("equity_date_clean",inline = T),"-",textOutput("equity_sum",inline = T),"billion doses of vaccine given worldwide"),
plotlyOutput("equity_plot", height="400px", width="700px")
)
),
"Source for vaccine roll-out data:", a("Our World in Data.", href="https://ourworldindata.org/covid-vaccinations", target="_blank"),
"Source for income data:", a("Gapminder.", href="https://www.gapminder.org/tools/", target="_blank"),
"Source for income group data:", a("World Bank.", href="https://data.worldbank.org", target="_blank"),
tags$br(),tags$br(),
h4("Testing and implementation status of vaccines authorised for limited or full use as of 11th August 2022"),
tags$br(),
plotOutput("summary_matrix", height="900px", width="800px"),
tags$br(),
"Abbreviations: AZLB, Anhui Zhifei Longcom Biopharmaceutical;
CAMS, Chinese Academy of Medical Sciences;
CIGB, Center for Genetic Engineering and Biotechnology;
IMB, Institute of Medical Biology;
nr, non-replicating;
NVSI, National Vaccine and Serum Institute;
ODIR, Organization of Defensive/Innovation and Research;
RIBSP, Research Institute for Biological Safety Problems;
VLP, virus-like particle.
Candidates approved for widespread use in one or more countries are included.
Source for N countries reporting use: ",a("Our World in Data.", href="https://ourworldindata.org/covid-vaccinations", target="_blank"),
tags$br(), tags$br()
),
#################
### FAQs PAGE ###
#################
tabPanel("FAQs",
tags$h4("What is a clinical trial?"),
"Clinical trials are research studies that are used to determine if a new vaccine is safe and effective. In our",
a("animated video on clinical trials", href="https://www.youtube.com/watch?v=G49UhCumWOc", target="_blank"),
"below, we describe the four phases of vaccine clinical trials and the steps it takes to license a vaccine.",
tags$ul(
tags$li(tags$b("Phase I"), "is an initial trial with a small group of healthy volunteers and usually takes a few months."),
tags$li(tags$b("Phase II"), "examines consistency of the vaccine, any potential side effects and the presence of immune response expected. This phase can last several months."),
tags$li(tags$b("Phase III"), "gathers robust data on safety and efficacy and can last several years as it usually involves thousands of volunteers."),
tags$li(tags$b("Phase IV"), "occurs after the vaccine is licenced and used in the public. This phase continues for as long as the vaccine is being used in the community and monitors the vaccine’s benefits and any side effects.")
),
tags$br(),
tags$p(HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/G49UhCumWOc" frameborder="0" allowFullScreen="allowFullScreen"></iframe>'), align="center"),
tags$br(),tags$h4("What's in a vaccine?"),
tags$b("Each ingredient in every vaccine is present for a very specific purpose and our"),
a("animated video on vaccines", href="https://www.youtube.com/watch?v=LQKI5SuqtXk&feature=youtu.be", target="_blank"),
"below explores what goes into a vaccine and why.",
tags$br(), tags$br(),
"The main ingredient in any vaccine is the antigen, which is a small part of the virus or bacterium being targeted.",
"The antigen is the ingredient in the vaccine that challenges our immune system to generate the right defences.",
"Some vaccines add an adjuvant to the antigen to help strengthen and lengthen your body’s immune response.",
"Stabilisers are used to help the active ingredients to remain effective while the vaccine is made, stored, and moved.",
"Antibiotics and preservatives are sometimes used in the manufacturing process of some vaccines however these elements aren’t in the final vaccine.",
"The patient information leaflet that comes with every vaccine tells you exactly what was used in making the vaccine, what is still in it and how much is in the final product.",
tags$br(),tags$br(),
tags$p(HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/LQKI5SuqtXk" frameborder="0" allowFullScreen="allowFullScreen"></iframe>'), align="center"),
tags$br(),
tags$h4("How do we know that vaccines are safe?"),
"How safe are vaccines? How do we know that vaccines are safe? Our",
a("animated video on vaccine safety", href="https://www.youtube.com/watch?v=owFT2e8h7lw", target="_blank"),
"below explores the safety measures in place throughout the entire vaccine development process, from the four clinical trial phases and through to the use of vaccines in the community.",
tags$br(),tags$br(),
tags$p(HTML('<iframe width="560" height="315" src="https://www.youtube.com/embed/owFT2e8h7lw" frameborder="0" allowFullScreen="allowFullScreen"></iframe>'), align="center"),
tags$br(),
tags$h4("What are the different types of vaccine?"),
"All vaccines expose our immune system to antigens from a specific pathogen, but they do this in a variety of ways.",
"A summary of the key vaccine types being developed for COVID-19 is provided in the table below.",
tags$br(),
DT::dataTableOutput("vaccine_types", width="100%"),
tags$br(),
"For more information, please visit the",a("Vaccine Centre's full FAQs page.", href="https://www.lshtm.ac.uk/research/centres/vaccine-centre/vaccine-faqs", target="_blank"),
tags$br(),tags$br()
)
)
)
### server -------------------------------------------------------------------------------------
server <- function(input, output, session) {
######################
### LANDSCAPE PAGE ###
######################
# reactive timeline dataframe
reactive_timeline = reactive({
if ("term" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Terminated") }
if ("preclin" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Pre-clinical") }
if ("phasei" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Phase I") }
if ("phasei_ii" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Phase I/II") }
if ("phaseii" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Phase II") }
if ("phaseiii" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Phase III" & stage!="Phase II/III") }
if ("phaseiv" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Phase IV") }
if ("phaseheterol" %in% input$stage==FALSE) { timeline = subset(timeline, stage!="Heterologous") }
if ("not_in_use" %in% input$in_use==FALSE) { timeline = subset(timeline, use!="No") }
if ("in_use" %in% input$in_use==FALSE) { timeline = subset(timeline, use!="Yes") }
# remove publication filter as no longer updated from Feb 2022
# if ("pub_available" %in% input$pub_paper==TRUE) { timeline = subset(timeline, pub=="yes") }
if ("rna" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="RNA") }
if ("dna" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="DNA") }
if ("nrvv" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Vector (non-replicating)") }
if ("rvv" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Vector (replicating)") }
if ("inact" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Inactivated") }
if ("live" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Live-attenuated") }
if ("ps" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Protein subunit") }
if ("vlp" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Virus-like particle") }
if ("unknown" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Other/Unknown") }
if ("heterol" %in% input$vacc==FALSE) { timeline = subset(timeline, subgroup!="Heterologous") }
timeline
})
# dataframe with one row per candidate
reactive_groups = reactive({
groups_df[groups_df$id %in% reactive_timeline()$group,]
})
# timeline plot for selected groups
output$vaccine_timeline <- renderTimevis({
timevis(reactive_timeline() %>% select(-c(stage)),
groups = reactive_groups()) %>%
setWindow("2019-10-01", "2021-12-31")
})
# summary figure of landscape
output$summary_plot <- renderPlot({ summary_plot })
############################
### CLINICAL TRIALS PAGE ###
############################
# clinical trials database
output$trial_table <- DT::renderDataTable({
table = fread("input_data/VaC_LSHTM_trials.csv")
table$`Start date` = as.Date(table$`Start date`, format="%d/%m/%Y")
table$`Primary completion date` = as.Date(table$`Primary completion date`, format="%d/%m/%Y")
table$`Trial number` = paste0("<a href=",table$Link,' target="_blank">',table$`Trial number`,"</a>")
if (input$trial_select_subset=="All trials") { table_selected = table }
if (input$trial_select_subset=="Trials involving pregnant women") { table_selected = subset(table, Pregnancy==1) }
if (input$trial_select_subset=="Trials involving <18s") { table_selected = subset(table, Children==1) }
if (input$trial_select_subset=="Heterologous prime-boost trials") { table_selected = subset(table, `Heterologous prime boost`==1) }
if (input$trial_select_subset=="Variant of concern") { table_selected = subset(table, `Variant of concern`==1) }
DT::datatable(table_selected %>% select(-c(Institutes, Name, Link, Pregnancy, Children, `Heterologous prime boost`, `Variant of concern`, Multiple)), rownames=F, escape = FALSE,
options = list(ordering=T, pageLength = 20,
lengthMenu = c(20, 40, 60))) %>%
formatStyle(columns = c(1:13), fontSize = '80%') %>%
formatCurrency('N',currency = "", interval = 3, mark = ",", digits=0) %>%
formatDate(columns = c("Start date", "Primary completion date"), method = "toLocaleDateString",
params = list('en-GB'))
})
# download button
output$downloadCsv <- downloadHandler(
filename = function() { paste0("VaC_LSHTM_Covid_vaccine_trials_",str_replace_all(update_full, " ", ""),".xlsx") },
content = function(file) {
write_xlsx(fread("input_data/VaC_LSHTM_trials.csv") %>% select(-c(Link, Name, Pregnancy, Children, `Heterologous prime boost`, `Variant of concern`)), file)
}
)
#########################
### EFFICACY MAP PAGE ###
#########################
# updates when new vaccine selected
mapper_reactive_db = reactive({
trials %>% filter(Vaccine == input$mapper_vaccine_select)
})
observeEvent(input$mapper_vaccine_select, {
updatePickerInput(session = session, inputId = "mapper_location_select",
choices = as.character(unique(mapper_reactive_db()$Location)), selected = as.character(mapper_reactive_db()$Location[1]))
})
observeEvent(input$mapper_vaccine_select, {
output$mapper_trial_vaccine <- renderText({ as.character(mapper_reactive_db()$Vaccine[1]) })
output$mapper_trial_n <- renderText({ formatC(mapper_reactive_db()$N[1],big.mark=",") })
output$mapper_trial_n_doses <- renderText({ as.character(mapper_reactive_db()$N_doses[1]) })
output$mapper_trial_platform <- renderText({ as.character(mapper_reactive_db()$Platform[1]) })
output$mapper_trial_number <- renderUI({ HTML("<a href=",as.character(mapper_reactive_db()$Link[1]),'" target="_blank">',as.character(mapper_reactive_db()$Trial_number[1]),"</a>") })
output$mapper_trial_start_date <- renderText({ format(as.Date(mapper_reactive_db()$Start_date[1],"%d/%m/%Y"),"%d %b %Y") })
output$mapper_country_status <- renderUI({
if (mapper_reactive_db()$Location_status[1]=="Active/recruiting") {
HTML("<em><span style=\"color:green\">Active/recruiting</span></em>")
} else if (mapper_reactive_db()$Location_status[1]=="Recruiting") {
HTML("<em><span style=\"color:green\">Recruiting</span></em>")
} else if (mapper_reactive_db()$Location_status[1]=="Active, not recruiting") {
HTML("<em><span style=\"color:green\">Active, not recruiting</span></em>")
} else if (mapper_reactive_db()$Location_status[1]=="Suspended") {
HTML("<em><span style=\"color:orange\">Suspended</span></em>")
} else { HTML("<em><span style=\"color:orange\">Not yet recruiting</span></em>") }
})
output$mapper_trial_status <- renderUI({
if (mapper_reactive_db()$N_enrolled[1]=="Unknown") { return(NULL) } else {
HTML("<strong>Progress: </strong><a href=",as.character(mapper_reactive_db()$Update_link[1]),'" target="_blank">',as.character(mapper_reactive_db()$N_enrolled[1]),"</a><br>")
}
})
output$mapper_status_update_date <- renderUI({
if (is.na(mapper_reactive_db()$Update_date[1])) { return(NULL) } else {
HTML(paste0("<strong>Status date: </strong>",format(as.Date(mapper_reactive_db()$Update_date[1],"%d/%m/%Y"),"%d %b %Y"),"<br>")) }
})
output$mapper_country_plot <- renderPlot({
country_select = as.character(mapper_reactive_db()$Location_clean[1])
start_date = as.Date(mapper_reactive_db()$Start_date[1],"%d/%m/%y")
plot_start = as.Date("01/05/2020", "%d/%m/%y")
plot_df_new = subset(cv_cases, date>=plot_start & country==country_select)
grad_df <- data.frame(yintercept = seq(0,200, length.out = 200), alpha = c(seq(0.2, 0, length.out = 150), rep(0,50)))
ggplot(plot_df_new, aes(x = date, y = rolling7permill)) +
geom_area(fill = covid_col, alpha = 0.7) +
geom_hline(data = grad_df, aes(yintercept = yintercept, alpha = alpha), size = 1, colour = "white") +
geom_line(arrow = arrow(length=unit(0.20,"cm"), ends="last", type = "closed"), size=0.5, colour = covid_col) +
ylab("cases per million") + theme_bw() + ylim(0,1500) +
theme(legend.title = element_blank(), panel.grid.major = element_blank(), legend.position = "", plot.title = element_text(size=10),
plot.margin = margin(5, 12, 5, 5)) + theme(text = element_text(size=13)) +
scale_x_date(labels = date_format("%b %y"))
}, res = 80)
# map updates
recruiting_countries = subset(mapper_reactive_db(), Location_status=="Active/recruiting")
recruiting_countries = recruiting_countries[order(recruiting_countries$alpha3),]
plot_map_layer_1 <- worldcountry[worldcountry$ADM0_A3 %in% recruiting_countries$alpha3[1], ]
if (nrow(recruiting_countries)>1) {
for (i in 2:nrow(recruiting_countries)) {
plot_map_layer_1 = rbind(plot_map_layer_1, worldcountry[worldcountry$ADM0_A3 %in% recruiting_countries$alpha3[i], ])
}
}
pending_countries = subset(mapper_reactive_db(), Location_status=="Not yet recruiting")
pending_countries = pending_countries[order(pending_countries$alpha3),]
plot_map_layer_2 <- worldcountry[worldcountry$ADM0_A3 %in% pending_countries$alpha3[1], ]
if (nrow(pending_countries)>1) {
for (i in 2:nrow(pending_countries)) {
plot_map_layer_2 = rbind(plot_map_layer_2, worldcountry[worldcountry$ADM0_A3 %in% pending_countries$alpha3[i], ])
}
}
basemap_update = leafletProxy("efficacy_map") %>%
clearMarkers() %>% clearShapes()
if (nrow(pending_countries)>0) {
basemap_update = basemap_update %>%
addPolygons(data = plot_map_layer_2, smoothFactor = 0.1, fillOpacity = 0.2, fillColor = planned_col,
group = 'Not yet recruiting', weight = 1, color = planned_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", pending_countries$Location, pending_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = planned_col),
textsize = "15px", direction = "auto")) %>%
addCircleMarkers(data = pending_countries, lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 0.5, color = planned_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", pending_countries$Location, pending_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = planned_col),
textsize = "15px", direction = "auto"))
}
if (nrow(recruiting_countries)>0) {
basemap_update = basemap_update %>%
addPolygons(data = plot_map_layer_1, smoothFactor = 0.1, fillOpacity = 0.2, fillColor = active_col,
group = 'Active/recruiting', weight = 1, color = active_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", recruiting_countries$Location, recruiting_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = active_col),
textsize = "15px", direction = "auto")) %>%
addCircleMarkers(data = recruiting_countries, lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 0.5, color = active_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", recruiting_countries$Location, recruiting_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = active_col),
textsize = "15px", direction = "auto"))
}
basemap_update = basemap_update %>%
addCircleMarkers(data = mapper_reactive_db()[1,], lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 1, color = ~status_pal(Location_status),
label = sprintf("<strong>%s: </strong><i>%s</i>", mapper_reactive_db()$Location[1], mapper_reactive_db()$Location_status[1]) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = ~status_pal(Location_status)),
textsize = "15px", direction = "auto"))
})
# updates when new location selected
mapper_reactive_db_country = reactive({
mapper_reactive_db() %>% filter(Location == input$mapper_location_select)
})
observeEvent(input$mapper_location_select, {
output$mapper_trial_vaccine <- renderText({ as.character(mapper_reactive_db_country()$Vaccine[1]) })
output$mapper_trial_n <- renderText({ formatC(mapper_reactive_db_country()$N[1],big.mark=",") })
output$mapper_trial_n_doses <- renderText({ as.character(mapper_reactive_db_country()$N_doses[1]) })
output$mapper_trial_platform <- renderText({ as.character(mapper_reactive_db_country()$Platform[1]) })
output$mapper_trial_number <- renderUI({ HTML("<a href=",as.character(mapper_reactive_db_country()$Link[1]),'" target="_blank">',as.character(mapper_reactive_db_country()$Trial_number[1]),"</a>") })
output$mapper_trial_start_date <- renderText({ format(as.Date(mapper_reactive_db_country()$Start_date[1],"%d/%m/%Y"),"%d %b %Y") })
output$mapper_country_status <- renderUI({
if (mapper_reactive_db_country()$Location_status[1]=="Recruiting") {
HTML("<em><span style=\"color:green\">Recruiting</span></em>")
} else if (mapper_reactive_db_country()$Location_status[1]=="Active, not recruiting") {
HTML("<em><span style=\"color:green\">Active, not recruiting</span></em>")
} else if (mapper_reactive_db_country()$Location_status[1]=="Active/recruiting") {
HTML("<em><span style=\"color:green\">Active/recruiting</span></em>")
} else if (mapper_reactive_db_country()$Location_status[1]=="Suspended") {
HTML("<em><span style=\"color:orange\">Suspended</span></em>")
} else { HTML("<em><span style=\"color:orange\">Not yet recruiting</span></em>") }
})
output$mapper_trial_status <- renderUI({
if (mapper_reactive_db_country()$N_enrolled[1]=="Unknown") { return(NULL) } else {
HTML("<strong>Progress: </strong><a href=",as.character(mapper_reactive_db_country()$Update_link[1]),'" target="_blank">',as.character(mapper_reactive_db_country()$N_enrolled[1]),"</a><br>")
}
})
output$mapper_status_update_date <- renderUI({
if (is.na(mapper_reactive_db_country()$Update_date[1])) { return(NULL) } else {
HTML(paste0("<strong>Status date: </strong>",format(as.Date(mapper_reactive_db_country()$Update_date[1],"%d/%m/%Y"),"%d %b %Y"),"<br>")) }
})
output$mapper_country_plot <- renderPlot({
country_select = as.character(mapper_reactive_db_country()$Location_clean[1])
if (is.na(mapper_reactive_db_country()$Start_date[1])) { start_date = as.Date("01/09/2020", "%d/%m/%Y") } else {
start_date = as.Date(mapper_reactive_db_country()$Start_date[1],"%d/%m/%Y")
}
plot_start = as.Date("01/05/2020", "%d/%m/%y")
plot_df_new = subset(cv_cases, date>=plot_start & country==country_select)
grad_df <- data.frame(yintercept = seq(0,200, length.out = 200), alpha = c(seq(0.2, 0, length.out = 150), rep(0,50)))
g1 = ggplot(plot_df_new, aes(x = date, y = rolling7permill)) +
geom_area(fill = covid_col, alpha = 0.7) +
geom_hline(data = grad_df, aes(yintercept = yintercept, alpha = alpha), size = 1, colour = "white") +
geom_line(arrow = arrow(length=unit(0.20,"cm"), ends="last", type = "closed"), size=0.5, colour = covid_col) +
ylab("cases per million") + theme_bw() + ylim(0,1500) +
theme(legend.title = element_blank(), panel.grid.major = element_blank(), legend.position = "", plot.title = element_text(size=10),
plot.margin = margin(5, 12, 5, 5)) + theme(text = element_text(size=13)) +
scale_x_date(labels = date_format("%b %y"))
if (is.na(mapper_reactive_db_country()$Start_date[1])) { g1 } else {
g1 + geom_vline(xintercept=start_date, size=0.5, colour=active_col) +
annotate("segment", x = start_date, xend = start_date+25, y = 1000, yend = 1000, colour = active_col, size = 0.5, alpha=1, arrow=arrow(length=unit(0.20,"cm"), type = "closed")) +
annotate("text", x = start_date+10, y = 1150, label = c("start date") , color= active_col, size=4, fontface="italic", hjust = 0)
}
}, res = 80)
})
output$efficacy_map <- renderLeaflet({
basemap
})
# updates to map when selecting new location
observeEvent(input$mapper_location_select, {
basemap_update = leafletProxy("efficacy_map") %>% clearMarkers()
# create paramters for active trials layer
trial_layer = mapper_reactive_db()
recruiting_countries = subset(trial_layer, Location_status=="Active/recruiting")
pending_countries = subset(trial_layer, Location_status=="Not yet recruiting")
if (nrow(pending_countries)>0) {
basemap_update = basemap_update %>%
addCircleMarkers(data = pending_countries, lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 0.5, color = planned_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", pending_countries$Location, pending_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = planned_col),
textsize = "15px", direction = "auto"))
}
if (nrow(recruiting_countries)>0) {
basemap_update = basemap_update %>%
addCircleMarkers(data = recruiting_countries, lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 0.5, color = active_col,
label = sprintf("<strong>%s: </strong><i>%s</i>", recruiting_countries$Location, recruiting_countries$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px", "color" = active_col),
textsize = "15px", direction = "auto"))
}
basemap_update = basemap_update %>%
addCircleMarkers(data = mapper_reactive_db_country(), lat = ~ Latitude, lng = ~ Longitude, weight = 1,
fillOpacity = 1, color = ~status_pal(Location_status),
label = sprintf("<strong>%s: </strong><i>%s</i>", mapper_reactive_db_country()$Location, mapper_reactive_db_country()$Location_status) %>% lapply(htmltools::HTML),
labelOptions = labelOptions(