-
Notifications
You must be signed in to change notification settings - Fork 44
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
Healpix doc #2498
base: main
Are you sure you want to change the base?
Healpix doc #2498
Changes from 11 commits
3e4e59d
4cfb926
c58d3fc
e3c495e
1cf3ef1
b5e9012
54fc7bb
be44d76
bb74178
7499763
f624380
1fda4d8
569e18c
4ac8339
e86f307
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,3 +164,202 @@ for message in consumer.consume(end[0].offset - start[0].offset, timeout=1): | |
continue | ||
print(message.value()) | ||
``` | ||
|
||
--- | ||
|
||
handle: | ||
breadcrumb: HEALPix Maps | ||
|
||
--- | ||
|
||
import { Highlight } from '~/components/Highlight' | ||
import { Tab, Tabs } from '~/components/tabs' | ||
|
||
## HEALPix Sky Maps | ||
|
||
HEALPix stands for <b>H</b>ierarchical, <b>E</b>qual <b>A</b>rea, and iso-<b>L</b>atitude <b>Pix</b>elisation is a scheme for indexing positions on the unit sphere. | ||
For localization of events, the multi-messenger community uses the standard [HEALPix](https://healpix.sourceforge.io) format with the file extension `.fits.gz`, as well as multi-resolution HEALPix format with the file extension `.multiorder.fits`. The preferred format is the multi-resolution HEALPix format, that is only format explicitly listed in the GCN. | ||
|
||
### Multi-Order Sky Maps | ||
|
||
GCN strongly encourages the use of multi-order sky maps. These are a more complex form of healpix sky maps that utilize a variable resolution, with higher probability regions having higher resolution and lower probability regions being encoded with a lower resolution. This is signicantly more efficient than single-resolution healpix sky maps with respect to storage footprint and read speed. However, interpreting these multi-order sky maps can be more complex. | ||
|
||
### Working with HEALPix Maps | ||
|
||
HEALPix data is distrubuted in standard format with the file extension `.fits.gz`. These files are FITS image files and can be utilized with many common FITS tools. These files usually stored as HEALPix projection, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. incomplete sentence
Vidushi-GitHub marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### Reading Sky Maps | ||
|
||
Sky maps can be parsed using python; to start, import a handful of packages (note: while this documentation covers the use of `astropy-healpix`, there are several packages that can be used for this purpose; a number of alternatives are listed at the bottom of this page) | ||
|
||
```python | ||
import astropy_healpix as ah | ||
import numpy as np | ||
|
||
from astropy import units as u | ||
from astropy.table import QTable | ||
``` | ||
|
||
A given sky map can then be read in as | ||
|
||
```python | ||
skymap = QTable.read('skymap.multiofits) | ||
``` | ||
|
||
#### Most Probable Sky Location | ||
|
||
The index of the highest probability point can be found by doing the following | ||
|
||
```python | ||
hp_index = np.argmax(skymap['PROBDENSITY']) | ||
uniq = skymap[hq_index]['UNIQ'] | ||
|
||
level, ipix = ah.uniq_to_level_ipix(uniq) | ||
nside = ah.level_to_nside(level) | ||
|
||
ra, dec = ah.healpix_to_lonlat(ipix, nside, order='nested') | ||
``` | ||
|
||
#### Probability Density at a Known Position | ||
|
||
Similarly, one can calculate the probability density at a known position | ||
|
||
```python | ||
ra, dec = 197.450341598 * u.deg, -23.3814675445 * u.deg | ||
|
||
level, ipix = ah.uniq_to_level_ipix(skymap['UNIQ']) | ||
nside = ah.level_to_nside(level) | ||
|
||
match_ipix = ad.lonlat_to_healpix(ra, dec, nside, order='nested') | ||
|
||
match_index = np.flatnonzero(ipix == match_ipix)[0] | ||
|
||
prob_density = skymap[match_index]['PROBDENSITY'].to_value(u.deg**-2) | ||
``` | ||
|
||
#### Find the 90% Probability Region | ||
|
||
The estimation of a 90% probability region, involves sorting the pixel, calculating the area of each pixel, and then proceeding by the probability of each pixel. | ||
|
||
```python | ||
#Sort the pixels by decending probability density | ||
skymap.sort('PROBDENSITY', reverse=True) | ||
|
||
#Area of each pixel | ||
level, ipix = ah.uniq_to_level_ipix(skymap['UNIQ']) | ||
pixel_area = ah.nside_to_pixel_area(ah.level_to_nside(level)) | ||
|
||
#Pixel area times the probability | ||
prob = pixel_area * skymap['PROBDENSITY'] | ||
|
||
#Cummulative sum of probability | ||
cumprob = np.cumsum(prob) | ||
|
||
#Pixels for which cummulative is 0.9 | ||
i = cumprob.searchsorted(0.9) | ||
|
||
#Sum of the areas of the pixels up to that one | ||
area_90 = pixel_area[:i].sum() | ||
area_90.to_value(u.deg**2) | ||
|
||
``` | ||
|
||
#### Flat Resolution HEALPix Sky maps | ||
|
||
Let's say you have a sky map fits file, read in Python with Healpy: | ||
|
||
```python | ||
import healpy as hp | ||
import numpy as np | ||
|
||
# Read both the HEALPix image data and the FITS header | ||
hpx, header = hp.read_map('*.fits.gz,0', h=True) | ||
|
||
# Plotting a Mollweide-projection all-sky map | ||
np.mollview(hpx) | ||
``` | ||
|
||
Most Probable Sky Location | ||
|
||
```python | ||
# Find the highest probability pixel | ||
ipix_max = np.argmax(hpx) | ||
|
||
# Probability density per square degree at that position | ||
hpx[ipix_max] / hp.nside2pixarea(nside, degrees=True) | ||
|
||
# Highest probability pixel on the sky | ||
theta, phi = hp.pix2ang(nside, ipix_max) | ||
ra = np.rad2deg(phi) | ||
dec = np.rad2deg(0.5 * np.pi - theta) | ||
ra, dec | ||
``` | ||
|
||
#### Integrated probability in a Circle | ||
|
||
We call hp.query_disc to obtain an array of indices for the pixels inside the circle. | ||
|
||
```python | ||
# First define the Cartesian coordinates of the center of the Circle | ||
ra = 180.0 | ||
dec = -45.0 | ||
radius = 2.5 | ||
|
||
# We convert to spherical polar coordinates | ||
theta = 0.5 * np.pi - np.deg2rad(dec) | ||
phi = np.deg2rad(ra) | ||
radius = np.deg2rad(radius) | ||
|
||
# Calculate Cartesian coordinates of the center of the Circle | ||
xyz = hp.ang2vec(theta, phi) | ||
|
||
# Obtain an array of indices for the pixels inside the circle | ||
ipix_disc = hp.query_disc(nside, xyz, radius) | ||
|
||
# Sum the probability in all of the matching pixels: | ||
hpx[ipix_disc].sum() | ||
|
||
``` | ||
|
||
#### Integrated probability in a Polygon | ||
|
||
We can use the `hp.query_polygon` function to find the pixels inside a polygon and compute the probability that the source is inside the polygon by adding up the pixel values. | ||
|
||
```python | ||
# Indices of the pixels within a polygon (defined by the Cartesian coordinates of its vertices) | ||
|
||
xyz = [[-0.5, -0.4, -0.5], | ||
[-0.4, -0.4, -0.6], | ||
[-0.6, -0.3, -0.6], | ||
[-0.7 , -0.4, -0.5]] | ||
ipix_poly = hp.query_polygon(nside, xyz) | ||
hpx[ipix_poly].sum() | ||
``` | ||
|
||
##### Further documentation | ||
|
||
Additional information can be found on the [LIGO website](https://emfollow.docs.ligo.org/userguide/tutorial/multiorder_sky maps.html) | ||
|
||
[healpy](https://healpy.readthedocs.io/en/latest/): Official python library for handling the pixlated data on sphere | ||
|
||
[astropy-healpix](https://pypi.org/project/astropy-healpix/) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add description
Vidushi-GitHub marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[mhealpy](https://mhealpy.readthedocs.io/en/latest/): Object-oriented wrapper of healpy for handling the multi-resolution maps | ||
|
||
[MOCpy](https://cds-astro.github.io/mocpy/): Python library allowing easy creation, parsing and manipulation of Multi-Order Coverage maps. | ||
|
||
## Papers | ||
|
||
(1) Calabretta, M. R., & Roukema, B. F. 2007, Mon. Notices Royal Astron. Soc., 381, 865. [doi:10.1111/j.1365-2966.2007.12297.x](https://academic.oup.com/mnras/article/381/2/865/1021805?login=true) | ||
|
||
(2) Górski, K.M., Hivon, E., Banday, A.J., et al. 2005, Astrophys. J., 622, 759. [doi:10.1086/427976](https://iopscience.iop.org/article/10.1086/427976) | ||
|
||
(3) Górski, K. M., Wandelt, B. D., et al. 1999. [arXiv:astro-ph/9905275](https://arxiv.org/abs/astro-ph/9905275) | ||
|
||
(4) Fernique, P., Allen, et al. 2015, Astron. Astrophys., 578, A114. [doi:10.1051/0004-6361/201526075](https://www.aanda.org/articles/aa/full_html/2015/06/aa26075-15/aa26075-15.html) | ||
|
||
(5) Fernique, P., Boch, T., et al. 2014, IVOA Recommendation. [arXiv:1505.02937](https://arxiv.org/abs/1505.02937) | ||
|
||
(6) Martinez-Castellanos, I., Singer, L. P., et al. 2022, Astrophys. J., 163, 259. [doi:10.3847/1538-3881/ac6260](https://iopscience.iop.org/article/10.3847/1538-3881/ac6260) | ||
|
||
(7) Singer, L. P., & Price, L. R. 2016, Phys. Rev. D, 93, 024013. [doi:10.1103/PhysRevD.93.024013](https://journals.aps.org/prd/abstract/10.1103/PhysRevD.93.024013) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use DOIs for all paper URLs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. resolved in 569e18c |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'.gz' isn't specific to a healpix file, it's just showing that it's zipped.
Also, what is meant by "listed in the GCN"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not specific to HEALPix, but the convention for localization FITS files is that it's either a flat-resolution file and gzip-compressed, or a multi-order file and not compressed. @Vidushi-GitHub's text here is correct within this context.