Skip to main content

lytk

CI PyPI Python License: MIT

lytk reads and writes symbolic music, and turns it into training data. Scores in LilyPond, MusicXML, MIDI, ABC and Humdrum **kern go through one internal representation, so any format converts to any other. The same scores come out as NumPy note arrays, piano rolls and event sequences, ready for PyTorch or TensorFlow. The core is written in Rust; you use it from Python or from the command line.

Preview release (0.x). Conversion, transforms and the ML pipeline are tested and ready to use. The API can still change before 1.0: notation marks (articulations, ornaments, dynamics) will move from strings to enums.

Why lytk

  • LilyPond is a first-class format. lytk reads real LilyPond files, not a subset: variables, \relative, piano scores with several voices per staff, repeats and voltas, cadenzas, lyrics, chord names and figured bass. It writes them back out too, in any of LilyPond's 12 note-name languages.
  • Conversions are measured, not assumed. Every round trip (LilyPond, MusicXML, ABC, **kern, MIDI) is checked in CI against a test corpus for note counts, pitches, onsets and durations. The results can only improve from one release to the next.
  • Built for machine learning. Encoders for note arrays, piano rolls and Performance-RNN event sequences, objective metrics from the muspy family, datasets over folders or JSON Lines records with deterministic (or the records' own) splits and caching, and padded data loaders for PyTorch and TensorFlow.
  • Fast. A Rust core with prebuilt wheels, and a batch converter that uses every core. It transposes LilyPond about 50× faster than python-ly.

Install

pip install lytk                  # every format, transform and representation
pip install "lytk[torch]"         # + PyTorch datasets and data loaders
pip install "lytk[tensorflow]"    # + tf.data datasets and data loaders
pip install "lytk[eval]"          # + generation-evaluation metrics (scipy, FMD)
pip install "lytk[all]"           # everything above

Wheels are prebuilt for Linux, macOS and Windows and cover CPython 3.10 and newer, so no Rust toolchain is needed. PyTorch and TensorFlow are optional and only imported when you ask for a loader.

Quick start

import lytk

score = lytk.from_musicxml("input.xml")      # or from_lilypond, from_midi, from_abc, from_humdrum
score = lytk.transpose(score, semitones=3)   # also invert, retrograde, change_language
lytk.to_lilypond(score, "output.ly")         # or to_musicxml, to_midi, to_abc, to_humdrum
abc = lytk.to_abc(score)                     # without a path, writers return the text

Check LilyPond before you rely on it:

for d in lytk.check_lilypond(text, semantic=True):   # errors and warnings, in source order
    print(d)                                         # 3:12: error: missing `}` [missing-token]
score = lytk.from_lilypond("score.ly", strict=True)  # raises lytk.LilyPondSyntaxError on an error
score.diagnostics                                    # what the reading reported, either way
score.header                                         # every \header field, as a dict
fields = lytk.header_fields(text)                    # …or read from the text: key, value, span

A reader raises lytk.ParseError (a ValueError) when its input cannot be read, and OSError when the file cannot be opened.

Turn a score into arrays:

doc = score.to_music_document()
notes = lytk.to_note_array(doc)        # (N, 4): onset, duration, pitch, velocity
roll = lytk.to_piano_roll(doc)         # (T, 128)
events = lytk.to_event_sequence(doc)   # Performance-RNN event codes
stats = lytk.compute_metrics(doc)      # pitch-class entropy, polyphony, scale consistency, …

Each encoder has an inverse (from_note_array, …). The arrays are ordinary NumPy arrays, and NumPy supports DLPack, so PyTorch, JAX and CuPy can use them without copying:

import torch
tensor = torch.from_dlpack(lytk.to_piano_roll(doc))   # shares the buffer

Build a dataset from a folder of scores in any mix of formats:

from lytk.datasets import FolderDataset

data = FolderDataset("corpus/", cache_dir=".cache")
train, val, test = data.split((0.8, 0.1, 0.1), seed=0)

loader = train.to_pytorch_dataloader("event_sequence", batch_size=32, shuffle=True)
for events, lengths in loader:         # padded batch plus each item's true length
    ...

Scores differ in length, so each batch is padded. The true lengths come back alongside it because 0 is a valid event, pitch and velocity, so padding alone can't tell you where a score ends. to_tensorflow_dataloader works the same way.

A corpus kept as JSON Lines records (id, text, metadata) keeps its ids and its own splits:

from lytk.datasets import RecordsDataset

data = RecordsDataset.from_jsonl("scores.jsonl", split_field="split", on_error="skip")
splits = data.split()                  # {"train": …, "valid": …, "test": …}, as recorded
loader = splits["train"].to_pytorch_dataloader("note_array", batch_size=32, return_ids=True)
for arrays, lengths, ids in loader:
    ...

The package also installs a lytk command:

lytk convert input.xml -o output.ly           # formats are taken from the extensions
lytk convert corpus/ -o out/ -f xml -j 8      # a whole folder, in parallel
lytk transpose input.ly -s 3 -o up.ly
lytk flatten score.ly -o flat.ly              # inline every \include
lytk check score.ly --semantic                # report the errors of LilyPond files
lytk info input.mxl

It also inverts, reverses, changes note-name languages, compares scores (lytk diff) and runs JSON batch jobs; lytk --help lists every command and docs/cli.md describes them.

Formats

Format Extensions Read Write
LilyPond .ly .ily ✓ ✓
MusicXML .xml .musicxml ✓ ✓
Compressed MusicXML .mxl ✓ ✓
MIDI .mid .midi ✓ ✓
ABC .abc ✓ ✓
Humdrum **kern .krn ✓ ✓

docs/import-export.md lists what each reader and writer keeps. MusicXML is the most complete. MIDI export plays a score the way LilyPond's own MIDI does (dynamics, articulations, grace notes, repeats, pedal, lyrics); slurs and ornaments are not performed.

Not there yet

  • Tablature, unpitched notes and fretboard diagrams (LilyPond drums are read as their General MIDI keys on a percussion staff).
  • Performed MIDI is quantized less reliably when its tempo is far from the file's own, when chords are released unevenly, or at a low resolution.
  • Non-traditional key signatures, cross-staff notes (\change Staff), and Humdrum spine splits (*^, *v). Files that use spine splits are rejected with an error.
  • The ABC and **kern writers produce one stream per staff, so two voices sharing a staff are not kept separate.
  • MEI is planned after 1.0.

Documentation

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md, and SECURITY.md for reporting vulnerabilities.

Acknowledgements

lytk builds on a lot of prior work in music notation software. Its LilyPond parser uses the tree-sitter-lilypond grammar by Nathan Whetsell (MIT, notice in src/tree-sitter/LICENSE). Its design also owes a lot to LilyPond, python-ly, music21, muspy, abjad, symusic and MuseScore.

License

MIT, see LICENSE. The test fixtures are third-party scores under their own terms (tests/fixtures/README.md).

Metadata

Release files for lytk 0.4.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 lytk 0.4.0
File Size Uploaded
lytk-0.4.0.tar.gz 919.4 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for lytk 0.4.0
File
lytk-0.4.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
lytk-0.4.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
lytk-0.4.0-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details
lytk-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
lytk-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
lytk-0.4.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
lytk-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 27.2 MB

Release files / lytk-0.4.0.tar.gz

Download URL lytk-0.4.0.tar.gz
Size 919.4 kB
Tags Source
SHA-256 checksum
How to use checksums
612ed32b55c61137d8749fbd51038323a196f26265b045ef6af2a13157baae52
BLAKE2b-256 checksum
How to use checksums
a9e1bb4605a0061e55487308b46344a27c83a6312c8e7ef585ba8401a3899ae0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-win_amd64.whl

Download URL lytk-0.4.0-cp310-abi3-win_amd64.whl
Size 3.4 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
ab6c0f185bf7ca5c590e28c092bd5425182981f649e4daa1862332d38cd9c555
BLAKE2b-256 checksum
How to use checksums
efa918781323889021665db6a13d5c9333261b3b5651986286f778af1523e3fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL lytk-0.4.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 4.2 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
fb00aa4dd6a8fa6496b10e3153db44f9e364319f6a123d89ba862f22a8c3c619
BLAKE2b-256 checksum
How to use checksums
dcc6cd7842535e4982aab7c5bc802e17491d0062cdf8fbf4f8a0f270b13b7cbd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL lytk-0.4.0-cp310-abi3-musllinux_1_2_aarch64.whl
Size 4.0 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
0dcb522b01347797ce68a9274912120359b5e85316cd93fd10988abb75add4ca
BLAKE2b-256 checksum
How to use checksums
05864a816a2f04aa9809c9bede1a95d2cec30b7ef495afd61f818e3e0d59eb2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL lytk-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.8 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
2c9d1ed902e37aa00f55114472ed330bd5413544f2b2b54b87ac891a2339f8cf
BLAKE2b-256 checksum
How to use checksums
98bdb8003653521079eef943e3de64fd70d45fa88ec5959019cb7e9717bc3c9e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL lytk-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.8 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
cc12f7e4c066f7630665407421c870d7b9bf48e46affe5f0fc140a01ab7564f8
BLAKE2b-256 checksum
How to use checksums
44931f520d6ee3040776969b91958058e1aa14cc748616236b73e61c562a2184
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL lytk-0.4.0-cp310-abi3-macosx_11_0_arm64.whl
Size 3.5 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
85d86dd254d6fe021d0b06fa05fec27723b97a1c64238f5bc9bcd95141ece26f
BLAKE2b-256 checksum
How to use checksums
3996b1f088fe6d55d441f64a3929d40b08eebb0575a27ce7539aeff961662b86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / lytk-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL lytk-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 3.6 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
c0d5aff01a4a7693c8609a765105a975bdb853f2e8fc4cf33cab24548f534a3c
BLAKE2b-256 checksum
How to use checksums
df386540d3da3f245ae371fbdfbf2f4a1570161857e96840ef8fca916a0665ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.0

8 release files

This release

0.4.0 This release

8 release files

0.3.0

8 release files

0.2.0

8 release files

0.1.0

8 release files

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