- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| scorecount | ||
| tests | ||
| .gitignore | ||
| CHANGELOG.md | ||
| count_symbols.py | ||
| README.md | ||
| requirements.txt | ||
count_symbols
Counts notational elements in MusicXML scores (notes, articulations, dynamics, lyrics, etc) and turns them into weighted points. Intended for pricing engraving and transcription work per element rather than per page or per hour.
Install
pip install -r requirements.txt
Requires Python 3.8+.
Input
MusicXML only: .musicxml, .xml, .mxl. Export from your notation program
first (MuseScore: File > Export > MusicXML; Sibelius: File > Export > MusicXML).
Native .mscz, .mscx and .sib files are rejected with a hint.
Usage
python3 count_symbols.py score.musicxml
python3 count_symbols.py *.musicxml
python3 count_symbols.py -l score.musicxml # list parts with points
python3 count_symbols.py score.musicxml -p Clarinet # one part
python3 count_symbols.py score.musicxml -p 2 -m 20-40 # part 2, bars 20-40
python3 count_symbols.py score.musicxml --rate 2 --currency CZK # with price
Results are printed to the terminal. Add --csv to also write a
<name>_report.csv next to each input (with -p / -m the filter is added to
the file name so reports do not overwrite each other), or --out PATH to
choose the file.
Options
-p, --part PART count only this part: 1-based index, id (P1) or name
(exact, then substring); repeat for several parts
-m, --measures R count only this range: 20-40, 20-, -40 or 25 (inclusive,
uses the printed measure numbers)
-l, --list-parts list parts with point totals and exit
--no-system do not add the first part's system-level items to other
parts (see below)
--rate AMOUNT price per point, e.g. 0.35 or 0,35; prints a price
--currency CODE currency for --rate, e.g. EUR or CZK (required with --rate)
--decimals N decimal places in the price (default depends on currency)
--csv also write a CSV report next to each input
--out PATH write the CSV report to PATH (implies --csv; single
input file only)
-v, --verbose also print a per-item breakdown
-q, --quiet print only the grand total
--version
Multi-staff instruments (piano) are one part; both staves are counted. Exit code is 1 if any file failed.
Pricing
--rate is the price per point and --currency is required with it, so a
price is never shown with a guessed currency. Price is points x rate, computed
in exact decimal arithmetic and rounded half up (24.675 becomes 24.68) to the
currency's usual number of decimals: 0 for CZK, HUF, JPY, KRW, ISK, CLP, VND;
2 for EUR, USD, GBP, PLN, CHF and anything not listed. --decimals N overrides
it. The rate accepts a decimal point or comma.
To avoid retyping, set defaults in your shell profile:
export SCORECOUNT_RATE=2
export SCORECOUNT_CURRENCY=CZK
Price appears after the point total, in the -l part list (one price per
part), in the multi-file summary, and as a PRICE row in the CSV. The price
for several files is computed from their total points, not from the sum of the
rounded per-file prices.
System-level items in full scores
MuseScore (and other programs) write system-level items, meaning rehearsal marks, tempo, segno/coda/D.S. and volta endings, into the top part only. A part exported on its own gets them, so counting one part out of a full score would undercount it.
With -p (and in -l), every part other than the first therefore also gets
the first part's system-level items that it does not already have at the same
measure, so each part is counted as if exported on its own. The added amount is
printed, and shown as ... (system, from part 1) rows in -v and the CSV.
Use --no-system to turn this off. Without -p the whole score is counted
once, as is.
System-level items are recognised by system="only-top" on a direction, by
<sound> attributes such as segno, dalsegno, coda or tempo, and by volta
endings. Limitation: if a part has its own item with the same type in the same
measure as a system item, the system item is treated as already present.
What is counted
Weights live in scorecount/rules.py and can be edited there.
note(0.5): notes and restssymbol(1): articulations, ornaments, technical marks, slurs, ties, tuplets, fermatas, accidentals, clefs, key/time signatures, hairpins, octave lines, pedal, segno/coda, repeat and other special barlines, volta endingstext(2): dynamics, expression / tempo text, metronome marks, rehearsal marks, chord symbols, lyric syllables
Spanning symbols are counted once, at their start. Plain barlines and the
automatic final barline are not counted. Any element in a place where symbols
live but not listed in rules.py is reported as "not counted" so gaps are
visible.
CSV output
With --csv / --out, columns are: category, label, count, weight, points, then category totals, a
grand total, and per-part totals when more than one part is counted.
Tests
python3 -m unittest discover -s tests
Layout
count_symbols.py entry point
scorecount/
rules.py weights and element vocabulary
loader.py reading MusicXML, part and range selection
counter.py counting logic
report.py CSV and console output
cli.py argument handling
tests/