# -*- coding: utf-8 *-*
import numpy
from sys import exit
#import os
from copy import deepcopy
from diaGrabber import _utils
from scipy.interpolate import griddata
[docs]class _matrixBase(object):
[docs] def __init__(self, sourceClass):
self.sourceClass = sourceClass
self._basis_dim = self.sourceClass._basis_dim
self._merge_dim = self.sourceClass._merge_dim
try:
self.nMerge = len(self._merge_dim)
except(TypeError):
exit("ERROR: 'merge_dim' has to be a list")
#self.derivate_dim = derivate_dim
self.plot_overlay = []
try:
self.nDim = len(self._basis_dim)
except(TypeError):
exit("ERROR: 'basis_dim' has to be a list")
self.plot_overlay = []
self.recent_merge_set = []
for i in range(self.nMerge):
self.recent_merge_set.append([True,0.0,0.0])#[do_replace, new_value, intensity]
#every merge-dim has its on plot-overlay
self.plot_overlay.append([[], [], [], [], [], [],[]])
#plot_overlay = [(points), (lines), (broken lines), , (ellipses), (rectangles), (text), (legend)]
#(points),(broken lines), (lines) = [x-list,y-list]
#(ellipses) = list[ tuple(x,y), float(width), float(height), float(angle) ) ## str(color) ]
#(rectangles) = list[ tuple(x,y), float(width), float(height) ]
#(text) = list[ tuple(x,y), string(text)
#(legend) = list[str(...),... ]
sourceClass._prepareReadOut(self)
self._build()
[docs] def _build(self):
#empty matrix
matrix_str = "numpy.zeros(shape=("
for i in range(len(self._basis_dim)):
if self._basis_dim[i].resolution <= 0:
exit("ERROR: to build a matrix you need to set a number for %s.resolution" %self._basis_dim[i].name)
matrix_str += "%s," %self._basis_dim[i].resolution
matrix_str += "))"
self.densityMatrix = []
for i in range(self.nMerge):
self.densityMatrix.append(eval(matrix_str))
self.mergeMatrix = deepcopy(self.densityMatrix)
for i in range(self.nMerge):
self.mergeMatrix[i].fill(numpy.nan)
self._checkMinMax(self._basis_dim, self.nDim)
self.sortMatrix = []
for i in range(len(self._basis_dim)):
self.sortMatrix.append(self._basis_dim[i]._sort_range)
[docs] def _assign(self, basis_values, merge_values):
self._getPositionsIntensities(basis_values)
for position, intensity in self.positionsIntensities:
tPostion = tuple(position)
for n,merge in enumerate(self._merge_dim):
#mergeMethod
(replace_value, do_replace)= merge._mergeMethod._get(merge_values[n],
self.mergeMatrix[n][tPostion],self.densityMatrix[n][tPostion],intensity)
#replace an old value in the matrix with the recent one?
self.recent_merge_set[n][0] = do_replace
if do_replace:
self.recent_merge_set[n][1] = replace_value
self.recent_merge_set[n][2] = intensity
#for every alias-conection in every merge_dim
for n,merge in enumerate(self._merge_dim):
#for i in merge._alias_mergeIndex:
for i in merge._alias._index:
# the value on a mergeDim. with alias-connections can only be set,
# if all mergeDims in the _alias-list are 'do_replace=True'
if not self.recent_merge_set[i][0]:
self.recent_merge_set[n][0] = False
# write new values in an extra cycle is necassary for the alias-comparisons
for n ,mSet in enumerate(self.recent_merge_set):
if mSet[0]:#do_replace:
self.mergeMatrix[n][tPostion] = mSet[1]#replace_value
self.densityMatrix[n][tPostion] += mSet[2]#intensity
[docs] def _checkMinMax(self,basis_dim, nDim):
'''
get minMax-range for all unlimited dimensions
'''
get_MinMax_values = []
dims = []
dim_names = []
for i in range(nDim):
if basis_dim[i]._take_all_values:
dims.append(basis_dim[i])#.index)
dim_names.append(basis_dim[i].name)
if len(dims) > 0:
print "...getting range for dims %s" %dim_names
min_max = self.sourceClass._getMinMax(dims)
j = 0
for i in range(nDim):
if basis_dim[i]._take_all_values:
basis_dim[i]._include_from_to = min_max[j]
basis_dim[i]._initSortRange()
j+=1
print "set range for %s to %s" %(basis_dim[i].name,
basis_dim[i]._include_from_to)
[docs] def fill(self):
'''
Readout the whole source, then continue.
'''
print "reading out file %s" %self.sourceClass.file_name
self.sourceClass._readOut(False, False)
print "done"
[docs] def _fillInteractive(self, end_readOut):
'''
read only one line - able for iterable processes
'''
return self.sourceClass._readOut(True, end_readOut)
[docs] def fillInteractive(self, plotInstance, **kwargs):
'''
Fill the matrix with the source-values and plot the progress.
Therefore a plotInstance which is able to plot interactive is needed.
kwargs can be those from the plot-method of the used 'plotInstance'
'''
#check whether plotInstance is able to plot interactive
if not plotInstance.hasInteractiveModus:
exit("ERROR: plotInstance %s cannot be used formethod 'fillInteractive' of %s!"
%(plotInstance.__class__, self.__class__) )
#start interactive plotting/readout
kwargs["interactive"] = True
plotInstance.plot(self, **kwargs)
[docs] def save(self, file_name, folder_name = "", save_type = "bin"):
print "saving matrix ..."
file_name = _utils.prepareFileSystem(file_name, folder_name)
if save_type == "bin":
for i in range(self.nMerge):
f = "%s_%s_merge" %(file_name, self._merge_dim[i].name)
numpy.save(f, self.mergeMatrix[i])
print "created binary-file %s" %f
f = "%s_%s_density" %(file_name, self._merge_dim[i].name)
numpy.save(f, self.densityMatrix[i])
print "created binary-file %s" %f
f = "%s_basis" %(file_name)
numpy.save(f, self.sortMatrix)
print "created binary-file %s" %f
else:
#def txt(self):
for i in range(self.nMerge):
f = "%s_%s_merge" %(file_name, self._merge_dim[i].name)
numpy.savetxt(f, self.mergeMatrix[i], fmt = "%10.5f")
print "created txt-file %s" %f
#f = file_name + "_sort"
#exit("ERROR: save-txt doesnt work for sortMatrix at the moment")
#numpy.savetxt(f, numpy.array(self.sortMatrix), fmt = "%10.5f")
#print "created txt-file %s" %f
f = "%s_%s_density" %(file_name, self._merge_dim[i].name)
numpy.savetxt(f, self.densityMatrix[i], fmt = "%10.5f")
print "created txt-file %s" %f
[docs] def load(self, file_name, folder_name = "", load_type = "bin"):
print "loading matrix"
file_name = _utils.prepareFileSystem(file_name, folder_name)
if load_type == "bin":
#def bin(self):
self.mergeMatrix = []
self.sortMatrix = []
self.densityMatrix = []
for i in range(self.nMerge):
f = "%s_%s_merge.npy" %(file_name, self._merge_dim[i].name)
self.mergeMatrix.append(numpy.load(f))
print "loaded binary-file %s" %f
f = "%s_%s_density.npy" %(file_name, self._merge_dim[i].name)
self.densityMatrix.append(numpy.load(f))
print "loaded binary-file %s" %f
f = f = "%s_basis.npy" %(file_name)
self.sortMatrix = numpy.load(f)
print "loaded binary-file %s" %f
else:
exit("ERROR: load.txt is not implemented")
for i in range(len(self._basis_dim)):
if self._basis_dim[i]._take_all_values:
#define range for _include_from_to from loaded sortMatrix
self._basis_dim[i]._include_from_to = [min(self.sortMatrix[i]),max(self.sortMatrix[i])]
self._basis_dim[i]._take_all_values = False
print self._basis_dim[i]._include_from_to
[docs] def interpolate(self, method = "nearest"):
'''interpolate NaNs in matrix; method="nearest", "linear", "cubic"'''
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])
#print points
pointsT = zip(*points)
#pointsT = numpy.vstack(tuple(points)).transpose()
#do the interpolation
print "do interpolation"
#print pointsT
for i in range(self.nMerge):
#pointsT = zip(*points[i])
#print pointsT
self.mergeMatrix[i] = griddata(pointsT, merge[i], tuple(nDgrid), method)
print "done"
[docs] def multiDimMeshgrid(self):
'''like numpy.meshgrid but can also produce multi-dimensional meshgrids
takes list of arrays, where len(list)=nDim'''
print "create a multiDimMeshgrid"
sortMatrix = list(self.sortMatrix)#if type(sortMatrix)=array an error will be produced in numpy.repeat
sortMatrix.reverse()
lenDim = []
#nDim = len(sortMatrix)
newShape = [self.nDim]
for i in sortMatrix:
lenDim.append(len(i))
lenDimrev = deepcopy(lenDim)
lenDimrev.reverse()
newShape.extend(lenDimrev)
for i in range(self.nDim):
if i==0:
nRepeat = 1
else:
nRepeat = lenDim[i-1]
lenDim[i]*=nRepeat
#double items
sortMatrix[i] = sortMatrix[i].repeat(nRepeat)
lenGrid = len(sortMatrix[-1])
for i in range(self.nDim):
#repeate blocks
sortMatrix[i] = numpy.lib.stride_tricks.as_strided(
sortMatrix[i], (lenGrid/len(sortMatrix[i]),)+sortMatrix[i].shape, (0,)+sortMatrix[i].strides).flatten()
#reshape blocks
sortMatrix = numpy.array(sortMatrix)#reshape need an array
print "done"
return list(sortMatrix.reshape(tuple(newShape)))
#def eval2dGaussianDistribution(self, dEB_types=[], which_merge_dim = 0):
#print "eval2dGaussianDistribution"
#if self.nDim != 2:
#exit("ERROR: eval2dGaussianDistribution works only for 2d-matrixes")
#min_dEB_types = [0.25,0.5,0.75]#are at least necassary to get deviation to normaldistr.
#for i in min_dEB_types:
#if i not in dEB_types:
#dEB_types.append(i)#important to the the standard deviation
#
##from smalles to biggest diameter
#dEB_types.sort()
#dEB_types.reverse()#e.q.d_EB_75, d_EB_50, d_EB_25
#dEB_types.insert(0,0.95)
#
#w = int(which_merge_dim)
#
#peak = numpy.nanmax(self.mergeMatrix[w])
#peak_location = list(numpy.where(self.mergeMatrix[w]==peak))
#peak_location[0] = peak_location[0][0]
#peak_location[1] = peak_location[1][0]
##print peak_location, len(sortMatrix[0]),len(sortMatrix[1])
#
#environment = 0#approximated
#dEB_limit = []
#dEB = []
#border_locations = []
#deviationTh2RealList = []
#
#for i in range(len(dEB_types)):
#dEB_limit.append((peak-environment)*dEB_types[i])
#dEB.append(numpy.nan)
#border_locations.append([])
#deviationTh2RealList.append(0)
#
#n_circle_points = 40#has to be int(multiple of 2)
#n_part_diameters = n_circle_points/2
#
#delta_radian = 2*numpy.pi / n_circle_points
#
#for d in range(len(dEB_limit)):
#radian = 0.0
#for i in range(n_circle_points):
#n = 0#at peak_location
#at_border = False
#while not at_border:
#x = peak_location[0] + int(n*numpy.cos(radian))
#y = peak_location[1] + int(n*numpy.sin(radian))
#
#
#if self.mergeMatrix[w][x][y] < dEB_limit[d]:#found border
#at_border = True
#if [x,y] not in border_locations[d]:
#border_locations[d].append([x,y])
#n += 1
#radian += delta_radian
#
##reset the middle of the gaussiandistr. as the middle of the first (95%) polygon
#polygon = zip(*border_locations[0])
#peak_location[0] = int(sum(polygon[0])/len(polygon[0]))
#peak_location[1] = int(sum(polygon[1])/len(polygon[1]))
#peak_coord = [ self.sortMatrix[0][peak_location[0]], self.sortMatrix[1][peak_location[1]] ]
###calc the x-y-coord of all borders in d_EB_types
###and the distance from eBeammiddle to border
#border_coords = deepcopy(border_locations)
#distances = deepcopy(border_locations)
#print "Gausian-Diameters are..."
#for d in range(1,len(dEB_limit)):
#for i in range(len(border_locations[d])):
#border_coords[d][i] = [self.sortMatrix[0][border_locations[d][i][0]],
#self.sortMatrix[1][border_locations[d][i][1]]]
#distances[d][i] = _utils.pktAbs2(border_coords[d][i],peak_coord)
##values for dEB_types[i]
#dEB[d] = sum(distances[d]) / len(distances[d])#mean
#if dEB_types[d] == 0.50:
#st_deviation = dEB[d]
#print " for %s -> %s" %(dEB_types[d],dEB[d])
#
###get max/min diameter-factor and the radian(max_diameter) for each d_EB-area
#minMax_dEB = []
#for d in range(len(dEB_limit)-1):#for each diameter
#minMax_dEB.append([None,None,None,None])#min, max, max/min, radian_of_max
#for i in range(n_part_diameters):
## == radius + radius in opposite dir.
#part_diameter = distances[d+1][i] + distances[d+1][i+n_part_diameters]
##print minMax_dEB, d
#if part_diameter < minMax_dEB[d][0] or minMax_dEB[d][0] == None:#min
#minMax_dEB[d][0] = part_diameter
#if part_diameter > minMax_dEB[d][1] or minMax_dEB[d][1] == None:#max
#minMax_dEB[d][1] = part_diameter
#minMax_dEB[d][3] = delta_radian * i
#minMax_dEB[d][2] = minMax_dEB[d][1] / minMax_dEB[d][0] #max/min
##get mean max/min-factor and mean radian_of_max
#mean_maxMin_dEB = 0
#mean_max_radian = 0
#for d in range(len(dEB_limit)-1):#for each diameter
#mean_maxMin_dEB += minMax_dEB[d][2]
#mean_max_radian += minMax_dEB[d][3]
#mean_maxMin_dEB /= (len(dEB_limit)-1)
#mean_max_radian /= (len(dEB_limit)-1)
#print "The mean factor max/min-diameter is %s" % mean_maxMin_dEB
#print "The mean radian of the max diameter is %s" % mean_max_radian
##calc deviation to a normaldisribution defined as:
##normal_distribution_fn = \
#corrF = 1/ (
#1/(st_deviation* ((2*numpy.pi)**0.5) ) ) * numpy.e**(-0.5 *
#( ( 0 / st_deviation)**2 ) ) * (peak-environment)
#for d in range(1,len(dEB_limit)):
#for x in distances[d]:
#dEB_th = corrF * (
#1/(st_deviation* ((2*numpy.pi)**0.5) ) ) * numpy.e**(-0.5 *
#( ( x / st_deviation)**2 ) ) * (peak-environment)
#deviationTh2RealList[d] += abs( (dEB_th - dEB_limit[d]) / dEB_th)#dEB_limit[d]/dEB_th#
#deviationTh2RealList[d] /= (len(distances[d])-1) #middle fo difference between theory and reality
###middle of all deviantion-rings
#relDevianceTh2Real = sum(deviationTh2RealList) / ( len(deviationTh2RealList))
#print "The relative deviation/variance between theoretical an real distribution is %s" %relDevianceTh2Real
##add point middle of gaussian:
#self.plot_overlay[w][0].append(tuple(peak_coord))
#self.plot_overlay[w][6].append("Mittelpunkt")#x-,y-list
#self.plot_overlay[w][5].append("deviation= %s" %relDevianceTh2Real)
#self.plot_overlay[w][5].append("maxRad= %s" %mean_max_radian)
#self.plot_overlay[w][5].append("max/min-d-factor= %s" %mean_maxMin_dEB)
##add rings
#for d in range(1,len(dEB_limit)):
#self.plot_overlay[w][1].append(zip(*border_coords[d]))#x-,y-list
#self.plot_overlay[w][6].append("d_EB= %s" %(dEB_types[d]) )#x-,y-list
#print "done"
class coarseMatrix(_matrixBase):
'''
.. image:: _static/coarseMatrix_1D.png
.. image:: _static/coarseMatrix_2D.png
'''
def __init__(self, sourceClass):
super(coarseMatrix, self).__init__(sourceClass)
#self._basis_dim = basis_dim
self.positionsIntensities = [[[ ],1]]#intensity in every time =1 because thers no splitting
for i in range(self.nDim):
self.positionsIntensities[0][0].append(0)
def _getPositionsIntensities(self, basis_values):
for i in range(self.nDim):
difference_list = self.sortMatrix[i] - basis_values[i]
difference_list = abs(difference_list)
nearest_point = difference_list.argmin()
self._basis_dim[i]._recent_position = nearest_point
self.positionsIntensities[0][0][i] = nearest_point
#return self.positionsIntensities
#positionsIntensities = self._getPositionsIntensities(basis_values)
class fineMatrix(_matrixBase):
'''
This class isn't as fast as :class:`coarseMatrix` but can assign values
in a more accurate way if the following condition is fullfilled:
.. note:: number of datapoints in matrix>> matrix-resolution
.. image:: _static/fineMatrix_1D.png
.. image:: _static/fineMatrix_2D.png
'''
def __init__(self, sourceClass):
super(fineMatrix, self).__init__(sourceClass)
#self._basis_dim = basis_dim
self.positionsIntensities = [[[ ],1]]
self.anzAffectedCells = 2**self.nDim
self.affectedCellCounter = []
for i in range(1,self.nDim+1,1):
self.affectedCellCounter.append((2**i/2) -1)
for i in range(self.nDim):
self.positionsIntensities[0][0].append(0)
for i in range(self.anzAffectedCells-1):
#1D: 2 cells
#2D: 4 cells
#3D: 8 cells
self.positionsIntensities.append(deepcopy(self.positionsIntensities[0]))
def _getPositionsIntensities(self, basis_values):
for i in range(self.anzAffectedCells):#reset intensities (later there is a *=)
self.positionsIntensities[i][1] = 1
for i in range(self.nDim):
difference_list = self.sortMatrix[i] - basis_values[i]
difference_list = abs(difference_list)
nearest_point = difference_list.argmin()
self._basis_dim[i]._recent_position = nearest_point
if nearest_point == 0:#is first point of array - neared point is seond point
sec_nearest_point = 1
elif nearest_point == difference_list.size-1:#is last point of array
sec_nearest_point = difference_list.size-2
else:##whose of the neigbours is closer
if difference_list[nearest_point-1] < difference_list[nearest_point+1]:
sec_nearest_point = nearest_point-1
else:
sec_nearest_point = nearest_point+1
#sec_nearest_point get some of the intensity of the nearest point
transfered_intensity = (difference_list[sec_nearest_point]-
difference_list[nearest_point]) / difference_list[sec_nearest_point]
n = 0
write_point = nearest_point
nearest_intensity = 1 - transfered_intensity
sec_nearest_intensity = transfered_intensity
intensity = nearest_intensity
for j in range(self.anzAffectedCells):
self.positionsIntensities[j][0][i] = write_point
self.positionsIntensities[j][1] *= intensity
if n == self.affectedCellCounter[i]:
if write_point == nearest_point:
write_point = sec_nearest_point
intensity = sec_nearest_intensity
else:
write_point = nearest_point
intensity = nearest_intensity
n = -1
n += 1
#return self.positionsIntensities