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   // Ctors, dtor ---------------------------------------------------------------
00153 
00155   Partition() : RefBase() {}
00156 
00157   // Main methods --------------------------------------------------------------
00158 
00160   void addScalarLayer(const File::Layer &layer);
00162   void addVectorLayer(const File::Layer &layer);
00163 
00165   const File::Layer* scalarLayer(const std::string &name) const;
00167   const File::Layer* vectorLayer(const std::string &name) const;
00168   
00170   void getScalarLayerNames(std::vector<std::string> &names) const;
00172   void getVectorLayerNames(std::vector<std::string> &names) const;
00173 
00174   // Public data members -------------------------------------------------------
00175 
00177   std::string name;
00179   FieldMapping::Ptr mapping;
00180 
00181 private:
00182 
00183   // Private data members ------------------------------------------------------
00184 
00186   ScalarLayerList m_scalarLayers;
00188   VectorLayerList m_vectorLayers;
00189 
00190 };
00191 
00192 
00193 } // namespace File
00194 
00195 //----------------------------------------------------------------------------//
00196 // Field3DFileBase
00197 //----------------------------------------------------------------------------//
00198 
00206 //----------------------------------------------------------------------------//
00207 
00208 class Field3DFileBase
00209 {
00210 public:
00211 
00212   // Structs -------------------------------------------------------------------
00213 
00214   struct LayerInfo 
00215   {
00216     std::string name;
00217     std::string parentName;
00218     int components;  
00219     LayerInfo(std::string par, std::string nm, int cpt) 
00220       : name(nm), parentName(par), components(cpt) 
00221     { /* Empty */ }
00222   };
00223 
00224   // Typedefs ------------------------------------------------------------------
00225  
00226   typedef std::map<std::string, std::string> GroupMembershipMap;
00227 
00228   // Ctor, dtor ----------------------------------------------------------------
00229 
00232 
00233   Field3DFileBase();
00235   virtual ~Field3DFileBase() = 0;
00236 
00238 
00239   // Main methods --------------------------------------------------------------
00240 
00242   void clear();
00243 
00247   bool close();
00248 
00251 
00253   void getPartitionNames(std::vector<std::string> &names) const;
00255   void getScalarLayerNames(std::vector<std::string> &names, 
00256                            const std::string &partitionName) const;
00258   void getVectorLayerNames(std::vector<std::string> &names, 
00259                            const std::string &partitionName) const;
00260 
00263   File::Partition::Ptr getPartition(const std::string &partitionName) const
00264   { return partition(partitionName); }
00265 
00267 
00270 
00274   std::string intPartitionName(const std::string &partitionName,
00275                                const std::string &layerName,
00276                                FieldRes::Ptr field);
00277 
00280   std::string removeUniqueId(const std::string &partitionName) const;
00281 
00283   void addGroupMembership(const GroupMembershipMap &groupMembers);
00284 
00286 
00287   // Access to metadata --------------------------------------------------------  
00288 
00290   FieldMetadata<Field3DFileBase>& metadata()
00291   { return m_metadata; }
00292 
00294   const FieldMetadata<Field3DFileBase>& metadata() const
00295   { return m_metadata; }
00296  
00299   virtual void metadataHasChanged(const std::string &/* name */) 
00300   { /* Empty */ }
00301 
00302   // Debug ---------------------------------------------------------------------
00303 
00306 
00307   void printHierarchy() const;
00308 
00310 
00311 protected:
00312 
00313   // Internal typedefs ---------------------------------------------------------
00314 
00315   typedef std::vector<File::Partition::Ptr> PartitionList;
00316   typedef std::map<std::string, int> PartitionCountMap;
00317 
00318   // Convenience methods -------------------------------------------------------
00319 
00322 
00324   void closeInternal();
00327   File::Partition::Ptr partition(const std::string &partitionName);
00330   File::Partition::Ptr partition(const std::string &partitionName) const;
00331   
00333   void getIntPartitionNames(std::vector<std::string> &names) const;
00336   void getIntScalarLayerNames(std::vector<std::string> &names, 
00337                               const std::string &intPartitionName) const;
00340   void getIntVectorLayerNames(std::vector<std::string> &names, 
00341                               const std::string &intPartitionName) const;
00342   
00344   int numIntPartitions(const std::string &partitionName) const;
00345 
00348   std::string makeIntPartitionName(const std::string &partitionsName,
00349                                    int i) const;
00350 
00352 
00353   // Data members --------------------------------------------------------------
00354 
00356   std::vector<LayerInfo> m_layerInfo;
00357 
00359   hid_t m_file;
00361   PartitionList m_partitions;
00363   std::vector<std::string> m_partitionNames;
00364 
00367   PartitionCountMap m_partitionCount;
00368 
00372   GroupMembershipMap m_groupMembership;
00373 
00375   FieldMetadata<Field3DFileBase> m_metadata;
00376 
00377 private:
00378 
00379   // Private member functions --------------------------------------------------
00380 
00381   Field3DFileBase(const Field3DFileBase&);
00382   void operator =(const Field3DFileBase&); 
00383 
00384 
00385 };
00386 
00387 //----------------------------------------------------------------------------//
00388 // Field3DInputFile
00389 //----------------------------------------------------------------------------//
00390 
00404 //----------------------------------------------------------------------------//
00405 
00406 class Field3DInputFile : public Field3DFileBase 
00407 {
00408 public:
00409 
00410   // Ctors, dtor ---------------------------------------------------------------
00411 
00414 
00415   Field3DInputFile();
00416   virtual ~Field3DInputFile();
00417 
00419 
00420   // Main interface ------------------------------------------------------------
00421 
00424 
00429   template <class Data_T>
00430   typename Field<Data_T>::Vec
00431   readScalarLayers(const std::string &layerName = std::string("")) const;
00432 
00434   template <class Data_T>
00435   typename Field<Data_T>::Vec
00436   readScalarLayers(const std::string &partitionName, 
00437                    const std::string &layerName) const;
00438 
00443   template <class Data_T>
00444   typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00445   readVectorLayers(const std::string &layerName = std::string("")) const;
00446 
00448   template <class Data_T>
00449   typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00450   readVectorLayers(const std::string &partitionName, 
00451                    const std::string &layerName) const;
00452 
00455   template <template <typename T> class Field_T, class Data_T>
00456   typename Field_T<Data_T>::Vec
00457   readScalarLayersAs(const std::string &layerName = std::string("")) const;
00458 
00461   template <template <typename T> class Field_T, class Data_T>
00462   typename Field_T<Data_T>::Vec
00463   readScalarLayersAs(const std::string &partitionName, 
00464                      const std::string &layerName) const;
00465 
00468   template <template <typename T> class Field_T, class Data_T>
00469   typename Field_T<Data_T>::Vec
00470   readVectorLayersAs(const std::string &layerName = std::string("")) const;
00471 
00474   template <template <typename T> class Field_T, class Data_T>
00475   typename Field_T<Data_T>::Vec
00476   readVectorLayersAs(const std::string &partitionName, 
00477                      const std::string &layerName) const;
00478 
00480 
00483 
00487   template <class Data_T>
00488   typename EmptyField<Data_T>::Vec
00489   readProxyLayer(const std::string &partitionName, 
00490                  const std::string &layerName, 
00491                  bool isVectorLayer) const;
00492 
00496   template <class Data_T>
00497   typename EmptyField<Data_T>::Vec
00498   readProxyScalarLayers(const std::string &name = std::string("")) const;
00499 
00503   template <class Data_T>
00504   typename EmptyField<Data_T>::Vec
00505   readProxyVectorLayers(const std::string &name = std::string("")) const;
00506 
00508 
00509   // File IO ---
00510 
00513   bool open(const std::string &filename);
00514 
00515   // Callback convenience methods ----------------------------------------------
00516 
00519 
00521   herr_t parsePartition(hid_t loc_id, const std::string partitionName);
00522 
00524   herr_t parseLayer(hid_t loc_id, const std::string &partitionName,
00525                     const std::string &layerName);
00526 
00528 
00529   // Convenience methods -------------------------------------------------------
00530 
00532   bool readGroupMembership(GroupMembershipMap &gpMembershipMap);
00533 
00534 
00535 private:
00536 
00537   // Convenience methods -------------------------------------------------------
00538 
00541   template <class Data_T>
00542   typename Field<Data_T>::Ptr
00543   readScalarLayer(const std::string &intPartitionName, 
00544                   const std::string &layerName) const;
00545 
00548   template <class Data_T>
00549   typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
00550   readVectorLayer(const std::string &intPartitionName, 
00551                   const std::string &layerName) const;
00552   
00555   template <class Data_T>
00556   typename Field<Data_T>::Ptr 
00557   readLayer(const std::string &intPartitionName, 
00558             const std::string &layerName,
00559             bool isVectorLayer) const;
00560 
00562   bool readPartitionAndLayerInfo();
00563 
00565   bool readMetadata(hid_t metadata_id, FieldBase::Ptr field) const;
00566 
00568   bool readMetadata(hid_t metadata_id);
00569 
00570   // Data members --------------------------------------------------------------
00571 
00573   std::string m_filename;  
00574 
00575 };
00576 
00577 //----------------------------------------------------------------------------//
00578 // Field3DOutputFile
00579 //----------------------------------------------------------------------------//
00580 
00594 //----------------------------------------------------------------------------//
00595 
00596 class Field3DOutputFile : public Field3DFileBase 
00597 {
00598 public:
00599 
00600   // Enums ---------------------------------------------------------------------
00601 
00602   enum CreateMode {
00603     OverwriteMode,
00604     FailOnExisting
00605   };
00606 
00607   // Ctors, dtor ---------------------------------------------------------------
00608 
00611 
00612   Field3DOutputFile();
00613   virtual ~Field3DOutputFile();
00614 
00616 
00617   // Main interface ------------------------------------------------------------
00618 
00621 
00623   template <class Data_T>
00624   bool writeScalarLayer(const std::string &layerName, 
00625                         typename Field<Data_T>::Ptr layer)
00626   { return writeScalarLayer<Data_T>(layerName, std::string("default"), layer); }
00627 
00629   template <class Data_T>
00630   bool writeVectorLayer(const std::string &layerName, 
00631                         typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
00632   { return writeVectorLayer<Data_T>(layerName, std::string("default"), layer); }
00633 
00636   template <class Data_T>
00637   bool writeScalarLayer(const std::string &partitionName, 
00638                         const std::string &layerName, 
00639                         typename Field<Data_T>::Ptr layer);
00640 
00643   template <class Data_T>
00644   bool writeScalarLayer(typename Field<Data_T>::Ptr layer);
00645 
00648   template <class Data_T>
00649   bool writeVectorLayer(const std::string &partitionName, 
00650                         const std::string &layerName, 
00651                         typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
00652 
00655   template <class Data_T>
00656   bool writeVectorLayer(typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer);
00657 
00659 
00661   bool create(const std::string &filename, CreateMode cm = OverwriteMode);
00662 
00664   bool writeGlobalMetadata();
00665 
00668   bool writeGroupMembership();
00669 
00670  private:
00671   
00672   // Convenience methods -------------------------------------------------------
00673 
00677   bool writeMapping(hid_t partitionLocation, FieldMapping::Ptr mapping);
00678   
00680   template <class Data_T>
00681   bool writeLayer(const std::string &partitionName, 
00682                   const std::string &layerName, 
00683                   bool isVectorLayer, 
00684                   typename Field<Data_T>::Ptr layer);
00685 
00687   bool writeMetadata(hid_t metadataGroup, FieldBase::Ptr layer);
00688 
00690   bool writeMetadata(hid_t metadataGroup);
00691 
00692 };
00693 
00694 //----------------------------------------------------------------------------//
00695 // Field3DInputFile-related callback functions
00696 //----------------------------------------------------------------------------//
00697 
00699 namespace InputFile {
00700 
00704 struct ParseLayersInfo
00705 {
00706   Field3DInputFile *file;
00707   std::string partitionName;
00708 };
00709 
00713 herr_t parsePartitions(hid_t loc_id, const char *partitionName, 
00714                        const H5L_info_t *linfo, void *opdata);
00715 
00719 herr_t parseLayers(hid_t loc_id, const char *partitionName, 
00720                    const H5L_info_t *linfo, void *opdata);
00721 
00722 } // namespace InputFile
00723 
00724 //----------------------------------------------------------------------------//
00725 // Field3DInputFile
00726 //----------------------------------------------------------------------------//
00727 
00728 template <class Data_T>
00729 typename Field<Data_T>::Vec
00730 Field3DInputFile::readScalarLayers(const std::string &name) const
00731 {
00732   using namespace std;
00733   
00734   typedef typename Field<Data_T>::Ptr FieldPtr;
00735   typedef typename Field<Data_T>::Vec FieldList;
00736 
00737   FieldList ret;
00738   std::vector<std::string> parts;
00739   getIntPartitionNames(parts);
00740 
00741   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00742     std::vector<std::string> layers;
00743     getIntScalarLayerNames(layers, *p);
00744     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
00745       // Only read if it matches the name
00746       if ((name.length() == 0) || (*l == name)) {
00747         FieldPtr mf = readScalarLayer<Data_T>(*p, *l);
00748         if (mf) {
00749           ret.push_back(mf);
00750         }
00751       }
00752     }
00753   }
00754   
00755   return ret;
00756 }
00757 
00758 //----------------------------------------------------------------------------//
00759 
00760 template <class Data_T>
00761 typename Field<Data_T>::Vec
00762 Field3DInputFile::readScalarLayers(const std::string &partitionName, 
00763                                    const std::string &layerName) const
00764 {
00765   using namespace std;
00766   
00767   typedef typename Field<Data_T>::Ptr FieldPtr;
00768   typedef typename Field<Data_T>::Vec FieldList;
00769 
00770   FieldList ret;
00771 
00772   if ((layerName.length() == 0) || (partitionName.length() == 0))
00773     return ret;
00774   
00775   std::vector<std::string> parts;
00776   getIntPartitionNames(parts);
00777  
00778   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00779     std::vector<std::string> layers;
00780     getIntScalarLayerNames(layers, *p);
00781     if (removeUniqueId(*p) == partitionName) {
00782       for (vector<string>::iterator l = layers.begin(); 
00783            l != layers.end(); ++l) {
00784         // Only read if it matches the name
00785         if (*l == layerName) {
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<FIELD3D_VEC3_T<Data_T> >::Vec
00801 Field3DInputFile::readVectorLayers(const std::string &name) const
00802 {
00803   using namespace std;
00804   
00805   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
00806   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
00807   
00808   FieldList ret;
00809   
00810   std::vector<std::string> parts;
00811   getIntPartitionNames(parts);
00812   
00813   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00814     std::vector<std::string> layers;
00815     getIntVectorLayerNames(layers, *p);
00816     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
00817       // Only read if it matches the name
00818       if ((name.length() == 0) || (*l == name)) {
00819         FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
00820         if (mf)
00821           ret.push_back(mf);
00822       }
00823     }
00824   }
00825   
00826   return ret;
00827 }
00828 
00829 //----------------------------------------------------------------------------//
00830 
00831 template <class Data_T>
00832 typename Field<FIELD3D_VEC3_T<Data_T> >::Vec
00833 Field3DInputFile::readVectorLayers(const std::string &partitionName, 
00834                                    const std::string &layerName) const
00835 {
00836   using namespace std;
00837   
00838   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr FieldPtr;
00839   typedef typename Field<FIELD3D_VEC3_T<Data_T> >::Vec FieldList;
00840   
00841   FieldList ret;
00842 
00843   if ((layerName.length() == 0) || (partitionName.length() == 0))
00844     return ret;
00845   
00846   std::vector<std::string> parts;
00847   getIntPartitionNames(parts);
00848   
00849   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
00850     std::vector<std::string> layers;
00851     getIntVectorLayerNames(layers, *p);
00852     if (removeUniqueId(*p) == partitionName) {
00853       for (vector<string>::iterator l = layers.begin(); 
00854            l != layers.end(); ++l) {
00855         // Only read if it matches the name
00856         if (*l == layerName) {
00857           FieldPtr mf = readVectorLayer<Data_T>(*p, *l);
00858           if (mf)
00859             ret.push_back(mf);
00860         }
00861       }
00862     }
00863   }
00864   
00865   return ret;
00866 }
00867 
00868 //----------------------------------------------------------------------------//
00869 
00870 template <class Data_T>
00871 typename Field<Data_T>::Ptr
00872 Field3DInputFile::readLayer(const std::string &intPartitionName,
00873                             const std::string &layerName,
00874                             bool isVectorLayer) const
00875 {
00876   using namespace boost;
00877   using namespace std;
00878   using namespace Hdf5Util;
00879 
00880   // Instantiate a null pointer for easier code reading
00881   typename Field<Data_T>::Ptr nullPtr;
00882 
00883   // Find the partition
00884   File::Partition::Ptr part = partition(intPartitionName);
00885   if (!part) {
00886     Msg::print(Msg::SevWarning, "Couldn't find partition: " + intPartitionName);
00887     return nullPtr;
00888   }
00889 
00890   // Find the layer in the partition
00891   const File::Layer *l;
00892   if (isVectorLayer)
00893     l = part->vectorLayer(layerName);
00894   else
00895     l = part->scalarLayer(layerName);
00896   if (!l) {
00897     Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName );
00898     return nullPtr;
00899   }
00900 
00901   // Open the layer group
00902   string layerPath = l->parent + "/" + l->name;
00903   H5ScopedGopen layerGroup(m_file, layerPath.c_str());
00904 
00905   if (layerGroup.id() < 0) {
00906     Msg::print(Msg::SevWarning, "Couldn't find layer group " + layerName 
00907               + " in .f3d file ");
00908     return nullPtr;
00909   }
00910 
00911   // Get the class name
00912   string className;
00913   if (!readAttribute(layerGroup.id(), "class_name", className)) {
00914     Msg::print(Msg::SevWarning, "Couldn't find class_name attrib in layer " + 
00915               layerName);
00916     return nullPtr;
00917   }
00918   
00919 
00920   // Construct the field and load the data
00921  
00922   typename Field<Data_T>::Ptr field;
00923   field = readField<Data_T>(className, layerGroup.id(), m_filename, layerPath);
00924 
00925   if (!field) {
00926 #if 0 // This isn't really an error
00927     Msg::print(Msg::SevWarning, "Couldn't read the layer data of layer: " 
00928               + layerName);
00929 #endif
00930     return nullPtr;
00931   }
00932 
00933   // read the metadata 
00934   string metadataPath = layerPath + "/metadata";
00935   H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
00936   if (metadataGroup.id() > 0) {    
00937     readMetadata(metadataGroup.id(), field);
00938   }
00939 
00940   // Set the name of the field so it's possible to re-create the file
00941   field->name = removeUniqueId(intPartitionName);
00942   field->attribute = layerName;
00943   field->setMapping(part->mapping);
00944   
00945   return field;
00946 }
00947 
00948 //----------------------------------------------------------------------------//
00949 
00950 template <template <typename T> class Field_T, class Data_T>
00951 typename Field_T<Data_T>::Vec
00952 Field3DInputFile::readScalarLayersAs(const std::string &layerName) const
00953 {
00954   typedef typename Field<Data_T>::Vec FieldList;
00955   typedef typename Field_T<Data_T>::Vec TypedFieldList;
00956 
00957   // First, read the layers as-is
00958   FieldList originals;
00959   originals = readScalarLayers<Data_T>(layerName);
00960   
00961   // Loop over fields, converting if needed
00962   TypedFieldList output;
00963   typename FieldList::iterator i = originals.begin();
00964   for (; i != originals.end(); ++i) {
00965     typename Field_T<Data_T>::Ptr targetField;
00966     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
00967     if (targetField) {
00968       output.push_back(targetField);
00969     } else {
00970       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
00971       newTarget->name = (*i)->name;
00972       newTarget->attribute = (*i)->attribute;
00973       newTarget->copyMetadata(*i);
00974       newTarget->copyFrom(*i);
00975       output.push_back(newTarget);
00976     }
00977   }
00978 
00979   return output;
00980 }
00981 
00982 //----------------------------------------------------------------------------//
00983 
00984 template <template <typename T> class Field_T, class Data_T>
00985 typename Field_T<Data_T>::Vec
00986 Field3DInputFile::readScalarLayersAs(const std::string &partitionName, 
00987                                      const std::string &layerName) const
00988 {
00989   typedef typename Field<Data_T>::Vec FieldList;
00990   typedef typename Field_T<Data_T>::Vec TypedFieldList;
00991 
00992   // First, read the layers as-is
00993   FieldList originals;
00994   originals = readScalarLayers<Data_T>(partitionName, layerName);
00995   
00996   // Loop over fields, converting if needed
00997   TypedFieldList output;
00998   typename FieldList::iterator i = originals.begin();
00999   for (; i != originals.end(); ++i) {
01000     typename Field_T<Data_T>::Ptr targetField;
01001     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01002     if (targetField) {
01003       output.push_back(targetField);
01004     } else {
01005       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01006       newTarget->name = (*i)->name;
01007       newTarget->attribute = (*i)->attribute;
01008       newTarget->copyMetadata(**i);
01009       newTarget->copyFrom(*i);
01010       output.push_back(newTarget);
01011     }
01012   }
01013 
01014   return output;
01015 }
01016 
01017 //----------------------------------------------------------------------------//
01018 
01019 template <template <typename T> class Field_T, class Data_T>
01020 typename Field_T<Data_T>::Vec
01021 Field3DInputFile::readVectorLayersAs(const std::string &layerName) const
01022 {
01023   typedef typename Field<Data_T>::Vec FieldList;
01024   typedef typename Field_T<Data_T>::Vec TypedFieldList;
01025 
01026   // First, read the layers as-is
01027   FieldList originals;
01028   originals = readVectorLayers<Data_T>(layerName);
01029   
01030   // Loop over fields, converting if needed
01031   TypedFieldList output;
01032   typename FieldList::iterator i = originals.begin();
01033   for (; i != originals.end(); ++i) {
01034     typename Field_T<Data_T>::Ptr targetField;
01035     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01036     if (targetField) {
01037       output.push_back(targetField);
01038     } else {
01039       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01040       newTarget->name = (*i)->name;
01041       newTarget->attribute = (*i)->attribute;
01042       newTarget->copyMetadata(*i);
01043       newTarget->copyFrom(*i);
01044       output.push_back(newTarget);
01045     }
01046   }
01047 
01048   return output;
01049 }
01050 
01051 //----------------------------------------------------------------------------//
01052 
01053 template <template <typename T> class Field_T, class Data_T>
01054 typename Field_T<Data_T>::Vec
01055 Field3DInputFile::readVectorLayersAs(const std::string &partitionName, 
01056                                      const std::string &layerName) const
01057 {
01058   typedef typename Field<Data_T>::Vec FieldList;
01059   typedef typename Field_T<Data_T>::Vec TypedFieldList;
01060 
01061   // First, read the layers as-is
01062   FieldList originals;
01063   originals = readVectorLayers<Data_T>(partitionName, layerName);
01064   
01065   // Loop over fields, converting if needed
01066   TypedFieldList output;
01067   typename FieldList::iterator i = originals.begin();
01068   for (; i != originals.end(); ++i) {
01069     typename Field_T<Data_T>::Ptr targetField;
01070     targetField = field_dynamic_cast<Field_T<Data_T> >(*i);
01071     if (targetField) {
01072       output.push_back(targetField);
01073     } else {
01074       typename Field_T<Data_T>::Ptr newTarget(new Field_T<Data_T>);
01075       newTarget->name = (*i)->name;
01076       newTarget->attribute = (*i)->attribute;
01077       newTarget->copyMetadata(*i);
01078       newTarget->copyFrom(*i);
01079       output.push_back(newTarget);
01080     }
01081   }
01082 
01083   return output;
01084 }
01085 
01086 //----------------------------------------------------------------------------//
01087 
01088 template <class Data_T>
01089 typename EmptyField<Data_T>::Vec
01090 Field3DInputFile::readProxyLayer(const std::string &partitionName, 
01091                                  const std::string &layerName,
01092                                  bool isVectorLayer) const
01093 {
01094   using namespace boost;
01095   using namespace std;
01096   using namespace Hdf5Util;
01097 
01098   // Instantiate a null pointer for easier code reading
01099   typename EmptyField<Data_T>::Vec emptyList, output;
01100 
01101   if ((layerName.length() == 0) || (partitionName.length() == 0))
01102     return emptyList;
01103 
01104   std::vector<std::string> parts, layers;
01105   getIntPartitionNames(parts);
01106  
01107   bool foundPartition = false;
01108 
01109   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01110     if (removeUniqueId(*p) == partitionName) {
01111       foundPartition = true;
01112       if (isVectorLayer) {
01113         getIntVectorLayerNames(layers, *p);
01114       } else {
01115         getIntScalarLayerNames(layers, *p);
01116       }
01117       for (vector<string>::iterator l = layers.begin(); 
01118            l != layers.end(); ++l) {
01119         if (*l == layerName) {
01120           // Find the partition
01121           File::Partition::Ptr part = partition(*p);
01122           if (!part) {
01123             Msg::print(Msg::SevWarning, "Couldn't find partition: " + *p);
01124             return emptyList;
01125           }
01126           // Find the layer
01127           const File::Layer *layer;
01128           if (isVectorLayer)
01129             layer = part->vectorLayer(layerName);
01130           else
01131             layer = part->scalarLayer(layerName);
01132           if (!layer) {
01133             Msg::print(Msg::SevWarning, "Couldn't find layer: " + layerName);
01134             return emptyList;
01135           }
01136           // Open the layer group
01137           string layerPath = layer->parent + "/" + layer->name;
01138           H5ScopedGopen layerGroup(m_file, layerPath.c_str());
01139           if (layerGroup.id() < 0) {
01140             Msg::print(Msg::SevWarning, "Couldn't find layer group " 
01141                       + layerName + " in .f3d file ");
01142             return emptyList;
01143           }
01144           // Read the extents and data window
01145           Box3i extents, dataW;
01146           if (!readAttribute(layerGroup, "extents", 6, extents.min.x)) {
01147             return emptyList;
01148           }
01149           if (!readAttribute(layerGroup, "data_window", 6, dataW.min.x)) {
01150             return emptyList;
01151           } 
01152           // Construct the field and load the data
01153           typename EmptyField<Data_T>::Ptr field(new EmptyField<Data_T>);
01154           field->setSize(extents, dataW);
01155 
01156           // read the metadata 
01157           string metadataPath = layerPath + "/metadata";
01158           H5ScopedGopen metadataGroup(m_file, metadataPath.c_str());
01159           if (metadataGroup.id() > 0) {    
01160             readMetadata(metadataGroup.id(), field);
01161           }
01162 
01163           // ... Set the name of the field so it's possible to 
01164           // ... re-create the file
01165           field->name = partitionName;
01166           field->attribute = layerName;
01167           field->setMapping(part->mapping);
01168           // Add field to output
01169           output.push_back(field);
01170         }
01171       }
01172     }
01173   }
01174 
01175   if (!foundPartition) {
01176     Msg::print(Msg::SevWarning, "Couldn't find partition: " + partitionName);
01177     return emptyList;    
01178   }
01179   
01180   return output;
01181 }
01182 
01183 //----------------------------------------------------------------------------//
01184 
01185 template <class Data_T>
01186 typename EmptyField<Data_T>::Vec
01187 Field3DInputFile::readProxyScalarLayers(const std::string &name) const
01188 {
01189   using namespace std;
01190 
01191   typedef typename EmptyField<Data_T>::Ptr FieldPtr;
01192   typedef std::vector<FieldPtr> FieldList;
01193   
01194   FieldList ret;
01195   
01196   std::vector<std::string> parts;
01197   getPartitionNames(parts);
01198   
01199   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01200   std::vector<std::string> layers;
01201     getScalarLayerNames(layers, *p);
01202     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
01203       // Only read if it matches the name
01204       if ((name.length() == 0) || (*l == name)) {
01205         FieldList f = readProxyLayer<Data_T>(*p, *l, false);
01206         for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
01207           if (*i) {
01208             ret.push_back(*i);
01209           }
01210         }
01211       }
01212     }
01213   }
01214   
01215   return ret;
01216 }
01217 
01218 //----------------------------------------------------------------------------//
01219 
01220 template <class Data_T>
01221 typename EmptyField<Data_T>::Vec
01222 Field3DInputFile::readProxyVectorLayers(const std::string &name) const
01223 {
01224   using namespace std;
01225   
01226   typedef typename EmptyField<Data_T>::Ptr FieldPtr;
01227   typedef std::vector<FieldPtr> FieldList;
01228   
01229   FieldList ret;
01230   
01231   std::vector<std::string> parts;
01232   getPartitionNames(parts);
01233   
01234   for (vector<string>::iterator p = parts.begin(); p != parts.end(); ++p) {
01235   std::vector<std::string> layers;
01236     getVectorLayerNames(layers, *p);
01237     for (vector<string>::iterator l = layers.begin(); l != layers.end(); ++l) {
01238       // Only read if it matches the name
01239       if ((name.length() == 0) || (*l == name)) {
01240         FieldList f = readProxyLayer<Data_T>(*p, *l, true);
01241         for (typename FieldList::iterator i = f.begin(); i != f.end(); ++i) {
01242           if (*i) {
01243             ret.push_back(*i);
01244           }
01245         }
01246       }
01247     }
01248   }
01249   
01250   return ret;  
01251 }
01252 
01253 //----------------------------------------------------------------------------//
01254 
01255 template <class Data_T>
01256 typename Field<Data_T>::Ptr
01257 Field3DInputFile::readScalarLayer(const std::string &intPartitionName,
01258                                   const std::string &layerName) const
01259 {
01260   return readLayer<Data_T>(intPartitionName, layerName, false);
01261 }
01262 
01263 //----------------------------------------------------------------------------//
01264 
01265 template <class Data_T>
01266 typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr
01267 Field3DInputFile::readVectorLayer(const std::string &intPartitionName,
01268                                   const std::string &layerName) const
01269 {
01270   return readLayer<FIELD3D_VEC3_T<Data_T> >(intPartitionName, layerName, true);
01271 }
01272 
01273 //----------------------------------------------------------------------------//
01274 // Field3DOutputFile
01275 //----------------------------------------------------------------------------//
01276 
01277 template <class Data_T>
01278 bool 
01279 Field3DOutputFile::writeLayer(const std::string &userPartitionName, 
01280                               const std::string &layerName, 
01281                               bool isVectorLayer, 
01282                               typename Field<Data_T>::Ptr field)
01283 {
01284   using namespace std;
01285   using namespace Exc;
01286   using namespace Hdf5Util;
01287 
01288   if (!field) {
01289     Msg::print(Msg::SevWarning, 
01290                "Called writeLayer with null pointer. Ignoring...");
01291     return false;
01292   }
01293 
01294   if (m_file < 0) {
01295     Msg::print(Msg::SevWarning, 
01296                "Attempting to write layer without opening file first. ");
01297     return false;
01298   }
01299 
01300   string partitionName = intPartitionName(userPartitionName, layerName, field);
01301 
01302   // See if the partition already exists or if we need to make it ---
01303 
01304   File::Partition::Ptr part = partition(partitionName);
01305 
01306   if (!part) {
01307 
01308     File::Partition::Ptr newPart(new File::Partition);
01309 
01310     newPart->name = partitionName;
01311 
01312     H5ScopedGcreate partGroup(m_file, newPart->name.c_str());
01313     if (partGroup.id() < 0) {
01314       Msg::print(Msg::SevWarning, 
01315                  "Error creating partition: " + newPart->name);
01316       return false;
01317     } 
01318     
01319     m_partitions.push_back(newPart);
01320 
01321     // Pick up new pointer
01322     part = partition(partitionName);
01323 
01324     // Add mapping group to the partition
01327     try {
01328       if (!writeMapping(partGroup.id(), field->mapping())) {
01329         Msg::print(Msg::SevWarning, 
01330                   "writeMapping returned false for an unknown reason ");
01331         return false;
01332       }
01333     }
01334     catch (WriteMappingException &e) {
01335       Msg::print(Msg::SevWarning, "Couldn't write mapping for partition: " 
01336                 + partitionName);
01337       return false;
01338     }
01339     catch (...) {
01340       Msg::print(Msg::SevWarning, 
01341                  "Unknown error when writing mapping for partition: " 
01342                  + partitionName);
01343       return false;
01344     }
01345 
01346     // Set the mapping of the partition. Since all layers share their 
01347     // partition's mapping, we can just pick this first one. All subsequent
01348     // additions to the same partition are checked to have the same mapping
01349     part->mapping = field->mapping();
01350 
01351     // Tag node as partition
01352     // Create a version attribute on the root node
01353     if (!writeAttribute(partGroup.id(), "is_field3d_partition", "1")) {
01354       Msg::print(Msg::SevWarning, "Adding partition string.");
01355       return false;
01356     }    
01357 
01358   } else {
01359 
01360     // If the partition already existed, we need to make sure that the layer
01361     // doesn't also exist
01362     if (!isVectorLayer) {
01363       if (part->scalarLayer(layerName)) {
01364         Msg::print(Msg::SevWarning, 
01365                   "Trying to add layer that already exists in file. Ignoring");
01366         return false;
01367       }
01368     } else {
01369       if (part->vectorLayer(layerName)) {
01370         Msg::print(Msg::SevWarning, 
01371                   "Trying to add layer that already exists in file. Ignoring");
01372         return false;
01373       }
01374     }
01375   }
01376 
01377   if (!field->mapping()) {
01378     Msg::print(Msg::SevWarning, 
01379               "Couldn't add layer \"" + layerName + "\" to partition \""
01380               + partitionName + "\" because the layer's mapping is null.");
01381     return false;    
01382   }
01383 
01384   if (!part->mapping) {
01385     Msg::print(Msg::SevWarning, "Severe error - partition mapping is null: " 
01386               + partitionName);
01387     return false;    
01388   }
01389 
01390   // Check that the mapping matches what's already in the Partition
01391   if (!field->mapping()->isIdentical(part->mapping)) {
01392     Msg::print(Msg::SevWarning, "Couldn't add layer \"" + layerName 
01393               + "\" to partition \"" + partitionName 
01394               + "\" because mapping doesn't match");
01395     return false;
01396   }
01397 
01398   // Open the partition
01399   H5ScopedGopen partGroup(m_file, part->name.c_str(), H5P_DEFAULT);
01400 
01401   // Build a Layer object ---
01402 
01403   File::Layer layer;
01404   layer.name = layerName;
01405   layer.parent = partitionName;
01406 
01407   // Add Layer to file ---
01408 
01409   H5ScopedGcreate layerGroup(partGroup.id(), layerName.c_str(),
01410                              H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
01411 
01412   if (layerGroup.id() < 0) {
01413     Msg::print(Msg::SevWarning, "Error creating layer: " + layerName);
01414     return false;
01415   }
01416 
01417   // Tag as layer
01418   if (!writeAttribute(layerGroup.id(), "class_type", "field3d_layer")) {
01419     Msg::print(Msg::SevWarning, "Error adding layer string.");
01420     return false;
01421   }    
01422 
01423   // Add metadata group and write it out  
01424   H5ScopedGcreate metadataGroup(layerGroup.id(), "metadata");
01425   if (metadataGroup.id() < 0) {
01426     Msg::print(Msg::SevWarning, "Error creating group: metadata");
01427     return false;
01428   }  
01429   if (!writeMetadata(metadataGroup.id(), field)) {
01430     Msg::print(Msg::SevWarning, "Error writing metadata.");
01431     return false;
01432   }    
01433 
01434   if (!writeField(layerGroup.id(), field)) {
01435     Msg::print(Msg::SevWarning, "Error writing layer: " + layer.name);
01436     return false;
01437   }
01438   
01439   // Add layer to partition ---
01440 
01441   if (isVectorLayer)
01442     part->addVectorLayer(layer);
01443   else
01444     part->addScalarLayer(layer);
01445 
01446   return true;  
01447 }
01448 
01449 //----------------------------------------------------------------------------//
01450 
01451 template <class Data_T>
01452 bool 
01453 Field3DOutputFile::writeScalarLayer(const std::string &partitionName, 
01454                                     const std::string &layerName, 
01455                                     typename Field<Data_T>::Ptr field)
01456 {
01457   return writeLayer<Data_T>(partitionName, layerName, false, field);
01458 }
01459 
01460 //----------------------------------------------------------------------------//
01461 
01462 template <class Data_T>
01463 bool 
01464 Field3DOutputFile::writeScalarLayer(typename Field<Data_T>::Ptr layer)
01465 {
01466   if (layer->name.size() == 0) {
01467     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
01468                "Tried to write a scalar layer with no name");
01469     return false;
01470   }
01471   if (layer->attribute.size() == 0) {
01472     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeScalarLayer: "
01473                "Tried to write a scalar layer with no attribute name");
01474     return false;
01475   }
01476   return writeScalarLayer<Data_T>(layer->name, layer->attribute, layer);
01477 }
01478 
01479 //----------------------------------------------------------------------------//
01480 
01481 template <class Data_T>
01482 bool 
01483 Field3DOutputFile::
01484 writeVectorLayer(const std::string &partitionName, 
01485                  const std::string &layerName, 
01486                  typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr field)
01487 {
01488   return writeLayer<FIELD3D_VEC3_T<Data_T> >(partitionName, layerName, 
01489                                              true, field);
01490 }
01491 
01492 //----------------------------------------------------------------------------//
01493 
01494 template <class Data_T>
01495 bool 
01496 Field3DOutputFile::writeVectorLayer
01497   (typename Field<FIELD3D_VEC3_T<Data_T> >::Ptr layer)
01498 {
01499   if (layer->name.size() == 0) {
01500     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
01501                "Tried to write a vector layer with no name");
01502     return false;
01503   }
01504   if (layer->attribute.size() == 0) {
01505     Msg::print(Msg::SevWarning, "Field3DOutputFile::writeVectorLayer: "
01506                "Tried to write a vector layer with no attribute name");
01507     return false;
01508   }
01509   return writeVectorLayer<Data_T>(layer->name, layer->attribute, layer);
01510 }
01511 
01512 //----------------------------------------------------------------------------//
01513 // Template Function Implementations
01514 //----------------------------------------------------------------------------//
01515 
01516 template <class Data_T>
01517 typename Field<Data_T>::Ptr 
01518 readField(const std::string &className, hid_t layerGroup,
01519           const std::string &filename, const std::string &layerPath)
01520 {
01521 
01522   ClassFactory &factory = ClassFactory::singleton();
01523   
01524   typedef typename Field<Data_T>::Ptr FieldPtr;
01525 
01526   FieldIO::Ptr io = factory.createFieldIO(className);
01527   assert(io != 0);
01528   if (!io) {
01529     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01530                className);
01531     return FieldPtr();
01532   }
01533 
01534   DataTypeEnum typeEnum = DataTypeTraits<Data_T>::typeEnum();
01535   FieldBase::Ptr field = io->read(layerGroup, filename, layerPath, typeEnum);
01536   
01537   if (!field) {
01538     // We don't need to print a message, because it could just be that
01539     // a layer of the specified data type and name couldn't be found
01540     return FieldPtr();
01541   }
01542 
01543   FieldPtr result = field_dynamic_cast<Field<Data_T> >(field);
01544 
01545   if (result)
01546     return result;
01547 
01548   return FieldPtr();
01549 }
01550 
01551 //----------------------------------------------------------------------------//
01552 
01553 FIELD3D_NAMESPACE_HEADER_CLOSE
01554 
01555 //----------------------------------------------------------------------------//
01556 
01557 #endif