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