Field3D
Field3DFile.h
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
45 //----------------------------------------------------------------------------//
46 
47 #ifndef _INCLUDED_Field3D_Field3DFile_H_
48 #define _INCLUDED_Field3D_Field3DFile_H_
49 
50 //----------------------------------------------------------------------------//
51 
52 #include <list>
53 #include <string>
54 #include <vector>
55 
56 #include <hdf5.h>
57 
58 #include <boost/intrusive_ptr.hpp>
59 
60 #include "EmptyField.h"
61 #include "Field.h"
62 #include "FieldMetadata.h"
63 #include "ClassFactory.h"
64 #include "Hdf5Util.h"
65 
66 //----------------------------------------------------------------------------//
67 
68 #include "ns.h"
69 
71 
72 
73 
74 //----------------------------------------------------------------------------//
75 // Function Declarations
76 //----------------------------------------------------------------------------//
77 
79 // \{
80 
83 template <class Data_T>
84 typename Field<Data_T>::Ptr
85 readField(const std::string &className, hid_t layerGroup,
86  const std::string &filename, const std::string &layerPath);
89 bool writeField(hid_t layerGroup, FieldBase::Ptr field);
90 
93 FieldMapping::Ptr readFieldMapping(hid_t mappingGroup);
94 
98 bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping);
99 
101 
102 //----------------------------------------------------------------------------//
103 // Layer
104 //----------------------------------------------------------------------------//
105 
108 namespace File {
109 
117 class Layer
118 {
119 public:
121  std::string name;
124  std::string parent;
125 };
126 
127 } // namespace File
128 
129 //----------------------------------------------------------------------------//
130 // Partition
131 //----------------------------------------------------------------------------//
132 
133 namespace File {
134 
142 class Partition : public RefBase
143 {
144 public:
145 
146  typedef std::vector<Layer> ScalarLayerList;
147  typedef std::vector<Layer> VectorLayerList;
148 
149  typedef boost::intrusive_ptr<Partition> Ptr;
150  typedef boost::intrusive_ptr<const Partition> CPtr;
151 
152  // RTTI replacement ----------------------------------------------------------
153 
156 
157  static const char *classType()
158  {
159  return "Partition";
160  }
161 
162  // Ctors, dtor ---------------------------------------------------------------
163 
166  : RefBase()
167  { }
168 
169  // From RefBase --------------------------------------------------------------
170 
173 
174  virtual std::string className() const;
175 
177 
178  // Main methods --------------------------------------------------------------
179 
181  void addScalarLayer(const File::Layer &layer);
183  void addVectorLayer(const File::Layer &layer);
184 
186  const File::Layer* scalarLayer(const std::string &name) const;
188  const File::Layer* vectorLayer(const std::string &name) const;
189 
191  void getScalarLayerNames(std::vector<std::string> &names) const;
193  void getVectorLayerNames(std::vector<std::string> &names) const;
194 
195  // Public data members -------------------------------------------------------
196 
198  std::string name;
201 
202 private:
203 
204  // Private data members ------------------------------------------------------
205 
210 
211  // Typedefs ------------------------------------------------------------------
212 
214  typedef RefBase base;
215 
216 };
217 
218 } // namespace File
219 
220 //----------------------------------------------------------------------------//
221 // Field3DFileBase
222 //----------------------------------------------------------------------------//
223 
231 //----------------------------------------------------------------------------//
232 
234 {
235 public:
236 
237  // Structs -------------------------------------------------------------------
238 
239  struct LayerInfo
240  {
241  std::string name;
242  std::string parentName;
244  LayerInfo(std::string par, std::string nm, int cpt)
245  : name(nm), parentName(par), components(cpt)
246  { /* Empty */ }
247  };
248 
249  // Typedefs ------------------------------------------------------------------
250 
251  typedef std::map<std::string, std::string> GroupMembershipMap;
252 
253  // Ctor, dtor ----------------------------------------------------------------
254 
257 
258  Field3DFileBase();
260  virtual ~Field3DFileBase() = 0;
261 
263 
264  // Main methods --------------------------------------------------------------
265 
267  void clear();
268 
272  bool close();
273 
276 
278  void getPartitionNames(std::vector<std::string> &names) const;
280  void getScalarLayerNames(std::vector<std::string> &names,
281  const std::string &partitionName) const;
283  void getVectorLayerNames(std::vector<std::string> &names,
284  const std::string &partitionName) const;
285 
288  File::Partition::Ptr getPartition(const std::string &partitionName) const
289  { return partition(partitionName); }
290 
292 
295 
299  std::string intPartitionName(const std::string &partitionName,
300  const std::string &layerName,
301  FieldRes::Ptr field);
302 
305  std::string removeUniqueId(const std::string &partitionName) const;
306 
308  void addGroupMembership(const GroupMembershipMap &groupMembers);
309 
311 
312  // Access to metadata --------------------------------------------------------
313 
316  { return m_metadata; }
317 
320  { return m_metadata; }
321 
324  virtual void metadataHasChanged(const std::string &/* name */)
325  { /* Empty */ }
326 
327  // Debug ---------------------------------------------------------------------
328 
331 
332  void printHierarchy() const;
333 
335 
336 protected:
337 
338  // Internal typedefs ---------------------------------------------------------
339 
340  typedef std::vector<File::Partition::Ptr> PartitionList;
341  typedef std::map<std::string, int> PartitionCountMap;
342 
343  // Convenience methods -------------------------------------------------------
344 
347 
349  void closeInternal();
352  File::Partition::Ptr partition(const std::string &partitionName);
355  File::Partition::Ptr partition(const std::string &partitionName) const;
356 
358  void getIntPartitionNames(std::vector<std::string> &names) const;
361  void getIntScalarLayerNames(std::vector<std::string> &names,
362  const std::string &intPartitionName) const;
365  void getIntVectorLayerNames(std::vector<std::string> &names,
366  const std::string &intPartitionName) const;
367 
369  int numIntPartitions(const std::string &partitionName) const;
370 
373  std::string makeIntPartitionName(const std::string &partitionsName,
374  int i) const;
375 
377 
378  // Data members --------------------------------------------------------------
379 
381  std::vector<LayerInfo> m_layerInfo;
382 
384  hid_t m_file;
388  std::vector<std::string> m_partitionNames;
389 
393 
398 
401 
402 private:
403 
404  // Private member functions --------------------------------------------------
405 
407  void operator =(const Field3DFileBase&);
408 
409 
410 };
411 
412 //----------------------------------------------------------------------------//
413 // Field3DInputFile
414 //----------------------------------------------------------------------------//
415 
429 //----------------------------------------------------------------------------//
430 
432 {
433 public:
434 
435  // Ctors, dtor ---------------------------------------------------------------
436 
439 
441  virtual ~Field3DInputFile();
442 
444 
445  // Main interface ------------------------------------------------------------
446 
449 
454  template <class Data_T>
455  typename Field<Data_T>::Vec
456  readScalarLayers(const std::string &layerName = std::string("")) const;
457 
459  template <class Data_T>
460  typename Field<Data_T>::Vec
461  readScalarLayers(const std::string &partitionName,
462  const std::string &layerName) const;
463 
468  template <class Data_T>
469  typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
470  readVectorLayers(const std::string &layerName = std::string("")) const;
471 
473  template <class Data_T>
474  typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
475  readVectorLayers(const std::string &partitionName,
476  const std::string &layerName) const;
477 
480  template <template <typename T> class Field_T, class Data_T>
481  typename Field_T<Data_T>::Vec
482  readScalarLayersAs(const std::string &layerName = std::string("")) const;
483 
486  template <template <typename T> class Field_T, class Data_T>
487  typename Field_T<Data_T>::Vec
488  readScalarLayersAs(const std::string &partitionName,
489  const std::string &layerName) const;
490 
493  template <template <typename T> class Field_T, class Data_T>
494  typename Field_T<Data_T>::Vec
495  readVectorLayersAs(const std::string &layerName = std::string("")) const;
496 
499  template <template <typename T> class Field_T, class Data_T>
500  typename Field_T<Data_T>::Vec
501  readVectorLayersAs(const std::string &partitionName,
502  const std::string &layerName) const;
503 
505 
508 
514  template <class Data_T>
515  typename EmptyField<Data_T>::Vec
516  readProxyLayer(const std::string &partitionName,
517  const std::string &layerName,
518  bool isVectorLayer) const;
519 
525  template <class Data_T>
526  typename EmptyField<Data_T>::Vec
527  readProxyScalarLayers(const std::string &name = std::string("")) const;
528 
534  template <class Data_T>
535  typename EmptyField<Data_T>::Vec
536  readProxyVectorLayers(const std::string &name = std::string("")) const;
537 
539 
540  // File IO ---
541 
544  bool open(const std::string &filename);
545 
546  // Callback convenience methods ----------------------------------------------
547 
550 
552  herr_t parsePartition(hid_t loc_id, const std::string partitionName);
553 
555  herr_t parseLayer(hid_t loc_id, const std::string &partitionName,
556  const std::string &layerName);
557 
559 
560  // Convenience methods -------------------------------------------------------
561 
563  bool readGroupMembership(GroupMembershipMap &gpMembershipMap);
564 
565 private:
566 
567  // Convenience methods -------------------------------------------------------
568 
571  template <class Data_T>
572  typename Field<Data_T>::Ptr
573  readScalarLayer(const std::string &intPartitionName,
574  const std::string &layerName) const;
575 
578  template <class Data_T>
579  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
580  readVectorLayer(const std::string &intPartitionName,
581  const std::string &layerName) const;
582 
585  template <class Data_T>
586  typename Field<Data_T>::Ptr
587  readLayer(const std::string &intPartitionName,
588  const std::string &layerName,
589  bool isVectorLayer) const;
590 
593 
595  bool readMetadata(hid_t metadata_id, FieldBase::Ptr field) const;
596 
598  bool readMetadata(hid_t metadata_id);
599 
600  // Data members --------------------------------------------------------------
601 
603  std::string m_filename;
604 
605 };
606 
607 //----------------------------------------------------------------------------//
608 // Field3DOutputFile
609 //----------------------------------------------------------------------------//
610 
624 //----------------------------------------------------------------------------//
625 
627 {
628 public:
629 
630  // Enums ---------------------------------------------------------------------
631 
632  enum CreateMode {
635  };
636 
637  // Ctors, dtor ---------------------------------------------------------------
638 
641 
643  virtual ~Field3DOutputFile();
644 
646 
647  // Main interface ------------------------------------------------------------
648 
651 
653  template <class Data_T>
654  bool writeScalarLayer(const std::string &layerName,
655  typename Field<Data_T>::Ptr layer)
656  { return writeScalarLayer<Data_T>(layerName, std::string("default"), layer); }
657 
659  template <class Data_T>
660  bool writeVectorLayer(const std::string &layerName,
661  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
662  { return writeVectorLayer<Data_T>(layerName, std::string("default"), layer); }
663 
666  template <class Data_T>
667  bool writeScalarLayer(const std::string &partitionName,
668  const std::string &layerName,
669  typename Field<Data_T>::Ptr layer);
670 
673  template <class Data_T>
674  bool writeScalarLayer(typename Field<Data_T>::Ptr layer);
675 
678  template <class Data_T>
679  bool writeVectorLayer(const std::string &partitionName,
680  const std::string &layerName,
681  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
682 
685  template <class Data_T>
686  bool writeVectorLayer(typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
687 
689 
691  bool create(const std::string &filename, CreateMode cm = OverwriteMode);
692 
694  bool writeGlobalMetadata();
695 
698  bool writeGroupMembership();
699 
701  std::string incrementPartitionName(std::string &pname);
702 
704  template <class Data_T>
706  createNewPartition(const std::string &partitionName,
707  const std::string &layerName,
708  typename Field<Data_T>::Ptr field);
709  private:
710 
711  // Convenience methods -------------------------------------------------------
712 
716  bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping);
717 
719  template <class Data_T>
720  bool writeLayer(const std::string &partitionName,
721  const std::string &layerName,
722  bool isVectorLayer,
723  typename Field<Data_T>::Ptr layer);
724 
726  bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer);
727 
729  bool writeMetadata(hid_t metadataGroup);
730 
731 };
732 
733 //----------------------------------------------------------------------------//
734 // Field3DInputFile-related callback functions
735 //----------------------------------------------------------------------------//
736 
738 namespace InputFile {
739 
744 {
746  std::string partitionName;
747 };
748 
752 herr_t parsePartitions(hid_t loc_id, const char *partitionName,
753  const H5L_info_t *linfo, void *opdata);
754 
758 herr_t parseLayers(hid_t loc_id, const char *partitionName,
759  const H5L_info_t *linfo, void *opdata);
760 
761 } // namespace InputFile
762 
763 //----------------------------------------------------------------------------//
764 // Field3DInputFile
765 //----------------------------------------------------------------------------//
766 
767 template <class Data_T>
768 typename Field<Data_T>::Vec
769 Field3DInputFile::readScalarLayers(const std::string &name) const
770 {
771  using namespace std;
772 
773  typedef typename Field<Data_T>::Ptr FieldPtr;
774  typedef typename Field<Data_T>::Vec FieldList;
775 
776  FieldList ret;
777  std::vector<std::string> parts;
778  getIntPartitionNames(parts);
779 
780  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
781  std::vector<std::string> layers;
782  getIntScalarLayerNames(layers, *p);
783  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
784  // Only read if it matches the name
785  if ((name.length() == 0) || (*l == name)) {
786  FieldPtr mf = readScalarLayer<Data_T>(*p, *l);
787  if (mf) {
788  ret.push_back(mf);
789  }
790  }
791  }
792  }
793 
794  return ret;
795 }
796 
797 //----------------------------------------------------------------------------//
798 
799 template <class Data_T>
800 typename Field<Data_T>::Vec
801 Field3DInputFile::readScalarLayers(const std::string &partitionName,
802  const std::string &layerName) const
803 {
804  using namespace std;
805 
806  typedef typename Field<Data_T>::Ptr FieldPtr;
807  typedef typename Field<Data_T>::Vec FieldList;
808 
809  FieldList ret;
810 
811  if ((layerName.length() == 0) || (partitionName.length() == 0))
812  return ret;
813 
814  std::vector<std::string> parts;
815  getIntPartitionNames(parts);
816 
817  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
818  std::vector<std::string> layers;
819  getIntScalarLayerNames(layers, *p);
820  if (removeUniqueId(*p) == partitionName) {
821  for (vector<string>::iterator l = layers.begin();
822  l != layers.end(); ++l) {
823  // Only read if it matches the name
824  if (*l == layerName) {
825  FieldPtr mf = readScalarLayer<Data_T>(*p, *l);
826  if (mf)
827  ret.push_back(mf);
828  }
829  }
830  }
831  }
832 
833  return ret;
834 }
835 
836 //----------------------------------------------------------------------------//
837 
838 template <class Data_T>
839 typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
840 Field3DInputFile::readVectorLayers(const std::string &name) const
841 {
842  using namespace std;
843 
844  typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
845  typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
846 
847  FieldList ret;
848 
849  std::vector<std::string> parts;
850  getIntPartitionNames(parts);
851 
852  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
853  std::vector<std::string> layers;
854  getIntVectorLayerNames(layers, *p);
855  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
856  // Only read if it matches the name
857  if ((name.length() == 0) || (*l == name)) {
858  FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
859  if (mf)
860  ret.push_back(mf);
861  }
862  }
863  }
864 
865  return ret;
866 }
867 
868 //----------------------------------------------------------------------------//
869 
870 template <class Data_T>
871 typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
872 Field3DInputFile::readVectorLayers(const std::string &partitionName,
873  const std::string &layerName) const
874 {
875  using namespace std;
876 
877  typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
878  typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
879 
880  FieldList ret;
881 
882  if ((layerName.length() == 0) || (partitionName.length() == 0))
883  return ret;
884 
885  std::vector<std::string> parts;
886  getIntPartitionNames(parts);
887 
888  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
889  std::vector<std::string> layers;
890  getIntVectorLayerNames(layers, *p);
891  if (removeUniqueId(*p) == partitionName) {
892  for (vector<string>::iterator l = layers.begin();
893  l != layers.end(); ++l) {
894  // Only read if it matches the name
895  if (*l == layerName) {
896  FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
897  if (mf)
898  ret.push_back(mf);
899  }
900  }
901  }
902  }
903 
904  return ret;
905 }
906 
907 //----------------------------------------------------------------------------//
908 
909 template <class Data_T>
910 typename Field<Data_T>::Ptr
912  const std::string &layerName,
913  bool isVectorLayer) const
914 {
915  using namespace boost;
916  using namespace std;
917  using namespace Hdf5Util;
918 
919  // Instantiate a null pointer for easier code reading
920  typename Field<Data_T>::Ptr nullPtr;
921 
922  // Find the partition
923  File::Partition::Ptr part = partition(intPartitionName);
924  if (!part) {
925  Msg::print(Msg::SevWarning, "Couldn't find partition: " + intPartitionName);
926  return nullPtr;
927  }
928 
929  // Find the layer in the partition
930  const File::Layer *l;
931  if (isVectorLayer)
932  l = part->vectorLayer(layerName);
933  else
934  l = part->scalarLayer(layerName);
935  if (!l) {
936  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName );
937  return nullPtr;
938  }
939 
940  // Open the layer group
941  string layerPath = l->parent + "/" + l->name;
942  H5ScopedGopen layerGroup(m_file, layerPath.c_str());
943 
944  if (layerGroup.id() < 0) {
945  Msg::print(Msg::SevWarning, "Couldn't find layer group " + layerName
946  + " in .f3d file ");
947  return nullPtr;
948  }
949 
950  // Get the class name
951  string className;
952  if (!readAttribute(layerGroup.id(), "class_name", className)) {
953  Msg::print(Msg::SevWarning, "Couldn't find class_name attrib in layer " +
954  layerName);
955  return nullPtr;
956  }
957 
958  // Construct the field and load the data
959 
960  typename Field<Data_T>::Ptr field;
961  field = readField<Data_T>(className, layerGroup.id(), m_filename, layerPath);
962 
963  if (!field) {
964 #if 0 // This isn't really an error
965  Msg::print(Msg::SevWarning, "Couldn't read the layer data of layer: "
966  + layerName);
967 #endif
968  return nullPtr;
969  }
970 
971  // read the metadata
972  string metadataPath = layerPath + "/metadata";
973  H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
974  if (metadataGroup.id() > 0) {
975  readMetadata(metadataGroup.id(), field);
976  }
977 
978  // Set the name of the field so it's possible to re-create the file
979  field->name = removeUniqueId(intPartitionName);
980  field->attribute = layerName;
981  field->setMapping(part->mapping);
982 
983  return field;
984 }
985 
986 //----------------------------------------------------------------------------//
987 
988 template <template <typename T> class Field_T, class Data_T>
989 typename Field_T<Data_T>::Vec
990 Field3DInputFile::readScalarLayersAs(const std::string &layerName) const
991 {
992  typedef typename Field<Data_T>::Vec FieldList;
993  typedef typename Field_T<Data_T>::Vec TypedFieldList;
994 
995  // First, read the layers as-is
996  FieldList originals;
997  originals = readScalarLayers<Data_T>(layerName);
998 
999  // Loop over fields, converting if needed
1000  TypedFieldList output;
1001  typename FieldList::iterator i = originals.begin();
1002  for (; i != originals.end(); ++i) {
1003  typename Field_T<Data_T>::Ptr targetField;
1004  targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
1005  if (targetField) {
1006  output.push_back(targetField);
1007  } else {
1008  typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
1009  newTarget->name = (*i)->name;
1010  newTarget->attribute = (*i)->attribute;
1011  newTarget->copyMetadata(*i);
1012  newTarget->copyFrom(*i);
1013  output.push_back(newTarget);
1014  }
1015  }
1016 
1017  return output;
1018 }
1019 
1020 //----------------------------------------------------------------------------//
1021 
1022 template <template <typename T> class Field_T, class Data_T>
1023 typename Field_T<Data_T>::Vec
1024 Field3DInputFile::readScalarLayersAs(const std::string &partitionName,
1025  const std::string &layerName) const
1026 {
1027  typedef typename Field<Data_T>::Vec FieldList;
1028  typedef typename Field_T<Data_T>::Vec TypedFieldList;
1029 
1030  // First, read the layers as-is
1031  FieldList originals;
1032  originals = readScalarLayers<Data_T>(partitionName, layerName);
1033 
1034  // Loop over fields, converting if needed
1035  TypedFieldList output;
1036  typename FieldList::iterator i = originals.begin();
1037  for (; i != originals.end(); ++i) {
1038  typename Field_T<Data_T>::Ptr targetField;
1039  targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
1040  if (targetField) {
1041  output.push_back(targetField);
1042  } else {
1043  typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
1044  newTarget->name = (*i)->name;
1045  newTarget->attribute = (*i)->attribute;
1046  newTarget->copyMetadata(**i);
1047  newTarget->copyFrom(*i);
1048  output.push_back(newTarget);
1049  }
1050  }
1051 
1052  return output;
1053 }
1054 
1055 //----------------------------------------------------------------------------//
1056 
1057 template <template <typename T> class Field_T, class Data_T>
1058 typename Field_T<Data_T>::Vec
1059 Field3DInputFile::readVectorLayersAs(const std::string &layerName) const
1060 {
1061  typedef typename Field<Data_T>::Vec FieldList;
1062  typedef typename Field_T<Data_T>::Vec TypedFieldList;
1063 
1064  // First, read the layers as-is
1065  FieldList originals;
1066  originals = readVectorLayers<Data_T>(layerName);
1067 
1068  // Loop over fields, converting if needed
1069  TypedFieldList output;
1070  typename FieldList::iterator i = originals.begin();
1071  for (; i != originals.end(); ++i) {
1072  typename Field_T<Data_T>::Ptr targetField;
1073  targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
1074  if (targetField) {
1075  output.push_back(targetField);
1076  } else {
1077  typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
1078  newTarget->name = (*i)->name;
1079  newTarget->attribute = (*i)->attribute;
1080  newTarget->copyMetadata(*i);
1081  newTarget->copyFrom(*i);
1082  output.push_back(newTarget);
1083  }
1084  }
1085 
1086  return output;
1087 }
1088 
1089 //----------------------------------------------------------------------------//
1090 
1091 template <template <typename T> class Field_T, class Data_T>
1092 typename Field_T<Data_T>::Vec
1093 Field3DInputFile::readVectorLayersAs(const std::string &partitionName,
1094  const std::string &layerName) const
1095 {
1096  typedef typename Field<Data_T>::Vec FieldList;
1097  typedef typename Field_T<Data_T>::Vec TypedFieldList;
1098 
1099  // First, read the layers as-is
1100  FieldList originals;
1101  originals = readVectorLayers<Data_T>(partitionName, layerName);
1102 
1103  // Loop over fields, converting if needed
1104  TypedFieldList output;
1105  typename FieldList::iterator i = originals.begin();
1106  for (; i != originals.end(); ++i) {
1107  typename Field_T<Data_T>::Ptr targetField;
1108  targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
1109  if (targetField) {
1110  output.push_back(targetField);
1111  } else {
1112  typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
1113  newTarget->name = (*i)->name;
1114  newTarget->attribute = (*i)->attribute;
1115  newTarget->copyMetadata(*i);
1116  newTarget->copyFrom(*i);
1117  output.push_back(newTarget);
1118  }
1119  }
1120 
1121  return output;
1122 }
1123 
1124 //----------------------------------------------------------------------------//
1125 
1126 template <class Data_T>
1127 typename EmptyField<Data_T>::Vec
1128 Field3DInputFile::readProxyLayer(const std::string &partitionName,
1129  const std::string &layerName,
1130  bool isVectorLayer) const
1131 {
1132  using namespace boost;
1133  using namespace std;
1134  using namespace Hdf5Util;
1135 
1136  // Instantiate a null pointer for easier code reading
1137  typename EmptyField<Data_T>::Vec emptyList, output;
1138 
1139  if ((layerName.length() == 0) || (partitionName.length() == 0))
1140  return emptyList;
1141 
1142  std::vector<std::string> parts, layers;
1143  getIntPartitionNames(parts);
1144 
1145  bool foundPartition = false;
1146 
1147  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1148  if (removeUniqueId(*p) == partitionName) {
1149  foundPartition = true;
1150  if (isVectorLayer) {
1151  getIntVectorLayerNames(layers, *p);
1152  } else {
1153  getIntScalarLayerNames(layers, *p);
1154  }
1155  for (vector<string>::iterator l = layers.begin();
1156  l != layers.end(); ++l) {
1157  if (*l == layerName) {
1158  // Find the partition
1159  File::Partition::Ptr part = partition(*p);
1160  if (!part) {
1161  Msg::print(Msg::SevWarning, "Couldn't find partition: " + *p);
1162  return emptyList;
1163  }
1164  // Find the layer
1165  const File::Layer *layer;
1166  if (isVectorLayer)
1167  layer = part->vectorLayer(layerName);
1168  else
1169  layer = part->scalarLayer(layerName);
1170  if (!layer) {
1171  Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
1172  return emptyList;
1173  }
1174  // Open the layer group
1175  string layerPath = layer->parent + "/" + layer->name;
1176  H5ScopedGopen layerGroup(m_file, layerPath.c_str());
1177  if (layerGroup.id() < 0) {
1178  Msg::print(Msg::SevWarning, "Couldn't find layer group "
1179  + layerName + " in .f3d file ");
1180  return emptyList;
1181  }
1182  // Read the extents and data window
1183  Box3i extents, dataW;
1184  if (!readAttribute(layerGroup, "extents", 6, extents.min.x)) {
1185  return emptyList;
1186  }
1187  if (!readAttribute(layerGroup, "data_window", 6, dataW.min.x)) {
1188  return emptyList;
1189  }
1190  // Construct the field and load the data
1191  typename EmptyField<Data_T>::Ptr field(new EmptyField<Data_T>);
1192  field->setSize(extents, dataW);
1193 
1194  // read the metadata
1195  string metadataPath = layerPath + "/metadata";
1196  H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
1197  if (metadataGroup.id() > 0) {
1198  readMetadata(metadataGroup.id(), field);
1199  }
1200 
1201  // ... Set the name of the field so it's possible to
1202  // ... re-create the file
1203  field->name = partitionName;
1204  field->attribute = layerName;
1205  field->setMapping(part->mapping);
1206  // Add field to output
1207  output.push_back(field);
1208  }
1209  }
1210  }
1211  }
1212 
1213  if (!foundPartition) {
1214  Msg::print(Msg::SevWarning, "Couldn't find partition: " + partitionName);
1215  return emptyList;
1216  }
1217 
1218  return output;
1219 }
1220 
1221 //----------------------------------------------------------------------------//
1222 
1223 template <class Data_T>
1224 typename EmptyField<Data_T>::Vec
1225 Field3DInputFile::readProxyScalarLayers(const std::string &name) const
1226 {
1227  using namespace std;
1228 
1229  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1230  typedef std::vector<FieldPtr> FieldList;
1231 
1232  FieldList ret;
1233 
1234  std::vector<std::string> parts;
1235  getPartitionNames(parts);
1236 
1237  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1238  std::vector<std::string> layers;
1239  getScalarLayerNames(layers, *p);
1240  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1241  // Only read if it matches the name
1242  if ((name.length() == 0) || (*l == name)) {
1243  FieldList f = readProxyLayer<Data_T>(*p, *l, false);
1244  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1245  if (*i) {
1246  ret.push_back(*i);
1247  }
1248  }
1249  }
1250  }
1251  }
1252 
1253  return ret;
1254 }
1255 
1256 //----------------------------------------------------------------------------//
1257 
1258 template <class Data_T>
1259 typename EmptyField<Data_T>::Vec
1260 Field3DInputFile::readProxyVectorLayers(const std::string &name) const
1261 {
1262  using namespace std;
1263 
1264  typedef typename EmptyField<Data_T>::Ptr FieldPtr;
1265  typedef std::vector<FieldPtr> FieldList;
1266 
1267  FieldList ret;
1268 
1269  std::vector<std::string> parts;
1270  getPartitionNames(parts);
1271 
1272  for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
1273  std::vector<std::string> layers;
1274  getVectorLayerNames(layers, *p);
1275  for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
1276  // Only read if it matches the name
1277  if ((name.length() == 0) || (*l == name)) {
1278  FieldList f = readProxyLayer<Data_T>(*p, *l, true);
1279  for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
1280  if (*i) {
1281  ret.push_back(*i);
1282  }
1283  }
1284  }
1285  }
1286  }
1287 
1288  return ret;
1289 }
1290 
1291 //----------------------------------------------------------------------------//
1292 
1293 template <class Data_T>
1294 typename Field<Data_T>::Ptr
1296  const std::string &layerName) const
1297 {
1298  return readLayer<Data_T>(intPartitionName, layerName, false);
1299 }
1300 
1301 //----------------------------------------------------------------------------//
1302 
1303 template <class Data_T>
1304 typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
1306  const std::string &layerName) const
1307 {
1308  return readLayer<FIELD3D_VEC3_T<Data_T> >(intPartitionName, layerName, true);
1309 }
1310 
1311 //----------------------------------------------------------------------------//
1312 // Field3DOutputFile
1313 //----------------------------------------------------------------------------//
1314 
1315 template <class Data_T>
1317 Field3DOutputFile::createNewPartition(const std::string &partitionName,
1318  const std::string &layerName,
1319  typename Field<Data_T>::Ptr field)
1320 {
1321  using namespace Hdf5Util;
1322  using namespace Exc;
1323 
1325 
1326  newPart->name = partitionName;
1327 
1328  H5ScopedGcreate partGroup(m_file, newPart->name.c_str());
1329  if (partGroup.id() < 0) {
1331  "Error creating partition: " + newPart->name);
1332  return File::Partition::Ptr();
1333  }
1334 
1335  m_partitions.push_back(newPart);
1336 
1337  // Pick up new pointer
1338  File::Partition::Ptr part = partition(partitionName);
1339 
1340  // Add mapping group to the partition
1343  try {
1344  if (!writeMapping(partGroup.id(), field->mapping())) {
1346  "writeMapping returned false for an unknown reason ");
1347  return File::Partition::Ptr();
1348  }
1349  }
1350  catch (WriteMappingException &e) {
1351  Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: "
1352  + partitionName);
1353  return File::Partition::Ptr();
1354  }
1355  catch (...) {
1357  "Unknown error when writing mapping for partition: "
1358  + partitionName);
1359  return File::Partition::Ptr();
1360  }
1361 
1362  // Set the mapping of the partition. Since all layers share their
1363  // partition's mapping, we can just pick this first one. All subsequent
1364  // additions to the same partition are checked to have the same mapping
1365  part->mapping = field->mapping();
1366 
1367  // Tag node as partition
1368  // Create a version attribute on the root node
1369  if (!writeAttribute(partGroup.id(), "is_field3d_partition", "1")) {
1370  Msg::print(Msg::SevWarning, "Adding partition string.");
1371  return File::Partition::Ptr();
1372  }
1373 
1374  return part;
1375 }
1376 
1377 //----------------------------------------------------------------------------//
1378 
1379 template <class Data_T>
1380 bool
1381 Field3DOutputFile::writeLayer(const std::string &userPartitionName,
1382  const std::string &layerName,
1383  bool isVectorLayer,
1384  typename Field<Data_T>::Ptr field)
1385 {
1386  using namespace std;
1387  using namespace Exc;
1388  using namespace Hdf5Util;
1389 
1390  if (!field) {
1392  "Called writeLayer with null pointer. Ignoring...");
1393  return false;
1394  }
1395 
1396  if (m_file < 0) {
1398  "Attempting to write layer without opening file first. ");
1399  return false;
1400  }
1401 
1402  string partitionName = intPartitionName(userPartitionName, layerName, field);
1403 
1404  // See if the partition already exists or if we need to make it ---
1405 
1406  File::Partition::Ptr part = partition(partitionName);
1407 
1408  if (!part) {
1409  part = createNewPartition<Data_T>(partitionName,layerName,field);
1410  if (!part)
1411  return false;
1412  } else {
1413 
1414  if (!field->mapping()) {
1416  "Couldn't add layer \"" + layerName + "\" to partition \""
1417  + partitionName + "\" because the layer's mapping is null.");
1418  return false;
1419  }
1420 
1421  // If the partition already existed, we need to make sure that the layer
1422  // doesn't also exist
1423  if (!isVectorLayer) {
1424  if (part->scalarLayer(layerName)) {
1425  //need to create a new partition and then add the layer to that
1426  std::string newPartitionName = incrementPartitionName(partitionName);
1427  part = createNewPartition<Data_T>(newPartitionName,layerName,field);
1428  if (!part)
1429  return false;
1430  }
1431  } else {
1432  if (part->vectorLayer(layerName)) {
1433  //need to create a new partition and then add the layer to that
1434  std::string newPartitionName = incrementPartitionName(partitionName);
1435  part = createNewPartition<Data_T>(newPartitionName,layerName,field);
1436  if (!part)
1437  return false;
1438  }
1439  }
1440  }
1441 
1442  if (!part->mapping) {
1443  Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: "
1444  + partitionName);
1445  return false;
1446  }
1447 
1448  // Check that the mapping matches what's already in the Partition
1449  if (!field->mapping()->isIdentical(part->mapping)) {
1450  Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName
1451  + "\" to partition \"" + partitionName
1452  + "\" because mapping doesn't match");
1453  return false;
1454  }
1455 
1456  // Open the partition
1457  H5ScopedGopen partGroup(m_file, part->name.c_str(), H5P_DEFAULT);
1458 
1459  // Build a Layer object ---
1460 
1461  File::Layer layer;
1462  layer.name = layerName;
1463  layer.parent = partitionName;
1464 
1465  // Add Layer to file ---
1466 
1467  H5ScopedGcreate layerGroup(partGroup.id(), layerName.c_str(),
1468  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1469 
1470  if (layerGroup.id() < 0) {
1471  Msg::print(Msg::SevWarning, "Error creating layer: " + layerName);
1472  return false;
1473  }
1474 
1475  // Tag as layer
1476  if (!writeAttribute(layerGroup.id(), "class_type", "field3d_layer")) {
1477  Msg::print(Msg::SevWarning, "Error adding layer string.");
1478  return false;
1479  }
1480 
1481  // Add metadata group and write it out
1482  H5ScopedGcreate metadataGroup(layerGroup.id(), "metadata");
1483  if (metadataGroup.id() < 0) {
1484  Msg::print(Msg::SevWarning, "Error creating group: metadata");
1485  return false;
1486  }
1487  if (!writeMetadata(metadataGroup.id(), field)) {
1488  Msg::print(Msg::SevWarning, "Error writing metadata.");
1489  return false;
1490  }
1491 
1492  if (!writeField(layerGroup.id(), field)) {
1493  Msg::print(Msg::SevWarning, "Error writing layer: " + layer.name);
1494  return false;
1495  }
1496 
1497  // Add layer to partition ---
1498 
1499  if (isVectorLayer)
1500  part->addVectorLayer(layer);
1501  else
1502  part->addScalarLayer(layer);
1503 
1504  return true;
1505 }
1506 
1507 //----------------------------------------------------------------------------//
1508 
1509 template <class Data_T>
1510 bool
1511 Field3DOutputFile::writeScalarLayer(const std::string &partitionName,
1512  const std::string &layerName,
1513  typename Field<Data_T>::Ptr field)
1514 {
1515  return writeLayer<Data_T>(partitionName, layerName, false, field);
1516 }
1517 
1518 //----------------------------------------------------------------------------//
1519 
1520 template <class Data_T>
1521 bool
1523 {
1524  if (layer->name.size() == 0) {
1525  Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
1526  "Tried to write a scalar layer with no name");
1527  return false;
1528  }
1529  if (layer->attribute.size() == 0) {
1530  Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
1531  "Tried to write a scalar layer with no attribute name");
1532  return false;
1533  }
1534  return writeScalarLayer<Data_T>(layer->name, layer->attribute, layer);
1535 }
1536 
1537 //----------------------------------------------------------------------------//
1538 
1539 template <class Data_T>
1540 bool
1542 writeVectorLayer(const std::string &partitionName,
1543  const std::string &layerName,
1544  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr field)
1545 {
1546  return writeLayer<FIELD3D_VEC3_T<Data_T> >(partitionName, layerName,
1547  true, field);
1548 }
1549 
1550 //----------------------------------------------------------------------------//
1551 
1552 template <class Data_T>
1553 bool
1555  (typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
1556 {
1557  if (layer->name.size() == 0) {
1558  Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
1559  "Tried to write a vector layer with no name");
1560  return false;
1561  }
1562  if (layer->attribute.size() == 0) {
1563  Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
1564  "Tried to write a vector layer with no attribute name");
1565  return false;
1566  }
1567  return writeVectorLayer<Data_T>(layer->name, layer->attribute, layer);
1568 }
1569 
1570 //----------------------------------------------------------------------------//
1571 // Template Function Implementations
1572 //----------------------------------------------------------------------------//
1573 
1574 template <class Data_T>
1575 typename Field<Data_T>::Ptr
1576 readField(const std::string &className, hid_t layerGroup,
1577  const std::string &filename, const std::string &layerPath)
1578 {
1579 
1581 
1582  typedef typename Field<Data_T>::Ptr FieldPtr;
1583 
1584  FieldIO::Ptr io = factory.createFieldIO(className);
1585  assert(io != 0);
1586  if (!io) {
1587  Msg::print(Msg::SevWarning, "Unable to find class type: " +
1588  className);
1589  return FieldPtr();
1590  }
1591 
1593  FieldBase::Ptr field = io->read(layerGroup, filename, layerPath, typeEnum);
1594 
1595  if (!field) {
1596  // We don't need to print a message, because it could just be that
1597  // a layer of the specified data type and name couldn't be found
1598  return FieldPtr();
1599  }
1600 
1601  FieldPtr result = field_dynamic_cast<Field<Data_T> >(field);
1602 
1603  if (result)
1604  return result;
1605 
1606  return FieldPtr();
1607 }
1608 
1609 //----------------------------------------------------------------------------//
1610 
1612 
1613 //----------------------------------------------------------------------------//
1614 
1615 #endif