How we create Causal Diagrams
We wrote our own extension for Nikola, our static web page generator, to generate Causal Diagrams.
The basics are taken from this article. However, we modified this a bit and added more options to it. One of the mains ones is the ability to show and animate positions.
All animated diagrams have play/pause and step buttons; you can also click or tab onto a diagram and use the space bar (play/pause) and the left/right arrow keys (step one beat).
Currently, the generator can handle the following syntax:
Simple diagram
{{% causal_diagram %}}
3p 3 3 3 3p 3 3 3
3p 3 3 3 3p 3 3 3
{{% /causal_diagram %}}
results in:
The jugglers are automatically labeled "A", "B", etc.
Changing the labels at each beat
{{% causal_diagram %}}
3 3 3 3 3
(LR) 3 3 3 3 3
(LLRR) 3 3 3 3 3
(WOMBLE) 3 3 3 3 3
{{% /causal_diagram %}}
Letters in parenthesis will be repeated along the pattern. These can be different for each juggler.
Offsets and titles
{{% causal_diagram %}}
(RL 0) 3 3 3 3 3 3
(LR 0.5) 3 3 3 3 3 3
(RL 1) 3 3 3 3 3 3
title: how to do offsets
{{% /causal_diagram %}}
Offsets can be defined and a title for the whole diagram can be set:
Layout changes
To be able to make the layout a bit more compact or larger, you can change the step size between rows of jugglers and also between beats.
Note: if you make these too small, items in the graphic might overlap
Distance bewteen rows
{{% causal_diagram %}}
step_Y: 30
(RL 0) 3 3 3 3 3 3
(LR 0.5) 3 3 3 3 3 3
(RL 1) 3 3 3 3 3 3
title: how to change Y step size
{{% /causal_diagram %}}
Distances between beats
{{% causal_diagram %}}
step_X: 30
(RL 0) 3 3 3 3 3 3
(LR 0.5) 3 3 3 3 3 3
(RL 1) 3 3 3 3 3 3
title: how to change X step size
{{% /causal_diagram %}}
Multi-person passes
{{% causal_diagram %}}
3b 3b 3 3 3b 3b 3 3
3a 3a 3c 3c 3a 3a 3c 3c
3 3 3b 3b 3 3 3b 3b
{{% /causal_diagram %}}
When the pattern involves multiple jugglers, you define whom you are passing to by using 'a', 'b', etc. instead of 'p'.
Bars
{{% causal_diagram %}}
3p 3 4p 2 3 3 3p
3p 3 3 3p 2 3 3p
title: An early double in 3 count
bars:2.5,5.5
{{% /causal_diagram %}}
You can add bars at certain positions to make reading the pattern easier.
Lines styles
You can change the linestyle by adding certain characters at the end of a value. Allowed symbols are ",#><^*".
{{% causal_diagram %}}
3p> 3 3 3p^ 4, 2 3p
3p< 3 3 3p@ 3 3 3p*
{{% /causal_diagram %}}
Positions (static)
You can also define positions to get a diagram of where people should stand.
{{% causal_diagram %}}
3p 3 3 3p 3 3
3p 3 3 3p 3 3
position A: -100,0,0;
position B: +100,0,180
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
Positions need to be defined for each juggler for a position diagram to show up.
Once positions are defined, all passes will be animated in the diagram.
Positions are relative to a center position in the diagram. You can either specify 2 numbers as ΔX and ΔY or 3 numbers. In which case the last number is the orientation of the juggler (0=looking to the right, 180 looking to the left).
Predefined positions
For many patterns, people either stand in a line opposite each other or in a circle. You can use the following shortcuts for this:
Circle
{{% causal_diagram %}}
step_Y:30
step_X:30
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
positions: circle
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
Line
{{% causal_diagram %}}
step_Y:30
step_X:30
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
positions: line
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
Positions (walking)
You can also define walking patterns.
{{% causal_diagram %}}
3d 3 3 3 3 3
3c 3 3 3 3 3
3a 3 3 3 3 3
3b 3 3 3 3 3
title: Y (walking, 6 count)
position A: 0,-100,0,0; 6,-200,+100,0; 12,-300,0,0; 18,-200,-100,0; 24,-100,0,0;
position B: 0,-300,0,0; 6,-200,-100,0; 12,-100,0,0; 18,-200,+100,0; 24,-300,0,0;
position C: 0,+200,100,180; 6,+100,0,180; 12,200,-100,180; 18,+300,0,180; 24,200,100,180;
position D: 0,+200,-100,180; 6,+300,0,180; 12,200,+100,180; 18,+100,0,180; 24,200,-100,180;
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
In this case you need to always specify 4 values and specify multiple positions that are separated by ";".
The first number now specifies a time step. The last time step should be the same for every juggler. If the number of time steps is larger than the number of beats in the diagram. The pattern will just repeat. However the largest time step should be a multiple of the number of beats in the pattern.
Note that the number of positions for each juggler can vary.
Currently, the last position should be the same as the first to achieve a smooth pattern.
Dynamic angles with @ notation
Instead of specifying a fixed angle (like 0 or
180), you can use @ notation to make a
juggler automatically face toward a specific target. The angle will
be calculated dynamically based on the juggler's current
position.
Syntax
@0- face toward the center (origin)@A- face toward juggler A@B- face toward juggler B- etc.
Example:
position D: 0,100,0,@A; 4,100,50,@A; 8,100,0,@B
This makes juggler D face toward juggler A for the first two keyframes, then face toward juggler B at the third keyframe.
Rotation direction
By default, jugglers always rotate the shortest way when transitioning between angles. For example, rotating from 10° to 350° will go clockwise (+20°) rather than counterclockwise (-340°).
To force rotation the long way, add
! after the angle specification:
@A!- face toward A, but rotate the long way to get there@B!- face toward B, but rotate the long way to get there
Example:
position D: 0,100,0,0; 4,100,0,@A!
This forces juggler D to rotate the long way (340° instead of 20°) when turning to face A.
The ! flag works with both @ notation
and numeric angles. The normalization always happens between
consecutive keyframes, so the flag should be placed on the
target keyframe you're rotating toward.
Formatting
Comments
You can leave comments in the code starting with #
{{% causal_diagram %}}
step_Y:30 # an inline comment
step_X:30
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
3 3 3
# a comment on its own line
positions: line
{{% /causal_diagram %}}
Continuation lines
If lines get too long, you can break them up into multiple lines by using the '\' character at the end.
{{% causal_diagram %}}
3d 3 3 3 3 3
3c 3 3 3 3 3
3a 3 3 3 3 3
3b 3 3 3 3 3
title: Y (walking, 6 count)
position A: 0,-100,0,0; \
6,-200,+100,0; \
12,-300,0,0; \
18,-200,-100,0; \
24,-100,0,0;
position B: 0,-300,0,0; 6,-200,-100,0; 12,-100,0,0; 18,-200,+100,0; 24,-300,0,0;
position C: 0,+200,100,180; 6,+100,0,180; 12,200,-100,180; 18,+300,0,180; 24,200,100,180;
position D: 0,+200,-100,180; 6,+300,0,180; 12,200,+100,180; 18,+100,0,180; 24,200,-100,180;
{{% /causal_diagram %}}
Silent beats
A - marks a beat where a juggler does nothing (idle
or holding a club). It renders as a faint dashed circle.
{{% causal_diagram %}}
3 - 3 3
3 3 3 3
{{% /causal_diagram %}}
Steals, hand-ins, and zips
Sparse actions are written in an inline event block
(<beats>: <time> <action>; ...) that
takes the place of grid tokens. Times are relative to the start of
the block and can be fractional. Transfers use
source>destination, each side
[juggler][hand], with your own juggler implied when
omitted:
steal b>L— intercept B's club in flight, catch with the left handsteal cR>L— take the club held in C's right handhand R>cL— place your right-hand club into C's left handzip L>R— hand-across, own left to own rightthrow 3a R— a normal throw at an off-grid timecatch L— marks the receiving hand of an incoming pass (only needed when the catcher has no grid circle at that beat)flip— flip both clubs in place, shown as an F circle (no arrows)
The victim of a steal writes their line as if the pass were normal — the steal reroutes the arrow. A thin grey line shows a juggler carrying a club between a catch and the next release.
{{% causal_diagram %}}
3b 3 3 3
3a 3 3 3
(RL 1) (3: 0 steal a>L; 0.25 hand R>bL; 0.5 zip L>R)
{{% /causal_diagram %}}
Arrow labels
Attach a quoted text to any throw or event and it is drawn next to the arrow (in both diagrams):
{{% causal_diagram %}}
3b"lofty" 3 3 3
3a 3 3"chop" 3
{{% /causal_diagram %}}
Moving patterns: roles and swaps
For patterns where people rotate through positions, write the
pattern lines for the roles over one short cycle and
add a swap: line. swap: A->B means:
whoever is doing line A does line B in the next cycle (the last role
wraps around to the first, and independent chains can be separated by
commas). The diagram unrolls automatically until everyone is back in
their starting role; rows are labeled by person (named after their
starting role), and pass targets always mean "whoever is in that
role".
{{% causal_diagram %}}
swap: A->B
3b 3 3 3
3a 3 3 3
{{% /causal_diagram %}}
Positions can carry a role name, written as position
A("feeder"): .... The name is shown below the juggler in the
position diagram, and with swap: it follows the role:
whoever currently occupies the position shows its label.
{{% causal_diagram %}}
swap: A->B
3b 3 3 3
3a 3 3 3
position A("feeder"): 0, -100, 0, 0; 8, -100, 0, 0;
position B("feedee"): 0, 100, 0, 180; 8, 100, 0, 180;
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
Snapshots
For patterns where it helps to see the key moments as still
images, a snapshots: line renders static views of the
position diagram at the given beats, below the animated diagrams.
Each snapshot shows the jugglers where they are at that moment plus
every club in the air and transfer happening around it. Requires
positions.
{{% causal_diagram %}}
3b 3 3 3
3a 3 3 3
position A: -100, 0, @B
position B: 100, 0, @A
snapshots: 0.5, 2
{{% /causal_diagram %}}
Pattern Diagram
Position Diagram
Snapshots
More on long lines
Besides the \ continuation above, a line continues
automatically while a parenthesis is still open, so an event block
can be split over several lines without any marker:
{{% causal_diagram %}}
3b 3 3 3
3a 3 3 3
(RL 1) (3: 0 steal a>L;
0.25 hand R>bL;
0.5 zip L>R)
{{% /causal_diagram %}}