OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimH5Util.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: David Burken
8 //
9 // Description: OSSIM HDF5 utility class.
10 //
11 //----------------------------------------------------------------------------
12 // $Id
13 
14 #include "ossimH5Util.h"
15 #include "ossimH5Options.h"
16 
17 #include <ossim/base/ossimCommon.h>
18 #include <ossim/base/ossimEndian.h>
19 #include <ossim/base/ossimIrect.h>
21 #include <ossim/base/ossimNotify.h>
23 #include <ossim/base/ossimTrace.h>
25 
26 //---
27 // This includes everything! Note the H5 includes are order dependent; hence,
28 // the mongo include.
29 //---
30 #include <hdf5.h>
31 #include <H5Cpp.h>
32 
33 #include <iomanip> /* tmp */
34 #include <iostream> /* tmp */
35 #include <ostream>
36 #include <iterator>
37 using namespace std;
38 
39 static ossimTrace traceDebug("ossimH5Util:debug");
40 
42 {
43  if ( file )
44  {
45  std::string groupName = "/";
46  std::string prefix = "hdf5";
47  ossim_uint32 recurseCount = 0;
48 
49  std::vector<std::string> datasetNames;
50 
51 
52  getDatasetNames(file, datasetNames );
53 
54 //std::cout << "DATASET NAMES ======= " << datasetNames.size() << "\n";
55  ossim_uint32 datasetNameIdx = 0;
56  ossimString dataSetNamesStr;
57  for(;datasetNameIdx<datasetNames.size();++datasetNameIdx)
58  {
59  if(dataSetNamesStr.empty())
60  {
61  dataSetNamesStr = datasetNames[datasetNameIdx];
62  }
63  else
64  {
65  dataSetNamesStr = dataSetNamesStr + ", " + datasetNames[datasetNameIdx];
66  }
67  }
68  if(!dataSetNamesStr.empty())
69  {
70  out << prefix << ".datasetnames: " << dataSetNamesStr << "\n";
71  }
72 
73  ossim_hdf5::printIterative( file, groupName, prefix, recurseCount, out );
74  }
75 
76  return out;
77 }
78 
79 void ossim_hdf5::printIterative( H5::H5File* file,
80  const std::string& groupName,
81  const std::string& prefix,
82  ossim_uint32& recursedCount,
83  std::ostream& out )
84 {
85  if ( file && groupName.size() )
86  {
87  ++recursedCount;
88 
89  H5::Group* group = new H5::Group( file->openGroup(groupName) );
90 
91  // Print attributes:
92  const ossim_uint32 ATTRS_COUNT = group->getNumAttrs();
93  for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
94  {
95  H5::Attribute attr( group->openAttribute( aIdx ) );
96  ossim_hdf5::printAttribute( attr, prefix, out );
97  }
98 
99  const hsize_t OBJ_COUNT = group->getNumObjs();
100  for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
101  {
102  std::string objName = group->getObjnameByIdx(i);
103 
104  if ( objName.size() )
105  {
106  char separator = '/';
107  std::string combinedName;
108  combine( groupName, objName, separator, combinedName );
109 
110  separator = '.';
111  std::string combinedPrefix;
112  combine( prefix, objName, separator, combinedPrefix );
113 
114  H5G_obj_t objType = group->getObjTypeByIdx(i);
115 
116 #if 0
117  std::cout << "combinedName: " << combinedName
118  << "\ncombinedPrefix: " << combinedPrefix
119  << "\ngetObjnameByIdx[" << i << "]: " << objName
120  << "\ngetObjTypeByIdx[" << i << "]: " << objType
121  << std::endl;
122 #endif
123 
124  if ( objType == H5G_GROUP )
125  {
126  // Recursive call:
127  if ( recursedCount < ossimH5Options::instance()->getMaxRecursionLevel())//ossim_hdf5::MAX_RECURSION_LEVEL )
128  {
130  file, combinedName, combinedPrefix, recursedCount, out );
131  }
132  else
133  {
135  << "ossim_hdf5::printIterative WARNING!"
136  << "\nMax iterations reached!" << std::endl;
137  }
138  }
139  else if ( objType == H5G_DATASET )
140  {
141  printObject( file, combinedName, combinedPrefix, out );
142  }
143  else
144  {
146  << "ossim_hdf5::printIterative WARNING!"
147  << "\nUnhandled object type: " << objType << std::endl;
148  }
149  }
150  }
151 
152  group->close();
153  delete group;
154  group = 0;
155  --recursedCount;
156 
157  } // Matches: if ( file )
158 
159 } // End: void ossim_hdf5::printIterative method.
160 
161 void ossim_hdf5::printObject( H5::H5File* file,
162  const std::string& objectName,
163  const std::string& prefix,
164  std::ostream& out )
165 {
166 #if 0
167  std::cout << "printObject entered..."
168  << "\nobjectName: " << objectName
169  << "\nprefix: " << prefix
170  << std::endl;
171 #endif
172 
173  H5::DataSet dataset = file->openDataSet( objectName );
174  // Get the class of the datatype that is used by the dataset.
175  H5T_class_t type_class = dataset.getTypeClass();
176  out << prefix << ".class_type: "
177  << ossim_hdf5::getDatatypeClassType( type_class ) << std::endl;
178 
179  const ossim_uint32 ATTRS_COUNT = dataset.getNumAttrs();
180  for ( ossim_uint32 aIdx = 0; aIdx < ATTRS_COUNT; ++aIdx )
181  {
182  H5::Attribute attr = dataset.openAttribute( aIdx );
183  ossim_hdf5::printAttribute( attr, prefix, out );
184  }
185 
186  switch(type_class)
187  {
188  case H5T_COMPOUND:
189  {
190  ossim_hdf5::printCompound(dataset, prefix, out);
191  break;
192  }
193  case H5T_ENUM:
194  {
195  H5::EnumType dataType = dataset.getEnumType();
196  ossim_hdf5::printEnumType(dataset, dataType,
197  prefix, out);
198  break;
199  }
200  case H5T_REFERENCE:
201  {
202  out << prefix << ".class_type: "
203  << ossim_hdf5::getDatatypeClassType( type_class ) << std::endl;
204 
205  break;
206  }
207  default:
208  {
209  //std::cout << "TYPE CLASS NOT HANDLED ===== " << type_class << std::endl;
210  break;
211  }
212  }
213  //std::cout << "NPOINTS === "
214  // Extents:
215  std::vector<ossim_uint32> extents;
216  ossim_hdf5::getExtents( &dataset, extents );
217  for ( ossim_uint32 i = 0; i < extents.size(); ++i )
218  {
219  ossimString os;
220  std::string exStr = ".extent";
221  exStr += os.toString(i).string();
222  out << prefix << exStr << ": " << extents[i] << std::endl;
223  }
224 
225  ossimScalarType scalar;
226  switch(type_class)
227  {
228  case H5T_INTEGER:
229  {
230  H5::IntType dataType = dataset.getIntType();
231  bool isSigned = dataType.getSign() == H5T_SGN_NONE ? false : true;
232 
233  scalar = ossim_hdf5::getScalarType( type_class, dataType.getSize(), isSigned);
234 
235  break;
236  }
237  case H5T_FLOAT:
238  {
239  H5::FloatType dataType = dataset.getFloatType();
240  bool isSigned = true;
241 
242  scalar = ossim_hdf5::getScalarType( type_class, dataType.getSize(), isSigned);
243  break;
244  }
245  default:
246  {
247  scalar = OSSIM_SCALAR_UNKNOWN;
248  }
249  }
250  //dataset.getId() );
251  if ( scalar != OSSIM_SCALAR_UNKNOWN)
252  {
253  out << prefix << "." << ossimKeywordNames::SCALAR_TYPE_KW << ": "
254  << ossimScalarTypeLut::instance()->getEntryString( scalar ) << std::endl;
255 
256  if ( ossim::scalarSizeInBytes( scalar ) > 1 )
257  {
259  std::string byteOrderString = "little_endian";
260  if ( byteOrder == OSSIM_BIG_ENDIAN )
261  {
262  byteOrderString = "big_endian";
263  }
264  out << prefix << "." <<ossimKeywordNames::BYTE_ORDER_KW << ": "
265  << byteOrderString << std::endl;
266  }
267  }
268 
269 #if 0
270  // Attributes:
271  int numberOfAttrs = dataset.getNumAttrs();
272  cout << "numberOfAttrs: " << numberOfAttrs << endl;
273  for ( ossim_int32 attrIdx = 0; attrIdx < numberOfAttrs; ++attrIdx )
274  {
275  H5::Attribute attribute = dataset.openAttribute( attrIdx );
276  cout << "attribute.from class: " << attribute.fromClass() << endl;
277  }
278 #endif
279  dataset.close();
280 
281 } // End: printObject
282 
283 void ossim_hdf5::printEnumType(H5::DataSet& dataset,
284  H5::EnumType& dataType,
285  const std::string& prefix,
286  std::ostream& out)
287 {
288  ossim_int32 nEnumMembers = dataType.getNmembers();
289  ossim_int32 enumMemberIdx = 0;
290  ossim_int32 enumTypeSize = dataType.getSize();
291  if(dataType.getSize() == 4)
292  {
293  out << prefix << ".class_type: H5T_ENUM\n";
294  for(;enumMemberIdx<nEnumMembers;++enumMemberIdx)
295  {
296  try{
297  ossim_int32 value = 0;
298 
299  dataType.getMemberValue(enumMemberIdx, &value);
300  H5std_string name = dataType.nameOf(&value, 2048);
301  out << prefix << "." << name << ": " <<value <<"\n";
302  }
303  catch(H5::Exception& e)
304  {
305  }
306  }
307  }
308 }
309 
310 void ossim_hdf5::printIntType(H5::DataSet& dataset,
311  H5::IntType& dataType,
312  const char* dataPtr,
313  const std::string& prefix,
314  std::ostream& out)
315 {
316  ossim_uint32 dataTypeSize = dataType.getSize();
317  ossimByteOrder order = getByteOrder(&dataType);
318  ossimEndian endian;
319  bool isSigned = dataType.getSign() == H5T_SGN_NONE ? false : true;
320  ossimString valueStr;
321  ossimScalarType scalarType = getScalarType(dataType.getClass(), dataTypeSize, isSigned);
322  switch(scalarType)
323  {
324  case OSSIM_UINT8:
325  {
326  ossim_uint8 value = *reinterpret_cast<const ossim_uint8*>(dataPtr);
327  valueStr = ossimString::toString(value);
328  break;
329  }
330  case OSSIM_SINT8:
331  {
332  ossim_int8 value = *reinterpret_cast<const ossim_int8*>(dataPtr);
333  valueStr = ossimString::toString(value);
334  break;
335  }
336  case OSSIM_UINT16:
337  {
338  ossim_uint16 value = *reinterpret_cast<const ossim_uint16*>(dataPtr);
339  if(order!=ossim::byteOrder())
340  {
341  endian.swap(value);
342  }
343  valueStr = ossimString::toString(value);
344  break;
345  }
346  case OSSIM_SINT16:
347  {
348  ossim_int16 value = *reinterpret_cast<const ossim_int16*>(dataPtr);
349  if(order!=ossim::byteOrder())
350  {
351  endian.swap(value);
352  }
353  valueStr = ossimString::toString(value);
354  break;
355  }
356  case OSSIM_UINT32:
357  {
358  ossim_uint32 value = *reinterpret_cast<const ossim_uint32*>(dataPtr);
359  if(order!=ossim::byteOrder())
360  {
361  endian.swap(value);
362  }
363  valueStr = ossimString::toString(value);
364  break;
365  }
366  case OSSIM_SINT32:
367  {
368  ossim_int32 value = *reinterpret_cast<const ossim_int32*>(dataPtr);
369  if(order!=ossim::byteOrder())
370  {
371  endian.swap(value);
372  }
373  valueStr = ossimString::toString(value);
374  break;
375  }
376  case OSSIM_UINT64:
377  {
378  ossim_uint64 value = *reinterpret_cast<const ossim_uint64*>(dataPtr);
379  if(order!=ossim::byteOrder())
380  {
381  endian.swap(value);
382  }
383  valueStr = ossimString::toString(value);
384  break;
385  }
386  case OSSIM_SINT64:
387  {
388  ossim_int64 value = *reinterpret_cast<const ossim_int64*>(dataPtr);
389  if(order!=ossim::byteOrder())
390  {
391  endian.swap(value);
392  }
393  valueStr = ossimString::toString(value);
394  break;
395  }
396  default:
397  {
398  valueStr = "<UNHANDLED SCALAR TYPE>";
399  break;
400  }
401  }
402  out << prefix<<": "<<valueStr<<"\n";
403 }
404 
405 void ossim_hdf5::printFloatType(H5::DataSet& dataset,
406  H5::FloatType& dataType,
407  const char* dataPtr,
408  const std::string& prefix,
409  std::ostream& out)
410 {
411  ossim_uint32 floatSize = dataType.getSize();
412  ossimByteOrder order = getByteOrder(&dataType);
413  ossimEndian endian;
414 
415  if(floatSize == 4)
416  {
417  ossim_float32 value = *reinterpret_cast<const ossim_float32*>(dataPtr);
418  if(order!=ossim::byteOrder())
419  {
420  endian.swap(value);
421  }
422  out << prefix<<": "<<ossimString::toString(value)<<"\n";
423  }
424  else if(floatSize == 8)
425  {
426  ossim_float64 value = *reinterpret_cast<const ossim_float64*>(dataPtr);
427  if(order!=ossim::byteOrder())
428  {
429  endian.swap(value);
430  // std::cout << "NOT THE SAME ORDER!!!!!!!!!!!!\n";
431  }
432  out << prefix<<": "<<ossimString::toString(value)<<"\n";
433  }
434 }
435 
436 void ossim_hdf5::printStrType(H5::DataSet& dataset,
437  H5::StrType& dataType,
438  const char* dataPtr,
439  const std::string& prefix,
440  std::ostream& out)
441 {
442  const char* startPtr = dataPtr;
443  const char* endPtr = dataPtr;
444  const char* maxPtr = dataPtr + dataType.getSize();
445  while((endPtr != maxPtr)&&(*endPtr!='\0')) ++endPtr;
446  ossimString value(startPtr, endPtr);
447  out << prefix <<": "<<value<<"\n";
448 }
449 
450 void ossim_hdf5::printArrayType(H5::DataSet& dataset,
451  H5::ArrayType& dataType,
452  const char* dataPtr,
453  const std::string& prefix,
454  std::ostream& out)
455 {
456  ossim_uint32 arrayNdims = dataType.getArrayNDims();
457  ossimByteOrder order = getByteOrder(&dataType);
458  ossimEndian endian;
459  H5::DataType superType = dataType.getSuper();
460  //out << prefix<<".class_type: " << ossim_hdf5::getDatatypeClassType( dataType.getClass() ) << "\n";
461  if(arrayNdims)
462  {
463  std::vector<hsize_t> dims(arrayNdims);
464  dataType.getArrayDims(&dims.front());
465  if(dims.size() > 0)
466  {
467  std::stringstream dimOut;
468  ossimString dimString;
469  ossim_uint32 idx = 1;
470  ossim_uint32 nArrayElements = dims[0];
471  std::copy(dims.begin(), --dims.end(),
472  std::ostream_iterator<hsize_t>(dimOut,","));
473  for(;idx<dims.size();++idx)
474  {
475  nArrayElements*=dims[idx];
476  }
477  dimString = ossimString("(") + dimOut.str() + ossimString::toString(dims[dims.size()-1])+")";
478  out << prefix << ".dimensions: " << dimString << "\n";
479  ossim_uint32 typeSize = superType.getSize();
480  switch(superType.getClass())
481  {
482  case H5T_STRING:
483  {
484  out<<prefix<<".values: (";
485  const char* startPtr = 0;
486  const char* endPtr = 0;
487  const char* mem = 0;
488  H5T_str_t pad;
489  ossim_int32 strSize = 0;
490  for(idx=0;idx<nArrayElements;++idx)
491  {
492  mem = ((const char*)dataPtr) + (idx * typeSize);
493  if(superType.isVariableStr())
494  {
495  startPtr = *(char**) mem;
496  if(startPtr) strSize = std::strlen(startPtr);
497  else strSize = 0;
498  }
499  else
500  {
501  startPtr = mem;
502  }
503  if(startPtr)
504  {
505  ossim_uint32 charIdx = 0;
506  endPtr = startPtr;
507  for (; ((charIdx < strSize) && (*endPtr)); ++charIdx,++endPtr);
508 
509  //std::cout << "WHAT????? " << ossimString(startPtr, endPtr)<<std::endl;
510  }
511  ossimString value = ossimString(startPtr, endPtr);
512  if(idx == 0)
513  {
514  out << "\""<<value<< "\"";
515  }
516  else
517  {
518  out << ", \""<<value<< "\"";
519  }
520  }
521  //out<<prefix<<".array_type: H5T_STRING\n";
522 // out<<prefix<<".values: <NOT SUPPORTED>";
523  break;
524  }
525  case H5T_INTEGER:
526  {
527  //out<<prefix<<".array_type: H5T_INTEGER\n";
528  out<<prefix<<".values: (";
529  for(idx=0;idx<nArrayElements;++idx)
530  {
531  if(typeSize == 2)
532  {
533  ossim_int16 value = *reinterpret_cast<const ossim_int16*>(dataPtr);
534  if(order!=ossim::byteOrder())
535  {
536  endian.swap(value);
537  }
538  if((idx + 1) <nArrayElements)
539  {
540  out << ossimString::toString(value) << ", ";
541  }
542  else
543  {
544  out << ossimString::toString(value);
545  }
546  }
547  else if(typeSize == 4)
548  {
549  ossim_int32 value = *reinterpret_cast<const ossim_int32*>(dataPtr);
550  if(order!=ossim::byteOrder())
551  {
552  endian.swap(value);
553  }
554  if((idx + 1) <nArrayElements)
555  {
556  out << ossimString::toString(value) << ", ";
557  }
558  else
559  {
560  out << ossimString::toString(value);
561  }
562  }
563  dataPtr+=typeSize;
564  }
565  break;
566  }
567  case H5T_FLOAT:
568  {
569  //out<<prefix<<".array_type: H5T_FLOAT\n";
570  out<<prefix<<".values: (";
571  for(idx=0;idx<nArrayElements;++idx)
572  {
573  if(typeSize == 4)
574  {
575  ossim_float32 value = *reinterpret_cast<const ossim_float32*>(dataPtr);
576  if(order!=ossim::byteOrder())
577  {
578  endian.swap(value);
579  }
580  if((idx + 1) <nArrayElements)
581  {
582  out << ossimString::toString(value) << ", ";
583  }
584  else
585  {
586  out << ossimString::toString(value);
587  }
588  }
589  else if(typeSize == 8)
590  {
591  ossim_float64 value = *reinterpret_cast<const ossim_float64*>(dataPtr);
592  if(order!=ossim::byteOrder())
593  {
594  endian.swap(value);
595  }
596  if((idx + 1) <nArrayElements)
597  {
598  out << ossimString::toString(value) << ", ";
599  }
600  else
601  {
602  out << ossimString::toString(value);
603  }
604  }
605  dataPtr+=typeSize;
606  }
607  break;
608  }
609  default:
610  {
611  break;
612  }
613  }
614  out<<")\n";
615 
616  }
617  }
618 }
619 
620 void ossim_hdf5::printCompound(H5::DataSet& dataset,
621  const std::string& prefix,
622  std::ostream& out)
623 {
624  H5::CompType compound(dataset);
625  H5::DataSpace dataspace = dataset.getSpace();
626  ossim_uint32 dimensions = dataspace.getSimpleExtentNdims();
627  ossim_uint32 nElements = dataspace.getSimpleExtentNpoints();
628  ossim_int32 nMembers = compound.getNmembers();
629  ossim_uint64 size = compound.getSize();
630  ossim_int32 memberIdx = 0;
631  ossim_int32 elementIdx = 0;
632  H5::DataType compType = dataset.getDataType();
633  std::vector<char> compData(size*nElements);
634  dataset.read((void*)&compData.front(),compType);
635  char* compDataPtr = &compData.front();
636 
637  if(dimensions!=1)
638  {
639  return;
640  }
641 
642  for(;elementIdx<nElements;++elementIdx)
643  {
644  std::string elementPrefix = prefix;//+"."+"element"+ossimString::toString(elementIdx);
645  //std::cout << "ELEMENTS: " << elements << std::endl;
646  for(memberIdx=0;memberIdx < nMembers;++memberIdx)
647  {
648  H5::DataType dataType = compound.getMemberDataType(memberIdx);
649  H5std_string memberName = compound.getMemberName(memberIdx);
650  ossim_uint32 memberOffset = compound.getMemberOffset(memberIdx) ;
651  std::string newPrefix = elementPrefix + "."+ memberName;
652  switch(dataType.getClass())
653  {
654  case H5T_COMPOUND:
655  {
656  ossim_hdf5::printCompound(dataset, newPrefix, out);
657  break;
658  }
659  case H5T_INTEGER:
660  {
661  H5::IntType dataType = compound.getMemberIntType(memberIdx);
662  ossim_hdf5::printIntType(dataset, dataType, &compDataPtr[memberOffset], newPrefix, out);
663  break;
664  }
665  case H5T_FLOAT:
666  {
667  H5::FloatType dataType = compound.getMemberFloatType(memberIdx);
668  ossim_hdf5::printFloatType(dataset, dataType, &compDataPtr[memberOffset], newPrefix, out);
669  break;
670  }
671  case H5T_TIME:
672  case H5T_STRING:
673  {
674  H5::StrType dataType = compound.getMemberStrType(memberIdx);
675  ossim_hdf5::printStrType(dataset, dataType, &compDataPtr[memberOffset], newPrefix, out);
676  break;
677  }
678  case H5T_BITFIELD:
679  {
680  out << newPrefix << ": <H5T_BITFIELD NOT HANDLED>\n";
681  break;
682  }
683  case H5T_OPAQUE:
684  {
685  out << newPrefix << ": <H5T_OPAQUE NOT HANDLED>\n";
686  break;
687  }
688  case H5T_REFERENCE:
689  {
690  out << newPrefix << ": <H5T_REFERENCE NOT HANDLED>\n";
691  break;
692  }
693  case H5T_ENUM:
694  {
695  H5::EnumType dataType = compound.getMemberEnumType(memberIdx);
696  ossim_hdf5::printEnumType(dataset, dataType, newPrefix, out);
697  break;
698  }
699  case H5T_VLEN:
700  {
701  out << newPrefix << ": <H5T_VLEN NOT HANDLED>\n";
702  break;
703  }
704  case H5T_ARRAY:
705  {
706  H5::ArrayType dataType = compound.getMemberArrayType(memberIdx);
707  ossim_hdf5::printArrayType(dataset, dataType, &compDataPtr[memberOffset], newPrefix, out);
708  break;
709  }
710  case H5T_NO_CLASS:
711  default:
712  {
713  out<< newPrefix << ".class_type: "
714  << ossim_hdf5::getDatatypeClassType( dataType.getClass() ) << "\n";
715  out << newPrefix << ": <NOT HANDLED>\n";
716  break;
717  }
718  }
719  }
720  compDataPtr+=size;
721  }
722 }
723 
724 
725 bool ossim_hdf5::getGroupAttributeValue( H5::H5File* file,
726  const std::string& group,
727  const std::string& key,
728  std::string& value )
729 {
730  static const char MODULE[] = "ossim_hdf5::getGroupAttributeValue";
731 
732  bool result = false;
733 
734  if ( file )
735  {
736  try // HDF5 library throws exceptions so wrap with try{}catch...
737  {
738  // Open the root group:
739  H5::Group* h5Group = new H5::Group( file->openGroup( group ) );
740 
741  // Lookw for key:
742  H5::Attribute attr = h5Group->openAttribute( key );
743  std::string name = attr.getName();
744  H5::DataType type = attr.getDataType();
745  H5T_class_t typeClass = attr.getTypeClass();
746 
747  if ( ( name == key ) && ( typeClass == H5T_STRING ) )
748  {
749  attr.read( type, value );
750  result = true;
751  }
752 
753  // Cleanup:
754  attr.close();
755  h5Group->close();
756  delete h5Group;
757  h5Group = 0;
758  }
759  catch( const H5::Exception& e )
760  {
761  if (traceDebug())
762  {
764  << MODULE << " WARNING: Caught exception!\n"
765  << e.getDetailMsg() << std::endl;
766  }
767  }
768  catch( ... )
769  {
771  << MODULE << " WARNING: Caught unknown exception!" << std::endl;
772  }
773  }
774 
775  return result;
776 
777 } // End: ossim_hdf5::getGroupAttributeValue
778 
780  const std::string& objectName,
781  const std::string& key,
782  std::string& value )
783 {
784  static const char MODULE[] = "ossim_hdf5::getDatasetAttributeValue";
785 
786  bool result = false;
787 
788  if ( file )
789  {
790  try // HDF5 library throws exceptions so wrap with try{}catch...
791  {
792  // Open the dataset:
793  H5::DataSet dataset = file->openDataSet( objectName );
794 
795  // Lookw for key:
796  H5::Attribute attr = dataset.openAttribute( key );
797 
798  std::string name = attr.getName();
799  H5::DataType type = attr.getDataType();
800  H5T_class_t typeClass = attr.getTypeClass();
801 
802  if ( ( name == key ) && ( typeClass == H5T_STRING ) )
803  {
804  attr.read( type, value );
805  result = true;
806  }
807 
808  // Cleanup:
809  attr.close();
810  dataset.close();
811  }
812  catch( const H5::Exception& e )
813  {
815  << MODULE << " WARNING: Caught exception!\n"
816  << e.getDetailMsg() << std::endl;
817  }
818  catch( ... )
819  {
821  << MODULE << " WARNING: Caught unknown exception!" << std::endl;
822  }
823  }
824 
825  return result;
826 
827 } // End: ossim_hdf5::getDatasetAttributeValue
828 
829 void ossim_hdf5::printAttribute( const H5::Attribute& attr,
830  const std::string& prefix,
831  std::ostream& out )
832 {
833  std::string name = attr.getName();
834  H5::DataType type = attr.getDataType();
835  H5T_class_t typeClass = attr.getTypeClass();
836  size_t size = type.getSize();
837 
838  std::string value; // Initialized below.
839 
840  if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
841  {
842  bool isSigned = false;
843  if ( typeClass == H5T_INTEGER )
844  {
845  H5::IntType intType = attr.getIntType();
846  isSigned = intType.getSign() == H5T_SGN_NONE ? false : true;
847  }
848 
849  ossimScalarType scalar = ossim_hdf5::getScalarType( typeClass, size, isSigned );
850  ossimByteOrder order = ossim_hdf5::getByteOrder( &attr );
851  ossimEndian* endian = 0;
852  if ( ( size > 1 ) && ( order != ossim::byteOrder() ) )
853  {
854  endian = new ossimEndian(); // If set used as flag to byte swap.
855  }
856 
857  if ( typeClass == H5T_INTEGER )
858  {
859  switch ( scalar )
860  {
861  case OSSIM_UINT8:
862  {
863  if ( size == 1 )
864  {
865  ossim_uint8 i;
866  attr.read( type, (void*)&i );
867  value = ossimString::toString( ossim_int32(i) ).string();
868  }
869  break;
870  }
871  case OSSIM_SINT8:
872  {
873  if ( size == 1 )
874  {
875  ossim_sint8 i;
876  attr.read( type, (void*)&i );
877  value = ossimString::toString( ossim_int32(i) ).string();
878  }
879  break;
880  }
881  case OSSIM_UINT16:
882  {
883  if ( size == 2 )
884  {
885  ossim_uint16 i;
886  attr.read( type, (void*)&i );
887  if ( endian )
888  {
889  endian->swap( i );
890  }
891  value = ossimString::toString( i ).string();
892  }
893  break;
894  }
895  case OSSIM_SINT16:
896  {
897  if ( size == 2 )
898  {
899  ossim_sint16 i;
900  attr.read( type, (void*)&i );
901  if ( endian )
902  {
903  endian->swap( i );
904  }
905  value = ossimString::toString( i ).string();
906  }
907  break;
908  }
909  case OSSIM_UINT32:
910  {
911  if ( size == 4 )
912  {
913  ossim_uint32 i;
914  attr.read( type, (void*)&i );
915  if ( endian )
916  {
917  endian->swap( i );
918  }
919  value = ossimString::toString( i ).string();
920  }
921  break;
922  }
923  case OSSIM_SINT32:
924  {
925  if ( size == 4 )
926  {
927  ossim_sint32 i;
928  attr.read( type, (void*)&i );
929  if ( endian )
930  {
931  endian->swap( i );
932  }
933  value = ossimString::toString( i ).string();
934  }
935  break;
936  }
937  case OSSIM_UINT64:
938  {
939  if ( size == 8 )
940  {
941  ossim_uint64 i;
942  attr.read( type, (void*)&i );
943  if ( endian )
944  {
945  endian->swap( i );
946  }
947  value = ossimString::toString( i ).string();
948  }
949  break;
950  }
951  case OSSIM_SINT64:
952  {
953  if ( size == 8 )
954  {
955  ossim_sint32 i;
956  attr.read( type, (void*)&i );
957  if ( endian )
958  {
959  endian->swap( i );
960  }
961  value = ossimString::toString( i ).string();
962  }
963  break;
964  }
965  default:
966  break;
967  }
968  }
969  else if ( typeClass == H5T_FLOAT )
970  {
971  if ( scalar == OSSIM_FLOAT32 )
972  {
973  if ( size == 4 )
974  {
975  ossim_float32 f;
976  attr.read( type, (void*)&f );
977  if ( endian )
978  {
979  endian->swap( f );
980  }
981  value = ossimString::toString( f ).string();
982  }
983  }
984  if ( scalar == OSSIM_FLOAT64 )
985  {
986  if ( size == 8 )
987  {
988  ossim_float64 f;
989  attr.read( type, (void*)&f );
990  if ( endian )
991  {
992  endian->swap( f );
993  }
994  value = ossimString::toString( f ).string();
995  }
996  }
997  }
998 
999  if ( endian )
1000  {
1001  delete endian;
1002  endian = 0;
1003  }
1004  }
1005  else if ( typeClass == H5T_STRING )
1006  {
1007  attr.read( type, value );
1008  }
1009  else
1010  {
1011  if(traceDebug())
1012  {
1014  << "ossimH5Util::printAttribute WARN: Unhandled type class: " << ossim_hdf5::getDatatypeClassType( typeClass ) << "\n"
1015  << std::endl;
1016  }
1017  }
1018 
1019  out << prefix << "." << name << ": " << value << std::endl;
1020 
1021  type.close();
1022 
1023 } // End: ossim_hdf5::printAttribute
1024 
1025 void ossim_hdf5::combine( const std::string& left,
1026  const std::string& right,
1027  char separator,
1028  std::string& result )
1029 {
1030  if ( left.size() && right.size() )
1031  {
1032  result = left;
1033  if ( ( left[ left.size()-1 ] != separator ) && ( right[0] != separator ) )
1034  {
1035  result.push_back(separator);
1036  }
1037  result += right;
1038  }
1039 }
1040 
1041 void ossim_hdf5::getDatasetNames(H5::H5File* file,
1042  std::vector<std::string>& datasetNames )
1043 {
1044  datasetNames.clear();
1045 
1046  if ( file )
1047  {
1048  std::string groupName = "/";
1049  ossim_uint32 recurseCount = 0;
1050  ossim_hdf5::iterateGroupForDatasetNames( file, groupName, datasetNames, recurseCount );
1051 #if 0
1052  std::vector<std::string>::const_iterator i = datasetNames.begin();
1053  while ( i != datasetNames.end() )
1054  {
1055  std::cout << "dataset: " << (*i) << std::endl;
1056  ++i;
1057  }
1058 #endif
1059  }
1060 }
1061 
1063 {
1064  H5T_class_t classType = (H5T_class_t)type;
1065 
1066  std::string result;
1067  switch ( classType )
1068  {
1069  case H5T_INTEGER:
1070  result = "H5T_INTEGER";
1071  break;
1072  case H5T_FLOAT:
1073  result = "H5T_FLOAT";
1074  break;
1075  case H5T_TIME:
1076  result = "H5T_TIME";
1077  break;
1078  case H5T_STRING:
1079  result = "H5T_STRING";
1080  break;
1081  case H5T_BITFIELD:
1082  result = "H5T_BITFIELD";
1083  break;
1084  case H5T_OPAQUE:
1085  result = "H5T_OPAQUE";
1086  break;
1087  case H5T_COMPOUND:
1088  result = "H5T_COMPOUND";
1089  break;
1090  case H5T_REFERENCE:
1091  result = "H5T_REFERENCE";
1092  break;
1093  case H5T_ENUM:
1094  result = "H5T_ENUM";
1095  break;
1096  case H5T_VLEN:
1097  result = "H5T_VLEN";
1098  break;
1099  case H5T_ARRAY:
1100  result = "H5T_ARRAY";
1101  break;
1102  case H5T_NO_CLASS:
1103  default:
1104  result = "H5T_NO_CLASS";
1105  break;
1106  }
1107  return result;
1108 }
1109 
1110 bool ossim_hdf5::isLoadableAsImage( H5::H5File* file, const std::string& datasetName )
1111 {
1112  bool result = false;
1113 
1114  // std::cout << "isLoadable entered..." << std::endl;
1115  if ( file && datasetName.size() )
1116  {
1117  if ( ossimH5Options::instance()->isDatasetRenderable(datasetName)) //isExcludedDataset( datasetName ) == false )
1118  {
1119  H5::DataSet dataset = file->openDataSet( datasetName );
1120 
1121  // Get the class of the datatype that is used by the dataset.
1122  H5T_class_t type_class = dataset.getTypeClass();
1123  // std::cout << "Class type: " << ossim_hdf5::getDatatypeClassType( type_class )
1124  // << std::endl;
1125 
1126  if ( ( type_class == H5T_INTEGER ) || ( type_class == H5T_FLOAT ) )
1127  {
1128  // Get dataspace of the dataset.
1129  // H5::DataSpace dataspace = dataset.getSpace();
1130 
1131  // Get the extents:
1132  std::vector<ossim_uint32> extents;
1133  ossim_hdf5::getExtents( &dataset, extents );
1134 
1135  if ( extents.size() >= 2 )
1136  {
1137  if ( ( extents[0] > 1 ) && ( extents[1] > 1 ) )
1138  {
1139  // std::cout << "Accepting dataset: " << datasetName << std::endl;
1140  result = true;
1141  }
1142  }
1143 
1144  }
1145 
1146  dataset.close();
1147  }
1148  }
1149 
1150  // std::cout << "isLoadable exit status: " << (result?"true":"false") << std::endl;
1151 
1152  return result;
1153 }
1154 
1155 #if 0
1156 bool ossim_hdf5::isExcludedDataset( const std::string& datasetName )
1157 {
1158  bool result = false;
1159 
1160  ossimFilename f = datasetName;
1161  f = f.file();
1162 #if 1
1163  if ( f != "Radiance" )
1164  {
1165  result = true;
1166  }
1167 #endif
1168 
1169 #if 0
1170  if ( ( f == "Latitude" ) ||
1171  ( f == "Longitude" ) ||
1172  ( f == "SCAttitude" ) ||
1173  ( f == "SCPosition" ) ||
1174  ( f == "SCVelocity" ) )
1175  {
1176  result = true;
1177  }
1178 #endif
1179 
1180  return result;
1181 }
1182 #endif
1183 
1185  const std::string& groupName,
1186  std::vector<std::string>& datasetNames,
1187  ossim_uint32& recursedCount )
1188 {
1189  if ( file && groupName.size() )
1190  {
1191  ++recursedCount;
1192 
1193  // std::cout << "iterateGroup: " << groupName << std::endl;
1194 
1195  H5::Group* group = new H5::Group( file->openGroup(groupName) );
1196 
1197  const hsize_t OBJ_COUNT = group->getNumObjs();
1198 
1199  for ( hsize_t i = 0; i < OBJ_COUNT; ++i )
1200  {
1201  std::string objName = group->getObjnameByIdx(i);
1202 
1203  if ( objName.size() )
1204  {
1205  char separator = '/';
1206  std::string combinedName;
1207  combine( groupName, objName, separator, combinedName );
1208 
1209  H5G_obj_t objType = group->getObjTypeByIdx(i);
1210 
1211 #if 0
1212  std::cout << "combinedName: " << combinedName
1213  << "\ngetObjnameByIdx[" << i << "]: " << objName
1214  << "\ngetObjTypeByIdx[" << i << "]: " << objType
1215  << std::endl;
1216 #endif
1217 
1218  if ( objType == H5G_GROUP )
1219  {
1220  // Recursive call:
1221  if ( recursedCount < ossimH5Options::instance()->getMaxRecursionLevel())
1222  {
1224  file, combinedName, datasetNames, recursedCount );
1225  }
1226  else
1227  {
1229  << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
1230  << "\nMax iterations reached!" << std::endl;
1231  }
1232  }
1233  else if ( objType == H5G_DATASET )
1234  {
1235  datasetNames.push_back( combinedName );
1236  }
1237  else
1238  {
1240  << "ossim_hdf5::iterateGroupForDatasetNames WARNING!"
1241  << "\nUnhandled object type: " << objType << std::endl;
1242  }
1243  }
1244  }
1245 
1246  group->close();
1247  delete group;
1248  group = 0;
1249  --recursedCount;
1250 
1251  } // Matches: if ( file )
1252 
1253 } // End: void ossim_hdf5::iterateGroupForDatasetNames
1254 
1255 void ossim_hdf5::getExtents( const H5::DataSet* dataset,
1256  std::vector<ossim_uint32>& extents )
1257 {
1258  extents.clear();
1259 
1260  if ( dataset )
1261  {
1262  // Get dataspace of the dataset.
1263  H5::DataSpace dataspace = dataset->getSpace();
1264 
1265  // Number of dimensions:
1266  int ndims = dataspace.getSimpleExtentNdims();
1267  if ( ndims )
1268  {
1269  //hsize_t dims_out[ndims];
1270  std::vector<hsize_t> dims_out(ndims);
1271  dataspace.getSimpleExtentDims( &dims_out.front(), 0 );
1272  for ( ossim_int32 i = 0; i < ndims; ++i )
1273  {
1274  extents.push_back(static_cast<ossim_uint32>(dims_out[i]));
1275  }
1276  }
1277 
1278  dataspace.close();
1279  }
1280 }
1281 
1282 ossimScalarType ossim_hdf5::getScalarType( const H5::DataSet* dataset )
1283 {
1284  // cout << "typeClass: " << typeClass << "\nid: " << id << endl;
1285 
1287 
1288  if ( dataset )
1289  {
1290  ossim_int32 typeClass = dataset->getTypeClass();
1291 
1292  if ( ( typeClass == H5T_INTEGER ) || ( typeClass == H5T_FLOAT ) )
1293  {
1294  // hid_t mem_type_id = H5Dget_type(id);
1295  hid_t mem_type_id = H5Dget_type( dataset->getId() );
1296 
1297  // cout << "mem_type_id: " << mem_type_id << endl;
1298 
1299  if( mem_type_id > -1 )
1300  {
1301  hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
1302  // hid_t native_type = H5Tget_native_type(id, H5T_DIR_DEFAULT);
1303 
1304  if( H5Tequal(H5T_NATIVE_CHAR, native_type) )
1305  {
1306  scalar = OSSIM_SINT8;
1307  }
1308  else if ( H5Tequal( H5T_NATIVE_UCHAR, native_type) )
1309  {
1310  scalar = OSSIM_UINT8;
1311  }
1312  else if( H5Tequal( H5T_NATIVE_SHORT, native_type) )
1313  {
1314  scalar = OSSIM_SINT16;
1315  }
1316  else if(H5Tequal(H5T_NATIVE_USHORT, native_type))
1317  {
1318  scalar = OSSIM_UINT16;
1319  }
1320  else if(H5Tequal( H5T_NATIVE_INT, native_type))
1321  {
1322  scalar = OSSIM_SINT32;
1323  }
1324  else if(H5Tequal( H5T_NATIVE_UINT, native_type ) )
1325  {
1326  scalar = OSSIM_UINT32;
1327  }
1328  else if(H5Tequal( H5T_NATIVE_LONG, native_type))
1329  {
1330  scalar = OSSIM_SINT32;
1331  }
1332  else if(H5Tequal( H5T_NATIVE_ULONG, native_type))
1333  {
1334  scalar = OSSIM_UINT32;
1335  }
1336  else if(H5Tequal( H5T_NATIVE_LLONG, native_type))
1337  {
1338  scalar = OSSIM_SINT64;
1339  }
1340  else if(H5Tequal( H5T_NATIVE_ULLONG, native_type))
1341  {
1342  scalar = OSSIM_UINT64;
1343  }
1344  else if(H5Tequal( H5T_NATIVE_FLOAT, native_type))
1345  {
1346  scalar = OSSIM_FLOAT32;
1347  }
1348  else if(H5Tequal( H5T_NATIVE_DOUBLE, native_type))
1349  {
1350  scalar = OSSIM_FLOAT64;
1351  }
1352  }
1353 
1354  } // Matches: if ( ( typeClass == ...
1355 
1356  } // Matches: if ( dataset ){
1357 
1358  return scalar;
1359 
1360 } // End: ossim_hdf5::getScalarType( const H5::DataSet* dataset )
1361 
1363  size_t size,
1364  bool isSigned )
1365 {
1367 
1368  H5T_class_t h5tClassType = (H5T_class_t)typeClass;
1369 
1370  if ( h5tClassType == H5T_INTEGER )
1371  {
1372  if ( size == 1 )
1373  {
1374  if (!isSigned)
1375  {
1376  scalar = OSSIM_UINT8;
1377  }
1378  else
1379  {
1380  scalar = OSSIM_SINT8;
1381  }
1382  }
1383  else if ( size == 2 )
1384  {
1385  if (!isSigned)
1386  {
1387  scalar = OSSIM_UINT16;
1388  }
1389  else
1390  {
1391  scalar = OSSIM_SINT16;
1392  }
1393  }
1394  else if ( size == 4 )
1395  {
1396  if (!isSigned)
1397  {
1398  scalar = OSSIM_UINT32;
1399  }
1400  else
1401  {
1402  scalar = OSSIM_SINT32;
1403  }
1404  }
1405  else if ( size == 8 )
1406  {
1407  if (!isSigned)
1408  {
1409  scalar = OSSIM_UINT64;
1410  }
1411  else
1412  {
1413  scalar = OSSIM_SINT64;
1414  }
1415  }
1416  else
1417  {
1419  << "unhandled scalar size: " << size << endl;
1420  }
1421  }
1422  else if ( h5tClassType == H5T_FLOAT )
1423  {
1424  if ( size == 4 )
1425  {
1426  scalar = OSSIM_FLOAT32;
1427  }
1428  else
1429  {
1430  scalar = OSSIM_FLOAT64;
1431  }
1432  }
1433  else
1434  {
1436  << "unhandled type class: " << h5tClassType << endl;
1437  }
1438 
1439  return scalar;
1440 }
1441 
1442 // commenting this out. This is broke and we should use the one that takes the class_type, size, and isSigned
1443 // arguments.
1444 #if 0
1446 {
1447  std::cout << "ossim_hdf5::getScalarType: entered...................\n";
1449 
1450  H5T_class_t type_class = H5Tget_class(id);
1451  size_t size = H5Tget_size(id);
1452  H5T_sign_t sign = H5Tget_sign(id);
1453 
1454  if ( type_class == H5T_INTEGER )
1455  {
1456  if ( size == 1 && sign == H5T_SGN_2)
1457  {
1458  scalar = OSSIM_SINT8;
1459  }
1460  else if ( size == 2 && sign == H5T_SGN_2)
1461  {
1462  scalar = OSSIM_SINT16;
1463  }
1464  else if ( size == 4 && sign == H5T_SGN_2)
1465  {
1466  scalar = OSSIM_SINT32;
1467  }
1468  else if ( size == 8 && sign == H5T_SGN_2)
1469  {
1470  scalar = OSSIM_SINT64;
1471  }
1472  else if ( size == 1 && sign == H5T_SGN_NONE)
1473  {
1474  scalar = OSSIM_UINT8;
1475  }
1476  else if ( size == 2 && sign == H5T_SGN_NONE)
1477  {
1478  scalar = OSSIM_UINT16;
1479  }
1480  else if ( size == 4 && sign == H5T_SGN_NONE)
1481  {
1482  scalar = OSSIM_UINT32;
1483  }
1484  else if ( size == 8 && sign == H5T_SGN_NONE)
1485  {
1486  scalar = OSSIM_UINT64;
1487  }
1488  }
1489  else if ( type_class == H5T_FLOAT )
1490  {
1491  if ( size == 4)
1492  {
1493  scalar = OSSIM_FLOAT32;
1494  }
1495  else if ( size == 8)
1496  {
1497  scalar = OSSIM_FLOAT64;
1498  }
1499  }
1500 
1501  return scalar;
1502 }
1503 #endif
1504 
1505 ossimByteOrder ossim_hdf5::getByteOrder( const H5::DataType* dataType )
1506 {
1508 
1509  if(dataType)
1510  {
1511  const H5::AtomType* atomType = dynamic_cast<const H5::AtomType*>(dataType);
1512 
1513  if(atomType)
1514  {
1515  H5T_order_t h5order = atomType->getOrder();
1516 
1517  if(h5order == H5T_ORDER_LE)
1518  {
1520  }
1521  else if(h5order == H5T_ORDER_BE)
1522  {
1524  }
1525  }
1526  }
1527 
1528  return byteOrder;
1529 }
1530 
1531 ossimByteOrder ossim_hdf5::getByteOrder( const H5::AbstractDs* obj )
1532 {
1534  if ( obj )
1535  {
1536  // Get the class of the datatype that is used by the dataset.
1537  H5T_class_t typeClass = obj->getTypeClass();
1538 
1539  H5T_order_t order = H5T_ORDER_NONE;
1540 
1541  if ( typeClass == H5T_INTEGER )
1542  {
1543  H5::IntType intype = obj->getIntType();
1544  order = intype.getOrder();
1545  }
1546  else if ( typeClass == H5T_FLOAT )
1547  {
1548  H5::FloatType floatType = obj->getFloatType();
1549  order = floatType.getOrder();
1550  }
1551 
1552  if ( order == H5T_ORDER_LE )
1553  {
1555  }
1556  else if ( order == H5T_ORDER_BE )
1557  {
1559  }
1560  }
1561  return byteOrder;
1562 }
1563 
1564 bool ossim_hdf5::getValidBoundingRect( H5::DataSet& dataset,
1565  const std::string& name,
1566  ossimIrect& rect )
1567 {
1568  bool result = false;
1569  H5::DataSpace imageDataspace = dataset.getSpace();
1570  const ossim_int32 IN_DIM_COUNT = imageDataspace.getSimpleExtentNdims();
1571 
1572  if ( IN_DIM_COUNT == 2 )
1573  {
1574  // Get the extents. Assuming dimensions are same for lat lon dataset.
1575  std::vector<hsize_t> dimsOut(IN_DIM_COUNT);
1576  imageDataspace.getSimpleExtentDims( &dimsOut.front(), 0 );
1577 
1578  if ( dimsOut[0] && dimsOut[1] )
1579  {
1580 
1581  //---
1582  // Capture the rectangle:
1583  // dimsOut[0] is height, dimsOut[1] is width:
1584  //---
1585  rect = ossimIrect( 0, 0,
1586  static_cast<ossim_int32>( dimsOut[1]-1 ),
1587  static_cast<ossim_int32>( dimsOut[0]-1 ) );
1588 
1589  const ossim_int32 WIDTH = rect.width();
1590 
1591  std::vector<hsize_t> inputCount(IN_DIM_COUNT);
1592  std::vector<hsize_t> inputOffset(IN_DIM_COUNT);
1593 
1594  inputOffset[0] = 0;
1595  inputOffset[1] = 0;
1596 
1597  inputCount[0] = 1;
1598  inputCount[1] = WIDTH;
1599 
1600  // Output dataspace dimensions.
1601  const ossim_int32 OUT_DIM_COUNT = 3;
1602  std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
1603  outputCount[0] = 1; // single band
1604  outputCount[1] = 1; // single line
1605  outputCount[2] = WIDTH; // whole line
1606 
1607  // Output dataspace offset.
1608  std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
1609  outputOffset[0] = 0;
1610  outputOffset[1] = 0;
1611  outputOffset[2] = 0;
1612 
1613  ossimScalarType scalar = ossim_hdf5::getScalarType( &dataset );
1614  if ( scalar == OSSIM_FLOAT32 )
1615  {
1616  // See if we need to swap bytes:
1617  ossimEndian* endian = 0;
1618  if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &dataset ) ) )
1619  {
1620  endian = new ossimEndian();
1621  }
1622 
1623  // Native type:
1624  H5::DataType datatype = dataset.getDataType();
1625 
1626  // Output dataspace always the same one line.
1627  H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
1628  bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
1629  &outputCount.front(),
1630  &outputOffset.front() );
1631 
1632  //---
1633  // Dataset sample has NULL lines at the end so scan for valid rect.
1634  // Use "<= -999" for test as per NOAA as it seems the NULL value is
1635  // fuzzy. e.g. -999.3.
1636  //---
1637  const ossim_float32 NULL_VALUE = -999.0;
1638 
1639  //---
1640  // VIIRS Radiance data has a -1.5e-9 in the first column.
1641  // Treat this as a null.
1642  //---
1643  const ossim_float32 NULL_VALUE2 = ( name == "/All_Data/VIIRS-DNB-SDR_All/Radiance" )
1644  ? -1.5e-9 : NULL_VALUE;
1645  const ossim_float32 TOLERANCE = 0.1e-9; // For ossim::almostEqual()
1646 
1647  // Hold one line:
1648  std::vector<ossim_float32> values( WIDTH );
1649 
1650  // Find the ul pixel:
1651  ossimIpt ulIpt = rect.ul();
1652  bool found = false;
1653 
1654  // Line loop to find upper left pixel:
1655  while ( ulIpt.y <= rect.lr().y )
1656  {
1657  inputOffset[0] = static_cast<hsize_t>(ulIpt.y);
1658  imageDataspace.selectHyperslab( H5S_SELECT_SET,
1659  &inputCount.front(),
1660  &inputOffset.front() );
1661 
1662  // Read data from file into the buffer.
1663  dataset.read( (void*)&values.front(), datatype, bufferDataSpace, imageDataspace );
1664 
1665  if ( endian )
1666  {
1667  // If the endian pointer is initialized(not zero) swap the bytes.
1668  endian->swap( scalar, (void*)&values.front(), WIDTH );
1669  }
1670 
1671  // Sample loop:
1672  ulIpt.x = rect.ul().x;
1673  ossim_int32 index = 0;
1674  while ( ulIpt.x <= rect.lr().x )
1675  {
1676  if ( !ossim::almostEqual(values[index], NULL_VALUE2, TOLERANCE) &&
1677  ( values[index] > NULL_VALUE ) )
1678  {
1679  found = true; // Found valid pixel.
1680  break;
1681  }
1682  ++ulIpt.x;
1683  ++index;
1684 
1685  } // End: sample loop
1686 
1687  if ( found )
1688  {
1689  break;
1690  }
1691 
1692  ++ulIpt.y;
1693 
1694  } // End line loop to find ul pixel:
1695 
1696  // Find the lower right pixel:
1697  ossimIpt lrIpt = rect.lr();
1698  found = false;
1699 
1700  // Line loop to find last pixel:
1701  while ( lrIpt.y >= rect.ul().y )
1702  {
1703  inputOffset[0] = static_cast<hsize_t>(lrIpt.y);
1704  imageDataspace.selectHyperslab( H5S_SELECT_SET,
1705  &inputCount.front(),
1706  &inputOffset.front() );
1707 
1708  // Read data from file into the buffer.
1709  dataset.read( (void*)&values.front(), datatype, bufferDataSpace, imageDataspace );
1710 
1711  if ( endian )
1712  {
1713  // If the endian pointer is initialized(not zero) swap the bytes.
1714  endian->swap( scalar, (void*)&values.front(), WIDTH );
1715  }
1716 
1717  // Sample loop:
1718  lrIpt.x = rect.lr().x;
1719  ossim_int32 index = WIDTH-1;
1720 
1721  while ( lrIpt.x >= rect.ul().x )
1722  {
1723  if ( !ossim::almostEqual(values[index], NULL_VALUE2, TOLERANCE) &&
1724  ( values[index] > NULL_VALUE ) )
1725  {
1726  found = true; // Found valid pixel.
1727  break;
1728  }
1729  --lrIpt.x;
1730  --index;
1731 
1732  } // End: sample loop
1733 
1734  if ( found )
1735  {
1736  break;
1737  }
1738 
1739  --lrIpt.y;
1740 
1741  } // End line loop to find lower right pixel.
1742 
1743  rect = ossimIrect( ulIpt, lrIpt );
1744 
1745  // Cleanup:
1746  if ( endian )
1747  {
1748  delete endian;
1749  endian = 0;
1750  }
1751 
1752  result = true;
1753 
1754  }
1755  else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
1756  {
1758  << "ossim_hdf5::getBoundingRect WARNING!"
1759  << "\nUnhandled scalar type: "
1761  << std::endl;
1762  }
1763 
1764  } // Matches: if ( dimsOut...
1765 
1766  } // Matches: if ( IN_DIM_COUNT == 2 )
1767 
1768  imageDataspace.close();
1769 
1770  return result;
1771 
1772 } // End: ossim_hdf5::getBoundingRect(...)
1773 
1774 bool ossim_hdf5::crossesDateline( H5::DataSet& dataset, const ossimIrect& validRect )
1775 {
1776  bool result = false;
1777 
1778  H5::DataSpace dataspace = dataset.getSpace();
1779 
1780  // Number of dimensions of the input dataspace:
1781  const ossim_int32 DIM_COUNT = dataspace.getSimpleExtentNdims();
1782 
1783  if ( DIM_COUNT == 2 )
1784  {
1785  const ossim_uint32 ROWS = validRect.height();
1786  const ossim_uint32 COLS = validRect.width();
1787 
1788  // Get the extents. Assuming dimensions are same for lat lon dataset.
1789  std::vector<hsize_t> dimsOut(DIM_COUNT);
1790  dataspace.getSimpleExtentDims( &dimsOut.front(), 0 );
1791 
1792  if ( (ROWS <= dimsOut[0]) && (COLS <= dimsOut[1]) )
1793  {
1794  std::vector<hsize_t> inputCount(DIM_COUNT);
1795  std::vector<hsize_t> inputOffset(DIM_COUNT);
1796 
1797  inputCount[0] = 1; // row
1798  inputCount[1] = COLS; // col
1799 
1800  // Output dataspace dimensions.
1801  const ossim_int32 OUT_DIM_COUNT = 3;
1802  std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
1803  outputCount[0] = 1; // single band
1804  outputCount[1] = 1; // single line
1805  outputCount[2] = COLS; // single sample
1806 
1807  // Output dataspace offset.
1808  std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
1809  outputOffset[0] = 0;
1810  outputOffset[1] = 0;
1811  outputOffset[2] = 0;
1812 
1813  ossimScalarType scalar = ossim_hdf5::getScalarType( &dataset );
1814  if ( scalar == OSSIM_FLOAT32 )
1815  {
1816  // See if we need to swap bytes:
1817  ossimEndian* endian = 0;
1818  if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &dataset ) ) )
1819  {
1820  endian = new ossimEndian();
1821  }
1822 
1823  // Native type:
1824  H5::DataType datatype = dataset.getDataType();
1825 
1826  // Output dataspace always the same one line.
1827  H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
1828  bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
1829  &outputCount.front(),
1830  &outputOffset.front() );
1831 
1832  //---
1833  // Dataset sample has NULL lines at the end so scan for valid rect.
1834  // Use "<= -999" for test as per NOAA as it seems the NULL value is
1835  // fuzzy. e.g. -999.3.
1836  //---
1837 
1838  // Buffer to hold a line:
1839  std::vector<ossim_float32> lineBuffer(validRect.width());
1840 
1841  // Read the first line:
1842  inputOffset[0] = static_cast<hsize_t>(validRect.ul().y);
1843  inputOffset[1] = static_cast<hsize_t>(validRect.ul().x);
1844  dataspace.selectHyperslab( H5S_SELECT_SET,
1845  &inputCount.front(),
1846  &inputOffset.front() );
1847  dataset.read( &(lineBuffer.front()), datatype, bufferDataSpace, dataspace );
1848 
1849  if ( endian )
1850  {
1851  // If the endian pointer is initialized(not zero) swap the bytes.
1852  endian->swap( &(lineBuffer.front()), COLS );
1853  }
1854 
1855  // Test the first line:
1856  result = ossim_hdf5::crossesDateline( lineBuffer );
1857 
1858  if ( !result )
1859  {
1860  // Test the last line:
1861  inputOffset[0] = static_cast<hsize_t>(validRect.ll().y);
1862  inputOffset[1] = static_cast<hsize_t>(validRect.ll().x);
1863  dataspace.selectHyperslab( H5S_SELECT_SET,
1864  &inputCount.front(),
1865  &inputOffset.front() );
1866  dataset.read( &(lineBuffer.front()), datatype, bufferDataSpace, dataspace );
1867 
1868  result = ossim_hdf5::crossesDateline( lineBuffer );
1869  }
1870 
1871  if ( endian )
1872  {
1873  delete endian;
1874  endian = 0;
1875  }
1876  }
1877  else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
1878  {
1880  << "ossim_hdf5::crossesDateline WARNING!"
1881  << "\nUnhandled scalar type: "
1883  << std::endl;
1884  }
1885 
1886  } // Matches: if ( dimsOut...
1887 
1888  } // Matches: if ( IN_DIM_COUNT == 2 )
1889 
1890  dataspace.close();
1891 
1892  return result;
1893 
1894 } // End: ossim_hdf5::crossesDateline(...)
1895 
1896 bool ossim_hdf5::crossesDateline( const std::vector<ossim_float32>& lineBuffer)
1897 {
1898  bool result = false;
1899 
1900  ossim_int32 longitude = 0;
1901  bool found179 = false;
1902  bool found181 = false;
1903 
1904  for ( ossim_uint32 i = 0; i < lineBuffer.size(); ++i)
1905  {
1906  longitude = (ossim_int32)lineBuffer[i]; // Cast to integer.
1907 
1908  // look for 179 -> -179...
1909  if ( !found179 )
1910  {
1911  if ( longitude == 179 )
1912  {
1913  found179 = true;
1914  continue;
1915  }
1916  }
1917  else // found179 == true
1918  {
1919  if ( longitude == 178 )
1920  {
1921  break; // Going West, 179 -> 178
1922  }
1923  else if ( longitude == -179 )
1924  {
1925  result = true;
1926  break;
1927  }
1928  }
1929 
1930  // look for -179 -> 179...
1931  if ( !found181 )
1932  {
1933  if ( longitude == -179 )
1934  {
1935  found181 = true;
1936  continue;
1937  }
1938  }
1939  else // found181 == true
1940  {
1941  if ( longitude == -178 )
1942  {
1943  break; // Going East -179 -> -178
1944  }
1945  else if ( longitude == 179 )
1946  {
1947  result = true;
1948  break;
1949  }
1950  }
1951  }
1952 
1953  return result;
1954 
1955 } // End: ossim_hdf5::crossesDateline( lineBuffer )
1956 
1958  H5::DataSet& latDataSet, H5::DataSet& lonDataSet, const ossimIrect& validRect )
1959 {
1961 
1962  // Get dataspace of the dataset.
1963  H5::DataSpace latDataSpace = latDataSet.getSpace();
1964  H5::DataSpace lonDataSpace = lonDataSet.getSpace();
1965 
1966  // Number of dimensions of the input dataspace:
1967  const ossim_int32 DIM_COUNT = latDataSpace.getSimpleExtentNdims();
1968 
1969  if ( DIM_COUNT == 2 )
1970  {
1971  // Get the extents. Assuming dimensions are same for lat lon dataset.
1972  std::vector<hsize_t> dimsOut(DIM_COUNT);
1973  latDataSpace.getSimpleExtentDims( &dimsOut.front(), 0 );
1974 
1975  if ( dimsOut[0] && dimsOut[1] )
1976  {
1977  std::vector<hsize_t> inputCount(DIM_COUNT);
1978  std::vector<hsize_t> inputOffset(DIM_COUNT);
1979 
1980  inputOffset[0] = 0;
1981  inputOffset[1] = 0;
1982 
1983  inputCount[0] = 1;
1984  inputCount[1] = 1;
1985 
1986  // Output dataspace dimensions.
1987  const ossim_int32 OUT_DIM_COUNT = 3;
1988  std::vector<hsize_t> outputCount(OUT_DIM_COUNT);
1989  outputCount[0] = 1; // single band
1990  outputCount[1] = 1; // single line
1991  outputCount[2] = 1; // single sample
1992 
1993  // Output dataspace offset.
1994  std::vector<hsize_t> outputOffset(OUT_DIM_COUNT);
1995  outputOffset[0] = 0;
1996  outputOffset[1] = 0;
1997  outputOffset[2] = 0;
1998 
1999  ossimScalarType scalar = ossim_hdf5::getScalarType( &latDataSet );
2000  if ( scalar == OSSIM_FLOAT32 )
2001  {
2002  // See if we need to swap bytes:
2003  ossimEndian* endian = 0;
2004  if ( ( ossim::byteOrder() != ossim_hdf5::getByteOrder( &latDataSet ) ) )
2005  {
2006  endian = new ossimEndian();
2007  }
2008 
2009  // Native type:
2010  H5::DataType latDataType = latDataSet.getDataType();
2011  H5::DataType lonDataType = lonDataSet.getDataType();
2012 
2013  std::vector<ossimDpt> ipts;
2014  std::vector<ossimGpt> gpts;
2015  ossimGpt gpt(0.0, 0.0, 0.0); // Assuming WGS84...
2016  ossim_float32 latValue = 0.0;
2017  ossim_float32 lonValue = 0.0;
2018 
2019  // Only grab every 256th value.:
2020  const ossim_int32 GRID_SIZE = 256;
2021 
2022  // Output dataspace always the same one pixel.
2023  H5::DataSpace bufferDataSpace( OUT_DIM_COUNT, &outputCount.front());
2024  bufferDataSpace.selectHyperslab( H5S_SELECT_SET,
2025  &outputCount.front(),
2026  &outputOffset.front() );
2027 
2028  //---
2029  // Dataset sample has NULL lines at the end so scan for valid rect.
2030  // Use "<= -999" for test as per NOAA as it seems the NULL value is
2031  // fuzzy. e.g. -999.3.
2032  //---
2033  const ossim_float32 NULL_VALUE = -999.0;
2034 
2035  //---
2036  // Get the tie points within the valid rect:
2037  //---
2038  ossimDpt ipt = validRect.ul();
2039  while ( ipt.y <= validRect.lr().y )
2040  {
2041  inputOffset[0] = static_cast<hsize_t>(ipt.y);
2042 
2043  // Sample loop:
2044  ipt.x = validRect.ul().x;
2045  while ( ipt.x <= validRect.lr().x )
2046  {
2047  inputOffset[1] = static_cast<hsize_t>(ipt.x);
2048 
2049  latDataSpace.selectHyperslab( H5S_SELECT_SET,
2050  &inputCount.front(),
2051  &inputOffset.front() );
2052  lonDataSpace.selectHyperslab( H5S_SELECT_SET,
2053  &inputCount.front(),
2054  &inputOffset.front() );
2055 
2056  // Read data from file into the buffer.
2057  latDataSet.read( &latValue, latDataType, bufferDataSpace, latDataSpace );
2058  lonDataSet.read( &lonValue, lonDataType, bufferDataSpace, lonDataSpace );
2059 
2060  if ( endian )
2061  {
2062  // If the endian pointer is initialized(not zero) swap the bytes.
2063  endian->swap( latValue );
2064  endian->swap( lonValue );
2065  }
2066 
2067  if ( ( latValue > NULL_VALUE ) && ( lonValue > NULL_VALUE ) )
2068  {
2069  gpt.lat = latValue;
2070  gpt.lon = lonValue;
2071  gpts.push_back( gpt );
2072 
2073  // Add the image point subtracting the image offset.
2074  ossimIpt shiftedIpt = ipt - validRect.ul();
2075  ipts.push_back( shiftedIpt );
2076  }
2077 
2078  // Go to next point:
2079  if ( ipt.x < validRect.lr().x )
2080  {
2081  ipt.x += GRID_SIZE;
2082  if ( ipt.x > validRect.lr().x )
2083  {
2084  ipt.x = validRect.lr().x; // Clamp to last sample.
2085  }
2086  }
2087  else
2088  {
2089  break; // At the end:
2090  }
2091 
2092  } // End sample loop.
2093 
2094  if ( ipt.y < validRect.lr().y )
2095  {
2096  ipt.y += GRID_SIZE;
2097  if ( ipt.y > validRect.lr().y )
2098  {
2099  ipt.y = validRect.lr().y; // Clamp to last line.
2100  }
2101  }
2102  else
2103  {
2104  break; // At the end:
2105  }
2106 
2107  } // End line loop.
2108 
2109  if ( ipts.size() )
2110  {
2111  // Create the projection:
2113 
2114  // Add the tie points:
2115  bp->setTiePoints( ipts, gpts );
2116 
2117  // Assign to output projection:
2118  proj = bp.get();
2119  }
2120 
2121  // Cleanup:
2122  if ( endian )
2123  {
2124  delete endian;
2125  endian = 0;
2126  }
2127  }
2128  else // Matches: if ( scalar == OSSIM_FLOAT32 ){...}
2129  {
2131  << "ossim_hdf5::getBilinearProjection WARNING!"
2132  << "\nUnhandled scalar type: "
2134  << std::endl;
2135  }
2136 
2137  } // Matches: if ( dimsOut...
2138 
2139  } // Matches: if ( IN_DIM_COUNT == 2 )
2140 
2141  latDataSpace.close();
2142  lonDataSpace.close();
2143 
2144  return proj;
2145 
2146 } // End: ossim_hdf5::getBilinearProjection()
void printCompound(H5::DataSet &dataset, const std::string &prefix, std::ostream &out)
Prints a compound object.
8 bit signed integer
static const char * BYTE_ORDER_KW
char ossim_int8
Previous DLL import export section.
std::basic_stringstream< char > stringstream
Class for char mixed input and output memory streams.
Definition: ossimIosFwd.h:38
Real sign(Real x, Real y)
Definition: newmatrm.h:108
64 bit floating point
16 bit unsigned integer
float ossim_float32
virtual ossimString getEntryString(ossim_int32 entry_number) const
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
void combine(const std::string &left, const std::string &right, char separator, std::string &result)
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
static ossimString toString(bool aValue)
Numeric to string methods.
ossimScalarType getScalarType(const H5::DataSet *dataset)
16 bit signed integer
void printIntType(H5::DataSet &dataset, H5::IntType &dataType, const char *dataPtr, const std::string &prefix, std::ostream &out)
const ossimIpt & ul() const
Definition: ossimIrect.h:274
static ossimH5Options * instance()
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
signed char ossim_sint8
bool isLoadableAsImage(H5::H5File *file, const std::string &datasetName)
std::ostream & print(H5::H5File *file, std::ostream &out)
Print method.
Definition: ossimH5Util.cpp:41
void printIterative(H5::H5File *file, const std::string &groupName, const std::string &prefix, ossim_uint32 &recursedCount, std::ostream &out)
Iterative print method.
Definition: ossimH5Util.cpp:79
32 bit floating point
unsigned short ossim_uint16
void printFloatType(H5::DataSet &dataset, H5::FloatType &dataType, const char *dataPtr, const std::string &prefix, std::ostream &out)
const ossimIpt & ll() const
Definition: ossimIrect.h:277
32 bit unsigned integer
void printAttribute(const H5::Attribute &attr, const std::string &prefix, std::ostream &out)
double ossim_float64
static ossimScalarTypeLut * instance()
Returns the static instance of an ossimScalarTypeLut object.
OSSIM_DLL bool isSigned(ossimScalarType scalarType)
yy_size_t size
64 bit signed integer
ossim_float64 lon
Definition: ossimGpt.h:266
signed short ossim_sint16
bool getDatasetAttributeValue(H5::H5File *file, const std::string &objectName, const std::string &key, std::string &value)
Gets string value for attribute key.
32 bit signed integer
void printStrType(H5::DataSet &dataset, H5::StrType &dataType, const char *dataPtr, const std::string &prefix, std::ostream &out)
unsigned long long ossim_uint64
unsigned int ossim_uint32
void iterateGroupForDatasetNames(H5::H5File *file, const std::string &group, std::vector< std::string > &names, ossim_uint32 &recursedCount)
signed int ossim_sint32
void printEnumType(H5::DataSet &dataset, H5::EnumType &dataType, const std::string &prefix, std::ostream &out)
OSSIM_DLL ossim_uint32 scalarSizeInBytes(ossimScalarType scalarType)
ossimByteOrder
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual ossim_float64 setTiePoints(const std::vector< ossimDpt > &lsPt, const std::vector< ossimGpt > &geoPt)
ossim_uint32 width() const
Definition: ossimIrect.h:500
ossimByteOrder getByteOrder(const H5::AbstractDs *dataset)
ossimScalarType
bool getValidBoundingRect(H5::DataSet &dataset, const std::string &name, ossimIrect &rect)
Gets the valid bounding rect of the dataset excluding nulls on front and back.
void printArrayType(H5::DataSet &dataset, H5::ArrayType &dataType, const char *dataPtr, const std::string &prefix, std::ostream &out)
short ossim_int16
64 bit unsigned integer
bool getGroupAttributeValue(H5::H5File *file, const std::string &group, const std::string &key, std::string &value)
Gets string value for attribute key.
ossimRefPtr< ossimProjection > getBilinearProjection(H5::DataSet &latDataSet, H5::DataSet &lonDataSet, const ossimIrect &validRect)
Gets bilinear projection from Latitude, Longitude layer.
ossim_int32 y
Definition: ossimIpt.h:142
void getExtents(const H5::DataSet *dataset, std::vector< ossim_uint32 > &extents)
double x
Definition: ossimDpt.h:164
long long ossim_int64
static const char * SCALAR_TYPE_KW
bool empty() const
Definition: ossimString.h:411
bool isDatasetRenderable(const std::string &datasetName) const
ossimFilename file() const
ossim_int32 x
Definition: ossimIpt.h:141
ossim_float64 lat
Definition: ossimGpt.h:265
8 bit unsigned integer
void getDatasetNames(H5::H5File *file, std::vector< std::string > &names)
bool crossesDateline(H5::DataSet &dataset, const ossimIrect &validRect)
Checks for dateline cross.
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void printObject(H5::H5File *file, const std::string &objectName, const std::string &prefix, std::ostream &out)
Prints an object.
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
std::string getDatatypeClassType(ossim_int32 type)
int ossim_int32
const std::string & string() const
Definition: ossimString.h:414