-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow lmax greater than the exact bandlimit #18
Comments
Hi @zatkins2! Concerning the more specific question: This is a bit tricky to answer because I guess there are two different concepts of Concerning the more general question, I have put together a very simple demo script which generates a GL map from I admit that I haven't tried other grids yet; I'll have to make a few adjustments to get this to work, but I'll post my results here! import ducc0
import numpy as np
from time import time
rng = np.random.default_rng(48)
# helper functions
def nalm(lmax, mmax):
return ((mmax+1)*(mmax+2))//2 + (mmax+1)*(lmax-mmax)
def random_alm(lmax, mmax, spin, ncomp):
res = rng.uniform(-1., 1., (ncomp, nalm(lmax, mmax))) \
+ 1j*rng.uniform(-1., 1., (ncomp, nalm(lmax, mmax)))
# make a_lm with m==0 real-valued
res[:, 0:lmax+1].imag = 0.
ofs=0
for s in range(spin):
res[:, ofs:ofs+spin-s] = 0.
ofs += lmax+1-s
return res
# test function:
# - create a_lm with lmax=lmax, mmax=0,
# - put them on a suitable GL grid
# - analyze the grid using analysis_2d, resulting in alm2
# - brute-force "analyze" the grid (up to lmax2) using GL weights and
# adjoint_synthesis_2d, resulting in alm3
def test(lmax, lmax2):
geometry= "GL"
nrings = lmax+1
# randoom a_lm
alm = random_alm(lmax, 0, 0, 1)
# go to minimum GL map
map = ducc0.sht.experimental.synthesis_2d(alm=alm, lmax=lmax, mmax=0, spin=0, geometry=geometry,ntheta=nrings, nphi=1)
# standard analysis up to (and including) lmax
alm2 = ducc0.sht.experimental.analysis_2d(map=map, lmax=lmax, mmax=0, spin=0, geometry=geometry)
# apply GL weights
wgt = ducc0.sht.experimental.get_gridweights(geometry, nrings)
mapx = map*wgt.reshape((1,-1,1))
# non-standard analysis up to (and including) lmax2
alm3 = ducc0.sht.experimental.adjoint_synthesis_2d(lmax=lmax2, mmax=0, spin=0, map=mapx, nthreads=1, geometry=geometry)
# plot the results
import matplotlib.pyplot as plt
plt.plot(np.abs(alm2[0]),label="analysis_2d")
plt.plot(np.abs(alm3[0]),linestyle="dashed", label="nonstandard analysis")
plt.plot(np.abs(alm[0]),linestyle="dotted", label="input")
plt.legend()
plt.show()
test(lmax=10, lmax2=20) |
Here is a slightly different example which also works on non-GL grids. import ducc0
import numpy as np
rng = np.random.default_rng(48)
# helper functions
def nalm(lmax, mmax):
return ((mmax+1)*(mmax+2))//2 + (mmax+1)*(lmax-mmax)
def random_alm(lmax, mmax, spin, ncomp):
res = rng.uniform(-1., 1., (ncomp, nalm(lmax, mmax))) \
+ 1j*rng.uniform(-1., 1., (ncomp, nalm(lmax, mmax)))
# make a_lm with m==0 real-valued
res[:, 0:lmax+1].imag = 0.
ofs=0
for s in range(spin):
res[:, ofs:ofs+spin-s] = 0.
ofs += lmax+1-s
return res
# test function:
# - create a_lm wwhich are zero except at lmax=lmax, mmax=0,
# - put them on a grid with a number of rings required for a band limit of lmax2
# - analyze the grid using analysis_2d
# - show resulting a_lm
def test2(geometry, lmax_grid, lmax_data):
nrings = lmax_grid+1
if geometry=="CC":
nrings = lmax_grid+2
elif geometry=="DH":
nrings = 2*lmax_grid+2
elif geometry=="F2":
nrings = 2*lmax_grid+1
# random a_lm at (lmax_data,0)
alm = random_alm(lmax_data, 0, 0, 1)
alm *= 0
alm[0,lmax_data] = 1
# go to minimum map
map = ducc0.sht.experimental.synthesis_2d(alm=alm, lmax=lmax_data, mmax=0, spin=0, geometry=geometry,ntheta=nrings, nphi=1)
# standard analysis up to (and including) lmax_grid
alm2 = ducc0.sht.experimental.analysis_2d(map=map, lmax=lmax_grid, mmax=0, spin=0, geometry=geometry)
# plot the results
import matplotlib.pyplot as plt
plt.plot(np.abs(alm2[0]), label="result")
plt.legend()
plt.show()
test2("CC", lmax_data=12, lmax_grid=10) As you can see from the example, the "too high" moments cause severe aliasing; in other words, the spherical analysis interprets moments beyond the Nyquist frequency as other moments below Nyquist. Please note that using |
Hi @mreineck,
Just wanted to follow-up in a dedicated place to our discussion here. I guess I have two questions, one more specific and one more general.
More specific
Perhaps naively, I thought the maximum lmax of SHT analysis was 1 more than what's calculated here. For instance, for a regular rectangular pixelization (e.g.
CC
orF1
) with 0.5' pixel size (used in ACT), theducc
lmax is 21599, whereas the Nyquist frequency of such a pixelization is 21600 (withk_nyq = 0.5 * 2*pi / resolution
). Perhaps this is related to the novel algorithm you implement (or perhaps my intuition is just wrong)?More general
Again, unless there are new considerations from your algorithm that go beyond a ``classic" quadrature rule, I'm not sure I agree with your statement that
Considering a regular rectangular pixelization, don't rings farther from the equator sample frequencies beyond lmax in the x-direction? Not sure they could be usefully extracted with an SHT as I agree there will be more and more aliasing as you go farther beyond lmax (really my silly interest is to go 1 beyond lmax, as above, if nothing else because round numbers are nice 😛).
The text was updated successfully, but these errors were encountered: