music21.metadata

Classes and functions for creating and processing metadata associated with scores, works, and fragments, such as titles, movements, authors, publishers, and regions.

The Metadata object is the main public interface to metadata components. A Metadata object can be added to a Stream and used to set common score attributes, such as title and composer. A Metadata object found at offset zero can be accessed through a Stream’s metadata property.

The following example creates a Stream object, adds a Note object, and configures and adds the title and composer properties of a Metadata object.

>>> s = stream.Score()
>>> p = stream.Part()
>>> m = stream.Measure()
>>> m.append(note.Note())
>>> p.append(m)
>>> s.append(p)
>>> s.insert(0, metadata.Metadata())
>>> s.metadata.title = 'title'
>>> s.metadata.composer = 'composer'
>>> s.show()
../_images/moduleMetadata-01.png

AmbitusShort

class music21.metadata.AmbitusShort(semitones, diatonic, pitchLowest, pitchHighest)

Metadata

class music21.metadata.Metadata(*args, **keywords)

Metadata represent data for a work or fragment, including title, composer, dates, and other relevant information.

Metadata is a Music21Object subclass, meaning that it can be positioned on a Stream by offset and have a Duration.

In many cases, each Stream will have a single Metadata object at the zero offset position.

>>> md = metadata.Metadata(title='Concerto in F')
>>> md.title
'Concerto in F'

Or by three-letter abbreviation:

>>> md = metadata.Metadata(otl='Concerto in F')
>>> md.otl
'Concerto in F'
>>> md.title
'Concerto in F'

Or by setWorkId

>>> md.setWorkId('title', 'Rhapsody in Blue')
>>> md.title
'Rhapsody in Blue'
>>> md.otl
'Rhapsody in Blue'
>>> md.composer = 'Gershwin, George'

These are used by .search() methods to determine what attributes are made available by default.

>>> md.searchAttributes
('actNumber', 'alternativeTitle', 'associatedWork', 'collectionDesignation',
 'commission', 'composer', 'copyright', 'countryOfComposition', 'date', 'dedication',
 'groupTitle', 'localeOfComposition', 'movementName', 'movementNumber', 'number',
 'opusNumber', 'parentTitle', 'popularTitle', 'sceneNumber', 'textLanguage',
 'textOriginalLanguage', 'title', 'volume')

Plus anything that is in contributors…

All contributors are stored in a .contributors list:

>>> md.contributors
[<music21.metadata.primitives.Contributor composer:Gershwin, George>]

Metadata bases

Metadata read-only properties

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

Metadata read/write properties

Metadata.alternativeTitle

Get or set the alternative title.

>>> md = metadata.Metadata(popularTitle='Eroica')
>>> md.alternativeTitle = 'Heroic Symphony'
>>> md.alternativeTitle
'Heroic Symphony'
Metadata.composer

Get or set the composer of this work. Only the first composer can be got or set via properties. Instead add Composer roles to the .contributors list.

The composer attribute does not live in Metadata, but creates a Contributor object in the .contributors object.

>>> md = metadata.Metadata(
...     title='Symphony in e minor',
...     popularTitle='Gaelic',
...     composer='Beach, Mrs. H.H.A.',
...     )
>>> md.composer
'Beach, Mrs. H.H.A.'
>>> md.composer = 'Beach, Amy Marcy Cheney'
>>> md.composer
'Beach, Amy Marcy Cheney'
Metadata.composers

Get or set a list of strings of all composer roles.

>>> md = metadata.Metadata(title='Yellow River Concerto')
>>> md.composers = ['Xian Xinghai', 'Yin Chengzong']

(Yin Chengzong might be better called “Arranger” but this is for illustrative purposes)

>>> md.composers
['Xian Xinghai', 'Yin Chengzong']

Might as well add a third composer to the concerto committee?

>>> contrib3 = metadata.Contributor(role='composer', name='Chu Wanghua')
>>> md.addContributor(contrib3)
>>> md.composers
['Xian Xinghai', 'Yin Chengzong', 'Chu Wanghua']

If there are no composers, returns an empty list:

>>> md = metadata.Metadata(title='Sentient Algorithmic Composition')
>>> md.composers
[]
Metadata.date

