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