# functions for creating logos etc.
# get the coordinates and links to tile the logo 'repeats' times.
# x_start and y_start give the position of the first node
logo_shape <- function(x_start = 0, y_range = c(0, 1)) {
# coordinates and links of the base shape
coords <- data.frame(
x = c(0, 0, 1, 1, 2, 2, 3),
y = c(0, 1, 0.5, 1.5, 0, 1, 0.5)
)
links <- rbind(c(1, 3), c(2, 3), c(3, 6), c(4, 6), c(5, 7), c(6, 7))
scale <- abs(diff(y_range)) / 1.6
coords$x <- coords$x * scale + x_start
coords$y <- coords$y * scale + y_range[1]
list(coords = coords, links = links)
}
plot_logo <- function(
background = c('white', 'purple', 'light', 'lighter'),
pointsize = 4.5,
add = FALSE,
edge_width = 1,
...
) {
background <- match.arg(background)
data <- logo_shape(...)
bg_col <- switch(
background,
white = 'white',
light = greta:::greta_col('light'),
lighter = greta:::greta_col('lighter'),
purple = greta:::greta_col('main')
)
link_col <- switch(
background,
white = greta:::greta_col('light'),
light = greta:::greta_col('dark'),
lighter = greta:::greta_col('dark'),
purple = greta:::greta_col('dark')
)
node_col <- switch(
background,
white = greta:::greta_col('dark'),
light = greta:::greta_col('dark'),
lighter = greta:::greta_col('dark'),
purple = greta:::greta_col('dark')
)
if (!add) {
old_mar <- par()$mar
old_xpd <- par()$xpd
old_bg <- par()$bg
on.exit(par(mar = old_mar, xpd = old_xpd, bg = old_bg))
par(mar = rep(2, 4), xpd = NA, bg = bg_col)
plot.new()
plot.window(
xlim = range(data$coords$x),
ylim = range(data$coords$y),
asp = 1
)
}
# loop though from right to left, plotting points and edges to ensure
# gaps on either side distances
x_loc <- sort(unique(data$coords$x), decreasing = TRUE)
for (loc in x_loc) {
# find relevant nodes and edges
idx_nodes <- which(data$coords$x %in% loc)
idx_edges <- which(data$links[, 2] %in% idx_nodes)
nodes <- data$coords[idx_nodes, , drop = FALSE]
edges <- data$links[idx_edges, , drop = FALSE]
# plot nodes with fat edge
points(
y ~ x,
data = nodes,
pch = 21,
bg = node_col,
col = bg_col,
cex = pointsize - 1.5,
lwd = pointsize * 4 * edge_width
)
# plot lines
for (i in seq_len(nrow(edges))) {
link <- edges[i, ]
lines(
x = data$coords$x[link],
y = data$coords$y[link],
lwd = pointsize * 2.3 * edge_width,
col = link_col
)
}
# plot nodes with thin edge
points(
y ~ x,
data = nodes,
pch = 21,
bg = node_col,
col = bg_col,
cex = pointsize - 1.5,
lwd = 0
)
}
}
# greta logo generation
# Muli fontface from: https://fonts.google.com/specimen/Muli
# plot a purple banner, with greta in white
# 'width' gives the width:height ratio
# 'margin' gives the proportion of the vertical height to use a border on each side
# the text is scaled to never exceed that border
#' @importFrom graphics par plot.new plot.window strheight strwidth text
banner <- function(
background = c('purple', 'white', 'light', 'lighter'),
transparent_bg = FALSE,
width = 8,
margin = 0.2,
font = c('Muli', 'sans'),
add_logo = TRUE,
...
) {
font <- match.arg(font)
background <- match.arg(background)
# warn if the banner isn't height-filled
min_width <- 3.184175 + 2 * margin * (1 - 3.184175)
if (width < min_width) {
warning(
'with a margin of ',
margin,
' the minimum width to ensure the banner is height-filled is ',
min_width
)
}
bg_col <- switch(
background,
white = 'white',
light = greta:::greta_col('light'),
lighter = greta:::greta_col('lighter'),
purple = greta:::greta_col('main')
)
text_col <- switch(
background,
white = greta:::greta_col('dark'),
light = 'white',
lighter = greta:::greta_col('dark'),
purple = 'white'
)
# cache the old graphics options
old_bg <- par('bg')
old_mar <- par('mar')
old_family <- par('family')
# switch to a purple background, no margins and Muli typeface
par(bg = ifelse(transparent_bg, NA, bg_col), mar = rep(0, 4), family = font)
# set up the device, to have the correct width
plot.new()
plot.window(xlim = c(0, width), ylim = c(0, 1), asp = 1)
# scale the font, so that 'greta' fills the area (excluding self-imposed
# margins) either vertically or horizontally
max_height <- (1 - 2 * margin) / strheight('greta')
max_width <- (width - 2 * margin) / strwidth('greta')
fontsize <- min(max_height, max_width)
# find the final string dimensions
string_height <- fontsize * strheight('greta')
string_width <- fontsize * strwidth('greta')
# how far to indent 'greta'
xpos <- margin
# 'g' should be aligned to the left of the box
text(
x = xpos,
y = 0.5,
label = 'greta',
col = text_col,
cex = fontsize,
pos = 4,
offset = 0
)
if (add_logo) {
plot_logo(
background = background,
add = TRUE,
x_start = string_width + xpos * 3,
y_range = 0.55 + string_height * 0.5 * c(-1, 1),
...
)
}
par(bg = old_bg, mar = old_mar, family = old_family)
invisible(NULL)
}
# same dimensions as banner, but with no text
blank_banner <- function(width = 8, margin = 0.2) {
# cache the old graphics options
old_bg <- par('bg')
old_mar <- par('mar')
# switch to a purple background with no margins
par(bg = greta:::greta_col(), mar = rep(0, 4))
# set up the device, to have the correct width
plot.new()
plot.window(xlim = c(0, width), ylim = c(0, 1), asp = 1)
par(bg = old_bg, mar = old_mar)
invisible(NULL)
}
# make and save an image of a triangular tesselation GMRF pattern in greta purple
tesselation_image <- function(
ncol = 10,
nrow = 10,
max_edge = 0.08,
jitter = 0.1,
thickness = 1,
line_col = greta:::greta_col('light'),
ramp_cols = NULL
) {
if (is.null(ramp_cols)) {
cols <- c(greta:::greta_col('lighter'), greta:::greta_col('light'))
ramp_cols <- colorRampPalette(cols)(2000)[-(1:1000)]
}
require(INLA)
require(raster)
require(greta)
require(fields)
# grid sizes for sampling the GRF and for the final image
ncol_sim <- round(ncol / 10)
nrow_sim <- round(nrow / 10)
ratio <- ncol / nrow
grid <- list(
x = seq(0, 1, length.out = ncol_sim),
y = seq(0, 1, length.out = nrow_sim)
)
obj <- Exp.image.cov(grid = grid, theta = 0.1, setup = TRUE)
r <- raster(sim.rf(obj))
image <- raster(nrow = nrow, ncol = ncol)
extent(image) <- c(0, ratio, 0, 1)
extent(r) <- extent(image)
pts <- expand.grid(seq(0, ratio, length.out = 10), seq(0, 1, length.out = 10))
pts <- pts + cbind(rnorm(100, 0, jitter), rnorm(100, 0, jitter))
# make an inla mesh
sp <- as(extent(image), 'SpatialPolygons')
mesh <- inla.mesh.2d(
loc = pts,
boundary = inla.sp2segment(sp),
max.edge = max_edge,
offset = 0
)
# sample GRF at nodes
z <- extract(r, mesh$loc[, 1:2])
# get projection to raster
image_coords <- xyFromCell(image, 1:ncell(image))
A <- inla.spde.make.A(mesh, loc = image_coords)
# instead of linear interpolation, average the three node values
A2 <- A
A2@x[A2@x > 0] <- 1 / 3
image[] <- (A2 %*% z)[, 1]
pm <- par("mar")
on.exit(par(mar = pm))
par(mar = rep(0, 4))
image(image, col = ramp_cols, asp = 1, axes = FALSE, xlab = '', ylab = '')
plot(
mesh,
add = TRUE,
edge.color = line_col,
lwd = thickness,
draw.segments = FALSE
)
points(mesh$loc, pch = 16, cex = 0.5 * sqrt(thickness), col = line_col)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.