File indexing completed on 2024-12-22 04:18:07
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2007 The University of Toronto * 0004 * netterfield@astro.utoronto.ca * 0005 * copyright : (C) 2005 University of British Columbia * 0006 * dscott@phas.ubc.ca * 0007 * * 0008 * This program is free software; you can redistribute it and/or modify * 0009 * it under the terms of the GNU General Public License as published by * 0010 * the Free Software Foundation; either version 2 of the License, or * 0011 * (at your option) any later version. * 0012 * * 0013 ***************************************************************************/ 0014 0015 /* a type of spectrum. I'm not sure how this relates to the built in 0016 power spectrums. It could be removed from the default build (?) */ 0017 0018 #include "periodogram.h" 0019 #include "objectstore.h" 0020 #include "ui_periodogramconfig.h" 0021 0022 #define ONE_PI 3.1415926535897930475926 0023 #define TWO_PI 6.2831853071795858696103 0024 #define MACC 4.0 0025 0026 static const QString& VECTOR_IN_TIME = "Vector In Time"; 0027 static const QString& VECTOR_IN_DATA = "Vector In Data"; 0028 static const QString& SCALAR_IN_OVERSAMPLING = "Oversampling factor"; 0029 static const QString& SCALAR_IN_ANFF = "Average Nyquist outputVectorFrequency factor"; 0030 0031 static const QString& VECTOR_OUT_FREQUENCY = "Frequency"; 0032 static const QString& VECTOR_OUT_PERIODOGRAM = "Periodogram"; 0033 0034 class ConfigPeriodogramPlugin : public Kst::DataObjectConfigWidget, public Ui_PeriodogramConfig { 0035 public: 0036 ConfigPeriodogramPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_PeriodogramConfig() { 0037 _store = 0; 0038 setupUi(this); 0039 } 0040 0041 ~ConfigPeriodogramPlugin() {} 0042 0043 void setObjectStore(Kst::ObjectStore* store) { 0044 _store = store; 0045 _vectorTime->setObjectStore(store); 0046 _vectorData->setObjectStore(store); 0047 _scalarOversampling->setObjectStore(store); 0048 _scalarANFF->setObjectStore(store); 0049 _scalarOversampling->setDefaultValue(0); 0050 _scalarANFF->setDefaultValue(0); 0051 } 0052 0053 void setupSlots(QWidget* dialog) { 0054 if (dialog) { 0055 connect(_vectorTime, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0056 connect(_vectorData, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0057 connect(_scalarOversampling, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0058 connect(_scalarANFF, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0059 } 0060 } 0061 0062 Kst::VectorPtr selectedVectorTime() { return _vectorTime->selectedVector(); }; 0063 void setSelectedVectorTime(Kst::VectorPtr vector) { return _vectorTime->setSelectedVector(vector); }; 0064 0065 Kst::VectorPtr selectedVectorData() { return _vectorData->selectedVector(); }; 0066 void setSelectedVectorData(Kst::VectorPtr vector) { return _vectorData->setSelectedVector(vector); }; 0067 0068 Kst::ScalarPtr selectedScalarOversampling() { return _scalarOversampling->selectedScalar(); }; 0069 void setSelectedScalarOversampling(Kst::ScalarPtr scalar) { return _scalarOversampling->setSelectedScalar(scalar); }; 0070 0071 Kst::ScalarPtr selectedScalarANFF() { return _scalarANFF->selectedScalar(); }; 0072 void setSelectedScalarANFF(Kst::ScalarPtr scalar) { return _scalarANFF->setSelectedScalar(scalar); }; 0073 0074 virtual void setupFromObject(Kst::Object* dataObject) { 0075 if (PeriodogramSource* source = static_cast<PeriodogramSource*>(dataObject)) { 0076 setSelectedVectorTime(source->vectorTime()); 0077 setSelectedVectorData(source->vectorData()); 0078 setSelectedScalarOversampling(source->scalarOversampling()); 0079 setSelectedScalarANFF(source->scalarANFF()); 0080 } 0081 } 0082 0083 virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) { 0084 Q_UNUSED(store); 0085 Q_UNUSED(attrs); 0086 0087 bool validTag = true; 0088 0089 // QStringRef av; 0090 // av = attrs.value("value"); 0091 // if (!av.isNull()) { 0092 // _configValue = QVariant(av.toString()).toBool(); 0093 // } 0094 0095 return validTag; 0096 } 0097 0098 public slots: 0099 virtual void save() { 0100 if (_cfg) { 0101 _cfg->beginGroup("Periodogram DataObject Plugin"); 0102 _cfg->setValue("Input Vector Time", _vectorTime->selectedVector()->Name()); 0103 _cfg->setValue("Input Vector Data", _vectorData->selectedVector()->Name()); 0104 _cfg->setValue("Input Scalar Oversampling factor", _scalarOversampling->selectedScalar()->Name()); 0105 _cfg->setValue("Input Scalar Average Nyquist outputVectorFrequency factor", _scalarANFF->selectedScalar()->Name()); 0106 _cfg->endGroup(); 0107 } 0108 } 0109 0110 virtual void load() { 0111 if (_cfg && _store) { 0112 _cfg->beginGroup("Periodogram DataObject Plugin"); 0113 QString vectorName = _cfg->value("Input Vector Time").toString(); 0114 Kst::Object* object = _store->retrieveObject(vectorName); 0115 Kst::Vector* vectorTime = static_cast<Kst::Vector*>(object); 0116 if (vectorTime) { 0117 setSelectedVectorTime(vectorTime); 0118 } 0119 vectorName = _cfg->value("Input Vector Data").toString(); 0120 object = _store->retrieveObject(vectorName); 0121 Kst::Vector* vectorData = static_cast<Kst::Vector*>(object); 0122 if (vectorData) { 0123 setSelectedVectorData(vectorData); 0124 } 0125 QString scalarName = _cfg->value("Input Scalar Oversampling factor").toString(); 0126 object = _store->retrieveObject(scalarName); 0127 Kst::Scalar* scalarOversampling = static_cast<Kst::Scalar*>(object); 0128 if (scalarOversampling) { 0129 setSelectedScalarOversampling(scalarOversampling); 0130 } 0131 scalarName = _cfg->value("Input Scalar Average Nyquist outputVectorFrequency factor").toString(); 0132 object = _store->retrieveObject(scalarName); 0133 Kst::Scalar* scalarANFF = static_cast<Kst::Scalar*>(object); 0134 if (scalarANFF) { 0135 setSelectedScalarANFF(scalarANFF); 0136 } 0137 _cfg->endGroup(); 0138 } 0139 } 0140 0141 private: 0142 Kst::ObjectStore *_store; 0143 0144 }; 0145 0146 0147 PeriodogramSource::PeriodogramSource(Kst::ObjectStore *store) 0148 : Kst::BasicPlugin(store) { 0149 } 0150 0151 0152 PeriodogramSource::~PeriodogramSource() { 0153 } 0154 0155 0156 QString PeriodogramSource::_automaticDescriptiveName() const { 0157 return tr("Periodogram Plugin Object"); 0158 } 0159 0160 0161 void PeriodogramSource::change(Kst::DataObjectConfigWidget *configWidget) { 0162 if (ConfigPeriodogramPlugin* config = static_cast<ConfigPeriodogramPlugin*>(configWidget)) { 0163 setInputVector(VECTOR_IN_TIME, config->selectedVectorTime()); 0164 setInputVector(VECTOR_IN_DATA, config->selectedVectorData()); 0165 setInputScalar(SCALAR_IN_OVERSAMPLING, config->selectedScalarOversampling()); 0166 setInputScalar(SCALAR_IN_ANFF, config->selectedScalarANFF()); 0167 } 0168 } 0169 0170 0171 void PeriodogramSource::setupOutputs() { 0172 setOutputVector(VECTOR_OUT_FREQUENCY, ""); 0173 setOutputVector(VECTOR_OUT_PERIODOGRAM, ""); 0174 } 0175 0176 0177 bool PeriodogramSource::algorithm() { 0178 Kst::VectorPtr inputVectorTime = _inputVectors[VECTOR_IN_TIME]; 0179 Kst::VectorPtr inputVectorData = _inputVectors[VECTOR_IN_DATA]; 0180 Kst::ScalarPtr inputScalarOversampling = _inputScalars[SCALAR_IN_OVERSAMPLING]; 0181 Kst::ScalarPtr inputScalarANFF = _inputScalars[SCALAR_IN_ANFF]; 0182 0183 Kst::VectorPtr outputVectorFrequency = _outputVectors[VECTOR_OUT_FREQUENCY]; 0184 Kst::VectorPtr outputVectorPeriodogram = _outputVectors[VECTOR_OUT_PERIODOGRAM]; 0185 0186 unsigned long lSizeWork; 0187 unsigned long lSizeOut = 0; 0188 unsigned long lSizeIn; 0189 unsigned long lFreqt; 0190 unsigned long lFreq; 0191 unsigned long lMax; 0192 double dProb; 0193 double dVar; 0194 double* pResult[2]; 0195 bool bReturn = false; 0196 0197 //Make sure the input sizes match 0198 if (inputVectorTime->length() != inputVectorData->length()) { 0199 _errorString = tr("Error: Input Vector lengths do not match"); 0200 return false; 0201 } 0202 0203 lSizeIn = inputVectorTime->length(); 0204 if (lSizeIn > 1) { 0205 lFreqt = (unsigned long)( MACC * inputScalarOversampling->value() * inputScalarANFF->value() * lSizeIn ); 0206 lFreq = 64; 0207 while (lFreq < lFreqt) { 0208 lFreq *= 2; 0209 } 0210 lSizeWork = lFreq * 2; 0211 0212 outputVectorFrequency->resize(lSizeWork, true); 0213 pResult[0] = outputVectorFrequency->raw_V_ptr(); 0214 0215 outputVectorPeriodogram->resize(lSizeWork, true); 0216 pResult[1] = outputVectorPeriodogram->raw_V_ptr(); 0217 0218 if (pResult[0] != NULL && pResult[1] != NULL) { 0219 0220 for (int i = 0; i < outputVectorFrequency->length(); ++i) { 0221 outputVectorFrequency->raw_V_ptr()[i] = pResult[0][i]; 0222 } 0223 for (int i = 0; i < outputVectorPeriodogram->length(); ++i) { 0224 outputVectorPeriodogram->raw_V_ptr()[i] = pResult[1][i]; 0225 } 0226 0227 if (lSizeIn > 100) { 0228 FastLombPeriodogram( 0229 (double*)&(inputVectorTime->value()[-1]), 0230 (double*)&(inputVectorData->value()[-1]), 0231 inputVectorTime->length(), 0232 inputScalarOversampling->value(), 0233 inputScalarANFF->value(), 0234 (double*)&(outputVectorFrequency->raw_V_ptr()[-1]), 0235 (double*)&(outputVectorPeriodogram->raw_V_ptr()[-1]), 0236 lSizeWork, 0237 &lSizeOut, 0238 &lMax, 0239 &dProb, 0240 &dVar, 0241 0 ); 0242 } else { 0243 SlowLombPeriodogram( 0244 (double*)&(inputVectorTime->value()[-1]), 0245 (double*)&(inputVectorData->value()[-1]), 0246 inputVectorTime->length(), 0247 inputScalarOversampling->value(), 0248 inputScalarANFF->value(), 0249 (double*)&(outputVectorFrequency->raw_V_ptr()[-1]), 0250 (double*)&(outputVectorPeriodogram->raw_V_ptr()[-1]), 0251 lSizeWork, 0252 &lSizeOut, 0253 &lMax, 0254 &dProb, 0255 &dVar, 0256 0 ); 0257 } 0258 0259 if (lSizeOut > 0 && lSizeOut <= lSizeWork) { 0260 outputVectorFrequency->resize(lSizeOut, false); 0261 outputVectorPeriodogram->resize(lSizeOut, false); 0262 0263 bReturn = true; 0264 } 0265 } 0266 } 0267 0268 return bReturn; 0269 } 0270 0271 0272 Kst::VectorPtr PeriodogramSource::vectorTime() const { 0273 return _inputVectors[VECTOR_IN_TIME]; 0274 } 0275 0276 0277 Kst::VectorPtr PeriodogramSource::vectorData() const { 0278 return _inputVectors[VECTOR_IN_DATA]; 0279 } 0280 0281 0282 Kst::ScalarPtr PeriodogramSource::scalarOversampling() const { 0283 return _inputScalars[SCALAR_IN_OVERSAMPLING]; 0284 } 0285 0286 0287 Kst::ScalarPtr PeriodogramSource::scalarANFF() const { 0288 return _inputScalars[SCALAR_IN_ANFF]; 0289 } 0290 0291 0292 QStringList PeriodogramSource::inputVectorList() const { 0293 QStringList vectors(VECTOR_IN_TIME); 0294 vectors += VECTOR_IN_DATA; 0295 return vectors; 0296 } 0297 0298 0299 QStringList PeriodogramSource::inputScalarList() const { 0300 QStringList scalars(SCALAR_IN_OVERSAMPLING); 0301 scalars += SCALAR_IN_ANFF; 0302 return scalars; 0303 } 0304 0305 0306 QStringList PeriodogramSource::inputStringList() const { 0307 return QStringList( /*STRING_IN*/ ); 0308 } 0309 0310 0311 QStringList PeriodogramSource::outputVectorList() const { 0312 QStringList vectors(VECTOR_OUT_FREQUENCY); 0313 vectors += VECTOR_OUT_PERIODOGRAM; 0314 return vectors; 0315 } 0316 0317 0318 QStringList PeriodogramSource::outputScalarList() const { 0319 return QStringList( /*SCALAR_OUT*/ ); 0320 } 0321 0322 0323 QStringList PeriodogramSource::outputStringList() const { 0324 return QStringList( /*STRING_OUT*/ ); 0325 } 0326 0327 0328 void PeriodogramSource::saveProperties(QXmlStreamWriter &s) { 0329 Q_UNUSED(s); 0330 // s.writeAttribute("value", _configValue); 0331 } 0332 0333 0334 int PeriodogramSource::max(int a, int b) { 0335 if (a > b) { 0336 return a; 0337 } 0338 return b; 0339 } 0340 0341 0342 int PeriodogramSource::min(int a, int b) { 0343 if (a < b) { 0344 return a; 0345 } 0346 return b; 0347 } 0348 0349 0350 void PeriodogramSource::spread(double y, double yy[], unsigned long n, double x, int m) { 0351 int ihi; 0352 int ilo; 0353 int ix; 0354 int j; 0355 int nden; 0356 double fac; 0357 static int nfac[] = { 0, 0358 1, 0359 1, 0360 2, 0361 6, 0362 24, 0363 120, 0364 720, 0365 5040, 0366 40320, 0367 362880, 0368 39916800, 0369 479001600 }; 0370 0371 ix = (int)x; 0372 if (x == (double)ix) { 0373 yy[ix] += y; 0374 } else { 0375 ilo = min(max((int)(x - 0.5*m + 1.0), 1), (int)(n - m + 1)); 0376 ihi = ilo + m - 1; 0377 nden = nfac[m]; 0378 fac = x - ilo; 0379 for (j = ilo + 1;j <= ihi;++j) { 0380 fac *= x - (double)j; 0381 } 0382 yy[ihi] += y*fac/(double)(nden*(x - ihi)); 0383 for (j = ihi-1;j >= ilo;j--) { 0384 nden=(nden/(j+1-ilo))*(j-ihi); 0385 yy[j] += y*fac/(double)(nden*(x - j)); 0386 } 0387 } 0388 } 0389 0390 0391 void PeriodogramSource::four1(double data[], unsigned long nn, int isign) { 0392 unsigned long n; 0393 unsigned long mmax; 0394 unsigned long m; 0395 unsigned long j; 0396 unsigned long istep; 0397 unsigned long i; 0398 double dtemp; 0399 double wtemp; 0400 double wr; 0401 double wpr; 0402 double wpi; 0403 double wi; 0404 double theta; 0405 double tempr; 0406 double tempi; 0407 0408 n = nn << 1; 0409 j = 1; 0410 for (i = 1;i < n;i += 2) { 0411 if (j > i) { 0412 dtemp = data[i]; 0413 data[i] = data[j]; 0414 data[j] = dtemp; 0415 0416 dtemp = data[i+1]; 0417 data[i+1] = data[j+1]; 0418 data[j+1] = dtemp; 0419 } 0420 0421 m = n >> 1; 0422 while (m >= 2 && j > m) { 0423 j -= m; 0424 m >>= 1; 0425 } 0426 j += m; 0427 } 0428 0429 mmax = 2; 0430 while (n > mmax) { 0431 istep = mmax * 2; 0432 theta = isign*(TWO_PI/mmax); 0433 wtemp = sin(0.5*theta); 0434 wpr = -2.0*wtemp*wtemp; 0435 wpi = sin(theta); 0436 wr = 1.0; 0437 wi = 0.0; 0438 0439 for (m = 1;m < mmax;m += 2) { 0440 for (i = m;i <= n;i += istep) { 0441 j = i + mmax; 0442 tempr = wr*data[j] - wi*data[j+1]; 0443 tempi = wr*data[j+1] + wi*data[j]; 0444 data[j] = data[i] - tempr; 0445 data[j+1] = data[i+1] - tempi; 0446 data[i] += tempr; 0447 data[i+1] += tempi; 0448 } 0449 wr = (wtemp = wr)*wpr - wi*wpi + wr; 0450 wi = wi*wpr + wtemp*wpi + wi; 0451 } 0452 mmax = istep; 0453 } 0454 } 0455 0456 0457 void PeriodogramSource::realft(double data[], unsigned long n, int isign) { 0458 unsigned long i; 0459 unsigned long i1; 0460 unsigned long i2; 0461 unsigned long i3; 0462 unsigned long i4; 0463 unsigned long np3; 0464 double c1 = 0.5; 0465 double c2; 0466 double h1r; 0467 double h1i; 0468 double h2r; 0469 double h2i; 0470 double wr; 0471 double wi; 0472 double wpr; 0473 double wpi; 0474 double wtemp; 0475 double theta; 0476 0477 theta = ONE_PI / (double)(n>>1); 0478 if (isign == 1) { 0479 c2 = -0.5; 0480 four1(data, n>>1, 1); 0481 } else { 0482 c2 = 0.5; 0483 theta = -theta; 0484 } 0485 wtemp = sin(0.5*theta); 0486 wpr = -2.0*wtemp*wtemp; 0487 wpi = sin(theta); 0488 wr = 1.0 + wpr; 0489 wi = wpi; 0490 np3 = n+3; 0491 for (i = 2;i <= (n>>2);++i) { 0492 i1 = (2*i) - 1; 0493 i2 = i1 + 1; 0494 i3 = np3 - i2; 0495 i4 = i3 + 1; 0496 h1r = c1*(data[i1] + data[i3]); 0497 h1i = c1*(data[i2] - data[i4]); 0498 h2r = -c2*(data[i2] + data[i4]); 0499 h2i = c2*(data[i1] - data[i3]); 0500 data[i1] = h1r + wr*h2r - wi*h2i; 0501 data[i2] = h1i + wr*h2i + wi*h2r; 0502 data[i3] = h1r - wr*h2r + wi*h2i; 0503 data[i4] = -h1i + wr*h2i + wi*h2r; 0504 wtemp = wr; 0505 wr = wr*wpr - wi*wpi + wr; 0506 wi = wi*wpr + wtemp*wpi + wi; 0507 } 0508 0509 if (isign == 1) { 0510 h1r = data[1]; 0511 data[1] = h1r + data[2]; 0512 data[2] = h1r - data[2]; 0513 } else { 0514 h1r = data[1]; 0515 data[1] = c1*(h1r + data[2]); 0516 data[2] = c1*(h1r - data[2]); 0517 four1(data, n>>1, -1); 0518 } 0519 } 0520 0521 0522 void PeriodogramSource::avevar( 0523 double const data[], 0524 unsigned long n, 0525 double* ave, 0526 double* var) { 0527 unsigned long j; 0528 double s; 0529 double ep; 0530 0531 *ave = 0.0; 0532 *var = 0.0; 0533 ep = 0.0; 0534 0535 if (n > 0) { 0536 for (*ave = 0.0, j = 1;j <= n;++j) { 0537 *ave += data[j]; 0538 } 0539 *ave /= n; 0540 0541 if (n > 1) { 0542 for (j = 1;j <= n;++j) { 0543 s = data[j] - (*ave); 0544 ep += s; 0545 *var += s*s; 0546 } 0547 0548 *var = (*var - ep * ep / n) / (n - 1); 0549 } 0550 } 0551 } 0552 0553 0554 void PeriodogramSource::FastLombPeriodogram( 0555 double const x[], 0556 double const y[], 0557 unsigned long n, 0558 double ofac, 0559 double hifac, 0560 double wk1[], 0561 double wk2[], 0562 unsigned long ndim, 0563 unsigned long* nout, 0564 unsigned long* jmax, 0565 double* prob, 0566 double* pvar, 0567 int iIsWindowFunction) { 0568 unsigned long j; 0569 unsigned long k; 0570 double ave; 0571 double ck; 0572 double ckk; 0573 double cterm; 0574 double cwt; 0575 double den; 0576 double df; 0577 double effm; 0578 double expy; 0579 double fac; 0580 double fndim; 0581 double hc2wt; 0582 double hs2wt; 0583 double hypo; 0584 double pmax; 0585 double sterm; 0586 double swt; 0587 double xdif; 0588 double xmax; 0589 double xmin; 0590 0591 if (n > 0) { 0592 *nout = (unsigned long)(0.5 * ofac * hifac * n); 0593 0594 if (iIsWindowFunction) { 0595 ave = 0.0; 0596 *pvar = 0.0; 0597 } else { 0598 avevar(y, n, &ave, pvar); 0599 } 0600 0601 xmax = x[1]; 0602 xmin = x[1]; 0603 for (j = 2;j <= n;++j) { 0604 if (x[j] < xmin) { 0605 xmin = x[j]; 0606 } 0607 if (x[j] > xmax) { 0608 xmax = x[j]; 0609 } 0610 } 0611 xdif = xmax - xmin; 0612 for (j = 1;j <= ndim;++j) { 0613 wk1[j] = 0.0; 0614 wk2[j] = 0.0; 0615 } 0616 0617 fac = ndim / (xdif * ofac); 0618 fndim = ndim; 0619 0620 for (j = 1;j <= n;++j) { 0621 ck = (x[j] - xmin) * fac; 0622 ck = fmod(ck, fndim); 0623 ckk = 2.0*(ck++); 0624 ckk = fmod(ckk, fndim); 0625 ++ckk; 0626 spread(y[j] - ave, wk1, ndim, ck, (int)MACC); 0627 spread(1.0, wk2, ndim, ckk, (int)MACC); 0628 } 0629 0630 realft(wk1, ndim, 1); 0631 realft(wk2, ndim, 1); 0632 df = 1.0 / (xdif * ofac); 0633 pmax = -1.0; 0634 for (k = 3, j = 1;j <= (*nout);j++, k += 2) { 0635 hypo = sqrt(wk2[k]*wk2[k] + wk2[k+1]*wk2[k+1]); 0636 hc2wt = 0.5 * wk2[k ] / hypo; 0637 hs2wt = 0.5 * wk2[k+1] / hypo; 0638 cwt = sqrt(0.5 + hc2wt); 0639 swt = fabs(sqrt(0.5 - hc2wt)); 0640 if (hs2wt < 0.0) { 0641 swt *= -1.0; 0642 } 0643 den = 0.5*n + hc2wt*wk2[k] + hs2wt*wk2[k+1]; 0644 cterm = pow(cwt*wk1[k+0] + swt*wk1[k+1], 2.0) / den; 0645 if ((double)n - den == 0.0) { 0646 sterm = 0.0; 0647 } else { 0648 sterm = pow(cwt*wk1[k+1] - swt*wk1[k+0], 2.0) / ((double)n - den); 0649 } 0650 wk1[j] = (double)j * df; 0651 wk2[j] = (cterm + sterm); 0652 if (*pvar > 0.0) { 0653 wk2[j] /= (2.0 * *pvar); 0654 } 0655 if (wk2[j] > pmax) { 0656 pmax = wk2[ (*jmax = j) ]; 0657 } 0658 } 0659 expy = exp(-pmax); 0660 effm = 2.0 * (*nout) / ofac; 0661 *prob = effm * expy; 0662 if (*prob > 0.01) { 0663 *prob = 1.0 - pow(1.0 - expy, effm); 0664 } 0665 } else { 0666 *nout = 0; 0667 } 0668 } 0669 0670 0671 void PeriodogramSource::SlowLombPeriodogram( 0672 double const x[], 0673 double const y[], 0674 unsigned long n, 0675 double ofac, 0676 double hifac, 0677 double px[], 0678 double py[], 0679 unsigned long /*ndim*/, 0680 unsigned long* nout, 0681 unsigned long* jmax, 0682 double* prob, 0683 double* pvar, 0684 int iIsWindowFunction) { 0685 0686 unsigned long i; 0687 unsigned long j; 0688 double* wi = NULL; 0689 double* wpi = NULL; 0690 double* wpr = NULL; 0691 double* wr = NULL; 0692 double arg; 0693 double wtemp; 0694 double ave; 0695 double c; 0696 double cc; 0697 double cwtau; 0698 double effm; 0699 double expy; 0700 double pnow; 0701 double pymax; 0702 double s; 0703 double ss; 0704 double sumc; 0705 double sumcy; 0706 double sums; 0707 double sumsh; 0708 double sumsy; 0709 double swtau; 0710 double wtau; 0711 double xave; 0712 double xdif; 0713 double xmax; 0714 double xmin; 0715 double yy; 0716 0717 if (n > 0) { 0718 wi = (double*)calloc(n+1, sizeof(double)); 0719 wpi = (double*)calloc(n+1, sizeof(double)); 0720 wpr = (double*)calloc(n+1, sizeof(double)); 0721 wr = (double*)calloc(n+1, sizeof(double)); 0722 0723 if (wi != NULL && 0724 wpi != NULL && 0725 wpr != NULL && 0726 wr != NULL) { 0727 *nout = (unsigned long)(0.5*ofac*hifac*n); 0728 0729 if (iIsWindowFunction) { 0730 ave = 0.0; 0731 *pvar = 0.0; 0732 } else { 0733 avevar(y, n, &ave, pvar); 0734 } 0735 0736 xmax = x[1]; 0737 xmin = x[1]; 0738 for (j=1;j<=n;++j) { 0739 if (x[j] > xmax) { 0740 xmax = x[j]; 0741 } 0742 if (x[j] < xmin) { 0743 xmin = x[j]; 0744 } 0745 } 0746 xdif = xmax-xmin; 0747 xave = 0.5*(xmax+xmin); 0748 pymax = 0.0; 0749 pnow = 1.0/(xdif*ofac); 0750 for (j=1;j<=n;++j) { 0751 arg = TWO_PI*((x[j]-xave)*pnow); 0752 wpr[j] = -2.0*(sin(0.5*arg)*sin(0.5*arg)); 0753 wpi[j] = sin(arg); 0754 wr[j] = cos(arg); 0755 wi[j] = wpi[j]; 0756 } 0757 for (i=1;i<=(*nout);++i) { 0758 sumsh = 0.0; 0759 sumc = 0.0; 0760 px[i] = pnow; 0761 0762 for (j=1;j<=n;++j) { 0763 c = wr[j]; 0764 s = wi[j]; 0765 sumsh += s*c; 0766 sumc += (c-s)*(c+s); 0767 } 0768 wtau = 0.5 * atan2(2.0 * sumsh, sumc); 0769 swtau = sin(wtau); 0770 cwtau = cos(wtau); 0771 sums = 0.0; 0772 sumc = 0.0; 0773 sumsy = 0.0; 0774 sumcy = 0.0; 0775 for (j=1;j<=n;++j) { 0776 s = wi[j]; 0777 c = wr[j]; 0778 ss = s*cwtau-c*swtau; 0779 cc = c*cwtau+s*swtau; 0780 sums += ss*ss; 0781 sumc += cc*cc; 0782 yy = y[j]-ave; 0783 sumsy += yy*ss; 0784 sumcy += yy*cc; 0785 wtemp = wr[j]; 0786 wr[j] = (wr[j]*wpr[j]-wi[j]*wpi[j])+wr[j]; 0787 wi[j] = (wi[j]*wpr[j]+wtemp*wpi[j])+wi[j]; 0788 } 0789 py[i] = (sumcy * sumcy / sumc + sumsy * sumsy / sums); 0790 if (*pvar > 0.0) { 0791 py[i] /= (2.0 * (*pvar)); 0792 } 0793 if (py[i] >= pymax) { 0794 *jmax = i; 0795 pymax = py[i]; 0796 } 0797 pnow += 1.0/(xdif*ofac); 0798 } 0799 expy = exp(-pymax); 0800 effm = 2.0*(*nout)/ofac; 0801 *prob = effm*expy; 0802 if (*prob > 0.01) { 0803 *prob = 1.0 - pow(1.0 - expy, effm); 0804 } 0805 } 0806 0807 if (wi != NULL) { 0808 free(wi); 0809 } 0810 if (wpi != NULL) { 0811 free(wpi); 0812 } 0813 if (wpr != NULL) { 0814 free(wpr); 0815 } 0816 if (wr != NULL) { 0817 free(wr); 0818 } 0819 } else { 0820 *nout = 0; 0821 } 0822 } 0823 0824 0825 QString PeriodogramPlugin::pluginName() const { return tr("Periodogram"); } 0826 QString PeriodogramPlugin::pluginDescription() const { return tr("Takes the outputVectorPeriodogram of a given inputVectorData set. The inputVectorData is not assumed to be sampled at equal inputVectorTime intervals."); } 0827 0828 0829 Kst::DataObject *PeriodogramPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const { 0830 0831 if (ConfigPeriodogramPlugin* config = static_cast<ConfigPeriodogramPlugin*>(configWidget)) { 0832 0833 PeriodogramSource* object = store->createObject<PeriodogramSource>(); 0834 0835 if (setupInputsOutputs) { 0836 object->setInputScalar(SCALAR_IN_OVERSAMPLING, config->selectedScalarOversampling()); 0837 object->setInputScalar(SCALAR_IN_ANFF, config->selectedScalarANFF()); 0838 object->setupOutputs(); 0839 object->setInputVector(VECTOR_IN_TIME, config->selectedVectorTime()); 0840 object->setInputVector(VECTOR_IN_DATA, config->selectedVectorData()); 0841 } 0842 0843 object->setPluginName(pluginName()); 0844 0845 object->writeLock(); 0846 object->registerChange(); 0847 object->unlock(); 0848 0849 return object; 0850 } 0851 return 0; 0852 } 0853 0854 0855 Kst::DataObjectConfigWidget *PeriodogramPlugin::configWidget(QSettings *settingsObject) const { 0856 ConfigPeriodogramPlugin *widget = new ConfigPeriodogramPlugin(settingsObject); 0857 return widget; 0858 } 0859 0860 #ifndef QT5 0861 Q_EXPORT_PLUGIN2(kstplugin_BinPlugin, PeriodogramPlugin) 0862 #endif 0863 0864 // vim: ts=2 sw=2 et