Skip to main content

holonomy-harmony

🎼 Chord progression analysis via holonomy — detect modulations, modal interchange, and cycle violations in harmony.

Holonomy-harmony proves that harmonic movement = cycle consistency. A chord progression has zero holonomy when it returns to its tonal center. When it doesn't, you've detected a modulation. This is constraint theory applied to music theory: the circle of fifths is a topological space, and chord progressions trace paths through it.

Why it exists

Music theory has always had an implicit spatial structure — the circle of fifths, the line of fifths, voice-leading spaces. But the connection between harmonic motion and topological holonomy (the "did you end up where you started?" invariant) hasn't been made explicit in a tool. This library makes that connection executable: every chord progression gets a holonomy number, and that number tells you exactly how "far from home" the harmony wandered.

The math in plain English

Holonomy measures whether a closed loop through a space returns you to the same orientation you started with. On the circle of fifths, each chord transition moves you clockwise (dominant direction) or counter-clockwise (subdominant direction). If you sum all those movements and get zero, the progression is tonally consistent — it returned home. If the sum is non-zero, you modulated.

Winding number counts how many full rotations around the circle of fifths the progression makes. A I-IV-V-I progression winds zero times. Coltrane's Giant Steps winds multiple times due to its major-third cycles.

Stability score (0–1) measures how "safe" a progression is: 1.0 = entirely diatonic, zero holonomy. 0.0 = highly chromatic with multiple modulations.

Quick start

pip install holonomy-harmony
from holonomy_harmony import analyze_progression, PROGRESSIONS

# Analyze the Pachelbel Canon progression in D major
symbols, tonic, mode = PROGRESSIONS["pachelbel_canon"]
result = analyze_progression(symbols, key_tonic=tonic, mode=mode)

print(f"Holonomy: {result.holonomy.holonomy}")        # -5
print(f"Winding:  {result.holonomy.winding_number}")   # 0.0833
print(f"Type:     {result.holonomy.progression_type}") # ProgressionType.MODULATION
print(f"Stability: {result.stability_score}")           # 0.35

# Analyze Giant Steps — much more adventurous
symbols, tonic, mode = PROGRESSIONS["giant_steps"]
result = analyze_progression(symbols, key_tonic=tonic, mode=mode)
print(f"Type:     {result.holonomy.progression_type}")  # ProgressionType.CHROMATIC
print(f"Stability: {result.stability_score}")            # lower

Output:

Holonomy: -5
Winding:  0.08333333333333333
Type:     ProgressionType.MODULATION
Stability: 0.35

Type:     ProgressionType.CHROMATIC_MEDIANT
Stability: 0.377

API overview

High-level: analyze_progression

from holonomy_harmony import analyze_progression

result = analyze_progression(
    symbols=["I", "vi", "IV", "V"],  # Roman numerals
    key_tonic=0,                      # C
    mode="major",                     # major or minor
    wrap=False,                       # treat as closed cycle?
)
# result.chords            -> List[Chord]
# result.holonomy          -> HolonomyResult
# result.graph             -> TonalGraph
# result.modulations       -> List[(index, description)]
# result.modal_interchanges -> List[(index, description)]
# result.stability_score   -> float (0.0-1.0)

Holonomy computation

from holonomy_harmony import compute_holonomy, winding_number, classify_progression

roots = [0, 7, 9, 5, 0]  # C, G, A, F, C

h = compute_holonomy(roots, wrap=True)
print(h.holonomy)       # net circle-of-fifths displacement
print(h.winding_number) # full rotations
print(h.max_deviation)  # furthest wander from tonic
print(h.is_consistent())# True if holonomy == 0

print(winding_number(roots))    # shortcut
print(classify_progression(roots))  # ProgressionType enum

Roman numeral parsing

from holonomy_harmony import parse_roman

chord = parse_roman("V7/vi", key_tonic=0, mode="major")
# Chord(root=10, quality='7', function='V7/vi',
#        is_secondary_dominant=True, implied_key=(9, 'major'))

Tonal graph

from holonomy_harmony import TonalGraph

g = TonalGraph()
g.build_from_progression([0, 7, 9, 5, 0])
print(g)  # <TonalGraph nodes=12 edges=4 total_weight=4.0>
print(g.adjacency_matrix())  # 12×12 transition matrix
print(g.transition_probability(0, 7))  # P(G|C)

Built-in progressions

20 famous progressions included:

from holonomy_harmony import PROGRESSIONS

for name in PROGRESSIONS:
    symbols, tonic, mode = PROGRESSIONS[name]
    print(f"{name}: {' '.join(symbols)}")

Includes: pachelbel_canon, blues_12_bar, giant_steps, chopin_em_prelude, axis_progression, autumn_leaves, coltrane_changes, rhythm_changes, hey_jude, creep, take_five, and more.

Architecture

┌─────────────┐    ┌───────────────┐    ┌──────────────┐
│  analyzer.py│───>│ cycle_checker │───>│ tonal_graph  │
│             │    │               │    │              │
│ parse_roman │    │ compute_      │    │ TonalGraph   │
│ analyze_    │    │ holonomy      │    │ Transition   │
│ progression │    │ winding_      │    │ Direction    │
│ detect_     │    │ number        │    │ adjacency    │
│ modulations │    │ classify_     │    │ matrix       │
│ score_      │    │ progression   │    │              │
│ stability   │    │ HolonomyResult│    │              │
└─────────────┘    └───────────────┘    └──────────────┘

Input: Roman numerals → Chord objects → pitch-class roots
Process: roots → circle-of-fifths steps → holonomy signature
Output: HolonomyResult + stability score + modulation list

Documentation

Related repos

Requirements

  • Python 3.10+
  • No external dependencies (pure Python)

Install

pip install holonomy-harmony

Or from source:

git clone https://github.com/SuperInstance/holonomy-harmony.git
cd holonomy-harmony
pip install -e .

License

Apache License 2.0

Metadata

Release files for holonomy-harmony 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for holonomy-harmony 0.1.0
File Size Uploaded Provenance Actions
holonomy_harmony-0.1.0.tar.gz 19.0 kB Without provenance Details for holonomy_harmony-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for holonomy-harmony 0.1.0
File Interpreter ABI Platform Actions
holonomy_harmony-0.1.0-py3-none-any.whl Python 3 none any Details for holonomy_harmony-0.1.0-py3-none-any.whl

Total release size: 33.2 kB

Release files / holonomy_harmony-0.1.0.tar.gz

Download URL holonomy_harmony-0.1.0.tar.gz
Size 19.0 kB
Tags Source
SHA-256 checksum
How to use checksums
84310414c9ec2a15f6a8cc4576a44a5841484eaeee6e1edb6d844eb2b2c18fc7
BLAKE2b-256 checksum
How to use checksums
b6cfcbde5f92b217fb23f64d418edc777a406805e7eac03c8d51865374e35d66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / holonomy_harmony-0.1.0-py3-none-any.whl

Download URL holonomy_harmony-0.1.0-py3-none-any.whl
Size 14.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
800acca77b4f3a480acb01318e08739b267a2117411afeea438d68163054af96
BLAKE2b-256 checksum
How to use checksums
a719a2e75daa7f1b34aedeca945e3cb948d0221259b96c6845bb858f2b6d9cf2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Security for holonomy-harmony 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page