""" Transformers to perform common preprocessing steps.
"""

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Mathieu Blondel <mathieu@mblondel.org>
# License: BSD

import numpy as np

from ..base import BaseEstimator, TransformerMixin


def _mean_and_std(X, axis=0, with_std=True):
    """Compute mean and std dev for centering, scaling

    Zero valued std components are reseted to 1.0 to avoid NaNs when scaling.
    """
    Xr = np.rollaxis(X, axis)
    mean_ = Xr.mean(axis=0)

    if with_std:
        std_ = Xr.std(axis=0)
        if isinstance(std_, np.ndarray):
            std_[std_ == 0.0] = 1.0
        elif std_ == 0.:
            std_ = 1.
    else:
        std_ = None

    return mean_, std_


def scale(X, axis=0, with_std=True, copy=True):
    """Method to standardize a dataset along any axis

    Center to the mean and component wise scale to unit variance.
    """
    mean_, std_ = _mean_and_std(X, axis, with_std)
    if copy:
        X = X.copy()
    Xr = np.rollaxis(X, axis)
    Xr -= mean_
    if with_std:
        Xr /= std_
    return X


class Scaler(BaseEstimator):
    """Object to standardize a dataset

    It centers the dataset and optionaly scales to fix the variance to 1 for
    each feature
    """

    def __init__(self, with_std=True):
        self.with_std = with_std

    def fit(self, X, y=None, **params):
        self._set_params(**params)
        self.mean_, self.std_ = _mean_and_std(X, axis=0,
                                              with_std=self.with_std)
        return self

    def transform(self, X, y=None, copy=True):
        if copy:
            X = X.copy()
        # We are taking a view of the X array and modifying it
        X -= self.mean_
        if self.with_std:
            X /= self.std_
        return X


class Normalizer(BaseEstimator):
    """Normalize vectors such that they sum to 1"""

    def fit(self, X, y=None, **params):
        self._set_params(**params)
        return self

    def transform(self, X, y=None, copy=True):
        if copy:
            X = X.copy()
        norms = X.sum(axis=1)[:, np.newaxis]
        norms[norms == 0.0] = 1.0
        X /= norms

        return X


class LengthNormalizer(BaseEstimator):
    """Normalize vectors to unit vectors"""

    def fit(self, X, y=None, **params):
        self._set_params(**params)
        return self

    def transform(self, X, y=None, copy=True):
        if copy:
            X = X.copy()

        norms = np.sqrt(np.sum(X ** 2, axis=1))[:, np.newaxis]
        norms[norms == 0.0] = 1.0
        X /= norms

        return X


class Binarizer(BaseEstimator):
    """Binarize data according to a threshold"""

    def __init__(self, threshold=0.0):
        self.threshold = threshold

    def fit(self, X, y=None, **params):
        self._set_params(**params)
        return self

    def transform(self, X, y=None, copy=True):
        if copy:
            X = X.copy()

        cond = X > self.threshold
        not_cond = np.logical_not(cond)
        X[cond] = 1
        X[not_cond] = 0

        return X


class LabelBinarizer(BaseEstimator, TransformerMixin):
    """Binarize labels in a one-vs-all fashion.

    Several regression and binary classification algorithms are available in the
    scikit. A simple way to extend these algorithms to the multi-class
    classification case is to use the so-called one-vs-all scheme.

    At learning time, this simply consists in learning one regressor or binary
    classifier per class. In doing so, one needs to convert multi-class labels
    to binary labels (belong or does not belong to the class). LabelBinarizer
    makes this process easy with the transform method.

    At prediction time, one assigns the class for which the corresponding model
    gave the greatest confidence. LabelBinarizer makes this easy with the
    inverse_transform method.

    Attributes
    ----------
    classes_ : array of shape [n_class]
        Holds the label for each class.

    Examples
    --------
    >>> from scikits.learn import preprocessing
    >>> clf = preprocessing.LabelBinarizer()
    >>> clf.fit([1,2,6,4,2])
    LabelBinarizer()
    >>> clf.classes_
    array([1, 2, 4, 6])
    >>> clf.transform([1, 6])
    array([[ 1.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  1.]])
    """

    def fit(self, y):
        """Fit label binarizer

        Parameters
        ----------
        y : numpy array of shape [n_samples]
            Target values

        Returns
        -------
        self : returns an instance of self.
        """
        self.classes_ = np.unique(y)
        return self

    def transform(self, y):
        """Transform multi-class labels to binary labels

        The output of transform is sometimes referred to by some authors as the
        1-of-K coding scheme.

        Parameters
        ----------
        y : numpy array of shape [n_samples]
            Target values

        Returns
        -------
        Y : numpy array of shape [n_samples, n_classes]
        """
        if len(self.classes_) == 2:
            Y = np.zeros((len(y), 1))
            Y[y == self.classes_[1], 0] = 1
            return Y

        elif len(self.classes_) >= 2:
            Y = np.zeros((len(y), len(self.classes_)))
            for i, k in enumerate(self.classes_):
                Y[y == k, i] = 1
            return Y

        else:
            raise ValueError

    def inverse_transform(self, Y):
        """Transform binary labels back to multi-class labels

        Parameters
        ----------
        Y : numpy array of shape [n_samples, n_classes]
            Target values

        Returns
        -------
        y : numpy array of shape [n_samples]

        Note
        -----
        In the case when the binary labels are fractional (probabilistic),
        inverse_transform chooses the class with the greatest value. Typically,
        this allows to use the output of a linear model's decision_function
        method directly as the input of inverse_transform.
        """
        if len(Y.shape) == 1 or Y.shape[1] == 1:
            y = np.array(Y.ravel() > 0, dtype=int)
        else:
            y = Y.argmax(axis=1)
        return self.classes_[y]

@@ -1346,32 +1346,24 @@
 fit(self, X,
- y=None,
  **params):%0A
@@ -1354,32 +1354,32 @@
 , X, **params):%0A
+
         self._se
@@ -1567,32 +1567,24 @@
 orm(self, X,
- y=None,
  copy=True):
@@ -1887,32 +1887,24 @@
 fit(self, X,
- y=None,
  **params):%0A
@@ -1981,32 +1981,24 @@
 orm(self, X,
- y=None,
  copy=True):
@@ -2258,32 +2258,24 @@
 fit(self, X,
- y=None,
  **params):%0A
@@ -2352,32 +2352,24 @@
 orm(self, X,
- y=None,
  copy=True):
@@ -2725,24 +2725,16 @@
 self, X,
- y=None,
  **param
@@ -2785,32 +2785,32 @@
    return self%0A%0A
+
     def transfor
@@ -2823,16 +2823,8 @@
 , X,
- y=None,
  cop

Remove references to y in preprocessing objects.