Previous topic

music21.metadata

Next topic

music21.metadata.caching

Table Of Contents

Table Of Contents

This Page

music21.metadata.bundles

MetadataBundle

class music21.metadata.bundles.MetadataBundle(expr=None)

An object that provides access to, searches within, and stores and loads multiple Metadata objects.

>>> from music21 import corpus, metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {14958 entries}>
>>> searchResults = coreBundle.search('bach', field='composer')
>>> searchResults
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> resultsEntries = searchResults.search('3/4')
>>> resultsEntries
<music21.metadata.bundles.MetadataBundle {4 entries}>

Results are ordered by their source path:

>>> resultsEntries[0]
<music21.metadata.bundles.MetadataEntry: bach_choraleAnalyses_riemenschneider001_rntxt>

To get a score out of the entry, call .parse()

>>> resultsEntries[0].parse()
<music21.stream.Score ...>

A metadata bundle can be instantiated via its static methods fromCoreCorpus(), fromLocalCorpus() and fromVirtualCorpus(), as well as from a Corpus instance, or a string indicating which corpus to draw from:

>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> localBundle = metadata.MetadataBundle.fromLocalCorpus()
>>> virtualBundle = metadata.MetadataBundle.fromVirtualCorpus()
>>> coreCorpus = corpus.CoreCorpus()
>>> coreBundle = metadata.MetadataBundle(coreCorpus)
>>> localCorpus = corpus.LocalCorpus()
>>> localBundle = metadata.MetadataBundle(localCorpus)
>>> virtualCorpus = corpus.VirtualCorpus()
>>> virtualBundle = metadata.MetadataBundle(virtualCorpus)
>>> coreBundle = metadata.MetadataBundle('core')
>>> localBundle = metadata.MetadataBundle('local')
>>> virtualBundle = metadata.MetadataBundle('virtual')

The static methods above take the additional step of reading the persisted-to-disk metadata bundle file, and caching the result in memory as necessary.

For the others, you’ll need to call read():

>>> coreBundle.read()
<music21.metadata.bundles.MetadataBundle 'core': {14958 entries}>

Additionally, any two metadata bundles can be operated on together as though they were sets, allowing us to build up more complex searches:

