numpy_scipy_matplotlib.py

#

Examples with numpy, scipy, and matplotlib

#

Original code is here.

#

NumPy

#

Imports the numpy library as the name np. This is a very common convention.

import numpy as np
#

Comparing Python lists and NumPy arrays.

#

a_list is a Python list

a_list = [1, 2, 3, 4, 5]
print('a_list is type', type(a_list))
#

a_array is a NumPy array

a_array = np.array(a_list)
print('a_array is type', type(a_array))
#

Can create Numpy arrays from a Python list and vice-versa

b_array = np.array([3, 2, 4, 1, 5])
b_list = list(b_array)
#

The + operator concatenates two lists

print('a_list + b_list =', a_list + b_list)
#

The + operator performs pairwise component addition for two arrays

print('a_array + b_array =', a_array + b_array)
#

The + operator can also add a scalar to an array

print('a_array + 5 =', a_array + 5)
#

Similarly, * will perform pairwise component multiplication

print('a_array * b_array = ', a_array * b_array)
#

Remember that when applied to a list and a scaler * will perform multiple concatenations

print('a_list * 3 =', a_list * 3)
#

When applied to two lists, however, * yields
TypeError: can't multiply sequence by non-int of type 'list' print('a_list * b_list =', a_list * b_list)

#

SciPy

#

Importing the pearsonr method from the scipy.stats.stats module. scipy builds on numpy.

from scipy.stats.stats import pearsonr
#

eight lists and their correlations

a = [1, 2, 3, 4, 5] # initial list
b = [1, 2, 3, 4, 5] # identical to `a`
c = [0, 1, 2, 3, 4] # identical to `a` minus 1
d = [2, 4, 6, 8, 10] # identical to `a` * 2
e = [1, 2, 3, 5, 4] # very similar, but not identical to `a`
f = [1, 5, 4, 2, 3] # not similar to `a`
g = [5, 4, 3, 2, 1] # opposite of `a`
h = [1, 1, 1, 1, 1] # flat shape; standard deviation of `h` is 0
#

Correlations between a and the other lists:

comparisons = [b, c, d, e, f, g, h]
for comparison in comparisons:
#

pearsonr returns a tuple corresponding to the r and p values

    corr, p = pearsonr(a, comparison)
#

Correlation between a and b, c, and d is 1.0 (maximal).
Correlation between a and e is 0.9 (high, but not maximal).
Correlation between a and f is 0.1, indicating almost no correlation.
Correlation between a and g is -1.0,indicating a maximal inverse inverse correlation.
Correlation between a and h is nan (not a number), since the calculation of correlation involves division by the standard deviations (which for h is 0).

    print('Correlation between', a, 'and', comparison, ':', corr)
#

Using scipy distance measures in music

#

harmonic_distance measures the Euclidean distance between two interval vectors. This is identical to Richard Teitelbaum's "similarity index". You can substitute different distance measures from the scipy.spatial.distance module. For instance, using cityblock distance recreates Robert Morris' "SIM" measure.

#

p and q are lists of pitches. harmonic_distance depends on music21 and scipy.

Returns the harmonic distance of p and q interpreted as chords based on the Euclidean distance from the scipy.spatial.distance module. Prints an error message and returns None if the lists are of unequal length.

def harmonic_distance(p, q):
#
    from music21 import chord
    from scipy.spatial import distance

    if len(p) != len(q):
        print('lists of pitches are of unequal lengths')
        return None
#

Using the music21 Chord class .intervalVector property

    iv_p = chord.Chord(p).intervalVector
    iv_q = chord.Chord(q).intervalVector
    return distance.euclidean(iv_p, iv_q)
#

Using harmonic_distance to compare the harmonic similarity of three chords

chords = [[0, 2, 3, 7], [0, 2, 4, 6], [0, 4, 8, 11]]
print('Harmonic distances')
for i in range(2):
    u = chords[i]
    for j in range(i+1, 3):
        v = chords[j]
        print(u, '<-->', v, ':', harmonic_distance(u, v))
#

Matplotlib

#

pyplot is a module in matplotlib for plotting. matplotlib depends onnumpy`. See https://matplotlib.org/api/pyplot_api.html for more details.

import matplotlib.pyplot as plt
#

plotting two lists on the plane

x = [1, 2, 3, 4, 5]
y = [1, 7, 4, 2, 3]
plt.plot(x, y)
#

plot should automatically open

plt.show()
#

arange is the numpy array equivalent of Python's built-in range function.

x = np.arange(20)
print('x is', x)
#

plot f(x) = x**2

print('x squared is', x**2)
plt.plot(x, x**2)
plt.show()
#

plot f(x) = sin(2πx/20) using numpy's sin function and pi constant

y = np.sin(x * 2 * np.pi / len(x))
plt.plot(x, y)
plt.show()