Computing power spectra

Binder

Example of how to compute a power spectrum from CAMELS data

[1]:
import numpy as np
import h5py
import hdf5plugin
import MAS_library as MASL
import Pk_library as PKL
import matplotlib.pylab as plt

Get the name of the snapshot

[2]:
f_snap = '/home/jovyan/Data/Sims/SIMBA/LH/LH_367/snap_020.hdf5'

Open the snapshot file

[3]:
data = h5py.File(f_snap, 'r')

Read the snapshot header

[4]:
BoxSize      = data['Header'].attrs[u'BoxSize']/1e3    #size of the snapshot in comoving Mpc/h
redshift     = data['Header'].attrs[u'Redshift']       #reshift of the snapshot
scale_factor = data['Header'].attrs[u'Time']           #scale factor
h            = data['Header'].attrs[u'HubbleParam']    #value of the hubble parameter in 100 km/s/(Mpc/h)
Masses       = data['Header'].attrs[u'MassTable']*1e10 #masses of the particles in Msun/h
Np           = data['Header'].attrs[u'NumPart_Total']  #total number of particles for specie
Omega_m      = data['Header'].attrs[u'Omega0']         #Omega_matter
Omega_L      = data['Header'].attrs[u'OmegaLambda']    #Omega_Lambda

Read the positions and the masses of the gas particles

[5]:
pos_gas   = data['PartType0/Coordinates'][:]/1e3 #Mpc/h
mass_gas  = data['PartType0/Masses'][:]*1e10     #Msun/h

Check the masses positions and masses of the gas particles

[6]:
print('Box size: %.2f Mpc/h'%BoxSize)
print('Snapshot redshift: %.2f'%redshift)
print('%.2f < pos_gas_X < %.2f'%(np.min(pos_gas[:,0]), np.max(pos_gas[:,0])))
print('%.3e < mass_gas  < %.3e'%(np.min(mass_gas), np.max(mass_gas)))
Box size: 25.00 Mpc/h
Snapshot redshift: 0.86
0.00 < pos_gas_X < 25.00
1.219e+07 < mass_gas  < 3.811e+07

Make sure the positions are a numpy float32 array

[7]:
pos_gas = pos_gas.astype(np.float32)

Define array the will contain the gas density field

[8]:
grid  = 512
delta = np.zeros((grid,grid,grid), dtype=np.float32) #grid will have (512,512,512) voxels

Assign gas particle positions and masses to the regular grid We will use the Cloud-in-Cell mass assignment scheme

[9]:
MAS     = 'CIC'
verbose = True
MASL.MA(pos_gas, delta, BoxSize, MAS, W=mass_gas, verbose=verbose)

Using CIC mass assignment scheme with weights
Time taken = 1.496 seconds

Check that the mass in the grid is the same as the mass of all particles

[10]:
print('Sum of all particle masses:         %.3e Msun/h'%np.sum(mass_gas, dtype=np.float64))
print('Sum of the mass in all grid voxels: %.3e Msun/h'%np.sum(delta, dtype=np.float64))
Sum of all particle masses:         2.062e+14 Msun/h
Sum of the mass in all grid voxels: 2.062e+14 Msun/h

calculate the gas overdensity field delta = mass_gas / < mass_gas > - 1

[11]:
delta /= np.mean(delta, dtype=np.float32)
delta -= 1.0

Check that mean is zero, and minimum cant be smaller than -1

[12]:
print('%.2f < delta < %.2f'%(np.min(delta), np.max(delta)))
print('< delta > = %.2e'%(np.mean(delta, dtype=np.float64)))
-1.00 < delta < 11278.17
< delta > = -2.41e-06

Calculate the power spectrum

[13]:
axis     = 0     #specifies the axes along which redshift-space distortions are place. Not used in real-space
MAS      = 'CIC' #specifies the mass assignment scheme used to construct the density field
threads  = 1     #number of openmp threads
verbose  = True
Pk_class = PKL.Pk(delta, BoxSize, axis, MAS, threads, verbose)
k        = Pk_class.k3D
Pk       = Pk_class.Pk[:,0]

Computing power spectrum of the field...
Time to complete loop = 7.01
Time taken = 12.10 seconds

Plot power spectrum

[14]:
plt.xlabel(r'$k [h/{\rm Mpc}]$')
plt.ylabel(r'$P(k) [({\rm Mpc}/h)^3]$')
plt.xscale('log')
plt.yscale('log')
plt.plot(k, Pk)
plt.show()
../_images/examples_Pk_27_0.png
[ ]: