Information on an SPT-3G D1 data release

This page is linked from the South Pole Telescope homepage and was created using the tools Jupyter Notebook and Quarto.

1 Introduction

This page provides information on a data release relevant to mainly the following two works:

  • Quan et al., SPT-3G D1: Maps of the millimeter-wave sky from 2019 and 2020 observations of the SPT-3G Main field (hereafter Q26)
  • Camphuis et al., SPT-3G D1: CMB temperature and polarization power spectra and cosmology from 2019 and 2020 observations of the SPT-3G Main field (hereafter C25)

The data products made available in this data release are stored in the directory d1_midell_tqu_healpix inside a Globus Collection for SPT-3G public data releases (Collection UUID: 0bf0cefa-568a-4b37-861d-32c9102ce7d6). Information on how to transfer files on Globus can be found in the final section of this documentation.

The data products form three groups: real-data maps, simulated maps, and ancillary products. The directories in d1_midell_tqu_healpix reflect this grouping as follows:

d1_midell_tqu_healpix/
├── ancillary_products  (2.8G)
├── real_data_maps      (2.4T)
└── simulated_maps      (3.3T)

Please do not hesitate to contact Wei Quan (weiquan@uchicago.edu) for any questions on accessing the Globus Collection and/or on using any data products provided in this data release.

The following list shows the different types of data products provided within each group, and more information on each type of data product can be found in a corresponding section.

List of Data Products

from matplotlib import pyplot
import healpy, numpy, os, matplotlib, sys

print("python version:", sys.version)
print("matplotlib version:", matplotlib.__version__)
print("healpy version:", healpy.__version__)
print("numpy version:", numpy.__version__)

matplotlib.rcParams["font.size"] = 14
matplotlib.rcParams["font.family"] = "DeJavu Serif"
matplotlib.rcParams["font.serif"] = ["Times New Roman"]
matplotlib.rcParams["mathtext.fontset"] = "dejavuserif"
matplotlib.rcParams["legend.fontsize"] = 14
matplotlib.rcParams["axes.grid"] = True
matplotlib.rcParams["axes.grid.which"] = "both"
matplotlib.rcParams["grid.linestyle"] = "dotted"
matplotlib.rcParams["grid.linewidth"] = 0.35
matplotlib.rcParams["xtick.direction"] = "in"
matplotlib.rcParams["ytick.direction"] = "in"
matplotlib.rcParams["axes.labelsize"] = 14
matplotlib.rcParams["axes.labelpad"] = 6
matplotlib.rcParams["axes.titlesize"] = 14
matplotlib.rcParams["axes.titlepad"] = 10
matplotlib.rcParams["xtick.labelsize"] = 14
matplotlib.rcParams["ytick.labelsize"] = 14

root_dir = os.path.join(
    "/lcrc/project/SPT3G/globusshare/public_data_releases",
    "d1_midell_tqu_healpix")
real_data_maps_dir = os.path.join(
    root_dir,
    "real_data_maps")
ancillary_products_dir = os.path.join(
    root_dir,
    "ancillary_products")
simulated_maps_dir = os.path.join(
    root_dir,
    "simulated_maps")


def show_map_full_field(
        m, vmin, vmax, title, unit,
        cmap="gray", badcolor="white"):

    pyplot.figure(figsize=(13, 7), num=0, facecolor="white")
    healpy.azeqview(
        m,
        rot=(0, -59.5, 0),
        xsize=1300, ysize=700, reso=3.5, fig=0,
        half_sky=True, lamb=True,
        cmap=cmap, min=vmin, max=vmax,
        badcolor=badcolor,
        title=title, unit=unit)
    pyplot.show()
    pyplot.close()


