diff --git "a/server.R" "b/server.R"
--- "a/server.R"
+++ "b/server.R"
@@ -1,2328 +1,2272 @@
-# server.R
-library(shiny)
-library(readxl)
-library(DT)
-library(dplyr)
-
-# Source the warning overlay and long operations code
-source("warning_overlay.R", local = TRUE)
-source("long_operations.R", local = TRUE)
-
-# setwd("/Users/audrey/Downloads/research/ckweb/Tcellstates")
-
-# Define server logic
-function(input, output, session) {
-
- # --- START: TaijiChat R Callback for Python Agent Thoughts ---
- python_agent_thought_callback <- function(thought_message_from_python) {
- # Attempt to explicitly convert to R character and clean up
- thought_message_text <- tryCatch({
- as.character(thought_message_from_python)[1] # Take the first element after converting
- }, error = function(e) {
- print(paste("R Callback: Error converting thought to character:", e$message))
- return(NULL)
- })
-
- if (!is.null(thought_message_text) && is.character(thought_message_text) && length(thought_message_text) == 1 && nzchar(trimws(thought_message_text))) {
- # print(paste("R Callback: Valid thought from Python -", thought_message_text)) # For R console debugging
- session$sendCustomMessage(type = "agent_new_thought", message = list(text = trimws(thought_message_text)))
- } else {
- # Log the original and potentially converted type for better debugging
- print(paste("R Callback: Received invalid or empty thought. Original type:", class(thought_message_from_python), ", Value:", thought_message_from_python, ", Converted text:", thought_message_text))
- }
- }
- # --- END: TaijiChat R Callback for Python Agent Thoughts ---
-
- # --- START: TaijiChat Agent Initialization ---
- # This assumes manager_agent_module is globally available from ui.R's sourcing.
- # ui.R does: manager_agent_module <- reticulate::import("agents.manager_agent")
-
- api_key_val <- NULL
- # First try to get API key from environment variable
- api_key_val <- Sys.getenv("OPENAI_API_KEY")
-
- # If environment variable is not set, try reading from file
- if (api_key_val == "") {
- tryCatch({
- api_key_content <- readLines("api_key.txt", warn = FALSE)
- if (length(api_key_content) > 0 && nzchar(trimws(api_key_content[1]))) {
- api_key_val <- trimws(api_key_content[1])
- print("TaijiChat: API key successfully read from file in server.R.")
- } else {
- warning("TaijiChat: api_key.txt is empty or not found. LLM features may be disabled.")
- print("TaijiChat: api_key.txt is empty or not found.")
- }
- }, error = function(e) {
- warning(paste("TaijiChat: Error reading api_key.txt in server.R:", e$message))
- print(paste("TaijiChat: Error reading api_key.txt:", e$message))
- })
- } else {
- print("TaijiChat: API key successfully read from environment variable.")
- }
-
- py_openai_client_instance <- NULL
- if (!is.null(api_key_val)) {
- tryCatch({
- # Ensure reticulate is configured to use the correct Python environment
- if (reticulate::py_available(initialize = TRUE)) {
- openai_py_module <- reticulate::import("openai", convert = FALSE) # convert=FALSE for raw Python objects
- py_openai_client_instance <- openai_py_module$OpenAI(api_key = api_key_val)
- print("TaijiChat: Python OpenAI client initialized successfully in server.R via reticulate.")
- } else {
- warning("TaijiChat: Python (reticulate) not available or not initialized. Cannot create OpenAI client.")
- print("TaijiChat: Python (reticulate) not available. Cannot create OpenAI client.")
- }
- }, error = function(e) {
- warning(paste("TaijiChat: Failed to initialize Python OpenAI client in server.R:", e$message))
- print(paste("TaijiChat: Failed to initialize Python OpenAI client:", e$message))
- py_openai_client_instance <- NULL
- })
- } else {
- print("TaijiChat: API key is NULL, skipping Python OpenAI client initialization.")
- }
-
- rv_agent_instance <- reactiveVal(NULL)
-
- # Attempt to create the agent instance once.
- current_manager_agent_module <- NULL
- tryCatch({
- # Force reload the module to ensure we get the latest version
- print("TaijiChat: Attempting to reload Python modules to ensure latest version...")
- reticulate::py_run_string("
-import sys
-import importlib
-if 'agents.manager_agent' in sys.modules:
- print('Reloading agents.manager_agent module...')
- importlib.reload(sys.modules['agents.manager_agent'])
-")
-
- current_manager_agent_module <- reticulate::import("agents.manager_agent", convert = FALSE)
- if (is.null(current_manager_agent_module)) {
- warning("TaijiChat: reticulate::import('agents.manager_agent') returned NULL in server.R.")
- print("TaijiChat: reticulate::import('agents.manager_agent') returned NULL in server.R.")
- } else {
- print("TaijiChat: Successfully imported/retrieved 'agents.manager_agent' module in server.R.")
- }
- }, error = function(e) {
- warning(paste("TaijiChat: Failed to import agents.manager_agent in server.R:", e$message))
- print(paste("TaijiChat: Failed to import agents.manager_agent in server.R:", e$message))
- })
-
- if (!is.null(current_manager_agent_module)) {
- # Module is available, now try to instantiate the agent
- if (!is.null(py_openai_client_instance)) {
- tryCatch({
- agent_inst <- current_manager_agent_module$ManagerAgent(
- openai_client = py_openai_client_instance,
- r_callback_fn = python_agent_thought_callback # Pass the R callback here
- )
- rv_agent_instance(agent_inst)
- print("TaijiChat: Python ManagerAgent instance created in server.R using pre-initialized client and R callback.")
- }, error = function(e) {
- warning(paste("TaijiChat: Failed to instantiate ManagerAgent in server.R with client & callback:", e$message))
- print(paste("TaijiChat: Failed to instantiate ManagerAgent with client & callback:", e$message))
- })
- } else if (!is.null(api_key_val)) { # Try with API key if client object failed but key exists
- tryCatch({
- agent_inst <- current_manager_agent_module$ManagerAgent(
- openai_api_key = api_key_val,
- r_callback_fn = python_agent_thought_callback # Pass the R callback here
- )
- rv_agent_instance(agent_inst)
- print("TaijiChat: Python ManagerAgent instance created in server.R with API key and R callback (client to be init by Python).")
- }, error = function(e) {
- warning(paste("TaijiChat: Failed to instantiate ManagerAgent with API key & callback in server.R:", e$message))
- print(paste("TaijiChat: Failed to instantiate ManagerAgent with API key & callback:", e$message))
- })
- } else {
- # Neither client nor API key is available for the agent
- warning("TaijiChat: Cannot create ManagerAgent instance: OpenAI client/API key not available for agent constructor.")
- print("TaijiChat: Cannot create ManagerAgent: OpenAI client/API key not available for agent constructor.")
- }
- } else {
- # Module itself could not be imported/retrieved
- warning("TaijiChat: agents.manager_agent module is NULL after import attempt. Agent not created.")
- print("TaijiChat: agents.manager_agent module is NULL after import attempt. Agent not created.")
- }
- # --- END: TaijiChat Agent Initialization ---
-
- # Server logic for home tab
- output$home <- renderText({
- "Welcome to the Home page"
- })
-
- observeEvent(input$read_now, {
- # Trigger a redirect using JavaScript
- session$sendCustomMessage(type = "redirect",
- message = "https://doi.org/10.1101/2023.01.03.522354")
- })
-
-
- # NEW READ EXCEL FILE FOR TRANSPOSED DATASET
- new_read_excel_file <- function(path) {
- withWarningOverlay(session, function() {
- df <- read_excel(path)
- colnames(df)[1] <- "Regulator Names"
-
- # Transpose the dataframe
- df_transposed <- as.data.frame(t(df))
-
- # Fix the column names of the transposed dataframe (optional)
- colnames(df_transposed) <- df_transposed[1, ] # Set first row as column names
- df_transposed <- df_transposed[-1, ] # Remove the first row which is now used as column names
-
- return(df_transposed)
- }, "Reading and processing Excel file...")
- }
-
- # # NEW FILTER FUNCTION FOR TRANSPOSED DATASET
- # new_filter_data <- function(df, keyword) {
- #
- # # Find the columns whose names contain the keyword
- # matching_columns <- grepl(keyword, colnames(df), ignore.case = TRUE)
- #
- # # Check if any matching columns exist
- # if (sum(matching_columns) == 0) {
- # # If no matching columns are found, return an empty dataframe with proper structure
- # return(data.frame())
- # }
- #
- # # Subset the dataframe, ensuring the result is always a dataframe
- # filtered_df <- df[, matching_columns, drop = FALSE]
- #
- # return(filtered_df)
- # }
-
- #NEW FILTER FUNCTION FOR MULTIPLE GENE SEARCH
- # new_filter_data <- function(df, keywords) {
- # # Split the keywords by commas and remove any leading/trailing whitespace
- # keyword_list <- strsplit(keywords, ",")[[1]]
- # keyword_list <- trimws(keyword_list)
- #
- # # Initialize an empty logical vector for matching columns
- # matching_columns <- rep(FALSE, ncol(df))
- #
- # # Loop through each keyword and update the matching_columns vector
- # for (keyword in keyword_list) {
- # matching_columns <- matching_columns | grepl(keyword, colnames(df), ignore.case = TRUE)
- # }
- #
- # # Check if any matching columns exist
- # if (sum(matching_columns) == 0) {
- # # If no matching columns are found, return an empty dataframe with proper structure
- # return(data.frame())
- # }
- #
- # # Subset the dataframe, ensuring the result is always a dataframe
- # filtered_df <- df[, matching_columns, drop = FALSE]
- #
- # return(filtered_df)
- # }
-
- new_filter_data <- function(df, keywords) {
- # If no keywords are provided, return the full dataset
- if (is.null(keywords) || keywords == "") {
- return(df)
- }
-
- # Split the keywords by commas and remove any leading/trailing whitespace
- keyword_list <- strsplit(keywords, ",")[[1]]
- keyword_list <- trimws(keyword_list) # Remove leading/trailing spaces
-
- # Initialize an empty logical vector for matching columns
- matching_columns <- rep(FALSE, ncol(df))
-
- # Loop through each keyword and update the matching_columns vector
- for (keyword in keyword_list) {
- matching_columns <- matching_columns | grepl(keyword, colnames(df), ignore.case = TRUE)
- }
-
- # Check if any matching columns exist
- if (sum(matching_columns) == 0) {
- # If no matching columns are found, return an empty dataframe
- return(data.frame())
- }
-
- # Subset the dataframe, ensuring the result is always a dataframe
- filtered_df <- df[, matching_columns, drop = FALSE]
-
- return(filtered_df)
- }
-
-
-
-
- # TESTING FUNCTIONS
-
- #NEW ALL DATA SEARCH
- data <- reactive({
- new_read_excel_file("www/tablePagerank/Table_TF PageRank Scores for Audrey.xlsx")
- })
-
- # Track the current column page
- column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for main page data
- observeEvent(input$search_input, {
- column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked
- observeEvent(input$next_btn, {
- current_page <- column_page()
- total_cols <- ncol(new_filter_data(data(), input$search_input))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- column_page(current_page + 1)
- }
-
- # new_page <- column_page() + 1
- # column_page(new_page)
- })
-
- observeEvent(input$prev_btn, {
- current_page <- column_page()
- column_page(max(current_page - 1, 1))
- # new_page <- max(column_page() - 1, 1) # Ensure the page does not go below 1
- # column_page(new_page)
- })
-
- # # OLD: Reactive for filtering the data based on input$search_input
- # new_filtered_data <- reactive({
- #
- # df <- new_filter_data(data(), input$search_input)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # Ensure start_col is within the number of columns
- # if (start_col > total_cols) {
- # return(df) # Return the filtered dataframe as-is if start_col exceeds the number of columns
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- # return(df_subset)
- # })
-
- #NEW FILTER DATA TO INCLUDE ADDITIONAL DESCRIPTION ROW + WORKS WITH SEARCHING INDIVIDUAL GENES
- new_filtered_data <- reactive({
- # Filter the data and determine the total number of columns
- df <- new_filter_data(data(), input$search_input)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold)
- style <- "
TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Combine the data with the description and styled "Cell state data" row
- df_subset <- rbind(df_subset[1:2, , drop = FALSE], description_row, df_subset[-(1:2), , drop = FALSE])
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 2; // Adjust this index to the row you want highlighted
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered data table and showing all rows
- output$table <- renderDT({
- new_filtered_data()
- }, options = list(pageLength = nrow(new_filtered_data()), dom = 't'))
-
-
-
-
- #NEW NAIVE SEARCH
- naive_data <- reactive({
- new_read_excel_file("www/tablePagerank/Naive.xlsx")
- })
-
- # Track the current column page for naive data
- naive_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for naive data
- observeEvent(input$search_input_naive, {
- naive_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Reset the column page when the search input changes for naive data
- observeEvent(input$search_input_naive, {
- naive_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for naive data
- observeEvent(input$naive_next_btn, {
- current_page <- naive_column_page()
- total_cols <- ncol(new_filter_data(naive_data(), input$search_input_naive))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- naive_column_page(current_page + 1)
- }
-
- # new_page <- naive_column_page() + 1
- # naive_column_page(new_page)
- })
-
- observeEvent(input$naive_prev_btn, {
- current_page <- naive_column_page()
- naive_column_page(max(current_page - 1, 1))
- # new_page <- max(naive_column_page() - 1, 1) # Ensure the page does not go below 1
- # naive_column_page(new_page)
- })
-
- #OLD FILTERED DATA
- # filtered_naive_data <- reactive({
- #
- # df <- new_filter_data(naive_data(), input$search_input_naive)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (naive_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # Ensure start_col is within the number of columns
- # if (start_col > total_cols) {
- # return(df) # Return the filtered dataframe as-is if start_col exceeds the number of columns
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_naive_data <- reactive({
- # Filter the naive data and determine the total number of columns
- df <- new_filter_data(naive_data(), input$search_input_naive)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (naive_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- output$table_naive <- renderDT({
- filtered_naive_data()
- }, options = list(pageLength = nrow(filtered_naive_data()), dom = 't'))
-
-
-
- #NEW TE SEARCH
- te_data <- reactive({
- new_read_excel_file("www/tablePagerank/TE.xlsx")
- })
-
- # Track the current column page for "te" data
- te_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "te" data
- observeEvent(input$search_input_te, {
- te_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "te" data
- observeEvent(input$te_next_btn, {
- current_page <- te_column_page()
- total_cols <- ncol(new_filter_data(te_data(), input$search_input_te))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- te_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$te_prev_btn, {
- current_page <- te_column_page()
- te_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "te" page data
- # filtered_te_data <- reactive({
- # df <- new_filter_data(te_data(), input$search_input_te)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (te_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_te_data <- reactive({
- # Filter the TE data and determine the total number of columns
- df <- new_filter_data(te_data(), input$search_input_te)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (te_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "te" page data table and showing all rows
- output$table_te <- renderDT({
- filtered_te_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_te_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
-
- #NEW MP SEARCH
- mp_data <- reactive({
- new_read_excel_file("www/tablePagerank/MP.xlsx")
- })
-
- # Track the current column page for "mp" data
- mp_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "mp" data
- observeEvent(input$search_input_mp, {
- mp_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "mp" data
- observeEvent(input$mp_next_btn, {
- current_page <- mp_column_page()
- total_cols <- ncol(new_filter_data(mp_data(), input$search_input_mp))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- mp_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$mp_prev_btn, {
- current_page <- mp_column_page()
- mp_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "mp" page data
- # filtered_mp_data <- reactive({
- # df <- new_filter_data(mp_data(), input$search_input_mp)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (mp_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_mp_data <- reactive({
- # Filter the MP data and determine the total number of columns
- df <- new_filter_data(mp_data(), input$search_input_mp)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (mp_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "mp" page data table and showing all rows
- output$table_mp <- renderDT({
- filtered_mp_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_mp_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
-
- #NEW TCM SEARCH
- tcm_data <- reactive({
- new_read_excel_file("www/tablePagerank/TCM.xlsx")
- })
-
- # Track the current column page for "tcm" data
- tcm_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "tcm" data
- observeEvent(input$search_input_tcm, {
- tcm_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "tcm" data
- observeEvent(input$tcm_next_btn, {
- current_page <- tcm_column_page()
- total_cols <- ncol(new_filter_data(tcm_data(), input$search_input_tcm))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- tcm_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$tcm_prev_btn, {
- current_page <- tcm_column_page()
- tcm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "tcm" page data
- # filtered_tcm_data <- reactive({
- # df <- new_filter_data(tcm_data(), input$search_input_tcm)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (tcm_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_tcm_data <- reactive({
- # Filter the TCM data and determine the total number of columns
- df <- new_filter_data(tcm_data(), input$search_input_tcm)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (tcm_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "tcm" page data table and showing all rows
- output$table_tcm <- renderDT({
- filtered_tcm_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_tcm_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
- #NEW TEM SEARCH
- tem_data <- reactive({
- new_read_excel_file("www/tablePagerank/TEM.xlsx")
- })
-
- # Track the current column page for "tem" data
- tem_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "tem" data
- observeEvent(input$search_input_tem, {
- tem_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "tem" data
- observeEvent(input$tem_next_btn, {
- current_page <- tem_column_page()
- total_cols <- ncol(new_filter_data(tem_data(), input$search_input_tem))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- tem_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$tem_prev_btn, {
- current_page <- tem_column_page()
- tem_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "tem" page data
- # filtered_tem_data <- reactive({
- # df <- new_filter_data(tem_data(), input$search_input_tem)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (tem_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_tem_data <- reactive({
- # Filter the TEM data and determine the total number of columns
- df <- new_filter_data(tem_data(), input$search_input_tem)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (tem_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "tem" page data table and showing all rows
- output$table_tem <- renderDT({
- filtered_tem_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_tem_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
- #NEW TRM SEARCH
- trm_data <- reactive({
- new_read_excel_file("www/tablePagerank/TRM.xlsx")
- })
-
- # Track the current column page for "trmm" data
- trm_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "trmm" data
- observeEvent(input$search_input_trm, {
- trm_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "trmm" data
- observeEvent(input$trm_next_btn, {
- current_page <- trm_column_page()
- total_cols <- ncol(new_filter_data(trm_data(), input$search_input_trm))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- trm_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$trm_prev_btn, {
- current_page <- trm_column_page()
- trm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "trmm" page data
- # filtered_trm_data <- reactive({
- # df <- new_filter_data(trm_data(), input$search_input_trm)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (trm_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_trm_data <- reactive({
- # Filter the TRM data and determine the total number of columns
- df <- new_filter_data(trm_data(), input$search_input_trm)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (trm_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "trmm" page data table and showing all rows
- output$table_trm <- renderDT({
- filtered_trm_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_trm_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
- #NEW TEX PROG SEARCH
- texprog_data <- reactive({
- new_read_excel_file("www/tablePagerank/TEXprog.xlsx")
- })
-
- # Track the current column page for "texprog" data
- texprog_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "texprog" data
- observeEvent(input$search_input_texprog, {
- texprog_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "texprog" data
- observeEvent(input$texprog_next_btn, {
- current_page <- texprog_column_page()
- total_cols <- ncol(new_filter_data(texprog_data(), input$search_input_texprog))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- texprog_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$texprog_prev_btn, {
- current_page <- texprog_column_page()
- texprog_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "texprog" page data
- # filtered_texprog_data <- reactive({
- # df <- new_filter_data(texprog_data(), input$search_input_texprog)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (texprog_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_texprog_data <- reactive({
- # Filter the TEXprog data and determine the total number of columns
- df <- new_filter_data(texprog_data(), input$search_input_texprog)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (texprog_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "texprog" page data table and showing all rows
- output$table_texprog <- renderDT({
- filtered_texprog_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_texprog_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
- #NEW TEX EFF LIKE SEARCH
- texefflike_data <- reactive({
- new_read_excel_file("www/tablePagerank/TEXeff.xlsx")
- })
-
- # Track the current column page for "texefflike" data
- texefflike_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "texefflike" data
- observeEvent(input$search_input_texefflike, {
- texefflike_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "texefflike" data
- observeEvent(input$texefflike_next_btn, {
- current_page <- texefflike_column_page()
- total_cols <- ncol(new_filter_data(texefflike_data(), input$search_input_texefflike))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- texefflike_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$texefflike_prev_btn, {
- current_page <- texefflike_column_page()
- texefflike_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "texefflike" page data
- # filtered_texefflike_data <- reactive({
- # df <- new_filter_data(texefflike_data(), input$search_input_texefflike)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (texefflike_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_texefflike_data <- reactive({
- # Filter the TEXefflike data and determine the total number of columns
- df <- new_filter_data(texefflike_data(), input$search_input_texefflike)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (texefflike_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "texefflike" page data table and showing all rows
- output$table_texefflike <- renderDT({
- filtered_texefflike_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_texefflike_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
-
- #NEW TEX TERM SEARCH
- texterm_data <- reactive({
- new_read_excel_file("www/tablePagerank/TEXterm.xlsx")
- })
-
- # Track the current column page for "texterm" data
- texterm_column_page <- reactiveVal(1)
-
- # Reset the column page when the search input changes for "texterm" data
- observeEvent(input$search_input_texterm, {
- texterm_column_page(1) # Reset to page 1 when a new search is made
- })
-
- # Update the column page when buttons are clicked for "texterm" data
- observeEvent(input$texterm_next_btn, {
- current_page <- texterm_column_page()
- total_cols <- ncol(new_filter_data(texterm_data(), input$search_input_texterm))
-
- # Calculate the maximum possible number of pages
- max_page <- ceiling(total_cols / 4)
-
- # Move to the next page, but do not exceed the max_page
- if (current_page < max_page) {
- texterm_column_page(current_page + 1)
- }
- })
-
- observeEvent(input$texterm_prev_btn, {
- current_page <- texterm_column_page()
- texterm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
- })
-
- #OLD: Reactive for filtering and paginating the "texterm" page data
- # filtered_texterm_data <- reactive({
- # df <- new_filter_data(texterm_data(), input$search_input_texterm)
- #
- # # Get the total number of columns in the filtered dataframe
- # total_cols <- ncol(df)
- #
- # # Ensure there are columns after filtering
- # if (total_cols == 0) {
- # return(data.frame()) # Return an empty dataframe if no columns match the search
- # }
- #
- # # Define the start and end index for columns based on the current page
- # start_col <- (texterm_column_page() - 1) * 4 + 1
- # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
- #
- # # If start_col exceeds the total number of columns, return the last valid subset
- # if (start_col > total_cols) {
- # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
- # end_col <- total_cols # End with the last column
- # }
- #
- # # Subset the columns for the current page
- # df_subset <- df[, start_col:end_col, drop = FALSE]
- #
- # return(df_subset)
- # })
-
- #NEW FILTERED DATA
- filtered_texterm_data <- reactive({
- # Filter the TEXterm data and determine the total number of columns
- df <- new_filter_data(texterm_data(), input$search_input_texterm)
- total_cols <- ncol(df)
-
- # Return empty dataframe if no columns match the search
- if (total_cols == 0) return(data.frame())
-
- # Define the column range for the current page
- start_col <- (texterm_column_page() - 1) * 4 + 1
- end_col <- min(start_col + 3, total_cols)
-
- # Return filtered data if start_col exceeds the total columns
- if (start_col > total_cols) return(df)
-
- # Subset the dataframe for the current page
- df_subset <- df[, start_col:end_col, drop = FALSE]
-
- # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
- if (nrow(df_subset) >= 2) {
- description_row <- data.frame(
- matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
- )
-
- # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
- style <- "TF activity score
"
-
- # Apply style to both description and "Cell state data"
- description_row[1, ] <- style
- rownames(description_row)[1] <- "Cell state data"
-
- # Move the description row to the first row of the subset
- df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
- }
-
- # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
- DT::datatable(df_subset, escape = FALSE, options = list(
- pageLength = 45,
- lengthChange = FALSE,
- searching = FALSE, # Remove the search box
- rowCallback = JS(
- "function(row, data, index) {
- var highlightedRow = 0; // Apply styling to the first row
-
- if (index === highlightedRow) {
- $('td', row).css({
- 'background-color': '#95a5a6',
- 'color': 'white',
- 'font-weight': 'bold'
- });
- }
- }"
- )
- ))
- })
-
- # Rendering the filtered "texterm" page data table and showing all rows
- output$table_texterm <- renderDT({
- filtered_texterm_data() # Use the filtered data with pagination logic applied
- }, options = list(
- pageLength = nrow(filtered_texterm_data()), # Show all rows
- dom = 't', # Remove the row length dropdown
- scrollX = TRUE # Enable horizontal scrolling if needed
- ))
-
-
-
-
- # # ORIGINAL READ EXCEL FILE
- # read_excel_file <- function(path) {
- # df <- read_excel(path)
- # colnames(df)[1] <- "Regulator Names"
- # return(df)
- # }
- #
- # # ORIGINAL FILTER FUNCTION
- # filter_data <- function(data, keyword) {
- # if (is.null(keyword) || is.na(keyword) || keyword == "") {
- # return(data)
- # } else {
- # keyword <- tolower(keyword)
- # return(data[apply(data, 1, function(x) any(grepl(keyword, tolower(x)))), ])
- # }
- # }
- #
- # #ORIGINAL DISPLAY TABLE FUNCTION
- # # Main page data
- # data <- reactive({
- # read_excel_file("www/tablePagerank/Table_TF PageRank Scores for Audrey.xlsx")
- # })
- #
- # filtered_data <- reactive({
- # filter_data(data(), input$search_input)
- # })
- #
- # output$table <- renderDT({
- # filtered_data()
- # })
-
-
-
- # Server logic for naive tab
- output$naive <- renderText({
- "TF Activity Score: Naive"
- })
-
- # OLD NAIVE DATA TABLE
- # naive_data <- reactive({
- # read_excel_file("www/tablePagerank/Naive.xlsx")
- # })
- #
- # filtered_naive_data <- reactive({
- # filter_data(naive_data(), input$search_input_naive)
- # })
- #
- # output$table_naive <- renderDT({
- # filtered_naive_data()
- # })
-
-
- # Server logic for TE tab
- output$te <- renderText({
- "TF Activity Score: TE"
- })
-
- # OLD TE DATA TABLE
- # te_data <- reactive({
- # read_excel_file("www/tablePagerank/TE.xlsx")
- # })
- #
- # filtered_te_data <- reactive({
- # filter_data(te_data(), input$search_input_te)
- # })
- #
- # output$table_te <- renderDT({
- # filtered_te_data()
- # })
-
- # Server logic for MP tab
- output$mp <- renderText({
- "TF Activity Score: MP"
- })
-
- # OLD MP DATA
- # mp_data <- reactive({
- # read_excel_file("www/tablePagerank/MP.xlsx")
- # })
- #
- # filtered_mp_data <- reactive({
- # filter_data(mp_data(), input$search_input_mp)
- # })
- #
- # output$table_mp <- renderDT({
- # filtered_mp_data()
- # })
-
- # Server logic for T CM tab
- output$tcm <- renderText({
- "TF Activity Score: T CM"
- })
-
- # OLD TCM DATA
- # tcm_data <- reactive({
- # read_excel_file("www/tablePagerank/TCM.xlsx")
- # })
- #
- # filtered_tcm_data <- reactive({
- # filter_data(tcm_data(), input$search_input_tcm)
- # })
- #
- # output$table_tcm <- renderDT({
- # filtered_tcm_data()
- # })
-
- # Server logic for T EM tab
- output$tem <- renderText({
- "TF Activity Score: T EM"
- })
-
- # OLD TEM DATA
- # tem_data <- reactive({
- # read_excel_file("www/tablePagerank/TEM.xlsx")
- # })
- #
- # filtered_tem_data <- reactive({
- # filter_data(tem_data(), input$search_input_tem)
- # })
- #
- # output$table_tem <- renderDT({
- # filtered_tem_data()
- # })
- #
- # # Server logic for T RM tab
- # output$trm <- renderText({
- # "TF Activity Score: T RM"
- # })
-
- # OLD TRM DATA
- # trm_data <- reactive({
- # read_excel_file("www/tablePagerank/TRM.xlsx")
- # })
- #
- # filtered_trm_data <- reactive({
- # filter_data(trm_data(), input$search_input_trm)
- # })
- #
- # output$table_trm <- renderDT({
- # filtered_trm_data()
- # })
-
- # Server logic for Tex Prog tab
- output$texprog <- renderText({
- "TF Activity Score: Tex Prog"
- })
-
- # OLD TEX PROG DATA
- # texprog_data <- reactive({
- # read_excel_file("www/tablePagerank/TEXprog.xlsx")
- # })
- #
- # filtered_texprog_data <- reactive({
- # filter_data(texprog_data(), input$search_input_texprog)
- # })
- #
- # output$table_texprog <- renderDT({
- # filtered_texprog_data()
- # })
-
-
- # Server logic for Tex Eff-like tab
- output$texefflike <- renderText({
- "TF Activity Score: Tex Eff-like"
- })
-
- # OLD TEX EFF LIKE DATA
- # texefflike_data <- reactive({
- # read_excel_file("www/tablePagerank/TEXeff.xlsx")
- # })
- #
- # filtered_texefflike_data <- reactive({
- # filter_data(texefflike_data(), input$search_input_texefflike)
- # })
- #
- # output$table_texefflike <- renderDT({
- # filtered_texefflike_data()
- # })
-
- # Server logic for Tex Term tab
- output$texterm <- renderText({
- "TF Activity Score: Tex Term"
- })
-
- # OLD TEX TERM DATA
- # texterm_data <- reactive({
- # read_excel_file("www/tablePagerank/TEXterm.xlsx")
- # })
- #
- # filtered_texterm_data <- reactive({
- # filter_data(texterm_data(), input$search_input_texterm)
- # })
- #
- # output$table_texterm <- renderDT({
- # filtered_texterm_data()
- # })
-
-
-
- #click image code for TF Wave Analysis
- observeEvent(input$c1_link, {
- updateNavbarPage(session, "mainNav", selected = "c1")
- })
-
- observeEvent(input$c2_link, {
- updateNavbarPage(session, "mainNav", selected = "c2")
- })
-
- observeEvent(input$c3_link, {
- updateNavbarPage(session, "mainNav", selected = "c3")
- })
-
- observeEvent(input$c4_link, {
- updateNavbarPage(session, "mainNav", selected = "c4")
- })
-
- observeEvent(input$c5_link, {
- updateNavbarPage(session, "mainNav", selected = "c5")
- })
-
- observeEvent(input$c6_link, {
- updateNavbarPage(session, "mainNav", selected = "c6")
- })
-
- observeEvent(input$c7_link, {
- updateNavbarPage(session, "mainNav", selected = "c7")
- })
-
-
- # Handle specific image part clicks to navigate to the subpages
- observeEvent(input$to_tfcat, {
- updateNavbarPage(session, "mainNav", selected = "tfcatpage")
- })
-
- observeEvent(input$to_tfwave, {
- updateNavbarPage(session, "mainNav", selected = "overview")
- })
-
- observeEvent(input$to_tfnet, {
- updateNavbarPage(session, "mainNav", selected = "tfnetpage")
- })
-
- # SEARCH FOR A TF AND FIND OUT WHICH WAVE THEY ARE APART OF
- # Function to read the file and assign proper column names
- read_searchwave_file <- function(path) {
- df <- read_excel(path) # Read the Excel file
- colnames(df) <- c("Wave1", "Wave2", "Wave3", "Wave4", "Wave5", "Wave6", "Wave7") # Customize as needed
- return(df)
-
- return(df)
- }
-
- # Load data reactively
- searchwavedata <- reactive({
- # Provide the path to your Excel file
- read_searchwave_file("www/waveanalysis/searchtfwaves.xlsx") # Path to your file
- })
-
- # Reactive function to search and filter the data based on the wave search input
- filtered_wave_data <- reactive({
- # Get the search input
- search_term <- input$search_input_wave
-
- # If no search term, return the entire dataset in the desired transposed format
- if (is.null(search_term) || search_term == "") {
- # Initialize an empty list to store the gene names for each wave
- wave_genes <- list()
-
- # Iterate over each wave column and get the associated genes
- for (col in colnames(searchwavedata())) {
- wave_genes[[col]] <- searchwavedata()[[col]] # Store all gene names for each wave
- }
-
- # Create a data frame with waves as columns and genes as rows
- result_df <- data.frame(wave_genes)
-
- # Return the transposed data frame with wave numbers as column headers and genes as rows
- return(result_df)
- }
-
- # Initialize an empty list to store the result
- result <- list()
-
- # Iterate through each column and check if the search term exists
- for (col in colnames(searchwavedata())) {
- # Filter genes for each column where the search term matches
- matching_genes <- searchwavedata()[[col]][grepl(search_term, searchwavedata()[[col]], ignore.case = TRUE)]
-
- # If there are matching genes, store them
- if (length(matching_genes) > 0) {
- result[[col]] <- paste(matching_genes, collapse = ", ") # Combine matching genes as a string
- }
- }
-
- # If no results are found, return an empty dataframe
- if (length(result) == 0) {
- return(data.frame(Wave = character(0), Gene = character(0))) # Return empty data frame if nothing matches
- }
-
- # Convert the result list to a data frame
- result_df <- data.frame(
- Wave = names(result), # Column names as 'Wave'
- Gene = unlist(result), # Concatenated list of matching gene names
- stringsAsFactors = FALSE
- )
-
- # Remove any duplicate wave names (keep only one occurrence per wave)
- result_df <- result_df[!duplicated(result_df$Wave), ]
-
- # Remove rows where Gene column is NA or empty
- result_df <- result_df[!is.na(result_df$Gene) & result_df$Gene != "", ]
-
- # Create a matrix with wave names as columns and gene names as rows
- transposed_df <- matrix(unlist(result_df$Gene), nrow = 1) # Convert the gene names to a row
-
- # Set the column names to the wave numbers, replacing "Wave 1" instead of "wave.1"
- colnames(transposed_df) <- paste("Wave", seq_along(result_df$Wave))
-
- # Return the transposed result
- return(as.data.frame(transposed_df))
- })
-
- # Render the table output based on the filtered and transposed data
- output$table_wave <- renderDT({
- # Get the filtered and transposed data
- df <- filtered_wave_data()
-
- # Render the data table without row names and disable the default search box
- datatable(df, options = list(searching = FALSE), rownames = FALSE)
- })
-
-
-
-
- # # Function to read Excel files
- # read_regulator_file <- function(path) {
- # df <- read_excel(path)
- # colnames(df)[1] <- " " # Adjust column name as needed
- # return(df)
- # }
- #
- # # Load data initially
- # tfregulated_data <- reactive({
- # read_regulator_file("www/networkanalysis/comp_log2FC_RegulatedData_TRMTEXterm.xlsx")
- # })
- #
- # # Filtered data based on search input
- # filtered_tfregulated_data <- reactive({
- # req(tfregulated_data()) # Ensure tfregulated_data() is available
- # if (is.null(input$search_tfregulated_data) || input$search_tfregulated_data == "") {
- # return(tfregulated_data())
- # } else {
- # # Perform filtering based on input$search_tfregulated_data
- # # Example filtering logic:
- # # filtered_data <- tfregulated_data() %>%
- # # filter(...) # Add your filtering logic here
- # # return(filtered_data)
- # # Replace the above with your actual filtering logic
- # return(tfregulated_data()) # Placeholder for now
- # }
- # })
- #
- # # Render the DataTable
- # output$table_tfregulated_data <- renderDT({
- # datatable(filtered_tfregulated_data())
- # })
-
-
-
- # ORIGINALLY SEARCH TRM TEXterm COORELATION
- # Load Excel file when the app starts
- data_tftfimage <- read_excel("www/TFcorintextrm/TF-TFcorTRMTEX.xlsx")
-
- # Reactive function to filter the data based on the search input (case-insensitive)
- filtered_data_tftfimage <- reactive({
- req(input$search) # Ensure search input is available
-
- # Convert both the column and search input to lowercase for case-insensitive comparison
- data_filtered <- data_tftfimage[tolower(data_tftfimage[["TF Name"]]) == tolower(input$search), ]
- return(data_filtered)
- })
-
-
- # Render the first column (Gene Names) as clickable links
- output$gene_list_table <- renderUI({
- tagList(
- lapply(data_tftfimage[[1]], function(gene_name) { # Assuming the first column contains gene names
- tags$div(
- actionLink(
- inputId = paste0("gene_", gene_name), # Unique input ID for each gene
- label = gene_name
- ),
- style = "margin-bottom: 10px;" # Add spacing between links
- )
- })
- )
- })
-
- # Generate dynamic observers for each gene link
- lapply(data_tftfimage[[1]], function(gene_name) {
- observeEvent(input[[paste0("gene_", gene_name)]], {
- # Find the row corresponding to the clicked gene
- selected_gene_data <- data_tftfimage[data_tftfimage[[1]] == gene_name, ]
- img_src <- selected_gene_data[["TF Merged Graph Path"]] # Replace with the actual image column name
-
- # Update the image gallery output with the selected gene's image
- output$image_gallery <- renderUI({
- if (!is.null(img_src) && nchar(img_src) > 0) {
- tags$div(
- style = "text-align: center;",
- tags$img(src = img_src, style = "max-width: 100%; height: auto;"),
- tags$p(gene_name) # Optionally display the gene name below the image
- )
- } else {
- "No image available for the selected gene."
- }
- })
- })
- })
-
- # Event to handle search functionality (unchanged from your original code)
- observeEvent(input$search_btn, {
- output$result_table <- renderTable({
- if (nrow(filtered_data_tftfimage()) > 0) {
- filtered_data_tftfimage()[, -which(names(filtered_data_tftfimage()) == "TF Merged Graph Path")] # Show all columns except the image path
- } else {
- NULL # If no results, display nothing
- }
- })
-
- output$image_gallery <- renderUI({
- if (nrow(filtered_data_tftfimage()) > 0) {
- image_list <- lapply(1:nrow(filtered_data_tftfimage()), function(i) {
- img_src <- filtered_data_tftfimage()[[ "TF Merged Graph Path" ]][i]
- tags$div(
- style = "text-align: center; margin-bottom: 20px;",
- tags$img(src = img_src, style = "max-width: 100%; height: auto;")
- )
- })
- do.call(tags$div, image_list)
- } else {
- "TF not found. Please search for a valid TF."
- }
- })
- })
-
-
-
- #tf communities
- # Read the first Excel file directly from the specified path
- datatrm <- read_excel("www/tfcommunities/trmcommunities.xlsx")
-
- # Read the second Excel file directly from the specified path
- datatex <- read_excel("www/tfcommunities/texcommunities.xlsx")
-
- # Render the first table without the search button
- output$trmcom <- renderDT({
- datatable(
- datatrm,
- options = list(
- lengthChange = FALSE,
- pageLength = 5,
- searching = FALSE # Disable the search button
- )
- )
- })
-
- # Render the second table without the search button
- output$texcom <- renderDT({
- datatable(
- datatex,
- options = list(
- lengthChange = FALSE,
- pageLength = 5,
- searching = FALSE # Disable the search button
- )
- )
- })
-
-
- # Load your multiomics file
- multiexcel_data <- read_excel("www/multi-omicsdata.xlsx")
-
- # #Render data table + hyperlinks author's name to DOI
- # output$multiomicsdatatable <- renderDT({
- # # Transform the "author" column to contain hyperlinks using the "DOI" column
- # multiexcel_data <- multiexcel_data %>%
- # mutate(
- # Author = paste0(
- # "",
- # Author, # Column with the display text (e.g., author name)
- # ""
- # )
- # ) %>%
- # select(-DOI) # Remove the "DOI" column after linking it to the "author" column
- #
- # # Dynamically remove empty columns ("18", "19", etc.)
- # multiexcel_data <- multiexcel_data %>%
- # select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
- #
- # # Render the data table with HTML content and no row names
- # datatable(multiexcel_data,
- # options = list(searching = FALSE),
- # rownames = FALSE,
- # escape = FALSE) # Allow HTML rendering
- # })
-
- #Render and hyperlink table + edit size so that everything fits into webpage
- output$multiomicsdatatable <- renderDT({
- # Transform the "author" column to contain hyperlinks using the "DOI" column
- multiexcel_data <- multiexcel_data %>%
- mutate(
- Author = paste0(
- "",
- Author, # Column with the display text (e.g., author name)
- ""
- )
- ) %>%
- select(-DOI) # Remove the "DOI" column after linking it to the "author" column
-
- # Dynamically remove empty columns ("18", "19", etc.)
- multiexcel_data <- multiexcel_data %>%
- select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
-
- # Render the data table with fit-to-page options
- datatable(
- multiexcel_data,
- options = list(
- autoWidth = TRUE, # Adjust column widths automatically
- scrollX = TRUE, # Enable horizontal scrolling
- pageLength = 10 # Limit rows displayed per page (adjustable)
- ),
- rownames = FALSE,
- escape = FALSE # Allow HTML rendering for links
- )
- })
-
- # --- START: TaijiChat Message Handling ---
- chat_history <- reactiveVal(list()) # Stores list of lists: list(role="user/assistant", content="message")
-
- observeEvent(input$user_chat_message, {
- req(input$user_chat_message)
- user_message_text <- trimws(input$user_chat_message)
- print(paste("TaijiChat: Received user_chat_message -", user_message_text))
-
- if (nzchar(user_message_text)) {
- current_hist <- chat_history()
- updated_hist_user <- append(current_hist, list(list(role = "user", content = user_message_text)))
- chat_history(updated_hist_user)
-
- agent_instance_val <- rv_agent_instance()
-
- if (!is.null(agent_instance_val)) {
- # Ensure history is a list of R named lists, then r_to_py will convert to list of Python dicts
- py_hist_for_agent <- lapply(updated_hist_user, function(turn) {
- list(role = turn$role, content = turn$content)
- })
- # py_hist_for_agent_converted <- reticulate::r_to_py(py_hist_for_agent)
-
- # Send a "Thinking..." message to UI before long computation
- session$sendCustomMessage(type = "agent_thinking_started", message = list(text = "Thinking..."))
-
- tryCatch({
- print(paste("TaijiChat: Sending to Python agent - Query:", user_message_text))
- # For debugging, convert history to JSON string to see its structure if needed
- # hist_json_debug <- jsonlite::toJSON(py_hist_for_agent, auto_unbox = TRUE)
- # print(paste("TaijiChat: Conversation history (JSON for debug):", hist_json_debug))
-
- # Call Python agent method
- # The process_single_query method in Python expects history as a list of dicts.
- # reticulate::r_to_py should handle the conversion of the list of R named lists.
- agent_reply_py <- agent_instance_val$process_single_query(
- user_query_text = user_message_text,
- conversation_history_from_r = py_hist_for_agent # Pass the R list of lists
- )
- # Explicitly convert potential Python object to R character string
- agent_reply_text <- as.character(agent_reply_py)
-
- print(paste("TaijiChat: Received from Python agent -", agent_reply_text))
-
- # Check if this is a literature confirmation request
- if (startsWith(agent_reply_text, "TAIJICHAT_LITERATURE_CONFIRMATION:")) {
- # Extract the JSON part
- json_str <- substr(agent_reply_text, 35, nchar(agent_reply_text)) # 35 = length of "TAIJICHAT_LITERATURE_CONFIRMATION:"
-
- tryCatch({
- confirmation_info <- jsonlite::fromJSON(json_str)
- session$sendCustomMessage(type = "literature_confirmation_request",
- message = list(
- text = confirmation_info$message,
- type = confirmation_info$type
- ))
- }, error = function(e) {
- warning(paste("Failed to parse literature confirmation JSON:", e$message))
- session$sendCustomMessage(type = "agent_chat_response",
- message = list(text = "Error processing literature confirmation request."))
- })
-
- # Don't update chat history or send response yet - wait for user confirmation
- return()
- }
-
- # Check if this is an image response
- if (startsWith(agent_reply_text, "TAIJICHAT_IMAGE_RESPONSE:")) {
- # Extract the JSON part - START AFTER THE COLON IN THE PREFIX
- json_str <- substr(agent_reply_text, 26, nchar(agent_reply_text))
-
- # Debug the JSON string
- print(paste("Attempting to parse JSON:", json_str))
-
- # Try parsing in a safer way
- tryCatch({
- # Remove any leading/trailing whitespace and ensure proper JSON format
- json_str <- trimws(json_str)
-
- # Try to parse the JSON
- image_info <- NULL
- if (nchar(json_str) > 0) {
- # Attempt to parse using various approaches
- image_info <- tryCatch({
- jsonlite::fromJSON(json_str)
- }, error = function(e1) {
- tryCatch({
- # Try unescaping first
- jsonlite::fromJSON(gsub('\\\\"', '"', json_str))
- }, error = function(e2) {
- NULL
- })
- })
- }
-
- if (!is.null(image_info) && !is.null(image_info$image_path)) {
- # Debug image path
- image_path_original <- image_info$image_path
- image_path_normalized <- sub("^www/", "", image_info$image_path)
-
- # Check if file exists
- file_exists_check <- file.exists(image_path_original)
- print(paste("Image path debug - Original:", image_path_original,
- "Normalized:", image_path_normalized,
- "File exists:", file_exists_check))
-
- # Add a special marker to the message to trigger image display in UI
- image_html <- paste0(
- '',
- '

',
- '
'
- )
-
- # Get original response or use a default
- original_response <- ifelse(!is.null(image_info$original_response),
- image_info$original_response,
- "I've analyzed this image.")
-
- # Combine the image HTML with the original text response
- enhanced_reply <- paste0(
- image_html,
- "
",
- original_response
- )
-
- agent_reply_text <- enhanced_reply
-
- # Send a custom message to ensure the image display script is active
- session$sendCustomMessage(type = "activate_image_viewer", message = list())
- } else {
- warning("Failed to extract image path from JSON")
- agent_reply_text <- paste("I analyzed an image but had trouble displaying it. Here's what I found:",
- gsub("TAIJICHAT_IMAGE_RESPONSE:.*", "", agent_reply_text))
- }
- }, error = function(e) {
- warning(paste("JSON parsing error:", e$message, "- JSON string:", json_str))
- print(paste("JSON parsing error:", e$message, "- JSON string:", json_str))
- # Just use the original text in case of parsing error
- agent_reply_text <- paste("I analyzed an image but had trouble displaying it. Here's what I found:",
- substr(agent_reply_text, 25, nchar(agent_reply_text)))
- })
- }
-
- final_hist <- append(updated_hist_user, list(list(role = "assistant", content = agent_reply_text)))
- chat_history(final_hist)
-
- session$sendCustomMessage(type = "agent_chat_response", message = list(text = agent_reply_text))
-
- }, error = function(e) {
- error_message <- paste("TaijiChat: Error calling Python agent or processing response:", e$message)
- warning(error_message)
- print(error_message)
- session$sendCustomMessage(type = "agent_chat_response", message = list(text = paste("Sorry, an error occurred with the agent.")))
- })
- } else {
- warning("TaijiChat: Agent instance is NULL. Cannot process chat message.")
- print("TaijiChat: Agent instance is NULL. Cannot process chat message.")
- session$sendCustomMessage(type = "agent_chat_response", message = list(text = "The chat agent is not available. Please check server logs."))
- }
- } else {
- print("TaijiChat: Received empty user_chat_message.")
- }
- })
-
- # --- Literature Confirmation Handler ---
- observeEvent(input$literature_confirmation_response, {
- req(input$literature_confirmation_response)
-
- user_response <- input$literature_confirmation_response
- print(paste("TaijiChat: Received literature confirmation response:", user_response))
-
- agent_instance_val <- rv_agent_instance()
-
- if (!is.null(agent_instance_val)) {
- tryCatch({
- # Call the agent's literature confirmation handler
- agent_reply_py <- agent_instance_val$handle_literature_confirmation(
- user_response = as.character(user_response)
- )
- agent_reply_text <- as.character(agent_reply_py)
-
- print(paste("TaijiChat: Literature confirmation processed, response:", agent_reply_text))
-
- # Update chat history with the agent's response
- current_hist <- chat_history()
- final_hist <- append(current_hist, list(list(role = "assistant", content = agent_reply_text)))
- chat_history(final_hist)
-
- # Send the response to UI
- session$sendCustomMessage(type = "agent_chat_response", message = list(text = agent_reply_text))
-
- }, error = function(e) {
- error_message <- paste("TaijiChat: Error processing literature confirmation:", e$message)
- warning(error_message)
- print(error_message)
- session$sendCustomMessage(type = "agent_chat_response",
- message = list(text = "Sorry, an error occurred processing your literature preference."))
- })
- } else {
- warning("TaijiChat: Agent instance is NULL during literature confirmation.")
- session$sendCustomMessage(type = "agent_chat_response",
- message = list(text = "The chat agent is not available for literature confirmation."))
- }
- })
-
- # --- END: TaijiChat Message Handling ---
-
- #Render and hyperlink table + edit size so that everything fits into webpage
- output$multiomicsdatatable <- renderDT({
- # Transform the "author" column to contain hyperlinks using the "DOI" column
- multiexcel_data <- multiexcel_data %>%
- mutate(
- Author = paste0(
- "",
- Author, # Column with the display text (e.g., author name)
- ""
- )
- ) %>%
- select(-DOI) # Remove the "DOI" column after linking it to the "author" column
-
- # Dynamically remove empty columns ("18", "19", etc.)
- multiexcel_data <- multiexcel_data %>%
- select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
-
- # Render the data table with fit-to-page options
- datatable(
- multiexcel_data,
- options = list(
- autoWidth = TRUE, # Adjust column widths automatically
- scrollX = TRUE, # Enable horizontal scrolling
- pageLength = 10 # Limit rows displayed per page (adjustable)
- ),
- rownames = FALSE,
- escape = FALSE # Allow HTML rendering for links
- )
- })
-
- # Update reactive expressions to use warning overlay
- output$tfData <- renderDT({
- withWarningOverlayReactive(session, {
- # Your existing reactive code here
- # This will automatically show the warning overlay for long-running operations
- }, "get_processed_tf_data")
- })
-}
-
-
+# server.R
+library(shiny)
+library(readxl)
+library(DT)
+library(dplyr)
+
+# Source the warning overlay and long operations code
+source("warning_overlay.R", local = TRUE)
+source("long_operations.R", local = TRUE)
+
+# setwd("/Users/audrey/Downloads/research/ckweb/Tcellstates")
+
+# Define server logic
+function(input, output, session) {
+
+ # --- START: TaijiChat R Callback for Python Agent Thoughts ---
+ python_agent_thought_callback <- function(thought_message_from_python) {
+ # Attempt to explicitly convert to R character and clean up
+ thought_message_text <- tryCatch({
+ as.character(thought_message_from_python)[1] # Take the first element after converting
+ }, error = function(e) {
+ print(paste("R Callback: Error converting thought to character:", e$message))
+ return(NULL)
+ })
+
+ if (!is.null(thought_message_text) && is.character(thought_message_text) && length(thought_message_text) == 1 && nzchar(trimws(thought_message_text))) {
+ # print(paste("R Callback: Valid thought from Python -", thought_message_text)) # For R console debugging
+ session$sendCustomMessage(type = "agent_new_thought", message = list(text = trimws(thought_message_text)))
+ } else {
+ # Log the original and potentially converted type for better debugging
+ print(paste("R Callback: Received invalid or empty thought. Original type:", class(thought_message_from_python), ", Value:", thought_message_from_python, ", Converted text:", thought_message_text))
+ }
+ }
+ # --- END: TaijiChat R Callback for Python Agent Thoughts ---
+
+ # --- START: TaijiChat Agent Initialization ---
+ # This assumes manager_agent_module is globally available from ui.R's sourcing.
+ # ui.R does: manager_agent_module <- reticulate::import("agents.manager_agent")
+
+ api_key_val <- NULL
+ # First try to get API key from environment variable
+ api_key_val <- Sys.getenv("OPENAI_API_KEY")
+
+ # If environment variable is not set, try reading from file
+ if (api_key_val == "") {
+ tryCatch({
+ api_key_content <- readLines("api_key.txt", warn = FALSE)
+ if (length(api_key_content) > 0 && nzchar(trimws(api_key_content[1]))) {
+ api_key_val <- trimws(api_key_content[1])
+ print("TaijiChat: API key successfully read from file in server.R.")
+ } else {
+ warning("TaijiChat: api_key.txt is empty or not found. LLM features may be disabled.")
+ print("TaijiChat: api_key.txt is empty or not found.")
+ }
+ }, error = function(e) {
+ warning(paste("TaijiChat: Error reading api_key.txt in server.R:", e$message))
+ print(paste("TaijiChat: Error reading api_key.txt:", e$message))
+ })
+ } else {
+ print("TaijiChat: API key successfully read from environment variable.")
+ }
+
+ py_openai_client_instance <- NULL
+ if (!is.null(api_key_val)) {
+ tryCatch({
+ # Ensure reticulate is configured to use the correct Python environment
+ if (reticulate::py_available(initialize = TRUE)) {
+ openai_py_module <- reticulate::import("openai", convert = FALSE) # convert=FALSE for raw Python objects
+ py_openai_client_instance <- openai_py_module$OpenAI(api_key = api_key_val)
+ print("TaijiChat: Python OpenAI client initialized successfully in server.R via reticulate.")
+ } else {
+ warning("TaijiChat: Python (reticulate) not available or not initialized. Cannot create OpenAI client.")
+ print("TaijiChat: Python (reticulate) not available. Cannot create OpenAI client.")
+ }
+ }, error = function(e) {
+ warning(paste("TaijiChat: Failed to initialize Python OpenAI client in server.R:", e$message))
+ print(paste("TaijiChat: Failed to initialize Python OpenAI client:", e$message))
+ py_openai_client_instance <- NULL
+ })
+ } else {
+ print("TaijiChat: API key is NULL, skipping Python OpenAI client initialization.")
+ }
+
+ rv_agent_instance <- reactiveVal(NULL)
+
+ # Attempt to create the agent instance once.
+ current_manager_agent_module <- NULL
+ tryCatch({
+ # Force reload the module to ensure we get the latest version
+ print("TaijiChat: Attempting to reload Python modules to ensure latest version...")
+ reticulate::py_run_string("
+import sys
+import importlib
+if 'agents.manager_agent' in sys.modules:
+ print('Reloading agents.manager_agent module...')
+ importlib.reload(sys.modules['agents.manager_agent'])
+")
+
+ current_manager_agent_module <- reticulate::import("agents.manager_agent", convert = FALSE)
+ if (is.null(current_manager_agent_module)) {
+ warning("TaijiChat: reticulate::import('agents.manager_agent') returned NULL in server.R.")
+ print("TaijiChat: reticulate::import('agents.manager_agent') returned NULL in server.R.")
+ } else {
+ print("TaijiChat: Successfully imported/retrieved 'agents.manager_agent' module in server.R.")
+ }
+ }, error = function(e) {
+ warning(paste("TaijiChat: Failed to import agents.manager_agent in server.R:", e$message))
+ print(paste("TaijiChat: Failed to import agents.manager_agent in server.R:", e$message))
+ })
+
+ if (!is.null(current_manager_agent_module)) {
+ # Module is available, now try to instantiate the agent
+ if (!is.null(py_openai_client_instance)) {
+ tryCatch({
+ agent_inst <- current_manager_agent_module$ManagerAgent(
+ openai_client = py_openai_client_instance,
+ r_callback_fn = python_agent_thought_callback # Pass the R callback here
+ )
+ rv_agent_instance(agent_inst)
+ print("TaijiChat: Python ManagerAgent instance created in server.R using pre-initialized client and R callback.")
+ }, error = function(e) {
+ warning(paste("TaijiChat: Failed to instantiate ManagerAgent in server.R with client & callback:", e$message))
+ print(paste("TaijiChat: Failed to instantiate ManagerAgent with client & callback:", e$message))
+ })
+ } else if (!is.null(api_key_val)) { # Try with API key if client object failed but key exists
+ tryCatch({
+ agent_inst <- current_manager_agent_module$ManagerAgent(
+ openai_api_key = api_key_val,
+ r_callback_fn = python_agent_thought_callback # Pass the R callback here
+ )
+ rv_agent_instance(agent_inst)
+ print("TaijiChat: Python ManagerAgent instance created in server.R with API key and R callback (client to be init by Python).")
+ }, error = function(e) {
+ warning(paste("TaijiChat: Failed to instantiate ManagerAgent with API key & callback in server.R:", e$message))
+ print(paste("TaijiChat: Failed to instantiate ManagerAgent with API key & callback:", e$message))
+ })
+ } else {
+ # Neither client nor API key is available for the agent
+ warning("TaijiChat: Cannot create ManagerAgent instance: OpenAI client/API key not available for agent constructor.")
+ print("TaijiChat: Cannot create ManagerAgent: OpenAI client/API key not available for agent constructor.")
+ }
+ } else {
+ # Module itself could not be imported/retrieved
+ warning("TaijiChat: agents.manager_agent module is NULL after import attempt. Agent not created.")
+ print("TaijiChat: agents.manager_agent module is NULL after import attempt. Agent not created.")
+ }
+ # --- END: TaijiChat Agent Initialization ---
+
+ # Server logic for home tab
+ output$home <- renderText({
+ "Welcome to the Home page"
+ })
+
+ observeEvent(input$read_now, {
+ # Trigger a redirect using JavaScript
+ session$sendCustomMessage(type = "redirect",
+ message = "https://doi.org/10.1101/2023.01.03.522354")
+ })
+
+
+ # NEW READ EXCEL FILE FOR TRANSPOSED DATASET
+ new_read_excel_file <- function(path) {
+ withWarningOverlay(session, function() {
+ df <- read_excel(path)
+ colnames(df)[1] <- "Regulator Names"
+
+ # Transpose the dataframe
+ df_transposed <- as.data.frame(t(df))
+
+ # Fix the column names of the transposed dataframe (optional)
+ colnames(df_transposed) <- df_transposed[1, ] # Set first row as column names
+ df_transposed <- df_transposed[-1, ] # Remove the first row which is now used as column names
+
+ return(df_transposed)
+ }, "Reading and processing Excel file...")
+ }
+
+ # # NEW FILTER FUNCTION FOR TRANSPOSED DATASET
+ # new_filter_data <- function(df, keyword) {
+ #
+ # # Find the columns whose names contain the keyword
+ # matching_columns <- grepl(keyword, colnames(df), ignore.case = TRUE)
+ #
+ # # Check if any matching columns exist
+ # if (sum(matching_columns) == 0) {
+ # # If no matching columns are found, return an empty dataframe with proper structure
+ # return(data.frame())
+ # }
+ #
+ # # Subset the dataframe, ensuring the result is always a dataframe
+ # filtered_df <- df[, matching_columns, drop = FALSE]
+ #
+ # return(filtered_df)
+ # }
+
+ #NEW FILTER FUNCTION FOR MULTIPLE GENE SEARCH
+ # new_filter_data <- function(df, keywords) {
+ # # Split the keywords by commas and remove any leading/trailing whitespace
+ # keyword_list <- strsplit(keywords, ",")[[1]]
+ # keyword_list <- trimws(keyword_list)
+ #
+ # # Initialize an empty logical vector for matching columns
+ # matching_columns <- rep(FALSE, ncol(df))
+ #
+ # # Loop through each keyword and update the matching_columns vector
+ # for (keyword in keyword_list) {
+ # matching_columns <- matching_columns | grepl(keyword, colnames(df), ignore.case = TRUE)
+ # }
+ #
+ # # Check if any matching columns exist
+ # if (sum(matching_columns) == 0) {
+ # # If no matching columns are found, return an empty dataframe with proper structure
+ # return(data.frame())
+ # }
+ #
+ # # Subset the dataframe, ensuring the result is always a dataframe
+ # filtered_df <- df[, matching_columns, drop = FALSE]
+ #
+ # return(filtered_df)
+ # }
+
+ new_filter_data <- function(df, keywords) {
+ # If no keywords are provided, return the full dataset
+ if (is.null(keywords) || keywords == "") {
+ return(df)
+ }
+
+ # Split the keywords by commas and remove any leading/trailing whitespace
+ keyword_list <- strsplit(keywords, ",")[[1]]
+ keyword_list <- trimws(keyword_list) # Remove leading/trailing spaces
+
+ # Initialize an empty logical vector for matching columns
+ matching_columns <- rep(FALSE, ncol(df))
+
+ # Loop through each keyword and update the matching_columns vector
+ for (keyword in keyword_list) {
+ matching_columns <- matching_columns | grepl(keyword, colnames(df), ignore.case = TRUE)
+ }
+
+ # Check if any matching columns exist
+ if (sum(matching_columns) == 0) {
+ # If no matching columns are found, return an empty dataframe
+ return(data.frame())
+ }
+
+ # Subset the dataframe, ensuring the result is always a dataframe
+ filtered_df <- df[, matching_columns, drop = FALSE]
+
+ return(filtered_df)
+ }
+
+
+
+
+ # TESTING FUNCTIONS
+
+ #NEW ALL DATA SEARCH
+ data <- reactive({
+ new_read_excel_file("www/tablePagerank/Table_TF PageRank Scores for Audrey.xlsx")
+ })
+
+ # Track the current column page
+ column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for main page data
+ observeEvent(input$search_input, {
+ column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked
+ observeEvent(input$next_btn, {
+ current_page <- column_page()
+ total_cols <- ncol(new_filter_data(data(), input$search_input))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ column_page(current_page + 1)
+ }
+
+ # new_page <- column_page() + 1
+ # column_page(new_page)
+ })
+
+ observeEvent(input$prev_btn, {
+ current_page <- column_page()
+ column_page(max(current_page - 1, 1))
+ # new_page <- max(column_page() - 1, 1) # Ensure the page does not go below 1
+ # column_page(new_page)
+ })
+
+ # # OLD: Reactive for filtering the data based on input$search_input
+ # new_filtered_data <- reactive({
+ #
+ # df <- new_filter_data(data(), input$search_input)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # Ensure start_col is within the number of columns
+ # if (start_col > total_cols) {
+ # return(df) # Return the filtered dataframe as-is if start_col exceeds the number of columns
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ # return(df_subset)
+ # })
+
+ #NEW FILTER DATA TO INCLUDE ADDITIONAL DESCRIPTION ROW + WORKS WITH SEARCHING INDIVIDUAL GENES
+ new_filtered_data <- reactive({
+ # Filter the data and determine the total number of columns
+ df <- new_filter_data(data(), input$search_input)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Combine the data with the description and styled "Cell state data" row
+ df_subset <- rbind(df_subset[1:2, , drop = FALSE], description_row, df_subset[-(1:2), , drop = FALSE])
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 2; // Adjust this index to the row you want highlighted
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered data table and showing all rows
+ output$table <- renderDT({
+ new_filtered_data()
+ }, options = list(pageLength = nrow(new_filtered_data()), dom = 't'))
+
+
+
+
+ #NEW NAIVE SEARCH
+ naive_data <- reactive({
+ new_read_excel_file("www/tablePagerank/Naive.xlsx")
+ })
+
+ # Track the current column page for naive data
+ naive_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for naive data
+ observeEvent(input$search_input_naive, {
+ naive_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Reset the column page when the search input changes for naive data
+ observeEvent(input$search_input_naive, {
+ naive_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for naive data
+ observeEvent(input$naive_next_btn, {
+ current_page <- naive_column_page()
+ total_cols <- ncol(new_filter_data(naive_data(), input$search_input_naive))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ naive_column_page(current_page + 1)
+ }
+
+ # new_page <- naive_column_page() + 1
+ # naive_column_page(new_page)
+ })
+
+ observeEvent(input$naive_prev_btn, {
+ current_page <- naive_column_page()
+ naive_column_page(max(current_page - 1, 1))
+ # new_page <- max(naive_column_page() - 1, 1) # Ensure the page does not go below 1
+ # naive_column_page(new_page)
+ })
+
+ #OLD FILTERED DATA
+ # filtered_naive_data <- reactive({
+ #
+ # df <- new_filter_data(naive_data(), input$search_input_naive)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (naive_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # Ensure start_col is within the number of columns
+ # if (start_col > total_cols) {
+ # return(df) # Return the filtered dataframe as-is if start_col exceeds the number of columns
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_naive_data <- reactive({
+ # Filter the naive data and determine the total number of columns
+ df <- new_filter_data(naive_data(), input$search_input_naive)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (naive_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ output$table_naive <- renderDT({
+ filtered_naive_data()
+ }, options = list(pageLength = nrow(filtered_naive_data()), dom = 't'))
+
+
+
+ #NEW TE SEARCH
+ te_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TE.xlsx")
+ })
+
+ # Track the current column page for "te" data
+ te_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "te" data
+ observeEvent(input$search_input_te, {
+ te_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "te" data
+ observeEvent(input$te_next_btn, {
+ current_page <- te_column_page()
+ total_cols <- ncol(new_filter_data(te_data(), input$search_input_te))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ te_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$te_prev_btn, {
+ current_page <- te_column_page()
+ te_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "te" page data
+ # filtered_te_data <- reactive({
+ # df <- new_filter_data(te_data(), input$search_input_te)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (te_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_te_data <- reactive({
+ # Filter the TE data and determine the total number of columns
+ df <- new_filter_data(te_data(), input$search_input_te)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (te_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "te" page data table and showing all rows
+ output$table_te <- renderDT({
+ filtered_te_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_te_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+
+ #NEW MP SEARCH
+ mp_data <- reactive({
+ new_read_excel_file("www/tablePagerank/MP.xlsx")
+ })
+
+ # Track the current column page for "mp" data
+ mp_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "mp" data
+ observeEvent(input$search_input_mp, {
+ mp_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "mp" data
+ observeEvent(input$mp_next_btn, {
+ current_page <- mp_column_page()
+ total_cols <- ncol(new_filter_data(mp_data(), input$search_input_mp))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ mp_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$mp_prev_btn, {
+ current_page <- mp_column_page()
+ mp_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "mp" page data
+ # filtered_mp_data <- reactive({
+ # df <- new_filter_data(mp_data(), input$search_input_mp)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (mp_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_mp_data <- reactive({
+ # Filter the MP data and determine the total number of columns
+ df <- new_filter_data(mp_data(), input$search_input_mp)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (mp_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "mp" page data table and showing all rows
+ output$table_mp <- renderDT({
+ filtered_mp_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_mp_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+
+ #NEW TCM SEARCH
+ tcm_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TCM.xlsx")
+ })
+
+ # Track the current column page for "tcm" data
+ tcm_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "tcm" data
+ observeEvent(input$search_input_tcm, {
+ tcm_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "tcm" data
+ observeEvent(input$tcm_next_btn, {
+ current_page <- tcm_column_page()
+ total_cols <- ncol(new_filter_data(tcm_data(), input$search_input_tcm))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ tcm_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$tcm_prev_btn, {
+ current_page <- tcm_column_page()
+ tcm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "tcm" page data
+ # filtered_tcm_data <- reactive({
+ # df <- new_filter_data(tcm_data(), input$search_input_tcm)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (tcm_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_tcm_data <- reactive({
+ # Filter the TCM data and determine the total number of columns
+ df <- new_filter_data(tcm_data(), input$search_input_tcm)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (tcm_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "tcm" page data table and showing all rows
+ output$table_tcm <- renderDT({
+ filtered_tcm_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_tcm_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+ #NEW TEM SEARCH
+ tem_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TEM.xlsx")
+ })
+
+ # Track the current column page for "tem" data
+ tem_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "tem" data
+ observeEvent(input$search_input_tem, {
+ tem_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "tem" data
+ observeEvent(input$tem_next_btn, {
+ current_page <- tem_column_page()
+ total_cols <- ncol(new_filter_data(tem_data(), input$search_input_tem))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ tem_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$tem_prev_btn, {
+ current_page <- tem_column_page()
+ tem_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "tem" page data
+ # filtered_tem_data <- reactive({
+ # df <- new_filter_data(tem_data(), input$search_input_tem)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (tem_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_tem_data <- reactive({
+ # Filter the TEM data and determine the total number of columns
+ df <- new_filter_data(tem_data(), input$search_input_tem)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (tem_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "tem" page data table and showing all rows
+ output$table_tem <- renderDT({
+ filtered_tem_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_tem_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+ #NEW TRM SEARCH
+ trm_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TRM.xlsx")
+ })
+
+ # Track the current column page for "trmm" data
+ trm_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "trmm" data
+ observeEvent(input$search_input_trm, {
+ trm_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "trmm" data
+ observeEvent(input$trm_next_btn, {
+ current_page <- trm_column_page()
+ total_cols <- ncol(new_filter_data(trm_data(), input$search_input_trm))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ trm_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$trm_prev_btn, {
+ current_page <- trm_column_page()
+ trm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "trmm" page data
+ # filtered_trm_data <- reactive({
+ # df <- new_filter_data(trm_data(), input$search_input_trm)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (trm_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_trm_data <- reactive({
+ # Filter the TRM data and determine the total number of columns
+ df <- new_filter_data(trm_data(), input$search_input_trm)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (trm_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "trmm" page data table and showing all rows
+ output$table_trm <- renderDT({
+ filtered_trm_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_trm_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+ #NEW TEX PROG SEARCH
+ texprog_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TEXprog.xlsx")
+ })
+
+ # Track the current column page for "texprog" data
+ texprog_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "texprog" data
+ observeEvent(input$search_input_texprog, {
+ texprog_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "texprog" data
+ observeEvent(input$texprog_next_btn, {
+ current_page <- texprog_column_page()
+ total_cols <- ncol(new_filter_data(texprog_data(), input$search_input_texprog))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ texprog_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$texprog_prev_btn, {
+ current_page <- texprog_column_page()
+ texprog_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "texprog" page data
+ # filtered_texprog_data <- reactive({
+ # df <- new_filter_data(texprog_data(), input$search_input_texprog)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (texprog_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_texprog_data <- reactive({
+ # Filter the TEXprog data and determine the total number of columns
+ df <- new_filter_data(texprog_data(), input$search_input_texprog)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (texprog_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "texprog" page data table and showing all rows
+ output$table_texprog <- renderDT({
+ filtered_texprog_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_texprog_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+ #NEW TEX EFF LIKE SEARCH
+ texefflike_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TEXeff.xlsx")
+ })
+
+ # Track the current column page for "texefflike" data
+ texefflike_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "texefflike" data
+ observeEvent(input$search_input_texefflike, {
+ texefflike_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "texefflike" data
+ observeEvent(input$texefflike_next_btn, {
+ current_page <- texefflike_column_page()
+ total_cols <- ncol(new_filter_data(texefflike_data(), input$search_input_texefflike))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ texefflike_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$texefflike_prev_btn, {
+ current_page <- texefflike_column_page()
+ texefflike_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "texefflike" page data
+ # filtered_texefflike_data <- reactive({
+ # df <- new_filter_data(texefflike_data(), input$search_input_texefflike)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (texefflike_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_texefflike_data <- reactive({
+ # Filter the TEXefflike data and determine the total number of columns
+ df <- new_filter_data(texefflike_data(), input$search_input_texefflike)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (texefflike_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "texefflike" page data table and showing all rows
+ output$table_texefflike <- renderDT({
+ filtered_texefflike_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_texefflike_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+
+ #NEW TEX TERM SEARCH
+ texterm_data <- reactive({
+ new_read_excel_file("www/tablePagerank/TEXterm.xlsx")
+ })
+
+ # Track the current column page for "texterm" data
+ texterm_column_page <- reactiveVal(1)
+
+ # Reset the column page when the search input changes for "texterm" data
+ observeEvent(input$search_input_texterm, {
+ texterm_column_page(1) # Reset to page 1 when a new search is made
+ })
+
+ # Update the column page when buttons are clicked for "texterm" data
+ observeEvent(input$texterm_next_btn, {
+ current_page <- texterm_column_page()
+ total_cols <- ncol(new_filter_data(texterm_data(), input$search_input_texterm))
+
+ # Calculate the maximum possible number of pages
+ max_page <- ceiling(total_cols / 4)
+
+ # Move to the next page, but do not exceed the max_page
+ if (current_page < max_page) {
+ texterm_column_page(current_page + 1)
+ }
+ })
+
+ observeEvent(input$texterm_prev_btn, {
+ current_page <- texterm_column_page()
+ texterm_column_page(max(current_page - 1, 1)) # Ensure the page does not go below 1
+ })
+
+ #OLD: Reactive for filtering and paginating the "texterm" page data
+ # filtered_texterm_data <- reactive({
+ # df <- new_filter_data(texterm_data(), input$search_input_texterm)
+ #
+ # # Get the total number of columns in the filtered dataframe
+ # total_cols <- ncol(df)
+ #
+ # # Ensure there are columns after filtering
+ # if (total_cols == 0) {
+ # return(data.frame()) # Return an empty dataframe if no columns match the search
+ # }
+ #
+ # # Define the start and end index for columns based on the current page
+ # start_col <- (texterm_column_page() - 1) * 4 + 1
+ # end_col <- min(start_col + 3, total_cols) # Show up to 4 columns
+ #
+ # # If start_col exceeds the total number of columns, return the last valid subset
+ # if (start_col > total_cols) {
+ # start_col <- (ceiling(total_cols / 4) - 1) * 4 + 1 # Set start_col to the last valid page
+ # end_col <- total_cols # End with the last column
+ # }
+ #
+ # # Subset the columns for the current page
+ # df_subset <- df[, start_col:end_col, drop = FALSE]
+ #
+ # return(df_subset)
+ # })
+
+ #NEW FILTERED DATA
+ filtered_texterm_data <- reactive({
+ # Filter the TEXterm data and determine the total number of columns
+ df <- new_filter_data(texterm_data(), input$search_input_texterm)
+ total_cols <- ncol(df)
+
+ # Return empty dataframe if no columns match the search
+ if (total_cols == 0) return(data.frame())
+
+ # Define the column range for the current page
+ start_col <- (texterm_column_page() - 1) * 4 + 1
+ end_col <- min(start_col + 3, total_cols)
+
+ # Return filtered data if start_col exceeds the total columns
+ if (start_col > total_cols) return(df)
+
+ # Subset the dataframe for the current page
+ df_subset <- df[, start_col:end_col, drop = FALSE]
+
+ # Apply HTML formatting to description and "Cell state data" rows, moving them to the first row
+ if (nrow(df_subset) >= 2) {
+ description_row <- data.frame(
+ matrix(NA, nrow = 1, ncol = ncol(df_subset), dimnames = list(NULL, colnames(df_subset)))
+ )
+
+ # Define the HTML style for the description row (making "TF activity score" bold with white font and background color)
+ style <- "TF activity score
"
+
+ # Apply style to both description and "Cell state data"
+ description_row[1, ] <- style
+ rownames(description_row)[1] <- "Cell state data"
+
+ # Move the description row to the first row of the subset
+ df_subset <- rbind(description_row, df_subset) # Move this styled row to the first position
+ }
+
+ # Return the data with HTML rendering enabled, show all 45 rows, and remove the search box
+ DT::datatable(df_subset, escape = FALSE, options = list(
+ pageLength = 45,
+ lengthChange = FALSE,
+ searching = FALSE, # Remove the search box
+ rowCallback = JS(
+ "function(row, data, index) {
+ var highlightedRow = 0; // Apply styling to the first row
+
+ if (index === highlightedRow) {
+ $('td', row).css({
+ 'background-color': '#95a5a6',
+ 'color': 'white',
+ 'font-weight': 'bold'
+ });
+ }
+ }"
+ )
+ ))
+ })
+
+ # Rendering the filtered "texterm" page data table and showing all rows
+ output$table_texterm <- renderDT({
+ filtered_texterm_data() # Use the filtered data with pagination logic applied
+ }, options = list(
+ pageLength = nrow(filtered_texterm_data()), # Show all rows
+ dom = 't', # Remove the row length dropdown
+ scrollX = TRUE # Enable horizontal scrolling if needed
+ ))
+
+
+
+
+ # # ORIGINAL READ EXCEL FILE
+ # read_excel_file <- function(path) {
+ # df <- read_excel(path)
+ # colnames(df)[1] <- "Regulator Names"
+ # return(df)
+ # }
+ #
+ # # ORIGINAL FILTER FUNCTION
+ # filter_data <- function(data, keyword) {
+ # if (is.null(keyword) || is.na(keyword) || keyword == "") {
+ # return(data)
+ # } else {
+ # keyword <- tolower(keyword)
+ # return(data[apply(data, 1, function(x) any(grepl(keyword, tolower(x)))), ])
+ # }
+ # }
+ #
+ # #ORIGINAL DISPLAY TABLE FUNCTION
+ # # Main page data
+ # data <- reactive({
+ # read_excel_file("www/tablePagerank/Table_TF PageRank Scores for Audrey.xlsx")
+ # })
+ #
+ # filtered_data <- reactive({
+ # filter_data(data(), input$search_input)
+ # })
+ #
+ # output$table <- renderDT({
+ # filtered_data()
+ # })
+
+
+
+ # Server logic for naive tab
+ output$naive <- renderText({
+ "TF Activity Score: Naive"
+ })
+
+ # OLD NAIVE DATA TABLE
+ # naive_data <- reactive({
+ # read_excel_file("www/tablePagerank/Naive.xlsx")
+ # })
+ #
+ # filtered_naive_data <- reactive({
+ # filter_data(naive_data(), input$search_input_naive)
+ # })
+ #
+ # output$table_naive <- renderDT({
+ # filtered_naive_data()
+ # })
+
+
+ # Server logic for TE tab
+ output$te <- renderText({
+ "TF Activity Score: TE"
+ })
+
+ # OLD TE DATA TABLE
+ # te_data <- reactive({
+ # read_excel_file("www/tablePagerank/TE.xlsx")
+ # })
+ #
+ # filtered_te_data <- reactive({
+ # filter_data(te_data(), input$search_input_te)
+ # })
+ #
+ # output$table_te <- renderDT({
+ # filtered_te_data()
+ # })
+
+ # Server logic for MP tab
+ output$mp <- renderText({
+ "TF Activity Score: MP"
+ })
+
+ # OLD MP DATA
+ # mp_data <- reactive({
+ # read_excel_file("www/tablePagerank/MP.xlsx")
+ # })
+ #
+ # filtered_mp_data <- reactive({
+ # filter_data(mp_data(), input$search_input_mp)
+ # })
+ #
+ # output$table_mp <- renderDT({
+ # filtered_mp_data()
+ # })
+
+ # Server logic for T CM tab
+ output$tcm <- renderText({
+ "TF Activity Score: T CM"
+ })
+
+ # OLD TCM DATA
+ # tcm_data <- reactive({
+ # read_excel_file("www/tablePagerank/TCM.xlsx")
+ # })
+ #
+ # filtered_tcm_data <- reactive({
+ # filter_data(tcm_data(), input$search_input_tcm)
+ # })
+ #
+ # output$table_tcm <- renderDT({
+ # filtered_tcm_data()
+ # })
+
+ # Server logic for T EM tab
+ output$tem <- renderText({
+ "TF Activity Score: T EM"
+ })
+
+ # OLD TEM DATA
+ # tem_data <- reactive({
+ # read_excel_file("www/tablePagerank/TEM.xlsx")
+ # })
+ #
+ # filtered_tem_data <- reactive({
+ # filter_data(tem_data(), input$search_input_tem)
+ # })
+ #
+ # output$table_tem <- renderDT({
+ # filtered_tem_data()
+ # })
+ #
+ # # Server logic for T RM tab
+ # output$trm <- renderText({
+ # "TF Activity Score: T RM"
+ # })
+
+ # OLD TRM DATA
+ # trm_data <- reactive({
+ # read_excel_file("www/tablePagerank/TRM.xlsx")
+ # })
+ #
+ # filtered_trm_data <- reactive({
+ # filter_data(trm_data(), input$search_input_trm)
+ # })
+ #
+ # output$table_trm <- renderDT({
+ # filtered_trm_data()
+ # })
+
+ # Server logic for Tex Prog tab
+ output$texprog <- renderText({
+ "TF Activity Score: Tex Prog"
+ })
+
+ # OLD TEX PROG DATA
+ # texprog_data <- reactive({
+ # read_excel_file("www/tablePagerank/TEXprog.xlsx")
+ # })
+ #
+ # filtered_texprog_data <- reactive({
+ # filter_data(texprog_data(), input$search_input_texprog)
+ # })
+ #
+ # output$table_texprog <- renderDT({
+ # filtered_texprog_data()
+ # })
+
+
+ # Server logic for Tex Eff-like tab
+ output$texefflike <- renderText({
+ "TF Activity Score: Tex Eff-like"
+ })
+
+ # OLD TEX EFF LIKE DATA
+ # texefflike_data <- reactive({
+ # read_excel_file("www/tablePagerank/TEXeff.xlsx")
+ # })
+ #
+ # filtered_texefflike_data <- reactive({
+ # filter_data(texefflike_data(), input$search_input_texefflike)
+ # })
+ #
+ # output$table_texefflike <- renderDT({
+ # filtered_texefflike_data()
+ # })
+
+ # Server logic for Tex Term tab
+ output$texterm <- renderText({
+ "TF Activity Score: Tex Term"
+ })
+
+ # OLD TEX TERM DATA
+ # texterm_data <- reactive({
+ # read_excel_file("www/tablePagerank/TEXterm.xlsx")
+ # })
+ #
+ # filtered_texterm_data <- reactive({
+ # filter_data(texterm_data(), input$search_input_texterm)
+ # })
+ #
+ # output$table_texterm <- renderDT({
+ # filtered_texterm_data()
+ # })
+
+
+
+ #click image code for TF Wave Analysis
+ observeEvent(input$c1_link, {
+ updateNavbarPage(session, "mainNav", selected = "c1")
+ })
+
+ observeEvent(input$c2_link, {
+ updateNavbarPage(session, "mainNav", selected = "c2")
+ })
+
+ observeEvent(input$c3_link, {
+ updateNavbarPage(session, "mainNav", selected = "c3")
+ })
+
+ observeEvent(input$c4_link, {
+ updateNavbarPage(session, "mainNav", selected = "c4")
+ })
+
+ observeEvent(input$c5_link, {
+ updateNavbarPage(session, "mainNav", selected = "c5")
+ })
+
+ observeEvent(input$c6_link, {
+ updateNavbarPage(session, "mainNav", selected = "c6")
+ })
+
+ observeEvent(input$c7_link, {
+ updateNavbarPage(session, "mainNav", selected = "c7")
+ })
+
+
+ # Handle specific image part clicks to navigate to the subpages
+ observeEvent(input$to_tfcat, {
+ updateNavbarPage(session, "mainNav", selected = "tfcatpage")
+ })
+
+ observeEvent(input$to_tfwave, {
+ updateNavbarPage(session, "mainNav", selected = "overview")
+ })
+
+ observeEvent(input$to_tfnet, {
+ updateNavbarPage(session, "mainNav", selected = "tfnetpage")
+ })
+
+ # SEARCH FOR A TF AND FIND OUT WHICH WAVE THEY ARE APART OF
+ # Function to read the file and assign proper column names
+ read_searchwave_file <- function(path) {
+ df <- read_excel(path) # Read the Excel file
+ colnames(df) <- c("Wave1", "Wave2", "Wave3", "Wave4", "Wave5", "Wave6", "Wave7") # Customize as needed
+ return(df)
+
+ return(df)
+ }
+
+ # Load data reactively
+ searchwavedata <- reactive({
+ # Provide the path to your Excel file
+ read_searchwave_file("www/waveanalysis/searchtfwaves.xlsx") # Path to your file
+ })
+
+ # Reactive function to search and filter the data based on the wave search input
+ filtered_wave_data <- reactive({
+ # Get the search input
+ search_term <- input$search_input_wave
+
+ # If no search term, return the entire dataset in the desired transposed format
+ if (is.null(search_term) || search_term == "") {
+ # Initialize an empty list to store the gene names for each wave
+ wave_genes <- list()
+
+ # Iterate over each wave column and get the associated genes
+ for (col in colnames(searchwavedata())) {
+ wave_genes[[col]] <- searchwavedata()[[col]] # Store all gene names for each wave
+ }
+
+ # Create a data frame with waves as columns and genes as rows
+ result_df <- data.frame(wave_genes)
+
+ # Return the transposed data frame with wave numbers as column headers and genes as rows
+ return(result_df)
+ }
+
+ # Initialize an empty list to store the result
+ result <- list()
+
+ # Iterate through each column and check if the search term exists
+ for (col in colnames(searchwavedata())) {
+ # Filter genes for each column where the search term matches
+ matching_genes <- searchwavedata()[[col]][grepl(search_term, searchwavedata()[[col]], ignore.case = TRUE)]
+
+ # If there are matching genes, store them
+ if (length(matching_genes) > 0) {
+ result[[col]] <- paste(matching_genes, collapse = ", ") # Combine matching genes as a string
+ }
+ }
+
+ # If no results are found, return an empty dataframe
+ if (length(result) == 0) {
+ return(data.frame(Wave = character(0), Gene = character(0))) # Return empty data frame if nothing matches
+ }
+
+ # Convert the result list to a data frame
+ result_df <- data.frame(
+ Wave = names(result), # Column names as 'Wave'
+ Gene = unlist(result), # Concatenated list of matching gene names
+ stringsAsFactors = FALSE
+ )
+
+ # Remove any duplicate wave names (keep only one occurrence per wave)
+ result_df <- result_df[!duplicated(result_df$Wave), ]
+
+ # Remove rows where Gene column is NA or empty
+ result_df <- result_df[!is.na(result_df$Gene) & result_df$Gene != "", ]
+
+ # Create a matrix with wave names as columns and gene names as rows
+ transposed_df <- matrix(unlist(result_df$Gene), nrow = 1) # Convert the gene names to a row
+
+ # Set the column names to the wave numbers, replacing "Wave 1" instead of "wave.1"
+ colnames(transposed_df) <- paste("Wave", seq_along(result_df$Wave))
+
+ # Return the transposed result
+ return(as.data.frame(transposed_df))
+ })
+
+ # Render the table output based on the filtered and transposed data
+ output$table_wave <- renderDT({
+ # Get the filtered and transposed data
+ df <- filtered_wave_data()
+
+ # Render the data table without row names and disable the default search box
+ datatable(df, options = list(searching = FALSE), rownames = FALSE)
+ })
+
+
+
+
+ # # Function to read Excel files
+ # read_regulator_file <- function(path) {
+ # df <- read_excel(path)
+ # colnames(df)[1] <- " " # Adjust column name as needed
+ # return(df)
+ # }
+ #
+ # # Load data initially
+ # tfregulated_data <- reactive({
+ # read_regulator_file("www/networkanalysis/comp_log2FC_RegulatedData_TRMTEXterm.xlsx")
+ # })
+ #
+ # # Filtered data based on search input
+ # filtered_tfregulated_data <- reactive({
+ # req(tfregulated_data()) # Ensure tfregulated_data() is available
+ # if (is.null(input$search_tfregulated_data) || input$search_tfregulated_data == "") {
+ # return(tfregulated_data())
+ # } else {
+ # # Perform filtering based on input$search_tfregulated_data
+ # # Example filtering logic:
+ # # filtered_data <- tfregulated_data() %>%
+ # # filter(...) # Add your filtering logic here
+ # # return(filtered_data)
+ # # Replace the above with your actual filtering logic
+ # return(tfregulated_data()) # Placeholder for now
+ # }
+ # })
+ #
+ # # Render the DataTable
+ # output$table_tfregulated_data <- renderDT({
+ # datatable(filtered_tfregulated_data())
+ # })
+
+
+
+ # ORIGINALLY SEARCH TRM TEXterm COORELATION
+ # Load Excel file when the app starts
+ data_tftfimage <- read_excel("www/TFcorintextrm/TF-TFcorTRMTEX.xlsx")
+
+ # Reactive function to filter the data based on the search input (case-insensitive)
+ filtered_data_tftfimage <- reactive({
+ req(input$search) # Ensure search input is available
+
+ # Convert both the column and search input to lowercase for case-insensitive comparison
+ data_filtered <- data_tftfimage[tolower(data_tftfimage[["TF Name"]]) == tolower(input$search), ]
+ return(data_filtered)
+ })
+
+
+ # Render the first column (Gene Names) as clickable links
+ output$gene_list_table <- renderUI({
+ tagList(
+ lapply(data_tftfimage[[1]], function(gene_name) { # Assuming the first column contains gene names
+ tags$div(
+ actionLink(
+ inputId = paste0("gene_", gene_name), # Unique input ID for each gene
+ label = gene_name
+ ),
+ style = "margin-bottom: 10px;" # Add spacing between links
+ )
+ })
+ )
+ })
+
+ # Generate dynamic observers for each gene link
+ lapply(data_tftfimage[[1]], function(gene_name) {
+ observeEvent(input[[paste0("gene_", gene_name)]], {
+ # Find the row corresponding to the clicked gene
+ selected_gene_data <- data_tftfimage[data_tftfimage[[1]] == gene_name, ]
+ img_src <- selected_gene_data[["TF Merged Graph Path"]] # Replace with the actual image column name
+
+ # Update the image gallery output with the selected gene's image
+ output$image_gallery <- renderUI({
+ if (!is.null(img_src) && nchar(img_src) > 0) {
+ tags$div(
+ style = "text-align: center;",
+ tags$img(src = img_src, style = "max-width: 100%; height: auto;"),
+ tags$p(gene_name) # Optionally display the gene name below the image
+ )
+ } else {
+ "No image available for the selected gene."
+ }
+ })
+ })
+ })
+
+ # Event to handle search functionality (unchanged from your original code)
+ observeEvent(input$search_btn, {
+ output$result_table <- renderTable({
+ if (nrow(filtered_data_tftfimage()) > 0) {
+ filtered_data_tftfimage()[, -which(names(filtered_data_tftfimage()) == "TF Merged Graph Path")] # Show all columns except the image path
+ } else {
+ NULL # If no results, display nothing
+ }
+ })
+
+ output$image_gallery <- renderUI({
+ if (nrow(filtered_data_tftfimage()) > 0) {
+ image_list <- lapply(1:nrow(filtered_data_tftfimage()), function(i) {
+ img_src <- filtered_data_tftfimage()[[ "TF Merged Graph Path" ]][i]
+ tags$div(
+ style = "text-align: center; margin-bottom: 20px;",
+ tags$img(src = img_src, style = "max-width: 100%; height: auto;")
+ )
+ })
+ do.call(tags$div, image_list)
+ } else {
+ "TF not found. Please search for a valid TF."
+ }
+ })
+ })
+
+
+
+ #tf communities
+ # Read the first Excel file directly from the specified path
+ datatrm <- read_excel("www/tfcommunities/trmcommunities.xlsx")
+
+ # Read the second Excel file directly from the specified path
+ datatex <- read_excel("www/tfcommunities/texcommunities.xlsx")
+
+ # Render the first table without the search button
+ output$trmcom <- renderDT({
+ datatable(
+ datatrm,
+ options = list(
+ lengthChange = FALSE,
+ pageLength = 5,
+ searching = FALSE # Disable the search button
+ )
+ )
+ })
+
+ # Render the second table without the search button
+ output$texcom <- renderDT({
+ datatable(
+ datatex,
+ options = list(
+ lengthChange = FALSE,
+ pageLength = 5,
+ searching = FALSE # Disable the search button
+ )
+ )
+ })
+
+
+ # Load your multiomics file
+ multiexcel_data <- read_excel("www/multi-omicsdata.xlsx")
+
+ # #Render data table + hyperlinks author's name to DOI
+ # output$multiomicsdatatable <- renderDT({
+ # # Transform the "author" column to contain hyperlinks using the "DOI" column
+ # multiexcel_data <- multiexcel_data %>%
+ # mutate(
+ # Author = paste0(
+ # "",
+ # Author, # Column with the display text (e.g., author name)
+ # ""
+ # )
+ # ) %>%
+ # select(-DOI) # Remove the "DOI" column after linking it to the "author" column
+ #
+ # # Dynamically remove empty columns ("18", "19", etc.)
+ # multiexcel_data <- multiexcel_data %>%
+ # select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
+ #
+ # # Render the data table with HTML content and no row names
+ # datatable(multiexcel_data,
+ # options = list(searching = FALSE),
+ # rownames = FALSE,
+ # escape = FALSE) # Allow HTML rendering
+ # })
+
+ #Render and hyperlink table + edit size so that everything fits into webpage
+ output$multiomicsdatatable <- renderDT({
+ # Transform the "author" column to contain hyperlinks using the "DOI" column
+ multiexcel_data <- multiexcel_data %>%
+ mutate(
+ Author = paste0(
+ "",
+ Author, # Column with the display text (e.g., author name)
+ ""
+ )
+ ) %>%
+ select(-DOI) # Remove the "DOI" column after linking it to the "author" column
+
+ # Dynamically remove empty columns ("18", "19", etc.)
+ multiexcel_data <- multiexcel_data %>%
+ select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
+
+ # Render the data table with fit-to-page options
+ datatable(
+ multiexcel_data,
+ options = list(
+ autoWidth = TRUE, # Adjust column widths automatically
+ scrollX = TRUE, # Enable horizontal scrolling
+ pageLength = 10 # Limit rows displayed per page (adjustable)
+ ),
+ rownames = FALSE,
+ escape = FALSE # Allow HTML rendering for links
+ )
+ })
+
+ # --- START: TaijiChat Message Handling ---
+ chat_history <- reactiveVal(list()) # Stores list of lists: list(role="user/assistant", content="message")
+
+ observeEvent(input$user_chat_message, {
+ req(input$user_chat_message)
+ user_message_text <- trimws(input$user_chat_message)
+ print(paste("TaijiChat: Received user_chat_message -", user_message_text))
+
+ if (nzchar(user_message_text)) {
+ current_hist <- chat_history()
+ updated_hist_user <- append(current_hist, list(list(role = "user", content = user_message_text)))
+ chat_history(updated_hist_user)
+
+ agent_instance_val <- rv_agent_instance()
+
+ if (!is.null(agent_instance_val)) {
+ # Ensure history is a list of R named lists, then r_to_py will convert to list of Python dicts
+ py_hist_for_agent <- lapply(updated_hist_user, function(turn) {
+ list(role = turn$role, content = turn$content)
+ })
+ # py_hist_for_agent_converted <- reticulate::r_to_py(py_hist_for_agent)
+
+ # Send a "Thinking..." message to UI before long computation
+ session$sendCustomMessage(type = "agent_thinking_started", message = list(text = "Thinking..."))
+
+ tryCatch({
+ print(paste("TaijiChat: Sending to Python agent - Query:", user_message_text))
+ # For debugging, convert history to JSON string to see its structure if needed
+ # hist_json_debug <- jsonlite::toJSON(py_hist_for_agent, auto_unbox = TRUE)
+ # print(paste("TaijiChat: Conversation history (JSON for debug):", hist_json_debug))
+
+ # Get literature search preference (default to FALSE if not set)
+ literature_enabled <- if (is.null(input$literature_search_enabled)) FALSE else input$literature_search_enabled
+ print(paste("TaijiChat: Literature search enabled:", literature_enabled))
+
+ # Call Python agent method with literature preference
+ # The process_single_query method in Python expects history as a list of dicts.
+ # reticulate::r_to_py should handle the conversion of the list of R named lists.
+ agent_reply_py <- agent_instance_val$process_single_query_with_preferences(
+ user_query_text = user_message_text,
+ conversation_history_from_r = py_hist_for_agent, # Pass the R list of lists
+ literature_enabled = literature_enabled
+ )
+ # Explicitly convert potential Python object to R character string
+ agent_reply_text <- as.character(agent_reply_py)
+
+ print(paste("TaijiChat: Received from Python agent -", agent_reply_text))
+
+
+ # Check if this is an image response
+ if (startsWith(agent_reply_text, "TAIJICHAT_IMAGE_RESPONSE:")) {
+ # Extract the JSON part - START AFTER THE COLON IN THE PREFIX
+ json_str <- substr(agent_reply_text, 26, nchar(agent_reply_text))
+
+ # Debug the JSON string
+ print(paste("Attempting to parse JSON:", json_str))
+
+ # Try parsing in a safer way
+ tryCatch({
+ # Remove any leading/trailing whitespace and ensure proper JSON format
+ json_str <- trimws(json_str)
+
+ # Try to parse the JSON
+ image_info <- NULL
+ if (nchar(json_str) > 0) {
+ # Attempt to parse using various approaches
+ image_info <- tryCatch({
+ jsonlite::fromJSON(json_str)
+ }, error = function(e1) {
+ tryCatch({
+ # Try unescaping first
+ jsonlite::fromJSON(gsub('\\\\"', '"', json_str))
+ }, error = function(e2) {
+ NULL
+ })
+ })
+ }
+
+ if (!is.null(image_info) && !is.null(image_info$image_path)) {
+ # Debug image path
+ image_path_original <- image_info$image_path
+ image_path_normalized <- sub("^www/", "", image_info$image_path)
+
+ # Check if file exists
+ file_exists_check <- file.exists(image_path_original)
+ print(paste("Image path debug - Original:", image_path_original,
+ "Normalized:", image_path_normalized,
+ "File exists:", file_exists_check))
+
+ # Add a special marker to the message to trigger image display in UI
+ image_html <- paste0(
+ '',
+ '

',
+ '
'
+ )
+
+ # Get original response or use a default
+ original_response <- ifelse(!is.null(image_info$original_response),
+ image_info$original_response,
+ "I've analyzed this image.")
+
+ # Combine the image HTML with the original text response
+ enhanced_reply <- paste0(
+ image_html,
+ "
",
+ original_response
+ )
+
+ agent_reply_text <- enhanced_reply
+
+ # Send a custom message to ensure the image display script is active
+ session$sendCustomMessage(type = "activate_image_viewer", message = list())
+ } else {
+ warning("Failed to extract image path from JSON")
+ agent_reply_text <- paste("I analyzed an image but had trouble displaying it. Here's what I found:",
+ gsub("TAIJICHAT_IMAGE_RESPONSE:.*", "", agent_reply_text))
+ }
+ }, error = function(e) {
+ warning(paste("JSON parsing error:", e$message, "- JSON string:", json_str))
+ print(paste("JSON parsing error:", e$message, "- JSON string:", json_str))
+ # Just use the original text in case of parsing error
+ agent_reply_text <- paste("I analyzed an image but had trouble displaying it. Here's what I found:",
+ substr(agent_reply_text, 25, nchar(agent_reply_text)))
+ })
+ }
+
+ final_hist <- append(updated_hist_user, list(list(role = "assistant", content = agent_reply_text)))
+ chat_history(final_hist)
+
+ session$sendCustomMessage(type = "agent_chat_response", message = list(text = agent_reply_text))
+
+ }, error = function(e) {
+ error_message <- paste("TaijiChat: Error calling Python agent or processing response:", e$message)
+ warning(error_message)
+ print(error_message)
+ session$sendCustomMessage(type = "agent_chat_response", message = list(text = paste("Sorry, an error occurred with the agent.")))
+ })
+ } else {
+ warning("TaijiChat: Agent instance is NULL. Cannot process chat message.")
+ print("TaijiChat: Agent instance is NULL. Cannot process chat message.")
+ session$sendCustomMessage(type = "agent_chat_response", message = list(text = "The chat agent is not available. Please check server logs."))
+ }
+ } else {
+ print("TaijiChat: Received empty user_chat_message.")
+ }
+ })
+
+
+ # --- END: TaijiChat Message Handling ---
+
+ #Render and hyperlink table + edit size so that everything fits into webpage
+ output$multiomicsdatatable <- renderDT({
+ # Transform the "author" column to contain hyperlinks using the "DOI" column
+ multiexcel_data <- multiexcel_data %>%
+ mutate(
+ Author = paste0(
+ "",
+ Author, # Column with the display text (e.g., author name)
+ ""
+ )
+ ) %>%
+ select(-DOI) # Remove the "DOI" column after linking it to the "author" column
+
+ # Dynamically remove empty columns ("18", "19", etc.)
+ multiexcel_data <- multiexcel_data %>%
+ select(where(~ !all(is.na(.)) & !all(. == ""))) # Keep only non-empty columns
+
+ # Render the data table with fit-to-page options
+ datatable(
+ multiexcel_data,
+ options = list(
+ autoWidth = TRUE, # Adjust column widths automatically
+ scrollX = TRUE, # Enable horizontal scrolling
+ pageLength = 10 # Limit rows displayed per page (adjustable)
+ ),
+ rownames = FALSE,
+ escape = FALSE # Allow HTML rendering for links
+ )
+ })
+
+ # Update reactive expressions to use warning overlay
+ output$tfData <- renderDT({
+ withWarningOverlayReactive(session, {
+ # Your existing reactive code here
+ # This will automatically show the warning overlay for long-running operations
+ }, "get_processed_tf_data")
+ })
+}
+
+
# # ############################## CODE GRAVEYARD ##############################
\ No newline at end of file