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