File indexing completed on 2024-12-22 03:35:45
0001 /* 0002 File : HDF5Filter.cpp 0003 Project : LabPlot 0004 Description : HDF5 I/O-filter 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2015-2022 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 SPDX-FileCopyrightText: 2017 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 /* TODO: 0012 * Feature: implement missing data types and ranks 0013 * Performance: only fill dataPointer or dataStrings (not both) 0014 */ 0015 0016 #include "backend/datasources/filters/HDF5Filter.h" 0017 #include "backend/core/column/Column.h" 0018 #include "backend/datasources/LiveDataSource.h" 0019 #include "backend/datasources/filters/HDF5FilterPrivate.h" 0020 #include "backend/lib/XmlStreamReader.h" 0021 #include "backend/lib/macros.h" 0022 0023 #include <KLocalizedString> 0024 #include <QFile> 0025 #include <QProcess> 0026 #include <QStandardPaths> 0027 #include <QTreeWidgetItem> 0028 0029 ///////////// macros /////////////////////////////////////////////// 0030 // type - data type 0031 #define HDF5_READ_1D(type) \ 0032 { \ 0033 for (int i = startRow - 1; i < std::min(endRow, lines + startRow - 1); ++i) { \ 0034 if (dataContainer) \ 0035 (*static_cast<QVector<type>*>(dataContainer))[i - startRow + 1] = data[i]; \ 0036 else /* for preview */ \ 0037 dataString << QString::number(static_cast<type>(data[i])); \ 0038 } \ 0039 } 0040 // type - data type, ctype - container type 0041 #define HDF5_READ_VLEN_1D(type, ctype) \ 0042 { \ 0043 auto* data = (type*)rdata[c].p; \ 0044 for (int i = startRow - 1; i < std::min(length, lines + startRow - 1); ++i) { \ 0045 if (dataSource) \ 0046 (*static_cast<QVector<ctype>*>(dataContainer[c - startColumn + 1]))[i - startRow + 1] = data[i]; \ 0047 else /* for preview */ \ 0048 dataStrings[i - startRow + 1] << QString::number(static_cast<type>(data[i])); \ 0049 } \ 0050 /* fill columns until maxLength */ \ 0051 if (!dataSource) \ 0052 for (int i = std::min(length, lines + startRow - 1); i < std::min(endRow, lines + startRow - 1); i++) { \ 0053 dataStrings[i - startRow + 1] << QString(); \ 0054 } \ 0055 } 0056 0057 // type - data type 0058 #define HDF5_READ_2D(type) \ 0059 { \ 0060 for (int i = startRow - 1; i < std::min(endRow, lines + startRow - 1); ++i) { \ 0061 QStringList line; \ 0062 line.reserve(endColumn - startColumn + 1); \ 0063 for (int j = startColumn - 1; j < endColumn; ++j) { \ 0064 if (dataPointer[0]) \ 0065 (*static_cast<QVector<type>*>(dataPointer[j - startColumn + 1]))[i - startRow + 1] = data[i][j]; \ 0066 else \ 0067 line << QString::number(static_cast<type>(data[i][j])); \ 0068 } \ 0069 dataStrings << line; \ 0070 } \ 0071 } 0072 0073 ////////////////////////////////////////////////////////////////////// 0074 0075 /*! 0076 \class HDF5Filter 0077 \brief Manages the import/export of data from/to a HDF5 file. 0078 0079 \ingroup datasources 0080 */ 0081 HDF5Filter::HDF5Filter() 0082 : AbstractFileFilter(FileType::HDF5) 0083 , d(new HDF5FilterPrivate(this)) { 0084 } 0085 0086 HDF5Filter::~HDF5Filter() = default; 0087 0088 /*! 0089 parses the content of the file \c fileName. 0090 */ 0091 int HDF5Filter::parse(const QString& fileName, QTreeWidgetItem* rootItem) { 0092 return d->parse(fileName, rootItem); 0093 } 0094 0095 /*! 0096 reads the content of the data set \c dataSet from file \c fileName. 0097 */ 0098 QVector<QStringList> 0099 HDF5Filter::readCurrentDataSet(const QString& fileName, AbstractDataSource* dataSource, bool& ok, AbstractFileFilter::ImportMode importMode, int lines) { 0100 return d->readCurrentDataSet(fileName, dataSource, ok, importMode, lines); 0101 } 0102 0103 /*! 0104 reads the content of the file \c fileName to the data source \c dataSource. 0105 */ 0106 void HDF5Filter::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode mode) { 0107 d->readDataFromFile(fileName, dataSource, mode); 0108 } 0109 0110 /*! 0111 writes the content of the data source \c dataSource to the file \c fileName. 0112 */ 0113 void HDF5Filter::write(const QString& fileName, AbstractDataSource* dataSource) { 0114 d->write(fileName, dataSource); 0115 } 0116 0117 /////////////////////////////////////////////////////////////////////// 0118 0119 void HDF5Filter::setCurrentDataSetName(const QString& ds) { 0120 DEBUG(Q_FUNC_INFO << ", name = " << STDSTRING(ds)) 0121 d->currentDataSetName = ds; 0122 } 0123 0124 const QString HDF5Filter::currentDataSetName() const { 0125 return d->currentDataSetName; 0126 } 0127 0128 void HDF5Filter::setStartRow(const int s) { 0129 d->startRow = s; 0130 } 0131 0132 int HDF5Filter::startRow() const { 0133 return d->startRow; 0134 } 0135 0136 void HDF5Filter::setEndRow(const int e) { 0137 d->endRow = e; 0138 } 0139 0140 int HDF5Filter::endRow() const { 0141 return d->endRow; 0142 } 0143 0144 void HDF5Filter::setStartColumn(const int c) { 0145 d->startColumn = c; 0146 } 0147 0148 int HDF5Filter::startColumn() const { 0149 return d->startColumn; 0150 } 0151 0152 void HDF5Filter::setEndColumn(const int c) { 0153 d->endColumn = c; 0154 } 0155 0156 int HDF5Filter::endColumn() const { 0157 return d->endColumn; 0158 } 0159 0160 QString HDF5Filter::fileInfoString(const QString& fileName) { 0161 DEBUG(Q_FUNC_INFO); 0162 QString info; 0163 #ifdef HAVE_HDF5 0164 DEBUG(Q_FUNC_INFO << ", fileName = " << qPrintable(fileName)); 0165 0166 // check file type first 0167 htri_t isHdf5 = H5Fis_hdf5(qPrintable(fileName)); 0168 if (isHdf5 == 0) { 0169 DEBUG(qPrintable(fileName) << " is not a HDF5 file! isHdf5 = " << isHdf5 << " Giving up."); 0170 return i18n("Not a HDF5 file"); 0171 } 0172 if (isHdf5 < 0) { 0173 DEBUG("H5Fis_hdf5() failed on " << qPrintable(fileName) << "! Giving up."); 0174 return i18n("Failed checking file"); 0175 } 0176 0177 // open file 0178 hid_t file = H5Fopen(qPrintable(fileName), H5F_ACC_RDONLY, H5P_DEFAULT); 0179 HDF5FilterPrivate::handleError((int)file, QStringLiteral("H5Fopen"), fileName); 0180 if (file < 0) { 0181 DEBUG("Opening file " << qPrintable(fileName) << " failed! Giving up."); 0182 return i18n("Failed opening HDF5 file"); 0183 } 0184 0185 hsize_t size; 0186 herr_t status = H5Fget_filesize(file, &size); 0187 if (status >= 0) { 0188 info += i18n("File size: %1 bytes", QString::number(size)); 0189 info += QLatin1String("<br>"); 0190 } 0191 0192 hssize_t freesize = H5Fget_freespace(file); 0193 info += i18n("Free space: %1 bytes", QString::number(freesize)); 0194 info += QLatin1String("<br>"); 0195 info += QLatin1String("<br>"); 0196 0197 ssize_t objectCount; 0198 objectCount = H5Fget_obj_count(file, H5F_OBJ_FILE); 0199 info += i18n("Number of files: %1", QString::number(objectCount)); 0200 info += QLatin1String("<br>"); 0201 objectCount = H5Fget_obj_count(file, H5F_OBJ_DATASET); 0202 info += i18n("Number of data sets: %1", QString::number(objectCount)); 0203 info += QLatin1String("<br>"); 0204 objectCount = H5Fget_obj_count(file, H5F_OBJ_GROUP); 0205 info += i18n("Number of groups: %1", QString::number(objectCount)); 0206 info += QLatin1String("<br>"); 0207 objectCount = H5Fget_obj_count(file, H5F_OBJ_DATATYPE); 0208 info += i18n("Number of named datatypes: %1", QString::number(objectCount)); 0209 info += QLatin1String("<br>"); 0210 objectCount = H5Fget_obj_count(file, H5F_OBJ_ATTR); 0211 info += i18n("Number of attributes: %1", QString::number(objectCount)); 0212 info += QLatin1String("<br>"); 0213 objectCount = H5Fget_obj_count(file, H5F_OBJ_ALL); 0214 info += i18n("Number of all objects: %1", QString::number(objectCount)); 0215 info += QLatin1String("<br>"); 0216 0217 #ifdef HAVE_AT_LEAST_HDF5_1_10_0 // using H5Fget_info2 struct (see H5Fpublic.h) 0218 H5F_info2_t file_info; 0219 status = H5Fget_info2(file, &file_info); 0220 if (status >= 0) { 0221 info += QLatin1String("<br>"); 0222 info += i18n("Version of superblock: %1", QString::number(file_info.super.version)); 0223 info += QLatin1String("<br>"); 0224 info += i18n("Size of superblock: %1 bytes", QString::number(file_info.super.super_size)); 0225 info += QLatin1String("<br>"); 0226 info += i18n("Size of superblock extension: %1 bytes", QString::number(file_info.super.super_ext_size)); 0227 info += QLatin1String("<br>"); 0228 info += i18n("Version of free-space manager: %1", QString::number(file_info.free.version)); 0229 info += QLatin1String("<br>"); 0230 info += i18n("Size of free-space manager metadata: %1 bytes", QString::number(file_info.free.meta_size)); 0231 info += QLatin1String("<br>"); 0232 info += i18n("Total size of free space: %1 bytes", QString::number(file_info.free.tot_space)); 0233 info += QLatin1String("<br>"); 0234 info += i18n("Version of shared object header: %1", QString::number(file_info.sohm.version)); 0235 info += QLatin1String("<br>"); 0236 info += i18n("Size of shared object header: %1 bytes", QString::number(file_info.sohm.hdr_size)); 0237 info += QLatin1String("<br>"); 0238 info += i18n("Size of all shared object header indexes: %1 bytes", QString::number(file_info.sohm.msgs_info.index_size)); 0239 info += QLatin1String("<br>"); 0240 info += i18n("Size of the heap: %1 bytes", QString::number(file_info.sohm.msgs_info.heap_size)); 0241 info += QLatin1String("<br>"); 0242 } 0243 #else // using H5Fget_info1 struct (named H5F_info_t in HDF5 1.8) 0244 H5F_info_t file_info; 0245 status = H5Fget_info(file, &file_info); 0246 if (status >= 0) { 0247 info += i18n("Size of superblock extension: %1 bytes", QString::number(file_info.super_ext_size)); 0248 info += QLatin1String("<br>"); 0249 info += i18n("Size of shared object header: %1 bytes", QString::number(file_info.sohm.hdr_size)); 0250 info += QLatin1String("<br>"); 0251 info += i18n("Size of all shared object header indexes: %1 bytes", QString::number(file_info.sohm.msgs_info.index_size)); 0252 info += QLatin1String("<br>"); 0253 info += i18n("Size of the heap: %1 bytes", QString::number(file_info.sohm.msgs_info.heap_size)); 0254 info += QLatin1String("<br>"); 0255 } 0256 #endif 0257 0258 // cache information 0259 // see https://support.hdfgroup.org/HDF5/doc/RM/RM_H5F.html 0260 info += QLatin1String("<br>"); 0261 H5AC_cache_config_t config; 0262 config.version = H5AC__CURR_CACHE_CONFIG_VERSION; 0263 status = H5Fget_mdc_config(file, &config); 0264 if (status >= 0) { 0265 info += i18n("Cache config version: %1", QString::number(config.version)); 0266 info += QLatin1String("<br>"); 0267 info += i18n("Adaptive cache resize report function enabled: %1", config.rpt_fcn_enabled ? i18n("Yes") : i18n("No")); 0268 info += QLatin1String("<br>"); 0269 info += i18n("Cache initial maximum size: %1 bytes", QString::number(config.initial_size)); 0270 info += QLatin1String("<br>"); 0271 info += i18n("Adaptive cache maximum size: %1 bytes", QString::number(config.max_size)); 0272 info += QLatin1String("<br>"); 0273 info += i18n("Adaptive cache minimum size: %1 bytes", QString::number(config.min_size)); 0274 info += QLatin1String("<br>"); 0275 // TODO: more settings 0276 } 0277 double hit_rate; 0278 status = H5Fget_mdc_hit_rate(file, &hit_rate); 0279 info += i18n("Metadata cache hit rate: %1", QString::number(hit_rate)); 0280 info += QLatin1String("<br>"); 0281 // TODO: herr_t H5Fget_mdc_image_info(hid_t file_id, haddr_t *image_addr, hsize_t *image_len) 0282 size_t max_size, min_clean_size, cur_size; 0283 int cur_num_entries; 0284 status = H5Fget_mdc_size(file, &max_size, &min_clean_size, &cur_size, &cur_num_entries); 0285 if (status >= 0) { 0286 info += i18n("Current cache maximum size: %1 bytes", QString::number(max_size)); 0287 info += QLatin1String("<br>"); 0288 info += i18n("Current cache minimum clean size: %1 bytes", QString::number(min_clean_size)); 0289 info += QLatin1String("<br>"); 0290 info += i18n("Current cache size: %1 bytes", QString::number(cur_size)); 0291 info += QLatin1String("<br>"); 0292 info += i18n("Current number of entries in the cache: %1", QString::number(cur_num_entries)); 0293 info += QLatin1String("<br>"); 0294 } 0295 // TODO: 1.10 herr_t H5Fget_metadata_read_retry_info( hid_t file_id, H5F_retry_info_t *info ) 0296 /* TODO: not available 0297 hbool_t atomicMode; 0298 status = H5Fget_mpi_atomicity(file, &atomicMode); 0299 if (status >= 0) { 0300 info += i18n("MPI file access atomic mode: %1", atomicMode ? i18n("Yes") : i18n("No")); 0301 info += QLatin1String("<br>"); 0302 }*/ 0303 #ifdef HAVE_AT_LEAST_HDF5_1_10_0 0304 hbool_t is_enabled, is_currently_logging; 0305 status = H5Fget_mdc_logging_status(file, &is_enabled, &is_currently_logging); 0306 if (status >= 0) { 0307 info += i18n("Logging enabled: %1", is_enabled ? i18n("Yes") : i18n("No")); 0308 info += QLatin1String("<br>"); 0309 info += i18n("Events are currently logged: %1", is_currently_logging ? i18n("Yes") : i18n("No")); 0310 info += QLatin1String("<br>"); 0311 } 0312 #endif 0313 #ifdef HAVE_AT_LEAST_HDF5_1_10_1 0314 unsigned int accesses[2], hits[2], misses[2], evictions[2], bypasses[2]; 0315 status = H5Fget_page_buffering_stats(file, accesses, hits, misses, evictions, bypasses); 0316 if (status >= 0) { 0317 info += i18n("Metadata/raw data page buffer accesses: %1 %2", QString::number(accesses[0]), QString::number(accesses[1])); 0318 info += QLatin1String("<br>"); 0319 info += i18n("Metadata/raw data page buffer hits: %1 %2", QString::number(hits[0]), QString::number(hits[1])); 0320 info += QLatin1String("<br>"); 0321 info += i18n("Metadata/raw data page buffer misses: %1 %2", QString::number(misses[0]), QString::number(misses[1])); 0322 info += QLatin1String("<br>"); 0323 info += i18n("Metadata/raw data page buffer evictions: %1 %2", QString::number(evictions[0]), QString::number(evictions[1])); 0324 info += QLatin1String("<br>"); 0325 info += i18n("Metadata/raw data accesses bypassing page buffer: %1 %2", QString::number(bypasses[0]), QString::number(bypasses[1])); 0326 info += QLatin1String("<br>"); 0327 } else { 0328 info += i18n("Page buffer disabled"); 0329 info += QLatin1String("<br>"); 0330 DEBUG("H5Fget_page_buffering_stats() status = " << status); 0331 } 0332 #endif 0333 #else 0334 Q_UNUSED(fileName); 0335 #endif 0336 return info; 0337 } 0338 0339 /*! 0340 * Get file content in DDL (Data Description Language) format 0341 * uses "h5dump" 0342 */ 0343 QString HDF5Filter::fileDDLString(const QString& fileName) { 0344 DEBUG(Q_FUNC_INFO); 0345 0346 QString DDLString; 0347 #ifdef Q_OS_LINUX 0348 const QString h5dumpFullPath = QStandardPaths::findExecutable(QLatin1String("h5dump")); 0349 if (h5dumpFullPath.isEmpty()) 0350 return i18n("h5dump not found."); 0351 0352 QProcess proc; 0353 QStringList args; 0354 args << QStringLiteral("-H") << fileName; 0355 proc.start(h5dumpFullPath, args); 0356 0357 if (proc.waitForReadyRead(1000) == false) 0358 DDLString += i18n("Reading from file %1 failed.", fileName); 0359 else { 0360 DDLString += QLatin1String(proc.readAll()); 0361 DDLString.replace(QLatin1Char('\n'), QLatin1String("<br>\n")); 0362 DDLString.replace(QLatin1Char('\t'), QLatin1String(" ")); 0363 // DEBUG(" DDL string: " << STDSTRING(DDLString)); 0364 } 0365 #else // TODO: h5dump on Win, Mac 0366 Q_UNUSED(fileName) 0367 #endif 0368 0369 return DDLString; 0370 } 0371 0372 // ##################################################################### 0373 // ################### Private implementation ########################## 0374 // ##################################################################### 0375 0376 HDF5FilterPrivate::HDF5FilterPrivate(HDF5Filter* owner) 0377 : q(owner) { 0378 #ifdef HAVE_HDF5 0379 m_status = 0; 0380 #endif 0381 } 0382 0383 #ifdef HAVE_HDF5 0384 void HDF5FilterPrivate::handleError(int err, const QString& function, const QString& arg) { 0385 #ifdef NDEBUG 0386 Q_UNUSED(err) 0387 Q_UNUSED(function) 0388 Q_UNUSED(arg) 0389 #else 0390 if (err < 0) { 0391 DEBUG("ERROR " << err << ": " << STDSTRING(function) << "() - " << STDSTRING(arg)); 0392 } 0393 #endif 0394 } 0395 0396 QString HDF5FilterPrivate::translateHDF5Order(H5T_order_t o) { 0397 QString order; 0398 switch (o) { 0399 case H5T_ORDER_LE: 0400 order = QStringLiteral("LE"); 0401 break; 0402 case H5T_ORDER_BE: 0403 order = QStringLiteral("BE"); 0404 break; 0405 case H5T_ORDER_VAX: 0406 order = QStringLiteral("VAX"); 0407 break; 0408 case H5T_ORDER_MIXED: 0409 order = QStringLiteral("MIXED"); 0410 break; 0411 case H5T_ORDER_NONE: 0412 order = QStringLiteral("NONE"); 0413 break; 0414 case H5T_ORDER_ERROR: 0415 order = QStringLiteral("ERROR"); 0416 break; 0417 } 0418 0419 return order; 0420 } 0421 0422 QString HDF5FilterPrivate::translateHDF5Type(hid_t t) { 0423 QString type; 0424 0425 if (H5Tequal(t, H5T_STD_I8LE) || H5Tequal(t, H5T_STD_I8BE)) 0426 type = QStringLiteral("CHAR"); 0427 else if (H5Tequal(t, H5T_STD_U8LE) || H5Tequal(t, H5T_STD_U8BE)) 0428 type = QStringLiteral("UCHAR"); 0429 else if (H5Tequal(t, H5T_STD_I16LE) || H5Tequal(t, H5T_STD_I16BE)) 0430 type = QStringLiteral("SHORT"); 0431 else if (H5Tequal(t, H5T_STD_U16LE) || H5Tequal(t, H5T_STD_U16BE)) 0432 type = QStringLiteral("USHORT"); 0433 else if (H5Tequal(t, H5T_STD_I32LE) || H5Tequal(t, H5T_STD_I32BE)) 0434 type = QStringLiteral("INT"); 0435 else if (H5Tequal(t, H5T_STD_U32LE) || H5Tequal(t, H5T_STD_U32BE)) 0436 type = QStringLiteral("UINT"); 0437 else if (H5Tequal(t, H5T_NATIVE_LONG)) 0438 type = QStringLiteral("LONG"); 0439 else if (H5Tequal(t, H5T_NATIVE_ULONG)) 0440 type = QStringLiteral("ULONG"); 0441 else if (H5Tequal(t, H5T_STD_I64LE) || H5Tequal(t, H5T_STD_I64BE)) 0442 type = QStringLiteral("LLONG"); 0443 else if (H5Tequal(t, H5T_STD_U64LE) || H5Tequal(t, H5T_STD_U64BE)) 0444 type = QStringLiteral("ULLONG"); 0445 else if (H5Tequal(t, H5T_IEEE_F32LE) || H5Tequal(t, H5T_IEEE_F32BE)) 0446 type = QStringLiteral("FLOAT"); 0447 else if (H5Tequal(t, H5T_IEEE_F64LE) || H5Tequal(t, H5T_IEEE_F64BE)) 0448 type = QStringLiteral("DOUBLE"); 0449 else if (H5Tequal(t, H5T_NATIVE_LDOUBLE)) 0450 type = QStringLiteral("LDOUBLE"); 0451 else 0452 type = QStringLiteral("UNKNOWN"); 0453 0454 return type; 0455 } 0456 0457 QString HDF5FilterPrivate::translateHDF5Class(H5T_class_t c) { 0458 QString dclass; 0459 switch (c) { 0460 case H5T_INTEGER: 0461 dclass = QStringLiteral("INTEGER"); 0462 break; 0463 case H5T_FLOAT: 0464 dclass = QStringLiteral("FLOAT"); 0465 break; 0466 case H5T_STRING: 0467 dclass = QStringLiteral("STRING"); 0468 break; 0469 case H5T_BITFIELD: 0470 dclass = QStringLiteral("BITFIELD"); 0471 break; 0472 case H5T_OPAQUE: 0473 dclass = QStringLiteral("OPAQUE"); 0474 break; 0475 case H5T_COMPOUND: 0476 dclass = QStringLiteral("COMPOUND"); 0477 break; 0478 case H5T_ARRAY: 0479 dclass = QStringLiteral("ARRAY"); 0480 break; 0481 case H5T_ENUM: 0482 dclass = QStringLiteral("ENUM"); 0483 break; 0484 case H5T_REFERENCE: 0485 dclass = QStringLiteral("REFERENCE"); 0486 break; 0487 case H5T_VLEN: 0488 dclass = QStringLiteral("VLEN"); 0489 break; 0490 case H5T_TIME: 0491 dclass = QStringLiteral("TIME"); 0492 break; 0493 case H5T_NCLASSES: 0494 dclass = QStringLiteral("NCLASSES"); 0495 break; 0496 case H5T_NO_CLASS: 0497 dclass = QStringLiteral("NOCLASS"); 0498 break; 0499 } 0500 return dclass; 0501 } 0502 0503 AbstractColumn::ColumnMode HDF5FilterPrivate::translateHDF5TypeToMode(hid_t t) { 0504 if (H5Tequal(t, H5T_STD_U32LE) || H5Tequal(t, H5T_STD_U32BE) || H5Tequal(t, H5T_NATIVE_LONG) || H5Tequal(t, H5T_NATIVE_ULONG) || H5Tequal(t, H5T_STD_I64LE) 0505 || H5Tequal(t, H5T_STD_I64BE) || H5Tequal(t, H5T_STD_U64LE) || H5Tequal(t, H5T_STD_U64BE)) 0506 return AbstractColumn::ColumnMode::BigInt; 0507 0508 if (H5Tequal(t, H5T_IEEE_F32LE) || H5Tequal(t, H5T_IEEE_F32BE) || H5Tequal(t, H5T_IEEE_F64LE) || H5Tequal(t, H5T_IEEE_F64BE) 0509 || H5Tequal(t, H5T_NATIVE_LDOUBLE)) 0510 return AbstractColumn::ColumnMode::Double; 0511 0512 // everything else 0513 return AbstractColumn::ColumnMode::Integer; 0514 } 0515 0516 QStringList HDF5FilterPrivate::readHDF5Compound(hid_t tid) { 0517 size_t typeSize = H5Tget_size(tid); 0518 0519 QString line; 0520 line += QLatin1String("COMPOUND(") + QString::number(typeSize) + QLatin1String(") : ("); 0521 int members = H5Tget_nmembers(tid); 0522 handleError(members, QStringLiteral("H5Tget_nmembers")); 0523 for (int i = 0; i < members; ++i) { 0524 H5T_class_t mclass = H5Tget_member_class(tid, i); 0525 handleError((int)mclass, QStringLiteral("H5Tget_member_class")); 0526 hid_t mtype = H5Tget_member_type(tid, i); 0527 handleError((int)mtype, QStringLiteral("H5Tget_member_type")); 0528 size_t size = H5Tget_size(mtype); 0529 handleError((int)size, QStringLiteral("H5Tget_size")); 0530 QString typeString = translateHDF5Class(mclass); 0531 if (mclass == H5T_INTEGER || mclass == H5T_FLOAT) 0532 typeString = translateHDF5Type(mtype); 0533 line += 0534 QLatin1String(H5Tget_member_name(tid, i)) + QStringLiteral("[") + typeString + QStringLiteral("(") + QString::number(size) + QStringLiteral(")]"); 0535 if (i == members - 1) 0536 line += QLatin1String(")"); 0537 else 0538 line += QLatin1String(","); 0539 m_status = H5Tclose(mtype); 0540 handleError(m_status, QStringLiteral("H5Tclose")); 0541 } 0542 0543 QStringList dataString; 0544 dataString << line; 0545 0546 return dataString; 0547 } 0548 0549 template<typename T> 0550 QStringList HDF5FilterPrivate::readHDF5Data1D(hid_t dataset, hid_t dtype, int rows, int lines, void* dataContainer) { 0551 DEBUG(Q_FUNC_INFO << ", rows = " << rows << ", lines = " << lines); 0552 QStringList dataString; 0553 0554 // we read all rows of data 0555 T* data = new T[rows]; 0556 0557 m_status = H5Dread(dataset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); 0558 handleError(m_status, QStringLiteral("H5Dread")); 0559 DEBUG(Q_FUNC_INFO << ", startRow = " << startRow << ", endRow = " << endRow); 0560 DEBUG(Q_FUNC_INFO << ", dataContainer = " << dataContainer); 0561 0562 H5T_class_t dclass = H5Tget_class(dtype); 0563 handleError((int)dclass, QStringLiteral("H5Dget_class")); 0564 if (dclass == H5T_INTEGER) { 0565 if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG) || H5Tequal(dtype, H5T_STD_U64LE) 0566 || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) { 0567 HDF5_READ_1D(qint64); 0568 } else 0569 HDF5_READ_1D(int); 0570 } else 0571 HDF5_READ_1D(double); 0572 0573 delete[] data; 0574 0575 return dataString; 0576 } 0577 0578 QStringList HDF5FilterPrivate::readHDF5CompoundData1D(hid_t dataset, hid_t tid, int rows, int lines, std::vector<void*>& dataContainer) { 0579 DEBUG(Q_FUNC_INFO << ", data container size = " << dataContainer.size()); 0580 int members = H5Tget_nmembers(tid); 0581 bool preview = !dataContainer[0]; 0582 handleError(members, QStringLiteral("H5Tget_nmembers")); 0583 // DEBUG(" # members = " << members); 0584 0585 QStringList dataString; 0586 if (preview) { 0587 for (int i = 0; i < std::min(rows, lines); ++i) 0588 dataString << QStringLiteral("("); 0589 dataContainer.resize(members); // avoid "index out of range" for preview 0590 } 0591 0592 for (int m = 0; m < members; ++m) { 0593 // DEBUG(Q_FUNC_INFO << ", member " << m) 0594 hid_t mtype = H5Tget_member_type(tid, m); 0595 handleError((int)mtype, QStringLiteral("H5Tget_member_type")); 0596 size_t msize = H5Tget_size(mtype); 0597 handleError((int)msize, QStringLiteral("H5Tget_size")); 0598 hid_t ctype = H5Tcreate(H5T_COMPOUND, msize); 0599 handleError((int)ctype, QStringLiteral("H5Tcreate")); 0600 m_status = H5Tinsert(ctype, H5Tget_member_name(tid, m), 0, mtype); 0601 handleError(m_status, QStringLiteral("H5Tinsert")); 0602 0603 QStringList mdataString; 0604 if (H5Tequal(mtype, H5T_STD_I8LE) || H5Tequal(mtype, H5T_STD_I8BE)) 0605 mdataString = readHDF5Data1D<qint8>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0606 else if (H5Tequal(mtype, H5T_NATIVE_CHAR)) { 0607 switch (sizeof(H5T_NATIVE_CHAR)) { 0608 case 1: 0609 mdataString = readHDF5Data1D<qint8>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0610 break; 0611 case 2: 0612 mdataString = readHDF5Data1D<qint16>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0613 break; 0614 case 4: 0615 mdataString = readHDF5Data1D<qint32>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0616 break; 0617 case 8: 0618 mdataString = readHDF5Data1D<qint64>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0619 break; 0620 } 0621 } else if (H5Tequal(mtype, H5T_STD_U8LE) || H5Tequal(mtype, H5T_STD_U8BE)) 0622 mdataString = readHDF5Data1D<uint8_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0623 else if (H5Tequal(mtype, H5T_NATIVE_UCHAR)) { 0624 switch (sizeof(H5T_NATIVE_UCHAR)) { 0625 case 1: 0626 mdataString = readHDF5Data1D<uint8_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0627 break; 0628 case 2: 0629 mdataString = readHDF5Data1D<uint16_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0630 break; 0631 case 4: 0632 mdataString = readHDF5Data1D<uint32_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0633 break; 0634 case 8: 0635 mdataString = readHDF5Data1D<uint64_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0636 break; 0637 } 0638 } else if (H5Tequal(mtype, H5T_STD_I16LE) || H5Tequal(mtype, H5T_STD_I16BE) || H5Tequal(mtype, H5T_NATIVE_SHORT)) 0639 mdataString = readHDF5Data1D<short>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0640 else if (H5Tequal(mtype, H5T_STD_U16LE) || H5Tequal(mtype, H5T_STD_U16BE) || H5Tequal(mtype, H5T_NATIVE_SHORT)) 0641 mdataString = readHDF5Data1D<unsigned short>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0642 else if (H5Tequal(mtype, H5T_STD_I32LE) || H5Tequal(mtype, H5T_STD_I32BE) || H5Tequal(mtype, H5T_NATIVE_INT)) 0643 mdataString = readHDF5Data1D<int>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0644 else if (H5Tequal(mtype, H5T_STD_U32LE) || H5Tequal(mtype, H5T_STD_U32BE) || H5Tequal(mtype, H5T_NATIVE_UINT)) 0645 mdataString = readHDF5Data1D<unsigned int>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0646 else if (H5Tequal(mtype, H5T_NATIVE_LONG)) 0647 mdataString = readHDF5Data1D<long>(dataset, ctype, rows, lines, dataContainer[m]); 0648 else if (H5Tequal(mtype, H5T_NATIVE_ULONG)) 0649 mdataString = readHDF5Data1D<unsigned long>(dataset, ctype, rows, lines, dataContainer[m]); 0650 else if (H5Tequal(mtype, H5T_STD_I64LE) || H5Tequal(mtype, H5T_STD_I64BE) || H5Tequal(mtype, H5T_NATIVE_LLONG)) 0651 mdataString = readHDF5Data1D<long long>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0652 else if (H5Tequal(mtype, H5T_STD_U64LE) || H5Tequal(mtype, H5T_STD_U64BE) || H5Tequal(mtype, H5T_NATIVE_ULLONG)) 0653 mdataString = readHDF5Data1D<unsigned long long>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0654 else if (H5Tequal(mtype, H5T_IEEE_F32LE) || H5Tequal(mtype, H5T_IEEE_F32BE)) 0655 mdataString = readHDF5Data1D<float>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0656 else if (H5Tequal(mtype, H5T_IEEE_F64LE) || H5Tequal(mtype, H5T_IEEE_F64BE)) 0657 mdataString = readHDF5Data1D<double>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, lines, dataContainer[m]); 0658 else if (H5Tequal(mtype, H5T_NATIVE_LDOUBLE)) 0659 mdataString = readHDF5Data1D<long double>(dataset, ctype, rows, lines, dataContainer[m]); 0660 else { 0661 if (dataContainer[m]) { 0662 for (int row = startRow - 1; row < std::min(endRow, lines + startRow - 1); ++row) 0663 static_cast<QVector<double>*>(dataContainer[m])->operator[](row - startRow + 1) = 0; 0664 } else { 0665 for (int i = 0; i < std::min(rows, lines); ++i) 0666 mdataString << QStringLiteral("_"); 0667 } 0668 H5T_class_t mclass = H5Tget_member_class(tid, m); 0669 handleError((int)mclass, QStringLiteral("H5Tget_member_class")); 0670 DEBUG(Q_FUNC_INFO << ", unsupported type of class " << STDSTRING(translateHDF5Class(mclass))); 0671 } 0672 0673 if (preview) { 0674 for (int i = 0; i < std::min(rows, lines); ++i) { 0675 dataString[i] += mdataString[i]; 0676 if (m < members - 1) 0677 dataString[i] += QLatin1String(","); 0678 } 0679 } 0680 0681 H5Tclose(ctype); 0682 } 0683 0684 if (preview) { 0685 for (int i = 0; i < std::min(rows, lines); ++i) 0686 dataString[i] += QLatin1String(")"); 0687 } 0688 0689 return dataString; 0690 } 0691 0692 template<typename T> 0693 QVector<QStringList> HDF5FilterPrivate::readHDF5Data2D(hid_t dataset, hid_t dtype, int rows, int cols, int lines, std::vector<void*>& dataPointer) { 0694 DEBUG(Q_FUNC_INFO << ", rows = " << rows << ", cols = " << cols << ", lines = " << lines); 0695 QVector<QStringList> dataStrings; 0696 0697 if (rows == 0 || cols == 0) 0698 return dataStrings; 0699 0700 // read all data 0701 T** data = (T**)malloc(rows * sizeof(T*)); 0702 data[0] = (T*)malloc(cols * rows * sizeof(T)); 0703 for (int i = 1; i < rows; ++i) 0704 data[i] = data[0] + i * cols; 0705 0706 m_status = H5Dread(dataset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &data[0][0]); 0707 handleError(m_status, QStringLiteral("H5Dread")); 0708 0709 H5T_class_t dclass = H5Tget_class(dtype); 0710 handleError((int)dclass, QStringLiteral("H5Dget_class")); 0711 if (dclass == H5T_INTEGER) { 0712 if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG) || H5Tequal(dtype, H5T_STD_U64LE) 0713 || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) { 0714 HDF5_READ_2D(qint64); 0715 } else 0716 HDF5_READ_2D(int); 0717 } else 0718 HDF5_READ_2D(double); 0719 0720 free(data[0]); 0721 free(data); 0722 0723 // QDEBUG(dataStrings); 0724 return dataStrings; 0725 } 0726 0727 QVector<QStringList> HDF5FilterPrivate::readHDF5CompoundData2D(hid_t dataset, hid_t tid, int rows, int cols, int lines) { 0728 DEBUG(Q_FUNC_INFO << ", rows =" << rows << "cols = " << cols << "lines = " << lines); 0729 0730 int members = H5Tget_nmembers(tid); 0731 handleError(members, QStringLiteral("H5Tget_nmembers")); 0732 DEBUG(" # members =" << members); 0733 0734 QVector<QStringList> dataStrings; 0735 for (int i = 0; i < std::min(rows, lines); ++i) { 0736 QStringList lineStrings; 0737 for (int j = 0; j < cols; ++j) 0738 lineStrings << QStringLiteral("("); 0739 dataStrings << lineStrings; 0740 } 0741 0742 // QStringList* data = new QStringList[members]; 0743 for (int m = 0; m < members; ++m) { 0744 hid_t mtype = H5Tget_member_type(tid, m); 0745 handleError((int)mtype, QStringLiteral("H5Tget_member_type")); 0746 size_t msize = H5Tget_size(mtype); 0747 handleError((int)msize, QStringLiteral("H5Tget_size")); 0748 hid_t ctype = H5Tcreate(H5T_COMPOUND, msize); 0749 handleError((int)ctype, QStringLiteral("H5Tcreate")); 0750 m_status = H5Tinsert(ctype, H5Tget_member_name(tid, m), 0, mtype); 0751 handleError(m_status, QStringLiteral("H5Tinsert")); 0752 0753 // dummy container for all data columns 0754 // initially contains one pointer set to NULL 0755 std::vector<void*> dummy(1, nullptr); 0756 QVector<QStringList> mdataStrings; 0757 if (H5Tequal(mtype, H5T_STD_I8LE) || H5Tequal(mtype, H5T_STD_I8BE)) 0758 mdataStrings = readHDF5Data2D<qint8>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0759 else if (H5Tequal(mtype, H5T_NATIVE_CHAR)) { 0760 switch (sizeof(H5T_NATIVE_CHAR)) { 0761 case 1: 0762 mdataStrings = readHDF5Data2D<qint8>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0763 break; 0764 case 2: 0765 mdataStrings = readHDF5Data2D<qint16>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0766 break; 0767 case 4: 0768 mdataStrings = readHDF5Data2D<qint32>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0769 break; 0770 case 8: 0771 mdataStrings = readHDF5Data2D<qint64>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0772 break; 0773 } 0774 } else if (H5Tequal(mtype, H5T_STD_U8LE) || H5Tequal(mtype, H5T_STD_U8BE)) 0775 mdataStrings = readHDF5Data2D<uint8_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0776 else if (H5Tequal(mtype, H5T_NATIVE_UCHAR)) { 0777 switch (sizeof(H5T_NATIVE_UCHAR)) { 0778 case 1: 0779 mdataStrings = readHDF5Data2D<uint8_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0780 break; 0781 case 2: 0782 mdataStrings = readHDF5Data2D<uint16_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0783 break; 0784 case 4: 0785 mdataStrings = readHDF5Data2D<uint32_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0786 break; 0787 case 8: 0788 mdataStrings = readHDF5Data2D<uint64_t>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0789 break; 0790 } 0791 } else if (H5Tequal(mtype, H5T_STD_I16LE) || H5Tequal(mtype, H5T_STD_I16BE) || H5Tequal(mtype, H5T_NATIVE_SHORT)) 0792 mdataStrings = readHDF5Data2D<short>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0793 else if (H5Tequal(mtype, H5T_STD_U16LE) || H5Tequal(mtype, H5T_STD_U16BE) || H5Tequal(mtype, H5T_NATIVE_USHORT)) 0794 mdataStrings = readHDF5Data2D<unsigned short>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0795 else if (H5Tequal(mtype, H5T_STD_I32LE) || H5Tequal(mtype, H5T_STD_I32BE) || H5Tequal(mtype, H5T_NATIVE_INT)) 0796 mdataStrings = readHDF5Data2D<int>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0797 else if (H5Tequal(mtype, H5T_STD_U32LE) || H5Tequal(mtype, H5T_STD_U32BE) || H5Tequal(mtype, H5T_NATIVE_UINT)) 0798 mdataStrings = readHDF5Data2D<unsigned int>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0799 else if (H5Tequal(mtype, H5T_NATIVE_LONG)) 0800 mdataStrings = readHDF5Data2D<long>(dataset, ctype, rows, cols, lines, dummy); 0801 else if (H5Tequal(mtype, H5T_NATIVE_ULONG)) 0802 mdataStrings = readHDF5Data2D<unsigned long>(dataset, ctype, rows, cols, lines, dummy); 0803 else if (H5Tequal(mtype, H5T_STD_I64LE) || H5Tequal(mtype, H5T_STD_I64BE) || H5Tequal(mtype, H5T_NATIVE_LLONG)) 0804 mdataStrings = readHDF5Data2D<long long>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0805 else if (H5Tequal(mtype, H5T_STD_U64LE) || H5Tequal(mtype, H5T_STD_U64BE) || H5Tequal(mtype, H5T_NATIVE_ULLONG)) 0806 mdataStrings = readHDF5Data2D<unsigned long long>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0807 else if (H5Tequal(mtype, H5T_IEEE_F32LE) || H5Tequal(mtype, H5T_IEEE_F32BE)) 0808 mdataStrings = readHDF5Data2D<float>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0809 else if (H5Tequal(mtype, H5T_IEEE_F64LE) || H5Tequal(mtype, H5T_IEEE_F64BE)) 0810 mdataStrings = readHDF5Data2D<double>(dataset, H5Tget_native_type(ctype, H5T_DIR_DEFAULT), rows, cols, lines, dummy); 0811 else if (H5Tequal(mtype, H5T_NATIVE_LDOUBLE)) 0812 mdataStrings = readHDF5Data2D<long double>(dataset, ctype, rows, cols, lines, dummy); 0813 else { 0814 for (int i = 0; i < std::min(rows, lines); ++i) { 0815 QStringList lineString; 0816 for (int j = 0; j < cols; ++j) 0817 lineString << QStringLiteral("_"); 0818 mdataStrings << lineString; 0819 } 0820 #ifndef NDEBUG 0821 H5T_class_t mclass = H5Tget_member_class(tid, m); 0822 DEBUG("unsupported class " << STDSTRING(translateHDF5Class(mclass))); 0823 #endif 0824 } 0825 0826 m_status = H5Tclose(ctype); 0827 handleError(m_status, QStringLiteral("H5Tclose")); 0828 0829 for (int i = 0; i < std::min(rows, lines); i++) { 0830 for (int j = 0; j < cols; j++) { 0831 dataStrings[i][j] += mdataStrings[i][j]; 0832 if (m < members - 1) 0833 dataStrings[i][j] += QStringLiteral(","); 0834 } 0835 } 0836 } 0837 0838 for (int i = 0; i < std::min(rows, lines); ++i) { 0839 for (int j = 0; j < cols; ++j) 0840 dataStrings[i][j] += QStringLiteral(")"); 0841 } 0842 0843 // QDEBUG("dataStrings =" << dataStrings); 0844 return dataStrings; 0845 } 0846 0847 QStringList HDF5FilterPrivate::readHDF5Attr(hid_t aid) { 0848 QStringList attr; 0849 0850 char name[MAXNAMELENGTH]; 0851 m_status = H5Aget_name(aid, MAXNAMELENGTH, name); 0852 handleError(m_status, QStringLiteral("H5Aget_name")); 0853 attr << QLatin1String(name); 0854 // DEBUG(Q_FUNC_INFO << ", name =" << name); 0855 0856 hid_t aspace = H5Aget_space(aid); // the dimensions of the attribute data 0857 handleError((int)aspace, QStringLiteral("H5Aget_space")); 0858 hid_t atype = H5Aget_type(aid); 0859 handleError((int)atype, QStringLiteral("H5Aget_type")); 0860 hid_t aclass = H5Tget_class(atype); 0861 handleError((int)aclass, QStringLiteral("H5Aget_class")); 0862 0863 if (aclass == H5T_STRING) { 0864 hid_t amem = H5Tget_native_type(atype, H5T_DIR_DEFAULT); 0865 handleError((int)amem, QStringLiteral("H5Aget_native_type")); 0866 htri_t isVariable = H5Tis_variable_str(amem); 0867 handleError((int)isVariable, QStringLiteral("H5Tis_variable_str")); 0868 // DEBUG("variable string: " << isVariable) 0869 char* buf = nullptr; // buffer to read attr value 0870 if (!isVariable) { // fixed length 0871 hsize_t sz = H5Tget_size(atype); 0872 handleError((int)sz, QStringLiteral("H5Aget_storage_size")); 0873 // DEBUG("variable string = " << isVariable << ", storage size = " << sz) 0874 buf = new char[sz + 1]; 0875 m_status = H5Aread(aid, amem, buf); 0876 buf[sz] = '\0'; 0877 } else 0878 m_status = H5Aread(aid, amem, &buf); 0879 handleError(m_status, QStringLiteral("H5Aread")); 0880 attr << QLatin1String("=") << QLatin1String(buf); 0881 // DEBUG(Q_FUNC_INFO << ", value = " << buf) 0882 m_status = H5Tclose(amem); 0883 handleError(m_status, QStringLiteral("H5Tclose")); 0884 } else if (aclass == H5T_INTEGER) { 0885 if (H5Tequal(atype, H5T_STD_I8LE)) { 0886 qint8 value; 0887 m_status = H5Aread(aid, H5T_STD_I8LE, &value); 0888 handleError(m_status, QStringLiteral("H5Aread")); 0889 attr << QLatin1String("=") << QString::number(value); 0890 } else if (H5Tequal(atype, H5T_STD_I8BE)) { 0891 qint8 value; 0892 m_status = H5Aread(aid, H5T_STD_I8BE, &value); 0893 handleError(m_status, QStringLiteral("H5Aread")); 0894 attr << QLatin1String("=") << QString::number(value); 0895 } else if (H5Tequal(atype, H5T_NATIVE_CHAR)) { 0896 switch (sizeof(H5T_NATIVE_CHAR)) { 0897 case 1: { 0898 qint8 value; 0899 m_status = H5Aread(aid, H5T_NATIVE_CHAR, &value); 0900 handleError(m_status, QStringLiteral("H5Aread")); 0901 attr << QLatin1String("=") << QString::number(value); 0902 break; 0903 } 0904 case 2: { 0905 qint16 value; 0906 m_status = H5Aread(aid, H5T_NATIVE_CHAR, &value); 0907 handleError(m_status, QStringLiteral("H5Aread")); 0908 attr << QLatin1String("=") << QString::number(value); 0909 break; 0910 } 0911 case 4: { 0912 qint32 value; 0913 m_status = H5Aread(aid, H5T_NATIVE_CHAR, &value); 0914 handleError(m_status, QStringLiteral("H5Aread")); 0915 attr << QLatin1String("=") << QString::number(value); 0916 break; 0917 } 0918 case 8: { 0919 qint64 value; 0920 m_status = H5Aread(aid, H5T_NATIVE_CHAR, &value); 0921 handleError(m_status, QStringLiteral("H5Aread")); 0922 attr << QLatin1String("=") << QString::number(value); 0923 break; 0924 } 0925 default: 0926 DEBUG("unknown size " << sizeof(H5T_NATIVE_CHAR) << " of H5T_NATIVE_CHAR"); 0927 return QStringList(QString()); 0928 } 0929 } else if (H5Tequal(atype, H5T_STD_U8LE)) { 0930 uint8_t value; 0931 m_status = H5Aread(aid, H5T_STD_U8LE, &value); 0932 handleError(m_status, QStringLiteral("H5Aread")); 0933 attr << QLatin1String("=") << QString::number(value); 0934 } else if (H5Tequal(atype, H5T_STD_U8BE)) { 0935 uint8_t value; 0936 m_status = H5Aread(aid, H5T_STD_U8BE, &value); 0937 handleError(m_status, QStringLiteral("H5Aread")); 0938 attr << QLatin1String("=") << QString::number(value); 0939 } else if (H5Tequal(atype, H5T_NATIVE_UCHAR)) { 0940 switch (sizeof(H5T_NATIVE_UCHAR)) { 0941 case 1: { 0942 uint8_t value; 0943 m_status = H5Aread(aid, H5T_NATIVE_UCHAR, &value); 0944 handleError(m_status, QStringLiteral("H5Aread")); 0945 attr << QLatin1String("=") << QString::number(value); 0946 break; 0947 } 0948 case 2: { 0949 uint16_t value; 0950 m_status = H5Aread(aid, H5T_NATIVE_UCHAR, &value); 0951 handleError(m_status, QStringLiteral("H5Aread")); 0952 attr << QLatin1String("=") << QString::number(value); 0953 break; 0954 } 0955 case 4: { 0956 uint32_t value; 0957 m_status = H5Aread(aid, H5T_NATIVE_UCHAR, &value); 0958 handleError(m_status, QStringLiteral("H5Aread")); 0959 attr << QLatin1String("=") << QString::number(value); 0960 break; 0961 } 0962 case 8: { 0963 uint64_t value; 0964 m_status = H5Aread(aid, H5T_NATIVE_UCHAR, &value); 0965 handleError(m_status, QStringLiteral("H5Aread")); 0966 attr << QLatin1String("=") << QString::number(value); 0967 break; 0968 } 0969 default: 0970 DEBUG("unknown size " << sizeof(H5T_NATIVE_UCHAR) << " of H5T_NATIVE_UCHAR"); 0971 return QStringList(QString()); 0972 } 0973 } else if (H5Tequal(atype, H5T_STD_I16LE) || H5Tequal(atype, H5T_STD_I16BE) || H5Tequal(atype, H5T_NATIVE_SHORT)) { 0974 short value; 0975 m_status = H5Aread(aid, H5T_NATIVE_SHORT, &value); 0976 handleError(m_status, QStringLiteral("H5Aread")); 0977 attr << QLatin1String("=") << QString::number(value); 0978 } else if (H5Tequal(atype, H5T_STD_U16LE) || H5Tequal(atype, H5T_STD_U16BE) || H5Tequal(atype, H5T_NATIVE_USHORT)) { 0979 unsigned short value; 0980 m_status = H5Aread(aid, H5T_NATIVE_USHORT, &value); 0981 handleError(m_status, QStringLiteral("H5Aread")); 0982 attr << QLatin1String("=") << QString::number(value); 0983 } else if (H5Tequal(atype, H5T_STD_I32LE) || H5Tequal(atype, H5T_STD_I32BE) || H5Tequal(atype, H5T_NATIVE_INT)) { 0984 int value; 0985 m_status = H5Aread(aid, H5T_NATIVE_INT, &value); 0986 handleError(m_status, QStringLiteral("H5Aread")); 0987 attr << QLatin1String("=") << QString::number(value); 0988 } else if (H5Tequal(atype, H5T_STD_U32LE) || H5Tequal(atype, H5T_STD_U32BE) || H5Tequal(atype, H5T_NATIVE_UINT)) { 0989 unsigned int value; 0990 m_status = H5Aread(aid, H5T_NATIVE_UINT, &value); 0991 handleError(m_status, QStringLiteral("H5Aread")); 0992 attr << QLatin1String("=") << QString::number(value); 0993 } else if (H5Tequal(atype, H5T_NATIVE_LONG)) { 0994 long value; 0995 m_status = H5Aread(aid, H5T_NATIVE_LONG, &value); 0996 handleError(m_status, QStringLiteral("H5Aread")); 0997 attr << QLatin1String("=") << QString::number(value); 0998 } else if (H5Tequal(atype, H5T_NATIVE_ULONG)) { 0999 unsigned long value; 1000 m_status = H5Aread(aid, H5T_NATIVE_ULONG, &value); 1001 handleError(m_status, QStringLiteral("H5Aread")); 1002 attr << QLatin1String("=") << QString::number(value); 1003 } else if (H5Tequal(atype, H5T_STD_I64LE) || H5Tequal(atype, H5T_STD_I64BE) || H5Tequal(atype, H5T_NATIVE_LLONG)) { 1004 long long value; 1005 m_status = H5Aread(aid, H5T_NATIVE_LLONG, &value); 1006 handleError(m_status, QStringLiteral("H5Aread")); 1007 attr << QLatin1String("=") << QString::number(value); 1008 } else if (H5Tequal(atype, H5T_STD_U64LE) || H5Tequal(atype, H5T_STD_U64BE) || H5Tequal(atype, H5T_NATIVE_ULLONG)) { 1009 unsigned long long value; 1010 m_status = H5Aread(aid, H5T_NATIVE_ULLONG, &value); 1011 handleError(m_status, QStringLiteral("H5Aread")); 1012 attr << QLatin1String("=") << QString::number(value); 1013 } else 1014 attr << QStringLiteral(" (unknown integer)"); 1015 } else if (aclass == H5T_FLOAT) { 1016 if (H5Tequal(atype, H5T_IEEE_F32LE) || H5Tequal(atype, H5T_IEEE_F32BE)) { 1017 float value; 1018 m_status = H5Aread(aid, H5T_NATIVE_FLOAT, &value); 1019 handleError(m_status, QStringLiteral("H5Aread")); 1020 attr << QLatin1String("=") << QString::number(value); 1021 } else if (H5Tequal(atype, H5T_IEEE_F64LE) || H5Tequal(atype, H5T_IEEE_F64BE)) { 1022 double value; 1023 m_status = H5Aread(aid, H5T_NATIVE_DOUBLE, &value); 1024 handleError(m_status, QStringLiteral("H5Aread")); 1025 attr << QLatin1String("=") << QString::number(value); 1026 } else if (H5Tequal(atype, H5T_NATIVE_LDOUBLE)) { 1027 long double value; 1028 m_status = H5Aread(aid, H5T_NATIVE_LDOUBLE, &value); 1029 handleError(m_status, QStringLiteral("H5Aread")); 1030 attr << QLatin1String("=") << QString::number((double)value); 1031 } else 1032 attr << QStringLiteral(" (unknown float)"); 1033 } 1034 1035 m_status = H5Tclose(atype); 1036 handleError(m_status, QStringLiteral("H5Tclose")); 1037 m_status = H5Sclose(aspace); 1038 handleError(m_status, QStringLiteral("H5Sclose")); 1039 1040 return attr; 1041 } 1042 1043 QStringList HDF5FilterPrivate::scanHDF5Attrs(hid_t oid) { 1044 QStringList attrList; 1045 1046 int numAttr = H5Aget_num_attrs(oid); 1047 handleError(numAttr, QStringLiteral("H5Aget_num_attrs")); 1048 // DEBUG(Q_FUNC_INFO << ", number of attr = " << numAttr); 1049 1050 for (int i = 0; i < numAttr; ++i) { 1051 hid_t aid = H5Aopen_idx(oid, i); 1052 handleError((int)aid, QStringLiteral("H5Aopen_idx")); 1053 attrList << readHDF5Attr(aid); 1054 if (i < numAttr - 1) 1055 attrList << QLatin1String(", "); 1056 m_status = H5Aclose(aid); 1057 handleError(m_status, QStringLiteral("H5Aclose")); 1058 } 1059 1060 return attrList; 1061 } 1062 1063 QStringList HDF5FilterPrivate::readHDF5DataType(hid_t tid) { 1064 H5T_class_t typeClass = H5Tget_class(tid); 1065 handleError((int)typeClass, QStringLiteral("H5Tget_class")); 1066 1067 QStringList typeProps; 1068 QString typeString = translateHDF5Class(typeClass); 1069 if (typeClass == H5T_INTEGER || typeClass == H5T_FLOAT) 1070 typeString = translateHDF5Type(tid); 1071 typeProps << typeString; 1072 1073 size_t size = H5Tget_size(tid); 1074 typeProps << QLatin1String(" (") << QString::number(size) << QLatin1String(") "); 1075 1076 H5T_order_t order = H5Tget_order(tid); 1077 handleError((int)order, QStringLiteral("H5Tget_order")); 1078 typeProps << translateHDF5Order(order); 1079 1080 // type specific props 1081 switch (typeClass) { 1082 case H5T_STRING: { 1083 H5T_cset_t cset = H5Tget_cset(tid); 1084 handleError((int)cset, QStringLiteral("H5Tget_cset")); 1085 switch (cset) { 1086 case H5T_CSET_ASCII: 1087 typeProps << QLatin1String(", ASCII"); 1088 break; 1089 case H5T_CSET_ERROR: 1090 typeProps << QLatin1String(", ERROR"); 1091 break; 1092 case H5T_CSET_UTF8: 1093 typeProps << QLatin1String(", UTF8"); 1094 break; 1095 case H5T_CSET_RESERVED_2: 1096 case H5T_CSET_RESERVED_3: 1097 case H5T_CSET_RESERVED_4: 1098 case H5T_CSET_RESERVED_5: 1099 case H5T_CSET_RESERVED_6: 1100 case H5T_CSET_RESERVED_7: 1101 case H5T_CSET_RESERVED_8: 1102 case H5T_CSET_RESERVED_9: 1103 case H5T_CSET_RESERVED_10: 1104 case H5T_CSET_RESERVED_11: 1105 case H5T_CSET_RESERVED_12: 1106 case H5T_CSET_RESERVED_13: 1107 case H5T_CSET_RESERVED_14: 1108 case H5T_CSET_RESERVED_15: 1109 typeProps << QLatin1String(", RESERVED"); 1110 break; 1111 } 1112 H5T_str_t strpad = H5Tget_strpad(tid); 1113 handleError((int)strpad, QStringLiteral("H5Tget_strpad")); 1114 switch (strpad) { 1115 case H5T_STR_NULLTERM: 1116 typeProps << QLatin1String(" NULLTERM"); 1117 break; 1118 case H5T_STR_NULLPAD: 1119 typeProps << QLatin1String(" NULLPAD"); 1120 break; 1121 case H5T_STR_SPACEPAD: 1122 typeProps << QLatin1String(" SPACEPAD"); 1123 break; 1124 case H5T_STR_ERROR: 1125 typeProps << QLatin1String(" ERROR"); 1126 break; 1127 case H5T_STR_RESERVED_3: 1128 case H5T_STR_RESERVED_4: 1129 case H5T_STR_RESERVED_5: 1130 case H5T_STR_RESERVED_6: 1131 case H5T_STR_RESERVED_7: 1132 case H5T_STR_RESERVED_8: 1133 case H5T_STR_RESERVED_9: 1134 case H5T_STR_RESERVED_10: 1135 case H5T_STR_RESERVED_11: 1136 case H5T_STR_RESERVED_12: 1137 case H5T_STR_RESERVED_13: 1138 case H5T_STR_RESERVED_14: 1139 case H5T_STR_RESERVED_15: 1140 typeProps << QLatin1String(" RESERVED"); 1141 break; 1142 } 1143 break; 1144 } 1145 case H5T_COMPOUND: { 1146 // not shown in tree widget 1147 // QDEBUG(readHDF5Compound(tid).join(QString())); 1148 break; 1149 } 1150 case H5T_ENUM: { 1151 // TODO 1152 break; 1153 } 1154 case H5T_INTEGER: 1155 // TODO 1156 break; 1157 case H5T_FLOAT: 1158 // TODO 1159 break; 1160 case H5T_TIME: 1161 // TODO 1162 break; 1163 case H5T_BITFIELD: 1164 // TODO 1165 break; 1166 case H5T_OPAQUE: 1167 // TODO 1168 break; 1169 case H5T_REFERENCE: 1170 // TODO 1171 break; 1172 case H5T_VLEN: 1173 // TODO 1174 break; 1175 case H5T_ARRAY: 1176 // TODO 1177 break; 1178 case H5T_NCLASSES: 1179 // TODO 1180 break; 1181 case H5T_NO_CLASS: 1182 break; 1183 } 1184 1185 return typeProps; 1186 } 1187 1188 QStringList HDF5FilterPrivate::readHDF5PropertyList(hid_t pid) { 1189 QStringList props; 1190 1191 hsize_t chunk_dims_out[2]; 1192 if (H5D_CHUNKED == H5Pget_layout(pid)) { 1193 int rank_chunk = H5Pget_chunk(pid, 2, chunk_dims_out); 1194 handleError(rank_chunk, QStringLiteral("H5Pget_chunk")); 1195 props << QLatin1String("chunk rank=") << QString::number(rank_chunk) << QLatin1String(", dimension=") << QString::number(chunk_dims_out[0]) 1196 << QString::number(chunk_dims_out[1]); 1197 } 1198 1199 int nfilters = H5Pget_nfilters(pid); 1200 handleError(nfilters, QStringLiteral("H5Pget_nfilters")); 1201 props << QLatin1String(" ") << QString::number(nfilters) << QLatin1String(" filter"); 1202 for (int i = 0; i < nfilters; ++i) { 1203 size_t cd_nelmts = 32; 1204 unsigned int filt_flags, filt_conf; 1205 unsigned int cd_values[32]; 1206 char f_name[MAXNAMELENGTH]; 1207 H5Z_filter_t filtn = H5Pget_filter(pid, (unsigned)i, &filt_flags, &cd_nelmts, cd_values, (size_t)MAXNAMELENGTH, f_name, &filt_conf); 1208 handleError((int)filtn, QStringLiteral("H5Pget_filter")); 1209 1210 switch (filtn) { 1211 case H5Z_FILTER_DEFLATE: /* AKA GZIP compression */ 1212 props << QLatin1String(": DEFLATE level =") << QString::number(cd_values[0]); 1213 break; 1214 case H5Z_FILTER_SHUFFLE: 1215 props << QLatin1String(": SHUFFLE"); /* no parms */ 1216 break; 1217 case H5Z_FILTER_FLETCHER32: 1218 props << QLatin1String(": FLETCHER32"); /* Error Detection Code */ 1219 break; 1220 case H5Z_FILTER_SZIP: { 1221 // unsigned int szip_options_mask = cd_values[0]; 1222 unsigned int szip_pixels_per_block = cd_values[1]; 1223 1224 props << QLatin1String(": SZIP COMPRESSION - PIXELS_PER_BLOCK ") << QString::number(szip_pixels_per_block); 1225 break; 1226 } 1227 default: 1228 props << QLatin1String(": Unknown filter"); 1229 break; 1230 } 1231 } 1232 1233 props << QLatin1String(", ALLOC_TIME:"); 1234 H5D_alloc_time_t at; 1235 m_status = H5Pget_alloc_time(pid, &at); 1236 handleError(m_status, QStringLiteral("H5Pget_alloc_time")); 1237 1238 switch (at) { 1239 case H5D_ALLOC_TIME_EARLY: 1240 props << QLatin1String(" EARLY"); 1241 break; 1242 case H5D_ALLOC_TIME_INCR: 1243 props << QLatin1String(" INCR"); 1244 break; 1245 case H5D_ALLOC_TIME_LATE: 1246 props << QLatin1String(" LATE"); 1247 break; 1248 case H5D_ALLOC_TIME_DEFAULT: 1249 props << QLatin1String(" DEFAULT"); 1250 break; 1251 case H5D_ALLOC_TIME_ERROR: 1252 props << QLatin1String(" ERROR"); 1253 break; 1254 } 1255 1256 props << QLatin1String(", FILL_TIME:"); 1257 H5D_fill_time_t ft; 1258 m_status = H5Pget_fill_time(pid, &ft); 1259 handleError(m_status, QStringLiteral("H5Pget_fill_time")); 1260 switch (ft) { 1261 case H5D_FILL_TIME_ALLOC: 1262 props << QLatin1String(" ALLOW"); 1263 break; 1264 case H5D_FILL_TIME_NEVER: 1265 props << QLatin1String(" NEVER"); 1266 break; 1267 case H5D_FILL_TIME_IFSET: 1268 props << QLatin1String(" IFSET"); 1269 break; 1270 case H5D_FILL_TIME_ERROR: 1271 props << QLatin1String(" ERROR"); 1272 break; 1273 } 1274 1275 H5D_fill_value_t fvstatus; 1276 m_status = H5Pfill_value_defined(pid, &fvstatus); 1277 handleError(m_status, QStringLiteral("H5Pfill_value_defined")); 1278 if (fvstatus == H5D_FILL_VALUE_UNDEFINED) 1279 props << QLatin1String(" No fill value defined"); 1280 else { 1281 /* TODO: Read the fill value with H5Pget_fill_value. 1282 * Fill value is the same data type as the dataset. 1283 * (details not shown) 1284 **/ 1285 } 1286 1287 return props; 1288 } 1289 1290 void HDF5FilterPrivate::scanHDF5DataType(hid_t tid, char* dataSetName, QTreeWidgetItem* parentItem) { 1291 QStringList typeProps = readHDF5DataType(tid); 1292 1293 QString attr = scanHDF5Attrs(tid).join(QLatin1Char(' ')); 1294 1295 char link[MAXNAMELENGTH]; 1296 m_status = H5Iget_name(tid, link, MAXNAMELENGTH); 1297 handleError(m_status, QStringLiteral("H5Iget_name")); 1298 1299 auto* dataTypeItem = 1300 new QTreeWidgetItem(QStringList() << QLatin1String(dataSetName) << QLatin1String(link) << i18n("data type") << typeProps.join(QString()) << attr); 1301 dataTypeItem->setIcon(0, QIcon::fromTheme(QStringLiteral("accessories-calculator"))); 1302 dataTypeItem->setFlags(Qt::ItemIsEnabled); 1303 parentItem->addChild(dataTypeItem); 1304 } 1305 1306 void HDF5FilterPrivate::scanHDF5DataSet(hid_t did, char* dataSetName, QTreeWidgetItem* parentItem) { 1307 QString attr = scanHDF5Attrs(did).join(QString()); 1308 1309 char link[MAXNAMELENGTH]; 1310 m_status = H5Iget_name(did, link, MAXNAMELENGTH); 1311 handleError(m_status, QStringLiteral("H5Iget_name")); 1312 1313 QStringList dataSetProps; 1314 hsize_t size = H5Dget_storage_size(did); 1315 handleError((int)size, QStringLiteral("H5Dget_storage_size")); 1316 hid_t datatype = H5Dget_type(did); 1317 handleError((int)datatype, QStringLiteral("H5Dget_type")); 1318 size_t typeSize = H5Tget_size(datatype); 1319 handleError((int)typeSize, QStringLiteral("H5Dget_size")); 1320 1321 dataSetProps << readHDF5DataType(datatype); 1322 1323 hid_t dataspace = H5Dget_space(did); 1324 int rank = H5Sget_simple_extent_ndims(dataspace); 1325 handleError(rank, QStringLiteral("H5Sget_simple_extent_ndims")); 1326 unsigned int rows = 1, cols = 1, regs = 1; 1327 if (rank == 1) { 1328 hsize_t dims_out[1]; 1329 m_status = H5Sget_simple_extent_dims(dataspace, dims_out, nullptr); 1330 handleError(m_status, QStringLiteral("H5Sget_simple_extent_dims")); 1331 rows = dims_out[0]; 1332 dataSetProps << QLatin1String(", ") << QString::number(rows) << QLatin1String(" (") << QString::number(size / typeSize) << QLatin1String(")"); 1333 } else if (rank == 2) { 1334 hsize_t dims_out[2]; 1335 m_status = H5Sget_simple_extent_dims(dataspace, dims_out, nullptr); 1336 handleError(m_status, QStringLiteral("H5Sget_simple_extent_dims")); 1337 rows = dims_out[0]; 1338 cols = dims_out[1]; 1339 dataSetProps << QLatin1String(", ") << QString::number(rows) << QLatin1String("x") << QString::number(cols) << QLatin1String(" (") 1340 << QString::number(size / typeSize) << QLatin1String(")"); 1341 } else if (rank == 3) { 1342 hsize_t dims_out[3]; 1343 m_status = H5Sget_simple_extent_dims(dataspace, dims_out, nullptr); 1344 handleError(m_status, QStringLiteral("H5Sget_simple_extent_dims")); 1345 rows = dims_out[0]; 1346 cols = dims_out[1]; 1347 regs = dims_out[2]; 1348 dataSetProps << QLatin1String(", ") << QString::number(rows) << QLatin1String("x") << QString::number(cols) << QLatin1String("x") 1349 << QString::number(regs) << QLatin1String(" (") << QString::number(size / typeSize) << QLatin1String(")"); 1350 } else 1351 dataSetProps << QLatin1String(", ") << i18n("rank %1 not supported yet", rank); 1352 1353 hid_t pid = H5Dget_create_plist(did); 1354 handleError((int)pid, QStringLiteral("H5Dget_create_plist")); 1355 dataSetProps << QStringLiteral(", ") << readHDF5PropertyList(pid).join(QString()); 1356 1357 auto* dataSetItem = 1358 new QTreeWidgetItem(QStringList() << QLatin1String(dataSetName) << QLatin1String(link) << i18n("data set") << dataSetProps.join(QString()) << attr); 1359 dataSetItem->setIcon(0, QIcon::fromTheme(QStringLiteral("x-office-spreadsheet"))); 1360 for (int i = 0; i < dataSetItem->columnCount(); ++i) { 1361 if (rows > 0 && cols > 0 && regs > 0) { 1362 dataSetItem->setBackground(i, QColor(192, 255, 192)); 1363 dataSetItem->setForeground(i, Qt::black); 1364 dataSetItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); 1365 } else 1366 dataSetItem->setFlags(Qt::NoItemFlags); 1367 } 1368 parentItem->addChild(dataSetItem); 1369 } 1370 1371 void HDF5FilterPrivate::scanHDF5Link(hid_t gid, char* linkName, QTreeWidgetItem* parentItem) { 1372 char target[MAXNAMELENGTH]; 1373 m_status = H5Gget_linkval(gid, linkName, MAXNAMELENGTH, target); 1374 handleError(m_status, QStringLiteral("H5Gget_linkval")); 1375 1376 auto* linkItem = new QTreeWidgetItem(QStringList() << QLatin1String(linkName) << i18n("symbolic link") << i18n("link to %1", QFile::decodeName(target))); 1377 linkItem->setIcon(0, QIcon::fromTheme(QStringLiteral("emblem-symbolic-link"))); 1378 linkItem->setFlags(Qt::ItemIsEnabled); 1379 parentItem->addChild(linkItem); 1380 } 1381 1382 void HDF5FilterPrivate::scanHDF5Group(hid_t gid, char* groupName, QTreeWidgetItem* parentItem) { 1383 // check for hard link 1384 H5G_stat_t statbuf; 1385 m_status = H5Gget_objinfo(gid, ".", true, &statbuf); 1386 handleError(m_status, QStringLiteral("H5Gget_objinfo")); 1387 if (statbuf.nlink > 1) { 1388 if (m_multiLinkList.contains(statbuf.objno[0])) { 1389 auto* objectItem = new QTreeWidgetItem(QStringList() << QLatin1String(groupName) << i18n("hard link")); 1390 objectItem->setIcon(0, QIcon::fromTheme(QStringLiteral("link"))); 1391 objectItem->setFlags(Qt::ItemIsEnabled); 1392 parentItem->addChild(objectItem); 1393 return; 1394 } else { 1395 m_multiLinkList.append(statbuf.objno[0]); 1396 DEBUG(" group multiple links: " << statbuf.objno[0] << ' ' << statbuf.objno[1]); 1397 } 1398 } 1399 1400 char link[MAXNAMELENGTH]; 1401 m_status = H5Iget_name(gid, link, MAXNAMELENGTH); 1402 handleError(m_status, QStringLiteral("H5Iget_name")); 1403 1404 QString attr = scanHDF5Attrs(gid).join(QLatin1Char(' ')); 1405 1406 auto* groupItem = new QTreeWidgetItem(QStringList() << QLatin1String(groupName) << QLatin1String(link) << QStringLiteral("group ") << attr); 1407 groupItem->setIcon(0, QIcon::fromTheme(QStringLiteral("folder"))); 1408 groupItem->setFlags(Qt::ItemIsEnabled); 1409 parentItem->addChild(groupItem); 1410 1411 hsize_t numObj; 1412 m_status = H5Gget_num_objs(gid, &numObj); 1413 handleError(m_status, QStringLiteral("H5Gget_num_objs")); 1414 // DEBUG(Q_FUNC_INFO << ", # of objects = " << numObj) 1415 1416 for (unsigned int i = 0; i < numObj; ++i) { 1417 char memberName[MAXNAMELENGTH]; 1418 m_status = H5Gget_objname_by_idx(gid, (hsize_t)i, memberName, (size_t)MAXNAMELENGTH); 1419 handleError(m_status, QStringLiteral("H5Gget_objname_by_idx")); 1420 1421 int otype = H5Gget_objtype_by_idx(gid, (size_t)i); 1422 handleError(otype, QStringLiteral("H5Gget_objtype_by_idx")); 1423 switch (otype) { 1424 case H5G_LINK: { 1425 scanHDF5Link(gid, memberName, groupItem); 1426 break; 1427 } 1428 case H5G_GROUP: { 1429 hid_t grpid = H5Gopen(gid, memberName, H5P_DEFAULT); 1430 handleError((int)grpid, QStringLiteral("H5Gopen")); 1431 scanHDF5Group(grpid, memberName, groupItem); 1432 m_status = H5Gclose(grpid); 1433 handleError(m_status, QStringLiteral("H5Gclose")); 1434 break; 1435 } 1436 case H5G_DATASET: { 1437 hid_t dsid = H5Dopen(gid, memberName, H5P_DEFAULT); 1438 handleError((int)dsid, QStringLiteral("H5Dopen")); 1439 scanHDF5DataSet(dsid, memberName, groupItem); 1440 m_status = H5Dclose(dsid); 1441 handleError(m_status, QStringLiteral("H5Dclose")); 1442 break; 1443 } 1444 case H5G_TYPE: { 1445 hid_t tid = H5Topen(gid, memberName, H5P_DEFAULT); 1446 handleError((int)tid, QStringLiteral("H5Topen")); 1447 scanHDF5DataType(tid, memberName, groupItem); 1448 m_status = H5Tclose(tid); 1449 handleError(m_status, QStringLiteral("H5Tclose")); 1450 break; 1451 } 1452 default: 1453 auto* objectItem = new QTreeWidgetItem(QStringList() << QLatin1String(memberName) << i18n("unknown")); 1454 objectItem->setFlags(Qt::ItemIsEnabled); 1455 groupItem->addChild(objectItem); 1456 break; 1457 } 1458 } 1459 } 1460 #endif 1461 1462 /*! 1463 parses the content of the file \c fileName and fill the tree using rootItem. 1464 returns -1 on error 1465 */ 1466 int HDF5FilterPrivate::parse(const QString& fileName, QTreeWidgetItem* rootItem) { 1467 #ifdef HAVE_HDF5 1468 DEBUG(Q_FUNC_INFO << ", fileName = " << qPrintable(fileName)); 1469 1470 // check file type first 1471 htri_t isHdf5 = H5Fis_hdf5(qPrintable(fileName)); 1472 if (isHdf5 == 0) { // not an HDF5 file 1473 DEBUG(qPrintable(fileName) << " is not a HDF5 file! Giving up."); 1474 return -1; 1475 } 1476 if (isHdf5 < 0) { // failing on file (like not found) 1477 DEBUG("H5Fis_hdf5() failed on " << qPrintable(fileName) << "! Giving up."); 1478 return -1; 1479 } 1480 1481 // open file 1482 hid_t file = H5Fopen(qPrintable(fileName), H5F_ACC_RDONLY, H5P_DEFAULT); 1483 handleError((int)file, QStringLiteral("H5Fopen"), fileName); 1484 if (file < 0) { 1485 DEBUG("Opening file " << qPrintable(fileName) << " failed! Giving up."); 1486 return -1; 1487 } 1488 char rootName[] = "/"; 1489 hid_t group = H5Gopen(file, rootName, H5P_DEFAULT); 1490 handleError((int)group, QStringLiteral("H5Gopen"), QLatin1String(rootName)); 1491 // multiLinkList.clear(); crashes 1492 scanHDF5Group(group, rootName, rootItem); 1493 m_status = H5Gclose(group); 1494 handleError(m_status, QStringLiteral("H5Gclose"), QString()); 1495 m_status = H5Fclose(file); 1496 handleError(m_status, QStringLiteral("H5Fclose"), QString()); 1497 #else 1498 DEBUG(Q_FUNC_INFO << ", HDF5 not available"); 1499 Q_UNUSED(fileName) 1500 Q_UNUSED(rootItem) 1501 #endif 1502 return 0; 1503 } 1504 1505 /*! 1506 reads the content of the date set in the file \c fileName to a string (for preview) or to the data source. 1507 */ 1508 QVector<QStringList> 1509 HDF5FilterPrivate::readCurrentDataSet(const QString& fileName, AbstractDataSource* dataSource, bool& ok, AbstractFileFilter::ImportMode mode, int lines) { 1510 QVector<QStringList> dataStrings; 1511 1512 if (currentDataSetName.isEmpty()) { 1513 // return QString("No data set selected").replace(QLatin1Char(' '),QChar::Nbsp); 1514 ok = false; 1515 return dataStrings << (QStringList() << i18n("No data set selected")); 1516 } 1517 DEBUG(Q_FUNC_INFO << ", current data set = " << STDSTRING(currentDataSetName)); 1518 1519 #ifdef HAVE_HDF5 1520 hid_t file = H5Fopen(qPrintable(fileName), H5F_ACC_RDONLY, H5P_DEFAULT); 1521 handleError((int)file, QStringLiteral("H5Fopen"), fileName); 1522 hid_t dataset = H5Dopen2(file, qPrintable(currentDataSetName), H5P_DEFAULT); 1523 handleError((int)file, QStringLiteral("H5Dopen2"), currentDataSetName); 1524 1525 // Get datatype and dataspace 1526 hid_t dtype = H5Dget_type(dataset); 1527 handleError((int)dtype, QStringLiteral("H5Dget_type")); 1528 DEBUG(Q_FUNC_INFO << ", type = " << STDSTRING(translateHDF5Type(dtype))) 1529 H5T_class_t dclass = H5Tget_class(dtype); 1530 handleError((int)dclass, QStringLiteral("H5Dget_class")); 1531 DEBUG(Q_FUNC_INFO << ", class = " << STDSTRING(translateHDF5Class(dclass))) 1532 size_t typeSize = H5Tget_size(dtype); 1533 handleError((int)(typeSize - 1), QStringLiteral("H5Dget_size")); 1534 1535 hid_t dataspace = H5Dget_space(dataset); 1536 handleError((int)dataspace, QStringLiteral("H5Dget_space")); 1537 int rank = H5Sget_simple_extent_ndims(dataspace); 1538 handleError(rank, QStringLiteral("H5Dget_simple_extent_ndims")); 1539 DEBUG(Q_FUNC_INFO << ", rank = " << rank); 1540 1541 int columnOffset = 0; // offset to import data 1542 int actualRows = 0, actualCols = 0; // rows and cols to read 1543 1544 // dataContainer is used to store the data read from the dataSource 1545 // it contains the pointers of all columns 1546 // initially there is one pointer set to nullptr 1547 // check for dataContainer[0] to decide if dataSource can be used 1548 std::vector<void*> dataContainer(1, nullptr); 1549 1550 // rank= 0: single value, 1: vector, 2: matrix, 3: 3D data, ... 1551 switch (rank) { 1552 case 0: { // single value 1553 actualCols = 1; 1554 1555 switch (dclass) { 1556 case H5T_STRING: { 1557 char* data = (char*)malloc(typeSize * sizeof(char)); 1558 hid_t memtype = H5Tcopy(H5T_C_S1); 1559 handleError((int)memtype, QStringLiteral("H5Tcopy")); 1560 m_status = H5Tset_size(memtype, typeSize); 1561 handleError(m_status, QStringLiteral("H5Tset_size")); 1562 1563 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); 1564 handleError(m_status, QStringLiteral("H5Tread")); 1565 dataStrings << (QStringList() << QLatin1String(data)); 1566 free(data); 1567 break; 1568 } 1569 case H5T_INTEGER: 1570 case H5T_FLOAT: 1571 case H5T_TIME: 1572 case H5T_BITFIELD: 1573 case H5T_OPAQUE: 1574 case H5T_COMPOUND: 1575 case H5T_REFERENCE: 1576 case H5T_ENUM: 1577 case H5T_VLEN: 1578 case H5T_ARRAY: 1579 case H5T_NO_CLASS: 1580 case H5T_NCLASSES: { 1581 ok = false; 1582 dataStrings << (QStringList() << i18n("rank 0 not implemented yet for type %1", translateHDF5Class(dclass))); 1583 QDEBUG(dataStrings); 1584 } 1585 default: 1586 break; 1587 } 1588 break; 1589 } 1590 case 1: { // 1D data 1591 hsize_t size, maxSize; 1592 m_status = H5Sget_simple_extent_dims(dataspace, &size, &maxSize); 1593 handleError(m_status, QStringLiteral("H5Sget_simple_extent_dims")); 1594 int rows = size; 1595 if (endRow == -1 && dclass != H5T_VLEN) 1596 endRow = rows; 1597 if (lines == -1 && dclass != H5T_VLEN) 1598 lines = endRow; 1599 actualRows = endRow - startRow + 1; 1600 actualCols = 1; // data is only one column (if not VLEN) 1601 #ifndef NDEBUG 1602 H5T_order_t order = H5Tget_order(dtype); 1603 handleError((int)order, QStringLiteral("H5Sget_order")); 1604 #endif 1605 QDEBUG(Q_FUNC_INFO << ": " << translateHDF5Class(dclass) << '(' << typeSize << ')' << translateHDF5Order(order) << ", rows:" << rows 1606 << " max:" << maxSize); 1607 1608 QVector<AbstractColumn::ColumnMode> columnModes; 1609 columnModes.resize(actualCols); 1610 // set other modes 1611 if (dclass == H5T_STRING) 1612 for (auto& mode : columnModes) 1613 mode = AbstractColumn::ColumnMode::Text; 1614 else if (dclass == H5T_INTEGER) { 1615 if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG) || H5Tequal(dtype, H5T_STD_U64LE) 1616 || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) 1617 for (auto& mode : columnModes) 1618 mode = AbstractColumn::ColumnMode::BigInt; 1619 else 1620 for (auto& mode : columnModes) 1621 mode = AbstractColumn::ColumnMode::Integer; 1622 } 1623 1624 // use current data set name (without path) for column name 1625 QStringList vectorNames = {currentDataSetName.mid(currentDataSetName.lastIndexOf(QLatin1Char('/')) + 1)}; 1626 QDEBUG(Q_FUNC_INFO << ", vector names = " << vectorNames) 1627 1628 if (dataSource && dclass != H5T_VLEN && dclass != H5T_COMPOUND) 1629 columnOffset = dataSource->prepareImport(dataContainer, mode, actualRows, actualCols, vectorNames, columnModes); 1630 1631 QStringList dataString; // data saved in a list 1632 switch (dclass) { 1633 case H5T_STRING: { 1634 DEBUG("rank 1 H5T_STRING"); 1635 hid_t memtype = H5Tcopy(H5T_C_S1); 1636 handleError((int)memtype, QStringLiteral("H5Tcopy")); 1637 1638 char** data = (char**)malloc(rows * sizeof(char*)); 1639 1640 if (H5Tis_variable_str(dtype)) { 1641 m_status = H5Tset_size(memtype, H5T_VARIABLE); 1642 handleError((int)memtype, QStringLiteral("H5Tset_size")); 1643 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); 1644 handleError(m_status, QStringLiteral("H5Dread")); 1645 } else { 1646 data[0] = (char*)malloc(rows * typeSize * sizeof(char)); 1647 for (int i = 1; i < rows; ++i) 1648 data[i] = data[0] + i * typeSize; 1649 1650 m_status = H5Tset_size(memtype, typeSize); 1651 handleError((int)memtype, QStringLiteral("H5Tset_size")); 1652 1653 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data[0]); 1654 handleError(m_status, QStringLiteral("H5Dread")); 1655 } 1656 1657 for (int i = startRow - 1; i < std::min(endRow, lines + startRow - 1); ++i) 1658 dataString << QLatin1String(data[i]); 1659 1660 free(data); 1661 break; 1662 } 1663 case H5T_INTEGER: { 1664 if (H5Tequal(dtype, H5T_STD_I8LE) || H5Tequal(dtype, H5T_STD_I8BE)) 1665 dataString = readHDF5Data1D<qint8>(dataset, dtype, rows, lines, dataContainer[0]); 1666 else if (H5Tequal(dtype, H5T_STD_U8LE) || H5Tequal(dtype, H5T_STD_U8BE)) 1667 dataString = readHDF5Data1D<uint8_t>(dataset, dtype, rows, lines, dataContainer[0]); 1668 else if (H5Tequal(dtype, H5T_NATIVE_CHAR)) { 1669 switch (sizeof(H5T_NATIVE_CHAR)) { 1670 case 1: 1671 dataString = readHDF5Data1D<qint8>(dataset, dtype, rows, lines, dataContainer[0]); 1672 break; 1673 case 2: 1674 dataString = readHDF5Data1D<qint16>(dataset, dtype, rows, lines, dataContainer[0]); 1675 break; 1676 case 4: 1677 dataString = readHDF5Data1D<qint32>(dataset, dtype, rows, lines, dataContainer[0]); 1678 break; 1679 case 8: 1680 dataString = readHDF5Data1D<qint64>(dataset, dtype, rows, lines, dataContainer[0]); 1681 break; 1682 } 1683 } else if (H5Tequal(dtype, H5T_NATIVE_UCHAR)) { 1684 switch (sizeof(H5T_NATIVE_UCHAR)) { 1685 case 1: 1686 dataString = readHDF5Data1D<uint8_t>(dataset, dtype, rows, lines, dataContainer[0]); 1687 break; 1688 case 2: 1689 dataString = readHDF5Data1D<uint16_t>(dataset, dtype, rows, lines, dataContainer[0]); 1690 break; 1691 case 4: 1692 dataString = readHDF5Data1D<uint32_t>(dataset, dtype, rows, lines, dataContainer[0]); 1693 break; 1694 case 8: 1695 dataString = readHDF5Data1D<uint64_t>(dataset, dtype, rows, lines, dataContainer[0]); 1696 break; 1697 } 1698 } else if (H5Tequal(dtype, H5T_STD_I16LE) || H5Tequal(dtype, H5T_STD_I16BE) || H5Tequal(dtype, H5T_NATIVE_SHORT)) 1699 dataString = readHDF5Data1D<short>(dataset, dtype, rows, lines, dataContainer[0]); 1700 else if (H5Tequal(dtype, H5T_STD_U16LE) || H5Tequal(dtype, H5T_STD_U16BE) || H5Tequal(dtype, H5T_NATIVE_USHORT)) 1701 dataString = readHDF5Data1D<unsigned short>(dataset, dtype, rows, lines, dataContainer[0]); 1702 else if (H5Tequal(dtype, H5T_STD_I32LE) || H5Tequal(dtype, H5T_STD_I32BE) || H5Tequal(dtype, H5T_NATIVE_INT)) 1703 dataString = readHDF5Data1D<int>(dataset, dtype, rows, lines, dataContainer[0]); 1704 else if (H5Tequal(dtype, H5T_STD_U32LE) || H5Tequal(dtype, H5T_STD_U32BE) || H5Tequal(dtype, H5T_NATIVE_UINT)) 1705 dataString = readHDF5Data1D<unsigned int>(dataset, dtype, rows, lines, dataContainer[0]); 1706 else if (H5Tequal(dtype, H5T_NATIVE_LONG)) 1707 dataString = readHDF5Data1D<long>(dataset, dtype, rows, lines, dataContainer[0]); 1708 else if (H5Tequal(dtype, H5T_NATIVE_ULONG)) 1709 dataString = readHDF5Data1D<unsigned long>(dataset, dtype, rows, lines, dataContainer[0]); 1710 else if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG)) 1711 dataString = readHDF5Data1D<long long>(dataset, dtype, rows, lines, dataContainer[0]); 1712 else if (H5Tequal(dtype, H5T_STD_U64LE) || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) 1713 dataString = readHDF5Data1D<unsigned long long>(dataset, dtype, rows, lines, dataContainer[0]); 1714 else { 1715 ok = false; 1716 dataString = (QStringList() << i18n("unsupported integer type for rank 1")); 1717 QDEBUG(dataString); 1718 } 1719 break; 1720 } 1721 case H5T_FLOAT: { 1722 if (H5Tequal(dtype, H5T_IEEE_F32LE) || H5Tequal(dtype, H5T_IEEE_F32BE)) 1723 dataString = readHDF5Data1D<float>(dataset, H5T_NATIVE_FLOAT, rows, lines, dataContainer[0]); 1724 else if (H5Tequal(dtype, H5T_IEEE_F64LE) || H5Tequal(dtype, H5T_IEEE_F64BE)) 1725 dataString = readHDF5Data1D<double>(dataset, H5T_NATIVE_DOUBLE, rows, lines, dataContainer[0]); 1726 else if (H5Tequal(dtype, H5T_NATIVE_LDOUBLE)) 1727 dataString = readHDF5Data1D<long double>(dataset, H5T_NATIVE_LDOUBLE, rows, lines, dataContainer[0]); 1728 else { 1729 ok = false; 1730 dataString = (QStringList() << i18n("unsupported float type for rank 1")); 1731 QDEBUG(dataString); 1732 } 1733 break; 1734 } 1735 case H5T_COMPOUND: { 1736 int members = H5Tget_nmembers(dtype); 1737 handleError(members, QStringLiteral("H5Tget_nmembers")); 1738 DEBUG(Q_FUNC_INFO << ", COMPOUND type. members: " << members) 1739 columnModes.resize(members); 1740 if (dataSource) // create data pointer here 1741 dataSource->prepareImport(dataContainer, mode, actualRows, members, vectorNames, columnModes); 1742 else 1743 dataStrings << readHDF5Compound(dtype); 1744 dataString = readHDF5CompoundData1D(dataset, dtype, rows, lines, dataContainer); 1745 break; 1746 } 1747 case H5T_VLEN: { 1748 DEBUG("H5T_VLEN") 1749 if (endColumn == -1) 1750 endColumn = size; 1751 actualCols = endColumn - startColumn + 1; 1752 DEBUG("size = " << size << ", actual cols = " << actualCols << ", rows/lines = " << rows << "/" << lines) 1753 1754 // set column mode 1755 hid_t base_type = H5Tget_super(dtype); 1756 columnModes.resize(actualCols); 1757 for (auto& mode : columnModes) 1758 mode = HDF5FilterPrivate::translateHDF5TypeToMode(base_type); 1759 1760 hvl_t* rdata = (hvl_t*)malloc(size * sizeof(hvl_t)); 1761 hid_t memtype = H5Tvlen_create(base_type); 1762 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata); 1763 1764 size_t maxLength = 0; 1765 for (int c = startColumn - 1; c < endColumn; c++) // columns 1766 maxLength = std::max(maxLength, rdata[c].len); 1767 if (endRow == -1 || endRow > (int)maxLength) 1768 endRow = maxLength; 1769 actualRows = endRow - startRow + 1; 1770 if (lines == -1 || lines > actualRows) 1771 lines = actualRows; 1772 dataStrings.resize(std::min(lines, actualRows)); 1773 1774 DEBUG("start/end row = " << startRow << "/" << endRow << ", lines = " << lines << ", max length = " << maxLength) 1775 DEBUG("start/end col = " << startColumn << "/" << endColumn) 1776 DEBUG("actual rows/cols = " << actualRows << " " << actualCols) 1777 if (dataSource) { 1778 if (size > 1) { // set vectorNames 1779 const QString datasetName = vectorNames.at(0); 1780 vectorNames.clear(); 1781 for (int i = startColumn; i <= endColumn; i++) 1782 vectorNames << datasetName + QStringLiteral("_") + QString::number(i); 1783 } 1784 // create data pointer here 1785 dataSource->prepareImport(dataContainer, mode, actualRows, actualCols, vectorNames, columnModes); 1786 } 1787 1788 for (int c = startColumn - 1; c < endColumn; c++) { // columns 1789 int length = rdata[c].len; 1790 // DEBUG("length = " << length) 1791 /*for (hsize_t j = 0; j < length; j++) { 1792 printf (" %d", data[j]); 1793 if ((j+1) < length) 1794 printf (","); 1795 } 1796 printf (" }\n");*/ 1797 // read column 1798 if (H5Tequal(base_type, H5T_STD_I8LE) || H5Tequal(base_type, H5T_STD_I8BE)) 1799 HDF5_READ_VLEN_1D(qint8, int) 1800 else if (H5Tequal(base_type, H5T_STD_U8LE) || H5Tequal(base_type, H5T_STD_U8BE)) 1801 HDF5_READ_VLEN_1D(quint8, int) 1802 else if (H5Tequal(base_type, H5T_NATIVE_CHAR)) { 1803 switch (sizeof(H5T_NATIVE_CHAR)) { 1804 case 1: 1805 HDF5_READ_VLEN_1D(qint8, int) 1806 break; 1807 case 2: 1808 HDF5_READ_VLEN_1D(qint16, int) 1809 break; 1810 case 4: 1811 HDF5_READ_VLEN_1D(qint32, int) 1812 break; 1813 case 8: 1814 HDF5_READ_VLEN_1D(qint64, qint64) 1815 break; 1816 } 1817 } else if (H5Tequal(base_type, H5T_NATIVE_UCHAR)) { 1818 switch (sizeof(H5T_NATIVE_UCHAR)) { 1819 case 1: 1820 HDF5_READ_VLEN_1D(quint8, int) 1821 break; 1822 case 2: 1823 HDF5_READ_VLEN_1D(quint16, int) 1824 break; 1825 case 4: 1826 HDF5_READ_VLEN_1D(quint32, int) 1827 break; 1828 case 8: 1829 HDF5_READ_VLEN_1D(quint64, qint64) 1830 break; 1831 } 1832 } else if (H5Tequal(base_type, H5T_STD_I16LE) || H5Tequal(base_type, H5T_STD_I16BE) || H5Tequal(base_type, H5T_NATIVE_SHORT)) 1833 HDF5_READ_VLEN_1D(qint16, int) 1834 else if (H5Tequal(base_type, H5T_STD_U16LE) || H5Tequal(base_type, H5T_STD_U16BE) || H5Tequal(base_type, H5T_NATIVE_USHORT)) 1835 HDF5_READ_VLEN_1D(quint16, int) 1836 else if (H5Tequal(base_type, H5T_STD_I32LE) || H5Tequal(base_type, H5T_STD_I32BE) || H5Tequal(base_type, H5T_NATIVE_INT)) 1837 HDF5_READ_VLEN_1D(qint32, int) 1838 else if (H5Tequal(base_type, H5T_STD_U32LE) || H5Tequal(base_type, H5T_STD_U32BE) || H5Tequal(base_type, H5T_NATIVE_UINT)) 1839 HDF5_READ_VLEN_1D(quint32, qint64) 1840 else if (H5Tequal(base_type, H5T_NATIVE_LONG)) 1841 HDF5_READ_VLEN_1D(long, qint64) 1842 else if (H5Tequal(base_type, H5T_NATIVE_ULONG)) 1843 HDF5_READ_VLEN_1D(unsigned long, qint64) 1844 else if (H5Tequal(base_type, H5T_STD_I64LE) || H5Tequal(base_type, H5T_STD_I64BE) || H5Tequal(base_type, H5T_NATIVE_LLONG)) 1845 HDF5_READ_VLEN_1D(qint64, qint64) 1846 else if (H5Tequal(base_type, H5T_STD_U64LE) || H5Tequal(base_type, H5T_STD_U64BE) || H5Tequal(base_type, H5T_NATIVE_ULLONG)) 1847 HDF5_READ_VLEN_1D(quint64, qint64) 1848 else if (H5Tequal(base_type, H5T_IEEE_F32LE) || H5Tequal(base_type, H5T_IEEE_F32BE)) 1849 HDF5_READ_VLEN_1D(float, double) 1850 else if (H5Tequal(base_type, H5T_IEEE_F64LE) || H5Tequal(base_type, H5T_IEEE_F64BE)) 1851 HDF5_READ_VLEN_1D(double, double) 1852 else if (H5Tequal(base_type, H5T_NATIVE_LDOUBLE)) 1853 HDF5_READ_VLEN_1D(double, double) // long double not supported from QString::number 1854 else { 1855 dataString = (QStringList() << i18n("unsupported integer type for rank 1")); 1856 QDEBUG(dataString); 1857 } 1858 } 1859 1860 free(rdata); 1861 break; 1862 } 1863 case H5T_TIME: 1864 case H5T_BITFIELD: 1865 case H5T_OPAQUE: 1866 case H5T_REFERENCE: 1867 case H5T_ENUM: 1868 case H5T_ARRAY: 1869 case H5T_NO_CLASS: 1870 case H5T_NCLASSES: { 1871 ok = false; 1872 dataString = (QStringList() << i18n("rank 1 not implemented yet for type %1", translateHDF5Class(dclass))); 1873 QDEBUG(dataString); 1874 } 1875 default: 1876 break; 1877 } 1878 1879 if (!dataSource && dclass != H5T_VLEN) { // preview (VLEN is special) 1880 QDEBUG("dataString =" << dataString); 1881 DEBUG(" data string size = " << dataString.size()); 1882 DEBUG(" rows = " << rows << ", lines = " << lines << ", actual rows = " << actualRows); 1883 for (int i = 0; i < std::min(actualRows, lines); ++i) 1884 dataStrings << (QStringList() << dataString[i]); 1885 } 1886 1887 break; 1888 } 1889 case 2: { // 2D data 1890 hsize_t dims_out[2]; 1891 m_status = H5Sget_simple_extent_dims(dataspace, dims_out, nullptr); 1892 handleError(m_status, QStringLiteral("H5Sget_simple_extent_dims")); 1893 int rows = dims_out[0]; 1894 int cols = dims_out[1]; 1895 1896 if (endRow == -1) 1897 endRow = rows; 1898 if (lines == -1) 1899 lines = endRow; 1900 if (endColumn == -1) 1901 endColumn = cols; 1902 actualRows = endRow - startRow + 1; 1903 actualCols = endColumn - startColumn + 1; 1904 1905 #ifndef NDEBUG 1906 H5T_order_t order = H5Tget_order(dtype); 1907 handleError((int)order, QStringLiteral("H5Tget_order")); 1908 #endif 1909 // QDEBUG(translateHDF5Class(dclass) << '(' << typeSize << ')' << translateHDF5Order(order) << "," << rows << "x" << cols); 1910 DEBUG(Q_FUNC_INFO << ", start/end row = " << startRow << "/" << endRow); 1911 DEBUG(Q_FUNC_INFO << ", start/end column = " << startColumn << "/" << endColumn); 1912 DEBUG(Q_FUNC_INFO << ", actual rows/cols = " << actualRows << "/" << actualCols); 1913 DEBUG(Q_FUNC_INFO << ", lines = " << lines); 1914 1915 QVector<AbstractColumn::ColumnMode> columnModes; 1916 columnModes.resize(actualCols); 1917 // set other modes 1918 if (dclass == H5T_STRING) 1919 for (auto& mode : columnModes) 1920 mode = AbstractColumn::ColumnMode::Text; 1921 else if (dclass == H5T_INTEGER) { 1922 if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG) || H5Tequal(dtype, H5T_STD_U64LE) 1923 || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) 1924 for (auto& mode : columnModes) 1925 mode = AbstractColumn::ColumnMode::BigInt; 1926 else 1927 for (auto& mode : columnModes) 1928 mode = AbstractColumn::ColumnMode::Integer; 1929 } 1930 1931 // use current data set name (without path) append by "_" and column number for column names 1932 QStringList vectorNames; 1933 QString colName = currentDataSetName.mid(currentDataSetName.lastIndexOf(QLatin1Char('/')) + 1); 1934 for (int i = 0; i < actualCols; i++) 1935 vectorNames << colName + QLatin1String("_") + QString::number(i + 1); 1936 QDEBUG(Q_FUNC_INFO << ", vector names = " << vectorNames) 1937 1938 if (dataSource) 1939 columnOffset = dataSource->prepareImport(dataContainer, mode, actualRows, actualCols, vectorNames, columnModes); 1940 1941 // read data 1942 switch (dclass) { 1943 case H5T_INTEGER: { 1944 if (H5Tequal(dtype, H5T_STD_I8LE)) 1945 dataStrings << readHDF5Data2D<qint8>(dataset, H5T_STD_I8LE, rows, cols, lines, dataContainer); 1946 else if (H5Tequal(dtype, H5T_STD_I8BE)) 1947 dataStrings << readHDF5Data2D<qint8>(dataset, H5T_STD_I8BE, rows, cols, lines, dataContainer); 1948 else if (H5Tequal(dtype, H5T_NATIVE_CHAR)) { 1949 switch (sizeof(H5T_NATIVE_CHAR)) { 1950 case 1: 1951 dataStrings << readHDF5Data2D<qint8>(dataset, H5T_NATIVE_CHAR, rows, cols, lines, dataContainer); 1952 break; 1953 case 2: 1954 dataStrings << readHDF5Data2D<qint16>(dataset, H5T_NATIVE_CHAR, rows, cols, lines, dataContainer); 1955 break; 1956 case 4: 1957 dataStrings << readHDF5Data2D<qint32>(dataset, H5T_NATIVE_CHAR, rows, cols, lines, dataContainer); 1958 break; 1959 case 8: 1960 dataStrings << readHDF5Data2D<qint64>(dataset, H5T_NATIVE_CHAR, rows, cols, lines, dataContainer); 1961 break; 1962 } 1963 } else if (H5Tequal(dtype, H5T_STD_U8LE)) 1964 dataStrings << readHDF5Data2D<uint8_t>(dataset, H5T_STD_U8LE, rows, cols, lines, dataContainer); 1965 else if (H5Tequal(dtype, H5T_STD_U8BE)) 1966 dataStrings << readHDF5Data2D<uint8_t>(dataset, H5T_STD_U8BE, rows, cols, lines, dataContainer); 1967 else if (H5Tequal(dtype, H5T_NATIVE_UCHAR)) { 1968 switch (sizeof(H5T_NATIVE_UCHAR)) { 1969 case 1: 1970 dataStrings << readHDF5Data2D<uint8_t>(dataset, H5T_NATIVE_UCHAR, rows, cols, lines, dataContainer); 1971 break; 1972 case 2: 1973 dataStrings << readHDF5Data2D<uint16_t>(dataset, H5T_NATIVE_UCHAR, rows, cols, lines, dataContainer); 1974 break; 1975 case 4: 1976 dataStrings << readHDF5Data2D<uint32_t>(dataset, H5T_NATIVE_UCHAR, rows, cols, lines, dataContainer); 1977 break; 1978 case 8: 1979 dataStrings << readHDF5Data2D<uint64_t>(dataset, H5T_NATIVE_UCHAR, rows, cols, lines, dataContainer); 1980 break; 1981 } 1982 } else if (H5Tequal(dtype, H5T_STD_I16LE) || H5Tequal(dtype, H5T_STD_I16BE) || H5Tequal(dtype, H5T_NATIVE_SHORT)) 1983 dataStrings << readHDF5Data2D<short>(dataset, H5T_NATIVE_SHORT, rows, cols, lines, dataContainer); 1984 else if (H5Tequal(dtype, H5T_STD_U16LE) || H5Tequal(dtype, H5T_STD_U16BE) || H5Tequal(dtype, H5T_NATIVE_USHORT)) 1985 dataStrings << readHDF5Data2D<unsigned short>(dataset, H5T_NATIVE_USHORT, rows, cols, lines, dataContainer); 1986 else if (H5Tequal(dtype, H5T_STD_I32LE) || H5Tequal(dtype, H5T_STD_I32BE) || H5Tequal(dtype, H5T_NATIVE_INT)) 1987 dataStrings << readHDF5Data2D<int>(dataset, H5T_NATIVE_INT, rows, cols, lines, dataContainer); 1988 else if (H5Tequal(dtype, H5T_STD_U32LE) || H5Tequal(dtype, H5T_STD_U32BE) || H5Tequal(dtype, H5T_NATIVE_UINT)) 1989 dataStrings << readHDF5Data2D<unsigned int>(dataset, H5T_NATIVE_UINT, rows, cols, lines, dataContainer); 1990 else if (H5Tequal(dtype, H5T_NATIVE_LONG)) 1991 dataStrings << readHDF5Data2D<long>(dataset, H5T_NATIVE_LONG, rows, cols, lines, dataContainer); 1992 else if (H5Tequal(dtype, H5T_NATIVE_ULONG)) 1993 dataStrings << readHDF5Data2D<unsigned long>(dataset, H5T_NATIVE_ULONG, rows, cols, lines, dataContainer); 1994 else if (H5Tequal(dtype, H5T_STD_I64LE) || H5Tequal(dtype, H5T_STD_I64BE) || H5Tequal(dtype, H5T_NATIVE_LLONG)) 1995 dataStrings << readHDF5Data2D<long long>(dataset, H5T_NATIVE_LLONG, rows, cols, lines, dataContainer); 1996 else if (H5Tequal(dtype, H5T_STD_U64LE) || H5Tequal(dtype, H5T_STD_U64BE) || H5Tequal(dtype, H5T_NATIVE_ULLONG)) 1997 dataStrings << readHDF5Data2D<unsigned long long>(dataset, H5T_NATIVE_ULLONG, rows, cols, lines, dataContainer); 1998 else { 1999 ok = false; 2000 dataStrings << (QStringList() << i18n("unsupported integer type for rank 2")); 2001 // QDEBUG(dataStrings); 2002 } 2003 break; 2004 } 2005 case H5T_FLOAT: { 2006 if (H5Tequal(dtype, H5T_IEEE_F32LE) || H5Tequal(dtype, H5T_IEEE_F32BE)) 2007 dataStrings << readHDF5Data2D<float>(dataset, H5T_NATIVE_FLOAT, rows, cols, lines, dataContainer); 2008 else if (H5Tequal(dtype, H5T_IEEE_F64LE) || H5Tequal(dtype, H5T_IEEE_F64BE)) 2009 dataStrings << readHDF5Data2D<double>(dataset, H5T_NATIVE_DOUBLE, rows, cols, lines, dataContainer); 2010 else if (H5Tequal(dtype, H5T_NATIVE_LDOUBLE)) 2011 dataStrings << readHDF5Data2D<long double>(dataset, H5T_NATIVE_LDOUBLE, rows, cols, lines, dataContainer); 2012 else { 2013 ok = false; 2014 dataStrings << (QStringList() << i18n("unsupported float type for rank 2")); 2015 QDEBUG(dataStrings); 2016 } 2017 break; 2018 } 2019 case H5T_COMPOUND: { 2020 dataStrings << readHDF5Compound(dtype); 2021 // QDEBUG(dataStrings); 2022 dataStrings << readHDF5CompoundData2D(dataset, dtype, rows, cols, lines); 2023 break; 2024 } 2025 case H5T_STRING: { 2026 DEBUG("rank 2 H5T_STRING"); 2027 hid_t memtype = H5Tcopy(H5T_C_S1); 2028 handleError((int)memtype, QStringLiteral("H5Tcopy")); 2029 2030 char** data = (char**)malloc(rows * cols * sizeof(char*)); 2031 2032 if (H5Tis_variable_str(dtype)) { 2033 m_status = H5Tset_size(memtype, H5T_VARIABLE); 2034 handleError((int)memtype, QStringLiteral("H5Tset_size")); 2035 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); 2036 handleError(m_status, QStringLiteral("H5Dread")); 2037 } else { 2038 data[0] = (char*)malloc(rows * cols * typeSize * sizeof(char)); 2039 for (int i = 1; i < rows * cols; ++i) 2040 data[i] = data[0] + i * typeSize; 2041 2042 m_status = H5Tset_size(memtype, typeSize); 2043 handleError((int)memtype, QStringLiteral("H5Tset_size")); 2044 2045 m_status = H5Dread(dataset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data[0]); 2046 handleError(m_status, QStringLiteral("H5Dread")); 2047 } 2048 2049 if (dataSource) { 2050 for (int i = 0; i < actualRows; ++i) { 2051 for (int j = 0; j < actualCols; ++j) { 2052 static_cast<QVector<QString>*>(dataContainer[(int)(j)])->operator[](i) = 2053 QLatin1String(data[(j + startColumn - 1) + (i + startRow - 1) * cols]); 2054 } 2055 } 2056 } else { 2057 for (int i = startRow - 1; i < std::min(endRow, lines + startRow - 1); ++i) { 2058 QStringList row; 2059 for (int j = startColumn - 1; j < endColumn; ++j) 2060 row << QLatin1String(data[j + i * cols]); 2061 dataStrings << row; 2062 } 2063 } 2064 2065 free(data); 2066 break; 2067 } 2068 case H5T_TIME: 2069 case H5T_BITFIELD: 2070 case H5T_OPAQUE: 2071 case H5T_REFERENCE: 2072 case H5T_ENUM: 2073 case H5T_VLEN: 2074 case H5T_ARRAY: 2075 case H5T_NO_CLASS: 2076 case H5T_NCLASSES: { 2077 ok = false; 2078 dataStrings << (QStringList() << i18n("rank 2 not implemented yet for type %1", translateHDF5Class(dclass))); 2079 QDEBUG(dataStrings); 2080 } 2081 default: 2082 break; 2083 } 2084 break; 2085 } 2086 default: { // 3D or higher dim data 2087 ok = false; 2088 dataStrings << (QStringList() << i18n("rank %1 not implemented yet for type %2", rank, translateHDF5Class(dclass))); 2089 QDEBUG(dataStrings); 2090 } 2091 } 2092 2093 m_status = H5Sclose(dataspace); 2094 handleError(m_status, QStringLiteral("H5Sclose")); 2095 m_status = H5Tclose(dtype); 2096 handleError(m_status, QStringLiteral("H5Tclose")); 2097 m_status = H5Dclose(dataset); 2098 handleError(m_status, QStringLiteral("H5Dclose")); 2099 m_status = H5Fclose(file); 2100 handleError(m_status, QStringLiteral("H5Fclose")); 2101 2102 if (!dataSource) 2103 return dataStrings; 2104 2105 DEBUG(Q_FUNC_INFO << ", finalize : actual cols = " << actualCols) 2106 dataSource->finalizeImport(columnOffset, 1, actualCols, QString(), mode); 2107 #else 2108 Q_UNUSED(fileName) 2109 Q_UNUSED(dataSource) 2110 Q_UNUSED(mode) 2111 Q_UNUSED(lines) 2112 #endif 2113 2114 return dataStrings; 2115 } 2116 2117 /*! 2118 reads the content of the file \c fileName to the data source \c dataSource. 2119 Uses the settings defined in the data source. 2120 */ 2121 void HDF5FilterPrivate::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode mode) { 2122 DEBUG(Q_FUNC_INFO); 2123 2124 if (currentDataSetName.isEmpty()) { 2125 DEBUG("WARNING: No data set selected"); 2126 return; 2127 } 2128 2129 bool ok = true; 2130 readCurrentDataSet(fileName, dataSource, ok, mode); 2131 } 2132 2133 /*! 2134 writes the content of \c dataSource to the file \c fileName. 2135 */ 2136 void HDF5FilterPrivate::write(const QString& /*fileName*/, AbstractDataSource* /*dataSource*/) { 2137 // TODO: writing HDF5 not implemented yet 2138 } 2139 2140 // ############################################################################## 2141 // ################## Serialization/Deserialization ########################### 2142 // ############################################################################## 2143 2144 /*! 2145 Saves as XML. 2146 */ 2147 void HDF5Filter::save(QXmlStreamWriter* writer) const { 2148 writer->writeStartElement(QStringLiteral("hdfFilter")); 2149 writer->writeEndElement(); 2150 } 2151 2152 /*! 2153 Loads from XML. 2154 */ 2155 bool HDF5Filter::load(XmlStreamReader*) { 2156 return true; 2157 }