#----------------------------------------------------------------------- #Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam # #Author: Daniel M. Pelt #Contact: D.M.Pelt@cwi.nl #Website: http://dmpelt.github.io/pyastratoolbox/ # # #This file is part of the Python interface to the #All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). # #The Python interface to the ASTRA Toolbox is free software: you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation, either version 3 of the License, or #(at your option) any later version. # #The Python interface to the ASTRA Toolbox is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #GNU General Public License for more details. # #You should have received a copy of the GNU General Public License #along with the Python interface to the ASTRA Toolbox. If not, see . # #----------------------------------------------------------------------- # distutils: language = c++ # distutils: libraries = astra import numpy as np import six from libcpp.string cimport string from libcpp.list cimport list from libcpp.vector cimport vector from cython.operator cimport dereference as deref, preincrement as inc from cpython.version cimport PY_MAJOR_VERSION cimport PyXMLDocument from .PyXMLDocument cimport XMLDocument from .PyXMLDocument cimport XMLNode from .PyIncludes cimport * cdef Config * dictToConfig(string rootname, dc): cdef Config * cfg = new Config() cfg.initialize(rootname) try: readDict(cfg.self, dc) except Exception as e: del cfg six.print_(e.strerror) return NULL return cfg def convert_item(item): if isinstance(item, six.string_types): return item.encode('ascii') if type(item) is not dict: return item out_dict = {} for k in item: out_dict[convert_item(k)] = convert_item(item[k]) return out_dict def wrap_to_bytes(value): if isinstance(value, six.binary_type): return value s = str(value) if PY_MAJOR_VERSION == 3: s = s.encode('ascii') return s def wrap_from_bytes(value): s = value if PY_MAJOR_VERSION == 3: s = s.decode('ascii') return s cdef void readDict(XMLNode * root, _dc): cdef XMLNode * listbase cdef XMLNode * itm cdef int i cdef int j dc = convert_item(_dc) for item in dc: val = dc[item] if isinstance(val, np.ndarray): if val.size == 0: break listbase = root.addChildNode(item) listbase.addAttribute(< string > six.b('listsize'), < float32 > val.size) index = 0 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 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 int i cdef int j for item in dc: val = dc[item] if node.hasOption(item): raise Exception('Duplicate Option: %s' % item) if isinstance(val, np.ndarray): if val.size == 0: 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 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 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)) cdef configToDict(Config *cfg): return XMLNode2dict(cfg.self) def castString3(input): return input.decode('utf-8') def castString2(input): return input if six.PY3: castString = castString3 else: castString = castString2 def stringToPythonValue(inputIn): input = castString(inputIn) # matrix if ';' in input: row_strings = input.split(';') col_strings = row_strings[0].split(',') nRows = len(row_strings) nCols = len(col_strings) out = np.empty((nRows,nCols)) for ridx, row in enumerate(row_strings): col_strings = row.split(',') for cidx, col in enumerate(col_strings): out[ridx,cidx] = float(col) return out # vector if ',' in input: items = input.split(',') out = np.empty(len(items)) for idx,item in enumerate(items): out[idx] = float(item) return out try: # integer return int(input) except ValueError: try: #float return float(input) except ValueError: # string return str(input) cdef XMLNode2dict(XMLNode * node): cdef XMLNode * subnode cdef list[XMLNode * ] nodes cdef list[XMLNode * ].iterator it dct = {} opts = {} if node.hasAttribute(six.b('type')): dct['type'] = castString(node.getAttribute(six.b('type'))) nodes = node.getNodes() it = nodes.begin() while it != nodes.end(): subnode = deref(it) if castString(subnode.getName())=="Option": 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