diff options
| -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)   { | 
