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

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 "fitsinusoid_weighted.h"
0017 #include "objectstore.h"
0018 #include "ui_fitsinusoid_weightedconfig.h"
0019 
0020 #include <gsl/gsl_fit.h>
0021 // #include "../common.h"
0022 #include "../linear_weighted.h"
0023 
0024 static const QString& VECTOR_IN_X = "X Vector";
0025 static const QString& VECTOR_IN_Y = "Y Vector";
0026 static const QString& VECTOR_IN_WEIGHTS = "Weights Vector";
0027 static const QString& VECTOR_OUT_Y_FITTED = "Fit";
0028 static const QString& VECTOR_OUT_Y_RESIDUALS = "Residuals";
0029 static const QString& VECTOR_OUT_Y_PARAMETERS = "Parameters Vector";
0030 static const QString& VECTOR_OUT_Y_COVARIANCE = "Covariance";
0031 static const QString& SCALAR_IN_PERIOD = "Period Scalar";
0032 static const QString& SCALAR_IN_HARMONICS = "Harmonics Scalar";
0033 static const QString& SCALAR_OUT = "chi^2/nu";
0034 
0035 class ConfigWidgetFitSinusoidWeightedPlugin : public Kst::DataObjectConfigWidget, public Ui_FitSinusoid_WeightedConfig {
0036   public:
0037     ConfigWidgetFitSinusoidWeightedPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_FitSinusoid_WeightedConfig() {
0038       _store = 0;
0039       setupUi(this);
0040     }
0041 
0042     ~ConfigWidgetFitSinusoidWeightedPlugin() {}
0043 
0044     void setObjectStore(Kst::ObjectStore* store) { 
0045       _store = store; 
0046       _vectorX->setObjectStore(store);
0047       _vectorY->setObjectStore(store);
0048       _vectorWeights->setObjectStore(store);
0049       _scalarHarmonics->setObjectStore(store);
0050       _scalarPeriod->setObjectStore(store);
0051       _scalarHarmonics->setDefaultValue(0);
0052       _scalarPeriod->setDefaultValue(1);
0053     }
0054 
0055     void setupSlots(QWidget* dialog) {
0056       if (dialog) {
0057         connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0058         connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0059         connect(_vectorWeights, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0060         connect(_scalarHarmonics, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0061         connect(_scalarPeriod, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0062       }
0063     }
0064 
0065     void setVectorX(Kst::VectorPtr vector) {
0066       setSelectedVectorX(vector);
0067     }
0068 
0069     void setVectorY(Kst::VectorPtr vector) {
0070       setSelectedVectorY(vector);
0071     }
0072 
0073     void setVectorsLocked(bool locked = true) {
0074       _vectorX->setEnabled(!locked);
0075       _vectorY->setEnabled(!locked);
0076     }
0077 
0078     Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); };
0079     void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); };
0080 
0081     Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); };
0082     void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); };
0083 
0084     Kst::VectorPtr selectedVectorWeights() { return _vectorWeights->selectedVector(); };
0085     void setSelectedVectorWeights(Kst::VectorPtr vector) { return _vectorWeights->setSelectedVector(vector); };
0086 
0087     Kst::ScalarPtr selectedScalarHarmonics() { return _scalarHarmonics->selectedScalar(); };
0088     void setSelectedScalarHarmonics(Kst::ScalarPtr scalar) { return _scalarHarmonics->setSelectedScalar(scalar); };
0089 
0090     Kst::ScalarPtr selectedScalarPeriod() { return _scalarPeriod->selectedScalar(); };
0091     void setSelectedScalarPeriod(Kst::ScalarPtr scalar) { return _scalarPeriod->setSelectedScalar(scalar); };
0092 
0093     virtual void setupFromObject(Kst::Object* dataObject) {
0094       if (FitSinusoidWeightedSource* source = static_cast<FitSinusoidWeightedSource*>(dataObject)) {
0095         setSelectedVectorX(source->vectorX());
0096         setSelectedVectorY(source->vectorY());
0097         setSelectedVectorWeights(source->vectorWeights());
0098         setSelectedScalarHarmonics(source->scalarHarmonics());
0099         setSelectedScalarPeriod(source->scalarPeriod());
0100       }
0101     }
0102 
0103     virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
0104       Q_UNUSED(store);
0105       Q_UNUSED(attrs);
0106 
0107       bool validTag = true;
0108 
0109 //       QStringRef av;
0110 //       av = attrs.value("value");
0111 //       if (!av.isNull()) {
0112 //         _configValue = QVariant(av.toString()).toBool();
0113 //       }
0114 
0115       return validTag;
0116     }
0117 
0118   public slots:
0119     virtual void save() {
0120       if (_cfg) {
0121         _cfg->beginGroup("Fit Sinusoid Weighted Plugin");
0122         _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name());
0123         _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name());
0124         _cfg->setValue("Input Vector Weights", _vectorWeights->selectedVector()->Name());
0125         _cfg->setValue("Input Scalar Harmonics", _scalarHarmonics->selectedScalar()->Name());
0126         _cfg->setValue("Input Scalar Period", _scalarPeriod->selectedScalar()->Name());
0127         _cfg->endGroup();
0128       }
0129     }
0130 
0131     virtual void load() {
0132       if (_cfg && _store) {
0133         _cfg->beginGroup("Fit Sinusoid Weighted Plugin");
0134         QString vectorName = _cfg->value("Input Vector X").toString();
0135         Kst::Object* object = _store->retrieveObject(vectorName);
0136         Kst::Vector* vectorx = static_cast<Kst::Vector*>(object);
0137         if (vectorx) {
0138           setSelectedVectorX(vectorx);
0139         }
0140         vectorName = _cfg->value("Input Vector Y").toString();
0141         object = _store->retrieveObject(vectorName);
0142         Kst::Vector* vectory = static_cast<Kst::Vector*>(object);
0143         if (vectory) {
0144           setSelectedVectorX(vectory);
0145         }
0146         vectorName = _cfg->value("Input Vector Weights").toString();
0147         object = _store->retrieveObject(vectorName);
0148         Kst::Vector* vectorweights = static_cast<Kst::Vector*>(object);
0149         if (vectorweights) {
0150           setSelectedVectorX(vectorweights);
0151         }
0152         QString scalarName = _cfg->value("Harmonics Scalar").toString();
0153         object = _store->retrieveObject(scalarName);
0154         Kst::Scalar* harmonicsScalar = static_cast<Kst::Scalar*>(object);
0155         if (harmonicsScalar) {
0156           setSelectedScalarHarmonics(harmonicsScalar);
0157         }
0158         scalarName = _cfg->value("Period Scalar").toString();
0159         object = _store->retrieveObject(scalarName);
0160         Kst::Scalar* periodScalar = static_cast<Kst::Scalar*>(object);
0161         if (periodScalar) {
0162           setSelectedScalarPeriod(periodScalar);
0163         }
0164         _cfg->endGroup();
0165       }
0166     }
0167 
0168   private:
0169     Kst::ObjectStore *_store;
0170 
0171 };
0172 
0173 
0174 FitSinusoidWeightedSource::FitSinusoidWeightedSource(Kst::ObjectStore *store)
0175 : Kst::BasicPlugin(store) {
0176 }
0177 
0178 
0179 FitSinusoidWeightedSource::~FitSinusoidWeightedSource() {
0180 }
0181 
0182 
0183 QString FitSinusoidWeightedSource::_automaticDescriptiveName() const {
0184   return tr("%1 Weighted Sinusoid").arg(vectorY()->descriptiveName());;
0185 }
0186 
0187 
0188 void FitSinusoidWeightedSource::change(Kst::DataObjectConfigWidget *configWidget) {
0189   if (ConfigWidgetFitSinusoidWeightedPlugin* config = static_cast<ConfigWidgetFitSinusoidWeightedPlugin*>(configWidget)) {
0190     setInputVector(VECTOR_IN_X, config->selectedVectorX());
0191     setInputVector(VECTOR_IN_Y, config->selectedVectorY());
0192     setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights());
0193     setInputScalar(SCALAR_IN_HARMONICS, config->selectedScalarHarmonics());
0194     setInputScalar(SCALAR_IN_PERIOD, config->selectedScalarPeriod());
0195   }
0196 }
0197 
0198 
0199 void FitSinusoidWeightedSource::setupOutputs() {
0200   setOutputVector(VECTOR_OUT_Y_FITTED, "");
0201   setOutputVector(VECTOR_OUT_Y_RESIDUALS, "");
0202   setOutputVector(VECTOR_OUT_Y_PARAMETERS, "");
0203   setOutputVector(VECTOR_OUT_Y_COVARIANCE, "");
0204   setOutputScalar(SCALAR_OUT, "");
0205 }
0206 
0207 
0208 double g_dPeriod;
0209 double calculate_matrix_entry( double dX, int iPos ) {
0210   double dY;
0211 
0212   if( iPos == 0 ) {
0213     dY = 1.0;
0214   } else if( iPos % 2 == 1 ) {
0215     dY =  cos( (double)( ( iPos + 1 ) / 2 ) * 2.0 * M_PI * dX / g_dPeriod );
0216   } else {
0217     dY = -sin( (double)( ( iPos + 0 ) / 2 ) * 2.0 * M_PI * dX / g_dPeriod );
0218   }
0219 
0220   return dY;
0221 }
0222 
0223 
0224 bool FitSinusoidWeightedSource::algorithm() {
0225   Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
0226   Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
0227   Kst::VectorPtr inputVectorWeights = _inputVectors[VECTOR_IN_WEIGHTS];
0228   Kst::ScalarPtr inputScalarHarmonics = _inputScalars[SCALAR_IN_HARMONICS];
0229   Kst::ScalarPtr inputScalarPeriod = _inputScalars[SCALAR_IN_PERIOD];
0230 
0231   Kst::VectorPtr outputVectorYFitted = _outputVectors[VECTOR_OUT_Y_FITTED];
0232   Kst::VectorPtr outputVectorYResiduals = _outputVectors[VECTOR_OUT_Y_RESIDUALS];
0233   Kst::VectorPtr outputVectorYParameters = _outputVectors[VECTOR_OUT_Y_PARAMETERS];
0234   Kst::VectorPtr outputVectorYCovariance = _outputVectors[VECTOR_OUT_Y_COVARIANCE];
0235   Kst::ScalarPtr outputScalar = _outputScalars[SCALAR_OUT];
0236 
0237 
0238   Kst::LabelInfo label_info = inputVectorY->labelInfo();
0239   label_info.name = tr("Sinusoidal Fit to %1").arg(label_info.name);
0240   outputVectorYFitted->setLabelInfo(label_info);
0241 
0242   label_info.name = tr("Sinusoidal Fit Residuals");
0243   outputVectorYResiduals->setLabelInfo(label_info);
0244 
0245   bool bReturn = false;
0246 
0247   int iNumParams;
0248 
0249   iNumParams = 3 + ( 2 * (int)floor( inputScalarHarmonics->value() ) );
0250   if( iNumParams >= 3 ) {
0251     g_dPeriod = inputScalarPeriod->value();
0252     if( g_dPeriod > 0.0 )
0253     {
0254       bReturn = kstfit_linear_weighted( inputVectorX, inputVectorY, inputVectorWeights,
0255                                         outputVectorYFitted, outputVectorYResiduals, outputVectorYParameters,
0256                                         outputVectorYCovariance, outputScalar, iNumParams );
0257     }
0258   }
0259 
0260   return bReturn;
0261 }
0262 
0263 
0264 Kst::VectorPtr FitSinusoidWeightedSource::vectorX() const {
0265   return _inputVectors[VECTOR_IN_X];
0266 }
0267 
0268 
0269 Kst::VectorPtr FitSinusoidWeightedSource::vectorY() const {
0270   return _inputVectors[VECTOR_IN_Y];
0271 }
0272 
0273 
0274 Kst::VectorPtr FitSinusoidWeightedSource::vectorWeights() const {
0275   return _inputVectors[VECTOR_IN_WEIGHTS];
0276 }
0277 
0278 
0279 Kst::ScalarPtr FitSinusoidWeightedSource::scalarHarmonics() const {
0280   return _inputScalars[SCALAR_IN_HARMONICS];
0281 }
0282 
0283 
0284 Kst::ScalarPtr FitSinusoidWeightedSource::scalarPeriod() const {
0285   return _inputScalars[SCALAR_IN_PERIOD];
0286 }
0287 
0288 
0289 QStringList FitSinusoidWeightedSource::inputVectorList() const {
0290   QStringList vectors(VECTOR_IN_X);
0291   vectors += VECTOR_IN_Y;
0292   vectors += VECTOR_IN_WEIGHTS;
0293   return vectors;
0294 }
0295 
0296 
0297 QStringList FitSinusoidWeightedSource::inputScalarList() const {
0298   QStringList scalars(SCALAR_IN_HARMONICS);
0299   scalars += SCALAR_IN_PERIOD;
0300   return scalars;
0301 }
0302 
0303 
0304 QStringList FitSinusoidWeightedSource::inputStringList() const {
0305   return QStringList( /*STRING_IN*/ );
0306 }
0307 
0308 
0309 QStringList FitSinusoidWeightedSource::outputVectorList() const {
0310   QStringList vectors(VECTOR_OUT_Y_FITTED);
0311   vectors += VECTOR_OUT_Y_RESIDUALS;
0312   vectors += VECTOR_OUT_Y_PARAMETERS;
0313   vectors += VECTOR_OUT_Y_COVARIANCE;
0314   vectors += VECTOR_OUT_Y_PARAMETERS;
0315   return vectors;
0316 }
0317 
0318 
0319 QStringList FitSinusoidWeightedSource::outputScalarList() const {
0320   return QStringList( SCALAR_OUT );
0321 }
0322 
0323 
0324 QStringList FitSinusoidWeightedSource::outputStringList() const {
0325   return QStringList( /*STRING_OUT*/ );
0326 }
0327 
0328 
0329 void FitSinusoidWeightedSource::saveProperties(QXmlStreamWriter &s) {
0330   Q_UNUSED(s);
0331 //   s.writeAttribute("value", _configValue);
0332 }
0333 
0334 
0335 QString FitSinusoidWeightedSource::parameterName(int index) const {
0336   QString parameter;
0337   switch (index) {
0338     case 0:
0339       parameter = "Mean";
0340       break;
0341     case 1:
0342       parameter = "cos(%1 2PI x/P)";
0343       parameter = parameter.arg((index + 1 ) / 2);
0344       break;
0345     case 2:
0346       parameter = "-sin(%1 2PI x/P)";
0347       parameter = parameter.arg((index + 0 ) / 2);
0348       break;
0349   }
0350 
0351   return parameter;
0352 }
0353 
0354 
0355 // Name used to identify the plugin.  Used when loading the plugin.
0356 QString FitSinusoidWeightedPlugin::pluginName() const { return tr("Sinusoid Weighted Fit"); }
0357 QString FitSinusoidWeightedPlugin::pluginDescription() const { return tr("Generates a sinusoid weighted fit for a set of data."); }
0358 
0359 
0360 Kst::DataObject *FitSinusoidWeightedPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
0361 
0362   if (ConfigWidgetFitSinusoidWeightedPlugin* config = static_cast<ConfigWidgetFitSinusoidWeightedPlugin*>(configWidget)) {
0363 
0364     Kst::ScalarPtr harmonics;
0365     Kst::ScalarPtr period;
0366 
0367     // access/create input scalars before creating plugin
0368     // in order to preserve continuous scalar shortnames
0369     if (setupInputsOutputs) {
0370       harmonics = config->selectedScalarHarmonics();
0371       period = config->selectedScalarPeriod();
0372     }
0373 
0374     FitSinusoidWeightedSource* object = store->createObject<FitSinusoidWeightedSource>();
0375 
0376     if (setupInputsOutputs) {
0377       object->setInputScalar(SCALAR_IN_HARMONICS, harmonics);
0378       object->setInputScalar(SCALAR_IN_PERIOD, period);
0379       object->setupOutputs();
0380       object->setInputVector(VECTOR_IN_X, config->selectedVectorX());
0381       object->setInputVector(VECTOR_IN_Y, config->selectedVectorY());
0382       object->setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights());
0383     }
0384 
0385     object->setPluginName(pluginName());
0386 
0387     object->writeLock();
0388     object->registerChange();
0389     object->unlock();
0390 
0391     return object;
0392   }
0393   return 0;
0394 }
0395 
0396 
0397 Kst::DataObjectConfigWidget *FitSinusoidWeightedPlugin::configWidget(QSettings *settingsObject) const {
0398   ConfigWidgetFitSinusoidWeightedPlugin *widget = new ConfigWidgetFitSinusoidWeightedPlugin(settingsObject);
0399   return widget;
0400 }
0401 
0402 #ifndef QT5
0403 Q_EXPORT_PLUGIN2(kstplugin_FitSinusoidWeightedPlugin, FitSinusoidWeightedPlugin)
0404 #endif
0405 
0406 // vim: ts=2 sw=2 et