Switch to unified view

a b/R/DIscBIO-generic-clustheatmap.R
1
#' @title Plotting clusters in a heatmap representation of the cell distances
2
#' @description  This functions plots a heatmap of the distance matrix grouped
3
#'   by clusters. Individual clusters are highlighted with rainbow colors along
4
#'   the x and y-axes.
5
#' @param object \code{DISCBIO} class object.
6
#' @param clustering_method either "k-means" or "model-based" ("k" and "mb" are
7
#' also accepted)
8
#' @param hmethod  Agglomeration method used for determining the cluster order
9
#'   from hierarchical clustering of the cluster medoids. This should be one of
10
#'   "ward.D", "ward.D2", "single", "complete", "average". Default is "single".
11
#' @param quiet if `TRUE`, intermediary output is suppressed
12
#' @param rseed Random integer to fix random results.
13
#' @param plot if `TRUE`, plots the heatmap; otherwise, just prints cclmo
14
#' @return Unless otherwise specified, a heatmap and a vector of the underlying
15
#'   cluster order.
16
#' @importFrom stats hclust as.dist cor
17
setGeneric(
18
  "clustheatmap",
19
  function(object,
20
           clustering_method = "k-means",
21
           hmethod = "single",
22
           rseed = NULL,
23
           quiet = FALSE,
24
           plot = TRUE) {
25
    standardGeneric("clustheatmap")
26
  }
27
)
28
29
#' @export
30
#' @rdname clustheatmap
31
setMethod(
32
  "clustheatmap",
33
  signature = "DISCBIO",
34
  definition = function(
35
    object, clustering_method, hmethod, rseed, quiet, plot
36
  ) {
37
    x <- object@fdata
38
    if (tolower(clustering_method) %in% c("k-means", "k")) {
39
      part <- object@kmeans$kpart
40
    } else if (tolower(clustering_method) %in% c("model-based", "mb")) {
41
      object@clusterpar$metric <- "pearson"
42
      y <- clustfun(
43
        object@fdata,
44
        clustnr = 20,
45
        bootnr = 50,
46
        metric = "pearson",
47
        do.gap = TRUE,
48
        SE.method = "Tibs2001SEmax",
49
        SE.factor = .25,
50
        B.gap = 50,
51
        cln = 0,
52
        rseed = rseed,
53
        quiet = quiet
54
      )
55
      object@distances <- as.matrix(y$di)
56
      part <- object@MBclusters$clusterid
57
    }
58
    na <- vector()
59
    j <- 0
60
    for (i in 1:max(part)) {
61
      if (sum(part == i) == 0) {
62
        next
63
      }
64
      j <- j + 1
65
      na <- append(na, i)
66
      d <- x[, part == i]
67
      if (sum(part == i) == 1) {
68
        cent <- d
69
      } else {
70
        cent <- apply(d, 1, mean)
71
      }
72
      if (j == 1) {
73
        tmp <- data.frame(cent)
74
      } else {
75
        tmp <- cbind(tmp, cent)
76
      }
77
    }
78
    names(tmp) <- paste("cl", na, sep = ".")
79
    if (max(part) > 1) {
80
      cclmo <-
81
        hclust(dist.gen(as.matrix(
82
          dist.gen(t(tmp), method = object@clusterpar$metric)
83
        )), method = hmethod)$order
84
    } else {
85
      cclmo <- 1
86
    }
87
    q <- part
88
    for (i in 1:max(part)) {
89
      q[part == na[cclmo[i]]] <- i
90
    }
91
    part <- q
92
    di <- as.data.frame(as.matrix(dist.gen(t(object@distances))))
93
    pto <- part[order(part, decreasing = FALSE)]
94
    ptn <- vector()
95
    for (i in 1:max(pto)) {
96
      pt <-
97
        names(pto)[pto == i]
98
      z <-
99
        if (length(pt) == 1) {
100
          pt
101
        } else {
102
          pt[hclust(as.dist(t(di[pt, pt])), method = hmethod)$order]
103
        }
104
      ptn <- append(ptn, z)
105
    }
106
    col <- c("black", "blue", "green", "red", "yellow", "gray")
107
    mi <- min(di, na.rm = TRUE)
108
    ma <- max(di, na.rm = TRUE)
109
    if (plot) {
110
      layout(
111
        matrix(
112
          data = c(1, 3, 2, 4),
113
          nrow = 2,
114
          ncol = 2
115
        ),
116
        widths = c(5, 1, 5, 1),
117
        heights = c(5, 1, 1, 1)
118
      )
119
      ColorRamp <- colorRampPalette(
120
        brewer.pal(n = 7, name = "RdYlBu")
121
      )(100)
122
      ColorLevels <- seq(mi, ma, length = length(ColorRamp))
123
      if (mi == ma) {
124
        ColorLevels <- seq(
125
          0.99 * mi, 1.01 * ma,
126
          length = length(ColorRamp)
127
        )
128
      }
129
130
      opar <- withr::local_par(mar = c(3, 5, 2.5, 2))
131
      on.exit(withr::local_par(opar))
132
      image(as.matrix(di[ptn, ptn]), col = ColorRamp, axes = FALSE)
133
      abline(0, 1)
134
      box()
135
136
      tmp <- vector()
137
      for (u in 1:max(part)) {
138
        ol <- (0:(length(part) - 1) /
139
          (length(part) - 1))[ptn %in% names(x)[part == u]]
140
        points(
141
          rep(0, length(ol)),
142
          ol,
143
          col = col[cclmo[u]],
144
          pch = 15,
145
          cex = .75
146
        )
147
        points(
148
          ol,
149
          rep(0, length(ol)),
150
          col = col[cclmo[u]],
151
          pch = 15,
152
          cex = .75
153
        )
154
        tmp <- append(tmp, mean(ol))
155
      }
156
      axis(1, at = tmp, labels = cclmo)
157
      axis(2, at = tmp, labels = cclmo)
158
      opar <- withr::local_par(mar = c(3, 2.5, 2.5, 2))
159
      on.exit(withr::local_par(opar))
160
      image(
161
        1,
162
        ColorLevels,
163
        matrix(
164
          data = ColorLevels,
165
          ncol = length(ColorLevels),
166
          nrow = 1
167
        ),
168
        col = ColorRamp,
169
        xlab = "",
170
        ylab = "",
171
        las = 2,
172
        xaxt = "n"
173
      )
174
      layout(1)
175
    }
176
    return(cclmo)
177
  }
178
)