Diff of /R/drawTree.R [000000] .. [53575d]

Switch to unified view

a b/R/drawTree.R
1
#' Function to draw TreeWAS results
2
#'
3
#' requires packages:
4
#'    plotly
5
#'    Rgraphviz
6
#'    graph
7
#'
8
#' @param tree Disease ontology
9
#' @param pp Posterior probabilities table
10
#' @param tree_title Title for plot
11
#' @param trim_tree_pp PP threshold to trim the tree
12
#'
13
#' @return Returns a plotly plot with TreeWAS results
14
15
drawTree <- function(
16
    tree            = NULL,
17
    pp              = NULL,
18
    tree_title      = "Tree",
19
    trim_tree_pp    = NULL
20
) {
21
22
    if ( ! is.null( trim_tree_pp ) ) {
23
        tmp <- trim_tree( tree = tree, pp = pp, pp.thr = trim_tree_pp )
24
        tree <- tmp$tree
25
        pp <- tmp$pp
26
    }
27
    
28
    matrix <- matrix(0, ncol = nrow(tree), nrow = nrow(tree))
29
    
30
    for( i in 1:( nrow( tree ) - 1 ) ) {
31
        p <- tree[i,"Par"]
32
        c <- tree[i,"ID"]
33
        matrix[p,c] <- 1
34
    }
35
36
    rownames(matrix) <- tree$ID
37
    colnames(matrix) <- tree$ID
38
    labels = tree$ID
39
    
40
    graph <- new("graphAM", adjMat = matrix, edgemode = 'directed')
41
    
42
    lGraph <- layoutGraph(graph)
43
    ninfo <- nodeRenderInfo(lGraph)
44
    
45
    node_state <- apply(pp,1,function(x) return( which.max(x) )) - 2
46
    tmp.pps <-c()
47
    for( i in 1:nrow(pp) ) tmp.pps[i] <- pp[i, node_state[i]+2]
48
    
49
    node_labels <- paste(
50
        tree$meaning,
51
        "<br>",
52
        "State: ", node_state,
53
        "<br>",
54
        "PP, = ", round(tmp.pps,2),
55
        sep = ""
56
    )
57
58
    nodeRI = data.frame(
59
        NODE    = names(ninfo$nodeX),
60
        PP1     = pp[,1],
61
        PP2     = pp[,2],
62
        PP3     = pp[,3],
63
        NODEX   = ninfo$nodeX,
64
        NODEY   = ninfo$nodeY,
65
        MEANING = tree$meaning,
66
        LABEL   = node_labels
67
    )
68
69
    col_pal_risk <- colorRampPalette( c( "white", rgb(112, 28, 28, max=255) ) )( 100 )
70
    col_pal_prot <- colorRampPalette( c( "white", rgb(8, 37, 103, max=255) ) )(100)
71
72
    cols1 <- map2color(pp[,3], col_pal_risk, limits = c(0,1))
73
    cols2 <- map2color(pp[,1], col_pal_prot, limits = c(0,1))
74
    cols <- rep("white",nrow(tree))
75
    idx <- which(node_state == 1)
76
    cols[idx] <- cols1[idx]
77
    idx <- which(node_state == -1)
78
    cols[idx] <- cols2[idx]
79
    nodeRI$COL <- cols
80
    
81
    attrs <- list(node = list(fillcolor = 'white'), edge = list(arrowsize=0.5))
82
    
83
    names(cols) <- labels
84
85
    nattrs <- list(fillcolor=cols)
86
    
87
    nodes <- buildNodeList(graph, nodeAttrs=nattrs, defAttrs=attrs$node)
88
    edges <- buildEdgeList(graph)
89
    vv <- agopen(name="foo", nodes=nodes, edges=edges, attrs=attrs,
90
                 edgeMode="directed")
91
92
    x <- vv
93
    y <- x@layoutType
94
    x <- graphLayout(x, y)
95
    ur <- upRight(boundBox(x))
96
    bl <- botLeft(boundBox(x))
97
    
98
    ##out <- list()
99
    ##out$nodeRI <- nodeRI
100
    
101
    ##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102
    ## Initalize plotly
103
    ##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104
    p <- plotly::plot_ly()
105
    
106
    xlim1 <- getX(ur)*1.02
107
    xlim0 <- -xlim1*0.02
108
    xlim <- c(xlim0, xlim1)
109
    
110
    ## Add an axis.
111
    p = plotly::layout(
112
        p,
113
        title      = tree_title,
114
        xaxis      = list(
115
            title          = "",
116
            showgrid       = FALSE,
117
            showticklabels = FALSE,
118
            showline       = FALSE,
119
            zeroline       = FALSE,
120
            range          = xlim
121
        ),
122
        yaxis      = list(
123
            title          = "",
124
            showgrid       = FALSE,
125
            showticklabels = FALSE,
126
            showline       = FALSE,
127
            zeroline       = FALSE,
128
            range          = c(getY(bl), getY(ur))
129
        ),
130
        showlegend = FALSE
131
    )
132
133
    ## Add the edges
134
    edges <- AgEdge(x)
135
    edges.p <- list()
136
    
137
    for( i in 1:length(edges) ) {
138
        
139
        edge <- edges[[i]]
140
        node.to <- edge@head
141
        node.from <- edge@tail
142
        
143
        for ( j in 1:length(splines(edge)) ) {
144
            z <- splines(edge)[[j]]
145
            points <- matrix(unlist(pointList(z)),ncol=2,byrow=TRUE)
146
            
147
            p <- add_trace(
148
                p,
149
                x          = points[,1],
150
                y          = points[,2],
151
                type       = "scatter",
152
                mode       = "lines",
153
                hoverinfo  = "none",
154
                line       = list(color = "gray"),
155
                showlegend = FALSE
156
            )
157
        }
158
159
        edges.p[[i]] <- points
160
        heads     = bezierPoints(z)
161
        head_from = heads[nrow(heads)-1, ]
162
        head_to   = heads[nrow(heads),]
163
    }
164
165
    ## Add the nodes
166
    order <- order(pp[,2],decreasing=TRUE)
167
    p = plotly::add_trace(
168
        p,
169
        x          = nodeRI$NODEX[order],
170
        y          = nodeRI$NODEY[order],
171
        type       = "scatter",
172
        mode       = "markers",
173
        text       = nodeRI$LABEL[order],
174
        hoverinfo  = "text",
175
        marker     = list(
176
            size   = 20,
177
            symbol = "circle",
178
            color = cols[order],
179
            line  = list( color = "black", width = 1)
180
        ),
181
        showlegend = FALSE
182
    )
183
    
184
    return(p)
185
    
186
}
187
188
trim_tree <- function( tree = tree, pp = pp, pp.thr = 0.75 )
189
{
190
  idx <- which(pp[,2] < 1 - pp.thr)
191
192
  t2 <- tree[idx,]
193
  siblings <- unique(unlist(lapply(t2$ID,get_tree_siblings,tree)))
194
  paths_to_root <- unique(unlist(lapply(t2$ID,get_path_ids_to_root,tree)))
195
196
  nodes_to_keep <- sort(unique(c(t2$ID,siblings,paths_to_root)),decreasing=F)
197
198
  t2 <- tree[tree$ID %in% nodes_to_keep, ]
199
  pp2 <- pp[tree$ID %in% nodes_to_keep,]
200
201
  new_id <- 1:nrow(t2)
202
  new_par <- new_id[match(t2$Par,t2$ID)]
203
204
  t2$ID <- new_id
205
  t2$Par <- new_par
206
207
  t2[nrow(t2),'Par'] <- 0
208
  o <- list(tree=t2,pp=pp2)
209
210
  return(o)
211
}
212
213
get_tree_siblings <- function(id,tree)
214
{
215
  par_id <- tree[ tree$ID %in% id, "Par"]
216
  sibling_ids <- tree[ tree$Par %in% par_id, "ID"]
217
218
  return(sibling_ids)
219
}
220
221
get_path_ids_to_root <- function( id, tree )
222
{
223
  out     <- id
224
  root_id <- tree[ nrow(tree), "ID"]
225
226
  while( ! root_id %in% out )
227
    out <- unique( c ( out, tree[ tree$ID %in% out, "Par" ] ) )
228
229
  return(out)
230
}
231
232
map2color <- function( x, pal, limits = range(x) )
233
{
234
  return( pal[ findInterval(
235
    x,
236
    seq(limits[1],limits[2],length.out=length(pal)+1),
237
    all.inside=TRUE
238
  ) ] )
239
}
240