File indexing completed on 2024-12-22 04:18:08
0001 /*************************************************************************** 0002 * * 0003 * copyright : (C) 2007 The University of Toronto * 0004 * netterfield@astro.utoronto.ca * 0005 * copyright : (C) 2005 University of British Columbia * 0006 * dscott@phas.ubc.ca * 0007 * * 0008 * This program is free software; you can redistribute it and/or modify * 0009 * it under the terms of the GNU General Public License as published by * 0010 * the Free Software Foundation; either version 2 of the License, or * 0011 * (at your option) any later version. * 0012 * * 0013 ***************************************************************************/ 0014 0015 /* bin Y values into N bins from X min to X max, according to their X values. 0016 This is like a 1D map, where X specifices the pixel the data go into. */ 0017 0018 #include "syncbin.h" 0019 #include "objectstore.h" 0020 #include "ui_syncbinconfig.h" 0021 0022 // macros to find the top, bottom, and middle of a bin 0023 #define BINMID(x) XMin+(XMax-XMin)*(double(x)+0.5)/double(nbins) 0024 0025 #define BIN( x ) int(double(nbins)*(x-XMin)/(XMax-XMin)) 0026 0027 static const QString& VECTOR_IN_X = "Vector In X"; 0028 static const QString& VECTOR_IN_Y = "Vector In Y"; 0029 static const QString& SCALAR_IN_BINS = "Number of Bins"; 0030 static const QString& SCALAR_IN_XMIN = "X Min"; 0031 static const QString& SCALAR_IN_XMAX = "X Max"; 0032 0033 static const QString& VECTOR_OUT_X_OUT = "X out"; 0034 static const QString& VECTOR_OUT_Y_OUT = "Y out"; 0035 static const QString& VECTOR_OUT_Y_ERROR = "Y error"; 0036 static const QString& VECTOR_OUT_N = "N"; 0037 0038 class ConfigSyncBinPlugin : public Kst::DataObjectConfigWidget, public Ui_SyncBinConfig { 0039 public: 0040 ConfigSyncBinPlugin(QSettings* cfg) : DataObjectConfigWidget(cfg), Ui_SyncBinConfig() { 0041 _store = 0; 0042 setupUi(this); 0043 } 0044 0045 ~ConfigSyncBinPlugin() {} 0046 0047 void setObjectStore(Kst::ObjectStore* store) { 0048 _store = store; 0049 _vectorX->setObjectStore(store); 0050 _vectorY->setObjectStore(store); 0051 _scalarBins->setObjectStore(store); 0052 _scalarXMin->setObjectStore(store); 0053 _scalarXMax->setObjectStore(store); 0054 _scalarBins->setDefaultValue(0); 0055 _scalarXMin->setDefaultValue(0); 0056 _scalarXMax->setDefaultValue(0); 0057 } 0058 0059 void setupSlots(QWidget* dialog) { 0060 if (dialog) { 0061 connect(_vectorX, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0062 connect(_vectorY, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0063 connect(_scalarBins, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0064 connect(_scalarXMin, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0065 connect(_scalarXMax, SIGNAL(selectionChanged(QString)), dialog, SIGNAL(modified())); 0066 } 0067 } 0068 0069 Kst::VectorPtr selectedVectorX() { return _vectorX->selectedVector(); }; 0070 void setSelectedVectorX(Kst::VectorPtr vector) { return _vectorX->setSelectedVector(vector); }; 0071 0072 Kst::VectorPtr selectedVectorY() { return _vectorY->selectedVector(); }; 0073 void setSelectedVectorY(Kst::VectorPtr vector) { return _vectorY->setSelectedVector(vector); }; 0074 0075 Kst::ScalarPtr selectedScalarBins() { return _scalarBins->selectedScalar(); }; 0076 void setSelectedScalarBins(Kst::ScalarPtr scalar) { return _scalarBins->setSelectedScalar(scalar); }; 0077 0078 Kst::ScalarPtr selectedScalarXMin() { return _scalarXMin->selectedScalar(); }; 0079 void setSelectedScalarXMin(Kst::ScalarPtr scalar) { return _scalarXMin->setSelectedScalar(scalar); }; 0080 0081 Kst::ScalarPtr selectedScalarXMax() { return _scalarXMax->selectedScalar(); }; 0082 void setSelectedScalarXMax(Kst::ScalarPtr scalar) { return _scalarXMax->setSelectedScalar(scalar); }; 0083 0084 0085 virtual void setupFromObject(Kst::Object* dataObject) { 0086 if (SyncBinSource* source = static_cast<SyncBinSource*>(dataObject)) { 0087 setSelectedVectorX(source->vectorX()); 0088 setSelectedVectorY(source->vectorY()); 0089 setSelectedScalarBins(source->scalarBins()); 0090 setSelectedScalarXMin(source->scalarXMin()); 0091 setSelectedScalarXMax(source->scalarXMax()); 0092 } 0093 } 0094 0095 virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) { 0096 Q_UNUSED(store); 0097 Q_UNUSED(attrs); 0098 0099 bool validTag = true; 0100 0101 // QStringRef av; 0102 // av = attrs.value("value"); 0103 // if (!av.isNull()) { 0104 // _configValue = QVariant(av.toString()).toBool(); 0105 // } 0106 0107 return validTag; 0108 } 0109 0110 public slots: 0111 virtual void save() { 0112 if (_cfg) { 0113 _cfg->beginGroup("SyncBin DataObject Plugin"); 0114 _cfg->setValue("Input Vector X", _vectorX->selectedVector()->Name()); 0115 _cfg->setValue("Input Vector Y", _vectorY->selectedVector()->Name()); 0116 _cfg->setValue("Input Scalar Number of Bins", _scalarBins->selectedScalar()->Name()); 0117 _cfg->setValue("Input Scalar X Min", _scalarXMin->selectedScalar()->Name()); 0118 _cfg->setValue("Input Scalar X Max", _scalarXMax->selectedScalar()->Name()); 0119 _cfg->endGroup(); 0120 } 0121 } 0122 0123 virtual void load() { 0124 if (_cfg && _store) { 0125 _cfg->beginGroup("SyncBin DataObject Plugin"); 0126 QString vectorName = _cfg->value("Input Vector X").toString(); 0127 Kst::Object* object = _store->retrieveObject(vectorName); 0128 Kst::Vector* vectorX = static_cast<Kst::Vector*>(object); 0129 if (vectorX) { 0130 setSelectedVectorX(vectorX); 0131 } 0132 vectorName = _cfg->value("Input Vector Y").toString(); 0133 object = _store->retrieveObject(vectorName); 0134 Kst::Vector* vectorY = static_cast<Kst::Vector*>(object); 0135 if (vectorY) { 0136 setSelectedVectorY(vectorY); 0137 } 0138 QString scalarName = _cfg->value("Input Scalar Number of Bins").toString(); 0139 object = _store->retrieveObject(scalarName); 0140 Kst::Scalar* scalarBins = static_cast<Kst::Scalar*>(object); 0141 if (scalarBins) { 0142 setSelectedScalarBins(scalarBins); 0143 } 0144 scalarName = _cfg->value("Input Scalar X Min").toString(); 0145 object = _store->retrieveObject(scalarName); 0146 Kst::Scalar* scalarXMin = static_cast<Kst::Scalar*>(object); 0147 if (scalarXMin) { 0148 setSelectedScalarXMin(scalarXMin); 0149 } 0150 scalarName = _cfg->value("Input Scalar X Max").toString(); 0151 object = _store->retrieveObject(scalarName); 0152 Kst::Scalar* scalarXMax = static_cast<Kst::Scalar*>(object); 0153 if (scalarXMax) { 0154 setSelectedScalarXMax(scalarXMax); 0155 } 0156 _cfg->endGroup(); 0157 } 0158 } 0159 0160 private: 0161 Kst::ObjectStore *_store; 0162 0163 }; 0164 0165 0166 SyncBinSource::SyncBinSource(Kst::ObjectStore *store) 0167 : Kst::BasicPlugin(store) { 0168 } 0169 0170 0171 SyncBinSource::~SyncBinSource() { 0172 } 0173 0174 0175 QString SyncBinSource::_automaticDescriptiveName() const { 0176 return tr("SyncBin Plugin Object"); 0177 } 0178 0179 0180 void SyncBinSource::change(Kst::DataObjectConfigWidget *configWidget) { 0181 if (ConfigSyncBinPlugin* config = static_cast<ConfigSyncBinPlugin*>(configWidget)) { 0182 setInputVector(VECTOR_IN_X, config->selectedVectorX()); 0183 setInputVector(VECTOR_IN_Y, config->selectedVectorY()); 0184 setInputScalar(SCALAR_IN_BINS, config->selectedScalarBins()); 0185 setInputScalar(SCALAR_IN_XMIN, config->selectedScalarXMin()); 0186 setInputScalar(SCALAR_IN_XMAX, config->selectedScalarXMax()); 0187 } 0188 } 0189 0190 0191 void SyncBinSource::setupOutputs() { 0192 setOutputVector(VECTOR_OUT_X_OUT, ""); 0193 setOutputVector(VECTOR_OUT_Y_OUT, ""); 0194 setOutputVector(VECTOR_OUT_Y_ERROR, ""); 0195 setOutputVector(VECTOR_OUT_N, ""); 0196 } 0197 0198 0199 bool SyncBinSource::algorithm() { 0200 Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X]; 0201 Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y]; 0202 Kst::ScalarPtr inputScalarBins = _inputScalars[SCALAR_IN_BINS]; 0203 Kst::ScalarPtr inputScalarXMin = _inputScalars[SCALAR_IN_XMIN]; 0204 Kst::ScalarPtr inputScalarXMax = _inputScalars[SCALAR_IN_XMAX]; 0205 0206 Kst::VectorPtr outputVectorX = _outputVectors[VECTOR_OUT_X_OUT]; 0207 Kst::VectorPtr outputVectorY = _outputVectors[VECTOR_OUT_Y_OUT]; 0208 Kst::VectorPtr outputVectorYError = _outputVectors[VECTOR_OUT_Y_ERROR]; 0209 Kst::VectorPtr outputVectorN = _outputVectors[VECTOR_OUT_N]; 0210 0211 int nbins = int( inputScalarBins->value() ); 0212 int n_in; 0213 double XMin = inputScalarXMin->value(); 0214 double XMax = inputScalarXMax->value(); 0215 double *Xout, *Yout, *Yerr, *N; 0216 0217 //Make sure there is at least 1 element in the input vector 0218 if (inputVectorX->length() < 1) { 0219 _errorString = tr("Error: Input Vector X invalid size"); 0220 return false; 0221 } 0222 if (inputVectorX->length() != inputVectorY->length()) { 0223 _errorString = tr("Error: Input Vector lengths do not match"); 0224 return false; 0225 } 0226 0227 if (nbins < 2) { 0228 _errorString = tr("Error: Bins must be at least 2"); 0229 return false; 0230 } 0231 0232 //resize the output arrays 0233 outputVectorX->resize(nbins, true); 0234 outputVectorY->resize(nbins, true); 0235 outputVectorYError->resize(nbins, true); 0236 outputVectorN->resize(nbins, true); 0237 0238 // convenience definitions 0239 n_in = int( inputVectorX->length() ); 0240 const double *Xin = inputVectorX->value(); 0241 const double *Yin = inputVectorY->value(); 0242 Xout = outputVectorX->raw_V_ptr(); 0243 Yout = outputVectorY->raw_V_ptr(); 0244 Yerr = outputVectorYError->raw_V_ptr(); 0245 N = outputVectorN->raw_V_ptr(); 0246 0247 // set/check XMax and XMin 0248 if ( XMax <= XMin ) { // autobin 0249 XMax = XMin = Xin[0]; 0250 for (int i=1; i<n_in; i++ ) { 0251 if ( XMax>Xin[i] ) XMax = Xin[i]; 0252 if ( XMin<Xin[i] ) XMin = Xin[i]; 0253 } 0254 // make sure end points are included. 0255 double d = (XMax - XMin)/double(nbins*100.0); 0256 XMax+=d; 0257 XMin-=d; 0258 } 0259 0260 if ( XMax == XMin ) { // don't want divide by zero... 0261 XMax +=1; 0262 XMin -=1; 0263 } 0264 0265 // Fill Xout and zero Yout and Yerr 0266 for ( int i=0; i<nbins; i++ ) { 0267 Xout[i] = BINMID( i ); 0268 Yout[i] = Yerr[i] = 0.0; 0269 N[i] = 0.0; 0270 } 0271 0272 //bin the data 0273 int bin, last_bin=-1; 0274 int last_N=0; 0275 double last_sY=0; 0276 0277 for ( int i=0; i<n_in; i++ ) { 0278 bin = BIN( Xin[i] ); 0279 if (bin == last_bin) { 0280 last_sY += Yin[i]; 0281 last_N++; 0282 } else { // new bin 0283 if (last_N>0) { 0284 last_sY/=last_N; 0285 if ( (last_bin>=0) && (last_bin<nbins) ) { 0286 Yout[last_bin]+=last_sY; 0287 Yerr[last_bin]+=last_sY*last_sY; 0288 N[last_bin]++; 0289 } 0290 } 0291 last_sY = Yin[i]; 0292 last_N = 1; 0293 last_bin = bin; 0294 } 0295 } 0296 if (last_N>0) { 0297 last_sY/=last_N; 0298 if ( (last_bin>=0) && (last_bin<nbins) ) { 0299 Yout[last_bin]+=last_sY; 0300 Yerr[last_bin]+=last_sY*last_sY; 0301 N[last_bin]++; 0302 } 0303 } 0304 0305 // normalize the inputScalarBins 0306 for ( int i = 0; i<nbins; i++ ) { 0307 if ( N[i]>0 ) { 0308 Yerr[i] = sqrt( Yerr[i] - Yout[i]*Yout[i]/N[i] )/N[i]; 0309 Yout[i]/=N[i]; 0310 } 0311 } 0312 0313 return true; 0314 } 0315 0316 0317 Kst::VectorPtr SyncBinSource::vectorX() const { 0318 return _inputVectors[VECTOR_IN_X]; 0319 } 0320 0321 0322 Kst::VectorPtr SyncBinSource::vectorY() const { 0323 return _inputVectors[VECTOR_IN_Y]; 0324 } 0325 0326 0327 Kst::ScalarPtr SyncBinSource::scalarBins() const { 0328 return _inputScalars[SCALAR_IN_BINS]; 0329 } 0330 0331 0332 Kst::ScalarPtr SyncBinSource::scalarXMin() const { 0333 return _inputScalars[SCALAR_IN_XMIN]; 0334 } 0335 0336 0337 Kst::ScalarPtr SyncBinSource::scalarXMax() const { 0338 return _inputScalars[SCALAR_IN_XMAX]; 0339 } 0340 0341 0342 QStringList SyncBinSource::inputVectorList() const { 0343 QStringList vectors(VECTOR_IN_X); 0344 vectors += VECTOR_IN_Y; 0345 return vectors; 0346 } 0347 0348 0349 QStringList SyncBinSource::inputScalarList() const { 0350 QStringList scalars(SCALAR_IN_BINS); 0351 scalars += SCALAR_IN_XMIN; 0352 scalars += SCALAR_IN_XMAX; 0353 return scalars; 0354 } 0355 0356 0357 QStringList SyncBinSource::inputStringList() const { 0358 return QStringList( /*STRING_IN*/ ); 0359 } 0360 0361 0362 QStringList SyncBinSource::outputVectorList() const { 0363 QStringList vectors(VECTOR_OUT_X_OUT); 0364 vectors += VECTOR_OUT_Y_OUT; 0365 vectors += VECTOR_OUT_Y_ERROR; 0366 vectors += VECTOR_OUT_N; 0367 return vectors; 0368 } 0369 0370 0371 QStringList SyncBinSource::outputScalarList() const { 0372 return QStringList( /*SCALAR_OUT*/ ); 0373 } 0374 0375 0376 QStringList SyncBinSource::outputStringList() const { 0377 return QStringList( /*STRING_OUT*/ ); 0378 } 0379 0380 0381 void SyncBinSource::saveProperties(QXmlStreamWriter &s) { 0382 Q_UNUSED(s); 0383 // s.writeAttribute("value", _configValue); 0384 } 0385 0386 0387 QString SyncBinPlugin::pluginName() const { return tr("SyncBin"); } 0388 QString SyncBinPlugin::pluginDescription() const { return tr("Synchronously coadd vector Y into inputScalarBins defined by vector X. Like a 1D map."); } 0389 0390 0391 Kst::DataObject *SyncBinPlugin::create(Kst::ObjectStore *store, Kst::DataObjectConfigWidget *configWidget, bool setupInputsOutputs) const { 0392 0393 if (ConfigSyncBinPlugin* config = static_cast<ConfigSyncBinPlugin*>(configWidget)) { 0394 0395 SyncBinSource* object = store->createObject<SyncBinSource>(); 0396 0397 if (setupInputsOutputs) { 0398 object->setInputScalar(SCALAR_IN_BINS, config->selectedScalarBins()); 0399 object->setInputScalar(SCALAR_IN_XMIN, config->selectedScalarXMin()); 0400 object->setInputScalar(SCALAR_IN_XMAX, config->selectedScalarXMax()); 0401 object->setupOutputs(); 0402 object->setInputVector(VECTOR_IN_X, config->selectedVectorX()); 0403 object->setInputVector(VECTOR_IN_Y, config->selectedVectorY()); 0404 } 0405 0406 object->setPluginName(pluginName()); 0407 0408 object->writeLock(); 0409 object->registerChange(); 0410 object->unlock(); 0411 0412 return object; 0413 } 0414 return 0; 0415 } 0416 0417 0418 Kst::DataObjectConfigWidget *SyncBinPlugin::configWidget(QSettings *settingsObject) const { 0419 ConfigSyncBinPlugin *widget = new ConfigSyncBinPlugin(settingsObject); 0420 return widget; 0421 } 0422 0423 #ifndef QT5 0424 Q_EXPORT_PLUGIN2(kstplugin_BinPlugin, SyncBinPlugin) 0425 #endif 0426 0427 // vim: ts=2 sw=2 et