Field3D
Field3DFile.cpp
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 
00043 //----------------------------------------------------------------------------//
00044 
00045 #include <sys/stat.h>
00046 #include <unistd.h>
00047 
00048 #include <hdf5.h>
00049 #include <H5Epublic.h>
00050 
00051 #include <boost/tokenizer.hpp>
00052 #include <boost/utility.hpp>
00053 
00054 #include "Field3DFile.h"
00055 #include "Field.h"
00056 #include "ClassFactory.h"
00057 
00058 //----------------------------------------------------------------------------//
00059 
00060 using namespace std;
00061 
00062 //----------------------------------------------------------------------------//
00063 
00064 FIELD3D_NAMESPACE_OPEN
00065 
00066 //----------------------------------------------------------------------------//
00067 // Field3D namespaces
00068 //----------------------------------------------------------------------------//
00069 
00070 using namespace Exc;
00071 using namespace Hdf5Util;
00072 using namespace File;
00073 
00074 //----------------------------------------------------------------------------//
00075 // Local namespace
00076 //----------------------------------------------------------------------------//
00077 
00078 namespace {
00079   
00080   // Strings used only in this file --------------------------------------------
00081 
00082   const std::string k_mappingStr("mapping");
00083   const std::string k_partitionName("partition");  
00084   const std::string k_versionAttrName("version_number");
00085   const std::string k_classNameAttrName("class_name");
00086   const std::string k_mappingTypeAttrName("mapping_type");
00087 
00090 
00091   int k_currentFileVersion[3] =
00092     { FIELD3D_MAJOR_VER, FIELD3D_MINOR_VER, FIELD3D_MICRO_VER };
00093   int k_minFileVersion[2] = { 0, 0 };
00094 
00095   // Function objects used only in this file -----------------------------------
00096 
00097   std::vector<std::string> makeUnique(std::vector<std::string> vec)
00098   {
00099     std::vector<string> ret;
00100     std::sort(vec.begin(), vec.end());
00101     std::vector<std::string>::iterator newEnd = 
00102       std::unique(vec.begin(), vec.end());
00103     ret.resize(std::distance(vec.begin(), newEnd));
00104     std::copy(vec.begin(), newEnd, ret.begin()); 
00105     return ret;
00106   }
00107 
00108 //----------------------------------------------------------------------------//
00109 
00111   template <class T>
00112   class print : std::unary_function<T, void>
00113   {
00114   public:
00115     print(int indentAmt)
00116       : indent(indentAmt)
00117     { }
00118     void operator()(const T& x) const
00119     {
00120       for (int i = 0; i < indent; i++)
00121         std::cout << " ";
00122       std::cout << x << std::endl;
00123     }
00124     int indent;
00125   };
00126 
00127 //----------------------------------------------------------------------------//
00128 
00134   bool fileExists(const std::string &filename)
00135   {
00136     struct stat statbuf;
00137     return (stat(filename.c_str(), &statbuf) != -1);
00138   }
00139 
00145   void checkFile(const std::string &filename)
00146   {
00147     if (!fileExists(filename))
00148     {
00149       throw NoSuchFileException(filename);
00150     }
00151   }
00152 
00153 //----------------------------------------------------------------------------//
00154 
00155   bool isSupportedFileVersion(const int fileVersion[3],
00156                               const int minVersion[2])
00157   {
00158     stringstream currentVersionStr;
00159     currentVersionStr << k_currentFileVersion[0] << "."
00160                       << k_currentFileVersion[1] << "."
00161                       << k_currentFileVersion[2];
00162     stringstream fileVersionStr;
00163     fileVersionStr << fileVersion[0] << "."
00164                    << fileVersion[1] << "."
00165                    << fileVersion[2];
00166     stringstream minVersionStr;
00167     minVersionStr << minVersion[0] << "."
00168                   << minVersion[1];
00169 
00170     if (fileVersion[0] > k_currentFileVersion[0] ||
00171         (fileVersion[0] == k_currentFileVersion[0] && 
00172          fileVersion[1] > k_currentFileVersion[1])) {
00173       Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
00174                  " is higher than the current version " +
00175                  currentVersionStr.str());
00176       return true;
00177     }
00178 
00179     if (fileVersion[0] < minVersion[0] ||
00180         (fileVersion[0] == minVersion[0] &&
00181          fileVersion[1] < minVersion[1])) {
00182       Msg::print(Msg::SevWarning, "File version " + fileVersionStr.str() +
00183                  " is lower than the minimum supported version " +
00184                  minVersionStr.str());
00185       return false;
00186     }
00187     return true;
00188   }
00189 
00190 //----------------------------------------------------------------------------//
00191 
00192   static herr_t localPrintError( hid_t estack_id, void *stream )
00193   {
00194     printf("H5E message -----------------------\n");
00195     return H5Eprint2(estack_id, static_cast<FILE*>(stream));
00196   }
00197   
00198 //----------------------------------------------------------------------------//
00199 
00200 } // end of local namespace
00201 
00202 //----------------------------------------------------------------------------//
00203 // Partition implementations
00204 //----------------------------------------------------------------------------//
00205 
00206 std::string Partition::className() const
00207 {
00208   return k_partitionName;
00209 }
00210 
00211 //----------------------------------------------------------------------------//
00212 
00213 void 
00214 Partition::addScalarLayer(const Layer &layer)
00215 {
00216   m_scalarLayers.push_back(layer);
00217 }
00218 
00219 //----------------------------------------------------------------------------//
00220 
00221 void 
00222 Partition::addVectorLayer(const Layer &layer)
00223 {
00224   m_vectorLayers.push_back(layer);
00225 }
00226 
00227 //----------------------------------------------------------------------------//
00228 
00229 const Layer* 
00230 Partition::scalarLayer(const std::string &name) const
00231 {
00232   for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
00233        i != m_scalarLayers.end(); ++i) {
00234     if (i->name == name)
00235       return &(*i);
00236   }
00237   return NULL;
00238 }
00239 
00240 //----------------------------------------------------------------------------//
00241 
00242 const Layer* 
00243 Partition::vectorLayer(const std::string &name) const
00244 {
00245   for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
00246        i != m_vectorLayers.end(); ++i) {
00247     if (i->name == name)
00248       return &(*i);
00249   }
00250   return NULL;
00251 }
00252 
00253 //----------------------------------------------------------------------------//
00254 
00255 void 
00256 Partition::getScalarLayerNames(std::vector<std::string> &names) const 
00257 {
00258   // We don't want to do names.clear() here, since this gets called
00259   // inside some loops that want to accumulate names.
00260   for (ScalarLayerList::const_iterator i = m_scalarLayers.begin();
00261        i != m_scalarLayers.end(); ++i) {
00262     names.push_back(i->name);
00263   }
00264 }
00265 
00266 //----------------------------------------------------------------------------//
00267 
00268 void 
00269 Partition::getVectorLayerNames(std::vector<std::string> &names) const
00270 {
00271   // We don't want to do names.clear() here, since this gets called
00272   // inside some loops that want to accumulate names.
00273   for (VectorLayerList::const_iterator i = m_vectorLayers.begin();
00274        i != m_vectorLayers.end(); ++i) {
00275     names.push_back(i->name);
00276   }
00277 }
00278 
00279 //----------------------------------------------------------------------------//
00280 // Field3DFileBase implementations
00281 //----------------------------------------------------------------------------//
00282 
00283 Field3DFileBase::Field3DFileBase()
00284   : m_file(-1), m_metadata(this)
00285 {
00286   // Suppressing HDF error messages
00287   // Explanation about the function for the error stack is here:
00288   // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5E.html#Error-SetAuto2
00289   if (getenv("DEBUG_HDF")) {
00290     cerr << "Field3DFile -- HDF5 messages are on" << endl;
00291     H5Eset_auto(H5E_DEFAULT, localPrintError, NULL);
00292   } else {
00293     H5Eset_auto(H5E_DEFAULT, NULL, NULL);
00294   }
00295 }
00296 
00297 //----------------------------------------------------------------------------//
00298 
00299 Field3DFileBase::~Field3DFileBase()
00300 {
00301   close();
00302 }
00303 
00304 //----------------------------------------------------------------------------//
00305 
00306 std::string 
00307 Field3DFileBase::intPartitionName(const std::string &partitionName,
00308                                   const std::string &layerName,
00309                                   FieldRes::Ptr field)
00310 {
00311   // Loop over existing partitions and see if there's a matching mapping
00312   for (PartitionList::const_iterator i = m_partitions.begin();
00313        i != m_partitions.end(); ++i) {
00314     if (removeUniqueId((**i).name) == partitionName) {
00315       if ((**i).mapping->isIdentical(field->mapping())) {
00316         return (**i).name;
00317       }
00318     }
00319   }
00320 
00321   // If there was no previously matching name, then make a new one
00322 
00323   int nextIdx = -1;
00324   if (m_partitionCount.find(partitionName) != m_partitionCount.end()) {
00325     nextIdx = ++m_partitionCount[partitionName];
00326   } else {
00327     nextIdx = 0;
00328     m_partitionCount[partitionName] = 0;
00329   }
00330 
00331   return makeIntPartitionName(partitionName, nextIdx);
00332 }
00333 
00334 //----------------------------------------------------------------------------//
00335 
00336 Partition::Ptr Field3DFileBase::partition(const string &partitionName) 
00337 {
00338   for (PartitionList::iterator i = m_partitions.begin();
00339        i != m_partitions.end(); ++i) {
00340     if ((**i).name == partitionName)
00341       return *i;
00342   }
00343 
00344   return Partition::Ptr();
00345 }
00346 
00347 //----------------------------------------------------------------------------//
00348 
00349 Partition::Ptr
00350 Field3DFileBase::partition(const string &partitionName) const
00351 {
00352   for (PartitionList::const_iterator i = m_partitions.begin();
00353        i != m_partitions.end(); ++i) {
00354     if ((**i).name == partitionName)
00355       return *i;
00356   }
00357 
00358   return Partition::Ptr();
00359 }
00360 
00361 //----------------------------------------------------------------------------//
00362 
00363 std::string 
00364 Field3DFileBase::removeUniqueId(const std::string &partitionName) const
00365 {
00366   size_t pos = partitionName.rfind(".");
00367   if (pos == partitionName.npos) {
00368     return partitionName;
00369   } else {
00370     return partitionName.substr(0, pos);
00371   }  
00372 }
00373 
00374 //----------------------------------------------------------------------------//
00375 
00376 void 
00377 Field3DFileBase::getPartitionNames(vector<string> &names) const
00378 {
00379   names.clear();
00380 
00381   vector<string> tempNames;
00382 
00383   for (PartitionList::const_iterator i = m_partitions.begin();
00384        i != m_partitions.end(); ++i) {
00385     tempNames.push_back(removeUniqueId((**i).name));
00386   }
00387 
00388   names = makeUnique(tempNames);
00389 }
00390 
00391 //----------------------------------------------------------------------------//
00392 
00393 void 
00394 Field3DFileBase::getScalarLayerNames(vector<string> &names, 
00395                                      const string &partitionName) const
00396 {
00397   names.clear();
00398 
00399   for (int i = 0; i < numIntPartitions(partitionName); i++) {
00400     string internalName = makeIntPartitionName(partitionName, i);
00401     Partition::Ptr part = partition(internalName);
00402     if (part)
00403       part->getScalarLayerNames(names);
00404   }
00405 
00406   names = makeUnique(names);
00407 }
00408 
00409 //----------------------------------------------------------------------------//
00410 
00411 void 
00412 Field3DFileBase::getVectorLayerNames(vector<string> &names, 
00413                                      const string &partitionName) const
00414 {
00415   names.clear();
00416 
00417   for (int i = 0; i < numIntPartitions(partitionName); i++) {
00418     string internalName = makeIntPartitionName(partitionName, i);
00419     Partition::Ptr part = partition(internalName);
00420     if (part)
00421       part->getVectorLayerNames(names);
00422   }
00423 
00424   names = makeUnique(names);
00425 }
00426 
00427 //----------------------------------------------------------------------------//
00428 
00429 void 
00430 Field3DFileBase::getIntPartitionNames(vector<string> &names) const
00431 {
00432   names.clear();
00433 
00434   for (PartitionList::const_iterator i = m_partitions.begin();
00435        i != m_partitions.end(); ++i) {
00436     names.push_back((**i).name);
00437   }
00438 }
00439 
00440 //----------------------------------------------------------------------------//
00441 
00442 void 
00443 Field3DFileBase::getIntScalarLayerNames(vector<string> &names, 
00444                                         const string &intPartitionName) const
00445 {
00446   names.clear();
00447 
00448   Partition::Ptr part = partition(intPartitionName);
00449 
00450   if (!part) {
00451     Msg::print("getIntScalarLayerNames no partition: " + intPartitionName);
00452     return;
00453   }
00454 
00455   part->getScalarLayerNames(names);
00456 }
00457 
00458 //----------------------------------------------------------------------------//
00459 
00460 void 
00461 Field3DFileBase::getIntVectorLayerNames(vector<string> &names, 
00462                                         const string &intPartitionName) const
00463 {
00464   names.clear();
00465 
00466   Partition::Ptr part = partition(intPartitionName);
00467 
00468   if (!part) {
00469     Msg::print("getIntVectorLayerNames no partition: " + intPartitionName);    
00470     return;
00471   }
00472 
00473   part->getVectorLayerNames(names);
00474 }
00475 
00476 //----------------------------------------------------------------------------//
00477 
00478 void Field3DFileBase::clear()
00479 {
00480   closeInternal();
00481   m_partitions.clear();
00482   m_groupMembership.clear();
00483 }
00484 
00485 //----------------------------------------------------------------------------//
00486 
00487 bool Field3DFileBase::close()
00488 {
00489   closeInternal();
00490 
00491   return true;
00492 }
00493 
00494 //----------------------------------------------------------------------------//
00495 
00496 void Field3DFileBase::closeInternal()
00497 {
00498   if (m_file != -1) {
00499     if (H5Fclose(m_file) < 0) {
00500       Msg::print(Msg::SevWarning, "Failed to close hdf5 file handle");
00501       return;
00502     }    
00503     m_file = -1;
00504   }
00505 }
00506 
00507 //----------------------------------------------------------------------------//
00508 
00509 int 
00510 Field3DFileBase::numIntPartitions(const std::string &partitionName) const
00511 {
00512   int count = 0;
00513 
00514   for (PartitionList::const_iterator i = m_partitions.begin();
00515        i != m_partitions.end(); ++i) {
00516     string name = (**i).name;
00517     size_t pos = name.rfind(".");
00518     if (pos != name.npos) {
00519       if (name.substr(0, pos) == partitionName) {
00520         count++;
00521       }
00522     }
00523   }
00524 
00525   return count;
00526 }
00527 
00528 //----------------------------------------------------------------------------//
00529 
00530 string 
00531 Field3DFileBase::makeIntPartitionName(const std::string &partitionName,
00532                                       int i) const
00533 {
00534   return partitionName + "." + boost::lexical_cast<std::string>(i);
00535 }
00536 
00537 //----------------------------------------------------------------------------//
00538 
00539 void 
00540 Field3DFileBase::addGroupMembership(const GroupMembershipMap& groupMembers)
00541 {
00542   GroupMembershipMap::const_iterator i= groupMembers.begin();
00543   GroupMembershipMap::const_iterator end= groupMembers.end();
00544 
00545   for (; i != end; ++i) {
00546     GroupMembershipMap::iterator foundGroupIter = 
00547       m_groupMembership.find(i->first);
00548     if (foundGroupIter != m_groupMembership.end()){
00549       std::string value = m_groupMembership[i->first] + i->second;
00550       m_groupMembership[i->first] = value;
00551     } else { 
00552       m_groupMembership[i->first] = i->second;
00553     }
00554   }
00555 }
00556 
00557 //----------------------------------------------------------------------------//
00558 // Field3DInputFile implementations
00559 //----------------------------------------------------------------------------//
00560 
00561 Field3DInputFile::Field3DInputFile() 
00562 { 
00563   // Empty
00564 }
00565 
00566 //----------------------------------------------------------------------------//
00567 
00568 Field3DInputFile::~Field3DInputFile() 
00569 { 
00570   clear(); 
00571 }
00572 
00573 //----------------------------------------------------------------------------//
00574 
00575 bool Field3DInputFile::open(const string &filename)
00576 {
00577   clear();
00578 
00579   bool success = true;
00580 
00581   m_filename = filename;
00582 
00583   try {
00584 
00585     string version;
00586 
00587     // Throws exceptions if the file doesn't exist.
00588     // This was added because H5Fopen prints out a lot of junk
00589     // to the terminal.
00590     checkFile(filename);
00591 
00592     m_file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
00593 
00594     if (m_file < 0)
00595       throw NoSuchFileException(filename);
00596 
00597     int fileVersion[3];
00598     try { 
00599       if (!readAttribute(m_file, k_versionAttrName, 3, fileVersion[0])) {
00600         //Msg::print(Msg::SevWarning, "Missing version_number attribute");
00601       } else {
00602         if (!isSupportedFileVersion(fileVersion, k_minFileVersion)) {
00603           stringstream versionStr;
00604           versionStr << fileVersion[0] << "."
00605                      << fileVersion[1] << "."
00606                      << fileVersion[2];
00607           throw UnsupportedVersionException(versionStr.str());
00608         }
00609       }
00610     }
00611     catch (MissingAttributeException &e) {
00612       //Msg::print(Msg::SevWarning, "Missing version_number attribute");
00613     }
00614 
00615     try { 
00616       if (H5Lexists(m_file, "field3d_global_metadata", H5P_DEFAULT)) {      
00617         // read the metadata 
00618         H5ScopedGopen metadataGroup(m_file, "field3d_global_metadata");
00619         if (metadataGroup.id() > 0) {    
00620           readMetadata(metadataGroup.id());
00621         }
00622       }
00623     }
00624     catch (...) {
00625       Msg::print(Msg::SevWarning, 
00626                  "Unknown error when reading file metadata ");
00627       //throw BadFileHierarchyException(filename);
00628     }
00629 
00630     try {
00631       if (!readPartitionAndLayerInfo()) {
00632         success = false;
00633       }
00634     } 
00635     catch (MissingGroupException &e) {
00636       Msg::print(Msg::SevWarning, "Missing group: " + string(e.what()));
00637       throw BadFileHierarchyException(filename);
00638     }
00639     catch (ReadMappingException &e) {
00640       Msg::print(Msg::SevWarning, "Couldn't read mapping for partition: " 
00641                 + string(e.what()));
00642       throw BadFileHierarchyException(filename);
00643     }
00644     catch (Exception &e) {
00645       Msg::print(Msg::SevWarning, "Unknown error when reading file hierarchy: "
00646                 + string(e.what()));
00647       throw BadFileHierarchyException(filename);
00648     }
00649     catch (...) {
00650       Msg::print(Msg::SevWarning, 
00651                  "Unknown error when reading file hierarchy. ");
00652       throw BadFileHierarchyException(filename);
00653     }
00654 
00655   }
00656   catch (NoSuchFileException &e) {
00657     Msg::print(Msg::SevWarning, "Couldn't open file: " 
00658               + string(e.what()) );
00659     success = false;    
00660   }
00661   catch (MissingAttributeException &e) {
00662     Msg::print(Msg::SevWarning, 
00663                "In file: " + filename + " - "
00664               + string(e.what()) );
00665     success = false;
00666   }
00667   catch (UnsupportedVersionException &e) {    
00668     Msg::print(Msg::SevWarning, 
00669                "In file: " + filename + " - File version can not be read: " 
00670               + string(e.what()));
00671     success = false;    
00672   }
00673   catch (BadFileHierarchyException &e) {
00674     Msg::print(Msg::SevWarning, 
00675                "In file: " + filename + " - Bad file hierarchy. ");
00676     success = false;    
00677   }
00678   catch (...) {
00679     Msg::print(Msg::SevWarning, 
00680                "In file: " + filename + " Unknown exception ");
00681     success = false;
00682   }
00683 
00684   if (!success)
00685     close();
00686   
00687   return success;
00688 }
00689 
00690 //----------------------------------------------------------------------------//
00691 
00692 bool Field3DInputFile::readPartitionAndLayerInfo()
00693 {
00694   using namespace InputFile;
00695 
00696   // First, find the partitions ---
00697 
00698   herr_t status;
00699   status = H5Literate(m_file, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, 
00700                       &parsePartitions, this);
00701 
00702   // Get the partition names to store 
00703   m_partitions.clear();
00704 
00705   for (size_t i=0; i < m_partitionNames.size(); i++) {
00706     Partition::Ptr part(new Partition);
00707     part->name = m_partitionNames[i];    
00708     m_partitions.push_back(part);
00709   }
00710   
00711   // For each partition, find its mapping ---
00712 
00713   for (PartitionList::iterator i = m_partitions.begin();
00714        i != m_partitions.end(); ++i) {
00715 
00716     // Open the partition
00717     H5ScopedGopen partitionGroup(m_file, (**i).name);
00718 
00719     string mappingPath = "/" + (**i).name + "/" + k_mappingStr;
00720 
00721     // Open up the mapping group
00722     H5ScopedGopen mappingGroup(m_file, mappingPath);
00723     if (mappingGroup.id() < 0)
00724       throw MissingGroupException((**i).name + "/" + k_mappingStr);
00725 
00726     // Try to build a mapping from it
00727     FieldMapping::Ptr mapping;
00728 
00729     mapping = readFieldMapping(mappingGroup.id());
00730     if (!mapping) {
00731       Msg::print(Msg::SevWarning, "Got a null pointer when reading mapping");
00732       throw ReadMappingException((**i).name);
00733     }
00734     
00735     // Attach the mapping to the partition
00736     (**i).mapping = mapping;
00737 
00738   }
00739 
00740   // ... And then find its layers ---
00741 
00742   for (PartitionList::const_iterator i = m_partitions.begin();
00743        i != m_partitions.end(); ++i) {
00744 
00745     // Open the partition
00746     H5ScopedGopen partitionGroup(m_file, (**i).name);
00747     
00748     // Set up the info struct for the callback
00749     ParseLayersInfo info;
00750     info.file = this;
00751     info.partitionName = (**i).name;
00752 
00753     m_layerInfo.clear();
00754 
00755     status = H5Literate(partitionGroup.id(), H5_INDEX_NAME, H5_ITER_NATIVE, 
00756                         NULL, &parseLayers, &info);
00757 
00758     //set the layer information on the partitions here
00759 
00760     for (std::vector<LayerInfo>::iterator i = m_layerInfo.begin();
00761          i != m_layerInfo.end(); i++) {
00762 
00763       std::string parent = i->parentName;      
00764 
00765       Partition::Ptr part = partition(parent);
00766 
00767       Layer layer;
00768       layer.name = i->name;
00769       layer.parent = i->parentName;
00770       if (i->components == 1) {
00771         part->addScalarLayer(layer);
00772       } else if (i->components == 3) {
00773         part->addVectorLayer(layer);
00774       }
00775     }
00776 
00777   }
00778 
00779   return true;
00780 }
00781 
00782 //----------------------------------------------------------------------------//
00783 
00784 herr_t Field3DInputFile::parsePartition(hid_t loc_id, 
00785                                         const std::string itemName)
00786 {
00787   // Add the partition ---
00788   
00789   m_partitionNames.push_back(string(itemName));
00790   return 0;
00791 }
00792 
00793 //----------------------------------------------------------------------------//
00794 
00798 herr_t Field3DInputFile::parseLayer(hid_t layerGroup, 
00799                                const std::string &partitionName,
00800                                const std::string &layerName)
00801 {
00802   int components;
00803   if (!readAttribute(layerGroup, string("components"), 1, components)) {
00804     Msg::print(Msg::SevWarning, "Couldn't read components attribute for layer " 
00805               + partitionName + "/" + layerName);
00806     return 0;
00807   }
00808 
00809   LayerInfo linfo(partitionName,layerName,components);
00810 
00811   m_layerInfo.push_back(linfo);
00812 
00813   return 0;
00814 }
00815 
00816 //----------------------------------------------------------------------------//
00817 
00819 bool  
00820 Field3DInputFile::
00821 readMetadata(hid_t metadata_id, FieldBase::Ptr field) const
00822 {
00823 
00824   hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
00825 
00826   if (num_attrs > 0) { 
00827     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
00828       H5ScopedAopenIdx attrIdx(metadata_id, idx);
00829       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
00830       if (len > 0) {
00831         char *name = new char[len+1];
00832         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
00833           H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
00834           H5ScopedAget_space attrSpace(attr);
00835           H5ScopedAget_type attrType(attr);           
00836           H5T_class_t typeClass = H5Tget_class(attrType);
00837 
00838           if (typeClass == H5T_STRING) { 
00839             string value;
00840             if (!readAttribute(metadata_id, name, value)) {
00841               Msg::print(Msg::SevWarning, 
00842                          "Failed to read metadata " + string(name));
00843               if (name) {
00844                 delete[] name;
00845               }
00846               continue;
00847             }
00848             field->metadata().setStrMetadata(name, value);
00849              
00850           }
00851           else {
00852 
00853             if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
00854               Msg::print(Msg::SevWarning, "Bad attribute rank for attribute " 
00855                         + string(name));
00856               if (name) {
00857                 delete[] name;
00858               }
00859               continue;
00860             }            
00861 
00862             hsize_t dims[1];
00863             H5Sget_simple_extent_dims(attrSpace, dims, NULL);
00864  
00865             if (typeClass == H5T_INTEGER) { 
00866               if (dims[0] == 1){
00867                 int value;
00868                 if (!readAttribute(metadata_id, name, dims[0], value))
00869                   Msg::print(Msg::SevWarning, "Failed to read metadata " 
00870                             + string(name));
00871                 field->metadata().setIntMetadata(name, value);
00872               }
00873               else if (dims[0] == 3){
00874                 V3i value;
00875                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00876                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00877                             string(name) );
00878                 field->metadata().setVecIntMetadata(name, value);
00879               }
00880               else {
00881                 Msg::print(Msg::SevWarning, 
00882                            "Attribute of size " + 
00883                            boost::lexical_cast<std::string>(dims[0]) 
00884                            + " is not valid for metadata");
00885               }
00886             }
00887             else if (typeClass == H5T_FLOAT) { 
00888               if (dims[0] == 1){
00889                 float value;
00890                 if (!readAttribute(metadata_id, name, dims[0], value))
00891                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00892                             string(name) );
00893                 
00894                 field->metadata().setFloatMetadata(name, value);
00895               }
00896               else if (dims[0] == 3){
00897                 V3f value;
00898                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00899                   Msg::print(Msg::SevWarning, "Failed to read metadata "+ 
00900                             string(name) );
00901                 field->metadata().setVecFloatMetadata(name, value);
00902               }
00903               else {
00904                 Msg::print(Msg::SevWarning, "Attribute of size " +
00905                            boost::lexical_cast<std::string>(dims[0]) +
00906                            " is not valid for metadata");
00907               }
00908             }
00909             else {               
00910               Msg::print(Msg::SevWarning, "Attribute '" + string(name) + 
00911                         + "' has unsupported data type for metadata");
00912               
00913             }
00914           }
00915         }
00916         if (name) {
00917           delete[] name;
00918         }
00919       }
00920     }
00921   }
00922 
00923   return true;
00924 }
00925 
00926 //----------------------------------------------------------------------------//
00927 
00929 bool  
00930 Field3DInputFile::readMetadata(hid_t metadata_id)
00931 {
00932 
00933   hsize_t num_attrs = H5Aget_num_attrs(metadata_id);
00934 
00935   if (num_attrs > 0) { 
00936     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
00937       H5ScopedAopenIdx attrIdx(metadata_id, idx);
00938       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
00939       if (len > 0) {
00940         char *name = new char[len+1];
00941         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
00942           H5ScopedAopen attr(metadata_id, name, H5P_DEFAULT);
00943           H5ScopedAget_space attrSpace(attr);
00944           H5ScopedAget_type attrType(attr);           
00945           H5T_class_t typeClass = H5Tget_class(attrType);
00946 
00947           if (typeClass == H5T_STRING) { 
00948             string value;
00949             if (!readAttribute(metadata_id, name, value)) {
00950               Msg::print(Msg::SevWarning, 
00951                          "Failed to read metadata " + string(name));
00952               if (name) {
00953                 delete[] name;
00954               }
00955               continue;
00956             }
00957             metadata().setStrMetadata(name, value);
00958              
00959           }
00960           else {
00961 
00962             if (H5Sget_simple_extent_ndims(attrSpace) != 1) {
00963               Msg::print(Msg::SevWarning, "Bad attribute rank for attribute " 
00964                         + string(name));
00965               if (name) {
00966                 delete[] name;
00967               }
00968               continue;
00969             }            
00970 
00971             hsize_t dims[1];
00972             H5Sget_simple_extent_dims(attrSpace, dims, NULL);
00973  
00974             if (typeClass == H5T_INTEGER) { 
00975               if (dims[0] == 1){
00976                 int value;
00977                 if (!readAttribute(metadata_id, name, dims[0], value))
00978                   Msg::print(Msg::SevWarning, "Failed to read metadata " 
00979                             + string(name));
00980                 metadata().setIntMetadata(name, value);
00981               }
00982               else if (dims[0] == 3){
00983                 V3i value;
00984                 if (!readAttribute(metadata_id, name, dims[0], value.x))
00985                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
00986                             string(name) );
00987                 metadata().setVecIntMetadata(name, value);
00988               }
00989               else {
00990                 Msg::print(Msg::SevWarning, 
00991                            "Attribute of size " + 
00992                            boost::lexical_cast<std::string>(dims[0]) 
00993                            + " is not valid for metadata");
00994               }
00995             }
00996             else if (typeClass == H5T_FLOAT) { 
00997               if (dims[0] == 1){
00998                 float value;
00999                 if (!readAttribute(metadata_id, name, dims[0], value))
01000                   Msg::print(Msg::SevWarning, "Failed to read metadata " + 
01001                             string(name) );
01002                 
01003                 metadata().setFloatMetadata(name, value);
01004               }
01005               else if (dims[0] == 3){
01006                 V3f value;
01007                 if (!readAttribute(metadata_id, name, dims[0], value.x))
01008                   Msg::print(Msg::SevWarning, "Failed to read metadata "+ 
01009                             string(name) );
01010                 metadata().setVecFloatMetadata(name, value);
01011               }
01012               else {
01013                 Msg::print(Msg::SevWarning, "Attribute of size " +
01014                            boost::lexical_cast<std::string>(dims[0]) +
01015                            " is not valid for metadata");
01016               }
01017             }
01018             else {               
01019               Msg::print(Msg::SevWarning, "Attribute '" + string(name) + 
01020                         + "' has unsupported data type for metadata");
01021               
01022             }
01023           }
01024         }
01025         if (name) {
01026           delete[] name;
01027         }
01028       }
01029     }
01030   }
01031 
01032   return true;
01033 }
01034 
01035 //----------------------------------------------------------------------------//
01036 
01037 bool
01038 Field3DInputFile::
01039 readGroupMembership(GroupMembershipMap &gpMembershipMap)
01040 {
01041   if (!H5Lexists(m_file, "field3d_group_membership", H5P_DEFAULT)) {
01042     return false;
01043   }
01044 
01045   H5ScopedGopen memberGroup(m_file, "field3d_group_membership");
01046   if (memberGroup < 0) {
01047     return false;
01048   }
01049   
01050   typedef boost::tokenizer<boost::char_separator<char> > Tok;
01051 
01052   hsize_t num_attrs = H5Aget_num_attrs(memberGroup);
01053   if (num_attrs > 0) { 
01054     
01055     for (hsize_t idx=0; idx < num_attrs ; ++idx) {
01056       H5ScopedAopenIdx attrIdx(memberGroup, idx);        
01057       size_t len = H5Aget_name(attrIdx.id(), 0, NULL);
01058       if (len>0) {
01059         char *name = new char[len+1];
01060         if (H5Aget_name(attrIdx.id(), len+1, name) > 0) {
01061 
01062           if (string(name) == "is_field3d_group_membership")
01063             continue;
01064 
01065           H5ScopedAopen attr(memberGroup, name, H5P_DEFAULT);
01066           H5ScopedAget_space attrSpace(attr);
01067           H5ScopedAget_type attrType(attr);           
01068           H5T_class_t typeClass = H5Tget_class(attrType);
01069 
01070           if (typeClass == H5T_STRING) { 
01071             string value;
01072             if (!readAttribute(memberGroup, name, value)) {
01073               Msg::print(Msg::SevWarning, 
01074                          "Failed to read group membership data  " 
01075                         + string(name));
01076               continue;
01077             }
01078 
01079             {
01080               boost::char_separator<char> sep(" :");
01081               Tok tok(value, sep);
01082               string new_value;
01083               for(Tok::iterator beg=tok.begin(); beg!=tok.end();){
01084 
01085                 string fieldgroup = *beg; ++beg;
01086                 fieldgroup = removeUniqueId(fieldgroup) + ":" + *beg; ++beg;
01087                 new_value += fieldgroup + " "; 
01088               }
01089 
01090               m_groupMembership[name] = value;
01091               gpMembershipMap[name] = new_value;
01092             }
01093           }
01094         }
01095       }
01096     }
01097   }
01098 
01099   return true;
01100 }
01101 
01102 //----------------------------------------------------------------------------//
01103 // Field3DFile-related callback functions
01104 //----------------------------------------------------------------------------//
01105 
01106 namespace InputFile {
01107 
01108 //----------------------------------------------------------------------------//
01109 
01110 herr_t parsePartitions(hid_t loc_id, const char *itemName, 
01111                        const H5L_info_t *linfo, void *opdata)
01112 {
01113   herr_t          status;
01114   H5O_info_t      infobuf;
01115 
01116   status = H5Oget_info_by_name(loc_id, itemName, &infobuf, H5P_DEFAULT);
01117 
01118   if (status < 0) {
01119     return -1;
01120   }
01121   
01122   if (infobuf.type == H5O_TYPE_GROUP) {
01123 
01124     // Check that we have a name 
01125     if (!itemName) {
01126       return -1;
01127     }
01128 
01129     // check that this group is not "groupMembership"
01130     if (string(itemName) != "field3d_group_membership" &&
01131         string(itemName) != "field3d_global_metadata")
01132     { 
01133 
01134       // Get a pointer to the file data structure
01135       Field3DInputFile* fileObject = static_cast<Field3DInputFile*>(opdata);
01136       if (!fileObject) {
01137         return -1;
01138       }
01139       
01140       return fileObject->parsePartition(loc_id, itemName);
01141     }
01142   }
01143   return 0;
01144 }
01145 
01146 //----------------------------------------------------------------------------//
01147 
01148 herr_t parseLayers(hid_t loc_id, const char *itemName, 
01149                    const H5L_info_t *linfo, void *opdata)
01150 {
01151   herr_t          status;
01152   H5O_info_t      infobuf;
01153   
01154   status = H5Oget_info_by_name (loc_id, itemName, &infobuf, H5P_DEFAULT);
01155 
01156   if (infobuf.type == H5O_TYPE_GROUP) {
01157 
01158     // Check that we have a name 
01159     if (!itemName)
01160       return -1;
01161 
01162     // Get a pointer to the file data structure
01163     ParseLayersInfo* info = static_cast<ParseLayersInfo*>(opdata);
01164     if (!info) 
01165       return -1;
01166 
01167     // Open up the layer group
01168     H5ScopedGopen layerGroup(loc_id, itemName);
01169 
01170     // Check if it's a layer
01171     string classType;
01172     try {
01173       if (!readAttribute(layerGroup.id(), "class_type", classType)) {
01174         return 0;
01175       }
01176       if (classType == string("field3d_layer")) 
01177         return info->file->parseLayer(layerGroup.id(), info->partitionName,
01178                                       itemName);
01179                                    
01180     }
01181     catch (MissingAttributeException &e) {
01182       
01183     }
01184     return 0;
01185 
01186   }
01187 
01188   return 0;
01189 }
01190 
01191 //----------------------------------------------------------------------------//
01192 
01193 } // namespace InputFile
01194 
01195 //----------------------------------------------------------------------------//
01196 // Field3DOutputFile implementations
01197 //----------------------------------------------------------------------------//
01198 
01199 Field3DOutputFile::Field3DOutputFile() 
01200 { 
01201   // Empty
01202 }
01203 
01204 //----------------------------------------------------------------------------//
01205 
01206 Field3DOutputFile::~Field3DOutputFile() 
01207 { 
01208 
01209 }
01210 
01211 //----------------------------------------------------------------------------//
01212 
01215 bool Field3DOutputFile::create(const string &filename, CreateMode cm)
01216 {
01217   closeInternal();
01218 
01219   bool success = true;
01220 
01221   try {
01222 
01223     hid_t faid = H5Pcreate(H5P_FILE_ACCESS);
01224     H5Pset_libver_bounds(faid, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
01225 
01226     // Create new file
01227     switch (cm) {
01228     case OverwriteMode:
01229       m_file = H5Fcreate(filename.c_str(), 
01230                          H5F_ACC_TRUNC, H5P_DEFAULT, faid);
01231       break;
01232     case FailOnExisting:
01233       m_file = H5Fcreate(filename.c_str(), 
01234                          H5F_ACC_EXCL, H5P_DEFAULT, faid);
01235       break;
01236     }
01237     
01238     // Check that file was created
01239     if (m_file < 0)
01240       throw ErrorCreatingFileException(filename);
01241     
01242     // Create a version attribute on the root node
01243     if (!writeAttribute(m_file, k_versionAttrName, 3,
01244                         k_currentFileVersion[0])) {
01245       Msg::print(Msg::SevWarning, "Adding version number.");
01246       closeInternal();
01247       return false;
01248     }
01249 
01250   }
01251   catch (ErrorCreatingFileException &e) {
01252     Msg::print(Msg::SevWarning, "Couldn't create file: " + string(e.what()) );
01253     success = false;
01254   } 
01255   catch (WriteAttributeException &e) {
01256     Msg::print(Msg::SevWarning, "In file : " + filename +
01257               " - Couldn't add attribute " + string(e.what()) );
01258     success = false;
01259   }
01260   catch (...) {
01261     Msg::print(Msg::SevWarning, 
01262                "Unknown error when creating file: " + filename );
01263     success = false;
01264   }
01265 
01266   return success;
01267 }
01268 
01269 //----------------------------------------------------------------------------//
01270 
01271 bool Field3DOutputFile::writeMapping(hid_t partitionGroup, 
01272                                      FieldMapping::Ptr mapping)
01273 {
01274   try {
01275     // Make a group under the partition to store the mapping data
01276     H5ScopedGcreate mappingGroup(partitionGroup, k_mappingStr);
01277     if (mappingGroup.id() < 0)
01278       throw CreateGroupException(k_mappingStr);
01279     // Let FieldMappingIO handle the rest
01280     if (!writeFieldMapping(mappingGroup.id(), mapping))
01281       throw WriteMappingException(k_mappingStr);       
01282   }
01283   catch (CreateGroupException &e) {
01284     Msg::print(Msg::SevWarning, "Couldn't create group: " + string(e.what()) );
01285     throw WriteMappingException(k_mappingStr);
01286   }
01287   return true;
01288 }
01289 
01290 //----------------------------------------------------------------------------//
01291 
01292 bool Field3DOutputFile::writeMetadata(hid_t metadataGroup, FieldBase::Ptr field)
01293 {
01294   using namespace Hdf5Util;
01295 
01296   {
01297     FieldMetadata<FieldBase>::StrMetadata::const_iterator i = 
01298       field->metadata().strMetadata().begin();
01299     FieldMetadata<FieldBase>::StrMetadata::const_iterator end = 
01300       field->metadata().strMetadata().end();
01301     for (; i != end; ++i) {
01302       if (!writeAttribute(metadataGroup, i->first, i->second))
01303       {
01304         Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
01305         return false;
01306       }
01307     }
01308   }
01309 
01310   {
01311     FieldMetadata<FieldBase>::IntMetadata::const_iterator i = 
01312       field->metadata().intMetadata().begin();
01313     FieldMetadata<FieldBase>::IntMetadata::const_iterator end = 
01314       field->metadata().intMetadata().end();
01315     for (; i != end; ++i) {
01316       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01317       {
01318         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01319         return false;
01320       }
01321     }
01322   }
01323 
01324   {
01325     FieldMetadata<FieldBase>::FloatMetadata::const_iterator i = 
01326       field->metadata().floatMetadata().begin();
01327     FieldMetadata<FieldBase>::FloatMetadata::const_iterator end = 
01328       field->metadata().floatMetadata().end();
01329     for (; i != end; ++i) {
01330       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01331       {
01332         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01333         return false;
01334       }
01335     }
01336   }
01337 
01338   {
01339     FieldMetadata<FieldBase>::VecIntMetadata::const_iterator i = 
01340       field->metadata().vecIntMetadata().begin();
01341     FieldMetadata<FieldBase>::VecIntMetadata::const_iterator end = 
01342       field->metadata().vecIntMetadata().end();
01343     for (; i != end; ++i) {
01344       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01345       {
01346         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01347         return false;
01348       }
01349     }
01350   }
01351 
01352   {
01353     FieldMetadata<FieldBase>::VecFloatMetadata::const_iterator i = 
01354       field->metadata().vecFloatMetadata().begin();
01355     FieldMetadata<FieldBase>::VecFloatMetadata::const_iterator end = 
01356       field->metadata().vecFloatMetadata().end();
01357     for (; i != end; ++i) {
01358       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01359       {
01360         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01361         return false;
01362       }
01363     }
01364 
01365   }
01366 
01367   return true;
01368 
01369 }
01370 
01371 //----------------------------------------------------------------------------//
01372 
01373 bool Field3DOutputFile::writeMetadata(hid_t metadataGroup)
01374 {
01375   using namespace Hdf5Util;
01376 
01377   {
01378     FieldMetadata<Field3DFileBase>::StrMetadata::const_iterator i = 
01379       metadata().strMetadata().begin();
01380     FieldMetadata<Field3DFileBase>::StrMetadata::const_iterator end = 
01381       metadata().strMetadata().end();
01382     for (; i != end; ++i) {
01383       if (!writeAttribute(metadataGroup, i->first, i->second))
01384       {
01385         Msg::print(Msg::SevWarning, "Writing attribute " + i->first );
01386         return false;
01387       }
01388     }
01389   }
01390 
01391   {
01392     FieldMetadata<Field3DFileBase>::IntMetadata::const_iterator i = 
01393       metadata().intMetadata().begin();
01394     FieldMetadata<Field3DFileBase>::IntMetadata::const_iterator end = 
01395       metadata().intMetadata().end();
01396     for (; i != end; ++i) {
01397       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01398       {
01399         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01400         return false;
01401       }
01402     }
01403   }
01404 
01405   {
01406     FieldMetadata<Field3DFileBase>::FloatMetadata::const_iterator i = 
01407       metadata().floatMetadata().begin();
01408     FieldMetadata<Field3DFileBase>::FloatMetadata::const_iterator end = 
01409       metadata().floatMetadata().end();
01410     for (; i != end; ++i) {
01411       if (!writeAttribute(metadataGroup, i->first, 1, i->second))
01412       {
01413         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01414         return false;
01415       }
01416     }
01417   }
01418 
01419   {
01420     FieldMetadata<Field3DFileBase>::VecIntMetadata::const_iterator i = 
01421       metadata().vecIntMetadata().begin();
01422     FieldMetadata<Field3DFileBase>::VecIntMetadata::const_iterator end = 
01423       metadata().vecIntMetadata().end();
01424     for (; i != end; ++i) {
01425       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01426       {
01427         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01428         return false;
01429       }
01430     }
01431   }
01432 
01433   {
01434     FieldMetadata<Field3DFileBase>::VecFloatMetadata::const_iterator i = 
01435       metadata().vecFloatMetadata().begin();
01436     FieldMetadata<Field3DFileBase>::VecFloatMetadata::const_iterator end = 
01437       metadata().vecFloatMetadata().end();
01438     for (; i != end; ++i) {
01439       if (!writeAttribute(metadataGroup, i->first, 3, i->second.x))
01440       {
01441         Msg::print(Msg::SevWarning, "Writing attribute " + i->first);
01442         return false;
01443       }
01444     }
01445 
01446   }
01447 
01448   return true;
01449 
01450 }
01451 
01452 //----------------------------------------------------------------------------//
01453 
01454 bool 
01455 Field3DOutputFile::writeGlobalMetadata()
01456 {
01457 
01458   // Add metadata group and write it out  
01459   H5ScopedGcreate metadataGroup(m_file, "field3d_global_metadata");
01460   if (metadataGroup.id() < 0) {
01461     Msg::print(Msg::SevWarning, "Error creating group: file metadata");
01462     return false;
01463   }  
01464   if (!writeMetadata(metadataGroup.id())) {
01465     Msg::print(Msg::SevWarning, "Error writing file metadata.");
01466     return false;
01467   }    
01468  
01469   return true;
01470 }
01471 
01472 //----------------------------------------------------------------------------//
01473 
01474 bool 
01475 Field3DOutputFile::writeGroupMembership()
01476 {
01477   using namespace std;
01478   using namespace Hdf5Util;
01479 
01480   if (!m_groupMembership.size())
01481     return true;
01482 
01483   H5ScopedGcreate group(m_file, "field3d_group_membership");
01484   if (group < 0) {
01485     Msg::print(Msg::SevWarning, 
01486                "Error creating field3d_group_membership group.");      
01487     return false;
01488   } 
01489 
01490   if (!writeAttribute(group, "is_field3d_group_membership", "1")) {
01491     Msg::print(Msg::SevWarning, 
01492                "Failed to write field3d_group_membership attribute.");
01493     return false;
01494   }    
01495 
01496   std::map<std::string, std::string>::const_iterator iter = 
01497     m_groupMembership.begin();
01498   std::map<std::string, std::string>::const_iterator iEnd = 
01499     m_groupMembership.end();
01500   
01501   for (; iter != iEnd; ++iter) {
01502     if (!writeAttribute(group, iter->first, iter->second)) {
01503       Msg::print(Msg::SevWarning, 
01504                  "Failed to write groupMembership string: "+ iter->first);
01505       return false;
01506     }        
01507   }
01508   
01509   return true;
01510 }
01511 
01512 //----------------------------------------------------------------------------//
01513 
01514 std::string
01515 Field3DOutputFile::incrementPartitionName(std::string &partitionName)
01516 {
01517   std::string myPartitionName = removeUniqueId(partitionName);
01518   int nextIdx = -1;
01519   if (m_partitionCount.find(myPartitionName) != m_partitionCount.end()) {
01520     nextIdx = ++m_partitionCount[myPartitionName];
01521   } else {
01522     nextIdx = 0;
01523     m_partitionCount[myPartitionName] = 0;
01524   }
01525 
01526   return makeIntPartitionName(myPartitionName, nextIdx);
01527 }
01528 
01529 //----------------------------------------------------------------------------//
01530 // Debug
01531 //----------------------------------------------------------------------------//
01532 
01533 void Field3DFileBase::printHierarchy() const
01534 {
01535   // For each partition
01536   for (PartitionList::const_iterator i = m_partitions.begin();
01537        i != m_partitions.end(); ++i) {
01538     cout << "Name: " << (**i).name << endl;
01539     if ((**i).mapping)
01540       cout << "  Mapping: " << (**i).mapping->className() << endl;
01541     else 
01542       cout << "  Mapping: NULL" << endl;
01543     cout << "  Scalar layers: " << endl;
01544     vector<string> sNames;
01545     (**i).getScalarLayerNames(sNames);
01546     for_each(sNames.begin(), sNames.end(), print<string>(4));
01547     cout << "  Vector layers: " << endl;
01548     vector<string> vNames;
01549     (**i).getVectorLayerNames(vNames);
01550     for_each(vNames.begin(), vNames.end(), print<string>(4));
01551   }
01552 }
01553 
01554 //----------------------------------------------------------------------------//
01555 // Function Implementations
01556 //----------------------------------------------------------------------------//
01557 
01558 bool writeField(hid_t layerGroup, FieldBase::Ptr field)
01559 {
01560   ClassFactory &factory = ClassFactory::singleton();
01561     
01562   FieldIO::Ptr io = factory.createFieldIO(field->className());
01563   assert(io != 0);
01564   if (!io) {
01565     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01566                field->className());
01567     return false;
01568   }
01569 
01570   // Add class name attribute
01571   if (!writeAttribute(layerGroup, k_classNameAttrName, 
01572                       field->className())) {
01573     Msg::print(Msg::SevWarning, "Error adding class name attribute.");
01574     return false;
01575   }
01576 
01577   return io->write(layerGroup, field);
01578 }
01579 
01580 //----------------------------------------------------------------------------//
01581 
01582 FieldMapping::Ptr readFieldMapping(hid_t mappingGroup)
01583 {
01584   ClassFactory &factory = ClassFactory::singleton();
01585 
01586   std::string className;
01587 
01588   if (!readAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
01589     Msg::print(Msg::SevWarning, "Couldn't find " + k_mappingTypeAttrName + 
01590               " attribute");
01591     return FieldMapping::Ptr();    
01592   }
01593 
01594   FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
01595   assert(io != 0);
01596   if (!io) {
01597     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01598                className);
01599     return FieldMapping::Ptr();
01600   }
01601 
01602 
01603   FieldMapping::Ptr mapping = io->read(mappingGroup);
01604   if (!mapping) {
01605     Msg::print(Msg::SevWarning, "Couldn't read mapping");
01606     return FieldMapping::Ptr();
01607   }
01608   
01609   return mapping;
01610 }
01611 
01612 //----------------------------------------------------------------------------//
01613 
01614 bool writeFieldMapping(hid_t mappingGroup, FieldMapping::Ptr mapping)
01615 {
01616   ClassFactory &factory = ClassFactory::singleton();
01617 
01618   std::string className = mapping->className();
01619 
01620   if (!writeAttribute(mappingGroup, k_mappingTypeAttrName, className)) {
01621     Msg::print(Msg::SevWarning, "Couldn't add " + className + " attribute");
01622     return false;
01623   }
01624 
01625   FieldMappingIO::Ptr io = factory.createFieldMappingIO(className);
01626   assert(io != 0);
01627   if (!io) {
01628     Msg::print(Msg::SevWarning, "Unable to find class type: " + 
01629                className);
01630     return false;
01631   }
01632 
01633   return io->write(mappingGroup, mapping);
01634 }
01635 
01636 //----------------------------------------------------------------------------//
01637 
01638 FIELD3D_NAMESPACE_SOURCE_CLOSE
01639 
01640 //----------------------------------------------------------------------------//