Field3D
Field3DFile.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2014 Sony Pictures Imageworks Inc.,
5  * Pixar Animation Studios Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the
18  * distribution. Neither the name of Sony Pictures Imageworks nor the
19  * names of its contributors may be used to endorse or promote
20  * products derived from this software without specific prior written
21  * permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34  * OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 //----------------------------------------------------------------------------//
38 
44 //----------------------------------------------------------------------------//
45 
46 #include "Field3DFile.h"
47 
48 #include <sys/stat.h>
49 #ifndef WIN32
50 #include <unistd.h>
51 #endif
52 
53 #include <boost/tokenizer.hpp>
54 #include <boost/utility.hpp>
55 
56 #include "Field.h"
57 #include "FieldCache.h"
58 #include "Field3DFileHDF5.h"
59 #include "ClassFactory.h"
60 #include "OArchive.h"
61 #include "OgIAttribute.h"
62 #include "OgIDataset.h"
63 #include "OgIGroup.h"
64 #include "OgOAttribute.h"
65 #include "OgODataset.h"
66 #include "OgOGroup.h"
67 
68 //----------------------------------------------------------------------------//
69 
70 using namespace std;
71 
72 //----------------------------------------------------------------------------//
73 
75 
76 //----------------------------------------------------------------------------//
77 // Field3D namespaces
78 //----------------------------------------------------------------------------//
79 
80 using namespace Exc;
81 
82 //----------------------------------------------------------------------------//
83 // Local namespace
84 //----------------------------------------------------------------------------//
85 
86 namespace {
87 
88  // Strings used only in this file --------------------------------------------
89 
90  const std::string k_mappingStr("mapping");
91  const std::string k_partitionName("partition");
92  const std::string k_versionAttrName("version_number");
93  const std::string k_classNameAttrName("class_name");
94  const std::string k_mappingTypeAttrName("mapping_type");
95 
98 
99  V3i k_currentFileVersion = V3i(FIELD3D_MAJOR_VER,
102  int k_minFileVersion[2] = { 0, 0 };
103 
104  // Function objects used only in this file -----------------------------------
105 
106  std::vector<std::string> makeUnique(std::vector<std::string> vec)
107  {
108  std::vector<string> ret;
109  std::sort(vec.begin(), vec.end());
110  std::vector<std::string>::iterator newEnd =
111  std::unique(vec.begin(), vec.end());
112  ret.resize(std::distance(vec.begin(), newEnd));
113  std::copy(vec.begin(), newEnd, ret.begin());
114  return ret;
115  }
116 
117  //--------------------------------------------------------------------------//
118 
120  template <class T>
121  class print : std::unary_function<T, void>
122  {
123  public:
124  print(int indentAmt)
125  : indent(indentAmt)
126  { }
127  void operator()(const T& x) const
128  {
129  for (int i = 0; i < indent; i++)
130  std::cout << " ";
131  std::cout << x << std::endl;
132  }
133  int indent;
134  };
135 
136  //--------------------------------------------------------------------------//
137 
143  void checkFile(const std::string &filename)
144  {
145  if (!fileExists(filename))
146  {
147  throw NoSuchFileException(filename);
148  }
149  }
150 
151  //--------------------------------------------------------------------------//
152 
153  bool isSupportedFileVersion(const int fileVersion[3],
154  const int minVersion[2])
155  {
156  stringstream currentVersionStr;
157  currentVersionStr << k_currentFileVersion[0] << "."
158  << k_currentFileVersion[1] << "."
159  << k_currentFileVersion[2];
160  stringstream fileVersionStr;
161  fileVersionStr << fileVersion[0] << "."
162  << fileVersion[1] << "."
163  << fileVersion[2];
164  stringstream minVersionStr;
165  minVersionStr << minVersion[0] << "."
166  << minVersion[1];
167 
168  if (fileVersion[0] > k_currentFileVersion[0] ||
169  (fileVersion[0] == k_currentFileVersion[0] &&
170  fileVersion[1] > k_currentFileVersion[1])) {
171  Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
172  " is higher than the current version " +
173  currentVersionStr.str());
174  return true;
175  }
176 
177  if (fileVersion[0] < minVersion[0] ||
178  (fileVersion[0] == minVersion[0] &&
179  fileVersion[1] < minVersion[1])) {
180  Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
181  " is lower than the minimum supported version " +
182  minVersionStr.str());
183  return false;
184  }
185  return true;
186  }
187 
190  FIELD3D_API FieldMapping::Ptr readFieldMapping(const OgIGroup &mappingGroup)
191  {
193 
194  OgIAttribute<string> mappingAttr =
195  mappingGroup.findAttribute<string>(k_mappingTypeAttrName);
196  if (!mappingAttr.isValid()) {
197  Msg::print(Msg::SevWarning, "Couldn't find " + k_mappingTypeAttrName +
198  " attribute");
199  return FieldMapping::Ptr();
200  }
201  const std::string className = mappingAttr.value();
202 
203  FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
204  assert(io != 0);
205  if (!io) {
206  Msg::print(Msg::SevWarning, "Unable to find class type: " + className);
207  return FieldMapping::Ptr();
208  }
209 
210  FieldMapping::Ptr mapping = io->read(mappingGroup);
211  if (!mapping) {
212  Msg::print(Msg::SevWarning, "Couldn't read mapping");
213  return FieldMapping::Ptr();
214  }
215 
216  return mapping;
217  }
218 
219  //--------------------------------------------------------------------------//
220 
223  FIELD3D_API bool writeField(OgOGroup &layerGroup, FieldBase::Ptr field)
224  {
226 
227  FieldIO::Ptr io = factory.createFieldIO(field->className());
228  assert(io != 0);
229  if (!io) {
230  Msg::print(Msg::SevWarning, "Unable to find class type: " +
231  field->className());
232  return false;
233  }
234 
235  // Add class name attribute
236  OgOAttribute<string>(layerGroup, k_classNameAttrName, field->className());
237 
238  return io->write(layerGroup, field);
240  return false;
241  }
242 
243  //--------------------------------------------------------------------------//
244 
247  template <class Data_T>
248  typename Field<Data_T>::Ptr
249  readField(const std::string &className, const OgIGroup &layerGroup,
250  const std::string &filename, const std::string &layerPath)
251  {
253 
254  typedef typename Field<Data_T>::Ptr FieldPtr;
255 
256  FieldIO::Ptr io = factory.createFieldIO(className);
257  if (!io) {
258  Msg::print(Msg::SevWarning, "Unable to find class type: " +
259  className);
260  return FieldPtr();
261  }
262 
263  OgDataType typeEnum = OgawaTypeTraits<Data_T>::typeEnum();
264  FieldBase::Ptr field = io->read(layerGroup, filename, layerPath, typeEnum);
265 
266  if (!field) {
267  // We don't need to print a message, because it could just be that
268  // a layer of the specified data type and name couldn't be found
269  return FieldPtr();
270  }
271 
272  FieldPtr result = field_dynamic_cast<Field<Data_T> >(field);
273 
274  if (result) {
275  return result;
276  }
277 
278  return FieldPtr();
279  }
280 
281  //--------------------------------------------------------------------------//
282 
283  bool readMeta(const OgIGroup &group, FieldMetadata &metadata)
284  {
285  // Grab all the attribute names
286  std::vector<std::string> attrs = group.attributeNames();
287  // Loop over attribute names and test types
288  for (size_t i = 0, end = attrs.size(); i < end; ++i) {
289  // String metadata
290  {
291  OgIAttribute<string> attr = group.findAttribute<string>(attrs[i]);
292  if (attr.isValid()) {
293  metadata.setStrMetadata(attrs[i], attr.value());
294  }
295  }
296  // Int metadata
297  {
298  OgIAttribute<int> attr = group.findAttribute<int>(attrs[i]);
299  if (attr.isValid()) {
300  metadata.setIntMetadata(attrs[i], attr.value());
301  }
302  }
303  // Float metadata
304  {
305  OgIAttribute<float> attr = group.findAttribute<float>(attrs[i]);
306  if (attr.isValid()) {
307  metadata.setFloatMetadata(attrs[i], attr.value());
308  }
309  }
310  // VecInt metadata
311  {
312  OgIAttribute<veci32_t> attr = group.findAttribute<veci32_t>(attrs[i]);
313  if (attr.isValid()) {
314  metadata.setVecIntMetadata(attrs[i], attr.value());
315  }
316  }
317  // VecFloat metadata
318  {
319  OgIAttribute<vec32_t> attr = group.findAttribute<vec32_t>(attrs[i]);
320  if (attr.isValid()) {
321  metadata.setVecFloatMetadata(attrs[i], attr.value());
322  }
323  }
324  }
325 
326  return true;
327  }
328 
329  //--------------------------------------------------------------------------//
330 
331 } // end of local namespace
332 
333 //----------------------------------------------------------------------------//
334 // File namespace
335 //----------------------------------------------------------------------------//
336 
337 namespace File {
338 
339 //----------------------------------------------------------------------------//
340 // Partition implementations
341 //----------------------------------------------------------------------------//
342 
343 std::string Partition::className() const
344 {
345  return k_partitionName;
346 }
347 
348 //----------------------------------------------------------------------------//
349 
350 void
351 Partition::addLayer(const Layer &layer)
352 {
353  m_layers.push_back(layer);
354 }
355 
356 //----------------------------------------------------------------------------//
357 
358 const Layer*
359 Partition::layer(const std::string &name) const
360 {
361  for (LayerList::const_iterator i = m_layers.begin();
362  i != m_layers.end(); ++i) {
363  if (i->name == name) {
364  return &(*i);
365  }
366  }
367  return NULL;
368 }
369 
370 //----------------------------------------------------------------------------//
371 
372 void
373 Partition::getLayerNames(std::vector<std::string> &names) const
374 {
375  // We don't want to do names.clear() here, since this gets called
376  // inside some loops that want to accumulate names.
377  for (LayerList::const_iterator i = m_layers.begin();
378  i != m_layers.end(); ++i) {
379  names.push_back(i->name);
380  }
381 }
382 
383 //----------------------------------------------------------------------------//
384 
385 OgOGroup& Partition::group() const
386 {
387  return *m_group;
388 }
389 
390 //----------------------------------------------------------------------------//
391 
392 void Partition::setGroup(boost::shared_ptr<OgOGroup> ptr)
393 {
394  m_group = ptr;
395 }
396 
397 //----------------------------------------------------------------------------//
398 
399 } // namespace File
400 
401 //----------------------------------------------------------------------------//
402 // Field3DFileBase implementations
403 //----------------------------------------------------------------------------//
404 
406  : m_metadata(this)
407 {
408  // Empty
409 }
410 
411 //----------------------------------------------------------------------------//
412 
414 {
415  m_partitions.clear();
416  m_groupMembership.clear();
417 }
418 
419 //----------------------------------------------------------------------------//
420 
421 std::string
422 Field3DFileBase::intPartitionName(const std::string &partitionName,
423  const std::string & /* layerName */,
424  FieldRes::Ptr field)
425 {
426  // Loop over existing partitions and see if there's a matching mapping
427  for (PartitionList::const_iterator i = m_partitions.begin();
428  i != m_partitions.end(); ++i) {
429  if (removeUniqueId((**i).name) == partitionName) {
430  if ((**i).mapping->isIdentical(field->mapping())) {
431  return (**i).name;
432  }
433  }
434  }
435 
436  // If there was no previously matching name, then make a new one
437 
438  int nextIdx = -1;
439  if (m_partitionCount.find(partitionName) != m_partitionCount.end()) {
440  nextIdx = ++m_partitionCount[partitionName];
441  } else {
442  nextIdx = 0;
443  m_partitionCount[partitionName] = 0;
444  }
445 
446  return makeIntPartitionName(partitionName, nextIdx);
447 }
448 
449 //----------------------------------------------------------------------------//
450 
451 File::Partition::Ptr Field3DFileBase::partition(const string &partitionName)
452 {
453  for (PartitionList::iterator i = m_partitions.begin();
454  i != m_partitions.end(); ++i) {
455  if ((**i).name == partitionName)
456  return *i;
457  }
458 
459  return File::Partition::Ptr();
460 }
461 
462 //----------------------------------------------------------------------------//
463 
465 Field3DFileBase::partition(const string &partitionName) const
466 {
467  for (PartitionList::const_iterator i = m_partitions.begin();
468  i != m_partitions.end(); ++i) {
469  if ((**i).name == partitionName)
470  return *i;
471  }
472 
473  return File::Partition::Ptr();
474 }
475 
476 //----------------------------------------------------------------------------//
477 
478 std::string
479 Field3DFileBase::removeUniqueId(const std::string &partitionName) const
480 {
481  size_t pos = partitionName.rfind(".");
482  if (pos == partitionName.npos) {
483  return partitionName;
484  } else {
485  return partitionName.substr(0, pos);
486  }
487 }
488 
489 //----------------------------------------------------------------------------//
490 
491 void
492 Field3DFileBase::getPartitionNames(vector<string> &names) const
493 {
494  if (m_hdf5Base) {
495  m_hdf5Base->getPartitionNames(names);
496  return;
497  }
498 
499  names.clear();
500 
501  vector<string> tempNames;
502 
503  for (PartitionList::const_iterator i = m_partitions.begin();
504  i != m_partitions.end(); ++i) {
505  tempNames.push_back(removeUniqueId((**i).name));
506  }
507 
508  names = makeUnique(tempNames);
509 }
510 
511 //----------------------------------------------------------------------------//
512 
513 void
515  const string &partitionName) const
516 {
517  if (m_hdf5Base) {
518  m_hdf5Base->getScalarLayerNames(names, partitionName);
519  return;
520  }
521 
523 
524  names.clear();
525 
526  for (int i = 0; i < numIntPartitions(partitionName); i++) {
527  string internalName = makeIntPartitionName(partitionName, i);
528  File::Partition::Ptr part = partition(internalName);
529  if (part)
530  part->getLayerNames(names);
531  }
532 
533  names = makeUnique(names);
534 }
535 
536 //----------------------------------------------------------------------------//
537 
538 void
540  const string &partitionName) const
541 {
542  if (m_hdf5Base) {
543  m_hdf5Base->getVectorLayerNames(names, partitionName);
544  return;
545  }
546 
548 
549  names.clear();
550 
551  for (int i = 0; i < numIntPartitions(partitionName); i++) {
552  string internalName = makeIntPartitionName(partitionName, i);
553  File::Partition::Ptr part = partition(internalName);
554  if (part)
555  part->getLayerNames(names);
556  }
557 
558  names = makeUnique(names);
559 }
560 
561 //----------------------------------------------------------------------------//
562 
563 void
564 Field3DFileBase::getIntPartitionNames(vector<string> &names) const
565 {
566  names.clear();
567 
568  for (PartitionList::const_iterator i = m_partitions.begin();
569  i != m_partitions.end(); ++i) {
570  names.push_back((**i).name);
571  }
572 }
573 
574 //----------------------------------------------------------------------------//
575 
576 void
578  const string &intPartitionName) const
579 {
581 
582  names.clear();
583 
584  File::Partition::Ptr part = partition(intPartitionName);
585 
586  if (!part) {
587  Msg::print("getIntScalarLayerNames no partition: " + intPartitionName);
588  return;
589  }
590 
591  part->getLayerNames(names);
592 }
593 
594 //----------------------------------------------------------------------------//
595 
596 void
598  const string &intPartitionName) const
599 {
601 
602  names.clear();
603 
604  File::Partition::Ptr part = partition(intPartitionName);
605 
606  if (!part) {
607  Msg::print("getIntVectorLayerNames no partition: " + intPartitionName);
608  return;
609  }
610 
611  part->getLayerNames(names);
612 }
613 
614 //----------------------------------------------------------------------------//
615 
617 {
618  if (m_hdf5Base) {
619  m_hdf5Base->clear();
620  return;
621  }
622 
623  closeInternal();
624  m_partitions.clear();
625  m_groupMembership.clear();
626 }
627 
628 //----------------------------------------------------------------------------//
629 
631 {
632  if (m_hdf5Base) {
633  return m_hdf5Base->close();
634  }
635 
636  closeInternal();
637 
638  return true;
639 }
640 
641 //----------------------------------------------------------------------------//
642 
643 int
644 Field3DFileBase::numIntPartitions(const std::string &partitionName) const
645 {
646  int count = 0;
647 
648  for (PartitionList::const_iterator i = m_partitions.begin();
649  i != m_partitions.end(); ++i) {
650  string name = (**i).name;
651  size_t pos = name.rfind(".");
652  if (pos != name.npos) {
653  if (name.substr(0, pos) == partitionName) {
654  count++;
655  }
656  }
657  }
658 
659  return count;
660 }
661 
662 //----------------------------------------------------------------------------//
663 
664 string
665 Field3DFileBase::makeIntPartitionName(const std::string &partitionName,
666  int i) const
667 {
668  return partitionName + "." + boost::lexical_cast<std::string>(i);
669 }
670 
671 //----------------------------------------------------------------------------//
672 
673 void
675 {
676  if (m_hdf5Base) {
677  m_hdf5Base->addGroupMembership(groupMembers);
678  return;
679  }
680 
681  GroupMembershipMap::const_iterator i = groupMembers.begin();
682  GroupMembershipMap::const_iterator end = groupMembers.end();
683 
684  for (; i != end; ++i) {
685  GroupMembershipMap::iterator foundGroupIter =
686  m_groupMembership.find(i->first);
687  if (foundGroupIter != m_groupMembership.end()){
688  std::string value = m_groupMembership[i->first] + i->second;
689  m_groupMembership[i->first] = value;
690  } else {
691  m_groupMembership[i->first] = i->second;
692  }
693  }
694 }
695 
696 //----------------------------------------------------------------------------//
697 // Field3DInputFile implementations
698 //----------------------------------------------------------------------------//
699 
701 {
702  // Empty
703 }
704 
705 //----------------------------------------------------------------------------//
706 
708 {
709  cleanup();
710 }
711 
712 //----------------------------------------------------------------------------//
713 
714 bool Field3DInputFile::open(const string &filename)
715 {
716  clear();
717 
718  bool success = true;
719 
720  // Record filename
721  m_filename = filename;
722 
723  try {
724 
725  // Throws exceptions if the file doesn't exist.
726  checkFile(filename);
727 
728  // Open the Ogawa archive
729  m_archive.reset(new Alembic::Ogawa::IArchive(filename));
730 
731  // Error check and HDF5 fallback
732  if (!m_archive->isValid()) {
733  m_hdf5.reset(new Field3DInputFileHDF5);
734  m_hdf5Base = m_hdf5;
735  if (m_hdf5->open(filename)) {
736  // Handled. Just return.
737  return true;
738  } else {
739  throw NoSuchFileException(filename);
740  }
741  }
742 
743  // Grab the root group
744  m_root.reset(new OgIGroup(*m_archive));
745 
746  // Check version number
747  try {
748  OgIAttribute<veci32_t> version =
749  m_root->findAttribute<veci32_t>(k_versionAttrName);
750  if (!version.isValid()) {
751  throw OgIAttributeException("Missing version attribute.");
752  }
753  int fileVersion[3] = { version.value()[0],
754  version.value()[1],
755  version.value()[2] };
756  if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
757  stringstream versionStr;
758  versionStr << fileVersion[0] << "."
759  << fileVersion[1] << "."
760  << fileVersion[2];
761  throw UnsupportedVersionException(versionStr.str());
762  }
763  }
764  catch (OgIAttributeException &e) {
765 
766  }
767 
768  // Read the global metadata. This does not always exists,
769  // depends on if it was written or not.
770  try {
771  const OgIGroup metadataGroup = m_root->findGroup("field3d_global_metadata");
772  if (metadataGroup.isValid()) {
773  readMetadata(metadataGroup);
774  }
775  }
776  catch (...) {
778  "Unknown error when reading file metadata ");
779  }
780 
781  // Read the partition and layer info
782  try {
783  if (!readPartitionAndLayerInfo()) {
784  success = false;
785  }
786  }
787  catch (MissingGroupException &e) {
788  Msg::print(Msg::SevWarning, "Missing group: " + string(e.what()));
789  throw BadFileHierarchyException(filename);
790  }
791  catch (ReadMappingException &e) {
792  Msg::print(Msg::SevWarning, "Couldn't read mapping for partition: "
793  + string(e.what()));
794  throw BadFileHierarchyException(filename);
795  }
796  catch (Exception &e) {
797  Msg::print(Msg::SevWarning, "Unknown error when reading file hierarchy: "
798  + string(e.what()));
799  throw BadFileHierarchyException(filename);
800  }
801  catch (...) {
803  "Unknown error when reading file hierarchy. ");
804  throw BadFileHierarchyException(filename);
805  }
806  }
807  catch (NoSuchFileException &e) {
808  Msg::print(Msg::SevWarning, "Couldn't open file: "
809  + string(e.what()) );
810  success = false;
811  }
812  catch (MissingAttributeException &e) {
814  "In file: " + filename + " - "
815  + string(e.what()) );
816  success = false;
817  }
818  catch (UnsupportedVersionException &e) {
820  "In file: " + filename + " - File version can not be read: "
821  + string(e.what()));
822  success = false;
823  }
824  catch (BadFileHierarchyException &) {
826  "In file: " + filename + " - Bad file hierarchy. ");
827  success = false;
828  }
829  catch (runtime_error &e) {
830  // HDF5 fallback
831  m_hdf5.reset(new Field3DInputFileHDF5);
832  m_hdf5Base = m_hdf5;
833  if (m_hdf5->open(filename)) {
834  // Handled. Just return.
835  return true;
836  } else {
838  "In file: " + filename + ": " + string(e.what()));
839  success = false;
840  }
841  }
842  catch (...) {
844  "In file: " + filename + " Unknown exception ");
845  success = false;
846  }
847 
848  if (!success) {
849  close();
850  }
851 
852  return success;
853 }
854 
855 //----------------------------------------------------------------------------//
856 
858 {
859  // Find all the partition names
860  std::vector<std::string> groups = m_root->groupNames();
861 
862  // Store the partition names
863  m_partitions.clear();
864  for (std::vector<std::string>::const_iterator i = groups.begin(),
865  end = groups.end(); i != end; ++i) {
866  // Grab the name
867  const std::string &name = *i;
868  // Skip metadata
869  if (name == "field3d_global_metadata") {
870  continue;
871  }
872  // Build partition
874  part->name = name;
875  m_partitions.push_back(part);
876  }
877 
878  // For each partition, find its mapping ---
879 
880  for (PartitionList::iterator i = m_partitions.begin();
881  i != m_partitions.end(); ++i) {
882  // Grab the name
883  const std::string &name = (**i).name;
884  // Open the partition group
885  const OgIGroup partitionGroup = m_root->findGroup(name);
886  if (!partitionGroup.isValid()) {
887  Msg::print(Msg::SevWarning, "Couldn't open partition group " + name);
888  }
889  // Open the mapping group
890  const OgIGroup mappingGroup = partitionGroup.findGroup(k_mappingStr);
891  if (!mappingGroup.isValid()) {
892  Msg::print(Msg::SevWarning, "Couldn't open mapping group " + name);
893  }
894  // Build the mapping
895  FieldMapping::Ptr mapping = readFieldMapping(mappingGroup);
896 #if 0
897  if (!mapping) {
898  Msg::print(Msg::SevWarning, "Got a null pointer when reading mapping");
899  throw ReadMappingException((**i).name);
900  }
901 #endif
902  // Attach the mapping to the partition
903  (**i).mapping = mapping;
904  }
905 
906  // ... And then find its layers ---
907 
908  for (PartitionList::const_iterator i = m_partitions.begin();
909  i != m_partitions.end(); ++i) {
910  // Grab the name
911  const std::string &partitionName = (**i).name;
912  // Open the partition group
913  const OgIGroup partitionGroup = m_root->findGroup(partitionName);
914  if (!partitionGroup.isValid()) {
915  Msg::print(Msg::SevWarning, "Couldn't open partition group " +
916  partitionName);
917  }
918  // Get all the layer names
919  groups = partitionGroup.groupNames();
920  for (std::vector<std::string>::const_iterator l = groups.begin(),
921  lEnd = groups.end(); l != lEnd; ++l) {
922  // Grab layer name
923  const std::string layerName = *l;
924  // Skip the mapping group
925  if (layerName == k_mappingStr) {
926  continue;
927  }
928  // Construct the layer
929  File::Layer layer;
930  layer.name = *l;
931  layer.parent = partitionName;
932  // Add to partition
933  partition(partitionName)->addLayer(layer);
934  }
935  }
936 
937  return true;
938 }
939 
940 //----------------------------------------------------------------------------//
941 
942 bool Field3DInputFile::readMetadata(const OgIGroup &metadataGroup,
943  FieldBase::Ptr field) const
944 {
945  return readMeta(metadataGroup, field->metadata());
946 }
947 
948 //----------------------------------------------------------------------------//
949 
950 bool Field3DInputFile::readMetadata(const OgIGroup &metadataGroup)
951 {
952  return readMeta(metadataGroup, metadata());
953 }
954 
955 //----------------------------------------------------------------------------//
956 // Field3DOutputFile implementations
957 //----------------------------------------------------------------------------//
958 
960 
961 //----------------------------------------------------------------------------//
962 
964 {
965  // Empty
966 }
967 
968 //----------------------------------------------------------------------------//
969 
971 {
972  cleanup();
973 }
974 
975 //----------------------------------------------------------------------------//
976 
977 bool Field3DOutputFile::create(const string &filename, CreateMode cm)
978 {
979  if (!ms_doOgawa) {
980  m_hdf5.reset(new Field3DOutputFileHDF5);
981  m_hdf5Base = m_hdf5;
982  int ccm = cm;
983  return m_hdf5->create(filename, Field3DOutputFileHDF5::CreateMode(ccm));
984  }
985 
986  closeInternal();
987 
988  if (cm == FailOnExisting && fileExists(filename)) {
989  return false;
990  }
991 
992  // Create the Ogawa archive
993  m_archive.reset(new Alembic::Ogawa::OArchive(filename));
994 
995  // Check that it's valid
996  if (!m_archive->isValid()) {
997  m_archive.reset();
998  return false;
999  }
1000 
1001  // Get the root
1002  m_root.reset(new OgOGroup(*m_archive));
1003 
1004  // Create the version attribute
1005  OgOAttribute<veci32_t> f3dVersion(*m_root, k_versionAttrName,
1006  k_currentFileVersion);
1007 
1008  return true;
1009 }
1010 
1011 //----------------------------------------------------------------------------//
1012 
1013 bool Field3DOutputFile::writeMapping(OgOGroup &partitionGroup,
1014  FieldMapping::Ptr mapping)
1015 {
1017  const std::string className = mapping->className();
1018 
1019  try {
1020 
1021  OgOGroup mappingGroup(partitionGroup, k_mappingStr);
1022 
1023  OgOAttribute<string> classNameAttr(mappingGroup, k_mappingTypeAttrName,
1024  className);
1025 
1026  FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
1027  if (!io) {
1028  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1029  className);
1030  return false;
1031  }
1032 
1033  return io->write(mappingGroup, mapping);
1034 
1035  }
1036  catch (OgOGroupException &e) {
1037  Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
1038  throw WriteMappingException(k_mappingStr);
1039  }
1040 
1041 }
1042 
1043 //----------------------------------------------------------------------------//
1044 
1045 bool Field3DOutputFile::writeMetadata(OgOGroup &metadataGroup,
1046  FieldBase::Ptr field)
1047 {
1048  {
1049  FieldMetadata::StrMetadata::const_iterator i =
1050  field->metadata().strMetadata().begin();
1051  FieldMetadata::StrMetadata::const_iterator end =
1052  field->metadata().strMetadata().end();
1053  for (; i != end; ++i) {
1054  try {
1055  OgOAttribute<string>(metadataGroup, i->first, i->second);
1056  }
1057  catch (OgOAttributeException &e) {
1058  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1059  " " + e.what());
1060  return false;
1061  }
1062  }
1063  }
1064 
1065  {
1066  FieldMetadata::IntMetadata::const_iterator i =
1067  field->metadata().intMetadata().begin();
1068  FieldMetadata::IntMetadata::const_iterator end =
1069  field->metadata().intMetadata().end();
1070  for (; i != end; ++i) {
1071  try {
1072  OgOAttribute<int32_t>(metadataGroup, i->first, i->second);
1073  }
1074  catch (OgOAttributeException &e) {
1075  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1076  " " + e.what());
1077  return false;
1078  }
1079  }
1080  }
1081 
1082  {
1083  FieldMetadata::FloatMetadata::const_iterator i =
1084  field->metadata().floatMetadata().begin();
1085  FieldMetadata::FloatMetadata::const_iterator end =
1086  field->metadata().floatMetadata().end();
1087  for (; i != end; ++i) {
1088  try {
1089  OgOAttribute<float32_t>(metadataGroup, i->first, i->second);
1090  }
1091  catch (OgOAttributeException &e) {
1092  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1093  " " + e.what());
1094  return false;
1095  }
1096  }
1097  }
1098 
1099  {
1100  FieldMetadata::VecIntMetadata::const_iterator i =
1101  field->metadata().vecIntMetadata().begin();
1102  FieldMetadata::VecIntMetadata::const_iterator end =
1103  field->metadata().vecIntMetadata().end();
1104  for (; i != end; ++i) {
1105  try {
1106  OgOAttribute<veci32_t>(metadataGroup, i->first, i->second);
1107  }
1108  catch (OgOAttributeException &e) {
1109  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1110  " " + e.what());
1111  return false;
1112  }
1113  }
1114  }
1115 
1116  {
1117  FieldMetadata::VecFloatMetadata::const_iterator i =
1118  field->metadata().vecFloatMetadata().begin();
1119  FieldMetadata::VecFloatMetadata::const_iterator end =
1120  field->metadata().vecFloatMetadata().end();
1121  for (; i != end; ++i) {
1122  try {
1123  OgOAttribute<vec32_t>(metadataGroup, i->first, i->second);
1124  }
1125  catch (OgOAttributeException &e) {
1126  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1127  " " + e.what());
1128  return false;
1129  }
1130  }
1131 
1132  }
1133 
1134  return true;
1135 
1136 }
1137 
1138 //----------------------------------------------------------------------------//
1139 
1140 bool Field3DOutputFile::writeMetadata(OgOGroup &metadataGroup)
1141 {
1142  {
1143  FieldMetadata::StrMetadata::const_iterator i =
1144  metadata().strMetadata().begin();
1145  FieldMetadata::StrMetadata::const_iterator end =
1146  metadata().strMetadata().end();
1147  for (; i != end; ++i) {
1148  try {
1149  OgOAttribute<string>(metadataGroup, i->first, i->second);
1150  }
1151  catch (OgOAttributeException &e) {
1152  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1153  " " + e.what());
1154  return false;
1155  }
1156  }
1157  }
1158 
1159  {
1160  FieldMetadata::IntMetadata::const_iterator i =
1161  metadata().intMetadata().begin();
1162  FieldMetadata::IntMetadata::const_iterator end =
1163  metadata().intMetadata().end();
1164  for (; i != end; ++i) {
1165  try {
1166  OgOAttribute<int32_t>(metadataGroup, i->first, i->second);
1167  }
1168  catch (OgOAttributeException &e) {
1169  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1170  " " + e.what());
1171  return false;
1172  }
1173  }
1174  }
1175 
1176  {
1177  FieldMetadata::FloatMetadata::const_iterator i =
1178  metadata().floatMetadata().begin();
1179  FieldMetadata::FloatMetadata::const_iterator end =
1180  metadata().floatMetadata().end();
1181  for (; i != end; ++i) {
1182  try {
1183  OgOAttribute<float32_t>(metadataGroup, i->first, i->second);
1184  }
1185  catch (OgOAttributeException &e) {
1186  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1187  " " + e.what());
1188  return false;
1189  }
1190  }
1191  }
1192 
1193  {
1194  FieldMetadata::VecIntMetadata::const_iterator i =
1195  metadata().vecIntMetadata().begin();
1196  FieldMetadata::VecIntMetadata::const_iterator end =
1197  metadata().vecIntMetadata().end();
1198  for (; i != end; ++i) {
1199  try {
1200  OgOAttribute<veci32_t>(metadataGroup, i->first, i->second);
1201  }
1202  catch (OgOAttributeException &e) {
1203  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1204  " " + e.what());
1205  return false;
1206  }
1207  }
1208  }
1209 
1210  {
1211  FieldMetadata::VecFloatMetadata::const_iterator i =
1212  metadata().vecFloatMetadata().begin();
1213  FieldMetadata::VecFloatMetadata::const_iterator end =
1214  metadata().vecFloatMetadata().end();
1215  for (; i != end; ++i) {
1216  try {
1217  OgOAttribute<vec32_t>(metadataGroup, i->first, i->second);
1218  }
1219  catch (OgOAttributeException &e) {
1220  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1221  " " + e.what());
1222  return false;
1223  }
1224  }
1225 
1226  }
1227 
1228  return true;
1229 }
1230 
1231 //----------------------------------------------------------------------------//
1232 
1233 bool
1235 {
1236  if (m_hdf5) {
1237  return m_hdf5->writeGlobalMetadata();
1238  }
1239 
1240  OgOGroup ogMetadata(*m_root, "field3d_global_metadata");
1241  if (!writeMetadata(ogMetadata)) {
1242  Msg::print(Msg::SevWarning, "Error writing file metadata.");
1243  return false;
1244  }
1245 
1246  return true;
1247 }
1248 
1249 //----------------------------------------------------------------------------//
1250 
1251 bool
1253 {
1254  if (m_hdf5) {
1255  return m_hdf5->writeGroupMembership();
1256  }
1257 
1258 #if 0
1259 
1261 
1262  using namespace std;
1263  using namespace Hdf5Util;
1264 
1265  if (!m_groupMembership.size())
1266  return true;
1267 
1268  H5ScopedGcreate group(m_file, "field3d_group_membership");
1269  if (group < 0) {
1271  "Error creating field3d_group_membership group.");
1272  return false;
1273  }
1274 
1275  if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
1277  "Failed to write field3d_group_membership attribute.");
1278  return false;
1279  }
1280 
1281  std::map<std::string, std::string>::const_iterator iter =
1282  m_groupMembership.begin();
1283  std::map<std::string, std::string>::const_iterator iEnd =
1284  m_groupMembership.end();
1285 
1286  for (; iter != iEnd; ++iter) {
1287  if (!writeAttribute(group, iter->first, iter->second)) {
1289  "Failed to write groupMembership string: "+ iter->first);
1290  return false;
1291  }
1292  }
1293 
1294 #endif
1295 
1296  return true;
1297 }
1298 
1299 //----------------------------------------------------------------------------//
1300 
1301 std::string
1303 {
1304  std::string myPartitionName = removeUniqueId(partitionName);
1305  int nextIdx = -1;
1306  if (m_partitionCount.find(myPartitionName) != m_partitionCount.end()) {
1307  nextIdx = ++m_partitionCount[myPartitionName];
1308  } else {
1309  nextIdx = 0;
1310  m_partitionCount[myPartitionName] = 0;
1311  }
1312 
1313  return makeIntPartitionName(myPartitionName, nextIdx);
1314 }
1315 
1316 //----------------------------------------------------------------------------//
1317 // Debug
1318 //----------------------------------------------------------------------------//
1319 
1321 {
1322  // For each partition
1323  for (PartitionList::const_iterator i = m_partitions.begin();
1324  i != m_partitions.end(); ++i) {
1325  cout << "Name: " << (**i).name << endl;
1326  if ((**i).mapping)
1327  cout << " Mapping: " << (**i).mapping->className() << endl;
1328  else
1329  cout << " Mapping: NULL" << endl;
1330  cout << " Layers: " << endl;
1331  vector<string> names;
1332  (**i).getLayerNames(names);
1333  for_each(names.begin(), names.end(), print<string>(4));
1334  }
1335 }
1336 
1337 //----------------------------------------------------------------------------//
1338 // Function Implementations
1339 //----------------------------------------------------------------------------//
1340 
1341 bool fileExists(const std::string &filename)
1342 {
1343 #ifdef WIN32
1344  struct __stat64 statbuf;
1345  return (_stat64(filename.c_str(), &statbuf) != -1);
1346 #else
1347  struct stat statbuf;
1348  return (stat(filename.c_str(), &statbuf) != -1);
1349 #endif
1350 }
1351 
1352 //----------------------------------------------------------------------------//
1353 
1355 Field3DOutputFile::createNewPartition(const std::string &partitionName,
1356  const std::string & /* layerName */,
1357  FieldRes::Ptr field)
1358 {
1359  using namespace Exc;
1360 
1362  newPart->name = partitionName;
1363 
1364  boost::shared_ptr<OgOGroup> ogPartition(new OgOGroup(*m_root, newPart->name));
1365  newPart->setGroup(ogPartition);
1366 
1367  m_partitions.push_back(newPart);
1368 
1369  // Pick up new pointer
1370  File::Partition::Ptr part = partition(partitionName);
1371 
1372  // Add mapping group to the partition
1373  try {
1374  if (!writeMapping(*ogPartition, field->mapping())) {
1376  "writeMapping returned false for an unknown reason ");
1377  return File::Partition::Ptr();
1378  }
1379  }
1380  catch (WriteMappingException &e) {
1381  Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: "
1382  + partitionName);
1383  return File::Partition::Ptr();
1384  }
1385  catch (...) {
1387  "Unknown error when writing mapping for partition: "
1388  + partitionName);
1389  return File::Partition::Ptr();
1390  }
1391 
1392  // Set the mapping of the partition. Since all layers share their
1393  // partition's mapping, we can just pick this first one. All subsequent
1394  // additions to the same partition are checked to have the same mapping
1395  part->mapping = field->mapping();
1396 
1397  // Tag node as partition
1398  // Create a version attribute on the root node
1399  OgOAttribute<string>(*ogPartition, "is_field3d_partition", "1");
1400 
1401  return part;
1402 }
1403 
1404 //----------------------------------------------------------------------------//
1405 // Template implementations
1406 //----------------------------------------------------------------------------//
1407 
1408 template <class Data_T>
1409 bool Field3DOutputFile::writeLayer(const std::string &userPartitionName,
1410  const std::string &layerName,
1411  typename Field<Data_T>::Ptr field)
1412 {
1413  using std::string;
1414 
1415  // Null pointer check
1416  if (!field) {
1418  "Called writeLayer with null pointer. Ignoring...");
1419  return false;
1420  }
1421 
1422  // Make sure archive is open
1423  if (!m_archive) {
1425  "Attempting to write layer without opening file first.");
1426  return false;
1427  }
1428 
1429  // Get the partition name
1430  string partitionName = intPartitionName(userPartitionName, layerName, field);
1431 
1432  // Get the partition
1433  File::Partition::Ptr part = partition(partitionName);
1434 
1435  if (!part) {
1436  // Create a new partition
1437  part = createNewPartition(partitionName, layerName, field);
1438  // Make sure it was created
1439  if (!part) {
1440  return false;
1441  }
1442  } else {
1443  // Check that we have a valid mapping
1444  if (!field->mapping()) {
1446  "Couldn't add layer \"" + layerName + "\" to partition \""
1447  + partitionName + "\" because the layer's mapping is null.");
1448  return false;
1449  }
1450  // Check if the layer already exists. If it does, we need to make a
1451  // different partition
1452  if (part->layer(layerName)) {
1453  // Increment the internal partition name
1454  partitionName = incrementPartitionName(partitionName);
1455  // Create a new partition
1456  part = createNewPartition(partitionName, layerName, field);
1457  // Make sure it was created
1458  if (!part) {
1459  return false;
1460  }
1461  }
1462  }
1463 
1464  // Check mapping not null
1465  if (!part->mapping) {
1466  Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: "
1467  + partitionName);
1468  return false;
1469  }
1470 
1471  // Check that the mapping matches what's already in the Partition
1472  if (!field->mapping()->isIdentical(part->mapping)) {
1473  Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName
1474  + "\" to partition \"" + partitionName
1475  + "\" because mapping doesn't match");
1476  return false;
1477  }
1478 
1479  // Open the partition
1480 
1481  OgOGroup &ogPartition = part->group();
1482 
1483  // Build a Layer
1484 
1485  File::Layer layer;
1486  layer.name = layerName;
1487  layer.parent = partitionName;
1488 
1489  // Add Layer to file ---
1490 
1491  OgOGroup ogLayer(ogPartition, layerName);
1492 
1493  // Tag as layer
1494  OgOAttribute<string> classType(ogLayer, "class_type", "field3d_layer");
1495 
1496  // Create metadata
1497  OgOGroup ogMetadata(ogLayer, "metadata");
1498 
1499  // Write metadata
1500  writeMetadata(ogMetadata, field);
1501 
1502  // Write field data
1503  writeField(ogLayer, field);
1504 
1505  // Add to partition
1506 
1507  part->addLayer(layer);
1508 
1509  return true;
1510 }
1511 
1512 //----------------------------------------------------------------------------//
1513 
1514 template <class Data_T>
1515 typename Field<Data_T>::Ptr
1517  const std::string &layerName) const
1518 {
1519  typedef typename Field<Data_T>::Ptr FieldPtr;
1520 
1521  // Instantiate a null pointer for easier code reading
1522  FieldPtr nullPtr;
1523 
1524  // Find the partition
1525  File::Partition::Ptr part = partition(intPartitionName);
1526  if (!part) {
1527  Msg::print(Msg::SevWarning, "Couldn't find partition: " + intPartitionName);
1528  return nullPtr;
1529  }
1530 
1531  // Find the layer
1532  const File::Layer *layer = part->layer(layerName);
1533  if (!layer) {
1534  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
1535  return nullPtr;
1536  }
1537 
1538  // Open the partition group
1539  const OgIGroup partitionGroup = m_root->findGroup(intPartitionName);
1540  if (!partitionGroup.isValid()) {
1541  Msg::print(Msg::SevWarning, "Couldn't open partition group " +
1542  intPartitionName);
1543  return nullPtr;
1544  }
1545 
1546  // Open the layer group
1547  const OgIGroup layerGroup = partitionGroup.findGroup(layerName);
1548  if (!layerGroup.isValid()) {
1549  Msg::print(Msg::SevWarning, "Couldn't open layer group " +
1550  layerName);
1551  return nullPtr;
1552  }
1553 
1554  // Get the class name
1555  string layerPath = layer->parent + "/" + layer->name;
1556  string className;
1557  try {
1558  className = layerGroup.findAttribute<string>("class_name").value();
1559  }
1560  catch (OgIAttributeException &e) {
1561  Msg::print(Msg::SevWarning, "Couldn't find class_name attrib in layer " +
1562  layerName);
1563  return nullPtr;
1564  }
1565 
1566  // Check the cache
1567 
1569  FieldPtr cachedField = cache.getCachedField(m_filename, layerPath);
1570 
1571  if (cachedField) {
1572  return cachedField;
1573  }
1574 
1575  // Construct the field and load the data
1576 
1577  typename Field<Data_T>::Ptr field;
1578  field = readField<Data_T>(className, layerGroup, m_filename, layerPath);
1579 
1580  if (!field) {
1581  // This isn't really an error
1582  return nullPtr;
1583  }
1584 
1585  // Read the metadata
1586  const OgIGroup metadataGroup = layerGroup.findGroup("metadata");
1587  if (metadataGroup.isValid()) {
1588  readMetadata(metadataGroup, field);
1589  }
1590 
1591  // Set the name of the field appropriately
1592  field->name = removeUniqueId(intPartitionName);
1593  field->attribute = layerName;
1594  field->setMapping(part->mapping);
1595 
1596  // Cache the field for future use
1597  if (field) {
1598  cache.cacheField(field, m_filename, layerPath);
1599  }
1600 
1601  return field;
1602 }
1603 
1604 //----------------------------------------------------------------------------//
1605 
1606 template <class Data_T>
1607 typename Field<Data_T>::Vec
1608 Field3DInputFile::readLayers(const std::string &name) const
1609 {
1610  using std::vector;
1611  using std::string;
1612 
1613  typedef typename Field<Data_T>::Ptr FieldPtr;
1614  typedef typename Field<Data_T>::Vec FieldList;
1615 
1616  FieldList ret;
1617  std::vector<std::string> parts;
1618  getIntPartitionNames(parts);
1619 
1620  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1621  vector<std::string> layers;
1622  getIntScalarLayerNames(layers, *p);
1623  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1624  // Only read if it matches the name
1625  if ((name.length() == 0) || (*l == name)) {
1626  FieldPtr mf = readLayer<Data_T>(*p, *l);
1627  if (mf) {
1628  ret.push_back(mf);
1629  }
1630  }
1631  }
1632  }
1633 
1634  return ret;
1635 }
1636 
1637 //----------------------------------------------------------------------------//
1638 
1639 template <class Data_T>
1640 typename Field<Data_T>::Vec
1641 Field3DInputFile::readLayers(const std::string &partitionName,
1642  const std::string &layerName) const
1643 {
1644  using namespace std;
1645 
1646  typedef typename Field<Data_T>::Ptr FieldPtr;
1647  typedef typename Field<Data_T>::Vec FieldList;
1648 
1649  FieldList ret;
1650 
1651  if ((layerName.length() == 0) || (partitionName.length() == 0))
1652  return ret;
1653 
1654  std::vector<std::string> parts;
1655  getIntPartitionNames(parts);
1656 
1657  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1658  std::vector<std::string> layers;
1659  getIntScalarLayerNames(layers, *p);
1660  if (removeUniqueId(*p) == partitionName) {
1661  for (vector<string>::iterator l = layers.begin();
1662  l != layers.end(); ++l) {
1663  // Only read if it matches the name
1664  if (*l == layerName) {
1665  FieldPtr mf = readLayer<Data_T>(*p, *l);
1666  if (mf)
1667  ret.push_back(mf);
1668  }
1669  }
1670  }
1671  }
1672 
1673  return ret;
1674 }
1675 
1676 //----------------------------------------------------------------------------//
1677 
1678 template <class Data_T>
1679 typename EmptyField<Data_T>::Ptr
1681  const std::string &name,
1682  const std::string &attribute,
1683  FieldMapping::Ptr mapping) const
1684 {
1685  using namespace boost;
1686  using namespace std;
1687 
1688  typename EmptyField<Data_T>::Ptr null;
1689 
1690  const std::string extentsMinStr("extents_min");
1691  const std::string extentsMaxStr("extents_max");
1692  const std::string dataWindowMinStr("data_window_min");
1693  const std::string dataWindowMaxStr("data_window_max");
1694 
1695  Box3i extents, dataW;
1696 
1697  // Get extents ---
1698 
1699  OgIAttribute<veci32_t> extMinAttr =
1700  location.findAttribute<veci32_t>(extentsMinStr);
1701  OgIAttribute<veci32_t> extMaxAttr =
1702  location.findAttribute<veci32_t>(extentsMaxStr);
1703  if (!extMinAttr.isValid()) {
1704  throw MissingAttributeException("Couldn't find attribute " +
1705  extentsMinStr);
1706  }
1707  if (!extMaxAttr.isValid()) {
1708  throw MissingAttributeException("Couldn't find attribute " +
1709  extentsMaxStr);
1710  }
1711 
1712  extents.min = extMinAttr.value();
1713  extents.max = extMaxAttr.value();
1714 
1715  // Get data window ---
1716 
1717  OgIAttribute<veci32_t> dwMinAttr =
1718  location.findAttribute<veci32_t>(dataWindowMinStr);
1719  OgIAttribute<veci32_t> dwMaxAttr =
1720  location.findAttribute<veci32_t>(dataWindowMaxStr);
1721  if (!dwMinAttr.isValid()) {
1722  throw MissingAttributeException("Couldn't find attribute " +
1723  dataWindowMinStr);
1724  }
1725  if (!dwMaxAttr.isValid()) {
1726  throw MissingAttributeException("Couldn't find attribute " +
1727  dataWindowMaxStr);
1728  }
1729 
1730  dataW.min = dwMinAttr.value();
1731  dataW.max = dwMaxAttr.value();
1732 
1733  // Construct the field
1734  typename EmptyField<Data_T>::Ptr field(new EmptyField<Data_T>);
1735  field->setSize(extents, dataW);
1736 
1737  // Read the metadata
1738  OgIGroup metadataGroup = location.findGroup("metadata");
1739  if (metadataGroup.isValid()) {
1740  readMetadata(metadataGroup, field);
1741  }
1742 
1743  // Set field properties
1744  field->name = name;
1745  field->attribute = attribute;
1746  field->setMapping(mapping);
1747 
1748  return field;
1749 }
1750 
1751 //----------------------------------------------------------------------------//
1752 
1753 template <class Data_T>
1754 typename EmptyField<Data_T>::Vec
1755 Field3DInputFile::readProxyLayer(const std::string &partitionName,
1756  const std::string &layerName,
1757  bool isVectorLayer) const
1758 {
1759  using namespace boost;
1760  using namespace std;
1761  using namespace Hdf5Util;
1762 
1763  if (m_hdf5) {
1764  return m_hdf5->readProxyLayer<Data_T>(partitionName, layerName,
1765  isVectorLayer);
1766  }
1767 
1768  // Instantiate a null pointer for easier code reading
1769  typename EmptyField<Data_T>::Vec emptyList, output;
1770 
1771  if ((layerName.length() == 0) || (partitionName.length() == 0))
1772  return emptyList;
1773 
1774  std::vector<std::string> parts, layers;
1775  getIntPartitionNames(parts);
1776 
1777  bool foundPartition = false;
1778 
1779  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1780  if (removeUniqueId(*p) == partitionName) {
1781  foundPartition = true;
1782  if (isVectorLayer) {
1783  getIntVectorLayerNames(layers, *p);
1784  } else {
1785  getIntScalarLayerNames(layers, *p);
1786  }
1787  for (vector<string>::iterator l = layers.begin();
1788  l != layers.end(); ++l) {
1789  if (*l == layerName) {
1790  // Find the partition
1791  File::Partition::Ptr part = partition(*p);
1792  if (!part) {
1793  Msg::print(Msg::SevWarning, "Couldn't find partition: " + *p);
1794  return emptyList;
1795  }
1796  // Find the layer
1797  const File::Layer *layer;
1798  if (isVectorLayer) {
1799  layer = part->layer(layerName);
1800  } else {
1801  layer = part->layer(layerName);
1802  }
1803  if (!layer) {
1804  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
1805  return emptyList;
1806  }
1807  // Open the layer group
1808  string layerPath = layer->parent + "/" + layer->name;
1809  OgIGroup parent = m_root->findGroup(layer->parent);
1810  if (!parent.isValid()) {
1811  Msg::print(Msg::SevWarning, "Couldn't find layer parent "
1812  + layerPath + " in .f3d file ");
1813  return emptyList;
1814  }
1815  OgIGroup layerGroup = parent.findGroup(layer->name);
1816  if (!layerGroup.isValid()) {
1817  Msg::print(Msg::SevWarning, "Couldn't find layer group "
1818  + layerPath + " in .f3d file ");
1819  return emptyList;
1820  }
1821 
1822  // Make the proxy representation
1823  typename EmptyField<Data_T>::Ptr field =
1824  readProxyLayer<Data_T>(layerGroup, partitionName, layerName,
1825  part->mapping);
1826 
1827  // Read MIPField's number of mip levels
1828  int numLevels = 0;
1829  OgIGroup mipGroup = layerGroup.findGroup("mip_levels");
1830  if (mipGroup.isValid()) {
1831  OgIAttribute<uint32_t> levelsAttr =
1832  mipGroup.findAttribute<uint32_t>("levels");
1833  if (levelsAttr.isValid()) {
1834  numLevels = levelsAttr.value();
1835  }
1836  }
1837  field->metadata().setIntMetadata("mip_levels", numLevels);
1838 
1839  // Add field to output
1840  output.push_back(field);
1841  }
1842  }
1843  }
1844  }
1845 
1846  if (!foundPartition) {
1847  Msg::print(Msg::SevWarning, "Couldn't find partition: " + partitionName);
1848  return emptyList;
1849  }
1850 
1851  return output;
1852 }
1853 
1854 //----------------------------------------------------------------------------//
1855 
1856 template <class Data_T>
1857 typename EmptyField<Data_T>::Vec
1858 Field3DInputFile::readProxyScalarLayers(const std::string &name) const
1859 {
1860  using namespace std;
1861 
1862  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1863  typedef std::vector<FieldPtr> FieldList;
1864 
1865  FieldList ret;
1866 
1867  std::vector<std::string> parts;
1868  getPartitionNames(parts);
1869 
1870  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1871  std::vector<std::string> layers;
1872  getScalarLayerNames(layers, *p);
1873  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1874  // Only read if it matches the name
1875  if ((name.length() == 0) || (*l == name)) {
1876  FieldList f = readProxyLayer<Data_T>(*p, *l, false);
1877  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1878  if (*i) {
1879  ret.push_back(*i);
1880  }
1881  }
1882  }
1883  }
1884  }
1885 
1886  return ret;
1887 }
1888 
1889 //----------------------------------------------------------------------------//
1890 
1891 template <class Data_T>
1892 typename EmptyField<Data_T>::Vec
1893 Field3DInputFile::readProxyVectorLayers(const std::string &name) const
1894 {
1895  using namespace std;
1896 
1897  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1898  typedef std::vector<FieldPtr> FieldList;
1899 
1900  FieldList ret;
1901 
1902  std::vector<std::string> parts;
1903  getPartitionNames(parts);
1904 
1905  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1906  std::vector<std::string> layers;
1907  getVectorLayerNames(layers, *p);
1908  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1909  // Only read if it matches the name
1910  if ((name.length() == 0) || (*l == name)) {
1911  FieldList f = readProxyLayer<Data_T>(*p, *l, true);
1912  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1913  if (*i) {
1914  ret.push_back(*i);
1915  }
1916  }
1917  }
1918  }
1919  }
1920 
1921  return ret;
1922 }
1923 
1924 //----------------------------------------------------------------------------//
1925 // Template instantiations
1926 //----------------------------------------------------------------------------//
1927 
1928 #define FIELD3D_INSTANTIATION_WRITELAYER(type) \
1929  template \
1930  bool Field3DOutputFile::writeLayer<type> \
1931  (const std::string &, const std::string &, Field<type>::Ptr ); \
1932 
1939 
1940 //----------------------------------------------------------------------------//
1941 
1942 #if 0
1943 
1944 #define FIELD3D_INSTANTIATION_READLAYER(type) \
1945  template \
1946  Field<type>::Ptr \
1947  Field3DInputFile::readLayer<type> \
1948  (const std::string &, const std::string &) const; \
1949 
1950 FIELD3D_INSTANTIATION_READLAYER(float16_t);
1951 FIELD3D_INSTANTIATION_READLAYER(float32_t);
1952 FIELD3D_INSTANTIATION_READLAYER(float64_t);
1953 FIELD3D_INSTANTIATION_READLAYER(vec16_t);
1954 FIELD3D_INSTANTIATION_READLAYER(vec32_t);
1955 FIELD3D_INSTANTIATION_READLAYER(vec64_t);
1956 
1957 #endif
1958 
1959 //----------------------------------------------------------------------------//
1960 
1961 #define FIELD3D_INSTANTIATION_READLAYERS1(type) \
1962  template \
1963  Field<type>::Vec \
1964  Field3DInputFile::readLayers<type>(const std::string &name) const; \
1965 
1972 
1973 //----------------------------------------------------------------------------//
1974 
1975 #define FIELD3D_INSTANTIATION_READLAYERS2(type) \
1976  template \
1977  Field<type>::Vec \
1978  Field3DInputFile::readLayers<type>(const std::string &partitionName, \
1979  const std::string &layerName) const; \
1980 
1987 
1988 //----------------------------------------------------------------------------//
1989 
1990 #define FIELD3D_INSTANTIATION_READPROXYLAYER(type) \
1991  template \
1992  EmptyField<type>::Vec \
1993  Field3DInputFile::readProxyLayer<type>(const std::string &partitionName, \
1994  const std::string &layerName, \
1995  bool isVectorLayer) const \
1996 
2003 
2004 //----------------------------------------------------------------------------//
2005 
2006 #define FIELD3D_INSTANTIATION_READPROXYSCALARLAYER(type) \
2007  template \
2008  EmptyField<type>::Vec \
2009  Field3DInputFile::readProxyScalarLayers<type> \
2010  (const std::string &name) const \
2011 
2018 
2019 //----------------------------------------------------------------------------//
2020 
2021 #define FIELD3D_INSTANTIATION_READPROXYVECTORLAYER(type) \
2022  template \
2023  EmptyField<type>::Vec \
2024  Field3DInputFile::readProxyVectorLayers<type> \
2025  (const std::string &name) const \
2026 
2033 
2034 //----------------------------------------------------------------------------//
2035 
2037 
2038 //----------------------------------------------------------------------------//
Field_T::Ptr field_dynamic_cast(RefBase::Ptr field)
Dynamic cast that uses string-comparison in order to be safe even after an object crosses a shared li...
Definition: RefCount.h:256
Namespace for file I/O specifics.
Definition: Field3DFile.h:87
Imath::Box3i Box3i
Definition: SpiMathLib.h:77
virtual ~Field3DInputFile()
#define FIELD3D_INSTANTIATION_READPROXYSCALARLAYER(type)
bool writeGroupMembership()
This routine is called just before closing to write out any group membership to disk.
boost::intrusive_ptr< FieldMappingIO > Ptr
boost::shared_ptr< OgOGroup > m_root
Pointer to root group.
Definition: Field3DFile.h:846
bool writeGlobalMetadata()
This routine is call if you want to write out global metadata to disk.
virtual const char * what() const
Definition: Exception.h:90
Contains utility functions and classes for Hdf5 files.
Definition: Hdf5Util.h:86
File::Partition::Ptr createNewPartition(const std::string &partitionName, const std::string &layerName, FieldRes::Ptr field)
Create newPartition given the input config.
FIELD3D_API bool writeField(hid_t layerGroup, FieldBase::Ptr field)
This function creates a FieldIO instance based on field->className() which then writes the field data...
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
Contains the Field3DFile classesOSS sanitized.
boost::intrusive_ptr< Partition > Ptr
Definition: Field3DFile.h:127
std::string m_filename
Filename, only to be set by open().
Definition: Field3DFile.h:600
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
Field3D::V3d vec64_t
Definition: Traits.h:93
Field3D::V3f vec32_t
Definition: Traits.h:92
Namespace for Exception objects.
Definition: Exception.h:57
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 setVecFloatMetadata(const std::string &name, const V3f &val)
Set the a V3f value for the given metadata name.
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 ...
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...
#define FIELD3D_INSTANTIATION_READPROXYVECTORLAYER(type)
std::map< std::string, std::string > GroupMembershipMap
Definition: Field3DFile.h:228
void clear()
Clear the data structures and close the file.
void setIntMetadata(const std::string &name, const int val)
Set the a int value for the given metadata name.
float float32_t
Definition: Traits.h:87
boost::shared_ptr< Field3DOutputFileHDF5 > m_hdf5
HDF5 fallback.
Definition: Field3DFile.h:849
void setStrMetadata(const std::string &name, const std::string &val)
Set the a string value for the given metadata name.
Definition: Field.h:389
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
EmptyField< Data_T >::Vec readProxyLayer(const std::string &partitionName, const std::string &layerName, bool isVectorLayer) const
Retrieves a proxy version (EmptyField) of each layer .
Contains the FieldCache class.
static ClassFactory & singleton()
}
bool readMetadata(const OgIGroup &metadataGroup, FieldBase::Ptr field) const
Read metadata for this layer.
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
EmptyField< Data_T >::Vec readProxyVectorLayers(const std::string &name=std::string("")) const
Retrieves a proxy version (EmptyField) of each vector layer.
bool writeMapping(OgOGroup &partitionGroup, FieldMapping::Ptr mapping)
Writes the mapping to the given Og node. Mappings are assumed to be light-weight enough to be stored ...
boost::intrusive_ptr< FieldRes > Ptr
Definition: Field.h:213
boost::shared_ptr< OgIGroup > m_root
Pointer to root group.
Definition: Field3DFile.h:604
FieldPtr getCachedField(const std::string &filename, const std::string &layerPath)
Checks the cache for a previously loaded field.
Definition: FieldCache.h:148
Field< Data_T >::Ptr readField(const std::string &className, hid_t layerGroup, const std::string &filename, const std::string &layerPath)
This function creates a FieldIO instance based on className which then reads the field data from laye...
bool create(const std::string &filename, CreateMode cm=OverwriteMode)
Creates a .f3d file on disk.
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...
OgDataType
Enumerates the various uses for Ogawa-level groups.
Definition: Traits.h:125
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 ...
File::Partition::Ptr partition(const std::string &partitionName)
Returns a pointer to the given partition.
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 ...
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
Scoped object - creates a group on creation and closes it on destruction.
Definition: Hdf5Util.h:165
Field3D::V3h vec16_t
Definition: Traits.h:91
PartitionCountMap m_partitionCount
Contains a counter for each partition name. This is used to keep multiple fields with the same name u...
Definition: Field3DFile.h:377
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
half float16_t
Definition: Traits.h:86
boost::shared_ptr< Field3DFileHDF5Base > m_hdf5Base
HDF5 fallback.
Definition: Field3DFile.h:388
bool readPartitionAndLayerInfo()
Sets up all the partitions and layers, but does not load any data.
std::vector< Ptr > Vec
Definition: EmptyField.h:94
Imath::V3i V3i
Definition: SpiMathLib.h:71
boost::intrusive_ptr< FieldMapping > Ptr
Definition: FieldMapping.h:92
#define FIELD3D_INSTANTIATION_WRITELAYER(type)
void setSize(const V3i &size)
Resizes the object.
Definition: Field.h:913
void cacheField(FieldPtr field, const std::string &filename, const std::string &layerPath)
Adds the given field to the cache.
Definition: FieldCache.h:169
std::string name
The name of the layer (always available)
Definition: Field3DFile.h:100
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 addGroupMembership(const GroupMembershipMap &groupMembers)
Add to the group membership.
void setVecIntMetadata(const std::string &name, const V3i &val)
Set the a V3i value for the given metadata name.
void printHierarchy() const
EmptyField< Data_T >::Vec readProxyScalarLayers(const std::string &name=std::string("")) const
Retrieves a proxy version (EmptyField) of each scalar layer.
Field3D::V3i veci32_t
Definition: Traits.h:94
void setMapping(FieldMapping::Ptr mapping)
Sets the field's mapping.
Definition: Field.h:347
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
#define FIELD3D_MINOR_VER
Definition: ns.h:39
Provides reading of .f3d (internally, hdf5) files.Refer to using_files for examples of how to use thi...
FIELD3D_API FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
This function creates a FieldMappingIO instance based on className read from mappingGroup location wh...
PartitionList m_partitions
Vector of partitions.
Definition: Field3DFile.h:371
Contains the Field3DFileHDF5 classesOSS sanitized.
This subclass of Field does not store any data.
Definition: EmptyField.h:86
Provides writing of .f3d (internally, hdf5) files.
boost::shared_ptr< Field3DInputFileHDF5 > m_hdf5
HDF5 fallback.
Definition: Field3DFile.h:607
double float64_t
Definition: Traits.h:88
std::vector< Ptr > Vec
This is a convenience typedef for the list that Field3DInputFile::readScalarLayers() and Field3DInput...
Definition: Field.h:403
virtual ~Field3DFileBase()=0
Pure virtual destructor to ensure we never instantiate this class.
#define FIELD3D_API
Definition: ns.h:77
boost::intrusive_ptr< EmptyField > Ptr
Definition: EmptyField.h:93
virtual ~Field3DOutputFile()
static bool ms_doOgawa
Whether to output ogawa files.
Definition: Field3DFile.h:841
boost::shared_ptr< Alembic::Ogawa::IArchive > m_archive
Pointer to the Ogawa archive.
Definition: Field3DFile.h:602
bool writeMetadata(OgOGroup &metadataGroup, FieldBase::Ptr layer)
Writes metadata for this layer.
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...
bool close()
Closes the file. No need to call this unless you specifically want to close the file early...
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
FieldMetadata & metadata()
accessor to the m_metadata class
Definition: Field.h:155
#define FIELD3D_INSTANTIATION_READLAYERS1(type)
bool writeLayer(const std::string &layerName, typename Field< Data_T >::Ptr layer)
Writes a scalar layer to the "Default" partition.
Definition: Field3DFile.h:687
static FieldCache & singleton()
Returns a reference to the FieldCache singleton.
Definition: FieldCache.h:135
boost::shared_ptr< Alembic::Ogawa::OArchive > m_archive
Pointer to the Ogawa archive.
Definition: Field3DFile.h:844
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...
std::string attribute
Optional name of the attribute the field represents.
Definition: Field.h:173
Contains Field, WritableField and ResizableField classes.
FieldMetadata & metadata()
accessor to the m_metadata class
Definition: Field3DFile.h:276
Contains the ClassFactory class for registering Field3D classes.
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
virtual void closeInternal()=0
Closes the file if open.
Field< Data_T >::Vec readLayers(const std::string &layerName=std::string("")) const
boost::intrusive_ptr< FieldIO > Ptr
Definition: FieldIO.h:91
Field< Data_T >::Ptr readLayer(const std::string &intPartitionName, const std::string &layerName) const
This call does the actual reading of a layer. Notice that it expects a unique -internal- partition na...
bool fileExists(const std::string &filename)
checks to see if a file/directory exists or not
#define FIELD3D_MICRO_VER
Definition: ns.h:40
GroupMembershipMap m_groupMembership
Keeps track of group membership for each layer of partition name. The key is the "group" and the valu...
Definition: Field3DFile.h:382
void setFloatMetadata(const std::string &name, const float val)
Set the a float value for the given metadata name.
#define FIELD3D_INSTANTIATION_READPROXYLAYER(type)
#define FIELD3D_MAJOR_VER
Definition: ns.h:38
#define FIELD3D_INSTANTIATION_READLAYERS2(type)
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
std::string incrementPartitionName(std::string &pname)
Increment the partition or make it zero if there's not an integer suffix.
virtual void closeInternal()
Closes the file if open.
Definition: Field3DFile.h:796
bool open(const std::string &filename)
Opens the given file.
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
std::string parent
The name of the parent partition. We need this in order to open its group.
Definition: Field3DFile.h:103
boost::intrusive_ptr< Field > Ptr
Definition: Field.h:395
FieldMapping::Ptr mapping()
Returns a pointer to the mapping.
Definition: Field.h:263
std::string name
Optional name of the field.
Definition: Field.h:171