ScatterDraw: Some improvements in FFT

git-svn-id: svn://ultimatepp.org/upp/trunk@10145 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
koldo 2016-08-06 06:01:58 +00:00
parent d6c3e2336f
commit 0818a3d81c
3 changed files with 74 additions and 16 deletions

View file

@ -169,10 +169,12 @@ Vector<Pointf> 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<Pointf> DataSource::MovingAverage(Getdatafun getdataY, Getdatafun getdata
return ret;
}
Vector<Pointf> DataSource::SectorAverage(Getdatafun getdataY, Getdatafun getdataX, double width) {
Vector<Pointf> 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<double> &zeros, Vector<int64> &ids) {
zeros.Clear();
@ -270,7 +308,7 @@ double CArray::znFixed(int n, int64 id) {
}
Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, bool phase) {
Vector<Pointf> 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<Pointf> 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<double> fft;
@ -298,19 +346,21 @@ Vector<Pointf> 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;

View file

@ -48,11 +48,14 @@ public:
virtual Vector<int64> UpperEnvelopeY(double width) {return UpperEnvelope(&DataSource::y, &DataSource::x, width);}
virtual Vector<int64> LowerEnvelopeY(double width) {return LowerEnvelope(&DataSource::y, &DataSource::x, width);}
virtual Vector<Pointf> MovingAverageY(double width) {return MovingAverage(&DataSource::y, &DataSource::x, width);}
virtual Vector<Pointf> SectorAverageY(double width) {return SectorAverage(&DataSource::y, &DataSource::x, width);}
virtual void ZeroCrossingY(bool ascending, bool descending, Vector<double> &zeros, Vector<int64> &ids) {
return ZeroCrossing(&DataSource::y, &DataSource::x, ascending, descending, zeros, ids);}
Upp::Vector<Pointf> 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<Pointf> 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<int64> UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width);
Vector<int64> LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width);
Vector<Pointf> MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width);
Vector<Pointf> SectorAverage(Getdatafun getdataY, Getdatafun getdataX, double width);
void ZeroCrossing(Getdatafun getdataY, Getdatafun getdataX, bool ascending, bool descending,
Vector<double> &zeros, Vector<int64> &ids);
double SinEstim_Amplitude(double avg = Null);
bool SinEstim_FreqPhase(double &frequency, double &phase, double avg = Null);
Vector<Pointf> FFT(Getdatafun getdata, double tSample, bool frequency = false, bool phase = false);
Vector<Pointf> FFT(Getdatafun getdata, double tSample, bool frequency = false,
int type = FFT_TYPE::T_FFT, bool window = false);
protected:
bool isParam, isExplicit;

View file

@ -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);
}