394 lines
13 KiB
Python

import numpy as np
import math
maxf = 2
minf = 0.5
class EtaVELTr:
def __init__(self, numberOfPixels = 25, minn=0., maxx=1.):
self.nPixels = numberOfPixels
self.nCorners = self.nPixels + 1
self.minEta = minn
self.maxEta = maxx
#self.corners = []
self.edgesX = []
self.edgesY = []
self.edgesE = []
self.edgesF = []
self.edgesG = []
self.edgesH = []
self.counts = []
self.pOffset = (self.maxEta-self.minEta)/self.nPixels
self.cPosX = []
self.cPosY = []
self.zPosX = []
self.zPosY = []
self.sqSums = []
self.cIteration = 0
self.bSqSum = 0
self.initGrid()
#self.calculatePixelCorners()
self.update()
def initGrid(self):
dd = 1 / math.sqrt(2)
#self.corners = [ [self.minEta + x * pOffset, self.minEta + y * pOffset] for y in range(self.nPixels)] for x in range(self.nPixels)
self.cPosX = [ [self.minEta + x * self.pOffset for x in range(self.nCorners)] for y in range(self.nCorners) ]
self.cPosY = [ [self.minEta + y * self.pOffset for x in range(self.nCorners)] for y in range(self.nCorners) ]
self.counts = [ [ [0,0,0,0] for x in range(self.nPixels) ] for y in range(self.nPixels) ]
self.edgesX = [ [ 1 for x in range(self.nCorners) ] for y in range(self.nCorners + 1) ]
self.edgesY = [ [ 1 for x in range(self.nCorners+1) ] for y in range(self.nCorners) ]
self.edgesE = [ [ dd for x in range(self.nPixels) ] for y in range(self.nPixels) ]
self.edgesF = [ [ dd for x in range(self.nPixels) ] for y in range(self.nPixels) ]
self.edgesG = [ [ dd for x in range(self.nPixels) ] for y in range(self.nPixels) ]
self.edgesH = [ [ dd for x in range(self.nPixels) ] for y in range(self.nPixels) ]
def update(self):
self.normalizeEdgeLengths()
self.calculateEdgeLengths2()
self.calculatePixelCorners2()
conv = False
out = 0
outList = []
tot = self.nPixels*self.nPixels*4
sqSum = 0
avg = self.getAvgCounts()
avgPS = self.getAvgCounts() + 1*math.sqrt(self.getAvgCounts())
avgMS = self.getAvgCounts() - 1*math.sqrt(self.getAvgCounts())
for y in range(self.nPixels):
for x in range(self.nPixels):
for t in range(4):
sqSum += (avg -self.counts[y][x][t]) * (avg -self.counts[y][x][t])
if self.counts[y][x][t] > avgPS or self.counts[y][x][t] < avgMS:
out += 1
outList.append([y,x,t,self.counts[y][x][t]])
outList = sorted(outList,key=lambda t: abs(self.counts[t[0]][t[1]][t[2]]/self.getAvgCounts()))
self.counts = [ [ [0,0,0,0] for x in range(self.nPixels) ] for y in range(self.nPixels) ]
print("There are {} of {} triangles out of 1 std ({} %)".format(out,tot,out/tot*100))
print("Total Sq Err: {}".format(sqSum))
self.sqSums.append(sqSum)
if len(self.sqSums) > 2 and np.diff(self.sqSums)[-1] > 0:
print("converged after {} steps: sqSums {} diff(sqSums) {}".format(self.cIteration,self.sqSums,np.diff(self.sqSums)))
conv = True
self.bSqSum = self.sqSums[-2]
self.cIteration += 1
return [conv,outList,sqSum]
def normalizeEdgeLengths(self):
sumL = 0
sumL += sum(map(sum,zip(*self.edgesX)))
sumL += sum(map(sum,zip(*self.edgesY)))
sumL += sum(map(sum,zip(*self.edgesE)))
sumL += sum(map(sum,zip(*self.edgesF)))
sumL += sum(map(sum,zip(*self.edgesG)))
sumL += sum(map(sum,zip(*self.edgesH)))
avgL = sumL/(4*self.nPixels*self.nPixels+2*self.nCorners*(self.nCorners+1))
print("total Sum is {} avg: {}".format(sumL,avgL))
self.edgesX = [ [ x/avgL for x in y ] for y in self.edgesX ]
self.edgesY = [ [ x/avgL for x in y ] for y in self.edgesY ]
self.edgesE = [ [ x/avgL for x in y ] for y in self.edgesE ]
self.edgesF = [ [ x/avgL for x in y ] for y in self.edgesF ]
self.edgesG = [ [ x/avgL for x in y ] for y in self.edgesG ]
self.edgesH = [ [ x/avgL for x in y ] for y in self.edgesH ]
def _shapeF(self,f):
f = (f - 1) * 0.6 + 1
if f > maxf:
return maxf
if f < minf:
return minf
return f
def calculateEdgeLengths2(self):
if self.getTotalCounts() == 0:
return
avg = self.getAvgCounts()
for y in range(self.nPixels):
for x in range(self.nPixels):
for t in range(4):
pc = self.counts[y][x][t]
if pc == 0:
f = maxf
else:
f = math.sqrt(avg/pc)
if pc > avg-math.sqrt(avg) and pc < avg+math.sqrt(avg):
f = 1.
sf = self._shapeF(f)
if t == 0:
self.edgesX[y][x] = self.edgesX[y][x] / sf
self.edgesE[y][x] = self.edgesE[y][x] / sf
self.edgesF[y][x] = self.edgesF[y][x] / sf
if t == 1:
self.edgesY[y][x+1] = self.edgesY[y][x+1] / sf
self.edgesF[y][x] = self.edgesF[y][x] / sf
self.edgesH[y][x] = self.edgesH[y][x] / sf
if t == 2:
self.edgesX[y+1][x] = self.edgesX[y+1][x] / sf
self.edgesH[y][x] = self.edgesH[y][x] / sf
self.edgesG[y][x] = self.edgesG[y][x] / sf
if t == 3:
self.edgesY[y][x] = self.edgesY[y][x] / sf
self.edgesG[y][x] = self.edgesG[y][x] / sf
self.edgesE[y][x] = self.edgesE[y][x] / sf
def calculatePixelCorners2(self):
w = 20
posMat = []
CrVx = np.zeros((self.nCorners,self.nCorners))
CrVy = np.zeros((self.nCorners,self.nCorners))
ZrVx = np.zeros((self.nPixels,self.nPixels))
ZrVy = np.zeros((self.nPixels,self.nPixels))
#boundary conditions matrix/vectors
BCposMatX = []
BCposMatY = []
BCrVx = []
BCrVy = []
for y in range(self.nCorners):
for x in range(self.nCorners):
BClineX = np.zeros((self.nCorners,self.nCorners))
BClineY = np.zeros((self.nCorners,self.nCorners))
if (x == 0 and y == 0) or \
(x == 0 and y == self.nPixels) or \
(x == self.nPixels and y == 0) or \
(x == self.nPixels and y == self.nPixels):
BClineX[y][x] = w
BClineY[y][x] = w
BCrVx.append(self.getCornerPos(y,x)[0] * w)
BCrVy.append(self.getCornerPos(y,x)[1] * w)
#print("bclinex shape {} zeros shape {}".format( BClineX.reshape((self.nCorners*self.nCorners,)).shape , np.zeros((self.nPixels*self.nPixels)).shape ))
BCposMatX.append(np.hstack((BClineX.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
BCposMatY.append(np.hstack((BClineY.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
elif x == 0 or x == self.nPixels:
BClineX[y][x] = w
#BClineY[y][x] = 1
BCrVx.append(self.getCornerPos(y,x)[0] * w)
#BCrVy.append(self.getCornerPos(y,x)[1])
BCposMatX.append(np.hstack((BClineX.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
#BCposMatY.append(np.hstack((BClineY.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
elif y == 0 or y == self.nPixels:
#BClineX[y][x] = 1
BClineY[y][x] = w
#BCrVx.append(self.getCornerPos(y,x)[0])
BCrVy.append(self.getCornerPos(y,x)[1] * w)
#BCposMatX.append(np.hstack((BClineX.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
BCposMatY.append(np.hstack((BClineY.reshape((self.nCorners*self.nCorners,)),np.zeros((self.nPixels*self.nPixels,)) )) )
eLength = 0
if x != 0:
eLength += self.edgesX[y][x-1]
if y != 0:
eLength += self.edgesY[y-1][x]
if x != self.nPixels:
eLength += self.edgesX[y][x]
if y != self.nPixels:
eLength += self.edgesY[y][x]
if y != 0 and x != 0:
eLength += self.edgesH[y-1][x-1]
if y != self.nPixels and x != 0:
eLength += self.edgesF[y][x-1]
if y != 0 and x != self.nPixels:
eLength += self.edgesG[y-1][x]
if y != self.nPixels and x != self.nPixels:
eLength += self.edgesE[y][x]
line = np.zeros((self.nCorners,self.nCorners))
lineZ = np.zeros((self.nPixels,self.nPixels))
if x != 0:
line[y][x-1] = - self.edgesX[y][x-1]/eLength
if y != 0:
line[y-1][x] = - self.edgesY[y-1][x]/eLength
if x != self.nPixels:
line[y][x+1] = - self.edgesX[y][x]/eLength
if y != self.nPixels:
line[y+1][x] = - self.edgesY[y][x]/eLength
if y != 0 and x != 0:
lineZ[y-1][x-1] = -self.edgesH[y-1][x-1]/eLength
if y != self.nPixels and x != 0:
lineZ[y][x-1] = -self.edgesF[y][x-1]/eLength
if y != 0 and x != self.nPixels:
lineZ[y-1][x] = -self.edgesG[y-1][x]/eLength
if y != self.nPixels and x != self.nPixels:
lineZ[y][x] = -self.edgesE[y][x]/eLength
line[y][x] = 1
CrVx[y][x] = 0
CrVy[y][x] = 0
posMat.append( \
np.hstack(( \
line.reshape((self.nCorners*self.nCorners,)), \
lineZ.reshape((self.nPixels*self.nPixels,)) \
)) \
)
for y in range(self.nPixels):
for x in range(self.nPixels):
line = np.zeros((self.nCorners,self.nCorners))
lineZ = np.zeros((self.nPixels,self.nPixels))
eLength = self.edgesE[y][x] + self.edgesF[y][x] +self.edgesG[y][x] +self.edgesH[y][x]
line[y][x] = -self.edgesE[y][x] / eLength
line[y][x+1] = -self.edgesF[y][x] / eLength
line[y+1][x] = -self.edgesG[y][x] / eLength
line[y+1][x+1] = -self.edgesH[y][x] / eLength
lineZ[y][x] = 1
ZrVx[y][x] = 0
ZrVy[y][x] = 0
posMat.append( \
np.hstack(( \
line.reshape((self.nCorners*self.nCorners,)), \
lineZ.reshape((self.nPixels*self.nPixels,)) \
)) \
)
CrVxFlat = CrVx.reshape((self.nCorners*self.nCorners,))
CrVyFlat = CrVy.reshape((self.nCorners*self.nCorners,))
ZrVxFlat = ZrVx.reshape((self.nPixels*self.nPixels,))
ZrVyFlat = ZrVy.reshape((self.nPixels*self.nPixels,))
posMat = np.asarray(posMat)
BCrVyFlat = np.asarray(BCrVy)
BCrVxFlat = np.asarray(BCrVx)
BCposMatX = np.asarray(BCposMatX)
BCposMatY = np.asarray(BCposMatY)
print ("BCposMatY vy {} shape posMat {}".format(BCposMatY.shape,posMat.shape))
FinalrVy = np.hstack((CrVyFlat,ZrVyFlat,BCrVyFlat))
FinalrVx = np.hstack((CrVxFlat,ZrVxFlat,BCrVxFlat))
FinalposMatX = np.vstack((posMat,BCposMatX))
FinalposMatY = np.vstack((posMat,BCposMatY))
print("posMat shape {}".format(posMat.shape))
print("posMatX shape {}".format(FinalposMatX.shape))
print("rVxFlat shape {}".format(FinalrVx.shape))
#print("posMat {}".format(FinalposMat))
#print("rVxFlat {}".format(FinalrVx))
xPos = np.linalg.lstsq(FinalposMatX,FinalrVx)[0]
yPos = np.linalg.lstsq(FinalposMatY,FinalrVy)[0]
print("xPosShape {} cutXPosShape {}".format(xPos.shape,xPos[:self.nCorners][:self.nCorners].shape))
self.cPosX = xPos[:self.nCorners*self.nCorners].reshape((self.nCorners,self.nCorners))
self.cPosY = yPos[:self.nCorners*self.nCorners].reshape((self.nCorners,self.nCorners))
self.zPosX = xPos[self.nCorners*self.nCorners:].reshape((self.nPixels,self.nPixels))
self.zPosY = yPos[self.nCorners*self.nCorners:].reshape((self.nPixels,self.nPixels))
def fill(self,yy,xx,count = 1):
[y,x,t] = self.getPixel(yy,xx)
self.counts[y][x][t] += count
def getCountDist(self):
c = []
for y in range(self.nPixels):
for x in range(self.nPixels):
c.append(self.counts[y][x])
return c
def getPixel(self,yy,xx, debug = False):
for y in range(self.nPixels):
for x in range(self.nPixels):
for t in range(4):
[v1x,v1y,v2x,v2y,v3x,v3y] = self.getTriangleCorner(y,x,t)
if self.pointInTriangle([xx,yy],[v1x,v1y],[v2x,v2y],[v3x,v3y]):
return [y,x,t]
if not debug:
raise Exception("not inside a pixel")
else:
print("no pixel found")
return [0,0]
#http://stackoverflow.com/questions/2049582/how-to-determine-a-point-in-a-2d-triangle
def trSign (self, p1, p2, p3):
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);
def pointInTriangle (self,pt, v1, v2, v3):
b1 = self.trSign(pt, v1, v2) < 0.0
b2 = self.trSign(pt, v2, v3) < 0.0
b3 = self.trSign(pt, v3, v1) < 0.0
return ((b1 == b2) and (b2 == b3));
def getAvgCounts(self):
return self.getTotalCounts() / self.nPixels/self.nPixels/4.
def getTotalCounts(self):
tot = 0
for y in range(self.nPixels):
for x in range(self.nPixels):
for t in range(4):
tot += self.counts[y][x][t]
return tot
#tl tr bl br
def getPixelCorners(self,iy,ix):
return self.getCornerPos(iy,ix) + self.getCornerPos(iy,ix+1) + self.getCornerPos(iy+1,ix) + self.getCornerPos(iy+1,ix+1)
def getTriangleCorner(self,iy,ix,tr):
if tr == 0:
return self.getCornerPos(iy,ix) + self.getCornerPos(iy,ix+1) + [self.zPosX[iy][ix],self.zPosY[iy][ix]]
if tr == 1:
return self.getCornerPos(iy,ix+1) + self.getCornerPos(iy+1,ix+1) + [self.zPosX[iy][ix],self.zPosY[iy][ix]]
if tr == 2:
return self.getCornerPos(iy+1,ix+1) + self.getCornerPos(iy+1,ix) + [self.zPosX[iy][ix],self.zPosY[iy][ix]]
if tr == 3:
return self.getCornerPos(iy+1,ix) + self.getCornerPos(iy,ix) + [self.zPosX[iy][ix],self.zPosY[iy][ix]]
def getCornerPos(self,iy,ix):
return [self.cPosX[iy][ix],self.cPosY[iy][ix]]
def getXEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy,ix)
p2 = self.getCornerPos(iy,ix+1)
return [p1[0],p1[1],p2[0],p2[1]]
def getYEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy,ix)
p2 = self.getCornerPos(iy+1,ix)
return [p1[0],p1[1],p2[0],p2[1]]
def getEEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy,ix)
return [p1[0],p1[1],self.zPosX[iy][ix],self.zPosY[iy][ix]]
def getFEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy,ix+1)
return [p1[0],p1[1],self.zPosX[iy][ix],self.zPosY[iy][ix]]
def getGEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy+1,ix)
return [p1[0],p1[1],self.zPosX[iy][ix],self.zPosY[iy][ix]]
def getHEdgePos(self,iy,ix):
p1 = self.getCornerPos(iy+1,ix+1)
return [p1[0],p1[1],self.zPosX[iy][ix],self.zPosY[iy][ix]]