diff --git a/DESCRIPTION b/DESCRIPTION index 90db11d..d154771 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,7 +47,9 @@ Collate: 'class-Node.R' 'constructors-Node.R' 'class-Link.R' + 'class-CorrelationLink.R' 'class-Network.R' + 'class-CorrelationNetwork.R' 'methods-Links.R' 'methods-Nodes.R' 'class-Partitions.R' @@ -64,6 +66,8 @@ Collate: 'class-plotdata.R' 'group.R' 'methods-ContingencyTable.R' + 'methods-CorrelationLinks.R' + 'methods-CorrelationNetwork.R' 'methods-KPartiteNetwork.R' 'methods-Network.R' 'panel.R' diff --git a/NAMESPACE b/NAMESPACE index 03e79f2..08b7f5d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,6 +12,9 @@ S3method(numBinsToBinWidth,Date) S3method(numBinsToBinWidth,default) export("%>%") export(ContingencyTable) +export(CorrelationLink) +export(CorrelationLinkList) +export(CorrelationNetwork) export(KPartiteNetwork) export(Link) export(LinkList) @@ -63,10 +66,13 @@ export(orderByReferenceValues) export(outliers) export(posPredictiveValue) export(prevalence) +export(pruneCorrelationLinks) export(pruneDuplicateLinks) export(pruneIsolatedNodes) export(pruneLinksAboveWeight) export(pruneLinksBelowWeight) +export(pruneLinksByCorrelationCoef) +export(pruneLinksByPValue) export(pruneLinksByPredicate) export(relativeRisk) export(scattergl) @@ -77,6 +83,9 @@ export(specificity) export(writeJSON) export(writeNetworkJSON) exportClasses(ContingencyTable) +exportClasses(CorrelationLink) +exportClasses(CorrelationLinkList) +exportClasses(CorrelationNetwork) exportClasses(Link) exportClasses(LinkList) exportClasses(Network) @@ -111,7 +120,6 @@ exportMethods(relativeRisk) exportMethods(sensitivity) exportMethods(specificity) exportMethods(toJSON) -exportMethods(writeNetworkJSON) import(data.table) import(veupathUtils) importFrom(S4Vectors,SimpleList) diff --git a/R/class-CorrelationLink.R b/R/class-CorrelationLink.R new file mode 100644 index 0000000..37650f9 --- /dev/null +++ b/R/class-CorrelationLink.R @@ -0,0 +1,284 @@ + + +check_correlation_link <- function(object) { + + errors <- character() + + # check correlation coef (weight) and pvalue make some sense + if (object@correlationCoef < -1 || object@correlationCoef > 1) { + msg <- "Correlation coefficient must be between -1 and 1." + errors <- c(errors, msg) + } + + if (object@pValue < 0 || object@pValue > 1) { + msg <- "P-value must be between 0 and 1." + errors <- c(errors, msg) + } + + # check that weight is the abs value of the correlation coefficient + if (abs(object@correlationCoef) != object@weight) { + msg <- "Weight must be the absolute value of the correlation coefficient." + errors <- c(errors, msg) + } + + return(if (length(errors) == 0) TRUE else errors) +} + +#' CorrelationLink +#' +#' Represent one singular link in a correlation network. A link has a source, +#' a target, a correlation coefficient, and a p-value. Its weight is the +#' absolute value of the correlation coefficient. It is undirected. +#' It may have a color, timestamp, or label (coming soon!) +#' +#' @name CorrelationLink-class +#' @rdname CorrelationLink-class +#' @include class-Node.R +#' @include constructors-Node.R +#' @include class-Link.R +#' @export +setClass("CorrelationLink", + contains = "Link", + slots = list( + correlationCoef = "numeric", + pValue = "numeric" + ), + prototype = prototype( + source = NodeId(), + target = NodeId(), + color = NULL, + isDirected = FALSE, + correlationCoef = NA_real_, + pValue = NA_real_, + weight = NA_real_ # change default of 1 from parent Link class + ), + validity = check_correlation_link +) + +#' CorrelationLink constructor +#' +#' @param source The source node identifier +#' @param target The target node identifier +#' @param correlationCoef The correlation coefficient (weight) of the link +#' @param pValue The p-value of the link +#' @param color The color of the link +#' @export +#' @rdname CorrelationLink +setGeneric("CorrelationLink", +function( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) standardGeneric("CorrelationLink"), +signature = c("source", "target")) + +#' @rdname CorrelationLink +#' @aliases CorrelationLink,Node,Node-method +setMethod("CorrelationLink", c("Node", "Node"), function(source, target, correlationCoef, pValue, color = NULL) { + new("CorrelationLink", + source = NodeId(id(source)), + target = NodeId(id(target)), + correlationCoef = correlationCoef, + pValue = pValue, + color = color, + weight = abs(correlationCoef) + ) +}) + +#' @rdname CorrelationLink +#' @aliases CorrelationLink,character,character-method +setMethod("CorrelationLink", c("character", "character"), function(source, target, correlationCoef, pValue, color = NULL) { + CorrelationLink( + source = NodeId(source), + target = NodeId(target), + correlationCoef = correlationCoef, + pValue = pValue, + color = color + ) +}) + +#' @rdname CorrelationLink +#' @aliases CorrelationLink,numeric,numeric-method +setMethod("CorrelationLink", c("numeric", "numeric"), function(source, target, correlationCoef, pValue, color = NULL) { + CorrelationLink( + source = NodeId(source), + target = NodeId(target), + correlationCoef = correlationCoef, + pValue = pValue, + color = color + ) +}) + +#' @rdname CorrelationLink +#' @aliases CorrelationLink,NodeId,NodeId-method +setMethod("CorrelationLink", c("NodeId", "NodeId"), function(source, target, correlationCoef, pValue, color = NULL) { + new("CorrelationLink", + source = source, + target = target, + correlationCoef = correlationCoef, + pValue = pValue, + color = color, + weight = abs(correlationCoef) + ) +}) + +#' @rdname CorrelationLink +#' @aliases CorrelationLink,missing,missing-method +setMethod("CorrelationLink", c("missing", "missing"), function(source, target, correlationCoef, pValue, color = NULL) { + new("CorrelationLink") +}) + +check_correlation_link_list <- function(object) { + + errors <- character() + trueOrPrevErrors <- check_link_list(object) + if (inherits(trueOrPrevErrors, "character")) { + errors <- c(errors, trueOrPrevErrors) + } + + # If one link has a correlationCoef, all must have a correlationCoef + if (any(unlist(lapply(object, function(x) {!is.null(correlationCoef(x))})))) { + if (!all(unlist(lapply(object, function(x) {!is.null(correlationCoef(x))})))) { + errors <- c(errors, "If one link has a correlationCoef, all links must have a correlationCoef.") + } + } + + # If one link has a pValue, all must have a pValue + if (any(unlist(lapply(object, function(x) {!is.null(pValue(x))})))) { + if (!all(unlist(lapply(object, function(x) {!is.null(pValue(x))})))) { + errors <- c(errors, "If one link has a pValue, all links must have a pValue.") + } + } + + return(if (length(errors) == 0) TRUE else errors) + +} + +#' Correlation Link List +#' +#' A class for representing links in a correlation network +#' +#' @name CorrelationLinkList-class +#' @rdname CorrelationLinkList-class +#' @importFrom S4Vectors SimpleList +#' @export +setClass("CorrelationLinkList", + contains = "SimpleList", + prototype = prototype( + elementType = "CorrelationLink" + ), + validity = check_correlation_link_list +) + +#' Generate a CorrelationLinkList +#' +#' Generate a CorrelationLinkList from an edgeList +#' @param object Object containing data to be converted to a LinkList. Could be a SimpleList of Links or a data.frame +#' with columns source, target, correlationCoef, pValue. +#' @param linkColorScheme Either 'none' or 'posneg'. If 'posneg', the link color will be based on the sign of the correlation coefficient. +#' @param correlationCoefThreshold numeric value used to filter links based on correlationCoef. Default is NULL (i.e. no filtering). +#' Any links with an absolute correlationCoef below this threshold will be removed. +#' @param pValueThreshold numeric value used to filter links based on pValue. Default is NULL (i.e. no filtering). +#' Any links with an pValue above this threshold will be removed. +#' @return CorrelationLinkList +#' @export +#' @examples +#' CorrelationLinkList(data.frame(source='a',target='b',correlationCoef=0.5,pValue=0.01)) +#' @rdname CorrelationLinkList +setGeneric("CorrelationLinkList", +function( + object, + linkColorScheme = c('none', 'posneg'), + correlationCoefThreshold = NULL, + pValueThreshold = NULL +) standardGeneric("CorrelationLinkList"), signature = c("object")) + +#' @rdname CorrelationLinkList +#' @aliases CorrelationLinkList,data.frame-method +setMethod("CorrelationLinkList", "data.frame", +function( + object = data.frame( + source=character(), + target=character(), + correlationCoef=numeric(), + pValue=numeric() + ), + linkColorScheme = c('none', 'posneg'), + correlationCoefThreshold = NULL, + pValueThreshold = NULL +) { + linkColorScheme <- veupathUtils::matchArg(linkColorScheme) + + if (!inherits(isValidEdgeList(object), "logical")) { + stop(paste("Invalid edgeList:", isValidEdgeList(object), collapse = '\n')) + } + + ## additional validation of correlationCoef and pValue in edgeList + if (!all(c('correlationCoef', 'pValue') %in% colnames(object))) { + stop("edgeList must contain columns 'correlationCoef' and 'pValue' for CorrelationLinkList/ CorrelationNetwork") + } + + ## remove rows w NA correlationCoef, or not meeting thresholds + object <- object[!is.na(object$correlationCoef), ] + + if (!is.null(correlationCoefThreshold)) { + object <- object[abs(object$correlationCoef) >= correlationCoefThreshold, ] + } + if (!is.null(pValueThreshold)) { + object <- object[object$pValue <= pValueThreshold, ] + } + + if (nrow(object) == 0) { + new("CorrelationLinkList") + } + + makeLink <- function(rowInEdgeList, linkColorScheme) { + source <- unname(rowInEdgeList['source']) + target <- unname(rowInEdgeList['target']) + correlationCoef <- as.numeric(unname(rowInEdgeList['correlationCoef'])) + pValue <- as.numeric(unname(rowInEdgeList['pValue'])) + + if (linkColorScheme == 'posneg') { + if (correlationCoef < 0) { + color <- -1 + } else if (correlationCoef > 0) { + color <- 1 + } else { + color <- 0 + } + } else { + color <- NA_character_ + } + + if (is.na(color)) { + link <- CorrelationLink(source, target, correlationCoef, pValue, NULL) + } else { + link <- CorrelationLink(source, target, correlationCoef, pValue, color) + } + + return(link) + } + + linkList <- apply(object, 1, makeLink, linkColorScheme) + new("CorrelationLinkList", linkList) +}) + +#' @rdname CorrelationLinkList +#' @aliases CorrelationLinkList,missing-method +setMethod("CorrelationLinkList", "missing", function(object) { + new("CorrelationLinkList") +}) + +#' @rdname CorrelationLinkList +#' @aliases CorrelationLinkList,SimpleList-method +setMethod("CorrelationLinkList", "SimpleList", function(object) { + new("CorrelationLinkList", object) +}) + +#' @rdname CorrelationLinkList +#' @aliases CorrelationLinkList,list-method +setMethod("CorrelationLinkList", "list", function(object) { + new("CorrelationLinkList", object) +}) \ No newline at end of file diff --git a/R/class-CorrelationNetwork.R b/R/class-CorrelationNetwork.R new file mode 100644 index 0000000..f1a618d --- /dev/null +++ b/R/class-CorrelationNetwork.R @@ -0,0 +1,181 @@ +# Network class +check_correlation_network <- function(object) { + + errors <- character() + trueOrPrevErrors <- check_network(object) + if (inherits(trueOrPrevErrors, "character")) { + errors <- c(errors, trueOrPrevErrors) + } + + # Check all links meet thresholding requirements + if (!is.na(object@correlationCoefThreshold)) { + correlationCoefs <- sapply(object@links, correlationCoef) + if (any(abs(correlationCoefs) < object@correlationCoefThreshold)) { + errors <- c(errors, "Some links have correlation coefficients below the threshold.") + } + } + + if (!is.na(object@pValueThreshold)) { + pValues <- sapply(object@links, pValue) + if (any(pValues > object@pValueThreshold)) { + errors <- c(errors, "Some links have p-values above the threshold.") + } + } + + return(if (length(errors) == 0) TRUE else errors) +} + +#' Correlation Network +#' +#' A class for representing networks of pairwise correlations. A network is composed of nodes and links (edges, connections, etc.). +#' A link is represented as a pair of nodes, with attributes such as correlationCoef and pValue (see Link). To represent a network, +#' we need both the list of links in the network and a list of nodes in case some nodes have no links. A network can also have +#' properties such as directedness, levels, colors, etc. (coming soon). +#' +#' @slot links CorrelationLinkList object defining the links in the network. +#' @slot nodes NodeList object defining the nodes in the network. Some nodes may not have any links. +#' @slot linkColorScheme string defining the type of coloring scheme the links follow. Options are 'none' (default) and 'posneg'. +#' In the case of 'posneg', the links color slot will be set to 1 if the link is positive, and -1 if the link is negative. +#' Use a method assignLinkColors() to assign colors to links and set this slot's value. +#' @slot variableMapping veupathUtils::VariableMetadataList object defining the variable mappings in the network. +#' @slot correlationCoefThreshold numeric defining the correlation coefficient threshold for filtering links. Default is NA (no filtering). +#' Any link with an absolute correlation coefficient below this threshold will be filtered out. +#' @slot pValueThreshold numeric defining the p-value threshold for filtering links. Default is NA (no filtering). +#' Any link with an p-value above this threshold will be filtered out. +#' @name CorrelationNetwork-class +#' @rdname CorrelationNetwork-class +#' @include class-Network.R +#' @export +setClass("CorrelationNetwork", + contains = "BaseNetwork", + slots = list( + links = "CorrelationLinkList", + correlationCoefThreshold = "numeric", + pValueThreshold = "numeric" + ), + prototype = prototype( + links = CorrelationLinkList(), + nodes = NodeList(), + linkColorScheme = 'posneg', #change default from base Network's 'none' + correlationCoefThreshold = NA_real_, + pValueThreshold = NA_real_, + variableMapping = VariableMetadataList() + ), + validity = check_correlation_network +) + +#' @include utils.R +#' Generate a Correlation Network +#' +#' Generate a CorrelationNetwork from a CorrelationLinkList and NodeList, or from a +#' data.frame with columns 'source', 'target', 'correlationCoef', 'pValue'. +#' @param links CorrelationLinkList +#' @param nodes NodeList +#' @param object Object containing data to be converted to a Network +#' @param correlationCoefThreshold numeric defining the correlation coefficient threshold for filtering links. Default is NULL (no filtering). +#' Any link with an absolute correlation coefficient below this threshold will be filtered out. +#' @param pValueThreshold numeric defining the p-value threshold for filtering links. Default is NULL (no filtering). +#' Any link with an p-value above this threshold will be filtered out. +#' @param linkColorScheme string defining the type of coloring scheme the links follow. +#' Options are 'none' and 'posneg' (default). +#' @param layout string defining the layout of the network. Options are 'force', 'circle', +#' and 'nicely' which are implemented in igraph. Default is 'nicely'. +#' @param variables VariableMetadataList +#' @param ... additional arguments for different flavors of the CorrelationNetwork constructor +#' @return CorrelationNetwork +#' @export +#' @examples +#' CorrelationNetwork(data.frame(source='a', target='b', correlationCoef=0.5, pValue=0.05)) +#' @rdname CorrelationNetwork +setGeneric("CorrelationNetwork", + function( + object, + links, + nodes, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + linkColorScheme = 'posneg', + variables = VariableMetadataList(), + ... + ) standardGeneric("CorrelationNetwork"), + signature = c("object", "links", "nodes") +) + +#' @rdname CorrelationNetwork +#' @aliases CorrelationNetwork,missing,CorrelationLinkList,NodeList +setMethod("CorrelationNetwork", signature("missing", "CorrelationLinkList", "NodeList"), function( + object, + links, + nodes, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + linkColorScheme = 'posneg', + variables = VariableMetadataList(), + pruneIsolatedNodes = c(TRUE, FALSE) +) { + pruneIsolatedNodes <- veupathUtils::matchArg(pruneIsolatedNodes) + + links <- pruneCorrelationLinks(links, correlationCoefThreshold, pValueThreshold) + net <- new("CorrelationNetwork", + links=links, + nodes=nodes, + linkColorScheme=linkColorScheme, + variableMapping=variables, + correlationCoefThreshold=ifelse(is.null(correlationCoefThreshold), NA_real_, correlationCoefThreshold), + pValueThreshold=ifelse(is.null(pValueThreshold), NA_real_, pValueThreshold) + ) + + if (pruneIsolatedNodes) { + net <- pruneIsolatedNodes(net) + } + + return(net) +}) + +#' @rdname CorrelationNetwork +#' @aliases CorrelationNetwork,data.frame,missing,missing +setMethod("CorrelationNetwork", signature("data.frame", "missing", "missing"), function( + object = data.frame(source=character(),target=character()), + links, + nodes, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + linkColorScheme = 'posneg', + layout = c("nicely", "force", "circle"), + variables = VariableMetadataList(), + pruneIsolatedNodes = c(TRUE, FALSE) +) { + layout <- veupathUtils::matchArg(layout) + pruneIsolatedNodes <- veupathUtils::matchArg(pruneIsolatedNodes) + + # any additional validation and filtering are handled by the CorrelationLinkList constructor + net <- new("CorrelationNetwork", + links=CorrelationLinkList(object, linkColorScheme, correlationCoefThreshold, pValueThreshold), + nodes=NodeList(object, layout), + linkColorScheme=linkColorScheme, + variableMapping=variables, + correlationCoefThreshold=ifelse(is.null(correlationCoefThreshold), NA_real_, correlationCoefThreshold), + pValueThreshold=ifelse(is.null(pValueThreshold), NA_real_, pValueThreshold) + ) + + if (pruneIsolatedNodes) { + net <- pruneIsolatedNodes(net) + } + + return(net) +}) + +#' @rdname CorrelationNetwork +#' @aliases CorrelationNetwork,missing,missing,missing +setMethod("CorrelationNetwork", signature("missing", "missing", "missing"), function( + object, + links, + nodes, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + linkColorScheme = 'none', + variables = VariableMetadataList(), + ... +) { + new("CorrelationNetwork") +}) \ No newline at end of file diff --git a/R/class-KPartiteNetwork.R b/R/class-KPartiteNetwork.R index 4a39784..03ef330 100644 --- a/R/class-KPartiteNetwork.R +++ b/R/class-KPartiteNetwork.R @@ -66,12 +66,11 @@ check_kpartite_network <- function(object) { #' @slot nodes NodeList object defining the nodes in the network. Some nodes may not have any links. #' @slot linkColorScheme string defining the type of coloring scheme the links follow. Options are 'none' (default) and 'posneg'. #' Use a method assignLinkColors() to assign colors to links and set this slot's value. -#' @slot partitions list of node ids that belong to each partition -#' +#' @slot partitions list of node ids that belong to each partition #' @name KPartiteNetwork-class #' @rdname KPartiteNetwork-class #' @include class-Network.R -#' @export +#' @export KPartiteNetwork <- setClass("KPartiteNetwork", contains = "Network", slots = c( diff --git a/R/class-Network.R b/R/class-Network.R index 3357ff3..b90e974 100644 --- a/R/class-Network.R +++ b/R/class-Network.R @@ -23,6 +23,16 @@ check_network <- function(object) { return(if (length(errors) == 0) TRUE else errors) } +# an abstract/ non-implementable class for other types of networks to subclass +setClass("BaseNetwork", + slots = list( + nodes = "NodeList", + linkColorScheme = "character", + variableMapping = "VariableMetadataList" + ), + contains = "VIRTUAL" +) + #' Network #' #' A class for representing networks. A network is composed of nodes and links (edges, connections, etc.). A link is represented @@ -34,18 +44,15 @@ check_network <- function(object) { #' @slot linkColorScheme string defining the type of coloring scheme the links follow. Options are 'none' (default) and 'posneg'. #' In the case of 'posneg', the links color slot will be set to 1 if the link is positive, and -1 if the link is negative. #' Use a method assignLinkColors() to assign colors to links and set this slot's value. -#' @slot variableMapping veupathUtils::VariableMetadataList object defining the variable mappings in the network. -#' +#' @slot variableMapping veupathUtils::VariableMetadataList object defining the variable mappings in the network. #' @name Network-class #' @rdname Network-class #' @include class-Link.R #' @export -setClass("Network", - representation( - links = "LinkList", - nodes = "NodeList", - linkColorScheme = "character", - variableMapping = "VariableMetadataList" +setClass("Network", + contains = "BaseNetwork", + slots = list( + links = "LinkList" ), prototype = prototype( links = LinkList(), diff --git a/R/class-Node.R b/R/class-Node.R index 5e1c37b..617ceaa 100644 --- a/R/class-Node.R +++ b/R/class-Node.R @@ -22,7 +22,8 @@ check_node_id <- function(object) { #' A Node Id #' #' A class for representing node ids -#' +#' +#' @slot value character value representing the node id #' @name NodeId-class #' @rdname NodeId-class #' @export diff --git a/R/methods-CorrelationLinks.R b/R/methods-CorrelationLinks.R new file mode 100644 index 0000000..57c95fd --- /dev/null +++ b/R/methods-CorrelationLinks.R @@ -0,0 +1,89 @@ +# Methods for Link and LinkList objects + +# Accessors for fanciness +setGeneric("correlationCoef", function(object) standardGeneric("correlationCoef")) +setGeneric("correlationCoef<-", function(object, value) standardGeneric("correlationCoef<-")) +setGeneric("pValue", function(object) standardGeneric("pValue")) +setGeneric("pValue<-", function(object, value) standardGeneric("pValue<-")) + +setMethod("correlationCoef", "CorrelationLink", function(object) object@correlationCoef) +setMethod("correlationCoef<-", "CorrelationLink", function(object, value) {object@correlationCoef <- value; validObject(object); object}) +setMethod("pValue", "CorrelationLink", function(object) object@pValue) +setMethod("pValue<-", "CorrelationLink", function(object, value) {object@pValue <- value; validObject(object); object}) + +# Additional methods +#' @include methods-Links.R +setMethod("getSourceNodes", "CorrelationLinkList", function(object) lapply(object, function(x) source(x))) +setMethod("getTargetNodes", "CorrelationLinkList", function(object) lapply(object, function(x) target(x))) +setMethod("getWeights", "CorrelationLinkList", function(object) unlist(lapply(object, function(x) weight(x)))) +setMethod("getColors", "CorrelationLinkList", function(object) unlist(lapply(object, function(x) color(x)))) + +setGeneric("getCorrelationCoefs", function(object) standardGeneric("getCorrelationCoefs")) +setMethod("getCorrelationCoefs", "CorrelationLinkList", function(object) unlist(lapply(object, function(x) correlationCoef(x)))) +setGeneric("getPValues", function(object) standardGeneric("getPValues")) +setMethod("getPValues", "CorrelationLinkList", function(object) unlist(lapply(object, function(x) pValue(x)))) + +#' Filter Correlation Links +#' +#' This function filters CorrelationLinkList by pValue and correlationCoef +#' @param object CorrelationLinkList or CorrelationNetwork +#' @param correlationCoefThreshold threshold to filter edges by correlation coefficient. Default is NULL. +#' Any links with absolute correlation coefficients below this threshold will be removed. +#' @param pValueThreshold threshold to filter edges by p-value. Default is NULL. +#' Any links with p-values above this threshold will be removed. +#' @param verbose boolean indicating if timed logging is desired +#' @return CorrelationLinkList or CorrelationNetwork +#' @export +#' @rdname pruneCorrelationLinks +setGeneric("pruneCorrelationLinks", +function( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) { + standardGeneric("pruneCorrelationLinks") +}) + +#' @rdname pruneCorrelationLinks +#' @aliases pruneCorrelationLinks,CorrelationLinkList-method +setMethod("pruneCorrelationLinks", "CorrelationLinkList", +function( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) { + verbose <- veupathUtils::matchArg(verbose) + + if (!is.null(correlationCoefThreshold)) { + correlationCoefs <- sapply(object, correlationCoef) + newLinks <- object[abs(correlationCoefs) >= correlationCoefThreshold] + } else { + newLinks <- object + } + + if (!is.null(pValueThreshold)) { + pValues <- sapply(object, pValue) + newLinks <- newLinks[pValues <= pValueThreshold] + } + + if (verbose) { + message("Removed ", length(object) - length(newLinks), " links") + } + + validObject(newLinks) + return(newLinks) +}) + +toJSONGeneric <- getGeneric("toJSON", package = "veupathUtils") + +#' @export +setMethod(toJSONGeneric, signature("CorrelationLinkList"), function(object, named = c(TRUE, FALSE)) { + named <- veupathUtils::matchArg(named) + tmp <- veupathUtils::S4SimpleListToJSON(object, FALSE) + + if (named) tmp <- paste0('{"links":', tmp, "}") + + return(tmp) +}) \ No newline at end of file diff --git a/R/methods-CorrelationNetwork.R b/R/methods-CorrelationNetwork.R new file mode 100644 index 0000000..ce8dd9a --- /dev/null +++ b/R/methods-CorrelationNetwork.R @@ -0,0 +1,90 @@ +# Methods for the CorrelationNetwork class + +setGeneric("getCorrelationCoefThreshold", function(object) standardGeneric("getCorrelationCoefThreshold")) +setMethod("getCorrelationCoefThreshold", "CorrelationNetwork", function(object) object@correlationCoefThreshold) +setGeneric("getPValueThreshold", function(object) standardGeneric("getPValueThreshold")) +setMethod("getPValueThreshold", "CorrelationNetwork", function(object) object@pValueThreshold) + +#' Prune Links by Correlation Coefficient +#' +#' Removes links that have an absolute correlation coefficient below a +#' threshold. This is a convenience function that calls pruneCorrelationLinks. +#' @param net A CorrelationNetwork object +#' @param correlationCoefThreshold The threshold +#' @param verbose If TRUE, will print messages +#' @export +pruneLinksByCorrelationCoef <- function(net, correlationCoefThreshold = NULL, verbose = c(TRUE, FALSE)) { + verbose <- veupathUtils::matchArg(verbose) + + return(pruneCorrelationLinks(net = net, correlationCoefThreshold = correlationCoefThreshold, verbose = verbose)) +} + +#' Prune Links by P-Value +#' +#' Removes links that have a p-value above a threshold. This is a convenience +#' function that calls pruneCorrelationLinks. +#' @param net A Network object +#' @param pValueThreshold The threshold +#' @param verbose If TRUE, will print messages +#' @export +pruneLinksByPValue <- function(net, pValueThreshold = NULL, verbose = c(TRUE, FALSE)) { + verbose <- veupathUtils::matchArg(verbose) + + return(pruneCorrelationLinks(net = net, pValueThreshold = pValueThreshold, verbose = verbose)) +} + +#' @rdname pruneCorrelationLinks +#' @aliases pruneCorrelationLinks,CorrelationNetwork-method +setMethod("pruneCorrelationLinks", "CorrelationNetwork", +function( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) { + verbose <- veupathUtils::matchArg(verbose) + + object@links <- pruneCorrelationLinks( + object@links, + correlationCoefThreshold = correlationCoefThreshold, + pValueThreshold = pValueThreshold, + verbose = verbose + ) + + object@correlationCoefThreshold <- ifelse(is.null(correlationCoefThreshold), NA_real_, correlationCoefThreshold) + object@pValueThreshold <- ifelse(is.null(pValueThreshold), NA_real_, pValueThreshold) + + validObject(object) + return(object) +}) + +toJSONGeneric <- getGeneric("toJSON", package = "veupathUtils") + +#' Convert CorrelationNetwork object to JSON +#' +#' Converts a CorrelationNetwork object to JSON +#' @param object A CorrelationNetwork object +#' @param named boolean that declares if names should be included +#' @export +setMethod(toJSONGeneric, "CorrelationNetwork", function(object, named = c(TRUE, FALSE)) { + + named <- veupathUtils::matchArg(named) + tmp <- character() + + nodes_json <- veupathUtils::toJSON(object@nodes, named = FALSE) + links_json <- veupathUtils::toJSON(object@links, named = FALSE) + + tmp <- paste0('"nodes":', nodes_json, ',"links":', links_json) + tmp <- paste0('"data":{', tmp, '}') + tmp <- paste0( + '{', tmp, + ',"config":{', + '"variables":{', veupathUtils::toJSON(object@variableMapping, named = FALSE), '}', + ',"correlationCoefThreshold":', jsonlite::toJSON(jsonlite::unbox(object@correlationCoefThreshold)), + ',"pValueThreshold":', jsonlite::toJSON(jsonlite::unbox(object@pValueThreshold)), + '}}') + + if (named) tmp <- paste0('{"network":', tmp, '}') + + return(tmp) +}) \ No newline at end of file diff --git a/R/methods-Network.R b/R/methods-Network.R index f5e7fb7..55327f1 100644 --- a/R/methods-Network.R +++ b/R/methods-Network.R @@ -3,16 +3,16 @@ #' @include methods-Nodes.R # Fancy accessors setGeneric("getNodes", function(object) standardGeneric("getNodes")) -setMethod("getNodes", "Network", function(object) object@nodes) -setMethod("getNodeIds", "Network", function(object) getNodeIds(object@nodes)) +setMethod("getNodes", "BaseNetwork", function(object) object@nodes) +setMethod("getNodeIds", "BaseNetwork", function(object) getNodeIds(object@nodes)) setGeneric("getLinks", function(object) standardGeneric("getLinks")) -setMethod("getLinks", "Network", function(object) object@links) +setMethod("getLinks", "BaseNetwork", function(object) object@links) setGeneric("getLinkColorScheme", function(object) standardGeneric("getLinkColorScheme")) -setMethod("getLinkColorScheme", "Network", function(object) object@linkColorScheme) +setMethod("getLinkColorScheme", "BaseNetwork", function(object) object@linkColorScheme) # No setters! Once created, a network should only be updated via network methods -setMethod("getDegrees", "Network", function(object) getDegrees(getNodes(object))) -setMethod("getCoords", "Network", function(object) getCoords(getNodes(object))) +setMethod("getDegrees", "BaseNetwork", function(object) getDegrees(getNodes(object))) +setMethod("getCoords", "BaseNetwork", function(object) getCoords(getNodes(object))) ## General network methods @@ -24,7 +24,7 @@ setMethod("getCoords", "Network", function(object) getCoords(getNodes(object))) setGeneric("getIsolatedNodes", function(net) standardGeneric("getIsolatedNodes")) #' @export -setMethod("getIsolatedNodes", "Network", function(net) { +setMethod("getIsolatedNodes", "BaseNetwork", function(net) { nodes <- getNodes(net) links <- getLinks(net) @@ -45,7 +45,7 @@ setMethod("getIsolatedNodes", "Network", function(net) { setGeneric("pruneIsolatedNodes", function(net, verbose = c(TRUE, FALSE)) standardGeneric("pruneIsolatedNodes")) #' @export -setMethod("pruneIsolatedNodes", "Network", function(net, verbose = c(TRUE, FALSE)) { +setMethod("pruneIsolatedNodes", "BaseNetwork", function(net, verbose = c(TRUE, FALSE)) { verbose <- veupathUtils::matchArg(verbose) nodes <- getNodes(net) isolatedNodeIds <- getNodeIds(getIsolatedNodes(net)) @@ -74,7 +74,7 @@ getLinkUniqueString <- function(link) { setGeneric("getDuplicateLinks", function(net) standardGeneric("getDuplicateLinks")) #' @export -setMethod("getDuplicateLinks", "Network", function(net) { +setMethod("getDuplicateLinks", "BaseNetwork", function(net) { links <- getLinks(net) # check for links that have the same source and target node as another link @@ -93,7 +93,7 @@ setMethod("getDuplicateLinks", "Network", function(net) { setGeneric("pruneDuplicateLinks", function(net, verbose = c(TRUE, FALSE)) standardGeneric("pruneDuplicateLinks")) #' @export -setMethod("pruneDuplicateLinks", "Network", function(net, verbose = c(TRUE, FALSE)) { +setMethod("pruneDuplicateLinks", "BaseNetwork", function(net, verbose = c(TRUE, FALSE)) { verbose <- veupathUtils::matchArg(verbose) links <- getLinks(net) @@ -122,7 +122,7 @@ setMethod("pruneDuplicateLinks", "Network", function(net, verbose = c(TRUE, FALS setGeneric("pruneLinksByPredicate", function(net, predicate, verbose = c(TRUE, FALSE), ...) standardGeneric("pruneLinksByPredicate")) #' @export -setMethod("pruneLinksByPredicate", "Network", function(net, predicate, verbose = c(TRUE, FALSE), ...) { +setMethod("pruneLinksByPredicate", "BaseNetwork", function(net, predicate, verbose = c(TRUE, FALSE), ...) { verbose <- veupathUtils::matchArg(verbose) links <- getLinks(net) net@links <- links[which(!sapply(links, predicate, ...))] @@ -177,7 +177,7 @@ toJSONGeneric <- getGeneric("toJSON", package = "veupathUtils") #' @param object A Network object #' @param named boolean that declares if names should be included #' @export -setMethod(toJSONGeneric, "Network", function(object, named = c(TRUE, FALSE)) { +setMethod(toJSONGeneric, "BaseNetwork", function(object, named = c(TRUE, FALSE)) { named <- veupathUtils::matchArg(named) tmp <- character() @@ -199,22 +199,17 @@ setMethod(toJSONGeneric, "Network", function(object, named = c(TRUE, FALSE)) { #' This function returns the name of a json file which it has #' written an object out to. #' @param x an object to convert to json and write to a tmp file -#' @param verbose boolean that declares if logging is desired -#' @return character name of a tmp file w ext *.json -#' @export -setGeneric("writeNetworkJSON", function(x, pattern = NULL, verbose = c(TRUE, FALSE)) standardGeneric("writeNetworkJSON")) - -#' Write network json to local tmp file -#' -#' This function returns the name of a json file which it has -#' written a Network object out to. -#' @param x a data.table to convert to json and write to a tmp file #' @param pattern optional tmp file prefix #' @param verbose boolean that declares if logging is desired #' @return character name of a tmp file w ext *.json #' @importFrom jsonlite toJSON #' @export -setMethod("writeNetworkJSON", "Network", function(x, pattern=NULL, verbose = c(TRUE, FALSE)) { +#' @rdname writeNetworkJSON +setGeneric("writeNetworkJSON", function(x, pattern = NULL, verbose = c(TRUE, FALSE)) standardGeneric("writeNetworkJSON"), signature = c("x")) + +#' @rdname writeNetworkJSON +#' @aliases writeNetworkJSON,Network-method +setMethod("writeNetworkJSON", "BaseNetwork", function(x, pattern=NULL, verbose = c(TRUE, FALSE)) { net <- x verbose <- veupathUtils::matchArg(verbose) diff --git a/man/CorrelationLink-class.Rd b/man/CorrelationLink-class.Rd new file mode 100644 index 0000000..2409e05 --- /dev/null +++ b/man/CorrelationLink-class.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-CorrelationLink.R +\docType{class} +\name{CorrelationLink-class} +\alias{CorrelationLink-class} +\title{CorrelationLink} +\description{ +Represent one singular link in a correlation network. A link has a source, +a target, a correlation coefficient, and a p-value. Its weight is the +absolute value of the correlation coefficient. It is undirected. +It may have a color, timestamp, or label (coming soon!) +} diff --git a/man/CorrelationLink.Rd b/man/CorrelationLink.Rd new file mode 100644 index 0000000..81631f8 --- /dev/null +++ b/man/CorrelationLink.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-CorrelationLink.R +\name{CorrelationLink} +\alias{CorrelationLink} +\alias{CorrelationLink,Node,Node-method} +\alias{CorrelationLink,character,character-method} +\alias{CorrelationLink,numeric,numeric-method} +\alias{CorrelationLink,NodeId,NodeId-method} +\alias{CorrelationLink,missing,missing-method} +\title{CorrelationLink constructor} +\usage{ +CorrelationLink( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) + +\S4method{CorrelationLink}{Node,Node}( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) + +\S4method{CorrelationLink}{character,character}( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) + +\S4method{CorrelationLink}{numeric,numeric}( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) + +\S4method{CorrelationLink}{NodeId,NodeId}( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) + +\S4method{CorrelationLink}{missing,missing}( + source, + target, + correlationCoef = 1, + pValue = NULL, + color = NULL +) +} +\arguments{ +\item{source}{The source node identifier} + +\item{target}{The target node identifier} + +\item{correlationCoef}{The correlation coefficient (weight) of the link} + +\item{pValue}{The p-value of the link} + +\item{color}{The color of the link} +} +\description{ +CorrelationLink constructor +} diff --git a/man/CorrelationLinkList-class.Rd b/man/CorrelationLinkList-class.Rd new file mode 100644 index 0000000..cfafe9f --- /dev/null +++ b/man/CorrelationLinkList-class.Rd @@ -0,0 +1,9 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-CorrelationLink.R +\docType{class} +\name{CorrelationLinkList-class} +\alias{CorrelationLinkList-class} +\title{Correlation Link List} +\description{ +A class for representing links in a correlation network +} diff --git a/man/CorrelationLinkList.Rd b/man/CorrelationLinkList.Rd new file mode 100644 index 0000000..338ce10 --- /dev/null +++ b/man/CorrelationLinkList.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-CorrelationLink.R +\name{CorrelationLinkList} +\alias{CorrelationLinkList} +\alias{CorrelationLinkList,data.frame-method} +\alias{CorrelationLinkList,missing-method} +\alias{CorrelationLinkList,SimpleList-method} +\alias{CorrelationLinkList,list-method} +\title{Generate a CorrelationLinkList} +\usage{ +CorrelationLinkList( + object, + linkColorScheme = c("none", "posneg"), + correlationCoefThreshold = NULL, + pValueThreshold = NULL +) + +\S4method{CorrelationLinkList}{data.frame}( + object = data.frame(source = character(), target = character(), correlationCoef = + numeric(), pValue = numeric()), + linkColorScheme = c("none", "posneg"), + correlationCoefThreshold = NULL, + pValueThreshold = NULL +) + +\S4method{CorrelationLinkList}{missing}(object) + +\S4method{CorrelationLinkList}{SimpleList}(object) + +\S4method{CorrelationLinkList}{list}(object) +} +\arguments{ +\item{object}{Object containing data to be converted to a LinkList. Could be a SimpleList of Links or a data.frame +with columns source, target, correlationCoef, pValue.} + +\item{linkColorScheme}{Either 'none' or 'posneg'. If 'posneg', the link color will be based on the sign of the correlation coefficient.} + +\item{correlationCoefThreshold}{numeric value used to filter links based on correlationCoef. Default is NULL (i.e. no filtering). +Any links with an absolute correlationCoef below this threshold will be removed.} + +\item{pValueThreshold}{numeric value used to filter links based on pValue. Default is NULL (i.e. no filtering). +Any links with an pValue above this threshold will be removed.} +} +\value{ +CorrelationLinkList +} +\description{ +Generate a CorrelationLinkList from an edgeList +} +\examples{ +CorrelationLinkList(data.frame(source='a',target='b',correlationCoef=0.5,pValue=0.01)) +} diff --git a/man/CorrelationNetwork-class.Rd b/man/CorrelationNetwork-class.Rd new file mode 100644 index 0000000..cb08478 --- /dev/null +++ b/man/CorrelationNetwork-class.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/class-CorrelationNetwork.R +\docType{class} +\name{CorrelationNetwork-class} +\alias{CorrelationNetwork-class} +\title{Correlation Network} +\description{ +A class for representing networks of pairwise correlations. A network is composed of nodes and links (edges, connections, etc.). +A link is represented as a pair of nodes, with attributes such as correlationCoef and pValue (see Link). To represent a network, +we need both the list of links in the network and a list of nodes in case some nodes have no links. A network can also have +properties such as directedness, levels, colors, etc. (coming soon). +} +\section{Slots}{ + +\describe{ +\item{\code{links}}{CorrelationLinkList object defining the links in the network.} + +\item{\code{nodes}}{NodeList object defining the nodes in the network. Some nodes may not have any links.} + +\item{\code{linkColorScheme}}{string defining the type of coloring scheme the links follow. Options are 'none' (default) and 'posneg'. +In the case of 'posneg', the links color slot will be set to 1 if the link is positive, and -1 if the link is negative. +Use a method assignLinkColors() to assign colors to links and set this slot's value.} + +\item{\code{variableMapping}}{veupathUtils::VariableMetadataList object defining the variable mappings in the network.} + +\item{\code{correlationCoefThreshold}}{numeric defining the correlation coefficient threshold for filtering links. Default is NA (no filtering). +Any link with an absolute correlation coefficient below this threshold will be filtered out.} + +\item{\code{pValueThreshold}}{numeric defining the p-value threshold for filtering links. Default is NA (no filtering). +Any link with an p-value above this threshold will be filtered out.} +}} + diff --git a/man/NodeId-class.Rd b/man/NodeId-class.Rd index 409fa90..b3301c0 100644 --- a/man/NodeId-class.Rd +++ b/man/NodeId-class.Rd @@ -7,3 +7,9 @@ \description{ A class for representing node ids } +\section{Slots}{ + +\describe{ +\item{\code{value}}{character value representing the node id} +}} + diff --git a/man/pruneCorrelationLinks.Rd b/man/pruneCorrelationLinks.Rd new file mode 100644 index 0000000..22b4e8a --- /dev/null +++ b/man/pruneCorrelationLinks.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-CorrelationLinks.R, +% R/methods-CorrelationNetwork.R +\name{pruneCorrelationLinks} +\alias{pruneCorrelationLinks} +\alias{pruneCorrelationLinks,CorrelationLinkList-method} +\alias{pruneCorrelationLinks,CorrelationNetwork-method} +\title{Filter Correlation Links} +\usage{ +pruneCorrelationLinks( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) + +\S4method{pruneCorrelationLinks}{CorrelationLinkList}( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) + +\S4method{pruneCorrelationLinks}{CorrelationNetwork}( + object, + correlationCoefThreshold = NULL, + pValueThreshold = NULL, + verbose = c(TRUE, FALSE) +) +} +\arguments{ +\item{object}{CorrelationLinkList or CorrelationNetwork} + +\item{correlationCoefThreshold}{threshold to filter edges by correlation coefficient. Default is NULL. +Any links with absolute correlation coefficients below this threshold will be removed.} + +\item{pValueThreshold}{threshold to filter edges by p-value. Default is NULL. +Any links with p-values above this threshold will be removed.} + +\item{verbose}{boolean indicating if timed logging is desired} +} +\value{ +CorrelationLinkList or CorrelationNetwork +} +\description{ +This function filters CorrelationLinkList by pValue and correlationCoef +} diff --git a/man/pruneLinksByCorrelationCoef.Rd b/man/pruneLinksByCorrelationCoef.Rd new file mode 100644 index 0000000..bcda3b8 --- /dev/null +++ b/man/pruneLinksByCorrelationCoef.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-CorrelationNetwork.R +\name{pruneLinksByCorrelationCoef} +\alias{pruneLinksByCorrelationCoef} +\title{Prune Links by Correlation Coefficient} +\usage{ +pruneLinksByCorrelationCoef( + net, + correlationCoefThreshold = NULL, + verbose = c(TRUE, FALSE) +) +} +\arguments{ +\item{net}{A CorrelationNetwork object} + +\item{correlationCoefThreshold}{The threshold} + +\item{verbose}{If TRUE, will print messages} +} +\description{ +Removes links that have an absolute correlation coefficient below a +threshold. This is a convenience function that calls pruneCorrelationLinks. +} diff --git a/man/pruneLinksByPValue.Rd b/man/pruneLinksByPValue.Rd new file mode 100644 index 0000000..cf5f669 --- /dev/null +++ b/man/pruneLinksByPValue.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-CorrelationNetwork.R +\name{pruneLinksByPValue} +\alias{pruneLinksByPValue} +\title{Prune Links by P-Value} +\usage{ +pruneLinksByPValue(net, pValueThreshold = NULL, verbose = c(TRUE, FALSE)) +} +\arguments{ +\item{net}{A Network object} + +\item{pValueThreshold}{The threshold} + +\item{verbose}{If TRUE, will print messages} +} +\description{ +Removes links that have a p-value above a threshold. This is a convenience +function that calls pruneCorrelationLinks. +} diff --git a/man/toJSON-Network-method.Rd b/man/toJSON-BaseNetwork-method.Rd similarity index 70% rename from man/toJSON-Network-method.Rd rename to man/toJSON-BaseNetwork-method.Rd index 742b5cb..0322599 100644 --- a/man/toJSON-Network-method.Rd +++ b/man/toJSON-BaseNetwork-method.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-Network.R -\name{toJSON,Network-method} -\alias{toJSON,Network-method} +\name{toJSON,BaseNetwork-method} +\alias{toJSON,BaseNetwork-method} \title{Convert Network object to JSON} \usage{ -\S4method{toJSON}{Network}(object, named = c(TRUE, FALSE)) +\S4method{toJSON}{BaseNetwork}(object, named = c(TRUE, FALSE)) } \arguments{ \item{object}{A Network object} diff --git a/man/toJSON-CorrelationNetwork-method.Rd b/man/toJSON-CorrelationNetwork-method.Rd new file mode 100644 index 0000000..303cc5b --- /dev/null +++ b/man/toJSON-CorrelationNetwork-method.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-CorrelationNetwork.R +\name{toJSON,CorrelationNetwork-method} +\alias{toJSON,CorrelationNetwork-method} +\title{Convert CorrelationNetwork object to JSON} +\usage{ +\S4method{toJSON}{CorrelationNetwork}(object, named = c(TRUE, FALSE)) +} +\arguments{ +\item{object}{A CorrelationNetwork object} + +\item{named}{boolean that declares if names should be included} +} +\description{ +Converts a CorrelationNetwork object to JSON +} diff --git a/man/writeNetworkJSON-Network-method.Rd b/man/writeNetworkJSON-Network-method.Rd deleted file mode 100644 index 1872437..0000000 --- a/man/writeNetworkJSON-Network-method.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/methods-Network.R -\name{writeNetworkJSON,Network-method} -\alias{writeNetworkJSON,Network-method} -\title{Write network json to local tmp file} -\usage{ -\S4method{writeNetworkJSON}{Network}(x, pattern = NULL, verbose = c(TRUE, FALSE)) -} -\arguments{ -\item{x}{a data.table to convert to json and write to a tmp file} - -\item{pattern}{optional tmp file prefix} - -\item{verbose}{boolean that declares if logging is desired} -} -\value{ -character name of a tmp file w ext *.json -} -\description{ -This function returns the name of a json file which it has -written a Network object out to. -} diff --git a/man/writeNetworkJSON.Rd b/man/writeNetworkJSON.Rd index 1f32127..8b154c7 100644 --- a/man/writeNetworkJSON.Rd +++ b/man/writeNetworkJSON.Rd @@ -2,13 +2,19 @@ % Please edit documentation in R/methods-Network.R \name{writeNetworkJSON} \alias{writeNetworkJSON} +\alias{writeNetworkJSON,BaseNetwork-method} +\alias{writeNetworkJSON,Network-method} \title{Write network json to tmp file} \usage{ writeNetworkJSON(x, pattern = NULL, verbose = c(TRUE, FALSE)) + +\S4method{writeNetworkJSON}{BaseNetwork}(x, pattern = NULL, verbose = c(TRUE, FALSE)) } \arguments{ \item{x}{an object to convert to json and write to a tmp file} +\item{pattern}{optional tmp file prefix} + \item{verbose}{boolean that declares if logging is desired} } \value{ diff --git a/tests/testthat/test-correlation-network.R b/tests/testthat/test-correlation-network.R new file mode 100644 index 0000000..dde4b20 --- /dev/null +++ b/tests/testthat/test-correlation-network.R @@ -0,0 +1,230 @@ +test_that("correlation networks can be created", { + # Create some nodes + nodeA <- Node( + id = NodeId('A') + ) + nodeB <- Node( + id = NodeId('B') + ) + nodeC <- Node( + id = NodeId('C') + ) + + # Create some edges + link1 <- CorrelationLink(source = nodeA, target = nodeB, correlationCoef = .8, pValue = .01) + link2 <- CorrelationLink(source = nodeB, target = nodeC, correlationCoef = .3, pValue = .001) + link3 <- CorrelationLink(source = nodeC, target = nodeA, correlationCoef = -.8, pValue = .1) + + # Create a network + net <- CorrelationNetwork( + links = CorrelationLinkList(c(link1, link2, link3)), + nodes = NodeList(c(nodeA, nodeB, nodeC)), + pValueThreshold = .05 + ) + + expect_equal(getNodes(net), NodeList(c(nodeA, nodeB, nodeC))) + expect_equal(getLinks(net), CorrelationLinkList(c(link1, link2))) ## link 3 is pruned for high pValue + expect_equal(getLinkColorScheme(net), 'posneg') + + # Create a network + net <- CorrelationNetwork( + links = CorrelationLinkList(c(link1, link2, link3)), + nodes = NodeList(c(nodeA, nodeB, nodeC)) + ) + + expect_equal(getNodes(net), NodeList(c(nodeA, nodeB, nodeC))) + expect_equal(getLinks(net), CorrelationLinkList(c(link1, link2, link3))) ## link 3 should be back + expect_equal(getLinkColorScheme(net), 'posneg') +}) + +test_that("we cannot make inappropriate correlation networks", { + # Create some nodes + nodeA <- Node( + id = NodeId('A') + ) + nodeB <- Node( + id = NodeId('B') + ) + nodeC <- Node( + id = NodeId('C') + ) + + # Create links + link1 <- CorrelationLink(source = nodeA, target = nodeB, correlationCoef = .8, pValue = .01) + link2 <- CorrelationLink(source = nodeB, target = nodeC, correlationCoef = .3, pValue = .001) + + # Create a link w non-sensical pValue and correlationCoef + expect_error(CorrelationLink(source = nodeC, target = nodeA, correlationCoef = -.8, pValue = 1.1)) + expect_error(CorrelationLink(source = nodeC, target = nodeA, correlationCoef = 1.1, pValue = .1)) + + # Create a network with a node in links that isn't in nodes + expect_error(CorrelationNetwork(links = CorrelationLinkList(c(link1, link2)), nodes = NodeList(c(nodeB, nodeC)))) + + # Create a network with an invalid linkColorScheme + expect_error(CorrelationNetwork(links = CorrelationLinkList(c(link1, link2)), nodes = NodeList(c(nodeA, nodeB)), linkColorScheme = 'nope')) + + # Create a network with duplicate nodes + expect_error(CorrelationNetwork(links = CorrelationLinkList(c(link1, link2)), nodes = NodeList(c(nodeA, nodeB, nodeB)))) + + # Create a network where links dont meet threshold + net <- CorrelationNetwork(links = CorrelationLinkList(c(link1, link2)), nodes = NodeList(c(nodeA, nodeB, nodeC))) + net@pValueThreshold <- .001 + expect_error(validObject(net)) + +}) + +test_that("correlation networks can be pruned by threshold", { + nodeA <- Node( + id = NodeId('A') + ) + nodeB <- Node( + id = NodeId('B') + ) + nodeC <- Node( + id = NodeId('C') + ) + + # Create some edges + link1 <- CorrelationLink(source = nodeA, target = nodeB, correlationCoef = .8, pValue = .01) + link2 <- CorrelationLink(source = nodeB, target = nodeC, correlationCoef = .3, pValue = .001) + link3 <- CorrelationLink(source = nodeC, target = nodeA, correlationCoef = -.8, pValue = .1) + + # Create a network + net <- CorrelationNetwork( + links = CorrelationLinkList(c(link1, link2, link3)), + nodes = NodeList(c(nodeA, nodeB, nodeC)) + ) + + net <- pruneCorrelationLinks(net, pValueThreshold = .05) + + # links should be modified and nothing else + expect_equal(getNodes(net), NodeList(c(nodeA, nodeB, nodeC))) + expect_equal(getLinks(net), CorrelationLinkList(c(link1, link2))) ## link 3 is pruned for high pValue + expect_equal(getLinkColorScheme(net), 'posneg') +}) + +test_that("toJSON works for networks", { + # Create some nodes + nodeA <- Node( + id = NodeId('A'), + degree = 2 + ) + nodeB <- Node( + id = NodeId('B'), + degree = 2 + ) + nodeC <- Node( + id = NodeId('C'), + degree = 2 + ) + + # Create some edges + link1 <- CorrelationLink(source = nodeA, target = nodeB, correlationCoef = .8, pValue = .01) + link2 <- CorrelationLink(source = nodeB, target = nodeC, correlationCoef = .3, pValue = .001) + link3 <- CorrelationLink(source = nodeC, target = nodeA, correlationCoef = -.8, pValue = .1) + + # Create a network + net <- CorrelationNetwork( + links = CorrelationLinkList(c(link1, link2, link3)), + nodes = NodeList(c(nodeA, nodeB, nodeC)) + ) + + # Convert to JSON + json <- veupathUtils::toJSON(net) + jsonList <- jsonlite::fromJSON(json) + expect_equal(jsonList$network$data$links$source, c('A','B','C')) + expect_equal(jsonList$network$data$links$target, c('B','C','A')) + expect_equal(jsonList$network$data$links$weight, c(.8,.3,.8)) + expect_equal(jsonList$network$data$nodes$id, c('A','B','C')) + expect_equal(jsonList$network$data$nodes$degree, c(2,2,2)) + expect_equal(length(jsonList$network$config$variables), 0) + expect_equal(jsonList$network$config$correlationCoefThreshold, "NA") + expect_equal(jsonList$network$config$pValueThreshold, "NA") + + net <- CorrelationNetwork( + links = CorrelationLinkList(c(link1, link2, link3)), + nodes = NodeList(c(nodeA, nodeB, nodeC)), + pValueThreshold = .05 + ) + + json <- veupathUtils::toJSON(net) + jsonList <- jsonlite::fromJSON(json) + expect_equal(jsonList$network$data$links$source, c('A','B')) + expect_equal(jsonList$network$data$links$target, c('B','C')) + expect_equal(jsonList$network$data$links$weight, c(.8,.3)) + expect_equal(jsonList$network$data$nodes$id, c('A','B','C')) + expect_equal(jsonList$network$data$nodes$degree, c(2,2,2)) + expect_equal(length(jsonList$network$config$variables), 0) + expect_equal(jsonList$network$config$correlationCoefThreshold, "NA") + expect_equal(jsonList$network$config$pValueThreshold, 0.05) +}) + +test_that("we can build a Network from an edgeList data.frame", { + #w a weight column + edgeList <- data.frame( + source = c('a', 'b', 'c'), + target = c('b', 'c', 'a'), + correlationCoef = c(.8,.3,-.8), + pValue = c(.01,.001,.1) + ) + net <- CorrelationNetwork(object = edgeList, linkColorScheme = 'none') + expect_equal(getNodeIds(net), c('a', 'b', 'c')) + expect_equal(getDegrees(net), c(2, 2, 2)) + expect_equal(!is.null(getCoords(net)), TRUE) + expect_equal(getLinks(net)[[2]]@weight, .3) + expect_equal(getLinks(net)[[3]]@weight, .8) + expect_equal(getLinkColorScheme(net), 'none') + expect_equal(getDegrees(net), c(2, 2, 2)) + + #w a color scheme + edgeList <- data.frame( + source = c('a', 'b', 'c'), + target = c('b', 'c', 'a'), + correlationCoef = c(.8,.3,-.8), + pValue = c(.01,.001,.1) + ) + net <- CorrelationNetwork(object = edgeList, linkColorScheme = 'posneg') + expect_equal(getNodeIds(net), c('a', 'b', 'c')) + expect_equal(getDegrees(net), c(2, 2, 2)) + expect_equal(!is.null(getCoords(net)), TRUE) + expect_equal(getLinks(net)[[1]]@weight, .8) + expect_equal(getLinks(net)[[2]]@weight, .3) + expect_equal(getLinks(net)[[3]]@weight, .8) + expect_equal(getLinks(net)[[1]]@color, 1) + expect_equal(getLinks(net)[[2]]@color, 1) + expect_equal(getLinks(net)[[3]]@color, -1) + expect_equal(getLinkColorScheme(net), 'posneg') + expect_equal(getDegrees(net), c(2, 2, 2)) + + #w a pValueThreshold + edgeList <- data.frame( + source = c('a', 'b', 'c'), + target = c('b', 'c', 'a'), + correlationCoef = c(.8,.3,-.8), + pValue = c(.01,.001,.1) + ) + net <- CorrelationNetwork(object = edgeList, pValueThreshold = .05) + expect_equal(getNodeIds(net), c('a', 'b', 'c')) + expect_equal(getDegrees(net), c(2, 2, 2)) + expect_equal(!is.null(getCoords(net)), TRUE) + expect_equal(getLinkColorScheme(net), 'posneg') + expect_equal(length(getLinks(net)), 2) + expect_equal(getLinks(net)[[1]]@weight, .8) + expect_equal(getLinks(net)[[2]]@weight, .3) + + #w a correlationCoefThreshold + edgeList <- data.frame( + source = c('a', 'b', 'c'), + target = c('b', 'c', 'a'), + correlationCoef = c(.8,.3,-.8), + pValue = c(.01,.001,.1) + ) + net <- CorrelationNetwork(object = edgeList, correlationCoefThreshold = .5) + expect_equal(getNodeIds(net), c('a', 'b', 'c')) + expect_equal(getDegrees(net), c(2, 2, 2)) + expect_equal(!is.null(getCoords(net)), TRUE) + expect_equal(getLinkColorScheme(net), 'posneg') + expect_equal(length(getLinks(net)), 2) + expect_equal(getLinks(net)[[1]]@weight, .8) + expect_equal(getLinks(net)[[2]]@weight, .8) #second link is actually third link bc of correlationCoefThreshold!! +}) \ No newline at end of file