Euclidean rhythms (Bjorklund) with Toussaint evenness, Keith syncopation, and Pressing rhythmic oddity, in pure Python.
Project description
euclidean-rhythm
Generate Euclidean rhythms and analyze them with standard geometric measures, in pure Python with zero dependencies.
What are Euclidean rhythms?
Euclidean rhythms distribute k onsets as evenly as possible over n time steps using
Bjorklund's algorithm - the same Euclidean GCD logic that underlies many traditional
musical patterns worldwide.
The son clave (3 onsets, 8 steps): x . . x . . x .
The bossa nova clave (5 onsets, 8 steps): x . x x . x x .
Install
pip install euclidean-rhythm
PyPI release pending. Install from source:
git clone https://github.com/amaar-mc/euclidean-rhythm cd euclidean-rhythm pip install -e .
Quick start
from euclidean_rhythm import (
euclidean,
evenness,
inter_onset_intervals,
ioi_histogram,
necklace,
offbeatness,
onset_positions,
pattern_from_onsets,
rhythmic_oddity,
rotate,
syncopation,
)
# Generate rhythms
son = euclidean(pulses=3, steps=8)
# [1, 0, 0, 1, 0, 0, 1, 0]
bossa = euclidean(pulses=5, steps=8)
# [1, 0, 1, 1, 0, 1, 1, 0]
# Rotate
rotate(son, steps=2)
# [0, 1, 0, 0, 1, 0, 1, 0]
# Canonical necklace form (rotation-invariant)
necklace(son) == necklace(rotate(son, steps=3))
# True
# Evenness (1.0 = maximally even)
evenness(euclidean(pulses=4, steps=8))
# 1.0
# Keith syncopation (0 = no syncopation)
syncopation(euclidean(pulses=4, steps=8))
# 0
# Pressing rhythmic oddity
rhythmic_oddity(son)
# True
# Off-beat onset count (Toussaint offbeatness)
offbeatness(son)
# 1 -- onset at position 3 is off-beat in n=8; 0 and 6 are on-beat
# Inter-onset intervals (gaps in pulses, wrapping)
inter_onset_intervals(son)
# [3, 3, 2] -- sums to 8
# Histogram of inter-onset intervals
ioi_histogram(son)
# {3: 2, 2: 1}
# Convert between 0/1 pattern and onset-position list
onset_positions(son)
# [0, 3, 6]
pattern_from_onsets(positions=[0, 3, 6], steps=8)
# [1, 0, 0, 1, 0, 0, 1, 0]
CLI
euclidean-rhythm 3 8
# x..x..x.
euclidean-rhythm 5 8
# x.xx.xx.
API
All parameters are keyword-only.
| Function | Description |
|---|---|
euclidean(*, pulses, steps) |
Generate Euclidean rhythm (Bjorklund's algorithm) |
rotate(rhythm, *, steps) |
Rotate left by steps (mod len) |
necklace(rhythm) |
Lexicographically minimal rotation (canonical form) |
evenness(rhythm) |
Toussaint geometric evenness in (0, 1] |
syncopation(rhythm) |
Keith (1991) syncopation count |
rhythmic_oddity(rhythm) |
Pressing (1983) rhythmic oddity property |
offbeatness(rhythm) |
Count of onsets on off-beat positions (gcd-coprime to n) |
inter_onset_intervals(rhythm) |
Gaps in pulses between consecutive onsets, wrapping |
ioi_histogram(rhythm) |
Histogram of inter-onset interval lengths |
onset_positions(rhythm) |
Indices of onsets in a 0/1 pattern |
pattern_from_onsets(*, positions, steps) |
Build 0/1 pattern from onset indices |
Measures defined
Evenness (Toussaint 2005): Place onsets on a unit circle; sum all pairwise chord lengths; normalize by the maximum (equally spaced onsets). Score 1.0 means maximally even.
Syncopation (Keith 1991): Metric weight of position i is n for the downbeat
(i=0) and the largest power of 2 dividing i for i>0. A syncopation occurs when
an onset at a weak beat is followed by a rest at a stronger beat; the score accumulates
the weight difference.
Rhythmic oddity (Pressing 1983): True if no two onsets are diametrically opposite on the rhythm circle (no pair partitions the cycle into two equal halves).
Offbeatness (Toussaint): For a cycle of n pulses, position p is off-beat iff gcd(p, n) == 1 -- equivalently, p is not covered by any regular subdivision of the cycle (union of {k*n/d} for proper divisors d of n). Offbeatness is the count of onsets at such positions. Both characterizations produce identical off-beat sets, verified for n in 2..64.
Inter-onset intervals: The sequence of gaps (in pulses) between consecutive onsets around the cycle, wrapping from the last onset back to the first. Always sums to n.
References
- Bjorklund, E. (2003). The theory of rep-rate pattern generation in the SNS timing system.
- Toussaint, G. (2005). The Euclidean algorithm generates traditional musical rhythms. BRIDGES.
- Keith, M. (1991). From Polychords to Polya: Adventures in Musical Combinatorics.
- Pressing, J. (1983). Cognitive isomorphisms between pitch and rhythm in world musics. Studies in Music.
License
MIT. Copyright (c) 2026 Amaar Chughtai.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file euclidean_rhythm-0.2.0.tar.gz.
File metadata
- Download URL: euclidean_rhythm-0.2.0.tar.gz
- Upload date:
- Size: 936.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0ee5fd2204b734ddfae641e9e747576b111333991edccc711c7b8aa9938f230
|
|
| MD5 |
b9ffb1187004c85c506d6354470497cf
|
|
| BLAKE2b-256 |
a79138ba8cf8ca38cc594fff2349a1334fa6db7b6902fd4773bf2f5793ec20fb
|
File details
Details for the file euclidean_rhythm-0.2.0-py3-none-any.whl.
File metadata
- Download URL: euclidean_rhythm-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c90ab27d30401fe1595da2410772fff897f64014e5a9299932c59cc68d040db
|
|
| MD5 |
436173272b51977a0045c36dbf25ac05
|
|
| BLAKE2b-256 |
a160586dd137de3605b701dff1ffc7fc3b991e1c2245ca7fd5425fcf946cdffe
|