>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2012 entries}>
>>> bachBundle.intersection(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {4 entries}>

Finally, a metadata bundle need not be associated with any corpus at all, and can be populated ad hoc:

>>> anonymousBundle = metadata.MetadataBundle()
>>> paths = corpus.CoreCorpus().getMonteverdiMadrigals()[:4]
>>> failedPaths = anonymousBundle.addFromPaths(
...     paths, useMultiprocessing=False)
>>> failedPaths
[]
>>> anonymousBundle
<music21.metadata.bundles.MetadataBundle {4 entries}>

MetadataBundle read-only properties

MetadataBundle.corpus

The corpus.corpora.Corpus object associated with the metadata bundle’s name.

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> coreBundle
<music21.metadata.bundles.MetadataBundle 'core': {14958 entries}>
>>> coreBundle.corpus
<music21.corpus.corpora.CoreCorpus>
MetadataBundle.filePath

The filesystem name of the cached metadata bundle, if the metadata bundle’s name is not None.

MetadataBundle.name

The name of the metadata bundle.

Can be ‘core’, ‘local’, ‘virtual’ or None.

The names ‘core’, ‘local’ and ‘virtual refer to the core, local and virtual corpuses respectively:

>>> from music21 import metadata
>>> metadata.MetadataBundle().name is None
True
>>> metadata.MetadataBundle.fromCoreCorpus().name == 'core'
True

Return string or None.

MetadataBundle methods

MetadataBundle.addFromPaths(paths, useCorpus=False, useMultiprocessing=True)

Parse and store metadata from numerous files.

If any files cannot be loaded, their file paths will be collected in a list that is returned.

Returns a list of file paths with errors and stores the extracted metadata in self._metadataEntries.

>>> from music21 import corpus, metadata
>>> metadataBundle = metadata.MetadataBundle()
>>> metadataBundle.addFromPaths(
...     corpus.getWorkList('bwv66.6'),
...     useCorpus=True,
...     useMultiprocessing=False,
...     )
[]
>>> len(metadataBundle._metadataEntries)
1
MetadataBundle.clear()

Clear all keys in a metadata bundle:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> bachBundle.clear()
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {0 entries}>

Return none.

static MetadataBundle.corpusPathToKey(filePath, number=None)

Given a file path or corpus path, return the meta-data path:

>>> from music21 import metadata
>>> mb = metadata.MetadataBundle()
>>> key = mb.corpusPathToKey('bach/bwv1007/prelude')
>>> key.endswith('bach_bwv1007_prelude')
True
>>> key = mb.corpusPathToKey('/beethoven/opus59no1/movement1.xml')
>>> key.endswith('beethoven_opus59no1_movement1_xml')
True
MetadataBundle.delete()

Delete the filesystem cache of a named metadata bundle.

Does not delete the in-memory metadata bundle.

Return none.

MetadataBundle.difference(metadataBundle)

Compute the set-wise difference of two metadata bundles:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2012 entries}>
>>> bachBundle.difference(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {17 entries}>

Emit new metadata bundle.

classmethod MetadataBundle.fromCoreCorpus()

Return a metadata bundle for the core corpus.

Read from disk and cache it in memory if the bundle doesn’t already exist, otherwise pull from memory:

>>> from music21 import metadata
>>> coreCorpusA = metadata.MetadataBundle.fromCoreCorpus()
>>> coreCorpusB = metadata.MetadataBundle.fromCoreCorpus()
>>> coreCorpusA is coreCorpusB
True
classmethod MetadataBundle.fromLocalCorpus(name=None)

Return a metadata bundle for the local corpus.

Read from disk and cache it in memory if the bundle doesn’t already exist, otherwise pull from memory:

>>> from music21 import metadata
>>> localCorpusA = metadata.MetadataBundle.fromLocalCorpus()
>>> localCorpusB = metadata.MetadataBundle.fromLocalCorpus()
>>> localCorpusA is localCorpusB
True
classmethod MetadataBundle.fromVirtualCorpus()

Return a metadata bundle for the virtual corpus.

Read from disk and cache it in memory if the bundle doesn’t already exist, otherwise pull from memory:

>>> from music21 import metadata
>>> virtualCorpusA = metadata.MetadataBundle.fromVirtualCorpus()
>>> virtualCorpusB = metadata.MetadataBundle.fromVirtualCorpus()
>>> virtualCorpusA is virtualCorpusB
True
MetadataBundle.intersection(metadataBundle)

Compute the set-wise intersection of two metadata bundles:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2012 entries}>
>>> bachBundle.intersection(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {4 entries}>

Emit new metadata bundle.

MetadataBundle.isdisjoint(metadataBundle)

True if the set of keys in one metadata bundle are disjoint with the set of keys in another:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> beethovenBundle = coreBundle.search(
...     'beethoven',
...     field='composer',
...     )
>>> beethovenBundle
<music21.metadata.bundles.MetadataBundle {16 entries}>
>>> bachBundle.isdisjoint(beethovenBundle)
True
>>> tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2012 entries}>
>>> bachBundle.isdisjoint(tripleMeterBundle)
False

Return boolean.

MetadataBundle.issubset(metadataBundle)

True if the set of keys in one metadata bundle are a subset of the keys in another:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBachBundle = bachBundle.search('3/4')
>>> tripleMeterBachBundle
<music21.metadata.bundles.MetadataBundle {4 entries}>
>>> tripleMeterBachBundle.issubset(bachBundle)
True
>>> bachBundle.issubset(tripleMeterBachBundle)
False

Return boolean.

MetadataBundle.issuperset(metadataBundle)

True if the set of keys in one metadata bundle are a superset of the keys in another:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBachBundle = bachBundle.search('3/4')
>>> tripleMeterBachBundle
<music21.metadata.bundles.MetadataBundle {4 entries}>
>>> tripleMeterBachBundle.issuperset(bachBundle)
False
>>> bachBundle.issuperset(tripleMeterBachBundle)
True

Return boolean.

static MetadataBundle.listSearchFields()

List all available search field names:

>>> for field in metadata.MetadataBundle.listSearchFields():
...     field
...
'alternativeTitle'
'ambitus'
'composer'
'date'
'keySignatureFirst'
'keySignatures'
'localeOfComposition'
'movementName'
'movementNumber'
'noteCount'
'number'
'opusNumber'
'pitchHighest'
'pitchLowest'
'quarterLength'
'tempoFirst'
'tempos'
'timeSignatureFirst'
'timeSignatures'
'title'
MetadataBundle.read(filePath=None)

Load cached metadata from the file path suggested by the name of this MetadataBundle (‘core’, ‘local’, or ‘virtual’).

If a specific filepath is given with the filePath keyword, attempt to load cached metadata from the file at that location.

If filePath is None, and self.filePath is also None, do nothing.

>>> from music21 import metadata
>>> virtualBundle = metadata.MetadataBundle('virtual').read()

