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:

A: R L R L R L R L B: R L R L R L R L

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.

A: R L R L R B: L R L R L C: L L R R L D: W O M B L

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:

how to do offsets A: R L R L R L B: L R L R L R C: R L R L R L

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 %}}
    

how to change Y step size A: R L R L R L B: L R L R L R C: R L R L R L

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 %}}
    

how to change X step size A: R L R L R L B: L R L R L R C: R L R L R L

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

A: R L R L R L R L B: R L R L R L R L C: R L R L R L R L

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.

An early double in 3 count A: R L R L R L R B: R L R L R L R

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 %}}

    

A: R L R L R L R B: R L R L R L R

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

A: R L R L R L B: R L R L R L

Position Diagram

A B

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

A: R L R B: R L R C: R L R D: R L R E: R L R F: R L R

Position Diagram

A B C D E F

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

A: R L R B: R L R C: R L R D: R L R E: R L R F: R L R

Position Diagram

A B C D E F

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

Y (walking, 6 count) A: R L R L R L B: R L R L R L C: R L R L R L D: R L R L R L

Position Diagram

A B C D

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 %}}
    

A: R R L B: R L R L

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 hand
  • steal cR>L — take the club held in C's right hand
  • hand R>cL — place your right-hand club into C's left hand
  • zip L>R — hand-across, own left to own right
  • throw 3a R — a normal throw at an off-grid time
  • catch 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 %}}
    

A: R L R L B: R L R L C: L R L R L

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 %}}
    

A: R L R L B: R L R L lofty chop

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 %}}
    

A: R L R L R L R L B: R L R L R L R L

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

A: R L R L R L R L B: R L R L R L R L

Position Diagram

A feeder feedee B feedee feeder

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

A: R L R L B: R L R L

Position Diagram

A B

Snapshots

beat 0.5
A B
beat 2
A B

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 %}}