"""Metrics to assess performance on regression task

Functions named as ``*_score`` return a scalar value to maximize: the higher
the better

Function named as ``*_error`` or ``*_loss`` return a scalar value to minimize:
the lower the better
"""

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Mathieu Blondel <mathieu@mblondel.org>
#          Olivier Grisel <olivier.grisel@ensta.org>
#          Arnaud Joly <a.joly@ulg.ac.be>
#          Jochen Wersdorfer <jochen@wersdoerfer.de>
#          Lars Buitinck <L.J.Buitinck@uva.nl>
#          Joel Nothman <joel.nothman@gmail.com>
#          Noel Dawe <noel@dawe.me>
#          Manoj Kumar <manojkumarsivaraj334@gmail.com>
#          Michael Eickenberg <michael.eickenberg@gmail.com>
#          Konstantin Shmelkov <konstantin.shmelkov@polytechnique.edu>
# License: BSD 3 clause

from __future__ import division

import numpy as np

from ..utils.validation import check_array, check_consistent_length
from ..utils.validation import column_or_1d

import warnings

__ALL__ = [
    "mean_absolute_error",
    "mean_squared_error",
    "median_absolute_error",
    "r2_score",
    "explained_variance_score"
]

def _check_reg_targets(y_true, y_pred, multioutput):
    """Check that y_true and y_pred belong to the same regression task

    Parameters
    ----------
    y_true : array-like,

    y_pred : array-like,

    multioutput : array-like or string in ['raw_values', uniform_average',
        'variance_weighted'] or None
        None is accepted due to backward compatibility of r2_score().

    Returns
    -------
    type_true : one of {'continuous', continuous-multioutput'}
        The type of the true target data, as output by
        'utils.multiclass.type_of_target'

    y_true : array-like of shape = (n_samples, n_outputs)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples, n_outputs)
        Estimated target values.

    multioutput : array-like of shape = (n_outputs) or string in ['raw_values',
        uniform_average', 'variance_weighted'] or None
        Custom output weights if ``multioutput`` is array-like or
        just the corresponding argument if ``multioutput`` is a
        correct keyword.

    """
    check_consistent_length(y_true, y_pred)
    y_true = check_array(y_true, ensure_2d=False)
    y_pred = check_array(y_pred, ensure_2d=False)

    if y_true.ndim == 1:
        y_true = y_true.reshape((-1, 1))

    if y_pred.ndim == 1:
        y_pred = y_pred.reshape((-1, 1))

    if y_true.shape[1] != y_pred.shape[1]:
        raise ValueError("y_true and y_pred have different number of output "
                         "({0}!={1})".format(y_true.shape[1], y_pred.shape[1]))

    n_outputs = y_true.shape[1]
    multioutput_options = (None, 'raw_values', 'uniform_average',
                           'variance_weighted')
    if multioutput not in multioutput_options:
        multioutput = check_array(multioutput, ensure_2d=False)
        if n_outputs == 1:
            raise ValueError("Custom weights are useful only in "
                             "multi-output cases.")
        elif n_outputs != len(multioutput):
            raise ValueError(("There must be equally many custom weights "
                              "(%d) as outputs (%d).") %
                             (len(multioutput), n_outputs))
    y_type = 'continuous' if n_outputs == 1 else 'continuous-multioutput'

    return y_type, y_true, y_pred, multioutput

def mean_absolute_error(y_true, y_pred,
                        sample_weight=None,
                        multioutput='uniform_average'):
    """Mean absolute error regression loss

    Read more in the :ref:`User Guide <mean_absolute_error>`.

    Parameters
    ----------
    y_true : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Estimated target values.

    sample_weight : array-like of shape = (n_samples), optional
        Sample weights.

    multioutput : string in ['raw_values', 'uniform_average']
        or array-like of shape (n_outputs)
        Defines aggregating of multiple output values.
        Array-like value defines weights used to average errors.

        'raw_values' :
            Returns a full set of errors in case of multioutput input.

        'uniform_average' :
            Errors of all outputs are averaged with uniform weight.

    Returns
    -------
    loss : float or ndarray of floats
        If multioutput is 'raw_values', then mean absolute error is returned
        for each output separately.
        If multioutput is 'uniform_average' or an ndarray of weights, then the
        weighted average of all output errors is returned.

        MAE output is non-negative floating point. The best value is 0.0.

    Examples
    --------
    >>> from sklearn.metrics import mean_absolute_error
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> mean_absolute_error(y_true, y_pred)
    0.5
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> mean_absolute_error(y_true, y_pred)
    0.75
    >>> mean_absolute_error(y_true, y_pred, multioutput='raw_values')
    array([ 0.5,  1. ])
    >>> mean_absolute_error(y_true, y_pred, multioutput=[0.3, 0.7])
    ... # doctest: +ELLIPSIS
    0.849...
    """
    y_type, y_true, y_pred, multioutput = _check_reg_targets(
        y_true, y_pred, multioutput)
    output_errors = np.average(np.abs(y_pred - y_true),
                               weights=sample_weight, axis=0)
    if multioutput == 'raw_values':
        return output_errors
    elif multioutput == 'uniform_average':
        # pass None as weights to np.average: uniform mean
        multioutput = None

    return np.average(output_errors, weights=multioutput)

