From 47fe3421585302f2101691a685ab99b0e1ad5cfc Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 1 May 2015 17:48:32 +0200 Subject: Change XMLNode* to XMLNode An XMLNode object is already simply a pointer, so no need to dynamically allocate XMLNodes. --- python/astra/PyIncludes.pxd | 2 +- python/astra/PyXMLDocument.pxd | 8 ++++---- python/astra/utils.pyx | 29 ++++++++++------------------- 3 files changed, 15 insertions(+), 24 deletions(-) (limited to 'python') diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd index 1d8285b..909f58f 100644 --- a/python/astra/PyIncludes.pxd +++ b/python/astra/PyIncludes.pxd @@ -43,7 +43,7 @@ cdef extern from "astra/Config.h" namespace "astra": cdef cppclass Config: Config() void initialize(string rootname) - XMLNode *self + XMLNode self cdef extern from "astra/VolumeGeometry2D.h" namespace "astra": cdef cppclass CVolumeGeometry2D: diff --git a/python/astra/PyXMLDocument.pxd b/python/astra/PyXMLDocument.pxd index 69781f1..57c447e 100644 --- a/python/astra/PyXMLDocument.pxd +++ b/python/astra/PyXMLDocument.pxd @@ -44,14 +44,14 @@ cdef extern from "astra/Globals.h" namespace "astra": cdef extern from "astra/XMLNode.h" namespace "astra": cdef cppclass XMLNode: string getName() - XMLNode *addChildNode(string name) - XMLNode *addChildNode(string, string) + XMLNode addChildNode(string name) + XMLNode addChildNode(string, string) void addAttribute(string, string) void addAttribute(string, float32) void addOption(string, string) bool hasOption(string) string getAttribute(string) - list[XMLNode *] getNodes() + list[XMLNode] getNodes() vector[float32] getContentNumericalArray() string getContent() bool hasAttribute(string) @@ -59,7 +59,7 @@ cdef extern from "astra/XMLNode.h" namespace "astra": cdef extern from "astra/XMLDocument.h" namespace "astra": cdef cppclass XMLDocument: void saveToFile(string sFilename) - XMLNode *getRootNode() + XMLNode getRootNode() cdef extern from "astra/XMLDocument.h" namespace "astra::XMLDocument": cdef XMLDocument *createDocument(string rootname) diff --git a/python/astra/utils.pyx b/python/astra/utils.pyx index 0439f1b..8f1e0b7 100644 --- a/python/astra/utils.pyx +++ b/python/astra/utils.pyx @@ -80,9 +80,9 @@ def wrap_from_bytes(value): return s -cdef void readDict(XMLNode * root, _dc): - cdef XMLNode * listbase - cdef XMLNode * itm +cdef void readDict(XMLNode root, _dc): + cdef XMLNode listbase + cdef XMLNode itm cdef int i cdef int j @@ -102,34 +102,29 @@ cdef void readDict(XMLNode * root, _dc): itm.addAttribute(< string > six.b('index'), < float32 > index) itm.addAttribute( < string > six.b('value'), < float32 > val[i, j]) index += 1 - del itm 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 - del itm else: raise Exception("Only 1 or 2 dimensions are allowed") - del listbase elif isinstance(val, dict): if item == six.b('option') or item == six.b('options') or item == six.b('Option') or item == six.b('Options'): readOptions(root, val) else: itm = root.addChildNode(item) readDict(itm, val) - del itm else: if item == six.b('type'): root.addAttribute(< string > six.b('type'), wrap_to_bytes(val)) else: itm = root.addChildNode(item, wrap_to_bytes(val)) - del itm -cdef void readOptions(XMLNode * node, dc): - cdef XMLNode * listbase - cdef XMLNode * itm +cdef void readOptions(XMLNode node, dc): + cdef XMLNode listbase + cdef XMLNode itm cdef int i cdef int j for item in dc: @@ -150,17 +145,14 @@ cdef void readOptions(XMLNode * node, dc): itm.addAttribute(< string > six.b('index'), < float32 > index) itm.addAttribute( < string > six.b('value'), < float32 > val[i, j]) index += 1 - del itm 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 - del itm else: raise Exception("Only 1 or 2 dimensions are allowed") - del listbase else: node.addOption(item, wrap_to_bytes(val)) @@ -214,10 +206,10 @@ def stringToPythonValue(inputIn): return str(input) -cdef XMLNode2dict(XMLNode * node): - cdef XMLNode * subnode - cdef list[XMLNode * ] nodes - cdef list[XMLNode * ].iterator it +cdef XMLNode2dict(XMLNode node): + cdef XMLNode subnode + cdef list[XMLNode] nodes + cdef list[XMLNode].iterator it dct = {} opts = {} if node.hasAttribute(six.b('type')): @@ -230,7 +222,6 @@ cdef XMLNode2dict(XMLNode * node): opts[castString(subnode.getAttribute('key'))] = stringToPythonValue(subnode.getAttribute('value')) else: dct[castString(subnode.getName())] = stringToPythonValue(subnode.getContent()) - del subnode inc(it) if len(opts)>0: dct['options'] = opts return dct -- cgit v1.2.3 From fff7470f1d74b0085355130350fa834ea8d37069 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 6 May 2015 13:50:11 +0200 Subject: Make XML array handling consistent setContent and getContent were using different XML formats previously. --- include/astra/XMLNode.h | 35 +++++++--- matlab/mex/mexHelpFunctions.cpp | 22 +----- python/astra/PyXMLDocument.pxd | 2 + python/astra/utils.pyx | 35 +++------- src/XMLNode.cpp | 150 +++++++++++++++++++++++----------------- 5 files changed, 127 insertions(+), 117 deletions(-) (limited to 'python') 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 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 = 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 = 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 +#include +#include +#include + + using namespace rapidxml; using namespace astra; @@ -167,77 +172,43 @@ vector XMLNode::getContentArray() const //----------------------------------------------------------------------------- // Get node content - NUMERICAL LIST +// NB: A 2D matrix is returned as a linear list vector XMLNode::getContentNumericalArray() const { - // is scalar - if (!hasAttribute("listsize")) { - vector res(1); - res[0] = getContentNumerical(); - return res; - } + string input = getContent(); - int iSize = boost::lexical_cast(getAttribute("listsize")); - // create result array - vector res(iSize); - // loop all list item nodes - list nodes = getNodes("ListItem"); - for (list::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 items; + boost::split(items, input, boost::is_any_of(",;")); + + // init list + vector out; + out.resize(items.size()); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = boost::lexical_cast(items[i]); } - // return - return res; + return out; } vector XMLNode::getContentNumericalArrayDouble() const { - // is scalar - if (!hasAttribute("listsize")) { - vector res(1); - res[0] = getContentNumerical(); - return res; - } + string input = getContent(); - int iSize = boost::lexical_cast(getAttribute("listsize")); - // create result array - vector res(iSize); - // loop all list item nodes - list nodes = getNodes("ListItem"); - for (list::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 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(getAttribute("listsize")); - // create result array - _pfData = new float32[_iSize]; - // loop all list item nodes - list nodes = getNodes("ListItem"); - for (list::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 out; + out.resize(items.size()); + + // loop elements + for (unsigned int i = 0; i < items.size(); i++) { + out[i] = boost::lexical_cast(items[i]); } + return out; } //----------------------------------------------------------------------------- @@ -420,15 +391,68 @@ void XMLNode::setContent(float32 _fValue) //----------------------------------------------------------------------------- // Set content - LIST -void XMLNode::setContent(float32* pfList, int _iSize) -{ + +template +static std::string setContentList_internal(T* pfList, int _iSize) { std::string str = (_iSize > 0) ? boost::lexical_cast(pfList[0]) : ""; for (int i = 1; i < _iSize; i++) { str += "," + boost::lexical_cast(pfList[i]); } - setContent(str); + return str; +} + +void XMLNode::setContent(float32* pfList, int _iSize) +{ + setContent(setContentList_internal(pfList, _iSize)); +} + +void XMLNode::setContent(double* pfList, int _iSize) +{ + setContent(setContentList_internal(pfList, _iSize)); } +//----------------------------------------------------------------------------- +// Set content - MATRIX + +template +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(_pfMatrix[0*s1 + y*s2]); + for (int x = 1; x < _iWidth; x++) + str += "," + boost::lexical_cast(_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(_pfMatrix, _iWidth, _iHeight, transposed)); +} + +void XMLNode::setContent(double* _pfMatrix, int _iWidth, int _iHeight, bool transposed) +{ + setContent(setContentMatrix_internal(_pfMatrix, _iWidth, _iHeight, transposed)); +} + + //----------------------------------------------------------------------------- // Add attribute - STRING void XMLNode::addAttribute(string _sName, string _sText) -- cgit v1.2.3