OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHdf5.cpp
Go to the documentation of this file.
1 //---
2 //
3 // License: MIT
4 //
5 // Description: OSSIM HDF5 utility class.
6 //
7 //---
8 // $Id
9 
10 #include <ossim/hdf5/ossimHdf5.h>
12 #include <ossim/base/ossimCommon.h>
13 #include <ossim/base/ossimNotify.h>
14 #include <ossim/base/ossimEndian.h>
15 #include <string>
16 
17 using namespace H5;
18 using namespace std;
19 
21 : m_h5File (0)
22 { }
23 
25 {
26  close();
27 }
28 
29 bool ossimHdf5::open(const ossimFilename& fullname)
30 {
31  // Check for empty filename.
32  if (fullname.empty())
33  return false;
34 
35  m_filename = fullname;
36  if (m_h5File && !close())
37  return false;
38 
39  // H5 lib throws exceptions:
40  bool success = false;
41  try
42  {
43  // Turn off the auto-printing when failure occurs so that we can handle the errors:
44  H5::Exception::dontPrint();
45  if ( H5File::isHdf5( m_filename.string() ) )
46  {
47  m_h5File = new H5File(m_filename.string(), H5F_ACC_RDONLY);
48  success = true;
49  }
50  }
51  catch( const H5::Exception& e )
52  {
53  success = false;
54  ossimNotify(ossimNotifyLevel_WARN) <<e.getDetailMsg() << std::endl;
55  }
56  catch( ... )
57  {
58  ossimNotify(ossimNotifyLevel_WARN)<< "ossimH5Info::open WARNING Caught unhandled exception "
59  "for file <"<< fullname <<">"<< std::endl;
60  success = false;
61  }
62 
63  if (!success)
64  {
65  delete m_h5File;
66  m_h5File = 0;
67  }
68 
69  return success;
70 }
71 
73 {
74  bool success = true;
75  if (m_h5File)
76  {
77  try
78  {
79  m_h5File->close();
80  delete m_h5File;
81  m_h5File = 0;
82  }
83  catch( const H5::Exception& e )
84  {
85  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
86  success = false;
87  }
88  }
89  return success;
90 }
91 
92 
93 bool ossimHdf5::getRoot(Group& root) const
94 {
95  if (!m_h5File)
96  return false;
97 
98  bool success = true;
99  try
100  {
101  root = m_h5File->openGroup("/");
102  }
103  catch( const H5::Exception& e )
104  {
105  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
106  success = false;
107  }
108  return success;
109 
110 }
111 
112 bool ossimHdf5::getChildGroups(H5::Group group, vector<Group>& groupList,
113  bool recursive)
114 {
115  bool success = true;
116 
117  int numObjs = 0;
118 
119  try
120  {
121  numObjs = group.getNumObjs();
122  }
123  catch( const H5::Exception& e )
124  {
125  e.getDetailMsg();
126  success = false;
127  }
128  for (int i=0; (i<numObjs) && success; ++i)
129  {
130  try
131  {
132  H5G_obj_t h5type = group.getObjTypeByIdx(i);
133  if (h5type == H5G_GROUP)
134  {
135  string name = group.getObjnameByIdx(i);
136  groupList.push_back(group.openGroup(name));
137  if (recursive)
138  success = getChildGroups(groupList.back(), groupList, true);
139  }
140  }
141  catch( const H5::Exception& e )
142  {
143  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
144  success = false;
145  }
146  }
147  return success;
148 }
149 
150 bool ossimHdf5::getDatasets(H5::Group group, vector<DataSet>& datasetList,
151  bool recursive)
152 {
153  datasetList.clear();
154  vector<Group> groupList;
155  if (recursive)
156  {
157  getChildGroups(group, groupList, true);
158  }
159  groupList.insert(groupList.begin(), group);
160 
161  bool success = true;
162  try
163  {
164  vector<Group>::iterator group_iter = groupList.begin();
165  while (group_iter != groupList.end())
166  {
167  int numObjs = group_iter->getNumObjs();
168  for (int i=0; i<numObjs; ++i)
169  {
170  H5G_obj_t h5type = group_iter->getObjTypeByIdx(i);
171  if (h5type == H5G_DATASET)
172  {
173  string name = group_iter->getObjnameByIdx(i);
174  datasetList.push_back(group_iter->openDataSet(name));
175  }
176  }
177  ++group_iter;
178  }
179  }
180  catch( const H5::Exception& e )
181  {
182  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
183  success = false;
184  }
185  return success;
186 }
187 
188 bool ossimHdf5::getNdimDatasets(H5::Group group, vector<DataSet>& datasetList,
189  bool recursive)
190 {
191  datasetList.clear();
192  vector<Group> groupList;
193  if (recursive)
194  getChildGroups(group, groupList, true);
195  groupList.insert(groupList.begin(), group);
196 
197  bool success = true;
198  try
199  {
200  vector<Group>::iterator group_iter = groupList.begin();
201  while (group_iter != groupList.end())
202  {
203  int numObjs = group_iter->getNumObjs();
204  for (int i=0; i<numObjs; ++i)
205  {
206  H5G_obj_t h5type = group_iter->getObjTypeByIdx(i);
207  if (h5type == H5G_DATASET)
208  {
209  string name = group_iter->getObjnameByIdx(i);
210  DataSet dataset (group_iter->openDataSet(name));
211  DataSpace dspace (dataset.getSpace());
212  if (dspace.getSimpleExtentNdims() > 1)
213  datasetList.push_back(dataset);
214  }
215  }
216  ++group_iter;
217  }
218  }
219  catch( const H5::Exception& e )
220  {
221  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
222  success = false;
223  }
224  return success;
225 }
226 
227 bool ossimHdf5::getAttributes(const H5Object& obj, vector<Attribute>& attrList)
228 {
229  attrList.clear();
230 
231  // Find the object:
232  bool success = true;
233  try
234  {
235  int numAttr = obj.getNumAttrs();
236  for (int i=0; i<numAttr; ++i)
237  {
238  attrList.push_back(obj.openAttribute(i));
239  }
240  }
241  catch( const H5::Exception& e )
242  {
243  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
244  success = false;
245  }
246 
247  return success;
248 }
249 
250 
251 H5::Group* ossimHdf5::findGroupByName(const std::string& name, const H5::Group* parent, bool recursive)const
252 {
253  if (name.empty())
254  return NULL;
255 
256  H5::Group baseGroup;
257  if (parent == NULL)
258  {
259  if (!getRoot(baseGroup))
260  return NULL;
261  }
262  else
263  {
264  baseGroup = *parent;
265  }
266 
267  H5::Group* named_group = 0;
268  vector<Group> groupList;
269  if (!getChildGroups(baseGroup, groupList, recursive))
270  return NULL;
271 
272  try
273  {
274  std::vector<Group>::iterator group = groupList.begin();
275  while (group != groupList.end())
276  {
277  // bool found;
278  ossimString dsName = group->getObjName();
279  if (dsName.contains(name))
280  {
281  named_group = new Group(*group);
282  break;
283  }
284  ++group;
285  }
286  }
287  catch( const H5::Exception& e )
288  {
289  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
290  }
291 
292  return named_group;
293 }
294 
295 H5::DataSet* ossimHdf5::findDatasetByName(const std::string& name, const H5::Group* group,
296  bool recursive)const
297 {
298  if (name.empty())
299  return NULL;
300 
301  H5::Group baseGroup;
302  if (group == NULL)
303  {
304  if (!getRoot(baseGroup))
305  return NULL;
306  }
307  else
308  {
309  baseGroup = *group;
310  }
311  H5::DataSet* named_dataset = 0;
312  vector<DataSet> datasetList;
313  if (!getDatasets(baseGroup, datasetList, recursive))
314  return NULL;
315  try
316  {
317  std::vector<H5::DataSet>::iterator dataset = datasetList.begin();
318  while (dataset != datasetList.end())
319  {
320  // bool found;
321  ossimString dsName = dataset->getObjName();
322  if (dsName.contains(name))
323  {
324  named_dataset = new H5::DataSet(*dataset);
325  break;
326  }
327  ++dataset;
328  }
329  }
330  catch( const H5::Exception& e )
331  {
332  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
333  }
334  return named_dataset;
335 }
336 
337 ossimByteOrder ossimHdf5::getByteOrder( const H5::AbstractDs* obj )
338 {
340  if ( obj )
341  {
342  try
343  {
344 
345  // Get the class of the datatype that is used by the dataset.
346  H5T_class_t typeClass = obj->getTypeClass();
347 
348  H5T_order_t order = H5T_ORDER_NONE;
349 
350  if ( typeClass == H5T_INTEGER )
351  {
352  H5::IntType intype = obj->getIntType();
353  order = intype.getOrder();
354  }
355  else if ( typeClass == H5T_FLOAT )
356  {
357  H5::FloatType floatType = obj->getFloatType();
358  order = floatType.getOrder();
359  }
360 
361  if ( order == H5T_ORDER_LE )
362  {
364  }
365  else if ( order == H5T_ORDER_BE )
366  {
368  }
369  }
370  catch( const H5::Exception& e )
371  {
372  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
373  }
374  }
375  return byteOrder;
376 }
377 
378 ossimByteOrder ossimHdf5::getByteOrder( const H5::AtomType& obj )
379 {
381  H5T_order_t order = obj.getOrder();
382  if ( order == H5T_ORDER_LE )
383  {
385  }
386  else if ( order == H5T_ORDER_BE )
387  {
389  }
390 
391  return byteOrder;
392 }
393 
394 
396 {
397  H5T_class_t classType = (H5T_class_t)type;
398 
399  std::string result;
400  switch ( classType )
401  {
402  case H5T_INTEGER:
403  result = "H5T_INTEGER";
404  break;
405  case H5T_FLOAT:
406  result = "H5T_FLOAT";
407  break;
408  case H5T_TIME:
409  result = "H5T_TIME";
410  break;
411  case H5T_STRING:
412  result = "H5T_STRING";
413  break;
414  case H5T_BITFIELD:
415  result = "H5T_BITFIELD";
416  break;
417  case H5T_OPAQUE:
418  result = "H5T_OPAQUE";
419  break;
420  case H5T_COMPOUND:
421  result = "H5T_COMPOUND";
422  break;
423  case H5T_REFERENCE:
424  result = "H5T_REFERENCE";
425  break;
426  case H5T_ENUM:
427  result = "H5T_ENUM";
428  break;
429  case H5T_VLEN:
430  result = "H5T_VLEN";
431  break;
432  case H5T_ARRAY:
433  result = "H5T_ARRAY";
434  break;
435  case H5T_NO_CLASS:
436  default:
437  result = "H5T_NO_CLASS";
438  break;
439  }
440  return result;
441 }
442 
443 
444 void ossimHdf5::getExtents( const H5::DataSet& dataset, std::vector<ossim_uint32>& extents )
445 {
446  extents.clear();
447 
448  try
449  {
450  // Get dataspace of the dataset.
451  H5::DataSpace dataspace = dataset.getSpace();
452 
453  // Number of dimensions:
454  int ndims = dataspace.getSimpleExtentNdims();
455  if ( ndims )
456  {
457  //hsize_t dims_out[ndims];
458  std::vector<hsize_t> dims_out(ndims);
459  dataspace.getSimpleExtentDims( &dims_out.front(), 0 );
460  for ( ossim_int32 i = 0; i < ndims; ++i )
461  {
462  extents.push_back(static_cast<ossim_uint32>(dims_out[i]));
463  }
464  }
465 
466  dataspace.close();
467  }
468  catch( const H5::Exception& e )
469  {
470  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
471  }
472 }
473 
474 
475 ossimScalarType ossimHdf5::getScalarType( const H5::DataSet& dataset )
476 {
478 
479  try
480  {
481 
482  H5::DataType datatype = dataset.getDataType();
483  ossim_int32 typeClass = datatype.getClass();
484  if ( ( typeClass != H5T_INTEGER ) && ( typeClass != H5T_FLOAT ) )
485  return scalar;
486 
487  size_t size = 0;
488  hid_t mem_type_id = H5Dget_type( datatype.getId() );
489  if( mem_type_id > -1 )
490  {
491  hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
492 
493  if( H5Tequal(H5T_NATIVE_CHAR, native_type) )
494  scalar = OSSIM_SINT8;
495  else if ( H5Tequal( H5T_NATIVE_UCHAR, native_type) )
496  scalar = OSSIM_UINT8;
497  else if( H5Tequal( H5T_NATIVE_SHORT, native_type) )
498  scalar = OSSIM_SINT16;
499  else if(H5Tequal(H5T_NATIVE_USHORT, native_type))
500  scalar = OSSIM_UINT16;
501  else if(H5Tequal( H5T_NATIVE_INT, native_type))
502  scalar = OSSIM_SINT32;
503  else if(H5Tequal( H5T_NATIVE_UINT, native_type ) )
504  scalar = OSSIM_UINT32;
505  else if(H5Tequal( H5T_NATIVE_LONG, native_type))
506  scalar = OSSIM_SINT32;
507  else if(H5Tequal( H5T_NATIVE_ULONG, native_type))
508  scalar = OSSIM_UINT32;
509  else if(H5Tequal( H5T_NATIVE_LLONG, native_type))
510  scalar = OSSIM_SINT64;
511  else if(H5Tequal( H5T_NATIVE_ULLONG, native_type))
512  scalar = OSSIM_UINT64;
513  else if(H5Tequal( H5T_NATIVE_FLOAT, native_type))
514  scalar = OSSIM_FLOAT32;
515  else if(H5Tequal( H5T_NATIVE_DOUBLE, native_type))
516  scalar = OSSIM_FLOAT64;
517  }
518  else if ( typeClass == H5T_INTEGER )
519  {
520  H5::IntType intType (dataset);
521  bool isSigned = intType.getSign() == H5T_SGN_NONE ? false : true;
522  size = intType.getSize();
523  switch (size)
524  {
525  case 1:
526  if (isSigned)
527  scalar = OSSIM_SINT8;
528  else
529  scalar = OSSIM_UINT8;
530  break;
531  case 2:
532  if (isSigned)
533  scalar = OSSIM_SINT16;
534  else
535  scalar = OSSIM_UINT16;
536  break;
537  case 4:
538  if (isSigned)
539  scalar = OSSIM_SINT32;
540  else
541  scalar = OSSIM_UINT32;
542  break;
543  case 8:
544  if (isSigned)
545  scalar = OSSIM_SINT64;
546  else
547  scalar = OSSIM_UINT64;
548  break;
549  default:
550  break;
551  }
552  }
553  else // float
554  {
555  size = datatype.getSize();
556  switch (size)
557  {
558  case 4:
559  scalar = OSSIM_FLOAT32;
560  break;
561  case 8:
562  scalar = OSSIM_FLOAT64;
563  break;
564  default:
565  break;
566  }
567  }
568  }
569  catch( const H5::Exception& e )
570  {
571  ossimNotify(ossimNotifyLevel_WARN)<<e.getDetailMsg();
572  }
573 
574  return scalar;
575 }
576 
577 bool ossimHdf5::floatTypeToString(std::string& result,
578  const H5::FloatType& dataType,
579  const char* dataPtr)
580 {
581  char* buf = const_cast<char*>(dataPtr);
582  ossim_uint32 dataSize = dataType.getSize();
583  ossimByteOrder order = getByteOrder(dataType);
584  ossimEndian endian;
585  bool swapOrder = (order!=ossim::byteOrder());
586  bool returnValue = true;
587  switch(dataSize)
588  {
589  case 4:
590  {
591  ossim_float32* float_value=0;
592  float_value = reinterpret_cast<ossim_float32*>(buf);
593  if (swapOrder)
594  endian.swap(*float_value);
595  result = ossimString::toString(*float_value).string();
596  break;
597  }
598  case 8:
599  {
600  ossim_float64* float_value=0;
601  float_value = reinterpret_cast<ossim_float64*>(buf);
602  if (swapOrder)
603  endian.swap(*float_value);
604  result = ossimString::toString(*float_value).string();
605  break;
606  }
607  default:
608  {
609  returnValue = false;
610  break;
611  }
612  }
613  return returnValue;
614 }
615 
616 bool ossimHdf5::intTypeToString(std::string& result,
617  const H5::IntType& dataType,
618  const char* dataPtr)
619 {
620  char* buf = const_cast<char*>(dataPtr);
621  ossim_uint32 signType = H5Tget_sign(dataType.getId());
622  ossim_uint32 dataSize = dataType.getSize();
623  ossimByteOrder order = getByteOrder(dataType);
624  ossimEndian endian;
625  bool swapOrder = (order!=ossim::byteOrder());
626  bool returnValue = true;
627  switch(dataSize)
628  {
629  case 1: // one byte integer
630  {
631  switch(signType)
632  {
633  case H5T_SGN_NONE:
634  {
635  ossim_uint8* intValue=0;
636  intValue = reinterpret_cast<ossim_uint8*>(buf);
637  result = ossimString::toString(*intValue).string();
638 
639  break;
640  }
641  case H5T_SGN_2:
642  {
643  ossim_int8* intValue=0;
644  intValue = reinterpret_cast<ossim_int8*>(buf);
645  result = ossimString::toString(*intValue).string();
646 
647  break;
648  }
649  default:
650  {
651  returnValue = false;
652  break;
653  }
654  }
655  break;
656  }
657  case 2: // 2 byte integer
658  {
659  switch(signType)
660  {
661  case H5T_SGN_NONE: // unsigned
662  {
663  ossim_uint16* intValue=0;
664  intValue = reinterpret_cast<ossim_uint16*>(buf);
665  if (swapOrder)
666  endian.swap(*intValue);
667  result = ossimString::toString(*intValue).string();
668 
669  break;
670  }
671  case H5T_SGN_2: // Signed
672  {
673  ossim_int16* intValue=0;
674  intValue = reinterpret_cast<ossim_int16*>(buf);
675  if (swapOrder)
676  endian.swap(*intValue);
677  result = ossimString::toString(*intValue).string();
678  break;
679  }
680  default:
681  {
682  returnValue = false;
683  break;
684  }
685 
686  }
687  break;
688  }
689  case 4: // 4 byte integer
690  {
691  switch(signType)
692  {
693  case H5T_SGN_NONE:
694  {
695  ossim_uint32* intValue=0;
696  intValue = reinterpret_cast<ossim_uint32*>(buf);
697  if (swapOrder)
698  endian.swap(*intValue);
699  result = ossimString::toString(*intValue).string();
700 
701  break;
702  }
703  case H5T_SGN_2:
704  {
705  ossim_int32* intValue=0;
706  intValue = reinterpret_cast<ossim_int32*>(buf);
707  if (swapOrder)
708  endian.swap(*intValue);
709  result = ossimString::toString(*intValue).string();
710  break;
711  }
712  default:
713  {
714  returnValue = false;
715  break;
716  }
717  }
718  break;
719  }
720  case 8: // 8 byte integer
721  {
722  switch(signType)
723  {
724  case H5T_SGN_NONE:
725  {
726  ossim_uint64* intValue=0;
727  intValue = reinterpret_cast<ossim_uint64*>(buf);
728  if (swapOrder)
729  endian.swap(*intValue);
730  result = ossimString::toString(*intValue).string();
731 
732  break;
733  }
734  case H5T_SGN_2:
735  {
736  ossim_int64* intValue=0;
737  intValue = reinterpret_cast<ossim_int64*>(buf);
738  if (swapOrder)
739  endian.swap(*intValue);
740  result = ossimString::toString(*intValue).string();
741  break;
742  }
743  default:
744  {
745  returnValue = false;
746  break;
747  }
748  }
749  break;
750  }
751  default:
752  {
753  returnValue = false;
754  }
755  }
756 
757  return returnValue;
758 }
759 
760 bool ossimHdf5::stringTypeToString(std::string& result,
761  const H5::StrType& dataType,
762  const char* dataPtr)
763 {
764  bool returnValue = false;
765  const char* startPtr = dataPtr;
766  const char* endPtr = dataPtr;
767  const char* maxPtr = dataPtr + dataType.getSize();
768  if(dataPtr)
769  {
770  while((endPtr != maxPtr)&&(*endPtr!='\0')) ++endPtr;
771  result = std::string(startPtr, endPtr);
772  bool returnValue = true;
773  }
774 
775  return returnValue;
776 }
8 bit signed integer
char ossim_int8
Previous DLL import export section.
64 bit floating point
bool getRoot(H5::Group &root) const
Assigns the root group.
Definition: ossimHdf5.cpp:93
16 bit unsigned integer
float ossim_float32
bool contains(char aChar) const
Definition: ossimString.h:58
static ossimString toString(bool aValue)
Numeric to string methods.
16 bit signed integer
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
32 bit floating point
unsigned short ossim_uint16
32 bit unsigned integer
bool open(const ossimFilename &hdf5File)
Opens specified HDF5 file.
Definition: ossimHdf5.cpp:29
static bool getDatasets(H5::Group group, std::vector< H5::DataSet > &datasetList, bool recursive=false)
Assigns list of datasets under specified group.
Definition: ossimHdf5.cpp:150
double ossim_float64
OSSIM_DLL bool isSigned(ossimScalarType scalarType)
static ossimByteOrder getByteOrder(const H5::AbstractDs *obj)
Definition: ossimHdf5.cpp:337
ossimFilename m_filename
Definition: ossimHdf5.h:112
static ossimScalarType getScalarType(const H5::DataSet &dataset)
Definition: ossimHdf5.cpp:475
yy_size_t size
bool close()
Closes the file and deletes all pointers.
Definition: ossimHdf5.cpp:72
64 bit signed integer
H5::Group * findGroupByName(const std::string &group_name, const H5::Group *parent_group=0, bool recursive=false) const
Finds a group by name.
Definition: ossimHdf5.cpp:251
32 bit signed integer
static std::string getDatatypeClassType(ossim_int32 type)
Definition: ossimHdf5.cpp:395
unsigned long long ossim_uint64
unsigned int ossim_uint32
static bool getChildGroups(H5::Group group, std::vector< H5::Group > &groupList, bool recursive=false)
Assigns list of groups under specified group.
Definition: ossimHdf5.cpp:112
static bool stringTypeToString(std::string &result, const H5::StrType &dataType, const char *dataPtr)
Definition: ossimHdf5.cpp:760
ossimByteOrder
static bool floatTypeToString(std::string &result, const H5::FloatType &dataType, const char *dataPtr)
Definition: ossimHdf5.cpp:577
static bool getAttributes(const H5::H5Object &obj, std::vector< H5::Attribute > &attrList)
Definition: ossimHdf5.cpp:227
ossimScalarType
short ossim_int16
H5::DataSet * findDatasetByName(const std::string &dataset_name, const H5::Group *group=0, bool recursive=false) const
Finds a dataset by name.
Definition: ossimHdf5.cpp:295
64 bit unsigned integer
static void getExtents(const H5::DataSet &dataset, std::vector< ossim_uint32 > &extents)
Definition: ossimHdf5.cpp:444
long long ossim_int64
bool empty() const
Definition: ossimString.h:411
8 bit unsigned integer
static bool getNdimDatasets(H5::Group group, std::vector< H5::DataSet > &datasetList, bool recursive=false)
Assigns list of all multi-dimensional datasets under current active group.
Definition: ossimHdf5.cpp:188
H5::H5File * m_h5File
Definition: ossimHdf5.h:113
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
unsigned char ossim_uint8
static bool intTypeToString(std::string &result, const H5::IntType &dataType, const char *dataPtr)
Definition: ossimHdf5.cpp:616
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414