def mean_squared_error(y_true, y_pred,
                       sample_weight=None,
                       multioutput='uniform_average'):
    """Mean squared error regression loss

    Read more in the :ref:`User Guide <mean_squared_error>`.

    Parameters
    ----------
    y_true : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Estimated target values.

    sample_weight : array-like of shape = (n_samples), optional
        Sample weights.

    multioutput : string in ['raw_values', 'uniform_average']
        or array-like of shape (n_outputs)
        Defines aggregating of multiple output values.
        Array-like value defines weights used to average errors.

        'raw_values' :
            Returns a full set of errors in case of multioutput input.

        'uniform_average' :
            Errors of all outputs are averaged with uniform weight.

    Returns
    -------
    loss : float or ndarray of floats
        A non-negative floating point value (the best value is 0.0), or an
        array of floating point values, one for each individual target.

    Examples
    --------
    >>> from sklearn.metrics import mean_squared_error
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> mean_squared_error(y_true, y_pred)
    0.375
    >>> y_true = [[0.5, 1],[-1, 1],[7, -6]]
    >>> y_pred = [[0, 2],[-1, 2],[8, -5]]
    >>> mean_squared_error(y_true, y_pred)  # doctest: +ELLIPSIS
    0.708...
    >>> mean_squared_error(y_true, y_pred, multioutput='raw_values')
    ... # doctest: +ELLIPSIS
    array([ 0.416...,  1.        ])
    >>> mean_squared_error(y_true, y_pred, multioutput=[0.3, 0.7])
    ... # doctest: +ELLIPSIS
    0.824...

    """
    y_type, y_true, y_pred, multioutput = _check_reg_targets(
        y_true, y_pred, multioutput)
    output_errors = np.average((y_true - y_pred) ** 2, axis=0,
                               weights=sample_weight)
    if multioutput == 'raw_values':
        return output_errors
    elif multioutput == 'uniform_average':
        # pass None as weights to np.average: uniform mean
        multioutput = None

    return np.average(output_errors, weights=multioutput)

def median_absolute_error(y_true, y_pred):
    """Median absolute error regression loss

    Read more in the :ref:`User Guide <median_absolute_error>`.

    Parameters
    ----------
    y_true : array-like of shape = (n_samples)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples)
        Estimated target values.

    Returns
    -------
    loss : float
        A positive floating point value (the best value is 0.0).

    Examples
    --------
    >>> from sklearn.metrics import median_absolute_error
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> median_absolute_error(y_true, y_pred)
    0.5

    """
    y_type, y_true, y_pred, _ = _check_reg_targets(y_true, y_pred,
                                                   'uniform_average')
    if y_type == 'continuous-multioutput':
        raise ValueError("Multioutput not supported in median_absolute_error")
    return np.median(np.abs(y_pred - y_true))

def explained_variance_score(y_true, y_pred,
                             sample_weight=None,
                             multioutput='uniform_average'):
    """Explained variance regression score function

    Best possible score is 1.0, lower values are worse.

    Read more in the :ref:`User Guide <explained_variance_score>`.

    Parameters
    ----------
    y_true : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Estimated target values.

    sample_weight : array-like of shape = (n_samples), optional
        Sample weights.

    multioutput : string in ['raw_values', 'uniform_average', \
                'variance_weighted'] or array-like of shape (n_outputs)
        Defines aggregating of multiple output scores.
        Array-like value defines weights used to average scores.

        'raw_values' :
            Returns a full set of scores in case of multioutput input.

        'uniform_average' :
            Scores of all outputs are averaged with uniform weight.

        'variance_weighted' :
            Scores of all outputs are averaged, weighted by the variances
            of each individual output.

    Returns
    -------
    score : float or ndarray of floats
        The explained variance or ndarray if 'multioutput' is 'raw_values'.

    Notes
    -----
    This is not a symmetric function.

    Examples
    --------
    >>> from sklearn.metrics import explained_variance_score
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> explained_variance_score(y_true, y_pred)  # doctest: +ELLIPSIS
    0.957...
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> explained_variance_score(y_true, y_pred, multioutput='uniform_average')
    ... # doctest: +ELLIPSIS
    0.983...

    """
    y_type, y_true, y_pred, multioutput = _check_reg_targets(
        y_true, y_pred, multioutput)

    y_diff_avg = np.average(y_true - y_pred, weights=sample_weight, axis=0)
    numerator = np.average((y_true - y_pred - y_diff_avg) ** 2,
                           weights=sample_weight, axis=0)

    y_true_avg = np.average(y_true, weights=sample_weight, axis=0)
    denominator = np.average((y_true - y_true_avg) ** 2,
                             weights=sample_weight, axis=0)

    nonzero_numerator = numerator != 0
    nonzero_denominator = denominator != 0
    valid_score = nonzero_numerator & nonzero_denominator
    output_scores = np.ones(y_true.shape[1])

    output_scores[valid_score] = 1 - (numerator[valid_score] /
                                      denominator[valid_score])
    output_scores[nonzero_numerator & ~nonzero_denominator] = 0.
    if multioutput == 'raw_values':
        # return scores individually
        return output_scores
    elif multioutput == 'uniform_average':
        # passing to np.average() None as weights results is uniform mean
        avg_weights = None
    elif multioutput == 'variance_weighted':
        avg_weights = denominator
    else:
        avg_weights = multioutput

    return np.average(output_scores, weights=avg_weights)

