def wl_peak_counts( self, nbins: int, field_conversion: str, of: str = "orig", limits: Optional[tuple] = None, ) -> pd.DataFrame: """ Signal peak counts. This is used commonly used in weak-lensing, but it doesn't need to stop there... """ if field_conversion == "normalize": _map = self.data[of] - np.mean(self.skymap.data[of]) else: _map = self.data[of] if limits is None: lower_bound = np.percentile(self.data[of], 5) # np.min(self.data[of]) upper_bound = np.percentile(self.data[of], 95) # np.max(self.data[of]) else: lower_bound = min(limits) upper_bound = max(limits) map_bins = np.arange(lower_bound, upper_bound, (upper_bound - lower_bound) / nbins) _map = ConvergenceMap(data=_map, angle=self._opening_angle * un.deg) _kappa, _pos = _map.locatePeaks(map_bins) _hist, _kappa = np.histogram(_kappa, bins=nbins, density=False) _kappa = (_kappa[1:] + _kappa[:-1]) / 2 peak_counts_dic = {"kappa": _kappa, "counts": _hist} peak_counts_df = pd.DataFrame(data=peak_counts_dic) return peak_counts_df
def from_array( cls, skymap: Type[SkyArray], on: str, multipoles: Union[List[float], np.array] = np.arange(200.0, 50000.0, 200.0), ) -> "PowerSpectrum2D": """ Args: """ _map = ConvergenceMap(data=skymap.data[on], angle=skymap.opening_angle * un.deg) l, P = _map.powerSpectrum(multipoles) return cls(l, P)
def from_sky( cls, skymap: Type[SkyArray], on: str, bin_dsc: dict, kernel_width: float = 5, direction: int = 1, filters: bool = True, ) -> "Dipoles": """ Find peaks on the dipole signal map. It is assumed that the convergence maps were created with astrild.rays.visuals.map and filter with: I) high-pass II) DGD3 III) low-pass gaussian filters. Args: kernel_width: Smoothing kernel with [arcmin] Returns: """ if filters is True: skymap = cls._filter(skymap, kernel_width, direction) thresholds = cls._get_convergence_thresholds( sky_array=skymap.data[bin_dsc["on"]], nbins=bin_dsc["nbins"]) _map = ConvergenceMap(data=skymap.data[on], angle=skymap.opening_angle * un.deg) deltaT, pos_deg = _map.locatePeaks(thresholds) deltaT, pos_deg = cls._remove_peaks_crossing_edge( skymap.npix, skymap.opening_angle, kernel_width, deltaT, pos_deg) assert len(deltaT) != 0, "No peaks" peak_dir = { "deltaT": deltaT, "x_deg": pos_deg[:, 0], "y_deg": pos_deg[:, 1], } # find significance of peaks peak_dir["snr"] = cls._signal_to_noise_ratio(peak_dir["deltaT"], _map.data) peak_dir["x_pix"] = np.rint(peak_dir["x_deg"] * skymap.npix / skymap.opening_angle).astype(int) peak_dir["y_pix"] = np.rint(peak_dir["y_deg"] * skymap.npix / skymap.opening_angle).astype(int) peak_df = pd.DataFrame(data=peak_dir) # attrs is experimental and may change without warning. peak_df.attrs["map_file"] = skymap.map_file peak_df.attrs["filters"] = filters peak_df.attrs["kernel_width"] = kernel_width return cls.from_dataframe(peak_df)
def test_convergence_direct(): z_final = 2.0 #Start a bucket of light rays from these positions b = np.linspace(0.0,tracer.lens[0].side_angle.to(deg).value,512) xx,yy = np.meshgrid(b,b) pos = np.array([xx,yy]) * deg #Compute the convergence conv = tracer.convergenceDirect(pos,z=z_final) #Wrap into a ConvergenceMap and visualize conv_map = ConvergenceMap(data=conv,angle=tracer.lens[0].side_angle) conv_map.visualize(colorbar=True) conv_map.savefig("convergence_direct.png")
def gaussian( img: np.ndarray, theta: un.quantity.Quantity, theta_i: Optional[un.quantity.Quantity] = None, fwhm_i: Optional[un.quantity.Quantity] = None, **kwargs, ) -> np.ndarray: """ Gaussian filter for low-pass filter to get rid of long-wavelenths (e.g. CMB when interested in ISW-RS signals). Note: It is based on lenstools.ConvergenceMap.smooth function, but it has nothing in particular todo with convergence maps, and can be used for any other map, e.g. isw_rs. Args: img: partial sky-map theta: edge-lenght of field-of-view [deg] theta_i: sigma of gaussian used to indicated smoothing kernel width, [arcmin] fwhm_i: Full-Width-Half-Maximum (fwhm) of gaussian used to indicated smoothing kernel width, [arcmin] Returns: """ img = ConvergenceMap(data=img, angle=theta.to(un.deg)) fwhm_i = fwhm_i.to(un.arcmin).value if theta_i is None and fwhm_i is None: raise ValueError(f"Either theta_i or fwhm_i must be set for smoothing scale.") elif theta_i is None: sigma_i = Filters.fwhm_to_sigma(fwhm_i) else: sigma_i = theta_i sigma_i *= un.arcmin if len(img.data) < 500: # for image with less than 500^2 images real-space is faster img = img.smooth( scale_angle=sigma_i, kind="gaussian", **kwargs ) else: # for larger images FFT is optimal img = img.smooth( scale_angle=sigma_i, kind="gaussianFFT", **kwargs ) return img.data
def find_peaks( self, on: str, field_conversion: str, thresholds_dsc: dict, snr_sigma: Optional[float] = None, save: bool = False, ) -> None: """ Find peaks on convergence map. It is assumed that the convergence maps were created with astrild.rays.visuals.map and have appropriate smoothing and galaxy shape noise. Args: Returns: """ self.on = on if field_conversion == "normalize": _map = self.skymap.data[on] - np.mean(self.skymap.data[on]) else: _map = self.skymap.data[on] thresholds = self._get_convergence_thresholds(**thresholds_dsc) _map = ConvergenceMap(data=_map, angle=self.skymap.opening_angle * un.deg) _peaks = {} _peaks["kappa"], _peaks["pos"] = _map.locatePeaks(thresholds) _peaks["kappa"], _peaks["pos"] = self._remove_peaks_crossing_edge( **_peaks) assert len(_peaks["kappa"]) != 0, "No peaks" # find significance of peaks _peaks["snr"] = self._signal_to_noise_ratio(_peaks["kappa"], _map.data, snr_sigma) self.peaks = _peaks if save: # IO.save() pass
def map_stats(cosmo_tomo_cone): '''for fits file fn, generate ps, peaks, minima, pdf, MFs fn: input file name, including full path tomo=1, 2,..5: int, for tomographic bins cone=1, 2,..5: int, for light cones''' if len(cosmo_tomo_cone) == 3: cosmo, tomo, cone = cosmo_tomo_cone ipz = '' else: cosmo, tomo, cone, ipz = cosmo_tomo_cone ################################## ### generate random see, such that it is the same for all cosmology ### but different for tomo and cone ################################## if cosmo == 'cov': iseed = int(10000 + cone * 10 + tomo) out_dir = dir_cov fn = cov_fn_gen(tomo, cone) elif cosmo == 'bias': iseed = int(20000 + cone * 10 + tomo) #20000 out_dir = dir_bias fn = bias_fn_gen(tomo, ipz, cone) else: ## all cosmologies if cosmo[-1] == 'a': iseed = int(cone * 10 + tomo) ## cone goes from 1 to 25, so 10 to 250 #else:# elif cosmo[ -1] == 'f': ##'f' starts with a different seed from the 'a' cosmology iseed = int(1000 + cone * 10 + tomo) out_dir = dir_cosmos fn = cosmo_fn_gen(cosmo, tomo, cone) print(fn) ################################## #### check if the map and comoputed stats files are there ################################## ############ check fits file exist if not os.path.isfile(fn): print(fn, 'fits file does not exist \n') return 0 out_fn_arr = [ out_dir + cosmo + '_tomo%i_cone%s_s%i.npy' % (tomo, cone, theta_g) for theta_g in theta_g_arr ] ############# check if stats files exist; if yes, skip computation if np.prod(array([os.path.isfile(out_fn) for out_fn in out_fn_arr])): ### check if the product of boolean elements in the array = 1 (meaning for all smoothing scales) print(fn, 'stats files exist; skip computation.\n') return 0 ### all files already exist, no need to process ################################## ########## map operations ################################## imap = fits.open(fn)[0].data ## open the file ### add noise seed(iseed) noise_map = np.random.normal(loc=0.0, scale=sigma_pix_arr[tomo - 1], size=(map_pix, map_pix)) kappa_map = ConvergenceMap(data=imap + noise_map, angle=map_side_deg) noise_map = 0 ## release the memory ### compute stats ## 3 smoothing ## 9 cols: ell, ps, kappa, peak, minima, pdf, v0, v1, v2 ps_noiseless = ConvergenceMap(data=imap, angle=map_side_deg).powerSpectrum(l_edges) ps_unsmoothed = kappa_map.powerSpectrum( l_edges) ## power spectrum should be computed on unsmoothed maps s = 0 for theta_g in theta_g_arr: out_fn = out_dir + cosmo + '%s_tomo%i_cone%s_s%i.npy' % (ipz, tomo, cone, theta_g) imap = kappa_map.smooth(theta_g * u.arcmin) out = zeros(shape=(11, Nbin)) kappa_bins = kappa_bin_edges[s][tomo - 1] ps = imap.powerSpectrum(l_edges) peak = imap.peakCount(kappa_bins) minima = ConvergenceMap(data=-imap.data, angle=map_side_deg).peakCount(kappa_bins) pdf = imap.pdf(kappa_bins) mfs = imap.minkowskiFunctionals(kappa_bins) out[0] = ps[0] out[1] = ps_noiseless[1] out[2] = ps_unsmoothed[1] out[3] = ps[1] out[4] = peak[0] out[5] = peak[1] out[6] = minima[1][::-1] out[7] = pdf[1] out[8] = mfs[1] out[9] = mfs[2] out[10] = mfs[3] save(out_fn, out) ### save the file s += 1
def test_ray_simple(): z_final = 2.0 start = time.time() last_timestamp = start #Start a bucket of light rays from these positions b = np.linspace(0.0,tracer.lens[0].side_angle.to(deg).value,512) xx,yy = np.meshgrid(b,b) pos = np.array([xx,yy]) * deg #Trace the rays fin = tracer.shoot(pos,z=z_final) now = time.time() logging.info("Ray tracing completed in {0:.3f}s".format(now-last_timestamp)) last_timestamp = now #Build the deflection plane dfl = DeflectionPlane(fin.value-pos.value,angle=tracer.lens[0].side_angle,redshift=tracer.redshift[-1],cosmology=tracer.lens[0].cosmology,unit=pos.unit) #Compute shear and convergence conv = dfl.convergence() shear = dfl.shear() omega = dfl.omega() now = time.time() logging.info("Weak lensing calculations completed in {0:.3f}s".format(now-last_timestamp)) last_timestamp = now #Finally visualize the result conv.visualize(colorbar=True) conv.savefig("raytraced_convergence.png") omega.visualize(colorbar=True) omega.savefig("raytraced_omega.png") shear.visualize(colorbar=True) shear.savefig("raytraced_shear.png") #We want to plot the power spectrum of the raytraced maps fig,ax = plt.subplots() l_edges = np.arange(200.0,10000.0,100.0) l,Pl = conv.powerSpectrum(l_edges) ax.plot(l,l*(l+1)*Pl/(2.0*np.pi),label="From ray positions") #And why not, E and B modes too figEB,axEB = plt.subplots() l,EEl,BBl,EBl = shear.decompose(l_edges) axEB.plot(l,l*(l+1)*EEl/(2.0*np.pi),label="EE From ray positions",color="black") axEB.plot(l,l*(l+1)*BBl/(2.0*np.pi),label="BB From ray positions",color="green") axEB.plot(l,l*(l+1)*np.abs(EBl)/(2.0*np.pi),label="EB From ray positions",color="blue") #Now compute the shear and convergence raytracing the actual jacobians (more expensive computationally cause it computes the jacobian at every step) finJ = tracer.shoot(pos,z=z_final,kind="jacobians") conv = ConvergenceMap(data=1.0-0.5*(finJ[0]+finJ[3]),angle=conv.side_angle) shear = ShearMap(data=np.array([0.5*(finJ[3]-finJ[0]),-0.5*(finJ[1]+finJ[2])]),angle=shear.side_angle) now = time.time() logging.info("Jacobian ray tracing completed in {0:.3f}s".format(now-last_timestamp)) last_timestamp = now #Finally visualize the result conv.visualize(colorbar=True) conv.savefig("raytraced_convergence_jacobian.png") shear.visualize(colorbar=True) shear.savefig("raytraced_shear_jacobian.png") #We want to plot the power spectrum of the raytraced maps l,Pl = conv.powerSpectrum(l_edges) ax.plot(l,l*(l+1)*Pl/(2.0*np.pi),label="From Jacobians") ax.set_xlabel(r"$l$") ax.set_ylabel(r"$l(l+1)P_l/2\pi$") ax.set_xscale("log") ax.set_yscale("log") ax.legend() fig.savefig("raytracing_conv_power.png") #And why not, E and B modes too axEB.plot(l,l*(l+1)*EEl/(2.0*np.pi),label="EE From jacobians",color="black",linestyle="--") axEB.plot(l,l*(l+1)*BBl/(2.0*np.pi),label="BB From jacobians",color="green",linestyle="--") axEB.plot(l,l*(l+1)*np.abs(EBl)/(2.0*np.pi),label="EB From jacobians",color="blue",linestyle="--") axEB.set_xlabel(r"$l$") axEB.set_ylabel(r"$l(l+1)P_l/2\pi$") axEB.set_xscale("log") axEB.set_yscale("log") axEB.legend(loc="lower right",prop={"size":10}) figEB.savefig("raytracing_shear_power.png") now = time.time() logging.info("Total runtime {0:.3f}s".format(now-start))
def power_spectrum(self, im): """Calculate power spectrum.""" conv_map = ConvergenceMap(im, angle=u.degree * 3.5) l, Pl = conv_map.powerSpectrum(self.bins) return Pl