ScoreStruct

class maelzel.scorestruct.ScoreStruct(score=None, timesig=None, tempo=None, endless=True, title='', composer='', readonly=False)[source]

Bases: object

A ScoreStruct holds the structure of a score but no content

A ScoreStruct consists of some metadata and a list of MeasureDefs, where each MeasureDef defines the properties of the measure at the given index. If a ScoreStruct is marked as endless, it is possible to query it (convert beats to time, etc.) outside the defined measures.

The ScoreStruct class is used extensively within maelzel.core (see scorestruct-and-maelzel-core)

Parameters:
  • score (Optional[str]) – if given, a score definition as a string (see below for the format)

  • timesig (Union[Tuple[int, int], str, None]) – time-signature. If no score is given, a timesig can be passed to define a basic scorestruct with a time signature and a default or given tempo

  • tempo (Optional[int]) – the tempo of a quarter note, if given. Even if using a time-signature with a smaller denominator (like 3/8), the tempo is always given in reference to a quarter note.

  • endless (bool) – mark this ScoreStruct as endless. Defaults to True

  • title – title metadata for the score, used when rendering

  • composer – composer metadata for this score, used when rendering

Example

# create an endless score with a given time signature
s = ScoreStruct(endless=True)
s.addMeasure((4, 4), quarterTempo=72)

# this is the same as:
s = ScoreStruct.fromTimesig((4, 4), 72)

# Create the beginning of Sacre
s = ScoreStruct()
s.addMeasure((4, 4), 50)
s.addMeasure((3, 4))
s.addMeasure((4, 4))
s.addMeasure((2, 4))
s.addMeasure((3, 4), numMeasures=2)

# The same can be achieved via a score string:
s = ScoreStruct(r'''
4/4, 50
3/4
4/4
2/4
3/4
.
''')

# Or everything in one line:
s = ScoreStruct('4/4, 50; 3/4; 4/4; 2/4; 3/4; 3/4 ')

Format

A definitions are divided by new line or by ;. Each line has the form:

measureIndex, timeSig, tempo
  • Tempo refers always to a quarter note

  • Any value can be left out: , 5/8,

  • measure numbers start at 0

  • comments start with # and last until the end of the line

  • A line with a single “.” repeats the last defined measure

  • A score ending with the line … is an endless score

The measure number and/or the tempo can both be left out. The following definitions are all the same:

1, 5/8, 63
5/8, 63
5/8

Example:

0, 4/4, 60, "mark A"
,3/4,80     # Assumes measureIndex=1
10, 5/8, 120
30,,
.
.      # last measure (inclusive, the score will have 33 measures)

Methods Summary

addMeasure([timesig, quarterTempo, ...])

Add a measure definition to this score structure

addRehearsalMark(idx, mark[, box])

Add a rehearsal mark to this scorestruct

asBeat(location)

Given a beat or a location (measureidx, relativeoffset), returns an absolute beat

asText()

This ScoreStruct as parsable text format

b2t(beat)

Beat to time

beat(a[, b])

Convert a time in secs or a location (measure, beat) to a quarter-note beat

beatDelta(start, end)

Difference in beats between the two score locations or two times

beatToLocation(beat)

Return the location in score corresponding to the given beat

beatToTime(beat)

Convert beat-time to real-time

copy()

Create a copy of this ScoreStruct

dump()

Dump this ScoreStruct to stdout

durationQuarters()

The duration of this score, in quarternotes

durationSecs()

The duration of this score, in seconds

ensureDurationInMeasures(numMeasures)

Extends this score to have at least the given number of measures

ensureDurationInSeconds(duration)

Ensure that this scorestruct is long enough to include the given time

exportMidiClickTrack(midifile)

Generate a MIDI click track from this ScoreStruct

getMeasureDef(idx[, extend])

Returns the MeasureDef at the given index.

hasUniqueTempo()

Returns True if this ScoreStruct has no tempo changes

