# Path: facerec_py/facerec/feature.py
# class AbstractFeature(object):
#     def compute(self, X, y):
#         raise NotImplementedError("Every AbstractFeature must implement the compute method.")
# 
#     def extract(self, X):
#         raise NotImplementedError("Every AbstractFeature must implement the extract method.")
# 
#     def save(self):
#         raise NotImplementedError("Not implemented yet (TODO).")
# 
#     def load(self):
#         raise NotImplementedError("Not implemented yet (TODO).")
# 
#     def __repr__(self):
#         return self.short_name()
# 
#     def short_name(self):
#         return self.__class__.__name__
# 
# Path: facerec_py/facerec/util.py
# def asColumnMatrix(X):
#     """
#     Creates a column-matrix from multi-dimensional data items in list X.
#     
#     X [list] List with multi-dimensional data.
#     """
#     if len(X) == 0:
#         return np.array([])
#     total = 1
#     for i in range(0, np.ndim(X[0])):
#         total = total * X[0].shape[i]
#     mat = np.empty([total, 0], dtype=X[0].dtype)
#     for col in X:
#         mat = np.append(mat, col.reshape(-1, 1), axis=1)  # same as hstack
#     return np.asmatrix(mat)


from facerec_py.facerec.feature import AbstractFeature
from facerec_py.facerec.util import asColumnMatrix
from sklearn.decomposition import KernelPCA
import numpy as np

class KPCA(AbstractFeature):
    def __init__(self, num_components=50, kernel="poly", degree=3, coef0=0.0, gamma=None):
        AbstractFeature.__init__(self)
        self._num_components = num_components
        self._kernel = kernel
        self._degree = degree
        self._coef0 = coef0
        self._gamma = gamma

        self._kpca = None

    def compute(self, X, y):
        """
        PCA over the entire images set
        dimension reduction for entire images set


        * Prepare the data with each column representing an image.
        * Subtract the mean image from the data.
        * Calculate the eigenvectors and eigenvalues of the covariance matrix.
        * Find the optimal transformation matrix by selecting the principal components (eigenvectors with largest eigenvalues).
        * Project the centered data into the subspace.
        Reference: http://en.wikipedia.org/wiki/Eigenface#Practical_implementation

        :param X: The images, which is a Python list of numpy arrays.
        :param y: The corresponding labels (the unique number of the subject, person) in a Python list.
        :return:
        """
        # build the column matrix

# Path: facerec_py/facerec/feature.py
# class AbstractFeature(object):
#     def compute(self, X, y):
#         raise NotImplementedError("Every AbstractFeature must implement the compute method.")
# 
#     def extract(self, X):
#         raise NotImplementedError("Every AbstractFeature must implement the extract method.")
# 
#     def save(self):
#         raise NotImplementedError("Not implemented yet (TODO).")
# 
#     def load(self):
#         raise NotImplementedError("Not implemented yet (TODO).")
# 
#     def __repr__(self):
#         return self.short_name()
# 
#     def short_name(self):
#         return self.__class__.__name__
# 
# Path: facerec_py/facerec/util.py
# def asColumnMatrix(X):
#     """
#     Creates a column-matrix from multi-dimensional data items in list X.
#     
#     X [list] List with multi-dimensional data.
#     """
#     if len(X) == 0:
#         return np.array([])
#     total = 1
#     for i in range(0, np.ndim(X[0])):
#         total = total * X[0].shape[i]
#     mat = np.empty([total, 0], dtype=X[0].dtype)
#     for col in X:
#         mat = np.append(mat, col.reshape(-1, 1), axis=1)  # same as hstack
#     return np.asmatrix(mat)


# Path: expr/kernelpca_ski.py
from facerec_py.facerec.feature import AbstractFeature
from facerec_py.facerec.util import asColumnMatrix
from sklearn.decomposition import KernelPCA
import numpy as np


class KPCA(AbstractFeature):
    def __init__(self, num_components=50, kernel="poly", degree=3, coef0=0.0, gamma=None):
        AbstractFeature.__init__(self)
        self._num_components = num_components
        self._kernel = kernel
        self._degree = degree
        self._coef0 = coef0
        self._gamma = gamma

        self._kpca = None

    def compute(self, X, y):
        """
        PCA over the entire images set
        dimension reduction for entire images set


        * Prepare the data with each column representing an image.
        * Subtract the mean image from the data.
        * Calculate the eigenvectors and eigenvalues of the covariance matrix.
        * Find the optimal transformation matrix by selecting the principal components (eigenvectors with largest eigenvalues).
        * Project the centered data into the subspace.
        Reference: http://en.wikipedia.org/wiki/Eigenface#Practical_implementation

        :param X: The images, which is a Python list of numpy arrays.
        :param y: The corresponding labels (the unique number of the subject, person) in a Python list.
        :return:
        """
        # build the column matrix

        XC = asColumnMatrix(X)