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 "fitsinusoid_unweighted.h"
17 #include "objectstore.h"
18 #include "ui_fitsinusoid_unweightedconfig.h"
19
20 #include <gsl/gsl_fit.h>
21 // #include "../common.h"
22 #include "../linear.h"
23
24 static const QString& VECTOR_IN_X = "X Vector";
25 static const QString& VECTOR_IN_Y = "Y 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& SCALAR_IN_PERIOD = "Period Scalar";
31 static const QString& SCALAR_IN_HARMONICS = "Harmonics Scalar";
32 static const QString& SCALAR_OUT = "chi^2/nu";
33
34 class ConfigWidgetFitSinusoidUnweightedPlugin : public Kst::DataObjectConfigWidget, public Ui_FitSinusoid_UnweightedConfig {
35 public:
ConfigWidgetFitSinusoidUnweightedPlugin(QSettings * cfg)36 ConfigWidgetFitSinusoidUnweightedPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_FitSinusoid_UnweightedConfig() {
37 _store = 0;
38 setupUi(this);
39 }
40
~ConfigWidgetFitSinusoidUnweightedPlugin()41 ~ConfigWidgetFitSinusoidUnweightedPlugin() {}
42
setObjectStore(Kst::ObjectStore * store)43 void setObjectStore(Kst::ObjectStore* store) {
44 _store = store;
45 _vectorX->setObjectStore(store);
46 _vectorY->setObjectStore(store);
47 _scalarHarmonics->setObjectStore(store);
48 _scalarPeriod->setObjectStore(store);
49 _scalarHarmonics->setDefaultValue(0);
50 _scalarPeriod->setDefaultValue(1);
51 }
52
setupSlots(QWidget * dialog)53 void setupSlots(QWidget* dialog) {
54 if (dialog) {
55 connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
56 connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
57 connect(_scalarHarmonics, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
58 connect(_scalarPeriod, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
59 }
60 }
61
setVectorX(Kst::VectorPtr vector)62 void setVectorX(Kst::VectorPtr vector) {
63 setSelectedVectorX(vector);
64 }
65
setVectorY(Kst::VectorPtr vector)66 void setVectorY(Kst::VectorPtr vector) {
67 setSelectedVectorY(vector);
68 }
69
setVectorsLocked(bool locked=true)70 void setVectorsLocked(bool locked = true) {
71 _vectorX->setEnabled(!locked);
72 _vectorY->setEnabled(!locked);
73 }
74
selectedVectorX()75 Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); };
setSelectedVectorX(Kst::VectorPtr vector)76 void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); };
77
selectedVectorY()78 Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); };
setSelectedVectorY(Kst::VectorPtr vector)79 void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); };
80
selectedScalarHarmonics()81 Kst::ScalarPtr selectedScalarHarmonics() { return _scalarHarmonics->selectedScalar(); };
setSelectedScalarHarmonics(Kst::ScalarPtr scalar)82 void setSelectedScalarHarmonics(Kst::ScalarPtr scalar) { return _scalarHarmonics->setSelectedScalar(scalar); };
83
selectedScalarPeriod()84 Kst::ScalarPtr selectedScalarPeriod() { return _scalarPeriod->selectedScalar(); };
setSelectedScalarPeriod(Kst::ScalarPtr scalar)85 void setSelectedScalarPeriod(Kst::ScalarPtr scalar) { return _scalarPeriod->setSelectedScalar(scalar); };
86
setupFromObject(Kst::Object * dataObject)87 virtual void setupFromObject(Kst::Object* dataObject) {
88 if (FitSinusoidUnweightedSource* source = static_cast<FitSinusoidUnweightedSource*>(dataObject)) {
89 setSelectedVectorX(source->vectorX());
90 setSelectedVectorY(source->vectorY());
91 setSelectedScalarHarmonics(source->scalarHarmonics());
92 setSelectedScalarPeriod(source->scalarPeriod());
93 }
94 }
95
configurePropertiesFromXml(Kst::ObjectStore * store,QXmlStreamAttributes & attrs)96 virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
97 Q_UNUSED(store);
98 Q_UNUSED(attrs);
99
100 bool validTag = true;
101
102 // QStringRef av;
103 // av = attrs.value("value");
104 // if (!av.isNull()) {
105 // _configValue = QVariant(av.toString()).toBool();
106 // }
107
108 return validTag;
109 }
110
111 public slots:
save()112 virtual void save() {
113 if (_cfg) {
114 _cfg->beginGroup("Fit Sinusoid Plugin");
115 _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name());
116 _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name());
117 _cfg->setValue("Input Scalar Harmonics", _scalarHarmonics->selectedScalar()->Name());
118 _cfg->setValue("Input Scalar Period", _scalarPeriod->selectedScalar()->Name());
119 _cfg->endGroup();
120 }
121 }
122
load()123 virtual void load() {
124 if (_cfg && _store) {
125 _cfg->beginGroup("Fit Sinusoid Plugin");
126 QString vectorName = _cfg->value("Input Vector X").toString();
127 Kst::Object* object = _store->retrieveObject(vectorName);
128 Kst::Vector* vectorx = static_cast<Kst::Vector*>(object);
129 if (vectorx) {
130 setSelectedVectorX(vectorx);
131 }
132 vectorName = _cfg->value("Input Vector Y").toString();
133 object = _store->retrieveObject(vectorName);
134 Kst::Vector* vectory = static_cast<Kst::Vector*>(object);
135 if (vectory) {
136 setSelectedVectorX(vectory);
137 }
138 QString scalarName = _cfg->value("Harmonics Scalar").toString();
139 object = _store->retrieveObject(scalarName);
140 Kst::Scalar* harmonicsScalar = static_cast<Kst::Scalar*>(object);
141 if (harmonicsScalar) {
142 setSelectedScalarHarmonics(harmonicsScalar);
143 }
144 scalarName = _cfg->value("Period Scalar").toString();
145 object = _store->retrieveObject(scalarName);
146 Kst::Scalar* periodScalar = static_cast<Kst::Scalar*>(object);
147 if (periodScalar) {
148 setSelectedScalarPeriod(periodScalar);
149 }
150 _cfg->endGroup();
151 }
152 }
153
154 private:
155 Kst::ObjectStore *_store;
156
157 };
158
159
FitSinusoidUnweightedSource(Kst::ObjectStore * store)160 FitSinusoidUnweightedSource::FitSinusoidUnweightedSource(Kst::ObjectStore *store)
161 : Kst::BasicPlugin(store) {
162 }
163
164
~FitSinusoidUnweightedSource()165 FitSinusoidUnweightedSource::~FitSinusoidUnweightedSource() {
166 }
167
168
_automaticDescriptiveName() const169 QString FitSinusoidUnweightedSource::_automaticDescriptiveName() const {
170 return tr("%1 Sinusoid").arg(vectorY()->descriptiveName());;
171 }
172
173
change(Kst::DataObjectConfigWidget * configWidget)174 void FitSinusoidUnweightedSource::change(Kst::DataObjectConfigWidget *configWidget) {
175 if (ConfigWidgetFitSinusoidUnweightedPlugin* config = static_cast<ConfigWidgetFitSinusoidUnweightedPlugin*>(configWidget)) {
176 setInputVector(VECTOR_IN_X, config->selectedVectorX());
177 setInputVector(VECTOR_IN_Y, config->selectedVectorY());
178 setInputScalar(SCALAR_IN_HARMONICS, config->selectedScalarHarmonics());
179 setInputScalar(SCALAR_IN_PERIOD, config->selectedScalarPeriod());
180 }
181 }
182
183
setupOutputs()184 void FitSinusoidUnweightedSource::setupOutputs() {
185 setOutputVector(VECTOR_OUT_Y_FITTED, "");
186 setOutputVector(VECTOR_OUT_Y_RESIDUALS, "");
187 setOutputVector(VECTOR_OUT_Y_PARAMETERS, "");
188 setOutputVector(VECTOR_OUT_Y_COVARIANCE, "");
189 setOutputScalar(SCALAR_OUT, "");
190 }
191
192
193 double g_dPeriod;
calculate_matrix_entry(double dX,int iPos)194 double calculate_matrix_entry( double dX, int iPos ) {
195 double dY;
196
197 if( iPos == 0 ) {
198 dY = 1.0;
199 } else if( iPos % 2 == 1 ) {
200 dY = cos( (double)( ( iPos + 1 ) / 2 ) * 2.0 * M_PI * dX / g_dPeriod );
201 } else {
202 dY = -sin( (double)( ( iPos + 0 ) / 2 ) * 2.0 * M_PI * dX / g_dPeriod );
203 }
204
205 return dY;
206 }
207
208
algorithm()209 bool FitSinusoidUnweightedSource::algorithm() {
210 Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
211 Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
212 Kst::ScalarPtr inputScalarHarmonics = _inputScalars[SCALAR_IN_HARMONICS];
213 Kst::ScalarPtr inputScalarPeriod = _inputScalars[SCALAR_IN_PERIOD];
214
215 Kst::VectorPtr outputVectorYFitted = _outputVectors[VECTOR_OUT_Y_FITTED];
216 Kst::VectorPtr outputVectorYResiduals = _outputVectors[VECTOR_OUT_Y_RESIDUALS];
217 Kst::VectorPtr outputVectorYParameters = _outputVectors[VECTOR_OUT_Y_PARAMETERS];
218 Kst::VectorPtr outputVectorYCovariance = _outputVectors[VECTOR_OUT_Y_COVARIANCE];
219 Kst::ScalarPtr outputScalar = _outputScalars[SCALAR_OUT];
220
221 Kst::LabelInfo label_info = inputVectorY->labelInfo();
222 label_info.name = tr("Sinusoidal Fit to %1").arg(label_info.name);
223 outputVectorYFitted->setLabelInfo(label_info);
224
225 label_info.name = tr("Sinusoidal Fit Residuals");
226 outputVectorYResiduals->setLabelInfo(label_info);
227
228 bool bReturn = false;
229
230 int iNumParams;
231
232 iNumParams = 3 + ( 2 * (int)floor( inputScalarHarmonics->value() ) );
233 if( iNumParams >= 3 ) {
234 g_dPeriod = inputScalarPeriod->value();
235 if( g_dPeriod > 0.0 )
236 {
237 bReturn = kstfit_linear_unweighted( inputVectorX, inputVectorY,
238 outputVectorYFitted, outputVectorYResiduals, outputVectorYParameters,
239 outputVectorYCovariance, outputScalar, iNumParams );
240 }
241 }
242
243 return bReturn;
244 }
245
246
vectorX() const247 Kst::VectorPtr FitSinusoidUnweightedSource::vectorX() const {
248 return _inputVectors[VECTOR_IN_X];
249 }
250
251
vectorY() const252 Kst::VectorPtr FitSinusoidUnweightedSource::vectorY() const {
253 return _inputVectors[VECTOR_IN_Y];
254 }
255
256
scalarHarmonics() const257 Kst::ScalarPtr FitSinusoidUnweightedSource::scalarHarmonics() const {
258 return _inputScalars[SCALAR_IN_HARMONICS];
259 }
260
261
scalarPeriod() const262 Kst::ScalarPtr FitSinusoidUnweightedSource::scalarPeriod() const {
263 return _inputScalars[SCALAR_IN_PERIOD];
264 }
265
266
inputVectorList() const267 QStringList FitSinusoidUnweightedSource::inputVectorList() const {
268 QStringList vectors(VECTOR_IN_X);
269 vectors += VECTOR_IN_Y;
270 return vectors;
271 }
272
273
inputScalarList() const274 QStringList FitSinusoidUnweightedSource::inputScalarList() const {
275 QStringList scalars(SCALAR_IN_HARMONICS);
276 scalars += SCALAR_IN_PERIOD;
277 return scalars;
278 }
279
280
inputStringList() const281 QStringList FitSinusoidUnweightedSource::inputStringList() const {
282 return QStringList( /*STRING_IN*/ );
283 }
284
285
outputVectorList() const286 QStringList FitSinusoidUnweightedSource::outputVectorList() const {
287 QStringList vectors(VECTOR_OUT_Y_FITTED);
288 vectors += VECTOR_OUT_Y_RESIDUALS;
289 vectors += VECTOR_OUT_Y_PARAMETERS;
290 vectors += VECTOR_OUT_Y_COVARIANCE;
291 vectors += VECTOR_OUT_Y_PARAMETERS;
292 return vectors;
293 }
294
295
outputScalarList() const296 QStringList FitSinusoidUnweightedSource::outputScalarList() const {
297 return QStringList( SCALAR_OUT );
298 }
299
300
outputStringList() const301 QStringList FitSinusoidUnweightedSource::outputStringList() const {
302 return QStringList( /*STRING_OUT*/ );
303 }
304
305
saveProperties(QXmlStreamWriter & s)306 void FitSinusoidUnweightedSource::saveProperties(QXmlStreamWriter &s) {
307 Q_UNUSED(s);
308 // s.writeAttribute("value", _configValue);
309 }
310
311
parameterName(int index) const312 QString FitSinusoidUnweightedSource::parameterName(int index) const {
313 QString parameter;
314 switch (index) {
315 case 0:
316 parameter = "Mean";
317 break;
318 case 1:
319 parameter = "cos(%1 2PI x/P)";
320 parameter = parameter.arg((index + 1 ) / 2);
321 break;
322 case 2:
323 parameter = "-sin(%1 2PI x/P)";
324 parameter = parameter.arg((index + 0 ) / 2);
325 break;
326 }
327
328 return parameter;
329 }
330
331
332 // Name used to identify the plugin. Used when loading the plugin.
pluginName() const333 QString FitSinusoidUnweightedPlugin::pluginName() const { return tr("Sinusoid Fit"); }
pluginDescription() const334 QString FitSinusoidUnweightedPlugin::pluginDescription() const { return tr("Generates a sinusoid fit for a set of data."); }
335
336
create(Kst::ObjectStore * store,Kst::DataObjectConfigWidget * configWidget,bool setupInputsOutputs) const337 Kst::DataObject *FitSinusoidUnweightedPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
338
339 if (ConfigWidgetFitSinusoidUnweightedPlugin* config = static_cast<ConfigWidgetFitSinusoidUnweightedPlugin*>(configWidget)) {
340
341 Kst::ScalarPtr harmonics;
342 Kst::ScalarPtr period;
343
344 // access/create input scalars before creating plugin
345 // in order to preserve continuous scalar shortnames
346 if (setupInputsOutputs) {
347 harmonics = config->selectedScalarHarmonics();
348 period = config->selectedScalarPeriod();
349 }
350
351 FitSinusoidUnweightedSource* object = store->createObject<FitSinusoidUnweightedSource>();
352
353 if (setupInputsOutputs) {
354 object->setInputScalar(SCALAR_IN_HARMONICS, harmonics);
355 object->setInputScalar(SCALAR_IN_PERIOD, period);
356 object->setupOutputs();
357 object->setInputVector(VECTOR_IN_X, config->selectedVectorX());
358 object->setInputVector(VECTOR_IN_Y, config->selectedVectorY());
359 }
360
361 object->setPluginName(pluginName());
362
363 object->writeLock();
364 object->registerChange();
365 object->unlock();
366
367 return object;
368 }
369 return 0;
370 }
371
372
configWidget(QSettings * settingsObject) const373 Kst::DataObjectConfigWidget *FitSinusoidUnweightedPlugin::configWidget(QSettings *settingsObject) const {
374 ConfigWidgetFitSinusoidUnweightedPlugin *widget = new ConfigWidgetFitSinusoidUnweightedPlugin(settingsObject);
375 return widget;
376 }
377
378 #ifndef QT5
379 Q_EXPORT_PLUGIN2(kstplugin_FitSinusoidUnweightedPlugin, FitSinusoidUnweightedPlugin)
380 #endif
381
382 // vim: ts=2 sw=2 et
383