import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

print("="*60)
print("PCA REPORT — MANUAL vs SKLEARN")
print("="*60)

# ─────────────────────────────
# STEP 0: DATASET
# ─────────────────────────────
X = np.array([
    [2, 1],
    [3, 5],
    [4, 3],
    [5, 6],
    [6, 7],
    [7, 8]
])

print("\nOriginal Dataset:")
print(X)

# ─────────────────────────────
# STEP 1: MEAN
# ─────────────────────────────
mean = np.mean(X, axis=0)
print("\nStep 1: Mean Vector:")
print(mean)

# ─────────────────────────────
# STEP 2: CENTER DATA
# ─────────────────────────────
X_centered = X - mean
print("\nStep 2: Centered Data:")
print(X_centered)

# ─────────────────────────────
# STEP 3: COVARIANCE MATRIX
# ─────────────────────────────
cov_matrix = np.cov(X_centered.T)
print("\nStep 3: Covariance Matrix:")
print(cov_matrix)

# ─────────────────────────────
# STEP 4: EIGENVALUES & VECTORS
# ─────────────────────────────
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)

print("\nStep 4: Eigenvalues:")
print(eigenvalues)

print("\nStep 4: Eigenvectors:")
print(eigenvectors)

# ─────────────────────────────
# STEP 5: SORT
# ─────────────────────────────
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]

print("\nStep 5: Sorted Eigenvalues:")
print(eigenvalues)

print("\nStep 5: Sorted Eigenvectors:")
print(eigenvectors)

# ─────────────────────────────
# STEP 6: PROJECTION
# ─────────────────────────────
X_pca_manual = X_centered @ eigenvectors

print("\nStep 6: Manual PCA Transformed Data:")
print(X_pca_manual)

# ─────────────────────────────
# VARIANCE EXPLAINED (MANUAL)
# ─────────────────────────────
var_ratio_manual = eigenvalues / np.sum(eigenvalues)

print("\nManual Explained Variance Ratio:")
print(var_ratio_manual)

cumulative_var_manual = np.cumsum(var_ratio_manual)
print("\nManual Cumulative Variance Ratio:")
print(cumulative_var_manual)


# ─────────────────────────────
# SKLEARN PCA
# ─────────────────────────────
pca = PCA(n_components=2)
X_pca_sklearn = pca.fit_transform(X)

print("\n" + "="*60)
print("SKLEARN PCA RESULTS")
print("="*60)

print("\nTransformed Data:")
print(X_pca_sklearn)

print("\nExplained Variance:")
print(pca.explained_variance_)

print("\nExplained Variance Ratio:")
print(pca.explained_variance_ratio_)

print("\nPrincipal Components (Eigenvectors):")
print(pca.components_)

# ─────────────────────────────
# COMPARISON CHECK
# ─────────────────────────────
print("\n" + "="*60)
print("COMPARISON CHECK")
print("="*60)

print("Manual vs Sklearn (absolute match):")
print(np.allclose(np.abs(X_pca_manual), np.abs(X_pca_sklearn)))

print("Manual vs Sklearn (relative match):")
print(np.allclose(X_pca_manual, X_pca_sklearn) or np.allclose(X_pca_manual, -X_pca_sklearn))

print("\nVariance Ratio Comparison:")
print("Manual:", var_ratio_manual)
print("Sklearn:", pca.explained_variance_ratio_)

# ─────────────────────────────
# VISUALIZATION
# ─────────────────────────────
plt.figure(figsize=(15,5))

# Original Data
plt.subplot(1,3,1)
plt.scatter(X[:,0], X[:,1])
plt.title("Original Data")
plt.xlabel("X")
plt.ylabel("Y")
plt.grid()

# Manual PCA
plt.subplot(1,3,2)
plt.scatter(X_pca_manual[:,0], X_pca_manual[:,1])
plt.title("Manual PCA")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.grid()

# Sklearn PCA
plt.subplot(1,3,3)
plt.scatter(X_pca_sklearn[:,0], X_pca_sklearn[:,1])
plt.title("Sklearn PCA")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.grid()

plt.tight_layout()
plt.show()

# ─────────────────────────────
# VARIANCE BAR PLOT
# ─────────────────────────────
plt.figure()

labels = ["PC1", "PC2"]
x = np.arange(len(labels))

plt.bar(x - 0.15, var_ratio_manual, width=0.3)
plt.bar(x + 0.15, pca.explained_variance_ratio_, width=0.3)

plt.xticks(x, labels)
plt.title("Explained Variance Ratio (Manual vs Sklearn)")
plt.xlabel("Principal Components")
plt.ylabel("Variance Ratio")

plt.show()