/* * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * * https://www.orfeo-toolbox.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef otbSavitzkyGolayInterpolationFunctor_h #define otbSavitzkyGolayInterpolationFunctor_h #include "otbTimeSeries.h" #include "otbTimeSeriesLeastSquareFittingFunctor.h" namespace otb { namespace Functor { /** \class otbSavitzkyGolayInterpolationFunctor * * \brief: This functor implements a local polynomial regression (of * degree k) on a series of values (of at least k+1 points which are * treated as being equally spaced in the series) to determine the * smoothed value for each point. * * In this implementation, the interpolation is performed by least * squares fitting. The size of the moving window for the * interpolation can be set using the radius variable. If needed, * weights for each value of the series to be used by the least * squares estimation can be set (the higher the weight, the lower the * confidence in the value). * * Savitzky, A.; Golay, M.J.E. (1964). "Smoothing and Differentiation of * Data by Simplified Least Squares Procedures". Analytical Chemistry 36 * (8): 1627-1639. doi:10.1021/ac60214a047 * * \sa otbTimeSeriesLeastSquareFittingFunctor * * * \ingroup OTBTimeSeries */ template class SavitzkyGolayInterpolationFunctor { public: typedef typename TSeries::ValueType ValueType; typedef typename TDates::ValueType DateType; typedef typename TWeight::ValueType WeightType; typedef double CoefficientPrecisionType; typedef otb::PolynomialTimeSeries TSFunctionType; static const unsigned int nbDates = TSeries::Dimension; static const unsigned int InterpolatedLength = 2 * Radius + 1; typedef itk::FixedArray InterpolatedSeriesType; typedef itk::FixedArray InterpolatedDatesType; typedef itk::FixedArray InterpolatedWeightType; typedef otb::Functor::TimeSeriesLeastSquareFittingFunctor TLSFunctorType; /// Constructor SavitzkyGolayInterpolationFunctor() { } /// Destructor virtual ~SavitzkyGolayInterpolationFunctor() { } inline void SetWeights(const TWeight weights) { for (unsigned int i = 0; i < m_WeightSeries.Size(); ++i) m_WeightSeries[i] = weights[i]; } inline void SetDates(const TDates doy) { for (unsigned int i = 0; i < m_DoySeries.Size(); ++i) m_DoySeries[i] = doy[i]; } inline TSeries operator()(const TSeries& series) const { TSeries outSeries; unsigned int firstSample = Radius; unsigned int lastSample = nbDates - Radius - 1; for (unsigned int i = 0; i < firstSample; ++i) outSeries[i] = series[i]; for (unsigned int i = lastSample + 1; i < nbDates; ++i) outSeries[i] = series[i]; for (unsigned int i = firstSample; i <= lastSample; ++i) { InterpolatedSeriesType tmpInSeries; InterpolatedDatesType tmpDates; InterpolatedWeightType tmpWeights; for (unsigned int j = 0; j <= 2 * Radius; ++j) { tmpInSeries[j] = series[i + j - Radius]; tmpDates[j] = m_DoySeries[i + j - Radius]; tmpWeights[j] = m_WeightSeries[i + j - Radius]; } TLSFunctorType f; f.SetDates(tmpDates); f.SetWeights(tmpWeights); InterpolatedSeriesType tmpOutSeries = f(tmpInSeries); outSeries[i] = tmpOutSeries[Radius]; } return outSeries; } private: TWeight m_WeightSeries; TDates m_DoySeries; }; } } // namespace otb #endif