7 Measuring the kSZ effect with power spectra¶
This tutorial showcases a measurement of the kinematic Sunyaev-Zel'dovich (kSZ) effect via the kSZ-galaxy power spectrum. It follows the method outlined in Harscouet et al. 2025 (https://arxiv.org/abs/2512.14625) (H25). In this notebook, we measure the kSZ effect on real data, namely the ACT DR6 temperature map and the DESI Y1 Luminous Red Galaxy (LRG) spectroscopic sample.
In [2]:
import numpy as np
import pymaster as nmt
import pymaster.utils as ut
from astropy.io import fits
import matplotlib.pyplot as plt
from pixell import enmap, reproject, enplot
Loading the data¶
We start by importing the data:
- GALAXIES: you will need
- a catalog ($\rightarrow$
gal_data["cat"]) containing positions (RAandDEC) as well as an estimate of the peculiar velocity of each galaxy along the line of sightvR; - a mask ($\rightarrow$
gal_data["mask"]) tracking the number density of galaxies across the survey footprint;
- a catalog ($\rightarrow$
- CMB TEMPERATURE: you will need
- a component-separated "CMB+kSZ" map ($\rightarrow$
ksz_data["map"]); - an apodized mask ($\rightarrow$
ksz_data["mask"]) representing the ACT survey geometry.
- a component-separated "CMB+kSZ" map ($\rightarrow$
The ACT collaboration uses the CAR pixelization scheme for their data products, so we use their own pixell library to handle all maps and masks.
In [2]:
dir = 'your/data/directory'
gal_data = {"cat": f'{dir}/LRG_Y1_cigale_masked.fits',
"mask": f'{dir}/LRG_Y1_mask.fits'}
ksz_data = {"map": f'{dir}/hilc_fullRes_TT_17000.fits',
"mask": f'{dir}/wide_mask_GAL070_apod_1.50_deg_wExtended_srcfree_Will.fits'}
In [3]:
print("Reading catalog and map...")
# Galaxy catalog
gcat = fits.open(gal_data['cat'])[1].data
vr = gcat['vR'] # reading individual columns
ra = gcat['RA']
dec = gcat['DEC']
# Temperature map
tmap = enmap.read_map(ksz_data["map"])
print("Reading masks...")
gmask = enmap.read_map(gal_data['mask']) # galaxy mask
tmask = enmap.read_map(ksz_data["mask"]) # temperature mask
Reading catalog and map... Reading masks...
In [15]:
# Inspecting the maps and masks
# We first lower the resolution of the mask for quicker visualisation
tmap_dg = enmap.downgrade(tmap, 16)
enplot.show(enplot.plot(tmap_dg))
tmask_dg = enmap.downgrade(tmask, 16)
enplot.show(enplot.plot(tmask_dg))
gmask_dg = enmap.downgrade(gmask, 16)
enplot.show(enplot.plot(gmask_dg))