The Ascent video was created using a custom animation system that I wrote for the video. It's about 5,400 lines of Perl.
Having my own solution to animating the 5-dimensional scene gave me complete control (that could be automated) over every frame. If I wanted to add something (e.g. at some point Max wanted to see gradients mapped onto cube surfaces), I could “just” add it.
Having my own solution also meant a lot more fiddling and debugging, as I was caught up in my own high-dimensional loop of fixing and breaking the code.
I'm also not an animator — I have no familiarity with animation tools. I'm only vaguely aware of After Effects.
It was possible for me to code the animation system because the underlying math is relatively straightforward. The cubes are just a list of `n`-vectors that form their vertices and rotations are just matrix products applied to the vector.
The projection of the high-dimensional objects onto the 2-dimensional canvas was done in the simplest way possible — an orthographic projection, in which we keep the `x` and `y` components of a vector and throw out all others (no matter how many).
Adding more dimensions to the scene only requires that you add one more component to the vector and grow the rotation matrix by a row and column. It's as easy to animate a 3-dimensional scene as a 5-dimensional (or higher) scene.
A lot of the funky effects that you see in the video are achieved by the difference blend (logical NAND). The individual compoents (e.g. edges, faces) of the cubes are drawn one at a time and, because of the NAND blending, we never saturate the canvas.
The system works in a very simple way, even though its output can appear quite complicated (thanks difference blend!).
The entire animation is based on a set of `n`-dimensional cubes. For the final version of the video `n = 5`.
The scene is composed of one or more cubes. The cube is composed of (a) vertices (e.g. 32 vertices in 5-dimensional space) and (b) list of area maps to be projected onto one (or more) of its faces.
Cubes are also associated with parameters that determine how the cube is drawn. First, we define whether to draw the cube edges and/or faces. For example, at the start of the video the first cube has its edges drawn but not faces. Later, new cubes are added whose faces are drawn but not edges.
Second, each cube has a size parameter associated for each dimension. This allows me to shrink (or suppress) the cube along some dimensions. So, a 5-dimensional cube can be drawn as a square by setting the size of `z`, `w` and `v` dimensions to zero.
Third, a cubes edges (and faces) have themselves a parameter that determines how much of the edge (or face) to draw. This is independent of the cube's size along a given dimension. For example, I can choose to draw only 50% of the edge, which can be done by starting at the vertices (gap in the middle of the edge) or at the middle of the edge (gap at the vertices). For faces, this works the same way — a face can be drawn partially as a (growing or shrinking) square in the middle of a cube face or as four squares tucked up against the vertices.
This basic functionality is relatively easy to program. For each cube in the scene, you (a) iterate across its edges and faces, (b) determine their coordinates in 5-dimensional space by applying the scene's angles (both the camera and cube can rotate independently) as well as the size of the dimension, (c) determine how much of the element to draw based on the edge length (or the analogous parameter for faces) and then (b) draw it as a line (for edges) or filled polygon (faces) using the `(x,y)` coordinates of the element (orthographic projection).
Whereas the geometry is relatively straightfoward, by far the trickiest part of the system is how to define the scene and manage changes over time.
Some of the things that the system should know how to do (over time) is (a) zoom and rotate the camera (there are 10 independent axes of rotation in a 5-dimensional space), (b) add and remove cubes from the scene, (c) shrink and grow a cube, (d) shrink and grow edges and face fills, (e) add and remove area map projections to any set of faces of a cube and (f) shrink and grow area maps.
Finally, the system should be able to apply randomness to any of these parameters. This helps add variation to the animation. For example, I really don't want to have to define the angles of each keyframe manually — it's easier to initialize the angle and then apply a random drift to it over time.
To make the keyframe definitions more modular, I define various parameters that can be reused.
Parameters define either relative or absolute values. The difference between these is that relative values are used as scaling factors and absolute values are additive.
For example, if we define
param = var1 r0.965
and later use the command (see below for command syntax)
cube c0 size [x] var1
then the size of cube c0 along the `x` dimension will be multiplied by 0.965.
However, if we define
param = var1 d0.1
then the size of the cube will be increased by 0.1. Here d
stands for “delta”.
A great deal of what you see in the animation is randomly generated — in particular, the rotation angles. Nobody wants to manually manage the values of each of the 10 possible independent angles of rotation.
For example, the following parameter definition and command rotates the scene by angle `0.1 \times 2 \pi`.
param = var1 d0.1 # values of angles are in units of 2π angle xy var1
But if we define
param = var1 d0.1,0.2
then the value of the parameter will be sampled randomly (and uniformly) from the interval `[0.1,0.2]` each time it's used.
Rotations can be defined about one or more planes of rotation. For example, we can rotate by a given angle about the `xy` plane or about the `xy` and `yz` planes. The latter corresponds to composition of rotations achieved by mutiplying the rotation matrices.
However, given an angle of rotation, the scene will appear to rotate faster (there will be more motion) the more rotations we compose together. For this reason, parameter definitions (used only for angles) can include an n
to indicate that the value will be divided by the number of axes we're rotating around.
param = var1 dn0.020,0.040 frame = 1.a ; ... ; cube c1 angle [x][yz] var1 frame = 1.a ; ... ; cube c1 angle [xy][yzw] var1
will rotate cube c1 by a random value sampled from the interval [0.02,0.04], divided by the number of planes of rotation.
For frame 4.d, the planes of rotation are defined as [x][yz]
, which corresponds rotations about `xy` and `xz` (we make all pairs of dimensions from the two sets of brackets). Thus, in this case we have two axes of rotation so we would divide var1
by 2.
In the next keyframe we rotate about `xy`, `xz`, `xw`, `yz` and `yw`. We have 5 axes of rotation so we would divide var1
by 5.
A parameter value can be used to store a set of commands. For example,
param = rotxyz a [x][wv] var1 _ a [y][wv] var2
rotates about `xw` and `wv` by an amount var1
and about `yw` and `yv` by an amount var2
. This is convenient when you want to bundle up multiple rotations in a single definition.
frame = 1.a ; ... ; rotxyz
Here, var1
and var1
may be randomly sampled and normalized, as described above.
Parameters can also define a function, which helps shorten the syntax of keyframe definitions.
For example, the above could have been a function
param = rotxyz(v1,v2) a [x][wv] v1 _ a [y][wv] v2
which would be called
frame = 1.a ; ... ; rotxyz(var1,var2)
As another example, to add a cube with size 1 and edge length 0.5 to the scene, the syntax is
cube c1 + cube c1 size . 1 cube c1 fade . 0.5
This is pretty tedious. So we can define a function
param = cube_add(cn,sv,fv) cube cn + _ cube cn size . sv _ cube cn fade . fv
which will achieve the same thing if we call it as
frame = 1.a ; ... ; cube_add(c1,1,0.5)
These macros can be combined. The following will add the cube and rotate the scene. Notice how var2
defines an angle that is, on average, twice the size of var1
. This lets us rotate about one set of axes slowly and around another set more quickly.
param = var1 dn0.020,0.040 param = var2 dn0.040,0.080 frame = 1.a ; ... ; cube_add(c1,1,0.5) ; rotxyz(var1,var2)
Keyframes are defined by one or more commands.
################################################################ # global zoom dimensions size . 1.2 # apply to all dimensions size [xy] 1.2 # apply only to x,y ################################################################ # scene angle (all angles in units of 2π) angle xy 0.1 # rotate about xy by 0.1 angle [x][yz] 0.1 # rotate about xy and xz planes by 0.1 angle . 0.1 # rotate about all planes by 0.1 ################################################################ # add a cube cube c1 + # add cube named c1 ################################################################ # cube angle angle c1 xy 0.1 # rotate cube c1 about xy by 0.1 angle c1 [x][yz] 0.1 # rotate cube c1 about xy and xz by 0.1 angle c1 . 0.1 # rotate cube c1 about all planes by 0.1 ################################################################ # cube size cube c1 size x 0.1 # set size of x dimension of cube c1 to 0.1 cube c1 size [xy] 0.1 # set size of x and y dimensions of cube c1 to 0.1 cube c1 size . 0.1 # set size of all dimensions of cube c1 to 0.1 ################################################################ # cube edge fade # analogous to cube size, but now we define how much of the edge to hide cube c1 fade x 0.1 cube c1 fade [xy] 0.1 cube c1 fade . 0.1 ################################################################ # add an area map to a cube face # map 22a is added to xy plane for z = 0 face c1 xy0 map 22a + # map 22a is added to all faces face c1 . map 22a + ################################################################ # fade and zoom an area map face c1 xy0 map 22a fade 0.5 face c1 xy0 map 22a zoom 0.5
Most commands use a kind of regular expresion to narrow down their targets. For example,
# apply to cube c1 plane xy angle c1 xy 0.1 # apply to cube c1,c2,c3 plane xy angle c[1-3] xy 0.1 # apply to cube c1,c2,c3 and any plane angle c[1-3] . 0.1 # apply to any cube and any plane angle . . 0.1
Thus the last command would rotate all cubes on the scene about each plane by 0.1.
Keyframes are composed of one or more commands and the number of frames over which the parameters changed by the commands are interpolated (see below).
For example, the keyframe
frame = 1.a1 ; angle . 0
will set all angles of the scene to 0.
Frames are interpolated between keyframes to smoothly vary parameter changes that the keyframes define. The argument to n
defines how many frames to interpolate between these two keyframes.
For example, in this pair of keyframes we first set all angles of the scene to zero. In the second keyframe we add 0.1 to the angle about the `xy` plane and interpolate this change over 2fs
frames.
frame = 1.a1 ; angle . 0 frame = 1.a2 ; n 2fs ; angle xy d0.1
By default, fs = 24
, which is the number of frames per second. Thus, we have a 2 second rotation of 0.1 about the plane `xy`.
Here is a slightly more complex example
frame = 1.a1 ; angle . 0 # 2 second rotation about xy by 0.1 frame = 1.a2 ; n 2fs ; angle xy d0.1 # 2 second rotation about xy by 0.2 (faster rotation) frame = 1.a3 ; n 2fs ; angle xy d0.2 # 2 second rotation about xy by 0.2 (faster rotation) and by yz by 0.1 frame = 1.a4 ; n 2fs ; angle xy d0.2 ; angle yz d0.1
Keyframes can be repeated.
frame = 1.a4 ; n 2fs ; angle xy d0.2 ; angle yz d0.1 frame = 1.a5 ; n 2fs ; angle xy d0.2 ; angle yz d0.1
can be shortened to
frame = 1.a4 ; n 2fs ; angle xy d0.2 ; angle yz d0.1; rep 2
The purpose of the rep
command is to make the keyframe definitions more modular. For example, the above could have been written as
frame = 1.a4 ; n 4fs ; angle xy d0.4 ; angle yz d0.2;
where we interpolate over twice as many frames 4fs
and rotate about angles that are twice as large. However, over time course of defining scenes I discovered that it was very helpful to keep changes defined in keyframes incremental.
If you've gotten this far, then you're in a good place to understand how each of the keyframes in the Ascent video is defined. Here, I walk you through some of the early keyframes.
Here, I've added the parameter definitions before the keyframe that uses them. Normally, they're stored in a separate file.
# define a scene marker to which we can jump or stop at frame = 1: # add cube c0 param = fs 24 param = cube_add(cn,sv,fv) cube cn + _ cube cn size . sv _ cube cn fade . fv frame = 1.a; cube_add(c0,0,1) # arrange yw rotation for the split at 1.c* param = astepa2 d-0.048978 frame = 1.a0; a yw astepa2 # grow horizontal line frame = 1.a1; n 2fs; c c0 f [xy] 0 frame = 1.a2; n 2fs; c c0 s [x] 0.05 frame = 1.a3; n 2fs; c c0 s [x] 0.10 frame = 1.a4; n 2fs; c c0 s [x] 0.15 # grow y and rotate param = astepb3 d-0.041667 param = rxy3 a xy astepb3 frame = 1.a5; n 3fs; c c0 s [y] 0.05 ; rxy3 frame = 1.a6; n 3fs; c c0 s [y] 0.10 ; rxy3 frame = 1.a7; n 2fs; c c0 s [y] 0.15 ; rxy3 # grow z param = astepa6 d-0.016326 param = ryz6 a yz astepa6 frame = 1.b1; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.100 ; c c0 f [z] 0.80 ; ryz6 frame = 1.b2; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.110 ; c c0 f [z] 0.60 ; ryz6 frame = 1.b3; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.120 ; c c0 f [z] 0.40 ; ryz6 frame = 1.b4; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.130 ; c c0 f [z] 0.20 ; ryz6 frame = 1.b5; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.140 ; c c0 f [z] 0.10 ; ryz6 frame = 1.b6; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.150 ; c c0 f [z] 0.00 ; ryz6 # split cubes along w (needs yw angle set, see above) frame = 1.c1; n 1fs; c c0 s [xyz] 0.15 ; c c0 s [w] 0.815 # a pause frame = 1.c2; n 2fs;
Here are all the configuration files for the animation system. Each file has a hierarchy of blocks that define groups of parameters.
Typically, parameters in sub-blocks overwrite those in their parent blocks.
This is the top-level configuration for the animation.
Configuration files are imported via the include
directive.
# Debug groups, one or more # cube, eval, basis, angle, timer, step, schedule, size, map, key, param, progress, out, child, param, color, tween, render debug = cube,edge,basis,eval,timer,schedule,t,size,param,progress,out,param,tween scene_name = ascent-acropolis-1 #hdhalf = yes seed = 1 nproc = 100 haldnproc = 100 fps = 24 #wide = 3 lookup_tol = 0.001 lookup_make = yes cache_dir = /tmp/cube frame_dir = /tmp/cube hald_dir = ../hald map_dir = cache/maps clear_cache = no clear_frames = no aa = no # All angles in units of 2pi <angle> b = 0.125 # 0.78539816339 # pi/4 b2 = 0.0625 # 0.392699 # b/2 b4 = 0.03125 # 0.392699 # b/4 a = 0.097956 # 0.615479708670387 # Math::Trig::asin( Math::Trig::tan(pi/6) ) a2 = 0.048978 # 0.3077395 # a/2 a4 = 0.024489 # 0.3077395 # a/4 </angle> # Other useful angles param beta 0.125 param beta2 beta/2 param beta4 beta/4 param beta6 beta/6 param beta8 beta/8 param alpha 0.097956 param alpha2 alpha/2 param alpha4 alpha/4 param alpha6 alpha/6 param alpha8 alpha/8 param gamma 0.152043362 param gamma2 0.076021681 # angle bookmarks param refxy 135/360 # 147/360 #pi/180 ?135 param refxz 135/360 # 129/360 #pi/180 param refxw 270/360 # 259/360 #pi/180 param refxv 270/360 # 269/360 #pi/180 param refyz 180/360 # 192/360 # param refyw 180/360 # 210/360 #pi/180 param refyv 180/360 # 267/360 #pi/180 # elements to draw cube_edge = yes face_map = yes face_label = yes map_line = yes map_fill = yes z_tone = no z_tone_edge = no dim_color = yes xmult = 1 ymult = 1 ################################################################ # Break points # # 0 after scene init # 1 after keyframe # 2 after frame # 3 after memory size report # 4 after tween # ################################################################ # GLOBALS # Define dimensions ndim N # Inactive -COMMAND ... # -size 1 # -a 02 10 # Size dimensions size 1,1,1,1 # size . 1 # size 1 1 # size x 1 # size [12] 1 # size [xy] 1 # size [1-3] 1 # Global angle a 02 0.5 # a xz 0.5 # a [xy]z 0.5 # CUBES # # add a cube cube NAME + # # Cube angle a CUBE xz VALUE CUBE = RX (eg: . = all) # _ current # # Face f xy COMMAND all xy # f xy0 COMMAND xy z=0 # f xy1 COMMAND xy z=1 # f xy.1 COMMAND xy z=ANY w=1 # f xyz COMMAND all pairs from xyz # f xy1. COMMAND all xy z=1 w=ANY # f x COMMAND any with x # f x.1. COMMAND any with x z=1 # f x.10 COMMAND any with x z=1 w=0 (same as xy10) # f . COMMAND any face # Blends # diff creates dark intersections # add creates light intersections # lighten like add, but more subtle # multiply high contrast; needs white background, nice with opacity 0.5 # darken more subtle multiply # hue fun # # Some m/n Pi approximations # 19 6 3.166666666667 0.007981306249 improved # 22 7 3.142857142857 0.000402499435 improved # 179 57 3.140350877193 0.000395269704 improved # 201 64 3.140625000000 0.000308013704 improved # 223 71 3.140845070423 0.000237963113 improved # 245 78 3.141025641026 0.000180485705 improved # 267 85 3.141176470588 0.000132475164 improved # 289 92 3.141304347826 0.000091770575 improved # 311 99 3.141414141414 0.000056822190 improved # 333 106 3.141509433962 0.000026489630 improved # 355 113 3.141592920354 0.000000084914 improved # Layer # # cube:targetlayer:combine:opacity:color:ztone:thickness level = 3 # Variations of final video <<include acropolis/scene.ascent.conf>> # Scenes for testing <<include liverpool/scene.ascent.conf>> <<include scene.310.conf>> # 310 <<include scene.306.conf>> # 306 <<include scene.305.conf>> # 305 <<include scene.304.conf>> # 304 <<include scene.302.conf>> # 302 303 <<include scene.301.conf>> # 301 <<include scene.300.conf>> # 300 <<include scene.205.conf>> # 205 <<include scene.204.conf>> # 204 <<include scene.203.conf>> # 203 <<include scene.202.conf>> # 202 <<include scene.201.conf>> # 201 <<include scene.200.conf>> # 200 <<include scene.105.conf>> # 105 106 107 <<include scene.101.conf>> # 101 102 103 104 <<include scene.100.conf>> # 100 <<include scene.004.conf>> # 004 <<include scene.003.conf>> # 003 <<include scene.002.conf>> # 002 <<include scene.001.conf>> # 001 <<include scene.000.conf>> # 000 # Description of audio effects at specific frames # For debugging - they do not influence the animation. <schedule> 0 strt 1296 chng 1992 upmd 2184 bass 2592 dist 3840 chrd 5328 dyad 6672 peak 7392 outr 7800 dc 7944 fd 8568 end </scedule> # Times of musical accents in the video. # For debugging - they do not influence the animation. <accents> 0:16 * 0:28 * 0:34 * 0:43 * 1:07 * 1:13 * 1:22 * 1:30 * 1:36 * 1:57 * 1:59 * 2:06 * 2:16 * 2:22 * 2:27 * 2:47 * 2:56 * 3:14 * 3:23 * 3:34 * 3:52 * 4:03 * 4:10 * 4:16 * 4:22 * 4:32 * 5:26 * 5:28 * </accents> # Size of the rendered frame <canvas> width = 1920 height = 1080 scale = 0.5 </canvas> # Some colors <color> 0 = fg 1 = fg 2 = fg 3 = 255,0,0 4 = 0,255,0 5 = 0,0,255 6 = 255,0,255 7 = 0,255,255 8 = 255,255,0 bg = 0,0,0 lbg = 128,128,128 vlbg = 200,200,200 vvlbg = 225,225,225 fg = 255,255,255 orange = 251,176,59 blue = 41,171,226 dblue = 0,113,188 green = 140,198,63 dgreen = 0,146,69 red = 193,39,45 purple = 102,45,145 magenta= 237,30,121 eblue = 30,58,245 egreen = 127,249,107 epurple = 76,39,245 emagenta= magenta # If using 10 dims #d0 = 237,32,121 #d1 = 237,62,54 #d2 = 247,99,33 #d3 = 255,183,59 #d4 = 245,236,43 #d5 = 141,197,58 #d6 = 55,179,71 #d7 = 0,171,238 #d8 = 40,56,145 #d9 = 146,39,139 # If using 5 dims d0 = 237,32,121 #d1 = 237,62,54 d1 = 247,99,33 #d3 = 255,183,59 d2 = 245,236,43 #d5 = 141,197,58 d3 = 55,179,71 #d7 = 0,171,238 d4 = 40,56,145 #d9 = 146,39,139 #d2 = orange #d3 = red #d5 = blue #d9 = green </color> # For larger number of dimensions, PDL is faster # e.g. ndim=8, 1 frames per dim : PDL (8 sec), Math::Matrix (23 sec) use_pdl = no # Use precompiled rotation functions from rotate.pm (see bin/make_rotate_package) # For ndim > 8, PDL is faster use_fast_rot = no number = pi number_file = num/conf(number).5000.txt divide_ratio = 1
Parameters and functions used in the keyframe definitions.
# Not all these parameters are used - many are left over # from past versions. param = zremap -1 1 0 1 1 param = xmult 1; ymult 1 # Ways in which we shrink edges and faces. For example, edge fade # is set to 'shrinkcorners' meaning that when edges are drawn only # partially, there will a gap in the middle of the edge # shrinkmid | shrinkstart | shrinkend | shrinkcorners | hide | ignore param = mapedgefade shrinkmidrand param = mapfillfade shrinkmidrand param = edgefade shrinkcorners param = fillfade shrinkcorners param = facefillsort dimdesc # area | dim | faceidx # Randomly sampled angle rotation rates. # d - the value is an absolute amount to be added # n - the value is normalized by the number of axes we're rotating on # x,y - the value is sampled uniformly from [x,y] param = astep-vvslow dn0.001,0.002 param = astep-vslow dn0.002,0.005 param = astep-slow dn0.005,0.010 param = astep-med dn0.010,0.020 param = astep-fast dn0.020,0.040 param = astep-vfast dn0.040,0.060 param = astep-vvfast dn0.060,0.080 param = astep-vvvfast dn0.080,0.100 param = astep2-vvslow dn0.00125,0.0025 param = astep2-vslow dn0.00250,0.0060 param = astep2-slow dn0.00600,0.0125 param = astep2-med dn0.01250,0.0240 param = astep2-fast dn0.024,0.050 param = astep2-vfast dn0.050,0.070 param = astep2-vvfast dn0.070,0.090 param = astep2-vvvfast dn0.090,0.110 # Fixed values for rotation param = astepa d-alpha param = astepb d-beta param = astepa2 d-0.048978 param = astepb2 d-0.0625 param = astepa3 d-0.032652 param = astepb3 d-0.041667 param = astepa4 d-0.024489 param = astepb4 d-0.03125 param = astepa6 d-0.016326 # Various absolute (d) and relative (r) values used in sizing param = s3s d0.025 param = s3f d0.10 param = s4f d0.30 param = s4u d0.10 param = p1 r0.965 param = p2 d0.05 param = s5f d0.009 param = s5cf r0.96 param = s5cs r0.98 param = ps20 d0.05 param = ps21 d-0.025 # Specific plane rotations # e.g. rxy1 rotates in xy plane by amount astepb param = rxy1 a xy astepb param = ryz1 a yz astepa param = rxz1 a xz astepb param = rxy2 a xy astepb2 param = ryz2 a yz astepa2 param = rxz2 a xz astepa2 param = rxy3 a xy astepb3 param = ryz3 a yz astepa3 param = rxz3 a xz astepa3 param = rxy4 a xy astepb4 param = ryz4 a yz astepa4 param = rxz4 a xz astepa4 param = ryz6 a yz astepa6 # Function macros, _ acts as a delimiter between steps # # Adding, sizing, fading, rotating cubes param = cube_add(cn,sv,fv) cube cn + _ cube cn size . sv _ cube cn fade . fv param = map_add(cn,rx,mn) face cn rx map mn + _ face cn . map . fade 1 _ face cn . map . zoom 1 param = map_fade(cn,mn,fv) face cn . map mn fade fv param = cube_rot(cn,rx,av) cube cn a rx av param = cube_size(cn,sv) cube cn size . sv # Scene rotations # e.g. a [xy][wu] rotates about xw xu yw wu by astep-vvslow param = rotvvs a [xy][wu] astep-vvslow _ a [xy][vt] astep2-vvslow _ a xz astep-vvslow param = rotvs a [xy][wu] astep-vslow _ a [xy][vt] astep2-vslow _ a xz astep-vslow param = rots a [xy][wu] astep-slow _ a [xy][vt] astep2-slow _ a xz astep-slow param = rotm a [xy][wu] astep-med _ a [xy][vt] astep2-med _ a xz astep-med param = rotf a [xy][wu] astep-fast _ a [xy][vt] astep2-fast _ a xz astep-fast param = rotvf a [xy][wu] astep-vfast _ a [xy][vt] astep2-vfast _ a xz astep-vfast param = rotvvf a [xy][wu] astep-vvfast _ a [xy][vt] astep2-vvfast _ a xz astep-vvfast param = rotvvvf a [xy][wu] astep-vvvfast _ a [xy][vt] astep2-vvvfast _ a xz astep-vvvfast param = rotthis2 a [x][wu] astep-vslow _ a [y][zv] astep2-vslow _ ryz2 _ !rxz2 _ rxy2 param = rotthis3 a [x][wu] astep-fast _ a [y][zv] astep2-fast _ ryz2 _ rxy2 param = rot6vvvf a [x][wu] astep-vvfast _ a [y][zv] astep2-vvvfast param = rot6vvf a [x][wu] astep-vvfast _ a [y][zv] astep2-vvfast param = rot6vf a [x][wu] astep-vfast _ a [y][zv] astep2-vfast param = rot6f a [x][wu] astep-fast _ a [y][zv] astep2-fast param = rot6m a [x][wu] astep-med _ a [y][zv] astep2-med param = rot6s a [x][wu] astep-slow _ a [y][zv] astep2-slow param = rot6vs a [x][wu] astep-vslow _ a [y][zv] astep2-vslow param = rot6vvs a [x][wu] astep-vvslow _ a [y][zv] astep2-vvslow # rotate along each axis # here the . matches any plane of rotation param = rotallvvvf a . dn0.75-1.00 param = rotallvvf a . dn0.50-0.75 param = rotallvf a . dn0.25-0.50 param = rotallf a . dn0.125-0.25 param = rotallm a . astep-med param = rotalls a . astep-slow param = rotallvs a . astep-vslow param = rotallvvs a . astep-vvslow # some relative multipliers param = s2f r0.80 param = p3 r0.95 param = ps4 r1.01 param = ps5 0.95 param = ps6 0.950-0.990 param = ps7 0.925-0.950 param = ps8 0.900-0.925 param = ps9 0.875-0.900 param = ps10 0.850-0.875 param = ps11 0.825-0.850 param = ps12 0.800-0.825 param = ps13 0.850-0.900 param = ps14 0.900-0.950 param = ps15 0.950-0.975 param = p5 r0.95 param = q31 r0.85 param = q30 r0.75 param = q29 r0.65 param = q32 d0.125 param = q33 d0.025 param = q34 d0.05 param = q40 r0.70 param = q50 d0.0315
Variety of scene definitions. Most of these vary based on the color of elements. Here, colors are defined with e.g. color1
and then these values are used in the layer
definitions. All of these have the text “acropolis” because the initial version of the video was prepared for Max's Live at the Acropolis show.
The final version of the video is ascent-acropolis-11
.
################################################################ # B/W and color final render <scene ascent-acropolis-11> # viridis param = name acropolis param = version 11 param = color0 fg # initial cube param = color1 fg # param = color2 fg # param = color3 fg # param = color4 fg # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11v> # viridis param = name acropolis param = version 11v param = color0 map_plasma_rev # initial cube param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11p> # plasma param = name acropolis param = version 11p param = color0 map_viridis_rev # initial cube param = color1 map_plasma_rev # param = color2 map_plasma_rev # param = color3 map_plasma_rev # param = color4 map_plasma_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11pdebug> # plasma debug with annotation param = name acropolis param = version 11pdebug param = color0 map_viridis_rev # initial cube param = color1 map_plasma_rev # param = color2 map_plasma_rev # param = color3 map_plasma_rev # param = color4 map_plasma_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.debug.conf>> </scene> # ################################################################ # Other prototype scenes <scene ascent-acropolis-1> param = name acropolis param = version 1 param = color1 fg param = color2 fg param = color3 fg param = color4 fg <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-2> param = name acropolis param = version 2 param = color1 eblue # eblue param = color2 egreen # egreen param = color3 epurple # epurple param = color4 emagenta # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-3> param = name acropolis param = version 3 param = color1 blue # eblue param = color2 green # egreen param = color3 dblue # epurple param = color4 dgreen # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-4> param = name acropolis param = version 4 param = color1 eblue # eblue param = color2 egreen # egreen param = color3 eblue # epurple param = color4 egreen # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> # scene 6 is faster below # 4th maps level c in scene 6 and 7 <scene ascent-acropolis-5> param = name acropolis param = version 5 param = color1 eblue # eblue param = color2 egreen # egreen param = color3 epurple # epurple param = color4 emagenta # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-6> param = name acropolis param = version 6 param = color1 egreen # eblue param = color2 fg # egreen param = color3 eblue # epurple param = color4 emagenta # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-7> param = name acropolis param = version 7 param = color1 eblue # eblue param = color2 fg # egreen param = color3 fg # epurple param = color4 egreen # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-8> param = name acropolis param = version 8 param = color1 egreen # eblue param = color2 fg # egreen param = color3 fg # epurple param = color4 emagenta # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> <scene ascent-acropolis-9> param = name acropolis param = version 9 param = color1 fg # eblue param = color2 fg # egreen param = color3 fg # epurple param = color4 fg # emagenta <<include acropolis/scene.ascent.main.conf>> </scene> # This version used at the concert. <scene ascent-acropolis-10> param = name acropolis param = version 10 param = color1 fg # eblue param = color2 fg # egreen param = color3 fg # epurple param = color4 fg # emagenta <<include scene.ascent.layers.v10.conf>> <<include acropolis/scene.ascent.main.v10.conf>> </scene> <scene ascent-acropolis-11va> param = name acropolis param = version 11va param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11vb> param = name acropolis param = version 11vb param = area_fraction_max 0.02 param = area_transition 0.5 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v26 <scene ascent-acropolis-11vc> param = name acropolis param = version 11vc param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.01 param = area_transition 0.75 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v28 <scene ascent-acropolis-11vd> param = name acropolis param = version 11vd param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.02 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v28.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11ma> param = name acropolis param = version 11ma param = color1 map_magma_rev # param = color2 map_magma_rev # param = color3 map_magma_rev # param = color4 map_magma_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11mb> param = name acropolis param = version 11mb param = area_fraction_max 0.02 param = area_transition 0.5 param = color1 map_magma_rev # param = color2 map_magma_rev # param = color3 map_magma_rev # param = color4 map_magma_rev # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v26 <scene ascent-acropolis-11mc> param = name acropolis param = version 11mc param = color1 map_magma_rev # param = color2 map_magma_rev # param = color3 map_magma_rev # param = color4 map_magma_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.01 param = area_transition 0.75 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v28 <scene ascent-acropolis-11md> param = name acropolis param = version 11md param = color1 map_magma_rev # param = color2 map_magma_rev # param = color3 map_magma_rev # param = color4 map_magma_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.02 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v28.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11vma> param = name acropolis param = version 11vma param = colorm map_magma_rev # param = colorv map_viridis_rev # <<include scene.ascent.layers.v11vm.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-11vmb> param = name acropolis param = version 11vmb param = area_fraction_max 0.02 param = area_transition 0.5 param = colorm map_magma_rev # param = colorv map_viridis_rev # <<include scene.ascent.layers.v11vm.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v26 <scene ascent-acropolis-11vmc> param = name acropolis param = version 11vmc param = colorm map_magma_rev # param = colorv map_viridis_rev # param = area_fraction_max 0.01 param = area_transition 0.75 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> # old v28 <scene ascent-acropolis-11vmd> param = name acropolis param = version 11vmd param = colorm map_magma_rev # param = colorv map_viridis_rev # param = area_fraction_max 0.02 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v28vm.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> ################################################################ ################################################################ ################################################################ <scene ascent-acropolis-12> param = name acropolis param = version 12 param = color1 map_magma # param = color2 map_magma # param = color3 map_magma # param = color4 map_magma # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-13> param = name acropolis param = version 13 param = color1 map_inferno # param = color2 map_inferno # param = color3 map_inferno # param = color4 map_inferno # <<include scene.ascent.layers.v11.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-14> param = name acropolis param = version 14 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis # param = color4 map_viridis # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-14b> param = name acropolis param = version 14b param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis # param = color4 map_viridis # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-15> param = name acropolis param = version 15 param = color1 map_viridis # param = color2 map_viridis_rev # param = color3 map_viridis # param = color4 map_viridis_rev # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-16> param = name acropolis param = version 16 param = color1 map_viridis_rev # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-16b> param = name acropolis param = version 16b param = hald hald1 param = color1 map_viridis_rev # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17> param = name acropolis param = version 17 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17b> param = name acropolis param = version 17b param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17c> param = name acropolis param = version 17c param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = area_fraction_max 0.05 param = area_transition 0.5 <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17d> param = name acropolis param = version 17d param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = area_fraction_max 0.04 param = area_transition 0.5 <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17e> param = name acropolis param = version 17e param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = area_fraction_max 0.03 param = area_transition 0.5 <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17f> param = name acropolis param = version 17f param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = area_fraction_max 0.02 param = area_transition 0.5 <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-17g> param = name acropolis param = version 17g param = hald hald1 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = area_fraction_max 0.01 param = area_transition 0.5 <<include scene.ascent.layers.v14.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-18> param = name acropolis param = version 18 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # <<include scene.ascent.layers.v18.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-19> param = name acropolis param = version 19 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # <<include scene.ascent.layers.v19.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-20> param = name acropolis param = version 20 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # <<include scene.ascent.layers.v20.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-21> param = name acropolis param = version 21 param = color1 map_viridis # param = color2 map_viridis # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # <<include scene.ascent.layers.v21.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-22> param = name acropolis param = version 22 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.005 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-22b> param = name acropolis param = version 22b param = hald hald1 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.005 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-23> param = name acropolis param = version 23 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.004 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-24> param = name acropolis param = version 24 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.003 param = area_transition 0.35 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-24b> param = name acropolis param = version 24b param = hald hald1 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.003 param = area_transition 0.35 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-25> param = name acropolis param = version 25 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.0025 param = area_transition 0.2 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-26b> param = name acropolis param = version 26b param = hald hald1 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.002 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v22.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-27> param = name acropolis param = version 27 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.002 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v27.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-28b> param = name acropolis param = version 28b param = hald hald1 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.002 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v28.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene> <scene ascent-acropolis-29> param = name acropolis param = version 29 param = color1 map_viridis_rev # param = color2 map_viridis_rev # param = color3 map_viridis_rev # param = color4 map_viridis_rev # param = polycolor1 fg # param = polycolor2 fg # param = polycolor3 fg # param = polycolor4 fg # param = area_fraction_max 0.002 param = area_transition 0.5 param = zremap_local -1 1 0 1 1 <<include scene.ascent.layers.v29.conf>> <<include acropolis/scene.ascent.main.v11.conf>> </scene>
Parameters specific to the final version.
# Include annotations about scene on frame and/or file param = annot 0 param = annotcube 0 param = annotmap 0 param = annotframe 0 param = annotfile 0 # Number of child frame renderers to spawn param = nproc3 144 param = nproc4 144 param = nproc5 50 # careful here, this may need to be as low as 20 param = nproc6 10 param = ndim 5 # param = fs 24 # set to FPS to make fs = 1 second param = seed 1 param = tween 0.85 # final 0.85 <<include scene.ascent.mapcube.conf>> <<include scene.ascent.param.conf>> <<include scene.ascent.keyframes.conf>> # This is a funky feature in which we do not rotate about # the canonical axes but a random orthonormal basis. Because # we're not rotating about features of the cube, the projection # appears more uniformly complex (but actually less interesting!). # dimensions at this or larger index are random #param = randombasis 0
The layers define the order in which elements are drawn, which parts of the cube to draw (e.g. edges), what blend to use (mostly difference), which color to use and line thickness.
# Blend modes are one of # normal | multiply | add | subtract | diff | lighten | darken | hue | sat | value | color layer = c0:cubeline:normal:1:color0:no:2 layer = c1:cubeline:diff:1:color1:no:5 layer = c2:cubeline:diff:1:color2:no:5 layer = c3:cubeline:diff:1:color3:no:5 layer = c4:cubeline:diff:1:color4:no:5 layer = c1:mapline:diff:1:color1:no:2 layer = c2:mapline:diff:1:color2:no:2 layer = c3:mapline:diff:1:color3:no:2 layer = c4:mapline:diff:1:color4:no:2 layer = c5:cubeface:diff:1:color1:no:1 layer = c6:cubeface:diff:1:color2:no:1 layer = c7:cubeface:diff:1:color3:no:1 layer = c8:cubeface:diff:1:color4:no:1 layer = cg:mapfill:diff:1:color1:no:1 layer = ce:mapfill:diff:1:color2:no:1 layer = cf:mapfill:diff:1:color3:no:1 layer = ch:mapfill:diff:1:color4:no:1 layer = ca:mapfill:diff:1:color1:no:1 layer = cb:mapfill:diff:1:color2:no:1 layer = cc:mapfill:diff:1:color3:no:1 layer = cd:mapfill:diff:1:color4:no:1
Cubes and area maps to initialize. Cubes are called by name (e.g. c0, ca) in the keyframe definitions.
# Various approximations of pi map = 10a 10/3 50000 2 map = 10b 10/3 50000 3 map = 10c 10/3 50000 4 map = 10d 10/3 50000 5 map = 10e 10/3 50000 6 map = 22a 22/7 50000 2 map = 22b 22/7 50000 3 map = 22c 22/7 50000 4 map = 22d 22/7 50000 5 map = 22e 22/7 50000 6 map = 179a 179/57 50000 2 map = 179b 179/57 50000 3 map = 179c 179/57 50000 4 map = 179d 179/57 50000 5 map = 179e 179/57 50000 6 map = 179f 179/57 150000 7 map = 245a 245/78 50000 2 map = 245b 245/78 50000 3 map = 245c 245/78 50000 4 map = 245d 245/78 50000 5 map = 245e 245/78 50000 6 map = 245f 245/78 150000 7 map = 355a 355/113 50000 2 map = 355b 355/113 50000 3 map = 355c 355/113 50000 4 map = 355d 355/113 50000 5 map = 355e 355/113 50000 6 map = pia pi 50000 2 map = pib pi 50000 3 map = pic pi 50000 4 map = pid pi 50000 5 map = pie pi 50000 6 # Cube names cube = c0 cube = c1 cube = c2 cube = c3 cube = c4 cube = c5 cube = c6 cube = c7 cube = c8 cube = ca cube = cb cube = cc cube = cd cube = ce cube = cf cube = cg cube = ch
Keyframes for the final version of the video.
frame = init ; a . 0 ; size . 1; fade . 1 ################################################################ # SCENE 1 - cube c0 grows to max dimensions and c0 twinkles from corners frame = 1: frame = 1.a; cube_add(c0,0,1) # arrange yw rotation for the split at 1.c* frame = 1.a0; a yw astepa2 # grow horizontal line frame = 1.a1; n 2fs; c c0 f [xy] 0 frame = 1.a2; n 2fs; c c0 s [x] 0.05 ; frame = 1.a3; n 2fs; c c0 s [x] 0.10 ; frame = 1.a4; n 2fs; c c0 s [x] 0.15 ; # grow y and rotate frame = 1.a5; n 3fs; c c0 s [y] 0.05 ; rxy3 frame = 1.a6; n 3fs; c c0 s [y] 0.10 ; rxy3 frame = 1.a7; n 2fs; c c0 s [y] 0.15 ; rxy3 # grow z frame = 1.b1; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.100 ; c c0 f [z] 0.80 ; ryz6 frame = 1.b2; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.110 ; c c0 f [z] 0.60 ; ryz6 frame = 1.b3; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.120 ; c c0 f [z] 0.40 ; ryz6 frame = 1.b4; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.130 ; c c0 f [z] 0.20 ; ryz6 frame = 1.b5; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.140 ; c c0 f [z] 0.10 ; ryz6 frame = 1.b6; n 2fs; c c0 s [xy] 0.15 ; c c0 s [z] 0.150 ; c c0 f [z] 0.00 ; ryz6 # split cubes along w (needs yw angle set, see above) frame = 1.c1; n 1fs; c c0 s [xyz] 0.15 ; c c0 s [w] 0.815 frame = 1.c2; n 2fs; # grow w and start to rotate xy/yz/rot* frame = 1.d1; n 2fs; c c0 s [xyz] 0.15 ; c c0 s [w] 0.715 ; c c0 f [w] 0.9 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d2; n 2fs; c c0 s [xyz] 0.15 ; c c0 s [w] 0.615 ; c c0 f [w] 0.8 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d3; n 2fs; c c0 s [xyz] 0.15 ; c c0 s [w] 0.515 ; c c0 f [w] 0.7 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d4; n 2fs; ; c c0 s [w] 0.415 ; c c0 f [w] 0.6 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d5; n 2fs; ; c c0 s [w] 0.315 ; c c0 f [w] 0.4 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d6; n 2fs; ; c c0 s [w] 0.215 ; c c0 f [w] 0.2 ; rots; !ryz2; rxy2; a xw astepb4 frame = 1.d7; n 2fs; ; c c0 s [w] 0.150 ; c c0 f [w] 0.0 ; rots; !ryz2; rxy2; a xw astepb4 # grow v frame = 1.e1; n 2fs; ; c c0 s [v] 0.150 ; rots; ryz2; rxy2 frame = 1.e2; n 2fs; c c0 s [xyzwv] 0.150 ; ; c c0 f [v] 1.00 ; rots; ryz2; rxy2 frame = 1.e3; n 2fs; c c0 s [xyzwv] 0.175 ; ; c c0 f [v] 1.00 ; rots; ryz2; rxy2 frame = 1.e3; n 1fs; c c0 s [xyzwv] 0.175 ; ; c c0 f [v] 1.05 ; rots; ryz2; rxy2 frame = 1.e4; n 2fs; c c0 s [xyzwv] 0.200 ; ; c c0 f [v] 1.00 ; rots; ryz2; rxy2 frame = 1.e5; n 2fs; c c0 s [xyzwv] 0.225 ; ; c c0 f [v] 1.00 ; rots; ryz2; rxy2 ; size . 1.30 frame = 1.e6; n 2fs; c c0 s [xyzwv] 0.250 ; ; c c0 f [v] 0.80 ; rots; ryz2; rxy2 frame = 1.e7; n 2fs; c c0 s [xyzwv] 0.275 ; ; c c0 f [v] 0.70 ; rots; ryz2; rxy2 frame = 1.e8; n 2fs; c c0 s [xyzwv] 0.300 ; ; c c0 f [v] 0.50 ; rots; ryz2; rxy2 frame = 1.e9; n 2fs; c c0 s [xyzwv] 0.325 ; ; c c0 f [v] 0.40 ; rots; ryz2; rxy2 frame = 1.f1; n 2fs; ; c c0 f [v] 0.30 ; rots; ryz2; rxy2 frame = 1.f2; n 2fs; c c0 f [v] 0.20 ; rots; ryz2; rxy2 frame = 1.f3; n 2fs; c c0 f [v] 0.10 ; rots; ryz2; rxy2 frame = 1.f4; n 2fs; c c0 f [v] 0.00 ; rots; ryz2; rxy2 ################################################################ # xy, xz, xw, *** dimensions grow along edges of new cubes frame = 2: frame = 2.a; cube c1 copyfrom c0 . 1 frame = 2.a; cube c2 copyfrom c0 . 1 frame = 2.a; cube c3 copyfrom c0 . 1 frame = 2.a; cube c4 copyfrom c0 . 1 frame = 2.a; n 2fs; c c1 f [xy] s2f ; rotthis2; frame = 2.b; n 2fs; c c1 f [xy] s2f ; rotthis2; frame = 2.c; n 2fs; c c1 f [xy] s2f ; rotthis2; frame = 2.d; n 2fs; c c1 f [xy] s2f ; rotthis2; frame = 2.e; n 2fs; c c1 f [xy] s2f ; rotthis2; frame = 2.f; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; rotthis2; frame = 2.g; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; rotthis2; frame = 2.h; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; rotthis2; frame = 2.i; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; rotthis2; frame = 2.j; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; rotthis2; frame = 2.k; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; rotthis2; frame = 2.l; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; rotthis2; frame = 2.m; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; c c4 f [xv] s2f; rotthis2; frame = 2.n; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; c c4 f [xv] s2f; rotthis2; frame = 2.o; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; c c4 f [xv] s2f; rotthis2; frame = 2.p; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; c c4 f [xv] s2f; rotthis2; frame = 2.q; n 2fs; c c1 f [xy] s2f ; c c2 f [xz] s2f ; c c3 f [xw] s2f ; c c4 f [xv] s2f; rotthis2; frame = 2.r; n 2fs; c c1 f [xy] 0 ; c c2 f [xz] 0 ; c c3 f [xw] 0 ; c c4 f [xv] 0 ; rotthis2; ################################################################ # each cube from (2) expands, splitting up the dimension pairs frame = 3: frame = 3.a; n 2fs; c c1 s . s3s; rotthis2 frame = 3.b; n 2fs; c c1 s . s3s; rotthis2 frame = 3.c; n 2fs; c c1 s . s3s; c c2 s . s3s; rotthis2 frame = 3.d; n 2fs; c c1 s . s3s; c c2 s . s3s; rotthis2 frame = 3.e; n 2fs; c c1 s . s3s; c c2 s . s3s; c c3 s . s3s; c c0 f . s3f ; rotthis2 frame = 3.f; n 2fs; c c1 s . s3s; c c2 s . s3s; c c3 s . s3s; c c0 f . s3f ; rotthis2 frame = 3.g; n 2fs; c c[1-4] s . s3s; c c0 f . s3f ; rotthis2 frame = 3.h; n 2fs; c c[1-4] s . s3s; c c0 f . s3f ; rotthis2 frame = 3.i; n 2fs; c c[1-4] s . s3s; c c0 f . s3f ; rotthis2 ; rep 2 frame = 3.j; n 2fs; c c0 f . s3f ; rotthis2 ; rep 2 frame = 3.k; n 2fs; ; rotthis2 ; rep 2 ################################################################ # # maps fade in one at a time as original cube c0 shrinks to corners frame = 4: frame = 4.a; map_add(c1,xyzwv,22a) frame = 4.a; map_add(c2,xyzwv,22b) frame = 4.a; map_add(c3,xyzwv,22b) frame = 4.a; map_add(c4,xyzwv,22b) frame = 4.a; n 2fs; map_fade(c1,.,p1) ; c c1 f [xy] s4f ; c c[0-1] s . p2 ; size . s4u ; rotthis3; c c0 f . 0.90; frame = 4.b; n 2fs; map_fade(c1,.,p1) ; c c1 f [xy] s4f ; c c[0-1] s . p2 ; size . s4u ; rotthis3; frame = 4.c; n 2fs; map_fade(c1,.,p1) ; c c1 f [xy] s4f ; c c[0-1] s . p2 ; size . s4u ; rotthis3; frame = 4.d; n 2fs; map_fade(c2,.,p1) ; c c2 f [xz] s4f ; c c[0-2] s . p2 ; size . s4u ; rotthis3; cube c[1] a [xy][yzwvu] astep-fast frame = 4.e; n 2fs; map_fade(c2,.,p1) ; c c2 f [xz] s4f ; c c[0-2] s . p2 ; size . s4u ; rotthis3; cube c[1-2] a [xy][yzwvu] astep-fast frame = 4.f; n 2fs; map_fade(c2,.,p1) ; c c2 f [xz] s4f ; c c[0-2] s . p2 ; size . s4u ; rotthis3; cube c[1-2] a [xy][yzwvu] astep-fast frame = 4.g; n 2fs; map_fade(c3,.,p1) ; c c3 f [xw] s4f ; c c[0-3] s . p2 ; size . s4u ; rotthis3; cube c[1-2] a [xy][yzwvu] astep-fast frame = 4.h; n 2fs; map_fade(c3,.,p1) ; c c3 f [xw] s4f ; c c[0-3] s . p2 ; size . s4u ; rotthis3; cube c[1-3] a [xy][yzwvu] astep-fast frame = 4.i; n 2fs; map_fade(c4,.,p1) ; c c3 f [xw] s4f ; c c[0-3] s . p2 ; size . s4u ; rotthis3; cube c[1-3] a [xy][yzwvu] astep-fast frame = 4.j; n 2fs; map_fade(c[1-4],.,p1); c c4 f [xv] s4f ; size . s4u ; rotthis3; cube c[1-3] a [xy][yzwvu] astep-fast frame = 4.k; n 2fs; map_fade(c[1-4],.,p1); c c4 f [xv] s4f ; size . s4u ; rotthis3; cube c[1-4] a [xy][yzwvu] astep-fast frame = 4.l; n 2fs; map_fade(c[1-4],.,p1); c c4 f [xv] s4f ; size . s4u ; rotthis3; cube c[1-4] a [xy][yzwvu] astep-fast frame = 4.m; n 2fs; map_fade(c[1-4],.,p1); size . s4u ; rotthis3; cube c[1-4] a [xy][yzwvu] astep-fast # cube fills from corners and cubes start to independently rotate # fade out map edges c1-4 frame = 5: frame = 5.a; cube c5 copyfrom c1 . 1 frame = 5.a; cube c6 copyfrom c2 . 1 frame = 5.a; cube c7 copyfrom c3 . 1 frame = 5.a; cube c8 copyfrom c4 . 1 frame = 5.a; cube c[5-8] f . 1 frame = 5.a; face c[5-8] . map . - frame = 5.a; n 2fs; c c[5-5] f . s5cf; map_fade(c[1-4],.,s5f) ; rotthis3 ; c c[1-4] a [xy][yzwvu] astep-vfast frame = 5.b; n 2fs; c c[5-5] f . s5cf; map_fade(c[1-4],.,s5f) ; rotthis3 ; c c[1-4] a [xy][yzwvu] astep-vfast frame = 5.c; n 2fs; c c[5-6] f . s5cf; map_fade(c[1-4],.,s5f) ; rotthis3 ; c c[1-5] a [xy][yzwvu] astep-vfast ; rep 5 frame = 5.d; n 2fs; c c[5-7] f . s5cf; map_fade(c[1-4],.,s5f) ; rotthis3 ; c c[1-6] a [xy][yzwvu] astep-vfast ; rep 9 frame = 5.e; n 2fs; c c[5-8] f . s5cf; map_fade(c[1-4],.,s5f) ; rotthis3 ; c c[1-7] a [xy][yzwvu] astep-vfast ; rep 4 frame = 5.f; n 2fs; c c[5-8] f . s5cs; rotthis3 ; c c[1-8] a [xy][yzwvu] astep-vfast ; rep 5 frame = 5.g; n 2fs; c c[5-8] f . s5cs; rotthis3 ; c c[1-8] a [xy][yzwvu] astep-vfast ; rep 6 ################################################################ # dyads (28) # # Map fills grow frame = 6: frame = 6.a; cube ca copyfrom c1 . 1 frame = 6.a; cube cb copyfrom c2 . 1 frame = 6.a; cube cc copyfrom c3 . 1 frame = 6.a; cube cd copyfrom c4 . 1 frame = 5.a; cube c[a-d] f . 1 frame = 6.a; map_add(ca,xyzwv,179a) frame = 6.a; map_add(cb,xyzwv,179b) frame = 6.a; map_add(cc,xyzwv,179b) frame = 6.a; map_add(cd,xyzwv,179c) frame = 6.b; n 14fs; a xy refxy; a xz refxz; a xw refxw; a xv refxv ; a yz refyz; a yw refyw; a yv refyv; c c[0-9a-d] a . 0 ; map_fade(c[a-d],.,ps6) frame = 6.c; n 2fs; rot6vvs; a xw d0.01 ; f . . map . fade ps15 ; cube c[0-8] fade . ps15 ; cube_rot(.,[xy][yzwvu],astep-vvslow) ; size . ps20 frame = 6.d; n 2fs; rot6vs; a xw d0.01 ; f . . map . fade ps14 ; cube c[0-8] fade . ps14 ; cube_rot(.,[xy][yzwvu],astep-vvslow) ; a xy d-0.001 ; size . ps20 frame = 6.e; n 2fs; rot6s; a xw d0.01 ; f . . map . fade ps13 ; cube c[0-8] fade . ps13 ; cube_rot(.,[xy][yzwvu],astep-vslow) ; a xy d-0.002 ; size . ps20 frame = 6.f; n 2fs; rot6s; a xw d0.01 ; f . . map . fade ps12 ; cube c[0-8] fade . ps12 ; cube_rot(.,[xy][yzwvu],astep-slow) ; a xy d-0.002 ; size . ps20 frame = 6.g; n 2fs; rot6f; a xw d0.02 ; f . . map . fade ps11 ; cube c[0-8] fade . ps11 ; cube_rot(.,[xy][yzwvu],astep-slow) ; a xy d-0.002 ; size . ps20 frame = 6.h; n 2fs; rot6f; a xw d0.02 ; f . . map . fade ps10 ; cube c[0-8] fade . ps10 ; cube_rot(.,[xy][yzwvu],astep-med) ; a xy d-0.002 ; size . ps20 frame = 6.i; n 2fs; rot6vf; a xw d0.03 ; f . . map . fade ps9 ; cube c[0-8] fade . ps9 ; cube_rot(.,[xy][yzwvu],astep-med) ; a xy d-0.003 ; size . ps20 frame = 6.j; n 2fs; rot6vf; a xw d0.03 ; f . . map . fade ps8 ; cube c[0-8] fade . ps8 ; cube_rot(.,[xy][yzwvu],astep-fast) ; a xy d-0.003 ; size . ps20 frame = 6.k; n 2fs; rot6vf; a xw d0.04 ; f . . map . fade ps7 ; cube c[0-8] fade . ps7 ; cube_rot(.,[xy][yzwvu],astep-fast) ; a xy d-0.004 ; size . ps21 frame = 6.l; n 2fs; rot6vf; a xw d0.05 ; f . . map . fade ps6 ; cube c[0-8] fade . ps6 ; cube_rot(.,[xy][yzwvu],astep-vfast) ; a xy d-0.005 ; size . ps21 frame = 6.m; n 2fs; rot6vvf; a xw d0.06 ; f . . map . fade ps6 ; cube c[0-8] fade . ps6 ; cube_rot(.,[xy][yzwvu],astep-vfast) ; a xy d-0.010 ; size . ps21 frame = 6.n; n 2fs; rot6vvf; a xw d0.07 ; f . . map . fade ps6 ; cube c[0-8] fade . ps6 ; cube_rot(.,[xy][yzwvu],astep-vfast) ; a xy d-0.010 ; size . ps21 frame = 6.o; n 2fs; rot6vvvf; a xw d0.08 ; f . . map . fade ps8 ; cube c[0-8] fade . ps8 ; cube_rot(.,[xy][yzwvu],astep-vvfast) ; a xy d-0.007 ; size . ps21 frame = 6.p; n 2fs; rot6vvvf; a xw d0.05 ; f . . map . fade ps10 ; cube c[0-8] fade . ps10 ; cube_rot(.,[xy][yzwvu],astep-vvfast) ; a xy d-0.004 ; size . ps21 frame = 6.q; n 2fs; rot6vvvf; a xw d0.03 ; f . . map . fade ps12 ; cube c[0-8] fade . ps12 ; cube_rot(.,[xy][yzwvu],astep-vvfast) ; a xy d-0.002 ; size . ps21 frame = 6.r; n 2fs; rot6vvvf; a xw d0.01 ; f . . map . fade ps14 ; cube c[0-8] fade . ps14 ; cube_rot(.,[xy][yzwvu],astep-vvfast) ; a xy d-0.001 ; size . ps21 ################################################################ # peak (14) # # Grow four maps, drawing their edges. frame = 7: frame = 7.a; cube_add(ce,1,1) frame = 7.a; cube_add(cf,1,1) frame = 7.a; cube_add(cg,1,1) frame = 7.a; cube_add(ch,1,1) frame = 7.a; cube ce size . 1.1 frame = 7.a; cube cf size . 1.2 frame = 7.a; cube cg size . 1.35 frame = 7.a; cube ch size . 1.5 frame = 7.a; cube c[e-h] angle . 0-0.25 frame = 7.a; map_add(ce,xyzwv,pia) frame = 7.a; map_add(cf,xyzwv,pib) frame = 7.a; map_add(cg,xyzwv,pib) frame = 7.a; map_add(ch,xyzwv,pic) frame = 7.a; n 2fs; rot6f; rep 2 ; face c[0-9a-e] . map . fade p5 ; cube c[0-2] fade . p5 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.b; n 2fs; rot6f; rep 2 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.c; n 2fs; rot6vf; rep 2 ; face c[0-9a-f] . map . fade p5 ; cube c[0-4] fade . p5 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.d; n 2fs; rot6vf; rep 2 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.e; n 2fs; rot6vvf; rep 2 ; face c[0-9a-g] . map . fade p5 ; cube c[0-6] fade . p5 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.f; n 2fs; rot6vvf; rep 2 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.g; n 2fs; rot6vf; rep 2 ; face c[0-9a-h] . map . fade p5 ; cube c[0-8] fade . p5 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.h; n 2fs; rot6vf; rep 2 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.i; n 2fs; rot6vf; rep 2 ; face . . map . fade p5 ; cube c[0-8] fade . p5 ; cube_rot(.,[xy][yzwvu],astep-med) frame = 7.j; n 2fs; rot6vf; rep 2 ; cube_rot(.,[xy][yzwvu],astep-med) ################################################################ # outro (18) # # Slow down rotation and start shrinking and fading everything frame = 8: frame = 8.a; n 2fs ; rep 4 ; rot6f ; size . r0.95 ; cube_rot(.,[xy][yzwvu],astep-med) ; cube . f . q33 ; map_fade(.,.,q33) ; cube c[e-h] s . r0.95 frame = 8.a; n 2fs ; rep 2 ; rot6m ; size . r0.90 ; cube_rot(.,[xy][yzwvu],astep-med) ; cube . f . q33 ; map_fade(.,.,q33) ; cube c[e-h] s . r0.95 frame = 8.c; n 2fs ; rot6s ; rep 4 ; size . q31 ; cube_rot(.,[xy][yzwvu],astep-med) ; cube . f . q50 ; map_fade(.,.,q50) ; cube c[e-h] s . r0.95 ################################################################ # decay and fade (18) # # Further slow rotations and keep shrinking frame = 9: frame = 9.a; n 2fs ; rot6s ; rep 6 ; size . q30 ; cube_rot(.,[xy][ywvu],astep-med) ; cube . f . q50 ; map_fade(.,.,q50) frame = 9.b; n 2fs ; rot6s ; rep 6 ; size . q29 ; cube_rot(.,[xy][ywvu],astep-med) ; cube . f . q50 ; map_fade(.,.,q50) frame = 9.c; n 1fs ; rot6s ; size . 0 ; cube_rot(.,[xy][yzwvu],astep-med) ; cube . f . 1 ; map_fade(.,.,1) frame = stop
I don’t have good luck in the match points. —Rafael Nadal, Spanish tennis player
In many experimental designs, we need to keep in mind the possibility of confounding variables, which may give rise to bias in the estimate of the treatment effect.
If the control and experimental groups aren't matched (or, roughly, similar enough), this bias can arise.
Sometimes this can be dealt with by randomizing, which on average can balance this effect out. When randomization is not possible, propensity score matching is an excellent strategy to match control and experimental groups.
Kurz, C.F., Krzywinski, M. & Altman, N. (2024) Points of significance: Propensity score matching. Nat. Methods 21:1770–1772.
We'd like to say a ‘cosmic hello’: mathematics, culture, palaeontology, art and science, and ... human genomes.
All animals are equal, but some animals are more equal than others. —George Orwell
This month, we will illustrate the importance of establishing a baseline performance level.
Baselines are typically generated independently for each dataset using very simple models. Their role is to set the minimum level of acceptable performance and help with comparing relative improvements in performance of other models.
Unfortunately, baselines are often overlooked and, in the presence of a class imbalance, must be established with care.
Megahed, F.M, Chen, Y-J., Jones-Farmer, A., Rigdon, S.E., Krzywinski, M. & Altman, N. (2024) Points of significance: Comparing classifier performance with baselines. Nat. Methods 21:546–548.
Celebrate π Day (March 14th) and dig into the digit garden. Let's grow something.
Huge empty areas of the universe called voids could help solve the greatest mysteries in the cosmos.
My graphic accompanying How Analyzing Cosmic Nothing Might Explain Everything in the January 2024 issue of Scientific American depicts the entire Universe in a two-page spread — full of nothing.
The graphic uses the latest data from SDSS 12 and is an update to my Superclusters and Voids poster.
Michael Lemonick (editor) explains on the graphic:
“Regions of relatively empty space called cosmic voids are everywhere in the universe, and scientists believe studying their size, shape and spread across the cosmos could help them understand dark matter, dark energy and other big mysteries.
To use voids in this way, astronomers must map these regions in detail—a project that is just beginning.
Shown here are voids discovered by the Sloan Digital Sky Survey (SDSS), along with a selection of 16 previously named voids. Scientists expect voids to be evenly distributed throughout space—the lack of voids in some regions on the globe simply reflects SDSS’s sky coverage.”
Sofia Contarini, Alice Pisani, Nico Hamaus, Federico Marulli Lauro Moscardini & Marco Baldi (2023) Cosmological Constraints from the BOSS DR12 Void Size Function Astrophysical Journal 953:46.
Nico Hamaus, Alice Pisani, Jin-Ah Choi, Guilhem Lavaux, Benjamin D. Wandelt & Jochen Weller (2020) Journal of Cosmology and Astroparticle Physics 2020:023.
Sloan Digital Sky Survey Data Release 12
Alan MacRobert (Sky & Telescope), Paulina Rowicka/Martin Krzywinski (revisions & Microscopium)
Hoffleit & Warren Jr. (1991) The Bright Star Catalog, 5th Revised Edition (Preliminary Version).
H0 = 67.4 km/(Mpc·s), Ωm = 0.315, Ωv = 0.685. Planck collaboration Planck 2018 results. VI. Cosmological parameters (2018).
constellation figures
stars
cosmology
It is the mark of an educated mind to rest satisfied with the degree of precision that the nature of the subject admits and not to seek exactness where only an approximation is possible. —Aristotle
In regression, the predictors are (typically) assumed to have known values that are measured without error.
Practically, however, predictors are often measured with error. This has a profound (but predictable) effect on the estimates of relationships among variables – the so-called “error in variables” problem.
Error in measuring the predictors is often ignored. In this column, we discuss when ignoring this error is harmless and when it can lead to large bias that can leads us to miss important effects.
Altman, N. & Krzywinski, M. (2024) Points of significance: Error in predictor variables. Nat. Methods 21:4–6.
Altman, N. & Krzywinski, M. (2015) Points of significance: Simple linear regression. Nat. Methods 12:999–1000.
Lever, J., Krzywinski, M. & Altman, N. (2016) Points of significance: Logistic regression. Nat. Methods 13:541–542 (2016).
Das, K., Krzywinski, M. & Altman, N. (2019) Points of significance: Quantile regression. Nat. Methods 16:451–452.