# Path: cotede/qctests/gradient.py
# def curvature(x):
#     """Curvature of a timeseries
# 
#     This test is commonly known as gradient for historical reasons, but that
#     is a bad name choice since it is not the actual gradient, like:
#     d/dx + d/dy + d/dz,
#     but as defined by GTSPP, EuroGOOS and others, which is actually the
#     curvature of the timeseries..
# 
#     Note
#     ----
#     - Pandas.Series operates with indexes, so it should be done different. In
#       that case, call for _curvature_pandas.
#     """
#     if isinstance(x, ma.MaskedArray):
#         x[x.mask] = np.nan
#         x = x.data
# 
#     if PANDAS_AVAILABLE and isinstance(x, pd.Series):
#         return _curvature_pandas(x)
# 
#     x = np.atleast_1d(x)
#     y = np.nan * x
#     y[1:-1] = x[1:-1] - (x[:-2] + x[2:]) / 2.0
#     return y
# 
# def _curvature_pandas(x):
#     """Equivalent to curvature() but using pandas
# 
#     It looks like the numpy implementation is faster even for larger datasets,
#     so the default is with numpy.
# 
#     Note
#     ----
#     - In the future this will be useful to handle specific window widths.
#     """
#     if isinstance(x, ma.MaskedArray):
#         x[x.mask] = np.nan
#         x = x.data
# 
#     if not PANDAS_AVAILABLE:
#         return curvature(x)
# 
#     if hasattr(x, "to_series"):
#         x = x.to_series()
#     elif not isinstance(x, pd.Series):
#         x = pd.Series(x)
# 
#     y = np.nan * x
#     y = x - (x.shift(1) + x.shift(-1)) / 2.0
#     return np.array(y)
# 
# Path: cotede/qctests/gradient.py
# class Gradient(QCCheckVar):
#     def set_features(self):
#         self.features = {"gradient": curvature(self.data[self.varname])}
# 
#     def test(self):
#         self.flags = {}
#         try:
#             threshold = self.cfg["threshold"]
#         except KeyError:
#             module_logger.debug(
#                 "Deprecated cfg format. It should contain a threshold item."
#             )
#             threshold = self.cfg
# 
#         assert (
#             (np.size(threshold) == 1)
#             and (threshold is not None)
#             and (np.isfinite(threshold))
#         )
# 
#         flag = np.zeros(np.shape(self.data[self.varname]), dtype="i1")
#         feature = np.absolute(self.features["gradient"])
#         flag[feature > threshold] = self.flag_bad
#         flag[feature <= threshold] = self.flag_good
#         x = np.atleast_1d(self.data[self.varname])
#         flag[ma.getmaskarray(x) | ~np.isfinite(x)] = 9
#         self.flags["gradient"] = flag
# 
# Path: tests/data.py
# class DummyData(object):
#     def __init__(self):
#         self.attrs = {
#                 'datetime': datetime(2016,6,4),
#                 'LATITUDE': 15, 'LONGITUDE': -38}
#         self.data = {
#                 'PRES': ma.fix_invalid(
#                     [2, 6, 10, 21, 44, 79, 100, 150,
#                         200, 400, 410, 650, 1000, 2000, 5000]),
#                 'TEMP': ma.fix_invalid(
#                     [25.32, 25.34, 25.34, 25.31, 24.99, 23.46, 21.85, 17.95,
#                         15.39, 11.08, 6.93, 7.93, 5.71, 3.58, np.nan]),
#                 'PSAL': ma.fix_invalid(
#                     [36.49, 36.51, 36.52, 36.53, 36.59, 36.76, 36.81, 36.39,
#                         35.98, 35.30, 35.28, 34.93, 34.86, np.nan, np.nan])}
# 
#     def __getitem__(self, key):
#         return self.data[key]
# 
#     def keys(self):
#         return self.data.keys()
# 
#     @property
#     def attributes(self):
#         print('attributes will be removed. Use attrs instead!')
#         return self.attrs
# 
# Path: tests/qctests/compare.py
# def compare_feature_input_types(feature, *args, **kwargs):
#     compare_feature_tuple(feature, *args, **kwargs)
#     compare_feature_series(feature, *args, **kwargs)
#     compare_feature_dataarray(feature, *args, **kwargs)
# 
# def compare_input_types(Procedure, cfg):
#     compare_tuple(Procedure, cfg)
#     compare_pandas(Procedure, cfg)
#     compare_xarray(Procedure, cfg)


import numpy as np
from numpy import ma
from cotede.qctests.gradient import curvature, _curvature_pandas
from cotede.qctests import Gradient
from ..data import DummyData
from .compare import compare_feature_input_types, compare_input_types
                0.015,
                0.145,
                0.605,
                0.04,
                1.145,
                -0.67,
                0.875,
                -0.08,
                -2.575,
                1.61,
                -0.045,
                np.nan,
                np.nan,
            ]
        )
    }
    flags = {"gradient": [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 0, 9]}

    cfg = {"threshold": 1.5}

    y = Gradient(profile, "TEMP", cfg)

    for f in features:
        assert np.allclose(y.features[f], features[f], equal_nan=True)
    for f in flags:
        assert np.allclose(y.flags[f], flags[f], equal_nan=True)


def test_input_types():
    cfg = {"threshold": 4}

