Files
pytheory/examples/chord_charts.py
T
kennethreitz 6c83dbe5aa Low-to-high fingerings by default (high_to_low opt-out) — v0.43.0
Fretboard string lists and Fingering positions/string-names now read
low-to-high (lowest-pitched string first), matching how chord diagrams
and tablature are conventionally written. Pass high_to_low=True to any
fretboard constructor to restore the pre-0.43 high-to-low behavior.

Design: each board keeps a private canonical (high-to-low) tone store
so the fingering scorer and GUITAR_OVERRIDES table stay untouched; a
single _orient() helper re-orients at the user-facing boundary (and,
being self-inverse, also canonicalizes custom tuning/position input).
Fingering carries its own orientation flag and presents oriented
positions/names via properties. The fingering cache key now includes
orientation so the two orderings don't collide.

to_tab() and Part.strum() now sort by pitch internally, so their output
is identical regardless of board orientation.

- All 25 instrument presets gain a high_to_low param, routed through a
  canonical build path.
- Tests updated for the new default; added orientation-specific tests.
- Docs/examples flipped to low-to-high; chord_charts.py example now uses
  the built-in Fingering.tab() instead of a hand-rolled renderer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 10:42:11 -04:00

50 lines
1.8 KiB
Python

from pytheory import Fretboard, CHARTS
# Standard guitar fretboard. Since v0.43.0 fingerings read low to high
# (low E first) by default — exactly how tab is conventionally written.
fretboard = Fretboard.guitar()
# Define flat to sharp note mappings (updated to include all possible flats)
flat_to_sharp = {"Ab": "G#", "Bb": "A#", "Db": "C#", "Eb": "D#", "Gb": "F#"}
# Add sharp to flat mappings
sharp_to_flat = {v: k for k, v in flat_to_sharp.items()}
# Get all available chords from CHARTS
all_chords = sorted(CHARTS["western"].keys())
print("Standard Guitar Chord Charts:")
print("-" * 30)
for chord_name in all_chords:
# Store original chord name for lookup
lookup_name = chord_name
# Convert flat notation to sharp only for display
base_note = chord_name.rstrip("dim7956maj")
if base_note in flat_to_sharp:
# Replace the base note with its sharp equivalent for display only
sharp_base = flat_to_sharp[base_note]
sharp_name = chord_name.replace(base_note, sharp_base)
print(f" Converting {chord_name} to {sharp_name}") # Debug line
display_name = sharp_name
else:
display_name = chord_name
chord = CHARTS["western"][lookup_name] # Use original name for lookup
try:
fingering = chord.fingering(fretboard=fretboard)
print(f"\n{display_name}:")
print(fingering.tab())
except Exception as e:
print(f"{display_name}: Unable to calculate fingering - {str(e)}")
# Add more detailed debug information
print(f"Debug - Chord data: {chord}")
print(
f"Debug - Chord tones: {chord.tones if hasattr(chord, 'tones') else 'No tones available'}"
)
print(f"Debug - Fretboard tuning: {[str(t) for t in fretboard.tones]}")
print(f"Debug - Available fretboard tones: {[str(t) for t in fretboard.tones]}")