2024 π Daylatest newsbuy art
Twenty — minutes — maybe — more.Naomichoose four wordsmore 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

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.

Nasa to send our human genome discs to the Moon

Sat 23-03-2024

We'd like to say a ‘cosmic hello’: mathematics, culture, palaeontology, art and science, and ... human genomes.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
SANCTUARY PROJECT | A cosmic hello of art, science, and genomes. (details)
Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
SANCTUARY PROJECT | Benoit Faiveley, founder of the Sanctuary project gives the Sanctuary disc a visual check at CEA LeQ Grenoble (image: Vincent Thomas). (details)
Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
SANCTUARY PROJECT | Sanctuary team examines the Life disc at INRIA Paris Saclay (image: Benedict Redgrove) (details)

Comparing classifier performance with baselines

Fri 22-03-2024

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.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Nature Methods Points of Significance column: Comparing classifier performance with baselines. (read)

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.

Happy 2024 π Day—
sunflowers ho!

Sat 09-03-2024

Celebrate π Day (March 14th) and dig into the digit garden. Let's grow something.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
2024 π DAY | A garden of 1,000 digits of π. (details)

How Analyzing Cosmic Nothing Might Explain Everything

Thu 18-01-2024

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.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
How Analyzing Cosmic Nothing Might Explain Everything. Text by Michael Lemonick (editor), art direction by Jen Christiansen (Senior Graphics Editor), source: SDSS

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

voids

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

constellation figures

Alan MacRobert (Sky & Telescope), Paulina Rowicka/Martin Krzywinski (revisions & Microscopium)

stars

Hoffleit & Warren Jr. (1991) The Bright Star Catalog, 5th Revised Edition (Preliminary Version).

cosmology

H0 = 67.4 km/(Mpc·s), Ωm = 0.315, Ωv = 0.685. Planck collaboration Planck 2018 results. VI. Cosmological parameters (2018).

Error in predictor variables

Tue 02-01-2024

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.

Martin Krzywinski @MKrzywinski mkweb.bcgsc.ca
Nature Methods Points of Significance column: Error in predictor variables. (read)

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.

Background reading

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.

Martin Krzywinski | contact | Canada's Michael Smith Genome Sciences CentreBC Cancer Research CenterBC CancerPHSA
Google whack “vicissitudinal corporealization”
{ 10.9.234.152 }