def show_map_thumbnail(
        m, vmin, vmax, title, unit,
        cmap="gray", badcolor="white"):

    pyplot.figure(figsize=(8, 8), num=0, facecolor="white")
    healpy.gnomview(
        m,
        rot=(32, -51, 0),
        xsize=800, ysize=800, reso=0.2, fig=0,
        cmap=cmap, min=vmin, max=vmax,
        badcolor=badcolor,
        title=title, unit=unit)
    pyplot.show()
    pyplot.close()


def show_1d_functions_of_ell(
        ell, functions, labels, xlims, ylims, ylabel,
        yscale="linear", legend_loc="upper right", legend_ncols=1,
        vlines=[]):

    pyplot.figure(figsize=(8, 5))
    for function, label in zip(functions, labels):
        pyplot.plot(ell, function, label=label, alpha=0.8)
    for vline in vlines:
        pyplot.axvline(vline, color="black", linestyle="dotted")
    pyplot.yscale(yscale)
    pyplot.xlim(left=xlims[0], right=xlims[1])
    pyplot.ylim(bottom=ylims[0], top=ylims[1])
    if not (len(labels) == 1 and labels[0] == ""):
        pyplot.legend(loc=legend_loc, ncol=legend_ncols)
    pyplot.xlabel(r"$\ell$")
    pyplot.ylabel(ylabel)
    pyplot.show()
    pyplot.close()


def show_alm_triangle(
        alm, lmax, real=True,
        vmin=None, vmax=None, cmap="Oranges_r",
        xlims=None, ylims=None,
        title="Triangle"):

    import warnings
    warnings.filterwarnings("ignore")

    triangle = numpy.empty((lmax+1, lmax+1))
    triangle[:,:] = numpy.nan
    for l in range(lmax+1):
        for m in range(0, l+1):
            i = healpy.Alm.getidx(lmax, l, m)
            if real:
                triangle[m, l] = alm[i].real
            else:
                triangle[m, l] = alm[i]

    pyplot.figure(figsize=(7, 7))
    if vmin is None:
        vmin = numpy.min(triangle)
    if vmax is None:
        vmax = numpy.max(triangle)
    img = pyplot.imshow(
        triangle, origin="lower", vmin=vmin, vmax=vmax, cmap=cmap)
    if xlims is None:
        xlims = [0, triangle.shape[1]]
    if ylims is None:
        ylims = [0, triangle.shape[0]]
    pyplot.xlim(left=xlims[0], right=xlims[1])
    pyplot.ylim(bottom=ylims[0], top=ylims[1])
    pyplot.grid(False)
    cb = pyplot.colorbar(pad=0.03, shrink=0.8)
    pyplot.grid(True)
    pyplot.xlabel(r"$\ell$")
    pyplot.ylabel(r"$m$")
    pyplot.title(title)
    pyplot.show()
    pyplot.close()
python version: 3.10.1 (main, Jan  8 2024, 15:34:44) [GCC 10.3.0]
matplotlib version: 3.5.1
healpy version: 1.15.0
numpy version: 1.22.1

2 Real-data maps

The directory real_data_maps contains real-data maps. The structure of real_data_maps is shown below:

real_data_maps/
├── full
├── half
├── one_thirtieth
├── pre_null
│   ├── azimuth
│   ├── moon
│   ├── scan
│   ├── sun
│   ├── wafer
│   └── year
└── signflip_noise

Every map file in every directory contains one coadd, a set of weight-removed \(T/Q/U\) maps (HEALPix \(N_{\mathrm{side}} = 8192\), \(\ell_{\mathrm{max}} \sim 16000\)) for one frequency band. The \(Q/U\) maps are stored in accordance with the IAU convention. Details of the definition of a coadd are described in Section III C 1 of Q26. We provide the five types of coadds described in that section (the full, half, one-thirtieth, signflip-noise, and pre-null coadds) in this data release. Information on the files related to each type of coadd can be found below.