# Path: cotede/qctests/gradient.py
# def curvature(x):
#     """Curvature of a timeseries
# 
#     This test is commonly known as gradient for historical reasons, but that
#     is a bad name choice since it is not the actual gradient, like:
#     d/dx + d/dy + d/dz,
#     but as defined by GTSPP, EuroGOOS and others, which is actually the
#     curvature of the timeseries..
# 
#     Note
#     ----
#     - Pandas.Series operates with indexes, so it should be done different. In
#       that case, call for _curvature_pandas.
#     """
#     if isinstance(x, ma.MaskedArray):
#         x[x.mask] = np.nan
#         x = x.data
# 
#     if PANDAS_AVAILABLE and isinstance(x, pd.Series):
#         return _curvature_pandas(x)
# 
#     x = np.atleast_1d(x)
#     y = np.nan * x
#     y[1:-1] = x[1:-1] - (x[:-2] + x[2:]) / 2.0
#     return y
# 
# def _curvature_pandas(x):
#     """Equivalent to curvature() but using pandas
# 
#     It looks like the numpy implementation is faster even for larger datasets,
#     so the default is with numpy.
# 
#     Note
#     ----
#     - In the future this will be useful to handle specific window widths.
#     """
#     if isinstance(x, ma.MaskedArray):
#         x[x.mask] = np.nan
#         x = x.data
# 
#     if not PANDAS_AVAILABLE:
#         return curvature(x)
# 
#     if hasattr(x, "to_series"):
#         x = x.to_series()
#     elif not isinstance(x, pd.Series):
#         x = pd.Series(x)
# 
#     y = np.nan * x
#     y = x - (x.shift(1) + x.shift(-1)) / 2.0
#     return np.array(y)
# 
# Path: cotede/qctests/gradient.py
# class Gradient(QCCheckVar):
#     def set_features(self):
#         self.features = {"gradient": curvature(self.data[self.varname])}
# 
#     def test(self):
#         self.flags = {}
#         try:
#             threshold = self.cfg["threshold"]
#         except KeyError:
#             module_logger.debug(
#                 "Deprecated cfg format. It should contain a threshold item."
#             )
#             threshold = self.cfg
# 
#         assert (
#             (np.size(threshold) == 1)
#             and (threshold is not None)
#             and (np.isfinite(threshold))
#         )
# 
#         flag = np.zeros(np.shape(self.data[self.varname]), dtype="i1")
#         feature = np.absolute(self.features["gradient"])
#         flag[feature > threshold] = self.flag_bad
#         flag[feature <= threshold] = self.flag_good
#         x = np.atleast_1d(self.data[self.varname])
#         flag[ma.getmaskarray(x) | ~np.isfinite(x)] = 9
#         self.flags["gradient"] = flag
# 
# Path: tests/data.py
# class DummyData(object):
#     def __init__(self):
#         self.attrs = {
#                 'datetime': datetime(2016,6,4),
#                 'LATITUDE': 15, 'LONGITUDE': -38}
#         self.data = {
#                 'PRES': ma.fix_invalid(
#                     [2, 6, 10, 21, 44, 79, 100, 150,
#                         200, 400, 410, 650, 1000, 2000, 5000]),
#                 'TEMP': ma.fix_invalid(
#                     [25.32, 25.34, 25.34, 25.31, 24.99, 23.46, 21.85, 17.95,
#                         15.39, 11.08, 6.93, 7.93, 5.71, 3.58, np.nan]),
#                 'PSAL': ma.fix_invalid(
#                     [36.49, 36.51, 36.52, 36.53, 36.59, 36.76, 36.81, 36.39,
#                         35.98, 35.30, 35.28, 34.93, 34.86, np.nan, np.nan])}
# 
#     def __getitem__(self, key):
#         return self.data[key]
# 
#     def keys(self):
#         return self.data.keys()
# 
#     @property
#     def attributes(self):
#         print('attributes will be removed. Use attrs instead!')
#         return self.attrs
# 
# Path: tests/qctests/compare.py
# def compare_feature_input_types(feature, *args, **kwargs):
#     compare_feature_tuple(feature, *args, **kwargs)
#     compare_feature_series(feature, *args, **kwargs)
#     compare_feature_dataarray(feature, *args, **kwargs)
# 
# def compare_input_types(Procedure, cfg):
#     compare_tuple(Procedure, cfg)
#     compare_pandas(Procedure, cfg)
#     compare_xarray(Procedure, cfg)


# Path: tests/qctests/test_qc_gradient.py
import numpy as np
from numpy import ma
from cotede.qctests.gradient import curvature, _curvature_pandas
from cotede.qctests import Gradient
from ..data import DummyData
from .compare import compare_feature_input_types, compare_input_types

                0.015,
                0.145,
                0.605,
                0.04,
                1.145,
                -0.67,
                0.875,
                -0.08,
                -2.575,
                1.61,
                -0.045,
                np.nan,
                np.nan,
            ]
        )
    }
    flags = {"gradient": [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 0, 9]}

    cfg = {"threshold": 1.5}

    y = Gradient(profile, "TEMP", cfg)

    for f in features:
        assert np.allclose(y.features[f], features[f], equal_nan=True)
    for f in flags:
        assert np.allclose(y.flags[f], flags[f], equal_nan=True)


def test_input_types():
    cfg = {"threshold": 4}

    compare_input_types(Gradient, cfg)