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