File indexing completed on 2024-12-22 04:18:05

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 "linefit.h"
0017 #include "objectstore.h"
0018 #include "ui_linefitconfig.h"
0019 
0020 #include "math_kst.h"
0021 
0022 static const QString& VECTOR_IN_X = "Vector In X";
0023 static const QString& VECTOR_IN_Y = "Vector In Y";
0024 static const QString& VECTOR_OUT_X = "X Interpolated";
0025 static const QString& VECTOR_OUT_Y = "Y Interpolated";
0026 
0027 static const QString& SCALAR_OUT_A = "a";
0028 static const QString& SCALAR_OUT_B = "b";
0029 static const QString& SCALAR_OUT_CHI2 = "chi^2";
0030 
0031 
0032 class ConfigWidgetLineFitPlugin : public Kst::DataObjectConfigWidget, public Ui_LineFitConfig {
0033   public:
0034     ConfigWidgetLineFitPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_LineFitConfig() {
0035       _store = 0;
0036       setupUi(this);
0037     }
0038 
0039     ~ConfigWidgetLineFitPlugin() {}
0040 
0041     void setObjectStore(Kst::ObjectStore* store) { 
0042       _store = store; 
0043       _vectorX->setObjectStore(store); 
0044       _vectorY->setObjectStore(store); 
0045     }
0046 
0047     void setupSlots(QWidget* dialog) {
0048       if (dialog) {
0049         connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0050         connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
0051       }
0052     }
0053 
0054     Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); };
0055     void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); };
0056 
0057     Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); };
0058     void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); };
0059 
0060     virtual void setupFromObject(Kst::Object* dataObject) {
0061       if (LineFitSource* source = static_cast<LineFitSource*>(dataObject)) {
0062         setSelectedVectorX(source->vectorX());
0063         setSelectedVectorY(source->vectorY());
0064       }
0065     }
0066 
0067     virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
0068       Q_UNUSED(store);
0069       Q_UNUSED(attrs);
0070 
0071       bool validTag = true;
0072 
0073 //       QStringRef av;
0074 //       av = attrs.value("value");
0075 //       if (!av.isNull()) {
0076 //         _configValue = QVariant(av.toString()).toBool();
0077 //       }
0078 
0079       return validTag;
0080     }
0081 
0082   public slots:
0083     virtual void save() {
0084       if (_cfg) {
0085         _cfg->beginGroup("Line Fit DataObject Plugin");
0086         _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name());
0087         _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name());
0088         _cfg->endGroup();
0089       }
0090     }
0091 
0092     virtual void load() {
0093       if (_cfg && _store) {
0094         _cfg->beginGroup("Line Fit DataObject Plugin");
0095         QString vectorName = _cfg->value("Input Vector X").toString();
0096         Kst::Object* object = _store->retrieveObject(vectorName);
0097         Kst::Vector* vector = static_cast<Kst::Vector*>(object);
0098         if (vector) {
0099           setSelectedVectorX(vector);
0100         }
0101         vectorName = _cfg->value("Input Vector Y").toString();
0102         object = _store->retrieveObject(vectorName);
0103         Kst::Vector* vectory = static_cast<Kst::Vector*>(object);
0104         if (vectory) {
0105           setSelectedVectorY(vectory);
0106         }
0107         _cfg->endGroup();
0108       }
0109     }
0110 
0111   private:
0112     Kst::ObjectStore *_store;
0113 
0114 };
0115 
0116 
0117 LineFitSource::LineFitSource(Kst::ObjectStore *store)
0118 : Kst::BasicPlugin(store) {
0119 }
0120 
0121 
0122 LineFitSource::~LineFitSource() {
0123 }
0124 
0125 
0126 QString LineFitSource::_automaticDescriptiveName() const {
0127   return tr("Line Fit Plugin Object");
0128 }
0129 
0130 
0131 void LineFitSource::change(Kst::DataObjectConfigWidget *configWidget) {
0132   if (ConfigWidgetLineFitPlugin* config = static_cast<ConfigWidgetLineFitPlugin*>(configWidget)) {
0133     setInputVector(VECTOR_IN_X, config->selectedVectorX());
0134     setInputVector(VECTOR_IN_Y, config->selectedVectorY());
0135   }
0136 }
0137 
0138 
0139 void LineFitSource::setupOutputs() {
0140   setOutputVector(VECTOR_OUT_X, "");
0141   setOutputVector(VECTOR_OUT_Y, "");
0142   setOutputScalar(SCALAR_OUT_A, "");
0143   setOutputScalar(SCALAR_OUT_B, "");
0144   setOutputScalar(SCALAR_OUT_CHI2, "");
0145 }
0146 
0147 
0148 bool LineFitSource::algorithm() {
0149   Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
0150   Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
0151   Kst::VectorPtr outputVectorX = _outputVectors[VECTOR_OUT_X];
0152   Kst::VectorPtr outputVectorY = _outputVectors[VECTOR_OUT_Y];
0153 
0154   Kst::ScalarPtr outputScalarA = _outputScalars[SCALAR_OUT_A];
0155   Kst::ScalarPtr outputScalarB = _outputScalars[SCALAR_OUT_B];
0156   Kst::ScalarPtr outputScalarChi = _outputScalars[SCALAR_OUT_CHI2];
0157 
0158   int i = 0;
0159   double a = 0.0, b = 0.0, sx = 0.0, sy = 0.0, sxoss = 0.0, st2 = 0.0, chi2 = 0.0;
0160   double xScale;
0161 
0162   if (inputVectorY->length() < 1) {
0163     _errorString = tr("Error: Input Vector Y Length invalid");
0164     return false;
0165   }
0166 
0167   if (inputVectorX->length() < 1) {
0168     _errorString = tr("Error: Input Vector X Length invalid");
0169     return false;
0170   }
0171 
0172   outputVectorX->resize( 2, false );
0173   outputVectorY->resize( 2, false );
0174 
0175   double const * vX_in = inputVectorX->noNanValue();
0176   double const * vY_in = inputVectorY->noNanValue();
0177   double* vX_out = outputVectorX->raw_V_ptr();
0178   double* vY_out = outputVectorY->raw_V_ptr();
0179 
0180   if (inputVectorY->length() == 1) {
0181     vX_out[0] = vX_in[0];
0182     vX_out[1] = vX_in[inputVectorX->length() - 1];
0183     vY_out[0] = vY_in[0];
0184     vY_out[1] = vY_in[0];
0185     outputScalarA->setValue( vY_in[0] );
0186     outputScalarB->setValue( 0 );
0187     outputScalarChi->setValue( chi2 );
0188     return true;
0189   }
0190 
0191   xScale = inputVectorX->length()/inputVectorY->length();
0192 
0193   for (i = 0; i < inputVectorY->length(); ++i) {
0194     double z = xScale*i;
0195     long int idx = long(Kst::roundDouble(z));
0196     double skew = z - floor(z); /* [0..1] */
0197     long int idx2 = idx + 1;
0198     sy += vY_in[i];
0199     while (idx2 >= inputVectorY->length()) {
0200       idx2--;
0201     }
0202     sx += vX_in[idx] + (vX_in[idx2] - vX_in[idx])*skew;
0203   }
0204 
0205   sxoss = sx / inputVectorX->length();
0206 
0207   for (i = 0; i < inputVectorX->length(); ++i) {
0208     double t = vX_in[i] - sxoss;
0209     st2 += t * t;
0210     b += t * vY_in[i];
0211   }
0212 
0213   b /= st2;
0214   a = (sy - sx*b)/inputVectorX->length();
0215 
0216   /* could put goodness of fit, etc, in here */
0217 
0218   vX_out[0] = vX_in[0];
0219   vX_out[1] = vX_in[inputVectorX->length()-1];
0220   vY_out[0] = a+b*vX_out[0];
0221   vY_out[1] = a+b*vX_out[1];
0222 
0223   for (i = 0; i < inputVectorX->length(); ++i) {
0224     double z = xScale*i;
0225     long int idx = long(Kst::roundDouble(z));
0226     double skew = z - floor(z); /* [0..1] */
0227     long int idx2 = idx + 1;
0228     double newX;
0229     double ci;
0230     while (idx2 >= inputVectorX->length()) {
0231       idx2--;
0232     }
0233     newX = vX_in[idx] + (vX_in[idx2] - vX_in[idx])*skew;
0234     ci = vY_in[i] - a - b*newX;
0235     chi2 += ci*ci;
0236   }
0237 
0238   outputScalarA->setValue( a );
0239   outputScalarB->setValue( b );
0240   outputScalarChi->setValue( chi2 );
0241   return true;
0242 }
0243 
0244 
0245 Kst::VectorPtr LineFitSource::vectorX() const {
0246   return _inputVectors[VECTOR_IN_X];
0247 }
0248 
0249 
0250 Kst::VectorPtr LineFitSource::vectorY() const {
0251   return _inputVectors[VECTOR_IN_Y];
0252 }
0253 
0254 
0255 QStringList LineFitSource::inputVectorList() const {
0256   QStringList vectors(VECTOR_IN_X);
0257   vectors += VECTOR_IN_Y;
0258   return vectors;
0259 }
0260 
0261 
0262 QStringList LineFitSource::inputScalarList() const {
0263   return QStringList( /*SCALAR_IN*/ );
0264 }
0265 
0266 
0267 QStringList LineFitSource::inputStringList() const {
0268   return QStringList( /*STRING_IN*/ );
0269 }
0270 
0271 
0272 QStringList LineFitSource::outputVectorList() const {
0273   QStringList vectors(VECTOR_OUT_X);
0274   vectors += VECTOR_OUT_Y;
0275   return vectors;
0276 }
0277 
0278 
0279 QStringList LineFitSource::outputScalarList() const {
0280   QStringList scalars(SCALAR_OUT_A);
0281   scalars += SCALAR_OUT_B;
0282   scalars += SCALAR_OUT_CHI2;
0283   return scalars;
0284 }
0285 
0286 
0287 QStringList LineFitSource::outputStringList() const {
0288   return QStringList( /*STRING_OUT*/ );
0289 }
0290 
0291 
0292 void LineFitSource::saveProperties(QXmlStreamWriter &s) {
0293   Q_UNUSED(s);
0294 //   s.writeAttribute("value", _configValue);
0295 }
0296 
0297 
0298 QString LineFitPlugin::pluginName() const { return tr("Line Fit"); }
0299 QString LineFitPlugin::pluginDescription() const { return tr("Generates a line of best fit for a set of data."); }
0300 
0301 
0302 Kst::DataObject *LineFitPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
0303 
0304   if (ConfigWidgetLineFitPlugin* config = static_cast<ConfigWidgetLineFitPlugin*>(configWidget)) {
0305 
0306     LineFitSource* object = store->createObject<LineFitSource>();
0307 
0308     if (setupInputsOutputs) {
0309       object->setupOutputs();
0310       object->setInputVector(VECTOR_IN_X, config->selectedVectorX());
0311       object->setInputVector(VECTOR_IN_Y, config->selectedVectorY());
0312     }
0313 
0314     object->setPluginName(pluginName());
0315 
0316     object->writeLock();
0317     object->registerChange();
0318     object->unlock();
0319 
0320     return object;
0321   }
0322   return 0;
0323 }
0324 
0325 
0326 Kst::DataObjectConfigWidget *LineFitPlugin::configWidget(QSettings *settingsObject) const {
0327   ConfigWidgetLineFitPlugin *widget = new ConfigWidgetLineFitPlugin(settingsObject);
0328   return widget;
0329 }
0330 
0331 #ifndef QT5
0332 Q_EXPORT_PLUGIN2(kstplugin_ConvolvePlugin, LineFitPlugin)
0333 #endif
0334 
0335 // vim: ts=2 sw=2 et