Use HAMON
HAMON ships as a Python library, hamonpy, with a
hamon command line tool. It reads harmony out of any supported encoding
into one typed model, and writes that model back out to any other.
hamonpy is on
PyPI, so the install below is all you
need. The standard itself — the grammar, the conformance corpus, the documentation
— is in the public repository,
which is also where this site is served from. That repository is a published snapshot of
a private working one, so pull requests have nowhere to land:
open an issue
instead. A label HAMON reads wrong, a format that loses something it should not, a
missing encoding — that is the way to reach us, and we read them.
1 · Install
Python 3.10 or newer. The library itself has a single dependency, the ANTLR runtime.
pip install hamonpy
Prefer an environment of its own? Either of these gets you to the same place:
# conda
conda create -n hamon python=3.11 -y
conda activate hamon
python -m pip install hamonpy
# venv, from the standard library
python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install hamonpy
Two habits are worth keeping here. Give conda create an
explicit python=3.11: without it conda builds an environment with no
interpreter in it at all, and every command you type afterwards quietly falls through to
whatever Python your shell already had. And write python -m pip rather than
plain pip, which guarantees you install into the interpreter you are about
to run. Get either of them wrong and the symptom is the same puzzling pair:
pip reports “Requirement already satisfied” while python
answers ModuleNotFoundError: No module named 'hamonpy'.
Optional extras bring in the ecosystems HAMON can read from and write
to: pip install "hamonpy[music21,ms3,partitura]". Installing from a checkout
instead? The package lives in the hamonpy/ subdirectory, so point pip at
./hamonpy rather than at the repository root.
2 · Parse a progression
A HAMON file is one label per line, under a header saying which system they are in. Parsing gives you a typed sequence that serializes to JSON and round-trips back to the exact glyphs you started from.
from hamonpy.parse import parse_hamon_sequence
from hamonpy.serialize import sequence_to_json, sequence_to_hamon_text
seq = parse_hamon_sequence("@cs\nCmaj7\nAm7\nDm7\nG7")
print(sequence_to_json(seq)) # the canonical JSON
print(sequence_to_hamon_text(seq)) # back to the surface, unchanged
3 · Convert between encodings
Reading a real file needs no more than this. The format is detected from the extension, or you can name it.
from hamonpy.cli import convert_file
seq = convert_file("song.mei") # MEI, MusicXML, Humdrum, DCML, Harte…
seq = convert_file("changes.lab", "harte")
4 · Or from the command line
hamon convert changes.tsv # any supported format → canonical HAMON JSON
hamon export song.mei --to harte # one encoding → another, through HAMON
hamon report song.mei --to harte # the same, and name everything the target loses
hamon validate corpus.hamon --strict # corpus QA: opaque labels, position warnings
The export prints the target's own vocabulary, nothing smuggled:
$ hamon export song.mei --to harte
C:min7
F:7
Bb:maj7
Eb:maj7
A:min7
Swap export for report and you get the same
conversion plus a field-by-field account of what that encoding could not carry — the
measurement behind the ICCCM'26 page.
5 · Next
The checkout carries the full documentation, also bundled as a single PDF: a tutorial from one chord to a positioned analysis, a per-format cookbook, the complete command reference, and the grammar. The loss viewer shows what every encoding does with the same music, and the fixture corpus is the conformance suite, browsable.
Please cite the paper if you use HAMON in your work — see how to cite. The code is Apache-2.0 and the standard and its data are CC BY 4.0.