hasUniqueTimesig()

Returns True if this ScoreStruct does not have any time-signature change

iterMeasureDefs()

Iterate over all measure definitions in this ScoreStruct.

locationToBeat(measure[, beat])

Returns the number of quarter notes up to the given location

locationToTime(measure[, beat])

Return the elapsed time at the given score location

ltob(measure, beat)

A shortcut to locationToBeat

makeClickTrack([minMeasures, clickdur, ...])

Create a click track from this ScoreStruct

measureOffsets([startIndex, stopIndex])

Returns a list with the time offsets of each measure

measuresBetween(start, end)

List of measures defined between the given times as beats

modified()

mark this ScoreStruct as modified

numMeasures()

Returns the number of measures in this score structure

remapFrom(sourcestruct, location)

Remap a beat from sourcestruct to this this struct

remapSpan(sourcestruct, offset, duration)

Remap a time span from a source score structure to this score structure

remapTo(deststruct, location)

Remap a beat from this struct to another struct

setBarline(measureIndex, linetype)

Set the right barline type

setEnd(numMeasures)

Set an end measure to this ScoreStruct, in place

setTempo(tempo[, reference, measureIndex])

Set the tempo of the given measure, until the next tempo change

setTimeSignature(measureIndex, timesig)

rtype:

None

show([fmt, app, scalefactor, backend, ...])

Render and show this ScoreStruct

t2b(t)

Time to beat

tempoAtTime(time)

Returns the tempo active at the given time (in seconds)

time(a[, b])

Convert a quarter-note beat or a location (measure, beat) to an absolute time in secs

timeDelta(start, end)

Returns the elapsed time between two beats or score locations.

timeToBeat(t)

Convert a time to a quarternote offset according to this ScoreStruct

timeToLocation(time)

Find the location in score corresponding to the given time in seconds

write(path[, backend, renderoptions])

Export this score structure

Methods Documentation

addMeasure(timesig=None, quarterTempo=None, annotation='', numMeasures=1, rehearsalMark=None, keySignature=None, barline='', **kws)[source]

Add a measure definition to this score structure

Parameters:
  • timesig (Union[tuple[int, int], str, TimeSignature, None]) – the time signature of the new measure. If not given, the last time signature will be used. The timesig can be given as str in the form “num/den”. For a compound time signature use “3/8+2/8”. To specify the internal subdivision use a TimeSignature object or a string in the form “5/8(3-2)”

  • quarterTempo (Union[float, Rational, Fraction, None]) – the tempo of a quarter note. If not given, the last tempo will be used

  • annotation – each measure can have a text annotation

  • numMeasures – if this is > 1, multiple measures of the same kind can be added

  • rehearsalMark (Union[str, RehearsalMark, None]) – if given, add a rehearsal mark to the new measure definition. A rehearsal mark can be a text or a RehearsalMark, which enables you to customize the rehearsal mark further

  • keySignature (Union[tuple[int, str], KeySignature, None]) – either a KeySignature object or a tuple (fifths, mode); for example for A-Major, (3, 'major'). Mode can also be left as an ampty string

  • barline – if needed, the right barline of the measure can be set to one of ‘single’, ‘final’, ‘double’, ‘solid’, ‘dotted’, ‘dashed’, ‘tick’, ‘short’, ‘double-thin’ or ‘none’

  • **kws – any extra keyword argument will be saved as a property of the MeasureDef

Return type:

None

Example:

# Create a 4/4 score, 32 measures long
>>> s = ScoreStruct()
>>> s.addMeasure((4, 4), 52, numMeasures=32)
addRehearsalMark(idx, mark, box='square')[source]

Add a rehearsal mark to this scorestruct

The measure definition for the given index must already exist or the score must be set to autoextend

Parameters:
  • idx (int) – the measure index

  • mark (RehearsalMark | str) – the rehearsal mark, as text or as a RehearsalMark

  • box (str) – one of ‘square’, ‘circle’ or ‘’ to avoid drawing a box around the rehearsal mark