def r2_score(y_true, y_pred,
             sample_weight=None,
             multioutput=None):
    """R^2 (coefficient of determination) regression score function.

    Best possible score is 1.0, lower values are worse.

    Read more in the :ref:`User Guide <r2_score>`.

    Parameters
    ----------
    y_true : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Ground truth (correct) target values.

    y_pred : array-like of shape = (n_samples) or (n_samples, n_outputs)
        Estimated target values.

    sample_weight : array-like of shape = (n_samples), optional
        Sample weights.

    multioutput : string in ['raw_values', 'uniform_average',
                'variance_weighted'] or None or array-like of shape (n_outputs)
        Defines aggregating of multiple output scores.
        Array-like value defines weights used to average scores.
        Default value correponds to 'variance_weighted', but
        will be changed to 'uniform_average' in next versions.

        'raw_values' :
            Returns a full set of scores in case of multioutput input.

        'uniform_average' :
            Scores of all outputs are averaged with uniform weight.

        'variance_weighted' :
            Scores of all outputs are averaged, weighted by the variances
            of each individual output.

    Returns
    -------
    z : float or ndarray of floats
        The R^2 score or ndarray of scores if 'multioutput' is
        'raw_values'.

    Notes
    -----
    This is not a symmetric function.

    Unlike most other scores, R^2 score may be negative (it need not actually
    be the square of a quantity R).

    References
    ----------
    .. [1] `Wikipedia entry on the Coefficient of determination
            <http://en.wikipedia.org/wiki/Coefficient_of_determination>`_

    Examples
    --------
    >>> from sklearn.metrics import r2_score
    >>> y_true = [3, -0.5, 2, 7]
    >>> y_pred = [2.5, 0.0, 2, 8]
    >>> r2_score(y_true, y_pred)  # doctest: +ELLIPSIS
    0.948...
    >>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
    >>> y_pred = [[0, 2], [-1, 2], [8, -5]]
    >>> r2_score(y_true, y_pred, multioutput='variance_weighted')  # doctest: +ELLIPSIS
    0.938...

    """
    y_type, y_true, y_pred, multioutput = _check_reg_targets(
        y_true, y_pred, multioutput)

    if sample_weight is not None:
        sample_weight = column_or_1d(sample_weight)
        weight = sample_weight[:, np.newaxis]
    else:
        weight = 1.

    numerator = (weight * (y_true - y_pred) ** 2).sum(axis=0,
                                                      dtype=np.float64)
    denominator = (weight * (y_true - np.average(
        y_true, axis=0, weights=sample_weight)) ** 2).sum(axis=0,
                                                          dtype=np.float64)
    nonzero_denominator = denominator != 0
    nonzero_numerator = numerator != 0
    valid_score = nonzero_denominator & nonzero_numerator
    output_scores = np.ones([y_true.shape[1]])
    output_scores[valid_score] = 1 - (numerator[valid_score] /
                                      denominator[valid_score])
    # arbitrary set to zero to avoid -inf scores, having a constant
    # y_true is not interesting for scoring a regression anyway
    output_scores[nonzero_numerator & ~nonzero_denominator] = 0.
    if multioutput is None and y_true.shape[1] != 1:
        # @FIXME change in 0.18
        warnings.warn("Default 'multioutput' behavior now corresponds to "
                      "'variance_weighted' value, it will be changed "
                      "to 'uniform_average' in 0.18.",
                      DeprecationWarning)
        multioutput = 'variance_weighted'
    if multioutput == 'raw_values':
        # return scores individually
        return output_scores
    elif multioutput == 'uniform_average':
        # passing None as weights results is uniform mean
        avg_weights = None
    elif multioutput == 'variance_weighted':
        avg_weights = denominator
        # avoid fail on constant y or one-element arrays
        if not np.any(nonzero_denominator):
            if not np.any(nonzero_numerator):
                return 1.0
            else:
                return 0.0
    else:
        avg_weights = multioutput

    return np.average(output_scores, weights=avg_weights)


# Author: Vlad Niculae
# License: BSD 3 clause

import sys

import numpy as np

from sklearn.utils.testing import assert_array_almost_equal
from sklearn.utils.testing import assert_equal
from sklearn.utils.testing import assert_array_equal
from sklearn.utils.testing import SkipTest
from sklearn.utils.testing import assert_true
from sklearn.utils.testing import assert_false
from sklearn.utils.testing import if_safe_multiprocessing_with_blas

from sklearn.decomposition import SparsePCA, MiniBatchSparsePCA
from sklearn.utils import check_random_state

def generate_toy_data(n_components, n_samples, image_size, random_state=None):
    n_features = image_size[0] * image_size[1]

    rng = check_random_state(random_state)
    U = rng.randn(n_samples, n_components)
    V = rng.randn(n_components, n_features)

    centers = [(3, 3), (6, 7), (8, 1)]
    sz = [1, 2, 1]
    for k in range(n_components):
        img = np.zeros(image_size)
        xmin, xmax = centers[k][0] - sz[k], centers[k][0] + sz[k]
        ymin, ymax = centers[k][1] - sz[k], centers[k][1] + sz[k]
        img[xmin:xmax][:, ymin:ymax] = 1.0
        V[k, :] = img.ravel()

    # Y is defined by : Y = UV + noise
    Y = np.dot(U, V)
    Y += 0.1 * rng.randn(Y.shape[0], Y.shape[1])  # Add noise
    return Y, U, V

# SparsePCA can be a bit slow. To avoid having test times go up, we
# test different aspects of the code in the same test

def test_correct_shapes():
    rng = np.random.RandomState(0)
    X = rng.randn(12, 10)
    spca = SparsePCA(n_components=8, random_state=rng)
    U = spca.fit_transform(X)
    assert_equal(spca.components_.shape, (8, 10))
    assert_equal(U.shape, (12, 8))
    # test overcomplete decomposition
    spca = SparsePCA(n_components=13, random_state=rng)
    U = spca.fit_transform(X)
    assert_equal(spca.components_.shape, (13, 10))
    assert_equal(U.shape, (12, 13))

def test_fit_transform():
    alpha = 1
    rng = np.random.RandomState(0)
    Y, _, _ = generate_toy_data(3, 10, (8, 8), random_state=rng)  # wide array
    spca_lars = SparsePCA(n_components=3, method='lars', alpha=alpha,
                          random_state=0)
    spca_lars.fit(Y)

    # Test that CD gives similar results
    spca_lasso = SparsePCA(n_components=3, method='cd', random_state=0,
                           alpha=alpha)
    spca_lasso.fit(Y)
    assert_array_almost_equal(spca_lasso.components_, spca_lars.components_)

