DrawMap = function(Data_Map, data, projectType, varargin){
map <- Data_Map$map
if (map$map.preproc){
data <- Data_Map$data
}
N <- nrow(data)
dims <- ncol(data)
# Parse varargin
Source <- NULL
smooth <- 0.15
for (i in 1:length(varargin)){
if (names(varargin)[i] == 'classes'){ classes <- varargin$classes }
if (names(varargin)[i] == 'markColour'){ markColour <- varargin$markColour }
if (names(varargin)[i] == 'coloring'){ Source <- varargin$coloring }
if (names(varargin)[i] == 'ColorMap'){ colMap <- varargin$ColorMap }
if (names(varargin)[i] == 'flatColoring'){ flatColoring <- varargin$flatColoring }
if (names(varargin)[i] == 'Surf'){ Surf <- varargin$Surf }
}
if (isempty(classes)) {
classes <- ones(size(data, 1), 1)
cls <- 1
} else { cls <- unique(classes) }
nCls <- length(cls)
# Get map internal
intern <- map$map.internal
# Get map links
links <- map$map.links
# Get map faces
faces <- map$map.faces
# Get map mapped
mapped <- map$map.mapped
kind <-'internal'
# Project data onto map
dataP <- NULL
if (!isempty(data)) {
cType = strcmpi('mapped', kind)
points <- data
if (projectType == 0) {
# Projection to the nearest node
# Search the nearest node
x1 <- rowSums(points^2)
x2 <- t(rowSums(mapped^2))
x1 <- matrix(x1)
x1 = kronecker(matrix(1, 1, dim(x2)[2]), x1)
x2 = kronecker(matrix(1, dim(x1)[1], 1), x2)
dist1 <- bsxfun('+', x1, x2)-2*(points%*%t(mapped))
dist <- apply(dist1,1,min)
k <- nrow(dist1)
num <- rep(0,k)
for (i in 1:k) {num[i] <- which.min(dist1[i, ])}
if (cType) { dataP <- mapped[num, ]
} else { dataP <- intern[num, ] }
}
if (projectType == 1) {
# projection onto nearest edge
# Get array of edges end
V2 <- t(mapped[links[, 2], ])
# Form matrix of edges directions
dir <- t(mapped[links[, 1], ]) - V2
# Calculate squared length of edge directions
len <- (colSums(dir^2))
# Calculate projections length (l in documentation, matrix analogue of (2))
pr <- bsxfun('-', points%*%dir, kronecker(matrix(1, nrow(points), 1), t(colSums(V2*dir))))
# Copy projections to normalize (l* in documentation)
prn <- bsxfun('/', pr, kronecker(matrix(1, nrow(points), 1), t(len)))
# Non negativity
prn[prn<0] <- 0
#Cut too long projections (it is the same as step 3 of algorithm in documentation)
prn[prn>1] <- 1
# Calculate distances:
x <- kronecker(matrix(1, 1, dim(links)[1]), rowSums(points^2))
y <- kronecker(matrix(1, 1, N), as.matrix(colSums(V2^2)))
dist <- bsxfun('+', x, t(y)) - 2*points%*%V2 +
prn*( bsxfun('*', prn, kronecker(matrix(1, N, 1), t(len)))-2*pr)
# Select the nearest edge
edge <- apply(dist, 1, which.min)
dist <- apply(dist, 1, min)
# form index to find length of projections
ind <- t(1:N) + (edge - 1)*N
if (cType) {
dataP <- bsxfun('*', kronecker(matrix(1, 1, ncol(mapped)), (1-prn[ind])), mapped[links[edge, 2], ])
+ bsxfun('*', kronecker(matrix(1, 1, ncol(mapped)), prn[ind]), mapped[links[edge, 1], ])
} else {
c11 <- kronecker(matrix(1,1,2), (1-prn[ind]))
c12 <- kronecker(matrix(1,1,2), prn[ind])
c21 <- intern[links[edge, 2], ]
c22 <- intern[links[edge, 1], ]
dataP <- bsxfun('*', c11, c21) + bsxfun('*', c12, c22)}
}
if (projectType == 2) {
#form auxiliary vectors
Y2 <- t(mapped[faces[, 3], ])
Y20 <- Y2-t(mapped[faces[, 1], ])
Y21 <- Y2-t(mapped[faces[, 2], ])
Y10 <- t(mapped[faces[, 2], ] - mapped[faces[, 1], ])
Y20Y20 <- colSums(Y20 ^ 2)
Y21Y20 <- colSums(Y20 * Y21)
Y21Y21 <- colSums(Y21 ^ 2)
# Calculate projections
A20 <- bsxfun('-', kronecker(matrix(1, nrow(points), 1), t(as.matrix(colSums(Y2*Y20)))), points%*%Y20)
A21 <- bsxfun('-', kronecker(matrix(1, nrow(points), 1), t(as.matrix(colSums(Y2*Y21)))), points%*%Y21)
A10 <- bsxfun('/', bsxfun('-', (A20-A21), kronecker(matrix(1, nrow(points), 1), t(as.matrix(colSums(Y21*Y10))))),
kronecker(matrix(1, nrow(points), 1), t(as.matrix(colSums(Y10^2)))))
tmp <- Y20Y20*Y21Y21 - Y21Y20^2
A0 <- bsxfun('/', bsxfun('*', A20,kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y21Y21))))
-bsxfun('*', A21, kronecker(matrix(1, nrow(points),1),t(as.matrix(Y21Y20)))),
kronecker(matrix(1, nrow(points),1), t(as.matrix(tmp))))
A1 <- bsxfun('/',bsxfun('*', A21,kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y20Y20))))
-bsxfun('*',A20, kronecker(matrix(1, nrow(points),1), t(as.matrix(Y21Y20)))),
kronecker(matrix(1, nrow(points), 1), t(as.matrix(tmp))))
A20 <- bsxfun('/', A20, kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y20Y20))))
A21 <- bsxfun('/', A21, kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y21Y21))))
# Normalize projections
A20N <- A20
A20N[A20N<0] <- 0
A20N[A20N>1] <- 1
A21N <- A21
A21N[A21N<0] <- 0
A21N[A21N>1] <- 1
A10[A10<0] <- 0
A10[A10>1] <- 1
tmp <- A0<0
A0[tmp] <- 0
A1[tmp] <- A21N[tmp]
tmp <- A1<0
A0[tmp] <- A20N[tmp]
A1[tmp] <- 0
tmp <- (1-(A0+A1))<0
A0[tmp] <- A10[tmp]
A1[tmp] <- 1-A10[tmp]
# Calculate distances
dist1 <- bsxfun('+', kronecker(matrix(1, 1, nrow(faces)), rowSums(points^2)),
kronecker(matrix(1, nrow(points), 1), t(colSums(Y2^2)))) - 2*points%*%Y2
dist2 <- bsxfun('*', A0, kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y20Y20))))*(A0-2*A20)
dist3 <- bsxfun('*', A1, kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y21Y21))))*(A1-2*A21)
dist4 <- 2 * bsxfun('*', A0*A1, kronecker(matrix(1, nrow(points), 1), t(as.matrix(Y21Y20))))
dist <- dist1 + dist2 + dist3 + dist4
tmp <- apply(dist, 1, which.min)
dist <- apply(dist, 1, min)
ind <- t(1:N) + (tmp - 1)*N
if (cType){
dataP <- bsxfun('*', A0[ind], mapped[faces[tmp, 1], ])
+ bsxfun('*', A1[ind], mapped[faces[tmp, 2], ])
+ bsxfun('*', 1-A0[ind]-A1[ind], mapped[faces[tmp, 3], ])
} else {
c1 <- bsxfun('*', kronecker(matrix(1,1,2), A0[ind]), intern[faces[tmp, 1], ])
c2 <- bsxfun('*', kronecker(matrix(1,1,2), A1[ind]), intern[faces[tmp, 2], ])
c3 <- bsxfun('*', kronecker(matrix(1,1,2), (1-A0[ind]-A1[ind])), intern[faces[tmp, 3], ])
dataP <- c1 + c2 + c3
}
}
}
if (!isempty(Source)) {
d <- ncol(mapped)
# Extract grid
for(i in 1:nrow(faces)) { faces[i, ] <- sort(faces[i, ]) }
# Form list of all edges in grid
edges <- rbind(faces[, 1:2], faces[, 2:3], faces[, c(1, 3)])
# Search unique values
edges <- as.matrix(distinct(tibble(edges)))
# Step 2. Form list of nodes in new node list
nN <- nrow(mapped)
nE <- nrow(edges)
maps <- rbind(mapped, (mapped[edges[, 1], ] + mapped[edges[, 2], ]) / 2)
inter <- rbind(intern, (intern[edges[, 1], ] + intern[edges[, 2], ]) / 2)
# Form list of indexes for nodes
ind <- matrix(0, nE + nN,nE + nN)
siz <- dim(ind)
indL <- (edges[,1]) + ((edges[,2]) - 1)*siz[1]
ind[indL] <- (nN + 1):(nN + nE)
# Step 3. form list of six nodes for each face
face <- cbind(faces, ind[(faces[, 1]) + ((faces[, 2]) - 1)*siz[1]],
ind[(faces[, 2]) + ((faces[, 3]) - 1)*siz[1]],
ind[(faces[, 1]) + ((faces[, 3]) - 1)*siz[1]])
# Step 4. Form final list of triangles
grid <- rbind(face[, c(2, 4, 5)], face[, c(1, 4, 6)],
face[, c(3, 5, 6)], face[, c(4, 5, 6)])
gridReady <- grid
nodeMap <- maps
nodeInt <- inter
if (is.numeric(Source)) {
if (length(Source) == 1) {
# It is number of coordinate or PCs
Source <- round(Source)
if (Source > 0 ) {
# It is coordinate
# Get data in original space
temp <- bsxfun( '+', nodeMap %*% t(map$map.PCs), kronecker(matrix(1, nrow(nodeMap), 1),
matrix(map$map.means, nrow = 1, byrow = TRUE)))
t <- mapped[, Source]
if (Source > ncol(temp)) {f <- temp[, Source]}
}
if (Source > 0 ) {
if (map$map.preproc) {
# Get required coordinate
f <- nodeMap[, -source]
}else {
# Calculate projection on required PC
f <- bsxfun('-', nodeMap, map.means)* map$map.PCs[, -source]
}
}
}
if (is.array(Source)) {
Source <- c(Source)
if (length(Source) != nrow(data)){
stop('Number of elements in vector "coloring" ', nrow(Source),
' must coincides with number of data points ', nrow(data))
}
smooth <- -1 / (smooth * mean(diag(var(dataP))));
# Calculate distances from each node to each datapoint
d1 <- kronecker(matrix(1,1,nrow(nodeInt)),as.matrix(rowSums(dataP^2)))
d2 <- kronecker(matrix(1,nrow(dataP),1),as.matrix(t(rowSums(nodeInt^2))))
dist <- bsxfun('+',d1,d2) - 2 * (dataP %*% t(nodeInt))
# Calclulate RBF in each point
tmp <- bsxfun('*', exp(dist * smooth), kronecker(matrix(1,1,ncol(dist)),Source))
# Calculate result
res <- t(colSums(tmp))
mins <- min(res)
res <- (res - mins) / (max(res) - mins)
f <- res
}
}
if (is.character(Source) && strcmp(Source,'density')){
# Calculate variances for all attributes
smooth <- -1 / (smooth * mean(diag(var(dataP))));
# Calculate distances from each node to each datapoint
d1 <- kronecker(matrix(1, 1, nrow(nodeInt)), as.matrix(rowSums(dataP^2)))
d2 <- kronecker(matrix(1, nrow(dataP), 1), as.matrix(t(rowSums(nodeInt^2))))
dist <- bsxfun('+',d1,d2) - 2 * (dataP %*% t(nodeInt))
# Calclulate RBF in each point
tmp <- bsxfun('*', exp(dist * smooth), kronecker(matrix(1, 1, ncol(dist)), matrix(1, nrow(data), 1)))
# Calculate result
res <- t(colSums(tmp))
mins <- min(res)
res <- (res - mins) / (max(res) - mins)
# Draw colouring
f <- res
}
m <- cbind(nodeInt,t(f))
zmean <- apply((gridReady), MARGIN = 1, function(row){mean(m[row,3])})
facecolor <- colour_ramp(viridis_pal()(8))( rescale( x = zmean ) )
if (flatColoring) {
# draw 2d surface
if (colMap == 'continuous'){
p <- plot_ly(x = intern[,1], y = intern[,2],type = 'scatter',
mode = 'markers', marker = list(size = 3, color = 'red'),
name = 'Map nodes')%>%
add_trace(x = nodeInt[,1], y = nodeInt[,2], z = array(f/mean(f)),
type = 'heatmap',colors = facecolor, name = 'Heat Map Plot')%>%
layout(title = ' Map Colouring ',xaxis = list(title = 'x'),
yaxis = list(title = 'y'))
}
if (colMap == 'discrete'){
p <- plot_ly(x = intern[,1], y = intern[,2],type = 'scatter',
mode = 'markers',marker = list(size = 3,color = 'red'),
name = 'Map nodes')%>%
add_trace(x = nodeInt[,1], y = nodeInt[,2], z = array(f/mean(f)),
type = 'contour', name = 'Contour Plot')%>%
layout(title = ' Map Colouring ',xaxis = list(title = 'x'),
yaxis = list(title = 'y'))
}
for (i in 1:nCls){
p <- add_trace(p,
x = dataP[which(classes == i),1],
y = dataP[which(classes == i),2],
type = 'scatter', mode = 'markers',
marker = list(color = markColour[i], size = 7, symbol = 201),
name = paste('Class',toString(i)))
}
return(p)
}
if (!flatColoring) {
if (Surf == "Internal"){
p <- plot_ly(x = nodeInt[,1], y = nodeInt[,2], z = array(f),type = 'mesh3d',
i = gridReady[,1]-1,
j = gridReady[,2]-1,
k = gridReady[,3]-1,
facecolor = facecolor)
}
if (Surf == "External"){
p <- plot_ly(x = nodeMap[,1], y = nodeMap[,2], z = nodeMap[,3],
type = 'mesh3d',
i = gridReady[,1]-1,
j = gridReady[,2]-1,
k = gridReady[,3]-1,
facecolor = facecolor,
name = '3D surface')
for (i in 1:nCls){
p <- add_trace(p,
x = data[which(classes == i),1],
y = data[which(classes == i),2],
z = data[which(classes == i),3],
type = 'scatter3d',mode = 'markers',
marker = list(color = markColour[i], size = 6, symbol = 201),
name = paste('Class',toString(i)))
}
}
return(p)
}
}
if (isempty(Source)) {
data <- dataP
# Draw Map
nrows <- map$map.sizes[1]
ncols <- map$map.sizes[2]
Vmap_xy <- matrix(NaN,(nrows*ncols+(ncols-1)),2)
Hmap_xy <- matrix(NaN,1,2)
for (i in 1:ncols){
k1 <- 1 + (i-1)*(nrows+1)
k2 <- 1 + (i-1)*(nrows)
Vmap_xy[k1:(k1 + (nrows - 1)),] <- intern[k2:(k2 + (nrows - 1)), ]
}
for (i in 1:nrows){
Hmap_xy <- rbind(Hmap_xy,
matrix(c(1:ncols, rep(i,ncols)),
ncol = 2, nrow = ncols), matrix(NaN,1,2))
}
map_xy <- rbind(Vmap_xy,Hmap_xy)
# Project data to map
if (projectType == 0) {
lims <- matrix(0, 1, 4)
lims[c(1, 3)] <- min(intern) - 0.5
lims[c(2, 4)] <- max(intern) + 0.5
plot(NULL, xlim = lims[1:2], ylim = lims[3:4], ylab="y", xlab="x")
L <- map$map.sizes[1]
for(i in 1:L) {
points2D(intern[(L*i-L+1):(L*i), 1],
intern[(L*i-L+1):(L*i), 2],
xlim = lims[1:2], ylim = lims[3:4],
type ='l', col = "red", add = TRUE)
}
for(i in 1:L) {
points2D(intern[seq(i, (i + L*(L-1)),L), 1],
intern[seq(i, (i + L*(L-1)),L), 2],
type ='l',col = "black",add = TRUE)
}
if (!is.null(data)) {
d <- 10*data[, 1] + data[, 2]
# Search unique points
d1 <- uniq(d)
dat <- data[d1$m, ]
ic <- d1$n
count <- histc(ic, 1:length(d1$b))$cnt
ma <- max(count)
if (nCls==1) { # No classes
plot(dat[,1], dat[,2],
pch = 19, col = 'green',cex = 1.35*count,
xlim = c(1,10), ylim = c(1,10), xlab = 'X', ylab = 'Y')
}
nDat <- nrow(dat)
Proportions <- matrix(0, nDat, nCls)
for (k in 1:nCls){
ind <- classes == cls[k]
Proportions[,k] <- histc(ic[ind], 1:nDat)$cnt
}
for (k in 1:nDat){
# Transform counts to proportions
prop <- Proportions[k,] / sum(Proportions[k,])
# Starts from zero angle
angle <- 0
# Draw chart
if (length(prop) == 1){
# One class chart
for (i in 1:length(Proportions[k,])){
color <- markColour[i,]
t <- seq(0,2*pi,0.05)
xp <- count[k]/(ma*2)*cos(t) + dat[k, 1]
yp <- count[k]/(ma*2)*sin(t) + dat[k,2]
polygon2D(xp, yp, col = color, xlim = lims[1:2], ylim = lims[3:4])
}
} else {
# Several classes case
for (i in 1:length(Proportions[k,])){
th1 <- angle
th2 <- angle + prop[i]*2*pi
color <- markColour[i]
t <- linspace(th1,th2)
xp <- count[k]/(ma*2)*cos(t) + dat[k, 1]
yp <- count[k]/(ma*2)*sin(t) + dat[k,2]
xp <- c(xp,dat[k, 1],xp[1])
yp <- c(yp,dat[k,2],yp[1])
polygon2D(xp, yp, col = color, add = TRUE, xlim = lims[1:2], ylim = lims[3:4])
angle <- th2
}
}
}
}
}
if (projectType == 1) {
p <- plot_ly(x = map_xy[, 1],
y = map_xy[, 2],
type = 'scatter', mode ='lines',
marker = list(color = 'red'),
name = 'Map frame')
for (i in 1:nCls){
p <- add_trace(p,
x = data[which(classes == i),1],
y = data[which(classes == i),2],
type = 'scatter',mode = 'markers',
marker = list(color = markColour[i], size = 8, symbol = 201),
name = paste('Class',toString(i)))%>%
layout(title = "Projection of data points to the nearest edge",
xaxis = list (title = "x"),
yaxis = list (title = "y"))
}
return(p)
}
if (projectType == 2) {
p <- plot_ly (x = map_xy[, 1],
y = map_xy[, 2],
type = 'scatter', mode ='lines',
marker = list(color = 'red'),
name = 'Map frame')
for (i in 1:nCls){
p <- add_trace(p,
x = data[which(classes == i),1],
y = data[which(classes == i),2],
type = 'scatter',mode = 'markers',
marker = list(color = markColour[i], size = 7, symbol = 201),
name = paste('Class',toString(i)))%>%
layout(title = "Projection of data points to the face",
xaxis = list (title = "x"),
yaxis = list (title = "y"))
}
return(p)
}
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.