mwdust 1.6__cp314-cp314-macosx_11_0_arm64.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.

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
@@ -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)