def __init__(self, comm=MPI.COMM_WORLD, nnz=1, dtype=np.float64, nside=16): if libsharp is None: raise RuntimeError('libsharp not available') self.data = None self._comm = comm self._nnz = nnz self._dtype = dtype self._nest = False self._nside = nside self._cache = Cache() self._libsharp_grid, self._local_ring_indices = distribute_rings( self._nside, self._comm.rank, self._comm.size) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo( self._nside, self._local_ring_indices.astype(np.int64)) local_npix = self._libsharp_grid.local_size() self._local_pixels = self._cache.create( "local_pixels", shape=(local_npix,), type=np.int64) expand_pix(startpix, ringpix, local_npix, self._local_pixels) self.data = self._cache.create( "data", shape=(local_npix, self._nnz), type=self._dtype)
def __init__(self, comm=MPI.COMM_WORLD, nnz=1, dtype=np.float64, nside=16): if libsharp is None: raise RuntimeError('libsharp not available') self.data = None self._comm = comm self._nnz = nnz self._dtype = dtype self._nest = False self._nside = nside self._cache = Cache() self._libsharp_grid, self._local_ring_indices = distribute_rings( self._nside, self._comm.rank, self._comm.size) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo( self._nside, self._local_ring_indices.astype(np.int64)) local_npix = self._libsharp_grid.local_size() self._local_pixels = self._cache.create("local_pixels", shape=(local_npix, ), type=np.int64) expand_pix(startpix, ringpix, local_npix, self._local_pixels) self.data = self._cache.create("data", shape=(local_npix, self._nnz), type=self._dtype)
def distribute_rings_libsharp(mpi_comm, nside, lmax): """Create a libsharp map distribution based on rings Build a libsharp grid object to distribute a HEALPix map balancing North and South distribution of rings to achieve the best performance on Harmonic Transforms Returns the grid object and the pixel indices array in RING ordering Parameters --------- mpi_comm : mpi4py.MPI.Comm mpi4py communicator nside : int nside of the map Returns ------- grid : libsharp.healpix_grid libsharp object that includes metadata about HEALPix distributed rings local_pix : np.ndarray integer array of local pixel indices in the current MPI process in RING ordering """ import libsharp nrings = 4 * nside - 1 # four missing pixels # ring indices are 1-based ring_indices_emisphere = np.arange(2 * nside, dtype=np.int32) + 1 local_ring_indices = ring_indices_emisphere[mpi_comm.rank::mpi_comm.size] # to improve performance, symmetric rings north/south need to be in the same rank # therefore we use symmetry to create the full ring indexing if local_ring_indices[-1] == 2 * nside: # has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1]) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1]) libsharp_grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(int)) local_npix = libsharp_grid.local_size() local_pixels = expand_pix(startpix, ringpix, local_npix).astype(int) local_m_indices = np.arange(mpi_comm.rank, lmax + 1, mpi_comm.size, dtype=np.int32) libsharp_order = libsharp.packed_real_order(lmax, ms=local_m_indices) return local_pixels, libsharp_grid, libsharp_order
def polar_profile(m, nest=False): """Obtain the marginalized polar profile of sky map. Parameters ---------- m : np.ndarray The input HEALPix array. nest : bool, default=False Indicates whether the input sky map is in nested rather than ring-indexed HEALPix coordinates (default: ring). Returns ------- theta : np.ndarray The polar angles (i.e., the colatitudes) of the isolatitude rings. m_int : np.ndarray The normalized probability density, such that `np.trapz(m_int, theta)` is approximately `np.sum(m)`. """ npix = len(m) nside = hp.npix2nside(npix) nrings, = hp.pix2ring(nside, np.asarray([npix])) startpix, ringpix, costheta, sintheta, _ = hp.ringinfo( nside, np.arange(1, nrings)) if nest: m = hp.reorder(m, n2r=True) theta = np.arccos(costheta) m_int = np.asarray([ m[i:i + j].sum() * stheta * 0.5 * npix / j for i, j, stheta in zip(startpix, ringpix, sintheta) ]) return theta, m_int
def polar_profile(m, nest=False): """Obtain the marginalized polar profile of sky map. Parameters ---------- m : np.ndarray The input HEALPix array. nest : bool, default=False Indicates whether the input sky map is in nested rather than ring-indexed HEALPix coordinates (default: ring). Returns ------- theta : np.ndarray The polar angles (i.e., the colatitudes) of the isolatitude rings. m_int : np.ndarray The normalized probability density, such that `np.trapz(m_int, theta)` is approximately `np.sum(m)`. """ npix = len(m) nside = hp.npix2nside(npix) nrings, = hp.pix2ring(nside, np.asarray([npix])) startpix, ringpix, costheta, sintheta, _ = hp.ringinfo( nside, np.arange(1, nrings)) if nest: m = hp.reorder(m, n2r=True) theta = np.arccos(costheta) m_int = np.asarray( [m[i:i+j].sum() * stheta * 0.5 * npix / j for i, j, stheta in zip(startpix, ringpix, sintheta)]) return theta, m_int
) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1] ) print("rank", rank, "n_rings", len(local_ring_indices)) if not mpi: local_ring_indices = None grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(np.int64)) local_npix = grid.local_size() def expand_pix(startpix, ringpix, local_npix): """Turn first pixel index and number of pixel in full array of pixels to be optimized with cython or numba """ local_pix = np.empty(local_npix, dtype=np.int64) i = 0 for start, num in zip(startpix, ringpix): local_pix[i:i+num] = np.arange(start, start+num) i += num return local_pix
for ifov, fov in enumerate(fovs): raAvgmap = truemap.copy() raAvgFOVmap = truemap.copy() decHi = lat + fov * .5 decLo = lat - fov * .5 if decHi >= 90.: decHi = 90. if decLo <= -90.: decLo = -90. fovPix = 0. ringLo = int(4 * nside * (90. - decHi) / 180.) ringHi = int(4 * nside * (90. - decLo) / 180.) for ring in range(1, 4 * nside + 1): ringInfo = h.ringinfo(nside, np.array([ring])) startpix = ringInfo[0] ringpix = ringInfo[1] avg = sum(truemap[startpix:startpix + ringpix] / ringpix) for pix in range(startpix, startpix + ringpix): raAvgmap[pix] -= avg # Limit FOV if ring in range(ringLo, ringHi + 1): raAvgFOVmap[pix] = raAvgmap[pix] fovPix += 1 else: raAvgFOVmap[pix] = 0. cov = 1. * fovPix / len(raAvgmap) covs[ilat][ifov][dipole] = cov
# has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1]) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1]) print("rank", rank, "n_rings", len(local_ring_indices)) if not mpi: local_ring_indices = None grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(np.int64)) local_npix = grid.local_size() def expand_pix(startpix, ringpix, local_npix): """Turn first pixel index and number of pixel in full array of pixels to be optimized with cython or numba """ local_pix = np.empty(local_npix, dtype=np.int64) i = 0 for start, num in zip(startpix, ringpix): local_pix[i:i + num] = np.arange(start, start + num) i += num return local_pix