Field3D
Field3DFileHDF5.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
43 //----------------------------------------------------------------------------//
44 
45 #include <sys/stat.h>
46 #ifndef WIN32
47 #include <unistd.h>
48 #endif
49 
50 #include <hdf5.h>
51 #include <H5Epublic.h>
52 
53 #include <boost/tokenizer.hpp>
54 #include <boost/utility.hpp>
55 
56 #include "Field3DFileHDF5.h"
57 #include "Field.h"
58 #include "ClassFactory.h"
59 
60 //----------------------------------------------------------------------------//
61 
62 using namespace std;
63 
64 //----------------------------------------------------------------------------//
65 
67 
68 //----------------------------------------------------------------------------//
69 // Field3D namespaces
70 //----------------------------------------------------------------------------//
71 
72 using namespace Exc;
73 using namespace Hdf5Util;
74 using namespace FileHDF5;
75 
76 //----------------------------------------------------------------------------//
77 // Local namespace
78 //----------------------------------------------------------------------------//
79 
80 namespace {
81 
82  // Strings used only in this file --------------------------------------------
83 
84  const std::string k_mappingStr("mapping");
85  const std::string k_partitionName("partition");
86  const std::string k_versionAttrName("version_number");
87  const std::string k_classNameAttrName("class_name");
88  const std::string k_mappingTypeAttrName("mapping_type");
89 
92 
93  int k_currentFileVersion[3] =
95  int k_minFileVersion[2] = { 0, 0 };
96 
97  // Function objects used only in this file -----------------------------------
98 
99  std::vector<std::string> makeUnique(std::vector<std::string> vec)
100  {
101  std::vector<string> ret;
102  std::sort(vec.begin(), vec.end());
103  std::vector<std::string>::iterator newEnd =
104  std::unique(vec.begin(), vec.end());
105  ret.resize(std::distance(vec.begin(), newEnd));
106  std::copy(vec.begin(), newEnd, ret.begin());
107  return ret;
108  }
109 
110 //----------------------------------------------------------------------------//
111 
113  template <class T>
114  class print : std::unary_function<T, void>
115  {
116  public:
117  print(int indentAmt)
118  : indent(indentAmt)
119  { }
120  void operator()(const T& x) const
121  {
122  for (int i = 0; i < indent; i++)
123  std::cout << " ";
124  std::cout << x << std::endl;
125  }
126  int indent;
127  };
128 
129 //----------------------------------------------------------------------------//
130 
136  bool fileExists(const std::string &filename)
137  {
138 #ifdef WIN32
139  struct __stat64 statbuf;
140  return (_stat64(filename.c_str(), &statbuf) != -1);
141 #else
142  struct stat statbuf;
143  return (stat(filename.c_str(), &statbuf) != -1);
144 #endif
145  }
146 
152  void checkFile(const std::string &filename)
153  {
154  if (!fileExists(filename))
155  {
156  throw NoSuchFileException(filename);
157  }
158  }
159 
160 //----------------------------------------------------------------------------//
161 
162  bool isSupportedFileVersion(const int fileVersion[3],
163  const int minVersion[2])
164  {
165  stringstream currentVersionStr;
166  currentVersionStr << k_currentFileVersion[0] << "."
167  << k_currentFileVersion[1] << "."
168  << k_currentFileVersion[2];
169  stringstream fileVersionStr;
170  fileVersionStr << fileVersion[0] << "."
171  << fileVersion[1] << "."
172  << fileVersion[2];
173  stringstream minVersionStr;
174  minVersionStr << minVersion[0] << "."
175  << minVersion[1];
176 
177  if (fileVersion[0] > k_currentFileVersion[0] ||
178  (fileVersion[0] == k_currentFileVersion[0] &&
179  fileVersion[1] > k_currentFileVersion[1])) {
180  Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
181  " is higher than the current version " +
182  currentVersionStr.str());
183  return true;
184  }
185 
186  if (fileVersion[0] < minVersion[0] ||
187  (fileVersion[0] == minVersion[0] &&
188  fileVersion[1] < minVersion[1])) {
189  Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
190  " is lower than the minimum supported version " +
191  minVersionStr.str());
192  return false;
193  }
194  return true;
195  }
196 
197 //----------------------------------------------------------------------------//
198 
199  static herr_t localPrintError( hid_t estack_id, void *stream )
200  {
201  printf("H5E message -----------------------\n");
202  return H5Eprint2(estack_id, static_cast<FILE*>(stream));
203  }
204 
205 //----------------------------------------------------------------------------//
206 
207 } // end of local namespace
208 
209 //----------------------------------------------------------------------------//
210 // Partition implementations
211 //----------------------------------------------------------------------------//
212 
213 std::string Partition::className() const
214 {
215  return k_partitionName;
216 }
217 
218 //----------------------------------------------------------------------------//
219 
220 void
221 Partition::addScalarLayer(const Layer &layer)
222 {
223  m_scalarLayers.push_back(layer);
224 }
225 
226 //----------------------------------------------------------------------------//
227 
228 void
229 Partition::addVectorLayer(const Layer &layer)
230 {
231  m_vectorLayers.push_back(layer);
232 }
233 
234 //----------------------------------------------------------------------------//
235 
236 const Layer*
237 Partition::scalarLayer(const std::string &name) const
238 {
239  for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
240  i != m_scalarLayers.end(); ++i) {
241  if (i->name == name)
242  return &(*i);
243  }
244  return NULL;
245 }
246 
247 //----------------------------------------------------------------------------//
248 
249 const Layer*
250 Partition::vectorLayer(const std::string &name) const
251 {
252  for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
253  i != m_vectorLayers.end(); ++i) {
254  if (i->name == name)
255  return &(*i);
256  }
257  return NULL;
258 }
259 
260 //----------------------------------------------------------------------------//
261 
262 void
263 Partition::getScalarLayerNames(std::vector<std::string> &names) const
264 {
265  // We don't want to do names.clear() here, since this gets called
266  // inside some loops that want to accumulate names.
267  for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
268  i != m_scalarLayers.end(); ++i) {
269  names.push_back(i->name);
270  }
271 }
272 
273 //----------------------------------------------------------------------------//
274 
275 void
276 Partition::getVectorLayerNames(std::vector<std::string> &names) const
277 {
278  // We don't want to do names.clear() here, since this gets called
279  // inside some loops that want to accumulate names.
280  for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
281  i != m_vectorLayers.end(); ++i) {
282  names.push_back(i->name);
283  }
284 }
285 
286 //----------------------------------------------------------------------------//
287 // Field3DFileHDF5Base implementations
288 //----------------------------------------------------------------------------//
289 
291  : m_file(-1), m_metadata(this)
292 {
293  GlobalLock lock(g_hdf5Mutex);
294 
295  // Suppressing HDF error messages
296  // Explanation about the function for the error stack is here:
297  // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5E.html#Error-SetAuto2
298  if (getenv("DEBUG_HDF")) {
299  cerr << "Field3DFileHDF5 -- HDF5 messages are on" << endl;
300  H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
301  } else {
302  H5Eset_auto(H5E_DEFAULT, NULL, NULL);
303  }
304 }
305 
306 //----------------------------------------------------------------------------//
307 
309 {
310  close();
311 }
312 
313 //----------------------------------------------------------------------------//
314 
315 std::string
316 Field3DFileHDF5Base::intPartitionName(const std::string &partitionName,
317  const std::string & /* layerName */,
318  FieldRes::Ptr field)
319 {
320  // Loop over existing partitions and see if there's a matching mapping
321  for (PartitionList::const_iterator i = m_partitions.begin();
322  i != m_partitions.end(); ++i) {
323  if (removeUniqueId((**i).name) == partitionName) {
324  if ((**i).mapping->isIdentical(field->mapping())) {
325  return (**i).name;
326  }
327  }
328  }
329 
330  // If there was no previously matching name, then make a new one
331 
332  int nextIdx = -1;
333  if (m_partitionCount.find(partitionName) != m_partitionCount.end()) {
334  nextIdx = ++m_partitionCount[partitionName];
335  } else {
336  nextIdx = 0;
337  m_partitionCount[partitionName] = 0;
338  }
339 
340  return makeIntPartitionName(partitionName, nextIdx);
341 }
342 
343 //----------------------------------------------------------------------------//
344 
345 Partition::Ptr Field3DFileHDF5Base::partition(const string &partitionName)
346 {
347  for (PartitionList::iterator i = m_partitions.begin();
348  i != m_partitions.end(); ++i) {
349  if ((**i).name == partitionName)
350  return *i;
351  }
352 
353  return Partition::Ptr();
354 }
355 
356 //----------------------------------------------------------------------------//
357 
359 Field3DFileHDF5Base::partition(const string &partitionName) const
360 {
361  for (PartitionList::const_iterator i = m_partitions.begin();
362  i != m_partitions.end(); ++i) {
363  if ((**i).name == partitionName)
364  return *i;
365  }
366 
367  return Partition::Ptr();
368 }
369 
370 //----------------------------------------------------------------------------//
371 
372 std::string
373 Field3DFileHDF5Base::removeUniqueId(const std::string &partitionName) const
374 {
375  size_t pos = partitionName.rfind(".");
376  if (pos == partitionName.npos) {
377  return partitionName;
378  } else {
379  return partitionName.substr(0, pos);
380  }
381 }
382 
383 //----------------------------------------------------------------------------//
384 
385 void
386 Field3DFileHDF5Base::getPartitionNames(vector<string> &names) const
387 {
388  names.clear();
389 
390  vector<string> tempNames;
391 
392  for (PartitionList::const_iterator i = m_partitions.begin();
393  i != m_partitions.end(); ++i) {
394  tempNames.push_back(removeUniqueId((**i).name));
395  }
396 
397  names = makeUnique(tempNames);
398 }
399 
400 //----------------------------------------------------------------------------//
401 
402 void
404  const string &partitionName) const
405 {
406  names.clear();
407 
408  for (int i = 0; i < numIntPartitions(partitionName); i++) {
409  string internalName = makeIntPartitionName(partitionName, i);
410  Partition::Ptr part = partition(internalName);
411  if (part)
412  part->getScalarLayerNames(names);
413  }
414 
415  names = makeUnique(names);
416 }
417 
418 //----------------------------------------------------------------------------//
419 
420 void
422  const string &partitionName) const
423 {
424  names.clear();
425 
426  for (int i = 0; i < numIntPartitions(partitionName); i++) {
427  string internalName = makeIntPartitionName(partitionName, i);
428  Partition::Ptr part = partition(internalName);
429  if (part)
430  part->getVectorLayerNames(names);
431  }
432 
433  names = makeUnique(names);
434 }
435 
436 //----------------------------------------------------------------------------//
437 
438 void
439 Field3DFileHDF5Base::getIntPartitionNames(vector<string> &names) const
440 {
441  names.clear();
442 
443  for (PartitionList::const_iterator i = m_partitions.begin();
444  i != m_partitions.end(); ++i) {
445  names.push_back((**i).name);
446  }
447 }
448 
449 //----------------------------------------------------------------------------//
450 
451 void
453  const string &intPartitionName) const
454 {
455  names.clear();
456 
458 
459  if (!part) {
460  Msg::print("getIntScalarLayerNames no partition: " + intPartitionName);
461  return;
462  }
463 
464  part->getScalarLayerNames(names);
465 }
466 
467 //----------------------------------------------------------------------------//
468 
469 void
471  const string &intPartitionName) const
472 {
473  names.clear();
474 
476 
477  if (!part) {
478  Msg::print("getIntVectorLayerNames no partition: " + intPartitionName);
479  return;
480  }
481 
482  part->getVectorLayerNames(names);
483 }
484 
485 //----------------------------------------------------------------------------//
486 
488 {
489  closeInternal();
490  m_partitions.clear();
491  m_groupMembership.clear();
492 }
493 
494 //----------------------------------------------------------------------------//
495 
497 {
498  closeInternal();
499 
500  return true;
501 }
502 
503 //----------------------------------------------------------------------------//
504 
506 {
507  GlobalLock lock(g_hdf5Mutex);
508 
509  if (m_file != -1) {
510  if (H5Fclose(m_file) < 0) {
511  Msg::print(Msg::SevWarning, "Failed to close hdf5 file handle");
512  return;
513  }
514  m_file = -1;
515  }
516 }
517 
518 //----------------------------------------------------------------------------//
519 
520 int
521 Field3DFileHDF5Base::numIntPartitions(const std::string &partitionName) const
522 {
523  int count = 0;
524 
525  for (PartitionList::const_iterator i = m_partitions.begin();
526  i != m_partitions.end(); ++i) {
527  string name = (**i).name;
528  size_t pos = name.rfind(".");
529  if (pos != name.npos) {
530  if (name.substr(0, pos) == partitionName) {
531  count++;
532  }
533  }
534  }
535 
536  return count;
537 }
538 
539 //----------------------------------------------------------------------------//
540 
541 string
542 Field3DFileHDF5Base::makeIntPartitionName(const std::string &partitionName,
543  int i) const
544 {
545  return partitionName + "." + boost::lexical_cast<std::string>(i);
546 }
547 
548 //----------------------------------------------------------------------------//
549 
550 void
552 {
553  GroupMembershipMap::const_iterator i= groupMembers.begin();
554  GroupMembershipMap::const_iterator end= groupMembers.end();
555 
556  for (; i != end; ++i) {
557  GroupMembershipMap::iterator foundGroupIter =
558  m_groupMembership.find(i->first);
559  if (foundGroupIter != m_groupMembership.end()){
560  std::string value = m_groupMembership[i->first] + i->second;
561  m_groupMembership[i->first] = value;
562  } else {
563  m_groupMembership[i->first] = i->second;
564  }
565  }
566 }
567 
568 //----------------------------------------------------------------------------//
569 // Field3DInputFileHDF5 implementations
570 //----------------------------------------------------------------------------//
571 
573 {
574  // Empty
575 }
576 
577 //----------------------------------------------------------------------------//
578 
580 {
581  clear();
582 }
583 
584 //----------------------------------------------------------------------------//
585 
586 bool Field3DInputFileHDF5::open(const string &filename)
587 {
588  GlobalLock lock(g_hdf5Mutex);
589 
590  clear();
591 
592  bool success = true;
593 
594  // Record filename
595  m_filename = filename;
596 
597  try {
598 
599  string version;
600 
601  // Throws exceptions if the file doesn't exist.
602  // This was added because H5Fopen prints out a lot of junk
603  // to the terminal.
604  checkFile(filename);
605 
606  m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
607 
608  if (m_file < 0)
609  throw NoSuchFileException(filename);
610 
611  int fileVersion[3];
612  try {
613  if (!readAttribute(m_file, k_versionAttrName, 3, fileVersion[0])) {
614  //Msg::print(Msg::SevWarning, "Missing version_number attribute");
615  } else {
616  if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
617  stringstream versionStr;
618  versionStr << fileVersion[0] << "."
619  << fileVersion[1] << "."
620  << fileVersion[2];
621  throw UnsupportedVersionException(versionStr.str());
622  }
623  }
624  }
625  catch (MissingAttributeException &) {
626  //Msg::print(Msg::SevWarning, "Missing version_number attribute");
627  }
628 
629  try {
630  if (H5Lexists(m_file, "field3d_global_metadata", H5P_DEFAULT)) {
631  // read the metadata
632  H5ScopedGopen metadataGroup(m_file, "field3d_global_metadata");
633  if (metadataGroup.id() > 0) {
634  readMetadata(metadataGroup.id());
635  }
636  }
637  }
638  catch (...) {
640  "Unknown error when reading file metadata ");
641  //throw BadFileHierarchyException(filename);
642  }
643 
644  try {
645  if (!readPartitionAndLayerInfo()) {
646  success = false;
647  }
648  }
649  catch (MissingGroupException &e) {
650  Msg::print(Msg::SevWarning, "Missing group: " + string(e.what()));
651  throw BadFileHierarchyException(filename);
652  }
653  catch (ReadMappingException &e) {
654  Msg::print(Msg::SevWarning, "Couldn't read mapping for partition: "
655  + string(e.what()));
656  throw BadFileHierarchyException(filename);
657  }
658  catch (Exception &e) {
659  Msg::print(Msg::SevWarning, "Unknown error when reading file hierarchy: "
660  + string(e.what()));
661  throw BadFileHierarchyException(filename);
662  }
663  catch (...) {
665  "Unknown error when reading file hierarchy. ");
666  throw BadFileHierarchyException(filename);
667  }
668 
669  }
670  catch (NoSuchFileException &e) {
671  Msg::print(Msg::SevWarning, "Couldn't open file: "
672  + string(e.what()) );
673  success = false;
674  }
675  catch (MissingAttributeException &e) {
677  "In file: " + filename + " - "
678  + string(e.what()) );
679  success = false;
680  }
681  catch (UnsupportedVersionException &e) {
683  "In file: " + filename + " - File version can not be read: "
684  + string(e.what()));
685  success = false;
686  }
687  catch (BadFileHierarchyException &) {
689  "In file: " + filename + " - Bad file hierarchy. ");
690  success = false;
691  }
692  catch (...) {
694  "In file: " + filename + " Unknown exception ");
695  success = false;
696  }
697 
698  if (!success)
699  close();
700 
701  return success;
702 }
703 
704 //----------------------------------------------------------------------------//
705 
707 {
708  using namespace InputFileHDF5;
709 
710  GlobalLock lock(g_hdf5Mutex);
711 
712  // First, find the partitions ---
713 
714  herr_t status;
715  status = H5Literate(m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
716  &parsePartitions, this);
717 
718  // Get the partition names to store
719  m_partitions.clear();
720 
721  for (size_t i=0; i < m_partitionNames.size(); i++) {
722  Partition::Ptr part(new Partition);
723  part->name = m_partitionNames[i];
724  m_partitions.push_back(part);
725  }
726 
727  // For each partition, find its mapping ---
728 
729  for (PartitionList::iterator i = m_partitions.begin();
730  i != m_partitions.end(); ++i) {
731 
732  // Open the partition
733  H5ScopedGopen partitionGroup(m_file, (**i).name);
734 
735  string mappingPath = "/" + (**i).name + "/" + k_mappingStr;
736 
737  // Open up the mapping group
738  H5ScopedGopen mappingGroup(m_file, mappingPath);
739  if (mappingGroup.id() < 0)
740  throw MissingGroupException((**i).name + "/" + k_mappingStr);
741 
742  // Try to build a mapping from it
743  FieldMapping::Ptr mapping;
744 
745  mapping = readFieldMapping(mappingGroup.id());
746  if (!mapping) {
747  Msg::print(Msg::SevWarning, "Got a null pointer when reading mapping");
748  throw ReadMappingException((**i).name);
749  }
750 
751  // Attach the mapping to the partition
752  (**i).mapping = mapping;
753 
754  }
755 
756  // ... And then find its layers ---
757 
758  for (PartitionList::const_iterator i = m_partitions.begin();
759  i != m_partitions.end(); ++i) {
760 
761  // Open the partition
762  H5ScopedGopen partitionGroup(m_file, (**i).name);
763 
764  // Set up the info struct for the callback
765  ParseLayersInfo info;
766  info.file = this;
767  info.partitionName = (**i).name;
768 
769  m_layerInfo.clear();
770 
771  status = H5Literate(partitionGroup.id(), H5_INDEX_NAME, H5_ITER_NATIVE,
772  NULL, &parseLayers, &info);
773 
774  //set the layer information on the partitions here
775 
776  for (std::vector<LayerInfo>::iterator i = m_layerInfo.begin();
777  i != m_layerInfo.end(); i++) {
778 
779  std::string parent = i->parentName;
780 
781  Partition::Ptr part = partition(parent);
782 
783  Layer layer;
784  layer.name = i->name;
785  layer.parent = i->parentName;
786  if (i->components == 1) {
787  part->addScalarLayer(layer);
788  } else if (i->components == 3) {
789  part->addVectorLayer(layer);
790  }
791  }
792 
793  }
794 
795  return true;
796 }
797 
798 //----------------------------------------------------------------------------//
799 
800 herr_t Field3DInputFileHDF5::parsePartition(hid_t /* loc_id */,
801  const std::string itemName)
802 {
803  // Add the partition ---
804 
805  m_partitionNames.push_back(string(itemName));
806  return 0;
807 }
808 
809 //----------------------------------------------------------------------------//
810 
814 herr_t Field3DInputFileHDF5::parseLayer(hid_t layerGroup,
815  const std::string &partitionName,
816  const std::string &layerName)
817 {
818  int components;
819  if (!readAttribute(layerGroup, string("components"), 1, components)) {
820  Msg::print(Msg::SevWarning, "Couldn't read components attribute for layer "
821  + partitionName + "/" + layerName);
822  return 0;
823  }
824 
825  LayerInfo linfo(partitionName,layerName,components);
826 
827  m_layerInfo.push_back(linfo);
828 
829  return 0;
830 }
831 
832 //----------------------------------------------------------------------------//
833 
835 bool
837 readMetadata(hid_t metadata_id, FieldBase::Ptr field) const
838 {
839  GlobalLock lock(g_hdf5Mutex);
840 
841  hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
842 
843  if (num_attrs > 0) {
844  for (hsize_t idx=0; idx < num_attrs ; ++idx) {
845  H5ScopedAopenIdx attrIdx(metadata_id, idx);
846  size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
847  if (len > 0) {
848  char *name = new char[len+1];
849  if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
850  H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
851  H5ScopedAget_space attrSpace(attr);
852  H5ScopedAget_type attrType(attr);
853  H5T_class_t typeClass = H5Tget_class(attrType);
854 
855  if (typeClass == H5T_STRING) {
856  string value;
857  if (!readAttribute(metadata_id, name, value)) {
859  "Failed to read metadata " + string(name));
860  if (name) {
861  delete[] name;
862  }
863  continue;
864  }
865  field->metadata().setStrMetadata(name, value);
866 
867  }
868  else {
869 
870  if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
871  Msg::print(Msg::SevWarning, "Bad attribute rank for attribute "
872  + string(name));
873  if (name) {
874  delete[] name;
875  }
876  continue;
877  }
878 
879  hsize_t dims[1];
880  H5Sget_simple_extent_dims(attrSpace, dims, NULL);
881 
882  if (typeClass == H5T_INTEGER) {
883  if (dims[0] == 1){
884  int value;
885  if (!readAttribute(metadata_id, name, dims[0], value))
886  Msg::print(Msg::SevWarning, "Failed to read metadata "
887  + string(name));
888  field->metadata().setIntMetadata(name, value);
889  }
890  else if (dims[0] == 3){
891  V3i value;
892  if (!readAttribute(metadata_id, name, dims[0], value.x))
893  Msg::print(Msg::SevWarning, "Failed to read metadata " +
894  string(name) );
895  field->metadata().setVecIntMetadata(name, value);
896  }
897  else {
899  "Attribute of size " +
900  boost::lexical_cast<std::string>(dims[0])
901  + " is not valid for metadata");
902  }
903  }
904  else if (typeClass == H5T_FLOAT) {
905  if (dims[0] == 1){
906  float value;
907  if (!readAttribute(metadata_id, name, dims[0], value))
908  Msg::print(Msg::SevWarning, "Failed to read metadata " +
909  string(name) );
910 
911  field->metadata().setFloatMetadata(name, value);
912  }
913  else if (dims[0] == 3){
914  V3f value;
915  if (!readAttribute(metadata_id, name, dims[0], value.x))
916  Msg::print(Msg::SevWarning, "Failed to read metadata "+
917  string(name) );
918  field->metadata().setVecFloatMetadata(name, value);
919  }
920  else {
921  Msg::print(Msg::SevWarning, "Attribute of size " +
922  boost::lexical_cast<std::string>(dims[0]) +
923  " is not valid for metadata");
924  }
925  }
926  else {
927  Msg::print(Msg::SevWarning, "Attribute '" + string(name) +
928  + "' has unsupported data type for metadata");
929 
930  }
931  }
932  }
933  if (name) {
934  delete[] name;
935  }
936  }
937  }
938  }
939 
940  return true;
941 }
942 
943 //----------------------------------------------------------------------------//
944 
946 bool
948 {
949  GlobalLock lock(g_hdf5Mutex);
950 
951  hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
952 
953  if (num_attrs > 0) {
954  for (hsize_t idx=0; idx < num_attrs ; ++idx) {
955  H5ScopedAopenIdx attrIdx(metadata_id, idx);
956  size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
957  if (len > 0) {
958  char *name = new char[len+1];
959  if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
960  H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
961  H5ScopedAget_space attrSpace(attr);
962  H5ScopedAget_type attrType(attr);
963  H5T_class_t typeClass = H5Tget_class(attrType);
964 
965  if (typeClass == H5T_STRING) {
966  string value;
967  if (!readAttribute(metadata_id, name, value)) {
969  "Failed to read metadata " + string(name));
970  if (name) {
971  delete[] name;
972  }
973  continue;
974  }
975  metadata().setStrMetadata(name, value);
976 
977  }
978  else {
979 
980  if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
981  Msg::print(Msg::SevWarning, "Bad attribute rank for attribute "
982  + string(name));
983  if (name) {
984  delete[] name;
985  }
986  continue;
987  }
988 
989  hsize_t dims[1];
990  H5Sget_simple_extent_dims(attrSpace, dims, NULL);
991 
992  if (typeClass == H5T_INTEGER) {
993  if (dims[0] == 1){
994  int value;
995  if (!readAttribute(metadata_id, name, dims[0], value))
996  Msg::print(Msg::SevWarning, "Failed to read metadata "
997  + string(name));
998  metadata().setIntMetadata(name, value);
999  }
1000  else if (dims[0] == 3){
1001  V3i value;
1002  if (!readAttribute(metadata_id, name, dims[0], value.x))
1003  Msg::print(Msg::SevWarning, "Failed to read metadata " +
1004  string(name) );
1005  metadata().setVecIntMetadata(name, value);
1006  }
1007  else {
1009  "Attribute of size " +
1010  boost::lexical_cast<std::string>(dims[0])
1011  + " is not valid for metadata");
1012  }
1013  }
1014  else if (typeClass == H5T_FLOAT) {
1015  if (dims[0] == 1){
1016  float value;
1017  if (!readAttribute(metadata_id, name, dims[0], value))
1018  Msg::print(Msg::SevWarning, "Failed to read metadata " +
1019  string(name) );
1020 
1021  metadata().setFloatMetadata(name, value);
1022  }
1023  else if (dims[0] == 3){
1024  V3f value;
1025  if (!readAttribute(metadata_id, name, dims[0], value.x))
1026  Msg::print(Msg::SevWarning, "Failed to read metadata "+
1027  string(name) );
1028  metadata().setVecFloatMetadata(name, value);
1029  }
1030  else {
1031  Msg::print(Msg::SevWarning, "Attribute of size " +
1032  boost::lexical_cast<std::string>(dims[0]) +
1033  " is not valid for metadata");
1034  }
1035  }
1036  else {
1037  Msg::print(Msg::SevWarning, "Attribute '" + string(name) +
1038  + "' has unsupported data type for metadata");
1039 
1040  }
1041  }
1042  }
1043  if (name) {
1044  delete[] name;
1045  }
1046  }
1047  }
1048  }
1049 
1050  return true;
1051 }
1052 
1053 //----------------------------------------------------------------------------//
1054 
1055 bool
1057 readGroupMembership(GroupMembershipMap &gpMembershipMap)
1058 {
1059  GlobalLock lock(g_hdf5Mutex);
1060 
1061  if (!H5Lexists(m_file, "field3d_group_membership", H5P_DEFAULT)) {
1062  return false;
1063  }
1064 
1065  H5ScopedGopen memberGroup(m_file, "field3d_group_membership");
1066  if (memberGroup < 0) {
1067  return false;
1068  }
1069 
1070  typedef boost::tokenizer<boost::char_separator<char> > Tok;
1071 
1072  hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
1073  if (num_attrs > 0) {
1074 
1075  for (hsize_t idx=0; idx < num_attrs ; ++idx) {
1076  H5ScopedAopenIdx attrIdx(memberGroup, idx);
1077  size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
1078  if (len>0) {
1079  char *name = new char[len+1];
1080  if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
1081 
1082  if (string(name) == "is_field3d_group_membership")
1083  continue;
1084 
1085  H5ScopedAopen attr(memberGroup, name, H5P_DEFAULT);
1086  H5ScopedAget_space attrSpace(attr);
1087  H5ScopedAget_type attrType(attr);
1088  H5T_class_t typeClass = H5Tget_class(attrType);
1089 
1090  if (typeClass == H5T_STRING) {
1091  string value;
1092  if (!readAttribute(memberGroup, name, value)) {
1094  "Failed to read group membership data "
1095  + string(name));
1096  continue;
1097  }
1098 
1099  {
1100  boost::char_separator<char> sep(" :");
1101  Tok tok(value, sep);
1102  string new_value;
1103  for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
1104 
1105  string fieldgroup = *beg; ++beg;
1106  fieldgroup = removeUniqueId(fieldgroup) + ":" + *beg; ++beg;
1107  new_value += fieldgroup + " ";
1108  }
1109 
1110  m_groupMembership[name] = value;
1111  gpMembershipMap[name] = new_value;
1112  }
1113  }
1114  }
1115  }
1116  }
1117  }
1118 
1119  return true;
1120 }
1121 
1122 //----------------------------------------------------------------------------//
1123 // Field3DFileHDF5-related callback functions
1124 //----------------------------------------------------------------------------//
1125 
1126 namespace InputFileHDF5 {
1127 
1128 //----------------------------------------------------------------------------//
1129 
1130 herr_t parsePartitions(hid_t loc_id, const char *itemName,
1131  const H5L_info_t * /* linfo */, void *opdata)
1132 {
1133  GlobalLock lock(g_hdf5Mutex);
1134 
1135  herr_t status;
1136  H5O_info_t infobuf;
1137 
1138  status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
1139 
1140  if (status < 0) {
1141  return -1;
1142  }
1143 
1144  if (infobuf.type == H5O_TYPE_GROUP) {
1145 
1146  // Check that we have a name
1147  if (!itemName) {
1148  return -1;
1149  }
1150 
1151  // check that this group is not "groupMembership"
1152  if (string(itemName) != "field3d_group_membership" &&
1153  string(itemName) != "field3d_global_metadata")
1154  {
1155 
1156  // Get a pointer to the file data structure
1157  Field3DInputFileHDF5* fileObject = static_cast<Field3DInputFileHDF5*>(opdata);
1158  if (!fileObject) {
1159  return -1;
1160  }
1161 
1162  return fileObject->parsePartition(loc_id, itemName);
1163  }
1164  }
1165  return 0;
1166 }
1167 
1168 //----------------------------------------------------------------------------//
1169 
1170 herr_t parseLayers(hid_t loc_id, const char *itemName,
1171  const H5L_info_t * /* linfo */, void *opdata)
1172 {
1173  GlobalLock lock(g_hdf5Mutex);
1174 
1175  herr_t status;
1176  H5O_info_t infobuf;
1177 
1178  status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
1179 
1180  if (infobuf.type == H5O_TYPE_GROUP) {
1181 
1182  // Check that we have a name
1183  if (!itemName)
1184  return -1;
1185 
1186  // Get a pointer to the file data structure
1187  ParseLayersInfo* info = static_cast<ParseLayersInfo*>(opdata);
1188  if (!info)
1189  return -1;
1190 
1191  // Open up the layer group
1192  H5ScopedGopen layerGroup(loc_id, itemName);
1193 
1194  // Check if it's a layer
1195  string classType;
1196  try {
1197  if (!readAttribute(layerGroup.id(), "class_type", classType)) {
1198  return 0;
1199  }
1200  if (classType == string("field3d_layer"))
1201  return info->file->parseLayer(layerGroup.id(), info->partitionName,
1202  itemName);
1203 
1204  }
1205  catch (MissingAttributeException &) {
1206 
1207  }
1208  return 0;
1209 
1210  }
1211 
1212  return 0;
1213 }
1214 
1215 //----------------------------------------------------------------------------//
1216 
1217 } // namespace InputFileHDF5
1218 
1219 //----------------------------------------------------------------------------//
1220 // Field3DOutputFileHDF5 implementations
1221 //----------------------------------------------------------------------------//
1222 
1224 {
1225  // Empty
1226 }
1227 
1228 //----------------------------------------------------------------------------//
1229 
1231 {
1232 
1233 }
1234 
1235 //----------------------------------------------------------------------------//
1236 
1239 bool Field3DOutputFileHDF5::create(const string &filename, CreateMode cm)
1240 {
1241  GlobalLock lock(g_hdf5Mutex);
1242 
1243  closeInternal();
1244 
1245  bool success = true;
1246 
1247  try {
1248 
1249  hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
1250  H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
1251 
1252  // Create new file
1253  switch (cm) {
1254  case OverwriteMode:
1255  m_file = H5Fcreate(filename.c_str(),
1256  H5F_ACC_TRUNC, H5P_DEFAULT, faid);
1257  break;
1258  case FailOnExisting:
1259  m_file = H5Fcreate(filename.c_str(),
1260  H5F_ACC_EXCL, H5P_DEFAULT, faid);
1261  break;
1262  }
1263 
1264  // Check that file was created
1265  if (m_file < 0)
1266  throw ErrorCreatingFileException(filename);
1267 
1268  // Create a version attribute on the root node
1269  if (!writeAttribute(m_file, k_versionAttrName, 3,
1270  k_currentFileVersion[0])) {
1271  Msg::print(Msg::SevWarning, "Adding version number.");
1272  closeInternal();
1273  return false;
1274  }
1275 
1276  }
1277  catch (ErrorCreatingFileException &e) {
1278  Msg::print(Msg::SevWarning, "Couldn't create file: " + string(e.what()) );
1279  success = false;
1280  }
1281  catch (WriteAttributeException &e) {
1282  Msg::print(Msg::SevWarning, "In file : " + filename +
1283  " - Couldn't add attribute " + string(e.what()) );
1284  success = false;
1285  }
1286  catch (...) {
1288  "Unknown error when creating file: " + filename );
1289  success = false;
1290  }
1291 
1292  return success;
1293 }
1294 
1295 //----------------------------------------------------------------------------//
1296 
1297 bool Field3DOutputFileHDF5::writeMapping(hid_t partitionGroup,
1298  FieldMapping::Ptr mapping)
1299 {
1300  GlobalLock lock(g_hdf5Mutex);
1301 
1302  try {
1303  // Make a group under the partition to store the mapping data
1304  H5ScopedGcreate mappingGroup(partitionGroup, k_mappingStr);
1305  if (mappingGroup.id() < 0)
1306  throw CreateGroupException(k_mappingStr);
1307  // Let FieldMappingIO handle the rest
1308  if (!writeFieldMapping(mappingGroup.id(), mapping))
1309  throw WriteMappingException(k_mappingStr);
1310  }
1311  catch (CreateGroupException &e) {
1312  Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
1313  throw WriteMappingException(k_mappingStr);
1314  }
1315  return true;
1316 }
1317 
1318 //----------------------------------------------------------------------------//
1319 
1321 {
1322  using namespace Hdf5Util;
1323 
1324  {
1325  FieldMetadata::StrMetadata::const_iterator i =
1326  field->metadata().strMetadata().begin();
1327  FieldMetadata::StrMetadata::const_iterator end =
1328  field->metadata().strMetadata().end();
1329  for (; i != end; ++i) {
1330  if (!writeAttribute(metadataGroup, i->first, i->second))
1331  {
1332  Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
1333  return false;
1334  }
1335  }
1336  }
1337 
1338  {
1339  FieldMetadata::IntMetadata::const_iterator i =
1340  field->metadata().intMetadata().begin();
1341  FieldMetadata::IntMetadata::const_iterator end =
1342  field->metadata().intMetadata().end();
1343  for (; i != end; ++i) {
1344  if (!writeAttribute(metadataGroup, i->first, 1, i->second))
1345  {
1346  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1347  return false;
1348  }
1349  }
1350  }
1351 
1352  {
1353  FieldMetadata::FloatMetadata::const_iterator i =
1354  field->metadata().floatMetadata().begin();
1355  FieldMetadata::FloatMetadata::const_iterator end =
1356  field->metadata().floatMetadata().end();
1357  for (; i != end; ++i) {
1358  if (!writeAttribute(metadataGroup, i->first, 1, i->second))
1359  {
1360  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1361  return false;
1362  }
1363  }
1364  }
1365 
1366  {
1367  FieldMetadata::VecIntMetadata::const_iterator i =
1368  field->metadata().vecIntMetadata().begin();
1369  FieldMetadata::VecIntMetadata::const_iterator end =
1370  field->metadata().vecIntMetadata().end();
1371  for (; i != end; ++i) {
1372  if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
1373  {
1374  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1375  return false;
1376  }
1377  }
1378  }
1379 
1380  {
1381  FieldMetadata::VecFloatMetadata::const_iterator i =
1382  field->metadata().vecFloatMetadata().begin();
1383  FieldMetadata::VecFloatMetadata::const_iterator end =
1384  field->metadata().vecFloatMetadata().end();
1385  for (; i != end; ++i) {
1386  if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
1387  {
1388  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1389  return false;
1390  }
1391  }
1392 
1393  }
1394 
1395  return true;
1396 
1397 }
1398 
1399 //----------------------------------------------------------------------------//
1400 
1401 bool Field3DOutputFileHDF5::writeMetadata(hid_t metadataGroup)
1402 {
1403  using namespace Hdf5Util;
1404 
1405  {
1406  FieldMetadata::StrMetadata::const_iterator i =
1407  metadata().strMetadata().begin();
1408  FieldMetadata::StrMetadata::const_iterator end =
1409  metadata().strMetadata().end();
1410  for (; i != end; ++i) {
1411  if (!writeAttribute(metadataGroup, i->first, i->second))
1412  {
1413  Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
1414  return false;
1415  }
1416  }
1417  }
1418 
1419  {
1420  FieldMetadata::IntMetadata::const_iterator i =
1421  metadata().intMetadata().begin();
1422  FieldMetadata::IntMetadata::const_iterator end =
1423  metadata().intMetadata().end();
1424  for (; i != end; ++i) {
1425  if (!writeAttribute(metadataGroup, i->first, 1, i->second))
1426  {
1427  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1428  return false;
1429  }
1430  }
1431  }
1432 
1433  {
1434  FieldMetadata::FloatMetadata::const_iterator i =
1435  metadata().floatMetadata().begin();
1436  FieldMetadata::FloatMetadata::const_iterator end =
1437  metadata().floatMetadata().end();
1438  for (; i != end; ++i) {
1439  if (!writeAttribute(metadataGroup, i->first, 1, i->second))
1440  {
1441  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1442  return false;
1443  }
1444  }
1445  }
1446 
1447  {
1448  FieldMetadata::VecIntMetadata::const_iterator i =
1449  metadata().vecIntMetadata().begin();
1450  FieldMetadata::VecIntMetadata::const_iterator end =
1451  metadata().vecIntMetadata().end();
1452  for (; i != end; ++i) {
1453  if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
1454  {
1455  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1456  return false;
1457  }
1458  }
1459  }
1460 
1461  {
1462  FieldMetadata::VecFloatMetadata::const_iterator i =
1463  metadata().vecFloatMetadata().begin();
1464  FieldMetadata::VecFloatMetadata::const_iterator end =
1465  metadata().vecFloatMetadata().end();
1466  for (; i != end; ++i) {
1467  if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
1468  {
1469  Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
1470  return false;
1471  }
1472  }
1473 
1474  }
1475 
1476  return true;
1477 
1478 }
1479 
1480 //----------------------------------------------------------------------------//
1481 
1482 bool
1484 {
1485  GlobalLock lock(g_hdf5Mutex);
1486 
1487  // Add metadata group and write it out
1488  H5ScopedGcreate metadataGroup(m_file, "field3d_global_metadata");
1489  if (metadataGroup.id() < 0) {
1490  Msg::print(Msg::SevWarning, "Error creating group: file metadata");
1491  return false;
1492  }
1493  if (!writeMetadata(metadataGroup.id())) {
1494  Msg::print(Msg::SevWarning, "Error writing file metadata.");
1495  return false;
1496  }
1497 
1498  return true;
1499 }
1500 
1501 //----------------------------------------------------------------------------//
1502 
1503 bool
1505 {
1506  using namespace std;
1507  using namespace Hdf5Util;
1508 
1509  GlobalLock lock(g_hdf5Mutex);
1510 
1511  if (!m_groupMembership.size())
1512  return true;
1513 
1514  H5ScopedGcreate group(m_file, "field3d_group_membership");
1515  if (group < 0) {
1517  "Error creating field3d_group_membership group.");
1518  return false;
1519  }
1520 
1521  if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
1523  "Failed to write field3d_group_membership attribute.");
1524  return false;
1525  }
1526 
1527  std::map<std::string, std::string>::const_iterator iter =
1528  m_groupMembership.begin();
1529  std::map<std::string, std::string>::const_iterator iEnd =
1530  m_groupMembership.end();
1531 
1532  for (; iter != iEnd; ++iter) {
1533  if (!writeAttribute(group, iter->first, iter->second)) {
1535  "Failed to write groupMembership string: "+ iter->first);
1536  return false;
1537  }
1538  }
1539 
1540  return true;
1541 }
1542 
1543 //----------------------------------------------------------------------------//
1544 
1545 std::string
1547 {
1548  std::string myPartitionName = removeUniqueId(partitionName);
1549  int nextIdx = -1;
1550  if (m_partitionCount.find(myPartitionName) != m_partitionCount.end()) {
1551  nextIdx = ++m_partitionCount[myPartitionName];
1552  } else {
1553  nextIdx = 0;
1554  m_partitionCount[myPartitionName] = 0;
1555  }
1556 
1557  return makeIntPartitionName(myPartitionName, nextIdx);
1558 }
1559 
1560 //----------------------------------------------------------------------------//
1561 // Debug
1562 //----------------------------------------------------------------------------//
1563 
1565 {
1566  // For each partition
1567  for (PartitionList::const_iterator i = m_partitions.begin();
1568  i != m_partitions.end(); ++i) {
1569  cout << "Name: " << (**i).name << endl;
1570  if ((**i).mapping)
1571  cout << " Mapping: " << (**i).mapping->className() << endl;
1572  else
1573  cout << " Mapping: NULL" << endl;
1574  cout << " Scalar layers: " << endl;
1575  vector<string> sNames;
1576  (**i).getScalarLayerNames(sNames);
1577  for_each(sNames.begin(), sNames.end(), print<string>(4));
1578  cout << " Vector layers: " << endl;
1579  vector<string> vNames;
1580  (**i).getVectorLayerNames(vNames);
1581  for_each(vNames.begin(), vNames.end(), print<string>(4));
1582  }
1583 }
1584 
1585 //----------------------------------------------------------------------------//
1586 // Function Implementations
1587 //----------------------------------------------------------------------------//
1588 
1589 bool writeField(hid_t layerGroup, FieldBase::Ptr field)
1590 {
1592 
1593  FieldIO::Ptr io = factory.createFieldIO(field->className());
1594  assert(io != 0);
1595  if (!io) {
1596  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1597  field->className());
1598  return false;
1599  }
1600 
1601  // Add class name attribute
1602  if (!writeAttribute(layerGroup, k_classNameAttrName,
1603  field->className())) {
1604  Msg::print(Msg::SevWarning, "Error adding class name attribute.");
1605  return false;
1606  }
1607 
1608  return io->write(layerGroup, field);
1609 }
1610 
1611 //----------------------------------------------------------------------------//
1612 
1614 {
1616 
1617  std::string className;
1618 
1619  if (!readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1620  Msg::print(Msg::SevWarning, "Couldn't find " + k_mappingTypeAttrName +
1621  " attribute");
1622  return FieldMapping::Ptr();
1623  }
1624 
1625  FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
1626  assert(io != 0);
1627  if (!io) {
1628  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1629  className);
1630  return FieldMapping::Ptr();
1631  }
1632 
1633 
1634  FieldMapping::Ptr mapping = io->read(mappingGroup);
1635  if (!mapping) {
1636  Msg::print(Msg::SevWarning, "Couldn't read mapping");
1637  return FieldMapping::Ptr();
1638  }
1639 
1640  return mapping;
1641 }
1642 
1643 //----------------------------------------------------------------------------//
1644 
1645 bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
1646 {
1648 
1649  std::string className = mapping->className();
1650 
1651  if (!writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
1652  Msg::print(Msg::SevWarning, "Couldn't add " + className + " attribute");
1653  return false;
1654  }
1655 
1656  FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
1657  assert(io != 0);
1658  if (!io) {
1659  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1660  className);
1661  return false;
1662  }
1663 
1664  return io->write(mappingGroup, mapping);
1665 }
1666 
1667 //----------------------------------------------------------------------------//
1668 
1670 
1671 //----------------------------------------------------------------------------//
Contains the ClassFactory class for registering Field3D classes.
FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
Contains the Field3DFileHDF5 classes.
bool fileExists(const std::string &filename)
checks to see if a file/directory exists or not
Contains Field, WritableField and ResizableField classes.
FIELD3D_NAMESPACE_OPEN FIELD3D_API boost::recursive_mutex g_hdf5Mutex
Definition: Hdf5Util.cpp:67
boost::recursive_mutex::scoped_lock GlobalLock
Definition: Hdf5Util.h:78
Imath::V3i V3i
Definition: SpiMathLib.h:71
Imath::V3f V3f
Definition: SpiMathLib.h:73
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
static ClassFactory & singleton()
}
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
std::vector< std::string > m_partitionNames
This stores partition names.
PartitionList m_partitions
Vector of partitions.
std::string makeIntPartitionName(const std::string &partitionsName, int i) const
Makes an internal partition name given the external partition name. Effectively just tacks on ....
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
bool close()
Closes the file. No need to call this unless you specifically want to close the file early....
void getIntVectorLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the vector layers in a given partition, but assumes that partition name is the ...
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
hid_t m_file
The hdf5 id of the current file. Will be -1 if no file is open.
void getIntScalarLayerNames(std::vector< std::string > &names, const std::string &intPartitionName) const
Gets the names of all the scalar layers in a given partition, but assumes that partition name is the ...
void closeInternal()
Closes the file if open.
std::string intPartitionName(const std::string &partitionName, const std::string &layerName, FieldRes::Ptr field)
Returns a unique partition name given the requested name. This ensures that partitions with matching ...
virtual ~Field3DFileHDF5Base()=0
Pure virtual destructor to ensure we never instantiate this class.
void addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
std::vector< LayerInfo > m_layerInfo
This stores layer info.
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
FieldMetadata & metadata()
accessor to the m_metadata class
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
FileHDF5::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
void clear()
Clear the data structures and close the file.
std::map< std::string, std::string > GroupMembershipMap
Provides reading of .f3d (internally, hdf5) files.
std::string m_filename
Filename, only to be set by open().
herr_t parsePartition(hid_t loc_id, const std::string partitionName)
Gets called from parsePartitions. Not intended for any other use.
bool readMetadata(hid_t metadata_id, FieldBase::Ptr field) const
Read metadata for this layer.
herr_t parseLayer(hid_t loc_id, const std::string &partitionName, const std::string &layerName)
Gets called from parsePartitions. Not intended for any other use.
bool readPartitionAndLayerInfo()
Sets up all the partitions and layers, but does not load any data.
bool readGroupMembership(GroupMembershipMap &gpMembershipMap)
Read the group membership for the partitions.
bool open(const std::string &filename)
Opens the given file.
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping)
Writes the mapping to the given hdf5 node. Mappings are assumed to be light-weight enough to be store...
bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
std::string incrementPartitionName(std::string &pname)
increment the partition or make it zero if there's not an integer suffix
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
boost::intrusive_ptr< FieldIO > Ptr
Definition: FieldIO.h:91
boost::intrusive_ptr< FieldMappingIO > Ptr
boost::intrusive_ptr< FieldMapping > Ptr
Definition: FieldMapping.h:92
void setIntMetadata(const std::string &name, const int val)
Set the a int value for the given metadata name.
void setStrMetadata(const std::string &name, const std::string &val)
Set the a string value for the given metadata name.
void setVecFloatMetadata(const std::string &name, const V3f &val)
Set the a V3f value for the given metadata name.
void setVecIntMetadata(const std::string &name, const V3i &val)
Set the a V3i value for the given metadata name.
V3f vecFloatMetadata(const std::string &name, const V3f &defaultVal) const
Tries to retrieve a V3f metadata value. Returns the specified default value if no metadata was found.
V3i vecIntMetadata(const std::string &name, const V3i &defaultVal) const
Tries to retrieve a V3i metadata value. Returns the specified default value if no metadata was found.
int intMetadata(const std::string &name, const int defaultVal) const
Tries to retrieve an int metadata value. Returns the specified default value if no metadata was found...
std::string strMetadata(const std::string &name, const std::string &defaultVal) const
Tries to retrieve a string metadata value. Returns the specified default value if no metadata was fou...
float floatMetadata(const std::string &name, const float defaultVal) const
Tries to retrieve a float metadata value. Returns the specified default value if no metadata was foun...
void setFloatMetadata(const std::string &name, const float val)
Set the a float value for the given metadata name.
boost::intrusive_ptr< FieldRes > Ptr
Definition: Field.h:213
std::string parent
The name of the parent partition. We need this in order to open its group.
std::string name
The name of the layer (always available)
boost::intrusive_ptr< Partition > Ptr
hid_t id() const
Query the hid_t value.
Definition: Hdf5Util.h:100
Scoped object - opens an attribute data space on creation and closes it on destruction.
Definition: Hdf5Util.h:288
Scoped object - opens an attribute data type on creation and closes it on destruction.
Definition: Hdf5Util.h:311
Scoped object - Opens attribute by index and closes it on destruction.
Definition: Hdf5Util.h:143
Scoped object - Opens attribute by name and closes it on destruction.
Definition: Hdf5Util.h:114
Scoped object - creates a group on creation and closes it on destruction.
Definition: Hdf5Util.h:166
Scoped object - opens a group on creation and closes it on destruction.
Definition: Hdf5Util.h:195
FIELD3D_API bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
Namespace for Exception objects.
Definition: Exception.h:57
Namespace for file I/O specifics.
Contains utility functions and classes for Hdf5 files.
Definition: Hdf5Util.h:86
Namespace for file input specifics.
FIELD3D_API herr_t parsePartitions(hid_t loc_id, const char *partitionName, const H5L_info_t *linfo, void *opdata)
Gets called from readPartitionAndLayerInfo to check each group found under the root of the file....
FIELD3D_API herr_t parseLayers(hid_t loc_id, const char *partitionName, const H5L_info_t *linfo, void *opdata)
Gets called from readPartitionAndLayerInfo to check each group found under the root of the file....
@ SevWarning
Definition: Log.h:68
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Definition: Log.cpp:70
#define FIELD3D_MAJOR_VER
Definition: ns.h:38
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
#define FIELD3D_MINOR_VER
Definition: ns.h:39
#define FIELD3D_MICRO_VER
Definition: ns.h:40
struct used to pass the class and partition info back to the parseLayers() callback
Field3DInputFileHDF5 * file