Skip to content

Instantly share code, notes, and snippets.

@slowkow
Last active June 30, 2023 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slowkow/a9907d8fdc2e85ce539ca4015983b893 to your computer and use it in GitHub Desktop.
Save slowkow/a9907d8fdc2e85ce539ca4015983b893 to your computer and use it in GitHub Desktop.
Make an animation to visualize millions of points in 3 dimensions.
library(data.table)
library(glue)
library(rgl)
# https://github.com/google/palette.js/blob/master/palette.js
mpn65 <- c(
'#ff0029', '#377eb8', '#66a61e', '#984ea3', '#00d2d5', '#ff7f00', '#af8d00',
'#7f80cd', '#b3e900', '#c42e60', '#a65628', '#f781bf', '#8dd3c7', '#bebada',
'#fb8072', '#80b1d3', '#fdb462', '#fccde5', '#bc80bd', '#ffed6f', '#c4eaff',
'#cf8c00', '#1b9e77', '#d95f02', '#e7298a', '#e6ab02', '#a6761d', '#0097ff',
'#00d067', '#000000', '#252525', '#525252', '#737373', '#969696', '#bdbdbd',
'#f43600', '#4ba93b', '#5779bb', '#927acc', '#97ee3f', '#bf3947', '#9f5b00',
'#f48758', '#8caed6', '#f2b94f', '#eff26e', '#e43872', '#d9b100', '#9d7a00',
'#698cff', '#d9d9d9', '#00d27e', '#d06800', '#009f82', '#c49200', '#cbe8ff',
'#fecddf', '#c27eb6', '#8cd2ce', '#c4b8d9', '#f883b0', '#a49100', '#f48800',
'#27d0df', '#a04a9b'
)
# 4 columns: X, Y, Z, color
coords <- fread("coords.tsv.gz")
# Thanks to Bryan Hanson for this post:
# https://stackoverflow.com/a/14479967/330558
rgl.open()
# background color
rgl.bg(color = "white")
rgl.points(
x = coords[,1],
y = coords[,2],
z = coords[,3],
col = mpn65[coords$color]
)
my_height <- 900
my_width <- my_height * 1.618
par3d(windowRect = c(0, 0, my_width, my_height)) # make the window large
par3d(zoom = 0.6) # larger values make the image smaller
# you can test your settings interactively at this point
my_params <- par3d("userMatrix") # save your settings to pass to the movie
dir.create("frames", showWarnings = FALSE)
movie3d(
par3dinterp(
time = (0:2)*5,
userMatrix = list(
my_params,
# rotate3d(my_params, pi / 4, 0, 1, 0),
rotate3d(my_params, pi, 0, 1, 0),
rotate3d(my_params, -2 * pi, 0, 1, 0)
),
method = "linear",
extrapolate = "constant"
),
duration = 10,
fps = 30,
movie = "frame",
convert = FALSE,
clean = FALSE,
dir = "frames"
)
rgl.close()
cmd <- glue(
"ffmpeg -y -framerate 30 -i frames/frame%03d.png -pix_fmt yuv420p movie.mp4"
)
system(cmd) # convert the .png files to a .mp4 file
system("rm -rf frames") # we don't need the .png files anymore
@slowkow
Copy link
Author

slowkow commented Aug 22, 2022

Below is an example of the output produced by this R script.

800k_cells.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment