Exemplo n.º 1
0
    def to_pixel(self, Nside=None, Npix=None, dtype=None, out=None):
        """
        ::
        
            >>> insh = harmonic_sphere_map(0, 0, 4)
            >>> insh.to_pixel(8)
            Pixel sphere map (ring-ordered, Nside=8, Npix=768)

        Convert a uniform map::        
            >>> shmap = harmonic_sphere_map([[23], [0, 0], [0, 0, 0]])
            >>> pixmap = shmap.to_pixel(8); pixmap
            Pixel sphere map (ring-ordered, Nside=8, Npix=768)
            >>> np.allclose(pixmap, 23.0 / np.sqrt(4*np.pi))
            True

        One can convert multiple maps at once::

            >>> M = shmap
            >>> M = np.hstack((M[:,None], M[:,None], M[:,None], M[:,None]))
            >>> M = np.dstack((M, M))
            >>> M = harmonic_sphere_map(M, 0, 2); M
            (4, 2)-stack of brief complex harmonic sphere maps with l=0..2 (6 coefficients)
            >>> x = M.to_pixel(4); x
            (4, 2)-stack of pixel sphere maps (ring-ordered, Nside=4, Npix=192)
            >>> np.allclose(x, 23.0 / np.sqrt(4*np.pi))
            True

        """
        self._check_not_pretending()
        if self.format is not COMPLEX_BRIEF:
            return self.to_complex().to_pixel(Nside, Npix, dtype, out)
        if Nside is None:
            if Npix is None: raise ValueError("Provide Nside or Npix")
            Nside = npix2nside(Npix)
        if Npix is None:
            Npix = nside2npix(Nside)
        if dtype is None:
            dtype = self.dtype
        dtype = to_real_dtype(dtype)
        # for now, only double...
        assert dtype == np.float64
        
        size = self.shape[1:]
        if out is None:
            out = np.empty((Npix,) + size, dtype, order='F')

        # Todo: Optimize -- have lmin in complexpacked2complexmatrix
        if self.lmin == 0:
            source = self
        else:
            source = np.empty((l_to_lm(self.lmax + 1),) + size, complex_dtype, order='F')
            source[:l_to_lm(self.lmin)] = 0
            source[l_to_lm(self.lmin):] = self

        for mapidx in np.ndindex(*size):
            idx = (slice(None),) + mapidx
            alm_matrix = mapdatautils.alm_complexpacked2complexmatrix(source[idx])
            mapdatautils.alm2map(Nside, alm_matrix, out=out[idx])

        return _PixelSphereMap(out, pixel_order='ring')
Exemplo n.º 2
0
    def rotate(self, psi, theta, phi):
        """
        Returns a rotated copy of self. O(lmax^3).

        ::
        
            >>> M = harmonic_sphere_map([[1, 0], [1, 0, 0]], lmin=1)
            >>> R = M.rotate(0, np.pi, 0); R
            Brief complex harmonic sphere map with l=1..2 (5 coefficients)
            >>> np.round(R.to_array(), 4)
            array([-1.+0.j, -0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j])

        One can convert multiple maps at once::

        TODO write tests

        """
        from healpix import rotate_alm_d
        self._check_not_pretending()

        if psi == 0 and theta == 0 and phi == 0:
            return self.copy()
        
        if self.format is not COMPLEX_BRIEF:
            x = self.to_complex().rotate(psi, theta, phi)
            if self.format is REAL_FULL:
                return x.to_real()
            else:
                assert False

        size = self.shape[1:]

        # Todo: Optimize -- have lmin in complexpacked2complexmatrix
        out = np.empty((l_to_lm(self.lmax + 1),) + size, complex_dtype, order='F')
        out[:l_to_lm(self.lmin), ...] = 0
        out[l_to_lm(self.lmin):, ...] = self

        alm_matrix = np.empty((1, self.lmax + 1, self.lmax + 1), complex_dtype, order='F')

        for mapidx in np.ndindex(*size):
            idx = (slice(None),) + mapidx
            mapdatautils.alm_complexpacked2complexmatrix(out[idx], alm_matrix[0,:,:])
            rotate_alm_d(self.lmax, alm_matrix, psi, theta, phi)
            mapdatautils.alm_complexmatrix2complexpacked(alm_matrix[0,:,:], out[idx])
        out = out[l_to_lm(self.lmin):, ...]
        return _HarmonicSphereMap(out, self.lmin, self.lmax, COMPLEX_BRIEF)
