mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-02 16:22:40 -06:00
ScatterDraw: Improved PSD and added new spectral options.
git-svn-id: svn://ultimatepp.org/upp/trunk@10933 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
90accc7728
commit
82b71d8360
6 changed files with 408 additions and 90 deletions
|
|
@ -36,6 +36,71 @@ double DataSource::Max(Getdatafun getdata, int64& id) {
|
|||
return maxVal;
|
||||
}
|
||||
|
||||
void DataSource::MaxList(Getdatafun getdataY, Getdatafun getdataX, Vector<int64> &id, double width) {
|
||||
id.Clear();
|
||||
for (int64 i = 1; i < GetCount() - 1; ++i) {
|
||||
double d = Membercall(getdataY)(i);
|
||||
if (IsNull(d))
|
||||
continue;
|
||||
int64 ii;
|
||||
for (ii = i-1; ii >= 0; --ii) {
|
||||
if (!IsNull(Membercall(getdataY)(ii)))
|
||||
break;
|
||||
}
|
||||
if (ii < 0)
|
||||
continue;
|
||||
double d_1 = Membercall(getdataY)(ii);
|
||||
for (ii = i+1; ii < GetCount(); ++ii) {
|
||||
if (!IsNull(Membercall(getdataY)(ii)))
|
||||
break;
|
||||
}
|
||||
if (ii >= GetCount())
|
||||
continue;
|
||||
double d1 = Membercall(getdataY)(ii);
|
||||
if (d >= d_1 && d > d1) {
|
||||
if (id.GetCount() == 0 ||
|
||||
(Membercall(getdataX)(i) - Membercall(getdataX)(id.GetCount() - 1) >= width))
|
||||
id << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pointf DataSource::MaxSubDataImp(Getdatafun getdataY, Getdatafun getdataX, int64 maxId, int64 width)
|
||||
{
|
||||
Vector<Pointf> p;
|
||||
|
||||
int iw;
|
||||
int64 idMin, idMax;
|
||||
iw = 0;
|
||||
for (idMin = maxId - 1; idMin >= 0 && iw < width; idMin--) {
|
||||
if (IsNull(Membercall(getdataY)(idMin)) || IsNull(Membercall(getdataX)(idMin)))
|
||||
continue;
|
||||
iw++;
|
||||
}
|
||||
if (idMin < 0)
|
||||
idMin = 0;
|
||||
iw = 0;
|
||||
for (idMax = maxId + 1; idMax < GetCount() && iw < width; idMax++) {
|
||||
if (IsNull(Membercall(getdataY)(idMax)) || IsNull(Membercall(getdataX)(idMax)))
|
||||
continue;
|
||||
iw++;
|
||||
}
|
||||
if (idMax >= GetCount())
|
||||
idMax = GetCount() - 1;
|
||||
for (int64 i = idMin; i <= idMax; ++i) {
|
||||
if (IsNull(Membercall(getdataY)(i)) || IsNull(Membercall(getdataX)(i)))
|
||||
continue;
|
||||
p << Pointf(Membercall(getdataX)(i), Membercall(getdataY)(i));
|
||||
}
|
||||
VectorPointf pf(p);
|
||||
PolynomialEquation2 polyFit;
|
||||
polyFit.Fit(pf);
|
||||
const Vector<double> &coeff = polyFit.GetCoeff();
|
||||
double b = coeff[1];
|
||||
double a = coeff[2];
|
||||
return Pointf(-b/2/a, polyFit.f(-b/2/a));
|
||||
}
|
||||
|
||||
double DataSource::Avg(Getdatafun getdata) {
|
||||
double ret = 0;
|
||||
int count = 0;
|
||||
|
|
@ -327,43 +392,49 @@ double CArray::znFixed(int n, int64 id) {
|
|||
return Null;
|
||||
}
|
||||
|
||||
|
||||
Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, int type, bool window) {
|
||||
int numData = int(GetCount());
|
||||
VectorXd timebuf(numData);
|
||||
int num = 0;
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
double data = Membercall(getdata)(i);
|
||||
if (!IsNull(data)) {
|
||||
timebuf[i] = Membercall(getdata)(i);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
Vector<Pointf> res;
|
||||
if (num < 3)
|
||||
return res;
|
||||
timebuf.resize(num);
|
||||
Vector<Pointf> FFTSimple(VectorXd &data, double tSample, bool frequency, int type,
|
||||
int window, int numOver) {
|
||||
int numData = int(data.size());
|
||||
|
||||
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;
|
||||
|
||||
double numDataFact = 0;
|
||||
switch (window) {
|
||||
case DataSource::HAMMING:
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
double windowFact = 0.54 - 0.46*cos(2*M_PI*i/numData);
|
||||
numDataFact += windowFact;
|
||||
data[i] *= windowFact;
|
||||
}
|
||||
break;
|
||||
case DataSource::COS:
|
||||
for (int i = 0; i < numOver; ++i) {
|
||||
double windowFact = 0.5*(1 - cos(M_PI*i/numOver));
|
||||
numDataFact += windowFact;
|
||||
data[i] *= windowFact;
|
||||
}
|
||||
for (int i = numOver; i < numData - numOver; ++i) {
|
||||
double windowFact = 1; // 1.004
|
||||
numDataFact += windowFact;
|
||||
//data[i] *= windowFact;
|
||||
}
|
||||
for (int i = numData - numOver; i < numData; ++i) {
|
||||
double windowFact = 0.5*(1 + cos(M_PI*(numData - i - numOver)/numOver));
|
||||
numDataFact += windowFact;
|
||||
data[i] *= windowFact;
|
||||
}
|
||||
break;
|
||||
default: numDataFact = numData;
|
||||
}
|
||||
Vector<Pointf> res;
|
||||
VectorXcd freqbuf;
|
||||
try {
|
||||
Eigen::FFT<double> fft;
|
||||
fft.SetFlag(fft.HalfSpectrum);
|
||||
fft.fwd(freqbuf, timebuf);
|
||||
fft.fwd(freqbuf, data);
|
||||
} catch(...) {
|
||||
return res;
|
||||
}
|
||||
double threshold = 0;
|
||||
if (type == T_PHASE) {
|
||||
if (type == DataSource::T_PHASE) {
|
||||
for (int i = 0; i < int(freqbuf.size()); ++i) {
|
||||
if (threshold < std::abs(freqbuf[i]))
|
||||
threshold = std::abs(freqbuf[i]);
|
||||
|
|
@ -375,13 +446,16 @@ Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequenc
|
|||
double xdata = i/(tSample*numData);
|
||||
|
||||
switch (type) {
|
||||
case T_PHASE: if (std::abs(freqbuf[i]) > threshold)
|
||||
res << Pointf(xdata, std::arg(freqbuf[i]));
|
||||
else
|
||||
res << Pointf(xdata, 0);
|
||||
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));
|
||||
case DataSource::T_PHASE:
|
||||
if (std::abs(freqbuf[i]) > threshold)
|
||||
res << Pointf(xdata, std::arg(freqbuf[i]));
|
||||
else
|
||||
res << Pointf(xdata, 0);
|
||||
break;
|
||||
case DataSource::T_FFT:
|
||||
res << Pointf(xdata, 2*std::abs(freqbuf[i])/numDataFact); break;
|
||||
case DataSource::T_PSD:
|
||||
res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(numDataFact/tSample));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -389,19 +463,188 @@ Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequenc
|
|||
double xdata = (tSample*numData)/i;
|
||||
|
||||
switch (type) {
|
||||
case T_PHASE: if (std::abs(freqbuf[i]) > threshold)
|
||||
res << Pointf(xdata, std::arg(freqbuf[i]));
|
||||
else
|
||||
res << Pointf(xdata, 0);
|
||||
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));
|
||||
case DataSource::T_PHASE:
|
||||
if (std::abs(freqbuf[i]) > threshold)
|
||||
res << Pointf(xdata, std::arg(freqbuf[i]));
|
||||
else
|
||||
res << Pointf(xdata, 0);
|
||||
break;
|
||||
case DataSource::T_FFT:
|
||||
res << Pointf(xdata, 2*std::abs(freqbuf[i])/numDataFact); break;
|
||||
case DataSource::T_PSD:
|
||||
res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(numDataFact/tSample));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, int type,
|
||||
int window, int numSub, double overlapping) {
|
||||
int numData = int(GetCount());
|
||||
|
||||
VectorXd data(numData);
|
||||
int num = 0;
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
double d = Membercall(getdata)(i);
|
||||
if (!IsNull(d)) {
|
||||
data[i] = d;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
numData = num;
|
||||
|
||||
Vector<Pointf> res;
|
||||
if (num < 3)
|
||||
return res;
|
||||
data.resize(numData);
|
||||
double numOver;
|
||||
|
||||
if (numSub == 1) {
|
||||
numOver = numData*overlapping;
|
||||
return FFTSimple(data, tSample, frequency, type, window, int(numOver));
|
||||
} else { // solve v t=2*(v-f*v/2) + (n-2)*(v-f*v) ==> v=t/(f + n -f*n)
|
||||
double numDataPart = numData/(overlapping + numSub - overlapping*numSub);
|
||||
int inumDataPart = int(numDataPart);
|
||||
numOver = numDataPart*overlapping;
|
||||
VectorXd dataPart(inumDataPart);
|
||||
double izero = 0;
|
||||
int izerod = 0;
|
||||
Vector<Pointf> fft;
|
||||
for (int iPart = 0; iPart < numSub; ++iPart) {
|
||||
if (iPart > 0) {
|
||||
izero += int(numDataPart - numOver);
|
||||
izerod = int(izero);
|
||||
}
|
||||
for (int i = 0; i < inumDataPart; ++i)
|
||||
dataPart[i] = data[izerod + i];
|
||||
Vector<Pointf> fftPart;
|
||||
fftPart = FFTSimple(dataPart, tSample, frequency, type, window, int(numOver));
|
||||
if (iPart == 0)
|
||||
fft = clone(fftPart); // pick()
|
||||
else {
|
||||
for (int i = 0; i < fftPart.GetCount(); ++i) {
|
||||
fft[i].y += fftPart[i].y;
|
||||
ASSERT(fft[i].x == fftPart[i].x);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < fft.GetCount(); ++i)
|
||||
fft[i].y /= numSub;
|
||||
return fft;
|
||||
}
|
||||
}
|
||||
|
||||
double DataSource::Integral(double from, double to, double n) {
|
||||
double h = (to - from)/n;
|
||||
double h2 = h/2;
|
||||
|
||||
double sum1 = 0, sum2 = 0;
|
||||
for(int i = 0; i < n; i++) {
|
||||
sum1 += f(from + h*i + h2);
|
||||
sum2 += f(from + h*i);
|
||||
}
|
||||
return h/6*(f(from) + f(to) + 4*sum1 + 2*sum2);
|
||||
}
|
||||
|
||||
double DataSource::Integral(Getdatafun getdataY, Getdatafun getdataX) {
|
||||
double prevx = Membercall(getdataX)(0);
|
||||
double prevy = Membercall(getdataY)(0);
|
||||
double sum = 0;
|
||||
for (int i = 1; i < GetCount(); ++i) {
|
||||
double x = Membercall(getdataX)(i);
|
||||
double y = Membercall(getdataY)(i);
|
||||
sum += (x - prevx)*(y + prevy);
|
||||
prevx = x;
|
||||
prevy = y;
|
||||
}
|
||||
return sum/2;
|
||||
}
|
||||
|
||||
void DataSource::GetSpectralMoments(double from, double to, double n, bool frequency,
|
||||
double &m_1, double &m0, double &m1, double &m2) {
|
||||
if (!frequency) {
|
||||
from = 1/to;
|
||||
to = 1/from;
|
||||
}
|
||||
double h = (to - from)/n;
|
||||
double h2 = h/2;
|
||||
|
||||
double sum1_m_1 = 0, sum2_m_1 = 0;
|
||||
double sum1_m0 = 0, sum2_m0 = 0;
|
||||
double sum1_m1 = 0, sum2_m1 = 0;
|
||||
double sum1_m2 = 0, sum2_m2 = 0;
|
||||
double f1, f2, x1, x2;
|
||||
for(int i = 0; i < n; i++) {
|
||||
if (frequency) {
|
||||
x1 = from + h*i + h2;
|
||||
x2 = from + h*i;
|
||||
f1 = f(x1);
|
||||
f2 = f(x2);
|
||||
} else {
|
||||
x1 = 1/(from + h*i + h2);
|
||||
x2 = 1/(from + h*i);
|
||||
f1 = f(1/x1);
|
||||
f2 = f(1/x2);
|
||||
}
|
||||
sum1_m_1 += f1/x1;
|
||||
sum2_m_1 += f2/x2;
|
||||
sum1_m0 += f1;
|
||||
sum2_m0 += f2;
|
||||
sum1_m1 += f1*x1;
|
||||
sum2_m1 += f2*x2;
|
||||
sum1_m2 += f1*x1*x1;
|
||||
sum2_m2 += f2*x2*x2;
|
||||
}
|
||||
double f_from, f_to;
|
||||
if (frequency) {
|
||||
f_from = f(from);
|
||||
f_to = f(to);
|
||||
} else {
|
||||
f_from = f(1/from);
|
||||
f_to = f(1/to);
|
||||
}
|
||||
m_1 = h/6*(f_from/from + f_to/to + 4*sum1_m_1 + 2*sum2_m_1);
|
||||
m0 = h/6*(f_from + f(to) + 4*sum1_m0 + 2*sum2_m0);
|
||||
m1 = h/6*(f_from*from + f_to*to + 4*sum1_m1 + 2*sum2_m1);
|
||||
m2 = h/6*(f_from*from*from + f_to*to*to + 4*sum1_m2 + 2*sum2_m2);
|
||||
}
|
||||
|
||||
void DataSource::GetSpectralMoments(Getdatafun getdataY, Getdatafun getdataX, bool frequency,
|
||||
double &m_1, double &m0, double &m1, double &m2) {
|
||||
double prevx = Membercall(getdataX)(0);
|
||||
double Si_1 = Membercall(getdataY)(0);
|
||||
m_1 = m0 = m1 = m2 = 0;
|
||||
for (int i = 1; i < GetCount(); ++i) {
|
||||
double x = Membercall(getdataX)(i);
|
||||
double Si = Membercall(getdataY)(i);
|
||||
|
||||
double deltaX;
|
||||
double fi, fi_1;
|
||||
if (frequency) {
|
||||
fi = x;
|
||||
fi_1 = prevx;
|
||||
deltaX = fi - fi_1;
|
||||
} else {
|
||||
fi = 1/x;
|
||||
fi_1 = 1/prevx;
|
||||
deltaX = fi_1 - fi;
|
||||
}
|
||||
if (fi != 0 && fi_1 != 0) {
|
||||
m_1 += (Si/fi + Si_1/fi_1)*deltaX;
|
||||
m0 += (Si + Si_1)*deltaX;
|
||||
m1 += (Si*fi + Si_1*fi_1)*deltaX;
|
||||
m2 += (Si*fi*fi + Si_1*fi_1*fi_1)*deltaX;
|
||||
}
|
||||
prevx = x;
|
||||
Si_1 = Si;
|
||||
}
|
||||
m_1 /= 2;
|
||||
m0 /= 2;
|
||||
m1 /= 2;
|
||||
m2 /= 2;
|
||||
}
|
||||
|
||||
bool DataSource::SameX(DataSource &data) {
|
||||
int64 num = GetCount();
|
||||
if (data.GetCount() != num)
|
||||
|
|
|
|||
|
|
@ -50,14 +50,32 @@ public:
|
|||
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 MaxListY(Vector<int64> &id, double width){MaxList(&DataSource::y, &DataSource::x, id, width);}
|
||||
virtual Pointf MaxSubDataImpY(int64 maxId, int width) {return MaxSubDataImp(&DataSource::y, &DataSource::x, maxId, width);}
|
||||
virtual void ZeroCrossingY(bool ascending, bool descending, Vector<double> &zeros, Vector<int64> &ids) {
|
||||
return ZeroCrossing(&DataSource::y, &DataSource::x, ascending, descending, zeros, ids);}
|
||||
return ZeroCrossing(&DataSource::y, &DataSource::x, ascending, descending, zeros, ids);}
|
||||
virtual double IntegralY() {return Integral(&DataSource::y, &DataSource::x);}
|
||||
virtual double IntegralY(double from, double to, double n) {return Integral(from, to, n);}
|
||||
|
||||
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);}
|
||||
enum FFT_WINDOW {NO_WINDOW = 0, HAMMING, COS};
|
||||
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,
|
||||
int window = FFT_WINDOW::HAMMING, int numSub = 1, double overlapping = 0) {
|
||||
return FFT(&DataSource::y, tSample, frequency, type, window, numSub, overlapping);}
|
||||
static int GetFFTWindowCount() {return 3;}
|
||||
static const char *GetFFTWindowStr(int i) {
|
||||
const char *str[] = {"no window", "hamming", "cos"};
|
||||
if (i < 0 || i >= GetFFTWindowCount())
|
||||
return 0;
|
||||
return str[i];
|
||||
}
|
||||
void GetSpectralMomentsY(double from, double to, double n, bool frequency,
|
||||
double &m_1, double &m0, double &m1, double &m2)
|
||||
{GetSpectralMoments(from, to, n, frequency, m_1, m0, m1, m2);}
|
||||
void GetSpectralMomentsY(bool frequency, double &m_1, double &m0, double &m1, double &m2)
|
||||
{GetSpectralMoments(&DataSource::y, &DataSource::x, frequency, m_1, m0, m1, m2);}
|
||||
|
||||
double Min(Getdatafun getdata, int64& id);
|
||||
double Max(Getdatafun getdata, int64& id);
|
||||
double Avg(Getdatafun getdata);
|
||||
|
|
@ -69,18 +87,27 @@ public:
|
|||
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 MaxList(Getdatafun getdataY, Getdatafun getdataX, Vector<int64> &id, double width);
|
||||
Pointf MaxSubDataImp(Getdatafun getdataY, Getdatafun getdataX, int64 maxId, int64 width);
|
||||
void ZeroCrossing(Getdatafun getdataY, Getdatafun getdataX, bool ascending, bool descending,
|
||||
Vector<double> &zeros, Vector<int64> &ids);
|
||||
double Integral(Getdatafun getdataY, Getdatafun getdataX);
|
||||
double Integral(double from, double to, double n);
|
||||
|
||||
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,
|
||||
int type = FFT_TYPE::T_FFT, bool window = false);
|
||||
|
||||
int type = FFT_TYPE::T_FFT, int window = FFT_WINDOW::HAMMING,
|
||||
int numSub = 1, double overlapping = 0);
|
||||
void GetSpectralMoments(double from, double to, double n, bool frequency,
|
||||
double &m_1, double &m0, double &m1, double &m2);
|
||||
void GetSpectralMoments(Getdatafun getdataY, Getdatafun getdataX, bool frequency,
|
||||
double &m_1, double &m0, double &m1, double &m2);
|
||||
bool SameX(DataSource &data);
|
||||
|
||||
protected:
|
||||
bool isParam, isExplicit;
|
||||
|
||||
|
||||
private:
|
||||
int key;
|
||||
|
||||
|
|
@ -172,7 +199,13 @@ private:
|
|||
double x0, deltaX;
|
||||
|
||||
public:
|
||||
VectorY(Vector<Y> &yData, double x0, double deltaX) : yData(&yData), x0(x0), deltaX(deltaX) {}
|
||||
VectorY() : yData(0), x0(0), deltaX(0) {}
|
||||
VectorY(Vector<Y> &yData, double x0, double deltaX) {Init(yData, x0, deltaX);}
|
||||
void Init(Vector<Y> &yData, double x0, double deltaX) {
|
||||
this->yData = &yData;
|
||||
this->x0 = x0;
|
||||
this->deltaX = deltaX;
|
||||
}
|
||||
virtual inline double y(int64 id) {return (*yData)[int(id)];}
|
||||
virtual inline double x(int64 id) {return id*deltaX + x0;}
|
||||
virtual inline int64 GetCount() {return yData->GetCount();}
|
||||
|
|
@ -188,7 +221,13 @@ private:
|
|||
double x0, deltaX;
|
||||
|
||||
public:
|
||||
ArrayY(Upp::Array<Y> &yData, double x0, double deltaX) : yData(&yData), x0(x0), deltaX(deltaX) {}
|
||||
ArrayY() : yData(0), x0(0), deltaX(0) {}
|
||||
ArrayY(Upp::Array<Y> &yData, double x0, double deltaX) {Init(yData, x0, deltaX);}
|
||||
void Init(Upp::Array<Y> &yData, double x0, double deltaX) {
|
||||
this->yData = &yData;
|
||||
this->x0 = x0;
|
||||
this->deltaX = deltaX;
|
||||
}
|
||||
virtual inline double y(int64 id) {return (*yData)[ptrdiff_t(id)];}
|
||||
virtual inline double x(int64 id) {return id*deltaX + x0;}
|
||||
virtual inline int64 GetCount() {return yData->GetCount();}
|
||||
|
|
@ -210,35 +249,35 @@ private:
|
|||
public:
|
||||
VectorVectorY() : data(0), useRows(true), beginData(0), numData(Null), idx(0), idy(1) {}
|
||||
VectorVectorY(Vector<Vector<Y> > &data, int idx, int idy,
|
||||
Vector<int> &idsx, Vector<int> &idsy, Vector<int> &idsFixed, bool useRows = true, int beginData = 0, int numData = Null) :
|
||||
data(&data), useRows(useRows), beginData(beginData), numData(numData) {
|
||||
Vector<int> &idsx, Vector<int> &idsy, Vector<int> &idsFixed,
|
||||
bool useRows = true, int beginData = 0, int numData = Null) {
|
||||
Init(data, idx, idy, idsx, idsy, idsFixed, useRows, beginData, numData);
|
||||
}
|
||||
void Init(Vector<Vector<Y> > &_data, int _idx, int _idy, Vector<int> &_idsx, Vector<int> &_idsy, Vector<int> &_idsFixed,
|
||||
bool _useRows = true, int _beginData = 0, int _numData = Null) {
|
||||
data = &_data;
|
||||
useRows = _useRows;
|
||||
void Init(Vector<Vector<Y> > &data, int idx, int idy, Vector<int> &idsx, Vector<int> &idsy, Vector<int> &idsFixed,
|
||||
bool useRows = true, int beginData = 0, int numData = Null) {
|
||||
this->data = &data;
|
||||
this->useRows = useRows;
|
||||
|
||||
idx = _idx;
|
||||
idy = _idy;
|
||||
idsx = clone(_idsx);
|
||||
idsy = clone(_idsy);
|
||||
idsFixed = clone(_idsFixed);
|
||||
beginData = _beginData;
|
||||
numData = _numData;
|
||||
if (IsNull(_numData)) {
|
||||
this->idx = idx;
|
||||
this->idy = idy;
|
||||
this->idsx = clone(idsx);
|
||||
this->idsy = clone(idsy);
|
||||
this->idsFixed = clone(idsFixed);
|
||||
this->beginData = beginData;
|
||||
this->numData = numData;
|
||||
if (IsNull(numData)) {
|
||||
if (!useRows) {
|
||||
if (data->IsEmpty())
|
||||
numData = 0;
|
||||
if (data.IsEmpty())
|
||||
this->numData = 0;
|
||||
else
|
||||
numData = (*data)[0].GetCount() - beginData;
|
||||
this->numData = data[0].GetCount() - beginData;
|
||||
} else
|
||||
numData = data->GetCount() - beginData;
|
||||
this->numData = data.GetCount() - beginData;
|
||||
}
|
||||
}
|
||||
void Init(Vector<Vector<Y> > &_data, int idx, int idy, bool _useRows = true, int _beginData = 0, int _numData = Null) {
|
||||
void Init(Vector<Vector<Y> > &data, int idx, int idy, bool useRows = true, int beginData = 0, int numData = Null) {
|
||||
static Vector<int> idsVoid;
|
||||
Init(_data, idx, idy, idsVoid, idsVoid, idsVoid, _useRows, _beginData, _numData);
|
||||
Init(data, idx, idy, idsVoid, idsVoid, idsVoid, useRows, beginData, numData);
|
||||
}
|
||||
virtual inline double y(int64 id) {
|
||||
if (!IsNull(idy) && idy >= 0) {
|
||||
|
|
@ -342,22 +381,23 @@ public:
|
|||
virtual inline double x(int64 id) {return (*data).GetKey(int(id));}
|
||||
virtual inline int64 GetCount() {return data->GetCount();}
|
||||
};
|
||||
|
||||
|
||||
class FuncSource : public DataSource {
|
||||
private:
|
||||
double (*function)(double);
|
||||
protected:
|
||||
Function <double(double)> function;
|
||||
|
||||
public:
|
||||
FuncSource(double (*function)(double)) : function(function) {isExplicit = true;}
|
||||
FuncSource() {isExplicit = true;}
|
||||
FuncSource(Function <double(double)> function) : function(function) {isExplicit = true;}
|
||||
virtual inline double f(double x) {return function(x);}
|
||||
};
|
||||
|
||||
class FuncSourceV : public DataSource {
|
||||
private:
|
||||
void (*function)(double&, double);
|
||||
Event<double&, double> function;
|
||||
|
||||
public:
|
||||
FuncSourceV(void (*function)(double&, double)) : function(function) {isExplicit = true;}
|
||||
FuncSourceV(Event<double&, double> function) : function(function) {isExplicit = true;}
|
||||
virtual inline double f(double x) {double y; function(y, x); return y;}
|
||||
};
|
||||
|
||||
|
|
@ -392,8 +432,9 @@ public:
|
|||
virtual inline int64 GetCount() {return numPoints;}
|
||||
};
|
||||
|
||||
typedef Callback2<double&, double> PlotExplicFunc;
|
||||
typedef Callback2<Pointf&, double> PlotParamFunc;
|
||||
typedef Event<double&, double> PlotExplicFunc;
|
||||
typedef Event<Pointf&, double> PlotParamFunc;
|
||||
|
||||
|
||||
class PlotExplicFuncSource : public DataSource {
|
||||
private:
|
||||
|
|
@ -439,7 +480,6 @@ struct PointfLess {
|
|||
bool operator () (const Pointf& a, const Pointf& b) const { return a.x < b.x; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ void ExplicitEquation::SetNumCoeff(int num) {
|
|||
}
|
||||
|
||||
ExplicitEquation::FitError ExplicitEquation::Fit(DataSource &series, double &r2) {
|
||||
r2 = 0;
|
||||
if (series.IsExplicit() || series.IsParam())
|
||||
return InadequateDataSource;
|
||||
|
||||
|
|
@ -61,20 +60,27 @@ ExplicitEquation::FitError ExplicitEquation::Fit(DataSource &series, double &r2)
|
|||
if (ret == LevenbergMarquardtSpace::TooManyFunctionEvaluation)
|
||||
return TooManyFunctionEvaluation;
|
||||
|
||||
double mean = series.AvgY();
|
||||
r2 = R2Y(series);
|
||||
|
||||
return NoError;
|
||||
}
|
||||
|
||||
double ExplicitEquation::R2Y(DataSource &series, double mean) {
|
||||
if (IsNull(mean))
|
||||
mean = series.AvgY();
|
||||
double sse = 0, sst = 0;
|
||||
for (int64 i = 0; i < series.GetCount(); ++i) {
|
||||
double y = series.y(i);
|
||||
if (!IsNull(y)) {
|
||||
double res = y - f(series.x(i));
|
||||
sse += res*res;
|
||||
double err = y - f(series.x(i));
|
||||
sse += err*err;
|
||||
double d = y - mean;
|
||||
sst += d*d;
|
||||
}
|
||||
}
|
||||
r2 = 1 - sse/sst;
|
||||
|
||||
return NoError;
|
||||
if (sst == 0)
|
||||
return Null;
|
||||
return 1 - sse/sst;
|
||||
}
|
||||
|
||||
int ExplicitEquation::maxFitFunctionEvaluations = 1000;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
double R2Y(DataSource &series, double mean = Null);
|
||||
|
||||
protected:
|
||||
Vector<double> coeff;
|
||||
|
|
|
|||
|
|
@ -779,6 +779,19 @@ double ScatterDraw::GetValueX(int index, int64 idata) {
|
|||
}
|
||||
}
|
||||
|
||||
Value ScatterDraw::GetStringX(int index, int64 idata) {
|
||||
double ret = GetValueX(index, idata);
|
||||
if (IsNull(ret))
|
||||
return Null;
|
||||
if (cbModifFormatX) {
|
||||
String sret;
|
||||
cbModifFormatX(sret, int(idata), ret);
|
||||
return sret;
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
double ScatterDraw::GetValueY(int index, int64 idata) {
|
||||
ASSERT(IsValid(index) && !IsNull(GetCount(index)));
|
||||
ASSERT(idata >= 0 && idata < series[index].PointsData()->GetCount());
|
||||
|
|
@ -789,8 +802,21 @@ double ScatterDraw::GetValueY(int index, int64 idata) {
|
|||
return Null;
|
||||
}
|
||||
}
|
||||
|
||||
Value ScatterDraw::GetStringY(int index, int64 idata) {
|
||||
double ret = GetValueY(index, idata);
|
||||
if (IsNull(ret))
|
||||
return Null;
|
||||
String sret;
|
||||
if (cbModifFormatY) {
|
||||
String sret;
|
||||
cbModifFormatY(sret, int(idata), ret);
|
||||
return sret;
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
|
||||
ScatterDraw &ScatterDraw::SetNoPlot(int index) {
|
||||
ScatterDraw &ScatterDraw::SetNoPlot(int index) {
|
||||
ASSERT(IsValid(index));
|
||||
|
||||
series[index].seriesPlot = NULL;
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ public:
|
|||
ScatterDraw &SetZoomStyleX(ZoomStyle style = TO_CENTER) {zoomStyleX = style; return *this;}
|
||||
ScatterDraw &SetZoomStyleY(ZoomStyle style = TO_CENTER) {zoomStyleY = style; return *this;}
|
||||
|
||||
ScatterDraw& SetRange(double rx, double ry, double ry2 = 100);
|
||||
ScatterDraw& SetRange(double rx, double ry = Null, double ry2 = Null);
|
||||
//double GetRangeX() {return xRange;}
|
||||
//double GetRangeY() {return yRange;}
|
||||
//double GetRangeY2() {return yRange2;}
|
||||
|
|
@ -363,7 +363,9 @@ public:
|
|||
int64 GetCount(int index);
|
||||
void GetValues(int index, int64 idata, double &x, double &y);
|
||||
double GetValueX(int index, int64 idata);
|
||||
Value GetStringX(int index, int64 idata);
|
||||
double GetValueY(int index, int64 idata);
|
||||
Value GetStringY(int index, int64 idata);
|
||||
|
||||
ScatterDraw &SetNoPlot(int index);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue