File indexing completed on 2024-12-22 04:17:19
0001 /*************************************************************************** 0002 datavector.cpp - a vector which gets its data from 0003 a datasource. 0004 ------------------- 0005 begin : Fri Sep 22 2000 0006 copyright : (C) 2000-2015 by C. Barth Netterfield 0007 email : netterfield@astro.utoronto.ca 0008 ***************************************************************************/ 0009 0010 /*************************************************************************** 0011 * * 0012 * This program is free software; you can redistribute it and/or modify * 0013 * it under the terms of the GNU General Public License as published by * 0014 * the Free Software Foundation; either version 2 of the License, or * 0015 * (at your option) any later version. * 0016 * Permission is granted to link with any opensource library * 0017 * * 0018 ***************************************************************************/ 0019 #include "datavector.h" 0020 0021 #include <assert.h> 0022 #include <math.h> 0023 #include <stdlib.h> 0024 0025 #include <QDebug> 0026 #include <QXmlStreamWriter> 0027 0028 #include "datacollection.h" 0029 #include "debug.h" 0030 #include "datasource.h" 0031 #include "math_kst.h" 0032 #include "objectstore.h" 0033 #include "updatemanager.h" 0034 #include "vectorscriptinterface.h" 0035 0036 // ReqNF <=0 means read from ReqF0 to end of File 0037 // ReqF0 < means start at EndOfFile-ReqNF. 0038 // 0039 // ReqNF ReqF0 Action 0040 // < 1 >=0 read from ReqF0 to end of file 0041 // < 1 < 0 illegal: fixed in checkIntegrity 0042 // 1 ?? illegal: fixed in checkIntegrity 0043 // > 1 < 0 read the last ReqNF frames from the file 0044 // > 1 >=0 Read ReqNF frames starting at frame ReqF0 0045 0046 namespace Kst { 0047 0048 const QString DataVector::staticTypeString = "Data Vector"; 0049 const QString DataVector::staticTypeTag = "datavector"; 0050 0051 const int INVALIDS_PER_RESET = 5; 0052 0053 DataVector::DataInfo::DataInfo() : 0054 frameCount(-1), 0055 samplesPerFrame(-1) 0056 { 0057 } 0058 0059 0060 DataVector::DataInfo::DataInfo(int fc, int spf) : 0061 frameCount(fc), 0062 samplesPerFrame(spf) 0063 { 0064 } 0065 0066 /** Create a DataVector: raw data from a file */ 0067 DataVector::DataVector(ObjectStore *store) 0068 : Vector(store), DataPrimitive(this) { 0069 0070 _saveable = true; 0071 _numSamples = 0; 0072 _scalars["sum"]->setValue(0.0); 0073 _scalars["sumsquared"]->setValue(0.0); 0074 F0 = NF = 0; // nothing read yet 0075 0076 N_AveReadBuf = 0; 0077 AveReadBuf = 0L; 0078 0079 ReqF0 = 0; 0080 ReqNF = -1; 0081 Skip = 1; 0082 DoSkip = false; 0083 DoAve = false; 0084 _invalidCount = 0; 0085 } 0086 0087 0088 const QString& DataVector::typeString() const { 0089 return staticTypeString; 0090 } 0091 0092 0093 /** return true if it has a valid file and field, or false otherwise */ 0094 bool DataVector::isValid() const { 0095 if (dataSource()) { 0096 dataSource()->readLock(); 0097 bool rc = dataSource()->vector().isValid(_field); 0098 dataSource()->unlock(); 0099 return rc; 0100 } 0101 return false; 0102 } 0103 0104 0105 ScriptInterface* DataVector::createScriptInterface() { 0106 return new DataVectorSI(this); 0107 } 0108 0109 0110 bool DataVector::checkValidity(const DataSourcePtr& ds) const { 0111 if (ds) { 0112 ds->readLock(); 0113 bool rc = ds->vector().isValid(_field); 0114 ds->unlock(); 0115 return rc; 0116 } 0117 return false; 0118 } 0119 0120 void DataVector::change(DataSourcePtr in_file, const QString &in_field, 0121 int in_f0, int in_n, 0122 int in_skip, bool in_DoSkip, 0123 bool in_DoAve) { 0124 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0125 0126 Skip = in_skip; 0127 DoSkip = in_DoSkip; 0128 DoAve = in_DoAve; 0129 if (DoSkip && Skip < 1) { 0130 Skip = 1; 0131 } 0132 0133 setDataSource(in_file); 0134 ReqF0 = in_f0; 0135 ReqNF = in_n; 0136 _field = in_field; 0137 0138 if (dataSource()) { 0139 dataSource()->writeLock(); 0140 } 0141 reset(); 0142 if (dataSource()) { 0143 dataSource()->unlock(); 0144 } 0145 0146 if (ReqNF <= 0 && ReqF0 < 0) { 0147 ReqF0 = 0; 0148 } 0149 registerChange(); 0150 } 0151 0152 qint64 DataVector::minInputSerial() const { 0153 if (dataSource()) { 0154 return (dataSource()->serial()); 0155 } 0156 return LLONG_MAX; 0157 } 0158 0159 qint64 DataVector::maxInputSerialOfLastChange() const { 0160 if (dataSource()) { 0161 return (dataSource()->serialOfLastChange()); 0162 } 0163 return NoInputs; 0164 } 0165 0166 0167 void DataVector::changeFile(DataSourcePtr in_file) { 0168 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0169 0170 if (!in_file) { 0171 Debug::self()->log(tr("Data file for vector %1 was not opened.").arg(Name()), Debug::Warning); 0172 } 0173 setDataSource(in_file); 0174 if (dataSource()) { 0175 dataSource()->writeLock(); 0176 } 0177 reset(); 0178 if (dataSource()) { 0179 dataSource()->unlock(); 0180 } 0181 registerChange(); 0182 } 0183 0184 0185 void DataVector::changeFrames(int in_f0, int in_n, 0186 int in_skip, bool in_DoSkip, 0187 bool in_DoAve) { 0188 0189 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0190 0191 if (dataSource()) { 0192 dataSource()->writeLock(); 0193 } 0194 reset(); 0195 if (dataSource()) { 0196 dataSource()->unlock(); 0197 } 0198 Skip = in_skip; 0199 DoSkip = in_DoSkip; 0200 DoAve = in_DoAve; 0201 if (DoSkip && Skip < 1) { 0202 Skip = 1; 0203 } 0204 0205 ReqF0 = in_f0; 0206 ReqNF = in_n; 0207 0208 if (ReqNF <= 0 && ReqF0 < 0) { 0209 ReqF0 = 0; 0210 } 0211 registerChange(); 0212 } 0213 0214 0215 void DataVector::setFromEnd() { 0216 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0217 0218 ReqF0 = -1; 0219 if (ReqNF < 2) { 0220 ReqNF = numFrames(); 0221 if (ReqNF < 2) { 0222 ReqF0 = 0; 0223 } 0224 } 0225 registerChange(); 0226 } 0227 0228 0229 DataVector::~DataVector() { 0230 if (AveReadBuf) { 0231 free(AveReadBuf); 0232 AveReadBuf = 0L; 0233 } 0234 } 0235 0236 0237 bool DataVector::readToEOF() const { 0238 return ReqNF <= 0; 0239 } 0240 0241 0242 bool DataVector::countFromEOF() const { 0243 return ReqF0 < 0; 0244 } 0245 0246 0247 /** Return Starting Frame of Vector */ 0248 int DataVector::startFrame() const { 0249 return F0; 0250 } 0251 0252 0253 /** Return frames per skip to read */ 0254 int DataVector::skip() const { 0255 return DoSkip ? Skip : 0; 0256 } 0257 0258 0259 bool DataVector::doSkip() const { 0260 return DoSkip; 0261 } 0262 0263 0264 bool DataVector::doAve() const { 0265 return DoAve; 0266 } 0267 0268 0269 /** Return frames held in Vector */ 0270 int DataVector::numFrames() const { 0271 return NF; 0272 } 0273 0274 0275 int DataVector::reqNumFrames() const { 0276 return ReqNF; 0277 } 0278 0279 0280 int DataVector::reqStartFrame() const { 0281 return ReqF0; 0282 } 0283 0284 0285 /** Save vector information */ 0286 void DataVector::save(QXmlStreamWriter &s) { 0287 if (dataSource()) { 0288 s.writeStartElement("datavector"); 0289 saveFilename(s); 0290 s.writeAttribute("field", _field); 0291 0292 s.writeAttribute("start", QString::number(ReqF0)); 0293 s.writeAttribute("count", QString::number(ReqNF)); 0294 0295 if (doSkip()) { 0296 s.writeAttribute("skip", QString::number(Skip)); 0297 if (doAve()) { 0298 s.writeAttribute("doAve", "true"); 0299 } 0300 } else { 0301 s.writeAttribute("skip", QString::number(-1)); 0302 s.writeAttribute("doAve", "false"); 0303 } 0304 0305 s.writeAttribute("startUnits", startUnits()); 0306 s.writeAttribute("rangeUnits", rangeUnits()); 0307 0308 saveNameInfo(s, VECTORNUM|SCALARNUM); 0309 s.writeEndElement(); 0310 } 0311 } 0312 0313 0314 /** 0315 * @brief Generate default label info for axis associated with this vector. 0316 * Use meta-scalars "units" or "quantity" if they are defined. 0317 * Escape special characters in the field name. 0318 * 0319 * @return LabelInfo 0320 **/ 0321 0322 LabelInfo DataVector::labelInfo() const { 0323 LabelInfo label_info; 0324 0325 if (_fieldStrings.contains("quantity")) { 0326 label_info.quantity = _fieldStrings.value("quantity")->value(); 0327 label_info.quantity.replace('[', "\\[").replace(']', "\\]"); 0328 } else { 0329 label_info.quantity.clear(); 0330 } 0331 0332 if (_fieldStrings.contains("units")) { 0333 label_info.units = _fieldStrings.value("units")->value(); 0334 label_info.units.replace('[', "\\[").replace(']', "\\]"); 0335 } else { 0336 label_info.units.clear(); 0337 } 0338 0339 label_info.name = descriptiveName();// _field; 0340 0341 label_info.file = filename(); 0342 0343 return label_info; 0344 } 0345 0346 0347 void DataVector::reset() { // must be called with a lock 0348 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0349 0350 if (dataSource()) { 0351 SPF = dataInfo(_field).samplesPerFrame; 0352 } 0353 F0 = NF = 0; 0354 resize(0); 0355 _numSamples = 0; 0356 _dirty = true; 0357 _resetFieldMetadata(); 0358 0359 Object::reset(); 0360 } 0361 0362 0363 bool DataVector::checkIntegrity() { 0364 if (DoSkip && Skip < 1) { 0365 Skip = 1; 0366 } 0367 0368 if (_dirty) { 0369 reset(); 0370 } 0371 0372 // if the file seems to have shrunk/changed, return false. 0373 // if it has happened several times in a row, assume the 0374 // file has been over-written, and re-read it. 0375 // this is a hack to handle glitchy file system situations. 0376 // TODO: there has to be a better way. 0377 const DataInfo info = dataInfo(_field); 0378 if (dataSource() && (SPF != info.samplesPerFrame || info.frameCount < NF)) { 0379 _invalidCount++; 0380 if (_invalidCount>INVALIDS_PER_RESET) { 0381 0382 reset(); 0383 _invalidCount=0; 0384 } 0385 return false; 0386 } 0387 0388 // check for illegal NF and F0 values 0389 if (ReqNF < 1 && ReqF0 < 0) { 0390 ReqF0 = 0; // for this illegal case, read the whole file 0391 } 0392 0393 if (ReqNF == 1) { 0394 ReqNF = 2; 0395 } 0396 0397 _invalidCount = 0; 0398 return true; 0399 } 0400 0401 // Some things to consider about the following routine... 0402 // Frames: 0403 // Some data sources have data divided into frames. Each field 0404 // has a fixed number of samples per frame. For some (eg, ascii files) 0405 // each frame has 1 sample. For others (eg, dirfiles) you may have more. 0406 // Different fields in the same data source may have different samples per frame. 0407 // Within a data source, it is assumed that the first sample of each frame is 0408 // simultaneous between fields. 0409 // Last Frame Read: 0410 // Only read the first sample of the last frame read, in cases where there are more 0411 // than one sample per frame. This allows for more sensible association of vectors 0412 // into curves, when the X and Y vectors have different numbers of samples per frame. 0413 // The rule is that we assume is that the first sample of each frame is simultaneous. 0414 // Skip reading: 0415 // -'Skip' means read 1 sample each 'Skip' frames (not read one sample, 0416 // then skip 'Skip' samples or something else). 0417 // -In order that the data are not re-drawn each time a new sample arrives, and to 0418 // ensure the re-usability (via shifting) of previously read data, and to make a 0419 // region of data look the same regardless of the chouse of f0, all samples 0420 // read with skip enabled are read on 'skip boundries'... ie, the first samples of 0421 // frame 0, Skip, 2*Skip... N*skip, and never M*Skip+1. 0422 0423 void DataVector::internalUpdate() { 0424 int i, k, shift, n_read=0; 0425 int ave_nread; 0426 int new_f0, new_nf; 0427 bool start_past_eof = false; 0428 0429 if (dataSource()) { 0430 dataSource()->writeLock(); 0431 } else { 0432 return; 0433 } 0434 0435 const DataInfo info = dataInfo(_field); 0436 if (!checkIntegrity()) { 0437 if (dataSource()) { 0438 dataSource()->unlock(); 0439 } 0440 return; 0441 } 0442 0443 if (DoSkip && Skip < 2 && SPF == 1) { 0444 DoSkip = false; 0445 } 0446 0447 0448 // set new_nf and new_f0 0449 int fc = info.frameCount; 0450 if (ReqNF < 1) { // read to end of file 0451 new_f0 = ReqF0; 0452 new_nf = fc - new_f0; 0453 } else if (ReqF0 < 0) { // count back from end of file 0454 new_nf = fc; 0455 if (new_nf > ReqNF) { 0456 new_nf = ReqNF; 0457 } 0458 new_f0 = fc - new_nf; 0459 } else { 0460 new_f0 = ReqF0; 0461 new_nf = ReqNF; 0462 if (new_f0 + new_nf > fc) { 0463 new_nf = fc - new_f0; 0464 } 0465 if (new_nf <= 0) { 0466 // Tried to read starting past the end. 0467 new_f0 = 0; 0468 new_nf = 1; 0469 start_past_eof = true; 0470 } 0471 } 0472 0473 if (DoSkip) { 0474 // in count from end mode, change new_f0 and new_nf so they both lie on skip boundaries 0475 if ((new_f0 != 0) && (ReqF0<0)) { 0476 new_f0 = ((new_f0-1)/Skip+1)*Skip; 0477 } 0478 new_nf = (new_nf/Skip)*Skip; 0479 } 0480 0481 // shift vector if necessary 0482 if (new_f0 < F0 || new_f0 >= F0 + NF) { // No useful data around. 0483 reset(); 0484 } else { // shift stuff rather than re-read 0485 if (DoSkip) { 0486 shift = (new_f0 - F0)/Skip; 0487 NF -= (new_f0 - F0); 0488 _numSamples = NF/Skip; 0489 } else { 0490 shift = SPF*(new_f0 - F0); 0491 NF -= (new_f0 - F0); 0492 //_numSamples = (NF-1)*SPF; 0493 if (shift > 0) { 0494 if (SPF == 1) { 0495 _numSamples = NF; 0496 } else { 0497 _numSamples = (NF-1)*SPF; 0498 } 0499 } 0500 } 0501 0502 memmove(_v_raw, _v_raw+shift, _numSamples*sizeof(double)); 0503 } 0504 0505 if (DoSkip) { 0506 // reallocate V if necessary 0507 if (new_nf / Skip != _size) { 0508 if (! resize(new_nf/Skip)) { 0509 // TODO: Is aborting all we can do? 0510 fatalError("Not enough memory for vector data"); 0511 return; 0512 } 0513 } 0514 n_read = 0; 0515 /** read each sample from the File */ 0516 double *t = _v_raw + _numSamples; 0517 int new_nf_Skip = new_nf - Skip; 0518 if (DoAve) { 0519 for (i = NF; new_nf_Skip >= i; i += Skip) { 0520 /* enlarge AveReadBuf if necessary */ 0521 if (N_AveReadBuf < Skip*SPF) { 0522 N_AveReadBuf = Skip*SPF; 0523 if (!kstrealloc(AveReadBuf, N_AveReadBuf*sizeof(double))) { 0524 qCritical() << "Vector resize failed"; 0525 } 0526 if (!AveReadBuf) { 0527 // FIXME: handle failed resize 0528 } 0529 } 0530 ave_nread = readField(AveReadBuf, _field, new_f0+i, Skip); 0531 for (k = 1; k < ave_nread; ++k) { 0532 AveReadBuf[0] += AveReadBuf[k]; 0533 } 0534 if (ave_nread > 0) { 0535 *t = AveReadBuf[0]/double(ave_nread); 0536 n_read++; 0537 } 0538 ++t; 0539 } 0540 } else { 0541 for (i = NF; new_nf_Skip >= i; i += Skip) { 0542 n_read += readField(t++, _field, new_f0 + i, -1); 0543 } 0544 } 0545 } else { 0546 // reallocate V if necessary 0547 if ((new_nf - 1)*SPF + 1 != _size) { 0548 if (!resize((new_nf - 1)*SPF + 1)) { 0549 // TODO: Is aborting all we can do? 0550 fatalError("Not enough memory for vector data"); 0551 return; 0552 } 0553 } 0554 0555 // read the new data from file 0556 if (start_past_eof) { 0557 _v_raw[0] = NOPOINT; 0558 n_read = 1; 0559 } else if (info.samplesPerFrame > 1) { 0560 if (NF>0) { 0561 NF--; /* last frame read was only partially read... */ 0562 } 0563 int safe_nf = (new_nf>0 ? new_nf : 0); 0564 0565 assert(new_f0 + NF >= 0); 0566 //assert(new_f0 + safe_nf - 1 >= 0); 0567 if ((new_f0 + safe_nf - 1 >= 0) && (safe_nf - NF > 1)) { 0568 n_read = readField(_v_raw+NF*SPF, _field, new_f0 + NF, safe_nf - NF - 1); 0569 n_read += readField(_v_raw+(safe_nf-1)*SPF, _field, new_f0 + safe_nf - 1, -1); 0570 } 0571 } else { 0572 assert(new_f0 + NF >= 0); 0573 if (new_nf - NF > 0 || new_nf - NF == -1) { 0574 n_read = readField(_v_raw+NF*SPF, _field, new_f0 + NF, new_nf - NF); 0575 } 0576 } 0577 } 0578 _numNew = _size - _numSamples; 0579 NF = new_nf; 0580 F0 = new_f0; 0581 _numSamples += n_read; 0582 0583 // if for some reason (eg, realtime reading an nfs mounted 0584 // dirfile) not all of the data was read, the data will never 0585 // be read; the samples will be filled in with the last data 0586 // point read, and a complete reset will be requested. 0587 // This is bad - I think it will be worthwhile 0588 // to add blocking w/ timeout to KstFile. 0589 // As a first fix, mount all nsf mounted dirfiles with "-o noac" 0590 _dirty = false; 0591 if (_numSamples != _size && !(_numSamples == 0 && _size == 1)) { 0592 _dirty = true; 0593 for (i = _numSamples; i < _size; ++i) { 0594 _v_raw[i] = _v_raw[0]; 0595 } 0596 } 0597 0598 if (_numNew > _size) { 0599 _numNew = _size; 0600 } 0601 if (_numShifted > _size) { 0602 _numShifted = _size; 0603 } 0604 0605 if (dataSource()) { 0606 dataSource()->unlock(); 0607 } 0608 0609 if (n_read>0) { 0610 Vector::internalUpdate(); 0611 } 0612 } 0613 0614 QByteArray DataVector::scriptInterface(QList<QByteArray> &c) 0615 { 0616 Q_ASSERT(c.size()); 0617 if(c[0]=="changeFrames") { 0618 if(c.size()!=6) { 0619 return QByteArray("Bad parameter count (!=5)."); 0620 } 0621 changeFrames(c[1].toInt(),c[2].toInt(),c[3].toInt(),(c[4]=="true")?1:0,(c[5]=="true")?1:0); 0622 return QByteArray("Done."); 0623 } else if(c[0]=="numFrames") { 0624 return QByteArray::number(numFrames()); 0625 } else if(c[0]=="startFrame") { 0626 return QByteArray::number(startFrame()); 0627 } else if(c[0]=="doSkip") { 0628 return QByteArray(doSkip()?"true":"false"); 0629 } else if(c[0]=="doAve") { 0630 return QByteArray(doAve()?"true":"false"); 0631 } else if(c[0]=="skip") { 0632 return QByteArray::number(skip()); 0633 } else if(c[0]=="reload") { 0634 reload(); 0635 return QByteArray("Done"); 0636 } else if(c[0]=="samplesPerFrame") { 0637 return QByteArray::number(samplesPerFrame()); 0638 } else if(c[0]=="fileLength") { 0639 return QByteArray::number(fileLength()); 0640 } else if(c[0]=="readToEOF") { 0641 return QByteArray(readToEOF()?"true":"false"); 0642 } else if(c[0]=="countFromEOF") { 0643 return QByteArray(countFromEOF()?"true":"false"); 0644 } else if(c[0]=="descriptionTip") { 0645 return QByteArray(descriptionTip().toLatin1()); 0646 } else if(c[0]=="isValid") { 0647 return isValid()?"true":"false"; 0648 } 0649 0650 return "No such command..."; 0651 } 0652 0653 0654 /** Returns intrinsic samples per frame */ 0655 int DataVector::samplesPerFrame() const { 0656 return SPF; 0657 } 0658 0659 0660 int DataVector::fileLength() const { 0661 0662 if (dataSource()) { 0663 int rc = dataInfo(_field).frameCount; 0664 0665 return rc; 0666 } 0667 0668 return 0; 0669 } 0670 0671 0672 void DataVector::reload() { 0673 Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); 0674 0675 if (dataSource()) { 0676 dataSource()->writeLock(); 0677 dataSource()->reset(); 0678 dataSource()->unlock(); 0679 reset(); 0680 _resetFieldMetadata(); 0681 registerChange(); 0682 } 0683 } 0684 0685 void DataVector::_resetFieldMetadata() { 0686 _resetFieldScalars(); 0687 _resetFieldStrings(); 0688 } 0689 0690 void DataVector::_resetFieldStrings() { 0691 const QMap<QString, QString> meta_strings = dataSource()->vector().metaStrings(_field); 0692 0693 QStringList fieldStringKeys = _fieldStrings.keys(); 0694 // remove field strings that no longer need to exist 0695 readLock(); 0696 for (int i=0; i<fieldStringKeys.count(); ++i) { 0697 QString key = fieldStringKeys.at(i); 0698 if (!meta_strings.contains(key)) { 0699 StringPtr sp = _fieldStrings[key]; 0700 _strings.remove(key); 0701 _fieldStrings.remove(key); 0702 sp = 0L; 0703 } 0704 } 0705 // find or insert strings, to set their value 0706 QMapIterator<QString, QString> it(meta_strings); 0707 while (it.hasNext()) { 0708 it.next(); 0709 QString key = it.key(); 0710 StringPtr sp; 0711 if (!_fieldStrings.contains(key)) { // insert a new one 0712 _strings.insert(key, sp = store()->createObject<String>()); 0713 _fieldStrings.insert(key, sp); 0714 sp->setProvider(this); 0715 sp->setSlaveName(key); 0716 } else { // find it 0717 sp = _fieldStrings[key]; 0718 } 0719 sp->setValue(it.value()); 0720 } 0721 unlock(); 0722 } 0723 0724 0725 void DataVector::_resetFieldScalars() { 0726 const QMap<QString, double> meta_scalars = dataSource()->vector().metaScalars(_field); 0727 0728 0729 QStringList fieldScalarKeys = _fieldScalars.keys(); 0730 // remove field scalars that no longer need to exist 0731 readLock(); 0732 for (int i=0; i<fieldScalarKeys.count(); ++i) { 0733 QString key = fieldScalarKeys.at(i); 0734 if (!meta_scalars.contains(key)) { 0735 ScalarPtr sp = _fieldScalars[key]; 0736 _scalars.remove(key); 0737 _fieldScalars.remove(key); 0738 sp = 0L; 0739 } 0740 } 0741 // find or insert scalars, to set their value 0742 QMapIterator<QString, double> it(meta_scalars); 0743 while (it.hasNext()) { 0744 it.next(); 0745 QString key = it.key(); 0746 ScalarPtr sp; 0747 if (!_fieldScalars.contains(key)) { // insert a new one 0748 _scalars.insert(key, sp = store()->createObject<Scalar>()); 0749 _fieldScalars.insert(key, sp); 0750 sp->setProvider(this); 0751 sp->setSlaveName(key); 0752 } else { // find it 0753 sp = _fieldScalars[key]; 0754 } 0755 sp->setValue(it.value()); 0756 } 0757 unlock(); 0758 } 0759 0760 0761 PrimitivePtr DataVector::makeDuplicate() const { 0762 Q_ASSERT(store()); 0763 DataVectorPtr vector = store()->createObject<DataVector>(); 0764 0765 vector->writeLock(); 0766 vector->change(dataSource(), _field, ReqF0, ReqNF, Skip, DoSkip, DoAve); 0767 if (descriptiveNameIsManual()) { 0768 vector->setDescriptiveName(descriptiveName()); 0769 } 0770 0771 vector->registerChange(); 0772 vector->unlock(); 0773 0774 return kst_cast<Primitive>(vector); 0775 } 0776 0777 QString DataVector::_automaticDescriptiveName() const { 0778 QString name; 0779 name = _field; 0780 // un-escape escaped special characters so they aren't escaped 2x. 0781 name.replace("\\_", "_").replace("\\^","^").replace("\\[", "[").replace("\\]", "]"); 0782 // now escape the special characters. 0783 name.replace('_', "\\_").replace('^', "\\^").replace('[', "\\[").replace(']', "\\]"); 0784 return name; 0785 } 0786 0787 QString DataVector::descriptionTip() const { 0788 QString IDstring; 0789 //QString range_string; 0790 0791 if (dataSource()) { 0792 IDstring = tr( 0793 "Data Vector: %1\n" 0794 " %2\n" 0795 " Field: %3" 0796 ).arg(Name()).arg(dataSource()->fileName()).arg(_field); 0797 if (countFromEOF()) { 0798 IDstring += tr("\n Last %1 frames.").arg(numFrames()); 0799 } else if (readToEOF()) { 0800 IDstring += tr("\n Frame %1 to end.").arg(startFrame()); 0801 } else { 0802 IDstring += tr("\n %1 Frames starting at %2.").arg(numFrames()).arg(startFrame()); 0803 } 0804 if (skip()) { 0805 if (!doAve()) { 0806 IDstring+=tr("\n Read 1 sample per %1 frames.").arg(skip()); 0807 } else { 0808 IDstring+=tr("\n Average each %1 frames.").arg(skip()); 0809 } 0810 } 0811 } else{ 0812 IDstring.clear(); 0813 } 0814 0815 return IDstring; 0816 } 0817 0818 QString DataVector::propertyString() const { 0819 return tr("%2 F0: %3 N: %4 of %1", "%2 is a variable name. F0 is short for the first element. N is the number of elements").arg(dataSource()->fileName()).arg(_field).arg(startFrame()).arg(numFrames()); 0820 } 0821 0822 0823 int DataVector::readField(double *v, const QString& field, int s, int n, int skip) 0824 { 0825 ReadInfo par = {v, s, n, skip}; 0826 return dataSource()->vector().read(field, par); 0827 } 0828 0829 const DataVector::DataInfo DataVector::dataInfo(const QString& field) const 0830 { 0831 dataSource()->readLock(); 0832 const DataInfo info = dataSource()->vector().dataInfo(field); 0833 dataSource()->unlock(); 0834 return info; 0835 } 0836 0837 bool DataVector::isTime() const { 0838 return dataSource()->isTime(_field); 0839 } 0840 0841 } 0842 // vim: ts=2 sw=2 et