Source code for DABISpectralToolbox.DABIMisc

# -*- coding: utf-8 -*-
"""
=========================================
DABI Miscellaneous
=========================================

Created on Wed Feb 27

@author: Daniele Bigoni (dabi@dtu.dk)

Collection of miscellaneous functions used in the DABISpectralToolbox

"""

__revision__ = filter(str.isdigit, "$Revision: 101 $")

__author__ = "Daniele Bigoni"
__copyright__ = """Copyright 2012, Daniele Bigoni"""
__credits__ = ["Daniele Bigoni"]
__maintainer__ = "Daniele Bigoni"
__email__ = "dabi@dtu.dk"
__status__ = "Production"

import numpy as np

[docs]def MultiIndex(d,N): """ MultiIndex(): generates the multi index ordering for the construction of multidimensional Generalized Vandermonde matrices Syntax: ``IDX = MultiIndex(d,N)`` Input: * ``d`` = (int) dimension of the simplex * ``N`` = (int) the maximum value of the sum of the indeces OUTPUT: * ``IDX`` = (2d-array,int) array containing the ordered multi indeces """ from scipy.misc import comb # Compute the size of the number of multi-index elements (Pascal's simplex) NIDX = 0 for i in range(0,N+1): NIDX = NIDX + comb( i+(d-1),d-1,True) # Allocate memory IDX = np.zeros((NIDX,d),dtype=int) iIDX = 1 # index in the multi-index table on which the first n-th order is for n in range(1,N+1): IDX[iIDX,0] = n # Start recursion iIDX = __MultiIndexRec(IDX,d,iIDX+1,0) return IDX
def __MultiIndexRec(IDX,d,m,i): # Start splitting mFirstSplit = m-1 mLastSplit = m-1 mNew = m if (i+1 < d): while (IDX[mLastSplit,i] > 1): IDX[mNew,:i] = IDX[mLastSplit,:i] IDX[mNew,i] = IDX[mLastSplit,i]-1 IDX[mNew,i+1] = IDX[mLastSplit,i+1]+1 mLastSplit = mNew mNew = mNew + 1 # Call recursion on sub set mNew = __MultiIndexRec(IDX,d,mNew,i+1) # Move IDX[mNew,:i] = IDX[mFirstSplit,:i] IDX[mNew,i+1] = IDX[mFirstSplit,i] mNew = mNew + 1 # Call recursion on sub set mNew = __MultiIndexRec(IDX,d,mNew,i+1) return mNew
[docs]def machineEpsilon(func=float): """ machineEpsilon(): returns the abolute machine precision for the type passed as argument Syntax: ``eps = machineEpsilon([func=float])`` Input: * ``func`` : (default=float) type OUTPUT: * ``eps`` : absolute machine precision """ machine_epsilon = func(1) while func(1)+func(machine_epsilon) != func(1): machine_epsilon_last = machine_epsilon machine_epsilon = func(machine_epsilon) / func(2) return machine_epsilon_last
[docs]def compare(x,y,tol): """ compare(): compares two values up to a certain tolerance Syntax: ``n = compare(x,y,tol)`` Input: * ``x``, ``y`` : (float) values to be compared * ``tol`` : (float) tolerance to be used OUTPUT: * ``n`` : returns -1 if ``(x-y) < tol``, 1 if ``(x-y) > tol``, 0 otherwise """ for x_i,y_i in zip(x,y): d = x_i-y_i if (d < -tol): return -1 elif (d > tol): return 1 return 0
[docs]def almostEqual(x,y,tol): """ almostEqual(): check equality of two values up to a certain tolerance Syntax: ``b = almostEqual(x,y,tol)`` Input: * ``x``, ``y`` : (float) values to be compared * ``tol`` : (float) tolerance to be used OUTPUT: * ``b`` : returns ``true`` if equal, ``false`` otherwise """ return (compare(x,y,tol)==0)
[docs]def almostEqualList(xArray,y,tol): """ almostEqualList(): check equality of a list of floats against a value up to certain tolerance Syntax: ``b = almostEqualList(xArray,y,tol)`` Input: * ``xArray``: (1d-array,float) values to be compared to ``y`` * ``y`` : (float) values to be compared to * ``tol`` : (float) tolerance to be used OUTPUT: * ``b`` : (1d-array,bool) true if equal, false otherwise. """ if type(y) != np.ndarray and (np.dtype(y) == float and len(xArray.shape) == 1): y = np.array([y]) xArray = xArray.reshape((len(xArray),1)) if xArray.shape[1] == len(y): out = np.zeros(xArray.shape[0],dtype=bool) for i in range(xArray.shape[0]): out[i] = (almostEqual(xArray[i,:],y,tol)) return out else: print "Dimension error!" return
[docs]def argsort_insertion(X,tol,start_idx=1,end_idx=None): """ argsort_insertion(): Implements the insertion sort with ``binary_search``. Returns permutation indices. Syntax: ``perm = argsort_insertion(X,tol,[start_idx=1],[end_idx=None])`` Input: * ``X``: (2d-array,float) values ordered by row according to the compare function * ``tol`` : (float) tolerance to be used * ``start_idx``: (int) starting index for the ordering * ``end_idx`` : (int) ending index for the ordering OUTPUT: * ``perm`` : (1d-array,int) permutation indices """ if end_idx == None: end_idx = X.shape[0] if start_idx < 1: start_idx = 1 perm = range(0,end_idx) for i in range(start_idx,len(perm)): val = perm[i] # Binary search idx = binary_search(X,X[val,],-1,i+1,tol,perm=perm) # idx contains the index in perm of the last X < val perm[idx+1:i+1] = perm[idx:i] perm[idx] = val return perm
[docs]class ExpandingArray: __DEFAULT_ALLOC_INIT_DIM = 10 # default initial dimension for all the axis is nothing is given by the user __DEFAULT_MAX_INCREMENT = 10 # default value in order to limit the increment of memory allocation __MAX_INCREMENT = [] # Max increment __ALLOC_DIMS = [] # Dimensions of the allocated np.array __DIMS = [] # Dimensions of the view with data on the allocated np.array (__DIMS <= __ALLOC_DIMS) __ARRAY = [] # Allocated array def __init__(self,initData,allocInitDim=None,dtype=np.float64,maxIncrement=None): """ Initialization of the Expanding Array. :param initData: data Syntax: ``EA = ExpandingArray(initData,[allocInitDim=None,[dtype=np.float64,[maxIncrement=None]]])`` Input: * ``initData`` = (nd-array) InitialData with which to be initially filled. This must provide the number of dimensions of the array. * ``allocInitDim`` = (optional,1d-array,int) Initial allocated dimension. * ``dtype`` = (optional,dtype=np.float64) type for the data that will be contained in ``EA`` * ``maxIncrement`` = (int) upper limit for the allocation increment Description: """ self.__DIMS = np.array(initData.shape) self.__MAX_INCREMENT = maxIncrement if self.__MAX_INCREMENT == None: self.__MAX_INCREMENT = self.__DEFAULT_MAX_INCREMENT ''' Compute the allocation dimensions based on user's input ''' if allocInitDim == None: allocInitDim = self.__DIMS.copy() while np.any( allocInitDim < self.__DIMS ) or np.any(allocInitDim == 0): for i in range(len(self.__DIMS)): if allocInitDim[i] == 0: allocInitDim[i] = self.__DEFAULT_ALLOC_INIT_DIM if allocInitDim[i] < self.__DIMS[i]: allocInitDim[i] += min(allocInitDim[i]/2, self.__MAX_INCREMENT) ''' Allocate memory ''' self.__ALLOC_DIMS = allocInitDim self.__ARRAY = np.zeros(self.__ALLOC_DIMS,dtype=dtype) ''' Set initData ''' sliceIdxs = [slice(self.__DIMS[i]) for i in range(len(self.__DIMS))] self.__ARRAY[sliceIdxs] = initData
[docs] def shape(self): return tuple(self.__DIMS)
[docs] def getAllocArray(self): return self.__ARRAY
[docs] def getDataArray(self): ''' Get the view of the array with data ''' sliceIdxs = [slice(self.__DIMS[i]) for i in range(len(self.__DIMS))] return self.__ARRAY[sliceIdxs]
[docs] def concatenate(self,X,axis=0): if axis > len(self.__DIMS): print "Error: axis number exceed the number of dimensions" return ''' Check dimensions for remaining axis ''' for i in range(len(self.__DIMS)): if i != axis: if X.shape[i] != self.shape()[i]: print "Error: Dimensions of the input array are not consistent in the axis %d" % i return ''' Check whether allocated memory is enough ''' needAlloc = False while self.__ALLOC_DIMS[axis] < self.__DIMS[axis] + X.shape[axis]: needAlloc = True ''' Increase the __ALLOC_DIMS ''' self.__ALLOC_DIMS[axis] += min(self.__ALLOC_DIMS[axis]/2,self.__MAX_INCREMENT) ''' Reallocate memory and copy old data ''' if needAlloc: ''' Allocate ''' newArray = np.zeros(self.__ALLOC_DIMS) ''' Copy ''' sliceIdxs = [slice(self.__DIMS[i]) for i in range(len(self.__DIMS))] newArray[sliceIdxs] = self.__ARRAY[sliceIdxs] self.__ARRAY = newArray ''' Concatenate new data ''' sliceIdxs = [] for i in range(len(self.__DIMS)): if i != axis: sliceIdxs.append(slice(self.__DIMS[i])) else: sliceIdxs.append(slice(self.__DIMS[i],self.__DIMS[i]+X.shape[i])) self.__ARRAY[sliceIdxs] = X self.__DIMS[axis] += X.shape[axis]
[docs] def trim(self,N,axis=0): """ Trim the axis dimension of N elements """ self.__DIMS[axis] = max(self.__DIMS[axis]-N,0)