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

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