#Import Libraries
import matplotlib.pyplot as plt
import numpy as np
import random as rn
from matplotlib import style
import matplotlib.cm as cm
import pandas as pd 
from numpy.linalg import norm
from sklearn.metrics import silhouette_score,silhouette_samples
import csv
from sklearn.metrics.pairwise import pairwise_distances
from scipy.spatial import distance
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn import decomposition

"""# Problem 1: Limitations of PCA"""

# (a)
filename = r'C:\Users\relia001\OneDrive - University of Cyprus\UCY\TA\ECE805.2\Assignments\HW3\Solutions\2d_data.csv'
d = pd.read_csv(filename, header=None).values
filename = r'C:\Users\relia001\OneDrive - University of Cyprus\UCY\TA\ECE805.2\Assignments\HW3\Solutions\2d_label.csv'
c = pd.read_csv(filename, header=None).values
# d = np.genfromtxt('2d_data.csv',delimiter=',')
# c = np.genfromtxt('2d_label.csv',delimiter=',')
plt.scatter(d[:, 0], d[:, 1],c=c)
plt.title('X1 vs X2')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()

scaler = StandardScaler()
d_sc = scaler.fit_transform(d)
plt.scatter(d_sc[:, 0], d_sc[:, 1],c=c)
plt.title('X1 vs X2 - scaled')
plt.xlabel('X1_std')
plt.ylabel('X2_std')
plt.show()

pca = decomposition.PCA()
pca.n_components = 2
d_pca = pca.fit_transform(d_sc)
#scores_pca = pca.transform(d_pca)
plt.scatter(d_pca[:, 0], d_pca[:, 1],c=c)
plt.title('PC1 vs PC2')
plt.xlabel('PC11')
plt.ylabel('PC22')
plt.show()

plt.scatter(d_pca[:,0], d_pca[:,0]*0,c=c)
plt.title('Principal Component 1')
plt.xlabel('PC11')
plt.show()

plt.scatter(d_pca[:,1]*0, d_pca[:,1],c=c)
plt.title('Principal Component 2')
plt.ylabel('PC22')
plt.show()

# (b)
pca.explained_variance_ratio_

plt.figure(figsize = (10,8))
plt.plot(range(1,3),pca.explained_variance_ratio_.cumsum(),marker='o',linestyle='--')
plt.title('Explained Variance by Components')
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance')

"""# Problem 2: PCA and K-means"""

from sklearn.datasets import load_iris
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn import decomposition
import matplotlib.pyplot as plt

# (a)
# X = np.genfromtxt('iris_data.csv',delimiter=',')
# y = np.genfromtxt('iris_label.csv',delimiter=',')
filename = r'C:\Users\relia001\OneDrive - University of Cyprus\UCY\TA\ECE805.2\Assignments\HW3\Solutions\iris_data.csv'
X = pd.read_csv(filename, header=None).values
filename = r'C:\Users\relia001\OneDrive - University of Cyprus\UCY\TA\ECE805.2\Assignments\HW3\Solutions\iris_label.csv'
y = pd.read_csv(filename, header=None).values

"""##### K-means on original data"""

wcss = []
#scaler = StandardScaler()
#s_std = scaler.fit_transform(X)
for i in range(1,21):
  kmeans = KMeans(n_clusters=i,random_state=123)
  kmeans.fit(X)
  wcss.append(kmeans.inertia_)
plt.figure(figsize = (10,8))
plt.plot(range(1,21),wcss,marker = 'o',linestyle='--')
plt.xlabel('Number of Clusters')
plt.ylabel('Sum of Squared Distances')
plt.title('K-meeans without PCA Clustering')
plt.show()

"""##### Explaining PCA variance"""
# (b)
scaler = StandardScaler()
s_std = scaler.fit_transform(X)
pca = PCA()
pca.fit(s_std)
plt.figure(figsize = (10,8))
plt.plot(range(1,5),pca.explained_variance_ratio_.cumsum(),marker='o',linestyle='--')
plt.title('Explained Variance by Components')
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance')

"""##### Clustering with 2 principal *components*"""

pca2 = PCA(n_components=2)
pca2.fit(X)
X_pca2 = pca2.transform(s_std)
plt.scatter(X_pca2[:,0], X_pca2[:,1],c=y)
plt.xlabel('1st_principal')
plt.ylabel('2nd_principal')
plt.title('PC1 vs PC2 - Grount Truth Clustering')
plt.show()