Get or set the date of this work as one of the following date objects:

DateSingle, DateRelative, DateBetween, DateSelection,

>>> md = metadata.Metadata(
...     title='Third Symphony',
...     popularTitle='Eroica',
...     composer='Beethoven, Ludwig van',
...     )
>>> md.date = '1805'
>>> md.date
'1805/--/--'
>>> md.date = metadata.DateBetween(['1803/01/01', '1805/04/07'])
>>> md.date
'1803/01/01 to 1805/04/07'
Metadata.librettist

Gets or sets a single librettist for this work:

>>> md = metadata.Metadata(title='Death of Klinghoffer, The')
>>> md.librettist = 'Goodman, Alice'
>>> md.librettist
'Goodman, Alice'

To preserve continuity with Humdrum, library catalogues, etc., librettists should be distinguished from lyricists etc., but sometimes the line is not 100% clear.

Metadata.librettists

Gets or sets a list of librettists for this work:

>>> md = metadata.Metadata(title='Madama Butterfly')
>>> md.librettists = ['Illica, Luigi', 'Giacosa, Giuseppe']
>>> md.librettists
['Illica, Luigi', 'Giacosa, Giuseppe']

Should be distinguished from lyricists etc.

Metadata.localeOfComposition

Get or set the locale of composition, or origin, of the work.

Metadata.lyricist

Gets or sets a single lyricist for this work:

>>> md = metadata.Metadata(title='Girlfriend')
>>> md.lyricist = 'Keys, Alicia'

To preserve continuity with Humdrum, library catalogues, etc., lyricists should be distinguished from librettists etc., but sometimes the line is not 100% clear:

>>> md = metadata.Metadata(title='West Side Story')
>>> md.lyricist = 'Sondheim, Stephen'
Metadata.lyricists

Gets or sets a list of lyricists for this work:

>>> md = metadata.Metadata(title='Rumors')
>>> md.lyricists = ['Buckingham, Lindsey', 'McVie, Christine', 'Nicks, Stevie']
>>> md.lyricists
['Buckingham, Lindsey', 'McVie, Christine', 'Nicks, Stevie']

Should be distinguished from librettists etc.

Metadata.movementName

Get or set the movement title.

Note that a number of pieces from various MusicXML datasets have the piece title as the movement title. For instance, the Bach Chorales, since they are technically movements of larger cantatas.

Metadata.movementNumber

Get or set the movement number.

>>> md = metadata.Metadata(title='Ode to Joy')
>>> md.movementNumber = 3

Note that movement numbers are always returned as strings! This may change in the future.

>>> md.movementNumber
'3'
Metadata.number

Get or set the number of the work within a collection of pieces. (for instance, the number within a collection of ABC files)

Note that numbers are always returned as strings! This may change in the future.

Metadata.opusNumber

Get or set the opus number.

Note that opusNumbers are always returned as strings! This may change in the future.

Metadata.title

Get the title of the work, or the next-matched title string available from a related parameter fields.

>>> md = metadata.Metadata(title='Third Symphony')
>>> md.title
'Third Symphony'
>>> md = metadata.Metadata(popularTitle='Eroica')
>>> md.title
'Eroica'
>>> md = metadata.Metadata(
...     title='Third Symphony',
...     popularTitle='Eroica',
...     )
>>> md.title
'Third Symphony'
>>> md.popularTitle
'Eroica'
>>> md.otp
'Eroica'

Read/write properties inherited from Music21Object:

Metadata methods

static Metadata.abbreviationToWorkId(abbreviation)

Get work id abbreviations.

>>> metadata.Metadata.abbreviationToWorkId('otl')
'title'
>>> for work_id in metadata.Metadata.workIdAbbreviationDict:
...    result = metadata.Metadata.abbreviationToWorkId(work_id)
Metadata.addContributor(c)

Assign a Contributor object to this Metadata.

>>> md = metadata.Metadata(title='Gaelic Symphony')
>>> c = metadata.Contributor()
>>> c.name = 'Beach, Amy'
>>> c.role = 'composer'
>>> md.addContributor(c)
>>> md.composer
'Beach, Amy'

Add maiden name as an alternative composer name:

