Hdf5IncrementalWriter.h

Go to the documentation of this file.
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 HDF5_INCREMENTAL_WRITER_H
00011 #define HDF5_INCREMENTAL_WRITER_H
00012 
00013 #include "Hdf5CustomWriter.h"
00014 
00015 #include <string>
00016 #include <vector>
00017 
00018 #include <hdf5.h>
00019 
00020 /**
00021  * This class provides the ability to incrementally
00022  * write values to a HDF5 dataset without having
00023  * to write values to the entire dataset as 
00024  * HdfUtilities::writeDataset() requires.
00025  */
00026 template<typename T>
00027 class Hdf5IncrementalWriter
00028 {
00029 public:
00030    /**
00031     * Create the HDF5 dataset that will be written
00032     * to by this writer.  The dataset will be
00033     * created in the file with the given name
00034     * and dimensions.  The HDF5 type of the dataset
00035     * is determined by the T that this class
00036     * is templated on.  The HDF5 type of the dataset
00037     * will be queried from the
00038     * Hdf5CustomWriter::getWriteFileType() instance
00039     * that is constructed by calling
00040     * createCustomHdf5Writer() with the given T.
00041     * To determine if the HDF5 dataset was created
00042     * successfully in the file, call isValid()
00043     * after this object has been constructed.
00044     *
00045     * @param fileId
00046     *        A handle to an open HDF5 file that
00047     *        the dataset should be written to.
00048     * @param datasetName
00049     *        The full path to a location in the file
00050     *        where the HDF5 datatset should be created.
00051     *        This writer assumes that any required
00052     *        groups in the path have already been created
00053     *        in the file.
00054     * @param datasetDimensions
00055     *        A vector specifying the number of dimensions
00056     *        and the size of the dimensions that should
00057     *        be used when creating the HDF5 dataset.
00058     */
00059    Hdf5IncrementalWriter(hid_t fileId,
00060       const std::string& datasetName,
00061       const std::vector<hsize_t>& datasetDimensions)
00062    {
00063       mpWriter = createHdf5CustomWriter<T>();
00064       mDataset = -1;
00065       mDataspace = -1;
00066       if (mpWriter == NULL)
00067       {
00068          return;
00069       }
00070       if (datasetDimensions.empty())
00071       {
00072          mDataspace = H5Screate(H5S_SCALAR);
00073       }
00074       else
00075       {      
00076          mDataspace = H5Screate_simple(datasetDimensions.size(), &(datasetDimensions.front()), NULL);
00077       }
00078       if (mDataspace != -1)
00079       {
00080          mDataset = H5Dcreate1(fileId, datasetName.c_str(),
00081             *(mpWriter->getWriteFileType()), mDataspace, H5P_DEFAULT);
00082       }
00083    }
00084 
00085    /**
00086     * Destroys the writer instance.  This will also
00087     * close the HDF5 dataset that was being written
00088     * to by this writer.
00089     */
00090    virtual ~Hdf5IncrementalWriter()
00091    {
00092       delete mpWriter;
00093       if (mDataspace != -1)
00094       {
00095          H5Sclose(mDataspace);
00096       }
00097 
00098       if (mDataset != -1)
00099       {
00100          H5Dclose(mDataset);
00101       }
00102    }
00103 
00104    /**
00105     * Returns whether this writer
00106     * is valid to use.  If this
00107     * method returns false, you 
00108     * should not attempt to call
00109     * any other functions on this writer.
00110     * This method should be called
00111     * immediately after the constructor.
00112     *
00113     * @return Returns true is this writer 
00114     *         is valid, false otherwise.
00115     */
00116    bool isValid() const
00117    {
00118       return mpWriter != NULL && mDataspace != -1 && mDataset != -1;
00119    }
00120 
00121    /**
00122     * Returns a HDF5 handle to the dataset
00123     * that is being written to by this writer.
00124     *
00125     * @return Returns a HDF5 handle to the dataset
00126     *         that is being written to.
00127     */
00128    hid_t getDataSet() const
00129    {
00130       return mDataset;
00131    }
00132 
00133    /**
00134     * Returns the dataspace that represents
00135     * the selection within the dataset
00136     * that is being written to.
00137     *
00138     * @return Returns a HDF5 dataspace handle
00139     *         to the selection within the
00140     *         dataset that is being written to.
00141     */
00142    hid_t getDataSpace() const
00143    {
00144       return mDataspace;
00145    }
00146 
00147    /**
00148     * Provides a convenient way to write data
00149     * to a single dimensional HDF5 dataset.
00150     * (ie. a one-dimensional array).  This method
00151     * will write data to a single dimensional HDF5
00152     * dataset starting at the row provided.
00153     *
00154     * @param startRowNumber
00155     *        The starting row number in the single
00156     *        dimensional HDF5 dataset where data
00157     *        should be written.  This number is zero-based.
00158     * @param object
00159     *        The data that should be written to the
00160     *        HDF5 dataset starting at the given row
00161     *        number.  This data can be scalar or it
00162     *        can be single dimensional as well.
00163     *
00164     * Returns true if the write was successful, false otherwise.
00165     */
00166    bool writeBlock(hsize_t startRowNumber, const T& object)
00167    {
00168       DO_IF(!isValid(), return false);
00169       DO_IF(H5Sget_simple_extent_ndims(mDataspace) != 1, return false);
00170       DO_IF(!mpWriter->setDataToWrite(const_cast<T*>(&object)), return false);
00171       Hdf5DataSpaceResource memSpaceId(mpWriter->createDataSpace());
00172       DO_IF(*memSpaceId < 0, return false);
00173 
00174       hsize_t sizeArray[H5S_MAX_RANK];
00175       int numdims = H5Sget_simple_extent_dims(*memSpaceId, sizeArray, NULL);
00176       if (numdims == 0)
00177       {
00178          sizeArray[0] = 1;
00179       }
00180 
00181       hsize_t oneValue = 1;
00182       DO_IF(H5Sselect_hyperslab(mDataspace, H5S_SELECT_SET, &startRowNumber, &oneValue, sizeArray, NULL) < 0,
00183          return false);
00184 
00185       Hdf5TypeResource memTypeId(mpWriter->getWriteMemoryType());
00186       DO_IF(*memTypeId < 0, return false)
00187       const void* pData = mpWriter->getWriteBuffer();
00188       if (pData != NULL)
00189       {
00190          herr_t writeStatus = H5Dwrite(mDataset, *memTypeId, *memSpaceId,
00191             mDataspace, H5P_DEFAULT, pData);
00192          return writeStatus == 0;
00193       }
00194       return false;
00195    }
00196 
00197    /**
00198     * Writes the specified data to a selection
00199     * in the dataset defined by a hyperslab.
00200     * The hyperslab selection is done by using
00201     * H5Sselect_hyperslab() provided by the
00202     * HDF5 library.  Please note that this
00203     * method erases any previous selection in
00204     * the dataset before performing the hyperslab
00205     * selection.  The provided data will be
00206     * written to the selected hyperslab in
00207     * the HDF5 dataset.
00208     * 
00209     * @param pStart
00210     *        Please see H5Sselect_hyperslab() documentation.
00211     * @param pStride
00212     *        Please see H5Sselect_hyperslab() documentation.
00213     * @param pCount
00214     *        Please see H5Sselect_hyperslab() documentation.
00215     * @param pBlock
00216     *        Please see H5Sselect_hyperslab() documentation.
00217     * @param object
00218     *        The data that should be written to the selected
00219     *        hyperslab in the file.  The provided data
00220     *        must contain the same number of points as the
00221     *        selected hyperslab contains.
00222     *
00223     * @return Returns true if the hyperslab selection and
00224     *         write were successful, false otherwise.
00225     */
00226    bool writeHyperslab(const hsize_t* pStart,
00227       const hsize_t* pStride,
00228       const hsize_t* pCount,
00229       const hsize_t* pBlock,
00230       const T& object)
00231    {
00232       DO_IF(!isValid(), return false);
00233       DO_IF(H5Sselect_hyperslab(mDataspace, H5S_SELECT_SET, pStart, pStride, pCount, pBlock) < 0, return false);
00234       return writeToSelectedData(object);
00235    }
00236 
00237    /**
00238     * Writes the specified data to a selection
00239     * in the dataset defined by a element selection.
00240     * The element selection is done by using
00241     * H5Sselect_elements() provided by the
00242     * HDF5 library.  Please note that this
00243     * method erases any previous selection in
00244     * the dataset before performing the element
00245     * selection.  The provided data will be
00246     * written to the selected elements in
00247     * the HDF5 dataset.
00248     * 
00249     * @param num_elements
00250     *        Please see H5Sselect_elements() documentation.
00251     * @param pCoordinates
00252     *        Please see H5Sselect_elements() documentation.
00253     * @param object
00254     *        The data that should be written to the selected
00255     *        elements in the file.  The provided data
00256     *        must contain the same number of points as the
00257     *        element selection contains.
00258     *
00259     * @return Returns true if the element selection and
00260     *         write were successful, false otherwise.
00261     */
00262    bool writeElements(const size_t num_elements,
00263       const hsize_t * pCoordinates,
00264       const T& object)
00265    {
00266       DO_IF(!isValid(), return false);
00267       DO_IF(H5Sselect_elements(mDataspace, H5S_SELECT_SET, num_elements, pCoordinates) < 0, return false);
00268       return writeToSelectedData(object);
00269    }
00270 
00271    /**
00272     * Writes the provided data to the current selection
00273     * as returned by getDataSpace().  This method should
00274     * be used if the options provided by writeBlock(),
00275     * writeHyperslab() and writeElements() is insufficent.
00276     * In this case, you can get the dataspace by calling
00277     * getDataSpace() and the perform the selection manually
00278     * using HDF5 library calls.
00279     *
00280     * @param object
00281     *        The data that should be written to the current
00282     *        selection in the file.  The provided data
00283     *        must contain the same number of points as the
00284     *        current selection contains.
00285     *
00286     * @return Returns true if the write was successful,
00287     *         false otherwise.
00288     */
00289    bool writeToSelectedData(const T& object)
00290    {
00291       DO_IF(!isValid(), return false);
00292       DO_IF(!mpWriter->setDataToWrite(const_cast<T*>(&object)), return false);
00293       Hdf5DataSpaceResource memSpaceId(mpWriter->createDataSpace());
00294       DO_IF(*memSpaceId < 0, return false);
00295 
00296       DO_IF(H5Sget_select_npoints(mDataspace) != H5Sget_select_npoints(*memSpaceId), return false);
00297 
00298       Hdf5TypeResource memTypeId(mpWriter->getWriteMemoryType());
00299       DO_IF(*memTypeId < 0, return false)
00300       const void* pData = mpWriter->getWriteBuffer();
00301       if (pData != NULL)
00302       {
00303          herr_t writeStatus = H5Dwrite(mDataset, *memTypeId, *memSpaceId,
00304             mDataspace, H5P_DEFAULT, pData);
00305          return writeStatus == 0;
00306       }
00307       return false;
00308    }
00309 
00310 protected:
00311    hid_t mDataset;
00312    hid_t mDataspace;
00313    Hdf5CustomWriter* mpWriter;
00314 };
00315 
00316 #endif

Software Development Kit - Opticks 4.9.0 Build 16218