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