/// <summary> /// Uses least squares linear regression to calculate the best fit sine wave for the given data. /// </summary> /// <param name="yValues">The y values of the data points.</param> /// <param name="tValues">The time values of the data points, in seconds.</param> /// <param name="frequency">The frequency of the sine wave, in Hz.</param> /// <returns>A <see cref="SineWave"/> approximated from the given data points.</returns> 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 }); }
/// <summary> /// Uses least squares linear regression to calculate the best fit sine wave for the given data. /// </summary> /// <param name="yValues">The y values of the data points.</param> /// <param name="tValues">The time values of the data points, in seconds.</param> /// <param name="frequency">The frequency of the sine wave, in Hz.</param> /// <returns>A <see cref="SineWave"/> approximated from the given data points.</returns> public static SineWave SineFit(double[] yValues, double[] tValues, double frequency) { double[] z = yValues; double[] x = tValues.Select(t => Math.Sin(2.0 * Math.PI * frequency * t)).ToArray(); double[] y = tValues.Select(t => Math.Cos(2.0 * Math.PI * frequency * t)).ToArray(); double a, b, d; 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 }); }
private void PerformCalculation(object state) { try { m_calculating = true; double[] xValues; double[] yValues; // Calculations are made against a copy of the current data set to keep lock time on // data values down to a minimum. This allows data to be added with minimal delay. lock (m_xValues) { xValues = m_xValues.ToArray(); yValues = m_yValues.ToArray(); } // Takes new values and calculates slope (curve fit for 1st order polynomial). m_slope = CurveFit.Compute(1, xValues, yValues)[1]; } catch (Exception ex) { if ((object)Status != null) { Status(this, new EventArgs <string>("CurveFit failed: " + ex.Message)); } } finally { m_calculating = false; } if (Math.Sign(m_slope) != Math.Sign(m_lastSlope)) { m_slopeRun = DateTime.UtcNow; } m_lastSlope = m_slope; // Notifies consumer of new calculated slope. if ((object)Recalculated != null) { Recalculated(this, EventArgs.Empty); } }