If a metadata is unnamed, and no file path is specified, an exception will be thrown:

>>> anonymousBundle = metadata.MetadataBundle().read()
Traceback (most recent call last):
MetadataException: Unnamed MetadataBundles have no default file path to read from.
MetadataBundle.rebuild(useMultiprocessing=True)

Rebuild a named bundle from scratch.

If a bundle is associated with one of music21’s corpuses, delete any metadata cache on disk, clear the bundle’s contents and reload in all files from that associated corpus.

Return the rebuilt metadata bundle.

MetadataBundle.search(query, field=None, fileExtensions=None)

Perform search, on all stored metadata, permit regular expression matching.

>>> from music21 import corpus, metadata
>>> workList = corpus.getWorkList('ciconia')
>>> metadataBundle = metadata.MetadataBundle()
>>> metadataBundle.addFromPaths(
...     workList,
...     useCorpus=True,
...     useMultiprocessing=False,
...     )
[]
>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer'
...     )
>>> searchResult
<music21.metadata.bundles.MetadataBundle {1 entry}>
>>> len(searchResult)
1
>>> searchResult[0]
<music21.metadata.bundles.MetadataEntry: ciconia_quod_jactatur_xml>
>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer',
...     fileExtensions=('.krn',),
...     )
>>> len(searchResult) # no files in this format
0
>>> searchResult = metadataBundle.search(
...     'cicon',
...     field='composer',
...     fileExtensions=('.xml'),
...     )
>>> len(searchResult)
1
MetadataBundle.symmetric_difference(metadataBundle)

Compute the set-wise symmetric differnce of two metadata bundles:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> tripleMeterBundle = coreBundle.search('3/4')
>>> tripleMeterBundle
<music21.metadata.bundles.MetadataBundle {2012 entries}>
>>> bachBundle.symmetric_difference(tripleMeterBundle)
<music21.metadata.bundles.MetadataBundle {2025 entries}>

Emit new metadata bundle.

MetadataBundle.union(metadataBundle)

Compute the set-wise union of two metadata bundles:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> bachBundle = coreBundle.search(
...     'bach',
...     field='composer',
...     )
>>> bachBundle
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> beethovenBundle = coreBundle.search(
...     'beethoven',
...     field='composer',
...     )
>>> beethovenBundle
<music21.metadata.bundles.MetadataBundle {16 entries}>
>>> bachBundle.union(beethovenBundle)
<music21.metadata.bundles.MetadataBundle {37 entries}>

Emit new metadata bundle.

MetadataBundle.validate()

Validate each metadata entry in a metadata bundle.

If the entry represents a non-virtual corpus asset, test that its source path is locatable on disk. If not, remove the metadata entry from the metadata bundle.

MetadataBundle.write(filePath=None)

Write the metadata bundle to disk as a JSON file.

If filePath is None, use self.filePath.

Returns the metadata bundle.

>>> from music21 import metadata
>>> bachBundle = metadata.MetadataBundle.fromCoreCorpus().search(
...     'bach',
...     'composer',
...     )
>>> bachBundle.filePath is None
True
>>> import os
>>> import tempfile
>>> tempFilePath = tempfile.mkstemp()[1]
>>> bachBundle.write(filePath=tempFilePath)
<music21.metadata.bundles.MetadataBundle {21 entries}>
>>> os.remove(tempFilePath)

MetadataEntry

class music21.metadata.bundles.MetadataEntry(sourcePath=None, number=None, metadataPayload=None)

An entry in a metadata bundle.

The metadata entry holds information about the source of the metadata, and can be parsed to reconstitute the score object the metadata was derived from:

>>> from music21 import metadata
>>> coreBundle = metadata.MetadataBundle.fromCoreCorpus()
>>> metadataEntry = coreBundle.search('bwv66.6')[0]
>>> metadataEntry
<music21.metadata.bundles.MetadataEntry: bach_bwv66_6_mxl>

The source path of the metadata entry refers to the file path at which its score file is found:

>>> metadataEntry.sourcePath
u'bach/bwv66.6.mxl'

The metadata payload contains its metadata object:

>>> metadataEntry.metadataPayload
<music21.metadata.RichMetadata object at 0x...>

And the metadata entry can be parsed:

>>> metadataEntry.parse()
<music21.stream.Score ...>

MetadataEntry read-only properties

MetadataEntry.corpusPath
MetadataEntry.metadataPayload
MetadataEntry.number
MetadataEntry.sourcePath

MetadataEntry methods

MetadataEntry.parse()
MetadataEntry.search(query, field=None)
MetadataEntry.show(showFormat=None)