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