R/network.R

Defines functions networkplot

Documented in networkplot

#' Correlation network from spectral similarity data
#'
#' \code{networkplot()} is used to generate correlation networks from
#' spectral similarity data. An interactive visualisation can be produced using
#' \pkg{plotly}.
#'
#' @import sna
#' @import network
#' @import ggplot2
#'
#' @importFrom GGally ggnet2
#' @importFrom plotly ggplotly
#'
#' @param distmat A distance matrix as generated by
#'   \code{\link{distanceMatrix}}.
#'
#' @param interactive Logical, defaults to \code{FALSE}. If \code{TRUE}, an
#'   interactive visualisation is generated using \pkg{plotly}.
#'
#' @param show_labels Logical, defaults to \code{FALSE}. If \code{TRUE},
#'   feature IDs are printed as labels in the network plot. Argument has no
#'   effect if \code{interactive} is \code{TRUE} (because in this case, labels
#'   are displayed on mouse-over).
#'
#' @param label_size Numeric, defaults to \code{1.5}. If \code{show_labels} is
#'   \code{TRUE} and \code{interactive} is \code{FALSE}, \code{label_size}
#'   defines the size of labels in the plot.
#'
#' @param highlight_annotated Logical, defaults to \code{FALSE}. If
#'   \code{TRUE}, points for features for which an annotation was added before
#'   using \code{\link{distanceMatrix}} are highlighted by red colour, while
#'   other points are grey in the network plot.
#'
#' @param min_similarity Numeric, defaults to \code{0.1}. The minimum spectral
#'   contrast angle (see\code{\link{cossim}}) that is considered a spectral
#'   similarity and hence a connection in the network.
#'
#' @param exclude_singletons Logical, defaults to \code{FALSE}. If \code{TRUE},
#'   features that have no connection to any other feature will not be
#'   displayed in the network plot.
#'
#' @return A network plot generated with the help of
#'   \code{\link[network]{network}}, \code{\link[GGally]{ggnet2}} and, if
#'   interactive, \code{\link[plotly]{ggplotly}}. Edge weights correspond to
#'   spectral similarities.
#'
#' @examples
#' load(file = system.file("extdata",
#'     "distmat.RData",
#'     package = "CluMSIDdata"))
#'
#' networkplot(distmat[1:50,1:50], show_labels = TRUE,
#'                 exclude_singletons = TRUE)
#'
#' @export
networkplot <- function(distmat, interactive = FALSE, show_labels = FALSE,
                            label_size = 1.5, highlight_annotated = FALSE,
                            min_similarity = 0.1, exclude_singletons = FALSE){
    simmat <- 1 - distmat
    simmat[simmat < min_similarity] <- 0
    if(exclude_singletons){
        subvec <- colSums(simmat) >= 1 + min_similarity
        simmat <- simmat[subvec, subvec]
    }

    spec_net <- network::network(simmat, directed = FALSE,
                                matrix.type = "adjacency")
    network::set.vertex.attribute(spec_net, "ID", rownames(simmat))
    network::set.vertex.attribute(spec_net, "annotated",
                                grepl(pattern = " - ", x = rownames(simmat)))

    if(highlight_annotated == FALSE){
        colv <- rep("#333333", nrow(simmat))
    } else {
        colv <- as.character(network::get.vertex.attribute(
            spec_net, "annotated"))
        colv[colv == "TRUE"] <- "orangered"
        colv[colv == "FALSE"] <- "#333333"
    }
    names(colv) <- rownames(simmat)

    elist <- network::as.edgelist(spec_net)
    eweights <- c()
    for (i in seq_len(nrow(elist))){
        x <- elist[i,1]
        y <- elist[i,2]
        eweights[i] <- simmat[x,y]
    }
    network::set.edge.attribute(spec_net, "weight",
                                round(eweights, digits = 4))

    if(interactive){
        show_labels <- FALSE
    }

    netplot <- GGally::ggnet2(  spec_net,
                                color = "ID",
                                palette = colv,
                                size = 4,
                                alpha = 0.8,
                                edge.size = "weight",
                                edge.alpha = 0.25,
                                label = show_labels,
                                label.size = label_size) +
        ggplot2::theme( legend.position = "none",
                        axis.ticks = ggplot2::element_blank(),
                        axis.text = ggplot2::element_blank())

    if(interactive == FALSE){
        return(netplot)
    } else {
        suppressMessages(
            netplotly <- plotly::ggplotly(netplot, tooltip = "~factor(color)")
        )
        for(i in seq_along(netplotly$x$data)[-1]){
            netplotly$x$data[[i]]$text <- strsplit(netplotly$x$data[[i]]$text,
                                                    split = ": ")[[1]][2]
        }
        return(netplotly)
    }
}
tdepke/CluMSID documentation built on April 10, 2022, noon