| Title: | Juggling Pattern Validation and Visualisation |
|---|---|
| Description: | Validate and visualise juggling patterns expressed in siteswap notation. Supports vanilla, synchronous, multiplex, synchronous multiplex, and passing siteswap, with tools to check pattern validity and to retrieve raw throw data for custom visualisations. Patterns can be plotted as timeline arc diagrams or ladder diagrams, and animated via the 'JugglingLab' animation server (<https://jugglinglab.org/html/animinfo.html>). |
| Authors: | Ella Kaye [aut, cre, cph] |
| Maintainer: | Ella Kaye <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.0.0.9000 |
| Built: | 2026-07-06 12:49:57 UTC |
| Source: | https://github.com/EllaKaye/jugglr |
Generates an animated GIF of a juggling pattern via the
JugglingLab GIF server and
displays it in the RStudio viewer (or default browser). If path is given
the GIF is saved to disk instead.
animate( pattern, colors = NULL, prop = NULL, bps = NULL, width = NULL, height = NULL, fps = NULL, slowdown = NULL, ..., path = NULL )animate( pattern, colors = NULL, prop = NULL, bps = NULL, width = NULL, height = NULL, fps = NULL, slowdown = NULL, ..., path = NULL )
pattern |
A siteswap pattern string (e.g. |
colors |
Optional. A vector of R colours (one per prop), or one of the
special strings |
prop |
Prop type: |
bps |
Beats per second (numeric scalar). Controls the animation speed. |
width, height
|
Width and height of the animation in pixels (numeric scalars). |
fps |
Frames per second (numeric scalar). |
slowdown |
Slowdown factor (numeric scalar). The JugglingLab default is
|
... |
Additional named arguments passed to the JugglingLab GIF server.
Pattern-setting arguments include |
path |
Path to save the GIF (must end in |
Note that setting colors can introduce a short delay while the server
renders the animation.
Invisibly returns the path to the temporary HTML file (when
displaying) or the save path (when path is given).
## Not run: animate("531") animate(vanillaSiteswap("531"), prop = "ring", bps = 5) animate("531", path = tempfile(fileext = ".gif")) ## End(Not run)## Not run: animate("531") animate(vanillaSiteswap("531"), prop = "ring", bps = 5) animate("531", path = tempfile(fileext = ".gif")) ## End(Not run)
Produces a ladder diagram showing prop paths between hands across beats. The rails represent the hands and the rungs represent the beats. Each throw connects to its catch: cross-hand throws are drawn as straight segments between the rails, while same-hand throws curve back to the same rail. Throws are coloured by prop using the colour-blind-friendly Okabe-Ito palette (a ggplot2 default scale is used beyond seven props), and beat numbers are labelled along the axis.
ladder( siteswap, n_cycles = 3, direction = c("horizontal", "vertical", "h", "v"), title = TRUE, subtitle = TRUE, ... )ladder( siteswap, n_cycles = 3, direction = c("horizontal", "vertical", "h", "v"), title = TRUE, subtitle = TRUE, ... )
siteswap |
A vanillaSiteswap, synchronousSiteswap, multiplexSiteswap, synchronousMultiplexSiteswap, or passingSiteswap object. |
n_cycles |
Number of complete cycles to simulate (default 3). |
direction |
Orientation of the diagram: |
title |
Logical. If |
subtitle |
Logical. If |
... |
Additional arguments passed to methods. For |
ladder() is an S7 generic. There are methods available for the following
classes:
jugglr::multiplexSiteswap
jugglr::passingSiteswap
jugglr::synchronousMultiplexSiteswap
jugglr::synchronousSiteswap
jugglr::vanillaSiteswap
Where multiplex throws overlap (e.g. [33]), the lines fan apart slightly
so they are visible. Passing patterns use one pair of rails per juggler,
spaced by hand_gap and throws between jugglers cross between the rails.
The result is a standard ggplot2 object, so beyond the title and subtitle
toggles you can modify it by adding any ggplot2 function, for example
ggplot2::labs() or ggplot2::scale_colour_manual().
A ggplot2 object.
The siteswap constructors, e.g. siteswap() and vanillaSiteswap().
Other siteswap visualisation:
throw_data(),
timeline()
# Vanilla: straight cross-hand throws, curved same-hand throws ladder(siteswap("423")) # Synchronous: even-only beat numbering, crossing denoted by "x" ladder(siteswap("(4,2x)(2x,4)")) ladder(siteswap("(2,6x)([6x4x],2x)")) # Multiplex: identical simultaneous throws fan into separate curves ladder(siteswap("[33]"), n_cycles = 6) # Passing: one pair of rails per juggler ladder(siteswap("<3p 3|3p 3>")) ladder(siteswap("<4.5 3 3 | 3 4 3.5>")) # Vertical orientation, and customise like any ggplot2 object ladder(siteswap("423"), direction = "v", subtitle = FALSE) + ggplot2::labs(title = "423 or W")# Vanilla: straight cross-hand throws, curved same-hand throws ladder(siteswap("423")) # Synchronous: even-only beat numbering, crossing denoted by "x" ladder(siteswap("(4,2x)(2x,4)")) ladder(siteswap("(2,6x)([6x4x],2x)")) # Multiplex: identical simultaneous throws fan into separate curves ladder(siteswap("[33]"), n_cycles = 6) # Passing: one pair of rails per juggler ladder(siteswap("<3p 3|3p 3>")) ladder(siteswap("<4.5 3 3 | 3 4 3.5>")) # Vertical orientation, and customise like any ggplot2 object ladder(siteswap("423"), direction = "v", subtitle = FALSE) + ggplot2::labs(title = "423 or W")
Creates a multiplex siteswap object from a sequence in which square brackets
group simultaneous throws from the same hand. For example, "[43]1" means
the juggler throws heights 4 and 3 simultaneously on the first beat, then a
single 1 on the second beat. Any slot without brackets is a single throw
exactly as in vanilla siteswap.
multiplexSiteswap(sequence = character(0))multiplexSiteswap(sequence = character(0))
sequence |
A single character string of multiplex siteswap notation,
e.g. |
A multiplexSiteswap S7 object.
@typeAlways "multiplex" (read-only).
@slotsList of integer vectors, one element per time slot. Single-throw slots are length-1 vectors; multiplex slots have length > 1 (read-only).
@throwsInteger vector of all individual throw heights (flattened across all slots) (read-only).
@periodNumber of time slots per cycle (read-only).
@symmetry"symmetrical" when period is odd; "asymmetrical" when
period is even (read-only).
@n_propsTotal of all throw heights divided by the period — the number
of props required. (Note: sum(throws) / period, not mean(throws).)
(read-only).
@can_throwTRUE if for every slot the number of props thrown equals
the number of props landing (no conservation violation) (read-only).
@satisfies_average_theoremTRUE if n_props is a whole number
(read-only).
@validTRUE if both can_throw and satisfies_average_theorem are
TRUE (read-only).
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
passingSiteswap(),
siteswap(),
synchronousMultiplexSiteswap(),
synchronousSiteswap(),
vanillaSiteswap()
multiplexSiteswap("[43]1") multiplexSiteswap("[33]") s <- multiplexSiteswap("[43]1") s@n_props s@validmultiplexSiteswap("[43]1") multiplexSiteswap("[33]") s <- multiplexSiteswap("[43]1") s@n_props s@valid
Creates a passing siteswap object from a multi-juggler sequence in
<A|B> notation. Each section separated by | gives one juggler's throws;
a p suffix (e.g. "3p") marks a throw that passes to the next juggler.
Fractional notation (e.g. "<4.5 3 3 | 3 4 3.5>") is also supported,
where .5 throws are passes and the second juggler is half a beat later.
passingSiteswap(sequence = character(0))passingSiteswap(sequence = character(0))
sequence |
A single character string of passing siteswap notation,
e.g. |
In p-notation, both jugglers are fully synchronised: they throw on the same beat and alternate hands together. In fractional notation, the second juggler is offset by half a beat in the combined timeline.
A passingSiteswap S7 object.
@typeAlways "passing" (read-only).
@is_fractionalTRUE for fractional notation; FALSE for p-notation
(read-only).
@n_jugglersNumber of jugglers (sections in the sequence) (read-only).
@sequences_by_jugglerList of character vectors, one per juggler, each
giving the raw tokens (e.g. c("3p", "3", "3")) (read-only).
@throws_by_jugglerList of numeric vectors, one per juggler, of throw
heights (integers for p-notation; may include .5 for fractional)
(read-only).
@is_pass_by_jugglerList of logical vectors, one per juggler, indicating which throws are passes (read-only).
@periodNumber of throws per juggler per cycle (read-only).
@symmetry"symmetrical" when period is odd; "asymmetrical" when
period is even (read-only).
@n_propsTotal number of props (sum(all throws) / period) (read-only).
@can_throwTRUE if no two throws land on the same
(juggler, beat, hand) triple (no collision) (read-only).
@satisfies_average_theoremTRUE if n_props is a whole number
(read-only).
@validTRUE if both can_throw and satisfies_average_theorem are
TRUE (read-only).
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
multiplexSiteswap(),
siteswap(),
synchronousMultiplexSiteswap(),
synchronousSiteswap(),
vanillaSiteswap()
passingSiteswap("<3p 3 3 3 3 3 | 3p 3 3 3 3 3>") passingSiteswap("<4p 3 | 3 4p>") # Compact and spaced forms are equivalent s1 <- passingSiteswap("<3p33|3p33>") s2 <- passingSiteswap("<3p 3 3 | 3p 3 3>") identical(s1@throws_by_juggler, s2@throws_by_juggler) s <- passingSiteswap("<4p 3 | 3 4p>") s@n_props s@validpassingSiteswap("<3p 3 3 3 3 3 | 3p 3 3 3 3 3>") passingSiteswap("<4p 3 | 3 4p>") # Compact and spaced forms are equivalent s1 <- passingSiteswap("<3p33|3p33>") s2 <- passingSiteswap("<3p 3 3 | 3p 3 3>") identical(s1@throws_by_juggler, s2@throws_by_juggler) s <- passingSiteswap("<4p 3 | 3 4p>") s@n_props s@valid
Creates a typed siteswap object by detecting the notation style of
sequence. Vanilla siteswaps (alphanumeric strings such as "531") produce
a vanillaSiteswap object; synchronous siteswaps in (a,b) notation such
as "(4,2x)*" produce a synchronousSiteswap object; multiplex siteswaps
with square-bracket groups such as "[43]1" produce a
multiplexSiteswap object; passing siteswaps in <A|B> notation such as
"<3p 3 3 3 3 3 | 3p 3 3 3 3 3>" produce a passingSiteswap object.
siteswap(sequence)siteswap(sequence)
sequence |
A single character string of siteswap notation. |
A vanillaSiteswap, synchronousSiteswap, multiplexSiteswap, synchronousMultiplexSiteswap, or passingSiteswap S7 object.
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
multiplexSiteswap(),
passingSiteswap(),
synchronousMultiplexSiteswap(),
synchronousSiteswap(),
vanillaSiteswap()
siteswap("531") siteswap("(4,2x)*") siteswap("[43]1") siteswap("(2,4)([4x4],2x)") siteswap("<3p 3 3 3 3 3 | 3p 3 3 3 3 3>")siteswap("531") siteswap("(4,2x)*") siteswap("[43]1") siteswap("(2,4)([4x4],2x)") siteswap("<3p 3 3 3 3 3 | 3p 3 3 3 3 3>")
Creates a synchronous multiplex siteswap object. This combines synchronous
notation (both hands throw simultaneously, written as pairs in parentheses)
with multiplex notation (square brackets group simultaneous throws from the
same hand). For example, "(2,4)([4x4],2x)" is a 4-prop pattern where the
second slot has hand 0 throwing two balls simultaneously.
synchronousMultiplexSiteswap(sequence = character(0))synchronousMultiplexSiteswap(sequence = character(0))
sequence |
A single character string of synchronous multiplex siteswap
notation, e.g. |
All individual throw heights must be even. An x suffix marks a crossing
throw; a trailing * indicates the pattern alternates between two mirrored
versions.
A synchronousMultiplexSiteswap S7 object.
@typeAlways "synchronous multiplex" (read-only).
@full_sequenceThe expanded sequence with the * shorthand resolved
(read-only).
@throwsCharacter vector of all slot throw strings across one expanded
cycle. Multiplex groups are kept as single elements, e.g. "[4x4]"
(read-only).
@throws_by_handNamed list with elements hand_1 and hand_2, each a
character vector of throw strings per slot (one per sync slot) (read-only).
@periodNumber of throw slots per full cycle (2 × number of sync slots, since both hands throw on every beat; always even) (read-only).
@symmetry"symmetrical" if the pattern is its own mirror image;
"asymmetrical" otherwise (read-only).
@n_propsNumber of props: sum of all throw heights divided by the period (read-only).
@can_throwTRUE if thrown and landing prop counts balance at every
(slot, hand) pair within one cycle (read-only).
@satisfies_average_theoremTRUE if n_props is a whole number
(read-only).
@validTRUE if both can_throw and satisfies_average_theorem are
TRUE (read-only).
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
multiplexSiteswap(),
passingSiteswap(),
siteswap(),
synchronousSiteswap(),
vanillaSiteswap()
synchronousMultiplexSiteswap("(2,4)([4x4],2x)") synchronousMultiplexSiteswap("(4,[42x])*") s <- synchronousMultiplexSiteswap("(2,4)([4x4],2x)") s@n_props s@validsynchronousMultiplexSiteswap("(2,4)([4x4],2x)") synchronousMultiplexSiteswap("(4,[42x])*") s <- synchronousMultiplexSiteswap("(2,4)([4x4],2x)") s@n_props s@valid
Creates a synchronous siteswap object from a two-handed simultaneous-throw
sequence. Synchronous notation describes patterns where both hands throw at
the same time, written as pairs of throw heights in parentheses such as
"(4,4)" or "(4,2x)*". An x suffix marks a crossing throw; a trailing
* indicates the pattern alternates between two mirrored versions.
synchronousSiteswap(sequence = character(0))synchronousSiteswap(sequence = character(0))
sequence |
A single character string of synchronous siteswap notation,
e.g. |
A synchronousSiteswap S7 object.
@typeAlways "synchronous" (read-only).
@full_sequenceThe expanded sequence with the * shorthand resolved
(read-only).
@throwsCharacter vector of all individual throw values across one expanded cycle (read-only).
@throws_by_handNamed list with elements hand_1 and hand_2,
each a character vector of throws for that hand per slot (read-only).
@periodNumber of throw slots per full cycle (counts both hands per simultaneous beat, so always even) (read-only).
@symmetry"symmetrical" if the pattern is its own mirror image;
"asymmetrical" otherwise (read-only).
@n_propsMean of the slide sequence, equal to the number of props (read-only).
@can_throwTRUE if no collisions occur in the slide sequence
(read-only).
@satisfies_average_theoremTRUE if n_props is a whole number
(read-only).
@validTRUE if both can_throw and satisfies_average_theorem are
TRUE (read-only).
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
multiplexSiteswap(),
passingSiteswap(),
siteswap(),
synchronousMultiplexSiteswap(),
vanillaSiteswap()
synchronousSiteswap("(4,4)") synchronousSiteswap("(4,2x)*") s <- synchronousSiteswap("(4,2x)*") s@n_props s@validsynchronousSiteswap("(4,4)") synchronousSiteswap("(4,2x)*") s <- synchronousSiteswap("(4,2x)*") s@n_props s@valid
Returns a data frame describing each throw in the simulated pattern,
including which beat and hand each throw originates from, where it lands,
and which prop is thrown. This underpins timeline() and ladder(), and
can be used directly for custom visualisations.
throw_data(siteswap, n_cycles = 3, ...)throw_data(siteswap, n_cycles = 3, ...)
siteswap |
Any siteswap object: a |
n_cycles |
Number of complete cycles to simulate (default 3). Increase
for patterns with many props to ensure all appear in the data. Setting
|
... |
Additional arguments passed to methods. |
A data frame with one row per throw and columns:
beat: throw beat index
hand: throwing hand (0 or 1)
throw: throw height (integer)
catch_beat: beat on which the prop lands
catch_hand: hand that catches (0 or 1)
prop: prop identifier (integer)
Synchronous types add an is_crossing column. Passing types instead
include juggler, is_pass, and catch_juggler columns identifying which
juggler throws and catches each prop.
The siteswap constructors, e.g. siteswap() and vanillaSiteswap().
Other siteswap visualisation:
ladder(),
timeline()
s <- vanillaSiteswap("531") throw_data(s)s <- vanillaSiteswap("531") throw_data(s)
Produces a timeline (arc) diagram showing the trajectory of each prop across beats. Each arc represents a throw, with height proportional to the throw value and coloured by prop using the colour-blind-friendly Okabe-Ito palette (a ggplot2 default scale is used beyond seven props). The x-axis labels show the throw heights from the siteswap sequence.
timeline(siteswap, n_cycles = 3, title = TRUE, subtitle = TRUE, ...)timeline(siteswap, n_cycles = 3, title = TRUE, subtitle = TRUE, ...)
siteswap |
A vanillaSiteswap, synchronousSiteswap, multiplexSiteswap, synchronousMultiplexSiteswap, or passingSiteswap object. |
n_cycles |
Number of complete cycles to simulate (default 3). A warning is issued if not all props appear within the simulated range. |
title |
Logical. If |
subtitle |
Logical. If |
... |
Additional arguments passed to methods. |
timeline() is an S7 generic. There are methods available for the following
classes:
jugglr::multiplexSiteswap
jugglr::passingSiteswap
jugglr::synchronousMultiplexSiteswap
jugglr::synchronousSiteswap
jugglr::vanillaSiteswap
See Behaviour by siteswap type section below for details on the differences between the resulting plots.
The result is a standard ggplot2 object, so beyond the title and subtitle
toggles you can modify it by adding any ggplot2 function, for example
ggplot2::labs() or ggplot2::scale_colour_manual().
A ggplot2 object.
Vanilla and multiplex patterns are drawn single-sided, with all arcs
above a single baseline. The x-axis labels are the throw heights, and
multiplex labels keep their slot brackets (for example [54]).
Synchronous and synchronous multiplex patterns are drawn two-sided: one hand's arcs sit above a faint centre line and the other hand's arcs sit below it. Each hand gets its own x-axis labels, and the subtitle notes the two-sided layout.
Multiplex patterns (synchronous or not) that throw two or more identical props on the same beat fan those arcs to slightly different peak heights, so otherwise-overlapping throws render as concentric parabolas.
Passing patterns are drawn with one lane per juggler; passes arc between lanes. Fractional notation offsets the beat positions accordingly.
The siteswap constructors, e.g. siteswap() and vanillaSiteswap().
Other siteswap visualisation:
ladder(),
throw_data()
# Vanilla: single-sided arcs timeline(siteswap("423")) # Synchronous: two-sided, hands mirrored about a centre line timeline(siteswap("(4,2x)(2x,4)")) timeline(siteswap("(2,6x)([6x4x],2x)")) # Multiplex: identical simultaneous throws fan to distinct heights timeline(siteswap("[54]24")) timeline(siteswap("[33]")) # Passing: one lane per juggler, with passes arcing between them timeline(siteswap("<3p 3|3p 3>")) timeline(siteswap("<4.5 3 3 | 3 4 3.5>")) # Increasing n_cycles helpful for sequences with short period timeline(siteswap("3"), n_cycles = 6) # ggplot2 object: customise like any other plot timeline(siteswap("423")) + ggplot2::labs(title = "423 or W")# Vanilla: single-sided arcs timeline(siteswap("423")) # Synchronous: two-sided, hands mirrored about a centre line timeline(siteswap("(4,2x)(2x,4)")) timeline(siteswap("(2,6x)([6x4x],2x)")) # Multiplex: identical simultaneous throws fan to distinct heights timeline(siteswap("[54]24")) timeline(siteswap("[33]")) # Passing: one lane per juggler, with passes arcing between them timeline(siteswap("<3p 3|3p 3>")) timeline(siteswap("<4.5 3 3 | 3 4 3.5>")) # Increasing n_cycles helpful for sequences with short period timeline(siteswap("3"), n_cycles = 6) # ggplot2 object: customise like any other plot timeline(siteswap("423")) + ggplot2::labs(title = "423 or W")
Creates a vanilla siteswap object from an alphanumeric siteswap sequence
such as "531" or "97531". Vanilla siteswap describes solo juggling
patterns where one prop is thrown per beat, alternating hands.
vanillaSiteswap(sequence = character(0))vanillaSiteswap(sequence = character(0))
sequence |
A single character string of vanilla siteswap notation
(digits and letters only, e.g. |
A vanillaSiteswap S7 object.
@typeAlways "vanilla" (read-only).
@throwsInteger vector of throw heights for one cycle (read-only).
@periodNumber of throws per cycle (length of throws) (read-only).
@symmetry"symmetrical" when period is odd (pattern repeats with
swapped hands); "asymmetrical" when period is even (read-only).
@n_propsMean throw height, equal to the number of props required (read-only).
@can_throwTRUE if no two throws land on the same beat (no
collisions) (read-only).
@satisfies_average_theoremTRUE if n_props is a whole number
(read-only).
@validTRUE if both can_throw and satisfies_average_theorem are
TRUE (read-only).
The visualisation functions timeline(), ladder() and
throw_data().
Other siteswap constructors:
multiplexSiteswap(),
passingSiteswap(),
siteswap(),
synchronousMultiplexSiteswap(),
synchronousSiteswap()
vanillaSiteswap("531") vanillaSiteswap("97531") s <- vanillaSiteswap("531") s@n_props s@validvanillaSiteswap("531") vanillaSiteswap("97531") s <- vanillaSiteswap("531") s@n_props s@valid