As described in Section III B 5 of Q26, we binned the SPT-3G D1 timestreams into two pixelization schemes: the HEALPix pixels with \(N_{side} = 8192\) and the \(0^{\prime}.5625\) square pixels in the ZEA projection. While all the maps initially provided in this data release are the HEALPix maps for simplicity, the \(2^{\prime}.25\) ZEA maps (a rebinned version of the \(0^{\prime}.5625\) maps) used for Ge et al., Cosmology from CMB lensing and delensed \(EE\) power spectra using 2019-2020 SPT-3G polarization data can be made available upon request.

2.1 full coadds

The files in the directory full contain the full coadds, the full-depth coadds made from SPT-3G D1. The file names are based on the following template:

full_{freq}ghz.fits,

where {freq} is 095, 150, or 220.

Each file also contains the associated six weight maps. All the weight maps are normalized by the maximum value of the \(TT\) weight map. Below is part of the output from running the program fitsverify on one file, which shows the map stored in each column.

     Col# Name (Units)       Format
   1 PIXEL                      J
   2 TEMPERATURE (uK)           D
   3 Q_POLARISATION (uK)        D
   4 U_POLARISATION (uK)        D
   5 TT_NORMALIZED (unitless)   D
   6 TQ_NORMALIZED (unitless)   D
   7 TU_NORMALIZED (unitless)   D
   8 QQ_NORMALIZED (unitless)   D
   9 QU_NORMALIZED (unitless)   D
  10 UU_NORMALIZED (unitless)   D

In the following four cells, the 95 GHz full \(T\) map and \(TT\) weight map are loaded and plotted.

full_95_t = healpy.read_map(
    os.path.join(real_data_maps_dir, "full", "full_095ghz.fits"),
    field=0,
    partial=True)
show_map_full_field(
    full_95_t, -140, 140,
    r"95 GHz, $\tt{full}$, $\it{T}$ map", r"$\mathrm{{\mu}K}$",
    cmap="RdBu_r")

full_95_tt = healpy.read_map(
    os.path.join(real_data_maps_dir, "full", "full_095ghz.fits"),
    field=3,
    partial=True)
show_map_full_field(
    full_95_tt, 0, 1,
    r"95 GHz, $\tt{full}$, $\it{TT}$ weight map (normalized)", "Unitless",
    cmap="bone")

2.2 half and one-thirtieth coadds

The files in each of the two directories half and one_thirtieth contain the partial-depth coadds (bundles) made by randomly dividing the full dataset into two and thirty equal-depth bundles, respectively. The file names are based on the following tempates:

half_bundle{n}_{freq}ghz.fits,
one_thirtieth_bundle{m}_{freq}ghz.fits,

where {n} is 0 or 1, and {m} ranges from 0 to 29.

2.3 signflip-noise coadds

The files in the directory signflip_noise contain the 500 signflip-noise coadds. The file names are based on the following template:

signflip_noise_permutation{n}_{freq}ghz.fits,

where {n} ranges from 0 to 499. We use permutation followed by a number to distinguish the different permutations of the signs (\(+1\)s and \(-1\)s).

In the following two cells, the 95 GHz signflip-noise \(U\) map from one permutation is loaded an plotted.

signflip_noise_95_t = healpy.read_map(
    os.path.join(
        real_data_maps_dir,
        "signflip_noise",
        "signflip_noise_permutation421_095ghz.fits"),
    field=2,
    partial=True)
show_map_full_field(
    signflip_noise_95_t, -35, 35,
    r"95 GHz, $\tt{signflip-noise}$, $\it{U}$ map (IAU convention)",
    r"$\mathrm{{\mu}K}$",
    cmap="RdBu_r")

2.4 pre-null coadds

The files in the directory pre_null in turn are organized into six directories, each of which has the files that contain the coadds related to one of the six splits (azimuth, year, sun, moon, scan, and wafer) described in Section VII A 1 of Q26. The file names are based on the following template:

{split}_{half}_bundle{n}_{freq}.fits,

