Team Ai
Apppublic

softwareDevelopment/qtl_seq

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes
app.R498 linesDownload Raw Back to root
1library(shiny)2library(shinyjs)3library(shinythemes)4library(shinyBS)5library(plotly)6library(DT)7library(QTLseqr)8library(data.table)9library(dplyr)10library(tidyr)11library(vcfR)12library(ggplot2)13library(dbscan)14library(factoextra)15library(cluster)16library(viridis)17 18options(shiny.maxRequestSize = 100 * 1024^2)19 20# Modified qtlseq function21qtlseq <- function(input_csv = NULL,22                   refAlleleFreq = 0.20,23                   minTotalDepth = 100,24                   maxTotalDepth = 400,25                   minSampleDepth = 40,26                   minGQ = 99,27                   windowSize = NULL,28                   popStruc = NULL,29                   bulkSize = NULL,30                   replications = 10000,31                   intervals = c(95, 99),32                   alpha = 0.01,33                   save_plot = FALSE,34                   save_csv = FALSE) {35  data <- read.csv(input_csv)36  output_table <- tempfile(fileext = ".table")37  write.table(data, file = output_table, sep = "\t", row.names = FALSE, quote = FALSE)38  39  col_data <- colnames(data[5:ncol(data)])40  unique_samples <- unique(sub("\\..*", "", col_data))41  42  HighBulk <- unique_samples[1]43  LowBulk <- unique_samples[2]44  45  df <- importFromGATK(file = output_table, highBulk = HighBulk, lowBulk = LowBulk)46  47  df_filt <- filterSNPs(48    SNPset = df,49    refAlleleFreq = refAlleleFreq,50    minTotalDepth = minTotalDepth,51    maxTotalDepth = maxTotalDepth,52    minSampleDepth = minSampleDepth,53    minGQ = minGQ54  )55  56  df_filt <- runGprimeAnalysis(57    SNPset = df_filt,58    windowSize = windowSize,59    outlierFilter = "deltaSNP"60  )61  62  df_filt1 <- runQTLseqAnalysis(63    SNPset = df_filt,64    windowSize = windowSize,65    popStruc = popStruc,66    bulkSize = bulkSize,67    replications = replications,68    intervals = intervals69  )70  71  p <- ggplot(df_filt1, aes(x = POS / 1e6)) +72    geom_point(aes(y = deltaSNP), color = "blue", size = 0.5, alpha = 0.6) +73    geom_line(aes(y = tricubeDeltaSNP), color = "red", size = 0.8) +74    geom_line(aes(y = CI_95), color = "orange", linetype = "solid", size = 0.6) +75    geom_line(aes(y = -CI_95), color = "orange", linetype = "solid", size = 0.6) +76    geom_line(aes(y = CI_99), color = "green", linetype = "solid", size = 0.6) +77    geom_line(aes(y = -CI_99), color = "green", linetype = "solid", size = 0.6) +78    geom_hline(yintercept = c(-1, 0, 1), linetype = "dashed", color = "skyblue", alpha = 0.7) +79    facet_wrap(~CHROM, ncol = 4, scales = "free_x") +80    labs(x = "Position (Mb)", y = expression(Delta *"SNP-index"),81         title = "QTLseq Analysis: Delta SNP-index across Chromosomes") +82    theme_minimal(base_size = 12) +83    theme(84      strip.text = element_text(face = "bold", size = 10),85      axis.title = element_text(face = "bold"),86      plot.title = element_text(face = "bold", hjust = 0.5)87    )88  89  if (save_plot) ggsave("deltaSNPIndex.png", plot = p, dpi = 600, width = 12, height = 10, units = "in")90  91  qtl_table <- getQTLTable(SNPset = df_filt1, alpha = alpha, export = save_csv, fileName = "BSA_QTLseq.csv")92  93  return(list(QTLseqResults = df_filt1, GprimeResults = df_filt, plot = p, qtl_table = qtl_table))94}95 96# UI97ui <- fluidPage(98  theme = shinytheme("cerulean"),99  useShinyjs(),100  101  tags$head(102    tags$style(HTML("103      body { background-color: #f4f4f9; font-family: Arial, sans-serif; }104      .well { background-color: #ffffff; border: 1px solid #ddd; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }105      .btn-primary { background-color: #4CAF50; border-color: #4CAF50; }106      .btn-primary:hover { background-color: #45a049; }107      h3 { color: #333; font-weight: bold; }108      .infographic { 109        border: 2px solid #2196F3; 110        border-radius: 15px; 111        padding: 20px; 112        margin: 15px 0; 113        background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);114        box-shadow: 0 4px 8px rgba(0,0,0,0.1);115      }116      .info-header { 117        color: #1976d2; 118        border-bottom: 2px solid #64b5f6; 119        padding-bottom: 10px;120        margin-bottom: 15px;121      }122      .ml-card {123        background: white;124        border-radius: 10px;125        padding: 15px;126        margin: 10px 0;127        box-shadow: 0 2px 4px rgba(0,0,0,0.1);128        border-left: 4px solid #4CAF50;129      }130    "))131  ),132  133  titlePanel("QTLseq Shiny App: Advanced BSA with Machine Learning Insights"),134  135  sidebarLayout(136    sidebarPanel(137      fileInput("input_csv", "Upload Input CSV", accept = ".csv"),138      numericInput("refAlleleFreq", "Reference Allele Frequency", value = 0.20, min = 0, max = 1, step = 0.01),139      bsTooltip("refAlleleFreq", "Fraction of reads matching reference allele", placement = "right"),140      numericInput("minTotalDepth", "Min Total Depth", value = 100),141      bsTooltip("minTotalDepth", "Minimum total read depth for SNPs", placement = "right"),142      numericInput("maxTotalDepth", "Max Total Depth", value = 400),143      numericInput("minSampleDepth", "Min Sample Depth", value = 40),144      numericInput("minGQ", "Min GQ", value = 99),145      numericInput("windowSize", "Window Size", value = 5e5),146      selectInput("popStruc", "Population Structure", choices = c("F2", "RIL", "BC1")),147      textInput("bulkSize", "Bulk Size (e.g., 20,20)", value = "20,20"),148      numericInput("replications", "Replications", value = 10000),149      textInput("intervals", "Intervals (e.g., 95,99)", value = "95,99"),150      numericInput("alpha", "Alpha", value = 0.01, min = 0, max = 1, step = 0.01),151      actionButton("runAnalysis", "Run Analysis", class = "btn-primary")152    ),153    154    mainPanel(155      tabsetPanel(156        tabPanel("QTLseq Results",157                 plotlyOutput("deltaPlot"),158                 downloadButton("downloadPlot", "Download Plot"),159                 DTOutput("qtlTable"),160                 downloadButton("downloadCSV", "Download QTL CSV")161        ),162        163        tabPanel("ML Insights",164                 h3("Machine Learning Integrations for Enhanced BSA Analysis"),165                 166                 tabsetPanel(167                   tabPanel("K-Means Clustering",168                            div(class = "infographic",169                                h4("๐ŸŽฏ Automated Region Clustering with K-Means", class = "info-header"),170                                p("K-Means clustering automatically groups genomic regions based on their deltaSNP patterns, revealing natural groupings without manual threshold setting."),171                                plotlyOutput("clusterPlot"),172                                DTOutput("clusterSummary")173                            )174                   ),175                   176                   tabPanel("Outlier Detection",177                            div(class = "infographic",178                                h4("๐Ÿ” DBSCAN Outlier SNP Detection", class = "info-header"),179                                p("DBSCAN identifies statistical outliers that may represent key causative variants, sequencing artifacts, or novel biological phenomena worth investigating."),180                                plotlyOutput("outlierPlot"),181                                DTOutput("outlierTable")182                            )183                   ),184                   185                   tabPanel("PCA Overview",186                            div(class = "infographic",187                                h4("๐Ÿ“Š Genome-wide Pattern Analysis with PCA", class = "info-header"),188                                p("Principal Component Analysis provides a big-picture view of genomic patterns, helping identify batch effects, population structure, or technical artifacts."),189                                plotlyOutput("pcaPlot"),190                                plotOutput("pcaVariancePlot")191                            )192                   )193                 )194        ),195        196        tabPanel("Advanced Visualizations",197                 h3("Enhanced Interactive Infographics"),198                 199                 div(class = "infographic",200                     h4("๐Ÿ“ˆ Interactive Chromosome Explorer", class = "info-header"),201                     p("Explore each chromosome individually with enhanced zoom and hover capabilities for detailed QTL region investigation."),202                     selectInput("chromSelect", "Select Chromosome:", choices = NULL),203                     plotlyOutput("chromosomePlot")204                 ),205                 206                 div(class = "infographic",207                     h4("๐ŸŒŠ 3D DeltaSNP Landscape", class = "info-header"),208                     p("Visualize the deltaSNP landscape across chromosomes in 3D, revealing spatial patterns and relationships between genomic regions."),209                     plotlyOutput("threeDPlot")210                 )211        )212      )213    )214  )215)216 217# Server218server <- function(input, output, session) {219  220  results <- reactiveVal()221  222  observeEvent(input$runAnalysis, {223    req(input$input_csv)224    showNotification("Running QTLseq analysis...", type = "message")225    226    bulkSize_vec <- as.numeric(unlist(strsplit(input$bulkSize, ",")))227    intervals_vec <- as.numeric(unlist(strsplit(input$intervals, ",")))228    229    tryCatch({230      res <- qtlseq(231        input_csv = input$input_csv$datapath,232        refAlleleFreq = input$refAlleleFreq,233        minTotalDepth = input$minTotalDepth,234        maxTotalDepth = input$maxTotalDepth,235        minSampleDepth = input$minSampleDepth,236        minGQ = input$minGQ,237        windowSize = input$windowSize,238        popStruc = input$popStruc,239        bulkSize = bulkSize_vec,240        replications = input$replications,241        intervals = intervals_vec,242        alpha = input$alpha243      )244      245      results(res)246      showNotification("Analysis completed successfully!", type = "message")247      248      # Update chromosome selector249      chrom_choices <- unique(res$QTLseqResults$CHROM)250      updateSelectInput(session, "chromSelect", choices = chrom_choices)251      252    }, error = function(e) {253      showNotification(paste("Error:", e$message), type = "error")254    })255  })256  257  # QTLseq Plot258  output$deltaPlot <- renderPlotly({259    req(results())260    ggplotly(results()$plot, tooltip = c("x", "y", "CHROM")) %>%261      layout(height = 800)262  })263  264  # Download Plot265  output$downloadPlot <- downloadHandler(266    filename = "deltaSNPIndex.png",267    content = function(file) {268      ggsave(file, plot = results()$plot, dpi = 600, width = 12, height = 10, units = "in")269    }270  )271  272  # QTL Table273  output$qtlTable <- renderDT({274    req(results())275    datatable(results()$qtl_table, 276              options = list(pageLength = 10, scrollX = TRUE),277              caption = "Significant QTL Regions")278  })279  280  # Download CSV281  output$downloadCSV <- downloadHandler(282    filename = "BSA_QTLseq.csv",283    content = function(file) {284      write.csv(results()$qtl_table, file, row.names = FALSE)285    }286  )287  288  # K-Means Clustering289  output$clusterPlot <- renderPlotly({290    req(results())291    df <- results()$QTLseqResults292    293    # Prepare data for clustering294    cluster_data <- df %>% 295      select(POS, tricubeDeltaSNP) %>% 296      drop_na() %>%297      sample_n(min(10000, nrow(.))) # Sample for performance298    299    # Perform K-Means Clustering300    set.seed(123)301    kmeans_result <- kmeans(cluster_data, centers = 3)302    303    # Add cluster assignment304    df_sample <- df %>%305      filter(row_number() %in% as.numeric(rownames(cluster_data))) %>%306      mutate(Cluster = as.factor(kmeans_result$cluster))307    308    p <- ggplot(df_sample, aes(x = POS/1e6, y = tricubeDeltaSNP, color = Cluster,309                              text = paste("CHROM:", CHROM, "<br>POS:", POS, 310                                         "<br>Cluster:", Cluster))) +311      geom_point(alpha = 0.7, size = 2) +312      scale_color_viridis_d(option = "plasma") +313      labs(x = "Position (Mb)", y = "Tricube Delta SNP-index",314           title = "K-Means Clustering of Genomic Regions",315           subtitle = "Colors represent automated grouping based on deltaSNP patterns") +316      theme_minimal() +317      theme(legend.position = "bottom")318    319    ggplotly(p, tooltip = "text") %>%320      layout(height = 500)321  })322  323  output$clusterSummary <- renderDT({324    req(results())325    df <- results()$QTLseqResults326    327    cluster_data <- df %>% select(POS, tricubeDeltaSNP) %>% drop_na()328    set.seed(123)329    kmeans_result <- kmeans(cluster_data, centers = 3)330    331    summary_df <- data.frame(332      Cluster = 1:3,333      Size = as.numeric(table(kmeans_result$cluster)),334      Center_Position = kmeans_result$centers[,1],335      Center_DeltaSNP = kmeans_result$centers[,2]336    )337    338    datatable(summary_df, options = list(dom = 't'),339              caption = "Cluster Summary Statistics")340  })341  342  # DBSCAN Outlier Detection343  output$outlierPlot <- renderPlotly({344    req(results())345    df <- results()$QTLseqResults346    347    # Prepare data348    dbscan_data <- df %>% 349      select(POS, deltaSNP) %>% 350      drop_na() %>%351      sample_n(min(5000, nrow(.))) # Sample for performance352    353    # Scale data354    scaled_data <- scale(dbscan_data)355    356    # Perform DBSCAN357    dbscan_result <- dbscan(scaled_data, eps = 0.5, minPts = 10)358    359    # Add outlier status360    df_sample <- df %>%361      filter(row_number() %in% as.numeric(rownames(dbscan_data))) %>%362      mutate(Outlier = ifelse(dbscan_result$cluster == 0, "Outlier", "Normal"))363    364    p <- ggplot(df_sample, aes(x = POS/1e6, y = deltaSNP, color = Outlier,365                              text = paste("CHROM:", CHROM, "<br>POS:", POS,366                                         "<br>Status:", Outlier))) +367      geom_point(alpha = 0.7, size = 2) +368      scale_color_manual(values = c("Outlier" = "red", "Normal" = "blue")) +369      labs(x = "Position (Mb)", y = "Delta SNP-index",370           title = "DBSCAN Outlier Detection",371           subtitle = "Red points represent statistical outliers") +372      theme_minimal() +373      theme(legend.position = "bottom")374    375    ggplotly(p, tooltip = "text") %>%376      layout(height = 500)377  })378  379  output$outlierTable <- renderDT({380    req(results())381    df <- results()$QTLseqResults382    383    dbscan_data <- df %>% select(POS, deltaSNP) %>% drop_na()384    scaled_data <- scale(dbscan_data)385    dbscan_result <- dbscan(scaled_data, eps = 0.5, minPts = 10)386    387    outlier_df <- df %>%388      filter(row_number() %in% as.numeric(rownames(dbscan_data))) %>%389      mutate(Outlier = ifelse(dbscan_result$cluster == 0, "Yes", "No")) %>%390      filter(Outlier == "Yes") %>%391      select(CHROM, POS, deltaSNP, tricubeDeltaSNP, REF_FRQ)392    393    datatable(outlier_df, options = list(pageLength = 5, scrollX = TRUE),394              caption = "Detected Outlier SNPs")395  })396  397  # PCA Analysis398  output$pcaPlot <- renderPlotly({399    req(results())400    df <- results()$QTLseqResults401    402    # Sample data for PCA (for performance)403    pca_data <- df %>%404      group_by(CHROM) %>%405      sample_n(min(50, n())) %>%406      ungroup() %>%407      select(POS, REF_FRQ, deltaSNP) %>%408      drop_na()409    410    # Perform PCA411    pca_result <- prcomp(pca_data, scale. = TRUE)412    413    pca_df <- as.data.frame(pca_result$x)414    pca_df$CHROM <- df$CHROM[1:nrow(pca_df)]415    416    p <- ggplot(pca_df, aes(x = PC1, y = PC2, color = CHROM,417                           text = paste("PC1: ", round(PC1, 2), 418                                      "<br>PC2: ", round(PC2, 2)))) +419      geom_point(alpha = 0.7, size = 3) +420      scale_color_viridis_d(option = "magma") +421      labs(title = "PCA of Genomic Features",422           subtitle = "Each point represents a genomic region") +423      theme_minimal()424    425    ggplotly(p, tooltip = "text") %>%426      layout(height = 500)427  })428  429  output$pcaVariancePlot <- renderPlot({430    req(results())431    df <- results()$QTLseqResults432    433    pca_data <- df %>%434      group_by(CHROM) %>%435      sample_n(min(50, n())) %>%436      ungroup() %>%437      select(POS, REF_FRQ, deltaSNP) %>%438      drop_na()439    440    pca_result <- prcomp(pca_data, scale. = TRUE)441    442    fviz_eig(pca_result, addlabels = TRUE, 443             main = "PCA - Variance Explained by Principal Components",444             barfill = "#4CAF50", barcolor = "#4CAF50") +445      theme_minimal()446  })447  448  # Chromosome-specific plot449  output$chromosomePlot <- renderPlotly({450    req(results(), input$chromSelect)451    df <- results()$QTLseqResults452    453    chrom_df <- df %>% filter(CHROM == input$chromSelect)454    455    p <- ggplot(chrom_df, aes(x = POS/1e6, y = tricubeDeltaSNP,456                             text = paste("Position:", POS, 457                                        "<br>DeltaSNP:", round(tricubeDeltaSNP, 3)))) +458      geom_line(color = "red", size = 1) +459      geom_ribbon(aes(ymin = -CI_99, ymax = CI_99), fill = "green", alpha = 0.1) +460      geom_hline(yintercept = 0, linetype = "dashed", color = "gray") +461      labs(x = "Position (Mb)", y = "Tricube Delta SNP-index",462           title = paste("Chromosome", input$chromSelect, "Detailed View")) +463      theme_minimal()464    465    ggplotly(p, tooltip = "text") %>%466      layout(height = 400)467  })468  469  # 3D Plot470  output$threeDPlot <- renderPlotly({471    req(results())472    df <- results()$QTLseqResults473    474    # Sample data for 3D plot475    plot_data <- df %>%476      group_by(CHROM) %>%477      sample_n(min(100, n())) %>%478      ungroup()479    480    plot_ly(plot_data, x = ~POS/1e6, y = ~as.numeric(factor(CHROM)), z = ~tricubeDeltaSNP,481            type = 'scatter3d', mode = 'markers',482            color = ~tricubeDeltaSNP,483            colors = viridis::viridis(100),484            marker = list(size = 3),485            text = ~paste("CHROM:", CHROM, "<br>POS:", POS, 486                         "<br>DeltaSNP:", round(tricubeDeltaSNP, 3))) %>%487      layout(scene = list(488        xaxis = list(title = 'Position (Mb)'),489        yaxis = list(title = 'Chromosome'),490        zaxis = list(title = 'Delta SNP-index')491      ),492      title = "3D Genomic Landscape of Delta SNP-index"493      )494  })495}496 497# Run the app498shinyApp(ui = ui, server = server)