File indexing completed on 2025-01-12 04:09:50

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