Exemplo n.º 3
0
def simulate_harmonic_sphere_maps(lmin, lmax, size=None, state=np.random):
    """
    Simulates standard normal maps in spherical harmonic space.
    
    INPUT:
    
     - ``n`` - The number of maps to simulate

    EXAMPLES::

    >>> simulate_harmonic_sphere_maps(0, 3)
    Brief complex harmonic sphere map with l=0..3 (10 coefficients)
    >>> simulate_harmonic_sphere_maps(2, 3, size=10)
    (10,)-stack of brief complex harmonic sphere maps with l=2..3 (7 coefficients)

    
    """
    if size is None:
        size = ()
    if not isinstance(size, tuple):
        size = (size,)
    real_coefs = (lmax+1)**2
    complex_coefs = l_to_lm(lmax+1)
    lmin_lm = l_to_lm(lmin)
    Zreal = state.standard_normal((real_coefs,) + size).astype(real_dtype)
    Zcomplex = np.empty((complex_coefs,) + size, complex_dtype)
    Zcomplex
    if len(size) > 1:
        raise NotImplementedError()
    # TODO: Have lmin in realpacked2complexpacked
    # For now, just slice away output for 0:lmin
    if size == ():
        mapdatautils.alm_realpacked2complexpacked(Zreal, out=Zcomplex)
    else:
        for i in range(size[0]):
            mapdatautils.alm_realpacked2complexpacked(Zreal[:,i], out=Zcomplex[:,i])
    return _HarmonicSphereMap(Zcomplex[l_to_lm(lmin):, ...], lmin, lmax, COMPLEX_BRIEF)
Exemplo n.º 4
0
def harmonic_sphere_map(data, lmin=0, lmax=None, is_complex=None, is_brief=None):
    """
    Constructs a sphere map in harmonic space.

    EXAMPLES::
    
        >>> M = harmonic_sphere_map([[0], [1, 3+1j], [1, 1, 1], [1, 1, 1, 1]]); M
        Brief complex harmonic sphere map with l=0..3 (10 coefficients)
        >>> M2 = harmonic_sphere_map([[1, 1, 1, 1]], lmin=3); M2
        Brief complex harmonic sphere map with l=3..3 (4 coefficients)
        
        >>> harmonic_sphere_map([[0], [1 + 1j, 3+1j]])
        Traceback (most recent call last):
            ...
        ValueError: Entries on m=0-positions must be real
        >>> harmonic_sphere_map(np.dstack((M[:,None,None], M[:,None,None])))
        (1, 2)-stack of brief complex harmonic sphere maps with l=0..3 (10 coefficients)
        >>> M = harmonic_sphere_map(2, 0, 100); M
        Brief complex harmonic sphere map with l=0..100 (5151 coefficients)
        >>> np.sin(M) + 34 * M
        Brief complex harmonic sphere map with l=0..100 (5151 coefficients)

    Real coefficients are also supported::

        >>> M = harmonic_sphere_map([[0], [-1, 1, 3], [-1, -2, 3, 4, 5]]); M
        Real harmonic sphere map with l=0..2 (9 coefficients)

    Scalar initialization::

        >>> harmonic_sphere_map(10, 2, 4)
        Brief complex harmonic sphere map with l=2..4 (12 coefficients)
    """
    if np.isscalar(data):
        if is_complex is None:
            is_complex = True
        if lmax is None:
            raise ValueError('Cannot infer lmax from data')
        data = (np.ones(l_to_lm(lmax + 1, is_complex) - l_to_lm(lmin, is_complex),
                        dtype=complex_dtype if is_complex else real_dtype, order='F') *
                float(data))
    elif isinstance(data, list):
        # Need at least two nesting levels of lists
        if (not isinstance(data[0], list) or isinstance(data[0][0], list)):
            raise ValueError("Please provide coefficients as [[a00], [a10, a11], ...]")
        if lmax is None:
            lmax = len(data) + lmin - 1

        
        if is_complex is None:
            # Auto-detect is_complex from data
            if lmin == 0 and len(data) == 1:
                is_complex = True # only a00 given; assume is_complex
            elif lmin == 0:
                is_complex = (len(data[1]) == 2)
            else:
                is_complex = len(data[0]) == lmin + 1
        
        num_coefs = l_to_lm(lmax + 1, is_complex) - l_to_lm(lmin, is_complex)
        buf = np.zeros(num_coefs, dtype=complex_dtype if is_complex else real_dtype, order='F')

        i = 0
        for l, coefs_for_l in zip(range(lmin, lmax+1), data):
            n = l+1 if is_complex else 2*l + 1
            if len(coefs_for_l) != n:
                raise ValueError("Wrong number of coefficients for l=%d" % l)
            if coefs_for_l[0].imag != 0:
                raise ValueError("Entries on m=0-positions must be real")
            buf[i:i+n] = coefs_for_l
            i += n
        data = buf
    else:
        if is_complex is None:
            is_complex = True
        data = np.asfortranarray(data, dtype=complex_dtype if is_complex else real_dtype)
        lmax_wanted = num_alm_to_lmax(l_to_lm(lmin, is_complex) + data.shape[0], is_complex)
        if lmax is not None and lmax != lmax_wanted:
            raise ValueError('lmax given does not match data lmax')
        if lmax is None:
            lmax = lmax_wanted
    if is_brief is None:
        is_brief = is_complex
    if is_complex:
        format = COMPLEX_BRIEF if is_brief else COMPLEX_FULL
    else:
        if is_brief:
            raise ValueError()
        format = REAL_FULL
    return _HarmonicSphereMap(data, lmin=lmin, lmax=lmax, format=format)
