mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-22 14:38:14 +02:00
394 lines
13 KiB
Python
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]]
|
|
|