
Create a rotating 3D layout video
render_rotating_layout.RdDeprecated. Use cell_plot() and cell_plot_animate() instead.
render_rotating_layout can be used to generate a rotating 3D scatter
plot from a tibble with node layout coordinates. render_rotating_layout
offers a number of customization options, including the option to facet the
plot by additional columns in the tibble. See the sections below for more details
on how to adjust the appearance.
Usage
render_rotating_layout(
data,
file,
cell_col = NULL,
marker_col = NULL,
pt_opacity = 0.7,
pt_size = 1,
colors = RColorBrewer::brewer.pal(9, "Blues"),
max_degree = 360,
center_zero = FALSE,
scale_layout = TRUE,
frames = 500,
pad = 0.1,
show_first_frame = TRUE,
width = 500,
height = 500,
res = 150,
delay = 1/20,
ggplot_theme = NULL,
title = "",
bg = "white",
label_grid_axes = TRUE,
margin_widths = c(0.1, 0.1),
use_facet_grid = FALSE,
flip = FALSE,
graphics_use = c("base", "ggplot2"),
boomerang = FALSE,
cl = NULL,
keep_frames = FALSE,
use_illumination = FALSE,
illumination_ambient = 0.3,
illumination_sat_boost = 0.6,
illumination_shadow_colors = NULL,
normalize_illumination = TRUE,
light_direction = c(-0.6, 0.5, 0.62)
)Arguments
- data
A
data.frame-like object with columns 'x', 'y', 'z', and 'node_val'. The 'node_val' column can be either a numeric or a factor.- file
A character string specifying the path to the output file. The video format will be determined by the file extension. If the extension is '.gif', the
gifskiR package will be used to render a gif. Other file formats (such as mp4, mkv, mov, or flv) will be rendered using theavR package. Make sure to use a file format supported by eithergifskiorav.- cell_col, marker_col
A character string specifying columns to facet the plot by.
cell_colshould be a column with unique cell identifiers andmarker_colshould be a column with unique protein identifiers.- pt_opacity
A numeric value between 0 and 1 specifying the opacity of the points.
- pt_size
A numeric value indicating the maximum size of the points.
- colors
A vector of valid colors. If 'node_val' is a factor, the length of 'colors' should be equal to the number of unique levels. If 'node_val' is numeric, the colors will be used to create a gradient color scale.
- max_degree
A numeric value between 0 and 360. The maximum angle of rotation around the z axis. Default is 360, which corresponds to a full turn around the z axis.
- center_zero
A logical value indicating whether the color gradient should be centered around zero.
- scale_layout
A logical value indicating whether the layouts should be such that they all fit the same bounding box. This is typically necessary as layouts vary significantly in size.
- frames
A positive numeric value indicating the number of frames to render. More frames will result in a smoother animation but will increase the size of the output file and rendering time.
- pad
A numeric value between 0 and 1. The amount of padding to add to the axis range. Default is 0.1 which corresponds to an expansion of 10% along all three axes.
- show_first_frame
A logical value indicating whether the first frame should be displayed in the viewer before proceeding with the rendering. In interactive sessions, you will be prompted to enter 'Yes' to continue if you are satisfied with the first frame. Default is TRUE.
- width, height
An integer specifying the width and height of the video in pixels. Default is 500x500 which is suitable for a low resolution GIF file.
- res
A numeric value indicating the resolution of the png files in dpi. See
pngfor more details.- delay
A numeric value indicating the delay between frames in seconds. Default is 1/20, which corresponds to 20 frames per second. The value should be between 1/100 and 1.
- ggplot_theme
A ggplot2 theme object. Default is
NULL, which corresponds to the default plot theme.- title
A character string specifying the title of the plot.
- bg
A valid color string specifying the background color of the plot.
- label_grid_axes
A logical value indicating whether the rows and columns of the plot grid should be labeled.
- margin_widths
A numeric vector of length 2 specifying the width of the left and top margins relative to the width and height of the plot. Default is c(0.1, 0.1), meaning that the left and top margins will take up 10% of the width and height respectively.
- use_facet_grid
If set to TRUE, the plot will be faceted using
facet_grid. Note that with this option, the node colors will be mapped to a single color scale. If these selected markers have very different dynamic ranges, it might be difficult to observe trends in lowly expressed markers.- flip
A logical value indicating whether the plot should be flipped such that markers are arranged in columns and cells in rows.
- graphics_use
One of "ggplot2" or "base". The default, "base", is much faster but has fewer customization options. The "ggplot2" option comes with a number of customization options.
- boomerang
A logical value specifying whether the rotation should be reversed after reaching the maximum degree to create a "boomerang" effect. The frames are simply reversed and appended to the original frames. The resulting video will have twice as many frames as specified by the
framesargument and keep the same frame rate. Note that if the output is a gif file, it will double in size.- cl
A number of threads or a cluster object created by
makeCluster. The default isNULL, which corresponds to a single-threaded operation (sequential processing).- keep_frames
A logical value indicating whether the png files should be kept after rendering the video. This option is useful if you want to access to the individual frames later for further processing.
- use_illumination
A logical value indicating whether to modulate
node_valcolors with a heuristic illumination mask. Default isFALSE.- illumination_ambient
A numeric value between 0 and 1 specifying the minimum brightness floor when blending illumination. Default is
0.3.- illumination_sat_boost
A non-negative numeric value controlling saturation compensation in shadowed regions when using HSV blending. Ignored when
illumination_shadow_colorsis set. Increase this to increase saturation in darker points. Default is0.6.- illumination_shadow_colors
NULLor a vector of valid colors. WhenNULL(default), illumination is blended in HSV space. When set, each point's illumination is mapped to this palette instead and linearly interpolated with the basenode_valcolor.- normalize_illumination
A logical value indicating whether the illumination mask should be rescaled to
[0, 1]per cell. Default isTRUE.- light_direction
A numeric vector of length 3 in layout
(x, y, z)coordinates giving the directional light axis passed toheuristic_illumination. Internally normalized to unit length. Default isc(-0.6, 0.5, 0.62), a key light above and to the viewer's left. Usec(0, 0, 1)to light along the rotation axis. Lighting is in layout coordinates, not camera coordinates; see the illumination section.
cells and markers
The cell_col and marker_col arguments can be used to facet
the plot by additional columns in the tibble. For instance, if the tibble
contains layout coordinates for multiple cells and markers, two additional
columns should specify these groupings. In the final plot, each cell will
plotted in its own coordinate system to make sure that the layout fills
the plot area. Similarly, each marker will share the same color scale to make
sure that the colors are comparable across cells.
graphic parameters
The appearance of the plot can be customized using a number of graphics
parameters. Increasing the number of frames while decreasing the
delay will create a smoother transition but will take much longer to render.
The width and height parameters should be increased manually
to accommodate more cells and markers or to increase resolution.
The width and height parameters should be adjusted to match
the selected dpi (res). Note that when these parameters are increased,
the rendering time can increase drastically. Unfortunately, drawing ggplot
objects to the graphics device is relatively slow so the rendering might take
several minutes. Using base R graphics instead of ggplot2 can speed up the
rendering significantly, but it will limit the customization options.
Since the rendering is expensive, we might want to inspect the first frame to
make sure that the plot looks as expected. If the show_first_frame argument
is set to TRUE, which is the default, the first frame will be displayed
in the viewer before proceeding with the rendering. In interactive sessions,
you will be prompted to enter 'Yes' to continue if you are satisfied with the
first frame.
parallel processing
To speed up the rendering, the cl argument can be used to specify a
number of threads. This feature only works on unix-based systems.
This can significantly reduce the rendering time; however, it might create
artefacts in the output video. The default is NULL, which corresponds
to a single-threaded operation (sequential processing).
graphics_use
The graphics_use argument can be used to switch between the default
"base" and the "ggplot2" graphics system. The "base" option is much faster
but has fewer customization options. For instance, it is currently not possible to
get row and column labels with the "base" graphics option.
illumination
When use_illumination = TRUE, node colors are derived from node_val
and then modulated by a geometry-based illumination mask computed with
heuristic_illumination. This adds depth cues on top of the marker
color encoding. By default, shadows are blended in HSV space using
illumination_ambient as the minimum brightness floor (not the
ambient-occlusion weight in heuristic_illumination) and
illumination_sat_boost for saturation compensation in shadowed regions.
When illumination_shadow_colors is set, shadows are instead blended
toward a second color gradient mapped from the illumination mask; in that mode
illumination_sat_boost is ignored. PixelgenGradient(n, "NaturalBlue")
works well as a shadow palette while colors carries the marker signal.
Set normalize_illumination = FALSE to use raw output from
heuristic_illumination instead of rescaling the mask to [0, 1].
Directional lighting uses light_direction in layout (x, y, z)
coordinates, not camera coordinates. Frames are drawn with x across the
screen, z up the screen, and y as depth, so from the camera's point of view
+x is to the right, +z is up, and +y is toward the
viewer. The default c(-0.6, 0.5, 0.62) places the key light above and
to the viewer's left, slightly in front of the layout (roughly 38 degrees
above the horizon), which reads like afternoon sunlight rather than the flat
head-on look of a light on the camera axis.
The mask is computed once, before the points are rotated, so the key light is
fixed relative to the layout rather than the camera. With the default
direction the lit side therefore turns with the layout over a full rotation,
and the camera-facing side is brightest near the start and end of the turn
and dimmest around the halfway point. Pass light_direction = c(0, 0, 1)
to light along the rotation axis instead, which keeps the apparent shading
constant for the whole rotation.
Examples
library(dplyr)
pxl_file <- minimal_pna_pxl_file()
se <- ReadPNA_Seurat(pxl_file)
se <- se %>%
LoadCellGraphs(add_layouts = TRUE)
# Use cell_plot() and cell_plot_animate() instead
if (FALSE) { # \dontrun{
# Create a gif from a 3D layout
cg <- CellGraphs(se)[[3]]
df <- cg@layout$wpmds_3d %>%
mutate(node_val = cg@counts[, "CD3e"])
temp_gif <- fs::file_temp(ext = ".gif")
render_rotating_layout(
data = df,
file = temp_gif,
colors = c("lightgrey", "red"),
pt_size = 0.5,
max_degree = 90,
frames = 20,
delay = 1 / 5,
bg = "transparent",
label_grid_axes = FALSE,
show_first_frame = FALSE
)
magick::image_read(temp_gif)
} # }
if (FALSE) { # \dontrun{
# Include multiple facets
markers <- paste0("Marker", 1:3)
df <- lapply(1:2, function(i) {
set.seed(i)
cg <- simulate_bipartite_graph(n_nodes = 5e3, epsilon = 8) %>%
add_binary_marker_counts_pol(marker_polarize = "Marker1", epsilon = 12)
xyz <- layout_with_weighted_pmds(cg@cellgraph, dim = 3) %>%
as_tibble(.name_repair = ~ c("x", "y", "z"))
lapply(colnames(cg@counts)[1:2], function(m) {
xyz %>%
mutate(node_val = cg@counts[, m] %>% as.character()) %>%
mutate(marker = m)
}) %>%
bind_rows() %>%
mutate(cell = paste0("Cell", i))
}) %>% bind_rows()
temp_gif <- fs::file_temp(ext = ".gif")
render_rotating_layout(
data = df,
pt_size = 0.5,
width = 740,
height = 650,
cell_col = "cell",
marker_col = "marker",
colors = viridis::viridis(n = 2),
file = temp_gif,
max_degree = 90,
frames = 100,
delay = 1 / 20,
res = 150,
bg = "grey",
show_first_frame = FALSE,
cl = 9
)
magick::image_read(temp_gif)
# Use base R graphics
temp_gif <- fs::file_temp(ext = ".gif")
render_rotating_layout(
data = df,
pt_size = 0.5,
pt_opacity = 1,
width = 740,
height = 650,
cell_col = "cell",
marker_col = "marker",
colors = viridis::viridis(n = 2),
file = temp_gif,
max_degree = 360,
frames = 500,
delay = 1 / 20,
res = 150,
bg = "grey",
show_first_frame = FALSE,
graphics_use = "base",
cl = 9
)
magick::image_read(temp_gif)
} # }