Skip to content

Commit 6ad2234

Browse files
author
Serena Giardiello
committed
adding codes for planck source subtraction
1 parent 5e4952d commit 6ad2234

File tree

5 files changed

+410
-5
lines changed

5 files changed

+410
-5
lines changed

project/SO/pISO/python/dust/global_dust.dict

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ sq_win_alms_dir = "/scratch/c.spxsg6/iso/dust/sq_win_alms"
2020
cov_dir = "/scratch/c.spxsg6/iso/dust/covariances"
2121
montecarlo_dir = "/scratch/c.spxsg6/iso/dust/montecarlo"
2222
noise_alms_dir = "/scratch/c.spxsg6/iso/dust/noise_alms"
23+
catalog_dir = "/scratch/c.spxsg6/iso/dust/catalogs"
24+
2325

2426
deconvolve_pixwin = True
2527
pixwin_Planck = {"pix": 'HEALPIX', "nside": 2048}
@@ -57,13 +59,15 @@ passband_dir_planck = release_dir + "pspipe/for_planck/passbands/"
5759
freq_info_Planck_f143 = {"freq_tag": 143, "passband": passband_dir_planck + "passband_npipe_f143.dat"}
5860
freq_info_Planck_f353 = {"freq_tag": 353, "passband": passband_dir_planck + "passband_npipe_f353.dat"}
5961

60-
planck_fits_beam_path = release_dir + "pspipe/for_planck/beams/"
62+
planck_fits_beam_path = release_dir + "pspipe/for_planck/beams"
63+
64+
beam_dir = "/scratch/c.spxsg6/iso/dust/beams"
6165

62-
beam_T_Planck_f143 = "beams/npipe_DR6_AxB/bl_T_npipe_DR6_143Ax143B.dat" # Get from running pipeline_dust.yml
63-
beam_T_Planck_f353 = "beams/npipe_DR6_AxB/bl_T_npipe_DR6_353Ax353B.dat"
66+
beam_T_Planck_f143 = beam_dir + '/npipe_DR6_AxB/bl_T_npipe_DR6_AxB_143Ax143B.dat' # Get from running pipeline_dust.yml
67+
beam_T_Planck_f353 = beam_dir + '/npipe_DR6_AxB/bl_T_npipe_DR6_AxB_353Ax353B.dat'
68+
beam_pol_Planck_f143 = beam_dir + '/npipe_DR6_AxB/bl_pol_npipe_DR6_AxB_143Ax143B.dat'
69+
beam_pol_Planck_f353 = beam_dir + '/npipe_DR6_AxB/bl_pol_npipe_DR6_AxB_353Ax353B.dat'
6470

65-
beam_pol_Planck_f143 = "beams/npipe_DR6_AxB/bl_pol_npipe_DR6_143Ax143B.dat"
66-
beam_pol_Planck_f353 = "beams/npipe_DR6_AxB/bl_pol_npipe_DR6_353Ax353B.dat"
6771

