00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef HDF5UTILITIES_H 00011 #define HDF5UTILITIES_H 00012 00013 #include "HdfUtilities.h" 00014 00015 #include "AppVerify.h" 00016 #include "DataVariant.h" 00017 #include "Hdf5CustomWriter.h" 00018 #include "Hdf5Dataset.h" 00019 #include "Hdf5Element.h" 00020 #include "Hdf5Group.h" 00021 #include "TypesFile.h" 00022 00023 #include <hdf5.h> 00024 00025 #include <memory> 00026 #include <string> 00027 #include <vector> 00028 00029 /** 00030 * A collection of generic utilities provided to simplify use of the application's HDF API. 00031 */ 00032 namespace HdfUtilities 00033 { 00034 /** 00035 * Represents a version of H5T_INTEGER type that the HdfPlugInLib does not know how to parse. 00036 */ 00037 static const std::string UNKNOWN_INTEGER_TYPE = "Unknown HDF5 Integer Type"; 00038 00039 /** 00040 * Represents a version of H5T_FLOAT type that the HdfPlugInLib does not know how to parse. 00041 */ 00042 static const std::string UNKNOWN_FLOAT_TYPE = "Unknown HDF5 Float Type"; 00043 00044 /** 00045 * Represents the H5T_TIME type. The HdfPlugInLib will not parse data of this type. 00046 */ 00047 static const std::string TIME_TYPE = "HDF5 Time Type"; 00048 00049 /** 00050 * Represents the H5T_ARRAY type. The HdfPlugInLib will not parse data of this type. 00051 */ 00052 static const std::string ARRAY_TYPE = "HDF5 Array Type"; 00053 00054 /** 00055 * Represents the H5T_BITFIELD type. The HdfPlugInLib will not parse data of this type. 00056 */ 00057 static const std::string BITFIELD_TYPE = "HDF5 Bitfield Type"; 00058 00059 /** 00060 * Represents the H5T_OPAQUE type. The HdfPlugInLib will not parse data of this type. 00061 */ 00062 static const std::string OPAQUE_TYPE = "HDF5 Opaque Type"; 00063 00064 /** 00065 * Represents the H5T_COMPOUND type. The HdfPlugInLib will not parse data of this type. 00066 */ 00067 static const std::string COMPOUND_TYPE = "HDF5 Compound Type"; 00068 00069 /** 00070 * Represents the H5T_REFERENCE type. The HdfPlugInLib will not parse data of this type. 00071 */ 00072 static const std::string REFERENCE_TYPE = "HDF5 Reference Type"; 00073 00074 /** 00075 * Represents the H5T_ENUM type. The HdfPlugInLib will not parse data of this type. 00076 */ 00077 static const std::string ENUM_TYPE = "HDF5 ENUM Type"; 00078 00079 /** 00080 * Represents the H5T_VLEN type. The HdfPlugInLib will not parse data of this type. 00081 */ 00082 static const std::string VLEN_TYPE = "HDF5 VLEN Type"; 00083 00084 /** 00085 * Converts an HDF5 data type to a string. This method simply returns a string 00086 * representation of the type. It does not take the dataspace into account, ie. the 00087 * dimensionality. 00088 * 00089 * NOTE: You will need to statically link against the HDF5 libraries. 00090 * 00091 * @param dataTypeId 00092 * The value returned from H5Dget_type() or H5Aget_type(). 00093 * 00094 * @return A string that represents the HDF5 type. The return value could be one of 00095 * the following: 00096 * - TypeConverter::toString<char>(); 00097 * - TypeConverter::toString<unsigned char>(); 00098 * - TypeConverter::toString<short>(); 00099 * - TypeConverter::toString<unsigned short>(); 00100 * - TypeConverter::toString<int>(); 00101 * - TypeConverter::toString<unsigned int>(); 00102 * - TypeConverter::toString<float>(); 00103 * - TypeConverter::toString<double>(); 00104 * - TypeConverter::toString<string>(); 00105 * - HdfUtilities::UNKNOWN_INTEGER_TYPE 00106 * - HdfUtilities::UNKNOWN_FLOAT_TYPE 00107 * - HdfUtilities::UNKNOWN_TYPE 00108 * - HdfUtilities::TIME_TYPE 00109 * - HdfUtilities::ARRAY_TYPE 00110 * - HdfUtilities::BITFIELD_TYPE 00111 * - HdfUtilities::OPAQUE_TYPE 00112 * - HdfUtilities::COMPOUND_TYPE 00113 * - HdfUtilities::ENUM_TYPE 00114 * - HdfUtilities::VLEN_TYPE 00115 */ 00116 std::string hdf5TypeToTypeString(hid_t dataTypeId); 00117 00118 /** 00119 * Given an open HDF5 Attribute identifier retrieves 00120 * the attribute and places it in a variant. 00121 * 00122 * @param attrId 00123 * A handle to the HDF attribute. 00124 * @param var 00125 * The variant that the attribute data will be placed in. 00126 * 00127 * @return The number of elements (ie. 5 if a vector of 5 ints) in the attribute. 00128 */ 00129 bool readHdf5Attribute(hid_t attrId, DataVariant& var); 00130 00131 /** 00132 * Given an HDF5 Attribute handle, returns a string representing that attribute. 00133 * 00134 * This method only supports attributes supported by StringUtilities::toString() 00135 * and StringUtilities::fromString() minus the enumerated types in TypesFile.h. 00136 * 00137 * Throws an HdfUtilities::Exception if an error occurs. 00138 * 00139 * @param attrId 00140 * The attribute id returned by H5Aopen(). 00141 * 00142 * @return A string representing the attribute. For 1-dimensional vector types, 00143 * this returns the list of values: ie. (val1, val2, val3). 00144 */ 00145 std::string hdf5AttributeToString(hid_t attrId); 00146 00147 /** 00148 * Creates an HDF5 attribute with a given name and value. 00149 * 00150 * @param dataDescriptor 00151 * A handle to the HDF5 dataset or HDF5 group that this attribute should 00152 * be attached to. 00153 * @param attributeName 00154 * The name of the attribute that should be created on the HDF5 dataset 00155 * or HDF5 group. 00156 * @param attributeValue 00157 * The value that the created attribute should have. The value will 00158 * determine the HDF5 type and HDF5 dataspace of the created attribute. 00159 * Specifically, the Hdf5CustomWriter created for T will determine both 00160 * the HDF5 type and HDF5 dataspace. 00161 * 00162 * @return Returns true if the attribute could be created with the given name 00163 * and value successfully, false otherwise. 00164 */ 00165 template<typename T> 00166 bool writeAttribute(hid_t dataDescriptor, const std::string& attributeName, const T& attributeValue) 00167 { 00168 std::auto_ptr<Hdf5CustomWriter> pWriter(createHdf5CustomWriter<T>()); 00169 if (pWriter.get() == NULL) 00170 { 00171 return false; 00172 } 00173 00174 if (!pWriter->setDataToWrite(const_cast<T*>(&attributeValue))) 00175 { 00176 return false; 00177 } 00178 Hdf5DataSpaceResource spaceId = pWriter->createDataSpace(); 00179 VERIFY(*spaceId >= 0); 00180 Hdf5TypeResource memTypeId(pWriter->getWriteMemoryType()); 00181 Hdf5TypeResource fileTypeId(pWriter->getWriteFileType()); 00182 if (*memTypeId < 0 || *fileTypeId < 0) 00183 { 00184 return false; 00185 } 00186 Hdf5AttributeResource attrId(H5Acreate1(dataDescriptor, attributeName.c_str(), *fileTypeId, 00187 *spaceId, H5P_DEFAULT)); 00188 if (*attrId < 0) 00189 { 00190 return false; 00191 } 00192 00193 // now write the attribute 00194 const void* pData = pWriter->getWriteBuffer(); 00195 if (pData != NULL) 00196 { 00197 herr_t writeStatus = H5Awrite(*attrId, *memTypeId, pData); 00198 return writeStatus == 0; 00199 } 00200 return false; 00201 } 00202 00203 /** 00204 * Creates an HDF5 dataset with a given name and value. 00205 * 00206 * @param fileDescriptor 00207 * A handle to the HDF5 file that this dataset should be created in. 00208 * @param datasetName 00209 * The full path to where the HDF5 dataset should be created in 00210 * the HDF5 file. This function assumes that any required groups 00211 * in the path have already been created. 00212 * @param datasetValue 00213 * The value that the created dataset should have. The value will 00214 * determine the HDF5 type and HDF5 dataspace of the created dataset. 00215 * Specifically, the Hdf5CustomWriter created for T will determine both 00216 * the HDF5 type and HDF5 dataspace. 00217 * 00218 * @return Returns true if the dataset could be created at the given location 00219 * in the file with the given value successfully, false otherwise. 00220 */ 00221 template<typename T> 00222 bool writeDataset(hid_t fileDescriptor, const std::string& datasetName, const T& datasetValue) 00223 { 00224 std::auto_ptr<Hdf5CustomWriter> pWriter(createHdf5CustomWriter<T>()); 00225 if (pWriter.get() == NULL) 00226 { 00227 return false; 00228 } 00229 if (!pWriter->setDataToWrite(const_cast<T*>(&datasetValue))) 00230 { 00231 return false; 00232 } 00233 Hdf5DataSpaceResource spaceId = pWriter->createDataSpace(); 00234 VERIFY(*spaceId >= 0); 00235 00236 Hdf5TypeResource memTypeId(pWriter->getWriteMemoryType()); 00237 Hdf5TypeResource fileTypeId(pWriter->getWriteFileType()); 00238 if (*memTypeId < 0 || *fileTypeId < 0) 00239 { 00240 return false; 00241 } 00242 00243 Hdf5DataSetResource dataSet(H5Dcreate1(fileDescriptor, datasetName.c_str(), 00244 *fileTypeId, *spaceId, H5P_DEFAULT)); 00245 if (*dataSet < 0) 00246 { 00247 return false; 00248 } 00249 const void* pData = pWriter->getWriteBuffer(); 00250 if (pData != NULL) 00251 { 00252 herr_t writeStatus = H5Dwrite(*dataSet, *memTypeId, H5S_ALL, *spaceId, H5P_DEFAULT, pData); 00253 return writeStatus == 0; 00254 } 00255 return false; 00256 } 00257 00258 template<typename T> 00259 Hdf5TypeResource getHdf5Type(); 00260 00261 /** 00262 * Creates one or more HDF5 groups with the given names. 00263 * 00264 * @param hdfPath 00265 * One or more group names, separated by a '/' character, to be created. 00266 * 00267 * @param fileDescriptor 00268 * A handle to the HDF5 file that the group(s) should be created in. 00269 * 00270 * @param bLastItemIsGroup 00271 * True if the last item in the string is a group, false otherwise. 00272 * If this is false, the text after the final '/' in hdfPath is ignored. 00273 * 00274 * @return Returns true if the group(s) were created (or already existed) at the given location(s), false otherwise. 00275 */ 00276 bool createGroups(const std::string& hdfPath, hid_t fileDescriptor, bool bLastItemIsGroup = false); 00277 00278 } 00279 00280 #endif