Nothing
# https://github.com/r-spatial/sf/issues/572
st_envelope <- function(x) {
st_as_sfc(st_bbox(x))
}
st_is_ring <- function(x) {
boundary <- st_polygonize(x)
!st_is_empty(boundary)
}
# Redefine the 'filledContour' function from the 'raster' package
# since I don't like how the legend looks.
# For now, I have only changed how the legend/bar is plotted,
# the change itself is in the 'myfilled.contour' function
myfilledContour <- function(x, y = 1, maxpixels = 1e+05, add.key = TRUE, ...) {
if (nlayers(x) > 1) {
y <- min(max(1, y), nlayers(x))
x <- raster(x, y)
}
x <- sampleRegular(x, maxpixels, asRaster = TRUE, useGDAL = TRUE)
seq_cols <- seq_len(ncol(x))
seq_rows <- rev(seq_len(nrow(x)))
X <- xFromCol(x, seq_cols)
Y <- yFromRow(x, seq_rows)
Z <- t(matrix(getValues(x), ncol = x@ncols, byrow = TRUE)[seq_rows, ])
myfilled.contour(
x = X, y = Y, z = Z, add.key = add.key,
axes = FALSE, frame.plot = FALSE, ...
)
}
# I have only changed the legend/bar to remove the black border.
myfilled.contour <- function(x = seq(0, 1, length.out = nrow(z)),
y = seq(0, 1, length.out = ncol(z)), z,
xlim = range(x, finite = TRUE),
ylim = range(y, finite = TRUE),
zlim = range(z, finite = TRUE),
levels = pretty(zlim, nlevels), nlevels = 20,
color.palette = cm.colors, col = color.palette(length(levels) - 1),
plot.title, plot.axes, key.title, key.axes, asp = NA,
xaxs = "i", yaxs = "i", las = 1,
axes = TRUE, frame.plot = axes, add.title = FALSE, add.key = TRUE,
...) {
if (missing(z)) {
if (!missing(x)) {
if (is.list(x)) {
z <- x$z
y <- x$y
x <- x$x
} else {
z <- x
x <- seq.int(0, 1, length.out = nrow(z))
}
} else {
stop("no 'z' matrix specified")
}
} else if (is.list(x)) {
y <- x$y
x <- x$x
}
if (any(diff(x) <= 0) || any(diff(y) <= 0)) {
stop("increasing 'x' and 'y' values expected")
}
mar.orig <- (par.orig <- par(c("mar", "las", "mfrow")))$mar
on.exit(par(par.orig))
w <- (3 + mar.orig[2L]) * par("csi") * 2.54
if (add.key) {
layout(matrix(c(2, 1), ncol = 2L), widths = c(1, lcm(w)))
}
par(las = las)
mar <- mar.orig
mar[4L] <- mar[2L]
mar[2L] <- 1
par(mar = mar)
if (add.key) {
plot.new()
par(plt = c(0, 0.3, 0.1, 0.9))
# Change: add 'border = NA' and remove 'box()'
plot.window(xlim = c(0, 1), ylim = range(levels), xaxs = "i", yaxs = "i")
rect(0, levels[-length(levels)], 1, levels[-1L], col = col, border = NA)
if (missing(key.axes)) {
if (axes) {
axis(4)
}
} else {
key.axes
}
if (!missing(key.title)) {
key.title
}
}
mar <- mar.orig
mar[4L] <- 1
par(mar = mar)
plot.new()
# Change: make the plot region almost as big as the figure region
# but leave space for the main title
if (add.title) {
par(plt = c(0.02, 0.98, 0.02, 0.95))
} else {
par(plt = c(0.02, 0.98, 0.02, 0.98))
}
plot.window(xlim, ylim, "", asp = asp)
.filled.contour(x, y, z, levels, col)
if (missing(plot.axes)) {
if (axes) {
title(main = "", xlab = "", ylab = "")
Axis(x, side = 1)
Axis(y, side = 2)
}
} else {
plot.axes
}
if (frame.plot) {
box()
}
if (add.title) {
if (missing(plot.title)) {
title(...)
} else {
plot.title
}
}
invisible()
}
myfilled.legend <-
function(levels, color.palette = cm.colors,
col = color.palette(length(levels) - 1), plot.title, plot.axes,
key.title, key.axes, asp = NA, xaxs = "i", yaxs = "i", las = 1,
axes = TRUE, frame.plot = axes, ...) {
plot.new()
plot.window(xlim = c(0, 1), ylim = range(levels), xaxs = "i", yaxs = "i")
rect(0, levels[-length(levels)], 1, levels[-1L], col = col, border = NA)
if (!missing(key.axes)) {
key.axes
} else {
axis(4, tick = FALSE)
}
if (!missing(key.title)) {
key.title
}
}
filled.contour.points <- function(mcmcpath, longlat, plot.params, highlight) {
if (is.null(highlight)) {
return(NULL)
}
if (is.null(highlight$index)) {
message("Specify the indices of points to highlight")
return(NULL)
}
if (is.null(highlight$col)) highlight$col <- "red"
if (is.null(highlight$cex)) highlight$cex <- 1
if (is.null(highlight$pch)) highlight$pch <- 4
if (is.null(highlight$lwd)) highlight$lwd <- 2
graph <- read.graph(mcmcpath, longlat)
coord <- graph$demes[graph$ipmap, ]
index2coord <- match(highlight$index, seq_len(nrow(coord)))
index2highlight <- which(!is.na(index2coord))
index2coord <- index2coord[index2highlight]
# Check that there is at least one point to highlight
if (!length(index2highlight)) {
return(NULL)
}
coord <- coord[index2coord, ]
coord <- matrix(coord, ncol = 2)
# Transform the coordinates to a different projection if necessary
if (!is.null(plot.params$proj.out)) {
coord <- sp::SpatialPoints(coord, proj4string = CRS(plot.params$proj.in))
coord <- sp::spTransform(coord, CRSobj = CRS(plot.params$proj.out))
}
points(coord,
cex = highlight$cex[index2highlight],
col = highlight$col[index2highlight],
pch = highlight$pch[index2highlight],
lwd = highlight$lwd[index2highlight]
)
}
transform_rates <- function(dimns, tiles, rates, xseed, yseed, zero_mean) {
# Bind together the points which make up the raster image
# and the extra points provided by the user, if any
marks <- rbind(dimns$marks, dimns$coord)
coord_raster <- nrow(dimns$marks)
coord_extra <- nrow(dimns$coord)
# Compute the rates at all the points
if (zero_mean) {
rslts <- tiles2contours_standardize(
tiles, rates, cbind(xseed, yseed),
marks, dimns$dist.metric
)
} else {
rslts <- tiles2contours(
tiles, rates, cbind(xseed, yseed),
marks, dimns$dist.metric
)
}
Zvals <- matrix(rslts$zvals[seq_len(coord_raster)],
nrow = dimns$nxmrks, ncol = dimns$nymrks
)
if (coord_extra > 0) {
Zvals_extra <- rslts$zvals[seq_len(coord_extra) + coord_raster]
} else {
Zvals_extra <- NULL
}
if (zero_mean) {
# Without normalizing the migration rates m to have mean 0,
# it doesn't make sense to keep track of the number of times (m > 0) and (m < 0).
PrGT0 <- matrix(rslts$prgt0[seq_len(coord_raster)],
nrow = dimns$nxmrks, ncol = dimns$nymrks
)
PrLT0 <- matrix(rslts$prlt0[seq_len(coord_raster)],
nrow = dimns$nxmrks, ncol = dimns$nymrks
)
} else {
PrGT0 <- NULL
PrLT0 <- NULL
}
list(
Zvals = Zvals, PrGT0 = PrGT0, PrLT0 = PrLT0,
Zvals_extra = Zvals_extra, niters = length(tiles)
)
}
check.habitat.outer.is.valid <- function(mcmcpath, longlat) {
graph <- read.graph(mcmcpath, longlat)
outer <- graph$outer
# Check that the geometry of the habitat outline is both Simple (gIsSimple)
# and Closed (end points overlap).
x <- outer[, 1]
y <- outer[, 2]
l <- st_as_sfc(paste("LINESTRING(", paste(paste(x, y), collapse = ", "), ")"))
if (!st_is_ring(l)) {
message(
"Error:\n",
"The habitat geometry is not a valid ring (a ring is both simple and closed)\n",
"Let the habitat be the rectangle defined by (xmin, ymin) and (xmax, yxmax)\n",
"where xmin, xmax = range(longitude) and ymin, ymax = range(latitude)."
)
xmin <- min(outer[, 1])
xmax <- max(outer[, 1])
ymin <- min(outer[, 2])
ymax <- max(outer[, 2])
outer <- cbind(c(xmin, xmax, xmax, xmin, xmin), c(ymin, ymin, ymax, ymax, ymin))
}
outer
}
filled.contour.map <- function(mcmcpath, longlat, plot.params) {
if (!is.null(plot.params$proj.in) && plot.params$add.map) {
map <- rworldmap::getMap(resolution = "high")
map <- sp::spTransform(map, CRSobj = CRS(plot.params$proj.out))
plot(map, col = NA, border = plot.params$col.map, lwd = plot.params$lwd.map, add = TRUE)
}
}
filled.contour.outline <- function(mcmcpath, longlat, plot.params) {
outer <- check.habitat.outer.is.valid(mcmcpath, longlat)
boundary <- st_polygon(list(outer))
if (!is.null(plot.params$proj.in)) {
boundary <- st_sfc(boundary, crs = plot.params$proj.in)
boundary <- st_transform(boundary, plot.params$proj.out)
}
# The filledContour fills a rectangular plot; now color the habitat exterior white.
exterior <- st_difference(st_envelope(boundary), boundary)
if (!is.null(exterior)) {
plot(exterior, col = "white", border = "white", add = TRUE)
}
if (plot.params$add.outline) {
plot(boundary,
col = NA, border = plot.params$col.outline,
lwd = plot.params$lwd.outline, add = TRUE
)
}
}
filled.contour.graph <- function(mcmcpath, longlat, plot.params) {
graph <- read.graph(mcmcpath, longlat)
if (plot.params$add.grid) {
segments <- list()
for (e in seq_len(nrow(graph$edges))) {
segments[[e]] <- sp::Line(graph$demes[graph$edges[e, ], ])
}
segments <- sp::SpatialLines(list(Lines(segments, ID = "a")))
if (!is.null(plot.params$proj.in)) {
proj4string(segments) <- CRS(plot.params$proj.in)
segments <- sp::spTransform(segments, CRSobj = CRS(plot.params$proj.out))
}
lines(segments, col = plot.params$col.grid, lwd = plot.params$lwd.grid)
}
if (plot.params$all.demes) {
all.demes <- sp::SpatialPoints(matrix(graph$demes[graph$alpha, ],
ncol = 2
))
if (!is.null(plot.params$proj.in)) {
proj4string(all.demes) <- CRS(plot.params$proj.in)
all.demes <- sp::spTransform(all.demes, CRSobj = CRS(plot.params$proj.out))
}
points(all.demes,
col = plot.params$col.demes,
pch = plot.params$pch.demes, cex = plot.params$min.cex.demes
)
} else if (plot.params$add.demes) {
# Make sure that observed.demes is a matrix even if there is one alpha
observed.demes <- sp::SpatialPoints(matrix(graph$demes[graph$alpha, ],
ncol = 2
))
if (!is.null(plot.params$proj.in)) {
proj4string(observed.demes) <- CRS(plot.params$proj.in)
observed.demes <- sp::spTransform(observed.demes, CRSobj = CRS(plot.params$proj.out))
}
cex.points <- plot.params$min.cex.demes
if (min(graph$sizes) < max(graph$sizes)) {
cex.points <- cex.points +
(plot.params$max.cex.demes - plot.params$min.cex.demes) *
(graph$sizes - min(graph$sizes)) / (max(graph$sizes) - min(graph$sizes))
}
points(observed.demes,
col = plot.params$col.demes,
pch = plot.params$pch.demes, cex = cex.points
)
}
}
project_raster <- function(surface, proj.in, proj.out) {
raster::projection(surface) <- CRS(proj.in)
raster::projectRaster(surface, crs = CRS(proj.out))
}
points_to_raster <- function(points, dimns, params) {
surface <- raster::raster(t(points),
xmn = dimns$xlim[1], xmx = dimns$xlim[2],
ymn = dimns$ylim[1], ymx = dimns$ylim[2]
)
surface <- raster::flip(surface, direction = "y")
if (!is.null(params$proj.in)) {
surface <- project_raster(surface, params$proj.in, params$proj.out)
}
surface
}
null.eems.contour <- function(mcmcpath, longlat, plot.params,
plot.xy = NULL, highlight.samples = NULL) {
dimns <- read.dimns(mcmcpath, longlat)
eems.colors <- plot.params$eems.colors
num.levels <- length(eems.colors)
eems.levels <- seq(from = -2.5, to = +2.5, length = num.levels + 1)
main.title <- ""
key.title <- ""
Zeros <- matrix(0, nrow = dimns$nxmrks, ncol = dimns$nymrks)
myfilledContour(
points_to_raster(Zeros, dimns, plot.params),
col = eems.colors, levels = eems.levels, asp = 1,
add.key = plot.params$add.colbar,
key.axes = axis(4, tick = FALSE, hadj = 1, line = 3, cex.axis = 1.5),
key.title = mtext(key.title, side = 3, cex = 1.5, line = 1.5, font = 1),
add.title = plot.params$add.title,
plot.title = mtext(text = main.title, side = 3, line = 0, cex = 1.5),
plot.axes = {
filled.contour.outline(mcmcpath, longlat, plot.params)
filled.contour.map(mcmcpath, longlat, plot.params)
plot.xy
filled.contour.graph(mcmcpath, longlat, plot.params)
filled.contour.points(mcmcpath, longlat, plot.params, highlight.samples)
}
)
list(eems.colors = eems.colors, eems.levels = eems.levels)
}
one.eems.contour <- function(mcmcpath, dimns, Zmean, longlat, plot.params, is.mrates,
plot.xy = NULL, highlight.samples = NULL) {
eems.colors <- plot.params$eems.colors
num.levels <- length(eems.colors)
if (is.mrates) {
eems.levels <- eems.colscale(Zmean, num.levels, plot.params$m.colscale)
main.title <- "Posterior mean migration rates m (on the log10 scale)"
key.title <- "log(m)"
} else {
eems.levels <- eems.colscale(Zmean, num.levels, plot.params$q.colscale)
main.title <- "Posterior mean diversity rates q (on the log10 scale)"
key.title <- "log(q)"
}
myfilledContour(
points_to_raster(Zmean, dimns, plot.params),
col = eems.colors, levels = eems.levels, asp = 1,
add.key = plot.params$add.colbar,
key.axes = axis(4, tick = FALSE, hadj = 1, line = 3, cex.axis = 1.5),
key.title = mtext(key.title, side = 3, cex = 1.5, line = 1.5, font = 1),
add.title = plot.params$add.title,
plot.title = mtext(text = main.title, side = 3, line = 0, cex = 1.5),
plot.axes = {
filled.contour.outline(mcmcpath, longlat, plot.params)
filled.contour.map(mcmcpath, longlat, plot.params)
plot.xy
filled.contour.graph(mcmcpath, longlat, plot.params)
filled.contour.points(mcmcpath, longlat, plot.params, highlight.samples)
}
)
list(eems.colors = eems.colors, eems.levels = eems.levels)
}
one.prob.contour <- function(mcmcpath, dimns, Props, longlat, plot.params, is.mrates,
plot.xy = NULL, highlight.samples = NULL) {
Props <- (Props + 1) / 2
Props[Props < 0] <- 0
Props[Props > 1] <- 1
if (is.mrates) v <- "m" else v <- "q"
main.title <- paste0("Posterior probabilities P{log(", v, ") <> 0 | diffs}")
key.greaterthan0 <- paste0("P{log(", v, ") > 0}")
key.lessthan0 <- paste0("P{log(", v, ") < 0}")
# Probabilities are lie in the range [0, 1] but I can experiment with different ways
# to split the range [0, 1] into bins.
alpha <- plot.params$prob.levels
alpha <- alpha[alpha > 0.5 & alpha < 1]
alpha <- sort(unique(alpha))
prob.labels <- c("", as.character(rev(alpha)), as.character(alpha), "")
prob.levels <- c(0, 1 - rev(alpha), alpha, 1)
prob.colors <- default.eems.colors()
prob.colors <- colorRampPalette(prob.colors)(length(prob.levels) - 1)
myfilledContour(
points_to_raster(Props, dimns, plot.params),
col = prob.colors, levels = prob.levels, asp = 1,
add.key = plot.params$add.colbar,
key.axes = axis(4,
at = prob.levels, labels = prob.labels,
tick = FALSE, hadj = 0, line = 1, cex.axis = 1.5
),
key.title = {
mtext(key.greaterthan0, side = 3, cex = 1.5, line = 1.5, font = 1)
mtext(key.lessthan0, side = 1, cex = 1.5, line = 1.5, font = 1)
},
add.title = plot.params$add.title,
plot.title = mtext(text = main.title, side = 3, line = 0, cex = 1.5),
plot.axes = {
filled.contour.outline(mcmcpath, longlat, plot.params)
filled.contour.map(mcmcpath, longlat, plot.params)
# Including `plot.xy` has no effect because it has already been
# evaluated once to add extra points to the rates plot
plot.xy
filled.contour.graph(mcmcpath, longlat, plot.params)
filled.contour.points(mcmcpath, longlat, plot.params, highlight.samples)
}
)
list(prob.colors = prob.colors, prob.levels = prob.levels)
}
random.eems.contour <- function(mcmcpath, dimns, longlat, plot.params, is.mrates,
plot.xy = NULL, highlight.samples = NULL) {
if (is.mrates) {
message("Plotting effective migration surface (one posterior draw of m rates)")
zero_mean <- plot.params$m.zero_mean
log_scale <- plot.params$m.log_scale
} else {
message("Plotting effective diversity surface (one posterior draw of q rates)")
zero_mean <- plot.params$q.zero_mean
log_scale <- plot.params$q.log_scale
}
voronoi <- read.voronoi(mcmcpath, longlat, is.mrates, log_scale)
tiles <- voronoi$tiles
rates <- voronoi$rates
xseed <- voronoi$xseed
yseed <- voronoi$yseed
# Choose one saved posterior draw at random
niters <- length(tiles)
riter <- sample(seq_len(niters), 1)
message(mcmcpath)
message("Draw #", riter, " (out of ", niters, ")")
# Jump over stored parameters for draws 1 to (riter - 1)
skip <- sum(tiles[riter:1][-1])
now.tiles <- tiles[riter]
now.rates <- rates[(skip + 1):(skip + now.tiles)]
now.xseed <- xseed[(skip + 1):(skip + now.tiles)]
now.yseed <- yseed[(skip + 1):(skip + now.tiles)]
rslt <- transform_rates(dimns, now.tiles, now.rates, now.xseed, now.yseed, zero_mean)
Zvals <- rslt$Zvals
# Actually plot the colored contour plot
one.eems.contour(mcmcpath[1], dimns, Zvals, longlat, plot.params, is.mrates,
plot.xy = plot.xy, highlight.samples = highlight.samples
)
}
average.eems.contours <- function(mcmcpath, dimns, longlat, plot.params, is.mrates,
plot.xy = NULL, highlight.samples = NULL) {
if (is.mrates) {
message("Plotting effective migration surface (posterior mean of m rates)")
zero_mean <- plot.params$m.zero_mean
log_scale <- plot.params$m.log_scale
} else {
message("Plotting effective diversity surface (posterior mean of q rates)")
zero_mean <- plot.params$q.zero_mean
log_scale <- plot.params$q.log_scale
}
Zmean <- matrix(0, dimns$nxmrks, dimns$nymrks)
PrGT0 <- matrix(0, dimns$nxmrks, dimns$nymrks)
PrLT0 <- matrix(0, dimns$nxmrks, dimns$nymrks)
coord_extra <- nrow(dimns$coord)
Zmean_extra <- numeric(coord_extra)
niters <- 0
# Loop over each output directory in mcmcpath to average the colored contour plots
for (path in mcmcpath) {
message(path)
stopifnot(all(file.exists(file.path(path, c(
"mcmcmtiles.txt",
"mcmcmrates.txt",
"mcmcxcoord.txt",
"mcmcycoord.txt",
"mcmcqtiles.txt",
"mcmcqrates.txt",
"mcmcwcoord.txt",
"mcmczcoord.txt"
)))))
voronoi <- read.voronoi(path, longlat, is.mrates, log_scale)
tiles <- voronoi$tiles
rates <- voronoi$rates
xseed <- voronoi$xseed
yseed <- voronoi$yseed
rslt <- transform_rates(dimns, tiles, rates, xseed, yseed, zero_mean)
Zmean <- Zmean + rslt$Zvals
Zmean_extra <- Zmean_extra + rslt$Zvals_extra
niters <- niters + rslt$niters
if (zero_mean) {
PrGT0 <- PrGT0 + rslt$PrGT0
PrLT0 <- PrLT0 + rslt$PrLT0
}
}
Zmean <- Zmean / niters
PrGT0 <- PrGT0 / niters
PrLT0 <- PrLT0 / niters
Zmean_extra <- Zmean_extra / niters
# Actually plot the colored contour plot
# Pass one mcmcpath (shouldn't matter which one) in case adding extra information
# (demes, edges, etc.) on top of the contour plot.
rates.raster <- one.eems.contour(
mcmcpath[1], dimns, Zmean, longlat, plot.params, is.mrates,
plot.xy = plot.xy, highlight.samples = highlight.samples
)
xyz.values <- cbind(dimns$coord, Zmean_extra)
rates.raster$xyz.values <- xyz.values
if (zero_mean) {
raster.prob <- one.prob.contour(
mcmcpath[1], dimns, PrGT0 - PrLT0, longlat, plot.params, is.mrates,
plot.xy = plot.xy, highlight.samples = highlight.samples
)
}
rates.raster
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.