mwdust 1.6__cp314-cp314-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mwdust might be problematic. Click here for more details.
- healpix_c.cp314-win_amd64.pyd +0 -0
- mwdust/Combined15.py +61 -0
- mwdust/Combined19.py +62 -0
- mwdust/Drimmel03.py +293 -0
- mwdust/DustMap3D.py +99 -0
- mwdust/Green15.py +83 -0
- mwdust/Green17.py +85 -0
- mwdust/Green19.py +84 -0
- mwdust/HierarchicalHealpixMap.py +224 -0
- mwdust/Marshall06.py +265 -0
- mwdust/SFD.py +72 -0
- mwdust/Sale14.py +217 -0
- mwdust/Zero.py +63 -0
- mwdust/Zucker25.py +107 -0
- mwdust/__init__.py +27 -0
- mwdust/util/__init__.py +0 -0
- mwdust/util/combine_dustmaps19.py +202 -0
- mwdust/util/download.py +32 -0
- mwdust/util/extCurves/apj398709t6_ascii.txt +51 -0
- mwdust/util/extCurves/extinction.tbl +44 -0
- mwdust/util/extCurves.py +65 -0
- mwdust/util/fortranfile.py +260 -0
- mwdust/util/healpix.py +440 -0
- mwdust/util/read_Drimmel.py +55 -0
- mwdust/util/read_SFD.py +129 -0
- mwdust/util/tools.py +31 -0
- mwdust-1.6.dist-info/METADATA +264 -0
- mwdust-1.6.dist-info/RECORD +33 -0
- mwdust-1.6.dist-info/WHEEL +5 -0
- mwdust-1.6.dist-info/licenses/AUTHORS.txt +8 -0
- mwdust-1.6.dist-info/licenses/LICENSE +27 -0
- mwdust-1.6.dist-info/top_level.txt +4 -0
- sfd_c.cp314-win_amd64.pyd +0 -0
mwdust/util/healpix.py
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import sysconfig
|
|
3
|
+
import ctypes
|
|
4
|
+
import ctypes.util
|
|
5
|
+
from numpy.ctypeslib import ndpointer
|
|
6
|
+
import numpy as np
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
# healpy number to represent bad numbers
|
|
10
|
+
UNSEEN = -1.6375e30
|
|
11
|
+
|
|
12
|
+
# Find and load the library
|
|
13
|
+
_lib = None
|
|
14
|
+
_libname = ctypes.util.find_library("healpix_c")
|
|
15
|
+
_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
|
|
16
|
+
if _libname:
|
|
17
|
+
_lib = ctypes.CDLL(_libname)
|
|
18
|
+
if _lib is None:
|
|
19
|
+
# Add top-level mwdust repository directory for pip install (-e) .,
|
|
20
|
+
# just becomes site-packages for regular install
|
|
21
|
+
paths = sys.path
|
|
22
|
+
paths.append(str(Path(__file__).parent.parent.parent.absolute()))
|
|
23
|
+
for path in [Path(p) for p in paths]:
|
|
24
|
+
if not path.is_dir():
|
|
25
|
+
continue
|
|
26
|
+
try:
|
|
27
|
+
_lib = ctypes.CDLL(str(path / f"healpix_c{_ext_suffix}"))
|
|
28
|
+
except OSError:
|
|
29
|
+
_lib = None
|
|
30
|
+
else:
|
|
31
|
+
break
|
|
32
|
+
if _lib is None:
|
|
33
|
+
raise IOError("healpix/C module not found")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# useful utilities: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
|
|
37
|
+
def check_nside(nside, nest=False):
|
|
38
|
+
"""
|
|
39
|
+
Utility function
|
|
40
|
+
|
|
41
|
+
Check if healpix map with nside is valid in general
|
|
42
|
+
"""
|
|
43
|
+
# nside can only be a power of 2 for nest, but generally less than 2**29
|
|
44
|
+
nside_arr = np.array(nside).astype(np.int64)
|
|
45
|
+
is_ok = True
|
|
46
|
+
if np.all(
|
|
47
|
+
np.logical_and(
|
|
48
|
+
np.logical_and(nside == nside_arr, np.all(np.less(0, nside))),
|
|
49
|
+
nside_arr <= 2**29,
|
|
50
|
+
)
|
|
51
|
+
):
|
|
52
|
+
if nest:
|
|
53
|
+
is_ok = (nside_arr & (nside_arr - 1)) == 0
|
|
54
|
+
else:
|
|
55
|
+
is_ok = False
|
|
56
|
+
if not is_ok:
|
|
57
|
+
raise ValueError(f"{nside} is not valid")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def check_npix(npix):
|
|
61
|
+
"""
|
|
62
|
+
Utility function
|
|
63
|
+
|
|
64
|
+
Check if total pixel number of a healpix map are valid in general
|
|
65
|
+
"""
|
|
66
|
+
# check if npix is a valid value for healpix map size
|
|
67
|
+
nside = np.sqrt(np.asarray(npix) / 12.0)
|
|
68
|
+
if nside != np.floor(nside):
|
|
69
|
+
raise ValueError(f"{npix} is not a valid value for healpix map size")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def check_ipix_nside(ipix, nside):
|
|
73
|
+
"""
|
|
74
|
+
Utility function
|
|
75
|
+
|
|
76
|
+
Check if pixel number(s) are valid in a healpix map with nside
|
|
77
|
+
"""
|
|
78
|
+
# check if all ipix are valid for a healpix map size
|
|
79
|
+
if not np.all(ipix <= nside2npix(nside)):
|
|
80
|
+
raise ValueError(f"Not all ipix are valid for such healpix map size")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def npix2nside(npix):
|
|
84
|
+
"""
|
|
85
|
+
Utility function
|
|
86
|
+
|
|
87
|
+
Give the nside parameter for the given number of pixels.
|
|
88
|
+
"""
|
|
89
|
+
check_npix(npix)
|
|
90
|
+
return int(np.sqrt(npix / 12.0))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def lonlat2thetaphi(lon, lat):
|
|
94
|
+
"""
|
|
95
|
+
NAME:
|
|
96
|
+
lonlat2thetaphi
|
|
97
|
+
PURPOSE:
|
|
98
|
+
Angular coordinates convsrion: longitude and latitude (deg) to colatitude/longitude (rad)
|
|
99
|
+
INPUT:
|
|
100
|
+
lon, lat - longitude and latitude (deg)
|
|
101
|
+
OUTPUT:
|
|
102
|
+
HISTORY:
|
|
103
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
104
|
+
"""
|
|
105
|
+
return np.pi / 2.0 - np.radians(lat), np.radians(lon)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def thetaphi2lonlat(theta, phi):
|
|
109
|
+
"""
|
|
110
|
+
NAME:
|
|
111
|
+
thetaphi2lonlat
|
|
112
|
+
PURPOSE:
|
|
113
|
+
Angular coordinates convsrion: colatitude/longitude (rad) to longitude and latitude (deg)
|
|
114
|
+
INPUT:
|
|
115
|
+
theta, phi - colatitude/longitude (rad)
|
|
116
|
+
OUTPUT:
|
|
117
|
+
lon, lat - longitude and latitude (deg)
|
|
118
|
+
HISTORY:
|
|
119
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
120
|
+
"""
|
|
121
|
+
return np.degrees(phi), 90.0 - np.degrees(theta)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def ang2pix(nside, theta, phi, nest=False, lonlat=False):
|
|
125
|
+
"""
|
|
126
|
+
NAME:
|
|
127
|
+
ang2pix
|
|
128
|
+
PURPOSE:
|
|
129
|
+
Angular coordinates to healpix map pixel number
|
|
130
|
+
INPUT:
|
|
131
|
+
nside - a integer of healpix map nside
|
|
132
|
+
theta - colatitude
|
|
133
|
+
phi - longitude
|
|
134
|
+
nest - is using NEST?
|
|
135
|
+
lonlat - input in longitude and latitude (deg)?
|
|
136
|
+
OUTPUT:
|
|
137
|
+
ipix - pixel numbers
|
|
138
|
+
HISTORY:
|
|
139
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
140
|
+
"""
|
|
141
|
+
check_nside(nside)
|
|
142
|
+
theta, phi = np.atleast_1d(np.asarray(theta)), np.atleast_1d(np.asarray(phi))
|
|
143
|
+
nstars = len(theta)
|
|
144
|
+
if lonlat:
|
|
145
|
+
theta, phi = lonlat2thetaphi(theta, phi)
|
|
146
|
+
if nest is False:
|
|
147
|
+
raise NotImplementedError("RING scheme is not avaliable for now")
|
|
148
|
+
# ang2pix_c = _lib.ang2pix_ring
|
|
149
|
+
else:
|
|
150
|
+
ang2pix_c = _lib.ang2pix_nest
|
|
151
|
+
ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE")
|
|
152
|
+
|
|
153
|
+
ang2pix_c.argtypes = [
|
|
154
|
+
ctypes.c_long,
|
|
155
|
+
ndpointer(dtype=np.float64, flags=ndarrayFlags),
|
|
156
|
+
ndpointer(dtype=np.float64, flags=ndarrayFlags),
|
|
157
|
+
ctypes.c_long,
|
|
158
|
+
]
|
|
159
|
+
ang2pix_c.restype = ctypes.POINTER(ctypes.c_longlong)
|
|
160
|
+
|
|
161
|
+
# Array requirements, first store old order
|
|
162
|
+
f_cont = [theta.flags["F_CONTIGUOUS"], phi.flags["F_CONTIGUOUS"]]
|
|
163
|
+
theta = np.require(theta, dtype=np.float64, requirements=["C", "W"])
|
|
164
|
+
phi = np.require(phi, dtype=np.float64, requirements=["C", "W"])
|
|
165
|
+
res = ang2pix_c(
|
|
166
|
+
ctypes.c_long(nside),
|
|
167
|
+
theta.astype(np.float64, order="C", copy=False),
|
|
168
|
+
phi.astype(np.float64, order="C", copy=False),
|
|
169
|
+
ctypes.c_long(nstars),
|
|
170
|
+
)
|
|
171
|
+
result = np.fromiter(res, dtype=np.int32, count=nstars)
|
|
172
|
+
|
|
173
|
+
# Reset input arrays
|
|
174
|
+
if f_cont[0]:
|
|
175
|
+
theta = np.asfortranarray(theta)
|
|
176
|
+
if f_cont[1]:
|
|
177
|
+
phi = np.asfortranarray(phi)
|
|
178
|
+
|
|
179
|
+
return result
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def ang2vec(theta, phi, lonlat=False):
|
|
183
|
+
"""
|
|
184
|
+
NAME:
|
|
185
|
+
ang2vec
|
|
186
|
+
PURPOSE:
|
|
187
|
+
Angular coordinates to unit 3-vector direction
|
|
188
|
+
INPUT:
|
|
189
|
+
theta - colatitude
|
|
190
|
+
phi - longitude
|
|
191
|
+
lonlat - input in longitude and latitude (deg)?
|
|
192
|
+
OUTPUT:
|
|
193
|
+
x, y, z - unit 3-vector direction
|
|
194
|
+
HISTORY:
|
|
195
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
196
|
+
"""
|
|
197
|
+
theta, phi = np.atleast_1d(np.asarray(theta)), np.atleast_1d(np.asarray(phi))
|
|
198
|
+
nstars = len(theta)
|
|
199
|
+
if lonlat:
|
|
200
|
+
theta, phi = lonlat2thetaphi(theta, phi)
|
|
201
|
+
|
|
202
|
+
ang2vec_c = _lib.ang2vec
|
|
203
|
+
ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE")
|
|
204
|
+
|
|
205
|
+
ang2vec_c.argtypes = [
|
|
206
|
+
ndpointer(dtype=np.float64, flags=ndarrayFlags),
|
|
207
|
+
ndpointer(dtype=np.float64, flags=ndarrayFlags),
|
|
208
|
+
ctypes.c_long,
|
|
209
|
+
]
|
|
210
|
+
ang2vec_c.restype = ctypes.POINTER(ctypes.c_double)
|
|
211
|
+
|
|
212
|
+
# Array requirements, first store old order
|
|
213
|
+
f_cont = [theta.flags["F_CONTIGUOUS"], phi.flags["F_CONTIGUOUS"]]
|
|
214
|
+
theta = np.require(theta, dtype=np.float64, requirements=["C", "W"])
|
|
215
|
+
phi = np.require(phi, dtype=np.float64, requirements=["C", "W"])
|
|
216
|
+
res = ang2vec_c(
|
|
217
|
+
theta.astype(np.float64, order="C", copy=False),
|
|
218
|
+
phi.astype(np.float64, order="C", copy=False),
|
|
219
|
+
ctypes.c_long(nstars),
|
|
220
|
+
)
|
|
221
|
+
result = np.fromiter(res, dtype=np.float64, count=nstars * 3)
|
|
222
|
+
result = result.reshape(nstars, 3)
|
|
223
|
+
|
|
224
|
+
# Reset input arrays
|
|
225
|
+
if f_cont[0]:
|
|
226
|
+
theta = np.asfortranarray(theta)
|
|
227
|
+
if f_cont[1]:
|
|
228
|
+
phi = np.asfortranarray(phi)
|
|
229
|
+
|
|
230
|
+
return result
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def pix2vec(nside, ipix, nest=False):
|
|
234
|
+
"""
|
|
235
|
+
NAME:
|
|
236
|
+
pix2vec
|
|
237
|
+
PURPOSE:
|
|
238
|
+
Pixel number to unit 3-vector direction
|
|
239
|
+
INPUT:
|
|
240
|
+
nside - a integer of healpix map nside
|
|
241
|
+
ipix - a (list) of integer of pixel number
|
|
242
|
+
nest - is using NEST?
|
|
243
|
+
OUTPUT:
|
|
244
|
+
x, y, z - unit 3-vector direction
|
|
245
|
+
HISTORY:
|
|
246
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
247
|
+
"""
|
|
248
|
+
ipix = np.asarray(ipix)
|
|
249
|
+
check_nside(nside, nest=nest)
|
|
250
|
+
check_ipix_nside(ipix, nside)
|
|
251
|
+
ipix = np.atleast_1d(ipix)
|
|
252
|
+
npix = len(ipix)
|
|
253
|
+
if nest:
|
|
254
|
+
pix2vec_c = _lib.pix2vec_nest
|
|
255
|
+
else:
|
|
256
|
+
raise NotImplementedError("RING scheme is not avaliable for now")
|
|
257
|
+
# _lib.pix2ang_ring
|
|
258
|
+
ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE")
|
|
259
|
+
# (int nside, int npix, long long int *ipix)
|
|
260
|
+
pix2vec_c.argtypes = [
|
|
261
|
+
ctypes.c_long,
|
|
262
|
+
ctypes.c_long,
|
|
263
|
+
ndpointer(dtype=np.int64, flags=ndarrayFlags),
|
|
264
|
+
]
|
|
265
|
+
pix2vec_c.restype = ctypes.POINTER(ctypes.c_double)
|
|
266
|
+
|
|
267
|
+
# Array requirements, first store old order
|
|
268
|
+
f_cont = [ipix.flags["F_CONTIGUOUS"]]
|
|
269
|
+
ipix = np.require(ipix, dtype=np.int64, requirements=["C", "W"])
|
|
270
|
+
res = pix2vec_c(
|
|
271
|
+
nside,
|
|
272
|
+
npix,
|
|
273
|
+
ipix.astype(np.int64, order="C", copy=False),
|
|
274
|
+
)
|
|
275
|
+
result = np.fromiter(res, dtype=np.float64, count=npix * 3)
|
|
276
|
+
result = result.reshape(npix, 3)
|
|
277
|
+
|
|
278
|
+
# Reset input arrays
|
|
279
|
+
if f_cont[0]:
|
|
280
|
+
ipix = np.asfortranarray(ipix)
|
|
281
|
+
|
|
282
|
+
x, y, z = result[:, 0], result[:, 1], result[:, 2]
|
|
283
|
+
return x, y, z
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def pix2ang(nside, ipix, nest=False, lonlat=False):
|
|
287
|
+
"""
|
|
288
|
+
NAME:
|
|
289
|
+
pix2ang
|
|
290
|
+
PURPOSE:
|
|
291
|
+
Pixel number to angular coordinates
|
|
292
|
+
INPUT:
|
|
293
|
+
nside - a integer of healpix map nside
|
|
294
|
+
ipix - a (list) of integer of pixel number
|
|
295
|
+
nest - is using NEST?
|
|
296
|
+
lonlat - output in longitude and latitude (deg)?
|
|
297
|
+
OUTPUT:
|
|
298
|
+
theta, phi - angular coordinates
|
|
299
|
+
HISTORY:
|
|
300
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
301
|
+
"""
|
|
302
|
+
ipix = np.asarray(ipix)
|
|
303
|
+
check_nside(nside, nest=nest)
|
|
304
|
+
check_ipix_nside(ipix, nside)
|
|
305
|
+
ipix = np.atleast_1d(ipix)
|
|
306
|
+
npix = len(ipix)
|
|
307
|
+
if nest:
|
|
308
|
+
pix2ang_c = _lib.pix2ang_nest
|
|
309
|
+
else:
|
|
310
|
+
raise NotImplementedError("RING scheme is not avaliable for now")
|
|
311
|
+
# _lib.pix2ang_ring
|
|
312
|
+
ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE")
|
|
313
|
+
# (int nside, int npix, long long int *ipix)
|
|
314
|
+
pix2ang_c.argtypes = [
|
|
315
|
+
ctypes.c_long,
|
|
316
|
+
ctypes.c_long,
|
|
317
|
+
ndpointer(dtype=np.int64, flags=ndarrayFlags),
|
|
318
|
+
]
|
|
319
|
+
pix2ang_c.restype = ctypes.POINTER(ctypes.c_double)
|
|
320
|
+
|
|
321
|
+
# Array requirements, first store old order
|
|
322
|
+
f_cont = [ipix.flags["F_CONTIGUOUS"]]
|
|
323
|
+
ipix = np.require(ipix, dtype=np.int64, requirements=["C", "W"])
|
|
324
|
+
res = pix2ang_c(
|
|
325
|
+
nside,
|
|
326
|
+
npix,
|
|
327
|
+
ipix.astype(np.int64, order="C", copy=False),
|
|
328
|
+
)
|
|
329
|
+
result = np.fromiter(res, dtype=np.float64, count=npix * 2)
|
|
330
|
+
result = result.reshape(npix, 2)
|
|
331
|
+
|
|
332
|
+
# Reset input arrays
|
|
333
|
+
if f_cont[0]:
|
|
334
|
+
ipix = np.asfortranarray(ipix)
|
|
335
|
+
|
|
336
|
+
theta, phi = result[:, 0], result[:, 1]
|
|
337
|
+
|
|
338
|
+
if lonlat:
|
|
339
|
+
return thetaphi2lonlat(theta, phi)
|
|
340
|
+
else:
|
|
341
|
+
return theta, phi
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def nside2pixarea(nside):
|
|
345
|
+
"""
|
|
346
|
+
NAME:
|
|
347
|
+
nside2pixarea
|
|
348
|
+
PURPOSE:
|
|
349
|
+
Get area of a pixel for a healpix map with nside
|
|
350
|
+
INPUT:
|
|
351
|
+
nside - a integer of healpix map nside
|
|
352
|
+
OUTPUT:
|
|
353
|
+
pixarea - a float of healpix map pixel area
|
|
354
|
+
HISTORY:
|
|
355
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
356
|
+
"""
|
|
357
|
+
return np.pi / (3 * nside**2)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def nside2npix(nside):
|
|
361
|
+
"""
|
|
362
|
+
NAME:
|
|
363
|
+
nside2npix
|
|
364
|
+
PURPOSE:
|
|
365
|
+
Get how many pixel for a healpix map with nside
|
|
366
|
+
INPUT:
|
|
367
|
+
nside - a integer of healpix map nside
|
|
368
|
+
OUTPUT:
|
|
369
|
+
npix - a integer of number of healpix map pixel
|
|
370
|
+
HISTORY:
|
|
371
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
372
|
+
"""
|
|
373
|
+
return 12 * nside * nside
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def ud_grade(
|
|
377
|
+
map_in,
|
|
378
|
+
nside_plot,
|
|
379
|
+
pess=False,
|
|
380
|
+
order_in="RING",
|
|
381
|
+
order_out=None,
|
|
382
|
+
power=None,
|
|
383
|
+
dtype=None,
|
|
384
|
+
):
|
|
385
|
+
"""
|
|
386
|
+
NAME:
|
|
387
|
+
dust_vals_disk
|
|
388
|
+
PURPOSE:
|
|
389
|
+
Upgrade or degrade healpix map
|
|
390
|
+
INPUT:
|
|
391
|
+
map_in - healpix map to be upgraded or degraded
|
|
392
|
+
nside_plot - nside of the output map wanted
|
|
393
|
+
OUTPUT:
|
|
394
|
+
map_out - arrays of upgraded or degraded map(s)
|
|
395
|
+
HISTORY:
|
|
396
|
+
2023-03-01 - Written - Henry Leung (Toronto)
|
|
397
|
+
"""
|
|
398
|
+
# check if arguements are implemented
|
|
399
|
+
if order_in != "NEST" or (order_out is not None and order_out != "NEST"):
|
|
400
|
+
raise NotImplementedError(
|
|
401
|
+
"order_in and order_out for RING scheme is not implemented for now"
|
|
402
|
+
)
|
|
403
|
+
if power is not None:
|
|
404
|
+
raise NotImplementedError("power is not implemented for now")
|
|
405
|
+
if pess is not False:
|
|
406
|
+
raise NotImplementedError("pess=True is not implemented for now")
|
|
407
|
+
if dtype is not False:
|
|
408
|
+
raise NotImplementedError(
|
|
409
|
+
"dtype is implemented for now, output map always has the same dtype as input map"
|
|
410
|
+
)
|
|
411
|
+
check_nside(nside_plot, nest=order_in != "RING")
|
|
412
|
+
map_in = np.asarray(map_in)
|
|
413
|
+
|
|
414
|
+
num_of_map = len(np.atleast_2d(map_in))
|
|
415
|
+
if num_of_map != 1:
|
|
416
|
+
raise ValueError("This function only support one map at each time")
|
|
417
|
+
|
|
418
|
+
nside_in = npix2nside(len(map_in))
|
|
419
|
+
npix_in = nside2npix(nside_in)
|
|
420
|
+
npix_out = nside2npix(nside_in)
|
|
421
|
+
|
|
422
|
+
if nside_plot > nside_in: # upgrade
|
|
423
|
+
rat2 = npix_out // npix_in
|
|
424
|
+
fact = np.ones(rat2, dtype=map_in.dtype)
|
|
425
|
+
map_out = np.outer(map_in, fact).reshape(npix_out)
|
|
426
|
+
elif nside_plot < nside_in: # degrade
|
|
427
|
+
rat2 = npix_in // npix_out
|
|
428
|
+
mr = map_in.reshape(npix_out, rat2)
|
|
429
|
+
goods = ~(np.isclose(mr, UNSEEN) | (~np.isfinite(mr)) | (~np.isnan(mr)))
|
|
430
|
+
map_out = np.sum(mr * goods, axis=1)
|
|
431
|
+
nhit = goods.sum(axis=1)
|
|
432
|
+
map_out[nhit != 0] = map_out[nhit != 0] / nhit[nhit != 0]
|
|
433
|
+
try:
|
|
434
|
+
map_out[nhit == 0] = UNSEEN
|
|
435
|
+
except OverflowError:
|
|
436
|
+
pass
|
|
437
|
+
else:
|
|
438
|
+
map_out = map_in
|
|
439
|
+
|
|
440
|
+
return map_out
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import os, os.path
|
|
2
|
+
import numpy
|
|
3
|
+
import struct
|
|
4
|
+
from mwdust.util import fortranfile
|
|
5
|
+
_DRIMMELDIR= os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
|
6
|
+
'drimmeldata')
|
|
7
|
+
def readDrimmelAll():
|
|
8
|
+
out= {}
|
|
9
|
+
allFilenames= ['avgrid.dat','avori2.dat','rf_allsky.dat',
|
|
10
|
+
'avdisk.dat','avloc.dat','avspir.dat',
|
|
11
|
+
'avdloc.dat','avori.dat']
|
|
12
|
+
for filename in allFilenames:
|
|
13
|
+
f = fortranfile.FortranFile(os.path.join(_DRIMMELDIR,filename))
|
|
14
|
+
nx, ny, nz= 151, 151, 51
|
|
15
|
+
if 'avori2' in filename:
|
|
16
|
+
nx, ny, nz= 101, 201, 51
|
|
17
|
+
elif 'avori' in filename:
|
|
18
|
+
nx, ny, nz= 76, 151, 51
|
|
19
|
+
elif 'avloc' in filename:
|
|
20
|
+
nx, ny, nz= 101, 201, 51
|
|
21
|
+
elif 'avdloc' in filename:
|
|
22
|
+
nx, ny, nz= 31, 31, 51
|
|
23
|
+
if not 'rf_allsky' in filename:
|
|
24
|
+
out[filename.split('.')[0]]=\
|
|
25
|
+
f.readReals(prec='f').reshape((nz,ny,nx)).T
|
|
26
|
+
else:
|
|
27
|
+
#Need to do more work to read this file
|
|
28
|
+
rec= f._read_exactly(4) #Read the header
|
|
29
|
+
rec= f._read_exactly(4*393216)
|
|
30
|
+
num = len(rec)//struct.calcsize('i')
|
|
31
|
+
out_rf_pixnum= numpy.array(struct.unpack(f.ENDIAN+str(num)+'i',
|
|
32
|
+
rec),dtype='int')
|
|
33
|
+
rec= f._read_exactly(4*393216)
|
|
34
|
+
num = len(rec)//struct.calcsize('i')
|
|
35
|
+
out_rf_comp= numpy.array(struct.unpack(f.ENDIAN+str(num)+'i',
|
|
36
|
+
rec),dtype='int')
|
|
37
|
+
rec= f._read_exactly(4*393216)
|
|
38
|
+
num = len(rec)//struct.calcsize('f')
|
|
39
|
+
out_rf_glon= numpy.array(struct.unpack(f.ENDIAN+str(num)+'f',
|
|
40
|
+
rec),dtype=numpy.float32)
|
|
41
|
+
rec= f._read_exactly(4*393216)
|
|
42
|
+
num = len(rec)//struct.calcsize('f')
|
|
43
|
+
out_rf_glat= numpy.array(struct.unpack(f.ENDIAN+str(num)+'f',
|
|
44
|
+
rec),dtype=numpy.float32)
|
|
45
|
+
rec= f._read_exactly(4*393216)
|
|
46
|
+
num = len(rec)//struct.calcsize('f')
|
|
47
|
+
out_rf= numpy.array(struct.unpack(f.ENDIAN+str(num)+'f',
|
|
48
|
+
rec),dtype=numpy.float32)
|
|
49
|
+
out['rf_pixnum']= out_rf_pixnum
|
|
50
|
+
out['rf_comp']= out_rf_comp
|
|
51
|
+
out['rf_glon']= out_rf_glon
|
|
52
|
+
out['rf_glat']= out_rf_glat
|
|
53
|
+
out['rf']= out_rf
|
|
54
|
+
f.close()
|
|
55
|
+
return out
|
mwdust/util/read_SFD.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import sysconfig
|
|
3
|
+
import ctypes
|
|
4
|
+
import ctypes.util
|
|
5
|
+
from numpy.ctypeslib import ndpointer
|
|
6
|
+
import os, os.path
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import numpy
|
|
9
|
+
import platform
|
|
10
|
+
import tqdm
|
|
11
|
+
from mwdust.util.download import dust_dir
|
|
12
|
+
|
|
13
|
+
WIN32 = platform.system() == "Windows"
|
|
14
|
+
# Find and load the library
|
|
15
|
+
_lib = None
|
|
16
|
+
_libname = ctypes.util.find_library("sfd_c")
|
|
17
|
+
PY3 = sys.version > "3"
|
|
18
|
+
if PY3: # pragma: no cover
|
|
19
|
+
_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
|
|
20
|
+
else:
|
|
21
|
+
_ext_suffix = sysconfig.get_config_var("SO")
|
|
22
|
+
if _libname:
|
|
23
|
+
_lib = ctypes.CDLL(_libname)
|
|
24
|
+
if _lib is None:
|
|
25
|
+
# Add top-level mwdust repository directory for pip install (-e) .,
|
|
26
|
+
# just becomes site-packages for regular install
|
|
27
|
+
paths = sys.path
|
|
28
|
+
paths.append(str(Path(__file__).parent.parent.parent.absolute()))
|
|
29
|
+
for path in [Path(p) for p in paths]:
|
|
30
|
+
if not path.is_dir():
|
|
31
|
+
continue
|
|
32
|
+
try:
|
|
33
|
+
_lib = ctypes.CDLL(str(path / f"sfd_c{_ext_suffix}"))
|
|
34
|
+
except OSError:
|
|
35
|
+
_lib = None
|
|
36
|
+
else:
|
|
37
|
+
break
|
|
38
|
+
if _lib is None:
|
|
39
|
+
raise IOError("SFD/C module not found")
|
|
40
|
+
|
|
41
|
+
# MAP path names
|
|
42
|
+
ebvFileN = os.path.join(dust_dir, "maps", "SFD_dust_4096_ngp.fits")
|
|
43
|
+
ebvFileS = os.path.join(dust_dir, "maps", "SFD_dust_4096_sgp.fits")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def read_SFD_EBV(glon, glat, interp=True, noloop=False, verbose=False, pbar=True):
|
|
47
|
+
"""
|
|
48
|
+
NAME:
|
|
49
|
+
read_SFD_EBV
|
|
50
|
+
PURPOSE:
|
|
51
|
+
read an E(B-V) value from the Schlegel, Finkbeiner, & Davis (1998) maps
|
|
52
|
+
INPUT:
|
|
53
|
+
glon - Galactic longitude (deg), can be an array
|
|
54
|
+
glat - Galactic latitude (deg), can be an array
|
|
55
|
+
interp= (True) if True, interpolate using the nearest pixels
|
|
56
|
+
noloop= (False) if True, don't loop through the glons
|
|
57
|
+
verbose= (False) if True, be verbose
|
|
58
|
+
pbar= (True) if True, show progress bar
|
|
59
|
+
OUTPUT:
|
|
60
|
+
array of E(B-V) from Schlegel, Finkbeiner, & Davis (1998)
|
|
61
|
+
HISTORY:
|
|
62
|
+
2013-11-23 - Written - Bovy (IAS)
|
|
63
|
+
"""
|
|
64
|
+
# Parse input
|
|
65
|
+
if isinstance(glon, (int, float, numpy.float32, numpy.float64)):
|
|
66
|
+
glon = numpy.array([glon])
|
|
67
|
+
if isinstance(glat, (int, float, numpy.float32, numpy.float64)):
|
|
68
|
+
glat = numpy.array([glat])
|
|
69
|
+
|
|
70
|
+
nstar = len(glon)
|
|
71
|
+
if nstar > 1 and pbar:
|
|
72
|
+
pbar = tqdm.tqdm(total=nstar, leave=False)
|
|
73
|
+
pbar_func_ctype = ctypes.CFUNCTYPE(None)
|
|
74
|
+
pbar_c = pbar_func_ctype(pbar.update)
|
|
75
|
+
else: # pragma: no cover
|
|
76
|
+
pbar_c = None
|
|
77
|
+
|
|
78
|
+
# Set up the C code
|
|
79
|
+
ndarrayFlags = ("C_CONTIGUOUS", "WRITEABLE")
|
|
80
|
+
evalFunc = _lib.lambert_getval
|
|
81
|
+
evalFunc.argtypes = [
|
|
82
|
+
ctypes.c_char_p,
|
|
83
|
+
ctypes.c_char_p,
|
|
84
|
+
ctypes.c_long,
|
|
85
|
+
ndpointer(dtype=numpy.float32, flags=ndarrayFlags),
|
|
86
|
+
ndpointer(dtype=numpy.float32, flags=ndarrayFlags),
|
|
87
|
+
ctypes.c_int,
|
|
88
|
+
ctypes.c_int,
|
|
89
|
+
ctypes.c_int,
|
|
90
|
+
ndpointer(dtype=numpy.int32, flags=ndarrayFlags),
|
|
91
|
+
ctypes.c_void_p,
|
|
92
|
+
]
|
|
93
|
+
evalFunc.restype = ctypes.POINTER(ctypes.c_float)
|
|
94
|
+
|
|
95
|
+
# Array requirements, first store old order
|
|
96
|
+
f_cont = [glon.flags["F_CONTIGUOUS"], glat.flags["F_CONTIGUOUS"]]
|
|
97
|
+
glon = numpy.require(glon, dtype=numpy.float64, requirements=["C", "W"])
|
|
98
|
+
glat = numpy.require(glat, dtype=numpy.float64, requirements=["C", "W"])
|
|
99
|
+
err = numpy.require(0, dtype=numpy.int32, requirements=["C", "W"])
|
|
100
|
+
|
|
101
|
+
# Check that the filename isn't too long for the SFD code
|
|
102
|
+
if len(ebvFileN.encode("ascii")) >= 120 or len(ebvFileS.encode("ascii")) >= 120:
|
|
103
|
+
raise RuntimeError(
|
|
104
|
+
f"The path of the file that contains the SFD dust maps is too long ({len(ebvFileN.encode('ascii'))}); please shorten the path of DUST_DIR"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
res = evalFunc(
|
|
108
|
+
ctypes.c_char_p(ebvFileN.encode("ascii")),
|
|
109
|
+
ctypes.c_char_p(ebvFileS.encode("ascii")),
|
|
110
|
+
ctypes.c_long(nstar),
|
|
111
|
+
glon.astype(numpy.float32, order="C", copy=False),
|
|
112
|
+
glat.astype(numpy.float32, order="C", copy=False),
|
|
113
|
+
ctypes.c_int(interp),
|
|
114
|
+
ctypes.c_int(noloop),
|
|
115
|
+
ctypes.c_int(verbose),
|
|
116
|
+
err,
|
|
117
|
+
pbar_c,
|
|
118
|
+
)
|
|
119
|
+
if numpy.any(err == -10):
|
|
120
|
+
raise KeyboardInterrupt("Interrupted by CTRL-C (SIGINT)")
|
|
121
|
+
result = numpy.fromiter(res, dtype=float, count=nstar)
|
|
122
|
+
|
|
123
|
+
# Reset input arrays
|
|
124
|
+
if f_cont[0]:
|
|
125
|
+
glon = numpy.asfortranarray(glon)
|
|
126
|
+
if f_cont[1]:
|
|
127
|
+
glat = numpy.asfortranarray(glat)
|
|
128
|
+
|
|
129
|
+
return result
|
mwdust/util/tools.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# mwutils.util.tools: some general tools
|
|
4
|
+
#
|
|
5
|
+
###############################################################################
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def cos_sphere_dist(sintheta,costheta,
|
|
9
|
+
sinphi,cosphi,
|
|
10
|
+
sintheta_o,costheta_o,
|
|
11
|
+
sinphi_o,cosphi_o):
|
|
12
|
+
"""
|
|
13
|
+
NAME:
|
|
14
|
+
cos_sphere_dist
|
|
15
|
+
PURPOSE:
|
|
16
|
+
computes the cosine of the spherical distance between two
|
|
17
|
+
points on the sphere
|
|
18
|
+
INPUT:
|
|
19
|
+
theta - polar angle [0,pi]
|
|
20
|
+
phi - azimuth [0,2pi]
|
|
21
|
+
theta_o - polar angle of center of the disk
|
|
22
|
+
phi_o - azimuth of the center of the disk
|
|
23
|
+
OUTPUT:
|
|
24
|
+
spherical distance
|
|
25
|
+
HISTORY:
|
|
26
|
+
2010-04-29 -Written - Bovy (NYU)
|
|
27
|
+
"""
|
|
28
|
+
return (sintheta*sintheta_o
|
|
29
|
+
*(cosphi_o*cosphi+
|
|
30
|
+
sinphi_o*sinphi)+
|
|
31
|
+
costheta_o*costheta)
|