# Starlock's painterly pass (full, radius 5), seen per tap: the floors, the best lattice by number of
# levels, and where well-known lattice constants rank among all lattices. Prints out/starlock.txt.
import numpy as np
import filters as F, lattice as L

t = F.kuwahara(5)
bd = L.bounds(t)
print(f'floor for any dither: {bd["any"]:.4f} (|H| is smallest, {bd["hmin"]:.4f}, at {bd["at"][0]:.4f}, {bd["at"][1]:.4f} cycles per tap)')
print(f'floor for any threshold array: {bd["array"]:.4f}; for any irrational lattice: {bd["lattice"]:.4f}')
print('best lattice with at most N levels:')
top = (np.inf,)
for N in range(2, 257):
    S = L.search(F.grid_response(t, N), N); b, a = np.unravel_index(np.argmin(S), S.shape)
    if np.sqrt(S[b, a]) < top[0] - 1e-6:
        top = (np.sqrt(S[b, a]), a, b, N)
        print(f'  ({a},{b})/{N}: {top[0]:.4f}  ({top[0] / bd["any"]:.3f} x the floor)')
# every lattice with 1024 levels: the spread, and where R2's constants fall (rounded to /1024)
N = 1024
S = np.sqrt(L.search(F.grid_response(t, N), N)); v = S[np.isfinite(S)]
r2 = np.sqrt(L.J(round(0.7548776662 * N), round(0.5698402910 * N), N, F.grid_response(t, N))[0])
print(f'all {v.size} lattices with {N} levels: best {v.min():.4f}, median {np.median(v):.4f}, worst {v.max():.4f}')
print(f'R2 (rounded to /{N}): {r2:.4f}, better than {(v > r2).mean():.0%} of them')
