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