File indexing completed on 2024-12-22 04:18:02

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 
0016 #include "crossspectrum.h"
0017 #include "objectstore.h"
0018 #include "ui_crossspectrumconfig.h"
0019 
0020 static const QString& VECTOR_IN_ONE = "Vector In One";
0021 static const QString& VECTOR_IN_TWO = "Vector In Two";
0022 static const QString& SCALAR_IN_FFT = "Scalar In FFT";
0023 static const QString& SCALAR_IN_RATE = "Scalar In Sample Rate";
0024 static const QString& VECTOR_OUT_FREQ = "Frequency";
0025 static const QString& VECTOR_OUT_IMAG = "Imaginary";
0026 static const QString& VECTOR_OUT_REAL = "Real";
0027 
0028 class ConfigCrossSpectrumPlugin : public Kst::DataObjectConfigWidget, public Ui_CrossSpectrumConfig {
0029   public:
0030     ConfigCrossSpectrumPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_CrossSpectrumConfig() {
0031       _store = 0;
0032       setupUi(this);
0033     }
0034 
0035     ~ConfigCrossSpectrumPlugin() {}
0036 
0037     void setObjectStore(Kst::ObjectStore* store) { 
0038       _store = store; 
0039       _vectorOne->setObjectStore(store);
0040       _vectorTwo->setObjectStore(store);
0041       _scalarFFT->setObjectStore(store);
0042       _scalarRate->setObjectStore(store);
0043       _scalarFFT->setDefaultValue(10);
0044       _scalarRate->setDefaultValue(100);
0045     }
0046 
0047     void setupSlots(QWidget* dialog) {
0048       if (dialog) {
0049         connect(_vectorOne, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0050         connect(_vectorTwo, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0051         connect(_scalarFFT, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0052         connect(_scalarRate, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0053       }
0054     }
0055 
0056     Kst::VectorPtr selectedVectorOne() { return _vectorOne->selectedVector(); };
0057     void setSelectedVectorOne(Kst::VectorPtr vector) { return _vectorOne->setSelectedVector(vector); };
0058 
0059     Kst::VectorPtr selectedVectorTwo() { return _vectorTwo->selectedVector(); };
0060     void setSelectedVectorTwo(Kst::VectorPtr vector) { return _vectorTwo->setSelectedVector(vector); };
0061 
0062     Kst::ScalarPtr selectedScalarFFT() { return _scalarFFT->selectedScalar(); };
0063     void setSelectedScalarFFT(Kst::ScalarPtr scalar) { return _scalarFFT->setSelectedScalar(scalar); };
0064 
0065     Kst::ScalarPtr selectedScalarRate() { return _scalarRate->selectedScalar(); };
0066     void setSelectedScalarRate(Kst::ScalarPtr scalar) { return _scalarRate->setSelectedScalar(scalar); };
0067 
0068     virtual void setupFromObject(Kst::Object* dataObject) {
0069       if (CrossSpectrumSource* source = static_cast<CrossSpectrumSource*>(dataObject)) {
0070         setSelectedVectorOne(source->vectorOne());
0071         setSelectedVectorTwo(source->vectorTwo());
0072         setSelectedScalarFFT(source->scalarFFT());
0073         setSelectedScalarRate(source->scalarRate());
0074       }
0075     }
0076 
0077     virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
0078       Q_UNUSED(store);
0079       Q_UNUSED(attrs);
0080 
0081       bool validTag = true;
0082 
0083 //       QStringRef av;
0084 //       av = attrs.value("value");
0085 //       if (!av.isNull()) {
0086 //         _configValue = QVariant(av.toString()).toBool();
0087 //       }
0088 
0089       return validTag;
0090     }
0091 
0092   public slots:
0093     virtual void save() {
0094       if (_cfg) {
0095         _cfg->beginGroup("Cross Spectrum DataObject Plugin");
0096         _cfg->setValue("Input Vector One", _vectorOne->selectedVector()->Name());
0097         _cfg->setValue("Input Vector Two", _vectorTwo->selectedVector()->Name());
0098         _cfg->setValue("Input Scalar FFT", _scalarFFT->selectedScalar()->Name());
0099         _cfg->setValue("Input Scalar Sample Rate", _scalarRate->selectedScalar()->Name());
0100         _cfg->endGroup();
0101       }
0102     }
0103 
0104     virtual void load() {
0105       if (_cfg && _store) {
0106         _cfg->beginGroup("Cross Spectrum DataObject Plugin");
0107         QString vectorName = _cfg->value("Input Vector One").toString();
0108         Kst::Object* object = _store->retrieveObject(vectorName);
0109         Kst::Vector* vectorOne = static_cast<Kst::Vector*>(object);
0110         if (vectorOne) {
0111           setSelectedVectorOne(vectorOne);
0112         }
0113         vectorName = _cfg->value("Input Vector Two").toString();
0114         object = _store->retrieveObject(vectorName);
0115         Kst::Vector* vectorTwo = static_cast<Kst::Vector*>(object);
0116         if (vectorTwo) {
0117           setSelectedVectorTwo(vectorTwo);
0118         }
0119         QString scalarName = _cfg->value("Input Scalar FFT").toString();
0120         object = _store->retrieveObject(scalarName);
0121         Kst::Scalar* scalarFFT = static_cast<Kst::Scalar*>(object);
0122         if (scalarFFT) {
0123           setSelectedScalarFFT(scalarFFT);
0124         }
0125         scalarName = _cfg->value("Input Scalar Sample Rate").toString();
0126         object = _store->retrieveObject(scalarName);
0127         Kst::Scalar* scalarRate = static_cast<Kst::Scalar*>(object);
0128         if (scalarRate) {
0129           setSelectedScalarRate(scalarRate);
0130         }
0131         _cfg->endGroup();
0132       }
0133     }
0134 
0135   private:
0136     Kst::ObjectStore *_store;
0137 
0138 };
0139 
0140 
0141 CrossSpectrumSource::CrossSpectrumSource(Kst::ObjectStore *store)
0142 : Kst::BasicPlugin(store) {
0143 }
0144 
0145 
0146 CrossSpectrumSource::~CrossSpectrumSource() {
0147 }
0148 
0149 
0150 QString CrossSpectrumSource::_automaticDescriptiveName() const {
0151   return tr("Cross Spectrum");
0152 }
0153 
0154 
0155 void CrossSpectrumSource::change(Kst::DataObjectConfigWidget *configWidget) {
0156   if (ConfigCrossSpectrumPlugin* config = static_cast<ConfigCrossSpectrumPlugin*>(configWidget)) {
0157     setInputVector(VECTOR_IN_ONE, config->selectedVectorOne());
0158     setInputVector(VECTOR_IN_TWO, config->selectedVectorTwo());
0159     setInputScalar(SCALAR_IN_FFT, config->selectedScalarFFT());
0160     setInputScalar(SCALAR_IN_RATE, config->selectedScalarRate());
0161   }
0162 }
0163 
0164 
0165 void CrossSpectrumSource::setupOutputs() {
0166   setOutputVector(VECTOR_OUT_FREQ, "");
0167   setOutputVector(VECTOR_OUT_IMAG, "");
0168   setOutputVector(VECTOR_OUT_REAL, "");
0169 }
0170 
0171 #define KSTPSDMAXLEN 27
0172 extern "C" void rdft(int n, int isgn, double *a); //fast fourier transform...
0173 
0174 bool CrossSpectrumSource::algorithm() {
0175   Kst::VectorPtr iv1 = _inputVectors[VECTOR_IN_ONE];
0176   Kst::VectorPtr iv2 = _inputVectors[VECTOR_IN_TWO];
0177 
0178   double fft_len_exponent = _inputScalars[SCALAR_IN_FFT]->value();
0179   double SR = _inputScalars[SCALAR_IN_RATE]->value();
0180 
0181   int xps_len;
0182   
0183   double df;
0184   int i;
0185   int v_len;
0186 
0187   /* parse fft length */
0188   if ( fft_len_exponent > KSTPSDMAXLEN ) {
0189     fft_len_exponent = KSTPSDMAXLEN;
0190   }
0191   if ( fft_len_exponent < 2.0 )  {
0192     fft_len_exponent = 2.0;
0193   }
0194   xps_len = int (pow(2.0,  fft_len_exponent-1) + 0.1);
0195 
0196   /* input vector lengths - use the shorter one. */
0197   v_len = ( ( iv1->length() < iv2->length() ) ? iv1->length() : iv2->length() );
0198 
0199   while ( xps_len > v_len ) {
0200     xps_len/=2;
0201   }
0202 
0203   // allocate the lengths
0204   _outputVectors[VECTOR_OUT_REAL]->resize( xps_len, false );
0205   _outputVectors[VECTOR_OUT_IMAG]->resize( xps_len, false );
0206   _outputVectors[VECTOR_OUT_FREQ]->resize( xps_len, false );
0207 
0208   double *xspec_real = _outputVectors[VECTOR_OUT_REAL]->raw_V_ptr();
0209   double *xspec_imag = _outputVectors[VECTOR_OUT_IMAG]->raw_V_ptr();
0210   double *f = _outputVectors[VECTOR_OUT_FREQ]->raw_V_ptr();
0211 
0212 
0213   /* Fill the frequency and zero the xps */
0214   df = SR/( 2.0*double( xps_len-1 ) );
0215   for ( i=0; i<xps_len; ++i ) {
0216     f[i] = double( i ) * df;
0217     xspec_real[i] = 0.0;
0218     xspec_imag[i] = 0.0;
0219   }
0220 
0221   _psdCalculator.calculatePowerSpectrum(iv1->noNanValue(), v_len,
0222                                         xspec_real, xps_len,
0223                                         true,
0224                                         true, fft_len_exponent,
0225                                         true, WindowOriginal, 0,
0226                                         PSDPowerSpectrum, SR,
0227                                         iv2->noNanValue(), v_len, xspec_imag);
0228 
0229 
0230   Kst::LabelInfo label_info;
0231 
0232   label_info.quantity = tr("Cross Spectrum (real)");
0233   label_info.units.clear();
0234   label_info.name.clear();
0235   _outputVectors[VECTOR_OUT_REAL]->setLabelInfo(label_info);
0236 
0237   label_info.quantity = tr("Cross Spectrum (imaginary)");
0238   _outputVectors[VECTOR_OUT_IMAG]->setLabelInfo(label_info);
0239 
0240   label_info.quantity = tr("Frequency");
0241   _outputVectors[VECTOR_OUT_FREQ]->setLabelInfo(label_info);
0242 
0243   return true;
0244 }
0245 
0246 
0247 Kst::VectorPtr CrossSpectrumSource::vectorOne() const {
0248   return _inputVectors[VECTOR_IN_ONE];
0249 }
0250 
0251 
0252 Kst::VectorPtr CrossSpectrumSource::vectorTwo() const {
0253   return _inputVectors[VECTOR_IN_TWO];
0254 }
0255 
0256 
0257 Kst::ScalarPtr CrossSpectrumSource::scalarFFT() const {
0258   return _inputScalars[SCALAR_IN_FFT];
0259 }
0260 
0261 
0262 Kst::ScalarPtr CrossSpectrumSource::scalarRate() const {
0263   return _inputScalars[SCALAR_IN_RATE];
0264 }
0265 
0266 
0267 QStringList CrossSpectrumSource::inputVectorList() const {
0268   QStringList vectors(VECTOR_IN_ONE);
0269   vectors += VECTOR_IN_TWO;
0270   return vectors;
0271 }
0272 
0273 
0274 QStringList CrossSpectrumSource::inputScalarList() const {
0275   QStringList scalars(SCALAR_IN_FFT);
0276   scalars += SCALAR_IN_RATE;
0277   return scalars;
0278 }
0279 
0280 
0281 QStringList CrossSpectrumSource::inputStringList() const {
0282   return QStringList( /*STRING_IN*/ );
0283 }
0284 
0285 
0286 QStringList CrossSpectrumSource::outputVectorList() const {
0287   QStringList vectors(VECTOR_OUT_FREQ);
0288   vectors += VECTOR_OUT_IMAG;
0289   vectors += VECTOR_OUT_REAL;
0290   return vectors;
0291 }
0292 
0293 
0294 QStringList CrossSpectrumSource::outputScalarList() const {
0295   return QStringList( /*SCALAR_OUT*/ );
0296 }
0297 
0298 
0299 QStringList CrossSpectrumSource::outputStringList() const {
0300   return QStringList( /*STRING_OUT*/ );
0301 }
0302 
0303 
0304 void CrossSpectrumSource::saveProperties(QXmlStreamWriter &s) {
0305   Q_UNUSED(s);
0306 //   s.writeAttribute("value", _configValue);
0307 }
0308 
0309 
0310 QString CrossSpectrumPlugin::pluginName() const { return tr("Cross Spectrum"); }
0311 QString CrossSpectrumPlugin::pluginDescription() const { return tr("Generates the cross power spectrum of one vector with another."); }
0312 
0313 
0314 Kst::DataObject *CrossSpectrumPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
0315 
0316   if (ConfigCrossSpectrumPlugin* config = static_cast<ConfigCrossSpectrumPlugin*>(configWidget)) {
0317 
0318     CrossSpectrumSource* object = store->createObject<CrossSpectrumSource>();
0319 
0320     if (setupInputsOutputs) {
0321       object->setInputScalar(SCALAR_IN_FFT, config->selectedScalarFFT());
0322       object->setInputScalar(SCALAR_IN_RATE, config->selectedScalarRate());
0323       object->setupOutputs();
0324       object->setInputVector(VECTOR_IN_ONE, config->selectedVectorOne());
0325       object->setInputVector(VECTOR_IN_TWO, config->selectedVectorTwo());
0326     }
0327 
0328     object->setPluginName(pluginName());
0329 
0330     object->writeLock();
0331     object->registerChange();
0332     object->unlock();
0333 
0334     return object;
0335   }
0336   return 0;
0337 }
0338 
0339 
0340 Kst::DataObjectConfigWidget *CrossSpectrumPlugin::configWidget(QSettings *settingsObject) const {
0341   ConfigCrossSpectrumPlugin *widget = new ConfigCrossSpectrumPlugin(settingsObject);
0342   return widget;
0343 }
0344 
0345 #ifndef QT5
0346 Q_EXPORT_PLUGIN2(kstplugin_BinPlugin, CrossSpectrumPlugin)
0347 #endif
0348 
0349 // vim: ts=2 sw=2 et