diff --git a/R/getSubnetworkFromIndra.R b/R/getSubnetworkFromIndra.R index ab3e232..09f1f30 100644 --- a/R/getSubnetworkFromIndra.R +++ b/R/getSubnetworkFromIndra.R @@ -32,7 +32,9 @@ #' as "namespace:identifier", e.g. "HGNC:1234" or "CHEBI:4911". #' @param filter_by_curation logical, whether to filter out statements that #' have been curated as incorrect in INDRA. Default is FALSE. -#' @param api_key string of INDRA API key for accessing curated statements. +#' @param filter_by_ptm_site logical, whether to filter edges based on whether the +#' site information from INDRA matches with the PTM site in the input. Default is FALSE. +#' Only applicable for differential PTM abundance results. #' #' @return list of 2 data.frames, nodes and edges #' @@ -57,15 +59,17 @@ getSubnetworkFromIndra <- function(input, sources_filter = NULL, logfc_cutoff = NULL, force_include_other = NULL, - filter_by_curation = FALSE, - api_key = "") { + filter_by_curation = FALSE, + filter_by_ptm_site = FALSE) { input <- .filterGetSubnetworkFromIndraInput(input, pvalueCutoff, logfc_cutoff, force_include_other) .validateGetSubnetworkFromIndraInput(input, protein_level_data, sources_filter, force_include_other) res <- .callIndraCogexApi(input$HgncId, force_include_other) - res <- .filterIndraResponse(res, statement_types, evidence_count_cutoff, sources_filter, filter_by_curation, api_key) + res <- .filterIndraResponse(res, statement_types, evidence_count_cutoff, sources_filter) edges <- .constructEdgesDataFrame(res, input, protein_level_data) edges <- .filterEdgesDataFrame(edges, paper_count_cutoff, correlation_cutoff) nodes <- .constructNodesDataFrame(input, edges) + subnetwork = .filterByPtmSite(nodes, edges, filter_by_ptm_site) + subnetwork = .filterByCuration(subnetwork$nodes, subnetwork$edges, evidence_count_cutoff, filter_by_curation) warning( "NOTICE: This function includes third-party software components that are licensed under the BSD 2-Clause License. Please ensure to @@ -73,5 +77,5 @@ getSubnetworkFromIndra <- function(input, package or utilizing the results based on this package. See the LICENSE file for more details." ) - return(list(nodes = nodes, edges = edges)) + return(subnetwork) } diff --git a/R/utils_getSubnetworkFromIndra.R b/R/utils_getSubnetworkFromIndra.R index 3f3a674..a5a717c 100644 --- a/R/utils_getSubnetworkFromIndra.R +++ b/R/utils_getSubnetworkFromIndra.R @@ -68,9 +68,9 @@ #' @importFrom httr GET status_code content #' @importFrom jsonlite fromJSON -.get_incorrect_curation_count <- function(stmt_hash, api_key) { +.get_incorrect_curation_count <- function(stmt_hash) { stmt_hash_char <- as.character(stmt_hash) - url <- paste0("https://db.indra.bio/curation/list/", stmt_hash_char, "?api_key=", api_key) + url <- paste0("https://db.indra.bio/curation/list/", stmt_hash_char) tryCatch({ response <- GET(url) @@ -96,21 +96,18 @@ #' Call INDRA Cogex API and return response #' @param res response from INDRA -#' @param interaction_types interaction types to filter by +#' @param statement_types interaction types to filter by #' @param evidence_count_cutoff number of evidence to filter on for each paper #' @param sources_filter list of sources to filter by. Default is NULL, i.e. no filter -#' @param filter_by_curation logical, whether to filter out statements that -#' have been curated as incorrect in INDRA. Default is FALSE. -#' @param api_key string of INDRA API key for accessing curated statements. #' @return filtered list of INDRA statements #' @importFrom jsonlite fromJSON #' @keywords internal #' @noRd -.filterIndraResponse <- function(res, interaction_types, evidence_count_cutoff, - sources_filter = NULL, filter_by_curation = FALSE, api_key = "") { - if (!is.null(interaction_types)) { +.filterIndraResponse <- function(res, statement_types, evidence_count_cutoff, + sources_filter = NULL) { + if (!is.null(statement_types)) { res = Filter( - function(statement) statement$data$stmt_type %in% interaction_types, + function(statement) statement$data$stmt_type %in% statement_types, res) } if (!is.null(sources_filter)) { @@ -123,16 +120,6 @@ res ) } - if (filter_by_curation) { - for (i in seq_along(res)) { - stmt_json <- fromJSON(res[[i]]$data$stmt_json) - stmt_hash <- stmt_json$matches_hash - incorrect_count <- .get_incorrect_curation_count(stmt_hash, api_key) - res[[i]]$data$evidence_count <- res[[i]]$data$evidence_count - incorrect_count - # Todo: Also subtract source_counts accordingly if requested - Sys.sleep(0.1) - } - } res = Filter( function(statement) statement$data$evidence_count >= evidence_count_cutoff, res @@ -373,6 +360,31 @@ return(edges) } +.filterByCuration = function(nodes, edges, evidence_count_cutoff, filter_by_curation) { + if (filter_by_curation) { + incorrect_counts <- numeric(nrow(edges)) + for (i in seq_len(nrow(edges))) { + incorrect_counts[i] <- .get_incorrect_curation_count(edges$stmt_hash[i]) + Sys.sleep(0.1) + } + edges$evidenceCount <- edges$evidenceCount - incorrect_counts + edges <- edges[edges$evidenceCount >= evidence_count_cutoff, ] + nodes <- nodes[nodes$id %in% c(edges$source, edges$target), ] + } + return(list(nodes = nodes, edges = edges)) +} + +.filterByPtmSite = function(nodes, edges, filter_by_ptm_site) { + if (filter_by_ptm_site && nrow(nodes[!is.na(nodes$Site), ]) > 0) { + ptm_overlap <- .calculatePTMOverlapAggregated(edges, nodes) + keep <- ptm_overlap[paste(edges$source, edges$target, edges$interaction, sep = "-")] + edges <- edges[!is.na(keep) & keep != "", ] + edges <- edges[!is.na(edges$site),] + nodes <- nodes[nodes$id %in% c(edges$source, edges$target), ] + } + return(list(nodes = nodes, edges = edges)) +} + #' Construct correlation matrix from MSstats #' @param protein_level_data output of dataProcess #' @importFrom tidyr pivot_wider diff --git a/R/visualizeNetworksWithHTML.R b/R/visualizeNetworksWithHTML.R index 1c13cfa..db8b64c 100644 --- a/R/visualizeNetworksWithHTML.R +++ b/R/visualizeNetworksWithHTML.R @@ -78,8 +78,9 @@ getRelationshipProperties <- function() { #' @param edges Data frame with edge information including 'target' and 'site' columns #' @param nodes Data frame with node information including 'id' and 'Site' columns #' @return Vector of overlap descriptions for each unique edge (after consolidation) +#' @keywords internal #' @noRd -calculatePTMOverlapAggregated <- function(edges, nodes) { +.calculatePTMOverlapAggregated <- function(edges, nodes) { if (nrow(edges) == 0) return(character(0)) # Group edges by source-target-interaction to match consolidation logic @@ -153,7 +154,7 @@ consolidateEdges <- function(edges, nodes = NULL) { # Calculate aggregated PTM overlap information if nodes are provided ptm_overlap_map <- if (!is.null(nodes)) { - calculatePTMOverlapAggregated(edges, nodes) + .calculatePTMOverlapAggregated(edges, nodes) } else { NULL } @@ -1141,6 +1142,7 @@ createEdgeClickHandler <- function() { #' @param edges Data frame with edge information #' @param filename Output HTML filename #' @param displayLabelType Type of label to display ("id" or "hgncName") +#' @param nodeFontSize Font size for node labels (default: 12) #' @param ... Additional arguments passed to exportCytoscapeToHTML() #' @export #' @return Invisibly returns the file path of the created HTML file diff --git a/man/exportNetworkToHTML.Rd b/man/exportNetworkToHTML.Rd index 2e9910a..ca8f679 100644 --- a/man/exportNetworkToHTML.Rd +++ b/man/exportNetworkToHTML.Rd @@ -9,6 +9,7 @@ exportNetworkToHTML( edges, filename = "network_visualization.html", displayLabelType = "id", + nodeFontSize = 12, ... ) } @@ -21,6 +22,8 @@ exportNetworkToHTML( \item{displayLabelType}{Type of label to display ("id" or "hgncName")} +\item{nodeFontSize}{Font size for node labels (default: 12)} + \item{...}{Additional arguments passed to exportCytoscapeToHTML()} } \value{ diff --git a/man/generateCytoscapeConfig.Rd b/man/generateCytoscapeConfig.Rd index 07c70b8..fc6c562 100644 --- a/man/generateCytoscapeConfig.Rd +++ b/man/generateCytoscapeConfig.Rd @@ -10,7 +10,8 @@ generateCytoscapeConfig( display_label_type = "id", container_id = "network-cy", event_handlers = NULL, - layout_options = NULL + layout_options = NULL, + node_font_size = 12 ) } \arguments{ diff --git a/man/getSubnetworkFromIndra.Rd b/man/getSubnetworkFromIndra.Rd index 94d27f9..a670d6e 100644 --- a/man/getSubnetworkFromIndra.Rd +++ b/man/getSubnetworkFromIndra.Rd @@ -16,7 +16,7 @@ getSubnetworkFromIndra( logfc_cutoff = NULL, force_include_other = NULL, filter_by_curation = FALSE, - api_key = "" + filter_by_ptm_site = FALSE ) } \arguments{ @@ -60,7 +60,9 @@ as "namespace:identifier", e.g. "HGNC:1234" or "CHEBI:4911".} \item{filter_by_curation}{logical, whether to filter out statements that have been curated as incorrect in INDRA. Default is FALSE.} -\item{api_key}{string of INDRA API key for accessing curated statements.} +\item{filter_by_ptm_site}{logical, whether to filter edges based on whether the +site information from INDRA matches with the PTM site in the input. Default is FALSE. +Only applicable for differential PTM abundance results.} } \value{ list of 2 data.frames, nodes and edges diff --git a/man/previewNetworkInBrowser.Rd b/man/previewNetworkInBrowser.Rd index 6dde024..d0ac40e 100644 --- a/man/previewNetworkInBrowser.Rd +++ b/man/previewNetworkInBrowser.Rd @@ -4,7 +4,13 @@ \alias{previewNetworkInBrowser} \title{Preview network in browser} \usage{ -previewNetworkInBrowser(nodes, edges, displayLabelType = "id", ...) +previewNetworkInBrowser( + nodes, + edges, + displayLabelType = "id", + nodeFontSize = 12, + ... +) } \arguments{ \item{nodes}{Data frame with node information}