>>> c_alt = metadata.Contributor()
>>> c_alt.name = 'Cheney, Amy Marcy'
>>> c_alt.role = 'composer'
>>> md.addContributor(c_alt)
>>> md.composers
['Beach, Amy', 'Cheney, Amy Marcy']
>>> md.search('Beach')
(True, 'composer')
>>> md.search('Cheney')
(True, 'composer')

Note that in this case, a “composerAlias” would probably be a more appropriate role than a second composer.

All contributor roles are searchable, even if they are not standard roles:

>>> dancer = metadata.Contributor()
>>> dancer.names = ['Merce Cunningham', 'Martha Graham']
>>> dancer.role = 'interpretive dancer'
>>> md.addContributor(dancer)
>>> md.search('Cunningham')
(True, 'interpretive dancer')
Metadata.all(skipContributors=False)

Returns all values (as strings) stored in this metadata as a sorted list of tuples.

>>> c = corpus.parse('corelli/opus3no1/1grave')
>>> c.metadata.all()
[('arranger', 'Michael Scott Cuthbert'),
 ('composer', 'Arcangelo Corelli'),
 ('copyright', '© 2014, Creative Commons License (CC-BY)'),
 ('movementName', 'Sonata da Chiesa, No. I (opus 3, no. 1)')]

Skip contributors is there to help with musicxml parsing – there’s no reason for it except that we haven’t exposed enough functionality yet:

>>> c.metadata.date = metadata.DateRelative('1689', 'onOrBefore')
>>> c.metadata.localeOfComposition = 'Rome'
>>> c.metadata.all(skipContributors=True)
[('copyright', '© 2014, Creative Commons License (CC-BY)'),
 ('date', '1689/--/-- or earlier'),
 ('localeOfComposition', 'Rome'),
 ('movementName', 'Sonata da Chiesa, No. I (opus 3, no. 1)')]
Metadata.getContributorsByRole(value)

Return a Contributor if defined for a provided role.

>>> md = metadata.Metadata(title='Violin Concerto')
>>> c = metadata.Contributor()
>>> c.name = 'Price, Florence'
>>> c.role = 'composer'
>>> md.addContributor(c)
>>> cList = md.getContributorsByRole('composer')
>>> cList
[<music21.metadata.primitives.Contributor composer:Price, Florence>]
>>> cList[0].name
'Price, Florence'

Some musicxml files have contributors with no role defined. To get these contributors, search for getContributorsByRole(None). N.B. upon output to MusicXML, music21 gives these contributors the generic role of “creator”

>>> c2 = metadata.Contributor()
>>> c2.name = 'Baron van Swieten'
>>> md.addContributor(c2)
>>> noRoleList = md.getContributorsByRole(None)
>>> len(noRoleList)
1
>>> noRoleList[0].role
>>> noRoleList[0].name
'Baron van Swieten'
Metadata.search(query=None, field=None, **kwargs)

Search one or all fields with a query, given either as a string or a regular expression match.

>>> md = metadata.Metadata()
>>> md.composer = 'Joplin, Scott'
>>> md.title = 'Maple Leaf Rag'
>>> md.search(
...     'joplin',
...     field='composer',
...     )
(True, 'composer')

Note how the incomplete field name in the following example is still matched:

>>> md.search(
...     'joplin',
...     field='compos',
...     )
(True, 'composer')

These don’t work (Richard didn’t have the sense of rhythm to write this…)

>>> md.search(
...     'Wagner',
...     field='composer',
...     )
(False, None)
>>> md.search('Wagner')
(False, None)
>>> md.search('leaf')
(True, 'title')
>>> md.search(
...     'leaf',
...     field='composer',
...     )
(False, None)
>>> md.search(
...     'leaf',
...     field='title',
...     )
(True, 'title')
>>> md.search('leaf|entertainer')
(True, 'title')
>>> md.search('opl(.*)cott')
(True, 'composer')

New in v.4 – use a keyword argument to search that field directly:

>>> md.search(composer='Joplin')
(True, 'composer')
Metadata.setWorkId(idStr, value)

