Understanding Modes of the Major Heptatonic

Posted on Thu 21 February 2019 in music

While playing scales over and over on the Guitar, I have found some very interesting patterns in them that I thought would be worth summarizing here. Particularly, I am interested in verifying these properties through computation, and wherever trivial, proving them as well once we have achieved a reasonable formalism.

The Framework

Before we can begin describing these modal properties with any degree of precision, let us quickly establish the basic definitions we shall be working with. While in many cases, these definitions may not align completely with established formal definitions, I feel we can use them to start a useful discussion at this time.

Let us consider notes to be named members of the cyclic group $({Z}_{12}, +)$. We can formulate them in code as per the block below. The code specified below is admittedly somewhat fragile from a tuning theory perspective, but for the purposes of the scoped discussion we will be undertaking here, it is quite acceptable. We are not interested in discussing xenharmonics/microtonalities in this article.

In [114]:
notes = {
    0: "C",
    1: "C#",
    2: "D",
    3: "D#",
    4: "E",
    5: "F",
    6: "F#",
    7: "G",
    8: "G#",
    9: "A",
    10: "A#",
    11: "B"

rev_notes = {v:k for (k, v) in notes.items()}

Let us further define functions to obtain the scales for a given interval pattern and key, and to obtain the interval pattern given a particular scale. We shall neglect to state the formal definitions of these terms but shall proceed with the more commonly understood definition as long as we understand the following properties to hold:

  1. A scale is a sequence of notes
  2. The first note in the scale is considered to be the key
  3. The differences between the notes is considered to be the interval pattern for the scale.
    1. Corollary: The scale may be regenerated by providing a key and the interval pattern.
    2. We shall consider two scales to be equivalent modulo key if they share the same interval pattern.
In [131]:
def get_scale(key, intervals):
    ret = []
    accumulator = 0
    for i in intervals:
        accumulator += i
        ret.append(notes[(rev_notes[key] + accumulator) % len(notes.keys())])
    return ret

# create a differenced series
def difference(lst):
    diff = []
    for i in range(1, len(lst)):
        value = lst[i] - lst[i - 1]
    diff = [0] + diff
    return diff

def get_intervals(scale):
    ret = []
    key = scale[0]
    for note in scale:
        ret.append((rev_notes[note] - rev_notes[key] + len(notes.keys())) % len(notes.keys()))
    return difference(ret)

def get_all_scales(intervals):
    return {key: get_scale(key, intervals) for key in notes.values()}

Modes of the Major Heptatonic

Let us first restrict ourselves to the notes and modes of the traditional major heptatonic scale. This scale may be generally described as the following interval sequence:

In [117]:
major_ionian_intervals = [0, 2, 2, 1, 2, 2, 2]

Based on the above definitions, we may now proceed to generate the major heptatonic scale in all keys as below:

In [132]:
{'C': ['C', 'D', 'E', 'F', 'G', 'A', 'B'],
 'C#': ['C#', 'D#', 'F', 'F#', 'G#', 'A#', 'C'],
 'D': ['D', 'E', 'F#', 'G', 'A', 'B', 'C#'],
 'D#': ['D#', 'F', 'G', 'G#', 'A#', 'C', 'D'],
 'E': ['E', 'F#', 'G#', 'A', 'B', 'C#', 'D#'],
 'F': ['F', 'G', 'A', 'A#', 'C', 'D', 'E'],
 'F#': ['F#', 'G#', 'A#', 'B', 'C#', 'D#', 'F'],
 'G': ['G', 'A', 'B', 'C', 'D', 'E', 'F#'],
 'G#': ['G#', 'A#', 'C', 'C#', 'D#', 'F', 'G'],
 'A': ['A', 'B', 'C#', 'D', 'E', 'F#', 'G#'],
 'A#': ['A#', 'C', 'D', 'D#', 'F', 'G', 'A'],
 'B': ['B', 'C#', 'D#', 'E', 'F#', 'G#', 'A#']}

A quick sanity check below shows that the major scales as obtained above, are equivalent modulo key:

In [120]:
lst = [get_intervals(get_scale(k, major_ionian_intervals)) for k in notes.values()]
all(x == major_ionian_intervals for x in lst)

The $k^{th}$ mode is simply defined as a cyclic permutation of a provided scale. Musically, the effect this has is of specifying the same notes, but in the context of a different key since the first note of the scale has shifted. Let us therefore, for a 7 note root scale, consider the seven named modes defining the following cyclic permutational shifts:

In [112]:
def get_mode(scale, k):
    return scale[k:] + scale[:k]

modes = {
    "ionian": 0, # Major
    "dorian": 1, # Minor
    "phrygian": 2, # Minor
    "lydian":3, # Major
    "mixolydian": 4, # Major
    "aeolian": 5, # Minor
    "locrian": 6 # Diminshed
In [121]:
def get_mode_intervals(key, scale_intervals):
    return {k:get_intervals(get_mode(get_scale(key, major_ionian_intervals), mode))
                      for k, mode in modes.items()}
mode_intervals = get_mode_intervals('C', major_ionian_intervals)
{'ionian': [0, 2, 2, 1, 2, 2, 2],
 'dorian': [0, 2, 1, 2, 2, 2, 1],
 'phrygian': [0, 1, 2, 2, 2, 1, 2],
 'lydian': [0, 2, 2, 2, 1, 2, 2],
 'mixolydian': [0, 2, 2, 1, 2, 2, 1],
 'aeolian': [0, 2, 1, 2, 2, 1, 2],
 'locrian': [0, 1, 2, 2, 1, 2, 2]}

It is quite apparent that the patterns discovered above for all the nodes will hold for all keys since the computation above depends merely on the cyclic intervals of the major scale intervals defined above. Everything else, including node names are just nomenclature, and the math is indifferent to which key is used. Still, we can verify the same below quite trivially:

In [103]:
lst = [get_mode_intervals(k, major_ionian_intervals) for k in notes.values()]
all(x == lst[0] for x in lst)

Now that we have the mode interval patterns, we can generate the modes directly. For example, for the Phrygian mode, we have

In [133]:
{'C': ['C', 'C#', 'D#', 'F', 'G', 'G#', 'A#'],
 'C#': ['C#', 'D', 'E', 'F#', 'G#', 'A', 'B'],
 'D': ['D', 'D#', 'F', 'G', 'A', 'A#', 'C'],
 'D#': ['D#', 'E', 'F#', 'G#', 'A#', 'B', 'C#'],
 'E': ['E', 'F', 'G', 'A', 'B', 'C', 'D'],
 'F': ['F', 'F#', 'G#', 'A#', 'C', 'C#', 'D#'],
 'F#': ['F#', 'G', 'A', 'B', 'C#', 'D', 'E'],
 'G': ['G', 'G#', 'A#', 'C', 'D', 'D#', 'F'],
 'G#': ['G#', 'A', 'B', 'C#', 'D#', 'E', 'F#'],
 'A': ['A', 'A#', 'C', 'D', 'E', 'F', 'G'],
 'A#': ['A#', 'B', 'C#', 'D#', 'F', 'F#', 'G#'],
 'B': ['B', 'C', 'D', 'E', 'F#', 'G', 'A']}

As should be apparent by now from the preceeding discussion and the dictionary above, the Phrygian mode under the key of E consists of the same set of notes as the Ionian Mode under the key of C.

The Pentatonics

In order to drive the discussion forward, let us further derive the major and minor pentatonic scale intervals as defined in musical literature:

In [137]:
major_pentatonic_intervals = [0, 2, 2, 3, 2]
minor_pentatonic_intervals = [0, 3, 2, 2, 3]

The above definitions yield the following scales:

In [183]:
{'C': ['C', 'D', 'E', 'G', 'A'],
 'C#': ['C#', 'D#', 'F', 'G#', 'A#'],
 'D': ['D', 'E', 'F#', 'A', 'B'],
 'D#': ['D#', 'F', 'G', 'A#', 'C'],
 'E': ['E', 'F#', 'G#', 'B', 'C#'],
 'F': ['F', 'G', 'A', 'C', 'D'],
 'F#': ['F#', 'G#', 'A#', 'C#', 'D#'],
 'G': ['G', 'A', 'B', 'D', 'E'],
 'G#': ['G#', 'A#', 'C', 'D#', 'F'],
 'A': ['A', 'B', 'C#', 'E', 'F#'],
 'A#': ['A#', 'C', 'D', 'F', 'G'],
 'B': ['B', 'C#', 'D#', 'F#', 'G#']}
In [184]:
{'C': ['C', 'D#', 'F', 'G', 'A#'],
 'C#': ['C#', 'E', 'F#', 'G#', 'B'],
 'D': ['D', 'F', 'G', 'A', 'C'],
 'D#': ['D#', 'F#', 'G#', 'A#', 'C#'],
 'E': ['E', 'G', 'A', 'B', 'D'],
 'F': ['F', 'G#', 'A#', 'C', 'D#'],
 'F#': ['F#', 'A', 'B', 'C#', 'E'],
 'G': ['G', 'A#', 'C', 'D', 'F'],
 'G#': ['G#', 'B', 'C#', 'D#', 'F#'],
 'A': ['A', 'C', 'D', 'E', 'G'],
 'A#': ['A#', 'C#', 'D#', 'F', 'G#'],
 'B': ['B', 'D', 'E', 'F#', 'A']}

The minor pentatonic includes the same notes of a major pentatonic. However, the tonic or root note of the minor pentatonic begins on the 5th note of the major pentatonic as per the reference here.

The property above clearly describes a cyclic permutation! Hence it is apparent that the minor pentatonic scale may be considered a mode of the major pentatonic scale. Let us find out which one below:

In [154]:
[get_intervals(get_mode(get_scale('C', major_pentatonic_intervals), k)) == minor_pentatonic_intervals
     for k in range(5)]
[False, False, False, False, True]

As determined above, the minor pentatonic scale is nothing but the 4th mode of the major pentatonic scale, which is equivalent to the expression identified by the referred property above!

Understanding the relationships between scales

With a basic framework now developed, we can now get to the main body of this discussion. In the subsequent sections, I will try to formulate and discuss new and interesting properties of the scales we have explored above.

Scale Intersections

It has been quite clear to me for a while now, that there is a very clear backbone structure to all the modes of the major heptatonic scale, and that this common structure is essentially determined by the minor and major pentatonic scales.

In particular, the intersection of all the notes of the minor modes of the major scale, i.e., the dorian, the phrygian and the aeolian essentially form the minor pentatonic scale. In a similar manner, the intersection of all notes of the major modes, i.e. the ionian, the lydian and the myxolydian constitute the major pentatonic scale. I can't help but think that the existence of this property was by design, and that the pentatonic scale was first derived by intersecting the notes of two (or more) minor or major modes. Let us try to verify this property:

In [168]:
major_modes = ['ionian', 'lydian', 'mixolydian']
minor_modes = ['dorian', 'phrygian', 'aeolian']

for key in notes.values():
    all_major_modes = [set(get_scale(key, intervals)) for intervals in [mode_intervals[mode] for mode in major_modes]]
    all_minor_modes = [set(get_scale(key, intervals)) for intervals in [mode_intervals[mode] for mode in minor_modes]]
    major_intersection = set.intersection(*all_major_modes)
    minor_intersection = set.intersection(*all_minor_modes)
    major_pentatonic = set(get_scale(key, major_pentatonic_intervals))
    minor_pentatonic = set(get_scale(key, minor_pentatonic_intervals))
    if major_pentatonic != major_intersection:
        print(key, major_pentatonic, major_intersection)
    if minor_pentatonic != minor_intersection:
        print(key, minor_pentatonic, minor_intersection)

The lack of any output above confirms this property that the pentatonic scales are essentially intersections of the corresponding modes! I am curious about whether all three major/minor scales are required to get to the pentatonic intersection, and if the intersection of any two minor/major scales might yield some other interesting scales. Let us try this out:

In [182]:
key = 'C'

def get_intersecting_scale_set(*scales):
    return set.intersection(*[set(x) for x in scales])

def get_modal_scale_set(mode):
    intervals = mode_intervals[mode]
    scale = get_scale(key, intervals)
    return scale

def get_modal_intersections(*modes):
    return get_intersecting_scale_set(*[get_modal_scale_set(x) for x in modes])

print("Minor Pentatonic: ", get_modal_intersections("phrygian", "dorian", "aeolian"))
import itertools
for x, y in itertools.combinations(minor_modes, 2):
    print(x + " & " + y + ": ", get_modal_intersections(x, y))
print("Major Pentatonic: ", get_modal_intersections("ionian", "lydian", "mixolydian"))
import itertools
for x, y in itertools.combinations(major_modes, 2):
    print(x + " & " + y + ": ", get_modal_intersections(x, y))
Minor Pentatonic:  {'C', 'F', 'A#', 'G', 'D#'}
dorian & phrygian:  {'C', 'F', 'A#', 'G', 'D#'}
dorian & aeolian:  {'C', 'F', 'A#', 'G', 'D', 'D#'}
phrygian & aeolian:  {'C', 'F', 'A#', 'G#', 'G', 'D#'}
Major Pentatonic:  {'E', 'A', 'C', 'G', 'D'}
ionian & lydian:  {'E', 'B', 'A', 'C', 'G', 'D'}
ionian & mixolydian:  {'E', 'A', 'C', 'F', 'G', 'D'}
lydian & mixolydian:  {'E', 'A', 'C', 'G', 'D'}

This is an interesting result, and is concodant with my understanding of these scales when superimposed on the guitar. Dorian and Phrygian only have the pentatonic notes in common. Similar is the case with Lydian and Mixolydian.

However, each of these four scales have one more note in common with the Aeolian/Ionian mode. Using these additional notes as 'color' notes can produce interesting results in the right context. For instance, in the Stairway to Heaven solo by Led Zeppelin, the scale used is primarily Phrygian $\cap$ Aeolian if I remember correctly.

There is a vague parallel between the minor and major modes above. Let us try to explore this further.

Relative Minors

I don't think there should be anything particularly special about the Ionian, from which we generated the rest of the modes. As such, it is fairly natural to consider questions such as which mode of the Aeolian scale is the Ionian? Similarly, which mode is the Lydian of the Phrygian etc.

These modal scales are all clearly cyclic permutations of each other, and hence modes of each other. I particular I am curious if there are any similarities between Phrygian and Mixolydian, or between Dorian and Lydian.

In [195]:
print(modes['aeolian'] - modes['ionian'])
print(modes['phrygian'] - modes['mixolydian'] + 7)
print(modes['dorian'] - modes['lydian'] + 7)

The above makes for an interesting insight into the relationships between these scales. Just as Aeolian may be considered as the relative minor of the Ionian, in a similar manner, we can consider Phrygian to be the relative minor of the Mixolydian. Similarly, Dorian is a relative minor of the Lydian.

A well known property is that the minor and major pentatonic scales are 'relative' to each other and share the same shape on the guitar. The only difference is the root note which can be determined easily by using the relative minor concept.

This understanding makes these modes almost trivial to play on the guitar, since once you have the hang of the pentatonic scales, you just needs to add the right couple of notes in all their locations on the fretboard to the basic pentatonic structure, and immediately gain the ability to play every major and minor mode on the guitar in any key.

The above code snippet reveals another hint that the Phrygian mode uses the same notes as the Mixolydian mode, just in another root which is the relative minor of the corresponding major note. A similar story exists for the Dorian and the Lydian. Thus, all one needs to do is learn the notes on one of these groups of two, and that makes it trivial to derive all the notes on the guitar for the other modes. In my case, I first learnt the minor and major pentatonic scales. Using the minor pentatonic as a backbone, I learnt the Dorian and the Phrygian. Those patterns were the same as the ones for Mixolydian and Lydian respectively, as long as I used the correct key to play them in.