Skip to content

Network Visualization core logic#99

Merged
tonywu1999 merged 7 commits intodevel-bionetfrom
indra-integration
Jan 9, 2025
Merged

Network Visualization core logic#99
tonywu1999 merged 7 commits intodevel-bionetfrom
indra-integration

Conversation

@pnavada
Copy link
Copy Markdown
Contributor

@pnavada pnavada commented Nov 18, 2024

PR Type

enhancement


Description

  • Implemented core logic for network visualization using Cytoscape.js in the server module.
  • Developed a UI module to support network visualization, including data upload and settings.
  • Integrated the network server module into the main server function.
  • Added a new tab for network interpretation in the UI.

Changes walkthrough 📝

Relevant files
Enhancement
module-visualize-network-server.R
Implement network visualization server logic with Cytoscape.js

R/module-visualize-network-server.R

  • Added a server module to handle network visualization.
  • Implemented reactive expressions for data processing and network
    rendering.
  • Integrated Cytoscape.js for network visualization.
  • Added error handling for CSV data upload.
  • +114/-0 
    module-visualize-network-ui.R
    Develop UI for network visualization with Cytoscape.js     

    R/module-visualize-network-ui.R

  • Created a UI module for network visualization.
  • Integrated Cytoscape.js and related libraries.
  • Added UI components for data upload and network settings.
  • +69/-0   
    server.R
    Integrate network server module into main server                 

    R/server.R

  • Integrated the network server module into the main server function.
  • +2/-0     
    ui.R
    Add network interpretation tab to UI                                         

    R/ui.R

    • Added a new tab for network interpretation in the UI.
    +1/-0     

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    @pnavada pnavada changed the title Adding network visualization core logic Network Visualization core logic Nov 18, 2024
    @github-actions
    Copy link
    Copy Markdown

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 Security concerns

    JavaScript Injection Risk:
    The implementation directly uses user inputs in JavaScript code generation, which could lead to JavaScript injection vulnerabilities. This is particularly concerning in lines where node and edge data are dynamically generated based on user input. Consider sanitizing these inputs or employing other methods to ensure the security of the generated code.

    ⚡ Recommended focus areas for review

    Error Handling
    The error handling in the CSV reading function could be improved by providing more specific error messages or handling different types of errors differently.

    JavaScript Injection Risk
    Directly using user input in JavaScript code generation could lead to JavaScript injection vulnerabilities. Consider sanitizing or validating the inputs before use.

    Performance Concern
    The loop for edge elements creation might be inefficient for large datasets. Consider optimizing this section or using vectorized operations if possible.

    @github-actions
    Copy link
    Copy Markdown

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Possible bug
    Add error handling for data processing functions to improve robustness

    Consider adding error handling for the annotateProteinInfoFromIndra and
    getSubnetworkFromIndra functions to manage potential failures or exceptions in data
    processing.

    R/module-visualize-network-server.R [33-34]

    -annotated_df <- annotateProteinInfoFromIndra(df(), proteinIdType())
    -subnetwork <- getSubnetworkFromIndra(annotated_df, pValue())
    +annotated_df <- tryCatch({
    +    annotateProteinInfoFromIndra(df(), proteinIdType())
    +}, error = function(e) {
    +    showNotification(paste("Error in annotation:", e$message), type = "error")
    +    return(NULL)
    +})
    +subnetwork <- tryCatch({
    +    getSubnetworkFromIndra(annotated_df, pValue())
    +}, error = function(e) {
    +    showNotification(paste("Error in subnetwork extraction:", e$message), type = "error")
    +    return(NULL)
    +})
    Suggestion importance[1-10]: 8

    Why: Adding error handling for the functions annotateProteinInfoFromIndra and getSubnetworkFromIndra is crucial to manage potential failures, improving the robustness and user experience of the application.

    8
    Ensure numeric inputs are valid to prevent runtime errors

    Validate the numeric conversion of input$pValue and input$logFC to handle
    non-numeric inputs gracefully.

    R/module-visualize-network-server.R [20-28]

     pValue <- reactive({
         req(input$pValue)
    -    as.numeric(input$pValue)
    +    if (!is.na(as.numeric(input$pValue))) {
    +        as.numeric(input$pValue)
    +    } else {
    +        showNotification("Invalid pValue input", type = "error")
    +        return(NULL)
    +    }
     })
     logFC <- reactive({
         req(input$logFC)
    -    as.numeric(input$logFC)
    +    if (!is.na(as.numeric(input$logFC))) {
    +        as.numeric(input$logFC)
    +    } else {
    +        showNotification("Invalid logFC input", type = "error")
    +        return(NULL)
    +    }
     })
    Suggestion importance[1-10]: 7

    Why: Validating the numeric conversion of inputs pValue and logFC is essential to prevent runtime errors from non-numeric inputs, thus enhancing the application's stability and user experience.

    7
    Performance
    Implement caching to reduce redundant data processing and enhance responsiveness

    Implement caching for the df, proteinIdType, pValue, and logFC reactive expressions
    to improve performance by avoiding redundant computations.

    R/module-visualize-network-server.R [4-28]

     df <- reactive({
         req(input$dataUpload)
    -    tryCatch({
    -        read.csv(input$dataUpload$datapath)
    -    }, error = function(e) {
    -        ...
    +    isolate({
    +        if (!exists("cached_df")) {
    +            cached_df <<- tryCatch({
    +                read.csv(input$dataUpload$datapath)
    +            }, error = function(e) {
    +                ...
    +            })
    +        }
    +        cached_df
         })
     })
     proteinIdType <- reactive({
         req(input$proteinIdType)
    -    input$proteinIdType
    +    isolate({
    +        if (!exists("cached_proteinIdType")) {
    +            cached_proteinIdType <<- input$proteinIdType
    +        }
    +        cached_proteinIdType
    +    })
     })
     ...
    Suggestion importance[1-10]: 6

    Why: Implementing caching for reactive expressions can significantly enhance performance by reducing redundant computations, especially beneficial in scenarios with frequent data updates or large datasets.

    6
    Use more efficient methods for generating JavaScript code to enhance performance

    Optimize the JavaScript code generation by using more efficient string concatenation
    techniques or pre-compiled templates.

    R/module-visualize-network-server.R [54-60]

    -js_code <- paste0("
    -    cytoscape.use(cytoscapeDagre);
    -    var cy = cytoscape({
    -        container: document.getElementById('network-cy'),
    -        elements: [", paste(elements, collapse = ", "), "],
    -        ...
    -    });
    -    ")
    +js_template <- "cytoscape.use(cytoscapeDagre);
    +                var cy = cytoscape({
    +                    container: document.getElementById('network-cy'),
    +                    elements: [%s],
    +                    ...
    +                });"
    +js_code <- sprintf(js_template, paste(elements, collapse = ", "))
    Suggestion importance[1-10]: 5

    Why: Optimizing JavaScript code generation using templates can improve performance, although the impact might be moderate depending on the overall application size and complexity.

    5

    @tonywu1999 tonywu1999 changed the base branch from devel to devel-bionet December 4, 2024 16:29
    Comment thread R/module-visualize-network-server.R Outdated
    @@ -0,0 +1,176 @@
    networkServer <- function(input, output, session, parent_session, significant) {
    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    nit: Could you rename this to visualizeNetworkServer? I think networkServer may confuse people thinking it has something to do with computer networks.

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    Comment thread R/module-visualize-network-server.R Outdated
    if (is.null(input$dataUpload) && !is.null(significant())) {
    df <- significant()
    if (!is.null(df) && "Protein" %in% names(df)) {
    df$Protein <- as.character(significant()$Protein)
    Copy link
    Copy Markdown
    Contributor

    @tonywu1999 tonywu1999 Dec 4, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Code would be easier to follow if you do df$Protein <- as.character(df$Protein)

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    Comment thread R/module-statmodel-server.R Outdated
    return(
    list(
    input = input,
    significant = SignificantProteins,
    Copy link
    Copy Markdown
    Contributor

    @tonywu1999 tonywu1999 Dec 4, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I think this is where we had talked about using the proteins being already filtered before coming to step 5 network viz.

    I think adding a significant parameter to the returned object may not be necessary since you can use the dataComparison$ComparisonResult table as the list of proteins with their p-values

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    data_comp = data_comparison()
    significant = data_comp$ComparisonResult[
    which(data_comp$ComparisonResult$adj.pvalue < input$signif), ]
    print(significant)
    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Any reason for removing this print statement here?

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    added it back

    renderNetwork <- reactive({
    # Annotate protein info and filter the subnetwork based on p-value
    annotated_df <- tryCatch({
    annotateProteinInfoFromIndra(df(), proteinIdType())
    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Did you add a dependency on MSstatsBioNet for this package? i.e. using the @importFrom tag and adding the dependency in the DESCRIPTION file.

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    Comment thread R/module-visualize-network-server.R Outdated
    interaction <- edge_parts[3]

    # Get edges table
    edges_table <- renderNetwork()$edges_table
    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Will this call INDRA again? If so, could we use the original edges table that we had already.

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    No, it wont call INDRA again. It happens only when the inputs change

    Comment thread R/module-visualize-network-server.R Outdated
    # Observe the event when an edge is clicked
    observeEvent(input$edgeClicked, {
    edge_id <- input$edgeClicked$id
    edge_parts <- strsplit(edge_id, "-")[[1]]
    Copy link
    Copy Markdown
    Contributor

    @tonywu1999 tonywu1999 Dec 4, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    rather than a string split, I believe we already have source, target, and interaction data stored in the edge as well. Would it be simpler to pass and retrieve that information instead of the ID itself?

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    Comment thread R/server.R Outdated
    selected = "Uploaddata")
    })

    callModule(networkServer, "network", session, significant)
    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Instead of passing significant, could you instead pass data_comparison$ComparisonResult instead here?

    Copy link
    Copy Markdown
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    done

    @tonywu1999 tonywu1999 merged commit e7fd143 into devel-bionet Jan 9, 2025
    @tonywu1999 tonywu1999 deleted the indra-integration branch January 9, 2025 15:58
    tonywu1999 pushed a commit that referenced this pull request Jul 18, 2025
    * adding network visualization core logic
    
    * linking step 5 to the pipeline and adding nodes table to output in step 5
    
    * highlighting the selected edge from the network in edges table
    
    * error handling for indra method calls
    
    * swapping the positions of edges and nodes table in ui
    
    * PR suggestions
    
    * PR suggestions
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    2 participants