Exemplo n.º 5
0
    def to_harmonic(self, lmin, lmax, use_weights=True,
                    weights_transform=None):
        """
        ::
        
            >>> inpix = pixel_sphere_map(0, 4)
            >>> inpix.to_harmonic(0, 8)
            Brief complex harmonic sphere map with l=0..8 (45 coefficients)

        Convert a uniform map. First elements should be 12*sqrt(4 pi),
        the remaining elements 0::
        
            >>> N = pixel_sphere_map(Nside=8, data=12)
            >>> x = N.to_harmonic(0, 16)
            >>> np.allclose(x[0], 12 * np.sqrt(4*np.pi))
            True
            >>> np.allclose(x[1:], 0, atol=1e-1)
            True

        One can convert multiple maps at once:
            >>> N = np.hstack((N[:,None], N[:,None], N[:,None], N[:,None]))
            >>> N = np.dstack((N, N))
            >>> N = pixel_sphere_map(data=N, Nside=8); N
            (4, 2)-stack of pixel sphere maps (ring-ordered, Nside=8, Npix=768)
            >>> x = N.to_harmonic(0, 16); x
            (4, 2)-stack of brief complex harmonic sphere maps with l=0..16 (153 coefficients)
            >>> np.allclose(x[0,:,:], 12 * np.sqrt(4*np.pi))
            True
            >>> np.allclose(x[1:,:,:], 0, atol=.1)
            True



        """
        if self.pixel_order == 'nested':
            return self.to_ring().to_harmonic(lmin, lmax)
        assert self.pixel_order == 'ring'
        self._check_not_pretending()
        dtype = to_complex_dtype(self.dtype)
        # for now, only double...
        assert dtype == np.complex128

        size = self.shape[1:]
        numalm = l_to_lm(lmax + 1)
        alm_matrix_buf = np.empty((lmax + 1, lmax + 1), complex_dtype, order='F')
        alm = np.empty((numalm,) + size, complex_dtype, order='F')
        if use_weights:
            weight_ring_temperature = healpix_res.weight_ring(Nside=self.Nside)[0,:]
            if weights_transform is not None:
                weight_ring_temperature = weights_transform(weight_ring_temperature)
        else:
            weight_ring_temperature = np.ones(2 * self.Nside)

        for mapidx in np.ndindex(*size):
            idx = (slice(None),) + mapidx
            map = self[idx]
            mapdatautils.map2alm(lmax, map, weight_ring_temperature, out=alm_matrix_buf)
            mapdatautils.alm_complexmatrix2complexpacked(alm_matrix_buf, out=alm[idx])

        # Trim away portion up to lmin
        alm = alm[l_to_lm(lmin):,...]
        return _HarmonicSphereMap(alm, lmin, lmax, COMPLEX_BRIEF)