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