Commit c5929b52 authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Add string array type

Add tests for I/O of strings (to hdf5 and xml).
Fix bug in XdmfExodusReader when reading grid centered data.
Add string I/O in python and add tests.
parent 521435d9
......@@ -167,6 +167,12 @@ public:
return XdmfArrayType::UInt32();
}
shared_ptr<const XdmfArrayType>
getArrayType(const std::string * const) const
{
return XdmfArrayType::String();
}
shared_ptr<const XdmfArrayType>
operator()(const boost::blank & array) const
{
......@@ -685,6 +691,9 @@ XdmfArray::initialize(const shared_ptr<const XdmfArrayType> arrayType,
else if(arrayType == XdmfArrayType::UInt32()) {
this->initialize<unsigned int>(size);
}
else if(arrayType == XdmfArrayType::String()) {
this->initialize<std::string>(size);
}
else if(arrayType == XdmfArrayType::Uninitialized()) {
this->release();
}
......@@ -833,11 +842,21 @@ XdmfArray::populateItem(const std::map<std::string, std::string> & itemPropertie
unsigned int index = 0;
boost::char_separator<char> sep(" \t\n");
boost::tokenizer<boost::char_separator<char> > tokens(contentVal, sep);
for(boost::tokenizer<boost::char_separator<char> >::const_iterator
iter = tokens.begin();
iter != tokens.end();
++iter, ++index) {
this->insert(index, atof((*iter).c_str()));
if(arrayType == XdmfArrayType::String()) {
for(boost::tokenizer<boost::char_separator<char> >::const_iterator
iter = tokens.begin();
iter != tokens.end();
++iter, ++index) {
this->insert(index, *iter);
}
}
else {
for(boost::tokenizer<boost::char_separator<char> >::const_iterator
iter = tokens.begin();
iter != tokens.end();
++iter, ++index) {
this->insert(index, atof((*iter).c_str()));
}
}
}
else {
......
......@@ -89,6 +89,7 @@ class XdmfHeavyDataController;
* UInt8
* UInt16
* UInt32
* String
*/
class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
......@@ -527,6 +528,7 @@ private:
shared_ptr<std::vector<unsigned char> >,
shared_ptr<std::vector<unsigned short> >,
shared_ptr<std::vector<unsigned int> >,
shared_ptr<std::vector<std::string> >,
boost::shared_array<const char>,
boost::shared_array<const short>,
boost::shared_array<const int>,
......
This diff is collapsed.
......@@ -97,6 +97,13 @@ XdmfArrayType::UInt32()
return p;
}
shared_ptr<const XdmfArrayType>
XdmfArrayType::String()
{
static shared_ptr<const XdmfArrayType> p(new XdmfArrayType("String", 0));
return p;
}
XdmfArrayType::XdmfArrayType(const std::string & name,
const unsigned int precision) :
mName(name),
......@@ -141,6 +148,9 @@ XdmfArrayType::New(const std::map<std::string, std::string> & itemProperties)
}
return Int32();
}
else if(typeVal.compare("String") == 0) {
return String();
}
else if(typeVal.compare("Char") == 0) {
return Int8();
}
......
......@@ -47,6 +47,7 @@
* UInt8
* UInt16
* UInt32
* String
*/
class XDMFCORE_EXPORT XdmfArrayType : public XdmfItemProperty {
......@@ -67,6 +68,7 @@ public:
static shared_ptr<const XdmfArrayType> UInt8();
static shared_ptr<const XdmfArrayType> UInt16();
static shared_ptr<const XdmfArrayType> UInt32();
static shared_ptr<const XdmfArrayType> String();
/**
* Get the data size, in bytes, of the value associated with this
......
......@@ -245,6 +245,13 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
}
}
void insertAsString(int startIndex, PyObject * list) {
Py_ssize_t size = PyList_Size(list);
for(Py_ssize_t i = 0; i < size; ++i) {
$self->insert<std::string>(i+startIndex, PyString_AsString(PyList_GetItem(list, i)));
}
}
};
%extend XdmfArrayType {
......@@ -340,6 +347,7 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%template(getValueAsUInt8) XdmfArray::getValue<unsigned char>;
%template(getValueAsUInt16) XdmfArray::getValue<unsigned short>;
%template(getValueAsUInt32) XdmfArray::getValue<unsigned int>;
%template(getValueAsString) XdmfArray::getValue<std::string>;
%template(initializeAsInt8) XdmfArray::initialize<char>;
%template(initializeAsInt16) XdmfArray::initialize<short>;
......@@ -350,6 +358,7 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%template(initializeAsUInt8) XdmfArray::initialize<unsigned char>;
%template(initializeAsUInt16) XdmfArray::initialize<unsigned short>;
%template(initializeAsUInt32) XdmfArray::initialize<unsigned int>;
%template(initializeAsString) XdmfArray::initialize<std::string>;
%template(insertValueAsInt8) XdmfArray::insert<char>;
%template(insertValueAsInt16) XdmfArray::insert<short>;
......@@ -360,6 +369,7 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%template(insertValueAsUInt8) XdmfArray::insert<unsigned char>;
%template(insertValueAsUInt16) XdmfArray::insert<unsigned short>;
%template(insertValueAsUInt32) XdmfArray::insert<unsigned int>;
%template(insertValueAsString) XdmfArray::insert<std::string>;
%template(pushBackAsInt8) XdmfArray::pushBack<char>;
%template(pushBackAsInt16) XdmfArray::pushBack<short>;
......@@ -370,6 +380,7 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%template(pushBackAsUInt8) XdmfArray::pushBack<unsigned char>;
%template(pushBackAsUInt16) XdmfArray::pushBack<unsigned short>;
%template(pushBackAsUInt32) XdmfArray::pushBack<unsigned int>;
%template(pushBackAsString) XdmfArray::pushBack<std::string>;
%template(resizeAsInt8) XdmfArray::resize<char>;
%template(resizeAsInt16) XdmfArray::resize<short>;
......@@ -380,6 +391,7 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%template(resizeAsUInt8) XdmfArray::resize<unsigned char>;
%template(resizeAsUInt16) XdmfArray::resize<unsigned short>;
%template(resizeAsUInt32) XdmfArray::resize<unsigned int>;
%template(resizeAsString) XdmfArray::resize<std::string>;
%template(UIntVector) std::vector<unsigned int>;
%template(ItemVector) std::vector<boost::shared_ptr<XdmfItem> >;
......
......@@ -115,6 +115,7 @@ XdmfHDF5Controller::read(XdmfArray * const array, const int fapl)
NULL);*/
hid_t datatype;
bool closeDatatype = false;
if(mType == XdmfArrayType::Int8()) {
datatype = H5T_NATIVE_CHAR;
}
......@@ -142,6 +143,11 @@ XdmfHDF5Controller::read(XdmfArray * const array, const int fapl)
else if(mType == XdmfArrayType::UInt32()) {
datatype = H5T_NATIVE_UINT;
}
else if(mType == XdmfArrayType::String()) {
datatype = H5Tcopy(H5T_C_S1);
H5Tset_size(datatype, H5T_VARIABLE);
closeDatatype = true;
}
else {
XdmfError::message(XdmfError::FATAL,
"Unknown XdmfArrayType encountered in hdf5 "
......@@ -156,15 +162,37 @@ XdmfHDF5Controller::read(XdmfArray * const array, const int fapl)
"allocated size in XdmfArray.");
}
status = H5Dread(dataset,
datatype,
memspace,
dataspace,
H5P_DEFAULT,
array->getValuesInternal());
if(closeDatatype) {
char ** data = new char*[numVals];
status = H5Dread(dataset,
datatype,
memspace,
dataspace,
H5P_DEFAULT,
data);
for(hssize_t i=0; i<numVals; ++i) {
array->insert<std::string>(i, data[i]);
}
status = H5Dvlen_reclaim(datatype,
dataspace,
H5P_DEFAULT,
data);
delete [] data;
}
else {
status = H5Dread(dataset,
datatype,
memspace,
dataspace,
H5P_DEFAULT,
array->getValuesInternal());
}
status = H5Sclose(dataspace);
status = H5Sclose(memspace);
status = H5Dclose(dataset);
if(closeDatatype) {
status = H5Tclose(datatype);
}
status = H5Fclose(hdf5Handle);
}
......@@ -171,6 +171,7 @@ XdmfHDF5Writer::write(XdmfArray & array,
const int fapl)
{
hid_t datatype = -1;
bool closeDatatype = false;
if(array.isInitialized()) {
if(array.getArrayType() == XdmfArrayType::Int8()) {
......@@ -200,6 +201,11 @@ XdmfHDF5Writer::write(XdmfArray & array,
else if(array.getArrayType() == XdmfArrayType::UInt32()) {
datatype = H5T_NATIVE_UINT;
}
else if(array.getArrayType() == XdmfArrayType::String()) {
datatype = H5Tcopy(H5T_C_S1);
H5Tset_size(datatype, H5T_VARIABLE);
closeDatatype = true;
}
else {
XdmfError::message(XdmfError::FATAL,
"Array of unsupported type in "
......@@ -395,6 +401,9 @@ XdmfHDF5Writer::write(XdmfArray & array,
status = H5Sclose(memspace);
}
status = H5Dclose(dataset);
if(closeDatatype) {
status = H5Tclose(datatype);
}
if(closeFile) {
mImpl->closeFile();
}
......
......@@ -303,5 +303,25 @@ int main(int, char **)
array9->insert<double>(9, 1.0);
assert(array9->getDimensionsString() == "10");
//
// STRINGS
//
shared_ptr<XdmfArray> stringArray = XdmfArray::New();
stringArray->resize<std::string>(3, "");
std::string firstValue = stringArray->getValue<std::string>(0);
assert(firstValue.compare("") == 0);
stringArray->insert<std::string>(0, "foo");
stringArray->insert<std::string>(1, "bar");
stringArray->insert<std::string>(2, "cat");
firstValue = stringArray->getValue<std::string>(0);
assert(firstValue.compare("foo") == 0);
std::string allValues = stringArray->getValuesString();
assert(allValues.compare("foo bar cat") == 0);
stringArray->insert<int>(3, 1);
allValues = stringArray->getValuesString();
assert(allValues.compare("foo bar cat 1") == 0);
int num = stringArray->getValue<int>(3);
assert(num == 1);
return 0;
}
......@@ -22,4 +22,36 @@ int main(int, char **)
array->read();
assert(array->getValuesString().compare("1 2 3 4") == 0);
shared_ptr<XdmfArray> stringArray = XdmfArray::New();
stringArray->pushBack<std::string>("foo");
stringArray->pushBack<std::string>("bar");
stringArray->pushBack<std::string>("cat");
stringArray->pushBack<std::string>("dog");
stringArray->pushBack<std::string>("blah");
assert(stringArray->getSize() == 5);
assert(stringArray->getValuesString().compare("foo bar cat dog blah") == 0);
shared_ptr<XdmfHDF5Writer> stringWriter =
XdmfHDF5Writer::New("testString.h5");
stringArray->accept(stringWriter);
stringArray->release();
stringArray->read();
assert(stringArray->getSize() == 5);
assert(stringArray->getValuesString().compare("foo bar cat dog blah") == 0);
assert(stringArray->getValue<std::string>(0).compare("foo") == 0);
/*
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);
*/
}
......@@ -49,3 +49,18 @@ if __name__ == "__main__":
array9.insertAsUInt32(0, values1)
print array9.getValuesString()
assert array9.getArrayType() == XdmfArrayType.UInt32()
stringArray = XdmfArray.New()
stringArray.insertValueAsString(0, "foo")
strings = ["bar", "car", "cellar"]
assert stringArray.getArrayType() == XdmfArrayType.String()
stringArray.insertAsString(0, strings)
assert stringArray.getSize() == 3
assert stringArray.getValueAsString(0) == "bar"
stringArray.pushBackAsString("dog")
assert stringArray.getSize() == 4
assert stringArray.getValueAsString(3) == "dog"
stringArray.resizeAsString(5, "")
assert stringArray.getSize() == 5
assert stringArray.getValueAsString(4) == ""
print stringArray.getValuesString()
......@@ -40,11 +40,10 @@ int main(int, char **)
std::vector<shared_ptr<XdmfItem> > readItems2 =
reader->read("TestXdmfReader1.xmf", "//Attribute");
assert(readItems2.size() == 4);
assert(readItems2.size() == 6);
shared_ptr<XdmfAttribute> readAttribute =
shared_dynamic_cast<XdmfAttribute>(readItems2[0]);
assert(readAttribute->getName().compare("Nodal Attribute") == 0 ||
readAttribute->getName().compare("Cell Attribute"));
assert(readAttribute->getName().compare("Nodal Attribute") == 0);
return 0;
}
......@@ -56,7 +56,7 @@ int main(int, char **)
grid->accept(visitor);
assert(visitor->getCount() == 69);
assert(visitor->getCount() == 71);
return 0;
}
......@@ -20,10 +20,11 @@ public:
* Number of Attributes = 2
* Cell Attributes = 1
* Nodal Attributes = 1
* Grid Attributes = 1
* Number of Sets = 1
* Nodal Set = 1
* Time = 100
* Total Number of Values = 69
* Total Number of Values = 71
*/
static shared_ptr<XdmfUnstructuredGrid> createHexahedron()
{
......@@ -61,6 +62,16 @@ public:
cellAttribute->setCenter(XdmfAttributeCenter::Cell());
cellAttribute->insert(0, &cellValues[0], 2);
// Add Grid Attribute
shared_ptr<XdmfAttribute> gridAttribute = XdmfAttribute::New();
std::string gridValues[] = {"foo", "bar"};
//int gridValues[] = {1, 2};
gridAttribute->setName("Grid Attribute");
gridAttribute->setType(XdmfAttributeType::Vector());
gridAttribute->setCenter(XdmfAttributeCenter::Grid());
gridAttribute->insert(0, &gridValues[0], 2);
// Add Node Set
shared_ptr<XdmfSet> nodeSet = XdmfSet::New();
int nodeIds[] = {0, 1, 2};
......@@ -74,6 +85,7 @@ public:
grid->insert(nodalAttribute);
grid->insert(cellAttribute);
grid->insert(gridAttribute);
grid->insert(nodeSet);
return grid;
}
......
......@@ -561,7 +561,7 @@ XdmfExodusReader::read(const std::string & fileName,
// Global variable data
double * global_var_vals = new double[num_global_vars];
ex_get_glob_vars(exodusHandle, 1, num_global_vars, &global_var_vals);
ex_get_glob_vars(exodusHandle, 1, num_global_vars, global_var_vals);
for (int i=0; i<num_global_vars; ++i) {
// Write global attribute to xdmf
shared_ptr<XdmfAttribute> attribute = XdmfAttribute::New();
......
......@@ -33,17 +33,19 @@ int main(int, char *)
assert(grid->getTopology()->getValue<double>(i) ==
hexahedron->getTopology()->getValue<double>(i));
}
assert(hexahedron->getNumberAttributes() + 1 == grid->getNumberAttributes());
assert(hexahedron->getNumberAttributes() + 2 == grid->getNumberAttributes());
for(unsigned int i=0; i<hexahedron->getNumberAttributes(); ++i) {
shared_ptr<XdmfAttribute> attribute1 = hexahedron->getAttribute(i);
shared_ptr<XdmfAttribute> attribute2 =
grid->getAttribute(attribute1->getName());
assert(attribute1->getCenter() == attribute2->getCenter());
assert(attribute1->getType() == attribute2->getType());
assert(attribute1->getSize() == attribute2->getSize());
for(unsigned int j=0; j<attribute1->getSize(); ++j) {
assert(attribute1->getValue<double>(i) ==
attribute2->getValue<double>(i));
if(attribute1->getCenter() != XdmfAttributeCenter::Grid()) {
shared_ptr<XdmfAttribute> attribute2 =
grid->getAttribute(attribute1->getName());
assert(attribute1->getCenter() == attribute2->getCenter());
assert(attribute1->getType() == attribute2->getType());
assert(attribute1->getSize() == attribute2->getSize());
for(unsigned int j=0; j<attribute1->getSize(); ++j) {
assert(attribute1->getValue<double>(i) ==
attribute2->getValue<double>(i));
}
}
}
}
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