//****************************************************************************************************** // 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 }; } } }