def sliceSamples(angle, b, fftShape, center=False): ''' Generate the b points along slice at angle of DFT space with shape. ''' r, s = fftShape p, q = farey.get_pq(angle) u = [] v = [] offsetU = 0 offsetV = 0 if center: offsetU = r / 2 offsetV = s / 2 # increment = 1.0/math.sqrt(p**2+q**2) u.append(0 + offsetU) v.append(0 + offsetV) for m in range(1, (b - 1) / 2): u.append((1.0 / p) * m + offsetU) v.append(-(1.0 / q) * m + offsetV) for m in range(-(b - 1) / 2, 1): # print "m:", m, "delP:", -(1.0/p)*m + offsetU, "delQ:", (1.0/q)*m + offsetV u.append((1.0 / p) * m + offsetU) v.append(-(1.0 / q) * m + offsetV) # print "u:",u # print "v:",v return u, v
def toDRT(projections, angles, N, P, Q, center=False): ''' Convert the Mojette (asymetric) projection data to DRT (symetric) projections. Use the iFRT to reconstruct the image. Requires N+1 or N+N/2 projections if N is prime or dyadic respectively. Returns the resulting DRT space as a 2D array ''' size = int(N + N/2) dyadic = True if N % 2 == 1: # if odd, assume prime size = int(N+1) dyadic = False m = 0 frtSpace = np.zeros( (size,N) ) if dyadic: print("Dyadic size not tested yet.") #for each project '''for index, proj in enumerate(projections): p, q = farey.get_pq(angles[index]) m, inv = farey.toFinite(angles[index], N) frtSpace[m][:] = finiteProjection(proj, angles[index], P, Q, N, center)''' else: #prime size for index, proj in enumerate(projections): p, q = farey.get_pq(angles[index]) m, inv = farey.toFinite(angles[index], N) frtSpace[m][:] = finiteProjection(proj, angles[index], P, Q, N, center) return frtSpace
def finiteProjection(projection, angle, P, Q, N, center=False): ''' Convert a Mojette projection taken at angle into a finite (FRT) projection. ''' dyadic = True if N % 2 == 1: # if odd, assume prime dyadic = False shiftQ = int(N / 2.0 + 0.5) - int(Q / 2.0 + 0.5) shiftP = int(N / 2.0 + 0.5) - int(P / 2.0 + 0.5) finiteProj = np.zeros(N) p, q = farey.get_pq(angle) m, inv = farey.toFinite(angle, N) # print "p:", p, "q:", q, "m:", m, "inv:", inv translateOffset, perp = farey.finiteTranslateOffset(angle, N, P, Q) angleSign = p * q if dyadic: for translate, bin in enumerate(projection): if angleSign >= 0 and perp: #Reverse for perp translateMojette = translateOffset - translate else: translateMojette = translate - translateOffset translateFinite = (inv * translateMojette) % N if center: translateFinite = (translateFinite + shiftQ + m * (N - shiftP)) % N finiteProj[translateFinite] += bin else: for translate, bin in enumerate(projection): if angleSign >= 0 and perp: #Reverse for perp translateMojette = int(translateOffset) - int(translate) else: translateMojette = int(translate) - int(translateOffset) if translateMojette < 0: translateFinite = (N - (inv * abs(translateMojette)) % N) % N else: translateFinite = (inv * translateMojette ) % N #has issues in C, may need checking if center: translateFinite = (translateFinite + shiftQ + m * (N - shiftP)) % N finiteProj[translateFinite] += bin return finiteProj
def isKatzCriterion(P, Q, angles, K = 1): ''' Return true if angle set meets Katz criterion for exact reconstruction of discrete arrays ''' sumOfP = 0 sumOfQ = 0 n = len(angles) for j in range(0, n): p, q = farey.get_pq(angles[j]) sumOfP += abs(p) sumOfQ += abs(q) # if max(sumOfP, sumOfQ) > max(rows, cols): if sumOfP > K*P or sumOfQ > K*Q: return True else: return False
def angleSubSets_Symmetric(s, mode, P, Q, octant=0, binLengths=False, K=1): ''' Generate the minimal L1 angle set for the MT for s subsets. Parameter K controls the redundancy, K = 1 is minimal. If octant is non-zero, full quadrant will be used. Octant schemes are as follows: If octant = -1, the opposing octant is also used. If octant = 0,1 (default), only use one octant. If octant = 2, octant will be mirrored from diagonal to form a quadrant. If octant = 4, 2 quadrants. If octant = 8, all quadrants. Function can also return bin lengths for each bin. ''' angles = [] subsetAngles = [] for i in range(s): subsetAngles.append([]) fareyVectors = farey.Farey() maxPQ = max(P, Q) fareyVectors.compactOff() fareyVectors.generate(maxPQ - 1, 1) vectors = fareyVectors.vectors sortedVectors = sorted( vectors, key=lambda x: x.real**2 + x.imag**2) #sort by L2 magnitude index = 0 subsetIndex = 0 binLengthList = [] angles.append(sortedVectors[index]) subsetAngles[subsetIndex].append(sortedVectors[index]) binLengthList.append(projectionLength(sortedVectors[index], P, Q)) while not isKatzCriterion(P, Q, angles, K) and index < len(sortedVectors): # check Katz index += 1 angles.append(sortedVectors[index]) subsetAngles[subsetIndex].append(sortedVectors[index]) p, q = farey.get_pq(sortedVectors[index]) # p = imag, q = real binLengthList.append(projectionLength(sortedVectors[index], P, Q)) # if isKatzCriterion(P, Q, angles): # break if octant == 0: continue #add octants if octant == -1: nextOctantAngle = farey.farey(p, -q) #mirror from axis angles.append(nextOctantAngle) subsetAngles[subsetIndex].append(nextOctantAngle) binLengthList.append(projectionLength(nextOctantAngle, P, Q)) if mode == 1: subsetIndex += 1 subsetIndex %= s if octant > 0 and p != q: nextOctantAngle = farey.farey(q, p) #swap to mirror from diagonal angles.append(nextOctantAngle) subsetAngles[subsetIndex].append(nextOctantAngle) binLengthList.append(projectionLength(nextOctantAngle, P, Q)) if mode == 1: subsetIndex += 1 subsetIndex %= s if octant > 1: nextOctantAngle = farey.farey(p, -q) #mirror from axis angles.append(nextOctantAngle) subsetAngles[subsetIndex].append(nextOctantAngle) binLengthList.append(projectionLength(nextOctantAngle, P, Q)) if mode == 1: subsetIndex += 1 subsetIndex %= s if p != q: #dont replicate nextOctantAngle = farey.farey( q, -p) #mirror from axis and swap to mirror from diagonal angles.append(nextOctantAngle) subsetAngles[subsetIndex].append(nextOctantAngle) binLengthList.append(projectionLength(nextOctantAngle, P, Q)) if mode == 1: subsetIndex += 1 subsetIndex %= s if mode == 0: subsetIndex += 1 subsetIndex %= s if octant > 1: #add the diagonal and column projections when symmetric (all quadrant are wanted) nextOctantAngle = farey.farey(1, 0) #mirror from axis angles.append(nextOctantAngle) subsetAngles[0].append(nextOctantAngle) binLengthList.append(projectionLength(nextOctantAngle, P, Q)) if binLengths: return angles, subsetAngles, binLengthList return angles, subsetAngles