Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Healpy: From Data to Healpix map

I have a data grid where the rows represent theta (0, pi) and the columns represent phi (0, 2*pi) and where f(theta,phi) is the density of dark matter at that location. I wanted to calculate the power spectrum for this and have decided to use healpy.

What I can not understand is how to format my data for healpy to use. If someone could provide code (in python for obvious reasons) or point me to a tutorial, that would be great! I have tried my hand at doing it with the following code:

#grid dimensions are Nrows*Ncols (subject to change)
theta = np.linspace(0, np.pi, num=grid.shape[0])[:, None]
phi = np.linspace(0, 2*np.pi, num=grid.shape[1])
nside = 512
print "Pixel area: %.2f square degrees" % hp.nside2pixarea(nside, degrees=True)
pix = hp.ang2pix(nside, theta, phi)
healpix_map = np.zeros(hp.nside2npix(nside), dtype=np.double)
healpix_map[pix] = grid 

But, when I try to execute the code to do the power spectrum. Specifically, :

cl = hp.anafast(healpix_map[pix], lmax=1024)

I get this error:

TypeError: bad number of pixels

If anyone could point me to a good tutorial or help edit my code that would be great.

More specifications: my data is in a 2d np array and I can change the numRows/numCols if I need to.

Edit:

I have solved this problem by first changing the args of anafast to healpix_map. I also improved the spacing by making my Nrows*Ncols=12*nside*nside. But, my power spectrum is still giving errors. If anyone has links to good documentation/tutorial on how to calculate the power spectrum (condition of theta/phi args), that would be incredibly helpful.

like image 588
user3188290 Avatar asked Jul 22 '15 20:07

user3188290


2 Answers

There you go, hope it's what you're looking for. Feel free to comment with questions :)

import healpy as hp
import numpy as np
import matplotlib.pyplot as plt

# Set the number of sources and the coordinates for the input
nsources = int(1.e4)
nside = 16
npix = hp.nside2npix(nside)

# Coordinates and the density field f
thetas = np.random.random(nsources) * np.pi
phis = np.random.random(nsources) * np.pi * 2.
fs = np.random.randn(nsources)

# Go from HEALPix coordinates to indices
indices = hp.ang2pix(nside, thetas, phis)

# Initate the map and fill it with the values
hpxmap = np.zeros(npix, dtype=np.float)
for i in range(nsources):
    hpxmap[indices[i]] += fs[i]

# Inspect the map
hp.mollview(hpxmap)

enter image description here

Since the map above contains nothing but noise, the power spectrum should just contain shot noise, i.e. be flat.

# Get the power spectrum
Cl = hp.anafast(hpxmap)
plt.figure()
plt.plot(Cl)

enter image description here

like image 152
Daniel Lenz Avatar answered Nov 20 '22 17:11

Daniel Lenz


There is a faster way to do the map initialization using numpy.add.at, following this answer.

This is several times faster on my machine as compared to the first section of Daniel's excellent answer:

import healpy as hp
import numpy as np
import matplotlib.pyplot as plt

# Set the number of sources and the coordinates for the input
nsources = int(1e7)
nside = 64
npix = hp.nside2npix(nside)

# Coordinates and the density field f
thetas = np.random.uniform(0, np.pi, nsources)
phis = np.random.uniform(0, 2*np.pi, nsources)
fs = np.random.randn(nsources)

# Go from HEALPix coordinates to indices
indices = hp.ang2pix(nside, thetas, phis)

# Baseline, from Daniel Lenz's answer:
# time: ~5 s
hpxmap1 = np.zeros(npix, dtype=np.float)
for i in range(nsources):
    hpxmap1[indices[i]] += fs[i]

# Using numpy.add.at
# time: ~0.6 ms
hpxmap2 = np.zeros(npix, dtype=np.float)
np.add.at(hpxmap2, indices, fs)
like image 25
ampw Avatar answered Nov 20 '22 16:11

ampw