music21.timespans.trees¶
Tools for grouping notes and chords into a searchable tree organized by start and stop offsets.
TimespanTree¶
-
class
music21.timespans.trees.
TimespanTree
(elements=None, source=None)¶ A data structure for efficiently slicing a score.
While you can construct an TimespanTree by hand, inserting timespans one at a time, the common use-case is to construct the offset-tree from an entire score at once:
>>> bach = corpus.parse('bwv66.6') >>> tree = timespans.streamToTimespanTree(bach, flatten=True, classList=(note.Note, chord.Chord)) >>> print(tree.getVerticalityAt(17.0)) <Verticality 17.0 {F#3 C#4 A4}>
All offsets are assumed to be relative to the score’s origin if flatten is True
Example: How many moments in Bach are consonant and how many are dissonant:
>>> totalConsonances = 0 >>> totalDissonances = 0 >>> for v in tree.iterateVerticalities(): ... if v.toChord().isConsonant(): ... totalConsonances += 1 ... else: ... totalDissonances += 1 >>> (totalConsonances, totalDissonances) (34, 17)
So 1/3 of the vertical moments in Bach are dissonant! But is this an accurate perception? Let’s sum up the total consonant duration vs. dissonant duration.
Do it again pairwise to figure out the length (actually this won’t include the last element)
>>> totalConsonanceDuration = 0 >>> totalDissonanceDuration = 0 >>> iterator = tree.iterateVerticalitiesNwise(n=2) >>> for verticality1, verticality2 in iterator: ... offset1 = verticality1.offset ... offset2 = verticality2.offset ... quarterLength = offset2 - offset1 ... if verticality1.toChord().isConsonant(): ... totalConsonanceDuration += quarterLength ... else: ... totalDissonanceDuration += quarterLength >>> (totalConsonanceDuration, totalDissonanceDuration) (25.5, 9.5)
Remove neighbor tones from the Bach chorale:
Here in Alto, measure 7, there’s a neighbor tone E#.
>>> bach.parts['Alto'].measure(7).show('text') {0.0} <music21.note.Note F#> {0.5} <music21.note.Note E#> {1.0} <music21.note.Note F#> {1.5} <music21.note.Note F#> {2.0} <music21.note.Note C#>
We’ll get rid of it and a lot of other neighbor tones.
>>> for verticalities in tree.iterateVerticalitiesNwise(n=3): ... horizontalities = tree.unwrapVerticalities(verticalities) ... for unused_part, horizontality in horizontalities.items(): ... if horizontality.hasNeighborTone: ... merged = horizontality[0].new( ... endTime=horizontality[2].endTime, ... ) # merged is a new ElementTimeSpan ... tree.remove(horizontality[0]) ... tree.remove(horizontality[1]) ... tree.remove(horizontality[2]) ... tree.insert(merged) >>> newBach = timespans.timespansToPartwiseStream( ... tree, ... templateStream=bach, ... ) >>> newBach.parts[1].measure(7).show('text') {0.0} <music21.chord.Chord F#4> {1.5} <music21.chord.Chord F#3> {2.0} <music21.chord.Chord C#4>
The second F# is an octave lower, so it wouldn’t get merged even if adjacent notes were fused together (which they’re not).
Note
TimespanTree is an implementation of an extended AVL tree. AVL trees are a type of binary tree, like Red-Black trees. AVL trees are very efficient at insertion when the objects being inserted are already sorted - which is usually the case with data extracted from a score. TimespanTree is an extended AVL tree because each node in the tree keeps track of not just the start offsets of ElementTimespans stored at that node, but also the earliest and latest stop offset of all ElementTimespans stores at both that node and all nodes which are children of that node. This lets us quickly located ElementTimespans which overlap offsets or which are contained within ranges of offsets. This also means that the contents of a TimespanTree are always sorted.
TODO: newBach.parts[‘Alto’].measure(7).show(‘text’) should work. KeyError: ‘provided key (Alto) does not match any id or group’
TODO: Doc examples for all functions, including privates.
TimespanTree
bases
TimespanTree
read-only properties
-
TimespanTree.
allParts
¶
-
TimespanTree.
maximumOverlap
¶ The maximum number of timespans overlapping at any given moment in this timespan collection.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.maximumOverlap 4
Returns None if there is no verticality here.
-
TimespanTree.
minimumOverlap
¶ The minimum number of timespans overlapping at any given moment in this timespan collection.
In a tree created from a monophonic stream, the minimumOverlap will probably be either zero or one.
>>> score = corpus.parse('bwv66.6') >>> tree = timespans.streamToTimespanTree( ... score, flatten=False, classList=(note.Note, chord.Chord)) >>> tree[0].minimumOverlap 1
Returns None if there is no verticality here.
Read-only properties inherited from ElementTree
:
TimespanTree
read/write properties
-
TimespanTree.
element
¶ defined so a TimespanTree can be used like an ElementTimespan
TODO: Look at subclassing or at least deriving from a common base...
Read/write properties inherited from ElementTree
:
TimespanTree
methods
-
TimespanTree.
findNextElementTimespanInSameStreamByClass
(elementTimespan, classList=None)¶ Finds next element timespan in the same stream class as elementTimespan.
Default classList is (stream.Part, )
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> timespan = tree[0] >>> timespan <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>>
>>> timespan.part <music21.stream.Part Soprano>
>>> timespan = tree.findNextElementTimespanInSameStreamByClass(timespan) >>> timespan <ElementTimespan (0.5 to 1.0) <music21.note.Note B>>
>>> timespan.part <music21.stream.Part Soprano>
>>> timespan = tree.findNextElementTimespanInSameStreamByClass(timespan) >>> timespan <ElementTimespan (1.0 to 2.0) <music21.note.Note A>>
>>> timespan.part <music21.stream.Part Soprano>
-
TimespanTree.
findPreviousElementTimespanInSameStreamByClass
(elementTimespan, classList=None)¶ Finds next element timespan in the same Part/Measure, etc. (specify in classList) as the elementTimespan.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> timespan = tree[-1] >>> timespan <ElementTimespan (35.0 to 36.0) <music21.note.Note F#>>
>>> timespan.part <music21.stream.Part Bass>
>>> timespan = tree.findPreviousElementTimespanInSameStreamByClass(timespan) >>> timespan <ElementTimespan (34.0 to 35.0) <music21.note.Note B>>
>>> timespan.part <music21.stream.Part Bass>
>>> timespan = tree.findPreviousElementTimespanInSameStreamByClass(timespan) >>> timespan <ElementTimespan (33.0 to 34.0) <music21.note.Note D>>
>>> timespan.part <music21.stream.Part Bass>
-
TimespanTree.
getVerticalityAt
(offset)¶ Gets the verticality in this offset-tree which starts at offset.
>>> bach = corpus.parse('bwv66.6') >>> tree = bach.asTimespans() >>> tree.getVerticalityAt(2.5) <Verticality 2.5 {G#3 B3 E4 B4}>
Verticalities outside the range still return a Verticality, but it might be empty...
>>> tree.getVerticalityAt(2000) <Verticality 2000 {}>
Test that it still works if the tree is empty...
>>> tree = bach.asTimespans(classList=(instrument.Tuba,)) >>> tree <TimespanTree {0} (-inf to inf) <music21.stream.Score ...>> >>> tree.getVerticalityAt(5.0) <Verticality 5.0 {}>
Returns a verticality.Verticality object.
-
TimespanTree.
getVerticalityAtOrBefore
(offset)¶ Gets the verticality in this offset-tree which starts at offset.
If the found verticality has no start timespans, the function returns the next previous verticality with start timespans.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.getVerticalityAtOrBefore(0.125) <Verticality 0.0 {A3 E4 C#5}>
>>> tree.getVerticalityAtOrBefore(0.) <Verticality 0.0 {A3 E4 C#5}>
-
TimespanTree.
iterateConsonanceBoundedVerticalities
()¶ Iterates consonant-bounded verticality subsequences in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for subsequence in tree.iterateConsonanceBoundedVerticalities(): ... print('Subequence:') ... for verticality in subsequence: ... print('\t[{}] {}: {} [{}]'.format( ... verticality.measureNumber, ... verticality, ... verticality.isConsonant, ... verticality.beatStrength, ... )) ... Subequence: [2] <Verticality 6.0 {E3 E4 G#4 B4}>: True [0.25] [2] <Verticality 6.5 {E3 D4 G#4 B4}>: False [0.125] [2] <Verticality 7.0 {A2 C#4 E4 A4}>: True [0.5] Subequence: [3] <Verticality 9.0 {F#3 C#4 F#4 A4}>: True [1.0] [3] <Verticality 9.5 {B2 D4 G#4 B4}>: False [0.125] [3] <Verticality 10.0 {C#3 C#4 E#4 G#4}>: True [0.25] Subequence: [3] <Verticality 10.0 {C#3 C#4 E#4 G#4}>: True [0.25] [3] <Verticality 10.5 {C#3 B3 E#4 G#4}>: False [0.125] [3] <Verticality 11.0 {F#2 A3 C#4 F#4}>: True [0.5] Subequence: [3] <Verticality 12.0 {F#3 C#4 F#4 A4}>: True [0.25] [4] <Verticality 13.0 {G#3 B3 F#4 B4}>: False [1.0] [4] <Verticality 13.5 {F#3 B3 F#4 B4}>: False [0.125] [4] <Verticality 14.0 {G#3 B3 E4 B4}>: True [0.25] Subequence: [4] <Verticality 14.0 {G#3 B3 E4 B4}>: True [0.25] [4] <Verticality 14.5 {A3 B3 E4 B4}>: False [0.125] [4] <Verticality 15.0 {B3 D#4 F#4}>: True [0.5] Subequence: [4] <Verticality 15.0 {B3 D#4 F#4}>: True [0.5] [4] <Verticality 15.5 {B2 A3 D#4 F#4}>: False [0.125] [4] <Verticality 16.0 {C#3 G#3 C#4 E4}>: True [0.25] Subequence: [5] <Verticality 17.5 {F#3 D4 F#4 A4}>: True [0.125] [5] <Verticality 18.0 {G#3 C#4 E4 B4}>: False [0.25] [5] <Verticality 18.5 {G#3 B3 E4 B4}>: True [0.125] Subequence: [6] <Verticality 24.0 {F#3 C#4 F#4 A4}>: True [0.25] [7] <Verticality 25.0 {B2 D4 F#4 G#4}>: False [1.0] [7] <Verticality 25.5 {C#3 C#4 E#4 G#4}>: True [0.125] Subequence: [7] <Verticality 25.5 {C#3 C#4 E#4 G#4}>: True [0.125] [7] <Verticality 26.0 {D3 C#4 F#4}>: False [0.25] [7] <Verticality 26.5 {D3 F#3 B3 F#4}>: True [0.125] Subequence: [8] <Verticality 29.0 {A#2 F#3 C#4 F#4}>: True [1.0] [8] <Verticality 29.5 {A#2 F#3 D4 F#4}>: False [0.125] [8] <Verticality 30.0 {A#2 C#4 E4 F#4}>: False [0.25] [8] <Verticality 31.0 {B2 C#4 E4 F#4}>: False [0.5] [8] <Verticality 32.0 {C#3 B3 D4 F#4}>: False [0.25] [8] <Verticality 32.5 {C#3 A#3 C#4 F#4}>: False [0.125] [9] <Verticality 33.0 {D3 B3 F#4}>: True [1.0] Subequence: [9] <Verticality 33.0 {D3 B3 F#4}>: True [1.0] [9] <Verticality 33.5 {D3 B3 C#4 F#4}>: False [0.125] [9] <Verticality 34.0 {B2 B3 D4 F#4}>: True [0.25] Subequence: [9] <Verticality 34.0 {B2 B3 D4 F#4}>: True [0.25] [9] <Verticality 34.5 {B2 B3 D4 E#4}>: False [0.125] [9] <Verticality 35.0 {F#3 A#3 C#4 F#4}>: True [0.5]
-
TimespanTree.
iterateVerticalities
(reverse=False)¶ Iterates all vertical moments in this offset-tree.
Note
The offset-tree can be mutated while its verticalities are iterated over. Each verticality holds a reference back to the offset-tree and will ask for the start-offset after (or before) its own start offset in order to determine the next verticality to yield. If you mutate the tree by adding or deleting timespans, the next verticality will reflect those changes.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> iterator = tree.iterateVerticalities() >>> for _ in range(10): ... next(iterator) ... <Verticality 0.0 {A3 E4 C#5}> <Verticality 0.5 {G#3 B3 E4 B4}> <Verticality 1.0 {F#3 C#4 F#4 A4}> <Verticality 2.0 {G#3 B3 E4 B4}> <Verticality 3.0 {A3 E4 C#5}> <Verticality 4.0 {G#3 B3 E4 E5}> <Verticality 5.0 {A3 E4 C#5}> <Verticality 5.5 {C#3 E4 A4 C#5}> <Verticality 6.0 {E3 E4 G#4 B4}> <Verticality 6.5 {E3 D4 G#4 B4}>
Verticalities can also be iterated in reverse:
>>> iterator = tree.iterateVerticalities(reverse=True) >>> for _ in range(10): ... next(iterator) ... <Verticality 35.0 {F#3 A#3 C#4 F#4}> <Verticality 34.5 {B2 B3 D4 E#4}> <Verticality 34.0 {B2 B3 D4 F#4}> <Verticality 33.5 {D3 B3 C#4 F#4}> <Verticality 33.0 {D3 B3 F#4}> <Verticality 32.5 {C#3 A#3 C#4 F#4}> <Verticality 32.0 {C#3 B3 D4 F#4}> <Verticality 31.0 {B2 C#4 E4 F#4}> <Verticality 30.0 {A#2 C#4 E4 F#4}> <Verticality 29.5 {A#2 F#3 D4 F#4}>
-
TimespanTree.
iterateVerticalitiesNwise
(n=3, reverse=False)¶ Iterates verticalities in groups of length n.
Note
The offset-tree can be mutated while its verticalities are iterated over. Each verticality holds a reference back to the offset-tree and will ask for the start-offset after (or before) its own start offset in order to determine the next verticality to yield. If you mutate the tree by adding or deleting timespans, the next verticality will reflect those changes.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> iterator = tree.iterateVerticalitiesNwise(n=2) >>> for _ in range(4): ... print(next(iterator)) ... <VerticalitySequence: [ <Verticality 0.0 {A3 E4 C#5}>, <Verticality 0.5 {G#3 B3 E4 B4}> ]> <VerticalitySequence: [ <Verticality 0.5 {G#3 B3 E4 B4}>, <Verticality 1.0 {F#3 C#4 F#4 A4}> ]> <VerticalitySequence: [ <Verticality 1.0 {F#3 C#4 F#4 A4}>, <Verticality 2.0 {G#3 B3 E4 B4}> ]> <VerticalitySequence: [ <Verticality 2.0 {G#3 B3 E4 B4}>, <Verticality 3.0 {A3 E4 C#5}> ]>
Grouped verticalities can also be iterated in reverse:
>>> iterator = tree.iterateVerticalitiesNwise(n=2, reverse=True) >>> for _ in range(4): ... print(next(iterator)) ... <VerticalitySequence: [ <Verticality 34.5 {B2 B3 D4 E#4}>, <Verticality 35.0 {F#3 A#3 C#4 F#4}> ]> <VerticalitySequence: [ <Verticality 34.0 {B2 B3 D4 F#4}>, <Verticality 34.5 {B2 B3 D4 E#4}> ]> <VerticalitySequence: [ <Verticality 33.5 {D3 B3 C#4 F#4}>, <Verticality 34.0 {B2 B3 D4 F#4}> ]> <VerticalitySequence: [ <Verticality 33.0 {D3 B3 F#4}>, <Verticality 33.5 {D3 B3 C#4 F#4}> ]>
-
TimespanTree.
splitAt
(offsets)¶ Splits all timespans in this offset-tree at offsets, operating in place.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.elementsStartingAt(0.1) ()
>>> for elementTimespan in tree.elementsOverlappingOffset(0.1): ... print("%r, %s" % (elementTimespan, elementTimespan.part.id)) ... <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>>, Soprano <ElementTimespan (0.0 to 0.5) <music21.note.Note A>>, Tenor <ElementTimespan (0.0 to 0.5) <music21.note.Note A>>, Bass <ElementTimespan (0.0 to 1.0) <music21.note.Note E>>, Alto
>>> tree.splitAt(0.1) >>> for elementTimespan in tree.elementsStartingAt(0.1): ... print("%r, %s" % (elementTimespan, elementTimespan.part.id)) ... <ElementTimespan (0.1 to 0.5) <music21.note.Note C#>>, Soprano <ElementTimespan (0.1 to 1.0) <music21.note.Note E>>, Alto <ElementTimespan (0.1 to 0.5) <music21.note.Note A>>, Tenor <ElementTimespan (0.1 to 0.5) <music21.note.Note A>>, Bass
>>> tree.elementsOverlappingOffset(0.1) ()
-
TimespanTree.
toPartwiseTimespanTrees
()¶
-
static
TimespanTree.
unwrapVerticalities
(verticalities)¶ Unwraps a sequence of Verticality objects into a dictionary of Part:Horizontality key/value pairs.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> iterator = tree.iterateVerticalitiesNwise() >>> verticalities = next(iterator) >>> unwrapped = tree.unwrapVerticalities(verticalities) >>> for part in sorted(unwrapped, ... key=lambda x: x.getInstrument().partName, ... ): ... print(part) ... horizontality = unwrapped[part] ... for timespan in horizontality: ... print('\t%r' % timespan) ... <music21.stream.Part Alto> <ElementTimespan (0.0 to 1.0) <music21.note.Note E>> <ElementTimespan (1.0 to 2.0) <music21.note.Note F#>> <music21.stream.Part Bass> <ElementTimespan (0.0 to 0.5) <music21.note.Note A>> <ElementTimespan (0.5 to 1.0) <music21.note.Note G#>> <ElementTimespan (1.0 to 2.0) <music21.note.Note F#>> <music21.stream.Part Soprano> <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>> <ElementTimespan (0.5 to 1.0) <music21.note.Note B>> <ElementTimespan (1.0 to 2.0) <music21.note.Note A>> <music21.stream.Part Tenor> <ElementTimespan (0.0 to 0.5) <music21.note.Note A>> <ElementTimespan (0.5 to 1.0) <music21.note.Note B>> <ElementTimespan (1.0 to 2.0) <music21.note.Note C#>>
Methods inherited from ElementTree
:
Methods inherited from AVLTree
:
AVLTree¶
-
class
music21.timespans.trees.
AVLTree
¶ Data structure for working with timespans.node.AVLNode objects.
To be subclassed in order to do anything useful with music21 objects.
AVLTree
methods
-
AVLTree.
debug
()¶ Gets string representation of the timespan collection.
Useful only for debugging its internal node structure.
>>> tsList = [(0,2), (0,9), (1,1), (2,3), (3,4), (4,9), (5,6), (5,8), (6,8), (7,7)] >>> tss = [timespans.Timespan(x, y) for x, y in tsList] >>> tree = timespans.trees.TimespanTree() >>> tree.insert(tss)
>>> print(tree.debug()) <Node: Start:3 Indices:(0:4:5:10) Length:{1}> L: <Node: Start:1 Indices:(0:2:3:4) Length:{1}> L: <Node: Start:0 Indices:(0:0:2:2) Length:{2}> R: <Node: Start:2 Indices:(3:3:4:4) Length:{1}> R: <Node: Start:5 Indices:(5:6:8:10) Length:{2}> L: <Node: Start:4 Indices:(5:5:6:6) Length:{1}> R: <Node: Start:6 Indices:(8:8:9:10) Length:{1}> R: <Node: Start:7 Indices:(9:9:10:10) Length:{1}>
-
AVLTree.
getOffsetAfter
(offset)¶ Gets start offset after offset.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.getOffsetAfter(0.5) 1.0
Returns None if no succeeding offset exists.
>>> tree.getOffsetAfter(35) is None True
Generally speaking, negative offsets will usually return 0.0
>>> tree.getOffsetAfter(-999) 0.0
-
AVLTree.
getOffsetBefore
(offset)¶ Gets the start offset immediately preceding offset in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.getOffsetBefore(100) 35.0
Return None if no preceding offset exists.
>>> tree.getOffsetBefore(0) is None True
ElementTree¶
-
class
music21.timespans.trees.
ElementTree
(elements=None, source=None)¶ A data structure for efficiently storing a score: flat or recursed or normal.
This data structure stores TimespanNodes: objects which implement both a offset and endTime property. It provides fast lookups of such objects and can quickly locate vertical overlaps.
>>> et = timespans.trees.ElementTree() >>> et <ElementTree {0} (-inf to inf)>
>>> for i in range(100): ... n = note.Note() ... et.insert(float(i), n) >>> et <ElementTree {100} (0.0 to 100.0)>
>>> n2 = note.Note('D#') >>> et.insert(101.0, n2)
These operations are very fast...
>>> et.index(n2, 101.0) 100 >>> et.getOffsetAfter(100.5) 101.0
ElementTree
bases
ElementTree
read-only properties
-
ElementTree.
allEndTimes
¶ Gets all unique stop offsets of all timespans in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for offset in tree.allEndTimes[:10]: ... offset ... 0.5 1.0 2.0 4.0 5.5 6.0 7.0 8.0 9.5 10.5
-
ElementTree.
allOffsets
¶ Gets all unique offsets of all timespans in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for offset in tree.allOffsets[:10]: ... offset ... 0.0 0.5 1.0 2.0 3.0 4.0 5.0 5.5 6.0 6.5
-
ElementTree.
allTimePoints
¶ Gets all unique offsets (both starting and stopping) of all elements/timespans in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for offset in tree.allTimePoints[:10]: ... offset ... 0.0 0.5 1.0 2.0 3.0 4.0 5.0 5.5 6.0 6.5
-
ElementTree.
earliestEndTime
¶ Gets the earliest stop offset in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.earliestEndTime 0.5
-
ElementTree.
endTime
¶
-
ElementTree.
highestOffset
¶ Gets the latest start offset in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.highestOffset 35.0
-
ElementTree.
latestEndTime
¶ Gets the latest stop offset in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.latestEndTime 36.0
-
ElementTree.
lowestOffset
¶ Gets the earliest start offset in this offset-tree.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> tree.lowestOffset 0.0
-
ElementTree.
offset
¶
ElementTree
read/write properties
-
ElementTree.
source
¶ the original stream.
ElementTree
methods
-
ElementTree.
append
(el)¶
-
ElementTree.
copy
()¶ Creates a new offset-tree with the same timespans as this offset-tree.
This is analogous to dict.copy().
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> newTree = tree.copy()
-
ElementTree.
elementsOverlappingOffset
(offset)¶ Finds elements or timespans in this ElementTree which overlap offset.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for el in tree.elementsOverlappingOffset(0.5): ... el ... <ElementTimespan (0.0 to 1.0) <music21.note.Note E>>
-
ElementTree.
elementsStartingAt
(offset)¶ Finds timespans in this offset-tree which start at offset.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for timespan in tree.elementsStartingAt(0.5): ... timespan ... <ElementTimespan (0.5 to 1.0) <music21.note.Note B>> <ElementTimespan (0.5 to 1.0) <music21.note.Note B>> <ElementTimespan (0.5 to 1.0) <music21.note.Note G#>>
-
ElementTree.
elementsStoppingAt
(offset)¶ Finds timespans in this offset-tree which stop at offset.
>>> score = corpus.parse('bwv66.6') >>> tree = score.asTimespans() >>> for timespan in tree.elementsStoppingAt(0.5): ... timespan ... <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>> <ElementTimespan (0.0 to 0.5) <music21.note.Note A>> <ElementTimespan (0.0 to 0.5) <music21.note.Note A>>
-
ElementTree.
index
(element, offset=None)¶ Gets index of timespan in tree.
Since timespans do not have .sites, there is only one offset to deal with...
>>> tsList = [(0,2), (0,9), (1,1), (2,3), (3,4), (4,9), (5,6), (5,8), (6,8), (7,7)] >>> ts = [timespans.Timespan(x, y) for x, y in tsList] >>> tree = timespans.trees.TimespanTree() >>> tree.insert(ts)
>>> for timespan in ts: ... print("%r %d" % (timespan, tree.index(timespan))) ... <Timespan 0 2> 0 <Timespan 0 9> 1 <Timespan 1 1> 2 <Timespan 2 3> 3 <Timespan 3 4> 4 <Timespan 4 9> 5 <Timespan 5 6> 6 <Timespan 5 8> 7 <Timespan 6 8> 8 <Timespan 7 7> 9
>>> tree.index(timespans.Timespan(-100, 100)) Traceback (most recent call last): ValueError: <Timespan -100 100> not in Tree at offset -100.
-
ElementTree.
insert
(offsetsOrElements, elements=None)¶ Inserts elements or timespans into this offset-tree.
>>> n = note.Note() >>> et = timespans.trees.ElementTree() >>> et.insert(10.0, n) >>> et <ElementTree {1} (10.0 to 11.0)>
-
ElementTree.
remove
(elements, offsets=None)¶ Removes elements or timespans (a single one or a list) from this Tree.
Much safer (for non-timespans) if a list of offsets is used
TODO: raise exception if elements length and offsets length differ
Methods inherited from AVLTree
: