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