-
Notifications
You must be signed in to change notification settings - Fork 26
Description
Preserving work done on this problem for posterity
FLEBasis2D will be a new basis class introduced in #693, ported from https://github.com/nmarshallf/fle_2d.
Differences between this basis and the existing FBBasis2D mean that either
- There are fundamental differences in both selection of basis functions and calculation of coefficients or,
- The differences in the implementation between the two codes are such that comparison is very difficult
Initial basis count heuristic
FBBasis2D sets the count in advance using the following formula:
self.count = self.k_max[0] + sum(2 * self.k_max[1:])
k_max[i] is the number of Bessel zeros (q's in the paper) included for Bessel order i. So this is equivalent to the DC component plus all k,q combinations times 2 (positive and negative).
FLEBasis2D uses
self.count = int(self.nres**2 * np.pi / 4)
which is based on the geometry of the problem (pi * R**2: the area of the disc inscribed in the image box)
Basis functions used
FLEBasis2D can be forced to use the FBBasis2D heuristic to determine whether the same subset of basis functions are chosen.
The two classes store the 3 parameters determining the basis function (ell, k, and sign) differently in FBBasis2D._indices vs FLEBasis2D.ells/.ks but compare in the following way:
L = 32
fle = FLEBasis2D(L, match_fb=True, dtype=np.float64)
fb = FBBasis2D(L, dtype=np.float64)
fb_fns = []
for idx, ell in enumerate(fb._indices["ells"]):
fb_fns.append((ell, fb._indices["ks"][idx], fb._indices["sgns"][idx]))
def sign(x):
if ell==0:
return 1
else:
return np.sign(x)
fle_fns = []
for idx, ell in enumerate(fle.ells):
fle_fns.append((abs(ell), fle.ks[idx]-1, sign(ell)))The code above reveals two things to note:
FBBasis2Drecords the sign of the DC component as1, whileFLEhas0- All
ksforFLEare one ahead of those forFB
When these are corrected for, we seem to have the same set of functions:
>>> set(fle_fns) == set(fb_fns)
TrueThe following code sorts both sets of tuples and returns the indices after being sorted (like np.argsort but modified to work on ordering tuples)
Luckily, THIS IS NOT TRUE, YOU DO HAVE TO WORRY fb_indices is simply [0,1,2...count] in order, because the way FB indices are stored already exactly corresponds to the way Python sorts tuples by default. So all we need to worry about is fle_indicesfb_indices. CODE SNIPPETS UPDATED
fb_indices = sorted(range(len(fb_fns)), key=lambda k: fb_fns[k])
fle_indices = sorted(range(len(fle_fns)), key=lambda k: fle_fns[k])Visually compare matched basis functions using one-hot tests with evaluate
fb_images_sorted = fb.evaluate(np.eye(fb.count)[fb_indices])
fle_images_sorted = fle.evaluate(np.eye(fb.count)[fle_indices])Functions are visually similar when k=0 but diverge past that point. Note also that the deltas for those similar images are on a very very small scale (1e-8).
Image(fb_images_sorted[10:20]).show()
Image(fle_images_sorted[10:20]).show()
Image(fb_images_sorted[10:20] - fle_images_sorted[10:20]).show()FB
FLE
Deltas
This seems likely to be related to the off-by-one discrepancy with ks. To be continued


