Field3D
DenseFieldIO.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_DenseFieldIO_H_
00045 #define _INCLUDED_Field3D_DenseFieldIO_H_
00046 
00047 //----------------------------------------------------------------------------//
00048 
00049 #include <string>
00050 
00051 #include <boost/intrusive_ptr.hpp>
00052 
00053 #include <hdf5.h>
00054 
00055 #include "DenseField.h"
00056 #include "Exception.h"
00057 #include "FieldIO.h"
00058 #include "Field3DFile.h"
00059 #include "Hdf5Util.h"
00060 
00061 //----------------------------------------------------------------------------//
00062 
00063 #include "ns.h"
00064 
00065 FIELD3D_NAMESPACE_OPEN
00066 
00067 //----------------------------------------------------------------------------//
00068 // DenseFieldIO
00069 //----------------------------------------------------------------------------//
00070 
00076 //----------------------------------------------------------------------------//
00077 
00078 class DenseFieldIO : public FieldIO 
00079 {
00080 
00081 public:
00082 
00083   // Typedefs ------------------------------------------------------------------
00084   
00085   typedef boost::intrusive_ptr<DenseFieldIO> Ptr;
00086 
00087   // Constructors --------------------------------------------------------------
00088 
00090   DenseFieldIO() 
00091    : FieldIO()
00092   { }
00093 
00095   virtual ~DenseFieldIO() 
00096   { /* Empty */ }
00097 
00098 
00099   static FieldIO::Ptr create()
00100   { return Ptr(new DenseFieldIO); }
00101 
00102   // From FieldIO --------------------------------------------------------------
00103 
00107   virtual FieldBase::Ptr read(hid_t layerGroup, const std::string &filename, 
00108                               const std::string &layerPath,
00109                               DataTypeEnum typeEnum);
00110 
00114   virtual bool write(hid_t layerGroup, FieldBase::Ptr field);
00115 
00117   virtual std::string className() const
00118   { return std::string("DenseField"); }
00119 
00120 private:
00121 
00122   // Internal methods ----------------------------------------------------------
00123 
00125   template <class Data_T>
00126   bool writeInternal(hid_t layerGroup, 
00127                      typename DenseField<Data_T>::Ptr field);
00128 
00130   template <class Data_T>
00131   bool writeData(hid_t dataSet, typename DenseField<Data_T>::Ptr field,
00132                  Data_T dummy);
00133 
00135   template <class Data_T>
00136   typename DenseField<Data_T>::Ptr readData(hid_t dataSet, const Box3i &extents,
00137                                             const Box3i &dataW);
00138 
00139   // Strings -------------------------------------------------------------------
00140 
00141   static const int         k_versionNumber;
00142   static const std::string k_versionAttrName;
00143   static const std::string k_extentsStr;
00144   static const std::string k_dataWindowStr;
00145   static const std::string k_componentsStr;
00146   static const std::string k_dataStr;
00147 
00148 };
00149 
00150 //----------------------------------------------------------------------------//
00151 // Templated methods
00152 //----------------------------------------------------------------------------//
00153 
00155 template <class Data_T>
00156 bool DenseFieldIO::writeInternal(hid_t layerGroup, 
00157                                  typename DenseField<Data_T>::Ptr field)
00158 {
00159   using namespace Exc;
00160   using namespace Hdf5Util;
00161 
00162   const V3i& memSize = field->internalMemSize();
00163   int size[3];
00164   size[0] = memSize.x;
00165   size[1] = memSize.y;
00166   size[2] = memSize.z;
00167 
00168   int components = FieldTraits<Data_T>::dataDims();
00169 
00170   hsize_t totalSize[1];
00171   totalSize[0] = size[0] * size[1] * size[2] * components;
00172 
00173   // Make sure chunk size isn't too big.
00174   hsize_t preferredChunkSize = 4096 * 16;
00175   const hsize_t chunkSize = std::min(preferredChunkSize, totalSize[0] / 2);
00176 
00177   Box3i ext(field->extents()), dw(field->dataWindow());
00178 
00179   // Add extents attribute ---
00180 
00181   int extents[6] = 
00182     { ext.min.x, ext.min.y, ext.min.z, ext.max.x, ext.max.y, ext.max.z };
00183 
00184   if (!writeAttribute(layerGroup, k_extentsStr, 6, extents[0])) {
00185     throw WriteAttributeException("Couldn't write attribute " + k_extentsStr);
00186   }
00187 
00188   // Add data window attribute ---
00189 
00190   int dataWindow[6] = 
00191     { dw.min.x, dw.min.y, dw.min.z, dw.max.x, dw.max.y, dw.max.z };
00192 
00193   if (!writeAttribute(layerGroup, k_dataWindowStr, 6, dataWindow[0])) {
00194     throw WriteAttributeException("Couldn't write attribute " + k_dataWindowStr);
00195   }
00196 
00197   // Add components attribute ---
00198 
00199   if (!writeAttribute(layerGroup, k_componentsStr, 1, components)) {
00200     throw WriteAttributeException("Couldn't write attribute " + k_componentsStr);
00201   }
00202 
00203   // Add data to file ---
00204 
00205   H5ScopedScreate dataSpace(H5S_SIMPLE);
00206 
00207   if (dataSpace.id() < 0) {
00208     throw CreateDataSpaceException("Couldn't create data space in "
00209                                    "DenseFieldIO::writeInternal");
00210   }
00211 
00212   // Create a "simple" data structure ---
00213 
00214   H5Sset_extent_simple(dataSpace.id(), 1, totalSize, NULL);
00215 
00216   // Set up gzip property list
00217   bool gzipAvailable = checkHdf5Gzip();
00218   hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE);
00219   if (gzipAvailable) {
00220     herr_t status = H5Pset_deflate(dcpl, 9);
00221     if (status < 0) {
00222       return false;
00223     }
00224     status = H5Pset_chunk(dcpl, 1, &chunkSize);
00225     if (status < 0) {
00226       return false;
00227     }    
00228   }
00229   
00230   H5ScopedDcreate dataSet(layerGroup, k_dataStr, 
00231                           DataTypeTraits<Data_T>::h5type(), 
00232                           dataSpace.id(), 
00233                           H5P_DEFAULT, dcpl, H5P_DEFAULT);
00234 
00235   if (dataSet.id() < 0) {
00236     throw CreateDataSetException("Couldn't create data set in "
00237                                  "DenseFieldIO::writeInternal");
00238   }
00239 
00240   // Call out to the templated function, it will figure out how to get
00241   // the data into the file in the appropriate fashion.
00242   if (!writeData<Data_T>(dataSet.id(), field, Data_T(0.0f))) {
00243     throw WriteLayerException("Error writing layer");
00244   }
00245 
00246   return true; 
00247 }
00248 
00249 //----------------------------------------------------------------------------//
00250 
00251 template <class Data_T>
00252 bool DenseFieldIO::writeData(hid_t dataSet, 
00253                              typename DenseField<Data_T>::Ptr field,
00254                              Data_T dummy)
00255 { 
00256   using namespace Hdf5Util;
00257 
00258   hid_t err = H5Dwrite(dataSet, 
00259                        DataTypeTraits<Data_T>::h5type(), 
00260                        H5S_ALL, H5S_ALL, 
00261                        H5P_DEFAULT, &(*field->begin()));
00262 
00263   if (err < 0) {
00264     throw Exc::WriteLayerException("Error writing layer in "
00265                                    "DenseFieldIO::writeData");
00266   }
00267 
00268   return true;
00269 }
00270 
00271 //----------------------------------------------------------------------------//
00272 
00273 template <class Data_T>
00274 typename DenseField<Data_T>::Ptr 
00275 DenseFieldIO::readData(hid_t dataSet, const Box3i &extents, const Box3i &dataW)
00276 {
00277   typename DenseField<Data_T>::Ptr field(new DenseField<Data_T>);
00278   field->setSize(extents, dataW);
00279 
00280   if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(), 
00281               H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin())) < 0) 
00282   {
00283     std::string typeName = "DenseField<" + 
00284       DataTypeTraits<Data_T>::name() + ">";
00285     throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
00286   } 
00287 
00288   return field;
00289 }
00290 
00291 //----------------------------------------------------------------------------//
00292 
00293 FIELD3D_NAMESPACE_HEADER_CLOSE
00294 
00295 //----------------------------------------------------------------------------//
00296 
00297 #endif // Include guard