Field3D
SparseDataReader.h
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
42 //----------------------------------------------------------------------------//
43 
44 #ifndef _INCLUDED_Field3D_SparseDataReader_H_
45 #define _INCLUDED_Field3D_SparseDataReader_H_
46 
47 //----------------------------------------------------------------------------//
48 
49 #include <hdf5.h>
50 #include <string.h> // for memcpy
51 #include "Hdf5Util.h"
52 
53 //----------------------------------------------------------------------------//
54 
55 #include "ns.h"
56 
58 
59 //----------------------------------------------------------------------------//
60 // SparseDataReader
61 //----------------------------------------------------------------------------//
62 
67 template <class Data_T>
69 {
70 public:
71 
72  // Constructors --------------------------------------------------------------
73 
76  SparseDataReader(hid_t location, int valuesPerBlock, int occupiedBlocks);
77 
78  // Main methods --------------------------------------------------------------
79 
82  void readBlock(int idx, Data_T &result);
83 
86  void readBlockList(int idx, const std::vector<Data_T*>& memoryList);
87 
88 private:
89 
90  // Data members --------------------------------------------------------------
91 
96 
98 
99  const std::string k_dataStr;
100 };
101 
102 //----------------------------------------------------------------------------//
103 // SparseDataReader implementations
104 //----------------------------------------------------------------------------//
105 
106 template <class Data_T>
107 SparseDataReader<Data_T>::SparseDataReader(hid_t location, int valuesPerBlock,
108  int occupiedBlocks)
109  : m_valuesPerBlock(valuesPerBlock),
110  k_dataStr("data")
111 {
112  using namespace Hdf5Util;
113  using namespace Exc;
114 
115  hsize_t dims[2];
116  hsize_t memDims[1];
117 
118  // Open the data set
119  m_dataSet.open(location, k_dataStr, H5P_DEFAULT);
120  if (m_dataSet.id() < 0)
121  throw OpenDataSetException("Couldn't open data set: " + k_dataStr);
122 
123  // Get the space and type
126  if (m_fileDataSpace.id() < 0)
127  throw GetDataSpaceException("Couldn't get data space");
128  if (m_dataType.id() < 0)
129  throw GetDataTypeException("Couldn't get data type");
130 
131  // Make the memory data space
132  memDims[0] = m_valuesPerBlock;
133  m_memDataSpace.create(H5S_SIMPLE);
134  H5Sset_extent_simple(m_memDataSpace.id(), 1, memDims, NULL);
135 
136  // Get the dimensions and check they match
137  H5Sget_simple_extent_dims(m_fileDataSpace.id(), dims, NULL);
138  if (dims[1] != static_cast<hsize_t>(m_valuesPerBlock)) {
139  throw FileIntegrityException("Block length mismatch in "
140  "SparseDataReader");
141  }
142  if (dims[0] != static_cast<hsize_t>(occupiedBlocks))
143  throw FileIntegrityException("Block count mismatch in "
144  "SparseDataReader");
145 }
146 
147 //----------------------------------------------------------------------------//
148 
149 template <class Data_T>
150 void SparseDataReader<Data_T>::readBlock(int idx, Data_T &result)
151 {
152  using namespace Hdf5Util;
153  using namespace Exc;
154 
155  hsize_t offset[2];
156  hsize_t count[2];
157  herr_t status;
158 
159  offset[0] = idx; // Index of block
160  offset[1] = 0; // Index of first data in block. Always 0
161  count[0] = 1; // Number of columns to read. Always 1
162  count[1] = m_valuesPerBlock; // Number of values in one column
163 
164  status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET,
165  offset, NULL, count, NULL);
166  if (status < 0) {
167  throw ReadHyperSlabException("Couldn't select slab " +
168  boost::lexical_cast<std::string>(idx));
169  }
170 
171  status = H5Dread(m_dataSet.id(), DataTypeTraits<Data_T>::h5type(),
173  H5P_DEFAULT, &result);
174 }
175 
176 //----------------------------------------------------------------------------//
177 
178 template <class Data_T>
180 (int idxLo, const std::vector<Data_T*>& memoryList)
181 {
182  using namespace Hdf5Util;
183  using namespace Exc;
184 
185  hsize_t offset[2];
186  hsize_t count[2];
187  herr_t status;
188 
189  offset[0] = idxLo; // Index of block
190  offset[1] = 0; // Index of first data in block. Always 0
191  count[0] = memoryList.size(); // Number of columns to read.
192  count[1] = m_valuesPerBlock; // Number of values in one column
193 
194  status = H5Sselect_hyperslab(m_fileDataSpace.id(), H5S_SELECT_SET,
195  offset, NULL, count, NULL);
196  if (status < 0) {
197  throw ReadHyperSlabException("Couldn't select slab " +
198  boost::lexical_cast<std::string>(idxLo));
199  }
200 
201  // Make the memory data space ---
202 
203  Hdf5Util::H5ScopedScreate localMemDataSpace;
204  hsize_t memDims[2];
205  memDims[0] = memoryList.size();
206  memDims[1] = m_valuesPerBlock;
207  localMemDataSpace.create(H5S_SIMPLE);
208  H5Sset_extent_simple(localMemDataSpace.id(), 2, memDims, NULL);
209 
210  // Setup the temporary memory region ---
211 
212  int bytesPerValue = 0;
213  {
214  hid_t t = DataTypeTraits<Data_T>::h5type();
215  if (t == H5T_NATIVE_CHAR)
216  bytesPerValue = 1;
217  else if (t == H5T_NATIVE_SHORT)
218  bytesPerValue = 2;
219  else if (t == H5T_NATIVE_FLOAT)
220  bytesPerValue = 4;
221  else if (t == H5T_NATIVE_DOUBLE)
222  bytesPerValue = 8;
223  }
224 
225  int dim = sizeof(Data_T) / bytesPerValue;
226  std::vector<Data_T> bigblock(memoryList.size() * m_valuesPerBlock/dim);
227 
228  status = H5Dread(m_dataSet.id(),
230  localMemDataSpace.id(),
231  m_fileDataSpace.id(),
232  H5P_DEFAULT, &bigblock[0]);
233 
234  if (status < 0) {
235  throw Hdf5DataReadException("Couldn't read slab " +
236  boost::lexical_cast<std::string>(idxLo));
237  }
238 
239  // Distribute block data into memory slots ---
240  for (size_t i = 0; i < memoryList.size(); ++i) {
241  memcpy(memoryList[i],
242  &bigblock[i * m_valuesPerBlock / dim],
243  bytesPerValue * m_valuesPerBlock);
244  }
245 }
246 
247 //----------------------------------------------------------------------------//
248 
250 
251 //----------------------------------------------------------------------------//
252 
253 #endif