public double GetMainFreqAndFillPsdDataFromComLists() { //var lo = ""; //foreach (var v in listComY) //{ // lo += $",{v}"; //} //remove mean from list var avgX = Results.listComX.Average(); var avgY = Results.listComY.Average(); var listWithoutMeanX = Results.listComX.Select(x => x - avgX).ToList(); var listWithoutMeanY = Results.listComY.Select(x => x - avgY).ToList(); //returned value is max from average of two spectrums FftResult fftX = Fft.GetAmpSpectrumAndMax(frameRate, listWithoutMeanX, false);// false bc avg is already removed FftResult fftY = Fft.GetAmpSpectrumAndMax(frameRate, listWithoutMeanY, false); List <double> avgSpecList = new List <double>(); //List<(double,double)> psdAvgData = new List<(double, double)>(); Results.PsdAvgData = new List <(double, double)>(); //List<(double,double)> psdXData = new List<(double, double)>(); //List<(double,double)> psdYData = new List<(double, double)>(); for (int i = 0; i < fftX.Values.Count; i++) { double avg = (fftX.Values[i] + fftY.Values[i]) / 2; avgSpecList.Add(avg); Results.PsdAvgData.Add((fftX.Frequencies[i], avg)); //psdXData.Add((fftX.Frequencies[i],)) } int maxIndex = avgSpecList.IndexOf(avgSpecList.Max()); return(fftX.Frequencies[maxIndex]); }
//Method has optional bool argument removeAverage, because in other methods it accepts already averaged vector. public static FftResult GetAmpSpectrumAndMax(double fs, List <double> vector, bool removeAverage = true) { if (vector == null || !vector.Any()) { return(null); } if (vector.Count == 1) { throw new ArgumentException("Vector must have more than 1 value", nameof(vector)); } if (fs <= 0) { throw new ArgumentException("Fs cannot be less than or equal to zero", nameof(fs)); } Complex32[] vec = new Complex32[vector.Count]; int i = 0; double vecAvg = removeAverage ? vector.Average():0;//don't compute avg if not needed foreach (var ve in vector) { vec[i] = removeAverage ? new Complex32((float)(ve - vecAvg), 0) : new Complex32((float)ve, 0); i++; } Fourier.Forward(vec, FourierOptions.Matlab); FftResult res = new FftResult(); res.Frequencies = new List <double>(); res.Values = new List <double>(); int l = (int)Math.Round((double)vec.Length / 2, MidpointRounding.AwayFromZero); double konec = fs / 2; var k = Generate.LinearSpaced(l, 0, konec); for (int p = 0; p < l; p++) { k[p] = Math.Round(k[p], 10); res.Frequencies.Add(k[p]); res.Values.Add(Complex32.Abs(vec[p])); } res.MaxIndex = res.Values.FindIndex(n => n == (res.Values.Max())); return(res); }
//public static List<double> ComputeFftDuringSignal(double fs, List<double> vector, int windowSizeSamples, int step, bool removeAvgInSegment = true) //{ // if (vector == null || !vector.Any()) // return null; // if (vector.Count == 1) // throw new ArgumentException("Vector must have more than 1 value", nameof(vector)); // if (windowSizeSamples > vector.Count) // throw new ArgumentException("Size of window must be smaller than count of values in vector", nameof(windowSizeSamples)); // if (fs <= 0) // throw new ArgumentException("Fs cannot be less than or equal to zero", nameof(fs)); // if (windowSizeSamples <= 0) // throw new ArgumentException("Size of window cannot be less than or equal to zero", nameof(windowSizeSamples)); // if (step <= 0) // throw new ArgumentException("Step cannot be less than or equal to zero", nameof(step)); // //if(windowSize + step > vector.Count) // // throw new ArgumentException("WindowSize + step must be smaller than count of values in vector", nameof(step)); // var vectorToBeCut = new List<double>(vector);//copy list // var fftList = new List<double>(); // double[] segment = new double[windowSizeSamples]; // there are some changes, see this for 2 signals // while (vectorToBeCut.Count > (windowSizeSamples + step) - 1) // { // vectorToBeCut.CopyTo(0, segment, 0, windowSizeSamples); // vectorToBeCut.RemoveRange(0, step); // FftResult res = GetAmpSpectrumAndMax(fs, segment.ToList(), removeAvgInSegment); // var maxFromSegment = res.Frequencies[res.MaxIndex];//get max freq from current segment // fftList.Add(maxFromSegment); // } // return fftList; //} public static List <double> ComputeFftDuringSignalForTwoSignals(double fs, List <double> vector1, List <double> vector2, int windowSizeSamples, int step, bool removeAvgInSegment = true) { //todo vectors have to be the same length //todo: do this for both vectors //if (vector == null || !vector.Any()) // return null; //if (vector.Count == 1) // throw new ArgumentException("Vector must have more than 1 value", nameof(vector)); //if (windowSizeSamples > vector.Count) // throw new ArgumentException("Size of window must be smaller than count of values in vector", nameof(windowSizeSamples)); if (fs <= 0) { throw new ArgumentException("Fs cannot be less than or equal to zero", nameof(fs)); } if (windowSizeSamples <= 0) { throw new WindowLowerThanOneException(); } if (step <= 0) { throw new StepLowerThanOneException(); } if (vector1.Count != vector2.Count) { throw new ArgumentException("Vectors have to be same length", $"{nameof(vector1)},{nameof(vector2)}"); } if (vector1.Count < windowSizeSamples) { throw new WindowLongerThanSignalException(windowSizeSamples, vector1.Count); } //if(windowSize + step > vector.Count) // throw new ArgumentException("WindowSize + step must be smaller than count of values in vector", nameof(step)); var vectorToBeCut1 = new List <double>(vector1); //copy list var vectorToBeCut2 = new List <double>(vector2); //copy list var fftList = new List <double>(); double[] segment1 = new double[windowSizeSamples]; double[] segment2 = new double[windowSizeSamples]; do { vectorToBeCut1.CopyTo(0, segment1, 0, windowSizeSamples);//kde zacne v listu, kam to nakopiruje, kde zacne poklada, velikost vectorToBeCut1.RemoveRange(0, step); vectorToBeCut2.CopyTo(0, segment2, 0, windowSizeSamples); vectorToBeCut2.RemoveRange(0, step); FftResult res1 = GetAmpSpectrumAndMax(fs, segment1.ToList(), removeAvgInSegment); FftResult res2 = GetAmpSpectrumAndMax(fs, segment2.ToList(), removeAvgInSegment); List <double> avgSpecList = new List <double>(); for (int i = 0; i < res1.Values.Count; i++) { double avg = (res1.Values[i] + res2.Values[i]) / 2; avgSpecList.Add(avg); } int maxIndex = avgSpecList.IndexOf(avgSpecList.Max()); double maxFromSegment = res1.Frequencies[maxIndex]; fftList.Add(maxFromSegment); }while (vectorToBeCut1.Count >= windowSizeSamples); return(fftList); }