@if_safe_multiprocessing_with_blas
def test_fit_transform_parallel():
    alpha = 1
    rng = np.random.RandomState(0)
    Y, _, _ = generate_toy_data(3, 10, (8, 8), random_state=rng)  # wide array
    spca_lars = SparsePCA(n_components=3, method='lars', alpha=alpha,
                          random_state=0)
    spca_lars.fit(Y)
    U1 = spca_lars.transform(Y)
    # Test multiple CPUs
    spca = SparsePCA(n_components=3, n_jobs=2, method='lars', alpha=alpha,
                     random_state=0).fit(Y)
    U2 = spca.transform(Y)
    assert_true(not np.all(spca_lars.components_ == 0))
    assert_array_almost_equal(U1, U2)

def test_transform_nan():
    # Test that SparsePCA won't return NaN when there is 0 feature in all
    # samples.
    rng = np.random.RandomState(0)
    Y, _, _ = generate_toy_data(3, 10, (8, 8), random_state=rng)  # wide array
    Y[:, 0] = 0
    estimator = SparsePCA(n_components=8)
    assert_false(np.any(np.isnan(estimator.fit_transform(Y))))

def test_fit_transform_tall():
    rng = np.random.RandomState(0)
    Y, _, _ = generate_toy_data(3, 65, (8, 8), random_state=rng)  # tall array
    spca_lars = SparsePCA(n_components=3, method='lars',
                          random_state=rng)
    U1 = spca_lars.fit_transform(Y)
    spca_lasso = SparsePCA(n_components=3, method='cd', random_state=rng)
    U2 = spca_lasso.fit(Y).transform(Y)
    assert_array_almost_equal(U1, U2)

def test_initialization():
    rng = np.random.RandomState(0)
    U_init = rng.randn(5, 3)
    V_init = rng.randn(3, 4)
    model = SparsePCA(n_components=3, U_init=U_init, V_init=V_init, max_iter=0,
                      random_state=rng)
    model.fit(rng.randn(5, 4))
    assert_array_equal(model.components_, V_init)

def test_mini_batch_correct_shapes():
    rng = np.random.RandomState(0)
    X = rng.randn(12, 10)
    pca = MiniBatchSparsePCA(n_components=8, random_state=rng)
    U = pca.fit_transform(X)
    assert_equal(pca.components_.shape, (8, 10))
    assert_equal(U.shape, (12, 8))
    # test overcomplete decomposition
    pca = MiniBatchSparsePCA(n_components=13, random_state=rng)
    U = pca.fit_transform(X)
    assert_equal(pca.components_.shape, (13, 10))
    assert_equal(U.shape, (12, 13))

def test_mini_batch_fit_transform():
    raise SkipTest("skipping mini_batch_fit_transform.")
    alpha = 1
    rng = np.random.RandomState(0)
    Y, _, _ = generate_toy_data(3, 10, (8, 8), random_state=rng)  # wide array
    spca_lars = MiniBatchSparsePCA(n_components=3, random_state=0,
                                   alpha=alpha).fit(Y)
    U1 = spca_lars.transform(Y)
    # Test multiple CPUs
    if sys.platform == 'win32':  # fake parallelism for win32
        import sklearn.externals.joblib.parallel as joblib_par
        _mp = joblib_par.multiprocessing
        joblib_par.multiprocessing = None
        try:
            U2 = MiniBatchSparsePCA(n_components=3, n_jobs=2, alpha=alpha,
                                    random_state=0).fit(Y).transform(Y)
        finally:
            joblib_par.multiprocessing = _mp
    else:  # we can efficiently use parallelism
        U2 = MiniBatchSparsePCA(n_components=3, n_jobs=2, alpha=alpha,
                                random_state=0).fit(Y).transform(Y)
    assert_true(not np.all(spca_lars.components_ == 0))
    assert_array_almost_equal(U1, U2)
    # Test that CD gives similar results
    spca_lasso = MiniBatchSparsePCA(n_components=3, method='cd', alpha=alpha,
                                    random_state=0).fit(Y)
    assert_array_almost_equal(spca_lasso.components_, spca_lars.components_)


import pandas as pd
from pandas import DataFrame, merge_ordered
from pandas.util import testing as tm
from pandas.util.testing import assert_frame_equal

from numpy import nan

class TestMergeOrdered(object):

    def setup_method(self, method):
        self.left = DataFrame({'key': ['a', 'c', 'e'],
                               'lvalue': [1, 2., 3]})

        self.right = DataFrame({'key': ['b', 'c', 'd', 'f'],
                                'rvalue': [1, 2, 3., 4]})

    def test_basic(self):
        result = merge_ordered(self.left, self.right, on='key')
        expected = DataFrame({'key': ['a', 'b', 'c', 'd', 'e', 'f'],
                              'lvalue': [1, nan, 2, nan, 3, nan],
                              'rvalue': [nan, 1, 2, 3, nan, 4]})

        assert_frame_equal(result, expected)

    def test_ffill(self):
        result = merge_ordered(
            self.left, self.right, on='key', fill_method='ffill')
        expected = DataFrame({'key': ['a', 'b', 'c', 'd', 'e', 'f'],
                              'lvalue': [1., 1, 2, 2, 3, 3.],
                              'rvalue': [nan, 1, 2, 3, 3, 4]})
        assert_frame_equal(result, expected)

    def test_multigroup(self):
        left = pd.concat([self.left, self.left], ignore_index=True)

        left['group'] = ['a'] * 3 + ['b'] * 3

        result = merge_ordered(left, self.right, on='key', left_by='group',
                               fill_method='ffill')
        expected = DataFrame({'key': ['a', 'b', 'c', 'd', 'e', 'f'] * 2,
                              'lvalue': [1., 1, 2, 2, 3, 3.] * 2,
                              'rvalue': [nan, 1, 2, 3, 3, 4] * 2})
        expected['group'] = ['a'] * 6 + ['b'] * 6

        assert_frame_equal(result, expected.loc[:, result.columns])

        result2 = merge_ordered(self.right, left, on='key', right_by='group',
                                fill_method='ffill')
        assert_frame_equal(result, result2.loc[:, result.columns])

        result = merge_ordered(left, self.right, on='key', left_by='group')
        assert result['group'].notna().all()

    def test_merge_type(self):
        class NotADataFrame(DataFrame):

            @property
            def _constructor(self):
                return NotADataFrame

        nad = NotADataFrame(self.left)
        result = nad.merge(self.right, on='key')

        assert isinstance(result, NotADataFrame)

    def test_empty_sequence_concat(self):
        # GH 9157
        empty_pat = "[Nn]o objects"
        none_pat = "objects.*None"
        test_cases = [
            ((), empty_pat),
            ([], empty_pat),
            ({}, empty_pat),
            ([None], none_pat),
            ([None, None], none_pat)
        ]
        for df_seq, pattern in test_cases:
            tm.assert_raises_regex(ValueError, pattern, pd.concat, df_seq)

        pd.concat([pd.DataFrame()])
        pd.concat([None, pd.DataFrame()])
        pd.concat([pd.DataFrame(), None])


