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 
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 
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 (...) {
831  "In file: " + filename + " Unknown exception ");
832  success = false;
833  }
834 
835  if (!success) {
836  close();
837  }
838 
839  return success;
840 }
841 
842 //----------------------------------------------------------------------------//
843 
845 {
846  // Find all the partition names
847  std::vector<std::string> groups = m_root->groupNames();
848 
849  // Store the partition names
850  m_partitions.clear();
851  for (std::vector<std::string>::const_iterator i = groups.begin(),
852  end = groups.end(); i != end; ++i) {
853  // Grab the name
854  const std::string &name = *i;
855  // Skip metadata
856  if (name == "field3d_global_metadata") {
857  continue;
858  }
859  // Build partition
861  part->name = name;
862  m_partitions.push_back(part);
863  }
864 
865  // For each partition, find its mapping ---
866 
867  for (PartitionList::iterator i = m_partitions.begin();
868  i != m_partitions.end(); ++i) {
869  // Grab the name
870  const std::string &name = (**i).name;
871  // Open the partition group
872  const OgIGroup partitionGroup = m_root->findGroup(name);
873  if (!partitionGroup.isValid()) {
874  Msg::print(Msg::SevWarning, "Couldn't open partition group " + name);
875  }
876  // Open the mapping group
877  const OgIGroup mappingGroup = partitionGroup.findGroup(k_mappingStr);
878  if (!mappingGroup.isValid()) {
879  Msg::print(Msg::SevWarning, "Couldn't open mapping group " + name);
880  }
881  // Build the mapping
882  FieldMapping::Ptr mapping = readFieldMapping(mappingGroup);
883 #if 0
884  if (!mapping) {
885  Msg::print(Msg::SevWarning, "Got a null pointer when reading mapping");
886  throw ReadMappingException((**i).name);
887  }
888 #endif
889  // Attach the mapping to the partition
890  (**i).mapping = mapping;
891  }
892 
893  // ... And then find its layers ---
894 
895  for (PartitionList::const_iterator i = m_partitions.begin();
896  i != m_partitions.end(); ++i) {
897  // Grab the name
898  const std::string &partitionName = (**i).name;
899  // Open the partition group
900  const OgIGroup partitionGroup = m_root->findGroup(partitionName);
901  if (!partitionGroup.isValid()) {
902  Msg::print(Msg::SevWarning, "Couldn't open partition group " +
903  partitionName);
904  }
905  // Get all the layer names
906  groups = partitionGroup.groupNames();
907  for (std::vector<std::string>::const_iterator l = groups.begin(),
908  lEnd = groups.end(); l != lEnd; ++l) {
909  // Grab layer name
910  const std::string layerName = *l;
911  // Skip the mapping group
912  if (layerName == k_mappingStr) {
913  continue;
914  }
915  // Construct the layer
916  File::Layer layer;
917  layer.name = *l;
918  layer.parent = partitionName;
919  // Add to partition
920  partition(partitionName)->addLayer(layer);
921  }
922  }
923 
924  return true;
925 }
926 
927 //----------------------------------------------------------------------------//
928 
929 bool Field3DInputFile::readMetadata(const OgIGroup &metadataGroup,
930  FieldBase::Ptr field) const
931 {
932  return readMeta(metadataGroup, field->metadata());
933 }
934 
935 //----------------------------------------------------------------------------//
936 
937 bool Field3DInputFile::readMetadata(const OgIGroup &metadataGroup)
938 {
939  return readMeta(metadataGroup, metadata());
940 }
941 
942 //----------------------------------------------------------------------------//
943 // Field3DOutputFile implementations
944 //----------------------------------------------------------------------------//
945 
947 
948 //----------------------------------------------------------------------------//
949 
951 {
952  // Empty
953 }
954 
955 //----------------------------------------------------------------------------//
956 
958 {
959  cleanup();
960 }
961 
962 //----------------------------------------------------------------------------//
963 
964 bool Field3DOutputFile::create(const string &filename, CreateMode cm)
965 {
966  if (!ms_doOgawa) {
967  m_hdf5.reset(new Field3DOutputFileHDF5);
968  m_hdf5Base = m_hdf5;
969  int ccm = cm;
970  return m_hdf5->create(filename, Field3DOutputFileHDF5::CreateMode(ccm));
971  }
972 
973  closeInternal();
974 
975  if (cm == FailOnExisting && fileExists(filename)) {
976  return false;
977  }
978 
979  // Create the Ogawa archive
980  m_archive.reset(new Alembic::Ogawa::OArchive(filename));
981 
982  // Check that it's valid
983  if (!m_archive->isValid()) {
984  m_archive.reset();
985  return false;
986  }
987 
988  // Get the root
989  m_root.reset(new OgOGroup(*m_archive));
990 
991  // Create the version attribute
992  OgOAttribute<veci32_t> f3dVersion(*m_root, k_versionAttrName,
993  k_currentFileVersion);
994 
995  return true;
996 }
997 
998 //----------------------------------------------------------------------------//
999 
1000 bool Field3DOutputFile::writeMapping(OgOGroup &partitionGroup,
1001  FieldMapping::Ptr mapping)
1002 {
1004  const std::string className = mapping->className();
1005 
1006  try {
1007 
1008  OgOGroup mappingGroup(partitionGroup, k_mappingStr);
1009 
1010  OgOAttribute<string> classNameAttr(mappingGroup, k_mappingTypeAttrName,
1011  className);
1012 
1013  FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
1014  if (!io) {
1015  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1016  className);
1017  return false;
1018  }
1019 
1020  return io->write(mappingGroup, mapping);
1021 
1022  }
1023  catch (OgOGroupException &e) {
1024  Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
1025  throw WriteMappingException(k_mappingStr);
1026  }
1027 
1028 }
1029 
1030 //----------------------------------------------------------------------------//
1031 
1032 bool Field3DOutputFile::writeMetadata(OgOGroup &metadataGroup,
1033  FieldBase::Ptr field)
1034 {
1035  {
1036  FieldMetadata::StrMetadata::const_iterator i =
1037  field->metadata().strMetadata().begin();
1038  FieldMetadata::StrMetadata::const_iterator end =
1039  field->metadata().strMetadata().end();
1040  for (; i != end; ++i) {
1041  try {
1042  OgOAttribute<string>(metadataGroup, i->first, i->second);
1043  }
1044  catch (OgOAttributeException &e) {
1045  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1046  " " + e.what());
1047  return false;
1048  }
1049  }
1050  }
1051 
1052  {
1053  FieldMetadata::IntMetadata::const_iterator i =
1054  field->metadata().intMetadata().begin();
1055  FieldMetadata::IntMetadata::const_iterator end =
1056  field->metadata().intMetadata().end();
1057  for (; i != end; ++i) {
1058  try {
1059  OgOAttribute<int32_t>(metadataGroup, i->first, i->second);
1060  }
1061  catch (OgOAttributeException &e) {
1062  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1063  " " + e.what());
1064  return false;
1065  }
1066  }
1067  }
1068 
1069  {
1070  FieldMetadata::FloatMetadata::const_iterator i =
1071  field->metadata().floatMetadata().begin();
1072  FieldMetadata::FloatMetadata::const_iterator end =
1073  field->metadata().floatMetadata().end();
1074  for (; i != end; ++i) {
1075  try {
1076  OgOAttribute<float32_t>(metadataGroup, i->first, i->second);
1077  }
1078  catch (OgOAttributeException &e) {
1079  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1080  " " + e.what());
1081  return false;
1082  }
1083  }
1084  }
1085 
1086  {
1087  FieldMetadata::VecIntMetadata::const_iterator i =
1088  field->metadata().vecIntMetadata().begin();
1089  FieldMetadata::VecIntMetadata::const_iterator end =
1090  field->metadata().vecIntMetadata().end();
1091  for (; i != end; ++i) {
1092  try {
1093  OgOAttribute<veci32_t>(metadataGroup, i->first, i->second);
1094  }
1095  catch (OgOAttributeException &e) {
1096  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1097  " " + e.what());
1098  return false;
1099  }
1100  }
1101  }
1102 
1103  {
1104  FieldMetadata::VecFloatMetadata::const_iterator i =
1105  field->metadata().vecFloatMetadata().begin();
1106  FieldMetadata::VecFloatMetadata::const_iterator end =
1107  field->metadata().vecFloatMetadata().end();
1108  for (; i != end; ++i) {
1109  try {
1110  OgOAttribute<vec32_t>(metadataGroup, i->first, i->second);
1111  }
1112  catch (OgOAttributeException &e) {
1113  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1114  " " + e.what());
1115  return false;
1116  }
1117  }
1118 
1119  }
1120 
1121  return true;
1122 
1123 }
1124 
1125 //----------------------------------------------------------------------------//
1126 
1127 bool Field3DOutputFile::writeMetadata(OgOGroup &metadataGroup)
1128 {
1129  {
1130  FieldMetadata::StrMetadata::const_iterator i =
1131  metadata().strMetadata().begin();
1132  FieldMetadata::StrMetadata::const_iterator end =
1133  metadata().strMetadata().end();
1134  for (; i != end; ++i) {
1135  try {
1136  OgOAttribute<string>(metadataGroup, i->first, i->second);
1137  }
1138  catch (OgOAttributeException &e) {
1139  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1140  " " + e.what());
1141  return false;
1142  }
1143  }
1144  }
1145 
1146  {
1147  FieldMetadata::IntMetadata::const_iterator i =
1148  metadata().intMetadata().begin();
1149  FieldMetadata::IntMetadata::const_iterator end =
1150  metadata().intMetadata().end();
1151  for (; i != end; ++i) {
1152  try {
1153  OgOAttribute<int32_t>(metadataGroup, i->first, i->second);
1154  }
1155  catch (OgOAttributeException &e) {
1156  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1157  " " + e.what());
1158  return false;
1159  }
1160  }
1161  }
1162 
1163  {
1164  FieldMetadata::FloatMetadata::const_iterator i =
1165  metadata().floatMetadata().begin();
1166  FieldMetadata::FloatMetadata::const_iterator end =
1167  metadata().floatMetadata().end();
1168  for (; i != end; ++i) {
1169  try {
1170  OgOAttribute<float32_t>(metadataGroup, i->first, i->second);
1171  }
1172  catch (OgOAttributeException &e) {
1173  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1174  " " + e.what());
1175  return false;
1176  }
1177  }
1178  }
1179 
1180  {
1181  FieldMetadata::VecIntMetadata::const_iterator i =
1182  metadata().vecIntMetadata().begin();
1183  FieldMetadata::VecIntMetadata::const_iterator end =
1184  metadata().vecIntMetadata().end();
1185  for (; i != end; ++i) {
1186  try {
1187  OgOAttribute<veci32_t>(metadataGroup, i->first, i->second);
1188  }
1189  catch (OgOAttributeException &e) {
1190  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1191  " " + e.what());
1192  return false;
1193  }
1194  }
1195  }
1196 
1197  {
1198  FieldMetadata::VecFloatMetadata::const_iterator i =
1199  metadata().vecFloatMetadata().begin();
1200  FieldMetadata::VecFloatMetadata::const_iterator end =
1201  metadata().vecFloatMetadata().end();
1202  for (; i != end; ++i) {
1203  try {
1204  OgOAttribute<vec32_t>(metadataGroup, i->first, i->second);
1205  }
1206  catch (OgOAttributeException &e) {
1207  Msg::print(Msg::SevWarning, "Writing attribute " + i->first +
1208  " " + e.what());
1209  return false;
1210  }
1211  }
1212 
1213  }
1214 
1215  return true;
1216 }
1217 
1218 //----------------------------------------------------------------------------//
1219 
1220 bool
1222 {
1223  if (m_hdf5) {
1224  return m_hdf5->writeGlobalMetadata();
1225  }
1226 
1227  OgOGroup ogMetadata(*m_root, "field3d_global_metadata");
1228  if (!writeMetadata(ogMetadata)) {
1229  Msg::print(Msg::SevWarning, "Error writing file metadata.");
1230  return false;
1231  }
1232 
1233  return true;
1234 }
1235 
1236 //----------------------------------------------------------------------------//
1237 
1238 bool
1240 {
1241  if (m_hdf5) {
1242  return m_hdf5->writeGroupMembership();
1243  }
1244 
1245 #if 0
1246 
1248 
1249  using namespace std;
1250  using namespace Hdf5Util;
1251 
1252  if (!m_groupMembership.size())
1253  return true;
1254 
1255  H5ScopedGcreate group(m_file, "field3d_group_membership");
1256  if (group < 0) {
1258  "Error creating field3d_group_membership group.");
1259  return false;
1260  }
1261 
1262  if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
1264  "Failed to write field3d_group_membership attribute.");
1265  return false;
1266  }
1267 
1268  std::map<std::string, std::string>::const_iterator iter =
1269  m_groupMembership.begin();
1270  std::map<std::string, std::string>::const_iterator iEnd =
1271  m_groupMembership.end();
1272 
1273  for (; iter != iEnd; ++iter) {
1274  if (!writeAttribute(group, iter->first, iter->second)) {
1276  "Failed to write groupMembership string: "+ iter->first);
1277  return false;
1278  }
1279  }
1280 
1281 #endif
1282 
1283  return true;
1284 }
1285 
1286 //----------------------------------------------------------------------------//
1287 
1288 std::string
1290 {
1291  std::string myPartitionName = removeUniqueId(partitionName);
1292  int nextIdx = -1;
1293  if (m_partitionCount.find(myPartitionName) != m_partitionCount.end()) {
1294  nextIdx = ++m_partitionCount[myPartitionName];
1295  } else {
1296  nextIdx = 0;
1297  m_partitionCount[myPartitionName] = 0;
1298  }
1299 
1300  return makeIntPartitionName(myPartitionName, nextIdx);
1301 }
1302 
1303 //----------------------------------------------------------------------------//
1304 // Debug
1305 //----------------------------------------------------------------------------//
1306 
1308 {
1309  // For each partition
1310  for (PartitionList::const_iterator i = m_partitions.begin();
1311  i != m_partitions.end(); ++i) {
1312  cout << "Name: " << (**i).name << endl;
1313  if ((**i).mapping)
1314  cout << " Mapping: " << (**i).mapping->className() << endl;
1315  else
1316  cout << " Mapping: NULL" << endl;
1317  cout << " Layers: " << endl;
1318  vector<string> names;
1319  (**i).getLayerNames(names);
1320  for_each(names.begin(), names.end(), print<string>(4));
1321  }
1322 }
1323 
1324 //----------------------------------------------------------------------------//
1325 // Function Implementations
1326 //----------------------------------------------------------------------------//
1327 
1328 bool fileExists(const std::string &filename)
1329 {
1330 #ifdef WIN32
1331  struct __stat64 statbuf;
1332  return (_stat64(filename.c_str(), &statbuf) != -1);
1333 #else
1334  struct stat statbuf;
1335  return (stat(filename.c_str(), &statbuf) != -1);
1336 #endif
1337 }
1338 
1339 //----------------------------------------------------------------------------//
1340 
1342 Field3DOutputFile::createNewPartition(const std::string &partitionName,
1343  const std::string & /* layerName */,
1344  FieldRes::Ptr field)
1345 {
1346  using namespace Exc;
1347 
1349  newPart->name = partitionName;
1350 
1351  boost::shared_ptr<OgOGroup> ogPartition(new OgOGroup(*m_root, newPart->name));
1352  newPart->setGroup(ogPartition);
1353 
1354  m_partitions.push_back(newPart);
1355 
1356  // Pick up new pointer
1357  File::Partition::Ptr part = partition(partitionName);
1358 
1359  // Add mapping group to the partition
1360  try {
1361  if (!writeMapping(*ogPartition, field->mapping())) {
1363  "writeMapping returned false for an unknown reason ");
1364  return File::Partition::Ptr();
1365  }
1366  }
1367  catch (WriteMappingException &e) {
1368  Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: "
1369  + partitionName);
1370  return File::Partition::Ptr();
1371  }
1372  catch (...) {
1374  "Unknown error when writing mapping for partition: "
1375  + partitionName);
1376  return File::Partition::Ptr();
1377  }
1378 
1379  // Set the mapping of the partition. Since all layers share their
1380  // partition's mapping, we can just pick this first one. All subsequent
1381  // additions to the same partition are checked to have the same mapping
1382  part->mapping = field->mapping();
1383 
1384  // Tag node as partition
1385  // Create a version attribute on the root node
1386  OgOAttribute<string>(*ogPartition, "is_field3d_partition", "1");
1387 
1388  return part;
1389 }
1390 
1391 //----------------------------------------------------------------------------//
1392 // Template implementations
1393 //----------------------------------------------------------------------------//
1394 
1395 template <class Data_T>
1396 bool Field3DOutputFile::writeLayer(const std::string &userPartitionName,
1397  const std::string &layerName,
1398  typename Field<Data_T>::Ptr field)
1399 {
1400  using std::string;
1401 
1402  // Null pointer check
1403  if (!field) {
1405  "Called writeLayer with null pointer. Ignoring...");
1406  return false;
1407  }
1408 
1409  // Make sure archive is open
1410  if (!m_archive) {
1412  "Attempting to write layer without opening file first.");
1413  return false;
1414  }
1415 
1416  // Get the partition name
1417  string partitionName = intPartitionName(userPartitionName, layerName, field);
1418 
1419  // Get the partition
1420  File::Partition::Ptr part = partition(partitionName);
1421 
1422  if (!part) {
1423  // Create a new partition
1424  part = createNewPartition(partitionName, layerName, field);
1425  // Make sure it was created
1426  if (!part) {
1427  return false;
1428  }
1429  } else {
1430  // Check that we have a valid mapping
1431  if (!field->mapping()) {
1433  "Couldn't add layer \"" + layerName + "\" to partition \""
1434  + partitionName + "\" because the layer's mapping is null.");
1435  return false;
1436  }
1437  // Check if the layer already exists. If it does, we need to make a
1438  // different partition
1439  if (part->layer(layerName)) {
1440  // Increment the internal partition name
1441  partitionName = incrementPartitionName(partitionName);
1442  // Create a new partition
1443  part = createNewPartition(partitionName, layerName, field);
1444  // Make sure it was created
1445  if (!part) {
1446  return false;
1447  }
1448  }
1449  }
1450 
1451  // Check mapping not null
1452  if (!part->mapping) {
1453  Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: "
1454  + partitionName);
1455  return false;
1456  }
1457 
1458  // Check that the mapping matches what's already in the Partition
1459  if (!field->mapping()->isIdentical(part->mapping)) {
1460  Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName
1461  + "\" to partition \"" + partitionName
1462  + "\" because mapping doesn't match");
1463  return false;
1464  }
1465 
1466  // Open the partition
1467 
1468  OgOGroup &ogPartition = part->group();
1469 
1470  // Build a Layer
1471 
1472  File::Layer layer;
1473  layer.name = layerName;
1474  layer.parent = partitionName;
1475 
1476  // Add Layer to file ---
1477 
1478  OgOGroup ogLayer(ogPartition, layerName);
1479 
1480  // Tag as layer
1481  OgOAttribute<string> classType(ogLayer, "class_type", "field3d_layer");
1482 
1483  // Create metadata
1484  OgOGroup ogMetadata(ogLayer, "metadata");
1485 
1486  // Write metadata
1487  writeMetadata(ogMetadata, field);
1488 
1489  // Write field data
1490  writeField(ogLayer, field);
1491 
1492  // Add to partition
1493 
1494  part->addLayer(layer);
1495 
1496  return true;
1497 }
1498 
1499 //----------------------------------------------------------------------------//
1500 
1501 template <class Data_T>
1502 typename Field<Data_T>::Ptr
1504  const std::string &layerName) const
1505 {
1506  typedef typename Field<Data_T>::Ptr FieldPtr;
1507 
1508  // Instantiate a null pointer for easier code reading
1509  FieldPtr nullPtr;
1510 
1511  // Find the partition
1513  if (!part) {
1514  Msg::print(Msg::SevWarning, "Couldn't find partition: " + intPartitionName);
1515  return nullPtr;
1516  }
1517 
1518  // Find the layer
1519  const File::Layer *layer = part->layer(layerName);
1520  if (!layer) {
1521  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
1522  return nullPtr;
1523  }
1524 
1525  // Open the partition group
1526  const OgIGroup partitionGroup = m_root->findGroup(intPartitionName);
1527  if (!partitionGroup.isValid()) {
1528  Msg::print(Msg::SevWarning, "Couldn't open partition group " +
1530  return nullPtr;
1531  }
1532 
1533  // Open the layer group
1534  const OgIGroup layerGroup = partitionGroup.findGroup(layerName);
1535  if (!layerGroup.isValid()) {
1536  Msg::print(Msg::SevWarning, "Couldn't open layer group " +
1537  layerName);
1538  return nullPtr;
1539  }
1540 
1541  // Get the class name
1542  string layerPath = layer->parent + "/" + layer->name;
1543  string className;
1544  try {
1545  className = layerGroup.findAttribute<string>("class_name").value();
1546  }
1547  catch (OgIAttributeException &e) {
1548  Msg::print(Msg::SevWarning, "Couldn't find class_name attrib in layer " +
1549  layerName);
1550  return nullPtr;
1551  }
1552 
1553  // Check the cache
1554 
1556  FieldPtr cachedField = cache.getCachedField(m_filename, layerPath);
1557 
1558  if (cachedField) {
1559  return cachedField;
1560  }
1561 
1562  // Construct the field and load the data
1563 
1564  typename Field<Data_T>::Ptr field;
1565  field = readField<Data_T>(className, layerGroup, m_filename, layerPath);
1566 
1567  if (!field) {
1568  // This isn't really an error
1569  return nullPtr;
1570  }
1571 
1572  // Read the metadata
1573  const OgIGroup metadataGroup = layerGroup.findGroup("metadata");
1574  if (metadataGroup.isValid()) {
1575  readMetadata(metadataGroup, field);
1576  }
1577 
1578  // Set the name of the field appropriately
1580  field->attribute = layerName;
1581  field->setMapping(part->mapping);
1582 
1583  // Cache the field for future use
1584  if (field) {
1585  cache.cacheField(field, m_filename, layerPath);
1586  }
1587 
1588  return field;
1589 }
1590 
1591 //----------------------------------------------------------------------------//
1592 
1593 template <class Data_T>
1594 typename Field<Data_T>::Vec
1595 Field3DInputFile::readLayers(const std::string &name) const
1596 {
1597  using std::vector;
1598  using std::string;
1599 
1600  typedef typename Field<Data_T>::Ptr FieldPtr;
1601  typedef typename Field<Data_T>::Vec FieldList;
1602 
1603  FieldList ret;
1604  std::vector<std::string> parts;
1605  getIntPartitionNames(parts);
1606 
1607  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1608  vector<std::string> layers;
1609  getIntScalarLayerNames(layers, *p);
1610  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1611  // Only read if it matches the name
1612  if ((name.length() == 0) || (*l == name)) {
1613  FieldPtr mf = readLayer<Data_T>(*p, *l);
1614  if (mf) {
1615  ret.push_back(mf);
1616  }
1617  }
1618  }
1619  }
1620 
1621  return ret;
1622 }
1623 
1624 //----------------------------------------------------------------------------//
1625 
1626 template <class Data_T>
1627 typename Field<Data_T>::Vec
1628 Field3DInputFile::readLayers(const std::string &partitionName,
1629  const std::string &layerName) const
1630 {
1631  using namespace std;
1632 
1633  typedef typename Field<Data_T>::Ptr FieldPtr;
1634  typedef typename Field<Data_T>::Vec FieldList;
1635 
1636  FieldList ret;
1637 
1638  if ((layerName.length() == 0) || (partitionName.length() == 0))
1639  return ret;
1640 
1641  std::vector<std::string> parts;
1642  getIntPartitionNames(parts);
1643 
1644  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1645  std::vector<std::string> layers;
1646  getIntScalarLayerNames(layers, *p);
1647  if (removeUniqueId(*p) == partitionName) {
1648  for (vector<string>::iterator l = layers.begin();
1649  l != layers.end(); ++l) {
1650  // Only read if it matches the name
1651  if (*l == layerName) {
1652  FieldPtr mf = readLayer<Data_T>(*p, *l);
1653  if (mf)
1654  ret.push_back(mf);
1655  }
1656  }
1657  }
1658  }
1659 
1660  return ret;
1661 }
1662 
1663 //----------------------------------------------------------------------------//
1664 
1665 template <class Data_T>
1666 typename EmptyField<Data_T>::Ptr
1668  const std::string &name,
1669  const std::string &attribute,
1670  FieldMapping::Ptr mapping) const
1671 {
1672  using namespace boost;
1673  using namespace std;
1674 
1675  typename EmptyField<Data_T>::Ptr null;
1676 
1677  const std::string extentsMinStr("extents_min");
1678  const std::string extentsMaxStr("extents_max");
1679  const std::string dataWindowMinStr("data_window_min");
1680  const std::string dataWindowMaxStr("data_window_max");
1681 
1682  Box3i extents, dataW;
1683 
1684  // Get extents ---
1685 
1686  OgIAttribute<veci32_t> extMinAttr =
1687  location.findAttribute<veci32_t>(extentsMinStr);
1688  OgIAttribute<veci32_t> extMaxAttr =
1689  location.findAttribute<veci32_t>(extentsMaxStr);
1690  if (!extMinAttr.isValid()) {
1691  throw MissingAttributeException("Couldn't find attribute " +
1692  extentsMinStr);
1693  }
1694  if (!extMaxAttr.isValid()) {
1695  throw MissingAttributeException("Couldn't find attribute " +
1696  extentsMaxStr);
1697  }
1698 
1699  extents.min = extMinAttr.value();
1700  extents.max = extMaxAttr.value();
1701 
1702  // Get data window ---
1703 
1704  OgIAttribute<veci32_t> dwMinAttr =
1705  location.findAttribute<veci32_t>(dataWindowMinStr);
1706  OgIAttribute<veci32_t> dwMaxAttr =
1707  location.findAttribute<veci32_t>(dataWindowMaxStr);
1708  if (!dwMinAttr.isValid()) {
1709  throw MissingAttributeException("Couldn't find attribute " +
1710  dataWindowMinStr);
1711  }
1712  if (!dwMaxAttr.isValid()) {
1713  throw MissingAttributeException("Couldn't find attribute " +
1714  dataWindowMaxStr);
1715  }
1716 
1717  dataW.min = dwMinAttr.value();
1718  dataW.max = dwMaxAttr.value();
1719 
1720  // Construct the field
1721  typename EmptyField<Data_T>::Ptr field(new EmptyField<Data_T>);
1722  field->setSize(extents, dataW);
1723 
1724  // Read the metadata
1725  OgIGroup metadataGroup = location.findGroup("metadata");
1726  if (metadataGroup.isValid()) {
1727  readMetadata(metadataGroup, field);
1728  }
1729 
1730  // Set field properties
1731  field->name = name;
1732  field->attribute = attribute;
1733  field->setMapping(mapping);
1734 
1735  return field;
1736 }
1737 
1738 //----------------------------------------------------------------------------//
1739 
1740 template <class Data_T>
1741 typename EmptyField<Data_T>::Vec
1742 Field3DInputFile::readProxyLayer(const std::string &partitionName,
1743  const std::string &layerName,
1744  bool isVectorLayer) const
1745 {
1746  using namespace boost;
1747  using namespace std;
1748  using namespace Hdf5Util;
1749 
1750  if (m_hdf5) {
1751  return m_hdf5->readProxyLayer<Data_T>(partitionName, layerName,
1752  isVectorLayer);
1753  }
1754 
1755  // Instantiate a null pointer for easier code reading
1756  typename EmptyField<Data_T>::Vec emptyList, output;
1757 
1758  if ((layerName.length() == 0) || (partitionName.length() == 0))
1759  return emptyList;
1760 
1761  std::vector<std::string> parts, layers;
1762  getIntPartitionNames(parts);
1763 
1764  bool foundPartition = false;
1765 
1766  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1767  if (removeUniqueId(*p) == partitionName) {
1768  foundPartition = true;
1769  if (isVectorLayer) {
1770  getIntVectorLayerNames(layers, *p);
1771  } else {
1772  getIntScalarLayerNames(layers, *p);
1773  }
1774  for (vector<string>::iterator l = layers.begin();
1775  l != layers.end(); ++l) {
1776  if (*l == layerName) {
1777  // Find the partition
1778  File::Partition::Ptr part = partition(*p);
1779  if (!part) {
1780  Msg::print(Msg::SevWarning, "Couldn't find partition: " + *p);
1781  return emptyList;
1782  }
1783  // Find the layer
1784  const File::Layer *layer;
1785  if (isVectorLayer) {
1786  layer = part->layer(layerName);
1787  } else {
1788  layer = part->layer(layerName);
1789  }
1790  if (!layer) {
1791  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
1792  return emptyList;
1793  }
1794  // Open the layer group
1795  string layerPath = layer->parent + "/" + layer->name;
1796  OgIGroup parent = m_root->findGroup(layer->parent);
1797  if (!parent.isValid()) {
1798  Msg::print(Msg::SevWarning, "Couldn't find layer parent "
1799  + layerPath + " in .f3d file ");
1800  return emptyList;
1801  }
1802  OgIGroup layerGroup = parent.findGroup(layer->name);
1803  if (!layerGroup.isValid()) {
1804  Msg::print(Msg::SevWarning, "Couldn't find layer group "
1805  + layerPath + " in .f3d file ");
1806  return emptyList;
1807  }
1808 
1809  // Make the proxy representation
1810  typename EmptyField<Data_T>::Ptr field =
1811  readProxyLayer<Data_T>(layerGroup, partitionName, layerName,
1812  part->mapping);
1813 
1814  // Read MIPField's number of mip levels
1815  int numLevels = 0;
1816  OgIGroup mipGroup = layerGroup.findGroup("mip_levels");
1817  if (mipGroup.isValid()) {
1818  OgIAttribute<uint32_t> levelsAttr =
1819  mipGroup.findAttribute<uint32_t>("levels");
1820  if (levelsAttr.isValid()) {
1821  numLevels = levelsAttr.value();
1822  }
1823  }
1824  field->metadata().setIntMetadata("mip_levels", numLevels);
1825 
1826  // Add field to output
1827  output.push_back(field);
1828  }
1829  }
1830  }
1831  }
1832 
1833  if (!foundPartition) {
1834  Msg::print(Msg::SevWarning, "Couldn't find partition: " + partitionName);
1835  return emptyList;
1836  }
1837 
1838  return output;
1839 }
1840 
1841 //----------------------------------------------------------------------------//
1842 
1843 template <class Data_T>
1844 typename EmptyField<Data_T>::Vec
1845 Field3DInputFile::readProxyScalarLayers(const std::string &name) const
1846 {
1847  using namespace std;
1848 
1849  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1850  typedef std::vector<FieldPtr> FieldList;
1851 
1852  FieldList ret;
1853 
1854  std::vector<std::string> parts;
1855  getPartitionNames(parts);
1856 
1857  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1858  std::vector<std::string> layers;
1859  getScalarLayerNames(layers, *p);
1860  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1861  // Only read if it matches the name
1862  if ((name.length() == 0) || (*l == name)) {
1863  FieldList f = readProxyLayer<Data_T>(*p, *l, false);
1864  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1865  if (*i) {
1866  ret.push_back(*i);
1867  }
1868  }
1869  }
1870  }
1871  }
1872 
1873  return ret;
1874 }
1875 
1876 //----------------------------------------------------------------------------//
1877 
1878 template <class Data_T>
1879 typename EmptyField<Data_T>::Vec
1880 Field3DInputFile::readProxyVectorLayers(const std::string &name) const
1881 {
1882  using namespace std;
1883 
1884  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1885  typedef std::vector<FieldPtr> FieldList;
1886 
1887  FieldList ret;
1888 
1889  std::vector<std::string> parts;
1890  getPartitionNames(parts);
1891 
1892  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1893  std::vector<std::string> layers;
1894  getVectorLayerNames(layers, *p);
1895  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1896  // Only read if it matches the name
1897  if ((name.length() == 0) || (*l == name)) {
1898  FieldList f = readProxyLayer<Data_T>(*p, *l, true);
1899  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1900  if (*i) {
1901  ret.push_back(*i);
1902  }
1903  }
1904  }
1905  }
1906  }
1907 
1908  return ret;
1909 }
1910 
1911 //----------------------------------------------------------------------------//
1912 // Template instantiations
1913 //----------------------------------------------------------------------------//
1914 
1915 #define FIELD3D_INSTANTIATION_WRITELAYER(type) \
1916  template \
1917  bool Field3DOutputFile::writeLayer<type> \
1918  (const std::string &, const std::string &, Field<type>::Ptr ); \
1919 
1926 
1927 //----------------------------------------------------------------------------//
1928 
1929 #if 0
1930 
1931 #define FIELD3D_INSTANTIATION_READLAYER(type) \
1932  template \
1933  Field<type>::Ptr \
1934  Field3DInputFile::readLayer<type> \
1935  (const std::string &, const std::string &) const; \
1936 
1937 FIELD3D_INSTANTIATION_READLAYER(float16_t);
1938 FIELD3D_INSTANTIATION_READLAYER(float32_t);
1939 FIELD3D_INSTANTIATION_READLAYER(float64_t);
1940 FIELD3D_INSTANTIATION_READLAYER(vec16_t);
1941 FIELD3D_INSTANTIATION_READLAYER(vec32_t);
1942 FIELD3D_INSTANTIATION_READLAYER(vec64_t);
1943 
1944 #endif
1945 
1946 //----------------------------------------------------------------------------//
1947 
1948 #define FIELD3D_INSTANTIATION_READLAYERS1(type) \
1949  template \
1950  Field<type>::Vec \
1951  Field3DInputFile::readLayers<type>(const std::string &name) const; \
1952 
1959 
1960 //----------------------------------------------------------------------------//
1961 
1962 #define FIELD3D_INSTANTIATION_READLAYERS2(type) \
1963  template \
1964  Field<type>::Vec \
1965  Field3DInputFile::readLayers<type>(const std::string &partitionName, \
1966  const std::string &layerName) const; \
1967 
1974 
1975 //----------------------------------------------------------------------------//
1976 
1977 #define FIELD3D_INSTANTIATION_READPROXYLAYER(type) \
1978  template \
1979  EmptyField<type>::Vec \
1980  Field3DInputFile::readProxyLayer<type>(const std::string &partitionName, \
1981  const std::string &layerName, \
1982  bool isVectorLayer) const \
1983 
1990 
1991 //----------------------------------------------------------------------------//
1992 
1993 #define FIELD3D_INSTANTIATION_READPROXYSCALARLAYER(type) \
1994  template \
1995  EmptyField<type>::Vec \
1996  Field3DInputFile::readProxyScalarLayers<type> \
1997  (const std::string &name) const \
1998 
2005 
2006 //----------------------------------------------------------------------------//
2007 
2008 #define FIELD3D_INSTANTIATION_READPROXYVECTORLAYER(type) \
2009  template \
2010  EmptyField<type>::Vec \
2011  Field3DInputFile::readProxyVectorLayers<type> \
2012  (const std::string &name) const \
2013 
2020 
2021 //----------------------------------------------------------------------------//
2022 
2024 
2025 //----------------------------------------------------------------------------//
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)
FieldMappingIO::Ptr createFieldMappingIO(const std::string &className) const
Instances an IO object by name.
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.
int numIntPartitions(const std::string &partitionName) const
Returns the number of internal partitions for a given partition name.
Contains utility functions and classes for Hdf5 files.
Definition: Hdf5Util.h:86
void getVectorLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the vector layers in a given partition.
void getScalarLayerNames(std::vector< std::string > &names, const std::string &partitionName) const
Gets the names of all the scalar layers in a given partition.
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
void setVecFloatMetadata(const std::string &name, const V3f &val)
Set the a V3f value for the given metadata name.
EmptyField< Data_T >::Vec readProxyVectorLayers(const std::string &name=std::string("")) const
Retrieves a proxy version (EmptyField) of each vector layer.
#define FIELD3D_INSTANTIATION_READPROXYVECTORLAYER(type)
std::map< std::string, std::string > GroupMembershipMap
Definition: Field3DFile.h:228
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...
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
Contains the FieldCache class.
static ClassFactory & singleton()
}
virtual const char * what() const
Definition: Exception.h:90
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
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
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...
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:147
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.
OgDataType
Enumerates the various uses for Ogawa-level groups.
Definition: Traits.h:125
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 ...
Scoped object - creates a group on creation and closes it on destruction.
Definition: Hdf5Util.h:165
Field3D::V3h vec16_t
Definition: Traits.h:91
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 ...
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
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 printHierarchy() const
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 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:168
void getPartitionNames(std::vector< std::string > &names) const
Gets the names of all the partitions in the file.
std::string name
The name of the layer (always available)
Definition: Field3DFile.h:100
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.
FieldIO::Ptr createFieldIO(const std::string &className) const
Instances an IO object by name.
Field3D::V3i veci32_t
Definition: Traits.h:94
void setMapping(FieldMapping::Ptr mapping)
Sets the field&#39;s mapping.
Definition: Field.h:347
#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
EmptyField< Data_T >::Vec readProxyLayer(const std::string &partitionName, const std::string &layerName, bool isVectorLayer) const
Retrieves a proxy version (EmptyField) of each layer .
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...
virtual ~Field3DFileBase()=0
Pure virtual destructor to ensure we never instantiate this class.
#define FIELD3D_API
Definition: ns.h:77
bool readMetadata(const OgIGroup &metadataGroup, FieldBase::Ptr field) const
Read metadata for this layer.
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.
bool close()
Closes the file. No need to call this unless you specifically want to close the file early...
FieldMetadata & metadata()
accessor to the m_metadata class
Definition: Field.h:155
#define FIELD3D_INSTANTIATION_READLAYERS1(type)
void getIntPartitionNames(std::vector< std::string > &names) const
Gets the names of all the -internal- partitions in the file.
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:134
boost::shared_ptr< Alembic::Ogawa::OArchive > m_archive
Pointer to the Ogawa archive.
Definition: Field3DFile.h:844
std::string removeUniqueId(const std::string &partitionName) const
Strips any unique identifiers from the partition name and returns the original name.
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...
std::string attribute
Optional name of the attribute the field represents.
Definition: Field.h:173
Contains Field, WritableField and ResizableField classes.
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...
FieldMetadata & metadata()
accessor to the m_metadata class
Definition: Field3DFile.h:276
Contains the ClassFactory class for registering Field3D classes.
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 ...
virtual void closeInternal()=0
Closes the file if open.
boost::intrusive_ptr< FieldIO > Ptr
Definition: FieldIO.h:91
Field< Data_T >::Vec readLayers(const std::string &layerName=std::string("")) const
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
EmptyField< Data_T >::Vec readProxyScalarLayers(const std::string &name=std::string("")) const
Retrieves a proxy version (EmptyField) of each scalar layer.
#define FIELD3D_INSTANTIATION_READLAYERS2(type)
std::string incrementPartitionName(std::string &pname)
Increment the partition or make it zero if there&#39;s not an integer suffix.
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...
virtual void closeInternal()
Closes the file if open.
Definition: Field3DFile.h:796
bool open(const std::string &filename)
Opens the given file.
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