where {split} is one of the six names of the splits, {half} is the name for one of the two parts for that split, and {n} ranges from 0 to 24.

The following table shows the meanings of the two {half}s for each split.

Names Meaning
azimuth, near The observations whose median azimuth is in the 180\(^\circ\) range of azimuth centered at 150\(^\circ\)
azimuth, far The observations whose median azimuth is in the other 180\(^\circ\) range
year, 2019 The observations taken in 2019
year, 2020 The observations taken in 2020
sun (moon), below The observations taken when the Sun (moon) was below the horizon
sun (moon), above The observations taken when the Sun (moon) was above the horizon
scan, left The timestreams acquired during the left-going telescope scans of every observation
scan, right The timestreams acquired during the right-going telescope scans of every observation
wafer, large Every observation’s timestreams from the group of five wafers that have relatively large elevation-dependent gain changes
wafer, small Every observation’s timestreams from the group of five wafers that have relatively small elevation-dependent gain changes

In the following two cells, the 95 GHz \(T\) map from bundle 4 of the near half of the azimuth split is loaded and plotted.

az_near_bundle0_95_t = healpy.read_map(
    os.path.join(
        real_data_maps_dir,
        "pre_null/azimuth",
        "azimuth_near_bundle00_095ghz.fits"),
    field=0,
    partial=True)
show_map_full_field(
    az_near_bundle0_95_t, -140, 140,
    r"95 GHz, $\tt{pre-null}$, $\it{T}$ map "+
        "(the 'near' half of the azimuth split, bundle 0)",
    r"$\mathrm{{\mu}K}$",
    cmap="RdBu_r")

The 25 null bundles that we produced to calculate the average null spectra for each split are the differences between the 25 bundles in one half and those in the other half. For example, the 95 GHz \(T\) map in null bundle 4 from the azimuth split is equal to \((T_{\mathrm{near},4} - T_{\mathrm{far},4}) / 2\), where \(T_{\mathrm{near},4}\) is the \(T\) map from azimuth_near_bundle04_095ghz.fits, and \(T_{\mathrm{far},4}\) is from azimuth_far_bundle04_095ghz.fits.

Back to List of Data Products

3 Simulated maps

The directory simulated_maps contains the mock-observation input and output maps described in Section III D of Q26. The structure of simulated_maps is shown below:

simulated_maps/
├── input_maps
└── output_maps
    ├── masking_no
    └── masking_yes

As is the case with the map files in real_data_maps, every map file in simulated_maps contains one coadd (HEALPix \(N_{\mathrm{side}} = 8192\), \(\ell_{\mathrm{max}}=16000\)) for one frequency band, and the \(Q/U\) maps are stored in accordance with the IAU convention.

3.1 Input maps

The files in the directory input_maps contain the 500 realizations of input sky maps and the theory spectra associated with the realizations.

The names of the files storing the input sky maps are based on the following template:

input_maps_realization{rlz}_{freq}ghz.fits,

where {rlz} ranges from 0 to 499.

In the following two cells, one realization of the sky at 220 GHz is loaded and plotted. The footprint of each input sky map is slightly larger (\({\sim}10\%\)) than the footprint of the SPT-3G Main field. In addition, these maps had very-large angular-scale information (\(\ell<100\)) removed when they were generated.

mock_input_220_tqu = healpy.read_map(
    os.path.join(
        simulated_maps_dir,
        "input_maps",
        "input_maps_realization421_220ghz.fits"),
    field=(0, 1, 2),
    partial=True)
for s, m in zip("TQU", mock_input_220_tqu):
    if s == "T":
        lim = 300
        title = r"220 GHz, mock observation input, $\it{T}$ map"
    else:
        lim = 10
        title = r"220 GHz, mock observation input, "
        title += "$\it{}$ map (IAU convention)".format(s)
    show_map_full_field(
        m, -1*lim, lim,
        title,
        r"$\mathrm{{\mu}K}$",
        cmap="gray")