Field3D
DenseFieldIO.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_DenseFieldIO_H_
45 #define _INCLUDED_Field3D_DenseFieldIO_H_
46 
47 //----------------------------------------------------------------------------//
48 
49 #include <string>
50 
51 #include <boost/intrusive_ptr.hpp>
52 
53 #include <hdf5.h>
54 
55 #include "DenseField.h"
56 #include "Exception.h"
57 #include "FieldIO.h"
58 #include "Field3DFile.h"
59 #include "Hdf5Util.h"
60 
61 //----------------------------------------------------------------------------//
62 
63 #include "ns.h"
64 
66 
67 //----------------------------------------------------------------------------//
68 // DenseFieldIO
69 //----------------------------------------------------------------------------//
70 
76 //----------------------------------------------------------------------------//
77 
78 class DenseFieldIO : public FieldIO
79 {
80 
81 public:
82 
83  // Typedefs ------------------------------------------------------------------
84 
85  typedef boost::intrusive_ptr<DenseFieldIO> Ptr;
86 
87  // RTTI replacement ----------------------------------------------------------
88 
91 
92  static const char* classType()
93  {
94  return "DenseFieldIO";
95  }
96 
97  // Constructors --------------------------------------------------------------
98 
101  : FieldIO()
102  { }
103 
105  virtual ~DenseFieldIO()
106  { /* Empty */ }
107 
109  { return Ptr(new DenseFieldIO); }
110 
111  // From FieldIO --------------------------------------------------------------
112 
116  virtual FieldBase::Ptr read(hid_t layerGroup, const std::string &filename,
117  const std::string &layerPath,
118  DataTypeEnum typeEnum);
119 
123  virtual bool write(hid_t layerGroup, FieldBase::Ptr field);
124 
126  virtual std::string className() const
127  { return "DenseField"; }
128 
129 private:
130 
131  // Internal methods ----------------------------------------------------------
132 
134  template <class Data_T>
135  bool writeInternal(hid_t layerGroup,
136  typename DenseField<Data_T>::Ptr field);
137 
139  template <class Data_T>
140  bool writeData(hid_t dataSet, typename DenseField<Data_T>::Ptr field,
141  Data_T dummy);
142 
144  template <class Data_T>
145  typename DenseField<Data_T>::Ptr readData(hid_t dataSet, const Box3i &extents,
146  const Box3i &dataW);
147 
148  // Strings -------------------------------------------------------------------
149 
150  static const int k_versionNumber;
151  static const std::string k_versionAttrName;
152  static const std::string k_extentsStr;
153  static const std::string k_dataWindowStr;
154  static const std::string k_componentsStr;
155  static const std::string k_dataStr;
156 
157  // Typedefs ------------------------------------------------------------------
158 
160  typedef FieldIO base;
161 
162 };
163 
164 //----------------------------------------------------------------------------//
165 // Templated methods
166 //----------------------------------------------------------------------------//
167 
169 template <class Data_T>
170 bool DenseFieldIO::writeInternal(hid_t layerGroup,
171  typename DenseField<Data_T>::Ptr field)
172 {
173  using namespace Exc;
174  using namespace Hdf5Util;
175 
176  const V3i& memSize = field->internalMemSize();
177  int size[3];
178  size[0] = memSize.x;
179  size[1] = memSize.y;
180  size[2] = memSize.z;
181 
182  int components = FieldTraits<Data_T>::dataDims();
183 
184  hsize_t totalSize[1];
185  totalSize[0] = size[0] * size[1] * size[2] * components;
186 
187  // Make sure chunk size isn't too big.
188  hsize_t preferredChunkSize = 4096 * 16;
189  const hsize_t chunkSize = std::min(preferredChunkSize, totalSize[0] / 2);
190 
191  Box3i ext(field->extents()), dw(field->dataWindow());
192 
193  // Add extents attribute ---
194 
195  int extents[6] =
196  { ext.min.x, ext.min.y, ext.min.z, ext.max.x, ext.max.y, ext.max.z };
197 
198  if (!writeAttribute(layerGroup, k_extentsStr, 6, extents[0])) {
199  throw WriteAttributeException("Couldn't write attribute " + k_extentsStr);
200  }
201 
202  // Add data window attribute ---
203 
204  int dataWindow[6] =
205  { dw.min.x, dw.min.y, dw.min.z, dw.max.x, dw.max.y, dw.max.z };
206 
207  if (!writeAttribute(layerGroup, k_dataWindowStr, 6, dataWindow[0])) {
208  throw WriteAttributeException("Couldn't write attribute " + k_dataWindowStr);
209  }
210 
211  // Add components attribute ---
212 
213  if (!writeAttribute(layerGroup, k_componentsStr, 1, components)) {
214  throw WriteAttributeException("Couldn't write attribute " + k_componentsStr);
215  }
216 
217  // Add data to file ---
218 
219  H5ScopedScreate dataSpace(H5S_SIMPLE);
220 
221  if (dataSpace.id() < 0) {
222  throw CreateDataSpaceException("Couldn't create data space in "
223  "DenseFieldIO::writeInternal");
224  }
225 
226  // Create a "simple" data structure ---
227 
228  H5Sset_extent_simple(dataSpace.id(), 1, totalSize, NULL);
229 
230  // Set up gzip property list
231  bool gzipAvailable = checkHdf5Gzip();
232  hid_t dcpl = H5Pcreate(H5P_DATASET_CREATE);
233  if (gzipAvailable) {
234  herr_t status = H5Pset_deflate(dcpl, 9);
235  if (status < 0) {
236  return false;
237  }
238  status = H5Pset_chunk(dcpl, 1, &chunkSize);
239  if (status < 0) {
240  return false;
241  }
242  }
243 
244  H5ScopedDcreate dataSet(layerGroup, k_dataStr,
246  dataSpace.id(),
247  H5P_DEFAULT, dcpl, H5P_DEFAULT);
248 
249  if (dataSet.id() < 0) {
250  throw CreateDataSetException("Couldn't create data set in "
251  "DenseFieldIO::writeInternal");
252  }
253 
254  // Call out to the templated function, it will figure out how to get
255  // the data into the file in the appropriate fashion.
256  if (!writeData<Data_T>(dataSet.id(), field, Data_T(0.0f))) {
257  throw WriteLayerException("Error writing layer");
258  }
259 
260  return true;
261 }
262 
263 //----------------------------------------------------------------------------//
264 
265 template <class Data_T>
266 bool DenseFieldIO::writeData(hid_t dataSet,
267  typename DenseField<Data_T>::Ptr field,
268  Data_T dummy)
269 {
270  using namespace Hdf5Util;
271 
272  hid_t err = H5Dwrite(dataSet,
274  H5S_ALL, H5S_ALL,
275  H5P_DEFAULT, &(*field->begin()));
276 
277  if (err < 0) {
278  throw Exc::WriteLayerException("Error writing layer in "
279  "DenseFieldIO::writeData");
280  }
281 
282  return true;
283 }
284 
285 //----------------------------------------------------------------------------//
286 
287 template <class Data_T>
288 typename DenseField<Data_T>::Ptr
289 DenseFieldIO::readData(hid_t dataSet, const Box3i &extents, const Box3i &dataW)
290 {
291  typename DenseField<Data_T>::Ptr field(new DenseField<Data_T>);
292  field->setSize(extents, dataW);
293 
294  if (H5Dread(dataSet, DataTypeTraits<Data_T>::h5type(),
295  H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin())) < 0)
296  {
297  std::string typeName = "DenseField<" +
299  throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
300  }
301 
302  return field;
303 }
304 
305 //----------------------------------------------------------------------------//
306 
308 
309 //----------------------------------------------------------------------------//
310 
311 #endif // Include guard