Field3D
DenseFieldIO.cpp
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#include "DenseFieldIO.h"
45
46#include "OgIO.h"
47
48//----------------------------------------------------------------------------//
49
50using namespace boost;
51using namespace std;
52
53//----------------------------------------------------------------------------//
54
56
57//----------------------------------------------------------------------------//
58// Field3D namespaces
59//----------------------------------------------------------------------------//
60
61using namespace Exc;
62using namespace Hdf5Util;
63
64//----------------------------------------------------------------------------//
65// Static members
66//----------------------------------------------------------------------------//
67
68const int DenseFieldIO::k_versionNumber(1);
69const std::string DenseFieldIO::k_versionAttrName("version");
70const std::string DenseFieldIO::k_extentsStr("extents");
71const std::string DenseFieldIO::k_extentsMinStr("extents_min");
72const std::string DenseFieldIO::k_extentsMaxStr("extents_max");
73const std::string DenseFieldIO::k_dataWindowStr("data_window");
74const std::string DenseFieldIO::k_dataWindowMinStr("data_window_min");
75const std::string DenseFieldIO::k_dataWindowMaxStr("data_window_max");
76const std::string DenseFieldIO::k_componentsStr("components");
77const std::string DenseFieldIO::k_bitsPerComponentStr("bits_per_component");
78const std::string DenseFieldIO::k_dataStr("data");
79
80//----------------------------------------------------------------------------//
81
83DenseFieldIO::read(hid_t layerGroup, const std::string &/*filename*/,
84 const std::string &/*layerPath*/,
85 DataTypeEnum typeEnum)
86{
87 Box3i extents, dataW;
88 int components;
89 hsize_t dims[1];
90
91 if (layerGroup == -1)
92 throw BadHdf5IdException("Bad layer group in DenseFieldIO::read");
93
94 int version;
96 throw MissingAttributeException("Couldn't find attribute " +
98
99 if (version != k_versionNumber)
100 throw UnsupportedVersionException("DenseField version not supported: " +
102
103 if (!readAttribute(layerGroup, k_extentsStr, 6, extents.min.x))
104 throw MissingAttributeException("Couldn't find attribute " +
106
108 throw MissingAttributeException("Couldn't find attribute " +
110
111 if (!readAttribute(layerGroup, k_componentsStr, 1, components))
112 throw MissingAttributeException("Couldn't find attribute " +
114
116
117 if (dataSet.id() < 0)
118 throw OpenDataSetException("Couldn't open data set: " + k_dataStr);
119
123
124 if (dataSpace.id() < 0)
125 throw GetDataSpaceException("Couldn't get data space");
126
127 if (dataType.id() < 0)
128 throw GetDataTypeException("Couldn't get data type");
129
130 // Double-check that the sizes match ---
131
132 V3i size(dataW.size() + V3i(1));
133 int calculatedTotal = size.x * size.y * size.z;
134 int reportedSize = dims[0] / components;
135
137 throw FileIntegrityException("Data size doesn't match number of voxels");
138
139 // Build a DenseField to store everything in
140 FieldBase::Ptr result;
141
142 // Read the data ---
143
144 bool isHalf, isFloat, isDouble;
148
149 if (isHalf && components == 1 && typeEnum == DataTypeHalf)
150 result = readData<half>(dataSet.id(), extents, dataW);
151 if (isFloat && components == 1 && typeEnum == DataTypeFloat)
152 result = readData<float>(dataSet.id(), extents, dataW);
153 if (isDouble && components == 1 && typeEnum == DataTypeDouble)
154 result = readData<double>(dataSet.id(), extents, dataW);
155 if (isHalf && components == 3 && typeEnum == DataTypeVecHalf)
156 result = readData<V3h>(dataSet.id(), extents, dataW);
157 if (isFloat && components == 3 && typeEnum == DataTypeVecFloat)
158 result = readData<V3f>(dataSet.id(), extents, dataW);
159 if (isDouble && components == 3 && typeEnum == DataTypeVecDouble)
160 result = readData<V3d>(dataSet.id(), extents, dataW);
161
162 return result;
163}
164
165//----------------------------------------------------------------------------//
166
168DenseFieldIO::read(const OgIGroup &lg, const std::string &/*filename*/,
169 const std::string &/*layerPath*/, OgDataType typeEnum)
170{
171 Box3i extents, dataW;
172
173 if (!lg.isValid()) {
174 throw MissingGroupException("Invalid group in DenseFieldIO::read()");
175 }
176
177 // Check version ---
178
180 if (!versionAttr.isValid()) {
181 throw MissingAttributeException("Couldn't find attribute " +
183 }
184
185 int version = versionAttr.value();
186 if (version != k_versionNumber) {
187 throw UnsupportedVersionException("DenseField version not supported: " +
189 }
190
191 // Get extents ---
192
194 lg.findAttribute<veci32_t>(k_extentsMinStr);
196 lg.findAttribute<veci32_t>(k_extentsMaxStr);
197 if (!extMinAttr.isValid()) {
198 throw MissingAttributeException("Couldn't find attribute " +
200 }
201 if (!extMaxAttr.isValid()) {
202 throw MissingAttributeException("Couldn't find attribute " +
204 }
205
206 extents.min = extMinAttr.value();
207 extents.max = extMaxAttr.value();
208
209 // Get data window ---
210
212 lg.findAttribute<veci32_t>(k_dataWindowMinStr);
214 lg.findAttribute<veci32_t>(k_dataWindowMaxStr);
215 if (!dwMinAttr.isValid()) {
216 throw MissingAttributeException("Couldn't find attribute " +
218 }
219 if (!dwMaxAttr.isValid()) {
220 throw MissingAttributeException("Couldn't find attribute " +
222 }
223
224 dataW.min = dwMinAttr.value();
225 dataW.max = dwMaxAttr.value();
226
227 // Get num components ---
228
230 lg.findAttribute<int>(k_componentsStr);
231 if (!numComponentsAttr.isValid()) {
232 throw MissingAttributeException("Couldn't find attribute " +
234 }
235
236 // Read the data ---
237
238 FieldBase::Ptr result;
239
240 OgDataType typeOnDisk = lg.datasetType(k_dataStr);
241
242 if (typeEnum == typeOnDisk) {
243 if (typeEnum == F3DFloat16) {
244 result = readData<float16_t>(lg, extents, dataW);
245 } else if (typeEnum == F3DFloat32) {
246 result = readData<float32_t>(lg, extents, dataW);
247 } else if (typeEnum == F3DFloat64) {
248 result = readData<float64_t>(lg, extents, dataW);
249 } else if (typeEnum == F3DVec16) {
250 result = readData<vec16_t>(lg, extents, dataW);
251 } else if (typeEnum == F3DVec32) {
252 result = readData<vec32_t>(lg, extents, dataW);
253 } else if (typeEnum == F3DVec64) {
254 result = readData<vec64_t>(lg, extents, dataW);
255 }
256 }
257
258 return result;
259
260}
261
262//----------------------------------------------------------------------------//
263
264bool
265DenseFieldIO::write(hid_t layerGroup, FieldBase::Ptr field)
266{
267 if (layerGroup == -1)
268 throw BadHdf5IdException("Bad layer group in DenseFieldIO::write");
269
270 // Add version attribute
272 1, k_versionNumber))
273 throw WriteAttributeException("Couldn't write attribute " +
275
288
289 bool success = true;
290
291 if (floatField) {
293 }
294 else if (halfField) {
296 }
297 else if (doubleField) {
299 }
300 else if (vecFloatField) {
302 }
303 else if (vecHalfField) {
305 }
306 else if (vecDoubleField) {
308 }
309 else {
310 throw WriteLayerException("DenseFieldIO does not support the given "
311 "DenseField template parameter");
312 }
313
314 return success;
315}
316
317//----------------------------------------------------------------------------//
318
319bool
320DenseFieldIO::write(OgOGroup &layerGroup, FieldBase::Ptr field)
321{
322 using namespace Exc;
323
324 // Add version attribute
326
339
340 bool success = true;
341
342 if (floatField) {
344 }
345 else if (halfField) {
347 }
348 else if (doubleField) {
350 }
351 else if (vecFloatField) {
353 }
354 else if (vecHalfField) {
356 }
357 else if (vecDoubleField) {
359 }
360 else {
361 throw WriteLayerException("DenseFieldIO does not support the given "
362 "DenseField template parameter");
363 }
364
365 return success;
366}
367
368//----------------------------------------------------------------------------//
369// Templated methods
370//----------------------------------------------------------------------------//
371
373template <class Data_T>
374bool DenseFieldIO::writeInternal(hid_t layerGroup,
375 typename DenseField<Data_T>::Ptr field)
376{
377 using namespace Exc;
378 using namespace Hdf5Util;
379
380 const V3i& memSize = field->internalMemSize();
381 int size[3];
382 size[0] = memSize.x;
383 size[1] = memSize.y;
384 size[2] = memSize.z;
385
386 int components = FieldTraits<Data_T>::dataDims();
387
389 totalSize[0] = size[0] * size[1] * size[2] * components;
390
391 // Make sure chunk size isn't too big.
392 hsize_t preferredChunkSize = 4096 * 16;
393 const hsize_t chunkSize = std::min(preferredChunkSize, totalSize[0] / 2);
394
395 Box3i ext(field->extents()), dw(field->dataWindow());
396
397 // Add extents attribute ---
398
399 int extents[6] =
400 { ext.min.x, ext.min.y, ext.min.z, ext.max.x, ext.max.y, ext.max.z };
401
402 if (!writeAttribute(layerGroup, k_extentsStr, 6, extents[0])) {
403 throw WriteAttributeException("Couldn't write attribute " + k_extentsStr);
404 }
405
406 // Add data window attribute ---
407
408 int dataWindow[6] =
409 { dw.min.x, dw.min.y, dw.min.z, dw.max.x, dw.max.y, dw.max.z };
410
411 if (!writeAttribute(layerGroup, k_dataWindowStr, 6, dataWindow[0])) {
412 throw WriteAttributeException("Couldn't write attribute " + k_dataWindowStr);
413 }
414
415 // Add components attribute ---
416
417 if (!writeAttribute(layerGroup, k_componentsStr, 1, components)) {
418 throw WriteAttributeException("Couldn't write attribute " + k_componentsStr);
419 }
420
421 // Add the bits per component attribute ---
422
425 Msg::print(Msg::SevWarning, "Error adding bits per component attribute.");
426 return false;
427 }
428
429 // Add data to file ---
430
432
433 if (dataSpace.id() < 0) {
434 throw CreateDataSpaceException("Couldn't create data space in "
435 "DenseFieldIO::writeInternal");
436 }
437
438 // Create a "simple" data structure ---
439
441
442 // Set up gzip property list
445 if (gzipAvailable) {
447 if (status < 0) {
448 return false;
449 }
451 if (status < 0) {
452 return false;
453 }
454 }
455
458 dataSpace.id(),
460
461 if (dataSet.id() < 0) {
462 throw CreateDataSetException("Couldn't create data set in "
463 "DenseFieldIO::writeInternal");
464 }
465
466 // Call out to the templated function, it will figure out how to get
467 // the data into the file in the appropriate fashion.
468 if (!writeData<Data_T>(dataSet.id(), field, Data_T(0.0f))) {
469 throw WriteLayerException("Error writing layer");
470 }
471
472 return true;
473}
474
475//----------------------------------------------------------------------------//
476
477template <class Data_T>
478bool DenseFieldIO::writeInternal(OgOGroup &layerGroup,
479 typename DenseField<Data_T>::Ptr field)
480{
481 using namespace Exc;
482
483 const int components = FieldTraits<Data_T>::dataDims();
484 const V3i& memSize = field->internalMemSize();
486
487 Box3i ext(field->extents()), dw(field->dataWindow());
488
489 // Add extents attributes ---
490
493
494 // Add data window attributes ---
495
498
499 // Add components attribute ---
500
502
503 // Add the bits per component attribute ---
504
506
507 // Add data to file ---
508
509 const size_t length = memSize[0] * memSize[1] * memSize[2];
510
511 OgODataset<Data_T> data(layerGroup, k_dataStr);
512 data.addData(length, &(*field->begin()));
513
514 return true;
515}
516
517//----------------------------------------------------------------------------//
518
519template <class Data_T>
520bool DenseFieldIO::writeData(hid_t dataSet,
521 typename DenseField<Data_T>::Ptr field,
522 Data_T /* dummy */)
523{
524 using namespace Hdf5Util;
525
529 H5P_DEFAULT, &(*field->begin()));
530
531 if (err < 0) {
532 throw Exc::WriteLayerException("Error writing layer in "
533 "DenseFieldIO::writeData");
534 }
535
536 return true;
537}
538
539//----------------------------------------------------------------------------//
540
541template <class Data_T>
543DenseFieldIO::readData(hid_t dataSet, const Box3i &extents, const Box3i &dataW)
544{
546 field->setSize(extents, dataW);
547
549 H5S_ALL, H5S_ALL, H5P_DEFAULT, &(*field->begin())) < 0)
550 {
551 std::string typeName = "DenseField<" +
553 throw Exc::Hdf5DataReadException("Couldn't read " + typeName + " data");
554 }
555
556 return field;
557}
558
559//----------------------------------------------------------------------------//
560
561template <class Data_T>
563DenseFieldIO::readData(const OgIGroup &layerGroup, const Box3i &extents,
564 const Box3i &dataW)
565{
567 field->setSize(extents, dataW);
568
569 // Open the dataset
570 OgIDataset<Data_T> data = layerGroup.findDataset<Data_T>(k_dataStr);
571 if (!data.isValid()) {
572 throw Exc::ReadDataException("DenseFieldIO::readData() couldn't open "
573 "the dataset.");
574 }
575
576 // Read the data
577 if (!data.getData(0, &(*field->begin()), OGAWA_THREAD)) {
578 throw Exc::ReadDataException("DenseFieldIO::readData() couldn't read "
579 "the dataset.");
580 }
581
582 return field;
583}
584
585//----------------------------------------------------------------------------//
586
588
589//----------------------------------------------------------------------------//
Imath::V3i V3i
Definition SpiMathLib.h:71
Imath::Box3i Box3i
Definition SpiMathLib.h:77
#define FIELD3D_MTX_T
Definition StdMathLib.h:99
Field3D::V3i veci32_t
Definition Traits.h:94
OgDataType
Enumerates the various uses for Ogawa-level groups.
Definition Traits.h:125
@ F3DFloat32
Definition Traits.h:142
@ F3DFloat64
Definition Traits.h:143
@ F3DVec64
Definition Traits.h:148
@ F3DVec32
Definition Traits.h:147
@ F3DFloat16
Definition Traits.h:141
@ F3DVec16
Definition Traits.h:146
DataTypeEnum
Definition Traits.h:108
@ DataTypeFloat
Definition Traits.h:112
@ DataTypeHalf
Definition Traits.h:109
@ DataTypeVecHalf
Definition Traits.h:114
@ DataTypeVecDouble
Definition Traits.h:116
@ DataTypeVecFloat
Definition Traits.h:115
@ DataTypeDouble
Definition Traits.h:113
This subclass of Field stores data in a contiguous std::vector.
Definition DenseField.h:87
const FIELD3D_VEC3_T< size_t > & internalMemSize() const
Returns the internal memory size in each dimension. This is used for example in LinearInterpolator,...
Definition DenseField.h:196
iterator begin()
Iterator to first element.
Definition DenseField.h:602
boost::intrusive_ptr< DenseField > Ptr
Definition DenseField.h:92
boost::intrusive_ptr< FieldBase > Ptr
Definition Field.h:97
const Box3i & extents() const
Returns the extents of the data. This signifies the relevant area that the data exists over....
Definition Field.h:249
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Definition Field.h:253
static int dataDims()
Definition Traits.h:178
Scoped object - creates a dataset on creation and closes it on destruction.
Definition Hdf5Util.h:264
Scoped object - opens a dataset on creation and closes it on destruction.
Definition Hdf5Util.h:387
Scoped object - opens a dataset on creation and closes it on destruction.
Definition Hdf5Util.h:417
Scoped object - opens a dataset on creation and closes it on destruction.
Definition Hdf5Util.h:357
Scoped object - creates a dataspace on creation and closes it on destruction.
Definition Hdf5Util.h:235
void setSize(const V3i &size)
Resizes the object.
Definition Field.h:913
FIELD3D_API bool readAttribute(hid_t location, const std::string &attrName, std::string &value)
Reads a string attribute.
FIELD3D_API bool writeAttribute(hid_t location, const std::string &attrName, const std::string &value)
Writes a string attribute.
FIELD3D_API bool checkHdf5Gzip()
Checks whether gzip is available in the current hdf5 library.
Definition Hdf5Util.cpp:722
Namespace for Exception objects.
Definition Exception.h:57
Contains utility functions and classes for Hdf5 files.
Definition Hdf5Util.h:86
@ SevWarning
Definition Log.h:68
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Definition Log.cpp:70
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition ns.h:60
static std::string name()
Definition Traits.h:267
static int h5bits()