1 /***************************************************************************
2  *                                                                         *
3  *   copyright : (C) 2007 The University of Toronto                        *
4  *                   netterfield@astro.utoronto.ca                         *
5  *   copyright : (C) 2005  University of British Columbia                  *
6  *                   dscott@phas.ubc.ca                                    *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  ***************************************************************************/
14 
15 
16 #include "fitlinear_weighted.h"
17 #include "objectstore.h"
18 #include "ui_fitlinear_weightedconfig.h"
19 
20 #include <gsl/gsl_fit.h>
21 #include "../common.h"
22 
23 static const QString& VECTOR_IN_X = "X Vector";
24 static const QString& VECTOR_IN_Y = "Y Vector";
25 static const QString& VECTOR_IN_WEIGHTS = "Weights Vector";
26 static const QString& VECTOR_OUT_Y_FITTED = "Fit";
27 static const QString& VECTOR_OUT_Y_RESIDUALS = "Residuals";
28 static const QString& VECTOR_OUT_Y_PARAMETERS = "Parameters Vector";
29 static const QString& VECTOR_OUT_Y_COVARIANCE = "Covariance";
30 static const QString& VECTOR_OUT_Y_LO = "Lo Vector";
31 static const QString& VECTOR_OUT_Y_HI = "Hi Vector";
32 static const QString& SCALAR_OUT = "chi^2/nu";
33 
34 class ConfigWidgetFitLinearWeightedPlugin : public Kst::DataObjectConfigWidget, public Ui_FitLinear_WeightedConfig {
35   public:
ConfigWidgetFitLinearWeightedPlugin(QSettings * cfg)36     ConfigWidgetFitLinearWeightedPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_FitLinear_WeightedConfig() {
37       _store = 0;
38       setupUi(this);
39     }
40 
~ConfigWidgetFitLinearWeightedPlugin()41     ~ConfigWidgetFitLinearWeightedPlugin() {}
42 
setObjectStore(Kst::ObjectStore * store)43     void setObjectStore(Kst::ObjectStore* store) {
44       _store = store;
45       _vectorX->setObjectStore(store);
46       _vectorY->setObjectStore(store);
47       _vectorWeights->setObjectStore(store);
48     }
49 
setupSlots(QWidget * dialog)50     void setupSlots(QWidget* dialog) {
51       if (dialog) {
52         connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
53         connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
54         connect(_vectorWeights, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
55       }
56     }
57 
58 
setVectorX(Kst::VectorPtr vector)59     void setVectorX(Kst::VectorPtr vector) {
60       setSelectedVectorX(vector);
61     }
62 
setVectorY(Kst::VectorPtr vector)63     void setVectorY(Kst::VectorPtr vector) {
64       setSelectedVectorY(vector);
65     }
66 
setVectorsLocked(bool locked=true)67     void setVectorsLocked(bool locked = true) {
68       _vectorX->setEnabled(!locked);
69       _vectorY->setEnabled(!locked);
70     }
71 
selectedVectorX()72     Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); };
setSelectedVectorX(Kst::VectorPtr vector)73     void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); };
74 
selectedVectorY()75     Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); };
setSelectedVectorY(Kst::VectorPtr vector)76     void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); };
77 
selectedVectorWeights()78     Kst::VectorPtr selectedVectorWeights() { return _vectorWeights->selectedVector(); };
setSelectedVectorWeights(Kst::VectorPtr vector)79     void setSelectedVectorWeights(Kst::VectorPtr vector) { return _vectorWeights->setSelectedVector(vector); };
80 
setupFromObject(Kst::Object * dataObject)81     virtual void setupFromObject(Kst::Object* dataObject) {
82       if (FitLinearWeightedSource* source = static_cast<FitLinearWeightedSource*>(dataObject)) {
83         setSelectedVectorX(source->vectorX());
84         setSelectedVectorY(source->vectorY());
85         setSelectedVectorWeights(source->vectorWeights());
86       }
87     }
88 
configurePropertiesFromXml(Kst::ObjectStore * store,QXmlStreamAttributes & attrs)89     virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
90       Q_UNUSED(store);
91       Q_UNUSED(attrs);
92 
93       bool validTag = true;
94 
95 //       QStringRef av;
96 //       av = attrs.value("value");
97 //       if (!av.isNull()) {
98 //         _configValue = QVariant(av.toString()).toBool();
99 //       }
100 
101       return validTag;
102     }
103 
104   public slots:
save()105     virtual void save() {
106       if (_cfg) {
107         _cfg->beginGroup("Fit Linear Weighted Plugin");
108         _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name());
109         _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name());
110         _cfg->setValue("Input Vector Weights", _vectorWeights->selectedVector()->Name());
111         _cfg->endGroup();
112       }
113     }
114 
load()115     virtual void load() {
116       if (_cfg && _store) {
117         _cfg->beginGroup("Fit Linear Weighted Plugin");
118         QString vectorName = _cfg->value("Input Vector X").toString();
119         Kst::Object* object = _store->retrieveObject(vectorName);
120         Kst::Vector* vectorx = static_cast<Kst::Vector*>(object);
121         if (vectorx) {
122           setSelectedVectorX(vectorx);
123         }
124         vectorName = _cfg->value("Input Vector Y").toString();
125         object = _store->retrieveObject(vectorName);
126         Kst::Vector* vectory = static_cast<Kst::Vector*>(object);
127         if (vectory) {
128           setSelectedVectorX(vectory);
129         }
130         vectorName = _cfg->value("Input Vector Weights").toString();
131         object = _store->retrieveObject(vectorName);
132         Kst::Vector* vectorweights = static_cast<Kst::Vector*>(object);
133         if (vectorweights) {
134           setSelectedVectorX(vectorweights);
135         }
136         _cfg->endGroup();
137       }
138     }
139 
140   private:
141     Kst::ObjectStore *_store;
142 
143 };
144 
145 
FitLinearWeightedSource(Kst::ObjectStore * store)146 FitLinearWeightedSource::FitLinearWeightedSource(Kst::ObjectStore *store)
147 : Kst::BasicPlugin(store) {
148 }
149 
150 
~FitLinearWeightedSource()151 FitLinearWeightedSource::~FitLinearWeightedSource() {
152 }
153 
154 
_automaticDescriptiveName() const155 QString FitLinearWeightedSource::_automaticDescriptiveName() const {
156   return tr("%1 Weighted Linear").arg(vectorY()->descriptiveName());
157 }
158 
159 
change(Kst::DataObjectConfigWidget * configWidget)160 void FitLinearWeightedSource::change(Kst::DataObjectConfigWidget *configWidget) {
161   if (ConfigWidgetFitLinearWeightedPlugin* config = static_cast<ConfigWidgetFitLinearWeightedPlugin*>(configWidget)) {
162     setInputVector(VECTOR_IN_X, config->selectedVectorX());
163     setInputVector(VECTOR_IN_Y, config->selectedVectorY());
164     setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights());
165   }
166 }
167 
168 
setupOutputs()169 void FitLinearWeightedSource::setupOutputs() {
170   setOutputVector(VECTOR_OUT_Y_FITTED, "");
171   setOutputVector(VECTOR_OUT_Y_RESIDUALS, "");
172   setOutputVector(VECTOR_OUT_Y_PARAMETERS, "");
173   setOutputVector(VECTOR_OUT_Y_COVARIANCE, "");
174   setOutputVector(VECTOR_OUT_Y_LO, "");
175   setOutputVector(VECTOR_OUT_Y_HI, "");
176   setOutputScalar(SCALAR_OUT, "");
177 }
178 
179 
algorithm()180 bool FitLinearWeightedSource::algorithm() {
181   Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
182   Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
183   Kst::VectorPtr inputVectorWeights = _inputVectors[VECTOR_IN_WEIGHTS];
184 
185   Kst::VectorPtr outputVectorYFitted = _outputVectors[VECTOR_OUT_Y_FITTED];
186   Kst::VectorPtr outputVectorYResiduals = _outputVectors[VECTOR_OUT_Y_RESIDUALS];
187   Kst::VectorPtr outputVectorYParameters = _outputVectors[VECTOR_OUT_Y_PARAMETERS];
188   Kst::VectorPtr outputVectorYCovariance = _outputVectors[VECTOR_OUT_Y_COVARIANCE];
189   Kst::VectorPtr outputVectorYLo = _outputVectors[VECTOR_OUT_Y_LO];
190   Kst::VectorPtr outputVectorYHi = _outputVectors[VECTOR_OUT_Y_HI];
191   Kst::ScalarPtr outputScalar = _outputScalars[SCALAR_OUT];
192 
193   Kst::LabelInfo label_info = inputVectorY->labelInfo();
194   label_info.name = tr("Linear Fit to %1").arg(label_info.name);
195   outputVectorYFitted->setLabelInfo(label_info);
196 
197   label_info.name = tr("Linear Fit Residuals");
198   outputVectorYResiduals->setLabelInfo(label_info);
199 
200   label_info.name = tr("Linear Fit Lower Limit");
201   outputVectorYLo->setLabelInfo(label_info);
202 
203   label_info.name = tr("Linear Fit Upper Limit");
204   outputVectorYHi->setLabelInfo(label_info);
205 
206   int i = 0;
207   int iLength = 0;
208   bool bReturn = false;
209   double* pInputs[3];
210   double c0 = 0.0;
211   double c1 = 0.0;
212   double cov00 = 0.0;
213   double cov01 = 0.0;
214   double cov11 = 0.0;
215   double dSumSq = 0.0;
216   double y;
217   double yErr;
218 
219   if( precursor( inputVectorX, inputVectorY, inputVectorWeights, &iLength, true, true, 2, pInputs, outputVectorYFitted, outputVectorYResiduals, outputVectorYParameters, outputVectorYCovariance, outputVectorYLo, outputVectorYHi ) ) {
220 
221     if( !gsl_fit_wlinear( pInputs[XVALUES], 1, pInputs[WEIGHTS], 1, pInputs[YVALUES], 1, iLength, &c0, &c1, &cov00, &cov01, &cov11, &dSumSq ) ) {
222       for( i=0; i<iLength; ++i ) {
223         gsl_fit_linear_est( pInputs[XVALUES][i], c0, c1, cov00, cov01, cov11, &y, &yErr );
224         outputVectorYFitted->raw_V_ptr()[i] = y;
225         outputVectorYResiduals->raw_V_ptr()[i] = pInputs[YVALUES][i] - y;
226         outputVectorYLo->raw_V_ptr()[i] = y - yErr;
227         outputVectorYHi->raw_V_ptr()[i] = y + yErr;
228       }
229 
230       outputVectorYParameters->raw_V_ptr()[0] = c0;
231       outputVectorYParameters->raw_V_ptr()[1] = c1;
232       outputVectorYCovariance->raw_V_ptr()[0] = cov00;
233       outputVectorYCovariance->raw_V_ptr()[1] = cov01;
234       outputVectorYCovariance->raw_V_ptr()[2] = cov11;
235 
236       outputScalar->setValue(dSumSq / ( (double)iLength - 2.0 ));
237       bReturn = true;
238     }
239   }
240 
241   postcursor( true, pInputs );
242 
243   return bReturn;
244 }
245 
246 
vectorX() const247 Kst::VectorPtr FitLinearWeightedSource::vectorX() const {
248   return _inputVectors[VECTOR_IN_X];
249 }
250 
251 
vectorY() const252 Kst::VectorPtr FitLinearWeightedSource::vectorY() const {
253   return _inputVectors[VECTOR_IN_Y];
254 }
255 
256 
vectorWeights() const257 Kst::VectorPtr FitLinearWeightedSource::vectorWeights() const {
258   return _inputVectors[VECTOR_IN_WEIGHTS];
259 }
260 
261 
inputVectorList() const262 QStringList FitLinearWeightedSource::inputVectorList() const {
263   QStringList vectors(VECTOR_IN_X);
264   vectors += VECTOR_IN_Y;
265   vectors += VECTOR_IN_WEIGHTS;
266   return vectors;
267 }
268 
269 
inputScalarList() const270 QStringList FitLinearWeightedSource::inputScalarList() const {
271   return QStringList();
272 }
273 
274 
inputStringList() const275 QStringList FitLinearWeightedSource::inputStringList() const {
276   return QStringList( /*STRING_IN*/ );
277 }
278 
279 
outputVectorList() const280 QStringList FitLinearWeightedSource::outputVectorList() const {
281   QStringList vectors(VECTOR_OUT_Y_FITTED);
282   vectors += VECTOR_OUT_Y_RESIDUALS;
283   vectors += VECTOR_OUT_Y_PARAMETERS;
284   vectors += VECTOR_OUT_Y_COVARIANCE;
285   vectors += VECTOR_OUT_Y_LO;
286   vectors += VECTOR_OUT_Y_HI;
287   vectors += VECTOR_OUT_Y_PARAMETERS;
288   return vectors;
289 }
290 
291 
outputScalarList() const292 QStringList FitLinearWeightedSource::outputScalarList() const {
293   return QStringList( SCALAR_OUT );
294 }
295 
296 
outputStringList() const297 QStringList FitLinearWeightedSource::outputStringList() const {
298   return QStringList( /*STRING_OUT*/ );
299 }
300 
301 
saveProperties(QXmlStreamWriter & s)302 void FitLinearWeightedSource::saveProperties(QXmlStreamWriter &s) {
303   Q_UNUSED(s);
304 //   s.writeAttribute("value", _configValue);
305 }
306 
307 
parameterName(int index) const308 QString FitLinearWeightedSource::parameterName(int index) const {
309   QString parameter;
310   switch (index) {
311     case 0:
312       parameter = "Intercept";
313       break;
314     case 1:
315       parameter = "Gradient";
316       break;
317   }
318 
319   return parameter;
320 }
321 
322 
323 // Name used to identify the plugin.  Used when loading the plugin.
pluginName() const324 QString FitLinearWeightedPlugin::pluginName() const { return tr("Linear Weighted Fit"); }
pluginDescription() const325 QString FitLinearWeightedPlugin::pluginDescription() const { return tr("Generates a linear weighted fit for a set of data."); }
326 
327 
create(Kst::ObjectStore * store,Kst::DataObjectConfigWidget * configWidget,bool setupInputsOutputs) const328 Kst::DataObject *FitLinearWeightedPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
329 
330   if (ConfigWidgetFitLinearWeightedPlugin* config = static_cast<ConfigWidgetFitLinearWeightedPlugin*>(configWidget)) {
331 
332     FitLinearWeightedSource* object = store->createObject<FitLinearWeightedSource>();
333 
334     if (setupInputsOutputs) {
335       object->setupOutputs();
336       object->setInputVector(VECTOR_IN_X, config->selectedVectorX());
337       object->setInputVector(VECTOR_IN_Y, config->selectedVectorY());
338       object->setInputVector(VECTOR_IN_WEIGHTS, config->selectedVectorWeights());
339     }
340 
341     object->setPluginName(pluginName());
342 
343     object->writeLock();
344     object->registerChange();
345     object->unlock();
346 
347     return object;
348   }
349   return 0;
350 }
351 
352 
configWidget(QSettings * settingsObject) const353 Kst::DataObjectConfigWidget *FitLinearWeightedPlugin::configWidget(QSettings *settingsObject) const {
354   ConfigWidgetFitLinearWeightedPlugin *widget = new ConfigWidgetFitLinearWeightedPlugin(settingsObject);
355   return widget;
356 }
357 
358 #ifndef QT5
359 Q_EXPORT_PLUGIN2(kstplugin_FitLinearWeightedPlugin, FitLinearWeightedPlugin)
360 #endif
361 
362 // vim: ts=2 sw=2 et
363