Commit 5e8d6200 authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Add reading functionality to XdmfHDF5Controller

parent 7a4cb5d9
......@@ -221,7 +221,7 @@ public:
}
};
class XdmfArray::GetValuesPointer : public boost::static_visitor <const void* const> {
class XdmfArray::GetValuesPointer : public boost::static_visitor <const void * const> {
public:
GetValuesPointer()
......@@ -229,13 +229,13 @@ public:
}
template<typename T>
const void* const operator()(const boost::shared_ptr<std::vector<T> > & array) const
const void * const operator()(const boost::shared_ptr<std::vector<T> > & array) const
{
return &array->operator[](0);
}
template<typename T>
const void* const operator()(const boost::shared_array<const T> & array) const
const void * const operator()(const boost::shared_array<const T> & array) const
{
return array.get();
}
......@@ -244,6 +244,11 @@ public:
class XdmfArray::GetValuesString : public boost::static_visitor <std::string> {
public:
GetValuesString() :
mArrayPointerNumValues(0)
{
}
GetValuesString(const int arrayPointerNumValues) :
mArrayPointerNumValues(arrayPointerNumValues)
{
......@@ -397,7 +402,7 @@ boost::shared_ptr<XdmfHDF5Controller> XdmfArray::getHDF5Controller()
return mHDF5Controller;
}
const boost::shared_ptr<const XdmfHDF5Controller> XdmfArray::getHDF5Controller() const
boost::shared_ptr<const XdmfHDF5Controller> XdmfArray::getHDF5Controller() const
{
return mHDF5Controller;
}
......@@ -472,7 +477,7 @@ std::string XdmfArray::getType() const
return "";
}
const void* const XdmfArray::getValuesPointer() const
const void * const XdmfArray::getValuesPointer() const
{
if(mHaveArray)
{
......@@ -489,7 +494,7 @@ std::string XdmfArray::getValuesString() const
{
if(mHaveArray)
{
return boost::apply_visitor(GetValuesString(mArrayPointerNumValues), mArray);
return boost::apply_visitor(GetValuesString(), mArray);
}
else if(mHaveArrayPointer)
{
......@@ -506,6 +511,14 @@ void XdmfArray::internalizeArrayPointer()
}
}
void XdmfArray::read()
{
if(mHDF5Controller)
{
mHDF5Controller->read(this);
}
}
void XdmfArray::release()
{
releaseArray();
......
......@@ -67,10 +67,10 @@ public:
/**
* Copy values from an array into this array.
*
* @param startIndex the index in this array to begin insertion.
* @param valuesPointer a pointer to the values to copy into this array.
* @param startIndex the index in this XdmfArray to begin insertion.
* @param valuesPointer a pointer to the values to copy into this XdmfArray.
* @param numValues the number of values to copy into this array.
* @param arrayStride number of values to stride in this array between each copy.
* @param arrayStride number of values to stride in this XdmfArray between each copy.
* @param valuesStride number of values to stride in the pointer between each copy.
*/
template<typename T>
......@@ -79,7 +79,7 @@ public:
/**
* Remove all values from this array
*/
virtual void clear();
void clear();
/**
* Get the capacity of this array (the number of values this array can store without reallocation).
......@@ -104,21 +104,21 @@ public:
*
* @return the hdf5 controller attached to this XdmfArray.
*/
const boost::shared_ptr<const XdmfHDF5Controller> getHDF5Controller() const;
boost::shared_ptr<const XdmfHDF5Controller> getHDF5Controller() const;
/**
* Get the precision, in bytes, of the data type of this array.
*
* @return the precision, in bytes, of the data type of this array.
*/
virtual unsigned int getPrecision() const;
unsigned int getPrecision() const;
/**
* Get the number of values stored in this array.
*
* @return the number of values stored in this array.
*/
virtual unsigned int getSize() const;
unsigned int getSize() const;
/**
* Get the data type of this array.
......@@ -126,7 +126,7 @@ public:
* @return a string containing the Xdmf data type for the array, this is one of
* Char, Short, Int, Float, UChar, UShort, UInt.
*/
virtual std::string getType() const;
std::string getType() const;
/**
* Get a smart pointer to the values stored in this array.
......@@ -136,6 +136,18 @@ public:
template <typename T>
boost::shared_ptr<std::vector<T> > getValues();
/**
* Get a copy of the values stored in this array
*
* @param startIndex the index in this XdmfArray to begin copying from.
* @param valuesPointer a pointer to an array to copy into.
* @param numValues the number of values to copy.
* @param arrayStride number of values to stride in this XdmfArray between each copy.
* @param valuesStride number of values to stride in the pointer between each copy.
*/
template <typename T>
void getValuesCopy(const unsigned int startIndex, T * valuesPointer, const unsigned int numValues = 1, const unsigned int arrayStride = 1, const unsigned int valuesStride = 1) const;
/**
* Get a smart pointer to the values stored in this array (const version).
*
......@@ -145,18 +157,18 @@ public:
//const boost::shared_ptr<const std::vector<T> > getValues() const;
/**
* Get a pointer to the values stored in this array.
* Get a pointer to the values stored in this array (const version).
*
* @return a void pointer to the first value stored in this array.
*/
virtual const void * const getValuesPointer() const;
const void * const getValuesPointer() const;
/**
* Get the values stored in this array as a string.
*
* @return a string containing the contents of the array.
*/
virtual std::string getValuesString() const;
std::string getValuesString() const;
/**
* Initializes the array to contain an empty container of a particular type.
......@@ -166,6 +178,11 @@ public:
template <typename T>
boost::shared_ptr<std::vector<T> > initialize();
/**
* Read data from disk into memory.
*/
void read();
/**
* Release all data held by this XdmfArray.
*/
......@@ -179,14 +196,14 @@ public:
void reserve(const unsigned int size);
/**
* Resizes the XdmfArray to contain numValues. If numValues is larger than the current size, append values to end equal
* Resizes the XdmfArray to contain numValues. If numValues is larger than the current size, append values to the end equal
* to val. If numValues is less than the current size, values at indices larger than numValues are removed.
*
* @param numValues the number of values to resize this array to.
* @param val the number to initialized newly created values to, if needed.
* @param val the number to initialize newly created values to, if needed.
*/
template<typename T>
void resize(const unsigned int numValues, const T & val);
void resize(const unsigned int numValues, const T & val = 0);
/**
* Attach an hdf5 controller to this XdmfArray.
......@@ -278,6 +295,10 @@ private:
class GetPrecision;
class GetSize;
class GetType;
template<typename T>
class GetValuesCopy;
class GetValuesPointer;
class GetValuesString;
class InternalizeArrayPointer;
......
......@@ -41,6 +41,46 @@ private:
const unsigned int mValuesStride;
};
template<typename T>
class XdmfArray::GetValuesCopy : public boost::static_visitor <void> {
public:
GetValuesCopy(const unsigned int startIndex, T * valuesPointer, const unsigned int numValues, const unsigned int arrayStride, const unsigned int valuesStride) :
mStartIndex(startIndex),
mValuesPointer(valuesPointer),
mNumValues(numValues),
mArrayStride(arrayStride),
mValuesStride(valuesStride)
{
}
template<typename U>
void operator()(const boost::shared_array<const U> & array) const
{
for(int i=0; i<mNumValues; ++i)
{
mValuesPointer[i*mValuesStride] = (T)array[mStartIndex + i*mArrayStride];
}
}
template<typename U>
void operator()(const boost::shared_ptr<std::vector<U> > & array) const
{
for(int i=0; i<mNumValues; ++i)
{
mValuesPointer[i*mValuesStride] = (T)array->operator[](mStartIndex + i*mArrayStride);
}
}
private:
const unsigned int mStartIndex;
T * mValuesPointer;
const unsigned int mNumValues;
const unsigned int mArrayStride;
const unsigned int mValuesStride;
};
template<typename T>
class XdmfArray::Resize : public boost::static_visitor <void> {
public:
......@@ -116,6 +156,24 @@ boost::shared_ptr<std::vector<T> > XdmfArray::getValues()
// }
//}
template <typename T>
void XdmfArray::getValuesCopy(const unsigned int startIndex, T * valuesPointer, const unsigned int numValues, const unsigned int arrayStride, const unsigned int valuesStride) const
{
if(mHaveArray)
{
boost::apply_visitor(GetValuesCopy<T>(startIndex, valuesPointer, numValues, arrayStride, valuesStride), mArray);
}
else if(mHaveArrayPointer)
{
boost::apply_visitor(GetValuesCopy<T>(startIndex, valuesPointer, numValues, arrayStride, valuesStride), mArrayPointer);
}
else if(mHDF5Controller)
{
assert("Need to complete");
}
assert("Throw Exception No Data");
}
template <typename T>
boost::shared_ptr<std::vector<T> > XdmfArray::initialize()
{
......
// Kenneth Leiter
// Xdmf Smart Pointer Test
#include <hdf5.h>
#include <sstream>
#include <vector>
#include "XdmfArray.hpp"
#include "XdmfHDF5Controller.hpp"
XdmfHDF5Controller::XdmfHDF5Controller(const std::string & dataSetPath, const int precision,
XdmfHDF5Controller::XdmfHDF5Controller(const std::string & hdf5FilePath, const std::string & dataSetName, const int precision,
const int size, const std::string & type) :
mDataSetPath(dataSetPath),
mHDF5FilePath(hdf5FilePath),
mDataSetName(dataSetName),
mPrecision(precision),
mSize(size),
mType(type)
......@@ -18,7 +23,9 @@ XdmfHDF5Controller::~XdmfHDF5Controller()
std::string XdmfHDF5Controller::getDataSetPath() const
{
return mDataSetPath;
std::stringstream toReturn;
toReturn << mHDF5FilePath << ":" << mDataSetName;
return toReturn.str();
}
int XdmfHDF5Controller::getPrecision() const
......@@ -35,3 +42,80 @@ std::string XdmfHDF5Controller::getType() const
{
return mType;
}
void XdmfHDF5Controller::read(XdmfArray * const array)
{
hid_t hdf5Handle = H5Fopen(mHDF5FilePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
hid_t dataset = H5Dopen(hdf5Handle, mDataSetName.c_str(), H5P_DEFAULT);
hid_t dataspace = H5Dget_space(dataset);
hssize_t numVals = H5Sget_simple_extent_npoints(dataspace);
hid_t datatype = H5Dget_type(dataset);
void * valuesPointer;
if(H5Tequal(datatype, H5T_NATIVE_CHAR))
{
boost::shared_ptr<std::vector<char> > arrayValues = array->initialize<char>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_SHORT))
{
boost::shared_ptr<std::vector<short> > arrayValues = array->initialize<short>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_INT))
{
boost::shared_ptr<std::vector<int> > arrayValues = array->initialize<int>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_LONG))
{
boost::shared_ptr<std::vector<long> > arrayValues = array->initialize<long>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_FLOAT))
{
boost::shared_ptr<std::vector<float> > arrayValues = array->initialize<float>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_DOUBLE))
{
boost::shared_ptr<std::vector<double> > arrayValues = array->initialize<double>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_UCHAR))
{
boost::shared_ptr<std::vector<unsigned char> > arrayValues = array->initialize<unsigned char>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_USHORT))
{
boost::shared_ptr<std::vector<unsigned short> > arrayValues = array->initialize<unsigned short>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else if(H5Tequal(datatype, H5T_NATIVE_UINT))
{
boost::shared_ptr<std::vector<unsigned int> > arrayValues = array->initialize<unsigned int>();
array->resize(numVals, 0);
valuesPointer = &arrayValues->operator[](0);
}
else
{
assert("Unsupported HDF5 Data Type");
}
H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, valuesPointer);
herr_t status;
status = H5Tclose(datatype);
status = H5Sclose(dataspace);
status = H5Dclose(dataset);
status = H5Fclose(hdf5Handle);
}
#ifndef XDMFHDF5CONTROLLER_HPP_
#define XDMFHDF5CONTROLLER_HPP_
// Forward Declarations
class XdmfArray;
// Includes
#include <string>
#include "XdmfObject.hpp"
......@@ -23,10 +26,10 @@ public:
*
* @param dataSetPath the path to the hdf5 data set on disk.
*/
static boost::shared_ptr<XdmfHDF5Controller> New(const std::string & dataSetPath, const int precision,
const int size, const std::string & type)
static boost::shared_ptr<XdmfHDF5Controller> New(const std::string & hdf5FilePath, const std::string & dataSetName,
const int precision, const int size, const std::string & type)
{
boost::shared_ptr<XdmfHDF5Controller> p(new XdmfHDF5Controller(dataSetPath, precision, size, type));
boost::shared_ptr<XdmfHDF5Controller> p(new XdmfHDF5Controller(hdf5FilePath, dataSetName, precision, size, type));
return p;
}
......@@ -58,9 +61,16 @@ public:
*/
std::string getType() const;
/**
* Read data owned by this controller on disk into the passed XdmfArray.
*
* @param array and XdmfArray to read data into.
*/
void read(XdmfArray * const array);
protected:
XdmfHDF5Controller(const std::string & dataSetPath, const int precision, const int size,
XdmfHDF5Controller(const std::string & hdf5FilePath, const std::string & dataSetName, const int precision, const int size,
const std::string & type);
virtual ~XdmfHDF5Controller();
......@@ -69,7 +79,8 @@ private:
XdmfHDF5Controller(const XdmfHDF5Controller & hdf5Controller); // Not implemented.
void operator=(const XdmfHDF5Controller & hdf5Controller); // Not implemented.
std::string mDataSetPath;
std::string mDataSetName;
std::string mHDF5FilePath;
int mPrecision;
int mSize;
std::string mType;
......
......@@ -15,17 +15,14 @@ class XdmfHDF5Writer::XdmfHDF5WriterImpl {
public:
XdmfHDF5WriterImpl(const std::string & hdf5FilePath) :
mHDF5Handle(H5Fcreate(hdf5FilePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)),
mHeavyFileName(hdf5FilePath),
mHDF5FilePath(hdf5FilePath),
mLastWrittenDataSet("")
{
};
~XdmfHDF5WriterImpl()
{
herr_t status = H5Fclose(mHDF5Handle);
};
hid_t mHDF5Handle;
std::string mHeavyFileName;
std::string mHDF5FilePath;
std::string mLastWrittenDataSet;
static int mDataSetId;
};
......@@ -140,18 +137,41 @@ void XdmfHDF5Writer::visit(XdmfArray & array, boost::shared_ptr<Loki::BaseVisito
// Open a hdf5 dataset and write to it on disk.
herr_t status;
hsize_t size = array.getSize();
hid_t dataspace = H5Screate_simple(1, &size, NULL);
hid_t dataset = H5Dcreate(mImpl->mHDF5Handle, dataSetName.str().c_str(), datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
hid_t hdf5Handle;
// Save old error handler and turn off error handling for now
H5E_auto_t old_func;
void * old_client_data;
H5Eget_auto(0, &old_func, &old_client_data);
H5Eset_auto2(0, NULL, NULL);
if(H5Fis_hdf5(mImpl->mHDF5FilePath.c_str()) > 0)
{
hdf5Handle = H5Fopen(mImpl->mHDF5FilePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
}
else
{
hdf5Handle = H5Fcreate(mImpl->mHDF5FilePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
}
hid_t dataset = H5Dopen(hdf5Handle, dataSetName.str().c_str(), H5P_DEFAULT);
if(dataset < 0)
{
hid_t dataspace = H5Screate_simple(1, &size, NULL);
dataset = H5Dcreate(hdf5Handle, dataSetName.str().c_str(), datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
status = H5Sclose(dataspace);
}
status = H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, array.getValuesPointer());
status = H5Dclose(dataset);
status = H5Sclose(dataspace);
status = H5Fclose(hdf5Handle);
std::stringstream writtenDataSetPath;
writtenDataSetPath << mImpl->mHeavyFileName << ":" << dataSetName.str();
mImpl->mLastWrittenDataSet = writtenDataSetPath.str();
mImpl->mDataSetId++;
// Restore previous error handler
H5Eset_auto2(0, old_func, old_client_data);
boost::shared_ptr<XdmfHDF5Controller> newDataSetController = XdmfHDF5Controller::New(writtenDataSetPath.str(), array.getPrecision(), array.getSize(), array.getType());
boost::shared_ptr<XdmfHDF5Controller> newDataSetController = XdmfHDF5Controller::New(mImpl->mHDF5FilePath, dataSetName.str(),
array.getPrecision(), array.getSize(), array.getType());
array.setHDF5Controller(newDataSetController);
mImpl->mLastWrittenDataSet = newDataSetController->getDataSetPath();
mImpl->mDataSetId++;
}
}
set(XdmfCxxTests
TestXdmfAttribute
TestXdmfArray
TestXdmfArrayWriteRead
TestXdmfAttribute
TestXdmfDataItem
TestXdmfGeometry
TestXdmfGrid
......
......@@ -34,6 +34,13 @@ int main(int argc, char* argv[])
assert((*storedValues)[1] == 2);
assert((*storedValues)[2] == 3);
assert((*storedValues)[3] == 4);
// Assert we can copy values out correctly
std::vector<int> outValues(4);
array->getValuesCopy(0, &outValues[0], 4);
for(int i=0; i<outValues.size(); ++i)
{
assert(outValues[i] == values[i]);
}
/**
* Array stride = 2, Values stride = 1
......@@ -104,6 +111,9 @@ int main(int argc, char* argv[])
const int * const array5Pointer = (const int * const)array5->getValuesPointer();
assert(array5Pointer[0] == 1);
assert(array5Pointer[1] == 2);
// Assert we can copy values out correctly
array->getValuesCopy(1, &outValues[0], 4);
assert(outValues[0] == values[1]);
/**
* Copy after Set
......
#include "XdmfArray.hpp"
#include "XdmfHDF5Writer.hpp"
int main(int argc, char* argv[])
{
int values[] = {1, 2, 3, 4};
boost::shared_ptr<XdmfArray> array = XdmfArray::New();
array->copyValues(0, &values[0], 4, 1, 1);
assert(array->getSize() == 4);
assert(array->getValuesString().compare("1 2 3 4 ") == 0);
boost::shared_ptr<XdmfHDF5Writer> writer = XdmfHDF5Writer::New("test.h5");
array->accept(writer);
assert(array->getSize() == 4);
assert(array->getValuesString().compare("1 2 3 4 ") == 0);
array->release();
assert(array->getValuesString() == "");
assert(array->getSize() == 4);
array->read();
assert(array->getValuesString().compare("1 2 3 4 ") == 0);
}
......@@ -2,7 +2,7 @@ from Xdmf import *
if __name__ == "__main__":
writer = XdmfWriter.New()
writer = XdmfWriter.New("output.xmf")
writer.setLightDataLimit(10)
grid = XdmfGrid.New()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment