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

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 "deconvolve.h"
0017 #include "objectstore.h"
0018 #include "ui_deconvolveconfig.h"
0019 
0020 #include <gsl/gsl_fft_real.h>
0021 #include <gsl/gsl_fft_halfcomplex.h>
0022 
0023 
0024 static const QString& VECTOR_IN_ONE = "Vector One In";
0025 static const QString& VECTOR_IN_TWO = "Vector Two In";
0026 static const QString& VECTOR_OUT = "Vector Out";
0027 
0028 class ConfigWidgetDeconvolvePlugin : public Kst::DataObjectConfigWidget, public Ui_DeconvolveConfig {
0029   public:
0030     ConfigWidgetDeconvolvePlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_DeconvolveConfig() {
0031       _store = 0;
0032       setupUi(this);
0033     }
0034 
0035     ~ConfigWidgetDeconvolvePlugin() {}
0036 
0037     void setObjectStore(Kst::ObjectStore* store) { 
0038       _store = store; 
0039       _vectorOne->setObjectStore(store); 
0040       _vectorTwo->setObjectStore(store); 
0041     }
0042 
0043     void setupSlots(QWidget* dialog) {
0044       if (dialog) {
0045         connect(_vectorOne, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0046         connect(_vectorTwo, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0047       }
0048     }
0049 
0050     Kst::VectorPtr selectedVectorOne() { return _vectorOne->selectedVector(); };
0051     void setSelectedVectorOne(Kst::VectorPtr vector) { return _vectorOne->setSelectedVector(vector); };
0052 
0053     Kst::VectorPtr selectedVectorTwo() { return _vectorTwo->selectedVector(); };
0054     void setSelectedVectorTwo(Kst::VectorPtr vector) { return _vectorTwo->setSelectedVector(vector); };
0055 
0056     virtual void setupFromObject(Kst::Object* dataObject) {
0057       if (DeconvolveSource* source = static_cast<DeconvolveSource*>(dataObject)) {
0058         setSelectedVectorOne(source->vectorOne());
0059         setSelectedVectorTwo(source->vectorTwo());
0060       }
0061     }
0062 
0063     virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
0064       Q_UNUSED(store);
0065       Q_UNUSED(attrs);
0066 
0067       bool validTag = true;
0068 
0069 //       QStringRef av;
0070 //       av = attrs.value("value");
0071 //       if (!av.isNull()) {
0072 //         _configValue = QVariant(av.toString()).toBool();
0073 //       }
0074 
0075       return validTag;
0076     }
0077 
0078   public slots:
0079     virtual void save() {
0080       if (_cfg) {
0081         _cfg->beginGroup("Deconvolve DataObject Plugin");
0082         _cfg->setValue("Input Vector One", _vectorOne->selectedVector()->Name());
0083         _cfg->setValue("Input Vector Two", _vectorTwo->selectedVector()->Name());
0084         _cfg->endGroup();
0085       }
0086     }
0087 
0088     virtual void load() {
0089       if (_cfg && _store) {
0090         _cfg->beginGroup("Deconvolve DataObject Plugin");
0091         QString vectorName = _cfg->value("Input Vector One").toString();
0092         Kst::Object* object = _store->retrieveObject(vectorName);
0093         Kst::Vector* vector = static_cast<Kst::Vector*>(object);
0094         if (vector) {
0095           setSelectedVectorOne(vector);
0096         }
0097         vectorName = _cfg->value("Input Vector Two").toString();
0098         Kst::Object* object2 = _store->retrieveObject(vectorName);
0099         Kst::Vector* vector2 = static_cast<Kst::Vector*>(object2);
0100         if (vector2) {
0101           setSelectedVectorTwo(vector2);
0102         }
0103         _cfg->endGroup();
0104       }
0105     }
0106 
0107   private:
0108     Kst::ObjectStore *_store;
0109 
0110 };
0111 
0112 
0113 DeconvolveSource::DeconvolveSource(Kst::ObjectStore *store)
0114 : Kst::BasicPlugin(store) {
0115 }
0116 
0117 
0118 DeconvolveSource::~DeconvolveSource() {
0119 }
0120 
0121 
0122 QString DeconvolveSource::_automaticDescriptiveName() const {
0123   return tr("Deconvolve Plugin Object");
0124 }
0125 
0126 
0127 void DeconvolveSource::change(Kst::DataObjectConfigWidget *configWidget) {
0128   if (ConfigWidgetDeconvolvePlugin* config = static_cast<ConfigWidgetDeconvolvePlugin*>(configWidget)) {
0129     setInputVector(VECTOR_IN_ONE, config->selectedVectorOne());
0130     setInputVector(VECTOR_IN_TWO, config->selectedVectorTwo());
0131   }
0132 }
0133 
0134 
0135 void DeconvolveSource::setupOutputs() {
0136   setOutputVector(VECTOR_OUT, "");
0137 }
0138 
0139 
0140 bool DeconvolveSource::algorithm() {
0141   Kst::VectorPtr inputVectorOne = _inputVectors[VECTOR_IN_ONE];
0142   Kst::VectorPtr inputVectorTwo = _inputVectors[VECTOR_IN_TWO];
0143   Kst::VectorPtr outputVector = _outputVectors[VECTOR_OUT];
0144 
0145   if (inputVectorOne->length() <= 0 && inputVectorTwo->length() <= 0) {
0146     _errorString = tr("Error:  Input Vectors - invalid size");
0147     return false;
0148   }
0149 
0150   double* pdResponse;
0151   double* pdConvolve;
0152   double* pdResult;
0153   double  dReal;
0154   double  dImag;
0155   double  dSize;
0156 
0157   Kst::VectorPtr response;
0158   Kst::VectorPtr deconvolve;
0159 
0160   int iLength;
0161   int iLengthNew;
0162 
0163   bool bReturn = false;
0164   int iResponseMidpoint;
0165 
0166   // determine which is the response function:
0167   //  i.e. which is shorter...
0168   if (inputVectorOne->length() < inputVectorTwo->length()) {
0169     response = inputVectorOne;
0170     deconvolve = inputVectorTwo;
0171   } else {
0172     response = inputVectorTwo;
0173     deconvolve = inputVectorOne;
0174   }
0175 
0176   outputVector->resize(deconvolve->length(), false);
0177 
0178   iResponseMidpoint = response->length() / 2;
0179   iLength = deconvolve->length() + iResponseMidpoint;
0180 
0181   // round iLength up to the nearest factor of two...
0182   iLengthNew = 64;
0183   while (iLengthNew < iLength && iLengthNew > 0) {
0184     iLengthNew *= 2;
0185   }
0186   iLength = iLengthNew;
0187 
0188   if (iLength <= 0) {
0189     _errorString = tr("Error:  Invalid Input length calculated");
0190     return false;
0191   }
0192 
0193   pdResponse = new double[iLength];
0194   pdConvolve = new double[iLength];
0195   if (pdResponse != NULL && pdConvolve != NULL) {
0196     //
0197     // sort the response function into wrap-around order...
0198     //
0199     memset( pdResponse, 0, iLength * sizeof( double ) );
0200 
0201     for ( int i=0; i < iResponseMidpoint; i++) {
0202       pdResponse[i]                           = response->noNanValue()[iResponseMidpoint+i];
0203       pdResponse[iLength-iResponseMidpoint+i] = response->noNanValue()[i];
0204     }
0205 
0206     //
0207     // handle the case where the response function has an odd number of points...
0208     //
0209     if (iResponseMidpoint % 2 == 1) {
0210       pdResponse[iResponseMidpoint]           = response->noNanValue()[response->length()];
0211 
0212     }
0213 
0214     //
0215     // zero-pad the convolve array...
0216     //
0217     memset( pdConvolve, 0, iLength * sizeof( double ) );
0218     memcpy( pdConvolve, deconvolve->noNanValue(), deconvolve->length() * sizeof( double ) );
0219 
0220     //
0221     // calculate the FFTs of the two functions...
0222     //
0223     if (gsl_fft_real_radix2_transform( pdResponse, 1, iLength ) == 0) {
0224       if (gsl_fft_real_radix2_transform( pdConvolve, 1, iLength ) == 0) {
0225         //
0226         // divide one FFT by the other...
0227         //
0228         for ( int i=0; i < iLength/2; i++) {
0229           if (i==0 || i==(iLength/2)-1) {
0230             pdResponse[i] = pdConvolve[i] / pdResponse[i];
0231           } else {
0232             dSize = ( pdResponse[i] * pdResponse[i] ) + ( pdResponse[iLength-i] * pdResponse[iLength-i] );
0233 
0234             dReal  = pdResponse[i] * pdConvolve[i] + pdResponse[iLength-i] * pdConvolve[iLength-i];
0235             dImag  = pdResponse[i] * pdConvolve[iLength-i] - pdResponse[iLength-i] * pdConvolve[i];
0236             dReal /= dSize;
0237             dImag /= dSize;
0238 
0239             pdResponse[i]         = dReal;
0240             pdResponse[iLength-i] = dImag;
0241           }
0242         }
0243 
0244         //
0245         // do the inverse FFT...
0246         //
0247         if (gsl_fft_halfcomplex_radix2_inverse( pdResponse, 1, iLength ) == 0) {
0248           pdResult = outputVector->raw_V_ptr();
0249 
0250           if (pdResult != NULL) {
0251             for (int i = 0; i < deconvolve->length(); ++i) {
0252               outputVector->raw_V_ptr()[i] = pdResult[i];
0253             }
0254 
0255             memcpy( pdResult, pdResponse, deconvolve->length() * sizeof( double ) );
0256 
0257             bReturn = true;
0258           }
0259         }
0260       }
0261     }
0262   }
0263   delete[] pdResponse;
0264   delete[] pdConvolve;
0265 
0266   return bReturn;
0267 }
0268 
0269 
0270 Kst::VectorPtr DeconvolveSource::vectorOne() const {
0271   return _inputVectors[VECTOR_IN_ONE];
0272 }
0273 
0274 
0275 Kst::VectorPtr DeconvolveSource::vectorTwo() const {
0276   return _inputVectors[VECTOR_IN_TWO];
0277 }
0278 
0279 
0280 QStringList DeconvolveSource::inputVectorList() const {
0281   QStringList vectors(VECTOR_IN_ONE);
0282   vectors += VECTOR_IN_TWO;
0283   return vectors;
0284 }
0285 
0286 
0287 QStringList DeconvolveSource::inputScalarList() const {
0288   return QStringList( /*SCALAR_IN*/ );
0289 }
0290 
0291 
0292 QStringList DeconvolveSource::inputStringList() const {
0293   return QStringList( /*STRING_IN*/ );
0294 }
0295 
0296 
0297 QStringList DeconvolveSource::outputVectorList() const {
0298   return QStringList(VECTOR_OUT);
0299 }
0300 
0301 
0302 QStringList DeconvolveSource::outputScalarList() const {
0303   return QStringList( /*SCALAR_OUT*/ );
0304 }
0305 
0306 
0307 QStringList DeconvolveSource::outputStringList() const {
0308   return QStringList( /*STRING_OUT*/ );
0309 }
0310 
0311 
0312 void DeconvolveSource::saveProperties(QXmlStreamWriter &s) {
0313   Q_UNUSED(s);
0314 //   s.writeAttribute("value", _configValue);
0315 }
0316 
0317 
0318 QString DeconvolvePlugin::pluginName() const { return tr("Deconvolve"); }
0319 QString DeconvolvePlugin::pluginDescription() const { return tr("Generates the deconvolution of one vector with another."); }
0320 
0321 
0322 Kst::DataObject *DeconvolvePlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
0323 
0324   if (ConfigWidgetDeconvolvePlugin* config = static_cast<ConfigWidgetDeconvolvePlugin*>(configWidget)) {
0325 
0326     DeconvolveSource* object = store->createObject<DeconvolveSource>();
0327 
0328     if (setupInputsOutputs) {
0329       object->setupOutputs();
0330       object->setInputVector(VECTOR_IN_ONE, config->selectedVectorOne());
0331       object->setInputVector(VECTOR_IN_TWO, config->selectedVectorTwo());
0332     }
0333 
0334     object->setPluginName(pluginName());
0335 
0336     object->writeLock();
0337     object->registerChange();
0338     object->unlock();
0339 
0340     return object;
0341   }
0342   return 0;
0343 }
0344 
0345 
0346 Kst::DataObjectConfigWidget *DeconvolvePlugin::configWidget(QSettings *settingsObject) const {
0347   ConfigWidgetDeconvolvePlugin *widget = new ConfigWidgetDeconvolvePlugin(settingsObject);
0348   return widget;
0349 }
0350 
0351 #ifndef QT5
0352 Q_EXPORT_PLUGIN2(kstplugin_DeconvolvePlugin, DeconvolvePlugin)
0353 #endif
0354 
0355 // vim: ts=2 sw=2 et