-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.R
1652 lines (1520 loc) · 98.2 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
library(shiny)
library(shinyjs)
library(gridExtra)
# Source helpers ----
source("helpers.R")
ui <- shinyUI(
bootstrapPage(
shinyjs::useShinyjs(),
title="Shiny-SoSV",
#fluidPage(
#list(tags$head(HTML('<link rel="icon", href="logo.png", type="image/png" />'))
#),
#tagList(
#tags$head(tags$script(type="text/javascript", src = "code.js")),
tags$style(HTML(".navbar-default .navbar-nav > li > a {color:black;}
.navbar-default .navbar-nav > .active > a,
.navbar-default .navbar-nav > .active > a:focus,
.navbar-default .navbar-nav > .active > a:hover {color: white;background-color: #337ab7; font-weight: bold;}
.navbar-default .navbar-nav > li > a:hover {color: white; background-color:#337ab7; font-weight: bold;}
")),
navbarPage(
title=div(img(src ="logo_hcpcgcolors_capSV.png",height= "56px", width = "99px", align = "left",style = "margin:-10px 0px")),
id = "Shiny-SoSV",
tabPanel(title = "Home",
value = "introduction",
fluidRow(column(width=10,offset=1,
img(src = "logo_hcpcgcolors_capSV.png",height="30%", width="30%",style = "display: block; margin-left: auto; margin-right: auto; margin-top: 0px; margin-bottom: -25px"),
#fluidRow(column(width = 5, offset = 2,
# img(src = "logo_hcpcgcolors_capSV.png",height="30%", width="30%",style = "display: block; margin-left: auto; margin-right: auto; margin-top: 0px; margin-bottom: -25px")),
# column(width = 2, offset = 8,
# img(src = "lablogo.png",height="30%", width="30%"))),
#h1("Shiny-SoSV", align = "center"),
h3("A web-based performance calculator for somatic structural variant detection", align = "center"),
h5("Shiny-SoSV provides an interactive and visual platform to explore the impact of different parameters on the performance to detect somatic structural variants from short-read whole genome sequencing.", align = "center"),
br(),
p("Somatic structural variants are an important contributor to cancer development and evolution. ",
"Accurate detection of these complex variants from whole genome sequencing data is influenced by a multitude of parameters. ",
"However, there are currently no tools for guiding study design nor are there applications that could predict the performance of somatic structural variant detection. ",
"To address this gap, we developed Shiny-SoSV, a user-friendly web-based calculator for determining the impact of common variables on the sensitivity, precision and F1 score of somatic structural variant detection, including choice of variant detection tool, sequencing depth of coverage, variant allele fraction, and variant breakpoint resolution. ",
"Using simulation studies, we determined singular and combinatoric effects of these variables, modelled the results using a generalised additive model, allowing structural variant detection performance to be predicted for any combination of predictors. ",
"Shiny-SoSV provides an interactive and visual platform for users to easily compare individual and combined impact of different parameters. ",
"It predicts the performance of a proposed study design, on somatic structural variant detection, prior to the commencement of benchwork. "),
p("If you use this web app, please cite:"),
p("Tingting Gong, Vanessa M Hayes, Eva KF Chan. Shiny-SoSV: A web app for interactive evaluation of somatic structural variant calls. BioRxiv 668723; doi:",
a("https://doi.org/10.1101/668723", href="https://doi.org/10.1101/668723")),
br(),
#h4("Shiny-SoSV can be access here"),
fluidRow(column(10,offset=5,actionButton('jumpToEvaluation', 'Launch Shiny-SoSV', #class = "btn-warning"
style="color: #fff; background-color: #337ab7; border-color: #2e6da4; font-size:100%; font-weight: bold"))),
#style="color: #fff; background-color: #337ab7; border-color: #2e6da4; padding:4px;font-size:100%; font-weight: bold"))),
#style="color: #000; padding:4px;font-size:100%"))),
br(),
br(),
br(),
actionButton('jumpToEvaluation_svtype', 'Shiny-SoSV type', style="color: #fff; background-color: #337ab7; border-color: #2e6da4; font-size:100%; font-weight: bold"),
p("Shiny-SoSV user interface for SV types."),
br(),
actionButton('jumpToInstallation', 'Installation', style="color: #fff; background-color: #337ab7; border-color: #2e6da4; font-size:100%; font-weight: bold"),
p("Detailed description of how to obtain and install your own copy of Shiny-SoSV."),
br(),
actionButton('jumpToUserGuide', 'User Guide', style="color: #fff; background-color: #337ab7; border-color: #2e6da4; font-size:100%; font-weight: bold"),
p("Explanation of Shiny-SoSV’s user interface."),
br(),
actionButton('jumpToUseCase', 'Example Use Cases', style="color: #fff; background-color: #337ab7; border-color: #2e6da4; font-size:100%; font-weight: bold"),
p("Hypothetical scenarios of highlighting the Shiny-SoSV’s utility.")))
),
tabPanel(shinyjs::useShinyjs(),title = "Shiny-SoSV", value = "evaluation",#tweaks,
sidebarLayout(fluid=TRUE,
sidebarPanel(checkboxGroupInput(inputId = "SVCaller3",
label = ("SV Caller(s)"),
choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
selected = "Manta", inline=TRUE),
checkboxGroupInput(inputId = "SVCaller3.1",
label = ("SV Callers Union"),
choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
selected = c(), inline=TRUE),
#selected = c("Manta","Lumpy"),inline=TRUE,width='400px'),
checkboxGroupInput(inputId = "SVCaller3.2",
label = ("SV Caller Intersection"),
choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
selected = c(), inline=TRUE),
sliderInput("VAF3", "Tumour purity/VAF:",
min = 0.05, max = 1, value = 0.5, step= 0.01),
checkboxGroupInput("VAF3.1",
label= NULL,
choices = c("0.2" = 0.2,"0.8"= 0.8),
selected = NULL),
sliderInput("T_coverage3", "Tumour coverage:",
min = 20, max = 100, value = 60, step = 0.1, post = "x"),
checkboxGroupInput("T_coverage3.1",
label= NULL,
choices = c("30x","60x"),
selected = NULL),
sliderInput("N_coverage3", "Normal coverage:",
min = 20, max = 100, value = 30, step = 0.1, post = "x"),
sliderInput("BND_threshold3", "Breakpoint precision threshold:",
min = 2, max = 200, value = 100, step= 1, post = "bp"),
width=3
),
mainPanel(checkboxGroupInput("measurements3",
label="Evaluation measurement(s)",
choices = list("Sensitivity","Precision","F1 score"),
selected = "Sensitivity",inline=TRUE),
radioButtons("X_axis3",
label="Evaluation across",
choices = c("Tumour purity/VAF" = "VAF","Tumour coverage" = "T_coverage","Normal coverage" = "N_coverage","Breakpoint precision threshold" = "BND_threshold"),
selected = "VAF",inline=TRUE),
textOutput("txtOutput3"),
radioButtons("type3",
label="SV type",
choices = c("Total" = "","Deletion" = "DEL","Duplication" = "DUP","Domestic insertion" = "DINS","Foreign insertion" = "FINS","Inversion" = "INV","Translocation" = "TRA"),
selected = "",inline=TRUE),
fluidRow(column(4,numericInput("objective3.1", label= "Your desired sensitivity", value = 0.7, min=0, max = 1, step = 0.1)),
column(4,numericInput("objective3.2", label= "Your desired precision", value = 0.7, min=0, max = 1, step = 0.1)),
column(4,numericInput("objective3.3", label= "Your desired F1 score", value = 0.7, min=0, max = 1, step = 0.1))),
plotOutput("Plot3.1"),
br(),
fluidRow(column(6,tableOutput('table3.1')),
column(6,tableOutput('table3.2'))),
plotOutput("Plot3.2"),
br(),
fluidRow(column(6,tableOutput('table3.3'))),
width=9))
),
tabPanel(shinyjs::useShinyjs(),title = "Shiny-SoSV type", value = "evaluation_svtype", #tweaks,
sidebarLayout(fluid=TRUE, sidebarPanel(
# radioButtons(inputId = "SVCaller2",
# label = ("SV Caller"),
# choiceNames = as.character(list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly ")),
# choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
# selected = "Manta", inline=TRUE),
radioButtons(inputId = "SVCallset",
label = ("Choose the SV call set"),
choiceNames = as.character(list("Individual ", "Union ", "Intersection ")),
choiceValues = c("", "Union", "Intersect"),
selected = "", inline=TRUE),
radioButtons(inputId = "SVCaller2.1",
label = ("SV caller"),
choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
selected = "Manta", inline=TRUE),
radioButtons(inputId = "SVCaller2.2",
label = ("Another SV caller to combine"),
choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
selected = "Manta", inline=TRUE),
textOutput("txtOutput2"),
#checkboxGroupInput(inputId = "SVCaller2",
# label = ("SV Caller(s)"),
# choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
# choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
# selected = "Manta", inline=TRUE),
#checkboxGroupInput(inputId = "SVCaller2.1",
# label = ("SV Callers Union"),
# choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
# choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
# selected = c(), inline=TRUE),
#selected = c("Manta","Lumpy"),inline=TRUE,width='400px'),
# checkboxGroupInput(inputId = "SVCaller2.2",
# label = ("SV Caller Intersection"),
# choiceNames = list("Manta ", "Lumpy ", "GRIDSS ", "SvABA ", "Delly "),
# choiceValues = c("Manta", "Lumpy", "GRIDSS", "SvABA", "Delly"),
# selected = c(), inline=TRUE),
sliderInput("VAF2", "Tumour purity/VAF:",
min = 0.2, max = 1, value = 0.5, step= 0.01),
checkboxGroupInput("VAF2.1",
label= NULL,
choices = c("0.2" = 0.2,"0.8"= 0.8),
selected = NULL),
sliderInput("T_coverage2", "Tumour coverage:",
min = 30, max = 100, value = 60, step = 0.1, post = "x"),
checkboxGroupInput("T_coverage2.1",
label= NULL,
choices = c("30x","60x"),
selected = NULL),
sliderInput("N_coverage2", "Normal coverage:",
min = 20, max = 100, value = 30, step = 0.1, post = "x"),
sliderInput("BND_threshold2", "Breakpoint precision threshold:",
min = 2, max = 200, value = 100, step= 1, post = "bp"),
width=3
),
mainPanel(checkboxGroupInput("type2",
label="SV type(s)",
choices = c("Deletion" = "DEL","Duplication" = "DUP","Domestic insertion" = "DINS","Foreign insertion" = "FINS","Inversion" = "INV","Translocation" = "TRA"),
selected = "DEL",inline=TRUE),
checkboxGroupInput("measurements2",
label = "Evaluation measurement(s)",
choices = list("Sensitivity","Precision","F1 score"),
selected = "Sensitivity",inline=TRUE),
radioButtons("X_axis2",
label="Evaluation across",
choices = c("Tumour purity/VAF" = "VAF","Tumour coverage" = "T_coverage","Normal coverage" = "N_coverage","Breakpoint precision threshold" = "BND_threshold"),
selected = "VAF",inline=TRUE),
fluidRow(column(4,numericInput("objective2.1", label= "Your desired sensitivity", value = 0.7, min=0, max = 1, step = 0.1)),
column(4,numericInput("objective2.2", label= "Your desired precision", value = 0.7, min=0, max = 1, step = 0.1)),
column(4,numericInput("objective2.3", label= "Your desired F1 score", value = 0.7, min=0, max = 1, step = 0.1))),
plotOutput("Plot2.1"),
br(),
fluidRow(column(6,tableOutput('table2.1')),
column(6,tableOutput('table2.2'))),
plotOutput("Plot2.2"),
br(),
fluidRow(column(6,tableOutput('table2.3'))),
width=9)
)
),
tabPanel(title = "Installation", value = "installation", fluidRow(column(width=10,offset=1,
h4("Direct Web Access"),
p("Shiny-SoSV is hosted on shinyapp.io. The easiest way to access Shiny-SoSV is via the direct URL,", em("https://hcpcg.shinyapps.io/Shiny-SoSV/.")),
#br(),
h4("Launching from the GitHub repository"),
p("Download R or RStudio and run the following commands once to set up the environment:"),
code("install.packages(c('shiny','shinyjs','ggplot2', 'gridExtra', 'ggsci'))"),
br(),
br(),
p("Run the shiny app with command in R:"),
code("library(shiny)"),
br(),
code("runGitHub('Shiny-SoSV', 'tgong1')"),
br(),
br(),
h4("GitHub"),
p("Souce code is available at the GitHub repository tgong1/Shiny-SoSV."),
p("To copy the repo to your local machine, use the command:"),
code("git clone https://github.com/tgong1/Shiny-SoSV.git"),
br(),
br(),
p("The data_SV and scripts_R folders of the repo contains all evaluation results and R script of prediction model fitting respectively underlying the web app."),
br(),
strong("Note to SV caller developers:"),
p("If you would like to include your SV caller in Shiny-SoSV, please get in touch. We would be able to provide you a copy of the simulated aligned bam files to run your software on!")))
),
tabPanel(title = "User Guide", value = "userguide",fluidRow(column(width=10,offset=1,
h4("Shiny-SoSV provides predictions of the impact of common variables (SV caller, sequencing coverage, tumour allele frequencies, tolerance of breakpoint precision) on the performance (sensitivity, precision and F1 score) of somatic SV calls through interactive plots. Please click on “Launch Shiny-SoSV” in Home page or “Shiny-SoSV” tab on top navigation panel for the main interface below:"),
#img(src = "UserGuide.png",height=925, width=1914),
#img(src = "UserGuide.png"),
img(src = "UserGuide.png",height="100%", width="100%"),
#img(src = "UserGuide.pdf",height="100%", width="100%"),
h5("Predictor variables to be examined and visualised: "),
h5("Checkboxes allow additional prediction lines to be added/removed from the plots."),
p("[1] SV Caller(s): One or more SV callers can be examined (distinguished by line colour in the plots). "),
p("[2] SV Callers Union: Union set of SV callers can be examined (distinguished by line colour in the plots). Union sets (A∪B sets) are SV calls identified by either caller A or caller B. Caller A is the “dominant caller” such that any overlapping calls in the final callset is taken from the output from caller A (including coordinates and SV types). "),
p("[3] SV Callers Intersection: Intersection set of SV callers can be examined (distinguished by line colour in the plots). Interaction sets (A∩B sets) are SV calls identified by BOTH A and B. Caller A is the “dominant caller” such that any overlapping calls in the final callset is taken from the output from caller A (including coordinates and SV types). "),
h5("Slider bars allow different values of the corresponding variable to be altered in the prediction. "),
p("[4] Tumour purity/VAF: Up to three values of this predictor can be visualised on the plots (distinguished by line type on the plots) evaluating across “Tumour coverage” [10]. Two of the values are preset to 0.2 and 0.8 (as checkboxes). The third can be any value between 0.05 and 1 (adjustable via the sliderbar) when “Total” [13] is selected, or between 0.2 and 1 when individual SV type is selected. When evaluating across “Normal coverage” [11] or “Breakpoint precision threshold” [12], only one VAF values can be elected, and this can be done via the sliderbar. When evaluating across “Tumour purity/VAF” [9], this option is disabled (greyed out). "),
p("[5] Tumour coverage: When evaluating across “Tumour purity/VAF” [9], “Normal coverage” [11] or “Breakpoint precision threshold” [12], three Tumour coverage values can be examined simultaneously, including two preset values of 30x and 60x and a third definable by the user via the slider bar between 20x to 100x when “Total” [13] selected or between 30x to 100x when individual SV type selected. When evaluating across “Tumour Coverage” [10], this option is disabled (greyed out)."),
p("[6] Normal coverage: Only one value can be evaluated at any one time. When evaluating across “Normal coverage” [11], this option is disabled."),
p("[7] Breakpoint precision threshold: Only one value can be evaluated at any one time. When evaluating across “Breakpoint precision threshold” [12], this option is disabled."),
br(),
h5("One of four predictors to be plotted on the x-axis using the “Evaluation across” radio button, including:"),
p("[9] “Tumour purity/VAF”: proportion of sequencing reads supporting the variant in the tumour sample. The minimum value available for overall and individual SV type performance estimation is 0 and 0.2 respectively."),
p("[10] “Tumour coverage”: the depth of sequencing coverage of the tumour sample. The minimum value available for overall and individual SV type performance estimation is 20x and 30x respectively. "),
p("[11] “Normal coverage”: the depth of sequencing coverage of the normal sample."),
p("[12] “Breakpoint precision threshold”: the precision of the breakpoint calls in nucleotide units."),
h5("SVs are broadly classified into six types. Performance measures can be estimated for:"),
p("[13] “Total”: all SV types aggregated in one call set."),
p("[14] “Deletion”: the SV event of a DNA segment removal from the genome."),
p("[15] “Duplication”: also known as tandem duplication, is the event of copying a DNA segment and inserting it beside the original copy. The precision and F1 score for duplication of SvABA can also for insertion, as these two SV types are not distinguishable by SvABA. "),
p("[16] “Domestic insertion”: the addition of a DNA segment copied from a distant site of the same genome (i.e. “copy-and-paste”). "),
p("[17] “Foreign insertion”: the addition of a novel sequence, not known to be present in the sample genome. The precision and F1 score only estimated for a general insertion if this SV type or “Domestic insertion” [16] selected. Due to the limitations of callers in detecting insertion, the sensitivity estimation for this SV type by Lumpy and SvABA and precision and F1 score estimation by Lumpy, SvABA and GRIDSS are not available."),
p("[18] “Inversion”: the inversion of a DNA segment at the same locus."),
p("[19] “Translocation”: involves the deletion of a DNA segment from one locus and its reinsertion at another locus (i.e. “cut-and-paste”). Callers report breakend (BND) of fusion junctions for inter-chromosomal events, including domestic insertion and translocation, so the precision and F1 score of BND for will be shown for this SV type."),
h5("To visualise your desired sensitivity, precision and F1 score lines on the plot and make decisions on variables based on the objective:"),
p("[20] Enter your desired sensitivity, precision and F1 score."),
p("[21] Tables show the lower bound of variables to achieve desired sensitivity, precision and F1 score under the visualisation."),
br(),
h4("Shiny-SoSV type interface provides predictions of the impact of common variables (sequencing coverage, tumour allele frequencies, tolerance of breakpoint precision) on the performance (sensitivity, precision and F1 score) of different SV type calling for each call set through interactive plots. Please click on “Shiny-SoSV type” tab on top navigation panel for the interface:"),
img(src = "UserGuide_type.png",height="100%", width="100%"),
h5("Predictor variables can be altered and visualized in the same way as the main Shiny-SoSV interface, with the differences of: "),
p("[22] Choose the SV call set: Selection of the individual, union or intersection call set. "),
p("[23] SV caller: One individual SV caller or the first caller for union or intersection call sets. Any overlapping calls in the combined call set is taken from the output from the first caller. "),
p("[24] Another SV caller to combine: The second SV caller for union or intersection call set. When “individual” in [22] selected, this option is disabled. "),
p("[25] SV type(s): One or more SV types can be examined (distinguished by line colour in the plots)."),
tags$hr(),
strong("A note on the parameters:"),
tags$ul(
tags$li("Histopathological estimates of tumour purity or percentage tumour is typically the upper bound of observed VAF in genomics studies in part due to the likelihood of the presence of sub-clonality."),
tags$li("Breakpoint precision threshold is the maximum difference (in bp) between what was reported by the corresponding SV caller and what was simulated.")
)
))),
tabPanel(title = "Example Use Cases", value = "usecase",fluidRow(column(width=10,offset=1,
h5("Hypothetical scenarios of highlighting the Shiny-SoSV’s utility:"),
fluidRow(column(width = 11, h5("Scenario 1: I have a cohort of matched-normal cancer samples, each with different histopathology-estimates of tumour purity.",
"Our WGS (or bioinformatics) pipeline uses Lumpy, which could potentially be changed, though we’d rather not have to.",
"How much coverage would I need to achieve at least 80% sensitivity and >90% precision on somatic SV calls.")),
column(1,
actionButton("S1", label = "", icon = icon("angle-down"), class = "btn btn-info")
)),
fluidRow(column(width = 11,hidden(htmlOutput(outputId = "text_S1")))),
hidden(imageOutput(outputId = "image_S1", width = "100%", height = "100%")),
#hidden(imageOutput(outputId = "image_S1", width = "100%", height = "500px")),
#fluidRow(column(3,br(),br())),
fluidRow(column(11,h5("Scenario 2: I have a handful of tumour samples sequenced to 60x,",
"I am wondering if I can generate low pass coverage on the matched normal and still obtain good sensitivity and precision.",
"We haven’t decided on which SV caller to use yet.")),
column(1,
actionButton("S2", label = "", icon = icon("angle-down"), class = "btn btn-info")
)),
fluidRow(column(width = 11,hidden(htmlOutput(outputId = "text_S2")))),
hidden(imageOutput(outputId = "image_S2a", width = "100%", height = "100%")),
fluidRow(column(width = 11,hidden(htmlOutput(outputId = "text_S2.1")))),
hidden(imageOutput(outputId = "image_S2b", width = "100%", height = "100%")),
hidden(imageOutput(outputId = "image_S2c", width = "100%", height = "100%")),
fluidRow(column(11,h5("Scenario 3: I have a cancer sample with estimated tumour purity estimated of about 20%.",
"It is a precious sample, and we want to call confident SVs.",
"How much should we sequence to get >90% sensitivity and precision. Is it even possible?")),
column(1,
actionButton("S3", label = "", icon = icon("angle-down"), class = "btn btn-info")
)),
fluidRow(column(width = 11,hidden(htmlOutput(outputId = "text_S3")))),
hidden(imageOutput(outputId = "image_S3", width = "100%", height = "100%")),
fluidRow(column(11,h5("Scenario 4: I have a patient whom we cannot find a pathological SNV/indel from a 30x WGS.",
" We think the driver mutation may be a structural variant. We don’t know much about SVs or how to call them.",
"Which SV caller should we use? Our NGS data suggested the tumour purity is about 50%.",
"Do we need to sequence more?",
"We care about both false positives and false negatives, but would prefer to be confident in what we find than finding more of something that may be false.")),
column(1,
actionButton("S4", label = "", icon = icon("angle-down"), class = "btn btn-info")
)),
fluidRow(column(width = 11,hidden(htmlOutput(outputId = "text_S4")))),
hidden(imageOutput(outputId = "image_S4", width = "100%", height = "100%")),
p()
))),
tags$script("
Shiny.addCustomMessageHandler('resetValue', function(variableName) {
Shiny.onInputChange(variableName, null);
});
")
)))
server <- function(input, output, session)({
observeEvent(input$jumpToInstallation, {
updateTabsetPanel(session, "Shiny-SoSV",
selected = "installation")
})
observeEvent(input$jumpToUserGuide, {
updateTabsetPanel(session, "Shiny-SoSV",
selected = "userguide")
})
observeEvent(input$jumpToUseCase, {
updateTabsetPanel(session, "Shiny-SoSV",
selected = "usecase")
})
observeEvent(input$jumpToEvaluation, {
updateTabsetPanel(session, "Shiny-SoSV",
selected = "evaluation")
})
observeEvent(input$jumpToEvaluation_svtype, {
updateTabsetPanel(session, "Shiny-SoSV",
selected = "evaluation_svtype")
})
observeEvent(input$S1, {
toggle('text_S1')
output$text_S1 <- renderText({paste("To address this using Shiny-SoSV, as demonstrated in the figure, the user would evaluate “Sensitivity” and “Precision” across “Tumour purity/VAF”. On the sidebar, choose any (combination of) SV caller(s), including Lumpy (the implemented caller in this scenario). Here, Lumpy, GRIDSS and the union set of them have been selected. Three tumour coverages have also been selected for comparison: presets 30x and 60x selected via the checkboxes and 100x via slider bar. All other parameters are left as default.",
"<br>",
"From this, it is immediately obvious that tumour purity has a great impact on sensitivity, while little impact on precision, particularly for tumour purity within 5% and 30%. In addition, the union set of Lumpy and GRIDSS has the higher sensitivity, but slightly lower precision.
Entering the objectives (sensitivity > 80% and precision > 90%), the table shows that Lumpy cannot achieve 80% sensitivity even with tumour sequencing coverage at 100x. While, at 60x, the union set of Lumpy and GRIDSS can achieve > 80% sensitivity when tumour purity >30%. Therefore, the user could include GRIDSS into the pipeline and sequencing at 60x.
",
"</p>")})
})
observeEvent(input$S1, {
toggle('image_S1')
output$image_S1 <- renderImage({
filename <- normalizePath(file.path('./images',paste0('FigureS1', '.png')))
list(src = filename, height="100%", width="100%", alt="Figure 1")
#list(src = filename, height=500, width=900, alt="Figure 1")
}, deleteFile = FALSE)
})
observeEvent(input$S2, {
toggle('text_S2')
#output$text_S2 <- renderText({paste("There are several ways to address this. As we don’t know the expected tumour purity of these samples, we could evaluate across “Tumour Purity/VAF”, fixing tumour coverage at 60x and Normal coverage at the lowest option of 15x. Entering the desired sensitivity and precision, for example at least 80% sensitivity and precision, as shown in Figure 2a. Selecting all five SV callers shows that it is possible to achieve sensitivity above 80% with Manta but only if the tumour sample is at least 24% pure. Further selecting the union set of Manta and GRIDSS (the two best performing callers under this setting) suggests we might be able to reach > 80% sensitivity with tumour purity as low as 17%.",
# "</p>")})
output$text_S2 <- renderText({paste("There are several ways to address this. Start by choosing F1 score, the harmonic mean of the sensitivity and precision, as the evaluation measurement. As we don’t know the expected tumour purity of these samples, we could evaluate across “Tumour Purity/VAF”, fixing Tumour coverage at 60x and Normal coverage at the lowest option of 20x. Entering the desired F1 score, for example at least 90% F1 score, as shown in Figure 2a. Selecting all five SV callers shows that it is possible to achieve F1 score above 90% with Manta but only if the tumour sample is at least 27% pure. Further selecting the union set of Manta and GRIDSS (the two best performing callers under this setting) suggests we might be able to reach > 90% F1 score with tumour purity as low as 21%.",
"</p>")})
})
observeEvent(input$S2, {
toggle('image_S2a')
output$image_S2a <- renderImage({
filename <- normalizePath(file.path('./images',paste('FigureS2a', '.png', sep='')))
list(src = filename, height="100%", width="100%", alt="Figure 2")
}, deleteFile = FALSE)
})
observeEvent(input$S2, {
toggle('text_S2.1')
#output$text_S2.1 <- renderText({paste("Another way to address this question would be to evaluate across “Normal coverage” and setting Tumour coverage to 60x. Again, as we don’t know the purity of the tumour samples, we may need to explore a bit. For example, setting Tumour purity to 50% shown in Figure 2b, we see that the depth of coverage of the normal sample does not actually have very significant impact on the sensitivity or precision. Rather, it is the SV callers that have the biggest impact. Again, we see sensitivity exceeds 80% with Manta and union set of Manta and GRIDSS, providing tumour purity is > 50%. Lowering Tumour purity to 20% shown in Figure 2c, we note the need to use a combination of SV callers in order to achieve the desire sensitivity with low pass coverage of normal sample (15x).",
# "</p>")})
output$text_S2.1 <- renderText({paste("Another way to address this question would be to evaluate across “Normal coverage” and setting Tumour coverage to 60x. Again, as we don’t know the purity of the tumour samples, we may need to explore a bit. For example, setting Tumour purity to 80% shown in Figure 2b, we see that the depth of coverage of the normal sample does not actually have very significant impact on the F1 score. Rather, it is the SV callers that have the biggest impact. Again, we see F1 score exceeds 90% with Manta and union set of Manta and GRIDSS, providing tumour purity is > 80%. Lowering Tumour purity to 50% shown in Figure 2c, we note the need to use a combination of SV callers in order to achieve the desired F1 score with low pass coverage of normal sample (20x).",
"</p>")})
})
observeEvent(input$S2, {
toggle('image_S2b')
output$image_S2b <- renderImage({
filename <- normalizePath(file.path('./images',paste('FigureS2b', '.png', sep='')))
list(src = filename, height="100%", width="100%", alt="Figure 2")
}, deleteFile = FALSE)
})
observeEvent(input$S2, {
toggle('image_S2c')
output$image_S2c <- renderImage({
filename <- normalizePath(file.path('./images',paste('FigureS2c', '.png', sep='')))
list(src = filename, height="100%", width="100%", alt="Figure 2")
}, deleteFile = FALSE)
})
observeEvent(input$S3, {
toggle('text_S3')
#output$text_S3 <- renderText({paste("To address this using Shiny-SoSV, as demonstrated in the figure below, the user can evaluate both “Sensitivity” and “Precision” across “Tumour coverage”. On the sidebar, the user can choose all SV callers and their union sets aiming to increase sensitivity and set tumour purity/VAF to 0.2, while fixing all other parameters as default. ",
# "<br>","Entering the desired sensitivity and precision (90%) can help the user quickly calculate how much to sequence and which SV caller to choose. From the table and the plots, we can see it is possible to attain > 90% sensitivity with both Manta and GRIDSS, sequencing at least 77x coverage on the tumour. Moving the slider bar from 30x (default) to 90x to increase matched normal coverage has little improvement on sensitivity. While >90% precision can easily be reached (regardless of SV caller, depth of sequencing coverage, or breakpoint precision threshold). ",
# "</p>")})
output$text_S3 <- renderText({paste("To address this using Shiny-SoSV, as demonstrated in the figure below, the user can evaluate both “Sensitivity” and “Precision” across “Tumour coverage”. On the sidebar, the user can choose all SV callers and their union sets aiming to increase sensitivity and set tumour purity/VAF to 0.2. As the user want to call confident SVs, a higher breakpoint resolution can be required by setting breakpoint precision threshold to a lower value (e.g. 5bp), while fixing all other parameters as default. ",
"<br>","Entering the desired sensitivity and precision (90%) can help the user quickly calculate how much to sequence and which SV caller to choose. From the table and the plots, we can see that while >90% precision can easily be reached (regardless of SV caller, depth of sequencing coverage, or breakpoint precision threshold), the highest sensitivity can be attained is around 85% with such low tumour purity (20%). In addition, moving the slider bar from 30x (default) to 100x to increase matched normal coverage has little improvement on sensitivity. If we are to extrapolate on the plot shown, it may be possible to attain > 90% sensitivity with > 120x coverage on the tumour.",
"</p>")})
})
observeEvent(input$S3, {
toggle('image_S3')
output$image_S3 <- renderImage({
filename <- normalizePath(file.path('./images',paste('FigureS3', '.png', sep='')))
list(src = filename, height="100%", width="100%", alt="Figure 3")
}, deleteFile = FALSE)
})
observeEvent(input$S4, {
toggle('text_S4')
#output$text_S4 <- renderText({paste("To address this using Shiny-SoSV, as demonstrated in Figure, the user would select to evaluate both “Sensitivity” and “Precision” across “Tumour coverage”. On the sidebar, the user can choose all SV callers (Manta, Lumpy, GRIDSS, SvABA and Delly) for comparison in the first instance, setting Tumour purity to 0.5 and fixing all other parameters as default. ",
# "<br>","With these settings, Manta has the highest sensitivity, with 10% and 15% higher sensitivity than GRIDSS and Lumpy respectively. All SV callers can reach >90% precision, except SvABA. Considering the user’s preference to miss calls rather than make false calls, they may want to consider using two different SV callers and taking the intersection callset. From the table, the intersection callset from any two SV callers would increase the precision by around 1-18%, however, it is worth noting that sensitivity does drop. To explore how much more sequencing is needed to compensate the dropping sensitivity, the user can view the lower bound of variables required for the desired sensitivity. If the desired sensitivity is 70%, as shown in table, using the intersection set of Manta and GRIDSS would need another 14x depth of sequencing coverage on tumour, comparing to using Manta only.",
# "<br>","Therefore, the plots and table provide sufficient information for users to make educated decisions tailored for the situation. ",
# "</p>")})
output$text_S4 <- renderText({paste("To address this using Shiny-SoSV, as demonstrated in Figure, the user would select to evaluate both “Sensitivity” and “Precision” across “Tumour coverage”. On the sidebar, the user can choose all SV callers (Manta, Lumpy, GRIDSS, SvABA and Delly) for comparison in the first instance, setting tumour purity to 0.5, setting breakpoint precision threshold to low (e.g. 5bp) aiming to have a high breakpoint resolution and fixing all other parameters as default. ",
"<br>","With these settings, Manta has the highest sensitivity, with 10% and 15% higher sensitivity than GRIDSS and Lumpy respectively. All SV callers can reach >90% precision, except SvABA. Considering the user’s preference to miss calls rather than make false calls, they may want to consider using two different SV callers and taking the intersection callset. From the table, the intersection callset from any two SV callers would increase the precision by around 1-5%, however, it is worth noting that sensitivity does drop. To explore how much more sequencing is needed to compensate the dropping sensitivity, the user can view the lower bound of variables required for the desired sensitivity. If the desired sensitivity is 65%, as shown in table, using the intersection set of Manta and GRIDSS would need another 12x depth of sequencing coverage on tumour, while still have 8% lower sensitivity comparing to using Manta only.",
"<br>","Therefore, the plots and table provide sufficient information for users to make educated decisions tailored for the situation. ",
"</p>")})
})
observeEvent(input$S4, {
toggle('image_S4')
output$image_S4 <- renderImage({
filename <- normalizePath(file.path('./images',paste('FigureS4', '.png', sep='')))
list(src = filename, height="100%", width="100%", alt="Figure 4")
}, deleteFile = FALSE)
})
# disable("SVCaller3.1")
# disable("SVCaller3.2")
# disable("SVCaller2.2")
MeasureInput2 <- reactive({c("Sensitivity","Precision","F1 score") %in% input$measurements2})
MeasureInput3 <- reactive({c("Sensitivity","Precision","F1 score") %in% input$measurements3})
observe({if(input$type3 != ''){
updateSliderInput(session, "VAF3", min = 0.2)
}
})
observe({if(input$type3 != ''){
updateSliderInput(session, "T_coverage3", min = 30)
}
})
observe({if(input$X_axis3 == "VAF"){
disable("VAF3")
disable("VAF3.1")
enable("T_coverage3")
enable("T_coverage3.1")
enable("N_coverage3")
enable("BND_threshold3")
}else if(input$X_axis3 == "T_coverage"){
enable("VAF3")
enable("VAF3.1")
disable("T_coverage3")
disable("T_coverage3.1")
enable("N_coverage3")
enable("BND_threshold3")
}else if(input$X_axis3 == "N_coverage"){
enable("VAF3")
disable("VAF3.1")
enable("T_coverage3")
enable("T_coverage3.1")
disable("N_coverage3")
enable("BND_threshold3")
}else if(input$X_axis3 == "BND_threshold"){
disable("VAF3.1")
enable("T_coverage3")
enable("T_coverage3.1")
enable("N_coverage3")
disable("BND_threshold3")
}})
observe({if(input$X_axis2 == "VAF"){
disable("VAF2")
disable("VAF2.1")
enable("T_coverage2")
enable("T_coverage2.1")
enable("N_coverage2")
enable("BND_threshold2")
}else if(input$X_axis2 == "T_coverage"){
enable("VAF2")
enable("VAF2.1")
disable("T_coverage2")
disable("T_coverage2.1")
enable("N_coverage2")
enable("BND_threshold2")
}else if(input$X_axis2 == "N_coverage"){
enable("VAF2")
disable("VAF2.1")
enable("T_coverage2")
enable("T_coverage2.1")
disable("N_coverage2")
enable("BND_threshold2")
}else if(input$X_axis2 == "BND_threshold"){
disable("VAF2.1")
enable("T_coverage2")
enable("T_coverage2.1")
enable("N_coverage2")
disable("BND_threshold2")
}})
observe({if(!MeasureInput3()[1]){ disable("objective3.1") }})
observe({if(MeasureInput3()[1]){ enable("objective3.1") }})
observe({if(!MeasureInput3()[2]){ disable("objective3.2") }})
observe({if(MeasureInput3()[2]){ enable("objective3.2") }})
observe({if(!MeasureInput3()[3]){ disable("objective3.3") }})
observe({if(MeasureInput3()[3]){ enable("objective3.3") }})
observe({if(!MeasureInput2()[1]){ disable("objective2.1") }})
observe({if(MeasureInput2()[1]){ enable("objective2.1") }})
observe({if(!MeasureInput2()[2]){ disable("objective2.2") }})
observe({if(MeasureInput2()[2]){ enable("objective2.2") }})
observe({if(!MeasureInput2()[3]){ disable("objective2.3") }})
observe({if(MeasureInput2()[3]){ enable("objective2.3") }})
observe({if(input$SVCallset == ""){
disable("SVCaller2.2")
}else{
enable("SVCaller2.2")
}
})
SVCaller_name_input <- reactive({
if(input$SVCallset == ""){
SVCaller_name <- input$SVCaller2.1
SVCaller_name_label <- input$SVCaller2.1
}else if (input$SVCallset == "Union"){
if(input$SVCaller2.1 != input$SVCaller2.2){
SVCaller_name <- paste0(input$SVCaller2.1,input$SVCaller2.2,"Union")
SVCaller_name_label <- paste0("Union set of ", input$SVCaller2.1,input$SVCaller2.2)
}else{
SVCaller_name <- input$SVCaller2.1
SVCaller_name_label <- input$SVCaller2.1
}
}else if (input$SVCallset == "Intersect"){
if(input$SVCaller2.1 != input$SVCaller2.2){
SVCaller_name <- paste0(input$SVCaller2.1,input$SVCaller2.2,"Intersect")
SVCaller_name_label <- paste0("Intersection set of ", input$SVCaller2.1,input$SVCaller2.2)
}else{
SVCaller_name <- input$SVCaller2.1
SVCaller_name_label <- input$SVCaller2.1
}
}
return(list(SVCaller_name, SVCaller_name_label))
})
# SVCaller_name_input <- reactive({
# SVCaller_name <- input$SVCaller2.1
# SVCaller_name_label <- input$SVCaller2.1
#
# return(list(SVCaller_name, SVCaller_name_label))
# })
#output$txtOutput2 <- renderText({ paste(input$SVCallset, input$SVCaller2.1, input$SVCaller2.2, "----", SVCaller_name_input())})
newdata2 <- reactive({
SVCaller_name <- SVCaller_name_input()[[1]]
if(input$X_axis2 == "VAF"){
T_coverage_label = paste0(c(input$T_coverage2,30,60),"x")
VAF_label = c()
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
data <- data.frame(Caller = SVCaller_name,
T_coverage = rep(c(input$T_coverage2,30,60)),
N_coverage = input$N_coverage2,
VAF = rep(seq(0.2,1,0.01),each=length(T_coverage_label)),
BND_threshold = input$BND_threshold2)
xlabel <- "Tumour purity/VAF"
Tcov_var <- c(paste0(input$T_coverage2,"x"),input$T_coverage2.1)
Ncov_var <- paste0(input$N_coverage2,"x")
VAF_var <- paste0(seq(0.2,1,0.01))
BND_var <- paste0(input$BND_threshold2)
index <- 8
legend_label <- "Tumour coverage"
x_min <- 0.2
x_max <- 1
x_by <- 0.1
}else if(input$X_axis2 == "T_coverage"){
T_coverage_label = c()
VAF_label = paste0(c(input$VAF2,0.2,0.8))
line_type <- c("solid","twodash","dotted")
names(line_type) <- VAF_label
data <- data.frame(Caller = SVCaller_name,
T_coverage = rep(c(30:100),each = length(VAF_label)),
N_coverage = input$N_coverage2,
VAF = rep(c(input$VAF2,0.2,0.8)),
BND_threshold = input$BND_threshold2)
xlabel <- "Tumour coverage (x)"
Tcov_var <- paste0(c(30:100),"x")
Ncov_var <- paste0(input$N_coverage2,"x")
VAF_var <- c(paste0(input$VAF2),input$VAF2.1)
BND_var <- paste0(input$BND_threshold2)
index <- 10
legend_label <- "Tumour purity/VAF"
x_min <- 30
x_max <- 100
x_by <- 10
}else if(input$X_axis2 == "N_coverage"){
T_coverage_label = paste0(c(input$T_coverage2,30,60),"x")
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
VAF_label = c()
data <- data.frame(Caller = SVCaller_name,
T_coverage = rep(c(input$T_coverage2,30,60)),
N_coverage = rep(c(20:100), each = length(T_coverage_label)),
VAF = input$VAF2,
BND_threshold = input$BND_threshold2)
xlabel <- "Normal coverage (x)"
Tcov_var <- c(paste0(input$T_coverage2,"x"),input$T_coverage2.1)
Ncov_var <- paste0(c(20:100),"x")
VAF_var <- paste0(input$VAF2)
BND_var <- paste0(input$BND_threshold2)
index <- 8
legend_label <- "Tumour coverage"
x_min <- 20
x_max <- 100
x_by <- 10
}else if(input$X_axis2 == "BND_threshold"){
T_coverage_label = paste0(c(input$T_coverage2,30,60),"x")
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
VAF_label = c()
data <- data.frame(Caller = SVCaller_name,
T_coverage = rep(c(input$T_coverage2,30,60)),
N_coverage = input$N_coverage2,
VAF = input$VAF2,
BND_threshold = rep(c(2:200), each = length(T_coverage_label)))
xlabel <- "Breakpoint precision threshold (bp)"
Tcov_var <- c(paste0(input$T_coverage2,"x"),input$T_coverage2.1)
Ncov_var <- paste0(input$N_coverage2,"x")
VAF_var <- paste0(input$VAF2)
BND_var <- paste0(c(2:200))
index <- 8
legend_label <- "Tumour coverage"
x_min <- 0
x_max <- 200
x_by <- 20
}
return(list(data, T_coverage_label,VAF_label,Tcov_var, Ncov_var, VAF_var, BND_var,
xlabel,line_type,index,legend_label,x_min,x_max,x_by))
})
newdata3 <- reactive({
if(input$X_axis3 == "VAF"){
T_coverage_label = paste0(c(input$T_coverage3,60,30),"x")
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
VAF_label = c()
data <- data.frame(Caller = SV_caller,
T_coverage = rep(c(input$T_coverage3,60,30), each=length(SV_caller)),
N_coverage = input$N_coverage3,
VAF = rep(seq(0.05,1,0.01),each=length(T_coverage_label)*length(SV_caller)),
BND_threshold = input$BND_threshold3)
xlabel <- "Tumour purity/VAF"
Tcov_var <- c(paste0(input$T_coverage3,"x"),input$T_coverage3.1)
Ncov_var <- paste0(input$N_coverage3,"x")
VAF_var <- paste0(seq(0.05,1,0.01))
BND_var <- paste0(input$BND_threshold3)
index <- 8
legend_label <- "Tumour coverage"
if(input$type3 == ""){x_min <- 0}else{x_min <- 0.2}
x_max <- 1
x_by <- 0.1
}else if(input$X_axis3 == "T_coverage"){
VAF_label = paste0(c(input$VAF3,0.2,0.8))
line_type <- c("solid","twodash","dotted")
names(line_type) <- VAF_label
T_coverage_label = c()
data <- data.frame(Caller = SV_caller,
T_coverage = rep(c(20:100),each = length(VAF_label)*length(SV_caller)),
N_coverage = input$N_coverage3,
VAF = rep(c(input$VAF3,0.2,0.8), each=length(SV_caller)),
BND_threshold = input$BND_threshold3)
xlabel <- "Tumour coverage (x)"
Tcov_var <- paste0(c(20:100),"x")
Ncov_var <- paste0(input$N_coverage3,"x")
VAF_var <- c(paste0(input$VAF3),input$VAF3.1)
BND_var <- paste0(input$BND_threshold3)
index <- 10
legend_label <- "Tumour purity/VAF"
if(input$type3 == ""){x_min <- 20}else{x_min <- 30}
x_max <- 100
x_by <- 10
}else if(input$X_axis3 == "N_coverage"){
T_coverage_label = paste0(c(input$T_coverage3,60,30),"x")
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
VAF_label = c()
data <- data.frame(Caller = SV_caller,
T_coverage = rep(c(input$T_coverage3,60,30), each=length(SV_caller)),
N_coverage = rep(c(20:100), each = length(T_coverage_label)*length(SV_caller)),
VAF = input$VAF3,
BND_threshold = input$BND_threshold3)
xlabel <- "Normal coverage (x)"
Tcov_var <- c(paste0(input$T_coverage3,"x"),input$T_coverage3.1)
Ncov_var <- paste0(c(20:100),"x")
VAF_var <- paste0(input$VAF3)
BND_var <- paste0(input$BND_threshold3)
index <- 8
legend_label <- "Tumour coverage"
x_min <- 20
x_max <- 100
x_by <- 10
}else if(input$X_axis3 == "BND_threshold"){
T_coverage_label = paste0(c(input$T_coverage3,60,30),"x")
line_type <- c("solid","twodash","dotted")
names(line_type) <- T_coverage_label
VAF_label = c()
data <- data.frame(Caller = SV_caller,
T_coverage = rep(c(input$T_coverage3,60,30), each=length(SV_caller)),
N_coverage = input$N_coverage3,
VAF = input$VAF3,
BND_threshold = rep(c(2:200), each = length(T_coverage_label)*length(SV_caller)))
xlabel <- "Breakpoint precision threshold (bp)"
Tcov_var <- c(paste0(input$T_coverage3,"x"),input$T_coverage3.1)
Ncov_var <- paste0(input$N_coverage3,"x")
VAF_var <- paste0(input$VAF3)
BND_var <- paste0(c(2:200))
index <- 8
legend_label <- "Tumour coverage"
x_min <- 0
x_max <- 200
x_by <- 20
}
return(list(data, T_coverage_label,VAF_label,Tcov_var, Ncov_var, VAF_var, BND_var,
xlabel,line_type,index,legend_label,x_min,x_max,x_by))
})
########################################################################################################################
dataInput2.1 <- reactive({
input_type <- input$type2
SVCaller_name <- SVCaller_name_input()[[1]]
data <- newdata2()[[1]]
T_coverage_label <- newdata2()[[2]]
VAF_label <- newdata2()[[3]]
Tcov_var <- newdata2()[[4]]
Ncov_var <- newdata2()[[5]]
VAF_var <- newdata2()[[6]]
BND_var <- newdata2()[[7]]
df.Sensitivity <- c()
for (SVTYPE in SVTYPE_all){
if(!((SVCaller_name == "Lumpy" & SVTYPE == "FINS")|
(SVCaller_name == "SvABA" & SVTYPE == "FINS")|
(grepl("Lumpy",SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "FINS") |
(grepl("SvABA",SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "FINS") |
(grepl("LumpySvABAUnion", SVCaller_name) & SVTYPE == "FINS") |
(grepl("SvABALumpyUnion", SVCaller_name) & SVTYPE == "FINS"))){
newdata <- data
assign("df.Sensitivity_caller", data.frame(newdata,
#predict(eval(parse(text=paste0("gamsen_", SVCaller_name))),newdata,type = "response",se.fit = T,unconditional = TRUE),
predict(eval(parse(text=paste0("gamsen_",SVCaller_name, SVTYPE))),newdata,type = "response",se.fit = T,unconditional = TRUE),
T_coverage_label = paste0(newdata$T_coverage,"x"),
N_coverage_label = paste0(newdata$N_coverage,"x"),
VAF_label = paste0(newdata$VAF),
BND_label = paste0(newdata$BND_threshold),
SVTYPE = SVTYPE,
row.names = c(1:(nrow(newdata)))))
df.Sensitivity <- rbind(df.Sensitivity, df.Sensitivity_caller)
}
}
tmp1 <- df.Sensitivity
obj_row <- c()
if(input$X_axis2 %in% c("VAF","N_coverage","BND_threshold")){
for(i in 1: length(SVTYPE_all)){
for(j in 1: length(T_coverage_label)){
tmp = tmp1[(tmp1$SVTYPE %in% SVTYPE_all[i]) &
(tmp1$T_coverage_label %in% T_coverage_label[j]) &
(tmp1$N_coverage_label %in% Ncov_var) &
(tmp1$VAF_label %in% VAF_var) &
(tmp1$BND_threshold %in% BND_var),]
obj_row <- c(obj_row, rownames(tmp[tmp$fit>input$objective2.1,][1,]))
}
}
}else if(input$X_axis2 == "T_coverage"){
for(i in 1: length(SVTYPE_all)){
for(k in 1: length(VAF_label)){
tmp = tmp1[(tmp1$SVTYPE %in% SVTYPE_all[i]) &
(tmp1$T_coverage_label %in% Tcov_var) &
(tmp1$N_coverage_label %in% Ncov_var) &
(tmp1$VAF_label %in% VAF_label[k]) &
(tmp1$BND_threshold %in% BND_var),]
obj_row <- c(obj_row, rownames(tmp[tmp$fit>input$objective2.1,][1,]))
}
}
}
obj <- rep(FALSE,nrow(df.Sensitivity))
obj[as.numeric(obj_row[obj_row!="NA"])] <- TRUE
df.Sensitivity <- cbind(df.Sensitivity,obj)
obj.y <- rep(NA,nrow(df.Sensitivity))
obj.y[df.Sensitivity$obj] <- df.Sensitivity$fit[df.Sensitivity$obj]
df.Sensitivity <- cbind(df.Sensitivity, obj.y)
df.Sensitivity$Caller <- factor(df.Sensitivity$Caller, levels = SV_caller)
df = df.Sensitivity[(df.Sensitivity$SVTYPE %in% input_type) &
(df.Sensitivity$T_coverage_label %in% Tcov_var) &
(df.Sensitivity$N_coverage_label %in% Ncov_var) &
(df.Sensitivity$VAF_label %in% VAF_var) &
(df.Sensitivity$BND_label %in% BND_var),]
tmp <- cbind(df, SV_caller_label1[match(df$Caller,SV_caller)], SVTYPE_all_label[match(df$SVTYPE, SVTYPE_all)])
table <- cbind(tmp[tmp$obj, c(ncol(tmp)-1,ncol(tmp), 2:6)])
colnames(table) <- c("SV caller","SV type","Tumour coverage","Normal coverage","Tumour purity/VAF","Breakpoint precision threshold","Sensitivity")
#return(list(xlabel,line_type,index,legend_label,x_min,x_max,x_by,df.Sensitivity,df,table))
return(list(df.Sensitivity,df,table))
})
########################################################################################################################
dataInput2.2 <- reactive({
input_type <- input$type2
input_type[input_type %in% c("DINS","FINS")] <- "INS"
input_type[input_type %in% c("TRA")] <- "BND"
SVCaller_name <- SVCaller_name_input()[[1]]
data <- newdata2()[[1]]
T_coverage_label <- newdata2()[[2]]
VAF_label <- newdata2()[[3]]
Tcov_var <- newdata2()[[4]]
Ncov_var <- newdata2()[[5]]
VAF_var <- newdata2()[[6]]
BND_var <- newdata2()[[7]]
df.Precision <- c()
for (SVTYPE in SVTYPE_all2){
#if(SVTYPE == "DINS"|SVTYPE == "FINS"){SVTYPE_tmp <- "INS"}
#if(SVTYPE == "TRA"){SVTYPE_tmp <- "BND"}
#if(!((SVCaller_name == "Lumpy" & SVTYPE_tmp == "INS")|
# (SVCaller_name == "SvABA" & SVTYPE_tmp == "INS")|
# (SVCaller_name == "GRIDSS" & SVTYPE_tmp == "INS"))){
if(!((SVCaller_name == "Lumpy" & SVTYPE == "INS")|
(SVCaller_name == "SvABA" & SVTYPE == "INS")|
(SVCaller_name == "GRIDSS" & SVTYPE == "INS") |
(grepl("LumpySvABAUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("LumpyGRIDSSUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABALumpyUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABAGRIDSSUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSSLumpyUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSSSvABAUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("Lumpy", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABA", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSS", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS"))){
newdata <- data
assign("df.Precision_caller", data.frame(newdata,
predict(eval(parse(text=paste0("gampre_off_", SVCaller_name, SVTYPE))),newdata,type = "response",se.fit = T,unconditional = TRUE),
T_coverage_label = paste0(newdata$T_coverage,"x"),
N_coverage_label = paste0(newdata$N_coverage,"x"),
VAF_label = paste0(newdata$VAF),
BND_label = paste0(newdata$BND_threshold),
SVTYPE = SVTYPE,
row.names = c(1:(nrow(newdata)))))
df.Precision <- rbind(df.Precision, df.Precision_caller)
}
}
tmp1 <- df.Precision
obj_row <- c()
if(input$X_axis2 %in% c("VAF","N_coverage","BND_threshold")){
for(i in 1: length(SVTYPE_all2)){
for(j in 1: length(T_coverage_label)){
tmp = tmp1[(tmp1$SVTYPE %in% SVTYPE_all2[i]) &
(tmp1$T_coverage_label %in% T_coverage_label[j]) &
(tmp1$N_coverage_label %in% Ncov_var) &
(tmp1$VAF_label %in% VAF_var) &
(tmp1$BND_threshold %in% BND_var),]
obj_row <- c(obj_row,rownames(tmp[tmp$fit>input$objective2.2,][1,]))
}
}
}else if(input$X_axis2 == "T_coverage"){
for(i in 1: length(SVTYPE_all2)){
for(k in 1: length(VAF_label)){
tmp = tmp1[(tmp1$SVTYPE %in% SVTYPE_all2[i]) &
(tmp1$T_coverage_label %in% Tcov_var) &
(tmp1$N_coverage_label %in% Ncov_var) &
(tmp1$VAF_label %in% VAF_label[k]) &
(tmp1$BND_threshold %in% BND_var),]
obj_row <- c(obj_row,rownames(tmp[tmp$fit>input$objective2.2,][1,]))
}
}
}
obj <- rep(FALSE,nrow(df.Precision))
obj[as.numeric(obj_row[obj_row!="NA"])] <- TRUE
df.Precision <- cbind(df.Precision,obj)
obj.y <- rep(NA,nrow(df.Precision))
obj.y[df.Precision$obj] <- df.Precision$fit[df.Precision$obj]
df.Precision <- cbind(df.Precision,obj.y)
df.Precision$Caller <- factor(df.Precision$Caller, levels = SV_caller)
df = df.Precision[(df.Precision$SVTYPE %in% input_type) &
(df.Precision$T_coverage_label %in% Tcov_var) &
(df.Precision$N_coverage_label %in% Ncov_var) &
(df.Precision$VAF_label %in% VAF_var) &
(df.Precision$BND_label %in% BND_var),]
tmp <- cbind(df,SV_caller_label1[match(df$Caller,SV_caller)], SVTYPE_all_label2[match(df$SVTYPE, SVTYPE_all2)])
table <- cbind(tmp[tmp$obj, c(ncol(tmp)-1,ncol(tmp), 2:6)])
#table <- unique(table)
colnames(table) <- c("SV caller","SV type","Tumour coverage","Normal coverage","Tumour purity/VAF","Breakpoint precision threshold","Precision")
#return(list(xlabel,line_type,index,legend_label,x_min,x_max,x_by,df.Precision,df,table))
return(list(df.Precision,df,table))
})
########################################################################################################################
dataInput2.3 <- reactive({
input_type <- input$type2
input_type[input_type %in% c("DINS","FINS")] <- "INS"
input_type[input_type %in% c("TRA")] <- "BND"
SVCaller_name <- SVCaller_name_input()[[1]]
data <- newdata2()[[1]]
T_coverage_label <- newdata2()[[2]]
VAF_label <- newdata2()[[3]]
Tcov_var <- newdata2()[[4]]
Ncov_var <- newdata2()[[5]]
VAF_var <- newdata2()[[6]]
BND_var <- newdata2()[[7]]
df.F1_score <- c()
for (SVTYPE in SVTYPE_all2){
if(!((SVCaller_name == "Lumpy" & SVTYPE == "INS")|
(SVCaller_name == "SvABA" & SVTYPE == "INS")|
(SVCaller_name == "GRIDSS" & SVTYPE == "INS") |
(grepl("LumpySvABAUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("LumpyGRIDSSUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABALumpyUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABAGRIDSSUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSSLumpyUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSSSvABAUnion", SVCaller_name) & SVTYPE == "INS") |
(grepl("Lumpy", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS") |
(grepl("SvABA", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS") |
(grepl("GRIDSS", SVCaller_name) & grepl("Intersect", SVCaller_name) & SVTYPE == "INS"))){
newdata <- data
assign("df.F1_score_caller", data.frame(newdata,
predict(eval(parse(text=paste0("gamF1_score_", SVCaller_name, SVTYPE))),newdata,type = "response",se.fit = T,unconditional = TRUE),
T_coverage_label = paste0(newdata$T_coverage,"x"),
N_coverage_label = paste0(newdata$N_coverage,"x"),
VAF_label = paste0(newdata$VAF),
BND_label = paste0(newdata$BND_threshold),
SVTYPE = SVTYPE,
row.names = c(1:(nrow(newdata)))))
df.F1_score <- rbind(df.F1_score, df.F1_score_caller)
}
}
tmp1 <- df.F1_score
obj_row <- c()
if(input$X_axis2 %in% c("VAF","N_coverage","BND_threshold")){