Field3D
Field3DFile.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00045 //----------------------------------------------------------------------------//
00046 
00047 #ifndef _INCLUDED_Field3D_Field3DFile_H_
00048 #define _INCLUDED_Field3D_Field3DFile_H_
00049 
00050 //----------------------------------------------------------------------------//
00051 
00052 #include <list>
00053 #include <string>
00054 #include <vector>
00055 
00056 #include <hdf5.h>
00057 
00058 #include <boost/intrusive_ptr.hpp>
00059 
00060 #include "EmptyField.h"
00061 #include "Field.h"
00062 #include "FieldMetadata.h"
00063 #include "ClassFactory.h"
00064 #include "Hdf5Util.h"
00065 
00066 //----------------------------------------------------------------------------//
00067 
00068 #include "ns.h"
00069 
00070 FIELD3D_NAMESPACE_OPEN
00071 
00072 
00073 
00074 //----------------------------------------------------------------------------//
00075 // Function Declarations
00076 //----------------------------------------------------------------------------//
00077 
00079 // \{
00080 
00083 template <class Data_T>
00084 typename Field<Data_T>::Ptr 
00085 readField(const std::string &className, hid_t layerGroup,
00086           const std::string &filename, const std::string &layerPath);
00089 bool writeField(hid_t layerGroup, FieldBase::Ptr field);
00090 
00093 FieldMapping::Ptr readFieldMapping(hid_t mappingGroup);
00094 
00098 bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping);
00099 
00101 
00102 //----------------------------------------------------------------------------//
00103 // Layer
00104 //----------------------------------------------------------------------------//
00105 
00108 namespace File {
00109 
00117 class Layer
00118 {
00119 public:
00121   std::string name;
00124   std::string parent;
00125 };
00126   
00127 } // namespace File
00128 
00129 //----------------------------------------------------------------------------//
00130 // Partition
00131 //----------------------------------------------------------------------------//
00132 
00133 namespace File {
00134 
00142 class Partition : public RefBase
00143 {
00144 public:
00145 
00146   typedef std::vector<Layer> ScalarLayerList;
00147   typedef std::vector<Layer> VectorLayerList;
00148 
00149   typedef boost::intrusive_ptr<Partition> Ptr;
00150   typedef boost::intrusive_ptr<const Partition> CPtr;
00151 
00152   // RTTI replacement ----------------------------------------------------------
00153 
00154   typedef Partition class_type;
00155   DEFINE_FIELD_RTTI_CONCRETE_CLASS;   
00156   
00157   static const char *classType()
00158   {
00159     return "Partition";
00160   }
00161 
00162   // Ctors, dtor ---------------------------------------------------------------
00163 
00165   Partition() 
00166     : RefBase() 
00167   { }
00168 
00169   // From RefBase --------------------------------------------------------------
00170 
00173 
00174   virtual std::string className() const;
00175   
00177   
00178   // Main methods --------------------------------------------------------------
00179 
00181   void addScalarLayer(const File::Layer &layer);
00183   void addVectorLayer(const File::Layer &layer);
00184 
00186   const File::Layer* scalarLayer(const std::string &name) const;
00188   const File::Layer* vectorLayer(const std::string &name) const;
00189   
00191   void getScalarLayerNames(std::vector<std::string> &names) const;
00193   void getVectorLayerNames(std::vector<std::string> &names) const;
00194 
00195   // Public data members -------------------------------------------------------
00196 
00198   std::string name;
00200   FieldMapping::Ptr mapping;
00201 
00202 private:
00203 
00204   // Private data members ------------------------------------------------------
00205 
00207   ScalarLayerList m_scalarLayers;
00209   VectorLayerList m_vectorLayers;
00210 
00211   // Typedefs ------------------------------------------------------------------
00212 
00214   typedef RefBase base;
00215 
00216 };
00217 
00218 } // namespace File
00219 
00220 //----------------------------------------------------------------------------//
00221 // Field3DFileBase
00222 //----------------------------------------------------------------------------//
00223 
00231 //----------------------------------------------------------------------------//
00232 
00233 class Field3DFileBase
00234 {
00235 public:
00236 
00237   // Structs -------------------------------------------------------------------
00238 
00239   struct LayerInfo 
00240   {
00241     std::string name;
00242     std::string parentName;
00243     int components;  
00244     LayerInfo(std::string par, std::string nm, int cpt) 
00245       : name(nm), parentName(par), components(cpt) 
00246     { /* Empty */ }
00247   };
00248 
00249   // Typedefs ------------------------------------------------------------------
00250  
00251   typedef std::map<std::string, std::string> GroupMembershipMap;
00252 
00253   // Ctor, dtor ----------------------------------------------------------------
00254 
00257 
00258   Field3DFileBase();
00260   virtual ~Field3DFileBase() = 0;
00261 
00263 
00264   // Main methods --------------------------------------------------------------
00265 
00267   void clear();
00268 
00272   bool close();
00273 
00276 
00278   void getPartitionNames(std::vector<std::string> &names) const;
00280   void getScalarLayerNames(std::vector<std::string> &names, 
00281                            const std::string &partitionName) const;
00283   void getVectorLayerNames(std::vector<std::string> &names, 
00284                            const std::string &partitionName) const;
00285 
00288   File::Partition::Ptr getPartition(const std::string &partitionName) const
00289   { return partition(partitionName); }
00290 
00292 
00295 
00299   std::string intPartitionName(const std::string &partitionName,
00300                                const std::string &layerName,
00301                                FieldRes::Ptr field);
00302 
00305   std::string removeUniqueId(const std::string &partitionName) const;
00306 
00308   void addGroupMembership(const GroupMembershipMap &groupMembers);
00309 
00311 
00312   // Access to metadata --------------------------------------------------------  
00313 
00315   FieldMetadata<Field3DFileBase>& metadata()
00316   { return m_metadata; }
00317 
00319   const FieldMetadata<Field3DFileBase>& metadata() const
00320   { return m_metadata; }
00321  
00324   virtual void metadataHasChanged(const std::string &/* name */) 
00325   { /* Empty */ }
00326 
00327   // Debug ---------------------------------------------------------------------
00328 
00331 
00332   void printHierarchy() const;
00333 
00335 
00336 protected:
00337 
00338   // Internal typedefs ---------------------------------------------------------
00339 
00340   typedef std::vector<File::Partition::Ptr> PartitionList;
00341   typedef std::map<std::string, int> PartitionCountMap;
00342 
00343   // Convenience methods -------------------------------------------------------
00344 
00347 
00349   void closeInternal();
00352   File::Partition::Ptr partition(const std::string &partitionName);
00355   File::Partition::Ptr partition(const std::string &partitionName) const;
00356   
00358   void getIntPartitionNames(std::vector<std::string> &names) const;
00361   void getIntScalarLayerNames(std::vector<std::string> &names, 
00362                               const std::string &intPartitionName) const;
00365   void getIntVectorLayerNames(std::vector<std::string> &names, 
00366                               const std::string &intPartitionName) const;
00367   
00369   int numIntPartitions(const std::string &partitionName) const;
00370 
00373   std::string makeIntPartitionName(const std::string &partitionsName,
00374                                    int i) const;
00375 
00377 
00378   // Data members --------------------------------------------------------------
00379 
00381   std::vector<LayerInfo> m_layerInfo;
00382 
00384   hid_t m_file;
00386   PartitionList m_partitions;
00388   std::vector<std::string> m_partitionNames;
00389 
00392   PartitionCountMap m_partitionCount;
00393 
00397   GroupMembershipMap m_groupMembership;
00398 
00400   FieldMetadata<Field3DFileBase> m_metadata;
00401 
00402 private:
00403 
00404   // Private member functions --------------------------------------------------
00405 
00406   Field3DFileBase(const Field3DFileBase&);
00407   void operator =(const Field3DFileBase&); 
00408 
00409 
00410 };
00411 
00412 //----------------------------------------------------------------------------//
00413 // Field3DInputFile
00414 //----------------------------------------------------------------------------//
00415 
00429 //----------------------------------------------------------------------------//
00430 
00431 class Field3DInputFile : public Field3DFileBase 
00432 {
00433 public:
00434 
00435   // Ctors, dtor ---------------------------------------------------------------
00436 
00439 
00440   Field3DInputFile();
00441   virtual ~Field3DInputFile();
00442 
00444 
00445   // Main interface ------------------------------------------------------------
00446 
00449 
00454   template <class Data_T>
00455   typename Field<Data_T>::Vec
00456   readScalarLayers(const std::string &layerName = std::string("")) const;
00457 
00459   template <class Data_T>
00460   typename Field<Data_T>::Vec
00461   readScalarLayers(const std::string &partitionName, 
00462                    const std::string &layerName) const;
00463 
00468   template <class Data_T>
00469   typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00470   readVectorLayers(const std::string &layerName = std::string("")) const;
00471 
00473   template <class Data_T>
00474   typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00475   readVectorLayers(const std::string &partitionName, 
00476                    const std::string &layerName) const;
00477 
00480   template <template <typename T> class Field_T, class Data_T>
00481   typename Field_T<Data_T>::Vec
00482   readScalarLayersAs(const std::string &layerName = std::string("")) const;
00483 
00486   template <template <typename T> class Field_T, class Data_T>
00487   typename Field_T<Data_T>::Vec
00488   readScalarLayersAs(const std::string &partitionName, 
00489                      const std::string &layerName) const;
00490 
00493   template <template <typename T> class Field_T, class Data_T>
00494   typename Field_T<Data_T>::Vec
00495   readVectorLayersAs(const std::string &layerName = std::string("")) const;
00496 
00499   template <template <typename T> class Field_T, class Data_T>
00500   typename Field_T<Data_T>::Vec
00501   readVectorLayersAs(const std::string &partitionName, 
00502                      const std::string &layerName) const;
00503 
00505 
00508 
00514   template <class Data_T>
00515   typename EmptyField<Data_T>::Vec
00516   readProxyLayer(const std::string &partitionName, 
00517                  const std::string &layerName, 
00518                  bool isVectorLayer) const;
00519 
00525   template <class Data_T>
00526   typename EmptyField<Data_T>::Vec
00527   readProxyScalarLayers(const std::string &name = std::string("")) const;
00528 
00534   template <class Data_T>
00535   typename EmptyField<Data_T>::Vec
00536   readProxyVectorLayers(const std::string &name = std::string("")) const;
00537 
00539 
00540   // File IO ---
00541 
00544   bool open(const std::string &filename);
00545 
00546   // Callback convenience methods ----------------------------------------------
00547 
00550 
00552   herr_t parsePartition(hid_t loc_id, const std::string partitionName);
00553 
00555   herr_t parseLayer(hid_t loc_id, const std::string &partitionName,
00556                     const std::string &layerName);
00557 
00559 
00560   // Convenience methods -------------------------------------------------------
00561 
00563   bool readGroupMembership(GroupMembershipMap &gpMembershipMap);
00564 
00565 private:
00566 
00567   // Convenience methods -------------------------------------------------------
00568 
00571   template <class Data_T>
00572   typename Field<Data_T>::Ptr
00573   readScalarLayer(const std::string &intPartitionName, 
00574                   const std::string &layerName) const;
00575 
00578   template <class Data_T>
00579   typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
00580   readVectorLayer(const std::string &intPartitionName, 
00581                   const std::string &layerName) const;
00582   
00585   template <class Data_T>
00586   typename Field<Data_T>::Ptr 
00587   readLayer(const std::string &intPartitionName, 
00588             const std::string &layerName,
00589             bool isVectorLayer) const;
00590 
00592   bool readPartitionAndLayerInfo();
00593 
00595   bool readMetadata(hid_t metadata_id, FieldBase::Ptr field) const;
00596 
00598   bool readMetadata(hid_t metadata_id);
00599 
00600   // Data members --------------------------------------------------------------
00601 
00603   std::string m_filename;  
00604 
00605 };
00606 
00607 //----------------------------------------------------------------------------//
00608 // Field3DOutputFile
00609 //----------------------------------------------------------------------------//
00610 
00624 //----------------------------------------------------------------------------//
00625 
00626 class Field3DOutputFile : public Field3DFileBase 
00627 {
00628 public:
00629 
00630   // Enums ---------------------------------------------------------------------
00631 
00632   enum CreateMode {
00633     OverwriteMode,
00634     FailOnExisting
00635   };
00636 
00637   // Ctors, dtor ---------------------------------------------------------------
00638 
00641 
00642   Field3DOutputFile();
00643   virtual ~Field3DOutputFile();
00644 
00646 
00647   // Main interface ------------------------------------------------------------
00648 
00651 
00653   template <class Data_T>
00654   bool writeScalarLayer(const std::string &layerName, 
00655                         typename Field<Data_T>::Ptr layer)
00656   { return writeScalarLayer<Data_T>(layerName, std::string("default"), layer); }
00657 
00659   template <class Data_T>
00660   bool writeVectorLayer(const std::string &layerName, 
00661                         typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
00662   { return writeVectorLayer<Data_T>(layerName, std::string("default"), layer); }
00663 
00666   template <class Data_T>
00667   bool writeScalarLayer(const std::string &partitionName, 
00668                         const std::string &layerName, 
00669                         typename Field<Data_T>::Ptr layer);
00670 
00673   template <class Data_T>
00674   bool writeScalarLayer(typename Field<Data_T>::Ptr layer);
00675 
00678   template <class Data_T>
00679   bool writeVectorLayer(const std::string &partitionName, 
00680                         const std::string &layerName, 
00681                         typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
00682 
00685   template <class Data_T>
00686   bool writeVectorLayer(typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
00687 
00689 
00691   bool create(const std::string &filename, CreateMode cm = OverwriteMode);
00692 
00694   bool writeGlobalMetadata();
00695 
00698   bool writeGroupMembership();
00699 
00701   std::string incrementPartitionName(std::string &pname);
00702 
00704   template <class Data_T>
00705     File::Partition::Ptr
00706     createNewPartition(const std::string &partitionName,
00707                        const std::string &layerName,
00708                        typename Field<Data_T>::Ptr field);                          
00709  private:
00710   
00711   // Convenience methods -------------------------------------------------------
00712 
00716   bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping);
00717   
00719   template <class Data_T>
00720   bool writeLayer(const std::string &partitionName, 
00721                   const std::string &layerName, 
00722                   bool isVectorLayer, 
00723                   typename Field<Data_T>::Ptr layer);
00724 
00726   bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer);
00727 
00729   bool writeMetadata(hid_t metadataGroup);
00730 
00731 };
00732 
00733 //----------------------------------------------------------------------------//
00734 // Field3DInputFile-related callback functions
00735 //----------------------------------------------------------------------------//
00736 
00738 namespace InputFile {
00739 
00743 struct ParseLayersInfo
00744 {
00745   Field3DInputFile *file;
00746   std::string partitionName;
00747 };
00748 
00752 herr_t parsePartitions(hid_t loc_id, const char *partitionName, 
00753                        const H5L_info_t *linfo, void *opdata);
00754 
00758 herr_t parseLayers(hid_t loc_id, const char *partitionName, 
00759                    const H5L_info_t *linfo, void *opdata);
00760 
00761 } // namespace InputFile
00762 
00763 //----------------------------------------------------------------------------//
00764 // Field3DInputFile
00765 //----------------------------------------------------------------------------//
00766 
00767 template <class Data_T>
00768 typename Field<Data_T>::Vec
00769 Field3DInputFile::readScalarLayers(const std::string &name) const
00770 {
00771   using namespace std;
00772   
00773   typedef typename Field<Data_T>::Ptr FieldPtr;
00774   typedef typename Field<Data_T>::Vec FieldList;
00775 
00776   FieldList ret;
00777   std::vector<std::string> parts;
00778   getIntPartitionNames(parts);
00779 
00780   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00781     std::vector<std::string> layers;
00782     getIntScalarLayerNames(layers, *p);
00783     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
00784       // Only read if it matches the name
00785       if ((name.length() == 0) || (*l == name)) {
00786         FieldPtr mf = readScalarLayer<Data_T>(*p, *l);
00787         if (mf) {
00788           ret.push_back(mf);
00789         }
00790       }
00791     }
00792   }
00793   
00794   return ret;
00795 }
00796 
00797 //----------------------------------------------------------------------------//
00798 
00799 template <class Data_T>
00800 typename Field<Data_T>::Vec
00801 Field3DInputFile::readScalarLayers(const std::string &partitionName, 
00802                                    const std::string &layerName) const
00803 {
00804   using namespace std;
00805   
00806   typedef typename Field<Data_T>::Ptr FieldPtr;
00807   typedef typename Field<Data_T>::Vec FieldList;
00808 
00809   FieldList ret;
00810 
00811   if ((layerName.length() == 0) || (partitionName.length() == 0))
00812     return ret;
00813   
00814   std::vector<std::string> parts;
00815   getIntPartitionNames(parts);
00816  
00817   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00818     std::vector<std::string> layers;
00819     getIntScalarLayerNames(layers, *p);
00820     if (removeUniqueId(*p) == partitionName) {
00821       for (vector<string>::iterator l = layers.begin(); 
00822            l != layers.end(); ++l) {
00823         // Only read if it matches the name
00824         if (*l == layerName) {
00825           FieldPtr mf = readScalarLayer<Data_T>(*p, *l);
00826           if (mf)
00827             ret.push_back(mf);
00828         }
00829       }
00830     }
00831   }
00832   
00833   return ret;
00834 }
00835 
00836 //----------------------------------------------------------------------------//
00837 
00838 template <class Data_T>
00839 typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00840 Field3DInputFile::readVectorLayers(const std::string &name) const
00841 {
00842   using namespace std;
00843   
00844   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
00845   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
00846   
00847   FieldList ret;
00848   
00849   std::vector<std::string> parts;
00850   getIntPartitionNames(parts);
00851   
00852   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00853     std::vector<std::string> layers;
00854     getIntVectorLayerNames(layers, *p);
00855     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
00856       // Only read if it matches the name
00857       if ((name.length() == 0) || (*l == name)) {
00858         FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
00859         if (mf)
00860           ret.push_back(mf);
00861       }
00862     }
00863   }
00864   
00865   return ret;
00866 }
00867 
00868 //----------------------------------------------------------------------------//
00869 
00870 template <class Data_T>
00871 typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00872 Field3DInputFile::readVectorLayers(const std::string &partitionName, 
00873                                    const std::string &layerName) const
00874 {
00875   using namespace std;
00876   
00877   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
00878   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
00879   
00880   FieldList ret;
00881 
00882   if ((layerName.length() == 0) || (partitionName.length() == 0))
00883     return ret;
00884   
00885   std::vector<std::string> parts;
00886   getIntPartitionNames(parts);
00887   
00888   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00889     std::vector<std::string> layers;
00890     getIntVectorLayerNames(layers, *p);
00891     if (removeUniqueId(*p) == partitionName) {
00892       for (vector<string>::iterator l = layers.begin(); 
00893            l != layers.end(); ++l) {
00894         // Only read if it matches the name
00895         if (*l == layerName) {
00896           FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
00897           if (mf)
00898             ret.push_back(mf);
00899         }
00900       }
00901     }
00902   }
00903   
00904   return ret;
00905 }
00906 
00907 //----------------------------------------------------------------------------//
00908 
00909 template <class Data_T>
00910 typename Field<Data_T>::Ptr
00911 Field3DInputFile::readLayer(const std::string &intPartitionName,
00912                             const std::string &layerName,
00913                             bool isVectorLayer) const
00914 {
00915   using namespace boost;
00916   using namespace std;
00917   using namespace Hdf5Util;
00918 
00919   // Instantiate a null pointer for easier code reading
00920   typename Field<Data_T>::Ptr nullPtr;
00921 
00922   // Find the partition
00923   File::Partition::Ptr part = partition(intPartitionName);
00924   if (!part) {
00925     Msg::print(Msg::SevWarning, "Couldn't find partition: " + intPartitionName);
00926     return nullPtr;
00927   }
00928 
00929   // Find the layer in the partition
00930   const File::Layer *l;
00931   if (isVectorLayer)
00932     l = part->vectorLayer(layerName);
00933   else
00934     l = part->scalarLayer(layerName);
00935   if (!l) {
00936     Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName );
00937     return nullPtr;
00938   }
00939 
00940   // Open the layer group
00941   string layerPath = l->parent + "/" + l->name;
00942   H5ScopedGopen layerGroup(m_file, layerPath.c_str());
00943 
00944   if (layerGroup.id() < 0) {
00945     Msg::print(Msg::SevWarning, "Couldn't find layer group " + layerName 
00946               + " in .f3d file ");
00947     return nullPtr;
00948   }
00949 
00950   // Get the class name
00951   string className;
00952   if (!readAttribute(layerGroup.id(), "class_name", className)) {
00953     Msg::print(Msg::SevWarning, "Couldn't find class_name attrib in layer " + 
00954               layerName);
00955     return nullPtr;
00956   }
00957 
00958   // Construct the field and load the data
00959 
00960   typename Field<Data_T>::Ptr field;
00961   field = readField<Data_T>(className, layerGroup.id(), m_filename, layerPath);
00962 
00963   if (!field) {
00964 #if 0 // This isn't really an error
00965     Msg::print(Msg::SevWarning, "Couldn't read the layer data of layer: " 
00966               + layerName);
00967 #endif
00968     return nullPtr;
00969   }
00970 
00971   // read the metadata 
00972   string metadataPath = layerPath + "/metadata";
00973   H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
00974   if (metadataGroup.id() > 0) {    
00975     readMetadata(metadataGroup.id(), field);
00976   }
00977 
00978   // Set the name of the field so it's possible to re-create the file
00979   field->name = removeUniqueId(intPartitionName);
00980   field->attribute = layerName;
00981   field->setMapping(part->mapping);
00982 
00983   return field;
00984 }
00985 
00986 //----------------------------------------------------------------------------//
00987 
00988 template <template <typename T> class Field_T, class Data_T>
00989 typename Field_T<Data_T>::Vec
00990 Field3DInputFile::readScalarLayersAs(const std::string &layerName) const
00991 {
00992   typedef typename Field<Data_T>::Vec FieldList;
00993   typedef typename Field_T<Data_T>::Vec TypedFieldList;
00994 
00995   // First, read the layers as-is
00996   FieldList originals;
00997   originals = readScalarLayers<Data_T>(layerName);
00998   
00999   // Loop over fields, converting if needed
01000   TypedFieldList output;
01001   typename FieldList::iterator i = originals.begin();
01002   for (; i != originals.end(); ++i) {
01003     typename Field_T<Data_T>::Ptr targetField;
01004     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01005     if (targetField) {
01006       output.push_back(targetField);
01007     } else {
01008       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01009       newTarget->name = (*i)->name;
01010       newTarget->attribute = (*i)->attribute;
01011       newTarget->copyMetadata(*i);
01012       newTarget->copyFrom(*i);
01013       output.push_back(newTarget);
01014     }
01015   }
01016 
01017   return output;
01018 }
01019 
01020 //----------------------------------------------------------------------------//
01021 
01022 template <template <typename T> class Field_T, class Data_T>
01023 typename Field_T<Data_T>::Vec
01024 Field3DInputFile::readScalarLayersAs(const std::string &partitionName, 
01025                                      const std::string &layerName) const
01026 {
01027   typedef typename Field<Data_T>::Vec FieldList;
01028   typedef typename Field_T<Data_T>::Vec TypedFieldList;
01029 
01030   // First, read the layers as-is
01031   FieldList originals;
01032   originals = readScalarLayers<Data_T>(partitionName, layerName);
01033   
01034   // Loop over fields, converting if needed
01035   TypedFieldList output;
01036   typename FieldList::iterator i = originals.begin();
01037   for (; i != originals.end(); ++i) {
01038     typename Field_T<Data_T>::Ptr targetField;
01039     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01040     if (targetField) {
01041       output.push_back(targetField);
01042     } else {
01043       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01044       newTarget->name = (*i)->name;
01045       newTarget->attribute = (*i)->attribute;
01046       newTarget->copyMetadata(**i);
01047       newTarget->copyFrom(*i);
01048       output.push_back(newTarget);
01049     }
01050   }
01051 
01052   return output;
01053 }
01054 
01055 //----------------------------------------------------------------------------//
01056 
01057 template <template <typename T> class Field_T, class Data_T>
01058 typename Field_T<Data_T>::Vec
01059 Field3DInputFile::readVectorLayersAs(const std::string &layerName) const
01060 {
01061   typedef typename Field<Data_T>::Vec FieldList;
01062   typedef typename Field_T<Data_T>::Vec TypedFieldList;
01063 
01064   // First, read the layers as-is
01065   FieldList originals;
01066   originals = readVectorLayers<Data_T>(layerName);
01067   
01068   // Loop over fields, converting if needed
01069   TypedFieldList output;
01070   typename FieldList::iterator i = originals.begin();
01071   for (; i != originals.end(); ++i) {
01072     typename Field_T<Data_T>::Ptr targetField;
01073     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01074     if (targetField) {
01075       output.push_back(targetField);
01076     } else {
01077       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01078       newTarget->name = (*i)->name;
01079       newTarget->attribute = (*i)->attribute;
01080       newTarget->copyMetadata(*i);
01081       newTarget->copyFrom(*i);
01082       output.push_back(newTarget);
01083     }
01084   }
01085 
01086   return output;
01087 }
01088 
01089 //----------------------------------------------------------------------------//
01090 
01091 template <template <typename T> class Field_T, class Data_T>
01092 typename Field_T<Data_T>::Vec
01093 Field3DInputFile::readVectorLayersAs(const std::string &partitionName, 
01094                                      const std::string &layerName) const
01095 {
01096   typedef typename Field<Data_T>::Vec FieldList;
01097   typedef typename Field_T<Data_T>::Vec TypedFieldList;
01098 
01099   // First, read the layers as-is
01100   FieldList originals;
01101   originals = readVectorLayers<Data_T>(partitionName, layerName);
01102   
01103   // Loop over fields, converting if needed
01104   TypedFieldList output;
01105   typename FieldList::iterator i = originals.begin();
01106   for (; i != originals.end(); ++i) {
01107     typename Field_T<Data_T>::Ptr targetField;
01108     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01109     if (targetField) {
01110       output.push_back(targetField);
01111     } else {
01112       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01113       newTarget->name = (*i)->name;
01114       newTarget->attribute = (*i)->attribute;
01115       newTarget->copyMetadata(*i);
01116       newTarget->copyFrom(*i);
01117       output.push_back(newTarget);
01118     }
01119   }
01120 
01121   return output;
01122 }
01123 
01124 //----------------------------------------------------------------------------//
01125 
01126 template <class Data_T>
01127 typename EmptyField<Data_T>::Vec
01128 Field3DInputFile::readProxyLayer(const std::string &partitionName, 
01129                                  const std::string &layerName,
01130                                  bool isVectorLayer) const
01131 {
01132   using namespace boost;
01133   using namespace std;
01134   using namespace Hdf5Util;
01135 
01136   // Instantiate a null pointer for easier code reading
01137   typename EmptyField<Data_T>::Vec emptyList, output;
01138 
01139   if ((layerName.length() == 0) || (partitionName.length() == 0))
01140     return emptyList;
01141 
01142   std::vector<std::string> parts, layers;
01143   getIntPartitionNames(parts);
01144  
01145   bool foundPartition = false;
01146 
01147   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01148     if (removeUniqueId(*p) == partitionName) {
01149       foundPartition = true;
01150       if (isVectorLayer) {
01151         getIntVectorLayerNames(layers, *p);
01152       } else {
01153         getIntScalarLayerNames(layers, *p);
01154       }
01155       for (vector<string>::iterator l = layers.begin(); 
01156            l != layers.end(); ++l) {
01157         if (*l == layerName) {
01158           // Find the partition
01159           File::Partition::Ptr part = partition(*p);
01160           if (!part) {
01161             Msg::print(Msg::SevWarning, "Couldn't find partition: " + *p);
01162             return emptyList;
01163           }
01164           // Find the layer
01165           const File::Layer *layer;
01166           if (isVectorLayer)
01167             layer = part->vectorLayer(layerName);
01168           else
01169             layer = part->scalarLayer(layerName);
01170           if (!layer) {
01171             Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
01172             return emptyList;
01173           }
01174           // Open the layer group
01175           string layerPath = layer->parent + "/" + layer->name;
01176           H5ScopedGopen layerGroup(m_file, layerPath.c_str());
01177           if (layerGroup.id() < 0) {
01178             Msg::print(Msg::SevWarning, "Couldn't find layer group " 
01179                       + layerName + " in .f3d file ");
01180             return emptyList;
01181           }
01182           // Read the extents and data window
01183           Box3i extents, dataW;
01184           if (!readAttribute(layerGroup, "extents", 6, extents.min.x)) {
01185             return emptyList;
01186           }
01187           if (!readAttribute(layerGroup, "data_window", 6, dataW.min.x)) {
01188             return emptyList;
01189           } 
01190           // Construct the field and load the data
01191           typename EmptyField<Data_T>::Ptr field(new EmptyField<Data_T>);
01192           field->setSize(extents, dataW);
01193 
01194           // read the metadata 
01195           string metadataPath = layerPath + "/metadata";
01196           H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
01197           if (metadataGroup.id() > 0) {    
01198             readMetadata(metadataGroup.id(), field);
01199           }
01200 
01201           // ... Set the name of the field so it's possible to 
01202           // ... re-create the file
01203           field->name = partitionName;
01204           field->attribute = layerName;
01205           field->setMapping(part->mapping);
01206           // Add field to output
01207           output.push_back(field);
01208         }
01209       }
01210     }
01211   }
01212 
01213   if (!foundPartition) {
01214     Msg::print(Msg::SevWarning, "Couldn't find partition: " + partitionName);
01215     return emptyList;    
01216   }
01217   
01218   return output;
01219 }
01220 
01221 //----------------------------------------------------------------------------//
01222 
01223 template <class Data_T>
01224 typename EmptyField<Data_T>::Vec
01225 Field3DInputFile::readProxyScalarLayers(const std::string &name) const
01226 {
01227   using namespace std;
01228 
01229   typedef typename EmptyField<Data_T>::Ptr FieldPtr;
01230   typedef std::vector<FieldPtr> FieldList;
01231   
01232   FieldList ret;
01233   
01234   std::vector<std::string> parts;
01235   getPartitionNames(parts);
01236   
01237   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01238   std::vector<std::string> layers;
01239     getScalarLayerNames(layers, *p);
01240     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
01241       // Only read if it matches the name
01242       if ((name.length() == 0) || (*l == name)) {
01243         FieldList f = readProxyLayer<Data_T>(*p, *l, false);
01244         for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
01245           if (*i) {
01246             ret.push_back(*i);
01247           }
01248         }
01249       }
01250     }
01251   }
01252   
01253   return ret;
01254 }
01255 
01256 //----------------------------------------------------------------------------//
01257 
01258 template <class Data_T>
01259 typename EmptyField<Data_T>::Vec
01260 Field3DInputFile::readProxyVectorLayers(const std::string &name) const
01261 {
01262   using namespace std;
01263   
01264   typedef typename EmptyField<Data_T>::Ptr FieldPtr;
01265   typedef std::vector<FieldPtr> FieldList;
01266   
01267   FieldList ret;
01268   
01269   std::vector<std::string> parts;
01270   getPartitionNames(parts);
01271   
01272   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01273   std::vector<std::string> layers;
01274     getVectorLayerNames(layers, *p);
01275     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
01276       // Only read if it matches the name
01277       if ((name.length() == 0) || (*l == name)) {
01278         FieldList f = readProxyLayer<Data_T>(*p, *l, true);
01279         for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
01280           if (*i) {
01281             ret.push_back(*i);
01282           }
01283         }
01284       }
01285     }
01286   }
01287   
01288   return ret;  
01289 }
01290 
01291 //----------------------------------------------------------------------------//
01292 
01293 template <class Data_T>
01294 typename Field<Data_T>::Ptr
01295 Field3DInputFile::readScalarLayer(const std::string &intPartitionName,
01296                                   const std::string &layerName) const
01297 {
01298   return readLayer<Data_T>(intPartitionName, layerName, false);
01299 }
01300 
01301 //----------------------------------------------------------------------------//
01302 
01303 template <class Data_T>
01304 typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
01305 Field3DInputFile::readVectorLayer(const std::string &intPartitionName,
01306                                   const std::string &layerName) const
01307 {
01308   return readLayer<FIELD3D_VEC3_T<Data_T> >(intPartitionName, layerName, true);
01309 }
01310 
01311 //----------------------------------------------------------------------------//
01312 // Field3DOutputFile
01313 //----------------------------------------------------------------------------//
01314 
01315 template <class Data_T>
01316 File::Partition::Ptr
01317 Field3DOutputFile::createNewPartition(const std::string &partitionName,
01318                                       const std::string &layerName,
01319                                       typename Field<Data_T>::Ptr field)
01320 {
01321   using namespace Hdf5Util;
01322   using namespace Exc;
01323   
01324   File::Partition::Ptr newPart(new File::Partition);
01325 
01326   newPart->name = partitionName;
01327 
01328   H5ScopedGcreate partGroup(m_file, newPart->name.c_str());
01329   if (partGroup.id() < 0) {
01330     Msg::print(Msg::SevWarning, 
01331                "Error creating partition: " + newPart->name);
01332     return File::Partition::Ptr();
01333   } 
01334     
01335   m_partitions.push_back(newPart);
01336 
01337   // Pick up new pointer
01338   File::Partition::Ptr  part = partition(partitionName);
01339   
01340   // Add mapping group to the partition
01343   try {
01344     if (!writeMapping(partGroup.id(), field->mapping())) {
01345       Msg::print(Msg::SevWarning, 
01346                  "writeMapping returned false for an unknown reason ");
01347       return File::Partition::Ptr();
01348     }
01349   }
01350   catch (WriteMappingException &e) {
01351     Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: " 
01352                + partitionName);
01353     return File::Partition::Ptr();
01354   }
01355   catch (...) {
01356     Msg::print(Msg::SevWarning, 
01357                "Unknown error when writing mapping for partition: " 
01358                + partitionName);
01359     return File::Partition::Ptr();    
01360   }
01361 
01362   // Set the mapping of the partition. Since all layers share their 
01363   // partition's mapping, we can just pick this first one. All subsequent
01364   // additions to the same partition are checked to have the same mapping
01365   part->mapping = field->mapping();
01366 
01367   // Tag node as partition
01368   // Create a version attribute on the root node
01369   if (!writeAttribute(partGroup.id(), "is_field3d_partition", "1")) {
01370     Msg::print(Msg::SevWarning, "Adding partition string.");
01371     return File::Partition::Ptr();    
01372   }
01373 
01374   return part;
01375 }
01376 
01377 //----------------------------------------------------------------------------//
01378 
01379 template <class Data_T>
01380 bool 
01381 Field3DOutputFile::writeLayer(const std::string &userPartitionName, 
01382                               const std::string &layerName, 
01383                               bool isVectorLayer, 
01384                               typename Field<Data_T>::Ptr field)
01385 {
01386   using namespace std;
01387   using namespace Exc;
01388   using namespace Hdf5Util;
01389 
01390   if (!field) {
01391     Msg::print(Msg::SevWarning, 
01392                "Called writeLayer with null pointer. Ignoring...");
01393     return false;
01394   }
01395 
01396   if (m_file < 0) {
01397     Msg::print(Msg::SevWarning, 
01398                "Attempting to write layer without opening file first. ");
01399     return false;
01400   }
01401 
01402   string partitionName = intPartitionName(userPartitionName, layerName, field);
01403 
01404   // See if the partition already exists or if we need to make it ---
01405 
01406   File::Partition::Ptr part = partition(partitionName);
01407 
01408   if (!part) {
01409     part = createNewPartition<Data_T>(partitionName,layerName,field);
01410     if (!part)
01411       return false;
01412   } else {
01413 
01414     if (!field->mapping()) {
01415       Msg::print(Msg::SevWarning, 
01416                  "Couldn't add layer \"" + layerName + "\" to partition \""
01417                  + partitionName + "\" because the layer's mapping is null.");
01418       return false;    
01419     }
01420     
01421     // If the partition already existed, we need to make sure that the layer
01422     // doesn't also exist
01423     if (!isVectorLayer) {
01424       if (part->scalarLayer(layerName)) {
01425         //need to create a new partition and then add the layer to that
01426         std::string newPartitionName = incrementPartitionName(partitionName);
01427         part = createNewPartition<Data_T>(newPartitionName,layerName,field);
01428         if (!part)
01429           return false;
01430       }
01431     } else {
01432       if (part->vectorLayer(layerName)) {
01433         //need to create a new partition and then add the layer to that
01434         std::string newPartitionName = incrementPartitionName(partitionName);
01435         part = createNewPartition<Data_T>(newPartitionName,layerName,field);
01436         if (!part)
01437           return false;
01438       }
01439     }
01440   }
01441 
01442   if (!part->mapping) {
01443     Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: " 
01444               + partitionName);
01445     return false;    
01446   }
01447 
01448   // Check that the mapping matches what's already in the Partition
01449   if (!field->mapping()->isIdentical(part->mapping)) {
01450     Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName 
01451               + "\" to partition \"" + partitionName 
01452               + "\" because mapping doesn't match");
01453     return false;
01454   }
01455 
01456   // Open the partition
01457   H5ScopedGopen partGroup(m_file, part->name.c_str(), H5P_DEFAULT);
01458 
01459   // Build a Layer object ---
01460 
01461   File::Layer layer;
01462   layer.name = layerName;
01463   layer.parent = partitionName;
01464 
01465   // Add Layer to file ---
01466 
01467   H5ScopedGcreate layerGroup(partGroup.id(), layerName.c_str(),
01468                              H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
01469 
01470   if (layerGroup.id() < 0) {
01471     Msg::print(Msg::SevWarning, "Error creating layer: " + layerName);
01472     return false;
01473   }
01474 
01475   // Tag as layer
01476   if (!writeAttribute(layerGroup.id(), "class_type", "field3d_layer")) {
01477     Msg::print(Msg::SevWarning, "Error adding layer string.");
01478     return false;
01479   }    
01480 
01481   // Add metadata group and write it out  
01482   H5ScopedGcreate metadataGroup(layerGroup.id(), "metadata");
01483   if (metadataGroup.id() < 0) {
01484     Msg::print(Msg::SevWarning, "Error creating group: metadata");
01485     return false;
01486   }  
01487   if (!writeMetadata(metadataGroup.id(), field)) {
01488     Msg::print(Msg::SevWarning, "Error writing metadata.");
01489     return false;
01490   }    
01491 
01492   if (!writeField(layerGroup.id(), field)) {
01493     Msg::print(Msg::SevWarning, "Error writing layer: " + layer.name);
01494     return false;
01495   }
01496   
01497   // Add layer to partition ---
01498 
01499   if (isVectorLayer)
01500     part->addVectorLayer(layer);
01501   else
01502     part->addScalarLayer(layer);
01503 
01504   return true;  
01505 }
01506 
01507 //----------------------------------------------------------------------------//
01508 
01509 template <class Data_T>
01510 bool 
01511 Field3DOutputFile::writeScalarLayer(const std::string &partitionName, 
01512                                     const std::string &layerName, 
01513                                     typename Field<Data_T>::Ptr field)
01514 {
01515   return writeLayer<Data_T>(partitionName, layerName, false, field);
01516 }
01517 
01518 //----------------------------------------------------------------------------//
01519 
01520 template <class Data_T>
01521 bool 
01522 Field3DOutputFile::writeScalarLayer(typename Field<Data_T>::Ptr layer)
01523 {
01524   if (layer->name.size() == 0) {
01525     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
01526                "Tried to write a scalar layer with no name");
01527     return false;
01528   }
01529   if (layer->attribute.size() == 0) {
01530     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
01531                "Tried to write a scalar layer with no attribute name");
01532     return false;
01533   }
01534   return writeScalarLayer<Data_T>(layer->name, layer->attribute, layer);
01535 }
01536 
01537 //----------------------------------------------------------------------------//
01538 
01539 template <class Data_T>
01540 bool 
01541 Field3DOutputFile::
01542 writeVectorLayer(const std::string &partitionName, 
01543                  const std::string &layerName, 
01544                  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr field)
01545 {
01546   return writeLayer<FIELD3D_VEC3_T<Data_T> >(partitionName, layerName, 
01547                                              true, field);
01548 }
01549 
01550 //----------------------------------------------------------------------------//
01551 
01552 template <class Data_T>
01553 bool 
01554 Field3DOutputFile::writeVectorLayer
01555   (typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
01556 {
01557   if (layer->name.size() == 0) {
01558     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
01559                "Tried to write a vector layer with no name");
01560     return false;
01561   }
01562   if (layer->attribute.size() == 0) {
01563     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
01564                "Tried to write a vector layer with no attribute name");
01565     return false;
01566   }
01567   return writeVectorLayer<Data_T>(layer->name, layer->attribute, layer);
01568 }
01569 
01570 //----------------------------------------------------------------------------//
01571 // Template Function Implementations
01572 //----------------------------------------------------------------------------//
01573 
01574 template <class Data_T>
01575 typename Field<Data_T>::Ptr 
01576 readField(const std::string &className, hid_t layerGroup,
01577           const std::string &filename, const std::string &layerPath)
01578 {
01579 
01580   ClassFactory &factory = ClassFactory::singleton();
01581   
01582   typedef typename Field<Data_T>::Ptr FieldPtr;
01583 
01584   FieldIO::Ptr io = factory.createFieldIO(className);
01585   assert(io != 0);
01586   if (!io) {
01587     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01588                className);
01589     return FieldPtr();
01590   }
01591 
01592   DataTypeEnum typeEnum = DataTypeTraits<Data_T>::typeEnum();
01593   FieldBase::Ptr field = io->read(layerGroup, filename, layerPath, typeEnum);
01594 
01595   if (!field) {
01596     // We don't need to print a message, because it could just be that
01597     // a layer of the specified data type and name couldn't be found
01598     return FieldPtr();
01599   }
01600   
01601   FieldPtr result = field_dynamic_cast<Field<Data_T> >(field);
01602 
01603   if (result)
01604     return result;
01605 
01606   return FieldPtr();
01607 }
01608 
01609 //----------------------------------------------------------------------------//
01610 
01611 FIELD3D_NAMESPACE_HEADER_CLOSE
01612 
01613 //----------------------------------------------------------------------------//
01614 
01615 #endif