示例#1
0
	def decompose(self,l_edges,keep_fourier=False):

		"""
		Decomposes the shear map into its E and B modes components and returns the respective power spectral densities at the specified multipole moments

		:param l_edges: Multipole bin edges
		:type l_edges: array

		:param keep_fourier: If set to True, holds the Fourier transforms of the E and B mode maps into the E and B attributes of the ShearMap instance
		:type keep_fourier: bool. 

		:returns: :returns: tuple -- (l -- array,P_EE,P_BB,P_EB -- arrays) = (multipole moments, EE,BB power spectra and EB cross power)

		>>> test_map = ShearMap.load("shear.fit",format=load_fits_default_shear)
		>>> l_edges = np.arange(300.0,5000.0,200.0)
		>>> l,EE,BB,EB = test_map.decompose(l_edges)

		"""

		#Perform Fourier transforms
		ft_data1 = rfft2(self.data[0])
		ft_data2 = rfft2(self.data[1])

		#Compute frequencies
		lx = rfftfreq(ft_data1.shape[0])
		ly = fftfreq(ft_data1.shape[0])

		#Safety check
		assert len(lx)==ft_data1.shape[1]
		assert len(ly)==ft_data1.shape[0]

		#Compute sines and cosines of rotation angles
		l_squared = lx[np.newaxis,:]**2 + ly[:,np.newaxis]**2
		l_squared[0,0] = 1.0

		sin_2_phi = 2.0 * lx[np.newaxis,:] * ly[:,np.newaxis] / l_squared
		cos_2_phi = (lx[np.newaxis,:]**2 - ly[:,np.newaxis]**2) / l_squared

		#Compute E and B components
		ft_E = cos_2_phi * ft_data1 + sin_2_phi * ft_data2
		ft_B = -1.0 * sin_2_phi * ft_data1 + cos_2_phi * ft_data2

		ft_E[0,0] = 0.0
		ft_B[0,0] = 0.0

		assert ft_E.shape == ft_B.shape
		assert ft_E.shape == ft_data1.shape

		#Compute and return power spectra
		l = 0.5*(l_edges[:-1] + l_edges[1:])
		P_EE = _topology.rfft2_azimuthal(ft_E,ft_E,self.side_angle.to(deg).value,l_edges)
		P_BB = _topology.rfft2_azimuthal(ft_B,ft_B,self.side_angle.to(deg).value,l_edges)
		P_EB = _topology.rfft2_azimuthal(ft_E,ft_B,self.side_angle.to(deg).value,l_edges)

		if keep_fourier:
			self.fourier_E = ft_E
			self.fourier_B = ft_B

		return l,P_EE,P_BB,P_EB
示例#2
0
    def powerSpectrum(self, l_edges):
        """
		Measures the power spectrum of the convergence map at the multipole moments specified in the input

		:param l_edges: Multipole bin edges
		:type l_edges: array

		:returns: tuple -- (l -- array,Pl -- array) = (multipole moments, power spectrum at multipole moments)

		:raises: AssertionError if l_edges are not provided

		>>> test_map = ConvergenceMap.load("map.fit")
		>>> l_edges = np.arange(200.0,5000.0,200.0)
		>>> l,Pl = test_map.powerSpectrum(l_edges)

		"""

        assert not self._masked, "Power spectrum calculation for masked maps is not allowed yet!"
        assert l_edges is not None

        if self.side_angle.unit.physical_type == "length":
            raise NotImplementedError(
                "Power spectrum measurement not implemented yet if side physical unit is length!"
            )

        l = 0.5 * (l_edges[:-1] + l_edges[1:])

        #Calculate the Fourier transform of the map with numpy FFT
        ft_map = rfft2(self.data)

        #Compute the power spectrum with the C backend implementation
        power_spectrum = _topology.rfft2_azimuthal(
            ft_map, ft_map,
            self.side_angle.to(deg).value, l_edges)

        #Output the power spectrum
        return l, power_spectrum