"""
==============================================
A demo of the Spectral Co-Clustering algorithm
==============================================

This example demonstrates how to generate a dataset and bicluster it
using the the Spectral Co-Clustering algorithm.

The dataset is generated using the ``make_biclusters`` function, which
creates a matrix of small values and implants bicluster with large
values. The rows and columns are then shuffled and passed to the
Spectral Co-Clustering algorithm. Rearranging the shuffled matrix to
make biclusters contiguous shows how accurately the algorithm found
the biclusters.

"""
print(__doc__)

# Author: Kemal Eren <kemal@kemaleren.com>
# License: BSD 3 clause

import numpy as np
from matplotlib import pyplot as plt

from sklearn.datasets import make_biclusters
from sklearn.datasets import samples_generator as sg
from sklearn.cluster.bicluster import SpectralCoclustering
from sklearn.metrics import consensus_score

data, rows, columns = make_biclusters(
    shape=(300, 300), n_clusters=5, noise=5,
    shuffle=False, random_state=0)

plt.matshow(data, cmap=plt.cm.Blues)
plt.title("Original dataset")

data, row_idx, col_idx = sg._shuffle(data, random_state=0)
plt.matshow(data, cmap=plt.cm.Blues)
plt.title("Shuffled dataset")

model = SpectralCoclustering(n_clusters=5, random_state=0)
model.fit(data)
score = consensus_score(model.biclusters_,
                        (rows[:, row_idx], columns[:, col_idx]))

print("consensus score: {:.3f}".format(score))

fit_data = data[np.argsort(model.row_labels_)]
fit_data = fit_data[:, np.argsort(model.column_labels_)]

plt.matshow(fit_data, cmap=plt.cm.Blues)
plt.title("After biclustering; rearranged to show biclusters")

plt.show()


import matplotlib.pyplot as plt
import scipy.interpolate as scinterp
import numpy as np
import peakfinding
import peak_original
import smoothing
import plotter
import random
import readin
import sys
import os

if __name__== '__main__':
    Mbdata = []
    delM15data = []
    path = "/Users/zaidi/Documents/REU/restframe/"
    filenames = os.listdir(path)
    random.shuffle(filenames)
    for filename in filenames:
        current_file = os.path.join(path, filename)
        data= readin.readin_SNrest(filename)
        indB = np.where((data.band == 'B'))
        Bdata = data[indB]
        Bdata = np.sort(Bdata)
        if len(Bdata.phase) > 3:
            spl = scinterp.UnivariateSpline(Bdata.phase, Bdata.mag)
            spl.set_smoothing_factor(2./len(Bdata.phase))
            phase_new = np.arange(Bdata.phase[0], Bdata.phase[-1], 1)
            mag_new = spl(phase_new)
            maxp, minp = peak_original.peakdet(mag_new, 0.5, phase_new)
            if len(minp) > 0 and minp[0][0] < 5 and minp[0][0] > -5:
                Mb = minp[0][1]
                delM15 = minp[0][1] - spl(minp[0][0]+15)
                Mbdata.append(Mb)
                delM15data.append(delM15)
                if delM15 > 0 or delM15 < -5:
                    print minp
                    print filename
                    print spl(minp[0][0] + 15)
                    fig = plt.figure(1)
                    ax = fig.add_subplot(1,1,1)
                    ax.plot(phase_new, mag_new)
                    ax.plot(Bdata.phase, Bdata.mag)
                    if len(minp) > 0:
                        ax.scatter(minp[:,0],minp[:,1])
                    plt.show(fig)

        '''
        maxp, minp = peakfinding.peakdetect(mag_new, phase_new, 200, 1.5)
        if len(minp) > 0:
            print minp
            print filename
            fig = plt.figure(1)
            ax = fig.add_subplot(1,1,1)
            #ax.scatter(minp[:,0], minp[:,1],'bo')
            #ax.plot(Bdata.phase, Bdata.mag)
            #plt.show(fig)

        '''
        #interp = smoothing.Interpolate1D(data.phase
    print Mbdata
    print delM15data
    fig = plt.figure(2)
    ax = fig.add_subplot(1,1,1)
    ax.scatter(Mbdata, delM15data)
    plt.show(fig)


#!/usr/bin/python
"""code to help run the image-computable version of the model

we're using this primarily to check the effect of vignetting, but this does make our project
image-computable (though it's a linear model and so will fail in some trivial cases)

"""
import itertools
import argparse
import numpy as np
import pandas as pd
import pyrtools as pt
from scipy import interpolate

