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