File indexing completed on 2024-12-29 04:11:47

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2015 C. Barth Netterfield
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 
0013 #include "itsdatasource.h"
0014 #include "datamatrix.h"
0015 #include "its.h"
0016 
0017 #include <QFileInfo>
0018 
0019 #define MAX_IMAGES 16
0020 
0021 using namespace Kst;
0022 
0023 static const QString ITSTypeString = "Indexed Thumbnail Stream";
0024 
0025 
0026 /**********************
0027 ITSSource::Config - default config widget.  Not used.
0028 
0029 ***********************/
0030 class ITSSource::Config {
0031   public:
0032     Config() {
0033     }
0034 
0035     void read(QSettings *cfg, const QString& fileName = QString()) {
0036       Q_UNUSED(fileName);
0037       cfg->beginGroup(ITSTypeString);
0038       cfg->endGroup();
0039     }
0040 
0041     void save(QXmlStreamWriter& s) {
0042       Q_UNUSED(s);
0043     }
0044 
0045     void load(const QDomElement& e) {
0046       Q_UNUSED(e);
0047     }
0048 };
0049 
0050 
0051 //
0052 // Matrix interface
0053 //
0054 
0055 class DataInterfaceITSMatrix : public DataSource::DataInterface<DataMatrix>
0056 {
0057 public:
0058 
0059   DataInterfaceITSMatrix(ITSSource& its) : _its(its) {}
0060 
0061   // read one element
0062   int read(const QString&, DataMatrix::ReadInfo&);
0063 
0064   // named elements
0065   QStringList list() const { return _its._matrixNames.keys(); }
0066   bool isListComplete() const { return true; }
0067   bool isValid(const QString&) const;
0068 
0069   // T specific
0070   const DataMatrix::DataInfo dataInfo(const QString&, int frame=0) const;
0071   void setDataInfo(const QString&, const DataMatrix::DataInfo&) {}
0072 
0073   // meta data
0074   QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); }
0075   QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); }
0076 
0077 
0078   // no interface
0079   ITSSource& _its;
0080 
0081   void init();
0082   void clear();
0083 };
0084 
0085 void DataInterfaceITSMatrix::clear()
0086 {
0087 }
0088 
0089 void DataInterfaceITSMatrix::init()
0090 {
0091 }
0092 
0093 
0094 
0095 const DataMatrix::DataInfo DataInterfaceITSMatrix::dataInfo(const QString& matrix, int frame) const
0096 {
0097   if (_its._itsfile->status != ITS_OK) {
0098     return DataMatrix::DataInfo();
0099   }
0100 
0101   DataMatrix::DataInfo info;
0102 
0103   if (!_its._matrixNames.contains(matrix)) {
0104     return DataMatrix::DataInfo();
0105   }
0106 
0107   info.frameCount = ITSnframes(_its._itsfile);
0108   if (frame>=info.frameCount) {
0109     return DataMatrix::DataInfo();
0110   }
0111 
0112   int i_img = _its._matrixNames[matrix];
0113   ITSreadimage(_its._itsfile, frame, i_img, &_its._itsImage);
0114 
0115   info.xSize = _its._itsImage.w;
0116   info.ySize = _its._itsImage.h;
0117   info.invertXHint = false;
0118   info.invertYHint = false;
0119 
0120   return info;
0121 }
0122 
0123 
0124 int DataInterfaceITSMatrix::read(const QString& field, DataMatrix::ReadInfo& p)
0125 {
0126 
0127   int y0 = p.yStart;
0128   int y1 = p.yStart + p.yNumSteps;
0129   int x0 = p.xStart;
0130   int x1 = p.xStart + p.xNumSteps;
0131   int w;
0132   double* z = p.data->z;
0133   int frame = p.frame;
0134 
0135   /* verify validity */
0136   if (_its._itsfile->status != ITS_OK) {
0137     return 0;
0138   }
0139   if (!_its._matrixNames.contains(field)) {
0140     return 0;
0141   }
0142 
0143   /* read the ITSimage */
0144   int i_img = _its._matrixNames[field];
0145   ITSreadimage(_its._itsfile, frame, i_img, &_its._itsImage);
0146   w = _its._itsImage.w;
0147   x1 = qMin(x1, w);
0148   y1 = qMin((unsigned short)y1, _its._itsImage.h);
0149 
0150   /* copy the image */
0151   int i = 0;
0152   for (int px = x0; px<x1; ++px ) {
0153     for (int py=y1-1; py>=y0; --py ) {
0154       z[i] = _its._itsImage.img[px + py*w];
0155       ++i;
0156     }
0157   }
0158 
0159   // set the suggested matrix transform params: pixel index....
0160   p.data->xMin = x0;
0161   p.data->yMin = y0;
0162   p.data->xStepSize = 1;
0163   p.data->yStepSize = 1;
0164 
0165   return i;
0166 }
0167 
0168 
0169 bool DataInterfaceITSMatrix::isValid(const QString& field) const {
0170   return  _its._matrixNames.keys().contains( field );
0171 }
0172 
0173 
0174 //
0175 // Vector interface
0176 //
0177 
0178 class DataInterfaceITSVector : public DataSource::DataInterface<DataVector>
0179 {
0180 public:
0181 
0182   DataInterfaceITSVector(ITSSource& its) : _its(its) {}
0183 
0184   // read one element
0185   int read(const QString&, DataVector::ReadInfo&);
0186 
0187   // named elements
0188   QStringList list() const { return _its._vectorList; }
0189   bool isListComplete() const { return true; }
0190   bool isValid(const QString&) const;
0191 
0192   // T specific
0193   const DataVector::DataInfo dataInfo(const QString&, int frame=0) const;
0194   void setDataInfo(const QString&, const DataVector::DataInfo&) {}
0195 
0196   // meta data
0197   QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); }
0198   QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); }
0199 
0200 
0201   ITSSource& _its;
0202 
0203   void init();
0204   void clear();
0205 };
0206 
0207 void DataInterfaceITSVector::clear()
0208 {
0209 }
0210 
0211 void DataInterfaceITSVector::init()
0212 {
0213 }
0214 
0215 
0216 
0217 const DataVector::DataInfo DataInterfaceITSVector::dataInfo(const QString& vector, int) const
0218 {
0219   if (_its._itsfile->status != ITS_OK) {
0220     return DataVector::DataInfo();
0221   }
0222 
0223   if (!_its._vectorList.contains(vector)) {
0224     return DataVector::DataInfo();
0225   }
0226 
0227   return DataVector::DataInfo(_its._nframes, 1);
0228 }
0229 
0230 
0231 int DataInterfaceITSVector::read(const QString& field, DataVector::ReadInfo& p)
0232 {
0233 
0234   int f0 = p.startingFrame;
0235   int nr = p.numberOfFrames;
0236   int nf = _its._nframes;
0237 
0238   if (f0>nf) {
0239     return 0;
0240   }
0241 
0242   if (f0 + nr > nf) {
0243     nr = nf - f0;
0244   }
0245 
0246   if (!_its._vectorList.contains(field)) {
0247     return 0;
0248   }
0249 
0250   if ( field=="INDEX" ) {
0251     for (int i=0; i<nr; ++i ) {
0252       p.data[i] = i + f0;
0253     }
0254     return nr;
0255   }
0256 
0257   return 0;
0258 }
0259 
0260 
0261 bool DataInterfaceITSVector::isValid(const QString& field) const {
0262   return  _its._vectorList.contains( field );
0263 }
0264 
0265 
0266 /**********************
0267 ITSSource - the reader for streams of images developed for the Spider telescope.
0268 
0269 ***********************/
0270 ITSSource::ITSSource(Kst::ObjectStore *store, QSettings *cfg, const QString& filename, const QString& type, const QDomElement& e)
0271 : Kst::DataSource(store, cfg, filename, type), _config(0L),
0272  im(new DataInterfaceITSMatrix(*this)), iv(new DataInterfaceITSVector(*this)),_itsfile(0), _nframes(0)
0273 {
0274 
0275   _updateCheckType = None;
0276 
0277   ITSInitImage(&_itsImage);
0278 
0279   setInterface(im);
0280   setInterface(iv);
0281 
0282   startUpdating(None);
0283 
0284   _valid = false;
0285   if (!type.isEmpty() && type != ITSTypeString) {
0286     return;
0287   }
0288 
0289   _config = new ITSSource::Config;
0290   _config->read(cfg, filename);
0291   if (!e.isNull()) {
0292     _config->load(e);
0293   }
0294 
0295   if (init()) {
0296     _valid = true;
0297   }
0298 
0299   registerChange();
0300 }
0301 
0302 
0303 
0304 ITSSource::~ITSSource() {
0305   ITSFreeImage(&_itsImage);
0306   ITSclose(_itsfile);
0307   if (_config) {
0308     delete _config;
0309   }
0310 }
0311 
0312 
0313 void ITSSource::reset() {
0314   if (_itsfile) {
0315     ITSclose(_itsfile);
0316   }
0317   _nframes = 0;
0318   _valid = false;
0319   if (init()) {
0320     _valid = true;
0321   }
0322   Object::reset();
0323 }
0324 
0325 
0326 // If the datasource has any predefined fields they should be populated here.
0327 bool ITSSource::init() {
0328 
0329 
0330   _itsfile = ITSopen(_filename.toAscii().data());
0331   if (_itsfile->status != ITS_OK) {
0332     ITSclose(_itsfile);
0333     _nframes = 0;
0334     _itsfile = 0;
0335     return false;
0336   }
0337 
0338   _matrixNames.clear();
0339 
0340   for (int i=0; i < MAX_IMAGES; i++) {
0341     _matrixNames[QString("IMG%1").arg(int(i+1), 2, 10, QLatin1Char('0'))] = i;
0342   }
0343 
0344   _vectorList.clear();
0345   _vectorList.append("INDEX");
0346 
0347   _nframes = ITSnframes(_itsfile);
0348 
0349   _updateCheckType = Timer;
0350 
0351   registerChange();
0352   return true; // false if something went wrong
0353 }
0354 
0355 
0356 // Check if the data in the source has updated.  Typically done by checking the frame count of the datasource for
0357 // changes.
0358 Kst::Object::UpdateType ITSSource::internalDataSourceUpdate() {
0359   
0360   if (_valid) {
0361     int newNF = ITSnframes(_itsfile);
0362     bool isnew = newNF != _nframes;
0363 
0364     if (_nframes>newNF) {
0365       reset();
0366     }
0367 
0368     _nframes = newNF;
0369 
0370     return (isnew ? Updated : NoChange);
0371   }
0372 
0373   return Kst::Object::NoChange;
0374 }
0375 
0376 
0377 // TODO a DataSource::DataInterface implementation as example
0378 
0379 QString ITSSource::fileType() const {
0380   return ITSTypeString;
0381 }
0382 
0383 
0384 void ITSSource::save(QXmlStreamWriter &streamWriter) {
0385   Kst::DataSource::save(streamWriter);
0386 }
0387 
0388 
0389 // Name used to identify the plugin.  Used when loading the plugin.
0390 QString ITSSourcePlugin::pluginName() const { return tr("Indexed Thumbnail Stream Reader"); }
0391 QString ITSSourcePlugin::pluginDescription() const { return tr("Indexed Thumbnail Stream Reader"); }
0392 
0393 /**********************
0394 ITSSourcePlugin - This class defines the plugin interface to the DataSource defined by the plugin.
0395 The primary requirements of this class are to provide the necessary connections to create the object
0396 which includes providing access to the configuration widget.
0397 
0398 ***********************/
0399 
0400 Kst::DataSource *ITSSourcePlugin::create(Kst::ObjectStore *store,
0401                                             QSettings *cfg,
0402                                             const QString &filename,
0403                                             const QString &type,
0404                                             const QDomElement &element) const {
0405 
0406   return new ITSSource(store, cfg, filename, type, element);
0407 }
0408 
0409 
0410 // Provides the matrix list that this dataSource can provide from the provided filename.
0411 // This function should use understands to validate the file and then open and calculate the 
0412 // list of matrices.
0413 QStringList ITSSourcePlugin::matrixList(QSettings *cfg,
0414                                              const QString& filename,
0415                                              const QString& type,
0416                                              QString *typeSuggestion,
0417                                              bool *complete) const {
0418 
0419 
0420   if (typeSuggestion) {
0421     *typeSuggestion = ITSTypeString;
0422   }
0423   if ((!type.isEmpty() && !provides().contains(type)) ||
0424       0 == understands(cfg, filename)) {
0425     if (complete) {
0426       *complete = false;
0427     }
0428     return QStringList();
0429   }
0430   QStringList matrixList;
0431 
0432   matrixList += "IMG1";
0433   matrixList += "IMG2";
0434   matrixList += "IMG3";
0435   matrixList += "IMG4";
0436   matrixList += "IMG5";
0437 
0438   return matrixList;
0439 
0440 }
0441 
0442 
0443 // Provides the scalar list that this dataSource can provide from the provided filename.
0444 // This function should use understands to validate the file and then open and calculate the 
0445 // list of scalars if necessary.
0446 QStringList ITSSourcePlugin::scalarList(QSettings *cfg,
0447                                             const QString& filename,
0448                                             const QString& type,
0449                                             QString *typeSuggestion,
0450                                             bool *complete) const {
0451 
0452   QStringList scalarList;
0453 
0454   if ((!type.isEmpty() && !provides().contains(type)) || 0 == understands(cfg, filename)) {
0455     if (complete) {
0456       *complete = false;
0457     }
0458     return QStringList();
0459   }
0460 
0461   if (typeSuggestion) {
0462     *typeSuggestion = ITSTypeString;
0463   }
0464 
0465   //scalarList.append("FRAMES");
0466   return scalarList;
0467 
0468 }
0469 
0470 
0471 // Provides the string list that this dataSource can provide from the provided filename.
0472 // This function should use understands to validate the file and then open and calculate the 
0473 // list of strings if necessary.
0474 QStringList ITSSourcePlugin::stringList(QSettings *cfg,
0475                                       const QString& filename,
0476                                       const QString& type,
0477                                       QString *typeSuggestion,
0478                                       bool *complete) const {
0479 
0480   QStringList stringList;
0481 
0482   if ((!type.isEmpty() && !provides().contains(type)) || 0 == understands(cfg, filename)) {
0483     if (complete) {
0484       *complete = false;
0485     }
0486     return QStringList();
0487   }
0488 
0489   if (typeSuggestion) {
0490     *typeSuggestion = ITSTypeString;
0491   }
0492 
0493   //stringList.append("FILENAME");
0494   return stringList;
0495 
0496 }
0497 
0498 
0499 // Provides the field list that this dataSource can provide from the provided filename.
0500 // This function should use understands to validate the file and then open and calculate the 
0501 // list of fields if necessary.
0502 QStringList ITSSourcePlugin::fieldList(QSettings *cfg,
0503                                             const QString& filename,
0504                                             const QString& type,
0505                                             QString *typeSuggestion,
0506                                             bool *complete) const {  
0507   if (typeSuggestion) {
0508     *typeSuggestion = ITSTypeString;
0509   }
0510   if ((!type.isEmpty() && !provides().contains(type)) ||
0511       0 == understands(cfg, filename)) {
0512     if (complete) {
0513       *complete = false;
0514     }
0515     return QStringList();
0516   }
0517 
0518   if (complete) {
0519     *complete = true;
0520   }
0521 
0522   if (typeSuggestion) {
0523     *typeSuggestion = ITSTypeString;
0524   }
0525 
0526   QStringList fieldList;
0527 
0528   fieldList.append("INDEX");
0529   return fieldList;
0530 }
0531 
0532 
0533 // The main function used to determine if this plugin knows how to process the provided file.
0534 // Each datasource plugin should check the file and return a number between 0 and 100 based 
0535 // on the likelyhood of the file being this type.  100 should only be returned if there is no way
0536 // that the file could be any datasource other than this one.
0537 int ITSSourcePlugin::understands(QSettings *cfg, const QString& filename) const {
0538   Q_UNUSED(cfg)
0539 
0540   if (!QFile::exists(filename) || QFileInfo(filename).isDir()) {
0541     return 0;
0542   }
0543 
0544   if (isITSfile(filename.toAscii().data())) {
0545     return (99);
0546   }
0547   return 0;
0548 }
0549 
0550 
0551 bool ITSSourcePlugin::supportsTime(QSettings *cfg, const QString& filename) const {
0552   //FIXME
0553   Q_UNUSED(cfg)
0554   Q_UNUSED(filename)
0555   return false;
0556 }
0557 
0558 
0559 QStringList ITSSourcePlugin::provides() const {
0560   QStringList rc;
0561   rc += ITSTypeString;
0562   return rc;
0563 }
0564 
0565 
0566 // Request for this plugins configuration widget.  
0567 Kst::DataSourceConfigWidget *ITSSourcePlugin::configWidget(QSettings *cfg, const QString& filename) const {
0568   Q_UNUSED(cfg)
0569   Q_UNUSED(filename)
0570   return 0;;
0571 
0572 }
0573 
0574 #ifndef QT5
0575 Q_EXPORT_PLUGIN2(kstdata_itssource, ITSSourcePlugin)
0576 #endif
0577 
0578 // vim: ts=2 sw=2 et