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

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