Source code for diaGrabber.target._matrixMethods

# -*- coding: utf-8 *-*
import numpy
import bottleneck as bn
from sys import exit
from copy import deepcopy
from scipy.interpolate import griddata

#own modules
#from diaGrabber import source
from diaGrabber import _utils
from diaGrabber.source._source import mergeDimension, basisDimension


[docs]class matrixMethods(object): def __init__(self): pass
[docs] def autoZoom(self, **kwargs): ''' **Required kwargs** ("keyword arguments") are: ================== =============== ============= ================ Keyword Type Example Description ================== =============== ============= ================ *value* float/string *max* The merge-value to zoom in. Type 'min' or 'max' to use the equivalent extrem-value in the matrix *scale* string *'relative'* **OR** *'absolute'* *level* float 0.3 The relative zoom-level 0.3 means +-30% around the zoom-point ================== =============== ============= ================ **Optional kwargs** ("keyword arguments") are: ================== =============== ========= ================ Keyword Type Default Description ================== =============== ========= ================ *mergeDim* list(mergeDim) [{all}] one or more merge-dims to do the method on *basisDim* list(basisDim) [{all}] Which basisDimensions get a new scale. *operator* string "==" The zoom-point is defined as the first point in matrix where a value in "==" (equal), ">" (bigger) etc. than the given *value* ================== =============== ========= ================ ''' #standard mergeDim=None value=None scale=None level=None operator = "==" basisDim = range(self.nBasis) #individual for key in kwargs: if key == "mergeDim": _utils.checkClassInstance(kwargs[key],mergeDimension) mergeDim = kwargs[key] elif key == "value": if type(kwargs[key]) == str: if kwargs[key] != "max" and kwargs[key] != "min": exit("ERROR: 'value' can only be 'max', 'min' or a float") value = kwargs[key] else: value = str(kwargs[key]) elif key == "scale": if kwargs[key] != "absolute" and kwargs[key] != "relative": exit("ERROR: 'scale' in method 'autoZoom' has to be 'absolute' or 'relative'") scale = str(kwargs[key]) elif key == "level": level = abs(float(kwargs[key])) elif key == "operator": operator = str(kwargs[key]) elif key == "basisDim": basisDim = list(kwargs[key]) for n,b in enumerate(basisDim): _utils.checkClassInstance(b,basisDimension) if b not in self._basis_dim: exit("ERROR: the given basisDimension does not belong to those from target") basisDim[n] = self._basis_dim.index(b) else: raise KeyError("keyword '%s' not known" %key) _utils.checkRequiredArgs({ "mergeDim":mergeDim, "value":value, "scale":scale, "level":level}) #which mergeMatrix is involved? m=self.mergeMatrix[self._merge_dim.index(mergeDim)] #prepare value if value=="max": value = bn.nanmax(m) elif value=="min": value = bn.nanmin(m) #value = eval("m" + "." + value + "()") if numpy.isnan(value): raise ValueError("cannot autoZoom to nan") #get position in matrix positions=numpy.argwhere(eval(str(value) + operator + "m"))[0] print "\n... do autoZoom for basisDimensions at a mergeValue of %s" %value for n,p in enumerate(positions): if n in basisDim: #get basis-values at those positions zoompoint = self.basisMatrix[n][p] #calc. the new range if scale == "relative": basis_range = self._basis_dim[n]._include_from_to[1]-self._basis_dim[n]._include_from_to[0] zoomrange=[zoompoint-abs(basis_range*level),zoompoint+abs(basis_range*level)] ampl = zoomrange[1]-zoomrange[0] elif scale == "absolute": zoomrange=[zoompoint-level,zoompoint+level] #define a new include_from_to-range for that basisDim print "%s --> %s (offset: %s, amplitude: %s)" %(self._basis_dim[n].name,zoomrange, zoompoint, ampl) self._basis_dim[n]._includeFromTo(zoomrange) else: print "ignored %s for autozoom" %self._basis_dim[n].name
[docs] def interpolate(self, method = "nearest"): '''interpolate NaNs (empty points) in matrix :param method: {"nearest", "linear", "cubic"} :type method: string ''' if method == "cubic" and self.nBasis > 2: method = "linear" print "method='cubic' works only for one and two basisDimensions" print "--> interpolate matrix with method '%s'" %method #build a nD-meshgrid in which the interolation can be solved nDgrid = self._multiDimMeshgrid() #extract points from matrix points,merge = self.transformMatrixToPoints(nDgrid) #merge a dim-lists to a vector-list #--> X(1,2,3) Y(4,5,6) -> XY([1,4],[2,5],[3,6]) pointsT = zip(*points) #do the interpolation print "do interpolation" for i in range(self.nMerge): try: self.mergeMatrix[i] = griddata(pointsT, numpy.array(merge[i]), tuple(nDgrid), method) except ValueError, exInstance: print "WARNING: interpolation of mergeMatrix %s FAILED because of:" %self._merge_dim[i].name print " ValueError:",exInstance.args print " continue with original values" print "done"
[docs] def transformDim(self, rebuild_matrix = True): #transform old basisMatrix some_dim_transformed = False for i in range(self.nBasis): #rewrite basisMatrix for n,k in enumerate(self._basis_dim[i]._transformMethod._list): if not self._basis_dim[i]._transformMethod.adhoc[n]: some_dim_transformed = True #than: values were not transformed in readout for j in range(len(self.basisMatrix[i])): self.basisMatrix[i][j] =k.get(self.basisMatrix[i][j]) ##change dimension-unit and -range self._basis_dim[i].unit = k.unit new_range = [0.0,0.0] for j in range(2): new_range[j] = \ k.get(self._basis_dim[i]._getIncludeFromTo()[j]) #init new range self._basis_dim[i]._includeFromTo(new_range) if not some_dim_transformed: print "WARNING: no transformMethod defined in basisDimension" ##build discrete points from given matrix, and if rebuild_matrix and some_dim_transformed: points, merge = self.transformMatrixToPoints() points.reverse() for m in range(self.nMerge): ##transform merge points if self._merge_dim[m]._transformMethod._value: for i in range(len(merge[m])): merge[m][i] = self._merge_dim[m]._transformMethod._value.get(merge[m][i]) self._merge_dim[m].name = self._merge_dim[m]._transformMethod._value.name ##..build new matrix from those discrete and transformed points self.transformPointsToMatrix(points, merge)
[docs] def transformPointsToMatrix(self, points, merge): self._buildMatrices()#get new merge- sort-, densityMatrix #print self.basisMatrix[0] points = zip(*points) for m in range(self.nMerge): for i,self._basis_dim[i]._recent_value in enumerate(points): if i==5000000: exit() self._getPositionsIntensities(self) for position, intensity in self.positionsIntensities: tPostion = tuple(position) (replace_value, do_replace)= self._merge_dim[m]._mergeMethod._get(merge[m][i], self.mergeMatrix[m][tPostion],self.densityMatrix[m][tPostion],intensity) if do_replace: self.mergeMatrix[m][tPostion] = replace_value self.densityMatrix[m][tPostion] += intensity
[docs] def transformMatrixToPoints(self, givenMultiDimMeshgrid = None): '''transform all not-empty parts of a matrix to discrete points''' print "transform marix-indices to discrete points" if givenMultiDimMeshgrid: #print 111, givenMultiDimMeshgrid pointsi = deepcopy(givenMultiDimMeshgrid) else: pointsi = self._multiDimMeshgrid() #X,Y = numpy.meshgrid(basisMatrix[0],basisMatrix[1]) for i in range(self.nBasis): #transform to list - necassary when removing NaNs via list.pop() pointsi[i] = list(pointsi[i].flatten()) points = [] merge = [] for i in range(self.nMerge): #points.append(deepcopy(pointsi)) merge.append(list(deepcopy(self.mergeMatrix[i]).flatten())) j = 0 #print i, self.nMerge, len(merge), merge[0] while j < len(merge[0]): #remove point if merge == nan if numpy.isnan(merge[0][j]): for i in range(self.nMerge): merge[i].pop(j) for k in range(self.nBasis): #print i,k,j, len(points[i][k]), len(merge[i]) pointsi[k].pop(j) j -= 1 j += 1 print "done" return pointsi, merge
[docs] def posterize(self, **kwargs): ''' This method discretize/posterize the values in the mergeMatrix (of a given mergeDimension) to a given ammount of values (e.g. nValues= 4 ) or to a given list or values (e.g. values = [1,2,4]) **Optional kwargs** ("keyword arguments") are: ================== =============== ========= ================ Keyword Type Default Description ================== =============== ========= ================ *mergeDim* list(mergeDim) [{all}] one or more merge-dims to do the method on *nValues* int 5 the ammount of different values *values* list None given different values ================== =============== ========= ================ ''' #standard mergeDim = self._merge_dim nValues=5 values=None #individual for key in kwargs: if key == "mergeDim": if type(kwargs[key]) != list or type(kwargs[key]) != tuple: kwargs[key] = [ kwargs[key] ] for m in kwargs[key]: _utils.checkClassInstance(m,mergeDimension) mergeDim = kwargs[key] elif key == "nValues": nValues = int(kwargs[key]) elif key == "values": values = list(kwargs[key]) else: raise KeyError("keyword '%s' not known" %key) _utils.checkRequiredArgs({ "mergeDim":mergeDim}) merge_names = "" for i in mergeDim: merge_names += "%s " %i.name merge_names = merge_names[:-1] print "--> Posterize mergeMatrices of (%s) to the values %s" %(merge_names, values) for i in mergeDim: #which mergeMatrix is involved? m=self.mergeMatrix[self._merge_dim.index(i)] if values == None: #create values-list values = numpy.linspace(bn.nanmin(m),bn.nanmax(m),nValues) else: values = numpy.array(values) #do posterizing for x in numpy.nditer(m, op_flags=['readwrite']): diff=values-x diff=abs(diff) nearest = diff.argmin() x[...] = values[ nearest ] #######PRIVATE########
[docs] def _multiDimMeshgrid(self): '''like numpy.meshgrid but can also produce multi-dimensional meshgrids takes list of arrays, where len(list)=nBasis''' print "create a multiDimMeshgrid" #if type(basisMatrix)=array an error will be produced in numpy.repeat basisMatrix = list(self.basisMatrix) basisMatrix.reverse() lenBasis = [] newShape = [self.nBasis] for i in basisMatrix: lenBasis.append(len(i)) lenBasisrev = deepcopy(lenBasis) lenBasisrev.reverse() newShape.extend(lenBasisrev) for i in range(self.nBasis): if i==0: nRepeat = 1 else: nRepeat = lenBasis[i-1] lenBasis[i]*=nRepeat #double items basisMatrix[i] = basisMatrix[i].repeat(nRepeat) lenGrid = len(basisMatrix[-1]) for i in range(self.nBasis): #repeate blocks basisMatrix[i] = numpy.lib.stride_tricks.as_strided( basisMatrix[i], (lenGrid/len(basisMatrix[i]),)+basisMatrix[i].shape, (0,)+basisMatrix[i].strides).flatten() #reshape blocks basisMatrix = numpy.array(basisMatrix)#reshape need an array print "done" return list(basisMatrix.reshape(tuple(newShape)))