PyTheory is music theory for humans — a Python library that models tones, scales, chords, keys, fretboards, and rhythm in a way people can actually read. It speaks twelve-tone Western harmony fluently, but it isn't limited to it: Indian rāgas, Arabic maqāmāt, gamelan slendro & pelog, 19-TET, and a dozen other tonal systems are first-class citizens, complete with microtonal synthesis.
This playground
Everything on this site is computed live by pytheory on the server — no music theory is re-implemented in JavaScript. Each card cites the API call behind it. Explore:
- Guitar Tab — chord diagrams for six fretted instruments, with custom tunings, capo, and a click-to-edit fretboard that names whatever you finger. Charted chords keep their curated shapes; anything else (F♯m7♭5, Gadd9, C7sus4…) gets a voicing computed from its notes.
- Chord Lab — voicings, inversions, tension, pitch-class set theory, and tritone substitutions for any chord symbol.
- Scales — every scale and mode across sixteen tonal systems, harmonized and playable.
- Keys & Progressions — diatonic chords, borrowed chords, secondary dominants, named progressions, and a modulation planner.
- Ragas — fifty-four rāgas across the Hindustani and Carnatic traditions: aroha & avaroha, pakad, thaat or melakarta, and true shruti just intonation, played on a sitar.
- Maqamat — ten Arabic maqāmāt with their ajnas and seyir, tuned to real quarter-tones — the half-flat neutral intervals a piano can't play, rendered where they actually sit.
- Songwriter — sketch a whole arrangement from a vibe: sections, one hundred drum grooves with fills, chord styles, bass, and fade-out, rendered as audio, MIDI, or engraved sheet music.
- Tools — identify chords from fret positions, analyze progressions, detect keys, transcribe hummed or whistled recordings into notation, and convert MIDI to LilyPond (with PDF engraving), ABC, MusicXML, or tab — complete with a key-detected, Roman-numeral chord timeline of the file.
Install it
Not familiar with uv? It's the fast Python package manager — install it here.
$ uv add pytheory
Then, in a REPL:
>>> from pytheory import Fretboard, CHARTS >>> print(CHARTS["western"]["Cmaj7"].tab(fretboard=Fretboard.guitar()))
Links
- Source on GitHub
- ableton-pytheory — pytheory inside Ableton Live
- pytheory on PyPI
- Documentation
- kennethreitz.org
—
How it’s built root.interval_to(…)
Click the diagram to build your own voicing — clicks above the nut toggle open / muted strings, and a second click on a dot clears it. Whatever you finger, pytheory names it and keeps everything else in sync.
More voicings NamedChord.fingerings(…)
ASCII tab NamedChord.tab(fretboard=…)
On the neck TonedScale / Chord + fretboard, same tuning & capo
Root notes in red. Click any note to hear it. Follows the instrument, tuning, and capo above.
Tuner pytheory.tuner.Tuner · analyze_frame(…)
Tap the stream from your own JS — three lines
const tuner = new EventSource("http://localhost:8123/stream");
tuner.onmessage = (e) => {
const { freq, note, octave, cents, in_tune } = JSON.parse(e.data);
};
Open strings click to hear a reference tone
Allow microphone access, play one string at a time, and tune until the needle centers. Strings light up as you get close.
—
| intervals | |
| pitch classes | |
| Forte number | |
| figured bass | |
| tension | |
| dissonance |
Voicings chord.inversion() · .drop2() · .open_voicing()
Substitutions chord.tritone_sub() · .extensions()
Negative harmony chord.negative_harmony(key)
Mirror the chord across the key's tonic–dominant axis (Ernst Levy / Jacob Collier).
Reharmonize reharmonize(chord, key)
Substitution ideas — tritone sub, diatonic swaps, the secondary dominant that tonicises it, and its negative-harmony mirror.
Neo-Riemannian chord.parallel() · .leading_tone_exchange() · .relative()
The P / L / R transformations — each moves one voice a step to a closely related triad (the moves behind Romantic and film harmony).
Tuning & beats chord.beat_frequencies · Score(temperament=…)
The same chord in four temperaments — equal splits the octave evenly, just locks to pure ratios; listen for the beating.
Beat frequencies
Voice leading chord.voice_leading(other)
Solo over it scale.recommend(…) · chord_scales() · avoid_notes()
Scales that fit this chord's tones — improv starting points.
—
Harmonized scale.harmonize()
On the fretboard fretboard.scale_diagram(scale)
Circle of fifths Key(…).signature · key.relative
Click a key to explore it.
—
Chords by function key.chords_by_function()
Chords in the same family do the same harmonic job — swap one for another.
Circle neighbours key.circle_of_fifths()
A fifth either way shares all but one note — the smoothest places to modulate.
Progression key.progression(…)
Beyond the key key.borrowed_chords · key.secondary_dominant(…)
Borrowed (modal interchange)
Secondary dominants
What next? key.suggest_next(…)
Modulation planner key.modulation_path(…) · key.pivot_chords(…)
Songwriter Score.section(…) · part.arpeggio · part.fade_out · score.drums
One click sketches a whole arrangement — sections, grooves, chords, and a bass line — that you can rework below. pytheory renders the band.
mixer — part levels, reverb, drum feel Part(volume=…, reverb=…) · Score(drum_humanize=…)
Note inspector Tone.solfege · .helmholtz · .overtones(…)
Overtone series why the 7th harmonic sounds "off"
Chord identifier Fingering.identify()
Progression analyzer analyze_progression · find_cadences · check_voice_leading
Non-chord tones analyze_non_chord_tones(melody, chord)
Twelve-tone row ToneRow · .matrix() · .all_forms()
Key detector Key.detect(…)
Audio → LilyPond / ABC / Tab Score.from_wav(…)
Hum a melody, whistle a hook, or record a bass line — monophonic transcription via YIN pitch tracking. WAV, m4a voice memos, and mp3 all work.
MIDI → LilyPond / ABC / Tab Score.from_midi(…)
Chord timeline pytheory analyze song.mid — Key.detect · analyze_progression(secondary_dominants=True)
No MIDI handy? Grab one from the Keys & Progressions tab with the MIDI button.
—
| aroha ascending | |
| avaroha descending | |
| pakad catch-phrase | |
| vadi · samvadi |
Shruti intonation raga.shruti_table(sa) — just vs 12-TET
Each swara's just ratio and how far it sits from the equal-tempered piano (in cents).
—
| ajnas building blocks | |
| seyir melodic journey | |
| degrees |
A ↓ degree is a half-flat — the neutral 2nds, 3rds, 6ths and 7ths a piano can't play, sitting a quarter-tone low. The note names above are only the nearest 12-TET approximations; the table below is the real tuning.
Quarter-tone intonation maqam.maqam_table(tonic) — just vs 12-TET
Each degree's just ratio and how far it sits from the equal-tempered piano (in cents) — Rast's neutral third floats ~45¢ under the tempered E.
Accented downbeat. Runs in your browser with the Web Audio clock.
Tempo trainer pytheory.metronome.Metronome(end_bpm=…)
Ramp the tempo while you practise — start slow, speed up automatically.