2025 π Day latest news buy art
Love itself became the object of her love.Jonathan Safran Foercount sadnessesmore quotes
very clickable
music + math
Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
WELCOME TO THE 5TH DIMENSION | This isn't meant to be understood — it's meant to be enjoyed.
Love music and science? Explore my collaboration with Max Cooper where we tell the story of infinities and animate the digits of π. Both tracks appear on Max's Yearning for the Infinite album.
Another collaboration with Max!

Max Cooper's Ascent — Making of the Music video

Enter the 5th dimension

Ascent answers the question: if you were living in a 5-dimensional room and projected digits of `\pi` onto its walls, what would you see?

1 · building the animation from the ground up

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.

2 · straightforward math — complex output

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.

3 · how the animation system works

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).

4 · defining the scene

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.

4.1 · system parameters

To make the keyframe definitions more modular, I define various parameters that can be reused.

4.1.1 · absolute vs relative

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”.

4.1.2 · randomly sampled

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.

4.1.3 · normalized

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.

4.1.4 · macros

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.

4.1.5 · function macros

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)

4.2 · system commands

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.

4.3 · building keyframes

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.

4.4 · interpolating frames

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.

5 · walkthrough the first few keyframes of ascent

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;

6 · ascent configuration files

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.

6.1 · global system configuration

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

6.2 · global parameters

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

6.3 · scene variations

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>

6.4 · scene parameters

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 

6.5 · object layers

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

6.6 · cubes and area maps

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

6.7 · keyframes

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

news + thoughts

Beyond Belief Campaign BRCA Art

Wed 11-06-2025

Fuelled by philanthropy, findings into the workings of BRCA1 and BRCA2 genes have led to groundbreaking research and lifesaving innovations to care for families facing cancer.

This set of 100 one-of-a-kind prints explore the structure of these genes. Each artwork is unique — if you put them all together, you get the full sequence of the BRCA1 and BRCA2 proteins.

Propensity score weighting

Mon 17-03-2025

The needs of the many outweigh the needs of the few. —Mr. Spock (Star Trek II)

This month, we explore a related and powerful technique to address bias: propensity score weighting (PSW), which applies weights to each subject instead of matching (or discarding) them.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Nature Methods Points of Significance column: Propensity score weighting. (read)

Kurz, C.F., Krzywinski, M. & Altman, N. (2025) Points of significance: Propensity score weighting. Nat. Methods 22:1–3.

Happy 2025 π Day—
TTCAGT: a sequence of digits

Thu 13-03-2025

Celebrate π Day (March 14th) and sequence digits like its 1999. Let's call some peaks.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
2025 π DAY | TTCAGT: a sequence of digits. The digits of π are encoded into DNA sequence and visualized with Sanger sequencing. (details)

Crafting 10 Years of Statistics Explanations: Points of Significance

Sun 09-03-2025

I don’t have good luck in the match points. —Rafael Nadal, Spanish tennis player

Points of Significance is an ongoing series of short articles about statistics in Nature Methods that started in 2013. Its aim is to provide clear explanations of essential concepts in statistics for a nonspecialist audience. The articles favor heuristic explanations and make extensive use of simulated examples and graphical explanations, while maintaining mathematical rigor.

Topics range from basic, but often misunderstood, such as uncertainty and P-values, to relatively advanced, but often neglected, such as the error-in-variables problem and the curse of dimensionality. More recent articles have focused on timely topics such as modeling of epidemics, machine learning, and neural networks.

In this article, we discuss the evolution of topics and details behind some of the story arcs, our approach to crafting statistical explanations and narratives, and our use of figures and numerical simulations as props for building understanding.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Crafting 10 Years of Statistics Explanations: Points of Significance. (read)

Altman, N. & Krzywinski, M. (2025) Crafting 10 Years of Statistics Explanations: Points of Significance. Annual Review of Statistics and Its Application 12:69–87.

Propensity score matching

Mon 16-09-2024

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.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Nature Methods Points of Significance column: Propensity score matching. (read)

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.

Understanding p-values and significance

Tue 24-09-2024

P-values combined with estimates of effect size are used to assess the importance of experimental results. However, their interpretation can be invalidated by selection bias when testing multiple hypotheses, fitting multiple models or even informally selecting results that seem interesting after observing the data.

We offer an introduction to principled uses of p-values (targeted at the non-specialist) and identify questionable practices to be avoided.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Understanding p-values and significance. (read)

Altman, N. & Krzywinski, M. (2024) Understanding p-values and significance. Laboratory Animals 58:443–446.

Martin Krzywinski | contact | Canada's Michael Smith Genome Sciences CentrePHSA
Google whack “vicissitudinal corporealization”
{ 10.9.234.152 }