Directly set a work id, given either as a full string name or as a three character abbreviation. The following work id abbreviations and their full id string are given as follows. In many cases the Metadata object support properties for convenient access to these work ids.

Id abbreviations and strings::
  • otl / title

  • otp / popularTitle

  • ota / alternativeTitle

  • opr / parentTitle

  • oac / actNumber

  • osc / sceneNumber

  • omv / movementNumber

  • omd / movementName

  • ops / opusNumber

  • onm / number

  • ovm / volume

  • ode / dedication

  • oco / commission

  • gtl / groupTitle

  • gaw / associatedWork

  • gco / collectionDesignation

  • txo / textOriginalLanguage

  • txl / textLanguage

  • ocy / countryOfComposition

  • opc / localeOfComposition.

>>> md = metadata.Metadata(title='Quartet')
>>> md.title
'Quartet'
>>> md.setWorkId('otl', 'Trio')
>>> md.title
'Trio'
>>> md.setWorkId('ocy', 'Latvia')
>>> md.ocy
'Latvia'
>>> md.countryOfComposition
'Latvia'
>>> md.setWorkId('sdf', None)
Traceback (most recent call last):
music21.exceptions21.MetadataException: no work id available with id: sdf
static Metadata.workIdToAbbreviation(value)

Get a work abbreviation from a string representation.

>>> metadata.Metadata.workIdToAbbreviation('localeOfComposition')
'opc'

Static method.

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

Metadata instance variables

Instance variables inherited from Music21Object:

RichMetadata

class music21.metadata.RichMetadata(*args, **keywords)

RichMetadata adds to Metadata information about the contents of the Score it is attached to. TimeSignature, KeySignature and related analytical is stored. RichMetadata are generally only created in the process of creating stored JSON metadata.

>>> richMetadata = metadata.RichMetadata(title='Concerto in F')
>>> richMetadata.title
'Concerto in F'
>>> richMetadata.keySignatureFirst = key.KeySignature(-1)
>>> 'keySignatureFirst' in richMetadata.searchAttributes
True
>>> richMetadata.searchAttributes
('actNumber', 'alternativeTitle', 'ambitus', 'associatedWork', 'collectionDesignation',
 'commission', 'composer', 'copyright', 'countryOfComposition', 'date', 'dedication',
 'groupTitle', 'keySignatureFirst', 'keySignatures', 'localeOfComposition', 'movementName',
 'movementNumber', 'noteCount', 'number', 'numberOfParts',
 'opusNumber', 'parentTitle', 'pitchHighest',
 'pitchLowest', 'popularTitle', 'quarterLength', 'sceneNumber', 'sourcePath', 'tempoFirst',
 'tempos', 'textLanguage', 'textOriginalLanguage', 'timeSignatureFirst',
 'timeSignatures', 'title', 'volume')

RichMetadata bases

RichMetadata read-only properties

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

RichMetadata read/write properties

Read/write properties inherited from Metadata:

Read/write properties inherited from Music21Object:

RichMetadata methods

RichMetadata.getSourcePath(streamObj)

Get a string of the path after the corpus for the piece…useful for searching on corpus items without proper composer data…

>>> rmd = metadata.RichMetadata()
>>> b = corpus.parse('bwv66.6')
>>> rmd.getSourcePath(b)
'bach/bwv66.6.mxl'
RichMetadata.merge(other, favorSelf=False)

Given another Metadata or RichMetadata object, combine all attributes and return a new object.

>>> md = metadata.Metadata(title='Concerto in F')
>>> md.title
'Concerto in F'
>>> richMetadata = metadata.RichMetadata()
>>> richMetadata.merge(md)
>>> richMetadata.title
'Concerto in F'
RichMetadata.update(streamObj)

Given a Stream object, update attributes with stored objects.

>>> rmd = metadata.RichMetadata()
>>> rmd.keySignatureFirst is None
True
>>> rmd.sourcePath
''
>>> b = corpus.parse('bwv66.6')
>>> rmd.update(b)
>>> rmd.keySignatureFirst
3
>>> rmd.sourcePath
'bach/bwv66.6.mxl'
>>> rmd.numberOfParts
4

Methods inherited from Metadata:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

RichMetadata instance variables

Instance variables inherited from Music21Object: