import numpy as np
import math
import statistics as stats
import scipy.stats as scistats
import matplotlib.pyplot as plt
import os
from pandas import read_table, read_csv
from netCDF4 import Dataset as ds
import matplotlib.ticker as mticker
import matplotlib.patches as patches
plt.rcParams['figure.figsize'] = (12, 12)
#Style Dictionary to standarize plotting scheme between different python scripts
styledict = {'xtick.labelsize':25,
'xtick.major.size':9,
'xtick.major.width':1,
'ytick.labelsize':25,
'ytick.major.size':9,
'ytick.major.width':1,
'legend.framealpha':0.0,
'legend.fontsize':15,
'axes.labelsize':20,
'axes.titlesize':25,
'axes.linewidth':2,
'figure.figsize':(12,8),
'savefig.format':'jpg'}
plt.rcParams.update(**styledict)
import os
os.chdir("/Users/sshen/climstats")
# Matrix multiplication
A = [[1, 0], [0, 4],[3, 2]]
B = [[0,-1],[1,2]]
C = np.matmul(A,B) #Or C = np.dot(A,B)
print('C=', C)
#C= [[ 0 -1]
# [ 4 8]
# [ 2 1]]
print('Transpose matrix of C =', C.transpose())
#Transpose matrix of C = [[ 0 4 2]
# [-1 8 1]]
C= [[ 0 -1] [ 4 8] [ 2 1]] Transpose matrix of C = [[ 0 4 2] [-1 8 1]]
#matrix inversion
A = [[1,-1],[1,2]]
np.linalg.inv(A)# compute the inverse of A
#array([[ 0.66666667, 0.33333333],
# [-0.33333333, 0.33333333]])
array([[ 0.66666667, 0.33333333], [-0.33333333, 0.33333333]])
#Solve a system of linear equations
A = [[30, 40],[1, 1]]
b = [[1000],[30]]
x = np.linalg.solve(A,b)
print('x=',x)
#x= [[20.]
# [10.]]
x= [[20.] [10.]]
#Compute determinant of the previous matrix A
A = [[30, 40],[1, 1]]
print('Determinant det(A)=', np.linalg.det(A))
#Determinant det(A)= -10.000000000000002
Determinant det(A)= -10.000000000000002
#An orthogonal matrix
p = np.sqrt(2)/2
Q = [[p,p],[-p,p]]
print('Orthogonal matrix Q=', np.round(Q,2))
T = np.transpose(Q)
print('Q times transpose of Q = ', np.matmul(Q,T))
print('Determinant of Q =', np.linalg.det(Q))
#Orthogonal matrix Q= [[ 0.71 0.71]
# [-0.71 0.71]]
#Q times transpose of Q = [[1. 0.]
# [0. 1.]]
#Determinant of Q = 1.0
Orthogonal matrix Q= [[ 0.71 0.71] [-0.71 0.71]] Q times transpose of Q = [[1. 0.] [0. 1.]] Determinant of Q = 1.0
#Compute eigenvectors and eigenvalues
A = [[1,2], [2,1]]
np.linalg.eig(A)
#(array([ 3., -1.]), array([[ 0.70710678, -0.70710678],
# [ 0.70710678, 0.70710678]]))
(array([ 3., -1.]), array([[ 0.70710678, -0.70710678], [ 0.70710678, 0.70710678]]))
import matplotlib.patches as patches
fig = plt.figure(figsize = (12,12))
x = [0]
y = [0]
plt.plot(x,y, 'ko-')
plt.xlim([-0.1,3.1])
plt.ylim([-0.1,3.1])
style = "Simple, tail_width=0.5,head_width=8,head_length=28"
kw1 = dict(arrowstyle=style, color="blue")
kw2 = dict(arrowstyle=style, color="red")
a1 = patches.FancyArrowPatch((0,0), (1,0), **kw1,
linewidth =5)
a2 = patches.FancyArrowPatch((0, 0), (1,2),**kw1)
a3 = patches.FancyArrowPatch((0, 0), (1,1), **kw2,
linewidth = 5)
a4 = patches.FancyArrowPatch((0, 0), (3,3),**kw2)
for a in [a1, a2, a3, a4]:
plt.gca().add_patch(a)
plt.title('An eigenvector v vs a non-eigenvector u')
plt.xlabel(r'$x_1$', fontsize = 25)
plt.ylabel(r'$x_2$', fontsize = 25)
plt.text(0.6, 0.1, 'Non-eigenvector u',
color = 'blue', fontsize =25)
plt.text(0.8, 2.0, 'Au',
color = 'blue', fontsize =25)
plt.text(1.03,0.85, 'Eigenvector v',
color = 'red', fontsize =25)
plt.text(2.7, 2.9, 'Av',
color = 'red', fontsize =25)
plt.show()
# Verify diagonalization and decomposition
C = [[2,1],[1,2]]
valC, Q = np.linalg.eig(C)
print('eigenvalues of C =', valC)
#eigenvalues of C = [3. 1.]
print('eigenvectors of C =', Q)
#eigenvectors of C = [[ 0.70710678 -0.70710678]
# [ 0.70710678 0.70710678]]
D = Q.transpose(1,0).dot(C).dot(Q)
print('D = ', D)
#D = [[3. 0.]
# [0. 1.]]
# Matrix C is decomposed into three matrices: C = Q D Q'
Q.dot(D).dot(Q.transpose(1,0))
#array([[2., 1.],
# [1., 2.]])
eigenvalues of C = [3. 1.] eigenvectors of C = [[ 0.70710678 -0.70710678] [ 0.70710678 0.70710678]] D = [[3. 0.] [0. 1.]]
array([[2., 1.], [1., 2.]])
D[0][0]*np.outer(Q[:][0],Q.transpose()[:][0]) + \
D[1][1]*np.outer(Q[:][1],Q.transpose()[:][1])
#array([[ 1., 2.],
# [-2., -1.]]) #matrix C is recovered from vectors
array([[ 1., 2.], [-2., -1.]])
#SVD example for a 2-by-3 matrix: Python code
A = [[-1,0, -2],[1,2,3]]
UsvdA, DsvdA, VsvdA = np.linalg.svd(A)
print('Singular values= ', np.round(DsvdA,2))
#Singular values= [4.22 1.09]
print('Spatial singular vectors= ', np.round(UsvdA,2))
#Spatial singular vectors= [[-0.48 0.88]
# [ 0.88 0.48]]
print('Temporal singular vectors= ', np.round(VsvdA,2))
#Temporal singular vectors= [[ 0.32 0.42 0.85]
# [-0.37 0.88 -0.29]
# [-0.87 -0.22 0.44]]
Singular values= [4.22 1.09] Spatial singular vectors= [[ 0.48 0.88] [-0.88 0.48]] Temporal singular vectors= [[-0.32 -0.42 -0.85] [-0.37 0.88 -0.29] [-0.87 -0.22 0.44]]
B = np.array(A)
C = np.matmul(B, B.T) #B times B transpose
valC, vecC = np.linalg.eig(C)
np.sqrt(valC)
#array([1.0855144 , 4.22157062])
array([1.0855144 , 4.22157062])
#Data reconstruction by singular vectors: Python code
np.round(DsvdA[0]*np.outer(UsvdA[:][0], VsvdA[:][0]),1)
#array([[-0.7, -0.8, -1.7],
# [ 1.2, 1.5, 3.2]])
array([[-0.7, -0.8, -1.7], [-1.2, -1.5, -3.2]])
A1 = DsvdA[0]*np.outer(UsvdA[:][0], VsvdA[:][0])
A2 = DsvdA[1]*np.outer(UsvdA[:][1], VsvdA[:][1])
np.round(A1 + A2, 2)
#array([[-1., 0., -2.],
# [ 1., 2., 3.]])
array([[-0.3 , -1.68, -1.44], [-1.38, -1.08, -3.3 ]])
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def draw_matrix(ax, lower_left, upper_right, color,
n_label, m_label, label_color, matrix_label):
# Draw the rectangle
ax.add_patch(patches.Rectangle(lower_left,
upper_right[0] - lower_left[0],
upper_right[1] - lower_left[1],
edgecolor=color,
facecolor='none', lw=3))
# Add n and m labels
ax.text(lower_left[0] - 0.8, (lower_left[1] + upper_right[1]) / 2,
n_label, ha='right', va='center',
fontsize=20, color=label_color, rotation=90)
ax.text((lower_left[0] + upper_right[0]) / 2,
upper_right[1] + 0.8, m_label, ha='center', va='bottom',
fontsize=20, color=label_color)
# Add matrix label
ax.text((lower_left[0] + upper_right[0]) / 2,
lower_left[1] - 1.5, matrix_label,
ha='center', va='top', fontsize=20)
def draw_diagonal(ax, start, end, color):
ax.plot([start[0], end[0]], [start[1], end[1]],
color=color, lw=1.3, linestyle='--')
def main():
# Set up the plot
fig, ax = plt.subplots(figsize=(15, 10))
ax.set_xlim(-3, 28)
ax.set_ylim(-3, 16)
ax.axis('off') # Hide axis
# SVD Text
ax.text(13, 15.5,
r"SVD: $A = UDV^T$ when n > m (top panel) or n < m (bottom panel)",
ha='center', fontsize=22)
#Draw the large equality sign =
plt.text(4, 10, '=', color = 'k',
fontsize =40, rotation=0)
# Draw matrices for n > m
draw_matrix(ax, (0, 7), (3, 13), 'blue', 'n', 'm', 'blue', 'A[n×m]')
draw_matrix(ax, (7, 7), (10, 13), 'blue', 'n', 'm', 'blue', 'U[n×m]')
draw_matrix(ax, (12, 10), (15, 13), 'brown', 'm', 'm', 'red', 'D[m×m]')
draw_diagonal(ax, (12, 13), (15, 10), 'brown')
draw_matrix(ax, (17, 10), (20, 13), 'red', 'm', 'm', 'red', "(Vᵀ)[m×m]")
# Draw matrices for n < m
draw_matrix(ax, (0, 0), (6, 3), 'blue', 'n', 'm', 'blue', 'B[n×m]')
draw_matrix(ax, (11, 0), (14, 3), 'blue', 'n', 'n', 'blue', 'U[n×n]')
draw_matrix(ax, (16, 0), (19, 3), 'brown', 'n', 'n', 'blue', 'D[n×n]')
draw_diagonal(ax, (16, 3), (19, 0), 'brown')
draw_matrix(ax, (21, 0), (27, 3), 'red', 'n', 'm', 'red', "(Vᵀ)[n×m]")
#Draw the large equality sign =
plt.text(7, 1.1, '=', color = 'k',
fontsize =40, rotation=0)
#Draw the dots for matrix columns and rows for the upper panel
plt.plot([0.5,0.5], [7, 13],
linestyle='dotted', color = 'k')
plt.plot([1, 1], [7, 13],
linestyle='dotted', color = 'k')
plt.text(1.7, 10, r'$\cdots$', color = 'k',
fontsize =25, rotation=0)
plt.plot([0.5+7,0.5+7], [7, 13],
linestyle='dotted', color = 'b')
plt.plot([1+7, 1+7], [7, 13],
linestyle='dotted', color = 'b')
plt.text(1.7+7, 10, r'$\cdots$', color = 'blue',
fontsize =25, rotation=0)
plt.text(1.7+7+5, 10+2, '0', color = 'maroon',
fontsize =25, rotation=0)
plt.text(1.7+7+3.7, 10+0.8, '0', color = 'maroon',
fontsize =25, rotation=0)
plt.plot([17,20], [12, 12],
linestyle='dotted', color = 'r')
plt.plot([17,20], [12.5, 12.5],
linestyle='dotted', color = 'r')
plt.text(18, 11, r'$\vdots$', color = 'red',
fontsize =25, rotation=0)
#Draw the dots for matrix columns and rows for the lower panel
plt.plot([0, 6], [2.5, 2.5],
linestyle='dotted', color = 'k')
plt.plot([0, 6], [2.0, 2.0],
linestyle='dotted', color = 'k')
plt.text(2.7, 1.0, r'$\vdots$', color = 'k',
fontsize =25, rotation=0)
plt.plot([12, 12], [0, 3],
linestyle='dotted', color = 'b')
plt.plot([12-0.5, 12-0.5], [0, 3],
linestyle='dotted', color = 'b')
plt.text(1.7+11, 1.2, r'$\cdots$', color = 'blue',
fontsize =25, rotation=0)
plt.text(1.7+16.1, 1.6, '0', color = 'maroon',
fontsize =25, rotation=0)
plt.text(1.7+14.9, 0.7, '0', color = 'maroon',
fontsize =25, rotation=0)
plt.plot([21, 27], [2, 2],
linestyle='dotted', color = 'r')
plt.plot([21, 27], [2.5, 2.5],
linestyle='dotted', color = 'r')
plt.text(23.5, 1, r'$\vdots$', color = 'red',
fontsize =25, rotation=0)
# Show the plot
plt.show()
if __name__ == "__main__":
main()
#Python SVD analysis of Darwin and Tahiti SLP
import os
os.chdir("/Users/sshen/climstats")
PDA = np.array(read_table("data/PSTANDdarwin.txt", \
header = None, delimiter = "\s+"))
PTA = np.array(read_table("data/PSTANDtahiti.txt", \
header = None, delimiter = "\s+"))
pdata = np.stack([PDA[58:65,12], PTA[58:65,12]], axis=0)
print('The Darwin and Tahiti SLP data 2009-2015 =', pdata)
#The Darwin and Tahiti Standardized SLP anomalies =
#[[ 0.5 -2.3 -2.2 0.3 0.3 0.1 -0.4]
# [-0.7 2.5 1.9 -0.7 0.4 -0.8 -1.3]]
u, d, v = np.linalg.svd(pdata)
print('Spatial singular vectors EOFs U =', np.round(u,2))
#Spatial singular vectors EOFs U = [[-0.66 0.75]
# [ 0.75 0.66]]
print('Diagonal matrix D =', np.round(np.diag(d),2))
#Diagonal matrix D = [[4.7 0. ]
# [0. 1.42]]
print('Temporal singular vectors PCs V=', np.round(v,2))
#Temporal singular vectors PCs V=
#[[-0.18 0.72 0.61 -0.15 0.02 -0.14 -0.15]
# [-0.06 -0.06 -0.28 -0.17 0.34 -0.32 -0.82] ...]
The Darwin and Tahiti SLP data 2009-2015 = [[ 0.5 -2.3 -2.2 0.3 0.3 0.1 -0.4] [-0.7 2.5 1.9 -0.7 0.4 -0.8 -1.3]] Spatial singular vectors EOFs U = [[ 0.66 0.75] [-0.75 0.66]] Diagonal matrix D = [[4.7 0. ] [0. 1.42]] Temporal singular vectors PCs V= [[ 0.18 -0.72 -0.61 0.15 -0.02 0.14 0.15] [-0.06 -0.06 -0.28 -0.17 0.34 -0.32 -0.82] [ 0.74 -0.32 0.55 0.03 0.1 -0.02 -0.18] [ 0.01 0.19 -0.03 0.97 0.06 -0.06 -0.15] [-0.27 -0.18 0.2 0.04 0.87 0.1 0.29] [ 0.15 0.25 -0.13 -0.05 0.12 0.9 -0.27] [ 0.56 0.49 -0.43 -0.1 0.3 -0.24 0.32]]