Field3D
MACFieldIO.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 
00042 //----------------------------------------------------------------------------//
00043 
00044 #ifndef _INCLUDED_Field3D_MACFieldIO_H_
00045 #define _INCLUDED_Field3D_MACFieldIO_H_
00046 
00047 //----------------------------------------------------------------------------//
00048 
00049 #include <string>
00050 
00051 #include <boost/intrusive_ptr.hpp>
00052 
00053 #include <hdf5.h>
00054 
00055 #include "Exception.h"
00056 #include "Field3DFile.h"
00057 #include "FieldIO.h"
00058 #include "Hdf5Util.h"
00059 #include "MACField.h"
00060 
00061 //----------------------------------------------------------------------------//
00062 
00063 #include "ns.h"
00064 
00065 FIELD3D_NAMESPACE_OPEN
00066 
00067 //----------------------------------------------------------------------------//
00068 // MACFieldIO
00069 //----------------------------------------------------------------------------//
00070 
00076 //----------------------------------------------------------------------------//
00077 
00078 class MACFieldIO : public FieldIO 
00079 {
00080 
00081 public:
00082   
00083   // Typedefs ------------------------------------------------------------------
00084   
00085   typedef boost::intrusive_ptr<MACFieldIO> Ptr;
00086 
00087   // Constructors --------------------------------------------------------------
00088 
00090   MACFieldIO() 
00091    : FieldIO()
00092   { }
00093 
00095   virtual ~MACFieldIO() 
00096   { /* Empty */ }
00097 
00098   static FieldIO::Ptr create()
00099   { return Ptr(new MACFieldIO); }
00100 
00101   // From FieldIO --------------------------------------------------------------
00102 
00106   virtual FieldBase::Ptr read(hid_t layerGroup, const std::string &filename, 
00107                               const std::string &layerPath,
00108                               DataTypeEnum typeEnum);
00109 
00112   virtual bool write(hid_t layerGroup, FieldBase::Ptr field);
00113 
00115   virtual std::string className() const
00116   { return std::string("MACField"); }
00117 
00118 private:
00119 
00120   // Internal methods ----------------------------------------------------------
00121 
00123   template <class Data_T>
00124   bool writeInternal(hid_t layerGroup, typename MACField<Data_T>::Ptr field);
00125   
00127   template <class Data_T>
00128   bool writeData(hid_t layerGroup, typename MACField<Data_T>::Ptr field,
00129                  MACComponent comp);
00130 
00132   template <class Data_T>
00133   bool readData(hid_t location, typename MACField<Data_T>::Ptr result);
00134 
00135   // Strings -------------------------------------------------------------------
00136 
00137   static const int         k_versionNumber;
00138   static const std::string k_versionAttrName;
00139   static const std::string k_extentsStr;
00140   static const std::string k_dataWindowStr;
00141   static const std::string k_componentsStr;
00142   static const std::string k_bitsPerComponentStr;
00143   static const std::string k_uDataStr;
00144   static const std::string k_vDataStr;
00145   static const std::string k_wDataStr;
00146 
00147 };
00148  
00149 //----------------------------------------------------------------------------//
00150 // Template methods
00151 //----------------------------------------------------------------------------//
00152 
00154 template <class Data_T>
00155 bool MACFieldIO::writeInternal(hid_t layerGroup, 
00156                                  typename MACField<Data_T>::Ptr field)
00157 {
00158   using namespace Exc;
00159   using namespace Hdf5Util;
00160 
00161   int components = FieldTraits<Data_T>::dataDims();
00162   V3i compSize = field->getComponentSize();
00163   int size[3];
00164   size[0] = compSize.x;
00165   size[1] = compSize.y;
00166   size[2] = compSize.z;
00167 
00168   Box3i ext(field->extents()), dw(field->dataWindow());
00169 
00170   // Add extents attribute ---
00171 
00172   int extents[6] = 
00173     { ext.min.x, ext.min.y, ext.min.z, ext.max.x, ext.max.y, ext.max.z };
00174 
00175   if (!writeAttribute(layerGroup, k_extentsStr, 6, extents[0]))
00176     throw WriteAttributeException("Couldn't write attribute " + k_extentsStr);
00177 
00178   // Add data window attribute ---
00179 
00180   int dataWindow[6] = 
00181     { dw.min.x, dw.min.y, dw.min.z, dw.max.x, dw.max.y, dw.max.z };
00182 
00183   if (!writeAttribute(layerGroup, k_dataWindowStr, 6, dataWindow[0])) 
00184     throw WriteAttributeException("Couldn't write attribute " + k_dataWindowStr);
00185 
00186   // Add components attribute ---
00187 
00188   if (!writeAttribute(layerGroup, k_componentsStr, 1, components)) 
00189     throw WriteAttributeException("Couldn't write attribute " + k_componentsStr);
00190 
00191   // Add the bits per component attribute ---
00192 
00193   int bits = DataTypeTraits<Data_T>::h5bits();
00194   if (!writeAttribute(layerGroup, k_bitsPerComponentStr, 1, bits)) {
00195     throw WriteAttributeException("Couldn't write attribute " + k_bitsPerComponentStr);
00196     return false;    
00197   }
00198 
00199   // Add data to file ---
00200   if (!writeData<Data_T>(layerGroup, field, MACCompU)) {
00201     throw WriteMACFieldDataException("Error writing u_data");
00202     return false;
00203   }    
00204   if (!writeData<Data_T>(layerGroup, field, MACCompV)) {
00205     throw WriteMACFieldDataException("Error writing v_data");
00206     return false;
00207   }    
00208   if (!writeData<Data_T>(layerGroup, field, MACCompW)) {
00209     throw WriteMACFieldDataException("Error writing w_data");
00210     return false;
00211   }    
00212 
00213   return true; 
00214 }
00215 
00216 //----------------------------------------------------------------------------//
00217 
00218 template <class Data_T>
00219 bool MACFieldIO::writeData(hid_t layerGroup, 
00220                            typename MACField<Data_T>::Ptr field,
00221                            MACComponent comp)
00222 {
00223   using namespace Exc;
00224   using namespace Hdf5Util;
00225 
00226   const V3i &compSize = field->getComponentSize();
00227 
00228   hsize_t totalSize[1];
00229   std::string compStr;
00230 
00231   switch (comp) {
00232     case MACCompU:
00233       totalSize[0] = compSize.x;
00234       compStr = k_uDataStr;
00235         break;
00236     case MACCompV:
00237       totalSize[0] = compSize.y;
00238       compStr = k_vDataStr;
00239         break;
00240     case MACCompW:
00241       totalSize[0] = compSize.z;
00242       compStr = k_wDataStr;
00243         break;
00244     default:
00245       break;
00246   }    
00247 
00248   // Make sure chunk size isn't too big.
00249   hsize_t preferredChunkSize = 4096 * 16;
00250   const hsize_t chunkSize = std::min(preferredChunkSize, totalSize[0] / 2);
00251 
00252   H5ScopedScreate dataSpace(H5S_SIMPLE);
00253 
00254   if (dataSpace.id() < 0) 
00255     throw CreateDataSpaceException("Couldn't create data space in "
00256                                    "MACFieldIO::writeData");
00257 
00258   // Create a "simple" data structure ---
00259 
00260   H5Sset_extent_simple(dataSpace.id(), 1, totalSize, NULL);
00261 
00262   // Set up gzip property list
00263   bool gzipAvailable = checkHdf5Gzip();
00264   hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE);
00265   if (gzipAvailable) {
00266     herr_t status = H5Pset_deflate(dcpl, 9);
00267     if (status < 0) {
00268       return false;
00269     }
00270     status = H5Pset_chunk(dcpl, 1, &chunkSize);
00271     if (status < 0) {
00272       return false;
00273     }    
00274   }
00275   
00276   H5ScopedDcreate dataSet(layerGroup, compStr, 
00277                           DataTypeTraits<Data_T>::h5type(), 
00278                           dataSpace.id(), 
00279                           H5P_DEFAULT, dcpl, H5P_DEFAULT);
00280 
00281   if (dataSet.id() < 0) 
00282     throw CreateDataSetException("Couldn't create data set in "
00283                                  "MACFieldIO::writeData");
00284 
00285   hid_t err = H5Dwrite(dataSet, 
00286                        DataTypeTraits<Data_T>::h5type(), 
00287                        H5S_ALL, H5S_ALL, 
00288                        H5P_DEFAULT, &(*field->cbegin_comp(comp)));
00289   if (err < 0) 
00290     throw Exc::WriteLayerException("Error writing layer in "
00291                                    "MACFieldIO::writeData");
00292 
00293 
00294   return true;
00295 }
00296 
00297 //----------------------------------------------------------------------------//
00298 
00299 template <class Data_T>
00300 bool MACFieldIO::readData(hid_t layerGroup,
00301                           typename MACField<Data_T>::Ptr field)
00302 {
00303   using namespace std;
00304   using namespace Exc;
00305   using namespace Hdf5Util;
00306 
00307   hsize_t dims[1];
00308 
00309   // read u_data
00310   {
00311 
00312     H5ScopedDopen dataSet(layerGroup, k_uDataStr, H5P_DEFAULT);
00313     if (dataSet.id() < 0) 
00314       throw OpenDataSetException("Couldn't open data set: " + k_uDataStr);
00315 
00316     H5ScopedDget_space dataSpace(dataSet.id());
00317     H5ScopedDget_type dataType(dataSet.id());
00318     H5Sget_simple_extent_dims(dataSpace.id(), dims, NULL);
00319 
00320     if (dataSpace.id() < 0) 
00321       throw GetDataSpaceException("Couldn't get data space");
00322 
00323     if (dataType.id() < 0)
00324       throw GetDataTypeException("Couldn't get data type");
00325 
00326     if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(), 
00327                 H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin_comp(MACCompU))) < 0) 
00328       {
00329         std::string typeName = "MACField<" + 
00330           DataTypeTraits<Data_T>::name() + ">";
00331         throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
00332       } 
00333 
00334   }
00335 
00336   // read v_data
00337   {
00338 
00339     H5ScopedDopen dataSet(layerGroup, k_vDataStr, H5P_DEFAULT);
00340     if (dataSet.id() < 0) 
00341       throw OpenDataSetException("Couldn't open data set: " + k_vDataStr);
00342 
00343     H5ScopedDget_space dataSpace(dataSet.id());
00344     H5ScopedDget_type dataType(dataSet.id());
00345     H5Sget_simple_extent_dims(dataSpace.id(), dims, NULL);
00346 
00347     if (dataSpace.id() < 0) 
00348       throw GetDataSpaceException("Couldn't get data space");
00349 
00350     if (dataType.id() < 0)
00351       throw GetDataTypeException("Couldn't get data type");
00352 
00353 
00354     if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(), 
00355                 H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin_comp(MACCompV))) < 0) 
00356       {
00357         std::string typeName = "MACField<" + 
00358           DataTypeTraits<Data_T>::name() + ">";
00359         throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
00360       } 
00361 
00362   }
00363 
00364   // read w_data
00365   {
00366 
00367     H5ScopedDopen dataSet(layerGroup, k_wDataStr, H5P_DEFAULT);
00368     if (dataSet.id() < 0) 
00369       throw OpenDataSetException("Couldn't open data set: " + k_wDataStr);
00370 
00371     H5ScopedDget_space dataSpace(dataSet.id());
00372     H5ScopedDget_type dataType(dataSet.id());
00373     H5Sget_simple_extent_dims(dataSpace.id(), dims, NULL);
00374 
00375     if (dataSpace.id() < 0) 
00376       throw GetDataSpaceException("Couldn't get data space");
00377 
00378     if (dataType.id() < 0)
00379       throw GetDataTypeException("Couldn't get data type");
00380 
00381 
00382     if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(), 
00383                 H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin_comp(MACCompW))) < 0) 
00384       {
00385         std::string typeName = "MACField<" + 
00386           DataTypeTraits<Data_T>::name() + ">";
00387         throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
00388       } 
00389 
00390   }
00391 
00392   return true;
00393 }
00394 
00395 //----------------------------------------------------------------------------//
00396 
00397 FIELD3D_NAMESPACE_HEADER_CLOSE
00398 
00399 //----------------------------------------------------------------------------//
00400 
00401 #endif // Include guard