Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

from __future__ import division 

import numpy as np 

import healpy as hp 

 

__all__ = ['hpid2RaDec', 'raDec2Hpid', 'healbin', '_hpid2RaDec', '_raDec2Hpid', '_healbin', 'moc2array'] 

 

 

def _hpid2RaDec(nside, hpids, **kwargs): 

""" 

Correct for healpy being silly and running dec from 0-180. 

 

Parameters 

---------- 

nside : int 

Must be a value of 2^N. 

hpids : np.array 

Array (or single value) of healpixel IDs. 

 

Returns 

------- 

raRet : float (or np.array) 

RA positions of the input healpixel IDs. In radians. 

decRet : float (or np.array) 

Dec positions of the input healpixel IDs. In radians. 

""" 

 

lat, lon = hp.pix2ang(nside, hpids, **kwargs) 

decRet = np.pi / 2.0 - lat 

raRet = lon 

 

return raRet, decRet 

 

 

def hpid2RaDec(nside, hpids, **kwargs): 

""" 

Correct for healpy being silly and running dec from 0-180. 

 

Parameters 

---------- 

nside : int 

Must be a value of 2^N. 

hpids : np.array 

Array (or single value) of healpixel IDs. 

 

Returns 

------- 

raRet : float (or np.array) 

RA positions of the input healpixel IDs. In degrees. 

decRet : float (or np.array) 

Dec positions of the input healpixel IDs. In degrees. 

""" 

ra, dec = _hpid2RaDec(nside, hpids, **kwargs) 

return np.degrees(ra), np.degrees(dec) 

 

 

def _raDec2Hpid(nside, ra, dec, **kwargs): 

""" 

Assign ra,dec points to the correct healpixel. 

 

Parameters 

---------- 

nside : int 

Must be a value of 2^N. 

ra : np.array 

RA values to assign to healpixels. Radians. 

dec : np.array 

Dec values to assign to healpixels. Radians. 

 

Returns 

------- 

hpids : np.array 

Healpixel IDs for the input positions. 

""" 

lat = np.pi / 2.0 - dec 

hpids = hp.ang2pix(nside, lat, ra, **kwargs) 

return hpids 

 

 

def raDec2Hpid(nside, ra, dec, **kwargs): 

""" 

Assign ra,dec points to the correct healpixel. 

 

Parameters 

---------- 

nside : int 

Must be a value of 2^N. 

ra : np.array 

RA values to assign to healpixels. Degrees. 

dec : np.array 

Dec values to assign to healpixels. Degrees. 

 

Returns 

------- 

hpids : np.array 

Healpixel IDs for the input positions. 

""" 

return _raDec2Hpid(nside, np.radians(ra), np.radians(dec), **kwargs) 

 

 

def _healbin(ra, dec, values, nside=128, reduceFunc=np.mean, dtype=float, fillVal=hp.UNSEEN): 

""" 

Take arrays of ra's, dec's, and value and bin into healpixels. Like numpy.hexbin but for 

bins on a sphere. 

 

Parameters 

---------- 

ra : np.array 

RA positions of the data points. Radians. 

dec : np.array 

Dec positions of the data points. Radians 

values : np.array 

The values at each ra,dec position. 

nside : int 

Healpixel nside resolution. Must be a value of 2^N. 

reduceFunc : function (numpy.mean) 

A function that will return a single value given a subset of `values`. 

dtype : dtype ('float') 

Data type of the resulting mask 

 

Returns 

------- 

mapVals : np.array 

A numpy array that is a valid Healpixel map. 

""" 

 

hpids = _raDec2Hpid(nside, ra, dec) 

 

order = np.argsort(hpids) 

hpids = hpids[order] 

values = values[order] 

pixids = np.unique(hpids) 

 

left = np.searchsorted(hpids, pixids) 

right = np.searchsorted(hpids, pixids, side='right') 

 

mapVals = np.zeros(hp.nside2npix(nside), dtype=dtype) + fillVal 

 

# Wow, I thought histogram would be faster than the loop, but this has been faster! 

for i, idx in enumerate(pixids): 

mapVals[idx] = reduceFunc(values[left[i]:right[i]]) 

 

# Change any NaNs to fill value 

mapVals[np.isnan(mapVals)] = fillVal 

 

return mapVals 

 

 

def healbin(ra, dec, values, nside=128, reduceFunc=np.mean, dtype=float): 

""" 

Take arrays of ra's, dec's, and value and bin into healpixels. Like numpy.hexbin but for 

bins on a sphere. 

 

Parameters 

---------- 

ra : np.array 

RA positions of the data points. Degrees. 

dec : np.array 

Dec positions of the data points. Degrees. 

values : np.array 

The values at each ra,dec position. 

nside : int 

Healpixel nside resolution. Must be a value of 2^N. 

reduceFunc : function (numpy.mean) 

A function that will return a single value given a subset of `values`. 

dtype : dtype ('float') 

Data type of the resulting mask 

 

Returns 

------- 

mapVals : np.array 

A numpy array that is a valid Healpixel map. 

""" 

return _healbin(np.radians(ra), np.radians(dec), values, nside=nside, 

reduceFunc=reduceFunc, dtype=dtype) 

 

 

def moc2array(data, uniq, nside=128, reduceFunc=np.sum, density=True, fillVal=0.): 

"""Convert a Multi-Order Coverage Map to a single nside HEALPix array. Useful 

for converting maps output by LIGO alerts. Expect that future versions of 

healpy or astropy will be able to replace this functionality. Note that this is 

a convienence function that will probably degrade portions of the MOC that are 

sampled at high resolution. 

 

Details of HEALPix Mulit-Order Coverage map: http://ivoa.net/documents/MOC/20190404/PR-MOC-1.1-20190404.pdf 

 

Parameters 

---------- 

data : np.array 

Data values for the MOC map 

uniq : np.array 

The UNIQ values for the MOC map 

nside : int (128) 

The output map nside 

reduceFunc : function (np.sum) 

The function to use to combine data into single healpixels. 

density : bool (True) 

If True, multiplies data values by pixel area before applying reduceFunc, and divides 

the final array by the output pixel area. Should be True if working on a probability density MOC. 

fillVal : float (0.) 

Value to fill empty HEALPixels with. Good choices include 0 (default), hp.UNSEEN, and np.nan. 

 

Returns 

------- 

np.array : HEALpy array of nside. Units should be the same as the input map as processed by reduceFunc. 

""" 

 

# NUNIQ packing, from page 12 of http://ivoa.net/documents/MOC/20190404/PR-MOC-1.1-20190404.pdf 

orders = np.floor(np.log2(uniq / 4) / 2).astype(int) 

npixs = (uniq - 4 * 4**orders).astype(int) 

 

nsides = 2**orders 

names = ['ra', 'dec', 'area'] 

types = [float]*len(names) 

data_points = np.zeros(data.size, dtype=list(zip(names, types))) 

for order in np.unique(orders): 

good = np.where(orders == order) 

ra, dec = _hpid2RaDec(nsides[good][0], npixs[good], nest=True) 

data_points['ra'][good] = ra 

data_points['dec'][good] = dec 

data_points['area'][good] = hp.nside2pixarea(nsides[good][0]) 

 

if density: 

tobin_data = data*data_points['area'] 

else: 

tobin_data = data 

 

result = _healbin(data_points['ra'], data_points['dec'], tobin_data, nside=nside, 

reduceFunc=reduceFunc, fillVal=fillVal) 

 

if density: 

good = np.where(result != fillVal) 

result[good] = result[good] / hp.nside2pixarea(nside) 

 

return result