Skip to content

Commit

Permalink
feat(indra): Fetch networks from indra cogex and visualize with cytos…
Browse files Browse the repository at this point in the history
…cape
  • Loading branch information
Tony Wu committed Jul 5, 2024
1 parent 3cb49a7 commit 2bca6b5
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 2 deletions.
10 changes: 8 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,19 @@ Imports:
graphics,
methods,
statmod,
parallel
parallel,
RCy3,
httr,
jsonlite,
r2r
Suggests:
BiocStyle,
knitr,
rmarkdown,
tinytest,
covr,
markdown
markdown,
testthat (>= 3.0.0)
VignetteBuilder: knitr
biocViews: ImmunoOncology, MassSpectrometry, Proteomics, Software, Normalization,
QualityControl, TimeCourse
Expand All @@ -55,3 +60,4 @@ Packaged: 2017-10-20 02:13:12 UTC; meenachoi
LinkingTo:
Rcpp,
RcppArmadillo
Config/testthat/edition: 3
13 changes: 13 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ export(extractSDRF)
export(getProcessed)
export(getSamplesInfo)
export(getSelectedProteins)
export(getSubnetworkFromIndra)
export(groupComparison)
export(groupComparisonPlots)
export(makePeptidesDictionary)
export(modelBasedQCPlots)
export(quantification)
export(savePlot)
export(theme_msstats)
export(visualizeSubnetwork)
import(data.table)
import(ggplot2)
import(limma)
Expand All @@ -57,6 +59,10 @@ importFrom(MSstatsConvert,MSstatsImport)
importFrom(MSstatsConvert,MSstatsLogsSettings)
importFrom(MSstatsConvert,MSstatsMakeAnnotation)
importFrom(MSstatsConvert,MSstatsPreprocess)
importFrom(RCy3,createNetworkFromDataFrames)
importFrom(RCy3,createVisualStyle)
importFrom(RCy3,mapVisualProperty)
importFrom(RCy3,setVisualStyle)
importFrom(Rcpp,sourceCpp)
importFrom(data.table,as.data.table)
importFrom(data.table,melt)
Expand All @@ -79,6 +85,10 @@ importFrom(graphics,title)
importFrom(htmltools,div)
importFrom(htmltools,save_html)
importFrom(htmltools,tagList)
importFrom(httr,POST)
importFrom(httr,add_headers)
importFrom(httr,content)
importFrom(jsonlite,toJSON)
importFrom(limma,squeezeVar)
importFrom(lme4,lmer)
importFrom(marray,maPalette)
Expand All @@ -94,6 +104,9 @@ importFrom(plotly,plot_ly)
importFrom(plotly,style)
importFrom(plotly,subplot)
importFrom(preprocessCore,normalize.quantiles)
importFrom(r2r,hashmap)
importFrom(r2r,keys)
importFrom(r2r,query)
importFrom(stats,dist)
importFrom(stats,fitted)
importFrom(stats,formula)
Expand Down
40 changes: 40 additions & 0 deletions R/getSubnetworkFromIndra.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#' Get subnetwork from INDRA database with differential analysis results
#'
#' @param input groupComparison comparisionResult table with additional HGNC ID
#' and HGNC name columns
#' @param pvalue_cutoff p-value cutoff for filtering
#' @param stmt_types list of statement types to filter, default is c("Complex")
#' @importFrom r2r hashmap query keys
#'
#' @return list of 2 data.frames, nodes and edges
#'
#' @export
#'
#' @examples
#' input = data.table::fread(system.file("tinytest/processed_data/groupComparisonModel.csv",
#' package = "MSstats"))
#' # subnetwork = getSubnetworkFromIndra(input)
#' # head(subnetwork$nodes)
#' # head(subnetwork$edges)
#'
#'
getSubnetworkFromIndra = function(input, pvalue_cutoff = 0.05, stmt_types = c("Complex")) {
input = .filterAndProcessInput(input, pvalue_cutoff)
res = .callIndraCogexApi(input$HgncId)
res = .filterIndraResults(res, stmt_types)
res = .collapseIndraResultsIntoEdgeToEvidenceMapping(res, input)

nodes = data.frame(id=input$HgncId,
uniprot_id=input$Protein,
logFC=input$log2FC,
pvalue=input$adj.pvalue,
stringsAsFactors=FALSE)
edges = data.frame(source=sapply(keys(res), function(x) query(res, x)$source_id),
target=sapply(keys(res), function(x) query(res, x)$target_id),
interaction=sapply(keys(res), function(x) query(res, x)$data$stmt_type),
evidenceCount=sapply(keys(res), function(x) query(res, x)$data$evidence_count),
evidenceLink=sapply(keys(res), function(x) query(res, x)$data$evidence_list),
stringsAsFactors=FALSE)

return(list(nodes=nodes, edges=edges))
}
78 changes: 78 additions & 0 deletions R/utils_getSubnetworkFromIndra.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#' Call INDRA Cogex API and return response
#' @param hgnc_ids list of hgnc_ids
#' @return list of INDRA statements
#' @importFrom jsonlite toJSON
#' @importFrom httr POST add_headers content
#' @keywords internal
#' @noRd
.callIndraCogexApi = function(hgnc_ids) {
INDRA_COGEX_URL = "https://discovery.indra.bio/api/indra_subnetwork_relations"

groundings = lapply(hgnc_ids, function(x) list("HGNC", x))
groundings = list(nodes = groundings)
groundings = jsonlite::toJSON(groundings, auto_unbox = TRUE)

res = POST(
INDRA_COGEX_URL,
body = groundings,
add_headers("Content-Type" = "application/json"),
encode = "raw"
)
res = content(res)
return(res)
}

