knitr::opts_chunk$set( collapse = TRUE, comment = "#>", out.width = "100%", fig.path = "images/figures/" ) starttime <- Sys.time()
WebmorphR has plotting functions to make it easier to create reproducible figures from your stimuli.
library(webmorphR) library(webmorphR.stim) # for extra stimulus sets library(tidyverse) wm_opts(plot.maxwidth = 850)
stimuli <- demo_stim() plot(stimuli)
You can add a border to each image using pad
. Values less than 1 will set border width as a proportion of the image width, while values greater than or equal to 1 will set it as pixels. You can also change the border colour using fill
.
pad(stimuli, 1, fill = "hotpink")
You can set different border sizes for the top, right, bottom and left sides (think "TRouBLe"). This can be useful for creating space for labels outside the image.
stimuli |> pad(60, 0, 0, 0, fill = "black") |> label(color = "white", size = 50)
You can set the border colour separately for each image.
pad(stimuli, 10, fill = c("#F9DEC9", "#BAEDDD"))
Set nrow
or ncol
in the plot()
function to control the number of rows and columns.
comp <- load_stim_composite() |> resize(0.5) plot(comp, nrow = 2)
Set byrow = FALSE
to order the images by column instead of the default. You can control the space between images with padding
.
We'd set maxwidth
globally at the top of the script using wm_opts()
, but you can also set maxwidth
or maxheight
for a specific plot.
plot(comp, ncol = 2, byrow = FALSE, padding = 0, maxheight = 850*2)
To make a multipart figure, you usually don't want padding around the outside of a component image, so set external_pad = FALSE
. Set byrow = FALSE
to distribute images by column.
# make the centre columns ind <- comp[c(1:2,4:7,9:10)] |> plot(ncol = 2, byrow = FALSE, padding = 60, external_pad = FALSE) # add multi-ethnic composites to left and right on centre column c(comp[3], ind, comp[8]) |> resize(height = 500) |> # make sure parts are the same height plot(nrow = 1)
Use the draw_tem() function to show the delineations. By default, points are translucent green circles and lines are translucent blue.
stimuli |> draw_tem()
You can change the default colours and translucency with the line.color
, pt.color
, line.alpha
and pt.alpha
arguments. Remove the image and set the background colour with bg
.
stimuli |> resize(1000) |> draw_tem(line.color = "grey", line.size = 2, line.alpha = 0.2, pt.color = "red", pt.size = 4, bg = "grey") |> crop_tem(50)
There are two labelling functions: mlabel()
uses syntax like magick::image_annotate()
to configure labels and gglabel()
uses syntax like ggplot2::annotate()
to configure labels. They have slightly different features, but which you use will probably be determined by whether you're more familiar with magick or ggplot. The label()
function defaults to mlabel()
unless you use arguments that are only used in gglabel()
.
Label figure panels with the image name.
mlabel(stimuli)
Use the rename_stim()
function to set new names.
load_stim_composite() |> rename_stim(pattern = "f_", replacement = "Female ") |> rename_stim(pattern = "m_", replacement = "Male ") |> label() |> plot(nrow = 2)
Alternatively, set text
to a vector of labels to use. Labels can be positioned with the gravity
and location
arguments from the {magick} package. In the example below, the text is positioned at the northwest (upper-left) corner, 10 pixels to the right and 5 pixels down.
label(stimuli, text = c("Female", "Male"), gravity = "northwest", location = "+10+5", color = c("darkgreen", "darkmagenta"), size = 40, style = c("normal", "italic") )
You can customise the labels further, including vectors with a different value for each image. Vectors that are too long will be truncated and short vectors will be recycled.
directions <- c("north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest") rep(stimuli, 4) |> label( text = paste0(" ", directions, " "), gravity = directions, color = "white", boxcolor = rainbow(4), strokecolor = "black", font = "Arial", weight = 800, style = "italic", kerning = 1.2 ) |> plot(nrow = 2)
stimuli |> label(TRUE, color = "dodgerblue3", size = 40, weight = 700, gravity = "southwest", location = c("+10+100", "+10+110"), degrees = 45 )
Label figure panels with the image name.
gglabel(stimuli)
Set label
to a vector of labels to use. The default font size used by ggplot is pretty small, so increase size
. I can't help you with how to set that argument; I just use trial-and-error. Labels can be positioned with the x
and y
arguments. Unlike mlabel()
, the origin is the lower left corner, so setting the label 5 pixel below the top requires you to calculate the image height and subtract 5. However, unlike ggplot, x and y values less than or equal to 1 are interpreted as percentages. Adjust label alignment with hjust
and vjust
.
label(stimuli, label = c("Female", "Male"), size = 15, x = 10, y = height(stimuli) - 5, hjust = 0, vjust = 1, color = c("darkgreen", "darkmagenta"), fontface = c("plain", "italic") )
You can customise the labels further, including vectors with a different value for each image. Vectors that are too long will be truncated and short vectors will be recycled.
The "label" geom lets you set fill and passing for the labels.
directions <- c("north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest") rep(stimuli, 4) |> label( geom = "label", label = directions, size = 10, x = c(0.5, 1, 1, 1, 0.5, 0, 0, 0), y = c(1, 1, 0.5, 0, 0, 0, 0.5, 1), hjust = c(0.5, 1, 1, 1, 0.5, 0, 0, 0), vjust = c(1, 1, 0.5, 0, 0, 0, 0.5, 1), color = "white", fill = rainbow(4), family = "Arial", fontface = "bold.italic", label.padding = unit(3, "mm"), label.r = unit(0.5, "lines"), # round corners label.size = unit(1, "lines") # label border ) |> plot(nrow = 2)
You can set alpha
and angle
to create watermarked images.
stimuli |> label( label = "watermark", x = 0.5, y = 0.5, geom = "text", size = 20, color = "black", fontface = "bold", angle = -30, alpha = 0.25 )
While the gglabel()
function is mainly meant for "text" and "label" geoms, you can use it for other ggplot geoms.
# get eye points and calculate mean x and y coordinates for each image intercepts <- get_point(stimuli, 0:1) |> group_by(image) |> summarise(x = mean(x), y = mean(y), .groups = "drop") |> # face coordinate y-axis is opposite to ggplot y-axis mutate(y = height(stimuli) - y)
stimuli |> label( geom = "rect", xmin = 0, xmax = intercepts$x, ymin = 0, ymax = intercepts$y, fill = "grey" ) |> label( geom = "vline", xintercept = intercepts$x, color = "red", size = 2 ) |> label( geom = "hline", yintercept = intercepts$y, color = "purple", size = 2 )
elapsed <- (Sys.time() - starttime) |> as.numeric(units="mins") |> round(1)
This script took r elapsed
minutes to render all the included images from scratch.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.