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