From f61f2c175b9f913bbebba16a56fc981556649cc7 Mon Sep 17 00:00:00 2001 From: Midoux Cedric <cedric.midoux@irstea.fr> Date: Tue, 27 Mar 2018 10:55:06 +0200 Subject: [PATCH] mise en ligne des scripts --- server.R | 890 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui.R | 159 ++++++++++ 2 files changed, 1049 insertions(+) create mode 100644 server.R create mode 100644 ui.R diff --git a/server.R b/server.R new file mode 100644 index 0000000..ef60663 --- /dev/null +++ b/server.R @@ -0,0 +1,890 @@ +library(shinydashboard) + +shinyServer +(function(input, output, session) +{ + checkNull <- function(x) { + if (!exists(as.character(substitute(x)))) { + return(NULL) + } else if (is.null(x)) { + return(NULL) + } else if (length(x) > 1) { + return(x) + } + else if (x %in% c(0, "", NA, "NULL")) { + return(NULL) + } else { + return(x) + } + } + + beautifulTable <- function(data) { + DT::datatable( + data = data, + rownames = FALSE, + filter = "top", + extensions = c("Buttons", "ColReorder", "FixedColumns"), + options = list( + dom = "lBtip", + pageLength = 10, + lengthMenu = list(c(10, 25, 50, 100,-1), list('10', '25', '50', '100', 'All')), + buttons = list( + 'colvis', + list( + extend = 'collection', + buttons = c('copy', 'csv', 'excel', 'pdf'), + text = 'Download' + ) + ), + colReorder = TRUE, + scrollX = TRUE, + fixedColumns = list(leftColumns = 1, rightColumns = 0) + ), + width = "auto", + height = "auto" + ) + } + + source( + "https://raw.githubusercontent.com/mahendra-mariadassou/phyloseq-extended/master/R/load-extra-functions.R" + ) + + data16S <- reactive({ + if (input$biomFormat == "std") + { + d <- import_biom( + BIOMfilename = input$fileBiom$datapath, + treefilename = input$fileTree$datapath, + refseqfilename = input$fileSeq$datapath + ) + } else if (input$biomFormat == "frogs") { + d <- import_frogs( + biom = input$fileBiom$datapath, + treefilename = input$fileTree$datapath, + refseqfilename = input$fileSeq$datapath + ) + } + + colnames(tax_table(d)) <- + c("Kingdom", + "Phylum", + "Class", + "Order", + "Family", + "Genus", + "Species") + tax_table(d)[grep("unknown ", tax_table(d))] <- NA + #tax_table(d)[grep("Unclassified", tax_table(d))] <- NA + if (!is.null(input$fileMeta)) { + if (input$CSVsep == "excel") { + sample_data(d) <- + RcmdrMisc::readXL(input$fileMeta$datapath, + rownames = TRUE, + header = TRUE) + } else { + sample_data(d) <- read.csv( + input$fileMeta$datapath, + header = TRUE, + sep = input$CSVsep, + row.names = 1, + na.strings = NA + ) + } + } else { + n <- data.frame(sample_names(d) , row.names = sample_names(d)) + names(n) <- "sample_names" + sample_data(d) <- n + } + if (input$rareData) { + d <- rarefy_even_depth( + d, + replace = FALSE, + rngseed = as.integer(Sys.time()), + verbose = FALSE + ) + } + + return(d) + }) + + output$rarefactionMin <- renderText({ + if (!is.null(input$fileBiom)) { + paste("(min sample =", format(min(sample_sums(data16S( + + ))), big.mark = " "), "reads)") + } else { + paste("(min sample =", 0, "reads)") + } + }) + + output$rarefaction <- renderText({ + if (input$rareData) { + "<font color=\"#FF0000\"><b> Vous travaillez acctuellement avec des données raréfiés </b></font>" + } + }) + + output$phyloseqPrint <- renderPrint({ + validate( + need( + !is.null(input$fileBiom), + "Merci de commencer par importer un fichier d'abondance au format BIOM. Celui-ci peut etre obtenu a l'issue du workflow FROGS avec l'operation 'FROGS BIOM to std BIOM'" + ) + ) + data16S() + }) + + output$summaryTable <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Tables", + width = NULL, + status = "primary", + tabsetPanel( + tabPanel("otu_table", + beautifulTable( + data.frame(OTU = taxa_names(data16S()), otu_table(data16S())) + )), + tabPanel("tax_table", + beautifulTable( + data.frame(OTU = taxa_names(data16S()), tax_table(data16S())) + )), + if (!is.null(input$fileMeta)) { + tabPanel("sample_data", + beautifulTable(data.frame( + SAMPLE = sample_names(data16S()), sample_data(data16S()) + ))) + } + ) + ) + }) + + output$histUI <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + selectInput( + "barFill", + label = "Niveau taxo :", + choices = rank_names(data16S()) + ), + if (!is.null(input$fileMeta)) + { + selectInput( + "barGrid", + label = "Regroupement :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput("barX", + label = "X :", + choices = c("..." = 0, sample_variables(data16S()))) + } + ) + }) + + output$histo <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- plot_bar( + physeq = data16S(), + fill = input$barFill, + x = ifelse(is.null(checkNull(input$barX)), "Sample", input$barX) + ) + if (!is.null(checkNull(input$barGrid))) { + p <- + p + facet_grid(paste(".", "~", input$barGrid), scales = "free_x") + } + return(p) + }) + + output$histFocusUIfocusRank <- renderUI({ + if (is.null(input$fileBiom)) + return() + radioButtons( + "focusRank", + label = "Niveau taxo :", + choices = list( + "Kingdom" = 1, + "Phylum" = 2, + "Class" = 3, + "Order" = 4, + "Family" = 5, + "Genus" = 6 + ), + inline = TRUE, + selected = 1 + ) + }) + + output$histFocusUIfocusTaxa <- renderUI({ + if (is.null(input$fileBiom)) + return() + selectInput( + "focusTaxa", + label = "Taxa :", + choices = unique(as.matrix(as.data.frame( + tax_table(data16S()) + )[, as.integer(input$focusRank)])), + selected = TRUE + ) + }) + + output$histFocusUIfocusNbTaxa <- renderUI({ + if (is.null(input$fileBiom)) + return() + sliderInput( + "focusNbTaxa", + label = "Nombre de sous-taxons :", + min = 0, + #max = sum(tax_table(tax_glom(data16S(), rank_names(data16S())[1+as.integer(input$focusRank)]))[, as.integer(input$focusRank)]==input$focusTaxa) + max = 30 + , + value = 10 + ) + }) + + output$histFocusUIfocusGrid <- renderUI({ + if (is.null(input$fileBiom) && is.null(input$fileMeta)) + return() + selectInput( + "focusGrid", + label = "Regroupement :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }) + + output$histFocusUIfocusX <- renderUI({ + if (is.null(input$fileBiom) && is.null(input$fileMeta)) + return() + selectInput("focusX", + label = "X :", + choices = c("..." = 0, sample_variables(data16S()))) + }) + + output$histoFocus <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- plot_composition( + physeq = data16S(), + taxaRank1 = rank_names(data16S())[as.integer(input$focusRank)], + taxaSet1 = input$focusTaxa, + taxaRank2 = rank_names(data16S())[as.integer(input$focusRank) + 1], + numberOfTaxa = input$focusNbTaxa, + fill = rank_names(data16S())[as.integer(input$focusRank) + 1], + x = ifelse(is.null(checkNull(input$focusX)), "Sample", input$focusX) + ) + if (!is.null(checkNull(input$focusGrid))) { + p <- + p + facet_grid(paste(".", "~", input$focusGrid), scales = "free_x") + } + + return(p) + }) + + output$clustUI <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + selectInput( + "clustDist", + label = "Distance :", + choices = list( + "bray", + "jaccard", + "unifrac", + "wunifrac", + "dpcoa", + "jsd", + "euclidean" + ) + ), + selectInput( + "clustMethod", + label = "Methode :", + choices = list( + "ward.D2", + "ward.D", + "single", + "complete", + "average", + "mcquitty", + "median", + "centroid" + ) + ), + if (!is.null(input$fileMeta)) { + selectInput( + "clustCol", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + } + ) + }) + + output$clust <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + plot_clust( + physeq = data16S(), + dist = input$clustDist, + method = input$clustMethod, + color = checkNull(input$clustCol) + ) + }) + + output$richnessAUI <- renderUI({ + if (is.null(input$fileBiom)) { + return() + } + box( + title = "Paramètres", + width = NULL, + status = "primary", + checkboxGroupInput( + "richnessMeasures", + label = "Mesures :", + choices = c( + "Observed", + "Chao1", + "ACE", + "Shannon", + "Simpson", + "InvSimpson", + "Fisher" + ), + selected = c( + "Observed", + "Chao1", + "ACE", + "Shannon", + "Simpson", + "InvSimpson", + "Fisher" + ), + inline = TRUE + ), + if (!is.null(input$fileMeta)) { + selectInput( + "richnessX", + label = "X :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) { + selectInput( + "richnessColor", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) { + selectInput( + "richnessShape", + label = "Forme :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + radioButtons( + "richnessBoxplot", + label = "Representation :", + choices = list( + "Points seuls" = 1, + "Boxplot et points" = 2, + "Boxplot seul" = 3 + ), + selected = 2, + inline = TRUE + ) + ) + }) + + output$richnessA <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- plot_richness( + physeq = data16S(), + x = ifelse(is.null(checkNull( + input$richnessX + )), "samples", input$richnessX), + color = checkNull(input$richnessColor), + shape = checkNull(input$richnessShape), + measures = checkNull(input$richnessMeasures) + ) + if (input$richnessBoxplot >= 2) { + p <- p + geom_boxplot() + } + if (input$richnessBoxplot <= 2) { + p <- p + geom_point() + } + return(p) + }) + + output$richnessATable <- renderUI({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p(beautifulTable(data.frame( + SAMPLE = sample_names(data16S()), round(estimate_richness(data16S()), digits = 2) + ))) + }) + + output$richnessBUI <- renderUI({ + if (is.null(input$fileMeta)) { + return() + } + box( + title = "Paramètres", + width = NULL, + status = "primary", + selectInput( + "richnessOrder", + label = "Ordre de tri des echantillons :", + choices = c("..." = 0, sample_variables(data16S())) + ) + ) + }) + + output$richnessB <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + beta <- + melt(as(distance(data16S(), method = input$richnessBDist), "matrix")) + colnames(beta) <- c("x", "y", "distance") + if (!is.null(checkNull(input$richnessOrder))) + { + new_factor = as.factor(get_variable(data16S(), input$richnessOrder)) + variable_sort <- + as.factor(get_variable(data16S(), input$richnessOrder)[order(new_factor)]) + L = levels(reorder(sample_names(data16S()), as.numeric(new_factor))) + beta$x <- factor(beta$x, levels = L) + beta$y <- factor(beta$y, levels = L) + palette <- hue_pal()(length(levels(new_factor))) + tipColor <- + col_factor(palette, levels = levels(new_factor))(variable_sort) + } + p <- + ggplot(beta, aes(x = x, y = y, fill = distance)) + geom_tile() + p <- p + theme( + axis.text.x = element_text( + angle = 90, + hjust = 1, + color = checkNull(tipColor) + ), + axis.text.y = element_text(color = checkNull(tipColor)), + axis.title.x = element_blank(), + axis.title.y = element_blank() + ) + return(p + scale_fill_gradient2()) + }) + + output$networkBUI <- renderUI({ + if (is.null(input$fileBiom)) { + return() + } + box( + title = "Paramètres", + width = NULL, + status = "primary", + sliderInput( + "netwMax", + label = "Cutoff :", + min = 0, + max = 1, + value = 0.7 + ), + checkboxInput("netwOrphan", + label = "Garder les points orphelins", + value = TRUE), + if (!is.null(input$fileMeta)) { + selectInput( + "netwCol", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) { + selectInput( + "netwShape", + label = "Forme :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) { + selectInput( + "netwLabel", + label = "Label :", + choices = c( + select = "", + "Sample name" = "value", + sample_variables(data16S()) + ) + ) + } + ) + }) + + output$networkB <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + g <- make_network( + data16S(), + distance = input$richnessBDist, + max.dist = input$netwMax, + keep.isolates = input$netwOrphan + ) + p <- plot_network( + g, + physeq = data16S(), + color = checkNull(input$netwCol), + shape = checkNull(input$netwShape), + label = checkNull(input$netwLabel), + hjust = 2, + title = NULL + ) + return(p) + }) + + output$richnessBTable <- renderUI({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p(beautifulTable(data.frame( + SAMPLE = sample_names(data16S()), round(as.matrix( + distance(data16S(), method = input$richnessBDist) + ), digits = 2) + ))) + }) + + output$rarefactionCurve <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- ggrare( + physeq = data16S(), + step = input$rarefactionStep, + color = checkNull(input$rarefactionColor), + se = FALSE + ) + if (!is.null(checkNull(input$rarefactionGrid))) { + p <- p + facet_grid(paste(".", "~", input$rarefactionGrid)) + } + if (!input$rareData) + { + if (input$rarefactionMin) { + p <- + p + geom_vline(xintercept = min(sample_sums(data16S())), + color = "gray60") + } + } + + return(p) + + }) + + output$rarefactionCurveUI <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + sliderInput( + "rarefactionStep", + label = "Etapes de calcul :", + min = 1, + max = 1000, + value = 100 + ), + if (!input$rareData) + { + checkboxInput("rarefactionMin", label = "Afficher le seuil de l'echantillon minimal", value = TRUE) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "rarefactionColor", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "rarefactionGrid", + label = "Regroupement :", + choices = c("..." = 0, sample_variables(data16S())) + ) + } + ) + }) + + output$HeatmapUI <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + if (!is.null(input$fileMeta)) + { + selectInput( + "heatmapGrid", + label = "Regroupement :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "heatmapX", + label = "X :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + sliderInput( + "heatmapTopOtu", + label = "Selection des n OTU les plus abondant :", + min = 1, + max = ntaxa(data16S()), + value = 250 + ), + selectInput( + "heatmapDist", + label = "Distance :", + selected = "bray", + choices = list( + "bray", + "jaccard", + "unifrac", + "wunifrac", + "dpcoa", + "jsd", + "euclidean" + ) + ), + selectInput( + "heatmapMethod", + label = "Methode :", + selected = "NMDS", + choices = list( + "NMDS", + "ward.D2", + "ward.D", + "single", + "complete", + "average", + "mcquitty", + "median", + "centroid" + ) + ) + ) + }) + + output$Heatmap <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- plot_heatmap( + physeq = prune_taxa(names(sort( + taxa_sums(data16S()), decreasing = TRUE + )[1:input$heatmapTopOtu]), data16S()), + distance = input$heatmapDist, + method = input$heatmapMethod, + sample.order = checkNull(input$heatmapX), + low = "yellow", + high = "red", + na.value = "white" + ) + if (!is.null(checkNull(input$heatmapGrid))) { + p <- + p + facet_grid(paste(".", "~", input$heatmapGrid), scales = "free_x") + } + return(p) + }) + + output$treeUI <- renderUI({ + if (is.null(input$fileBiom) | is.null(input$fileTree)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + radioButtons( + "treeRank", + label = "Niveau taxonomique légendé :", + choices = list( + aucun = "", + "Kingdom", + "Phylum", + "Class", + "Order", + "Family", + "Genus", + "Species", + OTU = "taxa_names" + ), + inline = TRUE + ), + sliderInput( + "treeTopOtu", + label = "Selection des n OTU les plus abondant :", + min = 1, + max = ntaxa(data16S()), + value = 20 + ), + checkboxInput("treeRadial", label = "Arbre radial", value = FALSE), + if (!is.null(input$fileMeta)) { + selectInput( + "treeCol", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) { + selectInput( + "treeShape", + label = "Forme :", + choices = c("..." = 0, sample_variables(data16S())) + ) + } + ) + }) + + output$tree <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + validate(need(!is.null(input$fileTree), + "Merci d'importer un arbre")) + p <- plot_tree( + physeq = prune_taxa(names(sort( + taxa_sums(data16S()), decreasing = TRUE + )[1:input$treeTopOtu]), data16S()), + color = checkNull(input$treeCol), + shape = checkNull(input$treeShape), + size = "abundance", + label.tips = checkNull(input$treeRank), + sizebase = 2, + ladderize = "left", + plot.margin = 0 + ) + if (checkNull(input$treeRadial)) { + return(p + coord_polar(theta = "y")) + } else { + return(p) + } + }) + + output$acpUI <- renderUI({ + if (is.null(input$fileBiom)) + return() + box( + title = "Paramètres", + width = NULL, + status = "primary", + selectInput( + "acpDist", + label = "Distance :", + selected = "bray", + choices = list( + "bray", + "jaccard", + "unifrac", + "wunifrac", + "dpcoa", + "jsd", + "euclidean" + ) + ), + selectInput( + "acpMethod", + label = "Methode :", + selected = "MDS", + choices = list("DCA", "CCA", "RDA", "CAP", "DPCoA", "NMDS", "MDS", "PCoA") + ), + if (!is.null(input$fileMeta)) + { + selectInput( + "acpCol", + label = "Couleur :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "acpShape", + label = "Forme :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "acpEllipse", + label = "Ellipses :", + choices = c("..." = 0, sample_variables(data16S())) + ) + }, + if (!is.null(input$fileMeta)) + { + selectInput( + "acpRep", + label = "Barycentre :", + choices = c("..." = 0, sample_variables(data16S())) + ) + } + ) + }) + + output$acp <- renderPlot({ + validate(need( + !is.null(input$fileBiom), + "Merci d'importer un fichier d'abondance" + )) + p <- plot_samples( + data16S(), + ordination = ordinate( + data16S(), + method = input$acpMethod, + distance = input$acpDist + ), + axes = c(1, 2), + color = checkNull(input$acpCol), + replicate = checkNull(input$acpRep), + shape = checkNull(input$acpShape) + ) + if (!is.null(checkNull(input$acpEllipse))) { + p <- p + stat_ellipse(aes_string(group = input$acpEllipse)) + } + return(p + theme_bw()) + }) +}) \ No newline at end of file diff --git a/ui.R b/ui.R new file mode 100644 index 0000000..5154a3b --- /dev/null +++ b/ui.R @@ -0,0 +1,159 @@ +library(shinydashboard) +shinyUI(dashboardPage( + dashboardHeader(title = "Easy16S"), + dashboardSidebar( + tags$div( + title = "Fichier d'abondance au format BIOM produit avec FROGS avec 'FROGS BIOM to std BIOM'", + fileInput( + "fileBiom", + label = h4("Fichier d'abondance :"), + placeholder = "data.biom" + ), + radioButtons( + "biomFormat", + label = NULL, + inline = TRUE, + choices = list(`STD BIOM` = "std", + `FROGS BIOM` = "frogs"), + selected = "std" + ) + ), + tags$div( + style = "text-align:center", + title = "Rarefier les données avec un tirage aléatoire pour supprimer l'effet de la profondeur de séquençage", + checkboxInput("rareData", label = "Rarefier les donnees.", value = TRUE), + textOutput("rarefactionMin") + ), + tags$div( + title = "Tableau de métadonnées avec en colonne les variables, en ligne les échantillons. \nAssurez vous de bien respecter l'ortographe des noms d'échantillons (1ère colonne). \nL'import d'une table excel est possible mais déconseillé.", + fileInput( + "fileMeta", + label = h4("Metadata :"), + placeholder = "data.csv" + ) + ), + radioButtons( + "CSVsep", + label = "CSV Séparateur", + inline = TRUE, + choices = list( + `<tab>` = "\t", + `,` = ",", + `;` = ";", + excel = "excel" + ) + ), + tags$div( + title = "Arbre phylogéniques des OTU enracinné", + fileInput( + "fileTree", + label = h4("Arbre :"), + placeholder = "data.nwk" + ) + ), + tags$div( + title = "Séquences FASTA des OTU", + fileInput( + "fileSeq", + label = h4("Séquences de references :"), + placeholder = "data.fasta" + ) + ) + ), + dashboardBody( + tabsetPanel( + tabPanel( + "Summary", + verbatimTextOutput("phyloseqPrint"), + uiOutput("summaryTable") + ), + tabPanel( + "Histo global", + plotOutput("histo", height = 700), + uiOutput("histUI") + ), + tabPanel( + "Histo selectif", + plotOutput("histoFocus", height = 700), + box( + title = "Paramètres", + width = NULL, + status = "primary", + uiOutput("histFocusUIfocusRank"), + uiOutput("histFocusUIfocusTaxa"), + uiOutput("histFocusUIfocusNbTaxa"), + uiOutput("histFocusUIfocusGrid"), + uiOutput("histFocusUIfocusX") + ) + ), + tabPanel( + "Clustering", + plotOutput("clust", height = 700), + uiOutput("clustUI") + ), + tabPanel("Richesse alpha", box( + width = NULL, tabsetPanel( + tabPanel( + "Courbes", + htmlOutput("rarefaction"), + plotOutput("richnessA", height = 700), + uiOutput("richnessAUI") + ), + tabPanel("Tables", uiOutput("richnessATable")) + ) + )), + tabPanel( + "Richesse beta", + selectInput( + "richnessBDist", + label = "Distance :", + choices = list( + "bray", + "jaccard", + "unifrac", + "wunifrac", + "dpcoa", + "jsd", + "euclidean" + ) + ), + box(width = NULL, tabsetPanel( + tabPanel( + "Heatmap", + plotOutput("richnessB", height = 700), + uiOutput("richnessBUI") + ), + tabPanel( + "Networks", + plotOutput("networkB", height = 700), + uiOutput("networkBUI") + ), + tabPanel("Tables", uiOutput("richnessBTable")) + )) + ), + tabPanel( + "Courbe de rarefaction", + plotOutput("rarefactionCurve", height = 700), + uiOutput("rarefactionCurveUI") + ), + tabPanel( + "Arbre phylo", + plotOutput("tree", height = 700), + uiOutput("treeUI") + ), + tabPanel( + "Heatmap", + plotOutput("Heatmap", height = 700), + uiOutput("HeatmapUI") + ), + tabPanel("Analyses multivariées", plotOutput("acp", height = 700), uiOutput("acpUI")), + tabPanel( + "et plus ...", + div( + "Merci d'adresser vos remarques, bugs, demandes, besoins et conseils à ", + a(href = "mailto:cedric.midoux@irstea.fr?subject=[Easy16S]", "cedric.midoux@irstea.fr") + ) + ) + ) + ) +)) \ No newline at end of file -- GitLab