//******************************************************************************************************
// WaveFit.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), 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.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 06/19/2012 - Stephen C. Wills
// Generated original version of source code.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
namespace GSF.NumericalAnalysis
{
///
/// Represents a sine wave of the form y=A*sin(ω*t+Φ)+δ.
///
public struct SineWave
{
///
/// 2 * pi
///
public const double TwoPi = 2.0 * Math.PI;
///
/// Amplitude (A) of the sine wave.
///
public double Amplitude;
///
/// Frequency (ω) of the sine wave, in Hz.
///
public double Frequency;
///
/// Phase (Φ) shift of the sine wave.
///
public double Phase;
///
/// Vertical offset (δ) of the sine wave.
///
public double Bias;
///
/// Calculates the y-value for the given time.
///
/// The time, in seconds.
/// A*sin(ω*t+Φ)+δ
public double CalculateY(double t)
{
return Amplitude * Math.Sin(TwoPi * Frequency * t + Phase) + Bias;
}
}
///
/// Linear regression algorithm for sine waves.
///
public static class WaveFit
{
///
/// Uses least squares linear regression to calculate the best fit sine wave for the given data.
///
/// The y values of the data points.
/// The time values of the data points, in seconds.
/// The frequency of the sine wave, in Hz.
/// A approximated from the given data points.
public static SineWave SineFit(double[] yValues, double[] tValues, double frequency)
{
double[] z = yValues;
double[] x = new double[tValues.Length];
double[] y = new double[tValues.Length];
double a, b, d;
double rad = 2.0D * Math.PI * frequency;
for (int i = 0; i < tValues.Length; i++)
{
double angle = rad * tValues[i];
x[i] = Math.Sin(angle);
y[i] = Math.Cos(angle);
}
CurveFit.LeastSquares(z, x, y, out d, out a, out b);
return new SineWave
{
Amplitude = Math.Sqrt(a * a + b * b),
Frequency = frequency,
Phase = Math.Atan2(b, a),
Bias = d
};
}
}
}