<jupyter_start><jupyter_text>music21: A Toolkit for Comupter-Aided Musicology  Some examples to test basic music21 functionalities This is a Jupyter notebook created by [@musicenfanthen](https://github.com/musicEnfanthen) and [@aWilsonandmore](https://github.com/aWilsonandmore) to work with some basic functionalities of music21 (http://web.mit.edu/music21/). For more information on Jupyter notebooks go to http://jupyter.org/. To execute a block of code in this notebook, click in the cell and press `Shift+Enter`.To get help on any music21 routine, click on it and press `Shift+Tab`.  Imports and setup To use music21 in this notebook and python, you have to import all (\*) routines  from music21 at first with the following command."You’ll probably get a few warnings that you’re missing some optional modules. That’s okay. If you get a warning that “no module named music21” then something probably went wrong above." (Source: http://web.mit.edu/music21/doc/usersGuide/usersGuide_01_installing.html)<jupyter_code>from music21 import *<jupyter_output><empty_output><jupyter_text>Probably you have to set manually the correct file path to an Application that is able to open MusicXML files (like MuseScore). To do so, use the `music21.environment` module to set an `musicxmlPath` key.Make sure to change the string `path/to/your/musicXmlApplication` below to the correct file path (keep the quotation marks):- on Mac e.g.: `/Applications/MuseScore 2.app/Contents/MacOS/mscore` - or on Windows e.g.: `C:/Program Files (x86)/MuseScore 2/bin/MuseScore.exe`and uncomment the line (remove the `` at the begin of the line).In the same way, you can also add a path to your lilypond installation, using`env['lilypondPath']`:- on Mac e.g.: `Applications/Lilypond.app`- on Windows e.g.: `C:/Program Files (x86)/LilyPond/usr/bin/lilypond.exe`Sometimes it's also necessary to adapt the `musescoreDirectPNGPath`. Check if it corresponds to your museScore path.<jupyter_code>env = environment.Environment()
# env['musicxmlPath'] = 'path/to/your/musicXmlApplication'
# env['lilypondPath'] = 'path/to/your/lilypond'
# env['musescoreDirectPNGPath'] = 'path/to/your/museScore'

print('Environment settings:')
print('musicXML:  ', env['musicxmlPath'])
print('musescore: ', env['musescoreDirectPNGPath'])
print('lilypond:  ', env['lilypondPath'])<jupyter_output><empty_output><jupyter_text>Let's create some notes One possible way to create notes in music21 is to use the `Note()`-Object (CAPITAL LETTER) within music21's `note`-subModule (small letter).Let's use the twelve-tone row of Alban Berg's Violin Concerto (1935) as an example. Take care how the different octaves and accidentals are declared.<jupyter_code>note1 = note.Note("G3")     # declaration of first note
note2 = note.Note("B-3")
note3 = note.Note("D4")
note4 = note.Note("F#4")
note5 = note.Note("A4")
note6 = note.Note("C5")
note7 = note.Note("E5")
note8 = note.Note("G#5")
note9 = note.Note("B5")
note10 = note.Note("C#6")
note11 = note.Note("D#6")
note12 = note.Note("F6")

# combine the twelve notes in a row list
bergRow = [note1, note2, note3, note4, note5, note6, note7, note8, note9, note10, note11, note12]
bergRow    # output of bergRow (by just using the name of the variable)<jupyter_output><empty_output><jupyter_text>You can use `dir(MODULENAME)` to find out which objects any module contains at all (http://web.mit.edu/music21/doc/usersGuide/usersGuide_02_notes.htmlusersguide-02-notes):<jupyter_code>dir(note)<jupyter_output><empty_output><jupyter_text>To iterate over every single item in a list, you can use a "FOR"-loop.Syntax (indentation matters here!):    for ITEM in LIST:            do something with ITEM        ...<jupyter_code>for currentNote in bergRow:                                    # for every note in bergRow list do...
    currentNote.duration.type = 'whole'                        # ... declare duration of a whole note
    print(currentNote.duration, currentNote.nameWithOctave)    # ... output of note duration and name (using the print command)<jupyter_output><empty_output><jupyter_text>Create simple Streams Streams are fundamental objects in music21. Almost everything (`Score`, `Parts`, `Voices`, `Measures` a.o.) is organized in terms of this abstract data structure. An empty stream is created by using the `Stream()`-Object (CAPITAL LETTER) within music21's `stream`-subModule (small letter).<jupyter_code>bergStream = stream.Stream()        # create empty stream

for currentNote in bergRow:         # iterate over every note in bergRow and ...
    bergStream.append(currentNote)  # ... append current note to the stream

bergStream.show('text')             # output of the stream (using the .show()-method with option 'text'; compare to output above)<jupyter_output><empty_output><jupyter_text>You can get the length of a stream, what is the number of items in it, with `len(STREAM)`:<jupyter_code>len(bergStream)<jupyter_output><empty_output><jupyter_text>... or with just counting the Note-Elements (here you have to flatten the stream):<jupyter_code>len(bergStream.flat.getElementsByClass(note.Note))<jupyter_output><empty_output><jupyter_text>But let's have a look at the stream now. Calling the `.show()`-method without any option will display a graphical visualisation of any music object via the musicxmlApplication defined in the environment at the beginning of this notebook.If you encounter problems here, make sure you have set the correct environment settings for `musicxmlPath` and `musescoreDirectPNGPath`.<jupyter_code>bergStream.show()<jupyter_output><empty_output><jupyter_text>You can also use further options to get the output as `pdf` or `png` via `lilypond`:<jupyter_code>bergStream.show('lily.pdf')
bergStream.show('lily.png')<jupyter_output><empty_output><jupyter_text>You could also use music21.tinyNotation, "a simple way of specifying single line melodies" (http://web.mit.edu/music21/doc/moduleReference/moduleTinyNotation.html), to define the notes of the row:<jupyter_code>bergRowTiny = converter.parse("tinyNotation: G1 B- d f# a c' e' g'# b' c''# d''# f''")
bergRowTiny.show()<jupyter_output><empty_output><jupyter_text>Our `bergRowTiny` is also a stream because the tinyNotation converter created it automatically. But keep aware of the slightly different structure:<jupyter_code>bergRowTiny.show('text')<jupyter_output><empty_output><jupyter_text>Ok nice, but where is the analytical part? music21 provides a large amount of build-in analytical tools. To start right away, just let's get the ambitus of the row in the stream using the `.analyze()`-method (http://web.mit.edu/music21/doc/moduleReference/moduleStream.html):<jupyter_code>bergStream.analyze('ambitus')<jupyter_output><empty_output><jupyter_text>But always keep a "thinking" eye on the results:<jupyter_code>bergStream.analyze('key')<jupyter_output><empty_output><jupyter_text>The twelve-tone row of Berg's Violin Concerto is special because of its two major triads, two minor triads and a part of the whole tone scale. Let's separate these elements into new `Chord()`-Objects (part of `chord`-submodule):<jupyter_code># declare some variables as Chord()-Objects
triad1 = chord.Chord()
triad2 = chord.Chord()
triad3 = chord.Chord()
triad4 = chord.Chord()
wtScale = chord.Chord()

# iterate over the first three notes in the stream
for currentNote in bergStream[0:3]:
    triad1.add(currentNote)           # add the currentNote to the Chord()

# ...
for currentNote in bergStream[2:5]:
    triad2.add(currentNote)

# ...
for currentNote in bergStream[4:7]:
    triad3.add(currentNote)

# ...
for currentNote in bergStream[6:9]:
    triad4.add(currentNote)

# iterate over the last three notes in the stream
for currentNote in bergStream[8:12]:
    wtScale.add(currentNote)

# output the 5 chords
triad1.show()
triad2.show()
triad3.show()
triad4.show()
wtScale.show()<jupyter_output><empty_output><jupyter_text>You can recombine multiple Chords() within a new Chord()-Object:<jupyter_code>fullChord = chord.Chord([triad1, triad2, triad3, triad4, wtScale])

fullChord.show()<jupyter_output><empty_output><jupyter_text>You can also append the chords to a new Stream()-Object:<jupyter_code># create empty stream
chordsStream = stream.Stream()

# append all the triads to the stream
chordsStream.append(triad1);
chordsStream.append(triad2);
chordsStream.append(triad3);
chordsStream.append(triad4);
chordsStream.append(wtScale);

chordsStream.show()<jupyter_output><empty_output><jupyter_text>And you can add some analytical descriptions to the objects using the `.addLyric()`-method and different attributes (e.g. `pitchedCommonName`, `intervalVector`, `primeForm`, `forteClass`) of the chords:<jupyter_code># iterate over every chord in the stream, and ...
for currentChord in chordsStream:
    currentChord.addLyric(currentChord.pitchedCommonName)    # ... add triad name
    currentChord.addLyric(currentChord.intervalVector)       # ... add interval vector
    currentChord.addLyric(currentChord.primeForm)            # ... add prime form
    currentChord.addLyric(currentChord.forteClass)           # ... add forte class

chordsStream.show()<jupyter_output><empty_output><jupyter_text>Highlighting certain parts (e.g. all Forte classes "3-11A" = minor chord or "3-11B" = major chord) is also possible (http://web.mit.edu/music21/doc/usersGuide/usersGuide_10_examples1.html):<jupyter_code>for currentChord in chordsStream.recurse().getElementsByClass('Chord'):
    if currentChord.forteClass == '3-11A':
        currentChord.style.color = 'red'
        for x in currentChord.derivation.chain():
            x.style.color = 'blue'
    if currentChord.forteClass == '3-11B':
        currentChord.style.color = 'blue'
        for x in currentChord.derivation.chain():
            x.style.color = 'blue'

chordsStream.show()<jupyter_output><empty_output><jupyter_text>Introducing music21 the serial module Most (=all?) of the twelve tone rows by Schönberg, Berg and Webern are already incorporated into a dictionary list in music21. You get an sorted overview of the rows available in the dictionary with the following command: (http://web.mit.edu/music21/doc/moduleReference/moduleSerial.html)<jupyter_code>sorted(list(serial.historicalDict))<jupyter_output><empty_output><jupyter_text>For all these rows, music21 provides not only the pitches of the row, but some additional meta information. So let's see what we get with the 'RowBergViolinConcerto':<jupyter_code>bergRowInternal = serial.getHistoricalRowByName('RowBergViolinConcerto')
print(type(bergRowInternal))
print(bergRowInternal.composer)
print(bergRowInternal.opus)
print(bergRowInternal.title)
print(bergRowInternal.row)
print(bergRowInternal.pitchClasses())
bergRowInternal.noteNames()<jupyter_output><empty_output><jupyter_text>TransformationsUsing the serial modules' '.originalCenteredTransformation()'-method, you can retrieve transformational forms of a ToneRow()-Object. "Admissible transformations are ‘T’ (transposition), ‘I’ (inversion), ‘R’ (retrograde), and ‘RI’ (retrograde inversion)." (http://web.mit.edu/music21/doc/moduleReference/moduleSerial.html)<jupyter_code>g = bergRowInternal.originalCenteredTransformation('T', 0)
u = bergRowInternal.originalCenteredTransformation('I', 0)
k = bergRowInternal.originalCenteredTransformation('R', 0)
ku = bergRowInternal.originalCenteredTransformation('RI', 0)

print('original:')
g.show()

print('inversion:')
u.show()

print('retrograde:')
k.show()

print('retrograde inversion:')
ku.show()<jupyter_output><empty_output><jupyter_text>12-tone matrix You can also easily get the 12-tone matrix of a twelve tone row:<jupyter_code>bergMatrix1 = bergRowInternal.matrix()
print(bergMatrix1)
bergMatrix2 = serial.rowToMatrix(bergRowInternal.row)
print(bergMatrix2)<jupyter_output><empty_output><jupyter_text>SegmentationOne of the fundamental operations concerning the analysis of a twelve tone composition is segmentation. The following example provides a function, that iterates over a set of notes (`bergRowInternal`) and looks for every possible segment of a certain length (`segmentationSize`). Thus, per default, we iterate over every possible 3-tone segment of the Berg row.<jupyter_code>segmentationList = {}
segmentationLength = 3     # here you can choose the length of the segments (try other values)

rangeEnd = 12 - segmentationLength + 1


# iterate over the whole tone row in (rangeEnd - 1) steps
for i in range(0,rangeEnd):
    print('---')
    # create an empty placeholder for the segment as a ToneRow()-Object 
    # at the position i in the segmentationList
    segmentationList[i] = serial.ToneRow()
    
    # fill up the segment with the corresponding notes
    for currentNote in bergRowInternal[i:i+segmentationLength]:
        segmentationList[i].append(currentNote)
    print('Run ', i, ' completed.')     # This is for control only.
    
segmentationList     # output of the whole list<jupyter_output><empty_output><jupyter_text>Now that we have every possible 3-tone segment of the Berg row, we can check if there are any triads in it:<jupyter_code># check for triads in the segmentation list
# make sure to use segmentLength = 3 above 
# (for segmentLength = 4 you will get 7th and other tetra chords)

for i in segmentationList:
    print('---')
    print('RUN ', i)
    outputString = ''
    
    # get a list of the pitches of the current segment
    currentPitchList = segmentationList[i].pitches
    print(currentPitchList)
    
    #use the pitchList as input for a chord
    currentChord = chord.Chord(currentPitchList)
    
    # check for minor triad (with highlighting)
    # use forteClass 3-11A instead of 'isMinorTriad()'-method to catch enharmonic equivalents
    if currentChord.forteClass == '3-11A':        
        currentChord.style.color = 'red'
        outputString = 'MINOR TRIAD: '
    
    # check for major triad (with highlighting)
    # use forteClass 3-11B instead of 'isMajorTriad()'-method to catch enharmonic equivalents
    if currentChord.forteClass == '3-11B':
        currentChord.style.color = 'blue'
        outputString = 'MAJOR TRIAD: '
    
    currentChord.show()
    
    outputString += currentChord.pitchedCommonName
    print(outputString)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10431427569273939, 'fraction_numerical': 0.013539109084531743, 'mean_word_length': 5.068965517241379, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 101, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 5}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '25', 'dir': 'jupyter-structured-clean-dedup', 'id': '42455', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 4603, 'n_tokens_neox': 4371, 'n_words': 1349, 'path': 'Berg_Violin Concerto.ipynb', 'repo_name': 'jgarte/music21playground', 'size': '14255'}