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
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 //----------------------------------------------------------------------------//
Field3DFileHDF5Base::m_groupMembership
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
Definition: Field3DFileHDF5.h:403
Field3DFileHDF5Base::m_partitionNames
std::vector< std::string > m_partitionNames
This stores partition names.
Definition: Field3DFileHDF5.h:394
Field3DInputFileHDF5::~Field3DInputFileHDF5
virtual ~Field3DInputFileHDF5()
Definition: Field3DFileHDF5.cpp:579
ClassFactory::createFieldIO
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
Definition: ClassFactory.cpp:165
Hdf5Util::writeAttribute
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
V3i
Imath::V3i V3i
Definition: SpiMathLib.h:71
FieldMetadata::vecIntMetadata
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.
Definition: FieldMetadata.cpp:143
Field3DFileHDF5Base::m_partitionCount
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
Definition: Field3DFileHDF5.h:398
FieldMetadata::vecFloatMetadata
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.
Definition: FieldMetadata.cpp:113
Field3DFileHDF5Base::printHierarchy
void printHierarchy() const
Definition: Field3DFileHDF5.cpp:1564
Field3DOutputFileHDF5::writeMapping
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...
Definition: Field3DFileHDF5.cpp:1297
Field3DFileHDF5Base::Field3DFileHDF5Base
Field3DFileHDF5Base()
Definition: Field3DFileHDF5.cpp:290
FieldMetadata::intMetadata
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...
Definition: FieldMetadata.cpp:158
Exc::Exception::what
virtual const char * what() const
Definition: Exception.h:90
Field3DFileHDF5Base::GroupMembershipMap
std::map< std::string, std::string > GroupMembershipMap
Definition: Field3DFileHDF5.h:257
Field3DInputFileHDF5::open
bool open(const std::string &filename)
Opens the given file.
Definition: Field3DFileHDF5.cpp:586
Field3DFileHDF5Base::getScalarLayerNames
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
Definition: Field3DFileHDF5.cpp:403
Msg::SevWarning
Definition: Log.h:68
Field3DFileHDF5Base::numIntPartitions
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
Definition: Field3DFileHDF5.cpp:521
ClassFactory
Definition: ClassFactory.h:70
Field3DFileHDF5Base::close
bool close()
Closes the file. No need to call this unless you specifically want to close the file early....
Definition: Field3DFileHDF5.cpp:496
Field3DOutputFileHDF5::CreateMode
CreateMode
Definition: Field3DFileHDF5.h:773
InputFileHDF5::ParseLayersInfo::file
Field3DInputFileHDF5 * file
Definition: Field3DFileHDF5.h:886
FieldMappingIO::Ptr
boost::intrusive_ptr< FieldMappingIO > Ptr
Definition: FieldMappingIO.h:71
Hdf5Util::H5ScopedGcreate
Scoped object - creates a group on creation and closes it on destruction.
Definition: Hdf5Util.h:165
Field3DFileHDF5Base::clear
void clear()
Clear the data structures and close the file.
Definition: Field3DFileHDF5.cpp:487
Hdf5Util::H5Base::id
hid_t id() const
Query the hid_t value.
Definition: Hdf5Util.h:100
FileHDF5::Layer::name
std::string name
The name of the layer (always available)
Definition: Field3DFileHDF5.h:124
Field3DFileHDF5Base::partition
FileHDF5::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
Field3DInputFileHDF5::readPartitionAndLayerInfo
bool readPartitionAndLayerInfo()
Sets up all the partitions and layers, but does not load any data.
Definition: Field3DFileHDF5.cpp:706
InputFileHDF5::parsePartitions
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....
Definition: Field3DFileHDF5.cpp:1130
InputFileHDF5::ParseLayersInfo
struct used to pass the class and partition info back to the parseLayers() callback
Definition: Field3DFileHDF5.h:884
Field3DFileHDF5Base::removeUniqueId
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
Definition: Field3DFileHDF5.cpp:373
FIELD3D_MAJOR_VER
#define FIELD3D_MAJOR_VER
Definition: ns.h:38
Field3DOutputFileHDF5::writeMetadata
bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
Definition: Field3DFileHDF5.cpp:1320
Field3DFileHDF5Base::m_file
hid_t m_file
The hdf5 id of the current file. Will be -1 if no file is open.
Definition: Field3DFileHDF5.h:390
Field3DInputFileHDF5::parseLayer
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.
Definition: Field3DFileHDF5.cpp:814
Field3DOutputFileHDF5::incrementPartitionName
std::string incrementPartitionName(std::string &pname)
increment the partition or make it zero if there's not an integer suffix
Definition: Field3DFileHDF5.cpp:1546
FIELD3D_MICRO_VER
#define FIELD3D_MICRO_VER
Definition: ns.h:40
FieldMapping::Ptr
boost::intrusive_ptr< FieldMapping > Ptr
Definition: FieldMapping.h:92
Field3DInputFileHDF5::parsePartition
herr_t parsePartition(hid_t loc_id, const std::string partitionName)
Gets called from parsePartitions. Not intended for any other use.
Definition: Field3DFileHDF5.cpp:800
V3f
Imath::V3f V3f
Definition: SpiMathLib.h:73
Field3DFileHDF5Base::makeIntPartitionName
std::string makeIntPartitionName(const std::string &partitionsName, int i) const
Makes an internal partition name given the external partition name. Effectively just tacks on ....
Definition: Field3DFileHDF5.cpp:542
FileHDF5::Layer
Definition: Field3DFileHDF5.h:120
InputFileHDF5::parseLayers
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....
Definition: Field3DFileHDF5.cpp:1170
Field3DFileHDF5Base::getIntVectorLayerNames
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 ...
Definition: Field3DFileHDF5.cpp:470
FieldBase::Ptr
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
Hdf5Util::H5ScopedGopen
Scoped object - opens a group on creation and closes it on destruction.
Definition: Hdf5Util.h:194
Field3DOutputFileHDF5::create
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
Definition: Field3DFileHDF5.cpp:1239
FileHDF5::Layer::parent
std::string parent
The name of the parent partition. We need this in order to open its group.
Definition: Field3DFileHDF5.h:127
FIELD3D_MINOR_VER
#define FIELD3D_MINOR_VER
Definition: ns.h:39
Field3DFileHDF5Base::getIntScalarLayerNames
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 ...
Definition: Field3DFileHDF5.cpp:452
ClassFactory::singleton
static ClassFactory & singleton()
}
Definition: ClassFactory.cpp:278
Field3DOutputFileHDF5::~Field3DOutputFileHDF5
virtual ~Field3DOutputFileHDF5()
Definition: Field3DFileHDF5.cpp:1230
FieldMetadata::strMetadata
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...
Definition: FieldMetadata.cpp:173
Field3DFileHDF5Base::LayerInfo
Definition: Field3DFileHDF5.h:245
Exc::Exception
Definition: Exception.h:73
FieldRes::Ptr
boost::intrusive_ptr< FieldRes > Ptr
Definition: Field.h:213
FieldMetadata::setStrMetadata
void setStrMetadata(const std::string &name, const std::string &val)
Set the a string value for the given metadata name.
Definition: FieldMetadata.cpp:102
writeField
bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
Definition: Field3DFileHDF5.cpp:1589
FieldMetadata::setIntMetadata
void setIntMetadata(const std::string &name, const int val)
Set the a int value for the given metadata name.
Definition: FieldMetadata.cpp:91
Field3DFileHDF5Base::m_partitions
PartitionList m_partitions
Vector of partitions.
Definition: Field3DFileHDF5.h:392
Field3DFileHDF5.h
Contains the Field3DFileHDF5 classes.
FieldMetadata::setFloatMetadata
void setFloatMetadata(const std::string &name, const float val)
Set the a float value for the given metadata name.
Definition: FieldMetadata.cpp:69
Field3DInputFileHDF5::readMetadata
bool readMetadata(hid_t metadata_id, FieldBase::Ptr field) const
Read metadata for this layer.
Definition: Field3DFileHDF5.cpp:837
Field.h
Contains Field, WritableField and ResizableField classes.
Field3DFileHDF5Base::addGroupMembership
void addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
Definition: Field3DFileHDF5.cpp:551
Hdf5Util::H5ScopedAget_space
Scoped object - opens an attribute data space on creation and closes it on destruction.
Definition: Hdf5Util.h:287
g_hdf5Mutex
FIELD3D_NAMESPACE_OPEN FIELD3D_API boost::recursive_mutex g_hdf5Mutex
Definition: Hdf5Util.cpp:67
Field3DFileHDF5Base::~Field3DFileHDF5Base
virtual ~Field3DFileHDF5Base()=0
Pure virtual destructor to ensure we never instantiate this class.
Definition: Field3DFileHDF5.cpp:308
Hdf5Util::H5ScopedAopenIdx
Scoped object - Opens attribute by index and closes it on destruction.
Definition: Hdf5Util.h:142
Field3DFileHDF5Base::metadata
FieldMetadata & metadata()
accessor to the m_metadata class
Definition: Field3DFileHDF5.h:321
InputFileHDF5::ParseLayersInfo::partitionName
std::string partitionName
Definition: Field3DFileHDF5.h:887
FIELD3D_NAMESPACE_SOURCE_CLOSE
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
FieldMetadata::setVecFloatMetadata
void setVecFloatMetadata(const std::string &name, const V3f &val)
Set the a V3f value for the given metadata name.
Definition: FieldMetadata.cpp:58
Exc
Namespace for Exception objects.
Definition: Exception.h:57
Field3DOutputFileHDF5::Field3DOutputFileHDF5
Field3DOutputFileHDF5()
Definition: Field3DFileHDF5.cpp:1223
writeFieldMapping
bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
This function creates a FieldMappingIO instance based on mapping->className() which then writes Field...
Definition: Field3DFileHDF5.cpp:1645
GlobalLock
boost::recursive_mutex::scoped_lock GlobalLock
Definition: Hdf5Util.h:78
Field3DFileHDF5Base::closeInternal
void closeInternal()
Closes the file if open.
Definition: Field3DFileHDF5.cpp:505
Hdf5Util::readAttribute
FIELD3D_API bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
Field3DFileHDF5Base::intPartitionName
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 ...
Definition: Field3DFileHDF5.cpp:316
Hdf5Util
Contains utility functions and classes for Hdf5 files.
Definition: Hdf5Util.h:86
Field3DFileHDF5Base::getIntPartitionNames
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
Definition: Field3DFileHDF5.cpp:439
Field3DInputFileHDF5::m_filename
std::string m_filename
Filename, only to be set by open().
Definition: Field3DFileHDF5.h:736
readFieldMapping
FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
Definition: Field3DFileHDF5.cpp:1613
Hdf5Util::H5ScopedAopen
Scoped object - Opens attribute by name and closes it on destruction.
Definition: Hdf5Util.h:113
Field3DFileHDF5Base::getPartitionNames
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
Definition: Field3DFileHDF5.cpp:386
InputFileHDF5
Namespace for file input specifics.
Definition: Field3DFileHDF5.h:879
FieldIO::Ptr
boost::intrusive_ptr< FieldIO > Ptr
Definition: FieldIO.h:91
FIELD3D_NAMESPACE_OPEN
Definition: FieldMapping.cpp:74
Field3DOutputFileHDF5::writeGlobalMetadata
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
Definition: Field3DFileHDF5.cpp:1483
FileHDF5::Partition
Definition: Field3DFileHDF5.h:145
Field3DInputFileHDF5::readGroupMembership
bool readGroupMembership(GroupMembershipMap &gpMembershipMap)
Read the group membership for the partitions.
Definition: Field3DFileHDF5.cpp:1057
Msg::print
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
Field3DFileHDF5Base::m_layerInfo
std::vector< LayerInfo > m_layerInfo
This stores layer info.
Definition: Field3DFileHDF5.h:387
Field3DFileHDF5Base::getVectorLayerNames
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
Definition: Field3DFileHDF5.cpp:421
Hdf5Util::H5ScopedAget_type
Scoped object - opens an attribute data type on creation and closes it on destruction.
Definition: Hdf5Util.h:310
FileHDF5
Namespace for file I/O specifics.
Definition: Field3DFileHDF5.h:111
FieldMetadata::setVecIntMetadata
void setVecIntMetadata(const std::string &name, const V3i &val)
Set the a V3i value for the given metadata name.
Definition: FieldMetadata.cpp:80
FieldMetadata::floatMetadata
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...
Definition: FieldMetadata.cpp:128
ClassFactory::createFieldMappingIO
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
Definition: ClassFactory.cpp:266
Field3DOutputFileHDF5::writeGroupMembership
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
Definition: Field3DFileHDF5.cpp:1504
Field3DInputFileHDF5
Provides reading of .f3d (internally, hdf5) files.
Definition: Field3DFileHDF5.h:437
fileExists
bool fileExists(const std::string &filename)
checks to see if a file/directory exists or not
Definition: Field3DFile.cpp:1328
ClassFactory.h
Contains the ClassFactory class for registering Field3D classes.
Field3DInputFileHDF5::Field3DInputFileHDF5
Field3DInputFileHDF5()
Definition: Field3DFileHDF5.cpp:572
FileHDF5::Partition::Ptr
boost::intrusive_ptr< Partition > Ptr
Definition: Field3DFileHDF5.h:152