6872
include_beam_chromaticity_effect_in_best_fit = False
6973

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""
2+
Iterates over the sources in the MF ACT catalog
3+
and plot a submap centered on individual sources
4+
of the residual map (i.e. the source subtracted map)
5+
"""
6+
from pspy import so_map, pspy_utils, so_map, so_mpi, so_dict
7+
import numpy as np
8+
import pandas as pd
9+
import os, sys
10+
import pspipe
11+
from pspipe_utils import log
12+
13+
14+
d = so_dict.so_dict()
15+
d.read_from_file(sys.argv[1])
16+
log = log.get_logger(**d)
17+
18+
map_dir = "planck_projected"
19+
20+
planck_version = d["planck_version"]
21+
22+
out_dir = d["plots_base_dir"] + "/source_sub_check"
23+
pspy_utils.create_directory(out_dir)
24+
25+
# Read catalog
26+
cat_file = d["source_catalog"]
27+
cat = pd.read_table(cat_file, escapechar="#", sep="\s+")
28+
cat = cat.shift(1, axis=1)
29+
30+
# Sort by flux at 150 GHz
31+
cat.sort_values(by="flux_T2", inplace=True, ascending=False)
32+
33+
# Cuts
34+
snr_cut = 5
35+
flux_cut = 150 #mJy
36+
n_src_max = 100
37+
38+
mask = (cat.snr_T >= snr_cut) & (cat.flux_T2 >= flux_cut)
39+
cat = cat[mask]
40+
41+
ra_list = [ra for i, ra in enumerate(cat.ra) if i < n_src_max]
42+
dec_list = [dec for i, dec in enumerate(cat.dec) if i < n_src_max]
43+
44+
n = len(ra_list)
45+
log.info(f"Display {n} sources with 150 GHz flux >= {flux_cut:.1f} mJy and SNR >= {snr_cut:.1f}")
46+
47+
if planck_version == "legacy":
48+
map_root = "HFI_SkyMap_2048_R3.01_halfmission-{}_f{}_map.fits"
49+
map_splits = [1, 2]
50+
51+
if planck_version == "npipe":
52+
map_root = "npipe6v20{}_f{}_map.fits"
53+
map_splits = ['A', 'B']
54+
55+
map_freqs = [100, 143, 217]
56+
57+
for freq in map_freqs:
58+
for split in map_splits:
59+
60+
map_file = map_root.format(split, freq)
61+
map_path = f"{map_dir}/{map_file}"
62+
63+
m = so_map.read_map(map_path)
64+
m_srcfree = so_map.read_map(map_path.replace("map.fits", "map_srcfree.fits"))
65+
66+
so_mpi.init(True)
67+
subtasks = so_mpi.taskrange(imin=0, imax=n-1)
68+
69+
for task in subtasks:
70+
71+
log.info(f"Task {task} of {n-1}")
72+
73+
ra, dec = ra_list[task], dec_list[task]
74+
75+
ra0, ra1 = ra - 1., ra + 1.
76+
dec0, dec1 = dec - 1., dec + 1.
77+
78+
box = so_map.get_box(ra0, ra1, dec0, dec1)
79+
sub = so_map.get_submap_car(m, box)
80+
sub_srcfree = so_map.get_submap_car(m_srcfree, box)
81+
82+
sub.plot(file_name=f"{out_dir}/{planck_version}_f{freq}_{split}_{task:03d}",
83+
color_range=[250, 100, 100],
84+
ticks_spacing_car=0.6
85+
)
86+
sub_srcfree.plot(file_name=f"{out_dir}/{planck_version}_srcfree_f{freq}_{split}_{task:03d}",
87+
color_range=[250, 100, 100],
88+
ticks_spacing_car=0.6
89+
)
90+
91+
92+
# Generate HTML file for visualization
93+
ids_src = np.arange(n)
94+
multistep_path = os.path.join(os.path.dirname(pspipe.__file__), "js")
95+
os.system(f"cp {multistep_path}/multistep2.js {out_dir}/")
96+
97+
maps = [f"{freq}_{split}" for freq in map_freqs for split in map_splits]
98+
99+
filename = f"{out_dir}/{planck_version}_sources.html"
100+
g = open(filename, mode='w')
101+
g.write('<html>\n')
102+
g.write('<head>\n')
103+
g.write(f'<title> Source subtraction for Planck {planck_version} </title>\n')
104+
g.write(f'<script src="multistep2.js"></script>\n')
105+
g.write('<script> add_step("src_id", ["c","v"]) </script> \n')
106+
g.write('<script> add_step("srcfree", ["j","k"]) </script> \n')
107+
g.write('<script> add_step("map", ["a","z"]) </script> \n')
108+
g.write('</head> \n')
109+
g.write('<body> \n')
110+
g.write(f'<h1> Source subtraction for Planck {planck_version} </h1>')
111+
g.write('<p> This webpage display the 100 brightest sources at 150 GHz, with a flux higher than 150mJy detected with a SNR > 5. </p> \n')
112+
g.write('<p> You can switch between sources (c/v), between the map and source free map (j/k) and between the maps (a/z). </p> \n')
113+
g.write('<div class=src_id> \n')
114+
for src_id in ids_src:
115+
116+
g.write('<div class=srcfree>\n')
117+
for type in ["", "_srcfree"]:
118+
119+
prefix = f"{planck_version}{type}"
120+
g.write('<div class=map>\n')
121+
for map_name in maps:
122+
123+
freq, split = map_name.split("_")
124+
file_name = f"{prefix}_f{freq}_{split}_{src_id:03d}_T.png"
125+
g.write(f'<h2> {freq} GHz split {split} - {prefix} [Source no {src_id:03d}] </p> \n')
126+
g.write('<img src="' + file_name + '" width="40%" /> \n')
127+
g.write('</div>\n')
128+
129+
g.write('</div>\n')
130+
g.write('</div> \n')
131+
g.write('</body> \n')
132+
g.write('</html> \n')
133+
g.close()
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
"""
2+
Read the Planck beam files and save the beam as tables in .dat files.
3+
both the intensity, the polarisation and the leakage beam files
4+
"""
5+
6+
import sys
7+
8+
import numpy as np
9+
import pylab as plt
10+
import healpy as hp
11+
from astropy.io import fits
12+
from pspy import pspy_utils, so_dict
13+
from pspipe_utils import log
14+
15+
d = so_dict.so_dict()
16+
d.read_from_file(sys.argv[1])
17+
log = log.get_logger(**d)
18+
19+
planck_fits_beam_path = d["planck_fits_beam_path"]
20+
beam_dir_d = d["beam_dir"]
21+
22+
freqs = [100, 143, 217, 353]
23+
lmax = 3030
24+
lmax_for_plot = 2000
25+
releases = ["legacy", "npipe_DR6_AxB"]
26+
27+
for release in releases:
28+
29+
beam_dir = beam_dir_d + f"/{release}"
30+
pspy_utils.create_directory(beam_dir)
31+
32+
for freq in freqs:
33+
34+
if release == "npipe_DR6_AxB":
35+
s1, s2 = "A", "B"
36+
if freq != 353:
37+
Wl = fits.open(f"{planck_fits_beam_path}/QP_dr6_pa6_f150/Wl_npipe6v20_{freq}{s1}x{freq}{s2}.fits")
38+
else:
39+
print(f"use full sky beam for {freq} GHz")
40+
Wl = fits.open(f"{planck_fits_beam_path}/quickpol/Wl_npipe6v20_{freq}{s1}x{freq}{s2}.fits")
41+
42+
if release == "legacy":
43+
s1, s2 = "hm1", "hm2"
44+
if freq != 353:
45+
Wl = fits.open(f"{planck_fits_beam_path}/BeamWf_HFI_R3.01/Wl_R3.01_plikmask_{freq}{s1}x{freq}{s2}.fits")
46+
else:
47+
print(f"use full sky beam for {freq} GHz")
48+
Wl = fits.open(f"{planck_fits_beam_path}/BeamWf_HFI_R3.01/Wl_R3.01_fullsky_{freq}{s1}x{freq}{s2}.fits")
49+
50+
l = np.arange(lmax)
51+
52+
Wl_TT_2_TT = Wl[1].data["TT_2_TT"][0, :lmax]
53+
Wl_EE_2_EE = Wl[2].data["EE_2_EE"][0, :lmax]
54+
55+
# extract beam and polarised beam
56+
bl_T = np.sqrt(Wl_TT_2_TT)
57+
bl_pol = np.sqrt(Wl_EE_2_EE)
58+
59+
plt.figure(figsize=(12,8))
60+
plt.subplot(2, 1, 1)
61+
plt.plot(l[:lmax_for_plot], bl_T[:lmax_for_plot], label="temperature beam", color="lightblue")
62+
plt.errorbar(l[:lmax_for_plot], bl_pol[:lmax_for_plot], fmt="+", markevery=50, label="pol beam", color="red")
63+
plt.ylabel(r"$ B_{\ell}$", fontsize=14)
64+
plt.legend()
65+
plt.subplot(2, 1, 2)
66+
plt.plot(l[:lmax_for_plot], (bl_T[:lmax_for_plot] / bl_pol[:lmax_for_plot]) ** 2)
67+
plt.ylabel(r"$ (B^{\rm T}_{\ell}/B^{\rm pol}_{\ell})^{2} $", fontsize=14)
68+
plt.xlabel(r"$\ell$", fontsize=14)
69+
plt.savefig(f"{beam_dir}/beam_{freq}.png")
70+
plt.clf()
71+
plt.close()
72+
73+
np.savetxt(f"{beam_dir}/bl_T_{release}_{freq}{s1}x{freq}{s2}.dat", np.transpose([l, bl_T]))
74+
np.savetxt(f"{beam_dir}/bl_pol_{release}_{freq}{s1}x{freq}{s2}.dat", np.transpose([l, bl_pol]))
75+
76+
# extract leakage beam
77+
Wl_TE_2_TE = Wl[4].data["TE_2_TE"][0, :lmax]
78+
gamma_TE = Wl[1].data["TT_2_TE"][0, :lmax] / Wl_TE_2_TE
79+
gamma_ET = Wl[1].data["TT_2_ET"][0, :lmax] / Wl_TE_2_TE
80+
81+
gamma_TB = Wl[1].data["TT_2_TB"][0, :lmax] / Wl_TE_2_TE
82+
gamma_BT = Wl[1].data["TT_2_BT"][0, :lmax] / Wl_TE_2_TE
83+
84+
plt.figure(figsize=(12,8))
85+
plt.title(f"{freq} GHz x {freq} GHz", fontsize=14)
86+
plt.errorbar(l[:lmax_for_plot], 100 * gamma_TE[:lmax_for_plot], label=r"%s $T_{\rm %s} \ x \ E_{\rm %s}$" % (release, s1, s2), color="blue", fmt="-", markevery=50)
87+
plt.errorbar(l[:lmax_for_plot], 100 * gamma_ET[:lmax_for_plot], label=r"%s $T_{\rm %s} \ x \ E_{\rm %s}$" % (release, s2, s1), color="navy", fmt="+", markevery=50)
88+
plt.errorbar(l[:lmax_for_plot], 100 * (gamma_TE[:lmax_for_plot] + gamma_ET[:lmax_for_plot]) / 2, label=r"%s $T \ x \ E$" % (release), color="black", fmt="--", markevery=50)
89+
90+
plt.errorbar(l[:lmax_for_plot], 100 * gamma_TB[:lmax_for_plot], label=r"%s $T_{\rm %s} \ x \ B_{\rm %s}$" % (release, s1, s2), color="red", fmt="-.", markevery=50)
91+
plt.errorbar(l[:lmax_for_plot], 100 * gamma_BT[:lmax_for_plot], label=r"%s $T_{\rm %s} \ x \ B_{\rm %s}$" % (release, s2, s1), color="orange", fmt="*", markevery=50)
92+
plt.errorbar(l[:lmax_for_plot], 100 * (gamma_TB[:lmax_for_plot] + gamma_BT[:lmax_for_plot]) / 2, label=r"%s $T \ x \ B$" % (release), color="gray", fmt="--", markevery=50)
93+
94+
plt.ylim(-0.8, 0.8)
95+
plt.ylabel(r"$ \gamma_{\ell}$", fontsize=14)
96+
plt.legend()
97+
plt.xlabel(r"$\ell$", fontsize=14)
98+
plt.savefig(f"{beam_dir}/beam_leakage_{freq}.png")
99+
plt.clf()
100+
plt.close()
101+
102+
zeros = np.zeros(len(l))
103+
104+
np.savetxt(f"{beam_dir}/gamma_{release}_{freq}{s2}_t2e.dat", np.transpose([l, gamma_TE, zeros, zeros, zeros]))
105+
np.savetxt(f"{beam_dir}/gamma_{release}_{freq}{s1}_t2e.dat", np.transpose([l, gamma_ET, zeros, zeros, zeros]))
106+
107+
np.savetxt(f"{beam_dir}/gamma_{release}_{freq}{s2}_t2b.dat", np.transpose([l, gamma_TB, zeros, zeros, zeros]))
108+
np.savetxt(f"{beam_dir}/gamma_{release}_{freq}{s1}_t2b.dat", np.transpose([l, gamma_BT, zeros, zeros, zeros]))
109+
110+
gamma_mean_TE = (gamma_TE + gamma_ET) / 2
111+
gamma_mean_TB = (gamma_TB + gamma_BT) / 2
112+
113+
np.savetxt(f"{beam_dir}/gamma_mean_{release}_{freq}{s1}{s2}_t2e.dat", np.transpose([l, gamma_mean_TE, zeros, zeros, zeros]))
114+
np.savetxt(f"{beam_dir}/gamma_mean_{release}_{freq}{s1}{s2}_t2b.dat", np.transpose([l, gamma_mean_TB, zeros, zeros, zeros]))
115+
116+
# these beams will be used for source-sub, they have high ell max
117+
118+
release = "npipe"
119+
beam_dir = beam_dir_d + f"/{release}"
120+
pspy_utils.create_directory(beam_dir)
121+
122+
123+
pl = hp.pixwin(2048)
124+
125+
for freq in freqs:
126+
127+
Wl_AA = fits.open(f"{planck_fits_beam_path}/quickpol/Wl_npipe6v20_{freq}Ax{freq}A.fits")
128+
Wl_BB = fits.open(f"{planck_fits_beam_path}/quickpol/Wl_npipe6v20_{freq}Bx{freq}B.fits")
129+
130+
bl_T_A = np.sqrt(Wl_AA[1].data["TT_2_TT"][0, :])
131+
bl_T_B = np.sqrt(Wl_BB[1].data["TT_2_TT"][0, :])
132+
133+
bl_T_coadd = (bl_T_A + bl_T_B) / 2
134+
135+
bl_T_coadd = bl_T_coadd[:len(pl)]
136+
bl_T_coadd_pixwin = bl_T_coadd * pl
137+
138+
l = np.arange(len(bl_T_coadd))
139+
140+
141+
np.savetxt(f"{beam_dir}/bl_T_{release}_{freq}_coadd.dat", np.transpose([l, bl_T_coadd]))
142+
np.savetxt(f"{beam_dir}/bl_T_{release}_{freq}_coadd_pixwin.dat", np.transpose([l, bl_T_coadd_pixwin]))
143+
144+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
This script is used to reformat the ACT multifrequency
3+
point source catalog `cat_skn_multifreq_20220526_nightonly`
4+
in three different monofrequency catalogs (at 90,150 and 220 GHz)
5+
"""
6+
from pixell import utils
7+
import pandas as pd
8+
import numpy as np
9+
from pspy import pspy_utils, so_dict
10+
from pspipe_utils import log
11+
import sys
12+
13+
d = so_dict.so_dict()
14+
d.read_from_file(sys.argv[1])
15+
log = log.get_logger(**d)
16+
17+
cat_file = d["source_catalog"]
18+
out_dir = d["catalog_dir"]
19+
20+
pspy_utils.create_directory(out_dir)
21+
22+
input_catalog = pd.read_table(cat_file, escapechar="#", sep="\s+")
23+
input_catalog = input_catalog.shift(1, axis=1)
24+
25+
flux_id = {90: 1, 150: 2, 220: 3}
26+
27+
# https://phy-wiki.princeton.edu/polwiki/pmwiki.php?n=BeamAnalysis.BeamDistributionCenter
28+
beam_areas = {
29+
90: [484.17, 487.03],
30+
150: [228.44, 215.24, 221.88], #nsr
31+
220: [107.34]
32+
}
33+
34+
for freq, freq_id in flux_id.items():
35+
36+
flux = {
37+
m: getattr(input_catalog, f"flux_{m}{freq_id}") for m in "TQU"
38+
}
39+
dflux = {
40+
m: getattr(input_catalog, f"dflux_{m}{freq_id}") for m in "TQU"
41+
}
42+
43+
# nsr to sr
44+
beam_area = np.mean(beam_areas[freq])/1e9
45+
46+
amp = {}
47+
damp = {}
48+
for m in ["T", "Q", "U"]:
49+
# utils.dplanck converts Jy to Kelvins
50+
# flux is given in mJy and we want amps in mK
51+
amp[m] = flux[m] / (utils.dplanck(freq*1e9) * beam_area)
52+
damp[m] = dflux[m] / (utils.dplanck(freq*1e9) * beam_area)
53+
54+
ca = input_catalog.ca
55+
status = np.where(ca < 3, 1, 2)
56+
57+
snr = amp["T"] / damp["T"]
58+
# npix is not used anywhere
59+
npix = np.zeros_like(snr)
60+
61+
output_catalog = [input_catalog.ra, input_catalog.dec, snr, amp["T"], damp["T"], amp["Q"], damp["Q"], amp["U"], damp["U"],
62+
flux["T"], dflux["T"], flux["Q"], dflux["Q"], flux["U"], dflux["U"],
63+
npix, status]
64+
65+
output_catalog = np.transpose(output_catalog)
66+
67+
# ordering by snr
68+
output_catalog = output_catalog[output_catalog[:,2].argsort()[::-1]]
69+
70+
header = "ra dec SNR Tamp dTamp Qamp dQamp Uamp dUamp Tflux dTflux Qflux dQflux Uflux dUflux npix status"
71+
fmt = "%11.6f %11.6f %8.3f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %5.0f %2.0f"
72+
np.savetxt(f"{out_dir}/cat_skn_{freq:03d}_20220526_nightonly_ordered.txt", output_catalog, header=header, fmt=fmt)

0 commit comments

Comments
 (0)