From 0818a3d81ca71508bdea77a42bae7dc264a47f19 Mon Sep 17 00:00:00 2001 From: koldo Date: Sat, 6 Aug 2016 06:01:58 +0000 Subject: [PATCH] ScatterDraw: Some improvements in FFT git-svn-id: svn://ultimatepp.org/upp/trunk@10145 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/ScatterDraw/DataSource.cpp | 74 ++++++++++++++++++++++++++----- uppsrc/ScatterDraw/DataSource.h | 13 ++++-- uppsrc/ScatterDraw/Equation.cpp | 3 ++ 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/uppsrc/ScatterDraw/DataSource.cpp b/uppsrc/ScatterDraw/DataSource.cpp index d7c671a17..5b03b6628 100644 --- a/uppsrc/ScatterDraw/DataSource.cpp +++ b/uppsrc/ScatterDraw/DataSource.cpp @@ -169,10 +169,12 @@ Vector DataSource::MovingAverage(Getdatafun getdataY, Getdatafun getdata for (j = i+1; j < GetCount(); ++j) { double ynext = Membercall(getdataY)(j); double xnext = Membercall(getdataX)(j); - if (IsNull(xnext) || IsNull(ynext)) + if (IsNull(xnext)) continue; - if ((xnext - x) > width_2) + if ((xnext - x) > width_2) break; + if (IsNull(ynext)) + continue; sum += ynext; numAvg++; } @@ -183,6 +185,42 @@ Vector DataSource::MovingAverage(Getdatafun getdataY, Getdatafun getdata return ret; } +Vector DataSource::SectorAverage(Getdatafun getdataY, Getdatafun getdataX, double width) { + Vector ret; + + for (int i = 0; i < GetCount();) { + double y = Membercall(getdataY)(i); + double x = Membercall(getdataX)(i); + if (IsNull(x) || IsNull(y)) + continue; + + int numAvg = 1; + double sum = y; + double sumX = x; + int j; + for (j = i+1; j < GetCount(); ++j) { + double ynext = Membercall(getdataY)(j); + double xnext = Membercall(getdataX)(j); + if (IsNull(xnext)) + continue; + if ((xnext - x) > width) { + --j; + break; + } + if (IsNull(ynext)) + continue; + sumX += xnext; + sum += ynext; + numAvg++; + } + ret << Pointf(sumX/numAvg, sum/numAvg); + if (j == GetCount()) + break; + i = j+1; + } + return ret; +} + void DataSource::ZeroCrossing(Getdatafun getdataY, Getdatafun getdataX, bool ascending, bool descending, Vector &zeros, Vector &ids) { zeros.Clear(); @@ -270,7 +308,7 @@ double CArray::znFixed(int n, int64 id) { } -Vector DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, bool phase) { +Vector DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, int type, bool window) { int numData = int(GetCount()); VectorXd timebuf(numData); int num = 0; @@ -286,6 +324,16 @@ Vector DataSource::FFT(Getdatafun getdata, double tSample, bool frequenc return res; timebuf.resize(num); + double windowSum = 0; + if (window) { + for (int i = 0; i < numData; ++i) { + double windowDat = 0.54 - 0.46*cos(2*M_PI*i/numData); + windowSum += windowDat; + timebuf[i] *= windowDat; // Hamming window + } + } else + windowSum = numData; + VectorXcd freqbuf; try { Eigen::FFT fft; @@ -298,19 +346,21 @@ Vector DataSource::FFT(Getdatafun getdata, double tSample, bool frequenc for (int i = 0; i < int(freqbuf.size()); ++i) { double xdata = i/(tSample*numData); - if (phase) - res << Pointf(xdata, std::arg(freqbuf[i])); - else - res << Pointf(xdata, 2*std::abs(freqbuf[i])/numData); + switch (type) { + case T_PHASE: res << Pointf(xdata, std::arg(freqbuf[i])); break; + case T_FFT: res << Pointf(xdata, 2*std::abs(freqbuf[i])/windowSum); break; + case T_PSD: res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(windowSum/tSample)); + } } } else { - for (int i = int(freqbuf.size()); i > 0; --i) { + for (int i = int(freqbuf.size()) - 1; i > 0; --i) { double xdata = (tSample*numData)/i; - if (phase) - res << Pointf(xdata, std::arg(freqbuf[i])); - else - res << Pointf(xdata, 2*std::abs(freqbuf[i])/numData); + switch (type) { + case T_PHASE: res << Pointf(xdata, std::arg(freqbuf[i])); break; + case T_FFT: res << Pointf(xdata, 2*std::abs(freqbuf[i])/windowSum); break; + case T_PSD: res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(windowSum/tSample)); + } } } return res; diff --git a/uppsrc/ScatterDraw/DataSource.h b/uppsrc/ScatterDraw/DataSource.h index 8627db4f1..0395a645c 100644 --- a/uppsrc/ScatterDraw/DataSource.h +++ b/uppsrc/ScatterDraw/DataSource.h @@ -48,11 +48,14 @@ public: virtual Vector UpperEnvelopeY(double width) {return UpperEnvelope(&DataSource::y, &DataSource::x, width);} virtual Vector LowerEnvelopeY(double width) {return LowerEnvelope(&DataSource::y, &DataSource::x, width);} virtual Vector MovingAverageY(double width) {return MovingAverage(&DataSource::y, &DataSource::x, width);} + virtual Vector SectorAverageY(double width) {return SectorAverage(&DataSource::y, &DataSource::x, width);} virtual void ZeroCrossingY(bool ascending, bool descending, Vector &zeros, Vector &ids) { return ZeroCrossing(&DataSource::y, &DataSource::x, ascending, descending, zeros, ids);} - - Upp::Vector FFTY(double tSample, bool frequency = false, bool phase = false) { - return FFT(&DataSource::y, tSample, frequency, phase);} + + enum FFT_TYPE {T_FFT = 0, T_PHASE, T_PSD}; + + Upp::Vector FFTY(double tSample, bool frequency = false, int type = FFT_TYPE::T_FFT, bool window = false) { + return FFT(&DataSource::y, tSample, frequency, type, window);} double Min(Getdatafun getdata, int64& id); double Max(Getdatafun getdata, int64& id); @@ -63,11 +66,13 @@ public: Vector UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width); Vector LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width); Vector MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width); + Vector SectorAverage(Getdatafun getdataY, Getdatafun getdataX, double width); void ZeroCrossing(Getdatafun getdataY, Getdatafun getdataX, bool ascending, bool descending, Vector &zeros, Vector &ids); double SinEstim_Amplitude(double avg = Null); bool SinEstim_FreqPhase(double &frequency, double &phase, double avg = Null); - Vector FFT(Getdatafun getdata, double tSample, bool frequency = false, bool phase = false); + Vector FFT(Getdatafun getdata, double tSample, bool frequency = false, + int type = FFT_TYPE::T_FFT, bool window = false); protected: bool isParam, isExplicit; diff --git a/uppsrc/ScatterDraw/Equation.cpp b/uppsrc/ScatterDraw/Equation.cpp index e1f253d56..7c05668cb 100644 --- a/uppsrc/ScatterDraw/Equation.cpp +++ b/uppsrc/ScatterDraw/Equation.cpp @@ -147,6 +147,9 @@ EvalExpr::EvalExpr() { functions.Add("sinh", sinh); functions.Add("cosh", cosh); functions.Add("tanh", tanh); + functions.Add("log", log); + functions.Add("log10", log10); + functions.Add("exp", exp); functions.Add("degToRad", degToRad); }