def upsample(signal, target_shape):
    """upsample a signal to target_shape

    this uses scipy's interpolate.interp2d (and so will end up with a smoothed signal)
    """
    x = np.linspace(-(signal.shape[0]-1)/2, (signal.shape[0]-1)/2, num=signal.shape[0])
    y = np.linspace(-(signal.shape[1]-1)/2, (signal.shape[1]-1)/2, num=signal.shape[1])
    f = interpolate.interp2d(x, y, signal)
    x = np.linspace(-(signal.shape[0]-1)/2, (signal.shape[0]-1)/2, num=target_shape[0])
    y = np.linspace(-(signal.shape[1]-1)/2, (signal.shape[1]-1)/2, num=target_shape[1])
    return f(x,y)

def calc_energy_and_filters(stim, stim_df, n_orientations=6, save_path_template=None):
    """this creates the energy and filter arrays

    We assume the stimuli have natural groups, here indexed by the "class_idx" column in stim_df,
    and all stimuli within these groups should be considered the same stimuli, that is, we sum the
    energy across all of them. for the spatial frequency project, these are the different phases of
    the gratings (because of how we structure our experiment, we estimate a response amplitude to
    all phases together).

    Note that this will take a while to run (~10 or 20 minutes). Since it only needs to run once
    per experiment, didn't bother to make it efficient at all. The outputs will also be very large,
    totalling about 11GB

    Parameters
    ----------
    stim : np.ndarray
        The stimuli to produce energy for. Should have shape (n, *img_size), where n is the number
        of total stimuli.
    stim_df : pd.DataFrame
        The DataFrame describing the stimuli. Must contain the column "class_idx", which indexes
        the different stimulus classes (see above)
    n_orientations : int
        the number of orientations in the steerable pyramid. 6 is the number used to model fMRI
        voxels in Roth, Z. N., Heeger, D., & Merriam, E. (2018). Stimulus vignetting and
        orientation selectivity in human visual cortex. bioRxiv.
    save_path_template : str or None
        the template string for the save path we'll use for energy and filters. should end in .npy
        and contain one %s, which we'll replace with "energy" and "filters".

    Returns
    -------
    energy : np.ndarray
        energy has shape (stim_df.class_idx.nunique(), max_ht, n_orientations, *img_size) and
        contains the energy (square and absolute value the complex valued output of
        SteerablePyramidFreq; equivalently, square and sum the output of the quadrature pair of
        filters that make up the pyramid) for each image, at each scale and orientation. the energy
        has all been upsampled to the size of the initial image.
    filters : np.ndarray
        filters has shape (max_ht, n_orientations, *img_size) and is the fourier transform of the
        filters at each scale and orientation, zero-padded so they all have the same size. we only
        have one set of filters (instead of one per stimulus class) because the same pyramid was
        used for each of them; we ensure this by getting the filters for each stimulus class and
        checking that they're individually equal to the average across classes.

    """
    img_size = stim.shape[1:]
    # this computation comes from the SteerablePyramidFreq code
    max_ht = int(np.floor(np.log2(min(img_size))) - 2)
    energy = np.zeros((stim_df.class_idx.nunique(), max_ht, n_orientations, *img_size),
                      dtype=np.float32)
    filters = np.zeros_like(energy)
    for i, g in stim_df.groupby('class_idx'):
        idx = g.index
        filled_filters = False
        for j in idx:
            pyr = pt.pyramids.SteerablePyramidFreq(stim[j], order=n_orientations-1, is_complex=True)
            for k, l in itertools.product(range(max_ht), range(n_orientations)):
                energy[int(i), k, l, :, :] += upsample(np.abs(pyr.pyr_coeffs[(k, l)])**2, img_size)
                # we only want to run this once per stimulus class
                if not filled_filters:
                    if k > 0:
                        lomask = pyr._lomasks[k-1]
                    else:
                        lomask = pyr._lo0mask
                    filt = pyr._anglemasks[k][l] * pyr._himasks[k] * lomask
                    pad_num = []
                    for m in range(2):
                        pad_num.append([(img_size[m] - filt.shape[m])//2, (img_size[m] - filt.shape[m])//2])
                        if filt.shape[m] + 2*pad_num[m][0] != img_size[m]:
                            pad_num[m][0] += img_size[m] - (filt.shape[m] + 2*pad_num[m][0])
                    filters[int(i), k, l, :, :] = np.pad(filt, pad_num, 'constant', constant_values=0)
            filled_filters = True
    filter_mean = np.mean(filters, 0)
    for i in range(filters.shape[0]):
        if not(np.allclose(filter_mean, filters[i,:,:,:,:])):
            raise Exception("Something has gone terribly wrong, the filters for stim class %d are different than the rest!" % i)
    filters = filter_mean
    if save_path_template is not None:
        np.save(save_path_template % "energy", energy)
        np.save(save_path_template % "filters", filters)
    return energy, filters

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=("Calculate and save the energy for each stimulus class, as well as the Fourier"
                     " transform of the filters of the steerable pyramid we use to get this. For "
                     "use with image-computable version of this model"),
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("stimuli",
                        help=("Path to the stimulus .npy file."))
    parser.add_argument("stimuli_description_df",
                        help=("Path to the stimulus description dataframe .csv file."))
    parser.add_argument("save_path_template",
                        help=("Path template (with .npy extension) where we'll save the results. "
                              "Should contain one %s."))
    parser.add_argument('--n_orientations', '-n', default=6, type=int,
                        help=("The number of orientations in the steerable pyramid used here."))
    args = vars(parser.parse_args())
    stim = np.load(args.pop('stimuli'))
    stim_df = pd.read_csv(args.pop('stimuli_description_df'))
    calc_energy_and_filters(stim, stim_df, **args)


# Author: Lars Buitinck
# License: 3-clause BSD

import numpy as np
from ..base import BaseEstimator
from .base import SelectorMixin
from ..utils import check_array
from ..utils.sparsefuncs import mean_variance_axis
from ..utils.validation import check_is_fitted

class VarianceThreshold(BaseEstimator, SelectorMixin):
    """Feature selector that removes all low-variance features.

    This feature selection algorithm looks only at the features (X), not the
    desired outputs (y), and can thus be used for unsupervised learning.

    Read more in the :ref:`User Guide <variance_threshold>`.

    Parameters
    ----------
    threshold : float, optional
        Features with a training-set variance lower than this threshold will
        be removed. The default is to keep all features with non-zero variance,
        i.e. remove the features that have the same value in all samples.

    Attributes
    ----------
    variances_ : array, shape (n_features,)
        Variances of individual features.

    Examples
    --------
    The following dataset has integer features, two of which are the same
    in every sample. These are removed with the default setting for threshold::

        >>> X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
        >>> selector = VarianceThreshold()
        >>> selector.fit_transform(X)
        array([[2, 0],
               [1, 4],
               [1, 1]])
    """

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

    def fit(self, X, y=None):
        """Learn empirical variances from X.

        Parameters
        ----------
        X : {array-like, sparse matrix}, shape (n_samples, n_features)
            Sample vectors from which to compute variances.

        y : any
            Ignored. This parameter exists only for compatibility with
            sklearn.pipeline.Pipeline.

        Returns
        -------
        self
        """
        X = check_array(X, ('csr', 'csc'), dtype=np.float64)

        if hasattr(X, "toarray"):   # sparse matrix
            _, self.variances_ = mean_variance_axis(X, axis=0)
        else:
            self.variances_ = np.var(X, axis=0)

        if np.all(self.variances_ <= self.threshold):
            msg = "No feature in X meets the variance threshold {0:.5f}"
            if X.shape[0] == 1:
                msg += " (X contains only one sample)"
            raise ValueError(msg.format(self.threshold))

        return self

    def _get_support_mask(self):
        check_is_fitted(self, 'variances_')

        return self.variances_ > self.threshold


import numpy as np
import pandas as pd
from pandas import DataFrame
from pandas.compat import u
import pandas.io.formats.format as fmt
from pandas.util import testing as tm

class TestEngFormatter(object):

    def test_eng_float_formatter(self):
        df = DataFrame({'A': [1.41, 141., 14100, 1410000.]})

        fmt.set_eng_float_format()
        result = df.to_string()
        expected = ('             A\n'
                    '0    1.410E+00\n'
                    '1  141.000E+00\n'
                    '2   14.100E+03\n'
                    '3    1.410E+06')
        assert result == expected

        fmt.set_eng_float_format(use_eng_prefix=True)
        result = df.to_string()
        expected = ('         A\n'
                    '0    1.410\n'
                    '1  141.000\n'
                    '2  14.100k\n'
                    '3   1.410M')
        assert result == expected

        fmt.set_eng_float_format(accuracy=0)
        result = df.to_string()
        expected = ('         A\n'
                    '0    1E+00\n'
                    '1  141E+00\n'
                    '2   14E+03\n'
                    '3    1E+06')
        assert result == expected

        tm.reset_display_options()

    def compare(self, formatter, input, output):
        formatted_input = formatter(input)
        assert formatted_input == output

    def compare_all(self, formatter, in_out):
        """
        Parameters:
        -----------
        formatter: EngFormatter under test
        in_out: list of tuples. Each tuple = (number, expected_formatting)

        It is tested if 'formatter(number) == expected_formatting'.
        *number* should be >= 0 because formatter(-number) == fmt is also
        tested. *fmt* is derived from *expected_formatting*
        """
        for input, output in in_out:
            self.compare(formatter, input, output)
            self.compare(formatter, -input, "-" + output[1:])

    def test_exponents_with_eng_prefix(self):
        formatter = fmt.EngFormatter(accuracy=3, use_eng_prefix=True)
        f = np.sqrt(2)
        in_out = [
            (f * 10 ** -24, " 1.414y"), (f * 10 ** -23, " 14.142y"),
            (f * 10 ** -22, " 141.421y"), (f * 10 ** -21, " 1.414z"),
            (f * 10 ** -20, " 14.142z"), (f * 10 ** -19, " 141.421z"),
            (f * 10 ** -18, " 1.414a"), (f * 10 ** -17, " 14.142a"),
            (f * 10 ** -16, " 141.421a"), (f * 10 ** -15, " 1.414f"),
            (f * 10 ** -14, " 14.142f"), (f * 10 ** -13, " 141.421f"),
            (f * 10 ** -12, " 1.414p"), (f * 10 ** -11, " 14.142p"),
            (f * 10 ** -10, " 141.421p"), (f * 10 ** -9, " 1.414n"),
            (f * 10 ** -8, " 14.142n"), (f * 10 ** -7, " 141.421n"),
            (f * 10 ** -6, " 1.414u"), (f * 10 ** -5, " 14.142u"),
            (f * 10 ** -4, " 141.421u"), (f * 10 ** -3, " 1.414m"),
            (f * 10 ** -2, " 14.142m"), (f * 10 ** -1, " 141.421m"),
            (f * 10 ** 0, " 1.414"), (f * 10 ** 1, " 14.142"),
            (f * 10 ** 2, " 141.421"), (f * 10 ** 3, " 1.414k"),
            (f * 10 ** 4, " 14.142k"), (f * 10 ** 5, " 141.421k"),
            (f * 10 ** 6, " 1.414M"), (f * 10 ** 7, " 14.142M"),
            (f * 10 ** 8, " 141.421M"), (f * 10 ** 9, " 1.414G"),
            (f * 10 ** 10, " 14.142G"), (f * 10 ** 11, " 141.421G"),
            (f * 10 ** 12, " 1.414T"), (f * 10 ** 13, " 14.142T"),
            (f * 10 ** 14, " 141.421T"), (f * 10 ** 15, " 1.414P"),
            (f * 10 ** 16, " 14.142P"), (f * 10 ** 17, " 141.421P"),
            (f * 10 ** 18, " 1.414E"), (f * 10 ** 19, " 14.142E"),
            (f * 10 ** 20, " 141.421E"), (f * 10 ** 21, " 1.414Z"),
            (f * 10 ** 22, " 14.142Z"), (f * 10 ** 23, " 141.421Z"),
            (f * 10 ** 24, " 1.414Y"), (f * 10 ** 25, " 14.142Y"),
            (f * 10 ** 26, " 141.421Y")]
        self.compare_all(formatter, in_out)

    def test_exponents_without_eng_prefix(self):
        formatter = fmt.EngFormatter(accuracy=4, use_eng_prefix=False)
        f = np.pi
        in_out = [
            (f * 10 ** -24, " 3.1416E-24"),
            (f * 10 ** -23, " 31.4159E-24"),
            (f * 10 ** -22, " 314.1593E-24"),
            (f * 10 ** -21, " 3.1416E-21"),
            (f * 10 ** -20, " 31.4159E-21"),
            (f * 10 ** -19, " 314.1593E-21"),
            (f * 10 ** -18, " 3.1416E-18"),
            (f * 10 ** -17, " 31.4159E-18"),
            (f * 10 ** -16, " 314.1593E-18"),
            (f * 10 ** -15, " 3.1416E-15"),
            (f * 10 ** -14, " 31.4159E-15"),
            (f * 10 ** -13, " 314.1593E-15"),
            (f * 10 ** -12, " 3.1416E-12"),
            (f * 10 ** -11, " 31.4159E-12"),
            (f * 10 ** -10, " 314.1593E-12"),
            (f * 10 ** -9, " 3.1416E-09"),
            (f * 10 ** -8, " 31.4159E-09"),
            (f * 10 ** -7, " 314.1593E-09"),
            (f * 10 ** -6, " 3.1416E-06"),
            (f * 10 ** -5, " 31.4159E-06"),
            (f * 10 ** -4, " 314.1593E-06"),
            (f * 10 ** -3, " 3.1416E-03"),
            (f * 10 ** -2, " 31.4159E-03"),
            (f * 10 ** -1, " 314.1593E-03"),
            (f * 10 ** 0, " 3.1416E+00"),
            (f * 10 ** 1, " 31.4159E+00"),
            (f * 10 ** 2, " 314.1593E+00"),
            (f * 10 ** 3, " 3.1416E+03"),
            (f * 10 ** 4, " 31.4159E+03"),
            (f * 10 ** 5, " 314.1593E+03"),
            (f * 10 ** 6, " 3.1416E+06"),
            (f * 10 ** 7, " 31.4159E+06"),
            (f * 10 ** 8, " 314.1593E+06"),
            (f * 10 ** 9, " 3.1416E+09"),
            (f * 10 ** 10, " 31.4159E+09"),
            (f * 10 ** 11, " 314.1593E+09"),
            (f * 10 ** 12, " 3.1416E+12"),
            (f * 10 ** 13, " 31.4159E+12"),
            (f * 10 ** 14, " 314.1593E+12"),
            (f * 10 ** 15, " 3.1416E+15"),
            (f * 10 ** 16, " 31.4159E+15"),
            (f * 10 ** 17, " 314.1593E+15"),
            (f * 10 ** 18, " 3.1416E+18"),
            (f * 10 ** 19, " 31.4159E+18"),
            (f * 10 ** 20, " 314.1593E+18"),
            (f * 10 ** 21, " 3.1416E+21"),
            (f * 10 ** 22, " 31.4159E+21"),
            (f * 10 ** 23, " 314.1593E+21"),
            (f * 10 ** 24, " 3.1416E+24"),
            (f * 10 ** 25, " 31.4159E+24"),
            (f * 10 ** 26, " 314.1593E+24")]
        self.compare_all(formatter, in_out)

    def test_rounding(self):
        formatter = fmt.EngFormatter(accuracy=3, use_eng_prefix=True)
        in_out = [(5.55555, ' 5.556'), (55.5555, ' 55.556'),
                  (555.555, ' 555.555'), (5555.55, ' 5.556k'),
                  (55555.5, ' 55.556k'), (555555, ' 555.555k')]
        self.compare_all(formatter, in_out)

        formatter = fmt.EngFormatter(accuracy=1, use_eng_prefix=True)
        in_out = [(5.55555, ' 5.6'), (55.5555, ' 55.6'), (555.555, ' 555.6'),
                  (5555.55, ' 5.6k'), (55555.5, ' 55.6k'), (555555, ' 555.6k')]
        self.compare_all(formatter, in_out)

        formatter = fmt.EngFormatter(accuracy=0, use_eng_prefix=True)
        in_out = [(5.55555, ' 6'), (55.5555, ' 56'), (555.555, ' 556'),
                  (5555.55, ' 6k'), (55555.5, ' 56k'), (555555, ' 556k')]
        self.compare_all(formatter, in_out)

        formatter = fmt.EngFormatter(accuracy=3, use_eng_prefix=True)
        result = formatter(0)
        assert result == u(' 0.000')

    def test_nan(self):
        # Issue #11981

        formatter = fmt.EngFormatter(accuracy=1, use_eng_prefix=True)
        result = formatter(np.nan)
        assert result == u('NaN')

        df = pd.DataFrame({'a': [1.5, 10.3, 20.5],
                           'b': [50.3, 60.67, 70.12],
                           'c': [100.2, 101.33, 120.33]})
        pt = df.pivot_table(values='a', index='b', columns='c')
        fmt.set_eng_float_format(accuracy=1)
        result = pt.to_string()
        assert 'NaN' in result
        tm.reset_display_options()

    def test_inf(self):
        # Issue #11981

        formatter = fmt.EngFormatter(accuracy=1, use_eng_prefix=True)
        result = formatter(np.inf)
        assert result == u('inf')