Пример #1
0
void KstRWLock::writeLock() const {
#ifndef ONE_LOCK_TO_RULE_THEM_ALL
  QMutexLocker lock(&_mutex);

#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::writeLock() by tid=" << (int)QThread::currentThread() << endl;
//  kstdDebug() << kstdBacktrace(6) << endl;
#endif

  Qt::HANDLE me = QThread::currentThread();

  if (_readCount > 0) {
    QMap<Qt::HANDLE, int>::Iterator it = _readLockers.find(me);
    if (it != _readLockers.end() && it.data() > 0) {
      // cannot acquire a write lock if I already have a read lock -- ERROR
      kstdFatal() << "Thread " << (int)QThread::currentThread() << " tried to write lock KstRWLock " << (void*)this << " while holding a read lock" << endl;
      return;
    }
  }

  while (_readCount > 0 || (_writeCount > 0 && _writeLocker != me)) {
    ++_waitingWriters;
    _writerWait.wait(&_mutex);
    --_waitingWriters;
  }
  _writeLocker = me;
  ++_writeCount;

#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::writeLock() done by tid=" << (int)QThread::currentThread() << endl;
#endif
#else
  _mutex.lock();
#endif
}
// Note: e can be null
void KstViewWidget::paintEvent(QPaintEvent *e) {
#ifdef BENCHMARK
  QTime t;
  t.start();
#endif
  if (e) {  // Resize/expose/etc triggered by X11
    QRegion r = e->region();
    if (r.isEmpty()) {
      //kstdDebug() << "Paint event with NO region" << endl;
      _view->paint(KstPainter::P_PAINT);
    } else {
      //kstdDebug() << "Paint event with region " << e->region() << endl;
      _view->paint(KstPainter::P_PAINT, e->region());
    }
#ifdef BENCHMARK
    int x = t.elapsed();
    kstdDebug() << "Paint event: X11 triggered - " << x << "ms" << endl;
#endif
  } else { // explicitly forced paint in the code
    _view->paint(KstPainter::P_ZOOM);
#ifdef BENCHMARK
    int x = t.elapsed();
    kstdDebug() << "Paint event: Forced (zoom) - " << x << "ms" << endl;
#endif
  }
}
Пример #3
0
void KstRWLock::unlock() const {
#ifndef ONE_LOCK_TO_RULE_THEM_ALL
  QMutexLocker lock(&_mutex);

#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::unlock() by tid=" << (int)QThread::currentThread() << endl;
#endif

  Qt::HANDLE me = QThread::currentThread();

  if (_readCount > 0) {
    QMap<Qt::HANDLE, int>::Iterator it = _readLockers.find(me);
    if (it == _readLockers.end()) {
      // read locked but not by me -- ERROR
      kstdFatal() << "Thread " << (int)QThread::currentThread() << " tried to unlock KstRWLock " << (void*)this << " (read locked) without holding the lock" << endl;
      return;
    } else {
      --_readCount;
      if (it.data() == 1) {
        _readLockers.remove(it);
      } else {
        --(it.data());
      }
    }
  } else if (_writeCount > 0) {
    if (_writeLocker != me) {
      // write locked but not by me -- ERROR
      kstdFatal() << "Thread " << (int)QThread::currentThread() << " tried to unlock KstRWLock " << (void*)this << " (write locked) without holding the lock" << endl;
      return;
    } else {
      --_writeCount;
    }
  } else if (_readCount == 0 && _writeCount == 0) {
    // not locked -- ERROR
    kstdFatal() << "Thread " << (int)QThread::currentThread() << " tried to unlock KstRWLock " << (void*)this << " (unlocked) without holding the lock" << endl;
    return;
  }

  if (_readCount == 0 && _writeCount == 0) {
    // no locks remaining
    if (_waitingWriters) {
      _writerWait.wakeOne();
    } else if (_waitingReaders) {
      _readerWait.wakeAll();
    }
  }

#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::unlock() done by tid=" << (int)QThread::currentThread() << endl;
#endif
#else
  _mutex.unlock();
#endif
}
Пример #4
0
int NADDirectSource::samplesPerFrame(const QString &field) {
  if (!_valid) {
    return 0;
  }

  if (field == "INDEX") {
    kstdDebug() << "NAD::samplesPerFrame(" << field << ") = 1\n";
    return 1;
  }

  int spf = _conn->samplesPerFrame(field);
  kstdDebug() << "NAD::samplesPerFrame(" << field << ") = " << spf << endl;
  return spf;
}
Пример #5
0
KstObject::UpdateType NADDirectSource::update(int u) {
  if (KstObject::checkUpdateCounter(u)) {
    return lastUpdateResult();
  }

  if (_conn && _conn->updated()) {
    updateNumFramesScalar();
    kstdDebug() << "NAD::update(" << QString::number(u) << ") = UPDATE\n";
    return setLastUpdateResult(KstObject::UPDATE);
  } else {
    kstdDebug() << "NAD::update(" << QString::number(u) << ") = NO_CHANGE\n";
    return setLastUpdateResult(KstObject::NO_CHANGE);
  }
}
Пример #6
0
// if n > 0, read n FRAMES starting at frame s for field into buffer v
// if n < 0, read 1 SAMPLE from frame s for field into buffer v
int NADDirectSource::readField(double *v, const QString& field, int s, int n) {
  kstdDebug() << "NAD::readField(" << field << ", s=" + QString::number(s) + ", n=" + QString::number(n) + ")" << endl;

  if (field == "INDEX") {
    if (n < 0) {
      v[0] = double(s);
      return 1;
    }
    for (int i = 0; i < n; ++i) {
      v[i] = double(s + i);
    }
    return n > 0 ? n : 0;
  }

  if (!_valid || !_conn || !_conn->isValid()) {
    kstdDebug() << "tried to read from an invalid NAD source" << endl;
    kstdDebug() << "plugin is valid? " << _valid << endl;
    return -1;
  }

  QSize sz = _conn->range(field);
  long start = sz.width(), end = sz.height();
  long count = end - start + 1;

  if (s + start > end) {
    kstdDebug() << "Nothing to read: (" << start << "," << end << ") " << s << endl;
    return 0;
  }

  if (n < 0) { // reading less than 0 -> read only one sample!
    int spf = _conn->samplesPerFrame(field);
    double *temp = new double[spf];
    _conn->getData(field, temp, start + s, start + s);
    v[0] = temp[0];
    delete[] temp;
    return 1;
  } else {
    if (s + n > count) { // trying to read past the end
      n = count - s;
    }

//    assert(n != 0);
//    kstdDebug() << "NAD: calling getData()" << endl;
    int ret = _conn->getData(field, v, start + s, start + s + n - 1);
//    kstdDebug() << "NAD::readField(" << field << ", s=" + QString::number(s) + ", n=" + QString::number(n) + ") = " << ret << endl;
    return ret;
  }
}
Пример #7
0
QStringList provides_naddirect() {
  kstdDebug() << "in provides_naddirect" << endl;

  QStringList rc;
  rc += "Direct NAD Connection";
  return rc;
}
Пример #8
0
QStringList fieldList_naddirect(KConfig *cfg, const QString& filename, const QString& type, QString *typeSuggestion, bool *complete) {
  Q_UNUSED(cfg)

  kstdDebug() << "in fieldList_naddirect:" << filename << endl;

  if (!type.isEmpty() && !provides_naddirect().contains(type)) {
    return QStringList();
  }

  NAD::NADConnection conn;
  conn.setUrl(filename);
  if (!conn.isValid()) {
    return QStringList();
  }

  if (complete) {
    *complete = true;
  }

  if (typeSuggestion) {
    *typeSuggestion = "Direct NAD Connection";
  }

  QStringList rc = conn.getFields();
  if (!rc.empty()) {
    rc.prepend("INDEX");
  }

  return rc;
}
KstBaseCurvePtr KstCurveHint::makeCurve(const QString& tag, const QColor& color) const {
  KstVectorPtr x = xVector();
  KstVectorPtr y = yVector();
  if (!x || !y) {
    kstdDebug() << "Couldn't find either " << _xVectorName << " or " << _yVectorName << endl;
    return 0L;
  }

  return new KstVCurve(tag, x, y, 0L, 0L, 0L, 0L, color);
}
Пример #10
0
int NADDirectSource::frameCount(const QString& field) const {
  if (!_valid) {
    return 0;
  }

  if (field.isEmpty() || _fieldList.contains(field)) {
    int maxLen = 0;
    for (QStringList::ConstIterator i = _fieldList.begin(); i != _fieldList.end(); ++i) {
//      assert(!(*i).isEmpty());
      QSize sz = _conn->range(*i);
      maxLen = QMAX(sz.height() - sz.width() + 1, maxLen);
    }
    kstdDebug() << "NAD::frameCount(" << field << ") = maxLen = " << maxLen << endl;
    return maxLen;
  }

  QSize sz = _conn->range(field);
  kstdDebug() << "NAD::frameCount(" << field << ") = " << sz.height() - sz.width() + 1 << endl;
  return sz.height() - sz.width() + 1;
}
Пример #11
0
bool NADDirectSource::init() {
  kstdDebug() << "NAD::init()\n";
  if (_conn->isValid()) {
    _fieldList = _conn->getFields();
    if (!_fieldList.empty()) {
      _fieldList.prepend("INDEX");
    }
  }

  return update() == KstObject::UPDATE;
}
Пример #12
0
NADDirectSource::NADDirectSource(KConfig *cfg, const QString& filename, const QString& type)
: KstDataSource(cfg, filename, type) {
  kstdDebug() << "NAD: constructor (filename=" + filename + ")" << endl;

  _conn = new NAD::NADConnection();
  _conn->setUrl(filename);

  if (init()) {
    _valid = true;
  }
}
Пример #13
0
void KstTopLevelView::paint(KstPainter& p, const QRegion& bounds) {
  updateAlignment(p);
#ifdef BENCHMARK
  QTime t;
  t.start();
#endif
  KstViewObject::paint(p, bounds);
#ifdef BENCHMARK
  int x = t.elapsed();
  kstdDebug() << " -> Parent class took " << x << "ms" << endl;
#endif
}
Пример #14
0
int understands_naddirect(KConfig *cfg, const QString& filename) {
  Q_UNUSED(cfg)

  kstdDebug() << "in understands_naddirect:" << filename << endl;

  KURL url(filename);
  if (url.protocol().lower() == "nad") {
    return 99;
  } else {
    return 0;
  }
}
Пример #15
0
void KstRWLock::readLock() const {
#ifndef ONE_LOCK_TO_RULE_THEM_ALL
  QMutexLocker lock(&_mutex);
  
#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::readLock() by tid=" << (int)QThread::currentThread() << endl;
//  kstdDebug() << kstdBacktrace(6) << endl;
#endif

  Qt::HANDLE me = QThread::currentThread();

  if (_writeCount > 0 && _writeLocker == me) {
    // thread already has a write lock
#ifdef LOCKTRACE
    kstdDebug() << "Thread " << (int)QThread::currentThread() << " has a write lock on KstRWLock " << (void*)this << ", getting a read lock" << endl;
#endif
  } else {
    QMap<Qt::HANDLE, int>::Iterator it = _readLockers.find(me);
    if (it != _readLockers.end() && it.data() > 0) {
      // thread already has another read lock
    } else {
      while (_writeCount > 0 || _waitingWriters) {  // writer priority otherwise
        ++_waitingReaders;
        _readerWait.wait(&_mutex);
        --_waitingReaders;
      }
    }
  }

  _readLockers[me] = _readLockers[me] + 1;
  ++_readCount;

#ifdef LOCKTRACE
  kstdDebug() << (void*)this << " KstRWLock::readLock() done by tid=" << (int)QThread::currentThread() << endl;
#endif
#else
  _mutex.lock();
#endif
}
Пример #16
0
bool NADDirectSource::isEmpty() const {
  kstdDebug() << "NAD::isEmpty()" << endl;

  if (!_valid) {
    return true;
  }

  for (QStringList::ConstIterator i = _fieldList.begin(); i != _fieldList.end(); ++i) {
    QSize sz = _conn->range(*i);
    if (sz.height() - sz.width() + 1 > 0) {
      return false;
    }
  }

  return true;
}
void KstViewLabel::computeTextSize(Label::Parsed *lp) {
  if (lp && lp->chunk) {
    RenderContext rc(_fontName, _absFontSize, 0L);
    rc.setSubstituteScalars(_replace);
    rc.precision = _dataPrecision;
#ifdef BENCHMARK
    QTime t;
    t.start();
#endif
    renderLabel(rc, lp->chunk, _vectorsUsed, _scalarsUsed, _stringsUsed);
#ifdef BENCHMARK
    kstdDebug() << "compute (false render) took: " << t.elapsed() << endl;
#endif
    _textWidth = rc.xMax;
    _ascent = rc.ascent;
    _textHeight = 1 + rc.ascent + rc.descent;
  }
}
Пример #18
0
void renderLabel(RenderContext& rc, Label::Chunk *fi) {
  // FIXME: RTL support
  int oldSize = rc.size;
  int oldY = rc.y;
  int oldX = rc.x;
  
  while (fi) {
    if (fi->vOffset != Label::Chunk::None) {
      if (fi->vOffset == Label::Chunk::Up) {
        rc.y -= int(0.4 * rc.fontHeight());
      } else { // Down
        rc.y += int(0.4 * rc.fontHeight());
      }
      if (rc.size > 5) {
        rc.size = (rc.size*2)/3;
      }
    }

    QFont f = rc.font();
    if (rc.fontSize() != rc.size) {
      f.setPointSize(rc.size);
    }

    f.setBold(fi->attributes.bold);
    f.setItalic(fi->attributes.italic);
    f.setUnderline(fi->attributes.underline);
    if (rc.p && fi->attributes.color.isValid()) {
      rc.p->setPen(fi->attributes.color);
    } else if (rc.p) {
      rc.p->setPen(rc.pen);
    }
    rc.setFont(f);

    if (fi->linebreak) {
      rc.x = oldX;
      rc.y += rc.fontAscent() + rc.fontDescent() + 1;
      fi = fi->next;
      continue;
    }

    if (!rc.substitute && (fi->scalar || fi->vector)) {
      QString txt = QString("[") + fi->text + "]";
      if (rc.p) {
        rc.p->drawText(rc.x, rc.y, txt);
      }
      rc.x += rc.fontWidth(txt);
    } else if (fi->scalar) { 
      // do scalar/string/fit substitution
      QString txt;
      if (!fi->text.isEmpty() && fi->text[0] == '=') {
        // Parse and evaluate as an equation
        bool ok = false;
        const double eqResult(Equation::interpret(fi->text.mid(1).latin1(), &ok));
        txt = QString::number(eqResult, 'g', rc.precision);
        if (rc._cache) {
          rc._cache->append(DataRef(DataRef::DRExpression, fi->text, QString::null, 0.0, QVariant(eqResult)));
        }
      } else {
        KST::scalarList.lock().readLock();
        KstScalarPtr scp = *KST::scalarList.findTag(fi->text);
        KST::scalarList.lock().unlock();
        if (scp) {
          scp->readLock();
          txt = QString::number(scp->value(), 'g', rc.precision);
          if (rc._cache) {
            rc._cache->append(DataRef(DataRef::DRScalar, fi->text, QString::null, 0.0, QVariant(scp->value())));
          }
          scp->unlock();
        } else {
          KST::stringList.lock().readLock();
          KstStringPtr stp = *KST::stringList.findTag(fi->text);
          KST::stringList.lock().unlock();
          if (stp) {
            stp->readLock();
            txt = stp->value();
            if (rc._cache) {
              rc._cache->append(DataRef(DataRef::DRString, fi->text, QString::null, 0.0, QVariant(stp->value())));
            }
            stp->unlock();
          } else {
            KST::dataObjectList.lock().readLock();
            KstDataObjectList::Iterator oi = KST::dataObjectList.findTag(fi->text);
            KST::dataObjectList.lock().unlock();
            if (oi != KST::dataObjectList.end()) {
              KstPluginPtr fit = kst_cast<KstPlugin>(*oi);
              if (fit) {
                fit->readLock();
                const QString txtAll = fit->label(rc.precision);
                fit->unlock();
                
                const QValueList<QString> strList = QStringList::split('\n', txtAll);
                QValueListConstIterator<QString> last = --(strList.end());
                for (QValueListConstIterator<QString> iter = strList.begin(); iter != strList.end(); ++iter) {
                  txt = (*iter);

                  if (iter != last) {
                    if (rc.p) {
                      rc.p->drawText(rc.x, rc.y, txt);
                    } else {
                      rc.ascent = kMax(rc.ascent, -rc.y + rc.fontAscent());
                      if (-rc.y - rc.fontDescent() < 0) {
                        rc.descent = kMax(rc.descent, rc.fontDescent() + rc.y);
                      }
                    }
                    rc.x   += rc.fontWidth(txt);
                    rc.xMax = kMax(rc.xMax, rc.x);
                  
                    rc.x    = oldX;
                    rc.y   += rc.fontAscent() + rc.fontDescent() + 1;
                  }
                }                
                if (rc._cache) {
                  rc._cache->append(DataRef(DataRef::DRFit, fi->text, txtAll, rc.precision, QVariant(0.0)));
                }
              }
            }
          }
        }
      }
      if (rc.p) {
        rc.p->drawText(rc.x, rc.y, txt);
      }
      rc.x += rc.fontWidth(txt);
    } else if (fi->vector) {
      QString txt;
      KST::vectorList.lock().readLock();
      KstVectorPtr vp = *KST::vectorList.findTag(fi->text);
      KST::vectorList.lock().unlock();
      if (vp) {
        if (!fi->expression.isEmpty()) {
          // Parse and evaluate as an equation
          bool ok = false;
          // FIXME: make more efficient: cache the parsed equation
          const double idx = Equation::interpret(fi->expression.latin1(), &ok);
          if (ok) {
            vp->readLock();
            const double vVal(vp->value()[int(idx)]);
            txt = QString::number(vVal, 'g', rc.precision);
            if (rc._cache) {
              rc._cache->append(DataRef(DataRef::DRVector, fi->text, fi->expression, idx, QVariant(vVal)));
            }
            vp->unlock();
          } else {
            txt = "NAN";
          }
        }
      }
      if (rc.p) {
        rc.p->drawText(rc.x, rc.y, txt);
      }
      rc.x += rc.fontWidth(txt);
    } else if (fi->tab) {
      const int tabWidth = rc.fontWidth("MMMMMMMM");
      const int toSkip = tabWidth - (rc.x - rc.xStart) % tabWidth;
      if (rc.p && fi->attributes.underline) {
        const int spaceWidth = rc.fontWidth(" ");
        const int spacesToSkip = tabWidth / spaceWidth + (tabWidth % spaceWidth > 0 ? 1 : 0);
        rc.p->drawText(rc.x, rc.y, QString().fill(' ', spacesToSkip));
      }
      rc.x += toSkip;
    } else {
      if (rc.p) {
#ifdef BENCHMARK
        QTime t;
        t.start();
#endif
        rc.p->drawText(rc.x, rc.y, fi->text);
#ifdef BENCHMARK
        kstdDebug() << "Renderer did draw, time: " << t.elapsed() << endl;
#endif
      }
      rc.x += rc.fontWidth(fi->text);
    }

    if (!rc.p) {
      // No need to compute ascent and descent when really painting
      rc.ascent = kMax(rc.ascent, -rc.y + rc.fontAscent());
      if (-rc.y - rc.fontDescent() < 0) {
        rc.descent = kMax(rc.descent, rc.fontDescent() + rc.y);
      }
    }

    int xNext = rc.x;
    if (fi->group) {
      renderLabel(rc, fi->group);
      xNext = rc.x;
    }

    if (fi->up) {
      int xPrev = rc.x;
      renderLabel(rc, fi->up);
      xNext = kMax(xNext, rc.x);
      rc.x = xPrev;
    }

    if (fi->down) {
      renderLabel(rc, fi->down);
      xNext = kMax(xNext, rc.x);
    }

    rc.x = xNext;
    rc.xMax = kMax(rc.xMax, rc.x);

    fi = fi->next;
  }

  rc.size = oldSize;
  rc.y = oldY;
}
Пример #19
0
bool NADDirectSource::isValidField(const QString& field) const {
  bool valid = _fieldList.contains(field);
  kstdDebug() << "NAD::isValidField(" << field << ") = " << valid << endl;
  return valid;
}
Пример #20
0
int CdfSource::readField(double *v, const QString& field, int s, int n) {
  int i;
  CDFstatus status;
  CDFid id;
  long dataType = 0, maxRec = 0, numDims = 0, dimSizes[CDF_MAX_DIMS];
  long recCount = 0, indices[1] = {0}, counts[1] = {0};
  char varName[CDF_VAR_NAME_LEN+1];
  bool isZvar = true;     /* Should be the case for recent cdf files */
  // kstdDebug() << "Entering CdfSource::readField with params: " << field << ", from " << s << " for " << n << " values" << endl;
  // Handle the special case where we query INDEX
  if (field.lower() == "index") {
    if (n < 0) {
      v[0] = double(s);
      return 1;
    }
    for (int i = 0; i < n; ++i) {
      v[i] = double(s + i);
    }
    return n;
  }

  // If not INDEX, look into the CDF file...
  status = CDFopen(_filename.latin1(), &id);
  if (status < CDF_OK) {
    kstdDebug() << _filename << ": failed to open to read from field " << field << endl;
    return -1;
  }

  QString ftmp = field;
  ftmp.truncate(CDF_VAR_NAME_LEN);
  // Variable selection
  strcpy(varName, ftmp.latin1());
  status = CDFlib(SELECT_,
                     zVAR_NAME_, varName, 
                  GET_,
                     zVAR_DATATYPE_, &dataType, 
                  NULL_);
  if (status < CDF_OK) { // if not zVar, try rVar
    // kstdDebug() << ftmp << ": " << " not a zVAR (" << status <<")" << endl;
    isZvar = false;
    status = CDFlib(SELECT_, 
                       rVAR_NAME_, varName, 
                    GET_, 
                       rVAR_DATATYPE_, &dataType, 
                    NULL_);
  }

  // I suppose the returned int is the number of values read, <0 when there is a problem
  if (status < CDF_OK) {
    kstdDebug() << ftmp << ": " << " not a rVAR either -> exiting" << endl;
    CDFclose(id);
    return -1; 
  }

  // If n<0 set it to 1 as suggested by George Staikos
  // (needs to be documented better I guess !)
  // First check for the existence of more values for this field
  if (n < 0) {
    n = 1;
  }

  void *binary = 0L;
  void *pt = 0L;
 
  // Cast the iteration pointer to the right type and allocate the needed space for binary
  switch (dataType) {
    case CDF_INT2:
       binary = malloc(n*sizeof(Int16));
       pt = (Int16 *)binary;
      break;
    case CDF_INT4:
      binary = malloc(n*sizeof(Int32));
      pt = (Int32 *)binary;
      break;
    case CDF_UINT1:
      binary = malloc(n*sizeof(uChar));
      pt = (uChar *)binary;
      break;
    case CDF_UINT2:
      binary = malloc(n*sizeof(uInt16));
      pt = (uInt16 *)binary;
      break;
    case CDF_UINT4:
      binary = malloc(n*sizeof(uInt32));
      pt = (uInt32 *)binary;
      break;
    case CDF_REAL4:
    case CDF_FLOAT:
      binary = malloc(n*sizeof(float));
      pt = (float *)binary;
      break;
    case CDF_REAL8:
    case CDF_DOUBLE:
      binary = malloc(n*sizeof(double));
      pt = (double *)binary; 
      break;
    default :
      binary = malloc(n*sizeof(long double));
    break;
  }

  // Get some useful values
  status = CDFlib (GET_, 
                    BOO(isZvar, zVAR_MAXREC_, rVAR_MAXREC_), &maxRec,
                    BOO(isZvar, zVAR_NUMDIMS_, rVARs_NUMDIMS_), &numDims,
                    BOO(isZvar, zVAR_DIMSIZES_, rVARs_DIMSIZES_), dimSizes,
                 NULL_);
  maxRec += 1;

  if (numDims == 0 || (numDims == 1 && dimSizes[0] < 2)) { // Vars of dimension 0, or vectors of size 1 (pseudo scalars) with records > 1
    status = CDFlib (SELECT_,
                        BOO(isZvar, zVAR_RECNUMBER_, rVAR_SEQPOS_), (long) s,
                        BOO(isZvar, zVAR_RECCOUNT_, rVARs_RECCOUNT_), (long) n,
                     GET_,
                        BOO(isZvar, zVAR_HYPERDATA_, rVAR_HYPERDATA_), binary,
                     NULL_);
  }
  else { // Vectors of size [1: n>1] with only one sample/record a la Matlab
     indices[0] = s;
     counts[0] = n;
     recCount = 1;
     status = CDFlib (SELECT_, 
                         BOO(isZvar,zVAR_RECCOUNT_,rVARs_RECCOUNT_), recCount,
                         BOO(isZvar,zVAR_DIMINDICES_,rVARs_DIMINDICES_), indices, 
                         BOO(isZvar,zVAR_DIMCOUNTS_,rVARs_DIMCOUNTS_), counts, 
                      GET_,
                         BOO(isZvar,zVAR_HYPERDATA_,rVAR_HYPERDATA_), binary,
                      NULL_);
    maxRec = dimSizes[0];
  }

  for (i = 0; i < n && i < maxRec; i++) {
    switch (dataType) {
      case CDF_INT2:
        v[i] = (double) *((Int16 *)pt);
        pt = (Int16 *)pt + 1;
       break;
      case CDF_INT4:
        v[i] = (double) *((Int32 *)pt);
        pt = (Int32 *)pt + 1;
        break;
      case CDF_UINT1:
        v[i] = (double) *((uChar *)pt);
        pt = (uChar *)pt + 1;
        break;
      case CDF_UINT2:
        v[i] = (double) *((uInt16 *)pt);
        pt = (uInt16 *)pt + 1;
        break;
      case CDF_UINT4:
        v[i] = (double) *((uInt32 *)pt);
        pt = (uInt32 *)pt + 1;
        break;
      case CDF_REAL4:
      case CDF_FLOAT:
        v[i] = (double) *((float *)pt);
        pt = (float *)pt + 1;
        break;
      case CDF_REAL8:
      case CDF_DOUBLE: 
        v[i] = (double) *((double *)pt);
        pt = (double *)pt + 1;
       break;
    }
  }


  free(binary);

  status = CDFclose(id);

  return i;
}
Пример #21
0
bool CdfSource::initFile() {
  CDFid id;
  CDFstatus status = CDFopen(_filename.latin1(), &id);
  if (status < CDF_OK) {
    kstdDebug() << _filename << ": failed to open in initFile()" << endl;
    return false;
  }
  // Query field list and store it in _fieldList (plus "INDEX")
  _fieldList.clear();
  //_fieldList += "INDEX"; commented out as it leads to problems in countFrames():
  // which value should the method return when not all variables have the same length ?
  long numRvars = 0, numZvars = 0, varN = 0, numDims = 0, dimSizes[CDF_MAX_DIMS], maxRec = 0;
  char varName[CDF_VAR_NAME_LEN + 1];
  status = CDFlib(SELECT_, 
                     CDF_READONLY_MODE_, READONLYon,
                  GET_,
                     CDF_NUMrVARS_, &numRvars,
                     CDF_NUMzVARS_, &numZvars,
                  NULL_);

  // We accept the following types of fields:
  // - scalars (numDims == 0)
  // - vectors (numDims == 1) of size 1 (dimSizes[0] == 1)
  // - vectors (numDims == 1) of any size, PROVIDED THAT THEY HAVE ONLY 1 RECORD
  // Note that the last case is required by Matlab-generated CDFs, where vectors are stored that way  

  // Add 0-dimensional rVariables 
  for (varN = 0; varN < numRvars; varN++) {
    status = CDFlib(SELECT_,
                       rVAR_, varN,
                    GET_,
                       rVAR_NAME_, varName,
                       rVARs_NUMDIMS_, &numDims,
                       rVARs_DIMSIZES_, dimSizes,
                       rVAR_MAXREC_, &maxRec,
                    NULL_);
    // maxRec is not exactly the number of records :-)
    maxRec += 1;
    if (status == CDF_OK && numDims < 2) {
      if (numDims == 1 && dimSizes[0] > 1 && maxRec > 1) { // Ignore that, this is not really a vector
        kstdDebug() << "Variable " << varName << " can't be handled by kst: only CDF vectors with dimensionalities 0, 1[1] or 1[n] but only one record in the latter case are supported (try cdfexport on your CDF if you have problems)" << endl;
        continue;
      }
      _fieldList += varName;
      if (numDims == 1 && dimSizes[0] > 1) {
        _frameCounts[QString(varName)] = dimSizes[0];
      if ((int) dimSizes[0] > _maxFrameCount) {
        _maxFrameCount = dimSizes[0];
      }
      } else {
        _frameCounts[QString(varName)] = maxRec;
      if ((int) maxRec > _maxFrameCount) {
        _maxFrameCount = maxRec;
      }
      }
    }
  }
  // Add 0-dimensional zVariables 
  for (varN = 0; varN < numZvars; varN++) {
    status = CDFlib(SELECT_,
                       zVAR_, varN,
                    GET_,
                       zVAR_NAME_, varName,
                       zVAR_NUMDIMS_, &numDims,
                       zVAR_DIMSIZES_, dimSizes,
                       zVAR_MAXREC_, &maxRec,
                    NULL_);
    maxRec += 1;
    if (status == CDF_OK && numDims < 2) {
      if (numDims == 1 && dimSizes[0] > 1 && maxRec > 1) { // Ignore that, this is not really a vector
        kstdDebug() << "Variable " << varName << " can't be handled by kst: only CDF vectors with dimensionalities 0, 1[1] or 1[n] but only one record in the latter case are supported (try cdfexport on your CDF if you have problems)" << endl;
        continue;
      }
      _fieldList += varName;
      if (numDims == 1 && dimSizes[0] > 1) {
        _frameCounts[QString(varName)] = dimSizes[0];
      if ((int) dimSizes[0] > _maxFrameCount) {
        _maxFrameCount = dimSizes[0];
      }
      } else {
        _frameCounts[QString(varName)] = maxRec;
      if ((int) maxRec > _maxFrameCount) {
          _maxFrameCount = maxRec;
        }
      }
    }
  }

  // Close the file :-)
  status = CDFclose(id);

  return status >= CDF_OK;
}
bool UpdateThread::doUpdates(bool force, bool *gotData) {
  KstObject::UpdateType U = KstObject::NO_CHANGE;

  _updatedCurves.clear(); // HACK

  if (gotData) {
    *gotData = false;
  }
  
#if UPDATEDEBUG > 0
  if (force) {
    kstdDebug() << "Forced update!" << endl;
  }
#endif

  _updateCounter++;
  if (_updateCounter < 1) {
    _updateCounter = 1; // check for wrap around
  }

#if UPDATEDEBUG > 2
  kstdDebug() << "UPDATE: counter=" << _updateCounter << endl;
#endif

  {
    // Must make a copy to avoid deadlock
    KstBaseCurveList cl;
    KstDataObjectList dol;
    kstObjectSplitList<KstDataObject, KstBaseCurve>(KST::dataObjectList, cl, dol);
    qHeapSort(cl); 
    qHeapSort(dol); 

    // Update all curves
    for (uint i = 0; i < cl.count(); ++i) {
      KstBaseCurvePtr bcp = cl[i];
      bcp->writeLock();
      assert(bcp.data());
#if UPDATEDEBUG > 1
      kstdDebug() << "updating curve: " << (void*)bcp << " - " << bcp->tagName() << endl;
#endif
      KstObject::UpdateType ut = bcp->update(_updateCounter);
      bcp->unlock();

      if (ut == KstObject::UPDATE) { // HACK
        _updatedCurves.append(bcp);
      }

      if (U != KstObject::UPDATE) {
        U = ut;
        if (U == KstObject::UPDATE) {
#if UPDATEDEBUG > 0
          kstdDebug() << "Curve " << bcp->tagName() << " said UPDATE" << endl;
#endif
        }
      }

      if (_done || (_paused && !force)) {
#if UPDATEDEBUG > 1
        kstdDebug() << "5 Returning from scan with U=" << (int)U << endl;
#endif
        return U == KstObject::UPDATE;
      }
    }

    // Update all data objects
    for (uint i = 0; i < dol.count(); ++i) {
      KstDataObjectPtr dp = dol[i];
      dp->writeLock();
      assert(dp.data());
#if UPDATEDEBUG > 1
      kstdDebug() << "updating data object: " << (void*)dp << " - " << dp->tagName() << endl;
#endif
      dp->update(_updateCounter);
      dp->unlock();

      if (_done || (_paused && !force)) {
#if UPDATEDEBUG > 1
        kstdDebug() << "5 Returning from scan with U=" << (int)U << endl;
#endif
        return U == KstObject::UPDATE;
      }
    }
  }

  // Update the files
  if (!_paused) { // don't update even if paused && force
    KST::dataSourceList.lock().readLock();
    unsigned cnt = KST::dataSourceList.count();
    for (uint i = 0; i < cnt; ++i) {
      KstDataSourcePtr dsp = KST::dataSourceList[i];

      dsp->writeLock();
      dsp->update(_updateCounter);
      dsp->unlock();

      if (_done) {
        KST::dataSourceList.lock().unlock();
        return false;
      }
    }
    KST::dataSourceList.lock().unlock();
  }

  if (KstScalar::scalarsDirty()) {
    KstScalar::clearScalarsDirty(); // Must do this first and take a risk of
                                    // falling slightly behind
    KST::scalarList.lock().readLock();
    KstScalarList sl = QDeepCopy<KstScalarList>(KST::scalarList.list()); // avoid deadlock on exit
    KST::scalarList.lock().unlock();
    for (KstScalarList::ConstIterator i = sl.begin(); i != sl.end(); ++i) {
      KstScalarPtr sp = *i;

      sp->writeLock();
      KstObject::UpdateType ut = sp->update(_updateCounter);
      sp->unlock();

      if (ut == KstObject::UPDATE) {
        U = KstObject::UPDATE;
      }

      if (_done) {
        return false;
      }
    }
  }

  if (U == KstObject::UPDATE) {
    kstdDebug() << "Update plots" << endl;
    if (gotData) { // FIXME: do we need to consider all the other exit points?
      *gotData = true;
    }
  }

#if UPDATEDEBUG > 1
  kstdDebug() << "6 Returning from scan with U=" << (int)U << endl;
#endif
  return U == KstObject::UPDATE;
}
Пример #23
0
NADDirectSource::~NADDirectSource() {
  kstdDebug() << "NAD: destructor\n";
  if (_conn) {
    delete _conn;
  }
}
void UpdateThread::run() {
  bool force;
  int  updateTime;

#if UPDATEDEBUG > 0
  kstdDebug() << "Update thread running, tid=" << (int)QThread::currentThread() << endl;
#if UPDATEDEBUG > 2
  kstdDebug() << "dataObjectList lock is at " << (void*)(&KST::dataObjectList.lock()) << endl;
  kstdDebug() << "dataSourceList lock is at " << (void*)(&KST::dataSourceList.lock()) << endl;
#endif
#endif

  _done = false;

  while (!_done) {
    _statusMutex.lock();
    updateTime = _updateTime;
    _statusMutex.unlock();

    if (_waitCondition.wait(_updateTime)) {
#if UPDATEDEBUG > 0
      kstdDebug() << "Update timer " << _updateTime << endl;
#endif
      if (!_force) {
        break;
      }
    }

    _statusMutex.lock();
    if (_done) {
      _statusMutex.unlock();
      break;
    }
    force = _force;
    _force = false;
    _statusMutex.unlock();

    if (_paused && !force) {
#if UPDATEDEBUG > 0
      kstdDebug() << "Update thread paused..." << endl;
#endif
      continue;
    }

    bool gotData = false;
    if (doUpdates(force, &gotData) && !_done) {
#if UPDATEDEBUG > 1
      kstdDebug() << "Update resulted in: TRUE!" << endl;
#endif
      if (gotData) {
        kstdDebug() << "Posting UpdateDataDialogs" << endl;
        ThreadEvent *e = new ThreadEvent(ThreadEvent::UpdateDataDialogs);
        e->_curves = _updatedCurves;
        e->_counter = _updateCounter;
        QApplication::postEvent(_doc, e);
        // this event also triggers an implicit repaint
      } else {
        QApplication::postEvent(_doc, new ThreadEvent(ThreadEvent::Repaint));
      }
      // Wait for UI thread to finish events.  If we don't wait
      // 1: the UI thread could get flooded with events
      // 2: the update thread could change vectors during a paint, causing
      //    inconsistent curves to be plotted ie, the X vector updated
      //    and the Y vector not yet updated...

      // Race warning: Syncronization of updating() is not assured,
      // but updating() will always return a valid answer which was
      // true 'close' to when we asked.  This will safely keep the
      // update thread from over filling the UI thread.  The usleeps
      // will hopefully give the UI thread a chance to set itself...

      usleep(1000); // 1 ms on 2.6 kernel. 10ms on 2.4 kernel

      while (!_done && _doc->updating()) {  // wait for the UI to finish old events
        usleep(1000);
      }
      usleep(1000);
      // check again... not strictly needed given implicit repaint below,
      // but it should just return false, so no harm done.
      while (!_done && _doc->updating()) {
        usleep(1000);
      }
    } else {
      QApplication::postEvent(_doc, new ThreadEvent(ThreadEvent::NoUpdate));
    }
  }

  QApplication::postEvent(_doc, new ThreadEvent(ThreadEvent::Done));
}
Пример #25
0
// if n > 0, read 1 SAMPLE from each of n FRAMES starting at frame s skipping by 'skip' for field into buffer v
// if n < 0, read 1 SAMPLE from frame s for field into buffer v
int NADDirectSource::readField(double *v, const QString& field, int s, int n, int skip, int *lastFrameRead) {
  kstdDebug() << "NAD::readField(" << field << ", s=" + QString::number(s) + ", n=" + QString::number(n) + ", skip=" + QString::number(skip) + ")" << endl;
  if (lastFrameRead) *lastFrameRead = -1;

  if (field == "INDEX") {
    if (n < 0) {
      v[0] = double(s);
      if (lastFrameRead) *lastFrameRead = s;
      return 1;
    }
    for (int i = 0; i < n; ++i) {
      v[i] = double(s + i*skip);
    }
    if (lastFrameRead) *lastFrameRead = s + (n - 1) * skip;
    return n > 0 ? n : 0;
  }

  if (!_valid || !_conn || !_conn->isValid()) {
    kstdDebug() << "tried to read from an invalid NAD source" << endl;
    kstdDebug() << "plugin is valid? " << _valid << endl;
    return -1;
  }

  QSize sz = _conn->range(field);
  long start = sz.width(), end = sz.height();
  long count = end - start + 1;
  int spf = _conn->samplesPerFrame(field);

  if (s + start > end) {
    kstdDebug() << "Nothing to read: (" << start << "," << end << ") " << s << endl;
    return 0;
  }

  if (n < 0) { // reading less than 0 -> read only one sample!
    double *temp = new double[spf];
    _conn->getData(field, temp, start + s, start + s);
    v[0] = temp[0];
    delete[] temp;
    if (lastFrameRead) *lastFrameRead = s;
    return 1;
  } else {
    if (s + (n-1)*skip >= count) { // trying to read past the end
      // n = ceil((count-s)/skip)
      if ((count - s) % skip == 0) {
        n = (count - s) / skip;
      } else {
        n = (count - s) / skip + 1;
      }

      n = count - s;
    }

    double *tmp = new double[n * spf];
//    kstdDebug() << "NAD: calling getData()" << endl;
    int rc = _conn->getData(field, tmp, start + s, start + s + (n - 1) * skip, skip); // get skipped frames
    int framesRead = rc/spf;
    //kstdDebug() << "readObject rc=" << rc << " from=" << start+s << " to=" << start + s + (n - 1) * skip << endl;

    // extract first sample from each returned frame
    int i = 0;
    while (i < QMAX(n, framesRead)) {
      v[i] = tmp[i * spf];
      ++i;
    }
    delete[] tmp;

//    kstdDebug() << "NAD::readField(" << field << ", s=" + QString::number(s) + ", n=" + QString::number(n) + ", skip=" + QString::number(skip) + ") = " << i << endl;
    if (i > 0 && lastFrameRead) {
      *lastFrameRead = s + (i - 1) * skip;
    }
    return i;
  }
}
void KstViewLabel::drawToPainter(Label::Parsed *lp, QPainter& p) {
  int hJust = KST_JUSTIFY_H(_justify);
  if (QApplication::reverseLayout()) {
    if (hJust == KST_JUSTIFY_H_NONE) {
      hJust = KST_JUSTIFY_H_RIGHT;
    }
  } else {
    if (hJust == KST_JUSTIFY_H_NONE) {
      hJust = KST_JUSTIFY_H_LEFT;
    }
  }

  RenderContext rc(_fontName, _absFontSize, &p);
  rc.setSubstituteScalars(_replace);
  rc.precision = _dataPrecision;
  rc._cache = &_cache.data;
  _cache.valid = false;
  _cache.data.clear();
  double rotationRadians = M_PI * (int(_rotation) % 360) / 180;
  double absin = fabs(sin(rotationRadians));
  double abcos = fabs(cos(rotationRadians));

  int tx = 0, ty = 0; // translation
  const QRect cr(contentsRect());

  switch (hJust) {
    case KST_JUSTIFY_H_RIGHT:
      rc.x = -_textWidth / 2;
      tx = cr.width() - int(_textWidth * abcos + _textHeight * absin) / 2 - _labelMargin*_ascent/10;
      break;
    case KST_JUSTIFY_H_CENTER:
      rc.x = -_textWidth / 2;
      tx = cr.width() / 2;
      break;
    case KST_JUSTIFY_H_NONE:
      abort(); // should never be able to happen
    case KST_JUSTIFY_H_LEFT:
    default:
      rc.x = -_textWidth / 2;
      tx = int(_textWidth * abcos + _textHeight * absin) / 2  + _labelMargin*_ascent/10;
      break;
  }

  rc.y = _ascent - _textHeight / 2;
  ty = int(_textHeight * abcos + _textWidth * absin) / 2 + _labelMargin*_ascent/10;

  p.translate(tx, ty);
  p.rotate(_rotation);

  rc.pen = foregroundColor();

  rc.xStart = rc.x;
#ifdef BENCHMARK
  QTime t;
  t.start();
#endif
  if (lp && lp->chunk) {
    renderLabel(rc, lp->chunk, _vectorsUsed, _scalarsUsed, _stringsUsed);
    _cache.valid = true;
  }
#ifdef BENCHMARK
  kstdDebug() << "render took: " << t.elapsed() << endl;
  t.start();
#endif
  QApplication::syncX();
#ifdef BENCHMARK
  kstdDebug() << "sync X took: " << t.elapsed() << endl;
#endif
}
Пример #27
0
KstDataSource *create_naddirect(KConfig *cfg, const QString& filename, const QString& type) {
  kstdDebug() << "in create_naddirect:" << filename << endl;

  return new NADDirectSource(cfg, filename, type);
}
void doTests() {
    // the data file to use.
    // first determine the path used to call this program,
    // and then prepend that to the data file name.
    QString path = myName.section('/', 0, -3);
    QString datafile = path;
    datafile.append("/healpix_example_sm.fits");

    // create a temporary config file to use
    QString cfgfile = "testhealpix.temp";
    KConfig *cfg = new KConfig(cfgfile, false, false);
    cfg->setGroup("Healpix General");
    cfg->setGroup(datafile);
    cfg->writeEntry("Matrix X Dimension", XDIM);
    cfg->writeEntry("Matrix Y Dimension", YDIM);
    cfg->writeEntry("Theta Autoscale", true);
    cfg->writeEntry("Theta Units", 0);
    cfg->writeEntry("Theta Min", 0.0);
    cfg->writeEntry("Theta Max", 1.0);
    cfg->writeEntry("Phi Autoscale", true);
    cfg->writeEntry("Phi Units", 0);
    cfg->writeEntry("Phi Min", 0.0);
    cfg->writeEntry("Phi Max", 1.0);
    cfg->writeEntry("Vector Theta", 1);
    cfg->writeEntry("Vector Phi", 2);
    cfg->writeEntry("Vector Degrade Factor", DEGRADE);
    cfg->writeEntry("Vector Magnitude Autoscale", true);
    cfg->writeEntry("Vector Max Magnitude", 1.0);
    cfg->writeEntry("Vector is QU", true);

    // use the C functions to test for healpix support
    int verstehen = understands_healpix(cfg, datafile);
    if (verstehen) {
        kstdDebug() << "Data file " << datafile << " is supported" << endl;
        QString suggestion;
        bool complete;

        QStringList matrices = matrixList_healpix(cfg, datafile, "HEALPIX", &suggestion, &complete);
        kstdDebug() << "Available matrices are:" << endl;
        for ( QStringList::Iterator it = matrices.begin(); it != matrices.end(); ++it ) {
            kstdDebug() << "  " << *it << endl;
        }
        kstdDebug() << "  suggestion = " << suggestion << endl;
        kstdDebug() << "  complete = " << complete << endl;

        QStringList fields = fieldList_healpix(cfg, datafile, "HEALPIX", &suggestion, &complete);
        kstdDebug() << "Available fields are:" << endl;
        for ( QStringList::Iterator it = fields.begin(); it != fields.end(); ++it ) {
            kstdDebug() << "  " << *it << endl;
        }
        kstdDebug() << "  suggestion = " << suggestion << endl;
        kstdDebug() << "  complete = " << complete << endl;

        // actually create HealpixSource
        HealpixSource *hpx = new HealpixSource(cfg, datafile, "HEALPIX");

        // test that saveConfig produces the same as the
        // original input configuration
        QString cfgfile2 = "testhealpix.temp2";
        KConfig *chk = new KConfig(cfgfile2, false, false);
        hpx->saveConfig(chk);
        StringMap cfgmap = cfg->entryMap(datafile);
        StringMap chkmap = chk->entryMap(datafile);

        /*
        kstdDebug() << cfgmap["Matrix X Dimension"] << " " << chkmap["Matrix X Dimension"] << endl;
        kstdDebug() << cfgmap["Matrix Y Dimension"] << " " << chkmap["Matrix Y Dimension"] << endl;
        kstdDebug() << cfgmap["Theta Autoscale"] << " " << chkmap["Theta Autoscale"] << endl;
        kstdDebug() << cfgmap["Theta Units"] << " " << chkmap["Theta Units"] << endl;
        kstdDebug() << cfgmap["Theta Min"] << " " << chkmap["Theta Min"] << endl;
        kstdDebug() << cfgmap["Theta Max"] << " " << chkmap["Theta Max"] << endl;
        kstdDebug() << cfgmap["Phi Autoscale"] << " " << chkmap["Phi Autoscale"] << endl;
        kstdDebug() << cfgmap["Phi Units"] << " " << chkmap["Phi Units"] << endl;
        kstdDebug() << cfgmap["Phi Min"] << " " << chkmap["Phi Min"] << endl;
        kstdDebug() << cfgmap["Phi Max"] << " " << chkmap["Phi Max"] << endl;
        kstdDebug() << cfgmap["Vector Theta"] << " " << chkmap["Vector Theta"] << endl;
        kstdDebug() << cfgmap["Vector Phi"] << " " << chkmap["Vector Phi"] << endl;
        kstdDebug() << cfgmap["Vector Degrade Factor"] << " " << chkmap["Vector Degrade Factor"] << endl;
        kstdDebug() << cfgmap["Vector Magnitude Autoscale"] << " " << chkmap["Vector Magnitude Autoscale"] << endl;
        kstdDebug() << cfgmap["Vector Max Magnitude"] << " " << chkmap["Vector Max Magnitude"] << endl;
        kstdDebug() << cfgmap["Vector is QU"] << " " << chkmap["Vector is QU"] << endl;
        */

        if (cfgmap["Matrix X Dimension"] != chkmap["Matrix X Dimension"]) {
            QString msg = "Matrix X Dimension integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Matrix Y Dimension"] != chkmap["Matrix Y Dimension"]) {
            QString msg = "Matrix Y Dimension integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Theta Autoscale"] != chkmap["Theta Autoscale"]) {
            QString msg = "Theta Autoscale integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Theta Units"] != chkmap["Theta Units"]) {
            QString msg = "Theta Units integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Theta Min"] != chkmap["Theta Min"]) {
            QString msg = "Theta Min integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Theta Max"] != chkmap["Theta Max"]) {
            QString msg = "Theta Max integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Phi Autoscale"] != chkmap["Phi Autoscale"]) {
            QString msg = "Phi Autoscale integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Phi Units"] != chkmap["Phi Units"]) {
            QString msg = "Phi Units integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Phi Min"] != chkmap["Phi Min"]) {
            QString msg = "Phi Min integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Phi Max"] != chkmap["Phi Max"]) {
            QString msg = "Phi Max integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector Theta"] != chkmap["Vector Theta"]) {
            QString msg = "Vector Theta integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector Phi"] != chkmap["Vector Phi"]) {
            QString msg = "Vector Phi integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector Degrade Factor"] != chkmap["Vector Degrade Factor"]) {
            QString msg = "Vector Degrade Factor integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector Magnitude Autoscale"] != chkmap["Vector Magnitude Autoscale"]) {
            QString msg = "Vector Magnitude Autoscale integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector Max Magnitude"] != chkmap["Vector Max Magnitude"]) {
            QString msg = "Vector Max Magnitude integrity";
            testAssert(false, msg);
        }
        if (cfgmap["Vector is QU"] != chkmap["Vector is QU"]) {
            QString msg = "Vector is QU integrity";
            testAssert(false, msg);
        }
        kstdDebug() << "Save/Load config is consistent." << endl;

        // print _metaData and compute NSIDE and number
        // of samples in the vectors
        int nside = 0;
        int nvec;
        QString key;
        KstString *data;
        kstdDebug() << "Checking metaData:" << endl;
        QDict<KstString> metamap = hpx->metaData();
        QDictIterator<KstString> it(metamap);
        for ( ; it.current(); ++it ) {
            key = it.currentKey();
            data = it.current();
            if (data) {
                kstdDebug() << "  " << key.latin1() << " = " << data->value().latin1() << endl;
                if (key == "NSIDE") {
                    nside = data->value().toInt();
                }
            }
        }
        kstdDebug() << "Data file has nside = " << nside << endl;
        testAssert(nside != 0, "data file NSIDE");
        for (int i = 0; i < DEGRADE; i++) {
            nside = (int)(nside/2);
        }
        nvec = 12*nside*nside;
        kstdDebug() << "Degraded vectorfield has nside = " << nside << " and " << nvec << " full-sphere pixels" << endl;

        // check that all returned fields are valid, and that
        // optionally field number names are valid.
        kstdDebug() << "Checking matrix validity:" << endl;
        int num = 1;
        int xdim, ydim, nframe, sampframe;
        for ( QStringList::Iterator it = matrices.begin(); it != matrices.end(); ++it ) {
            if (hpx->isValidMatrix(*it)) {
                kstdDebug() << "  \"" << *it << "\" is VALID" << endl;
                hpx->matrixDimensions(*it, &xdim, &ydim);
                kstdDebug() << "    and has dimensions " << xdim << "x" << ydim << endl;
                testAssert((xdim == XDIM)&&(ydim == YDIM), "dimension integrity");
            } else {
                QString msg = (*it);
                msg.append(" validity");
                testAssert(false, msg);
            }
            QString numfield = QString("%1").arg(num);
            if (hpx->isValidMatrix(numfield)) {
                kstdDebug() << "  \"" << numfield << "\" is VALID" << endl;
                hpx->matrixDimensions(numfield, &xdim, &ydim);
                kstdDebug() << "    and has dimensions " << xdim << "x" << ydim << endl;
                testAssert((xdim == XDIM)&&(ydim == YDIM), "dimension integrity");
            } else {
                QString msg = numfield;
                msg.append(" validity");
                testAssert(false, msg);
            }
            num++;
        }
        kstdDebug() << "Checking field validity:" << endl;
        num = 1;
        for ( QStringList::Iterator it = fields.begin(); it != fields.end(); ++it ) {
            if (hpx->isValidField(*it)) {
                kstdDebug() << "  \"" << *it << "\" is VALID" << endl;
                nframe = hpx->frameCount(*it);
                sampframe = hpx->samplesPerFrame(*it);
                kstdDebug() << "    and has " << nframe << " frames of " << sampframe << " sample(s) each" << endl;
                testAssert(sampframe == 1, "samples per frame");
                testAssert(nframe == nvec, "number of frames");
            } else {
                QString msg = (*it);
                msg.append(" validity");
                testAssert(false, msg);
            }
            QString numfield = QString("%1").arg(num);
            if (hpx->isValidField(numfield)) {
                kstdDebug() << "  \"" << numfield << "\" is VALID" << endl;
                nframe = hpx->frameCount(numfield);
                sampframe = hpx->samplesPerFrame(numfield);
                kstdDebug() << "    and has " << nframe << " frames of " << sampframe << " sample(s) each" << endl;
                testAssert(sampframe == 1, "samples per frame");
                testAssert(nframe == nvec, "number of frames");
            } else {
                QString msg = numfield;
                msg.append(" validity");
                testAssert(false, msg);
            }
            num++;
        }

        // check reset function
        if (hpx->reset()) {
            kstdDebug() << "Reset function is implemented." << endl;
        } else {
            testAssert(false, "reset");
        }




    } else {
        testAssert(false, "understanding");
    }

}