R/EDAUserInterface.R

Defines functions EDAUserInterface

Documented in EDAUserInterface

#' UI function for EDA module in Shiny application
#' @param id Shiny module identifier

EDAUserInterface <- function(id) {
  bslib::layout_sidebar(

      htmltools::tags$head(
        htmltools::tags$style(htmltools::HTML("
        .tooltip-inner {
          max-width: 400px;  /* Adjust the width */
          white-space: normal;  /* Allow text to wrap */
          text-align: left;  /* Optional: aligns text to the left */
          border-radius: 4px !important;  /* Less curvature */
          background-color: #202020;      /* Optional: lighter background */
          color: #FFFFFF;                 /* Optional: darker text for readability */
          border: 1px solid #ccc;         /* Optional: subtle border */
        }
      "))
      ),
      htmltools::tags$style(".selectize-dropdown {position: static}"),
      shinyjs::useShinyjs(), # Enables JavaScript for more interactive features
      rintrojs::introjsUI(), # Allows the use of intro.js for creating interactive onboarding tours
      bslib::input_dark_mode(id = "dark_mode"), # Toggle for dark mode

    # sidebar EDA User Interface
      sidebar = bslib::sidebar(
        width = "23%",

        # 1 step - Import count matrices obtained from summarization step
          shiny::fluidRow(column(
            12, align = "left", htmltools::h5("Step 1 - Import count matrices"), htmltools::br()
          )),

          shiny::fluidRow(column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shinyFiles::shinyDirButton(shiny::NS(id, "directory_raw_count"),
                "Select_input_folder",
                "Please select the folder where the raw counts of the samples are stored"
                ,
                icon = shiny::icon("upload")
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "This is the input folder containing the count matrices for each sample in tab-separated format (e.g., '<sampleName>.tab'). Each column in the file is separated by tabs, and the files are the result of the summarization step. Ensure that the folder only contains the count matrices. The file names will be used as sample names, with the '.tab' extension removed. If files not generated by the inDAGO summarization module are uploaded, you must select the columns corresponding to genes and counts after loading the files. The 'col1' column should contain the gene names, while 'col2' should contain the quantification data. Additionally, make sure to remove any initial accessory rows.", placement = "right")
            ),
            # Displays the selected input directory path
            shiny::verbatimTextOutput(shiny::NS(id, "directory_raw_count_path")),

          )),

        # 2 step - Assigns groups by loading or creating matrix with 'Samples' and 'Groups'
          shiny::fluidRow(column(12, align = "left",  htmltools::tags$hr(
            htmltools::h5("Step 2 - Group assignment")
          ), htmltools::br())),

          shiny::fluidRow(column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::radioButtons(shiny::NS(id, "Import_table_exp"),
                label = "How to assign groups",
                choices = c("Load the matrix" = "Loading", "Generate the matrix" = "Create"),
                selected = "Loading"
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Upload a CSV or TAB-separated file containing 'Samples' and 'Groups' metadata, or generate the table interactively. Completing either task is sufficient; if both are done, only the uploaded file will be used. For more details, click the 'Info' button.", placement = "right")
            )
          )),

          # Conditional panel that appears if Import_table_exp == 'Loading'
          shiny::conditionalPanel(condition = sprintf("input['%s'] == 'Loading'", shiny::NS(id, "Import_table_exp")),
                           shiny::fluidRow(
            column(
              width = 12,
              shiny::splitLayout(
                cellWidths = c("90%", "10%"),
                shinyFiles::shinyFilesButton(shiny::NS(id, "assignGroupByTable"),
                  label = "Select_input_table",
                  title = "Please select the input table"
                  ,
                  icon = shiny::icon("upload"),
                  multiple = FALSE
                ),
                bslib::tooltip(bsicons::bs_icon("question-circle"), "This input table must contain two columns: 'Samples' and 'Groups'. The 'Samples' column should list sample names (e.g., A1, A2, A3, B1, B2, B3, C1, C2, C3), while the 'Groups' column should indicate the corresponding group names (e.g., A, A, A, B, B, B, C, C, C).", placement = "right")
              ),
              # Displays the selected file
              shiny::verbatimTextOutput(shiny::NS(id, "AssignGroupByTablePath")),

            )
          )),
          # Conditional panel that appears if Import_table_exp == 'Create'
          shiny::conditionalPanel(condition = sprintf("input['%s'] == 'Create'", shiny::NS(id,"Import_table_exp")),
                           shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::actionButton(shiny::NS(id, "assign_group"),
                           label = "View_matrix",
                           shiny::icon("table")),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "View table for group assignment'", placement = "right")
            )
          )), htmltools::br()),

        # 3 step - set options used to process data and generate edger DGEList object
          shiny::fluidRow(shiny::column(12, align = "left",  htmltools::tags$hr(
            htmltools::h5("Step 3 - Data Processing")
          ), htmltools::br())),

          # input: Set the filtering method
          shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::radioButtons(shiny::NS(id, "filterMethodPreProcess"),
                "Filter mode",
                choices = c("filterByExpr", "HTSFilter"),
                selected = "filterByExpr"
              ),
              bslib::tooltip(
                bsicons::bs_icon("question-circle"),
                "Choose a filter to use. The filterByExpr function, the default in edgeR, keeps rows with sufficient counts in a minimum number of samples. On the other hand, the HTSFilter function, implemented in the HTSFilter package, performs a filtering procedure for replicated transcriptome sequencing data using a global Jaccard similarity index. This identifies genes with low, constant levels of expression across one or more experimental conditions. The default parameters for HTSFilter are s.min = 1, s.max = 200, and s.len = 100. Please refer to the package documentation for further details. Note that to use the HTSFilter function, each experimental condition must have more than one biological replicate. 'filterByExpr' by deafult",
                placement = "right"
              )
            )
          )),

          shiny::conditionalPanel(
            condition = sprintf("input['%s'] == 'filterByExpr'", shiny::NS(id, "filterMethodPreProcess")),
          #input : set the minimum count required for at least some samples
          shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::numericInput(shiny::NS(id, "min_count"),
                label = "min_count",
                min = 1,
                value = 10
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Minimum count required for at least some samples. '10' by default", placement = "right")
            )
          )),

          # input: set the minimum total count required
          shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::numericInput(shiny::NS(id,  "min_total_count"),
                label = "min_total_count",
                min = 1,
                value = 15
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Minimum total count required. '15' by default", placement = "right")
            )
          )),

          # input: set number of samples per group that is considered to be “large”
          shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::numericInput(shiny::NS(id,  "large_n"),
                label = "large_n",
                min = 1,
                value = 10
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Number of Samples per group considered 'large'. '10' by default", placement = "right")
            )
          )),

          # input: In large sample situations, the minimum percentage of samples within a group in which a gene must be expressed
          shiny::fluidRow(shiny::column(
            width = 12, shiny::splitLayout(
              cellWidths = c("90%", "10%"),
              shiny::numericInput(shiny::NS(id,  "min_prop"),
                label = "min_prop",
                min = 0.1,
                value = 0.7,
                step = 0.1
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "In 'large' sample situations, the minimum percentage of samples within a group in which a gene must be expressed. '0.7' by default", placement = "right")
            )
          ))
          ),
          # close condition panel filterDEG == 'filterByExpr'

          #input : set the normalization method
          shiny::fluidRow(shiny::column(width = 12,shiny::splitLayout(cellWidths = c("90%", "10%"),
                                                 shiny::radioButtons(shiny::NS(id, "normMethodExp"),
                                                   "Normalization method",
                                                   choices = c("TMM","RLE"),
                                                   selected = "TMM"
                                                 ),
                                                 bslib::tooltip(
                                                   bsicons::bs_icon("question-circle"),
                                                   "The normalization method is used to adjust library sizes in a way that minimizes the log-fold changes between samples for most genes. The Trimmed Mean of M-values (TMM) is a scaling normalization method proposed by Robinson and Oshlack (2010). Alternatively, Relative Log Expression (RLE), a scaling factor method proposed by Anders and Huber (2010), can be used. 'TMM' by deafult",
                                                   placement = "right"
                                                 )))),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              #  The button to trigger the preparation of necessary input for plot generation
              shiny::actionButton(shiny::NS(id, "RunAnalysisExp"),
                           label = "Run processing",
                           class = "btn-primary",
                           shiny::icon("filter")),
              disabled(
                shiny::actionButton(shiny::NS(id, "killRunAnalysisExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Run the analysis to process the data. This involves generating an edgeR DGEList object and retaining only the genes with sufficiently high counts to ensure the data is displayed accurately.", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunAnalysisExpNote"))

          )),


        # 4 step - RUN plot
          shiny::fluidRow(shiny::column(12, align = "center",  htmltools::tags$hr(
            htmltools::h5("Step 4 - Generate plots")
          ), htmltools::br())),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the MDS analysis
              shiny::actionButton(shiny::NS(id, "RunMDSExp"),
                           label = "MDS",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              disabled(
                #  Button to enable deletion of MDS chart analysis
                shiny::actionButton(shiny::NS(id, "killRunMDSExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate-MultiDimensional Scaling (MDS) plot", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunMDSExpNote"))

          )),

          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the PCA analysis
              shiny::actionButton(shiny::NS(id, "RunPCAExp"),
                           label = "PCA",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of PCA chart analysis
                shiny::actionButton(shiny::NS(id, "killRunPCAExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate Principal Component Analysis (PCA) plot", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunPCAExpNote"))

          )),

          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the box plot analysis
              shiny::actionButton(shiny::NS(id, "RunBoxplotExp"),
                           label =  "Box plot",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of box chart analysis
                shiny::actionButton(shiny::NS(id, "killRunBoxplotExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate Box plot", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunBoxplotExpNote"))

          )),

          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the bar plot analysis
              shiny::actionButton(shiny::NS(id, "RunBarplotExp"),
                           label =  "Bar plot",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of bar chart analysis
                shiny::actionButton(shiny::NS(id, "killRunBarplotExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate Bar plot", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunBarplotExpNote"))

          )),

          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the Exp.heatmap analysis
              shiny::actionButton(shiny::NS(id, "RunHeatmapExp"),
                           label = "Exp.heatmap",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of Exp.heatmap chart analysis
                shiny::actionButton(shiny::NS(id, "killRunHeatmapExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate heat map based on the genes with the most variable expression levels between samples", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunHeatmapExpNote"))

          )),

          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the Cor.heatmap analysis
              shiny::actionButton(shiny::NS(id, "RunCorrPlotExp"),
                           label = "Cor.heatmap",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of Cor.heatmap chart analysis
                 shiny::actionButton(shiny::NS(id, "killRunCorrPlotExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate a heat map considering the correlation (pearson or spearman) between samples", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunCorrPlotExpNote"))

          )),
          htmltools::br(),

          shiny::fluidRow(shiny::column(
            width = 12,
            shiny::splitLayout(
              cellWidths = c("60%", "30%", "10%"),
              # Button to trigger the saturation analysis
              shiny::actionButton(shiny::NS(id, "RunSatPlotExp"),
                           label = "Sat. plot",
                           class = "btn-primary",
                           shiny::icon("rocket")),
              shinyjs::disabled(
                # Button to enable deletion of saturation chart analysis
                shiny::actionButton(shiny::NS(id,  "killRunSatPlotExp"),
                  label = "Kill",
                  class = "btn-warning",
                  icon = shiny::icon("fire")
                )
              ),
              bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate saturation plot", placement = "right")
            ),

            shiny::verbatimTextOutput(shiny::NS(id, "RunSatPlotExpNote"))

          ))
      ),

      # MAIN PANEL ________________________________________________________________

      bslib::accordion(

        # Dropdown button for information about the summarization process
        shinyWidgets::dropdownButton(inputId = shiny::NS(id, "InfoExploration"),
          status = "info",
          label = "Info",
          size = "sm",
          circle = FALSE,
          # Detailed description of the data exploration process
          htmltools::h3(shiny::strong("Data exploration process")),
          htmltools::br(),
          htmltools::h5(strong("WHEN TO PERFORM")),
          htmltools::h5("The data exploration process should be conducted after the summarization step and before detecting differentially
             expressed genes (DEGs)."),
          htmltools::br(),
          htmltools::br(),
          htmltools::h6(strong("WHAT IT DOES")),
          htmltools::h6("The purpose of data exploration is to identify patterns, trends, irregularities, or potential
             issues that could affect subsequent analyses. At this stage, users can refine their research
             questions or decide to collect new data if the current dataset is inadequate. The module outputs a
             series of exploratory plots to visualize patterns, detect potential outliers, and generate publication-ready figures."),
          htmltools::br(),
          htmltools::h6("Users can interactively modify all plots, adjusting colors and other settings for better visualization. "),
          htmltools::h6("Customization options include:"),
          htmltools::h6("- selecting the output path, format ('jpeg', 'png', 'tiff', 'eps', 'svg', or 'pdf'"),
          htmltools::h6("- adjusting resolution (in dpi)"),
          htmltools::h6("- setting dimensions (height and width) in inches, centimeters, millimeters, or pixels."),
          htmltools::h6("The module generates plots at two stages, before and after normalization, allowing users to visually assess normalization effects."),
          htmltools::br(),
          htmltools::h6("The input data for exploration consists of:"),
          htmltools::br(),
          htmltools::h6("-	count matrices: Results from the summarization step, where filenames (excluding extensions like .tab) serve as sample names."),
          htmltools::h6("- metadata table: A 'CSV' or 'TAB' file assigning groups to samples, structured in two columns as follows:"),
          htmltools::br(),
          htmltools::h6("Example:"),
          htmltools::h6("Samples,Groups"),
          htmltools::h6("A1,A"),
          htmltools::h6("A2,A"),
          htmltools::h6("A3,A"),
          htmltools::h6("B1,B"),
          htmltools::h6("B2,B"),
          htmltools::h6("B3,B"),
          htmltools::h6("C1,C"),
          htmltools::h6("C2,C"),
          htmltools::h6("C3,C"),
          htmltools::br(),
          htmltools::h6("Users can also generate this table interactively using the 'Generate the Matrix' button."),
          htmltools::br(),
          htmltools::br(),
          htmltools::h6(strong("OPERATIONAL INSTRUCTIONS")),
          htmltools::br(),
          htmltools::h6(strong("Step 1 - Import count matrices")),
          htmltools::h6("-	Celect the folder containing count matrix files in .tab format (e.g., <sampleName>.tab)."),
          htmltools::br(),
          htmltools::h6(strong("Step 2- Group assignment")),
          htmltools::h6("- Choose the metadata file in CSV or TAB format or create it interactively."),
          htmltools::br(),
          htmltools::h6(strong("Step 3 - Data Processing")),
          htmltools::h6("-	Process the data to generate edgeR objects."),
          htmltools::br(),
          htmltools::h6(strong("Step 4 - Generate plots")),
          htmltools::h6("- Generate the desired plots for visualization."),
          htmltools::br(),
          htmltools::br(),
          htmltools::h6(strong("RESULT")),
          htmltools::br(),
          htmltools::h6("- The module generates various plots exploring both pre-normalized and post-normalized data:"),
          htmltools::h6("- MultiDimensional Scaling (MDS)"),
          htmltools::h6("- Principal Component Analysis (PCA)"),
          htmltools::h6("- Box plot"),
          htmltools::h6("- Bar plot"),
          htmltools::h6("- Heat map: conserning most variable expressed genes or correlation of genes between samples"),
          htmltools::h6("- saturation plot"),
          htmltools::br(),
          htmltools::br(),
          htmltools::h6(strong("ADDITIONALLY NOTES")),
          htmltools::br(),
          htmltools::h6("Users can modify additional plot parameters after generation for better customization."),
          htmltools::br(),
          htmltools::br()
        ),
        htmltools::br(),

        # Section to view count matrices imported
          bslib::accordion_panel(
            title = "Step 1 Result - Import count matrices",
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "Here, we present the count matrices for each sample. Ensure that the first column lists the gene names and the second column contains the corresponding counts. You can select the relevant columns and remove any rows without count values using the control window on the right. The default settings assume the files are in the format produced by the inDAGO quantification process.",
              placement = "right"
            ),
            # Card to display the count matrix and sidebar controls for adjusting the view
            bslib::card(full_screen = TRUE, bslib::layout_sidebar(
              sidebar = bslib::sidebar(
                title = "Local controls",
                position = "right",

                # Sidebar control to set the number of lines to skip in the matrix
                shiny::fluidRow(shiny::column(12, align = "center", htmltools::h5("Check matrices"), htmltools::br())),

                # Numeric input for skipping rows in the matrix
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id,  "skip_preN"),
                      label = "Number of lines to skip",
                      min = 0,
                      value = 0
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Remove any rows that lack count values (e.g., rows containing statistical summaries or the total quantification result).", placement = "right")
                  )
                )),

                # Numeric input to specify the column containing gene IDs
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id,  "colIDgene"),
                      label = "Gene column",
                      min = 1,
                      value = 1
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the column with the gene names.", placement = "right")
                  )
                )),
                # Numeric input to specify the column containing counts
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "colCounts"),
                      label = "Count column",
                      min = 1,
                      value = 2
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the column with the count for each gene.", placement = "right")
                  )
                )),
                # Select which sample matrix to view
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "selectpn"),
                                label = "Number of imported matrices: 0",
                                choices = ""),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select a sample to view.", placement = "right")
                  )
                )),
                # Display either the full matrix or just the first few rows
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "disp"),
                      label = "Display",
                      choices = c("Head" = "head", "All" = "all"),
                      selected = "head"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose whether to display all rows or just the first 20.", placement = "right")
                  )
                ))


              ),

                shinycssloaders::withSpinner(tableOutput(shiny::NS(id, "ShowTable"))
                )
            ))
          ),


        # Section to view the matrix to assign group to each samples
          # Conditional panel if input.Import_table_exp == 'Loading'
          shiny::conditionalPanel(
            condition = sprintf("input['%s'] == 'Loading'", shiny::NS(id, "Import_table_exp")),
          bslib::accordion_panel(
            title = "Step 2 Result - Load the Matrix",
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "Here, we present the loaded matrix contaning metadata ('Samples' and 'Groups')",
              placement = "right"
            ),

              shinycssloaders::withSpinner(tableOutput(shiny::NS(id, "ImportedTable"))
              )
          )),

          # Conditional panel if input.Import_table_exp == 'Create'
          shiny::conditionalPanel(
            condition = sprintf("input['%s'] == 'Create'", shiny::NS(id, "Import_table_exp")),
          bslib::accordion_panel(
            title = "Step 2 Result - Generate the Matrix",
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "Here, you can create the matrix containing metadata ('Samples' and 'Groups') interactively. Be sure to save it once you've made your selections.",
              placement = "right"
            ),
            # Card containing the controls and layout for creating the matrix
            bslib::card(full_screen = TRUE, bslib::layout_sidebar(
              sidebar = bslib::sidebar(
                title = "Local controls",
                position = "right",

                 # Display a reminder to save the created matrix
                shiny::fluidRow(shiny::column(
                  12, align = "center", htmltools::h5("Remember to save it!"), htmltools::br()
                )),
                # Button to save the matrix, with a tooltip explaining its function
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::actionButton(shiny::NS(id, "save_group"),
                                 label = "Save_matrix",
                                 shiny::icon("table")),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Save the assigned groups", placement = "right")
                  )
                ))
              ),

              # Conditional panel that displays interactive group assignment options if the group assignment option is selected


              shiny::conditionalPanel(
                condition = sprintf("input['%s'] == true", shiny::NS(id, "assign_group")),

              # Tabset panel with two tabs for group assignment and saved groups
              tabsetPanel(
                tabPanel(
                  "Interactive group assignment",
                  DT::DTOutput(shiny::NS(id,"grouping"))
                  ),


                tabPanel(shiny::NS(id, "Groups saved"),
                tableOutput(shiny::NS(id, "groups_assigned"))
                            )


              )
              ),
              #Show message
              tableOutput(shiny::NS(id, "groupingMessage"))
            ))

          )
        ),

        # Accordion panel for the 3rd step result - Filtering and normalization
          bslib::accordion_panel(
            title = "Step 3 Result - Data Processing",
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "The matrix displays the results of the analysis related to the filtering of both normalized and non-normalized data. Make sure the data is entered correctly",
              placement = "right"
            ),

            bslib::card(full_screen = TRUE, bslib::layout_sidebar(
              sidebar = bslib::sidebar(title = "Local controls", position = "right",
            # Select info for either samples or the count matrix
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shiny::selectInput(shiny::NS(id, "selectInfoExp"), "Select info" , choices = ""),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose whether to display metadata information related to samples or the count matrix.", placement = "right")
                )
              )
              )),

              shiny::conditionalPanel(
                condition = paste0("output['", shiny::NS(id,"ConditionalRunAnalysisExp"), "'] == 'Running'"),
                tabsetPanel(
                  tabPanel(
                    "Pre normalization",
                    shinycssloaders::withSpinner(DT::DTOutput(shiny::NS(id,"infoPreNorm"))),
                    shiny::verbatimTextOutput(shiny::NS(id,"InfoFilteringPre"))
                  ),
                  tabPanel(
                    "Post normalization",
                    shinycssloaders::withSpinner(DT::DTOutput(shiny::NS(id,"infoPostNorm"))),
                    shiny::verbatimTextOutput(shiny::NS(id,"InfoFilteringPost"))
                  )
                )
            ),
           tableOutput(shiny::NS(id, "infoNormMessage")),
                # )
            ))
          ),

        # Conditional panel if input.RunMDSExp button is pressed'
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunMDS"), "'] == 'Running'"),
          bslib::accordion_panel(
          title = "MDS plots",
          # Tooltip providing a brief explanation of MDS and its relevance to RNA-seq data visualization
          bslib::tooltip(
            bsicons::bs_icon("question-circle"),
            "By visualizing samples in a lower-dimensional space, MDS highlights how samples cluster, revealing similarities in expression patterns that may reflect underlying biological conditions or treatments. MDS plots can also help identify outliers that deviate from expected groupings, prompting further investigation into potential issues such as sample quality problems or experimental artifacts.",
            placement = "right"
          ),
          bslib::card(full_screen = TRUE, bslib::layout_sidebar(
            sidebar = bslib::sidebar(
              width = "30%",
              title = "Local controls",
              position = "right",

              # Control to toggle between interactive and static MDS plot
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shinyWidgets::switchInput(shiny::NS(id, "MDS_interactively"),
                    label = "Interactive",
                    labelWidth = "120px",
                    onStatus = "primary",
                    offStatus = "default"
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                )
              )),

              # Accordion panel for MDS plot settings
              bslib::accordion_panel(
                "Plot settings",

                # shiny::selectInput for selecting the MDS plot component
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "selectMDSexp"),
                      "select value",
                      choices = c(
                        "eigen.values",
                        "eigen.vectors",
                        "var.explained",
                        "dim.plot",
                        "distance.matrix.squared",
                        "top",
                        "gene.selection",
                        "axislabel",
                        "x",
                        "y"
                      )
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the component you would like to view.", placement = "right")
                  )
                )),
              # shiny::selectInput for choose number of top genes used to calculate pairwise distances
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shiny::selectInput(shiny::NS(id, "MDStop"),
                    label = "numberTop",
                    choices = c(seq(from= 50, to = 5000, by = 50)),
                    selected = 500
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Set the number of top genes used to calculate pairwise distances. '500' by default", placement = "right")
                )
              )),
              # shiny::selectInput for choose gene.selection
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shiny::selectInput(shiny::NS(id, "MDSgene_selection"),
                    label = "gene_selection",
                    choices = c("pairwise","common"),
                    selected = "pairwise"
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Set the method: Choose 'pairwise' to select the top genes separately for each pairwise comparison between samples, or 'common' to select the same genes for all comparisons. This option is only used when method = 'logFC'. 'pairwise' by default", placement = "right")
                )
              )),
                # shiny::selectizeInput for selecting the color palette
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),

                    shiny::selectizeInput(shiny::NS(id, "MDSpalette"),
                      label = "Desired colours",
                      choices = ""
                    ),
                    bslib::tooltip(
                      bsicons::bs_icon("question-circle"),
                      "Choose the color palette you would like to use. If you are using the app in a browser, you can visit the following link to explore available palettes:" ,
                       htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                      placement = "right"
                    )
                  )
                )),

                # shiny::selectInput for adjusting label overlaps in the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "MDSMaxOverlaps"),
                      label = "maxOverlaps",
                      choices = c(1:20),
                      selected = 5
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Adjust the maximum overlap threshold to exclude labels that overlap with too many other elements. '5' by default", placement = "right")
                  )
                )),
                # shiny::selectInput for adjusting label size
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "MDSsizeLabel"),
                      label = "sizeLabel",
                      choices = c(1:20),
                      selected = 2
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Adjust the label size. '2' by default", placement = "right")
                  )
                )),
                # Button to refresh the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::actionButton(shiny::NS(id, "RefreshRunMDSExp"),
                                 label =  "Refresh",
                                 shiny::icon("refresh")),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                  )
                )),

              ),

              # Accordion panel for download settings
              bslib::accordion_panel(
                "Download settings",
                # Radio buttons for selecting the file format for downloading the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "MDSformat"),
                      label = "Desired format",
                      choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                      selected = "jpeg"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                  )
                )),
                # Radio buttons for selecting the unit for the plot dimensions
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "unitsMDS"),
                      label = "units",
                      choices = c("in", "cm", "mm", "px"),
                      selected = "cm"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                  )
                )),
                # Numeric input for setting the resolution of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "resMDS"),
                      label = "resolution",
                      step = 1,
                      min = 1,
                      value = 200
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                  )
                )),
                # Numeric input for setting the width of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id,  "widthMDS"),
                      label = "width",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                  )
                )),
                # Numeric input for setting the height of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id,  "heightMDS"),
                      label = "height",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                  )
                )),
                # Button to download the pre-normalized plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "MDSLinkpre"),
                                   label = "Download pre-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                  )
                )),
                # Button to download the post-normalized plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "MDSLinkpost"),
                                   label = "Download post-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                  )
                ))



              )
            ),
            # Tabset panel for visualizing MDS plots pre and post normalization
            tabsetPanel(
              tabPanel(
                "Pre normalization",
                # Conditional panel for static or interactive pre-normalization plot
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "MDS_interactively")),

                  shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "MDSpreNorm")
                                                          ))
                  ,
                  shiny::verbatimTextOutput(shiny::NS(id, "MDSValuePre"), placeholder = FALSE)


                ),

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "MDS_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "MDSpreNormPlottly")
                )))
              ),
              tabPanel(
                "post normalization",
                # Conditional panel for static or interactive post-normalization plot
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "MDS_interactively")),
                  shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "MDSpostNorm")
                                                          ))
                  ,
                  shiny::verbatimTextOutput(shiny::NS(id, "MDSValuePost"),
                                     placeholder = FALSE)
                ),

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "MDS_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "MDSpostNormPlottly")
                )))
              )
            )
          ))
        )),


        # Conditional panel to show PCA settings and visualization options when 'RunPCAExp' is triggered
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunPCA"), "'] == 'Running'"),
      # Accordion panel for PCA-related controls and plot settings
        bslib::accordion_panel(
          title = "PCA plots",
          # Tooltip providing a brief explanation of PCA and its relevance to RNA-seq data visualization
          bslib::tooltip(
            bsicons::bs_icon("question-circle"),
            "PCA reduces the high-dimensional RNA-seq data into fewer dimensions while retaining most of the variance. This makes it easier to visualize and interpret complex datasets,
            By transforming the data into principal components, PCA helps uncover patterns and relationships among samples, revealing how they cluster based on gene expression profiles.
            PCA as well as MDS can highlight outliers that could be further investigated",
            placement = "right",
        ),
        # Card with a sidebar layout for PCA controls
          bslib::card(full_screen = TRUE, bslib::layout_sidebar(
            sidebar = bslib::sidebar(
              width = "30%",
              title = "Local controls",
              position = "right",

              # Switch input for toggling between static and interactive plots
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shinyWidgets::switchInput(shiny::NS(id, "PCA_interactively"),
                    label = "Interactive",
                    labelWidth = "120px",
                    onStatus = "primary",
                    offStatus = "default"
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                )
              )),

              # Accordion panel for adjusting PCA plot settings
              bslib::accordion_panel(
                "Plot settings",
                # shiny::selectInput to choose the PCA component to view (e.g., 'sdev', 'rotation', etc.)
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "selectPCAExp"),
                      "select value",
                      choices = c("sdev", "rotation", "center", "scale", "x")
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the component you wish to view", placement = "right")
                  )
                )),
                # shiny::selectInput for center the variables
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "PCAcenter"),
                      label = "center",
                      choices = c("TRUE", "FALSE"),
                      selected = "TRUE"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Set whether variables should be shifted to be zero-centered. 'TRUE' by default", placement = "right")
                  )
                )),
                # shiny::selectInput for scale the variables
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "PCAscale"),
                      label = "scale",
                      choices = c("TRUE", "FALSE"),
                      selected = "FALSE"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Set whether variables should be scaled to have unit variance before analysis. 'FALSE ' by default", placement = "right")
                  )
                )),
                # shiny::selectInput for choosing a color palette for the plot
                shiny::fluidRow(shiny::column(width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shiny::selectizeInput(shiny::NS(id, "PCApalette"),
                    label = "Desired colours",
                    choices = ""
                  ),
                  bslib::tooltip(
                    bsicons::bs_icon("question-circle"),
                    "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                     htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                    placement = "right"
                  )
                ))),
                # shiny::selectInput for selecting the maximum overlap of labels in the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "PCAMaxOverlaps"),
                      label = "maxOverlaps",
                      choices = c(1:20),
                      selected = 5
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Set the maximum overlap to exclude labels when they overlap too many other things. '5' by default", placement = "right")
                  )
                )),
                # shiny::selectInput for selecting the size of the labels
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "PCAsizeLabel"),
                      label = "sizeLabel",
                      choices = c(1:20),
                      selected = 2
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Set the label size. '2' by default", placement = "right")
                  )
                )),
                # Refresh button to update the PCA plot with the new settings
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::actionButton(shiny::NS(id, "RefreshRunPCAExp"),
                                 label =  "Refresh",
                                 shiny::icon("refresh")),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                  )
                ))

              ),
              # Accordion panel for download settings
              bslib::accordion_panel(
                "Download settings",
                # shiny::radioButtons to select the format for downloading the plot (e.g., jpeg, png, etc.)
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "PCAformat"),
                      label =
                        "Desired format",
                      choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                      selected = "jpeg"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                  )
                )),
                # shiny::radioButtons to select the units for defining plot dimensions (e.g., inches, cm, etc.)
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "unitsPCA"),
                      label = "units",
                      choices = c("in", "cm", "mm", "px"),
                      selected = "cm"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the resolution of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "resPCA"),
                      label = "resolution",
                      step = 1,
                      min = 1,
                      value = 200
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the width of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "widthPCA"),
                      label = "width",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the height of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "heightPCA"),
                      label = "height",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                  )
                )),
                # shiny::downloadButton for downloading the pre-normalized PCA plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "PCALinkpre"),
                                   label = "Download pre-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                  )
                )),
                # shiny::downloadButton for downloading the post-normalized PCA plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "PCALinkpost"),
                                   label = "Download post-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                  )
                ))

              )
            ),

            tabsetPanel(
              tabPanel(
                "Pre normalization",
                # Conditional panel for static or interactive pre-normalization plot
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "PCA_interactively")),
                  shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PCApreNorm"))) ,
                  shiny::verbatimTextOutput(shiny::NS(id, "PCAValuePre"), placeholder = FALSE)
                ),

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "PCA_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PCApreNormPlottly")
                )))
              ),

              tabPanel(
                "post normalization",
                # Conditional panel for static or interactive post-normalization plot
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "PCA_interactively")),
                  shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PCApostNorm"))),
                  shiny::verbatimTextOutput(shiny::NS(id, "PCAValuePost"), placeholder = FALSE)
                ),

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "PCA_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PCApostNormPlottly")
                )))
              )
            )
          ))
        )),


      # Conditional panel to show Box plot settings and visualization options when 'RunBoxplotExp' is triggered
        shiny::conditionalPanel(
          condition = paste0("output['",shiny::NS(id,"ConditionalRunBox"), "'] == 'Running'"),
          # Accordion panel for Boxplot-related controls and plot settings
          bslib::accordion_panel(
          title = "BOX PLOT",
          # Tooltip providing a brief explanation of Boxplots and their relevance to gene expression visualization
          bslib::tooltip(
            bsicons::bs_icon("question-circle"),
            "Boxplots provide a clear visual representation of the distribution of gene expression levels across different samples or conditions, making it easy to compare data.
            It is particularly useful also for verifying the success of the normalization process. In this regard, the reference black line represents the median value calculated considering all samples.",
            placement = "right"
          ),
          # Card with a sidebar layout for Box plot controls and plot settings
          bslib::card(full_screen = TRUE, bslib::layout_sidebar(
            sidebar = bslib::sidebar(
              width = "30%",
              title = "Local controls",
              position = "right",
              # Switch input for toggling between static and interactive plots
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shinyWidgets::switchInput(shiny::NS(id, "BOXPLOT_interactively"),
                    label = "Interactive",
                    labelWidth = "120px",
                    onStatus = "primary",
                    offStatus = "default"
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                )
              )),

              # Accordion panel for adjusting Box plot plot settings
              bslib::accordion_panel(
                "Plot settings",

                # shiny::selectInput to choose how to order the x-axis (by 'Groups' or 'Samples')
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "selectOrderBoxplotExp"),
                      "select order",
                      choices = c("Groups", "Samples"),
                      selected = "Groups"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose how to order the x-axis: by 'Groups' or by 'Samples'.", placement = "right")
                  )
                )),
                # shiny::selectInput for choosing a color palette for the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectizeInput(shiny::NS(id, "selectColorBoxplotExp"),
                                "Desired colour", choices = ""),
                    bslib::tooltip(
                      bsicons::bs_icon("question-circle"),
                      "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                       htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                      placement = "right"
                    )
                  )
                )),
                # shiny::actionButton for refreshing the Box plot after changing settings
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::actionButton(shiny::NS(id, "RefreshBoxplotExp"),
                                 label =  "Refresh", shiny::icon("refresh")),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                  )
                )),

              ),
              # Accordion panel for download settings
              bslib::accordion_panel(
                "Download settings",
                # shiny::radioButtons to select the format for downloading the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "Boxplotformat"),
                      label =
                        "Desired format",
                      choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                      selected = "jpeg"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                  )
                )),
                # shiny::radioButtons to select the units for defining plot dimensions (e.g., inches, cm, etc.)
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "unitsBoxplot"),
                      label = "units",
                      choices = c("in", "cm", "mm", "px"),
                      selected = "cm"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the resolution of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "resBoxplot"),
                      label = "resolution",
                      step = 1,
                      min = 1,
                      value = 200
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the width of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id,  "widthBoxplot"),
                      label = "width",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                  )
                )),
                # shiny::numericInput for setting the height of the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "heightBoxplot"),
                      label = "height",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                  )
                )),
                # shiny::downloadButton for downloading the pre-normalized Boxplot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "BoxplotLinkpre"), label = "Download pre-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                  )
                )),
                # shiny::downloadButton for downloading the post-normalized Boxplot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "BoxplotLinkpost"),
                                   label = "Download post-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                  )
                ))

              )
            ),
            # Tabset panel to show pre- and post-normalization Boxplots
            tabsetPanel(
              tabPanel(
                "Pre normalization",
                # Conditional panels to show either static or interactive plots based on user selection
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "BOXPLOT_interactively")),
                                 shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "BOXpreNorm")
                                                                         ))),
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "BOXPLOT_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "BOXpreNormPlottly")
                )))
              ),

              tabPanel(
                "post normalization",
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "BOXPLOT_interactively")),
                                 shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "BOXpostNorm")
                                                                         ))),
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "BOXPLOT_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "BOXpostNormPlottly")
                )))
              )
            )
          ))
        )),

      # Conditional panel for Barplot section, displayed when 'RunBarplotExp' is pressed
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunBar"), "'] == 'Running'"),
      # Accordion panel for the Barplot section
      bslib::accordion_panel(
          title = "BAR PLOT",
          bslib::tooltip(
            bsicons::bs_icon("question-circle"),
            "Bar plot is used to visually represent the library size of each sample",
            placement = "right"
          ),
          # card layout for the barplot, includes a sidebar for controls
          bslib::card(full_screen = TRUE, bslib::layout_sidebar(
            sidebar = bslib::sidebar(
              width = "30%",
              title = "Local controls",
              position = "right",

              # SwitchInput to toggle between interactive and static plots
              shiny::fluidRow(shiny::column(
                width = 12, shiny::splitLayout(
                  cellWidths = c("90%", "10%"),
                  shinyWidgets::switchInput(shiny::NS(id, "BARPLOT_interactively"),
                    label = "Interactive",
                    labelWidth = "120px",
                    onStatus = "primary",
                    offStatus = "default"
                  ),
                  bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                )
              )),



              # Accordion panel for Plot settings
              bslib::accordion_panel(
                "Plot settings",
                # shiny::selectInput to select the order of the x-axis (Groups or Samples)
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectInput(shiny::NS(id, "selectOrderBarplotExp"),
                      "select order",
                      choices = c("Groups", "Samples"),
                      selected = "Groups"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select how to order the x axis, by 'Groups' or 'Samples'", placement = "right")
                  )
                )),
                # shiny::selectInput to select the color palette for the barplot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::selectizeInput(shiny::NS(id, "selectColorBarplotExp"),
                                "Desired colour", choices = ""),
                    bslib::tooltip(
                      bsicons::bs_icon("question-circle"),
                      "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                       htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                      placement = "right"
                    )
                  )
                )),
                # Refresh button to update the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::actionButton(shiny::NS(id, "RefreshBarplotExp"),
                                 label =  "Refresh",
                                 shiny::icon("refresh")),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                  )
                )),


              ),
              # Accordion panel for Download settings
              bslib::accordion_panel(
                "Download settings",
                # shiny::radioButtons to select the format for downloading the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "Barplotformat"),
                      label =
                        "Desired format",
                      choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                      selected = "jpeg"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                  )
                )),
                # shiny::radioButtons to select the units for the plot dimensions
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::radioButtons(shiny::NS(id, "unitsBarplot"),
                      label = "units",
                      choices = c("in", "cm", "mm", "px"),
                      selected = "cm"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                  )
                )),
                # shiny::numericInput to input the resolution for raster output formats
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "resBarplot"),
                      label = "resolution",
                      step = 1,
                      min = 1,
                      value = 200
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                  )
                )),
                # shiny::numericInput to input the width for the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "widthBarplot"),
                      label = "width",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                  )
                )),
                # shiny::numericInput to input the height for the plot
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::numericInput(shiny::NS(id, "heightBarplot"),
                      label = "height",
                      step = 1,
                      min = 1,
                      value = 10
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                  )
                )),
                # shiny::downloadButton for download buttons for pre and post-normalization plots
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "BarplotLinkpre"),
                                   label = "Download pre-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                  )
                )),

                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shiny::downloadButton(shiny::NS(id, "BarplotLinkpost"),
                                   label = "Download post-n plot"),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                  )
                ))

              )
            ),
            # Tabs for displaying pre and post-normalization plots, both static and interactive
            tabsetPanel(
              tabPanel(
                "Pre normalization",
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "BARPLOT_interactively")),
                                 shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PlotBARplotPre")
                                                                        ))),

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "BARPLOT_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PlotBARplotPrePlottly")
                )))
              ),

              tabPanel(
                "post normalization",

                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "BARPLOT_interactively")),
                                 shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PlotBARplotPost")
                                                                         ))),
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "BARPLOT_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PlotBARplotPostPlottly")
                )))
              )
            )
          ))
        )),

      # Heatmap Section, conditional panel displayed when 'RunHeatmapExp' is pressed
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunHeatmap"), "'] == 'Running'"),
          # Accordion panel for Heatmap section
          bslib::accordion_panel(
            # Tooltip explaining heatmap functionality
            title = "EXP.HEATMAP",
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "A heat map that incorporates expression levels enables you to visualize gene expression variability across samples. By using a heat map, you can identify which genes exhibit the most variation in expression and analyze samples based on their gene expression profiles. This allows you to detect clusters and subclusters of samples or genes that share similar expression patterns.",
              placement = "right"
            ),
            # Card layout for the heatmap, includes a sidebar for controls
            bslib::card(full_screen = TRUE, bslib::layout_sidebar(
              sidebar = bslib::sidebar(
                width = "30%",
                title = "Local controls",
                position = "right",

                # SwitchInput to toggle between interactive and static plots
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shinyWidgets::switchInput(shiny::NS(id, "HEATMAP_interactively"),
                      label = "Interactive",
                      labelWidth = "120px",
                      onStatus = "primary",
                      offStatus = "default"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                  )
                )),

                # Accordion panel for Plot Settings
                bslib::accordion_panel(
                  "Plot Setting",
                  # shiny::selectInput to select color palette for the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectizeInput(shiny::NS(id, "ColorPanelHeatmap"),
                        label = "Desired colour",
                        choices = ""
                      ),
                      bslib::tooltip(
                        bsicons::bs_icon("question-circle"),
                        "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                         htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                        placement = "right"
                      )
                    )
                  )),

                  # shiny::selectInput to select number of genes considered for the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id, "NumGenesHeatmap"),
                        "NumGenesHeatmap",
                        choices = seq(from =
                                        10, by = 10 , to = 1000),
                        selected = 100
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify the number of genes to include when generating the heat map.", placement = "right")
                    )
                  )),

                  # shiny::selectInput to select number of clusters for rows
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id,  "cutree_rowsHeatmap"),
                        label = "cutree_rows",
                        choices = seq(from =
                                        1, to = 27),
                        selected = 1
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to divide the rows.", placement = "right")
                    )
                  )),
                  # shiny::selectInput to select number of clusters for columns
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id, "cutree_colsHeatmap"),
                        label = "cutree_cols",
                        choices = seq(from =
                                        1, to = 27),
                        selected = 1
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to divide the columns.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons to select whether to scale the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "scaleHeatmap"),
                        label = "scale",
                        choices  = c("row", "column", "none"),
                        selected = "column"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to scale the columns or rows.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons to select whether to cluster the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "clusterHeatmap"),
                        label = "cluster",
                        choices  = c("both", "row", "column", "none"),
                        selected = "both"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether you want to cluster the columns or rows.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons to select whether to show row/column labels
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "show_namesHeatmap"),
                        label = "show_label",
                        choices  = c("both", "row", "column", "none"),
                        selected = "row"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to display the labels assigned to the columns or rows.", placement = "right")
                    )
                  )),
                  # Button to refresh the heatmap plot
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::actionButton(shiny::NS(id, "RefreshRunHeatmapExp"),
                                   label =  "Refresh",
                                   shiny::icon("refresh")),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                    )
                  ))
                ),

                # Accordion panel for Download Settings
                bslib::accordion_panel(
                  "Download settings",
                  # shiny::radioButtons to select the desired format for saving the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "Heatmapformat"),
                        label =
                          "Desired format",
                        choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                        selected = "jpeg"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                    )
                  )),
                  # shiny::radioButtons to select the units for defining the plot dimensions
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "unitsHeatmap"),
                        label = "units",
                        choices = c("in", "cm", "mm", "px"),
                        selected = "cm"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                    )
                  )),
                  # shiny::numericInput to set the resolution of the saved heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id, "resHeatmap"),
                        label = "resolution",
                        step = 1,
                        min = 1,
                        value = 200
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                    )
                  )),
                  # shiny::numericInput to set the width of the saved heatmap
                  shiny::fluidRow(
                    shiny::column(width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id, "widthHeatmap"),
                        label = "width",
                        step = 1,
                        min = 1,
                        value = 10
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                    )),
                    # shiny::numericInput to set the height of the saved heatmap
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::numericInput(shiny::NS(id,  "heightHeatmap"),
                          label = "height",
                          step = 1,
                          min = 1,
                          value = 10
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                      )
                    )),

                    # Button to download the pre-normalized heatmap
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::downloadButton(shiny::NS(id, "HeatmapLinkpre"), label = "Download pre-n plot"),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                      )
                    )),
                    # Button to download the post-normalized heatmap
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::downloadButton(shiny::NS(id, "HeatmapLinkpost"), label = "Download post-n plot"),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                      )
                    ))

                  )

                )
              ),
              # Tab panels for pre- and post-normalization heatmaps
              tabsetPanel(
                tabPanel(
                  "Pre normalization",
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '0'", shiny::NS(id, "HEATMAP_interactively")),
                                   shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "HeatmapPreNormExp")
                  ))),
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '1'", shiny::NS(id, "HEATMAP_interactively")),
                                   shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id,"HeatmapPreNormExpPlotly"))
                  ))
                ),

                tabPanel(
                  "post normalization",
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '0'", shiny::NS(id, "HEATMAP_interactively")),
                                   shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "HeatmapPostNormExp")
                  ))),
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '1'", shiny::NS(id, "HEATMAP_interactively")),
                                   shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "HeatmapPostNormExpPlotly") )
                  ))
                )
              )
            ))
          )
        ),


      # Conditional panel for the Correlation Plot section
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunCor"), "'] == 'Running'"),

          # Accordion panel for the correlation heatmap
          bslib::accordion_panel(
            title = "COR.HEATMAP",
            #Briefly explanation of correlation heat map
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "A correlation-based heat map highlights samples with similar gene expression profiles. Samples that show high correlation in gene expression are likely to share underlying biological characteristics. This clustering can help validate the consistency of replicates and reveal subgroups that might not have been identified through other analyses.",
              placement = "right"
            ),
            # Card layout with a sidebar for controls
            bslib::card(full_screen = TRUE, bslib::layout_sidebar(
              sidebar = bslib::sidebar(
                width = "30%",
                title = "Local controls",
                position = "right",

                # SwitchInput for toggling between interactive and static plots
                shiny::fluidRow(shiny::column(
                  width = 12, shiny::splitLayout(
                    cellWidths = c("90%", "10%"),
                    shinyWidgets::switchInput(shiny::NS(id, "CORRELATION_interactively"),
                      label = "Interactive",
                      labelWidth = "120px",
                      onStatus = "primary",
                      offStatus = "default"
                    ),
                    bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                  )
                )),


                # Accordion panel for plot settings
                bslib::accordion_panel(
                  "Plot settings",
                  # shiny::selectInput for color palette
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectizeInput(shiny::NS(id, "Corrpalette"),
                        label = "Desired colour",
                        choices = ""
                      ),
                      bslib::tooltip(
                        bsicons::bs_icon("question-circle"),
                        "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                         htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                        placement = "right"
                      )
                    )
                  )),
                  # shiny::radioButtons for selecting correlation type (Pearson or Spearman)
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "typeCorrPlot"),
                        label = "typeCorrPlot",
                        choices = c("pearson", "spearman"),
                        selected = "pearson"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify which correlation method to use: 'Pearson' or 'Spearman'.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons for selecting the display value (correlation or p-value)
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "displayCorrPlot"),
                        label = "displayCorrPlot",
                        choices = c("correlation", "pvalue"),
                        selected = "correlation"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose which value to display in the plot: 'correlation' or 'p-value'.", placement = "right")
                    )
                  )),
                  # shiny::numericInput to round the displayed values to a certain number of decimal places
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id, "round_numberCorrPlot"),
                        label = "round_numberCorrPlot",
                        value = 1,
                        step = 1,
                        min = 0,
                        max = 10
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify the number of decimal places to round the values to.", placement = "right")
                    )
                  )),
                  # shiny::selectInput for selecting the number of genes to include in the heatmap
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id, "NumGenesCorrPlot"),
                        label = "NumGenesCorrPlot",
                        choices  = seq(from =
                                         10, by = 10 , to = 1000),
                        selected  = 100
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify the number of genes to include when generating the heat map.", placement = "right")
                    )
                  )),


                  # shiny::selectInput for selecting row clustering cut levels
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id, "cutree_rowsCorrPlot"),
                        label = "cutree_rows",
                        choices = seq(from =
                                        1, to = 27),
                        selected = 1
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to divide the rows.", placement = "right")
                    )
                  )),
                  # shiny::selectInput for selecting column clustering cut levels
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::selectInput(shiny::NS(id, "cutree_colsCorrPlot"),
                        label = "cutree_cols",
                        choices = seq(from =
                                        1, to = 27),
                        selected = 1

                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to divide the columns.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons for selecting row or column scaling
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "scaleCorrPlot"),
                        label = "scale",
                        choices  = c("row", "column", "none"),
                        selected = "none"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to scale the columns or rows.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons for selecting row or column clustering
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "clusterCorrPlot"),
                        label = "cluster",
                        choices  = c("both", "row", "column", "none"),
                        selected = "both"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether you want to cluster the columns or rows.", placement = "right")
                    )
                  )),
                  # shiny::radioButtons for showing/hiding row/column names
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "show_namesCorrPlot"),
                        label = "show_label",
                        choices  = c("both", "row", "column", "none"),
                        selected = "both"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify whether to display the labels assigned to the columns or rows.", placement = "right")
                    )
                  )),
                  # Refresh button to regenerate the heatmap with updated settings
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::actionButton(shiny::NS(id, "RefreshRunCorrPlotExp"),
                                   label =  "Refresh",
                                   shiny::icon("refresh")),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                    )
                  )),


                ),
                # Accordion panel for download settings
                bslib::accordion_panel(
                  "Download settings",
                  # Radio buttons for selecting the plot format
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "CorrPlotformat"),
                        label =
                          "Desired format",
                        choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                        selected = "jpeg"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                    )
                  )),
                  # shiny::radioButtons for selecting units (inches, cm, mm, pixels)
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::radioButtons(shiny::NS(id, "unitsCorrPlot"),
                        label = "units",
                        choices = c("in", "cm", "mm", "px"),
                        selected = "cm"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                    )
                  )),
                  # shiny::numericInput for specifying the resolution of the plot
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id,  "resCorrPlot"),
                        label = "resolution",
                        step = 1,
                        min = 1,
                        value = 200
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                    )
                  )),
                  # shiny::numericInput for specifying the width of the plot
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id, "widthCorrPlot"),
                        label = "width",
                        step = 1,
                        min = 1,
                        value = 10
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                    )
                  )),
                  # shiny::numericInput for specifying the height of the plot
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::numericInput(shiny::NS(id,  "heightCorrPlot"),
                        label = "height",
                        step = 1,
                        min = 1,
                        value = 10
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                    )
                  )),
                  # Download buttons for pre-normalized and post-normalized data plots
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::downloadButton(shiny::NS(id, "CorrPlotLinkpre"),
                                     label = "Download pre-n plot"),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the pre-normalized data.", placement = "right")
                    )
                  )),

                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shiny::downloadButton(shiny::NS(id, "CorrPlotLinkpost"),
                                     label = "Download post-n plot"),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot for the post-normalized data.", placement = "right")
                    )
                  ))
                )
              ),
              # Main panel containing the plots
              tabsetPanel(
                tabPanel(
                  "Pre normalization",
                  # Conditional panel for static (non-interactive) pre-normalization plot
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '0'", shiny::NS(id, "CORRELATION_interactively")),
                                   shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PlotCorrplotPre")
                                                                           ))),
                  # Conditional panel for interactive (plotly) pre-normalization plot
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '1'", shiny::NS(id, "CORRELATION_interactively")),
                                   shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PlotCorrplotPrePlotly")
                  )))
                ),
                # Tab for post-normalization plots
                tabPanel(
                  "post normalization",
                  # Conditional panel for static (non-interactive) post-normalization plot
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '0'", shiny::NS(id, "CORRELATION_interactively")),
                                   shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id, "PlotCorrplotPost")
                                                                           ))),
                  # Conditional panel for interactive (plotly) post-normalization plot
                  shiny::conditionalPanel(
                    condition = sprintf("input['%s'] == '1'", shiny::NS(id, "CORRELATION_interactively")),
                                   shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id, "PlotCorrplotPostPlotly")
                  )))
                )
              )
            ))
          )
        ),

      # Conditional panel that displays the Saturation Plot options if 'RunSatPlotExp' is pressed
        shiny::conditionalPanel(
          condition = paste0("output['", shiny::NS(id,"ConditionalRunSat"), "'] == 'Running'"),

          # Accordion panel for Saturation Plot settings
          bslib::accordion_panel(
            title = "SATURATION PLOT",
            # Tooltip explaining the purpose of the saturation plot
            bslib::tooltip(
              bsicons::bs_icon("question-circle"),
              "A saturation plot is valuable for evaluating the effectiveness of a sequencing effort in capturing the transcriptome. It helps assess whether the sequencing depth is adequate or if additional reads are required to achieve a more complete representation of gene expression.",
              placement = "right"
            ),
            # Card layout containing the controls and plot
            bslib::card(
              full_screen = TRUE,
              bslib::layout_sidebar(
                sidebar = bslib::sidebar(
                  width = "30%",
                  title = "Local controls",
                  position = "right",

                  # Switch to toggle between interactive and static plot modes
                  shiny::fluidRow(shiny::column(
                    width = 12, shiny::splitLayout(
                      cellWidths = c("90%", "10%"),
                      shinyWidgets::switchInput(shiny::NS(id, "SATURATION_interactively"),
                        label = "Interactive",
                        labelWidth = "120px",
                        onStatus = "primary",
                        offStatus = "default"
                      ),
                      bslib::tooltip(bsicons::bs_icon("question-circle"), "Generate interactive plot", placement = "right")
                    )
                  )),
                  # Accordion panel for plot settings
                  bslib::accordion_panel(
                    "Plot settings",

                    # shiny::numericInput for setting the maximum number of reads to sample
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::numericInput(shiny::NS(id, "max_readsSatPlot"),
                          "max_reads",
                          step = 1,
                          min = 1000,
                          value = 1000000
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify the number of reads to sample.", placement = "right")
                      )
                    )),
                    # shiny::selectInput for selecting the color palette for the plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::selectizeInput(shiny::NS(id, "paletteSatPlot"),
                          label = "Desired colours",
                          choices = "",
                        ),
                        bslib::tooltip(
                          bsicons::bs_icon("question-circle"),
                          "Choose the colour palette you wish to use. If the app is opened in a browser you can reach the link 'https://pmassicotte.github.io/paletteer_gallery/' via the hyperlink:" ,
                           htmltools::tags$a("The paletteer gallery", href = "https://pmassicotte.github.io/paletteer_gallery/", target = "_blank"),
                          placement = "right"
                        )
                      )
                    )),
                    # shiny::radioButtons for selecting the method for saturation analysis
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::radioButtons(shiny::NS(id, "methodSatPlot"),
                          label = "method Saturation Plot",
                          choices = c("sampling", "division"),
                          selected = "sampling"
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Specify the method to use for saturation analysis with the 'estimate_saturation()' function from 'RNAseQC' package (https://github.com/BenaroyaResearch/RNAseQC.git). The 'sampling' method is slower but provides more realistic results and smoother curves, while the 'division' method is faster but less precise and yields coarser results.", placement = "right")
                      )
                    )),
                    # Refresh button to regenerate the saturation plot with updated settings
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::actionButton(shiny::NS(id, "RefreshRunSatPlotExp"),
                                     label =  "Refresh",
                                     shiny::icon("refresh")),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Refresh the plot to apply and view the changes", placement = "right")
                      )
                    )),
                  ),
                  # Accordion panel for download settings
                  bslib::accordion_panel(
                    "Download settings",
                    # shiny::radioButtons for selecting the format for saving the plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::radioButtons(shiny::NS(id, "SatPlotformat"),
                          label =
                            "Desired format",
                          choices = c("jpeg", "png", "tiff", "eps", "svg", "pdf"),
                          selected = "jpeg"
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the format to save the plot. 'jpeg' by default", placement = "right")
                      )
                    )),
                    # shiny::radioButtons for selecting the units (inches, cm, mm, pixels)
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::radioButtons(shiny::NS(id, "unitsSatPlot"),
                          label = "units",
                          choices = c("in", "cm", "mm", "px"),
                          selected = "cm"
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Choose the unit for defining the dimensions ('width' and 'height). 'cm' by default", placement = "right")
                      )
                    )),
                    # shiny::numericInput for specifying the resolution of the plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::numericInput(shiny::NS(id, "resSatPlot"),
                          label = "resolution",
                          step = 1,
                          min = 1,
                          value = 200
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the resolution (applies only to raster output types). '200' by default", placement = "right")
                      )
                    )),
                    # shiny::numericInput for specifying the width of the plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::numericInput(shiny::NS(id, "widthSatPlot"),
                          label = "width",
                          step = 1,
                          min = 1,
                          value = 10
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot width. '10' by default", placement = "right")
                      )
                    )),
                    # shiny::numericInput for specifying the height of the plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::numericInput(shiny::NS(id,  "heightSatPlot"),
                          label = "height",
                          step = 1,
                          min = 1,
                          value = 10
                        ),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Select the plot height. '10' by default", placement = "right")
                      )
                    )),
                    # Download button to save the saturation plot
                    shiny::fluidRow(shiny::column(
                      width = 12, shiny::splitLayout(
                        cellWidths = c("90%", "10%"),
                        shiny::downloadButton(shiny::NS(id, "SatPlotLink"),
                                       label = "Download plot"),
                        bslib::tooltip(bsicons::bs_icon("question-circle"), "Download the plot", placement = "right")
                      )
                    ))

                  )
                ),
                # Conditional panel to show a static saturation plot if interactive mode is OFF
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '0'", shiny::NS(id, "SATURATION_interactively")),
                                 shinycssloaders::withSpinner(shiny::plotOutput(shiny::NS(id,"SaturationPlot")
                                                                         ))),
                # Conditional panel to show an interactive saturation plot if interactive mode is ON
                shiny::conditionalPanel(
                  condition = sprintf("input['%s'] == '1'", shiny::NS(id, "SATURATION_interactively")),
                                 shinycssloaders::withSpinner(plotly::plotlyOutput(shiny::NS(id,"SaturationPlotly")
                                                                           )))
              )
            )
          )
        )
      )
  )
} # End of User

Try the inDAGO package in your browser

Any scripts or data that you put into this service are public.

inDAGO documentation built on Aug. 8, 2025, 7:47 p.m.