Score analysis¶
Vertical analysis begins with paeonia.Score.verticalities(). It divides
an aligned bar at every onset and release while retaining sustained notes,
exact rational offsets, written pitch spelling, and staff ownership. The
remaining Score methods derive their results from those time
frames and never modify the score.
For example:
score.verticalities(0)
score.sonority_at(0, Fraction(1, 2))
score.harmonic_context(0)
score.voice_leading_to(0) # bar 0 to bar 1
Objective methods such as paeonia.Score.pitch_class_set(),
paeonia.Score.interval_matrix(), paeonia.Score.density(), and
paeonia.Score.register_analysis() do not require a tonality. Functional
methods use the effective score, voice, and bar tonal context. If selected
staves disagree, pass tonality=... explicitly or select compatible staves
with staves=[...].
Analysis result types¶
Time-aware vertical, harmonic, registral, and voice-leading analysis.
The functions in this module inspect model objects without modifying them.
Durations and offsets remain exact fractions.Fraction values, and
written pitch classes are kept alongside their MIDI pitch classes so that
enharmonic spellings are never silently collapsed.
- class paeonia.analysis.BassMotion(from_offset, to_offset, from_pitch, to_pitch, semitones)[source]¶
Bases:
objectA change from one sounding bass pitch to the next.
- Parameters:
- from_offset: Fraction¶
- to_offset: Fraction¶
- semitones: int¶
- class paeonia.analysis.ChordCandidate(root, quality, symbol, intervals, inversion, confidence, matched_pitch_classes, missing_pitch_classes, extra_pitch_classes, roman_numeral=None)[source]¶
Bases:
objectA possible tertian or suspended interpretation of a sonority.
- Parameters:
root (PitchClass)
quality (str)
symbol (str)
intervals (frozenset[int])
inversion (int | None)
confidence (float)
matched_pitch_classes (frozenset[int])
missing_pitch_classes (frozenset[int])
extra_pitch_classes (frozenset[int])
roman_numeral (str | None)
- root: PitchClass¶
- quality: str¶
- symbol: str¶
- intervals: frozenset[int]¶
- inversion: int | None¶
- confidence: float¶
- matched_pitch_classes: frozenset[int]¶
- missing_pitch_classes: frozenset[int]¶
- extra_pitch_classes: frozenset[int]¶
- roman_numeral: str | None¶
- class paeonia.analysis.DensityPoint(offset, duration, pitch_count, active_staff_count)[source]¶
Bases:
objectThe number of sounding pitches and active staves in a time frame.
- Parameters:
offset (Fraction)
duration (Fraction)
pitch_count (int)
active_staff_count (int)
- offset: Fraction¶
- duration: Fraction¶
- pitch_count: int¶
- active_staff_count: int¶
- class paeonia.analysis.Doubling(midi_pitch_class, count, spellings, staves)[source]¶
Bases:
objectA MIDI pitch class occurring more than once in a verticality.
- Parameters:
midi_pitch_class (int)
count (int)
spellings (frozenset[PitchClass])
staves (tuple[str, ...])
- midi_pitch_class: int¶
- count: int¶
- spellings: frozenset[PitchClass]¶
- staves: tuple[str, ...]¶
- class paeonia.analysis.DoublingSnapshot(offset, duration, doublings)[source]¶
Bases:
objectPitch-class doublings for one vertical time frame.
- Parameters:
offset (Fraction)
duration (Fraction)
doublings (tuple[Doubling, ...])
- offset: Fraction¶
- duration: Fraction¶
- class paeonia.analysis.EventReference(staff, bar_index, event_index, pitch_index)[source]¶
Bases:
objectIdentify one spelled pitch in a source score event.
Event and pitch indices are local to the referenced bar. Keeping this identity in analysis results lets renderers annotate an exact event or an individual chord pitch without trying to recover it from MIDI value and offset.
- Parameters:
staff (str)
bar_index (int)
event_index (int)
pitch_index (int)
- staff: str¶
- bar_index: int¶
- event_index: int¶
- pitch_index: int¶
- class paeonia.analysis.HarmonicChange(offset, duration, candidate)[source]¶
Bases:
objectA contiguous span assigned the same primary chord interpretation.
- Parameters:
offset (Fraction)
duration (Fraction)
candidate (ChordCandidate | None)
- offset: Fraction¶
- duration: Fraction¶
- candidate: ChordCandidate | None¶
- property roman_numeral: str | None¶
Return this assignment’s functional label, when available.
- property symbol: str | None¶
Return this assignment’s chord symbol, when available.
- class paeonia.analysis.HarmonicContext(bar_index, tonality, verticalities, primary, primary_coverage, weighted_candidates, changes, non_chord_tones)[source]¶
Bases:
objectDuration-weighted harmonic interpretation of one score bar.
- Parameters:
bar_index (int)
tonality (Tonality)
verticalities (tuple[Verticality, ...])
primary (ChordCandidate | None)
primary_coverage (Fraction)
weighted_candidates (tuple[WeightedChord, ...])
changes (tuple[HarmonicChange, ...])
non_chord_tones (tuple[NonChordTone, ...])
- bar_index: int¶
- verticalities: tuple[Verticality, ...]¶
- primary: ChordCandidate | None¶
- primary_coverage: Fraction¶
- weighted_candidates: tuple[WeightedChord, ...]¶
- changes: tuple[HarmonicChange, ...]¶
- non_chord_tones: tuple[NonChordTone, ...]¶
- class paeonia.analysis.IntervalRelation(first_staff, second_staff, first_pitch, second_pitch, semitones, interval_class, dissonant)[source]¶
Bases:
objectThe sounding interval between pitches owned by two staves.
- Parameters:
- first_staff: str¶
- second_staff: str¶
- semitones: int¶
- interval_class: int¶
- dissonant: bool¶
- class paeonia.analysis.IntervalSnapshot(offset, duration, intervals)[source]¶
Bases:
objectCross-staff intervals for one vertical time frame.
- Parameters:
offset (Fraction)
duration (Fraction)
intervals (tuple[IntervalRelation, ...])
- offset: Fraction¶
- duration: Fraction¶
- intervals: tuple[IntervalRelation, ...]¶
- class paeonia.analysis.NonChordTone(offset, staff, pitch, kind, source=None)[source]¶
Bases:
objectA pitch outside a local chord interpretation.
- Parameters:
offset (Fraction)
staff (str)
pitch (Pitch)
kind (Literal['passing', 'neighbor', 'unclassified'])
source (EventReference | None)
- offset: Fraction¶
- staff: str¶
- kind: Literal['passing', 'neighbor', 'unclassified']¶
- source: EventReference | None¶
- class paeonia.analysis.ParallelMotion(first_staff, second_staff, interval_class)[source]¶
Bases:
objectParallel perfect fifth or octave between two staff-owned motions.
- Parameters:
first_staff (str)
second_staff (str)
interval_class (int)
- first_staff: str¶
- second_staff: str¶
- interval_class: int¶
- class paeonia.analysis.PitchClassSet(written, midi)[source]¶
Bases:
objectBoth written and sounding representations of a pitch-class set.
- Parameters:
written (frozenset[PitchClass])
midi (frozenset[int])
- written: frozenset[PitchClass]¶
- midi: frozenset[int]¶
- class paeonia.analysis.RegisterAnalysis(snapshots, overlaps)[source]¶
Bases:
objectRegister snapshots and cross-frame overlaps for one bar.
- Parameters:
snapshots (tuple[RegisterSnapshot, ...])
overlaps (tuple[RegisterOverlap, ...])
- snapshots: tuple[RegisterSnapshot, ...]¶
- overlaps: tuple[RegisterOverlap, ...]¶
- class paeonia.analysis.RegisterOverlap(offset, upper_staff, lower_staff)[source]¶
Bases:
objectAdjacent ordered staves overlapping across two time frames.
- Parameters:
offset (Fraction)
upper_staff (str)
lower_staff (str)
- offset: Fraction¶
- upper_staff: str¶
- lower_staff: str¶
- class paeonia.analysis.RegisterSnapshot(offset, duration, bass, soprano, ambitus, spacing, staff_ranges, crossings)[source]¶
Bases:
objectRegister, spacing, and voice-crossing data at one offset.
- Parameters:
offset (Fraction)
duration (Fraction)
bass (Pitch | None)
soprano (Pitch | None)
ambitus (int | None)
spacing (tuple[int, ...])
staff_ranges (tuple[StaffRange, ...])
crossings (tuple[tuple[str, str], ...])
- offset: Fraction¶
- duration: Fraction¶
- ambitus: int | None¶
- spacing: tuple[int, ...]¶
- staff_ranges: tuple[StaffRange, ...]¶
- crossings: tuple[tuple[str, str], ...]¶
- class paeonia.analysis.ScaleDegree(staff, pitch, position)[source]¶
Bases:
objectA staff-owned pitch analyzed within a tonality.
- Parameters:
staff (str)
pitch (Pitch)
position (ScalePosition)
- staff: str¶
- position: ScalePosition¶
- property number: int¶
Return the conventional one-based scale-degree number.
- class paeonia.analysis.ScaleDegreeSnapshot(offset, duration, degrees)[source]¶
Bases:
objectScale-degree analyses for one vertical time frame.
- Parameters:
offset (Fraction)
duration (Fraction)
degrees (tuple[ScaleDegree, ...])
- offset: Fraction¶
- duration: Fraction¶
- degrees: tuple[ScaleDegree, ...]¶
- class paeonia.analysis.StaffPitches(staff, pitches, sources=())[source]¶
Bases:
objectPitches and source identities sounding in one staff time frame.
- Parameters:
staff (str)
pitches (tuple[Pitch, ...])
sources (tuple[EventReference, ...])
- staff: str¶
- sources: tuple[EventReference, ...]¶
- class paeonia.analysis.StaffRange(staff, lowest, highest)[source]¶
Bases:
objectThe lowest and highest pitches sounding on a staff.
- staff: str¶
- class paeonia.analysis.Verticality(bar_index, offset, duration, staff_pitches)[source]¶
Bases:
objectAll pitches sounding over one exact, half-open time interval.
offsetanddurationare measured in whole-note units relative to the beginning ofbar_index.staff_pitchesfollows score insertion order and includes silent staves with an empty pitch tuple.- Parameters:
bar_index (int)
offset (Fraction)
duration (Fraction)
staff_pitches (tuple[StaffPitches, ...])
- bar_index: int¶
- offset: Fraction¶
- duration: Fraction¶
- staff_pitches: tuple[StaffPitches, ...]¶
- property sources: tuple[EventReference, ...]¶
Return source identities in staff and chord order.
- property pitch_classes: PitchClassSet¶
Return written and MIDI pitch-class sets for this frame.
- property interval_class_vector: tuple[int, int, int, int, int, int]¶
Return the six-entry interval-class vector of the MIDI set.
- property prime_form: tuple[int, ...]¶
Return a transposition/inversion-normalized pitch-class form.
- scale_degrees(tonality)[source]¶
Analyze every sounding pitch while preserving staff ownership.
- Parameters:
tonality (Tonality)
- Return type:
tuple[ScaleDegree, …]
- interval_matrix(*, dissonant_classes=frozenset({1, 2, 6}))[source]¶
Return every cross-staff pitch interval in this frame.
- Parameters:
dissonant_classes (Collection[int])
- Return type:
tuple[IntervalRelation, …]
- dissonances(*, dissonant_classes=frozenset({1, 2, 6}))[source]¶
Return relations classified as dissonant by MIDI interval class.
- Parameters:
dissonant_classes (Collection[int])
- Return type:
tuple[IntervalRelation, …]
- doublings()[source]¶
Return MIDI pitch classes represented by multiple pitches.
- Return type:
tuple[Doubling, …]
- chord_candidates(*, tonality=None, limit=5)[source]¶
Rank common chord templates against the sounding MIDI set.
- Parameters:
tonality (Tonality | None)
limit (int)
- Return type:
tuple[ChordCandidate, …]
- class paeonia.analysis.VoiceLeadingAnalysis(from_bar, to_bar, motions, common_tones, total_motion, contrary_pairs, parallel_perfects, leaps)[source]¶
Bases:
objectMotion from the final sonority of one bar to the first of another.
- Parameters:
from_bar (int)
to_bar (int)
motions (tuple[VoiceMotion, ...])
common_tones (tuple[int, ...])
total_motion (int)
contrary_pairs (tuple[tuple[str, str], ...])
parallel_perfects (tuple[ParallelMotion, ...])
leaps (tuple[VoiceMotion, ...])
- from_bar: int¶
- to_bar: int¶
- motions: tuple[VoiceMotion, ...]¶
- common_tones: tuple[int, ...]¶
- total_motion: int¶
- contrary_pairs: tuple[tuple[str, str], ...]¶
- parallel_perfects: tuple[ParallelMotion, ...]¶
- leaps: tuple[VoiceMotion, ...]¶
- class paeonia.analysis.VoiceMotion(staff, from_pitch, to_pitch, semitones)[source]¶
Bases:
objectOne pitch moving between two analyzed sonorities.
- staff: str¶
- semitones: int¶
- class paeonia.analysis.WeightedChord(candidate, duration, coverage)[source]¶
Bases:
objectA chord candidate weighted by its duration within a bar.
- Parameters:
candidate (ChordCandidate)
duration (Fraction)
coverage (Fraction)
- candidate: ChordCandidate¶
- duration: Fraction¶
- coverage: Fraction¶
- paeonia.analysis.interval_class_vector(pitch_classes)[source]¶
Return the standard interval-class vector for unique MIDI classes.
- Parameters:
pitch_classes (Iterable[int])
- Return type:
tuple[int, int, int, int, int, int]
- paeonia.analysis.prime_form(pitch_classes)[source]¶
Return a canonical form under transposition and inversion.
The most compact rotation of the set and its inversion are transposed to zero; the more tightly left-packed of those two forms is returned.
- Parameters:
pitch_classes (Iterable[int])
- Return type:
tuple[int, …]