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