Return type:

None

asBeat(location)[source]

Given a beat or a location (measureidx, relativeoffset), returns an absolute beat

Parameters:

location (Union[float, Rational, Fraction, tuple[int, Fraction]]) – the location

Return type:

Fraction

Returns:

the absolute beat in quarter notes

asText()[source]

This ScoreStruct as parsable text format

Return type:

str

Returns:

this score as text

b2t(beat)[source]

Beat to time

Return type:

Fraction

beat(a, b=None)[source]

Convert a time in secs or a location (measure, beat) to a quarter-note beat

Parameters:
  • a (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the time/location to convert. Either a time

  • b (Union[float, Rational, Fraction, None]) – when passign a location, the beat within the measure (a contains the measure index)

Return type:

Fraction

Returns:

the corresponding quarter note beat according to this ScoreStruct

Example

>>> sco = ScoreStruct.fromTimesig('3/4', 120)
# Convert time to beat
>>> sco.beat(0.5)
1.0
# Convert score location (measure 1, beat 2) to beats
>>> sco.beat((1, 2))
5.0
# Also supported, similar to the previous operation:
>>> sco.beat(1, 2)
5.0

See also

time()

beatDelta(start, end)[source]

Difference in beats between the two score locations or two times

Parameters:
  • start (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the start moment as a location (a tuple (measureIndex, beatOffset) or as a time

  • end (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the end location, a tuple (measureIndex, beatOffset)

Return type:

Fraction

Returns:

the distance between the two locations, in beats

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> s = ScoreStruct('4/4, 120; 3/4; 3/8; 5/8')
# delta, in quarternotes, between time=2secs and location (2, 0)
>>> s.beatDelta(2., (2, 0))
5

See also

timeDelta()

beatToLocation(beat)[source]

Return the location in score corresponding to the given beat

The beat is the time-offset in quarter-notes. Given a beat (in quarter-notes), return the score location (measure, beat offset within the measure). Tempo does not play any role within this calculation.

Return type:

tuple[int, Fraction]

Returns:

a tuple (measure index, beat). Raises ValueError if beat is not defined within this score

Note

In the special case where a ScoreStruct is not endless and the beat is exactly at the end of the last measure, we return (numMeasures, 0)

See also

locationToBeat(), which performs the opposite operation

Example

Given the following score: 4/4, 3/4, 4/4

input

output

4

(1, 0)

5.5

(1, 1.5)

8

(2, 1.0)

beatToTime(beat)[source]

Convert beat-time to real-time

Parameters:

beat (Union[float, Rational, Fraction]) – the quarter-note beat

Return type:

Fraction

Returns:

the corresponding time

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> sco = ScoreStruct.fromTimesig('4/4', quarterTempo=120)
>>> sco.beatToTime(2)
1.0
>>> sco.timeToBeat(2)
4.0

See also

timeToBeat()

copy()[source]

Create a copy of this ScoreStruct

Return type:

ScoreStruct

dump()[source]

Dump this ScoreStruct to stdout

Return type:

None

durationQuarters()[source]

The duration of this score, in quarternotes

Raises ValueError if this score is endless

Return type:

Fraction

durationSecs()[source]

The duration of this score, in seconds

Raises ValueError if this score is endless

Return type:

Fraction

ensureDurationInMeasures(numMeasures)[source]

Extends this score to have at least the given number of measures

If the scorestruct already has reached the given length this operation does nothing

Parameters:

numMeasures (int) – the minimum number of measures this score should have

Return type:

None

ensureDurationInSeconds(duration)[source]

Ensure that this scorestruct is long enough to include the given time

This is of relevance in certain edge cases including endless scorestructs:

  • When creating a clicktrack from an endless score.

  • When exporting a scorestruct to midi

Parameters:

duration (Fraction) – the duration in seconds to ensure

Return type:

None

exportMidiClickTrack(midifile)[source]

Generate a MIDI click track from this ScoreStruct

Parameters:

midifile (str) – the path of the MIDI file to generate

Return type:

None

See also

maelzel.core.clicktrack.makeClickTrack()

getMeasureDef(idx, extend=None)[source]

Returns the MeasureDef at the given index.

Parameters:
  • idx (int) – the measure index (measures start at 0)

  • extend (Optional[bool]) – if True and the index given is outside the defined measures, the score will be extended, repeating the last defined measure. For endless scores, the default is to extend the measure definitions.

Return type:

MeasureDef

If the scorestruct is endless and the index is outside the defined range, the returned MeasureDef will be a copy of the last defined MeasureDef.

The same result can be achieved via __getitem__

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> s = ScoreStruct(r'''
... 4/4, 50
... 3/4
... 5/4, 72
... 6/8
... ''')
>>> s.getMeasureDef(2)
MeasureDef(timesig=(5, 4), quarterTempo=72, annotation='', timesigInherited=False,
           tempoInherited=True, barline='', subdivisionStructure=None)
>>> s[2]
MeasureDef(timesig=(5, 4), quarterTempo=72, annotation='', timesigInherited=False,
           tempoInherited=True, barline='', subdivisionStructure=None)
hasUniqueTempo()[source]

Returns True if this ScoreStruct has no tempo changes

Return type:

bool

hasUniqueTimesig()[source]

Returns True if this ScoreStruct does not have any time-signature change

Return type:

bool

iterMeasureDefs()[source]

Iterate over all measure definitions in this ScoreStruct.

If it is marked as endless, then the last defined measure will be returned indefinitely.

Return type:

Iterator[MeasureDef]

locationToBeat(measure, beat=Fraction(0, 1))[source]

Returns the number of quarter notes up to the given location

This value is independent of any tempo given.

Parameters:
  • measure (int) – the measure number (measures start at 0)

  • beat (Union[float, Rational, Fraction]) – the beat within the given measure (beat 0 = start of the measure), in quarter notes.

Return type:

Fraction

Returns:

the location translated to quarter notes.

Example

>>> s = ScoreStruct(r'''
... 3/4, 120
... 3/8
... 4/4
... ''')
>>> s.locationToBeat(1, 0.5)
3.5
>>> s.locationToTime(1, 0.5)
1.75
locationToTime(measure, beat=Fraction(0, 1))[source]

Return the elapsed time at the given score location

Parameters:
  • measure (int) – the measure number (starting with 0)

  • beat (Union[float, Rational, Fraction]) – the beat within the measure

Return type:

Fraction

Returns:

a time in seconds (as a Fraction to avoid rounding problems)

ltob(measure, beat)[source]

A shortcut to locationToBeat

Parameters:
  • measure (int) – the measure index (measures start at 0

  • beat (Union[float, Rational, Fraction]) – the beat within the given measure

Return type:

Fraction

Returns:

the corresponding beat in quarter notes

makeClickTrack(minMeasures=0, clickdur=None, strongBeatPitch='5C', weakBeatPitch='5G', playTransposition=24)[source]

Create a click track from this ScoreStruct

The returned score can be displayed as notation via maelzel.core.Score.show() or exported as pdf or midi.

This is a shortcut to maelzel.core.tools.makeClickTrack(). Use that for more customization options

Note

The duration of the playback can be set individually from the duration of the displayed pitch

Parameters:
  • clickdur (Optional[Fraction]) – the length of each tick. Use None to use the duration of the beat.

  • strongBeatPitch – the pitch used as a strong beat (at the beginning of each measure)

  • weakBeatPitch – the pitch used as a weak beat

  • playTransposition – the transposition interval between notated pitch and playback pitch

Return type:

Score

Returns:

a maelzel.core.Score

Example

>>> from maelzel.core import *
>>> scorestruct = ScoreStruct(r"4/4,72; .; 5/8; 3/8; 2/4,96; .; 5/4; 3/4")
>>> clicktrack = scorestruct.makeClickTrack()
>>> clicktrack.write('click.pdf')
>>> clicktrack.play()
../_images/clicktrack2.png
measureOffsets(startIndex=0, stopIndex=0)[source]

Returns a list with the time offsets of each measure

Parameters:
  • startIndex – the measure index to start with. 0=last measure definition

  • stopIndex – the measure index to end with (not included)

Return type:

list[Fraction]

Returns:

a list of time offsets (start times), one for each measure in the interval selected

measuresBetween(start, end)[source]

List of measures defined between the given times as beats

Parameters:
  • start (Fraction) – start beat in quarter-tones

  • end (Fraction) – end beat in quarter-tones

Return type:

list[MeasureDef]

Returns:

modified()[source]

mark this ScoreStruct as modified

Return type:

None

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> s = ScoreStruct(r'''
... 4/4, 60
... 3/4
... 4/4
... .
... .
... 5/8
... ''')
>>> measure = s.getMeasureDef(3)
>>> measure.timesig = 6/8
>>> s.modified()
numMeasures()[source]

Returns the number of measures in this score structure

If self is endless, it returns the number of defined measures

Return type:

int

Example

We create an endless structure (which is the default) where the last defined measure is at index 9. The number of measures is 10

>>> from maelzel.scorestruct import *
>>> struct = ScoreStruct(r'''
... 4/4
... .
... 3/4
... 6, 4/4
... 9, 3/4
''')
>>> struct.numMeasures()
10
remapFrom(sourcestruct, location)[source]

Remap a beat from sourcestruct to this this struct

Parameters:
  • location (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the beat offset in quarternotes or a location (measureindex, offset)

  • sourcestruct (ScoreStruct) – the source score structure

Return type:

Fraction

Returns:

the beat within this struct which keeps the same absolute time as the given beat within sourcestruct

remapSpan(sourcestruct, offset, duration)[source]

Remap a time span from a source score structure to this score structure

Parameters:
  • sourcestruct (ScoreStruct) – the source score strcuture

  • offset (Union[float, Rational, Fraction]) – the offset

  • duration (Union[float, Rational, Fraction]) – the duration

Return type:

tuple[Fraction, Fraction]

Returns:

a tuple(offset, dur) where these represent the start and duration within this scorestruct which coincide in absolute time with the offset and duration given

remapTo(deststruct, location)[source]

Remap a beat from this struct to another struct

Parameters:
  • location (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the beat offset in quarternotes or a location (measureindex, offset)

  • deststruct (ScoreStruct) – the destination scores structure

Return type:

Fraction

Returns:

the beat within deststruct which keeps the same absolute time

setBarline(measureIndex, linetype)[source]

Set the right barline type

Parameters:
  • measureIndex (int) – the measure index to modify

  • linetype (str) – one of ‘single’, ‘double’, ‘final’, ‘solid’, ‘dashed’

Return type:

None

setEnd(numMeasures)[source]

Set an end measure to this ScoreStruct, in place

If the scorestruct has less defined measures as requested, then it is extended by duplicating the last defined measure as needed. Otherwise, the scorestruct is cropped. The scorestruct ceases to be endless if that was the case previously

Parameters:

numMeasures (int) – the requested number of measures after the operation

Return type:

None

setTempo(tempo, reference=1, measureIndex=0)[source]

Set the tempo of the given measure, until the next tempo change

Parameters:
  • tempo (float) – the new tempo

  • reference – the reference duration (1=quarternote, 2=halfnote, 0.5: 8th note, etc)

  • measureIndex (int) – the first measure to modify

Return type:

None

setTimeSignature(measureIndex, timesig)[source]
Return type:

None

show(fmt='png', app='', scalefactor=1.0, backend=None, renderoptions=None)[source]

Render and show this ScoreStruct

Parameters:
  • fmt – the format to render to, one of ‘png’ or ‘pdf’

  • app (str) – if given, the app used to open the produced document

  • scalefactor (float) – if given, a scale factor to enlarge or reduce the prduce image

  • backend (Optional[str]) – the backend used (None to use a sensible default). If given, one of ‘lilypond’ or ‘musicxml’

  • renderoptions (Optional[RenderOptions]) – if given, these options will be used for rendering this score structure as image.

Return type:

None

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> sco = ScoreStruct(r'''
... ...
... ''')
>>> from maelzel.scoring.render import RenderOptions
t2b(t)[source]

Time to beat

Return type:

Fraction

tempoAtTime(time)[source]

Returns the tempo active at the given time (in seconds)

Parameters:

time (Union[float, Rational, Fraction]) – point in the timeline (in seconds)

Return type:

Fraction

Returns:

the quarternote-tempo at the given time

time(a, b=None)[source]

Convert a quarter-note beat or a location (measure, beat) to an absolute time in secs

Parameters:
  • a (Union[float, Rational, Fraction, tuple[int, Union[float, Rational, Fraction]]]) – the beat/location to convert. Either a beat, a tuple (measureindex, beat) or the measureindex itself, in which case b is also needed

  • b (Union[float, Rational, Fraction, None]) – if given, then a is the measureindex and b is the beat

Return type:

Fraction

Returns:

the corresponding time according to this ScoreStruct

Example

>>> sco = ScoreStruct.fromTimesig('3/4', 120)
# Convert time to beat
>>> sco.time(1)
0.5
# Convert score location (measure 1, beat 2) to beats
>>> sco.time((1, 2))
2.5

See also

beat()

timeDelta(start, end)[source]

Returns the elapsed time between two beats or score locations.

Parameters:
  • start (beat_t) – the start location, as a beat or as a tuple (measureIndex, beatOffset)

  • end (beat_t) – the end location, as a beat or as a tuple (measureIndex, beatOffset)

Return type:

F

Returns:

the elapsed time, as a Fraction

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> s = ScoreStruct('4/4,60; 3/4; 3/8')
>>> s.timeDelta((0, 0.5), (2, 0.5))
7
>>> s.timeDelta(3, (1, 2))
3

See also

beatDelta()

timeToBeat(t)[source]

Convert a time to a quarternote offset according to this ScoreStruct

Parameters:

t (Union[float, Rational, Fraction]) – the time (in absolute seconds)

Return type:

Fraction

Returns:

A quarternote offset

will raise ValueError if the given time is outside this score structure

Example

>>> from maelzel.scorestruct import ScoreStruct
>>> sco = ScoreStruct.fromTimesig('4/4', quarterTempo=120)
>>> sco.beatToTime(2)
1.0
>>> sco.timeToBeat(2)
4.0

See also

beatToTime()

timeToLocation(time)[source]

Find the location in score corresponding to the given time in seconds

Parameters:

time (Union[float, Rational, Fraction]) – the time in seconds

Return type:

tuple[int | None, Fraction]

Returns:

a tuple (measureindex, measurebeat) where measureindex can be None if the score is not endless and time is outside the score

See also

beatToLocation()

write(path, backend=None, renderoptions=None)[source]

Export this score structure

Write this as musicxml (.xml), lilypond (.ly), MIDI (.mid) or render as pdf or png. The format is determined by the extension of the file. It is also possible to write the score as text (in its own format) in order to load it later (.txt)

Note

when saving as MIDI, notes are used to fill each beat because an empty MIDI score is not supported by the MIDI standard

Parameters:
  • path (str | Path) – the path of the written file

  • backend (Optional[str]) – for pdf or png only - the backend to use for rendering, one of ‘lilypond’ or ‘musicxml’

  • renderoptions (Optional[RenderOptions]) – if given, they will be used to customize the rendering process.

Return type:

None