示例#3
0
    def decompose(self, l_edges, keep_fourier=False):
        """
		Decomposes the shear map into its E and B modes components and returns the respective power spectral densities at the specified multipole moments

		:param l_edges: Multipole bin edges
		:type l_edges: array

		:param keep_fourier: If set to True, holds the Fourier transforms of the E and B mode maps into the E and B attributes of the ShearMap instance
		:type keep_fourier: bool. 

		:returns: :returns: tuple -- (l -- array,P_EE,P_BB,P_EB -- arrays) = (multipole moments, EE,BB power spectra and EB cross power)

		>>> test_map = ShearMap.load("shear.fit",format=load_fits_default_shear)
		>>> l_edges = np.arange(300.0,5000.0,200.0)
		>>> l,EE,BB,EB = test_map.decompose(l_edges)

		"""

        #Perform Fourier transforms
        ft_data1 = rfft2(self.data[0])
        ft_data2 = rfft2(self.data[1])

        #Compute frequencies
        lx = rfftfreq(ft_data1.shape[0])
        ly = fftfreq(ft_data1.shape[0])

        #Safety check
        assert len(lx) == ft_data1.shape[1]
        assert len(ly) == ft_data1.shape[0]

        #Compute sines and cosines of rotation angles
        l_squared = lx[np.newaxis, :]**2 + ly[:, np.newaxis]**2
        l_squared[0, 0] = 1.0

        sin_2_phi = 2.0 * lx[np.newaxis, :] * ly[:, np.newaxis] / l_squared
        cos_2_phi = (lx[np.newaxis, :]**2 - ly[:, np.newaxis]**2) / l_squared

        #Compute E and B components
        ft_E = cos_2_phi * ft_data1 + sin_2_phi * ft_data2
        ft_B = -1.0 * sin_2_phi * ft_data1 + cos_2_phi * ft_data2

        ft_E[0, 0] = 0.0
        ft_B[0, 0] = 0.0

        assert ft_E.shape == ft_B.shape
        assert ft_E.shape == ft_data1.shape

        #Compute and return power spectra
        l = 0.5 * (l_edges[:-1] + l_edges[1:])
        P_EE = _topology.rfft2_azimuthal(ft_E, ft_E,
                                         self.side_angle.to(deg).value,
                                         l_edges)
        P_BB = _topology.rfft2_azimuthal(ft_B, ft_B,
                                         self.side_angle.to(deg).value,
                                         l_edges)
        P_EB = _topology.rfft2_azimuthal(ft_E, ft_B,
                                         self.side_angle.to(deg).value,
                                         l_edges)

        if keep_fourier:
            self.fourier_E = ft_E
            self.fourier_B = ft_B

        return l, P_EE, P_BB, P_EB
示例#4
0
    def cross(self, other, statistic="power_spectrum", **kwargs):
        """
		Measures a cross statistic between maps

		:param other: The other convergence map
		:type other: ConvergenceMap instance

		:param statistic: the cross statistic to measure (default is 'power_spectrum')
		:type statistic: string or callable

		:param kwargs: the keyword arguments are passed to the statistic (when callable)
		:type kwargs: dict.

		:returns: tuple -- (l -- array,Pl -- array) = (multipole moments, cross power spectrum at multipole moments) if the statistic is the power spectrum, otherwise whatever statistic() returns on call

		:raises: AssertionError if the other map has not the same shape as the input one

		>>> test_map = ConvergenceMap.load("map.fit",format=load_fits_default_convergence)
		>>> other_map = ConvergenceMap.load("map2.fit",format=load_fits_default_convergence)
		
		>>> l_edges = np.arange(200.0,5000.0,200.0)
		>>> l,Pl = test_map.cross(other_map,l_edges=l_edges)

		"""
        #The other map must be of the same type as this one
        assert isinstance(other, self.__class__)

        if statistic == "power_spectrum":

            assert not (
                self._masked or other._masked
            ), "Power spectrum calculation for masked maps is not allowed yet!"

            if self.side_angle.unit.physical_type == "length":
                raise NotImplementedError(
                    "Power spectrum measurement not implemented yet if side physical unit is length!"
                )

            assert "l_edges" in kwargs.keys()
            l_edges = kwargs["l_edges"]

            assert l_edges is not None
            l = 0.5 * (l_edges[:-1] + l_edges[1:])

            assert self.side_angle == other.side_angle
            assert self.data.shape == other.data.shape

            #Calculate the Fourier transform of the maps with numpy FFTs
            ft_map1 = rfft2(self.data)
            ft_map2 = rfft2(other.data)

            #Compute the cross power spectrum with the C backend implementation
            cross_power_spectrum = _topology.rfft2_azimuthal(
                ft_map1, ft_map2,
                self.side_angle.to(deg).value, l_edges)

            #Output the cross power spectrum
            return l, cross_power_spectrum

        else:

            return statistic(self, other, **kwargs)