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