File indexing completed on 2024-12-22 04:17:23

0001 /***************************************************************************
0002                           vector.cpp  -  description
0003                              -------------------
0004     begin                : Fri Sep 22 2000
0005     copyright            : (C) 2000-2011 by C. Barth Netterfield
0006     email                : netterfield@astro.utoronto.ca
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *   Permission is granted to link with any opensource library             *
0016  *                                                                         *
0017  ***************************************************************************/
0018 
0019 #include "vector.h"
0020 
0021 #include <assert.h>
0022 #include <math.h>
0023 #include <stdlib.h>
0024 
0025 #include <QDebug>
0026 #include <QApplication>
0027 #include <QXmlStreamWriter>
0028 
0029 
0030 
0031 #include "datacollection.h"
0032 #include "math_kst.h"
0033 #include "debug.h"
0034 #include "objectstore.h"
0035 #include "updatemanager.h"
0036 #include "vectorscriptinterface.h"
0037 
0038 using namespace std;
0039 
0040 namespace Kst {
0041 
0042 #define INITSIZE 1
0043 
0044 const QString Vector::staticTypeString = "Vector";
0045 const QString Vector::staticTypeTag = "vector";
0046 
0047 /** Create a vector */
0048 Vector::Vector(ObjectStore *store)
0049     : Primitive(store, 0L), _nsum(0), _labelInfo(LabelInfo()), _titleInfo(LabelInfo()) {
0050 
0051   _initializeShortName();
0052 
0053   _editable = false;
0054   _numShifted = 0;
0055   _numNew = 0;
0056   _saveData = false;
0057   _isScalarList = false;
0058 
0059   _saveable = false;
0060 
0061   _labelInfo.name.clear();
0062   _labelInfo.quantity.clear();
0063   _labelInfo.units.clear();
0064 
0065   int size = INITSIZE;
0066 
0067   _v_raw = static_cast<double*>(malloc(size * sizeof(double)));
0068   _v_raw_managed = true;
0069 
0070   if (!_v_raw) { // Malloc failed
0071     _v_raw = static_cast<double*>(malloc(sizeof(double)));
0072     _size = 1;
0073   } else {
0074     _size = size;
0075   }
0076   _v_out = _v_raw;
0077   _is_rising = false;
0078   _has_nan = false;
0079   _v_no_nans_dirty = true;
0080   _v_no_nans_size = 0;
0081 
0082   _scalars.clear();
0083   _strings.clear();
0084 
0085   CreateScalars(store);
0086   setFlag(true);
0087 
0088   blank();
0089 
0090 }
0091 
0092 void Vector::_initializeShortName() {
0093   _shortName = 'V'+QString::number(_vectornum);
0094   if (_vectornum>max_vectornum)
0095     max_vectornum = _vectornum;
0096   _vectornum++;
0097 }
0098 
0099 Vector::~Vector() {
0100   if (_v_raw) {
0101     free(_v_raw);
0102     _v_raw = 0;
0103   }
0104 }
0105 
0106 
0107 ScriptInterface* Vector::createScriptInterface() {
0108   return new VectorSI(this);
0109 }
0110 
0111 
0112 void Vector::deleteDependents() {
0113 
0114   for (QHash<QString, ScalarPtr>::Iterator it = _scalars.begin(); it != _scalars.end(); ++it) {
0115     _store->removeObject(it.value());
0116   }
0117   for (QHash<QString, StringPtr>::Iterator it = _strings.begin(); it != _strings.end(); ++it) {
0118     _store->removeObject(it.value());
0119   }
0120   Object::deleteDependents();
0121 }
0122 
0123 
0124 const QString& Vector::typeString() const {
0125   return staticTypeString;
0126 }
0127 
0128 
0129 #define GENERATE_INTERPOLATION              \
0130   assert(_size > 0);                        \
0131   /** Limits checks - optional? **/         \
0132   if (in_i < 0 || _size == 1) {             \
0133     return _v_out[0];                           \
0134   }                                         \
0135                                             \
0136   if (in_i >= ns_i - 1) {                   \
0137     return _v_out[_size - 1];                   \
0138   }                                         \
0139                                             \
0140   /** speedup check **/                     \
0141   if (ns_i == _size) { /* no extrapolating or decimating needed */  \
0142     return _v_out[in_i];                        \
0143   }                                         \
0144                                             \
0145   double fj = in_i * double(_size - 1) / double(ns_i-1); /* scaled index */ \
0146                                             \
0147   int j = int(fj); /* index of sample one lower */ \
0148   /*assert(j==int(floor(fj)));*/ \
0149   assert(j+1 < _size && j >= 0);            \
0150   if (_v_out[j + 1] != _v_out[j + 1] || _v_out[j] != _v_out[j]) { \
0151     return NOPOINT;                    \
0152   }                                         \
0153                                             \
0154   double fdj = fj - float(j); /* fdj is fraction between _v_out[j] and _v_out[j+1] */ \
0155                                             \
0156   return _v_out[j + 1] * fdj + _v_out[j] * (1.0 - fdj);
0157 
0158 
0159 /** Return v[i], i is sample number, interpolated to have ns_i total
0160     samples in vector */
0161 double Vector::interpolate(int in_i, int ns_i) const {
0162   GENERATE_INTERPOLATION
0163 }
0164 
0165 /** same as above, but as a function for use in plugins, etc */
0166 double kstInterpolate(double *_v_out, int _size, int in_i, int ns_i) {
0167   GENERATE_INTERPOLATION
0168 }
0169 
0170 #undef GENERATE_INTERPOLATION
0171 
0172 #define RETURN_FIRST_NON_HOLE               \
0173     for (int i = 0; i < _size; ++i) {       \
0174       if (_v_out[i] == _v_out[i]) {                 \
0175         return _v_out[i];                       \
0176       }                                     \
0177     }                                       \
0178     return 0.;
0179 
0180 #define RETURN_LAST_NON_HOLE                \
0181     for (int i = _size - 1; i >= 0; --i) {  \
0182       if (_v_out[i] == _v_out[i]) {                 \
0183         return _v_out[i];                       \
0184       }                                     \
0185     }                                       \
0186     return 0.;
0187 
0188 #define FIND_LEFT(val, idx)                 \
0189     for (; idx >= 0; --idx) {               \
0190       if (_v_out[idx] == _v_out[idx]) {             \
0191         val = _v_out[idx]; break;               \
0192       }                                     \
0193     }
0194 
0195 #define FIND_RIGHT(val, idx)                \
0196     for (; idx < _size; ++idx) {            \
0197       if (_v_out[idx] == _v_out[idx]) {             \
0198         val = _v_out[idx]; break;               \
0199       }                                     \
0200     }
0201 
0202 #define GENERATE_INTERPOLATION              \
0203   assert(_size > 0);                        \
0204   /** Limits checks - optional? **/         \
0205   if (in_i <= 0 || _size == 1) {            \
0206     RETURN_FIRST_NON_HOLE                   \
0207   }                                         \
0208                                             \
0209   if (in_i >= ns_i - 1) {                   \
0210     RETURN_LAST_NON_HOLE                    \
0211   }                                         \
0212                                             \
0213   /** speedup check **/                     \
0214   if (ns_i == _size) {                      \
0215     if (_v_out[in_i] == _v_out[in_i]) {             \
0216       return _v_out[in_i];                      \
0217     }                                       \
0218     double left = 0., right = 0.;           \
0219     int leftIndex = in_i, rightIndex = in_i;\
0220     FIND_LEFT(left, leftIndex)              \
0221     FIND_RIGHT(right, rightIndex)           \
0222     if (leftIndex == -1) {                  \
0223       return right;                         \
0224     }                                       \
0225     if (rightIndex == _size) {              \
0226       return left;                          \
0227     }                                       \
0228     return left + (right - left) * double(in_i - leftIndex) / double(rightIndex - leftIndex); \
0229   }                                         \
0230   abort(); /* FIXME; this is effectivly assert(ns_i == _size) */                      \
0231   double indexScaleFactor = double(_size - 1) / double(ns_i - 1); \
0232   double fj = in_i * indexScaleFactor; /* scaled index */ \
0233                                             \
0234   int j = int(floor(fj)); /* index of sample one lower */ \
0235   assert(j+1 < _size && j >= 0);            \
0236   if (_v_out[j + 1] != _v_out[j + 1] || _v_out[j] != _v_out[j]) { \
0237     return NOPOINT;                    \
0238   }                                         \
0239                                             \
0240   double fdj = fj - float(j); /* fdj is fraction between _v_out[j] and _v_out[j+1] */ \
0241                                             \
0242   return _v_out[j + 1] * fdj + _v_out[j] * (1.0 - fdj);
0243 
0244 
0245 // FIXME: optimize me - possible that floor() (especially) and isnan() are
0246 //        expensive here.
0247 double Vector::interpolateNoHoles(int in_i, int ns_i) const {
0248   GENERATE_INTERPOLATION
0249 }
0250 
0251 
0252 #if 0
0253 double kstInterpolateNoHoles(double *_v, int _size, int in_i, int ns_i) {
0254   GENERATE_INTERPOLATION
0255 }
0256 #endif
0257 
0258 
0259 #undef FIND_LEFT
0260 #undef FIND_RIGHT
0261 #undef RETURN_LAST_NON_HOLE
0262 #undef RETURN_FIRST_NON_HOLE
0263 #undef GENERATE_INTERPOLATION
0264 
0265 double Vector::value(int i) const {
0266   if (i < 0 || i >= _size) { // can't look before beginning or past end
0267     return 0.0;
0268   }
0269   return _v_out[i];
0270 }
0271 
0272 double Vector::noNanValue(int i) {
0273   if (i < 0 || i >= _size) { // can't look before beginning or past end
0274     return 0.0;
0275   }
0276   if (_has_nan) {
0277     if (_v_no_nans_dirty) {
0278       updateVNoNans();
0279     }
0280     return _v_no_nans[i];
0281   }
0282   return _v_out[i];
0283 }
0284 
0285 void Vector::CreateScalars(ObjectStore *store) {
0286   if (!_isScalarList) {
0287     _min = _max = _mean = _minPos = 0.0;
0288     _imin = _imax = 0;
0289 
0290     Q_ASSERT(store);
0291     ScalarPtr sp;
0292     _scalars.insert("max", sp = store->createObject<Scalar>());
0293     sp->setProvider(this);
0294     sp->setSlaveName("Max");
0295 
0296     _scalars.insert("min", sp = store->createObject<Scalar>());
0297     sp->setProvider(this);
0298     sp->setSlaveName("Min");
0299 
0300     _scalars.insert("last", sp = store->createObject<Scalar>());
0301     sp->setProvider(this);
0302     sp->setSlaveName("Last");
0303 
0304     _scalars.insert("first", sp = store->createObject<Scalar>());
0305     sp->setProvider(this);
0306     sp->setSlaveName("First");
0307 
0308     _scalars.insert("mean", sp = store->createObject<Scalar>());
0309     sp->setProvider(this);
0310     sp->setSlaveName("Mean");
0311 
0312     _scalars.insert("sigma", sp = store->createObject<Scalar>());
0313     sp->setProvider(this);
0314     sp->setSlaveName("Sigma");
0315 
0316     _scalars.insert("rms", sp = store->createObject<Scalar>());
0317     sp->setProvider(this);
0318     sp->setSlaveName("Rms");
0319 
0320     _scalars.insert("ns", sp = store->createObject<Scalar>());
0321     sp->setProvider(this);
0322     sp->setSlaveName("NS");
0323 
0324     _scalars.insert("sum", sp = store->createObject<Scalar>());
0325     sp->setProvider(this);
0326     sp->setSlaveName("Sum");
0327 
0328     _scalars.insert("sumsquared", sp = store->createObject<Scalar>());
0329     sp->setProvider(this);
0330     sp->setSlaveName("SumSquared");
0331 
0332     _scalars.insert("minpos", sp = store->createObject<Scalar>());
0333     sp->setProvider(this);
0334     sp->setSlaveName("MinPos");
0335 
0336     if (store->sessionVersion>20000) {
0337       _scalars.insert("imax", sp = store->createObject<Scalar>());
0338       sp->setProvider(this);
0339       sp->setSlaveName("iMax");
0340 
0341       _scalars.insert("imin", sp = store->createObject<Scalar>());
0342       sp->setProvider(this);
0343       sp->setSlaveName("iMin");
0344     } else {
0345       //qDebug() << "old session version does not support iMin and iMax";
0346     }
0347   }
0348 }
0349 
0350 
0351 void Vector::updateScalars() {
0352   if (!_isScalarList) {
0353     _scalars["ns"]->setValue(_size);
0354 
0355     if (_nsum >= 2) {
0356       double sum = _scalars["sum"]->value();
0357       double sumsq = _scalars["sumsquared"]->value();
0358       _scalars["mean"]->setValue(_mean = sum/double(_nsum));
0359       _scalars["sigma"]->setValue(sqrt((sumsq - sum * sum / double(_nsum)) / double(_nsum-1)));
0360       _scalars["rms"]->setValue(sqrt(sumsq/double(_nsum)));
0361     } else {
0362       _scalars["sigma"]->setValue(_max - _min);
0363       _scalars["rms"]->setValue(sqrt(_scalars["sumsquared"]->value()));
0364       _scalars["mean"]->setValue(_mean = NOPOINT);
0365     }
0366   }
0367 }
0368 
0369 
0370 void Vector::setV(double *memptr, int newSize) {
0371   if (_v_raw_managed) {
0372     free(_v_raw);
0373     _v_raw_managed = false;
0374   }
0375   _v_raw = memptr;
0376   _v_out = _v_raw;
0377 
0378   _numNew = newSize;
0379   _size = newSize;
0380 }
0381 
0382 #define FIND_LEFT(val, idx)                 \
0383     for (; idx >= 0; --idx) {               \
0384       if (_v_out[idx] == _v_out[idx]) {             \
0385         val = _v_out[idx]; break;               \
0386       }                                     \
0387     }
0388 
0389 #define FIND_RIGHT(val, idx)                \
0390     for (; idx < _size; ++idx) {            \
0391       if (_v_out[idx] == _v_out[idx]) {             \
0392         val = _v_out[idx]; break;               \
0393       }                                     \
0394     }
0395 
0396 void Vector::updateVNoNans()  {
0397 
0398   if (_size != _v_no_nans_size) {
0399     if (_v_no_nans_size < 1) {
0400       _v_no_nans = NULL;
0401     }
0402     kstrealloc(_v_no_nans, _size*sizeof(double));
0403     _v_no_nans_size = _size;
0404   }
0405 
0406   for (int in_i = 0; in_i < _size; in_i++) {
0407     if (_v_out[in_i] == _v_out[in_i]) {
0408       _v_no_nans[in_i] = _v_out[in_i];
0409     } else {
0410       double left = 0., right = 0.;
0411       int leftIndex = in_i, rightIndex = in_i;
0412       FIND_LEFT(left, leftIndex);
0413       FIND_RIGHT(right, rightIndex);
0414       if (leftIndex == -1) {
0415         _v_no_nans[in_i] = right;
0416       } else if (rightIndex == _size) {
0417         _v_no_nans[in_i] = left;
0418       } else {
0419         _v_no_nans[in_i] = left + (right - left) * double(in_i - leftIndex) / double(rightIndex - leftIndex);
0420       }
0421     }
0422   }
0423   _v_no_nans_dirty = false;
0424 }
0425 #undef FIND_LEFT
0426 #undef FIND_RIGHT
0427 
0428 
0429 void Vector::zero() {
0430   _n_ns_stats = 0;
0431   _ns_stats_sorted = false;
0432 
0433   memset(_v_raw, 0, sizeof(double)*_size);
0434   updateScalars();
0435 }
0436 
0437 
0438 void Vector::blank() {
0439   _n_ns_stats = 0;
0440   _ns_stats_sorted = false;
0441 
0442   for (int i = 0; i < _size; ++i) {
0443     _v_raw[i] = NOPOINT;
0444   }
0445   updateScalars();
0446 }
0447 
0448 
0449 bool Vector::resize(int sz, bool init) {
0450   if (sz > 0) {
0451     if (!kstrealloc(_v_raw, sz*sizeof(double))){
0452        qCritical() << "Vector resize failed";
0453        return false;
0454     }
0455     if (init && _size < sz) {
0456       for (int i = _size; i < sz; ++i) {
0457         _v_raw[i] = NOPOINT;
0458       }
0459     }
0460     _size = sz;
0461     _v_out = _v_raw;
0462     updateScalars();
0463   }
0464   return true;
0465 }
0466 
0467 
0468 /* used for scripting IPC
0469     accepts an open writable file.
0470     returns false on failure */
0471 bool Vector::saveToTmpFile(QFile &fp) {
0472   qint64 n_written;
0473   qint64 n_write;
0474 
0475   n_write = length()*sizeof(double);
0476 
0477   n_written = fp.write((char *)_v_raw, n_write);
0478 
0479   fp.flush();
0480 
0481   return (n_write == n_written);
0482 }
0483 
0484 
0485 double Vector::ns_max(int ns_zoom_level) {
0486   if (!_ns_stats_sorted) {
0487     if (_n_ns_stats>4) {
0488       qSort(_v_ns_stats, _v_ns_stats+_n_ns_stats);
0489       _ns_stats_sorted = true;
0490     }
0491   }
0492   if (_n_ns_stats <= 4 ) {
0493     return max();
0494   }
0495 
0496   switch (ns_zoom_level) {
0497   case 0:
0498     return (_v_ns_stats[_n_ns_stats - 1]);
0499     break;
0500   case 1:
0501     return (_v_ns_stats[_n_ns_stats - _n_ns_stats/333 - 1]);
0502     break;
0503   case 2:
0504     return (_v_ns_stats[_n_ns_stats - _n_ns_stats/100 - 1]);
0505     break;
0506   case 3:
0507     return (_v_ns_stats[_n_ns_stats - _n_ns_stats/33 - 1]);
0508     break;
0509   default:
0510     return (_v_ns_stats[_n_ns_stats - _n_ns_stats/10 - 1]);
0511     break;
0512   }
0513 }
0514 
0515 double Vector::ns_min(int ns_zoom_level) {
0516   if (_n_ns_stats>2) {
0517     qSort(_v_ns_stats, _v_ns_stats+_n_ns_stats);
0518     _ns_stats_sorted = true;
0519   }
0520   if (_n_ns_stats <= 4 ) {
0521     return min();
0522   }
0523   switch (ns_zoom_level) {
0524   case 0:
0525     return (_v_ns_stats[1]);
0526     break;
0527   case 1:
0528     return (_v_ns_stats[_n_ns_stats/333 + 1]);
0529     break;
0530   case 2:
0531     return (_v_ns_stats[_n_ns_stats/100 + 1]);
0532     break;
0533   case 3:
0534     return (_v_ns_stats[_n_ns_stats/33 + 1]);
0535     break;
0536   default:
0537     return (_v_ns_stats[_n_ns_stats/10 + 1]);
0538     break;
0539   }
0540 }
0541 
0542 void Vector::internalUpdate() {
0543   int i, i0;
0544   double sum, sum2, last, first, v;
0545   double last_v;
0546   const double epsilon=DBL_MIN; // FIXME: this is not the smallest positive subnormal
0547 
0548   _max = _min = sum = sum2 = _minPos = last = first = NOPOINT;
0549   _imax = _imin = 0;
0550   _nsum = 0;
0551 
0552   _has_nan = false;
0553   _v_no_nans_dirty = true;
0554 
0555   if (_size > 0) {
0556     _is_rising = true;
0557 
0558     // FIXME: update V_out here
0559     _v_out = _v_raw;
0560 
0561     // Look for a valid (finite) point...
0562     for (i = 0; i < _size && !isfinite(_v_out[i]); ++i) {
0563       // do nothing
0564     }
0565 
0566     if (i>0) {
0567       _has_nan = true;
0568     }
0569 
0570     if (i == _size) { // there were no finite points:
0571       if (!_isScalarList) {
0572         _scalars["sum"]->setValue(sum);
0573         _scalars["sumsquared"]->setValue(sum2);
0574         _scalars["max"]->setValue(_max);
0575         _scalars["min"]->setValue(_min);
0576         _scalars["minpos"]->setValue(_minPos);
0577         _scalars["last"]->setValue(last);
0578         _scalars["first"]->setValue(first);
0579         if (store()->sessionVersion>20000) {
0580           _scalars["imax"]->setValue(_imax);
0581           _scalars["imin"]->setValue(_imin);
0582         }
0583       }
0584       _n_ns_stats = 0;
0585       _ns_stats_sorted = false;
0586 
0587       updateScalars();
0588       return;
0589     }
0590 
0591     i0 = i;
0592 
0593     if (i0 > 0) {
0594       _is_rising = false;
0595     }
0596 
0597     _max = _min = _v_out[i0];
0598     _imax = _imin = i0;
0599     sum = sum2 = 0.0;
0600 
0601     if (_v_out[i0] > epsilon) {
0602       _minPos = _v_out[i0];
0603     }
0604 
0605     last_v = _v_out[i0];
0606 
0607     for (i = i0; i < _size; ++i) {
0608       v = _v_out[i]; // get rid of redirections
0609 
0610       if (isfinite(v)) {
0611         if (v <= last_v) {
0612           if (i != i0) {
0613             _is_rising = false;
0614           }
0615         }
0616 
0617         last_v = v;
0618 
0619         _nsum++;
0620         sum += v;
0621         sum2 += v*v;
0622 
0623         if (v > _max) {
0624           _max = v;
0625           _imax = i;
0626         } else if (v < _min) {
0627           _min = v;
0628           _imin = i;
0629         }
0630         if ((isnan(_minPos) || v < _minPos) && v > epsilon) {
0631           _minPos = v;
0632         }
0633       } else {
0634         _is_rising = false;
0635         _has_nan = true;
0636       }
0637     }
0638 
0639     //no_spike_max_dv = 7.0*sqrt(dv2/double(_nsum));
0640 
0641     last_v = _v_out[i0];
0642 
0643     last = _v_out[_size-1];
0644     first = _v_out[0];
0645 
0646     /* make vector for spike insensitive autoscale */
0647     _n_ns_stats = 0;
0648     _ns_stats_sorted = false;
0649     double step = qMax(double(_size)/double(MAX_N_DESPIKE_STAT), 1.0);
0650     for (int k = 0; (k < _size) && (k < MAX_N_DESPIKE_STAT); k++) {
0651       int m = int(double(k) * step); // FIXME: add random([0, step]) to m
0652       if (isfinite(_v_out[m])) {
0653         _v_ns_stats[_n_ns_stats] = _v_out[m];
0654         _n_ns_stats++;
0655       }
0656     }
0657 
0658     if (_isScalarList) {
0659       _max = _min = _minPos = 0.0;
0660       _imax =_imin = 0;
0661     } else {
0662       _scalars["sum"]->setValue(sum);
0663       _scalars["sumsquared"]->setValue(sum2);
0664       _scalars["max"]->setValue(_max);
0665       _scalars["min"]->setValue(_min);
0666       _scalars["minpos"]->setValue(_minPos);
0667       _scalars["last"]->setValue(last);
0668       _scalars["first"]->setValue(first);
0669       if (store()->sessionVersion>20000) {
0670         _scalars["imax"]->setValue(_imax);
0671         _scalars["imin"]->setValue(_imin);
0672       }
0673     }
0674 
0675     updateScalars();
0676 
0677   }
0678 }
0679 
0680 void Vector::save(QXmlStreamWriter &s) {
0681   if (provider()) {
0682     return;
0683   }
0684   s.writeStartElement("vector");
0685   if (_saveData) {
0686     QByteArray qba(length()*sizeof(double), '\0');
0687     QDataStream qds(&qba, QIODevice::WriteOnly);
0688 
0689     for (int i = 0; i < length(); ++i) {
0690       qds << _v_raw[i];
0691     }
0692 
0693     s.writeTextElement("data_v2", qCompress(qba).toBase64());
0694   }
0695   saveNameInfo(s, VECTORNUM|SCALARNUM);
0696   s.writeEndElement();
0697 }
0698 
0699 void Vector::setNewAndShift(int inNew, int inShift) {
0700   _numNew = inNew;
0701   _numShifted = inShift;
0702 }
0703 
0704 double const *Vector::noNanValue() {
0705   if (_has_nan) {
0706     if (_v_no_nans_dirty) {
0707       updateVNoNans();
0708     }
0709     return _v_no_nans;
0710   }
0711   return _v_out;
0712 }
0713 
0714 
0715 void Vector::newSync() {
0716   _numNew = _numShifted = 0;
0717 }
0718 
0719 int Vector::getUsage() const {
0720   int adj = 0;
0721   for (QHash<QString, ScalarPtr>::ConstIterator it = _scalars.begin(); it != _scalars.end(); ++it) {
0722     adj += it.value()->getUsage() - 1;
0723   }
0724   return Object::getUsage() + adj;
0725 }
0726 
0727 
0728 bool Vector::saveable() const {
0729   return _saveable;
0730 }
0731 
0732 
0733 bool Vector::editable() const {
0734   return _editable;
0735 }
0736 
0737 
0738 void Vector::setEditable(bool editable) {
0739   _editable = editable;
0740 }
0741 
0742 
0743 bool Vector::saveData() const {
0744   return _saveData;
0745 }
0746 
0747 
0748 void Vector::setSaveData(bool save) {
0749   _saveData = save;
0750 }
0751 
0752 void Vector::oldChange(QByteArray &data) {
0753   if (!data.isEmpty()) {
0754     _saveable = true;
0755     _saveData = true;
0756 
0757     QDataStream qds(data);
0758 
0759     int sz = qMax(qint64((size_t)(INITSIZE)), qint64(data.size()/sizeof(double)));
0760     resize(sz, true);
0761 
0762     double sum=0.0;
0763     for (int i = 0; i<sz; ++i) {
0764       qds >> _v_raw[i];
0765       if(!i) {
0766           _min=_max=_minPos=sum=_v_raw[i];
0767           _imin = _imax = i;
0768           _minPos=qMax(_minPos,double(0.0));
0769       } else {
0770           _min=qMin(_v_raw[i],_min);
0771           _max=qMax(_v_raw[i],_max);
0772           _minPos=qMin(qMax(_v_raw[i],double(0.0)),_minPos);
0773           sum+=_v_raw[i];
0774       }
0775     }
0776     _mean=sum/double(_size);
0777   }
0778   updateScalars();
0779   internalUpdate();
0780 }
0781 
0782 void Vector::change(QByteArray &data) {
0783   if (!data.isEmpty()) {
0784     _saveable = true;
0785     _saveData = true;
0786 
0787     qint64 count;
0788     QDataStream qds(data);
0789     qds>>count;
0790 
0791     int sz = qMax(qint64((size_t)(INITSIZE)), count);
0792     resize(sz, true);
0793 
0794     double sum=0.0;
0795     for (int i = 0; i<count; ++i) {
0796       qds >> _v_raw[i];
0797       if(!i) {
0798           _min=_max=_minPos=sum=_v_raw[i];
0799           _minPos=qMax(_minPos,double(0.0));
0800       } else {
0801           _min=qMin(_v_raw[i],_min);
0802           _max=qMax(_v_raw[i],_max);
0803           _minPos=qMin(qMax(_v_raw[i],double(0.0)),_minPos);
0804           sum+=_v_raw[i];
0805       }
0806     }
0807     _mean=sum/double(count);
0808   }
0809   updateScalars();
0810   internalUpdate();
0811 }
0812 
0813 QString Vector::propertyString() const {
0814   if(_provider) {
0815       return tr("Provider: %1").arg(_provider->Name());
0816   } else {
0817       return Name();
0818   }
0819 }
0820 
0821 QString Vector::descriptionTip() const {
0822   return tr("Vector: %1\n  %2 samples\n%3").arg(Name()).arg(length()).arg(_provider->descriptionTip());
0823 }
0824 
0825 QString Vector::sizeString() const {
0826   return QString::number(length());
0827 }
0828 
0829 ObjectList<Primitive> Vector::outputPrimitives() const {
0830   PrimitiveList primitive_list;
0831 
0832   int n = _scalars.count();
0833   for (int i = 0; i< n; ++i) {
0834       primitive_list.append(kst_cast<Primitive>(_scalars.values().at(i)));
0835   }
0836 
0837   n = _strings.count();
0838   for (int i = 0; i< n; ++i) {
0839       primitive_list.append(kst_cast<Primitive>(_strings.values().at(i)));
0840   }
0841 
0842   return primitive_list;
0843 }
0844 
0845 PrimitiveMap Vector::metas() const
0846 {
0847   PrimitiveMap meta;
0848   for (QHash<QString, StringPtr>::ConstIterator it = _strings.begin(); it != _strings.end(); ++it) {
0849     meta[it.key()] = it.value();
0850   }
0851   for (QHash<QString, ScalarPtr>::ConstIterator it = _scalars.begin(); it != _scalars.end(); ++it) {
0852     meta[it.key()] = it.value();
0853   }
0854   return meta;
0855 }
0856 
0857 
0858 LabelInfo Vector::labelInfo() const {
0859   return _labelInfo;
0860 }
0861 
0862 
0863 LabelInfo Vector::titleInfo() const {
0864   return _titleInfo;
0865 }
0866 
0867 
0868 void Vector::setLabelInfo(const LabelInfo &label_info) {
0869   _labelInfo = label_info;
0870 }
0871 
0872 
0873 void Vector::setTitleInfo(const LabelInfo &label_info) {
0874   _titleInfo = label_info;
0875 }
0876 
0877 QByteArray Vector::scriptInterface(QList<QByteArray> &c) {
0878     Q_ASSERT(c.size());
0879     if(c[0]=="length") {
0880         return QByteArray::number(_size);
0881     } else if(c[0]=="interpolate") {
0882         if(c.size()!=3) {
0883             return "interpolate takes 2 args";
0884         }
0885         return QByteArray::number(interpolate(c[1].toInt(),c[2].toInt()));
0886     } else if(c[0]=="interpolateNoHoles") {
0887         if(c.size()!=3) {
0888             return "interpolateNoHoles takes 2 args";
0889         }
0890         return QByteArray::number(interpolateNoHoles(c[1].toInt(),c[2].toInt()));
0891     } else if(c[0]=="value") {
0892         if(c.size()!=2) {
0893             return "value takes 1 arg";
0894         }
0895         readLock();
0896         QByteArray ret = QByteArray::number(value(c[1].toDouble()));
0897         unlock();
0898         return ret;
0899     } else if(c[0]=="min") {
0900         return QByteArray::number(min());
0901     } else if(c[0]=="max") {
0902         return QByteArray::number(max());
0903     } else if(c[0]=="ns_max") {
0904         return QByteArray::number(ns_max(2));
0905     } else if(c[0]=="ns_min") {
0906         return QByteArray::number(ns_min(2));
0907     } else if(c[0]=="mean") {
0908         return QByteArray::number(mean());
0909     } else if(c[0]=="minPos") {
0910         return QByteArray::number(minPos());
0911     } else if(c[0]=="numNew") {
0912         return QByteArray::number(numNew());
0913     } else if(c[0]=="numShift") {
0914         return QByteArray::number(numShift());
0915     } else if(c[0]=="isRising") {
0916         return isRising()?"true":"false";
0917     } else if(c[0]=="newSync") {
0918         newSync();
0919         return "Ok";
0920     } else if(c[0]=="resize") {
0921         if(c.size()!=3) {
0922             return "takes 2 args";
0923         }
0924         return resize(c[1].toInt(),c[2].toInt())?"true":"false";
0925     } else if(c[0]=="setNewAndShift") {
0926         if(c.size()!=3) {
0927             return "takes 2 args";
0928         }
0929         setNewAndShift(c[0].toInt(),c[1].toInt());
0930         return "Ok";
0931     } else if(c[0]=="zero") {
0932         zero();
0933         return "Ok";
0934     } else if(c[0]=="blank") {
0935         blank();
0936         return "Ok";
0937     }
0938 
0939     return "No such command...";
0940 }
0941 
0942 QByteArray Vector::getBinaryArray() const {
0943     readLock();
0944     QByteArray ret;
0945     QDataStream ds(&ret,QIODevice::WriteOnly);
0946     ds<<(qint64)_size;
0947     for(int i=0; i<_size; ++i) {
0948         ds<<(double)_v_raw[i];
0949     }
0950     unlock();
0951     return ret;
0952 }
0953 
0954 #undef INITSIZE
0955 
0956 }
0957 // vim: et sw=2 ts=2