Commit 95c92a3b authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Fix Absolute/Relative path issues when reading and writing from separate...

ENH: Fix Absolute/Relative path issues when reading and writing from separate directories.  Modify XML attributes to be less verbose e.g. (AttributeType --> Type).  Separate XdmfGridCollection from XdmfGrid at the XdmfDomain level.
parent d0b6406b
......@@ -63,7 +63,11 @@ XdmfAttributeType::~XdmfAttributeType()
boost::shared_ptr<const XdmfAttributeType> XdmfAttributeType::New(const std::map<std::string, std::string> & itemProperties)
{
std::map<std::string, std::string>::const_iterator type = itemProperties.find("AttributeType");
std::map<std::string, std::string>::const_iterator type = itemProperties.find("Type");
if(type == itemProperties.end())
{
type = itemProperties.find("AttributeType");
}
if(type != itemProperties.end())
{
const std::string typeVal = type->second;
......@@ -115,5 +119,5 @@ bool XdmfAttributeType::operator!=(const XdmfAttributeType & attributeType) cons
void XdmfAttributeType::getProperties(std::map<std::string, std::string> & collectedProperties) const
{
collectedProperties["AttributeType"] = mName;
collectedProperties["Type"] = mName;
}
......@@ -7,6 +7,7 @@
#include "XdmfDomain.hpp"
#include "XdmfGrid.hpp"
#include "XdmfGridCollection.hpp"
XdmfDomain::XdmfDomain()
{
......@@ -20,11 +21,6 @@ XdmfDomain::~XdmfDomain()
const std::string XdmfDomain::ItemTag = "Domain";
void XdmfDomain::insert(const boost::shared_ptr<XdmfGrid> grid)
{
mGrids.push_back(grid);
}
boost::shared_ptr<XdmfGrid> XdmfDomain::getGrid(const unsigned int index)
{
return boost::const_pointer_cast<XdmfGrid>(static_cast<const XdmfDomain &>(*this).getGrid(index));
......@@ -35,11 +31,24 @@ boost::shared_ptr<const XdmfGrid> XdmfDomain::getGrid(const unsigned int index)
if(index >= mGrids.size())
{
assert(false);
// Out of range --- should we throw exceptions?
}
return mGrids[index];
}
boost::shared_ptr<XdmfGridCollection> XdmfDomain::getGridCollection(const unsigned int index)
{
return boost::const_pointer_cast<XdmfGridCollection>(static_cast<const XdmfDomain &>(*this).getGridCollection(index));
}
boost::shared_ptr<const XdmfGridCollection> XdmfDomain::getGridCollection(const unsigned int index) const
{
if(index >= mGridCollections.size())
{
assert(false);
}
return mGridCollections[index];
}
std::map<std::string, std::string> XdmfDomain::getItemProperties() const
{
std::map<std::string, std::string> domainProperties;
......@@ -51,16 +60,42 @@ std::string XdmfDomain::getItemTag() const
return ItemTag;
}
unsigned int XdmfDomain::getNumberOfGrids() const
unsigned int XdmfDomain::getNumberGrids() const
{
return mGrids.size();
}
unsigned int XdmfDomain::getNumberGridCollections() const
{
return mGridCollections.size();
}
void XdmfDomain::insert(const boost::shared_ptr<XdmfGrid> grid)
{
mGrids.push_back(grid);
}
void XdmfDomain::insert(const boost::shared_ptr<XdmfGridCollection> gridCollection)
{
mGridCollections.push_back(gridCollection);
}
void XdmfDomain::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems)
{
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
this->insert(boost::shared_dynamic_cast<XdmfGrid>(*iter));
if(boost::shared_ptr<XdmfGridCollection> gridCollection = boost::shared_dynamic_cast<XdmfGridCollection>(*iter))
{
this->insert(gridCollection);
}
else if(boost::shared_ptr<XdmfGrid> grid = boost::shared_dynamic_cast<XdmfGrid>(*iter))
{
this->insert(grid);
}
else
{
assert(false);
}
}
}
......@@ -73,10 +108,23 @@ void XdmfDomain::removeGrid(const unsigned int index)
mGrids.erase(mGrids.begin() + index);
}
void XdmfDomain::removeGridCollection(const unsigned int index)
{
if(index >= mGridCollections.size())
{
assert(false);
}
mGridCollections.erase(mGridCollections.begin() + index);
}
void XdmfDomain::traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor) const
{
for(std::vector<boost::shared_ptr<XdmfGrid> >::const_iterator iter = mGrids.begin(); iter != mGrids.end(); ++iter)
{
(*iter)->accept(visitor);
}
for(std::vector<boost::shared_ptr<XdmfGridCollection> >::const_iterator iter = mGridCollections.begin(); iter != mGridCollections.end(); ++iter)
{
(*iter)->accept(visitor);
}
}
......@@ -3,6 +3,7 @@
// Forward Declarations
class XdmfGrid;
class XdmfGridCollection;
// Includes
#include "XdmfItem.hpp"
......@@ -26,8 +27,8 @@ public:
/**
* Get a XdmfGrid attached to the domain.
*
* @param index an unsigned int of the grid to retrieve.
* @return smart pointer to the grid at the specified index attached to this domain.
* @param index of the grid to retrieve.
* @return grid at the specified index attached to this domain.
*/
boost::shared_ptr<XdmfGrid> getGrid(const unsigned int index);
......@@ -35,10 +36,26 @@ public:
* Get a XdmfGrid attached to this domain (const version).
*
* @param index of the grid to retrieve.
* @return pointer to the grid attached to this domain.
* @return grid at the specified index attached to this domain.
*/
boost::shared_ptr<const XdmfGrid> getGrid(const unsigned int index) const;
/**
* Get a XdmfGridCollection attached to the domain.
*
* @param index of the grid collection to retrieve.
* @return grid collection at the specified index attached to this domain.
*/
boost::shared_ptr<XdmfGridCollection> getGridCollection(const unsigned int index);
/**
* Get a XdmfGridCollection attached to the domain (const version).
*
* @param index of the grid collection to retrieve.
* @return grid collection at the specified index attached to this domain.
*/
boost::shared_ptr<const XdmfGridCollection> getGridCollection(const unsigned int index) const;
std::map<std::string, std::string> getItemProperties() const;
std::string getItemTag() const;
......@@ -48,7 +65,14 @@ public:
*
* @return unsigned int containing the number of XdmfGrids attached to this domain.
*/
unsigned int getNumberOfGrids() const;
unsigned int getNumberGrids() const;
/**
* Get the number of XdmfGridCollections attached to this domain.
*
* @return unsigned int containing the number of XdmfGridCollections attached to this domain.
*/
unsigned int getNumberGridCollections() const;
/**
* Insert a XdmfGrid into the domain.
......@@ -57,6 +81,13 @@ public:
*/
void insert(const boost::shared_ptr<XdmfGrid> grid);
/**
* Insert a XdmfGridCollection into the domain.
*
* @param gridCollection a shared pointer to an XdmfGridCollection to insert into the domain.
*/
void insert(const boost::shared_ptr<XdmfGridCollection> gridCollection);
/**
* Remove an XdmfGrid from the domain.
*
......@@ -64,6 +95,13 @@ public:
*/
void removeGrid(const unsigned int index);
/**
* Remove an XdmfGridCollection from the domain.
*
* @param index of the XdmfGridCollection to remove.
*/
void removeGridCollection(const unsigned int index);
virtual void traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor) const;
protected:
......@@ -77,6 +115,7 @@ private:
void operator=(const XdmfDomain & domain); // Not implemented.
std::vector<boost::shared_ptr<XdmfGrid> > mGrids;
std::vector<boost::shared_ptr<XdmfGridCollection> > mGridCollections;
};
#endif /* XDMFDOMAIN_HPP_ */
......@@ -74,7 +74,12 @@ XdmfGeometryType::~XdmfGeometryType()
boost::shared_ptr<const XdmfGeometryType> XdmfGeometryType::New(const std::map<std::string, std::string> & itemProperties)
{
std::map<std::string, std::string>::const_iterator type = itemProperties.find("GeometryType");
std::map<std::string, std::string>::const_iterator type = itemProperties.find("Type");
if(type == itemProperties.end())
{
type = itemProperties.find("GeometryType");
}
if(type != itemProperties.end())
{
const std::string typeVal = type->second;
......@@ -139,5 +144,5 @@ unsigned int XdmfGeometryType::getDimensions() const
void XdmfGeometryType::getProperties(std::map<std::string, std::string> & collectedProperties) const
{
collectedProperties["GeometryType"] = mName;
collectedProperties["Type"] = mName;
}
......@@ -166,7 +166,7 @@ void XdmfGrid::populateItem(const std::map<std::string, std::string> & itemPrope
}
else
{
assert(false);
mName = "";
}
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
......
......@@ -49,7 +49,11 @@ XdmfSetType::~XdmfSetType()
boost::shared_ptr<const XdmfSetType> XdmfSetType::New(const std::map<std::string, std::string> & itemProperties)
{
std::map<std::string, std::string>::const_iterator type = itemProperties.find("SetType");
std::map<std::string, std::string>::const_iterator type = itemProperties.find("Type");
if(type == itemProperties.end())
{
type = itemProperties.find("SetType");
}
if(type != itemProperties.end())
{
const std::string typeVal = type->second;
......@@ -93,5 +97,5 @@ bool XdmfSetType::operator!=(const XdmfSetType & setType) const
void XdmfSetType::getProperties(std::map<std::string, std::string> & collectedProperties) const
{
collectedProperties["SetType"] = this->mName;
collectedProperties["Type"] = this->mName;
}
......@@ -11,8 +11,7 @@
#include "XdmfTopologyType.hpp"
XdmfTopology::XdmfTopology() :
mTopologyType(XdmfTopologyType::NoTopologyType()),
mNumberElements(0)
mTopologyType(XdmfTopologyType::NoTopologyType())
{
std::cout << "Created Topology " << this << std::endl;
}
......@@ -33,9 +32,12 @@ std::map<std::string, std::string> XdmfTopology::getItemProperties() const
{
std::map<std::string, std::string> topologyProperties;
mTopologyType->getProperties(topologyProperties);
std::stringstream numElements;
numElements << this->getNumberElements();
topologyProperties["Dimensions"] = numElements.str();
if(mTopologyType != XdmfTopologyType::Polyvertex())
{
std::stringstream numElements;
numElements << this->getNumberElements();
topologyProperties["Dimensions"] = numElements.str();
}
return topologyProperties;
}
......
......@@ -59,7 +59,6 @@ private:
XdmfTopology(const XdmfTopology & topology); // Not implemented.
void operator=(const XdmfTopology & topology); // Not implemented.
int mNumberElements;
boost::shared_ptr<const XdmfTopologyType> mTopologyType;
};
......
......@@ -198,7 +198,12 @@ XdmfTopologyType::~XdmfTopologyType()
boost::shared_ptr<const XdmfTopologyType> XdmfTopologyType::New(const std::map<std::string, std::string> & itemProperties)
{
std::map<std::string, std::string>::const_iterator type = itemProperties.find("TopologyType");
std::map<std::string, std::string>::const_iterator type = itemProperties.find("Type");
if(type == itemProperties.end())
{
type = itemProperties.find("TopologyType");
}
std::map<std::string, std::string>::const_iterator nodesPerElement = itemProperties.find("NodesPerElement");
if(type != itemProperties.end())
{
......@@ -345,7 +350,7 @@ unsigned int XdmfTopologyType::getNodesPerElement() const
void XdmfTopologyType::getProperties(std::map<std::string, std::string> & collectedProperties) const
{
collectedProperties["TopologyType"] = mName;
collectedProperties["Type"] = mName;
if(mName.compare("Polygon") == 0)
{
std::stringstream nodesPerElement;
......
......@@ -220,6 +220,16 @@ public:
return toReturn.str();
}
std::string getValuesString(const unsigned char * const array, const int numValues) const
{
std::stringstream toReturn;
for(int i=0; i<numValues; ++i)
{
toReturn << (int)array[i] << " ";
}
return toReturn.str();
}
template<typename T>
std::string getValuesString(const T * const array, const int numValues) const
{
......@@ -562,6 +572,26 @@ void XdmfArray::populateItem(const std::map<std::string, std::string> & itemProp
{
if(format->second.compare("HDF") == 0)
{
std::map<std::string, std::string>::const_iterator xmlDir = itemProperties.find("XMLDir");
if(xmlDir == itemProperties.end())
{
assert(false);
}
size_t colonLocation = contentVal.find(":");
if(colonLocation != std::string::npos)
{
size_t fileDir = contentVal.substr(0, colonLocation).find_last_of("/\\");
if(fileDir == std::string::npos)
{
std::stringstream newContentVal;
newContentVal << xmlDir->second << "/" << contentVal;
contentVal = newContentVal.str();
}
}
else
{
assert(false);
}
mHDF5Controller = XdmfHDF5Controller::New(contentVal, sizeVal, arrayType);
}
else if(format->second.compare("XML") == 0)
......
......@@ -87,10 +87,14 @@ boost::shared_ptr<const XdmfArrayType> XdmfArrayType::New(const std::map<std::st
type = itemProperties.find("NumberType");
}
std::map<std::string, std::string>::const_iterator precision = itemProperties.find("Precision");
if(type != itemProperties.end() && precision != itemProperties.end())
if(type != itemProperties.end())
{
const std::string typeVal = type->second;
const unsigned int precisionVal = atoi(precision->second.c_str());
unsigned int precisionVal = 0;
if(precision != itemProperties.end())
{
precisionVal = atoi(precision->second.c_str());
}
if(typeVal.compare("None") == 0)
{
return Uninitialized();
......@@ -103,22 +107,22 @@ boost::shared_ptr<const XdmfArrayType> XdmfArrayType::New(const std::map<std::st
{
return Int16();
}
else if(typeVal.compare("Int") == 0 && precisionVal == 4)
{
return Int32();
}
else if(typeVal.compare("Int") == 0 && precisionVal == 8)
{
return Int64();
}
else if(typeVal.compare("Float") == 0 && precisionVal == 4)
else if(typeVal.compare("Int") == 0)
{
return Float32();
return Int32();
}
else if(typeVal.compare("Float") == 0 && precisionVal == 8)
{
return Float64();
}
else if(typeVal.compare("Float") == 0)
{
return Float32();
}
else if(typeVal.compare("UChar") == 0)
{
return UInt8();
......
......@@ -26,7 +26,7 @@ public:
/**
* Constructs XdmfItems for all nodes in currNode's tree. XdmfItems are constructed by recursively calling this function for all children of currNode.
*/
std::vector<boost::shared_ptr<XdmfItem> > read(xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap) const
std::vector<boost::shared_ptr<XdmfItem> > read(xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, const std::string & xmlDir) const
{
std::vector<boost::shared_ptr<XdmfItem> > myItems;
......@@ -50,14 +50,14 @@ public:
xmlXPathObjectPtr xPathObject = xmlXPtrEval(xpointer, xPathContext);
for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
{
this->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathContext, xPathMap, myItems);
this->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathContext, xPathMap, myItems, xmlDir);
}
xmlXPathFreeObject(xPathObject);
}
else
{
// Normal reading
this->readSingleNode(currNode, xPathContext, xPathMap, myItems);
this->readSingleNode(currNode, xPathContext, xPathMap, myItems, xmlDir);
}
}
currNode = currNode->next;
......@@ -70,7 +70,7 @@ private:
/**
* Reads a single xmlNode into an XdmfItem object in memory. The constructed XdmfItem is added to myItems and an entry is added mapping the xmlNodePtr to the new XdmfItem in the xPathMap.
*/
void readSingleNode(const xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, std::vector<boost::shared_ptr<XdmfItem> > & myItems) const
void readSingleNode(const xmlNodePtr currNode, const xmlXPathContextPtr xPathContext, std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > & xPathMap, std::vector<boost::shared_ptr<XdmfItem> > & myItems, const std::string & xmlDir) const
{
std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> >::const_iterator iter = xPathMap.find(currNode);
if(iter != xPathMap.end())
......@@ -83,18 +83,16 @@ private:
if(currNode->children != NULL)
{
itemProperties["Content"] = (const char *)currNode->children->content;
itemProperties["XMLDir"] = xmlDir;
}
else
{
itemProperties["Content"] = "";
}
xmlAttrPtr currAttribute = currNode->properties;
while(currAttribute != NULL)
{
itemProperties[(const char *)currAttribute->name] = (const char *)currAttribute->children->content;
currAttribute = currAttribute->next;
}
std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children, xPathContext, xPathMap);
std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children, xPathContext, xPathMap, xmlDir);
boost::shared_ptr<XdmfItem> newItem = mItemFactory->createItem((const char *)currNode->name, itemProperties);
newItem->populateItem(itemProperties, childItems);
myItems.push_back(newItem);
......@@ -119,6 +117,17 @@ XdmfCoreReader::~XdmfCoreReader()
boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
std::string xmlDir = "";
size_t index = filePath.find_last_of("/\\");
if(index != std::string::npos)
{
xmlDir = filePath.substr(0, index);
}
else
{
xmlDir = XdmfObject::getCWD();
}
const xmlDocPtr document = xmlReadFile(filePath.c_str(), NULL, 0);
const xmlXPathContextPtr xPathContext = xmlXPtrNewContext(document, NULL, NULL);
if(document == NULL)
......@@ -128,7 +137,7 @@ boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) c
const xmlNodePtr currNode = xmlDocGetRootElement(document);
std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > xPathMap;
const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children, xPathContext, xPathMap);
const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children, xPathContext, xPathMap, xmlDir);
xmlXPathFreeContext(xPathContext);
xmlFreeDoc(document);
xmlCleanupParser();
......
......@@ -9,10 +9,15 @@
XdmfObject::XdmfObject()
{
}
XdmfObject::~XdmfObject()
{
}
std::string XdmfObject::getCWD()
{
char buffer[256];
getcwd(buffer, 256);
return buffer;
}
......@@ -23,6 +23,13 @@ public:
virtual ~XdmfObject();
/**
* Gets the current working directory Xdmf is running in. This is useful for reading and writing files containing relative paths to hdf5 datasets.
*
* @return the current working directory.
*/
static std::string getCWD();
protected:
XdmfObject();
......
......@@ -126,25 +126,56 @@ void XdmfWriter::setMode(const Mode mode)
void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisitor> visitor)
{
std::stringstream xmlTextValues;
if(array.getHDF5Controller() && array.getHDF5Controller()->getFilePath().compare(mImpl->mHDF5Writer->getFilePath()) != 0 && mImpl->mMode == Default)
if(array.getSize() > 0)
{
array.read();
}
std::stringstream xmlTextValues;
if(array.getHDF5Controller() || array.getSize() > mImpl->mLightDataLimit)
{
mImpl->mHDF5Writer->visit(array, mImpl->mHDF5Writer);
xmlTextValues << mImpl->mHDF5Writer->getLastWrittenDataSet();
}
else
{
xmlTextValues << array.getValuesString();
}
if(array.getHDF5Controller() && array.getHDF5Controller()->getFilePath().compare(mImpl->mHDF5Writer->getFilePath()) != 0 && mImpl->mMode == Default)
{
array.read();
}
this->visit(dynamic_cast<XdmfItem &>(array), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
if(array.getHDF5Controller() || array.getSize() > mImpl->mLightDataLimit)
{
mImpl->mHDF5Writer->visit(array, mImpl->mHDF5Writer);
std::string contentVal = mImpl->mHDF5Writer->getLastWrittenDataSet();
std::cout << contentVal << std::endl;
if(size_t colonLocation = contentVal.find(":") != std::string::npos)
{
if(size_t fileDir = contentVal.substr(0, colonLocation).find_last_of("/\\") != std::string::npos)
{
// Absolute Path
std::string cwd = XdmfObject::getCWD();
if(size_t relPathBegin = contentVal.find(cwd) != std::string::npos)
{
// Substitute Relative Path
xmlTextValues << contentVal.substr(cwd.size() + 1, contentVal.size() - cwd.size());
}
else
{
// Write Absolute Path
xmlTextValues << contentVal;
}
}
else
{
// Relative Path
xmlTextValues << contentVal;
}
}
else
{
assert(false);
}
}
else
{
xmlTextValues << array.getValuesString();
}
this->visit(dynamic_cast<XdmfItem &>(array), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
}
}
void XdmfWriter::visit(XdmfItem & item, const boost::shared_ptr<XdmfBaseVisitor> visitor)
......
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