Skip to content

Commit

Permalink
Merge pull request #1283 from cuthbertLab/getElementsByCLASS
Browse files Browse the repository at this point in the history
Use more classes in getElementsByClass
  • Loading branch information
mscuthbert authored Apr 27, 2022
2 parents d7ec854 + 02d3463 commit e94a7bf
Show file tree
Hide file tree
Showing 48 changed files with 2,457 additions and 2,418 deletions.
30 changes: 15 additions & 15 deletions music21/abcFormat/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def abcToStreamPart(abcHandler, inputM21=None, spannerBundle=None):
pass
# clefs are not typically defined, but if so, are set to the first measure
# following the meta data, or in the open stream
if not clefSet and not p.recurse().getElementsByClass('Clef'):
if not clefSet and not p[clef.Clef]:
if useMeasures: # assume at start of measures
p.getElementsByClass(stream.Measure).first().clef = clef.bestClef(p, recurse=True)
else:
Expand All @@ -205,7 +205,7 @@ def abcToStreamPart(abcHandler, inputM21=None, spannerBundle=None):
if postTransposition != 0:
p.transpose(postTransposition, inPlace=True)

if useMeasures and p.recurse().getElementsByClass('TimeSignature'):
if useMeasures and p[meter.TimeSignature]:
# call make beams for now; later, import beams
# environLocal.printDebug(['abcToStreamPart: calling makeBeams'])
try:
Expand Down Expand Up @@ -660,7 +660,7 @@ def testChords(self):
self.assertEqual(len(s.parts[1].flatten().notesAndRests), 127)

# chords are defined in second part here
self.assertEqual(len(s.parts[1].flatten().getElementsByClass('Chord')), 32)
self.assertEqual(len(s.parts[1][chord.Chord]), 32)

