# Path: osrefl/loaders/reduction/correction.py
# class Correction(object):
#     properties = []  # Property sheet for interacting with correction
#     def apply(self, data):
#         """
#         Apply the correction to the dataset, modifying the dataset
#         in the process.  The data is returned, allowing users to
#         apply multiple corrections in one step:
#              C2(C1(data))
#         Each correction will automatically be logged in the data using
#         data.log(str(Correction))
#         """
#         raise NotImplementedError
# 
#     def __str__(self):
#         """
#         Name of the correction, and enough detail to record in the
#         reduced data log.
#         """
#         raise NotImplementedError
# 
#     # ==== Inherited behaviours ====
#     def __call__(self, data):
#         data = copy(data)
#         data.log(str(self))
#         self.apply(data)
#         return data
# 
#     def __or__(self, other):
#         # "Correction | Correction" forms a pipeline
#         if isinstance(other,Correction):
#             return Pipeline([self,other])
#         raise NotImplementedError
# 
#     def __ror__(self, other):
#         # "Pipeline | Correction" is handled by pipeline
#         # "data | Correction" applies the correction to the data
#         if not isinstance(other, Pipeline):
#             return self(other)
#         raise NotImplementedError
# 
# Path: osrefl/loaders/reduction/wsolve.py
# def wpolyfit(x,y,dy=1,degree=None,origin=False):
#     """
#     Return the polynomial of degree n that
#     minimizes sum( (p(x_i) - y_i)**2/dy_i**2).
# 
#     if origin is True, the fit should go through the origin.
#     """
#     assert degree != None, "Missing degree argument to wpolyfit"
# 
#     A = _poly_matrix(x,degree,origin)
#     s = wsolve(A,y,dy)
#     return PolynomialModel(s,origin=origin)


import numpy
    import pylab
from .correction import Correction
from .wsolve import wpolyfit
    from .examples import e3a12 as dataset
        """Apply the correction to the data"""
        if data.ispolarized():
            lines = [data.pp, data.pm, data.mp, data.mm]
        else:
            lines = [data]
        for L in lines:
            v,dv = smooth(L.x, L.v, L.dv, degree=self.degree, span=self.span)
            L.v,L.dv = v,dv

    def __str__(self):
        return "Smooth(degree=%d,span=%d)"%(self.degree,self.span)

# TODO: check for equal spacing and use Savitsky-Golay since it will
# TODO: be orders of magnitude faster. Precompute the SG coefficients
# TODO: in the Smooth class.


def smooth(x, y, dy=None, degree=2, span=5):
    """
    Moving least squares smoother.

    If x is equally spaced, then this is equivalent to a Savitsky-Golay
    filter of the same degree and span.
    """
    if dy == None: dy = numpy.ones(y.shape)
    yp,dyp = numpy.empty(y.shape),numpy.empty(y.shape)

    n = len(x)
    k = (span-1)/2


# Path: osrefl/loaders/reduction/correction.py
# class Correction(object):
#     properties = []  # Property sheet for interacting with correction
#     def apply(self, data):
#         """
#         Apply the correction to the dataset, modifying the dataset
#         in the process.  The data is returned, allowing users to
#         apply multiple corrections in one step:
#              C2(C1(data))
#         Each correction will automatically be logged in the data using
#         data.log(str(Correction))
#         """
#         raise NotImplementedError
# 
#     def __str__(self):
#         """
#         Name of the correction, and enough detail to record in the
#         reduced data log.
#         """
#         raise NotImplementedError
# 
#     # ==== Inherited behaviours ====
#     def __call__(self, data):
#         data = copy(data)
#         data.log(str(self))
#         self.apply(data)
#         return data
# 
#     def __or__(self, other):
#         # "Correction | Correction" forms a pipeline
#         if isinstance(other,Correction):
#             return Pipeline([self,other])
#         raise NotImplementedError
# 
#     def __ror__(self, other):
#         # "Pipeline | Correction" is handled by pipeline
#         # "data | Correction" applies the correction to the data
#         if not isinstance(other, Pipeline):
#             return self(other)
#         raise NotImplementedError
# 
# Path: osrefl/loaders/reduction/wsolve.py
# def wpolyfit(x,y,dy=1,degree=None,origin=False):
#     """
#     Return the polynomial of degree n that
#     minimizes sum( (p(x_i) - y_i)**2/dy_i**2).
# 
#     if origin is True, the fit should go through the origin.
#     """
#     assert degree != None, "Missing degree argument to wpolyfit"
# 
#     A = _poly_matrix(x,degree,origin)
#     s = wsolve(A,y,dy)
#     return PolynomialModel(s,origin=origin)


# Path: osrefl/loaders/reduction/smoothcor.py
import numpy
    import pylab
from .correction import Correction
from .wsolve import wpolyfit
    from .examples import e3a12 as dataset

        """Apply the correction to the data"""
        if data.ispolarized():
            lines = [data.pp, data.pm, data.mp, data.mm]
        else:
            lines = [data]
        for L in lines:
            v,dv = smooth(L.x, L.v, L.dv, degree=self.degree, span=self.span)
            L.v,L.dv = v,dv

    def __str__(self):
        return "Smooth(degree=%d,span=%d)"%(self.degree,self.span)

# TODO: check for equal spacing and use Savitsky-Golay since it will
# TODO: be orders of magnitude faster. Precompute the SG coefficients
# TODO: in the Smooth class.


def smooth(x, y, dy=None, degree=2, span=5):
    """
    Moving least squares smoother.

    If x is equally spaced, then this is equivalent to a Savitsky-Golay
    filter of the same degree and span.
    """
    if dy == None: dy = numpy.ones(y.shape)
    yp,dyp = numpy.empty(y.shape),numpy.empty(y.shape)

    n = len(x)
    k = (span-1)/2


    poly = wpolyfit(x[:span], y[:span], dy[:span], degree=degree)