# Path: facerec_py/facerec/model.py
# class PredictableModel(AbstractPredictableModel):
#     def __init__(self, feature, classifier):
#         super(PredictableModel, self).__init__()
#         if not isinstance(feature, AbstractFeature):
#             raise TypeError("feature must be of type AbstractFeature!")
#         if not isinstance(classifier, AbstractClassifier):
#             raise TypeError("classifier must be of type AbstractClassifier!")
# 
#         self.feature = feature
#         self.classifier = classifier
# 
#     def compute(self, X, y):
#         features = self.feature.compute(X, y)
#         self.classifier.compute(features, y)
# 
#     def predict(self, X):
#         q = self.feature.extract(X)
#         return self.classifier.predict(q)
# 
#     def __repr__(self):
#         feature_repr = repr(self.feature)
#         classifier_repr = repr(self.classifier)
#         return "%s(feature=%s, classifier=%s)" % (self.__class__.__name__, feature_repr, classifier_repr)
# 
# class AbstractPredictableModel(object):
#     def compute(self, X, y):
#         raise NotImplementedError("Every AbstractPredictableModel must implement the compute method.")
# 
#     def predict(self, X):
#         raise NotImplementedError("Every AbstractPredictableModel must implement the predict method.")
# 
#     def __repr__(self):
#         return self.__class__.__name__
# 
# Path: util/commons_util/fundamentals/generators.py
# def frange(start, stop, step):
#     return list(drange(start, stop, step))


import math as math
import random as random
import logging
import cv2
import numpy as np
from facerec_py.facerec.model import PredictableModel, AbstractPredictableModel
from util.commons_util.fundamentals.generators import frange
        X, y are original data
        :param X: X [dim x num_data] input data to validate on
        :param y: y [1 x num_data] classes
        :param description:
        :return:
        """
        if not self.froze_shuffle:
            X, y = shuffle(X, y)

        c = len(np.unique(y))
        foldIndices = []
        n = np.iinfo(np.int).max  # n, min input data number for every class
        for i in range(0, c):
            idx = np.where(y == i)[0]  # for a specific class
            n = min(n, idx.shape[0])
            foldIndices.append(idx.tolist());

        # I assume all folds to be of equal length, so the minimum
        # number of samples in a class is responsible for the number
        # of folds. This is probably not desired. Please adjust for
        # your use case.
        if n < self.k:
            self.k = n

        # for ORL, n = 10
        foldSize = int(math.floor(n / self.k))

        if self.threshold_up==0:
            threshold_r = [0]
        else:

# Path: facerec_py/facerec/model.py
# class PredictableModel(AbstractPredictableModel):
#     def __init__(self, feature, classifier):
#         super(PredictableModel, self).__init__()
#         if not isinstance(feature, AbstractFeature):
#             raise TypeError("feature must be of type AbstractFeature!")
#         if not isinstance(classifier, AbstractClassifier):
#             raise TypeError("classifier must be of type AbstractClassifier!")
# 
#         self.feature = feature
#         self.classifier = classifier
# 
#     def compute(self, X, y):
#         features = self.feature.compute(X, y)
#         self.classifier.compute(features, y)
# 
#     def predict(self, X):
#         q = self.feature.extract(X)
#         return self.classifier.predict(q)
# 
#     def __repr__(self):
#         feature_repr = repr(self.feature)
#         classifier_repr = repr(self.classifier)
#         return "%s(feature=%s, classifier=%s)" % (self.__class__.__name__, feature_repr, classifier_repr)
# 
# class AbstractPredictableModel(object):
#     def compute(self, X, y):
#         raise NotImplementedError("Every AbstractPredictableModel must implement the compute method.")
# 
#     def predict(self, X):
#         raise NotImplementedError("Every AbstractPredictableModel must implement the predict method.")
# 
#     def __repr__(self):
#         return self.__class__.__name__
# 
# Path: util/commons_util/fundamentals/generators.py
# def frange(start, stop, step):
#     return list(drange(start, stop, step))


# Path: facerec_py/facerec/validation.py
import math as math
import random as random
import logging
import cv2
import numpy as np
from facerec_py.facerec.model import PredictableModel, AbstractPredictableModel
from util.commons_util.fundamentals.generators import frange

        X, y are original data
        :param X: X [dim x num_data] input data to validate on
        :param y: y [1 x num_data] classes
        :param description:
        :return:
        """
        if not self.froze_shuffle:
            X, y = shuffle(X, y)

        c = len(np.unique(y))
        foldIndices = []
        n = np.iinfo(np.int).max  # n, min input data number for every class
        for i in range(0, c):
            idx = np.where(y == i)[0]  # for a specific class
            n = min(n, idx.shape[0])
            foldIndices.append(idx.tolist());

        # I assume all folds to be of equal length, so the minimum
        # number of samples in a class is responsible for the number
        # of folds. This is probably not desired. Please adjust for
        # your use case.
        if n < self.k:
            self.k = n

        # for ORL, n = 10
        foldSize = int(math.floor(n / self.k))

        if self.threshold_up==0:
            threshold_r = [0]
        else:

            threshold_r = frange(0, self.threshold_up, 0.001)