CoolFace
Apppublic

softwareDevelopment/BSA-SNPindex

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes
app.R464 linesDownload Raw Back to root
1library(shiny)2library(QTLseqr)3library(data.table)4library(dplyr)5library(tidyr)6library(vcfR)7library(ggplot2)8options(shiny.maxRequestSize = 50*1024^3)9options(timeout = 3600)  10 11# QTL-seq Analysis Function12qtlseq <- function(input_csv = NULL,13                   output_table = "/tmp/output_file.table",14                   delta_snp_plot = NULL,15                   qtlseq_csv = "/tmp/BSA_QTLseq.csv",16                   refAlleleFreq = 0.20,17                   minTotalDepth = 100,18                   maxTotalDepth = 400,19                   minSampleDepth = 40,20                   minGQ = 99,21                   windowSize = NULL,22                   popStruc = NULL,23                   bulkSize = NULL,24                   replications = 10000,25                   intervals = c(95, 99),26                   alpha = 0.01) {27  28  data <- read.csv(input_csv)29  write.table(data, file = output_table, sep = "\t", row.names = FALSE, quote = FALSE)30  31  col_data <- colnames(data[5:ncol(data)])32  unique_samples <- unique(sub("\\..*", "", col_data))33  34  HighBulk <- unique_samples[1]35  LowBulk <- unique_samples[2]36  chroms <- as.vector(unique(data[1]))37  df <- importFromGATK(file = output_table, highBulk = HighBulk, lowBulk = LowBulk)38  39  df_filt <- filterSNPs(40    SNPset = df,41    refAlleleFreq = refAlleleFreq,42    minTotalDepth = minTotalDepth,43    maxTotalDepth = maxTotalDepth,44    minSampleDepth = minSampleDepth,45    minGQ = minGQ46  )47  48  df_filt <- runGprimeAnalysis(49    SNPset = df_filt,50    windowSize = windowSize,51    outlierFilter = "deltaSNP"52  )53  54  df_filt1 <- runQTLseqAnalysis(55    SNPset = df_filt,56    windowSize = windowSize,57    popStruc = popStruc,58    bulkSize = bulkSize,59    replications = replications,60    intervals = intervals61  )62  63  p <- ggplot(df_filt1, aes(x = POS)) +64    geom_point(aes(y = deltaSNP), color = "#3b82f6", size = 0.5) +65    geom_line(aes(y = tricubeDeltaSNP), color = "#ef4444", size = 0.8) +66    geom_line(aes(y = CI_95), color = "#f97316", linetype = "solid", size = 0.6) +67    geom_line(aes(y = -CI_95), color = "#f97316", linetype = "solid", size = 0.6) +68    geom_line(aes(y = CI_99), color = "#10b981", linetype = "solid", size = 0.6) +69    geom_line(aes(y = -CI_99), color = "#10b981", linetype = "solid", size = 0.6) +70    geom_hline(yintercept = c(-1, 0, 1), linetype = "dashed", color = "#0ea5e9") +71    facet_wrap(~CHROM, ncol = 4, scales = "free_x") +72    labs(x = "Position (Mb)", y = expression(Delta *"SNP-index")) +73    theme_minimal(base_size = 12) +74    theme(75      strip.text = element_text(face = "bold"),76      axis.title = element_text(face = "bold")77    )78  79  ggsave("/tmp/deltaSNPIndex.png", plot = p, dpi = 600, width = 12, height = 10, units = "in")80  81  getQTLTable(SNPset = df_filt1, alpha = alpha, export = TRUE, fileName = qtlseq_csv)82  83  return(list(QTLseqResults = df_filt1, GprimeResults = df_filt, plot = p))84}85 86# UI87ui <- fluidPage(88  tags$head(89    tags$style(HTML("90      @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');91      92      body {93        font-family: 'Poppins', sans-serif;94        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);95        min-height: 100vh;96        padding: 20px;97      }98      99      .main-container {100        background: white;101        border-radius: 20px;102        box-shadow: 0 20px 60px rgba(0,0,0,0.3);103        padding: 0;104        overflow: hidden;105        max-width: 1400px;106        margin: 0 auto;107      }108      109      .header {110        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);111        color: white;112        padding: 30px 40px;113        text-align: center;114      }115      116      .header h1 {117        margin: 0;118        font-size: 2.5em;119        font-weight: 700;120        text-shadow: 2px 2px 4px rgba(0,0,0,0.2);121      }122      123      .header p {124        margin: 10px 0 0 0;125        font-size: 1.1em;126        opacity: 0.95;127      }128      129      .content-wrapper {130        padding: 40px;131      }132      133      .section-title {134        color: #667eea;135        font-size: 1.5em;136        font-weight: 600;137        margin-bottom: 20px;138        padding-bottom: 10px;139        border-bottom: 3px solid #667eea;140      }141      142      .card {143        background: #f8f9fa;144        border-radius: 15px;145        padding: 25px;146        margin-bottom: 30px;147        box-shadow: 0 4px 6px rgba(0,0,0,0.1);148        transition: transform 0.3s ease;149      }150      151      .card:hover {152        transform: translateY(-5px);153        box-shadow: 0 8px 12px rgba(0,0,0,0.15);154      }155      156      .upload-area {157        border: 3px dashed #667eea;158        border-radius: 15px;159        padding: 30px;160        text-align: center;161        background: linear-gradient(135deg, #f0f4ff 0%, #e9d5ff 100%);162        transition: all 0.3s ease;163      }164      165      .upload-area:hover {166        border-color: #764ba2;167        background: linear-gradient(135deg, #e9d5ff 0%, #f0f4ff 100%);168      }169      170      .btn-primary {171        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);172        border: none;173        color: white;174        padding: 12px 30px;175        font-size: 1.1em;176        font-weight: 600;177        border-radius: 25px;178        cursor: pointer;179        transition: all 0.3s ease;180        box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);181      }182      183      .btn-primary:hover {184        transform: translateY(-2px);185        box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);186      }187      188      .shiny-input-container {189        margin-bottom: 20px;190      }191      192      .shiny-input-container label {193        color: #4a5568;194        font-weight: 600;195        margin-bottom: 8px;196        display: block;197      }198      199      input[type='number'], input[type='text'], select {200        width: 100%;201        padding: 12px;202        border: 2px solid #e2e8f0;203        border-radius: 10px;204        font-size: 1em;205        transition: all 0.3s ease;206        font-family: 'Poppins', sans-serif;207      }208      209      input[type='number']:focus, input[type='text']:focus, select:focus {210        outline: none;211        border-color: #667eea;212        box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);213      }214      215      .param-grid {216        display: grid;217        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));218        gap: 20px;219      }220      221      .progress-section {222        background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);223        border-radius: 15px;224        padding: 20px;225        margin: 20px 0;226        text-align: center;227      }228      229      .results-section {230        background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);231        border-radius: 15px;232        padding: 25px;233        margin-top: 20px;234      }235      236      .plot-container {237        background: white;238        border-radius: 10px;239        padding: 20px;240        box-shadow: 0 4px 6px rgba(0,0,0,0.1);241        margin-top: 20px;242      }243      244      .download-btn {245        background: linear-gradient(135deg, #10b981 0%, #059669 100%);246        border: none;247        color: white;248        padding: 10px 25px;249        font-weight: 600;250        border-radius: 20px;251        cursor: pointer;252        margin: 5px;253        transition: all 0.3s ease;254      }255      256      .download-btn:hover {257        transform: translateY(-2px);258        box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);259      }260      261      .info-box {262        background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);263        border-left: 4px solid #3b82f6;264        padding: 15px;265        border-radius: 10px;266        margin: 15px 0;267      }268      269      .shiny-notification {270        position: fixed;271        top: 20px;272        right: 20px;273        border-radius: 10px;274        font-family: 'Poppins', sans-serif;275      }276    "))277  ),278  279  div(class = "main-container",280      div(class = "header",281          h1("๐Ÿงฌ QTL-seq Analysis Platform"),282          p("Quantitative Trait Loci Sequencing Analysis Tool")283      ),284      285      div(class = "content-wrapper",286          # File Upload Section287          div(class = "card",288              h3(class = "section-title", "๐Ÿ“ Data Input"),289              div(class = "upload-area",290                  fileInput("csvFile", 291                            label = NULL,292                            accept = c(".csv"),293                            buttonLabel = "Browse...",294                            placeholder = "Select CSV file"),295                  p(style = "color: #667eea; font-weight: 600; margin-top: 10px;",296                    "Upload your QTL-seq data in CSV format")297              )298          ),299          300          # Parameters Section301          div(class = "card",302              h3(class = "section-title", "โš™๏ธ Analysis Parameters"),303              div(class = "info-box",304                  p(style = "margin: 0; color: #1e40af;", 305                    "๐Ÿ“Œ Configure analysis parameters below. Default values are pre-filled.")306              ),307              308              div(class = "param-grid",309                  numericInput("refAlleleFreq", "Reference Allele Frequency", 0.20, min = 0, max = 1, step = 0.01),310                  numericInput("minTotalDepth", "Min Total Depth", 100, min = 0),311                  numericInput("maxTotalDepth", "Max Total Depth", 400, min = 0),312                  numericInput("minSampleDepth", "Min Sample Depth", 40, min = 0),313                  numericInput("minGQ", "Min Genotype Quality", 99, min = 0, max = 100),314                  numericInput("windowSize", "Window Size", 500000, min = 0)315              ),316              317              div(class = "param-grid", style = "margin-top: 20px;",318                  selectInput("popStruc", "Population Structure", 319                              choices = c("F2" = "F2", "RIL" = "RIL", "BC" = "BC")),320                  textInput("bulkSize", "Bulk Sizes (comma-separated)", "20,20"),321                  numericInput("replications", "Replications", 10000, min = 1000),322                  numericInput("alpha", "Alpha Level", 0.01, min = 0, max = 1, step = 0.01)323              )324          ),325          326          # Run Analysis Button327          div(style = "text-align: center; margin: 30px 0;",328              actionButton("runAnalysis", "๐Ÿš€ Run QTL-seq Analysis", 329                           class = "btn-primary",330                           style = "font-size: 1.2em; padding: 15px 40px;")331          ),332          333          # Progress Section334          conditionalPanel(335            condition = "input.runAnalysis > 0",336            div(class = "progress-section",337                h4(style = "color: #92400e; margin-top: 0;", "โณ Analysis in Progress..."),338                uiOutput("progressText")339            )340          ),341          342          # Results Section343          conditionalPanel(344            condition = "output.plotReady",345            div(class = "results-section",346                h3(class = "section-title", style = "color: #059669;", "โœ… Analysis Complete!"),347                348                div(class = "plot-container",349                    h4(style = "color: #4a5568; margin-top: 0;", "Delta SNP-index Plot"),350                    plotOutput("deltaPlot", height = "800px")351                ),352                353                div(style = "text-align: center; margin-top: 20px;",354                    downloadButton("downloadPlot", "๐Ÿ“Š Download Plot", class = "download-btn"),355                    downloadButton("downloadQTL", "๐Ÿ“„ Download QTL Table", class = "download-btn"),356                    downloadButton("downloadResults", "๐Ÿ’พ Download All Results", class = "download-btn")357                ),358                359                div(style = "margin-top: 30px;",360                    h4(style = "color: #4a5568;", "๐Ÿ“Š QTL Summary Statistics"),361                    tableOutput("qtlSummary")362                )363            )364          )365      )366  )367)368 369# Server370server <- function(input, output, session) {371  results <- reactiveValues(data = NULL, plot = NULL)372  373  observeEvent(input$runAnalysis, {374    req(input$csvFile)375    376    withProgress(message = 'Running QTL-seq Analysis', value = 0, {377      tryCatch({378        incProgress(0.2, detail = "Loading data...")379        380        bulkSizes <- as.numeric(strsplit(input$bulkSize, ",")[[1]])381        382        incProgress(0.3, detail = "Filtering SNPs...")383        384        result <- qtlseq(385          input_csv = input$csvFile$datapath,386          refAlleleFreq = input$refAlleleFreq,387          minTotalDepth = input$minTotalDepth,388          maxTotalDepth = input$maxTotalDepth,389          minSampleDepth = input$minSampleDepth,390          minGQ = input$minGQ,391          windowSize = input$windowSize,392          popStruc = input$popStruc,393          bulkSize = bulkSizes,394          replications = input$replications,395          alpha = input$alpha396        )397        398        incProgress(0.8, detail = "Generating plots...")399        400        results$data <- result401        results$plot <- result$plot402        403        incProgress(1, detail = "Complete!")404        405        showNotification("Analysis completed successfully!", type = "message", duration = 5)406        407      }, error = function(e) {408        showNotification(paste("Error:", e$message), type = "error", duration = 10)409      })410    })411  })412  413  output$plotReady <- reactive({414    return(!is.null(results$plot))415  })416  outputOptions(output, "plotReady", suspendWhenHidden = FALSE)417  418  output$deltaPlot <- renderPlot({419    req(results$plot)420    results$plot421  })422  423  output$qtlSummary <- renderTable({424    req(results$data)425    qtl_table <- read.csv("/tmp/BSA_QTLseq.csv")426    head(qtl_table, 10)427  })428  429  output$progressText <- renderUI({430    p(style = "color: #92400e; font-weight: 600;", 431      "Please wait while the analysis is running. This may take several minutes...")432  })433  434  output$downloadPlot <- downloadHandler(435    filename = function() {436      paste("deltaSNPIndex_", Sys.Date(), ".png", sep = "")437    },438    content = function(file) {439      file.copy("/tmp/deltaSNPIndex.png", file)440    }441  )442  443  output$downloadQTL <- downloadHandler(444    filename = function() {445      paste("BSA_QTLseq_", Sys.Date(), ".csv", sep = "")446    },447    content = function(file) {448      file.copy("/tmp/BSA_QTLseq.csv", file)449    }450  )451  452  output$downloadResults <- downloadHandler(453    filename = function() {454      paste("QTLseq_results_", Sys.Date(), ".zip", sep = "")455    },456    content = function(file) {457      files <- c("/tmp/deltaSNPIndex.png", "/tmp/BSA_QTLseq.csv", "/tmp/output_file.table")458      zip(file, files[file.exists(files)])459    }460  )461}462 463# Run the application464shinyApp(ui = ui, server = server)