File indexing completed on 2024-12-22 04:18:13
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 "fitlorentzian_weighted.h" 0017 #include "objectstore.h" 0018 #include "ui_fitlorentzian_weightedconfig.h" 0019 0020 #define NUM_PARAMS 3 0021 #define MAX_NUM_ITERATIONS 500 0022 0023 #include <gsl/gsl_fit.h> 0024 #include "../non_linear_weighted.h" 0025 0026 static const QString& VECTOR_IN_X = "X Vector"; 0027 static const QString& VECTOR_IN_Y = "Y Vector"; 0028 static const QString& VECTOR_IN_WEIGHTS = "Weights Vector"; 0029 static const QString& VECTOR_OUT_Y_FITTED = "Fit"; 0030 static const QString& VECTOR_OUT_Y_RESIDUALS = "Residuals"; 0031 static const QString& VECTOR_OUT_Y_PARAMETERS = "Parameters Vector"; 0032 static const QString& VECTOR_OUT_Y_COVARIANCE = "Covariance"; 0033 static const QString& SCALAR_OUT = "chi^2/nu"; 0034 0035 class ConfigWidgetFitLorentzianWeightedPlugin : public Kst::DataObjectConfigWidget, public Ui_FitLorentzian_WeightedConfig { 0036 public: 0037 ConfigWidgetFitLorentzianWeightedPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_FitLorentzian_WeightedConfig() { 0038 _store = 0; 0039 setupUi(this); 0040 } 0041 0042 ~ConfigWidgetFitLorentzianWeightedPlugin() {} 0043 0044 void setObjectStore(Kst::ObjectStore* store) { 0045 _store = store; 0046 _vectorX->setObjectStore(store); 0047 _vectorY->setObjectStore(store); 0048 _vectorWeights->setObjectStore(store); 0049 } 0050 0051 void setupSlots(QWidget* dialog) { 0052 if (dialog) { 0053 connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0054 connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0055 connect(_vectorWeights, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0056 } 0057 } 0058 0059 void setVectorX(Kst::VectorPtr vector) { 0060 setSelectedVectorX(vector); 0061 } 0062 0063 void setVectorY(Kst::VectorPtr vector) { 0064 setSelectedVectorY(vector); 0065 } 0066 0067 void setVectorsLocked(bool locked = true) { 0068 _vectorX->setEnabled(!locked); 0069 _vectorY->setEnabled(!locked); 0070 } 0071 0072 Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); }; 0073 void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); }; 0074 0075 Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); }; 0076 void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); }; 0077 0078 Kst::VectorPtr selectedVectorWeights() { return _vectorWeights->selectedVector(); }; 0079 void setSelectedVectorWeights(Kst::VectorPtr vector) { return _vectorWeights->setSelectedVector(vector); }; 0080 0081 virtual void setupFromObject(Kst::Object* dataObject) { 0082 if (FitLorentzianWeightedSource* source = static_cast<FitLorentzianWeightedSource*>(dataObject)) { 0083 setSelectedVectorX(source->vectorX()); 0084 setSelectedVectorY(source->vectorY()); 0085 setSelectedVectorWeights(source->vectorWeights()); 0086 } 0087 } 0088 0089 virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) { 0090 Q_UNUSED(store); 0091 Q_UNUSED(attrs); 0092 0093 bool validTag = true; 0094 0095 // QStringRef av; 0096 // av = attrs.value("value"); 0097 // if (!av.isNull()) { 0098 // _configValue = QVariant(av.toString()).toBool(); 0099 // } 0100 0101 return validTag; 0102 } 0103 0104 public slots: 0105 virtual void save() { 0106 if (_cfg) { 0107 _cfg->beginGroup("Fit Lorentzian Weighted Plugin"); 0108 _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name()); 0109 _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name()); 0110 _cfg->setValue("Input Vector Weights", _vectorWeights->selectedVector()->Name()); 0111 _cfg->endGroup(); 0112 } 0113 } 0114 0115 virtual void load() { 0116 if (_cfg && _store) { 0117 _cfg->beginGroup("Fit Lorentzian Weighted Plugin"); 0118 QString vectorName = _cfg->value("Input Vector X").toString(); 0119 Kst::Object* object = _store->retrieveObject(vectorName); 0120 Kst::Vector* vectorx = static_cast<Kst::Vector*>(object); 0121 if (vectorx) { 0122 setSelectedVectorX(vectorx); 0123 } 0124 vectorName = _cfg->value("Input Vector Y").toString(); 0125 object = _store->retrieveObject(vectorName); 0126 Kst::Vector* vectory = static_cast<Kst::Vector*>(object); 0127 if (vectory) { 0128 setSelectedVectorX(vectory); 0129 } 0130 vectorName = _cfg->value("Input Vector Weights").toString(); 0131 object = _store->retrieveObject(vectorName); 0132 Kst::Vector* vectorweights = static_cast<Kst::Vector*>(object); 0133 if (vectorweights) { 0134 setSelectedVectorX(vectorweights); 0135 } 0136 _cfg->endGroup(); 0137 } 0138 } 0139 0140 private: 0141 Kst::ObjectStore *_store; 0142 0143 }; 0144 0145 0146 FitLorentzianWeightedSource::FitLorentzianWeightedSource(Kst::ObjectStore *store) 0147 : Kst::BasicPlugin(store) { 0148 } 0149 0150 0151 FitLorentzianWeightedSource::~FitLorentzianWeightedSource() { 0152 } 0153 0154 0155 QString FitLorentzianWeightedSource::_automaticDescriptiveName() const { 0156 return tr("%1 Weighted Lorentzian").arg(vectorY()->descriptiveName());; 0157 } 0158 0159 0160 void FitLorentzianWeightedSource::change(Kst::DataObjectConfigWidget *configWidget) { 0161 if (ConfigWidgetFitLorentzianWeightedPlugin* config = static_cast<ConfigWidgetFitLorentzianWeightedPlugin*>(configWidget)) { 0162 setInputVector(VECTOR_IN_X, config->selectedVectorX()); 0163 setInputVector(VECTOR_IN_Y, config->selectedVectorY()); 0164 setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights()); 0165 } 0166 } 0167 0168 0169 void FitLorentzianWeightedSource::setupOutputs() { 0170 setOutputVector(VECTOR_OUT_Y_FITTED, ""); 0171 setOutputVector(VECTOR_OUT_Y_RESIDUALS, ""); 0172 setOutputVector(VECTOR_OUT_Y_PARAMETERS, ""); 0173 setOutputVector(VECTOR_OUT_Y_COVARIANCE, ""); 0174 setOutputScalar(SCALAR_OUT, ""); 0175 } 0176 0177 0178 void function_initial_estimate( const double* pdX, const double* pdY, int iLength, double* pdParameterEstimates ) { 0179 double dMin; 0180 double dMax; 0181 0182 gsl_stats_minmax( &dMin, &dMax, pdX, 1, iLength ); 0183 0184 pdParameterEstimates[0] = gsl_stats_mean( pdX, 1, iLength ); 0185 pdParameterEstimates[1] = ( dMax - dMin ) / 2.0; 0186 pdParameterEstimates[2] = gsl_stats_max( pdY, 1, iLength ); 0187 } 0188 0189 0190 double function_calculate( double dX, double* pdParameters ) { 0191 double dMean = pdParameters[0]; 0192 double dHW = pdParameters[1]; 0193 double dScale = pdParameters[2]; 0194 double dY; 0195 0196 dY = ( dScale / M_PI ) * ( dHW / 2.0 ); 0197 dY /= ( ( dX - dMean ) * ( dX - dMean ) )+( ( dHW / 2.0 ) * ( dHW / 2.0 ) ); 0198 0199 return dY; 0200 } 0201 0202 0203 void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) { 0204 double dMean = pdParameters[0]; 0205 double dHW = pdParameters[1]; 0206 double dScale = pdParameters[2]; 0207 double dDenom; 0208 double ddMean; 0209 double ddHW; 0210 double ddScale; 0211 0212 dDenom = ( ( dX - dMean ) * ( dX - dMean ) ) + ( ( dHW / 2.0 ) * ( dHW / 2.0 ) ); 0213 ddMean = ( dScale / M_PI ) * dHW * ( dMean - dX ) / ( dDenom * dDenom ); 0214 ddHW = ( dScale / ( 2.0 * M_PI ) ) / ( dDenom * dDenom ); 0215 ddHW *= dDenom - ( dHW * dHW / 2.0 ); 0216 ddScale = ( 1.0 / M_PI ) * ( dHW / 2.0 ) / dDenom; 0217 0218 pdDerivatives[0] = ddMean; 0219 pdDerivatives[1] = ddHW; 0220 pdDerivatives[2] = ddScale; 0221 } 0222 0223 0224 bool FitLorentzianWeightedSource::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 0229 Kst::VectorPtr outputVectorYFitted = _outputVectors[VECTOR_OUT_Y_FITTED]; 0230 Kst::VectorPtr outputVectorYResiduals = _outputVectors[VECTOR_OUT_Y_RESIDUALS]; 0231 Kst::VectorPtr outputVectorYParameters = _outputVectors[VECTOR_OUT_Y_PARAMETERS]; 0232 Kst::VectorPtr outputVectorYCovariance = _outputVectors[VECTOR_OUT_Y_COVARIANCE]; 0233 Kst::ScalarPtr outputScalar = _outputScalars[SCALAR_OUT]; 0234 0235 Kst::LabelInfo label_info = inputVectorY->labelInfo(); 0236 label_info.name = tr("Lorentzian Fit to %1").arg(label_info.name); 0237 outputVectorYFitted->setLabelInfo(label_info); 0238 0239 label_info.name = tr("Lorentzian Fit Residuals"); 0240 outputVectorYResiduals->setLabelInfo(label_info); 0241 0242 0243 bool bReturn = false; 0244 0245 bReturn = kstfit_nonlinear_weighted( inputVectorX, inputVectorY, inputVectorWeights, 0246 outputVectorYFitted, outputVectorYResiduals, outputVectorYParameters, 0247 outputVectorYCovariance, outputScalar ); 0248 return bReturn; 0249 } 0250 0251 0252 Kst::VectorPtr FitLorentzianWeightedSource::vectorX() const { 0253 return _inputVectors[VECTOR_IN_X]; 0254 } 0255 0256 0257 Kst::VectorPtr FitLorentzianWeightedSource::vectorY() const { 0258 return _inputVectors[VECTOR_IN_Y]; 0259 } 0260 0261 0262 Kst::VectorPtr FitLorentzianWeightedSource::vectorWeights() const { 0263 return _inputVectors[VECTOR_IN_WEIGHTS]; 0264 } 0265 0266 0267 QStringList FitLorentzianWeightedSource::inputVectorList() const { 0268 QStringList vectors(VECTOR_IN_X); 0269 vectors += VECTOR_IN_Y; 0270 vectors += VECTOR_IN_WEIGHTS; 0271 return vectors; 0272 } 0273 0274 0275 QStringList FitLorentzianWeightedSource::inputScalarList() const { 0276 return QStringList(); 0277 } 0278 0279 0280 QStringList FitLorentzianWeightedSource::inputStringList() const { 0281 return QStringList( /*STRING_IN*/ ); 0282 } 0283 0284 0285 QStringList FitLorentzianWeightedSource::outputVectorList() const { 0286 QStringList vectors(VECTOR_OUT_Y_FITTED); 0287 vectors += VECTOR_OUT_Y_RESIDUALS; 0288 vectors += VECTOR_OUT_Y_PARAMETERS; 0289 vectors += VECTOR_OUT_Y_COVARIANCE; 0290 vectors += VECTOR_OUT_Y_PARAMETERS; 0291 return vectors; 0292 } 0293 0294 0295 QStringList FitLorentzianWeightedSource::outputScalarList() const { 0296 return QStringList( SCALAR_OUT ); 0297 } 0298 0299 0300 QStringList FitLorentzianWeightedSource::outputStringList() const { 0301 return QStringList( /*STRING_OUT*/ ); 0302 } 0303 0304 0305 void FitLorentzianWeightedSource::saveProperties(QXmlStreamWriter &s) { 0306 Q_UNUSED(s); 0307 // s.writeAttribute("value", _configValue); 0308 } 0309 0310 0311 QString FitLorentzianWeightedSource::parameterName(int index) const { 0312 QString parameter; 0313 switch (index) { 0314 case 0: 0315 parameter = "Mean"; 0316 break; 0317 case 1: 0318 parameter = "Half-width"; 0319 break; 0320 case 2: 0321 parameter = "Scale"; 0322 break; 0323 } 0324 0325 return parameter; 0326 } 0327 0328 0329 // Name used to identify the plugin. Used when loading the plugin. 0330 QString FitLorentzianWeightedPlugin::pluginName() const { return tr("Lorentzian Weighted Fit"); } 0331 QString FitLorentzianWeightedPlugin::pluginDescription() const { return tr("Generates a lorentzian weighted fit for a set of data."); } 0332 0333 0334 Kst::DataObject *FitLorentzianWeightedPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const { 0335 0336 if (ConfigWidgetFitLorentzianWeightedPlugin* config = static_cast<ConfigWidgetFitLorentzianWeightedPlugin*>(configWidget)) { 0337 0338 FitLorentzianWeightedSource* object = store->createObject<FitLorentzianWeightedSource>(); 0339 0340 if (setupInputsOutputs) { 0341 object->setupOutputs(); 0342 object->setInputVector(VECTOR_IN_X, config->selectedVectorX()); 0343 object->setInputVector(VECTOR_IN_Y, config->selectedVectorY()); 0344 object->setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights()); 0345 } 0346 0347 object->setPluginName(pluginName()); 0348 0349 object->writeLock(); 0350 object->registerChange(); 0351 object->unlock(); 0352 0353 return object; 0354 } 0355 return 0; 0356 } 0357 0358 0359 Kst::DataObjectConfigWidget *FitLorentzianWeightedPlugin::configWidget(QSettings *settingsObject) const { 0360 ConfigWidgetFitLorentzianWeightedPlugin *widget = new ConfigWidgetFitLorentzianWeightedPlugin(settingsObject); 0361 return widget; 0362 } 0363 0364 #ifndef QT5 0365 Q_EXPORT_PLUGIN2(kstplugin_FitLorentzianWeightedPlugin, FitLorentzianWeightedPlugin) 0366 #endif 0367 0368 // vim: ts=2 sw=2 et