music21.humdrum.spineParser¶
music21.humdrum.spineParser is a collection of utilities for changing native humdrum code into music21 streams. Most music21 users will simply want to call:
>>> myFile = converter.parse('myFile.krn')
>>> myFile.show()
The methods in here are documented for developers wishing to expand music21’s ability to parse humdrum.
SpineParsing consists of several steps.
- The data file is read in and all events are sliced horizontally (EventCollections)
and vertically (Protospines)
- Protospines are parsed into HumdrumSpines by following Spine Path Indicators
(
*^
and*v
especially) Protospines that separate become new Protospines with their parentSpine indicated. Protospines that merge again then followed by the same Protospine as before. This will cause problems if a voice re-merges with another staff, but in practice I have not seen a .krn file that does this and should be avoided in any case.
- HumdrumSpines are reclassed according to their exclusive definition.
**kern
becomes KernSpines, etc.
- All reclassed HumdrumSpines are filled with music21 objects in their .stream property.
Measures are put into the spine but are empty containers. The resulting HumdrumSpine.stream objects look like Stream.semiFlat versions in many ways.
- For HumdrumSpines with parent spines their .stream contents are then
inserted into their parent spines with voice tagged as a music21 Group property.
Lyrics and Dynamics are placed into their corresponding HumdrumSpine.stream objects
Stream elements are moved into their measures within a Stream
Measures are searched for elements with voice groups and Voice objects are created
DynamSpine¶
- class music21.humdrum.spineParser.DynamSpine(spineId: int = 0, eventList=None, streamClass=<class 'music21.stream.base.Stream'>)¶
A DynamSpine is a type of humdrum spine with the **dynam attribute set and thus events are processed as if they are dynamics.
DynamSpine
bases
DynamSpine
read-only properties
Read-only properties inherited from ProtoM21Object
:
DynamSpine
read/write properties
Read/write properties inherited from HumdrumSpine
:
DynamSpine
methods
- DynamSpine.parse()¶
Dummy method that pushes all these objects to HumdrumSpine.stream as ElementWrappers. Should be overridden in specific Spine subclasses.
Methods inherited from HumdrumSpine
:
Methods inherited from ProtoM21Object
:
EventCollection¶
- class music21.humdrum.spineParser.EventCollection(maxSpines=0)¶
An EventCollection is a time slice of all events that have an onset of a certain time. If an event does not occur at a certain time, then you should check EventCollection[n].lastEvents to get the previous event. (If it is a note, it is the note still sounding, etc.). The happeningEvent method gets either currentEvent or lastEvent.
These objects normally get created by
parseProtoSpinesAndEventCollections()
so you won’t need to do all the setup.- Assume that ec1 is
C4 pp
- and ec2 is:
D4 .
>>> SE = humdrum.spineParser.SpineEvent >>> eventList1 = [SE('C4'),SE('pp')] >>> eventList2 = [SE('D4'),SE('.')] >>> ec1 = humdrum.spineParser.EventCollection(maxSpines=2) >>> ec1.events = eventList1 >>> ec2 = humdrum.spineParser.EventCollection(maxSpines=2) >>> ec2.events = eventList2 >>> ec2.lastEvents[1] = eventList1[1] >>> ec2.maxSpines 2 >>> ec2.getAllOccurring() [<music21.humdrum.spineParser.SpineEvent D4>, <music21.humdrum.spineParser.SpineEvent pp>]
EventCollection
methods
- EventCollection.addGlobalEvent(globalEvent)¶
- EventCollection.addLastSpineEvent(spineNum, spineEvent)¶
- EventCollection.addSpineEvent(spineNum, spineEvent)¶
- EventCollection.getAllOccurring()¶
- EventCollection.getSpineEvent(spineNum)¶
- EventCollection.getSpineOccurring(spineNum)¶
GlobalComment¶
- class music21.humdrum.spineParser.GlobalComment(comment='', **keywords)¶
A Music21Object that represents a comment for the whole score
>>> sc = humdrum.spineParser.GlobalComment('!! this is a global comment') >>> sc <music21.humdrum.spineParser.GlobalComment 'this is a global comment'> >>> sc.comment 'this is a global comment'
GlobalComment
bases
GlobalComment
read-only properties
Read-only properties inherited from Music21Object
:
Read-only properties inherited from ProtoM21Object
:
GlobalComment
read/write properties
Read/write properties inherited from Music21Object
:
GlobalComment
methods
Methods inherited from Music21Object
:
Methods inherited from ProtoM21Object
:
GlobalComment
instance variables
Instance variables inherited from Music21Object
:
GlobalCommentLine¶
- class music21.humdrum.spineParser.GlobalCommentLine(position: int = 0, contents: str = '')¶
A GlobalCommentLine is a humdrum comment that pertains to all spines In humdrum it is represented by two exclamation points (and usually one space)
The GlobalComment object takes two inputs and stores them as attributes:
position (line number in the humdrum file) contents (string of contents) value (contents minus !!)
The constructor can be passed (position, contents) if contents begins with bangs, they are removed along with up to one space directly afterwards
>>> com1 = humdrum.spineParser.GlobalCommentLine( ... position = 4, contents='!! this comment is global') >>> com1.position 4 >>> com1.contents '!! this comment is global' >>> com1.value 'this comment is global'
GlobalCommentLine
bases
GlobalReference¶
- class music21.humdrum.spineParser.GlobalReference(codeOrAll='', valueOrNone=None, **keywords)¶
A Music21Object that represents a reference in the score, called a “reference record” in Humdrum. See Humdrum User’s Guide Chapter 2.
>>> sc = humdrum.spineParser.GlobalReference('!!!REF:this is a global reference') >>> sc <music21.humdrum.spineParser.GlobalReference REF 'this is a global reference'> >>> sc.code 'REF' >>> sc.value 'this is a global reference'
Alternate form
>>> sc = humdrum.spineParser.GlobalReference('REF', 'this is a global reference') >>> sc <music21.humdrum.spineParser.GlobalReference REF 'this is a global reference'> >>> sc.code 'REF' >>> sc.value 'this is a global reference'
Language codes are parsed:
>>> sc = humdrum.spineParser.GlobalReference('!!!OPT@@RUS: Vesna svyashchennaya') >>> sc.code 'OPT' >>> sc.language 'RUS' >>> sc.isPrimary True
>>> sc = humdrum.spineParser.GlobalReference('!!!OPT@FRE: Le sacre du printemps') >>> sc.code 'OPT' >>> sc.language 'FRE' >>> sc.isPrimary False
GlobalReference
bases
GlobalReference
read-only properties
Read-only properties inherited from Music21Object
:
Read-only properties inherited from ProtoM21Object
:
GlobalReference
read/write properties
Read/write properties inherited from Music21Object
:
GlobalReference
methods
- GlobalReference.updateMetadata(md: Metadata)¶
update a metadata object according to information in this GlobalReference
See humdrum guide Appendix I for information
Methods inherited from Music21Object
:
Methods inherited from ProtoM21Object
:
GlobalReference
instance variables
Instance variables inherited from Music21Object
:
GlobalReferenceLine¶
- class music21.humdrum.spineParser.GlobalReferenceLine(position: int = 0, contents: str = '!!! NUL: None')¶
A GlobalReferenceLine is a type of HumdrumLine that contains information about the humdrum document.
In humdrum it is represented by three exclamation points followed by non-whitespace followed by a colon. Examples:
!!!COM: Stravinsky, Igor Fyodorovich !!!CDT: 1882/6/17/-1971/4/6 !!!ODT: 1911//-1913//; 1947// !!!OPT@@RUS: Vesna svyashchennaya !!!OPT@FRE: Le sacre du printemps
The GlobalReferenceLine object takes two inputs:
position line number in the humdrum file contents string of contents
And stores them as three attributes:
position: as above code: non-whitespace code (usually three letters) value: its value
>>> gr = humdrum.spineParser.GlobalReferenceLine( ... position = 20, contents = '!!!COM: Stravinsky, Igor Fyodorovich\n') >>> gr.position 20 >>> gr.code 'COM' >>> gr.value 'Stravinsky, Igor Fyodorovich'
TODO: add parsing of three-digit Kern comment codes into fuller metadata
GlobalReferenceLine
bases
HarmSpine¶
- class music21.humdrum.spineParser.HarmSpine(spineId: int = 0, eventList=None, streamClass=<class 'music21.stream.base.Stream'>)¶
A HarmSpine is a type of humdrum spine with the **harm attribute set and thus events are processed as if they are harmonic analysis annotations in the “harm” syntax.
The harm roman numeral annotations are parsed using a superset of the original **harm Humdrum representation, written for python and extending the syntax based on other projects like the RomanText and the MuseScore roman numeral notations.
HarmSpine
bases
HarmSpine
read-only properties
Read-only properties inherited from ProtoM21Object
:
HarmSpine
read/write properties
Read/write properties inherited from HumdrumSpine
:
HarmSpine
methods
- HarmSpine.parse()¶
Dummy method that pushes all these objects to HumdrumSpine.stream as ElementWrappers. Should be overridden in specific Spine subclasses.
Methods inherited from HumdrumSpine
:
Methods inherited from ProtoM21Object
:
HumdrumDataCollection¶
- class music21.humdrum.spineParser.HumdrumDataCollection(dataStream=None)¶
A HumdrumDataCollection takes in a mandatory list where each element is a line of humdrum data. Together this list represents a collection of spines. Essentially it’s the contents of a humdrum file.
Usually you will probably want to use HumdrumFile which can read in a file directly. This class exists in case you have your Humdrum data in another format (database, from the web, etc.) and already have it as a string.
You are probably better off running humdrum.parseFile(“filename”) which returns a humdrum.SpineCollection directly, or even better, converter.parse(‘file.krn’) which will just give you a stream.Score instead.
LIMITATIONS: (1) Spines cannot change definition (**exclusive interpretations) mid-spine.
So if you start off with **kern, the rest of the spine needs to be **kern (actually, the first exclusive interpretation for a spine is used throughout)
Note that, even though changing exclusive interpretations mid-spine seems to be legal by the humdrum definition, it looks like none of the conventional humdrum parsing tools allow for changing definitions mid-spine, so I don’t think this limitation is a problem. (Craig Stuart Sapp confirmed this to me)
The Aarden/Miller Palestrina dataset uses *- followed by **kern at the changes of sections thus some parsing of multiple exclusive interpretations in a protospine may be necessary.
Split spines are assumed to be voices in a single spine staff.
HumdrumDataCollection
bases
HumdrumDataCollection
read-only properties
Read-only properties inherited from ProtoM21Object
:
HumdrumDataCollection
methods
- HumdrumDataCollection.createHumdrumSpines(protoSpines=None, eventCollections=None)¶
Takes the data from the object’s protoSpines and eventCollections and returns a
SpineCollection
object that contains HumdrumSpine() objects.A HumdrumSpine object differs from a ProtoSpine in that it follows spinePathData – a ProtoSpine records all data in a given tab position, and thus might consist of data from several spines that move around. HumdrumSpines are smart enough not to have this limitation.
When we check for spinePathData we look for the following spine path indicators (from HumdrumDoc):
*+ add a new spine (to the right of the current spine) *- terminate a current spine *^ split a spine (into two) *v join (two or more) spines into one *x exchange the position of two spines * do nothing
- HumdrumDataCollection.determineIfDataStreamIsOpus(dataStream=None)¶
Some Humdrum files contain multiple pieces in one file which are better represented as
Opus
file containing multiple scores.This method examines that dataStream (or self.dataStream) and if it only has a single piece then it returns (False, None).
If it has multiple pieces, it returns True and a list of dataStreams.
>>> from pprint import pprint as pp
>>> mps = humdrum.testFiles.multipartSanctus >>> hdc = humdrum.spineParser.HumdrumDataCollection(mps) >>> (hasOpus, dataCollections) = hdc.determineIfDataStreamIsOpus() >>> hasOpus True >>> pp(dataCollections) [['!!!COM: Palestrina, Giovanni Perluigi da', '**kern\t**kern\t**kern\t**kern', '*Ibass\t*Itenor\t*Icalto\t*Icant', '!Bassus\t!Tenor\t!Altus\t!Cantus', '*clefF4\t*clefGv2\t*clefG2\t*clefG2', '*M4/2\t*M4/2\t*M4/2\t*M4/2', '=1\t=1\t=1\t=1', '0r\t0r\t1g\t1r', '.\t.\t1a\t1cc', '=2\t=2\t=2\t=2', '0r\t0r\t1g\t1dd', '.\t.\t1r\t1cc', '*-\t*-\t*-\t*-'], ['!! Pleni', '**kern\t**kern\t**kern', '*Ibass\t*Itenor\t*Icalto', '*clefF4\t*clefGv2\t*clefG2', '*M4/2\t*M4/2\t*M4/2', '=3\t=3\t=3', '1G\t1r\t0r', '1A\t1c\t.', '=4\t=4\t=4', '1B\t1d\t1r', '1c\t1e\t1g', '*-\t*-\t*-'], ['!! Hosanna', '**kern\t**kern\t**kern\t**kern', '*Ibass\t*Itenor\t*Icalto\t*Icant', '*clefF4\t*clefGv2\t*clefG2\t*clefG2', '*M3/2\t*M3/2\t*M3/2\t*M3/2', '=5\t=5\t=5\t=5', '1r\t1r\t1g\t1r', '2r\t2r\t[2a\t[2cc', '=5\t=5\t=5\t=5', '1r\t1r\t2a]\t2cc]', '.\t.\t2f\t1dd', '2r\t2r\t2g\t.', '*-\t*-\t*-\t*-']]
- HumdrumDataCollection.insertGlobalEvents()¶
Insert the Global Events (GlobalReferenceLines and GlobalCommentLines) into an appropriate place in the outer Stream.
Run after self.spineCollection.createMusic21Streams(). Is run automatically by self.parse(). uses self.spineCollection.getOffsetsAndPrioritiesByPosition()
- HumdrumDataCollection.parse()¶
Parse a list (dataStream) of lines into a HumdrumSpineCollection (which contains HumdrumSpines) and set it in self.spineCollection
if dataStream is None, look for it in self.dataStream. If that’s None too, return an exception.
- HumdrumDataCollection.parseEventListFromDataStream(dataStream=None)¶
Sets self.eventList from a dataStream (that is, a list of lines). It sets self.maxSpines to the largest number of spine events found on any line in the file.
It sets self.fileLength to the number of lines (excluding totally blank lines) in the file.
The difference between the dataStream and self.eventList are the following:
Blank lines are skipped.
!!! lines become
GlobalReferenceLine
objects!! lines become
GlobalCommentLine
objectsall other lines become
SpineLine
objects
Returns eventList in addition to setting it as self.eventList.
>>> eventString = ('!!! COM: Beethoven, Ludwig van\n' + ... '!! Not really a piece by Beethoven\n' + ... '**kern\t**dynam\n' + ... 'C4\tpp\n' + ... 'D8\t.\n') >>> hdc = humdrum.spineParser.HumdrumDataCollection(eventString) >>> hdc.maxSpines = 2 >>> eList = hdc.parseEventListFromDataStream() >>> eList is hdc.eventList True >>> for e in eList: ... print(e) <music21.humdrum.spineParser.GlobalReferenceLine object at 0x...> <music21.humdrum.spineParser.GlobalCommentLine object at 0x...> <music21.humdrum.spineParser.SpineLine object at 0x...> <music21.humdrum.spineParser.SpineLine object at 0x...> <music21.humdrum.spineParser.SpineLine object at 0x...> >>> print(eList[0].value) Beethoven, Ludwig van >>> print(eList[3].spineData) ['C4', 'pp']
- HumdrumDataCollection.parseMetadata(s=None)¶
Create a metadata object for the file.
- HumdrumDataCollection.parseNonOpus(dataStream)¶
The main parse function for non-opus data collections.
- HumdrumDataCollection.parseOpusDataCollections(dataCollections)¶
Take a dataCollection from determineIfDataStreamIsOpus and set self.stream to be an Opus instead.
>>> mps = humdrum.testFiles.multipartSanctus >>> hdc = humdrum.spineParser.HumdrumDataCollection(mps) >>> (hasOpus, dataCollections) = hdc.determineIfDataStreamIsOpus() >>> if hasOpus is True: ... op = hdc.parseOpusDataCollections(dataCollections) ... print(len(op.scores)) ... for sc in op.scores: ... print(sc) 3 <music21.stream.Score section_1> <music21.stream.Score section_2> <music21.stream.Score section_3>
- HumdrumDataCollection.parseProtoSpinesAndEventCollections()¶
Run after
parseEventListFromDataStream()
to take self.eventList and slice it horizontally to get self.eventCollections, which is a list of EventCollection objects, or things that happen simultaneously.And, more importantly, this method slices self.eventList vertically to get self.protoSpines which is a list of ProtoSpines, that is a vertical slice of everything that happens in a column, regardless of spine-path indicators.
EventCollection objects store global events at the position. ProtoSpines do not.
So self.eventCollections and self.protoSpines can each be thought of as a two-dimensional sheet of cells, but where the first index of the former is the vertical position in the dataStream and the first index of the latter is the horizontal position in the dataStream. The contents of each cell is a SpineEvent object or None (if there’s no data at that point). Even ‘.’ (continuation events) get translated into SpineEvent objects.
Calls
parseEventListFromDataStream()
if it hasn’t already been called.returns a tuple of protoSpines and eventCollections in addition to setting it in the calling object.
>>> eventString = ('!!!COM: Beethoven, Ludwig van\n' + ... '!! Not really a piece by Beethoven\n' + ... '**kern\t**dynam\n' + ... 'C4\tpp\n' + ... 'D8\t.\n') >>> hdc = humdrum.spineParser.HumdrumDataCollection(eventString) >>> hdc.maxSpines = 2 >>> hdc.fileLength = 5 >>> protoSpines, eventCollections = hdc.parseProtoSpinesAndEventCollections() >>> protoSpines is hdc.protoSpines True >>> eventCollections is hdc.eventCollections True
Looking at individual slices is unlikely to tell you much.
>>> for thisSlice in eventCollections: ... print(thisSlice) <music21.humdrum.spineParser.EventCollection object at 0x...> <music21.humdrum.spineParser.EventCollection object at 0x...> <music21.humdrum.spineParser.EventCollection object at 0x...> <music21.humdrum.spineParser.EventCollection object at 0x...> <music21.humdrum.spineParser.EventCollection object at 0x...>
>>> for thisSlice in protoSpines: ... print(thisSlice) <music21.humdrum.spineParser.ProtoSpine object at 0x...> <music21.humdrum.spineParser.ProtoSpine object at 0x...>
But looking at the individual slices is revealing:
>>> eventCollections[4].getAllOccurring() [<music21.humdrum.spineParser.SpineEvent D8>, <music21.humdrum.spineParser.SpineEvent pp>]
Methods inherited from ProtoM21Object
:
HumdrumFile¶
- class music21.humdrum.spineParser.HumdrumFile(filename: str | pathlib.Path | None = None)¶
A HumdrumFile is a HumdrumDataCollection which takes as a mandatory argument a filename to be opened and read.
HumdrumFile
bases
HumdrumFile
read-only properties
Read-only properties inherited from ProtoM21Object
:
HumdrumFile
methods
- HumdrumFile.parseFileHandle(fileHandle)¶
takes a fileHandle and returns a HumdrumCollection by calling parse()
- HumdrumFile.parseFilename(filename: str | pathlib.Path | None = None)¶
Methods inherited from HumdrumDataCollection
:
Methods inherited from ProtoM21Object
:
HumdrumLine¶
- class music21.humdrum.spineParser.HumdrumLine¶
HumdrumLine is a dummy class for subclassing
SpineLine
,GlobalCommentLine
, andGlobalReferenceLine
classes all of which represent one horizontal line of text in aHumdrumDataCollection
that is aware of its position in the file.See the documentation for the specific classes mentioned above for more details.
HumdrumSpine¶
- class music21.humdrum.spineParser.HumdrumSpine(spineId: int = 0, eventList=None, streamClass=<class 'music21.stream.base.Stream'>)¶
A HumdrumSpine is a representation of a generic HumdrumSpine regardless of **definition after spine path indicators have been simplified.
A HumdrumSpine is a collection of events arranged vertically that have a connection to each other. Each HumdrumSpine MUST have an id (numeric or string) attached to it.
>>> SE = humdrum.spineParser.SpineEvent >>> spineEvents = [SE('**kern'), SE('c,4'), SE('d#8')] >>> spine1Id = 5 >>> spine1 = humdrum.spineParser.HumdrumSpine(spine1Id, spineEvents) >>> spine1.insertPoint = 5 >>> spine1.endingPosition = 6 >>> spine1.parentSpine = 3 # spine 3 is the previous spine leading to this one >>> spine1.childSpines = [7, 8] # the spine ends by being split into spines 7 and 8
we keep weak references to the spineCollection so that we don’t have circular references
>>> spineCollection1 = humdrum.spineParser.SpineCollection() >>> spine1.spineCollection = spineCollection1
The spineType property searches the EventList or parentSpine to figure out the spineType
>>> spine1.spineType 'kern'
Spines can be iterated through:
>>> for e in spine1: ... print(e) **kern c,4 d#8
If you’d eventually like this spine to be converted to a class other than
Stream
, pass its classname in as the streamClass argument:>>> spine2 = humdrum.spineParser.HumdrumSpine(streamClass=stream.Part) >>> spine2.stream <music21.stream.Part ...>
HumdrumSpine
bases
HumdrumSpine
read-only properties
Read-only properties inherited from ProtoM21Object
:
HumdrumSpine
read/write properties
- HumdrumSpine.spineCollection¶
- HumdrumSpine.spineType¶
searches the current and parent spineType for a search
HumdrumSpine
methods
- HumdrumSpine.append(event)¶
add an item to this Spine
- HumdrumSpine.moveElementsIntoMeasures(streamIn)¶
Takes a parsed stream and moves the elements inside the measures. Works with pickup measures, etc. Does not automatically create ties, etc.
Why not just use Stream.makeMeasures()? because humdrum measures contain extra information about barlines etc. and pickups are explicitly defined.
>>> s1 = stream.Stream() >>> s1.append(meter.TimeSignature('2/4')) >>> m1 = stream.Measure() >>> m1.number = 1 >>> s1.append(m1) >>> s1.append(note.Note('C4', type='quarter')) >>> m2 = stream.Measure() >>> m2.number = 2 >>> s1.append(m2) >>> s1.append(note.Note('D4', type='half')) >>> s1.show('text') {0.0} <music21.stream.Measure 1 offset=0.0> {0.0} <music21.meter.TimeSignature 2/4> {0.0} <music21.note.Note C> {1.0} <music21.stream.Measure 2 offset=1.0> {1.0} <music21.note.Note D>
>>> hds = humdrum.spineParser.HumdrumSpine() >>> s2 = hds.moveElementsIntoMeasures(s1) >>> s2.show('text') {0.0} <music21.stream.Measure 1 offset=0.0> {0.0} <music21.meter.TimeSignature 2/4> {0.0} <music21.note.Note C> {1.0} <music21.stream.Measure 2 offset=1.0> {0.0} <music21.note.Note D>
The first measure is correctly identified as a pickup!
>>> s2.measure(1).paddingLeft 1.0
- HumdrumSpine.parse()¶
Dummy method that pushes all these objects to HumdrumSpine.stream as ElementWrappers. Should be overridden in specific Spine subclasses.
Methods inherited from ProtoM21Object
:
KernSpine¶
- class music21.humdrum.spineParser.KernSpine(spineId: int = 0, eventList=None, streamClass=<class 'music21.stream.base.Stream'>)¶
A KernSpine is a type of humdrum spine with the **kern attribute set and thus events are processed as if they are kern notes
KernSpine
bases
KernSpine
read-only properties
Read-only properties inherited from ProtoM21Object
:
KernSpine
read/write properties
Read/write properties inherited from HumdrumSpine
:
KernSpine
methods
- KernSpine.parse()¶
Dummy method that pushes all these objects to HumdrumSpine.stream as ElementWrappers. Should be overridden in specific Spine subclasses.
- KernSpine.processChordEvent(eventC)¶
Process a single chord event
Like processNoteEvent, stores information about current beam and tuplet state.
- KernSpine.processNoteEvent(eventC)¶
similar to hdStringToNote, this method processes a string representing a single note, but stores information about current beam and tuplet state.
- KernSpine.setBeamsForNote(n)¶
sets the beams for a Note (or Chord) given self.currentBeamNumbers and updates self.currentBeamNumbers based on stop beams.
Safe enough to use on elements such as rests that don’t have beam info.
- KernSpine.setTupletTypeForNote(n)¶
Methods inherited from HumdrumSpine
:
Methods inherited from ProtoM21Object
:
MiscTandem¶
- class music21.humdrum.spineParser.MiscTandem(tandem='', **keywords)¶
MiscTandem
bases
MiscTandem
read-only properties
Read-only properties inherited from Music21Object
:
Read-only properties inherited from ProtoM21Object
:
MiscTandem
read/write properties
Read/write properties inherited from Music21Object
:
MiscTandem
methods
Methods inherited from Music21Object
:
Methods inherited from ProtoM21Object
:
MiscTandem
instance variables
Instance variables inherited from Music21Object
:
ProtoSpine¶
- class music21.humdrum.spineParser.ProtoSpine(eventList=None)¶
A ProtoSpine is a collection of events arranged vertically. It differs from a HumdrumSpine in that spine paths are not followed. So ProtoSpine(1) would be everything in the 2nd column of a Humdrum file regardless of whether the 2nd column was at some point an independent Spine or if it later became a split from the first spine.
See
parseProtoSpinesAndEventCollections()
for more details on how ProtoSpine objects are created.
ProtoSpine
bases
ProtoSpine
read-only properties
Read-only properties inherited from ProtoM21Object
:
ProtoSpine
methods
Methods inherited from ProtoM21Object
:
SpineCollection¶
- class music21.humdrum.spineParser.SpineCollection¶
A SpineCollection is a set of HumdrumSpines with relationships to each other and where their position attributes indicate simultaneous onsets.
When you iterate over a SpineCollection, it goes from right to left, since that’s the order that humdrum expects.
SpineCollection
bases
SpineCollection
read-only properties
Read-only properties inherited from ProtoM21Object
:
SpineCollection
methods
- SpineCollection.addSpine(streamClass: type[music21.stream.base.Stream] = <class 'music21.stream.base.Part'>)¶
creates a new spine in the collection and returns it.
By default, the underlying music21 class of the spine is
Part
. This can be overridden by passing in a different streamClass.Automatically sets the id of the Spine.
>>> hsc = humdrum.spineParser.SpineCollection() >>> newSpine = hsc.addSpine() >>> newSpine.id 0 >>> newSpine.stream <music21.stream.Part ...> >>> newSpine2 = hsc.addSpine(streamClass=stream.Stream) >>> newSpine2.id 1 >>> newSpine2 <music21.humdrum.spineParser.HumdrumSpine: 1> >>> newSpine2.stream <music21.stream.Stream ...>
- SpineCollection.appendSpine(spine)¶
appendSpine(spine) – appends an already existing HumdrumSpine to the SpineCollection. Returns void
- SpineCollection.assignIds()¶
assign an ID based on the instrument or just a string of a number if none
>>> hsc = humdrum.spineParser.SpineCollection() >>> newSpineDefault = hsc.addSpine() >>> newSpineDefault2 = hsc.addSpine() >>> newSpineOboe1 = hsc.addSpine() >>> newSpineOboe2 = hsc.addSpine() >>> newSpineTrumpet = hsc.addSpine() >>> newSpineOboe1.stream.append(instrument.Oboe()) >>> newSpineOboe2.stream.append(instrument.Oboe()) >>> newSpineTrumpet.stream.append(instrument.Trumpet()) >>> hsc.assignIds() >>> for sp in hsc.spines: ... print(sp.stream.id) 1 2 Oboe-1 Oboe-2 Trumpet
- SpineCollection.createMusic21Streams()¶
Create Music21 Stream objects from spineCollections by running:
self.reclassSpines() self.parseMusic21() self.performInsertions() self.moveObjectsToMeasures() self.moveDynamicsAndLyricsToStreams() self.makeVoices() self.assignIds()
- SpineCollection.getOffsetsAndPrioritiesByPosition()¶
iterates through the spines by location and records the offset and priority for each
Returns a dictionary where each index is humdrumPosition and the value is a two-element tuple where the first element is the music21 offset and the second element is a list of Music21Objects at that position
- SpineCollection.getSpineById(spineId)¶
returns the HumdrumSpine with the given id.
raises a HumdrumException if the spine with a given id is not found
- SpineCollection.makeVoices() None ¶
make voices for each kernSpine – why not just run stream.makeVoices() ? because we have more information here that lets us make voices more intelligently
Should be done after measures have been made.
- SpineCollection.moveDynamicsAndLyricsToStreams()¶
move
**dynam
and**lyrics/**text
information to the appropriate staff.Assumes that
*staff
is consistent through the spine.
- SpineCollection.moveObjectsToMeasures()¶
run moveElementsIntoMeasures for each HumdrumSpine that is not a sub-spine.
Also fixes up the tuplets using duration.TupletFixer
- SpineCollection.parseMusic21()¶
runs spine.parse() for each Spine. thus populating the spine.stream for each Spine
- SpineCollection.performInsertions()¶
take a parsed spineCollection as music21 objects and take sub-spines and put them in their proper location
- SpineCollection.performSpineInsertion(thisSpine, newStream, insertionPoint)¶
Insert all the spines into newStream that should be inserted into thisSpine at insertionPoint.
- SpineCollection.reclassSpines()¶
changes the classes of HumdrumSpines to more specific types (KernSpine, DynamicSpine) according to their spineType (e.g., **kern, **dynam)
- SpineCollection.removeSpineById(spineId)¶
deletes a spine from the SpineCollection (after inserting, integrating, etc.)
>>> hsc = humdrum.spineParser.SpineCollection() >>> newSpine = hsc.addSpine() >>> newSpine.id 0 >>> newSpine2 = hsc.addSpine() >>> newSpine2.id 1 >>> hsc.spines [<music21.humdrum.spineParser.HumdrumSpine: 0>, <music21.humdrum.spineParser.HumdrumSpine: 1>] >>> hsc.removeSpineById(newSpine.id) >>> hsc.spines [<music21.humdrum.spineParser.HumdrumSpine: 1>]
raises a HumdrumException if the spine with a given id is not found
Methods inherited from ProtoM21Object
:
SpineComment¶
- class music21.humdrum.spineParser.SpineComment(comment='', **keywords)¶
A Music21Object that represents a comment in a single spine.
>>> sc = humdrum.spineParser.SpineComment('! this is a spine comment') >>> sc <music21.humdrum.spineParser.SpineComment 'this is a spine comment'> >>> sc.comment 'this is a spine comment'
SpineComment
bases
SpineComment
read-only properties
Read-only properties inherited from Music21Object
:
Read-only properties inherited from ProtoM21Object
:
SpineComment
read/write properties
Read/write properties inherited from Music21Object
:
SpineComment
methods
Methods inherited from Music21Object
:
Methods inherited from ProtoM21Object
:
SpineComment
instance variables
Instance variables inherited from Music21Object
:
SpineEvent¶
- class music21.humdrum.spineParser.SpineEvent(contents: str = '', position: int = 0)¶
A SpineEvent is an event in a HumdrumSpine or ProtoSpine.
It’s .contents property contains the contents of the spine, or it could be ‘.’, in which case it means that a particular event appears after the last event in a different spine. It could also be “None” indicating that there is no event at all at this moment in the humdrum file. Happens if no ProtoSpine exists at this point in the file in this tab position.
Should be initialized with its contents and position in file.
These attributes are optional but likely to be very helpful:
position -- event position in the file protoSpineId -- ProtoSpine id (0 to N) spineId -- id of HumdrumSpine actually attached to (after SpinePaths are parsed)
The toNote() method converts the contents into a music21 note as if it’s kern – useful to have in all spine types.
>>> se1 = humdrum.spineParser.SpineEvent('EEE-8') >>> se1.position = 40 >>> se1.contents 'EEE-8' >>> se1 <music21.humdrum.spineParser.SpineEvent EEE-8> >>> n = se1.toNote() >>> n <music21.note.Note E->
SpineEvent
bases
SpineEvent
read-only properties
Read-only properties inherited from ProtoM21Object
:
SpineEvent
methods
- SpineEvent.toNote(convertString=None)¶
parse the object as a **kern note and return a
Note
object (or Rest, or Chord)>>> se = humdrum.spineParser.SpineEvent('DD#4') >>> n = se.toNote() >>> n <music21.note.Note D#> >>> n.octave 2 >>> n.duration.type 'quarter'
Methods inherited from ProtoM21Object
:
SpineLine¶
- class music21.humdrum.spineParser.SpineLine(position: int = 0, contents: str = '')¶
A SpineLine is any horizontal line of a Humdrum file that contains one or more spine elements (separated by tabs) and not Global elements.
Takes in a position (line number in file, excluding blank lines) and a string of contents.
>>> hsl = humdrum.spineParser.SpineLine( ... position = 7, contents='C4\t!local comment\t*M[4/4]\t.\n') >>> hsl.position 7 >>> hsl.numSpines 4 >>> hsl.spineData ['C4', '!local comment', '*M[4/4]', '.']
SpineLine
bases
Functions¶
- music21.humdrum.spineParser.hdStringToMeasure(contents, previousMeasure=None)¶
kern uses an equals sign followed by processing instructions to create new measures.
N.B. – much of the code for describing how repeat signs are encoded is among the oldest code for music21 and was not updated when musicxml parsing was added. It does not yet use the bar.RepeatMark() class or any other post 2009 additions.
- music21.humdrum.spineParser.hdStringToNote(contents)¶
returns a
Note
(or Rest or Unpitched, etc.) matching the current SpineEvent. Does not check to see that it is sane or part of a**kern
spine, etc.New rhythmic extensions formerly defined in wiki.humdrum.org/index.php/Rational_rhythms and now at https://extras.humdrum.org/man/rscale/ are fully implemented:
>>> n = humdrum.spineParser.hdStringToNote('CC3%2') >>> n.duration.quarterLength Fraction(8, 3) >>> n.duration.fullName 'Whole Triplet (2 2/3 QL)'
>>> n = humdrum.spineParser.hdStringToNote('e-00.') >>> n.pitch <music21.pitch.Pitch E-4> >>> n.duration.quarterLength 24.0 >>> n.duration.fullName 'Perfect Longa'
>>> n = humdrum.spineParser.hdStringToNote('F#000') >>> n.duration.quarterLength 32.0 >>> n.duration.fullName 'Imperfect Maxima'
Note that the following example is interpreted as one note in the time of a double-dotted quarter not a double-dotted quarter-note triplet.
I believe that the latter definition, though used in https://kern.humdrum.org/cgi-bin/ksdata?l=musedata/mozart/quartet&file=k421-01.krn&f=kern and the Josquin Research Project [JRP] is incorrect, seeing as it contradicts the specification in https://web.archive.org/web/20100203144730/http://www.music-cog.ohio-state.edu/Humdrum/representations/kern.html#N-Tuplets
This is the default:
>>> humdrum.spineParser.flavors['JRP'] = False
>>> n = humdrum.spineParser.hdStringToNote('6..fff') >>> n.duration.quarterLength Fraction(7, 6)
>>> n.duration.dots 0
>>> n.duration.tuplets[0].durationNormal.dots 2
If you want the JRP definition, set humdrum.spineParser.flavors[‘JRP’] = True before calling converter.parse() or anything like that:
>>> humdrum.spineParser.flavors['JRP'] = True >>> n = humdrum.spineParser.hdStringToNote('6..fff') >>> n.duration.quarterLength Fraction(7, 6) >>> n.duration.dots 2 >>> n.duration.tuplets[0].durationNormal.dots 0
>>> n = humdrum.spineParser.hdStringToNote('gg#q/LL') >>> n.duration <music21.duration.GraceDuration unlinked type:eighth quarterLength:0.0> >>> n.duration.isGrace True
- music21.humdrum.spineParser.kernTandemToObject(tandem)¶
Kern uses symbols such as
*M5/4
and*clefG2
, etc., to control processingThis method converts them to music21 objects.
>>> m = humdrum.spineParser.kernTandemToObject('*M3/1') >>> m <music21.meter.TimeSignature 3/1>
Unknown objects are converted to MiscTandem objects:
>>> m2 = humdrum.spineParser.kernTandemToObject('*TandyUnk') >>> m2 <music21.humdrum.spineParser.MiscTandem *TandyUnk>