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   // RTTI replacement ----------------------------------------------------------
00088 
00089   typedef DenseFieldIO class_type;
00090   DEFINE_FIELD_RTTI_CONCRETE_CLASS;
00091 
00092   static const char* classType()
00093   {
00094     return "DenseFieldIO";
00095   }
00096 
00097   // Constructors --------------------------------------------------------------
00098 
00100   DenseFieldIO() 
00101    : FieldIO()
00102   { }
00103 
00105   virtual ~DenseFieldIO() 
00106   { /* Empty */ }
00107 
00108   static FieldIO::Ptr create()
00109   { return Ptr(new DenseFieldIO); }
00110 
00111   // From FieldIO --------------------------------------------------------------
00112 
00116   virtual FieldBase::Ptr read(hid_t layerGroup, const std::string &filename, 
00117                               const std::string &layerPath,
00118                               DataTypeEnum typeEnum);
00119 
00123   virtual bool write(hid_t layerGroup, FieldBase::Ptr field);
00124 
00126   virtual std::string className() const
00127   { return "DenseField"; }
00128   
00129 private:
00130 
00131   // Internal methods ----------------------------------------------------------
00132 
00134   template <class Data_T>
00135   bool writeInternal(hid_t layerGroup, 
00136                      typename DenseField<Data_T>::Ptr field);
00137 
00139   template <class Data_T>
00140   bool writeData(hid_t dataSet, typename DenseField<Data_T>::Ptr field,
00141                  Data_T dummy);
00142 
00144   template <class Data_T>
00145   typename DenseField<Data_T>::Ptr readData(hid_t dataSet, const Box3i &extents,
00146                                             const Box3i &dataW);
00147 
00148   // Strings -------------------------------------------------------------------
00149 
00150   static const int         k_versionNumber;
00151   static const std::string k_versionAttrName;
00152   static const std::string k_extentsStr;
00153   static const std::string k_dataWindowStr;
00154   static const std::string k_componentsStr;
00155   static const std::string k_dataStr;
00156 
00157   // Typedefs ------------------------------------------------------------------
00158 
00160   typedef FieldIO base;
00161 
00162 };
00163 
00164 //----------------------------------------------------------------------------//
00165 // Templated methods
00166 //----------------------------------------------------------------------------//
00167 
00169 template <class Data_T>
00170 bool DenseFieldIO::writeInternal(hid_t layerGroup, 
00171                                  typename DenseField<Data_T>::Ptr field)
00172 {
00173   using namespace Exc;
00174   using namespace Hdf5Util;
00175 
00176   const V3i& memSize = field->internalMemSize();
00177   int size[3];
00178   size[0] = memSize.x;
00179   size[1] = memSize.y;
00180   size[2] = memSize.z;
00181 
00182   int components = FieldTraits<Data_T>::dataDims();
00183 
00184   hsize_t totalSize[1];
00185   totalSize[0] = size[0] * size[1] * size[2] * components;
00186 
00187   // Make sure chunk size isn't too big.
00188   hsize_t preferredChunkSize = 4096 * 16;
00189   const hsize_t chunkSize = std::min(preferredChunkSize, totalSize[0] / 2);
00190 
00191   Box3i ext(field->extents()), dw(field->dataWindow());
00192 
00193   // Add extents attribute ---
00194 
00195   int extents[6] = 
00196     { ext.min.x, ext.min.y, ext.min.z, ext.max.x, ext.max.y, ext.max.z };
00197 
00198   if (!writeAttribute(layerGroup, k_extentsStr, 6, extents[0])) {
00199     throw WriteAttributeException("Couldn't write attribute " + k_extentsStr);
00200   }
00201 
00202   // Add data window attribute ---
00203 
00204   int dataWindow[6] = 
00205     { dw.min.x, dw.min.y, dw.min.z, dw.max.x, dw.max.y, dw.max.z };
00206 
00207   if (!writeAttribute(layerGroup, k_dataWindowStr, 6, dataWindow[0])) {
00208     throw WriteAttributeException("Couldn't write attribute " + k_dataWindowStr);
00209   }
00210 
00211   // Add components attribute ---
00212 
00213   if (!writeAttribute(layerGroup, k_componentsStr, 1, components)) {
00214     throw WriteAttributeException("Couldn't write attribute " + k_componentsStr);
00215   }
00216 
00217   // Add data to file ---
00218 
00219   H5ScopedScreate dataSpace(H5S_SIMPLE);
00220 
00221   if (dataSpace.id() < 0) {
00222     throw CreateDataSpaceException("Couldn't create data space in "
00223                                    "DenseFieldIO::writeInternal");
00224   }
00225 
00226   // Create a "simple" data structure ---
00227 
00228   H5Sset_extent_simple(dataSpace.id(), 1, totalSize, NULL);
00229 
00230   // Set up gzip property list
00231   bool gzipAvailable = checkHdf5Gzip();
00232   hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE);
00233   if (gzipAvailable) {
00234     herr_t status = H5Pset_deflate(dcpl, 9);
00235     if (status < 0) {
00236       return false;
00237     }
00238     status = H5Pset_chunk(dcpl, 1, &chunkSize);
00239     if (status < 0) {
00240       return false;
00241     }    
00242   }
00243   
00244   H5ScopedDcreate dataSet(layerGroup, k_dataStr, 
00245                           DataTypeTraits<Data_T>::h5type(), 
00246                           dataSpace.id(), 
00247                           H5P_DEFAULT, dcpl, H5P_DEFAULT);
00248 
00249   if (dataSet.id() < 0) {
00250     throw CreateDataSetException("Couldn't create data set in "
00251                                  "DenseFieldIO::writeInternal");
00252   }
00253 
00254   // Call out to the templated function, it will figure out how to get
00255   // the data into the file in the appropriate fashion.
00256   if (!writeData<Data_T>(dataSet.id(), field, Data_T(0.0f))) {
00257     throw WriteLayerException("Error writing layer");
00258   }
00259 
00260   return true; 
00261 }
00262 
00263 //----------------------------------------------------------------------------//
00264 
00265 template <class Data_T>
00266 bool DenseFieldIO::writeData(hid_t dataSet, 
00267                              typename DenseField<Data_T>::Ptr field,
00268                              Data_T dummy)
00269 { 
00270   using namespace Hdf5Util;
00271 
00272   hid_t err = H5Dwrite(dataSet, 
00273                        DataTypeTraits<Data_T>::h5type(), 
00274                        H5S_ALL, H5S_ALL, 
00275                        H5P_DEFAULT, &(*field->begin()));
00276 
00277   if (err < 0) {
00278     throw Exc::WriteLayerException("Error writing layer in "
00279                                    "DenseFieldIO::writeData");
00280   }
00281 
00282   return true;
00283 }
00284 
00285 //----------------------------------------------------------------------------//
00286 
00287 template <class Data_T>
00288 typename DenseField<Data_T>::Ptr 
00289 DenseFieldIO::readData(hid_t dataSet, const Box3i &extents, const Box3i &dataW)
00290 {
00291   typename DenseField<Data_T>::Ptr field(new DenseField<Data_T>);
00292   field->setSize(extents, dataW);
00293 
00294   if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(), 
00295               H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin())) < 0) 
00296   {
00297     std::string typeName = "DenseField<" + 
00298       DataTypeTraits<Data_T>::name() + ">";
00299     throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
00300   } 
00301 
00302   return field;
00303 }
00304 
00305 //----------------------------------------------------------------------------//
00306 
00307 FIELD3D_NAMESPACE_HEADER_CLOSE
00308 
00309 //----------------------------------------------------------------------------//
00310 
00311 #endif // Include guard