#' Filter and process groupComparison result input based on user-defined cutoffs
#' @param input groupComparison result
#' @param pvalue_cutoff p-value cutoff
#' @return filtered groupComparison result
#' @keywords internal
#' @noRd
.filterAndProcessInput = function(input, pvalue_cutoff) {
input = input[input$adj.pvalue < pvalue_cutoff,]
input = input[is.na(input$issue),]
input$HgncId = as.character(input$HgncId)
return(input)
}

#' Filter INDRA results based on user preferences
#' @param res INDRA response
#' @param stmt_types statement types filter
#' @return filtered INDRA response
#' @keywords internal
#' @noRd
.filterIndraResults = function(res, stmt_types) {
res = Filter(function(x) x$data$stmt_type %in% stmt_types, res)
return(res)
}

#' Collapse INDRA statements into a mapping of edge to evidence data
#' @param res INDRA response
#' @param input filtered groupComparison result
#' @return processed INDRA statements
#' @keywords internal
#' @noRd
.collapseIndraResultsIntoEdgeToEvidenceMapping = function(res, input) {
gene_id_map = hashmap()
gene_id_map[input$HgncId] = input$HgncName

edge_to_evidence_mapping = hashmap()
for (edge in res) {
key = paste(edge$source_id, edge$target_id, edge$data$stmt_type, sep="_")
if (key %in% keys(edge_to_evidence_mapping)) {
# Collapse duplicate edges and keep track of evidence count
edge_to_evidence_mapping[[key]]$data$evidence_count =
edge_to_evidence_mapping[[key]]$data$evidence_count + edge$data$evidence_count
} else {
# Add INDRA DB link for new edges
edge$data$evidence_list = paste(
"https://db.indra.bio/statements/from_agents?subject=",
query(gene_id_map, edge$source_id), "&object=",
query(gene_id_map, edge$target_id), "&type=",
edge$data$stmt_type, "&format=html", sep="")
edge_to_evidence_mapping[[key]] = edge
}
}

return(edge_to_evidence_mapping)
}
33 changes: 33 additions & 0 deletions R/visualizeSubnetwork.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#' Create visualization of subnetwork in cytoscape
#'
#' @param nodes dataframe of nodes
#' @param edges dataframe of edges
#' @importFrom RCy3 createNetworkFromDataFrames mapVisualProperty createVisualStyle setVisualStyle
#'
#' @export
#'
#' @examples
#' input = data.table::fread(system.file("tinytest/processed_data/groupComparisonModel.csv",
#' package = "MSstats"))
#' # subnetwork = getSubnetworkFromIndra(input)
#' # visualizeSubnetwork(subnetwork$nodes, subnetwork$edges)
#'
#'
visualizeSubnetwork = function(nodes, edges) {
DEFAULT_VISUAL_STYLE = list(
NODE_FILL_COLOR="lightblue",
NODE_SHAPE="ROUNDRECT",
NODE_SIZE=50,
NODE_LABEL_FONT_SIZE=6,
NODE_LABEL_POSITION="center",
EDGE_TARGET_ARROW_SHAPE="Arrow")
VISUAL_STYLE_NAME = "MSstats-Indra Visual Style"

createNetworkFromDataFrames(nodes, edges)

VISUAL_STYLE_MAPPINGS = list(
mapVisualProperty('Node Label','uniprot_id','p')
)
createVisualStyle(VISUAL_STYLE_NAME, DEFAULT_VISUAL_STYLE, VISUAL_STYLE_MAPPINGS)
setVisualStyle(VISUAL_STYLE_NAME)
}
4 changes: 4 additions & 0 deletions inst/tinytest/processed_data/groupComparisonModel.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
,Protein,Label,log2FC,SE,Tvalue,DF,pvalue,adj.pvalue,issue,MissingPercentage,ImputationPercentage,HgncId,HgncName
1,BRD2_HUMAN,DMSO-DbET6,2.046185244,0.114338622,17.89583616,260,0,0,NA,0.310067114,0,1103,BRD2
2,BRD3_HUMAN,DMSO-DbET6,3.333427936,0.126570545,26.33652185,257,0,0,NA,0.252348993,0,1104,BRD3
3,BRD4_HUMAN,DMSO-DbET6,2.668934662,0.101282782,26.35131665,257,0,0,NA,0.118120805,0,13575,BRD4
Binary file added inst/tinytest/processed_data/indraResponse.rds
Binary file not shown.
31 changes: 31 additions & 0 deletions man/getSubnetworkFromIndra.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions man/visualizeSubnetwork.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions tests/testthat.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file is part of the standard setup for testthat.
# It is recommended that you do not modify it.
#
# Where should you do additional test configuration?
# Learn more about the roles of various files in:
# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview
# * https://testthat.r-lib.org/articles/special-files.html

library(testthat)
library(MSstats)

test_check("MSstats")
11 changes: 11 additions & 0 deletions tests/testthat/test-getSubnetworkFromIndra.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test_that("getSubnetworkFromIndra works correctly", {
input = data.table::fread(
system.file("tinytest/processed_data/groupComparisonModel.csv", package = "MSstats")
)
local_mocked_bindings(.callIndraCogexApi = function(x) {
return(readRDS(system.file("tinytest/processed_data/indraResponse.rds", package = "MSstats")))
})
subnetwork = getSubnetworkFromIndra(input)
expect_equal(nrow(subnetwork$nodes), 3)
expect_equal(nrow(subnetwork$edges), 6)
})

0 comments on commit 2bca6b5

Please sign in to comment.