# check pitches in chords; sharps are applied due to key signature
match = [p.nameWithOctave for p in s.parts[1].flatten().getElementsByClass(
Expand Down Expand Up @@ -850,16 +850,16 @@ def testChordSymbols(self):
p1 = o.getScoreByNumber(81).parts[0]
self.assertEqual(p1.offset, 0.0)
self.assertEqual(len(p1.flatten().notesAndRests), 77)
self.assertEqual(len(list(p1.flatten().getElementsByClass('ChordSymbol'))), 25)
self.assertEqual(len(list(p1.flatten().getElementsByClass(harmony.ChordSymbol))), 25)
# Am/C
self.assertEqual(list(p1.flatten().getElementsByClass('ChordSymbol'))[7].root(),
self.assertEqual(list(p1.flatten().getElementsByClass(harmony.ChordSymbol))[7].root(),
pitch.Pitch('A3'))
self.assertEqual(list(p1.flatten().getElementsByClass('ChordSymbol'))[7].bass(),
self.assertEqual(list(p1.flatten().getElementsByClass(harmony.ChordSymbol))[7].bass(),
pitch.Pitch('C3'))
# G7/B
self.assertEqual(list(p1.flatten().getElementsByClass('ChordSymbol'))[14].root(),
self.assertEqual(list(p1.flatten().getElementsByClass(harmony.ChordSymbol))[14].root(),
pitch.Pitch('G3'))
self.assertEqual(list(p1.flatten().getElementsByClass('ChordSymbol'))[14].bass(),
self.assertEqual(list(p1.flatten().getElementsByClass(harmony.ChordSymbol))[14].bass(),
pitch.Pitch('B2'))

def testNoChord(self):
Expand All @@ -884,9 +884,9 @@ def testNoChord(self):

score = harmony.realizeChordSymbolDurations(score)

self.assertEqual(8, score.getElementsByClass('ChordSymbol')[
self.assertEqual(8, score.getElementsByClass(harmony.ChordSymbol)[
-1].quarterLength)
self.assertEqual(4, score.getElementsByClass('ChordSymbol')[
self.assertEqual(4, score.getElementsByClass(harmony.ChordSymbol)[
0].quarterLength)

def testAbcKeyImport(self):
Expand Down Expand Up @@ -944,13 +944,13 @@ def testRepeatBracketsA(self):
# s.show()
# one start, one end
# s.parts[0].show('t')
self.assertEqual(len(s.flatten().getElementsByClass('Repeat')), 2)
self.assertEqual(len(s['Repeat']), 2)
# s.show()

# this has a 1 note pickup
# has three repeat bars; first one is implied
s = converter.parse(testFiles.draughtOfAle)
self.assertEqual(len(s.flatten().getElementsByClass('Repeat')), 3)
self.assertEqual(len(s['Repeat']), 3)
self.assertEqual(s.parts[0].getElementsByClass(
'Measure')[0].notes[0].pitch.nameWithOctave, 'D4')

Expand All @@ -965,14 +965,14 @@ def testRepeatBracketsB(self):
from music21 import corpus
s = converter.parse(testFiles.morrisonsJig)
# TODO: get
self.assertEqual(len(s.flatten().getElementsByClass('RepeatBracket')), 2)
self.assertEqual(len(s[spanner.RepeatBracket]), 2)
# s.show()
# four repeat brackets here; 2 at beginning, 2 at end
s = converter.parse(testFiles.hectorTheHero)
self.assertEqual(len(s.flatten().getElementsByClass('RepeatBracket')), 4)
self.assertEqual(len(s[spanner.RepeatBracket]), 4)

s = corpus.parse('JollyTinkersReel')
self.assertEqual(len(s.flatten().getElementsByClass('RepeatBracket')), 4)
self.assertEqual(len(s[spanner.RepeatBracket]), 4)

def testMetronomeMarkA(self):
from music21.abcFormat import testFiles
Expand Down
19 changes: 10 additions & 9 deletions music21/analysis/discrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def clearSolutionsFound(self):

def getColorsUsed(self):
'''
Based on solutions found so far with with this processor,
Based on solutions found so far with this processor,
return the colors that have been used.
'''
post = []
Expand All @@ -140,7 +140,7 @@ def getColorsUsed(self):

def getSolutionsUsed(self):
'''
Based on solutions found so far with with this processor,
Based on solutions found so far with this processor,
return the solutions that have been used.
'''
post = []
Expand All @@ -167,7 +167,7 @@ def solutionUnitString(self):

def solutionToColor(self, solution):
'''
Given a analysis specific result, return the appropriate color.
Given an analysis specific result, return the appropriate color.
Must be able to handle None in the case that there is no result.
'''
pass
Expand Down Expand Up @@ -305,7 +305,7 @@ def _getSharpFlatCount(self, subStream) -> Tuple[int, int]:
>>> p._getSharpFlatCount(s.flatten())
(87, 0)
'''
# pitches gets a flat representation
# ".pitches" gets a flat representation
flatCount = 0
sharpCount = 0
for p in subStream.pitches:
Expand Down Expand Up @@ -496,7 +496,7 @@ def solutionLegend(self, compress=False):
if keyPitch.name not in valid:
mask = True
if mask:
# set as white so as to maintain spacing
# set as white to maintain spacing
color = '#ffffff'
keyStr = ''
else:
Expand Down Expand Up @@ -583,7 +583,7 @@ def _bestKeyEnharmonic(self, pitchObj, mode, sStream=None):

flipEnharmonic = False
# if pitchObj.accidental is not None:
# # if we have a sharp key and we need to favor flat, get enharmonic
# # if we have a sharp key, and we need to favor flat, get enharmonic
# if pitchObj.accidental.alter > 0 and favor == 'flat':
# flipEnharmonic = True
# elif pitchObj.accidental.alter < 0 and favor == 'sharp':
Expand Down Expand Up @@ -635,7 +635,7 @@ def process(self, sStream, storeAlternatives=False):
# mode = None
# solution = (None, mode, 0)

# see which has a higher correlation coefficient, the first major or the
# see which has a higher correlation coefficient, the first major or
# the first minor
if likelyKeysMajor is not None:
sortList = [(coefficient, p, 'major') for
Expand Down Expand Up @@ -1227,20 +1227,21 @@ def countMelodicIntervals(self, sStream, found=None, ignoreDirection=True, ignor
# note that Stream.findConsecutiveNotes() and Stream.melodicIntervals()
# offer similar approaches, but return Streams and manage offsets and durations,
# components not needed here
from music21 import stream

if found is None:
found = {}

# if this has parts, need to move through each at a time
if sStream.hasPartLikeStreams():
procList = list(sStream.getElementsByClass('Stream'))
procList = list(sStream.getElementsByClass(stream.Stream))
else: # assume a single list of notes, or sStream is a part
procList = [sStream]

for p in procList:
# get only Notes for now, skipping rests and chords
# flatten to reach notes contained in measures
noteStream = p.flatten().stripTies(inPlace=False).getElementsByClass('Note').stream()
noteStream = p.flatten().stripTies(inPlace=False).getElementsByClass(note.Note).stream()
# noteStream.show()
for i, n in enumerate(noteStream):
if i <= len(noteStream) - 2:
Expand Down
2 changes: 1 addition & 1 deletion music21/analysis/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def attributeCount(streamOrStreamIter, attrName='quarterLength') -> collections.
>>> from music21 import corpus
>>> bach = corpus.parse('bach/bwv324.xml')
>>> bachIter = bach.parts[0].recurse().getElementsByClass('Note')
>>> bachIter = bach.parts[0].recurse().getElementsByClass(note.Note)
>>> qlCount = analysis.elements.attributeCount(bachIter, 'quarterLength')
>>> qlCount.most_common(3)
[(1.0, 12), (2.0, 11), (4.0, 2)]
Expand Down
3 changes: 2 additions & 1 deletion music21/analysis/metrical.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ def thomassenMelodicAccent(streamIn):
.. _melac: https://www.humdrum.org/Humdrum/commands/melac.html
Takes in a Stream of :class:`~music21.note.Note` objects (use `.flatten().notes` to get it, or
better `.flatten().getElementsByClass('Note')` to filter out chords) and adds the attribute to
better `.flatten().getElementsByClass(note.Note)` to filter out chords)
and adds the attribute to
each. Note that Huron and Royal's work suggests that melodic accent has a correlation
with metrical accent only for solo works/passages; even treble passages do not have a
strong correlation. (Gregorian chants were found to have a strong ''negative'' correlation
Expand Down
2 changes: 1 addition & 1 deletion music21/analysis/reduceChords.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def run(self,
reduction.append(chordifiedPart)

if closedPosition:
for x in reduction.recurse().getElementsByClass('Chord'):
for x in reduction[chord.Chord]:
x.closedPosition(forceOctave=4, inPlace=True)

return reduction
Expand Down
4 changes: 2 additions & 2 deletions music21/analysis/reduceChordsOld.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ def testTrecentoMadrigal(self):
fixClef = True
if fixClef:
startClefs = c.parts[1].getElementsByClass(stream.Measure
).first().getElementsByClass('Clef')
).first().getElementsByClass(clef.Clef)
if startClefs:
clef1 = startClefs[0]
c.parts[1].getElementsByClass(stream.Measure).first().remove(clef1)
Expand All @@ -369,7 +369,7 @@ def testTrecentoMadrigal(self):
from music21 import key
from music21 import roman
cm = key.Key('G')
for thisChord in p.recurse().getElementsByClass('Chord'):
for thisChord in p[chord.Chord]:
thisChord.lyric = roman.romanNumeralFromChord(thisChord,
cm,
preferSecondaryDominants=True).figure
Expand Down
2 changes: 1 addition & 1 deletion music21/analysis/reduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def _createReduction(self):
v.makeRests(fillGaps=True, inPlace=True)
m.flattenUnnecessaryVoices(inPlace=True)
# hide all rests in all containers
for r in m.recurse().getElementsByClass('Rest'):
for r in m[note.Rest]:
r.style.hideObjectOnPrint = True
# m.show('t')
# add to score
Expand Down
28 changes: 16 additions & 12 deletions music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3877,14 +3877,14 @@ class ElementWrapper(Music21Object):
... el = music21.ElementWrapper(soundFile)
... s.insert(i, el)
>>> for j in s.getElementsByClass('ElementWrapper'):
>>> for j in s.getElementsByClass(base.ElementWrapper):
... if j.beatStrength > 0.4:
... (j.offset, j.beatStrength, j.getnchannels(), j.fileName)
(0.0, 1.0, 2, 'thisSound_1.wav')
(3.0, 1.0, 2, 'thisSound_16.wav')
(6.0, 1.0, 2, 'thisSound_12.wav')
(9.0, 1.0, 2, 'thisSound_8.wav')
>>> for j in s.getElementsByClass('ElementWrapper'):
>>> for j in s.getElementsByClass(base.ElementWrapper):
... if j.beatStrength > 0.4:
... (j.offset, j.beatStrength, j.getnchannels() + 1, j.fileName)
(0.0, 1.0, 3, 'thisSound_1.wav')
Expand All @@ -3894,7 +3894,7 @@ class ElementWrapper(Music21Object):
Test representation of an ElementWrapper
>>> for i, j in enumerate(s.getElementsByClass('ElementWrapper')):
>>> for i, j in enumerate(s.getElementsByClass(base.ElementWrapper)):
... if i == 2:
... j.id = None
... else:
Expand Down Expand Up @@ -4301,8 +4301,12 @@ def testSitesClef(self):
def testBeatAccess(self):
'''Test getting beat data from various Music21Objects.
'''
from music21 import clef
from music21 import corpus
from music21 import key
from music21 import meter
from music21 import stream

s = corpus.parse('bach/bwv66.6.xml')
p1 = s.parts['Soprano']

Expand All @@ -4311,18 +4315,18 @@ def testBeatAccess(self):

# clef/ks can get its beat; these objects are in a pickup,
# and this give their bar offset relative to the bar
eClef = p1.flatten().getElementsByClass('Clef').first()
eClef = p1.flatten().getElementsByClass(clef.Clef).first()
self.assertEqual(eClef.beat, 4.0)
self.assertEqual(eClef.beatDuration.quarterLength, 1.0)
self.assertEqual(eClef.beatStrength, 0.25)

eKS = p1.flatten().getElementsByClass('KeySignature').first()
eKS = p1.flatten().getElementsByClass(key.KeySignature).first()
self.assertEqual(eKS.beat, 4.0)
self.assertEqual(eKS.beatDuration.quarterLength, 1.0)
self.assertEqual(eKS.beatStrength, 0.25)

# ts can get beatStrength, beatDuration
eTS = p1.flatten().getElementsByClass('TimeSignature').first()
eTS = p1.flatten().getElementsByClass(meter.TimeSignature).first()
self.assertEqual(eTS.beatDuration.quarterLength, 1.0)
self.assertEqual(eTS.beatStrength, 0.25)

Expand Down Expand Up @@ -4575,15 +4579,15 @@ def testRecurseByClass(self):
s3.append(n3)

# only get n1 here, as that is only level available
self.assertEqual(s1.recurse().getElementsByClass('Note').first(), n1)
self.assertEqual(s2.recurse().getElementsByClass('Note').first(), n2)
self.assertEqual(s1.recurse().getElementsByClass('Clef').first(), c1)
self.assertEqual(s2.recurse().getElementsByClass('Clef').first(), c2)
self.assertEqual(s1.recurse().getElementsByClass(note.Note).first(), n1)
self.assertEqual(s2.recurse().getElementsByClass(note.Note).first(), n2)
self.assertEqual(s1[clef.Clef].first(), c1)
self.assertEqual(s2[clef.Clef].first(), c2)

# attach s2 to s1
s2.append(s1)
# stream 1 gets both notes
self.assertEqual(list(s2.recurse().getElementsByClass('Note')), [n2, n1])
self.assertEqual(list(s2.recurse().getElementsByClass(note.Note)), [n2, n1])

def testSetEditorial(self):
b2 = Music21Object()
Expand Down Expand Up @@ -4697,7 +4701,7 @@ def getnchannels(self):
matchBeatStrength = []
matchAudioChannels = []

for j in s.getElementsByClass('ElementWrapper'):
for j in s.getElementsByClass(base.ElementWrapper):
matchOffset.append(j.offset)
matchBeatStrength.append(j.beatStrength)
matchAudioChannels.append(j.getnchannels())
Expand Down
2 changes: 1 addition & 1 deletion music21/braille/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2124,7 +2124,7 @@ def test_drill10_4(self):
bm.insert(0, tempo.TempoText('Con brio'))
bm.insert(25.0, clef.TrebleClef())
bm.insert(32.0, clef.BassClef())
bm.recurse().getElementsByClass('TimeSignature').first().symbol = 'common'
bm[meter.TimeSignature].first().symbol = 'common'
bm.makeNotation(inPlace=True, cautionaryNotImmediateRepeat=False)
m = bm.getElementsByClass(stream.Measure)
m[0].padAsAnacrusis(useInitialRests=True)
Expand Down
Loading

0 comments on commit e94a7bf

Please sign in to comment.