-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharcDiagram.R
101 lines (94 loc) · 3.39 KB
/
arcDiagram.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
############################################################################
# Title: arcDiagram.R
# Description: function to plot a basic arc-diagram
# Author: Gaston Sanchez
# www.gastonsanchez.com
# License: BSD Simplified License
# http://www.opensource.org/license/BSD-3-Clause
# Copyright (c) 2012, Gaston Sanchez
# All rights reserved
############################################################################
arcDiagram <- function(
edgelist, sorted=TRUE, decreasing=FALSE, lwd=NULL,
col=NULL, cex=NULL, col.nodes=NULL, lend=1, ljoin=2, lmitre=1,
las=2, bg=NULL, mar=c(4,1,3,1))
{
# ARGUMENTS
# edgelist: two-column matrix with edges
# sorted: logical to indicate if nodes should be sorted
# decreasing: logical to indicate type of sorting (used only when sorted=TRUE)
# lwd: widths for the arcs (default 1)
# col: color for the arcs (default "gray50")
# cex: magnification of the nodes labels (default 1)
# col.nodes: color of the nodes labels (default "gray50")
# lend: the line end style for the arcs (see par)
# ljoin: the line join style for the arcs (see par)
# lmitre: the line mitre limit fort the arcs (see par)
# las: numeric in {0,1,2,3}; the style of axis labels (see par)
# bg: background color (default "white")
# mar: numeric vector for margins (see par)
# make sure edgelist is a two-col matrix
if (!is.matrix(edgelist) || ncol(edgelist)!=2)
stop("argument 'edgelist' must be a two column matrix")
edges = edgelist
# how many edges
ne = nrow(edges)
# get nodes
nodes = unique(as.vector(edges))
nums = seq_along(nodes)
# how many nodes
nn = length(nodes)
# ennumerate
if (sorted) {
nodes = sort(nodes, decreasing=decreasing)
nums = order(nodes, decreasing=decreasing)
}
# check default argument values
if (is.null(lwd)) lwd = rep(1, ne)
if (length(lwd) != ne) lwd = rep(lwd, length=ne)
if (is.null(col)) col = rep("gray50", ne)
if (length(col) != ne) col = rep(col, length=ne)
if (is.null(cex)) cex = rep(1, nn)
if (length(cex) != nn) cex = rep(cex, length=nn)
if (is.null(col.nodes)) col.nodes = rep("gray50", nn)
if (length(col.nodes) != nn) col.nodes = rep(col.nodes, length=nn)
if (is.null(bg)) bg = "white"
# node labels coordinates
nf = rep(1 / nn, nn)
# node labels center coordinates
fin = cumsum(nf)
ini = c(0, cumsum(nf)[-nn])
centers = (ini + fin) / 2
names(centers) = nodes
# arcs coordinates
# matrix with numeric indices
e_num = matrix(0, nrow(edges), ncol(edges))
for (i in 1:nrow(edges))
{
e_num[i,1] = centers[which(nodes == edges[i,1])]
e_num[i,2] = centers[which(nodes == edges[i,2])]
}
# max arc radius
radios = abs(e_num[,1] - e_num[,2]) / 2
max_radios = which(radios == max(radios))
max_rad = unique(radios[max_radios] / 2)
# arc locations
locs = rowSums(e_num) / 2
# plot
par(mar = mar, bg = bg)
plot.new()
plot.window(xlim=c(-0.025, 1.025), ylim=c(0, 1*max_rad*2))
# plot connecting arcs
z = seq(0, pi, l=100)
for (i in 1:nrow(edges))
{
radio = radios[i]
x = locs[i] + radio * cos(z)
y = radio * sin(z)
lines(x, y, col=col[i], lwd=lwd[i],
lend=lend, ljoin=ljoin, lmitre=lmitre)
}
# add node names
mtext(nodes, side=1, line=0, at=centers, cex=cex,
col=col.nodes, las=las)
}