general (adjoint) spin-n SHTs.
cunuSHT provides functions to calculate spherical harmonic transforms for any uniform and non-uniform grid.
It can run on both, CPU and GPU, and can do this for (custom) geometries. The code and method are described in: 2406.14542.
Operators:
nusht2d2()
: takes SHT coefficients and (possibly non-uniform) grid points at which they are to be evaluated and returns the SHT transformed position space data (a map).nusht2d1()
: this is the adjoint operation, takes a map with (possibly non-uniform grid points) and returns the SHT coefficients for a uniform grid.gclm2lenmap()
: similar to synthesis_general, but automatically performs dlm2pointing, iff no pointing is providedlenmap2gclm()
: similar to adjoint_synthesis_general, but again, perfroms dlm2pointing if needed.dlm2pointing()
: calculates the non-uniform grid points (pointing) from the coefficients of a deflection field (dlm).
Highly accurate remapping of pixels on the sphere, as shown in the following examples.
Psuedo-simulated movement of Jupiters cloudsRepeated deflection of the cosmic microwave background with random Gaussian Lambda-CDM deflection fields.
Currently in 2 steps:
Enter the cunusht/c
folder, and compile the C and CUDA library, and install the python module via the pyproject.toml
cd cunusht/c
pip install .
Then, go to the root directory, and install cunusht
:
cd ./../../
python3 setup.py install
See our tutorials in first steps.
The interface works as follows.
Set parameters,
lmax, mmax = 2047, 2047
geominfo = ('gl',{'lmax': lmax})
kwargs = {
'geominfo_deflection': geominfo,
'nuFFTtype': 2, # or 1 if you want to use nusht2d1()
'epsilon': 1e-7,
}
Construct your transformer,
import cunusht
t = cunusht.get_transformer(backend='GPU')(**kwargs)
- alm are the SHT coefficients for which the map should be calculated
- loc are the positions (theta, and phi) of the map for which the map should be calculated
- pointmap is the output array
res = t.nusht2d1(lmax=lmax, mmax=mmax, alm=coef, loc=loc, pointmap=pointmap, verbose=True)
Or, if you want to calculate the adjoint (not how nuFFTtype changes here!)
lmax, mmax = 2047, 2047
geominfo = ('gl',{'lmax': lmax})
kwargs = {
'geominfo_deflection': geominfo,
'nuFFTtype': 1, # or 2 if you want to use nusht2d2()
'epsilon': 1e-7,
}
import cunusht
t = cunusht.get_transformer(backend='GPU')(**kwargs)
res = t.nusht2d1(lmax=lmax, mmax=mmax, pointmap=m, loc=loc, alm=alm)
We provide convenience function for CMB weak lensing purposes.
This is a wrapper around nusht2d2 The function depends on,
- gclm: the SHT coefficients at the uniform grid points
- ptg: the (non-uniform) grid points (the pointing) for which the pointmap should be evaluated
- dlm(_scaled): the deflection field that is used to calculate pointing, iff ptg is not provided. Note, for the GPU backend, this is dlm_scaled and must be
dlm * np.sqrt(1/l(l+1))
. - lmax: the pointmap maximum SHT multipole
- mmax: the dlm_scaled mmax
- lenmap: the output
Choose your parameters, then
res = t.gclm2lenmap(gclm=cp.array(coef), dlm_scaled=cp.zeros(shape=coef.shape), lmax=lmax, mmax=lmax, lenmap=pointmap)
This is a wrapper around nusht2d1
This is the adjoint (inverse) operation of gclm2lenmap()
, if lenmap is not quadrature weighted (is multiplied by the maginification matrix, quadrature weighted, and deflection is zero).
Similar to above,
res = t.lenmap2gclm(lenmap, dlm_scaled=dlm_scaled, lmax=lmax, mmax=lmax, epsilon=epsilon, gclm=gclm)