diff options
author | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2015-05-06 13:50:11 +0200 |
---|---|---|
committer | Willem Jan Palenstijn <Willem.Jan.Palenstijn@cwi.nl> | 2015-05-06 15:18:04 +0200 |
commit | fff7470f1d74b0085355130350fa834ea8d37069 (patch) | |
tree | 941846f5ad9a07cc6e1e8b1b17a6fcb858d40e77 | |
parent | c6f6d6fbc3537cedefc0cef8e71819436a0a60c1 (diff) | |
download | astra-fff7470f1d74b0085355130350fa834ea8d37069.tar.gz astra-fff7470f1d74b0085355130350fa834ea8d37069.tar.bz2 astra-fff7470f1d74b0085355130350fa834ea8d37069.tar.xz astra-fff7470f1d74b0085355130350fa834ea8d37069.zip |
Make XML array handling consistent
setContent and getContent were using different XML formats previously.
-rw-r--r-- | include/astra/XMLNode.h | 35 | ||||
-rw-r--r-- | matlab/mex/mexHelpFunctions.cpp | 22 | ||||
-rw-r--r-- | python/astra/PyXMLDocument.pxd | 2 | ||||
-rw-r--r-- | python/astra/utils.pyx | 35 | ||||
-rw-r--r-- | src/XMLNode.cpp | 150 |
5 files changed, 127 insertions, 117 deletions
diff --git a/include/astra/XMLNode.h b/include/astra/XMLNode.h index f79c1a8..4d29d5c 100644 --- a/include/astra/XMLNode.h +++ b/include/astra/XMLNode.h @@ -119,14 +119,8 @@ public: */ vector<string> getContentArray() const; - /** Get the content of the XML node as a c-array of float32 data. - * - * @param _pfData data array, shouldn't be initialized already. - * @param _iSize number of elements stored in _pfData - */ - void getContentNumericalArray(float32*& _pfData, int& _iSize) const; - /** Get the content of the XML node as a stl container of float32 data. + * NB: A 2D matrix is returned as a linear list * * @return node content */ @@ -259,13 +253,38 @@ public: */ void setContent(float32 _fValue); - /** Add a list of numerical data to the node: <...>_sText</...> + /** Add a list of numerical data to the node * * @param _pfList data * @param _iSize number of elements in the list */ void setContent(float32* _pfList, int _iSize); + /** Add a list of numerical data to the node + * + * @param _pfList data + * @param _iSize number of elements in the list + */ + void setContent(double* _pfList, int _iSize); + + /** Add a (2D) matrix of numerical data to the node + * + * @param _pfMatrix data + * @param _iWidth width of the matrix + * @param _iHeight height of the matrix + * @param transposed true is C order, false is Fortran order + */ + void setContent(float32* _pfMatrix, int _iWidth, int _iHeight, bool transposed); + + /** Add a (2D) matrix of numerical data to the node + * + * @param _pfMatrix data + * @param _iWidth width of the matrix + * @param _iHeight height of the matrix + * @param transposed true is C order, false is Fortran order + */ + void setContent(double* _pfMatrix, int _iWidth, int _iHeight, bool transposed); + /** Add an attribute to this node: <... _sName="_sValue"> * * @param _sName name of the attribute diff --git a/matlab/mex/mexHelpFunctions.cpp b/matlab/mex/mexHelpFunctions.cpp index 00d766f..87a9672 100644 --- a/matlab/mex/mexHelpFunctions.cpp +++ b/matlab/mex/mexHelpFunctions.cpp @@ -218,17 +218,8 @@ bool structToXMLNode(XMLNode node, const mxArray* pStruct) return false; } XMLNode listbase = node.addChildNode(sFieldName); - listbase.addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); double* pdValues = mxGetPr(pField); - int index = 0; - for (unsigned int row = 0; row < mxGetM(pField); row++) { - for (unsigned int col = 0; col < mxGetN(pField); col++) { - XMLNode item = listbase.addChildNode("ListItem"); - item.addAttribute("index", index); - item.addAttribute("value", pdValues[col*mxGetM(pField)+row]); - index++; - } - } + listbase.setContent(pdValues, mxGetN(pField), mxGetM(pField), true); } // not castable to a single string @@ -278,17 +269,8 @@ bool optionsToXMLNode(XMLNode node, const mxArray* pOptionStruct) XMLNode listbase = node.addChildNode("Option"); listbase.addAttribute("key", sFieldName); - listbase.addAttribute("listsize", mxGetM(pField)*mxGetN(pField)); double* pdValues = mxGetPr(pField); - int index = 0; - for (unsigned int row = 0; row < mxGetM(pField); row++) { - for (unsigned int col = 0; col < mxGetN(pField); col++) { - XMLNode item = listbase.addChildNode("ListItem"); - item.addAttribute("index", index); - item.addAttribute("value", pdValues[col*mxGetM(pField)+row]); - index++; - } - } + listbase.setContent(pdValues, mxGetN(pField), mxGetM(pField), true); } else { mexErrMsgTxt("Unsupported option type"); return false; diff --git a/python/astra/PyXMLDocument.pxd b/python/astra/PyXMLDocument.pxd index 57c447e..033b8ef 100644 --- a/python/astra/PyXMLDocument.pxd +++ b/python/astra/PyXMLDocument.pxd @@ -53,6 +53,8 @@ cdef extern from "astra/XMLNode.h" namespace "astra": string getAttribute(string) list[XMLNode] getNodes() vector[float32] getContentNumericalArray() + void setContent(double*, int, int, bool) + void setContent(double*, int) string getContent() bool hasAttribute(string) diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 8f1e0b7..ddb37aa 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -26,6 +26,7 @@ # distutils: language = c++ # distutils: libraries = astra +cimport numpy as np import numpy as np import six from libcpp.string cimport string @@ -85,6 +86,7 @@ cdef void readDict(XMLNode root, _dc): cdef XMLNode itm cdef int i cdef int j + cdef double* data dc = convert_item(_dc) for item in dc: @@ -93,21 +95,11 @@ cdef void readDict(XMLNode root, _dc): if val.size == 0: break listbase = root.addChildNode(item) - listbase.addAttribute(< string > six.b('listsize'), < float32 > val.size) - index = 0 + data = <double*>np.PyArray_DATA(np.ascontiguousarray(val,dtype=np.float64)) if val.ndim == 2: - for i in range(val.shape[0]): - for j in range(val.shape[1]): - itm = listbase.addChildNode(six.b('ListItem')) - itm.addAttribute(< string > six.b('index'), < float32 > index) - itm.addAttribute( < string > six.b('value'), < float32 > val[i, j]) - index += 1 + listbase.setContent(data, val.shape[1], val.shape[0], False) elif val.ndim == 1: - for i in range(val.shape[0]): - itm = listbase.addChildNode(six.b('ListItem')) - itm.addAttribute(< string > six.b('index'), < float32 > index) - itm.addAttribute(< string > six.b('value'), < float32 > val[i]) - index += 1 + listbase.setContent(data, val.shape[0]) else: raise Exception("Only 1 or 2 dimensions are allowed") elif isinstance(val, dict): @@ -127,6 +119,7 @@ cdef void readOptions(XMLNode node, dc): cdef XMLNode itm cdef int i cdef int j + cdef double* data for item in dc: val = dc[item] if node.hasOption(item): @@ -136,21 +129,11 @@ cdef void readOptions(XMLNode node, dc): break listbase = node.addChildNode(six.b('Option')) listbase.addAttribute(< string > six.b('key'), < string > item) - listbase.addAttribute(< string > six.b('listsize'), < float32 > val.size) - index = 0 + data = <double*>np.PyArray_DATA(np.ascontiguousarray(val,dtype=np.float64)) if val.ndim == 2: - for i in range(val.shape[0]): - for j in range(val.shape[1]): - itm = listbase.addChildNode(six.b('ListItem')) - itm.addAttribute(< string > six.b('index'), < float32 > index) - itm.addAttribute( < string > six.b('value'), < float32 > val[i, j]) - index += 1 + listbase.setContent(data, val.shape[1], val.shape[0], False) elif val.ndim == 1: - for i in range(val.shape[0]): - itm = listbase.addChildNode(six.b('ListItem')) - itm.addAttribute(< string > six.b('index'), < float32 > index) - itm.addAttribute(< string > six.b('value'), < float32 > val[i]) - index += 1 + listbase.setContent(data, val.shape[0]) else: raise Exception("Only 1 or 2 dimensions are allowed") else: diff --git a/src/XMLNode.cpp b/src/XMLNode.cpp index 75985cc..0ec701f 100644 --- a/src/XMLNode.cpp +++ b/src/XMLNode.cpp @@ -32,6 +32,11 @@ $Id$ #include "rapidxml/rapidxml_print.hpp" #include <boost/lexical_cast.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/classification.hpp> + + using namespace rapidxml; using namespace astra; @@ -167,77 +172,43 @@ vector<string> XMLNode::getContentArray() const //----------------------------------------------------------------------------- // Get node content - NUMERICAL LIST +// NB: A 2D matrix is returned as a linear list vector<float32> XMLNode::getContentNumericalArray() const { - // is scalar - if (!hasAttribute("listsize")) { - vector<float32> res(1); - res[0] = getContentNumerical(); - return res; - } + string input = getContent(); - int iSize = boost::lexical_cast<int>(getAttribute("listsize")); - // create result array - vector<float32> res(iSize); - // loop all list item nodes - list<XMLNode> nodes = getNodes("ListItem"); - for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); it++) { - int iIndex = it->getAttributeNumerical("index"); - float32 fValue = it->getAttributeNumerical("value"); - ASTRA_ASSERT(iIndex < iSize); - res[iIndex] = fValue; + // split + std::vector<std::string> items; + boost::split(items, input, boost::is_any_of(",;")); + + // init list + vector<float32> out; + out.resize(items.size()); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = boost::lexical_cast<float32>(items[i]); } - // return - return res; + return out; } vector<double> XMLNode::getContentNumericalArrayDouble() const { - // is scalar - if (!hasAttribute("listsize")) { - vector<double> res(1); - res[0] = getContentNumerical(); - return res; - } + string input = getContent(); - int iSize = boost::lexical_cast<int>(getAttribute("listsize")); - // create result array - vector<double> res(iSize); - // loop all list item nodes - list<XMLNode> nodes = getNodes("ListItem"); - for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); it++) { - int iIndex = it->getAttributeNumerical("index"); - double fValue = it->getAttributeNumericalDouble("value"); - ASTRA_ASSERT(iIndex < iSize); - res[iIndex] = fValue; - } - // return - return res; -} + // split + std::vector<std::string> items; + boost::split(items, input, boost::is_any_of(",;")); -//----------------------------------------------------------------------------- -// Get node content - NUMERICAL LIST 2 -void XMLNode::getContentNumericalArray(float32*& _pfData, int& _iSize) const -{ - // is scalar - if (!hasAttribute("listsize")) { - _iSize = 1; - _pfData = new float32[_iSize]; - _pfData[0] = getContentNumerical(); - return; - } - // get listsize - _iSize = boost::lexical_cast<int>(getAttribute("listsize")); - // create result array - _pfData = new float32[_iSize]; - // loop all list item nodes - list<XMLNode> nodes = getNodes("ListItem"); - for (list<XMLNode>::iterator it = nodes.begin(); it != nodes.end(); it++) { - int iIndex = it->getAttributeNumerical("index"); - float32 fValue = it->getAttributeNumerical("value"); - ASTRA_ASSERT(iIndex < _iSize); - _pfData[iIndex] = fValue; + // init list + vector<double> out; + out.resize(items.size()); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = boost::lexical_cast<double>(items[i]); } + return out; } //----------------------------------------------------------------------------- @@ -420,16 +391,69 @@ void XMLNode::setContent(float32 _fValue) //----------------------------------------------------------------------------- // Set content - LIST -void XMLNode::setContent(float32* pfList, int _iSize) -{ + +template<typename T> +static std::string setContentList_internal(T* pfList, int _iSize) { std::string str = (_iSize > 0) ? boost::lexical_cast<std::string>(pfList[0]) : ""; for (int i = 1; i < _iSize; i++) { str += "," + boost::lexical_cast<std::string>(pfList[i]); } - setContent(str); + return str; +} + +void XMLNode::setContent(float32* pfList, int _iSize) +{ + setContent(setContentList_internal<float32>(pfList, _iSize)); +} + +void XMLNode::setContent(double* pfList, int _iSize) +{ + setContent(setContentList_internal<double>(pfList, _iSize)); } //----------------------------------------------------------------------------- +// Set content - MATRIX + +template<typename T> +static std::string setContentMatrix_internal(T* _pfMatrix, int _iWidth, int _iHeight, bool transposed) +{ + std::string str = ""; + + int s1,s2; + + if (!transposed) { + s1 = 1; + s2 = _iWidth; + } else { + s1 = _iHeight; + s2 = 1; + } + + for (int y = 0; y < _iHeight; ++y) { + if (_iWidth > 0) + str += boost::lexical_cast<std::string>(_pfMatrix[0*s1 + y*s2]); + for (int x = 1; x < _iWidth; x++) + str += "," + boost::lexical_cast<std::string>(_pfMatrix[x*s1 + y*s2]); + + if (y != _iHeight-1) + str += ";"; + } + + return str; +} + +void XMLNode::setContent(float32* _pfMatrix, int _iWidth, int _iHeight, bool transposed) +{ + setContent(setContentMatrix_internal<float32>(_pfMatrix, _iWidth, _iHeight, transposed)); +} + +void XMLNode::setContent(double* _pfMatrix, int _iWidth, int _iHeight, bool transposed) +{ + setContent(setContentMatrix_internal<double>(_pfMatrix, _iWidth, _iHeight, transposed)); +} + + +//----------------------------------------------------------------------------- // Add attribute - STRING void XMLNode::addAttribute(string _sName, string _sText) { |