# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# --------------------------------------------------------------------------------------------
# - Generated by tools/entrypoint_compiler.py: do not edit by hand
"""
GlobalContrastRowScaler
"""

__all__ = ["GlobalContrastRowScaler"]


from ....entrypoints.transforms_globalcontrastnormalizer import \
    transforms_globalcontrastnormalizer
from ....utils.utils import trace
from ...base_pipeline_item import BasePipelineItem, DefaultSignature


class GlobalContrastRowScaler(BasePipelineItem, DefaultSignature):
    """

    Normalizes columns as specified below.

    .. remarks::
        In linear classification algorithms instances are viewed as vectors
        in
        multi-dimensional space. Since the range of values of raw data varies
        widely, some objective functions do not work properly without
        normalization. For example, if one of the features has a broad range
        of
        values, the distances between points is governed by this particular
        feature. Therefore, the range of all features should be normalized so
        that each feature contributes approximately proportionately to the
        final
        distance. This can provide significant speedup and accuracy benefits.
        In
        all the linear algorithms in nimbusml (:py:class:`Logistic Regression
        <nimbusml.linear_model.LogisticRegressionClassifier>`,
        :py:class:`Averaged Perceptron
        <nimbusml.linear_model.AveragedPerceptronBinaryClassifier>`, etc.),
        the default is to normalize features before training.

        ``GlobalContrastRowScaler`` performs a global contrast normalization
        on
        input values: ``Y = (s * X - M) / D``, where s is a scale, M is mean
        and D
        is either L2 norm or standard deviation..

    :param sub_mean: Subtract mean from each value before normalizing.

    :param use_std_dev: Normalize by standard deviation rather than L2 norm.

    :param scale: Scale features by this value.

    :param params: Additional arguments sent to compute engine.

    .. seealso::
        :py:class:`MinMaxScaler
        <nimbusml.preprocessing.normalization.MinMaxScaler>`,
        :py:class:`Binner
        <nimbusml.preprocessing.normalization.Binner>`,
        :py:class:`MeanVarianceScaler
        <nimbusml.preprocessing.normalization.MeanVarianceScaler>`,
        :py:class:`LogMeanVarianceScaler
        <nimbusml.preprocessing.normalization.LogMeanVarianceScaler>`.

    .. index:: normalize, preprocessing

    Example:
       .. literalinclude:: /../nimbusml/examples/GlobalContrastRowScaler.py
              :language: python
    """

    @trace
    def __init__(
            self,
            sub_mean=True,
            use_std_dev=False,
            scale=1.0,
            **params):
        BasePipelineItem.__init__(
            self, type='transform', **params)

        self.sub_mean = sub_mean
        self.use_std_dev = use_std_dev
        self.scale = scale

    @property
    def _entrypoint(self):
        return transforms_globalcontrastnormalizer

    @trace
    def _get_node(self, **all_args):

        input_columns = self.input
        if input_columns is None and 'input' in all_args:
            input_columns = all_args['input']
        if 'input' in all_args:
            all_args.pop('input')

        output_columns = self.output
        if output_columns is None and 'output' in all_args:
            output_columns = all_args['output']
        if 'output' in all_args:
            all_args.pop('output')

        # validate input
        if input_columns is None:
            raise ValueError(
                "'None' input passed when it cannot be none.")

        if not isinstance(input_columns, list):
            raise ValueError(
                "input has to be a list of strings, instead got %s" %
                type(input_columns))

        # validate output
        if output_columns is None:
            output_columns = input_columns

        if not isinstance(output_columns, list):
            raise ValueError(
                "output has to be a list of strings, instead got %s" %
                type(output_columns))

        algo_args = dict(
            column=[
                dict(
                    Source=i,
                    Name=o) for i,
                o in zip(
                    input_columns,
                    output_columns)] if input_columns else None,
            sub_mean=self.sub_mean,
            use_std_dev=self.use_std_dev,
            scale=self.scale)

        all_args.update(algo_args)
        return self._entrypoint(**all_args)
