//-***************************************************************************** // Get the dimensions directly off of the dataspace on the dataset // This isn't suitable for string and wstring void ReadDataSetDimensions( hid_t iParent, const std::string &iName, hsize_t iExtent, Dimensions &oDims ) { // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { // Get the dimensions int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == 1, "H5Sget_simple_extent_ndims() must be 1." ); hsize_t hdim = 0; rank = H5Sget_simple_extent_dims( dspaceId, &hdim, NULL ); oDims.setRank(1); oDims[0] = hdim / iExtent; } else { oDims.setRank(1); oDims[0] = 0; } }
//-***************************************************************************** // Dimensions aren't a scalar, and thus must be read carefully. void ReadDimensions( hid_t iParent, const std::string &iAttrName, Dimensions &oDims ) { // Assume a maximum rank of 128. This is totally reasonable. uint32_t dimVals[128]; size_t readRank; ReadSmallArray( iParent, iAttrName, H5T_STD_U32LE, H5T_NATIVE_UINT32, 128, readRank, ( void * )dimVals ); Dimensions retDims; retDims.setRank( readRank ); for ( size_t r = 0; r < readRank; ++r ) { retDims[r] = ( size_t )dimVals[r]; } oDims = retDims; }
//-***************************************************************************** AbcA::ArraySamplePtr ReadArray( AbcA::ReadArraySampleCachePtr iCache, hid_t iParent, const std::string &iName, const AbcA::DataType &iDataType, hid_t iFileType, hid_t iNativeType ) { // Dispatch string stuff. if ( iDataType.getPod() == kStringPOD ) { return ReadStringArray( iCache, iParent, iName, iDataType ); } else if ( iDataType.getPod() == kWstringPOD ) { return ReadWstringArray( iCache, iParent, iName, iDataType ); } assert( iDataType.getPod() != kStringPOD && iDataType.getPod() != kWstringPOD ); // Open the data set. hid_t dsetId = H5Dopen( iParent, iName.c_str(), H5P_DEFAULT ); ABCA_ASSERT( dsetId >= 0, "Cannot open dataset: " << iName ); DsetCloser dsetCloser( dsetId ); // Read the data space. hid_t dspaceId = H5Dget_space( dsetId ); ABCA_ASSERT( dspaceId >= 0, "Could not get dataspace for dataSet: " << iName ); DspaceCloser dspaceCloser( dspaceId ); AbcA::ArraySample::Key key; bool foundDigest = false; // if we are caching, get the key and see if it is being used if ( iCache ) { key.origPOD = iDataType.getPod(); key.readPOD = key.origPOD; key.numBytes = Util::PODNumBytes( key.readPOD ) * H5Sget_simple_extent_npoints( dspaceId ); foundDigest = ReadKey( dsetId, "key", key ); AbcA::ReadArraySampleID found = iCache->find( key ); if ( found ) { AbcA::ArraySamplePtr ret = found.getSample(); assert( ret ); if ( ret->getDataType().getPod() != iDataType.getPod() ) { ABCA_THROW( "ERROR: Read data type for dset: " << iName << ": " << ret->getDataType() << " does not match expected data type: " << iDataType ); } // Got it! return ret; } } // Okay, we haven't found it in a cache. // Read the data type. hid_t dtypeId = H5Dget_type( dsetId ); ABCA_ASSERT( dtypeId >= 0, "Could not get datatype for dataSet: " << iName ); DtypeCloser dtypeCloser( dtypeId ); ABCA_ASSERT( EquivalentDatatypes( iFileType, dtypeId ), "File DataType clash for array dataset: " << iName ); AbcA::ArraySamplePtr ret; H5S_class_t dspaceClass = H5Sget_simple_extent_type( dspaceId ); if ( dspaceClass == H5S_SIMPLE ) { // Get the dimensions int rank = H5Sget_simple_extent_ndims( dspaceId ); ABCA_ASSERT( rank == 1, "H5Sget_simple_extent_ndims() must be 1." ); hsize_t hdim = 0; rank = H5Sget_simple_extent_dims( dspaceId, &hdim, NULL ); Dimensions dims; std::string dimName = iName + ".dims"; if ( H5Aexists( iParent, dimName.c_str() ) ) { ReadDimensions( iParent, dimName, dims ); } else { dims.setRank(1); dims[0] = hdim / iDataType.getExtent(); } ABCA_ASSERT( dims.numPoints() > 0, "Degenerate dims in Dataset read" ); // Create a buffer into which we shall read. ret = AbcA::AllocateArraySample( iDataType, dims ); assert( ret->getData() ); // And... read into it. herr_t status = H5Dread( dsetId, iNativeType, H5S_ALL, H5S_ALL, H5P_DEFAULT, const_cast<void*>( ret->getData() ) ); ABCA_ASSERT( status >= 0, "H5Dread() failed." ); } else if ( dspaceClass == H5S_NULL ) { Dimensions dims; std::string dimName = iName + ".dims"; if ( H5Aexists( iParent, dimName.c_str() ) ) { ReadDimensions( iParent, dimName, dims ); ABCA_ASSERT( dims.rank() > 0, "Degenerate rank in Dataset read" ); // Num points should be zero here. ABCA_ASSERT( dims.numPoints() == 0, "Expecting zero points in dimensions" ); } else { dims.setRank(1); dims[0] = 0; } ret = AbcA::AllocateArraySample( iDataType, dims ); } else { ABCA_THROW( "Unexpected scalar dataspace encountered." ); } // Store if there is a cache. if ( foundDigest && iCache ) { AbcA::ReadArraySampleID stored = iCache->store( key, ret ); if ( stored ) { return stored.getSample(); } } // Otherwise, just leave! ArraySamplePtr returned by AllocateArraySample // already has fancy-dan deleter built in. // I REALLY LOVE SMART PTRS. return ret; }
void readWriteColorArrayProperty(const std::string &archiveName) { { OArchive archive( Alembic::AbcCoreHDF5::WriteArchive(), archiveName, ErrorHandler::kThrowPolicy ); OObject archiveTop = archive.getTop(); OObject child( archiveTop, "test" ); OCompoundProperty childProps = child.getProperties(); OC3fArrayProperty shades( childProps, "shades", TimeSamplingType( 1.0 ) ); std::vector < C3f > grays(8); grays[0].x = 0.0; grays[0].y = 0.0; grays[0].z = 0.0; grays[1].x = 0.125; grays[1].y = 0.125; grays[1].z = 0.125; grays[2].x = 0.25; grays[2].y = 0.25; grays[2].z = 0.25; grays[3].x = 0.375; grays[3].y = 0.375; grays[3].z = 0.375; grays[4].x = 0.5; grays[4].y = 0.5; grays[4].z = 0.5; grays[5].x = 0.625; grays[5].y = 0.625; grays[5].z = 0.625; grays[6].x = 0.75; grays[6].y = 0.75; grays[6].z = 0.75; grays[7].x = 0.875; grays[7].y = 0.875; grays[7].z = 0.875; // let's write 4 different color3f[2] Dimensions d; d.setRank(2); d[0] = 2; d[1] = 4; C3fArraySample cas(&(grays.front()), d); shades.set(cas); } { // now read it IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); const unsigned int numChildren = archiveTop.getNumChildren(); IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); ICompoundProperty props = child.getProperties(); IC3fArrayProperty shades( props, "shades" ); C3fArraySamplePtr samplePtr; shades.get( samplePtr ); ABCA_ASSERT( samplePtr->getDimensions().rank() == 2, "Incorrect rank on the sample." ); ABCA_ASSERT( samplePtr->getDimensions().numPoints() == 8, "Incorrect number of total points." ); ABCA_ASSERT( samplePtr->getDimensions()[0] == 2, "Incorrect size on dimension 0." ); ABCA_ASSERT( samplePtr->getDimensions()[1] == 4, "Incorrect size on dimension 1." ); for (size_t i = 0; i < 8; ++i) { ABCA_ASSERT( (*samplePtr)[i].x == i/8.0 && (*samplePtr)[i].x == (*samplePtr)[i].y && (*samplePtr)[i].x == (*samplePtr)[i].z, "Color [" << i << "] is incorrect."); } } }
void readWriteColorArrayProperty(const std::string &archiveName, bool useOgawa) { { OArchive archive; if (useOgawa) { archive = OArchive( Alembic::AbcCoreOgawa::WriteArchive(), archiveName, ErrorHandler::kThrowPolicy ); } else { archive = OArchive( Alembic::AbcCoreHDF5::WriteArchive(), archiveName, ErrorHandler::kThrowPolicy ); } OObject archiveTop = archive.getTop(); OObject child( archiveTop, "test" ); OCompoundProperty childProps = child.getProperties(); OC3fArrayProperty shades( childProps, "shades", 0 ); std::vector < C3f > grays(8); grays[0].x = 0.0; grays[0].y = 0.0; grays[0].z = 0.0; grays[1].x = 0.125; grays[1].y = 0.125; grays[1].z = 0.125; grays[2].x = 0.25; grays[2].y = 0.25; grays[2].z = 0.25; grays[3].x = 0.375; grays[3].y = 0.375; grays[3].z = 0.375; grays[4].x = 0.5; grays[4].y = 0.5; grays[4].z = 0.5; grays[5].x = 0.625; grays[5].y = 0.625; grays[5].z = 0.625; grays[6].x = 0.75; grays[6].y = 0.75; grays[6].z = 0.75; grays[7].x = 0.875; grays[7].y = 0.875; grays[7].z = 0.875; // let's write 4 different color3f[2] Dimensions d; d.setRank(2); d[0] = 2; d[1] = 4; C3fArraySample cas(&(grays.front()), d); shades.set(cas); } { // now read it AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); TESTING_ASSERT( (useOgawa && coreType == AbcF::IFactory::kOgawa) || (!useOgawa && coreType == AbcF::IFactory::kHDF5) ); IObject archiveTop = archive.getTop(); IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); ICompoundProperty props = child.getProperties(); IC3fArrayProperty shades( props, "shades" ); C3fArraySamplePtr samplePtr; shades.get( samplePtr ); ABCA_ASSERT( samplePtr->getDimensions().rank() == 2, "Incorrect rank on the sample." ); ABCA_ASSERT( samplePtr->getDimensions().numPoints() == 8, "Incorrect number of total points." ); ABCA_ASSERT( samplePtr->getDimensions()[0] == 2, "Incorrect size on dimension 0." ); ABCA_ASSERT( samplePtr->getDimensions()[1] == 4, "Incorrect size on dimension 1." ); Alembic::Util::Dimensions dims; shades.getDimensions( dims ); ABCA_ASSERT( dims.rank() == 2, "Incorrect rank on the sample." ); ABCA_ASSERT( dims.numPoints() == 8, "Incorrect number of total points." ); ABCA_ASSERT( dims[0] == 2, "Incorrect size on dimension 0." ); ABCA_ASSERT( dims[1] == 4, "Incorrect size on dimension 1." ); for (size_t i = 0; i < 8; ++i) { ABCA_ASSERT( (*samplePtr)[i].x == i/8.0 && (*samplePtr)[i].x == (*samplePtr)[i].y && (*samplePtr)[i].x == (*samplePtr)[i].z, "Color [" << i << "] is incorrect."); } double start, end; GetArchiveStartAndEndTime( archive, start, end ); TESTING_ASSERT( almostEqual(start, 0.0) ); TESTING_ASSERT( almostEqual(end, 0.0) ); } }