134 lines
4.7 KiB
C#
134 lines
4.7 KiB
C#
|
|
using NUnit.Framework;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
|
|||
|
|
namespace FftSharp.Tests
|
|||
|
|
{
|
|||
|
|
[TestFixture]
|
|||
|
|
public class PowerSpectralDensityShould
|
|||
|
|
{
|
|||
|
|
#region helper functions
|
|||
|
|
private void ParseData(string filename, out List<double> vals1, out List<double> vals2)
|
|||
|
|
{
|
|||
|
|
vals1 = new List<double>();
|
|||
|
|
vals2 = new List<double>();
|
|||
|
|
|
|||
|
|
using (var rawReader = new StreamReader(TestContext.CurrentContext.TestDirectory + "\\" + filename))
|
|||
|
|
{
|
|||
|
|
while (!rawReader.EndOfStream)
|
|||
|
|
{
|
|||
|
|
var line = rawReader.ReadLine();
|
|||
|
|
var values = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|||
|
|
|
|||
|
|
if (double.TryParse(values[0], out double val1))
|
|||
|
|
{
|
|||
|
|
vals1.Add(val1);
|
|||
|
|
}
|
|||
|
|
if (double.TryParse(values[1], out double val2))
|
|||
|
|
{
|
|||
|
|
vals2.Add(val2);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool CloseEnough(double[] val1, double[] val2)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < val1.Length; i++)
|
|||
|
|
{
|
|||
|
|
var exp = Math.Floor(Math.Log10(val1[i]));
|
|||
|
|
var exp2 = Math.Floor(Math.Log10(val2[i]));
|
|||
|
|
exp += exp < 0 ? 1 : -1;
|
|||
|
|
if (exp <= -10 && exp2 <= -10) continue; // under 1e-10? we're in the noise floor, skip
|
|||
|
|
|
|||
|
|
var diff = Math.Abs(val1[i] - val2[i]);
|
|||
|
|
var delta = Math.Pow(10, exp);
|
|||
|
|
if (diff > delta)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
const int RawValueLength = 304478;
|
|||
|
|
const int PSDValueLength = 2049;
|
|||
|
|
|
|||
|
|
[Test]
|
|||
|
|
public void BasicWelch_1_RawTestDataShouldParse()
|
|||
|
|
{
|
|||
|
|
//Arrange
|
|||
|
|
List<double> gVals, sVals;
|
|||
|
|
ParseData("Raw.csv", out sVals, out gVals);
|
|||
|
|
//Act
|
|||
|
|
//Assert
|
|||
|
|
Assert.Multiple(() =>
|
|||
|
|
{
|
|||
|
|
Assert.That(gVals.Count, Is.EqualTo(RawValueLength));
|
|||
|
|
Assert.That(sVals.Count, Is.EqualTo(RawValueLength));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
[Test]
|
|||
|
|
public void BasicWelch_2_PSDResultsDataShouldParse()
|
|||
|
|
{
|
|||
|
|
//Arrange
|
|||
|
|
List<double> hzVals, g2ovHzVals;
|
|||
|
|
ParseData("PSD.csv", out hzVals, out g2ovHzVals);
|
|||
|
|
//Act
|
|||
|
|
//Assert
|
|||
|
|
Assert.Multiple(() =>
|
|||
|
|
{
|
|||
|
|
Assert.That(g2ovHzVals.Count, Is.EqualTo(PSDValueLength));
|
|||
|
|
Assert.That(hzVals.Count, Is.EqualTo(PSDValueLength));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
[Test]
|
|||
|
|
public void BasicWelch_3_FFTSharpFreqShouldMatchPSDResultFreq()
|
|||
|
|
{
|
|||
|
|
//Arrange
|
|||
|
|
List<double> hzVals, g2ovHzVals;
|
|||
|
|
ParseData("PSD.csv", out hzVals, out g2ovHzVals);
|
|||
|
|
var sampleRate = 10000;
|
|||
|
|
//Act
|
|||
|
|
var freq = FftSharp.Transform.FFTfreq(sampleRate, g2ovHzVals.Count);
|
|||
|
|
//Assert
|
|||
|
|
Assert.Multiple(() =>
|
|||
|
|
{
|
|||
|
|
Assert.That(hzVals.Count, Is.EqualTo(PSDValueLength));
|
|||
|
|
Assert.That(freq.Length, Is.EqualTo(PSDValueLength));
|
|||
|
|
// see if they're close enough
|
|||
|
|
Assert.That(hzVals.ToArray(), Is.EqualTo(freq).Using<double[]>(CloseEnough));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
[Test]
|
|||
|
|
public void BasicWelch_4_TestBasicFlatTopNoOverlap4096Width()
|
|||
|
|
{
|
|||
|
|
//Arrange
|
|||
|
|
List<double> gVals, sVals;
|
|||
|
|
ParseData("Raw.csv", out sVals, out gVals);
|
|||
|
|
List<double> hzVals, g2ovHzVals;
|
|||
|
|
ParseData("PSD.csv", out hzVals, out g2ovHzVals);
|
|||
|
|
var sampleRate = 10000;
|
|||
|
|
var averagingType = FftSharp.WindowAveragingType.Averaging;
|
|||
|
|
var windowWidth = 4096;
|
|||
|
|
var overlappingPct = 0;
|
|||
|
|
//Act
|
|||
|
|
FftSharp.WindowType type = WindowType.Rectangular;
|
|||
|
|
var psd = FftSharp.Transform.PSD_Welch(gVals.ToArray(), sampleRate, type, windowWidth, overlappingPct, averagingType);
|
|||
|
|
//Assert
|
|||
|
|
Assert.Multiple(() =>
|
|||
|
|
{
|
|||
|
|
Assert.That(g2ovHzVals.Count, Is.EqualTo(PSDValueLength));
|
|||
|
|
Assert.That(psd.Length, Is.EqualTo(PSDValueLength));
|
|||
|
|
// see if they're close enough
|
|||
|
|
Assert.That(g2ovHzVals.ToArray(), Is.EqualTo(psd).Using<double[]>(CloseEnough));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|