We start by adjusting the notebook settings.
In [1]:
%load_ext autoreload
%autoreload 2
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
In [2]:
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import healpy as hp
from astropy.io import fits
from astropy.utils.misc import NumpyRNGContext
import cygrid
The properties of the map are given by the ordering and the nside of the map. For more details, check the paper by Gorski et al. (2005).
In [3]:
NSIDE = 128
NPIX = hp.nside2npix(NSIDE)
The data are just random draws from the standard normal distribution. For the weights, we choose uniform weighting. The coordinates can be easily calculated with healpy.
In [4]:
# data and weights
with NumpyRNGContext(0):
# make sure to have "predictable" random numbers
input_data = np.random.randn(NPIX)
# coordinates
theta, phi = hp.pix2ang(NSIDE, np.arange(NPIX))
lons = np.rad2deg(phi)
lats = 90. - np.rad2deg(theta)
The pixel size for this NPIX is:
In [5]:
print('pixel size: {:.1f}"'.format(3600 * hp.nside2resol(NSIDE)))
A quick look confirms that our data looks just as expected.
In [6]:
hp.mollview(input_data)
We are now interested in the values of this map at a couple of given positions. It wouldn't make sense to use cygrid at all, if we were just interested in the values of the map at the given positions. Even when the positions are not exactly aligned with the HEALPix pixel centers, employing some interpolation routine would do a good job.
But let's assume that we would want to compare the values with another data set, whose angular resolution is much worse. Then it is reasonable to down-sample (i.e., lower the angular resolution by smoothing with a Gaussian kernel) our HEALPix map before extracting the sight-line values. With cygrid's sight-line gridder, this is done only for the vicinity of the requested positions, which can save a lot of computing time (only for large NSIDE, because healpy's smoothing function is very fast for small and moderate NSIDE due to the use of FFTs). cygrid would be at true advantage for most other projections, though.
In order to compare the results with healpy's smoothing routine (see below), we will use HEALPix pixel center coordinates without loss of generality.
In [7]:
with NumpyRNGContext(0):
target_hpx_indices = np.random.randint(0, NPIX, 5)
theta, phi = hp.pix2ang(NSIDE,target_hpx_indices)
target_lons = np.rad2deg(phi)
target_lats = 90. - np.rad2deg(theta)
print('{:>8s} {:>8s}'.format('glon', 'glat'))
for glon, glat in zip(target_lons, target_lats):
print('{:8.4f} {:8.4f}'.format(glon, glat))
We initiate the gridder by specifying the target sightlines.
In [8]:
gridder = cygrid.SlGrid(target_lons, target_lats)
The gridding kernel is of key importance for the entire gridding process. cygrid allows you to specify the shape of the kernel (e.g. elliptical Gaussian or tapered sinc) and its size.
In our example, we use a symmetrical Gaussian (i.e. the major and minor axis of the kernel are identical). In that case, we need to furthermore specify kernelsize_sigma, the sphere_radius up to which the kernel will be computed, and the maximum acceptable healpix resolution for which we recommend kernelsize_sigma/2.
We refer to section 3.5 of the paper ('a minimal example') for a short discussion of the kernel parameters.
In [9]:
kernelsize_fwhm = 1. # 1 degree
# see https://en.wikipedia.org/wiki/Full_width_at_half_maximum
kernelsize_sigma = kernelsize_fwhm / np.log(8 * np.sqrt(2))
sphere_radius = 4. * kernelsize_sigma
gridder.set_kernel(
'gauss1d',
(kernelsize_sigma,),
sphere_radius,
kernelsize_sigma / 2.
)
After the kernel has been set, we perform the actual gridding by calling grid() with the coordinates and the data.
In [10]:
gridder.grid(lons, lats, input_data)
To get the gridded data, we simply call get_datacube().
In [11]:
sightlines = gridder.get_datacube()
Finally, we get a list of our gridded sightlines within the chosen aperture.
We can compare this with the healpy smoothing operation:
In [12]:
smoothed_map = hp.sphtfunc.smoothing(
input_data,
fwhm=np.radians(kernelsize_fwhm),
)
smoothed_data = smoothed_map[target_hpx_indices]
In [13]:
print('{:>8s} {:>8s} {:>10s} {:>10s}'.format(
'glon', 'glat', 'cygrid', 'healpy')
)
for t in zip(
target_lons, target_lats,
sightlines, smoothed_data,
):
print('{:8.4f} {:8.4f} {:10.6f} {:10.6f}'.format(*t))
Note, that it is expected that the two methods differ somewhat, because they are based on very different techniques (healpy transforms the map to harmonic space and convolves the harmonic coefficients $a_{lm}$ with the beam, which is also transformed to harmonic space).