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