# (c)
wcss = []
for i in range(1,21):
  kmeans_pca = KMeans(n_clusters=i,random_state=123)
  kmeans_pca.fit(X_pca2)
  wcss.append(kmeans_pca.inertia_)
plt.figure(figsize = (10,8))
plt.plot(range(1,21),wcss,marker = 'o',linestyle='--')
plt.xlabel('Number of Clusters')
plt.ylabel('Sum of Square Distances')
plt.title('K-means with PCA Clustering - 2D')
plt.show()

kmeans_best = KMeans(n_clusters=3,random_state=123)
kmeans_best.fit(X_pca2)
plt.xlabel('1st_principal')
plt.ylabel('2nd_principal')
plt.title('PC1 vs PC2 - Clustering with 3 groups')
plt.scatter(X_pca2[:, 0], X_pca2[:, 1],c=kmeans_best.labels_)
plt.scatter(kmeans_best.cluster_centers_[:, 0], kmeans_best.cluster_centers_[:, 1], marker='*', s=300, c='r', label='centroid')

# (d)
"""#### Clustering with 3 groups on original data"""

#Do clustering at higher dimensional space and project back to 2d to visualize the results

kmeans_best = KMeans(n_clusters=3,random_state=123)
kmeans_best.fit(X)
plt.xlabel('1st_principal')
plt.ylabel('2nd_principal')
plt.title('PC1 vs PC2 - Clustering with 3 groups on original data')
plt.scatter(X_pca2[:, 0], X_pca2[:, 1],c=kmeans_best.labels_)
cluster_centers__std = scaler.fit_transform(kmeans_best.cluster_centers_)
#cluster_centers__std = kmeans_best.cluster_centers_
cluster_centers__std = pca2.transform(cluster_centers__std)
pca_centers = cluster_centers__std
plt.scatter(pca_centers[:, 0], pca_centers[:, 1], marker='*', s=300, c='r', label='centroid')

from sklearn.cluster import SpectralClustering
kmeans_best = SpectralClustering(n_clusters=3, affinity='nearest_neighbors',
                           assign_labels='kmeans')
kmeans_best.fit(X)
labels = kmeans_best.fit_predict(X)
plt.xlabel('1st_principal')
plt.ylabel('2nd_principal')
plt.title('PC1 vs PC2 - Spectral Clustering with 3 groups')
plt.scatter(X_pca2[:, 0], X_pca2[:, 1],c=labels)

pca3 = PCA(n_components=3)
pca3.fit(X)
X_pca3 = pca3.transform(s_std)

fig = plt.figure()
ax = plt.axes(projection='3d')

ax.scatter(X_pca3[:,0], X_pca3[:,1], X_pca3[:,2], c=y*20, s=50, alpha=0.6, edgecolors='w')

ax.set_xlabel('1st_principal')
ax.set_ylabel('2nd_principal')
ax.set_zlabel('3d_principal')

plt.show()

wcss = []
for i in range(1,21):
  kmeans_pca = KMeans(n_clusters=i,random_state=123)
  kmeans_pca.fit(X_pca3)
  wcss.append(kmeans_pca.inertia_)
plt.figure(figsize = (10,8))
plt.plot(range(1,21),wcss,marker = 'o',linestyle='--')
plt.xlabel('Number of Clusters')
plt.ylabel('Sum of Square Distances')
plt.title('K-means with PCA Clustering - 3D')
plt.show()

kmeans_best = KMeans(n_clusters=3,random_state=123)
kmeans_best.fit(X_pca3)
# plt.scatter(X_pca2[:, 0], X_pca2[:, 1],c=kmeans_best.labels_)
# plt.scatter(kmeans_best.cluster_centers_[:, 0], kmeans_best.cluster_centers_[:, 1], marker='*', s=300, c='r', label='centroid')

fig = plt.figure()
ax = plt.axes(projection='3d')

ax.scatter(kmeans_best.cluster_centers_[:,0], kmeans_best.cluster_centers_[:,1], kmeans_best.cluster_centers_[:,2], c='r', s=1000, marker='*')
ax.scatter(X_pca3[:,0], X_pca3[:,1], X_pca3[:,2], c=kmeans_best.labels_*20, s=50, alpha=0.5, edgecolors='w')

ax.set_xlabel('PC1 vs PC2 vs PC3 - Clustering with 3 groups')
ax.set_xlabel('1st_principal')
ax.set_ylabel('2nd_principal')
ax.set_zlabel('3d_principal')

plt.show()

