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 /* bin Y values into N bins from X min to X max, according to their X values.
16 This is like a 1D map, where X specifices the pixel the data go into. */
17
18 #include "syncbin.h"
19 #include "objectstore.h"
20 #include "ui_syncbinconfig.h"
21
22 // macros to find the top, bottom, and middle of a bin
23 #define BINMID(x) XMin+(XMax-XMin)*(double(x)+0.5)/double(nbins)
24
25 #define BIN( x ) int(double(nbins)*(x-XMin)/(XMax-XMin))
26
27 static const QString& VECTOR_IN_X = "Vector In X";
28 static const QString& VECTOR_IN_Y = "Vector In Y";
29 static const QString& SCALAR_IN_BINS = "Number of Bins";
30 static const QString& SCALAR_IN_XMIN = "X Min";
31 static const QString& SCALAR_IN_XMAX = "X Max";
32
33 static const QString& VECTOR_OUT_X_OUT = "X out";
34 static const QString& VECTOR_OUT_Y_OUT = "Y out";
35 static const QString& VECTOR_OUT_Y_ERROR = "Y error";
36 static const QString& VECTOR_OUT_N = "N";
37
38 class ConfigSyncBinPlugin : public Kst::DataObjectConfigWidget, public Ui_SyncBinConfig {
39 public:
ConfigSyncBinPlugin(QSettings * cfg)40 ConfigSyncBinPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_SyncBinConfig() {
41 _store = 0;
42 setupUi(this);
43 }
44
~ConfigSyncBinPlugin()45 ~ConfigSyncBinPlugin() {}
46
setObjectStore(Kst::ObjectStore * store)47 void setObjectStore(Kst::ObjectStore* store) {
48 _store = store;
49 _vectorX->setObjectStore(store);
50 _vectorY->setObjectStore(store);
51 _scalarBins->setObjectStore(store);
52 _scalarXMin->setObjectStore(store);
53 _scalarXMax->setObjectStore(store);
54 _scalarBins->setDefaultValue(0);
55 _scalarXMin->setDefaultValue(0);
56 _scalarXMax->setDefaultValue(0);
57 }
58
setupSlots(QWidget * dialog)59 void setupSlots(QWidget* dialog) {
60 if (dialog) {
61 connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
62 connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
63 connect(_scalarBins, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
64 connect(_scalarXMin, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
65 connect(_scalarXMax, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified()));
66 }
67 }
68
selectedVectorX()69 Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); };
setSelectedVectorX(Kst::VectorPtr vector)70 void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); };
71
selectedVectorY()72 Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); };
setSelectedVectorY(Kst::VectorPtr vector)73 void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); };
74
selectedScalarBins()75 Kst::ScalarPtr selectedScalarBins() { return _scalarBins->selectedScalar(); };
setSelectedScalarBins(Kst::ScalarPtr scalar)76 void setSelectedScalarBins(Kst::ScalarPtr scalar) { return _scalarBins->setSelectedScalar(scalar); };
77
selectedScalarXMin()78 Kst::ScalarPtr selectedScalarXMin() { return _scalarXMin->selectedScalar(); };
setSelectedScalarXMin(Kst::ScalarPtr scalar)79 void setSelectedScalarXMin(Kst::ScalarPtr scalar) { return _scalarXMin->setSelectedScalar(scalar); };
80
selectedScalarXMax()81 Kst::ScalarPtr selectedScalarXMax() { return _scalarXMax->selectedScalar(); };
setSelectedScalarXMax(Kst::ScalarPtr scalar)82 void setSelectedScalarXMax(Kst::ScalarPtr scalar) { return _scalarXMax->setSelectedScalar(scalar); };
83
84
setupFromObject(Kst::Object * dataObject)85 virtual void setupFromObject(Kst::Object* dataObject) {
86 if (SyncBinSource* source = static_cast<SyncBinSource*>(dataObject)) {
87 setSelectedVectorX(source->vectorX());
88 setSelectedVectorY(source->vectorY());
89 setSelectedScalarBins(source->scalarBins());
90 setSelectedScalarXMin(source->scalarXMin());
91 setSelectedScalarXMax(source->scalarXMax());
92 }
93 }
94
configurePropertiesFromXml(Kst::ObjectStore * store,QXmlStreamAttributes & attrs)95 virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
96 Q_UNUSED(store);
97 Q_UNUSED(attrs);
98
99 bool validTag = true;
100
101 // QStringRef av;
102 // av = attrs.value("value");
103 // if (!av.isNull()) {
104 // _configValue = QVariant(av.toString()).toBool();
105 // }
106
107 return validTag;
108 }
109
110 public slots:
save()111 virtual void save() {
112 if (_cfg) {
113 _cfg->beginGroup("SyncBin DataObject Plugin");
114 _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name());
115 _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name());
116 _cfg->setValue("Input Scalar Number of Bins", _scalarBins->selectedScalar()->Name());
117 _cfg->setValue("Input Scalar X Min", _scalarXMin->selectedScalar()->Name());
118 _cfg->setValue("Input Scalar X Max", _scalarXMax->selectedScalar()->Name());
119 _cfg->endGroup();
120 }
121 }
122
load()123 virtual void load() {
124 if (_cfg && _store) {
125 _cfg->beginGroup("SyncBin DataObject 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 setSelectedVectorY(vectorY);
137 }
138 QString scalarName = _cfg->value("Input Scalar Number of Bins").toString();
139 object = _store->retrieveObject(scalarName);
140 Kst::Scalar* scalarBins = static_cast<Kst::Scalar*>(object);
141 if (scalarBins) {
142 setSelectedScalarBins(scalarBins);
143 }
144 scalarName = _cfg->value("Input Scalar X Min").toString();
145 object = _store->retrieveObject(scalarName);
146 Kst::Scalar* scalarXMin = static_cast<Kst::Scalar*>(object);
147 if (scalarXMin) {
148 setSelectedScalarXMin(scalarXMin);
149 }
150 scalarName = _cfg->value("Input Scalar X Max").toString();
151 object = _store->retrieveObject(scalarName);
152 Kst::Scalar* scalarXMax = static_cast<Kst::Scalar*>(object);
153 if (scalarXMax) {
154 setSelectedScalarXMax(scalarXMax);
155 }
156 _cfg->endGroup();
157 }
158 }
159
160 private:
161 Kst::ObjectStore *_store;
162
163 };
164
165
SyncBinSource(Kst::ObjectStore * store)166 SyncBinSource::SyncBinSource(Kst::ObjectStore *store)
167 : Kst::BasicPlugin(store) {
168 }
169
170
~SyncBinSource()171 SyncBinSource::~SyncBinSource() {
172 }
173
174
_automaticDescriptiveName() const175 QString SyncBinSource::_automaticDescriptiveName() const {
176 return tr("SyncBin Plugin Object");
177 }
178
179
change(Kst::DataObjectConfigWidget * configWidget)180 void SyncBinSource::change(Kst::DataObjectConfigWidget *configWidget) {
181 if (ConfigSyncBinPlugin* config = static_cast<ConfigSyncBinPlugin*>(configWidget)) {
182 setInputVector(VECTOR_IN_X, config->selectedVectorX());
183 setInputVector(VECTOR_IN_Y, config->selectedVectorY());
184 setInputScalar(SCALAR_IN_BINS, config->selectedScalarBins());
185 setInputScalar(SCALAR_IN_XMIN, config->selectedScalarXMin());
186 setInputScalar(SCALAR_IN_XMAX, config->selectedScalarXMax());
187 }
188 }
189
190
setupOutputs()191 void SyncBinSource::setupOutputs() {
192 setOutputVector(VECTOR_OUT_X_OUT, "");
193 setOutputVector(VECTOR_OUT_Y_OUT, "");
194 setOutputVector(VECTOR_OUT_Y_ERROR, "");
195 setOutputVector(VECTOR_OUT_N, "");
196 }
197
198
algorithm()199 bool SyncBinSource::algorithm() {
200 Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
201 Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
202 Kst::ScalarPtr inputScalarBins = _inputScalars[SCALAR_IN_BINS];
203 Kst::ScalarPtr inputScalarXMin = _inputScalars[SCALAR_IN_XMIN];
204 Kst::ScalarPtr inputScalarXMax = _inputScalars[SCALAR_IN_XMAX];
205
206 Kst::VectorPtr outputVectorX = _outputVectors[VECTOR_OUT_X_OUT];
207 Kst::VectorPtr outputVectorY = _outputVectors[VECTOR_OUT_Y_OUT];
208 Kst::VectorPtr outputVectorYError = _outputVectors[VECTOR_OUT_Y_ERROR];
209 Kst::VectorPtr outputVectorN = _outputVectors[VECTOR_OUT_N];
210
211 int nbins = int( inputScalarBins->value() );
212 int n_in;
213 double XMin = inputScalarXMin->value();
214 double XMax = inputScalarXMax->value();
215 double *Xout, *Yout, *Yerr, *N;
216
217 //Make sure there is at least 1 element in the input vector
218 if (inputVectorX->length() < 1) {
219 _errorString = tr("Error: Input Vector X invalid size");
220 return false;
221 }
222 if (inputVectorX->length() != inputVectorY->length()) {
223 _errorString = tr("Error: Input Vector lengths do not match");
224 return false;
225 }
226
227 if (nbins < 2) {
228 _errorString = tr("Error: Bins must be at least 2");
229 return false;
230 }
231
232 //resize the output arrays
233 outputVectorX->resize(nbins, true);
234 outputVectorY->resize(nbins, true);
235 outputVectorYError->resize(nbins, true);
236 outputVectorN->resize(nbins, true);
237
238 // convenience definitions
239 n_in = int( inputVectorX->length() );
240 const double *Xin = inputVectorX->value();
241 const double *Yin = inputVectorY->value();
242 Xout = outputVectorX->raw_V_ptr();
243 Yout = outputVectorY->raw_V_ptr();
244 Yerr = outputVectorYError->raw_V_ptr();
245 N = outputVectorN->raw_V_ptr();
246
247 // set/check XMax and XMin
248 if ( XMax <= XMin ) { // autobin
249 XMax = XMin = Xin[0];
250 for (int i=1; i<n_in; i++ ) {
251 if ( XMax>Xin[i] ) XMax = Xin[i];
252 if ( XMin<Xin[i] ) XMin = Xin[i];
253 }
254 // make sure end points are included.
255 double d = (XMax - XMin)/double(nbins*100.0);
256 XMax+=d;
257 XMin-=d;
258 }
259
260 if ( XMax == XMin ) { // don't want divide by zero...
261 XMax +=1;
262 XMin -=1;
263 }
264
265 // Fill Xout and zero Yout and Yerr
266 for ( int i=0; i<nbins; i++ ) {
267 Xout[i] = BINMID( i );
268 Yout[i] = Yerr[i] = 0.0;
269 N[i] = 0.0;
270 }
271
272 //bin the data
273 int bin, last_bin=-1;
274 int last_N=0;
275 double last_sY=0;
276
277 for ( int i=0; i<n_in; i++ ) {
278 bin = BIN( Xin[i] );
279 if (bin == last_bin) {
280 last_sY += Yin[i];
281 last_N++;
282 } else { // new bin
283 if (last_N>0) {
284 last_sY/=last_N;
285 if ( (last_bin>=0) && (last_bin<nbins) ) {
286 Yout[last_bin]+=last_sY;
287 Yerr[last_bin]+=last_sY*last_sY;
288 N[last_bin]++;
289 }
290 }
291 last_sY = Yin[i];
292 last_N = 1;
293 last_bin = bin;
294 }
295 }
296 if (last_N>0) {
297 last_sY/=last_N;
298 if ( (last_bin>=0) && (last_bin<nbins) ) {
299 Yout[last_bin]+=last_sY;
300 Yerr[last_bin]+=last_sY*last_sY;
301 N[last_bin]++;
302 }
303 }
304
305 // normalize the inputScalarBins
306 for ( int i = 0; i<nbins; i++ ) {
307 if ( N[i]>0 ) {
308 Yerr[i] = sqrt( Yerr[i] - Yout[i]*Yout[i]/N[i] )/N[i];
309 Yout[i]/=N[i];
310 }
311 }
312
313 return true;
314 }
315
316
vectorX() const317 Kst::VectorPtr SyncBinSource::vectorX() const {
318 return _inputVectors[VECTOR_IN_X];
319 }
320
321
vectorY() const322 Kst::VectorPtr SyncBinSource::vectorY() const {
323 return _inputVectors[VECTOR_IN_Y];
324 }
325
326
scalarBins() const327 Kst::ScalarPtr SyncBinSource::scalarBins() const {
328 return _inputScalars[SCALAR_IN_BINS];
329 }
330
331
scalarXMin() const332 Kst::ScalarPtr SyncBinSource::scalarXMin() const {
333 return _inputScalars[SCALAR_IN_XMIN];
334 }
335
336
scalarXMax() const337 Kst::ScalarPtr SyncBinSource::scalarXMax() const {
338 return _inputScalars[SCALAR_IN_XMAX];
339 }
340
341
inputVectorList() const342 QStringList SyncBinSource::inputVectorList() const {
343 QStringList vectors(VECTOR_IN_X);
344 vectors += VECTOR_IN_Y;
345 return vectors;
346 }
347
348
inputScalarList() const349 QStringList SyncBinSource::inputScalarList() const {
350 QStringList scalars(SCALAR_IN_BINS);
351 scalars += SCALAR_IN_XMIN;
352 scalars += SCALAR_IN_XMAX;
353 return scalars;
354 }
355
356
inputStringList() const357 QStringList SyncBinSource::inputStringList() const {
358 return QStringList( /*STRING_IN*/ );
359 }
360
361
outputVectorList() const362 QStringList SyncBinSource::outputVectorList() const {
363 QStringList vectors(VECTOR_OUT_X_OUT);
364 vectors += VECTOR_OUT_Y_OUT;
365 vectors += VECTOR_OUT_Y_ERROR;
366 vectors += VECTOR_OUT_N;
367 return vectors;
368 }
369
370
outputScalarList() const371 QStringList SyncBinSource::outputScalarList() const {
372 return QStringList( /*SCALAR_OUT*/ );
373 }
374
375
outputStringList() const376 QStringList SyncBinSource::outputStringList() const {
377 return QStringList( /*STRING_OUT*/ );
378 }
379
380
saveProperties(QXmlStreamWriter & s)381 void SyncBinSource::saveProperties(QXmlStreamWriter &s) {
382 Q_UNUSED(s);
383 // s.writeAttribute("value", _configValue);
384 }
385
386
pluginName() const387 QString SyncBinPlugin::pluginName() const { return tr("SyncBin"); }
pluginDescription() const388 QString SyncBinPlugin::pluginDescription() const { return tr("Synchronously coadd vector Y into inputScalarBins defined by vector X. Like a 1D map."); }
389
390
create(Kst::ObjectStore * store,Kst::DataObjectConfigWidget * configWidget,bool setupInputsOutputs) const391 Kst::DataObject *SyncBinPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const {
392
393 if (ConfigSyncBinPlugin* config = static_cast<ConfigSyncBinPlugin*>(configWidget)) {
394
395 SyncBinSource* object = store->createObject<SyncBinSource>();
396
397 if (setupInputsOutputs) {
398 object->setInputScalar(SCALAR_IN_BINS, config->selectedScalarBins());
399 object->setInputScalar(SCALAR_IN_XMIN, config->selectedScalarXMin());
400 object->setInputScalar(SCALAR_IN_XMAX, config->selectedScalarXMax());
401 object->setupOutputs();
402 object->setInputVector(VECTOR_IN_X, config->selectedVectorX());
403 object->setInputVector(VECTOR_IN_Y, config->selectedVectorY());
404 }
405
406 object->setPluginName(pluginName());
407
408 object->writeLock();
409 object->registerChange();
410 object->unlock();
411
412 return object;
413 }
414 return 0;
415 }
416
417
configWidget(QSettings * settingsObject) const418 Kst::DataObjectConfigWidget *SyncBinPlugin::configWidget(QSettings *settingsObject) const {
419 ConfigSyncBinPlugin *widget = new ConfigSyncBinPlugin(settingsObject);
420 return widget;
421 }
422
423 #ifndef QT5
424 Q_EXPORT_PLUGIN2(kstplugin_BinPlugin, SyncBinPlugin)
425 #endif
426
427 // vim: ts=2 sw=2 et
428