Field3D
SparseDataReader.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_SparseDataReader_H_
00045 #define _INCLUDED_Field3D_SparseDataReader_H_
00046 
00047 //----------------------------------------------------------------------------//
00048 
00049 #include <hdf5.h>
00050 #include <string.h> // for memcpy
00051 #include "Hdf5Util.h"
00052 
00053 //----------------------------------------------------------------------------//
00054 
00055 #include "ns.h"
00056 
00057 FIELD3D_NAMESPACE_OPEN
00058 
00059 //----------------------------------------------------------------------------//
00060 // SparseDataReader
00061 //----------------------------------------------------------------------------//
00062 
00067 template <class Data_T>
00068 class SparseDataReader
00069 {
00070 public:
00071 
00072   // Constructors --------------------------------------------------------------
00073 
00076   SparseDataReader(hid_t location, int valuesPerBlock, int occupiedBlocks);
00077 
00078   // Main methods --------------------------------------------------------------
00079 
00082   void readBlock(int idx, Data_T &result);
00083 
00086   void readBlockList(int idx, const std::vector<Data_T*>& memoryList);
00087 
00088 private:
00089 
00090   // Data members --------------------------------------------------------------
00091 
00092   Hdf5Util::H5ScopedDopen m_dataSet;
00093   Hdf5Util::H5ScopedDget_space m_fileDataSpace;
00094   Hdf5Util::H5ScopedDget_type m_dataType;
00095   Hdf5Util::H5ScopedScreate m_memDataSpace;
00096   
00097   int m_valuesPerBlock;
00098 
00099   const std::string k_dataStr;
00100 };
00101 
00102 //----------------------------------------------------------------------------//
00103 // SparseDataReader implementations
00104 //----------------------------------------------------------------------------//
00105 
00106 template <class Data_T>
00107 SparseDataReader<Data_T>::SparseDataReader(hid_t location, int valuesPerBlock, 
00108                                            int occupiedBlocks) 
00109   : m_valuesPerBlock(valuesPerBlock), 
00110     k_dataStr("data")
00111 {
00112   using namespace Hdf5Util;
00113   using namespace Exc;
00114 
00115   hsize_t dims[2];
00116   hsize_t memDims[1];
00117 
00118   // Open the data set
00119   m_dataSet.open(location, k_dataStr, H5P_DEFAULT);
00120   if (m_dataSet.id() < 0) 
00121     throw OpenDataSetException("Couldn't open data set: " + k_dataStr);
00122     
00123   // Get the space and type
00124   m_fileDataSpace.open(m_dataSet.id());
00125   m_dataType.open(m_dataSet.id());
00126   if (m_fileDataSpace.id() < 0) 
00127     throw GetDataSpaceException("Couldn't get data space");
00128   if (m_dataType.id() < 0)
00129     throw GetDataTypeException("Couldn't get data type");
00130 
00131   // Make the memory data space
00132   memDims[0] = m_valuesPerBlock;
00133   m_memDataSpace.create(H5S_SIMPLE);
00134   H5Sset_extent_simple(m_memDataSpace.id(), 1, memDims, NULL);
00135 
00136   // Get the dimensions and check they match
00137   H5Sget_simple_extent_dims(m_fileDataSpace.id(), dims, NULL);
00138   if (dims[1] != static_cast<hsize_t>(m_valuesPerBlock)) {
00139     throw FileIntegrityException("Block length mismatch in "
00140                                  "SparseDataReader");
00141   }
00142   if (dims[0] != static_cast<hsize_t>(occupiedBlocks)) 
00143     throw FileIntegrityException("Block count mismatch in "
00144                                  "SparseDataReader");
00145 }
00146 
00147 //----------------------------------------------------------------------------//
00148 
00149 template <class Data_T>
00150 void SparseDataReader<Data_T>::readBlock(int idx, Data_T &result)
00151 {
00152   using namespace Hdf5Util;
00153   using namespace Exc;
00154 
00155   hsize_t offset[2];
00156   hsize_t count[2];
00157   herr_t status;
00158     
00159   offset[0] = idx;             // Index of block
00160   offset[1] = 0;               // Index of first data in block. Always 0
00161   count[0] = 1;                // Number of columns to read. Always 1
00162   count[1] = m_valuesPerBlock; // Number of values in one column
00163 
00164   status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET, 
00165                                offset, NULL, count, NULL);
00166   if (status < 0) {
00167     throw ReadHyperSlabException("Couldn't select slab " + 
00168                                  boost::lexical_cast<std::string>(idx));
00169   }
00170 
00171   status = H5Dread(m_dataSet.id(), DataTypeTraits<Data_T>::h5type(), 
00172                    m_memDataSpace.id(), m_fileDataSpace.id(), 
00173                    H5P_DEFAULT, &result);
00174 }
00175 
00176 //----------------------------------------------------------------------------//
00177 
00178 template <class Data_T>
00179 void SparseDataReader<Data_T>::readBlockList
00180 (int idxLo, const std::vector<Data_T*>& memoryList)
00181 {
00182   using namespace Hdf5Util;
00183   using namespace Exc;
00184 
00185   hsize_t offset[2];
00186   hsize_t count[2];
00187   herr_t status;
00188 
00189   offset[0] = idxLo;            // Index of block
00190   offset[1] = 0;                // Index of first data in block. Always 0
00191   count[0] = memoryList.size(); // Number of columns to read.
00192   count[1] = m_valuesPerBlock;  // Number of values in one column
00193   
00194   status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET, 
00195                                offset, NULL, count, NULL);
00196   if (status < 0) {
00197     throw ReadHyperSlabException("Couldn't select slab " + 
00198                                  boost::lexical_cast<std::string>(idxLo));
00199   }
00200 
00201   // Make the memory data space ---
00202  
00203   Hdf5Util::H5ScopedScreate localMemDataSpace;
00204   hsize_t memDims[2];  
00205   memDims[0] = memoryList.size();
00206   memDims[1] = m_valuesPerBlock;
00207   localMemDataSpace.create(H5S_SIMPLE);
00208   H5Sset_extent_simple(localMemDataSpace.id(), 2, memDims, NULL);
00209 
00210   // Setup the temporary memory region ---
00211 
00212   int bytesPerValue = 0;
00213   {
00214     hid_t t = DataTypeTraits<Data_T>::h5type();
00215     if (t == H5T_NATIVE_CHAR)
00216       bytesPerValue = 1;
00217     else if (t == H5T_NATIVE_SHORT)
00218       bytesPerValue = 2;
00219     else if (t == H5T_NATIVE_FLOAT)
00220       bytesPerValue = 4;
00221     else if (t == H5T_NATIVE_DOUBLE)
00222       bytesPerValue = 8;
00223   }
00224 
00225   int dim = sizeof(Data_T) / bytesPerValue;
00226   std::vector<Data_T> bigblock(memoryList.size() * m_valuesPerBlock/dim);
00227 
00228   status = H5Dread(m_dataSet.id(), 
00229                    DataTypeTraits<Data_T>::h5type(), 
00230                    localMemDataSpace.id(),
00231                    m_fileDataSpace.id(), 
00232                    H5P_DEFAULT, &bigblock[0]);
00233 
00234   if (status < 0) {
00235     throw Hdf5DataReadException("Couldn't read slab " + 
00236                                 boost::lexical_cast<std::string>(idxLo));
00237   }
00238 
00239   // Distribute block data into memory slots ---
00240   for (size_t i = 0; i < memoryList.size(); ++i) {
00241     memcpy(memoryList[i], 
00242            &bigblock[i * m_valuesPerBlock / dim],
00243            bytesPerValue * m_valuesPerBlock);
00244   }
00245 }
00246 
00247 //----------------------------------------------------------------------------//
00248 
00249 FIELD3D_NAMESPACE_HEADER_CLOSE
00250 
00251 //----------------------------------------------------------------------------//
00252 
00253 #endif