Calculate upglade redshifts (#128)

* Update redshift reading

* Add helio to CMB redshift

* Update imports

* Update nb

* Run for Quijote

* Add script

* Update

* Update .gitignore

* Update imports

* Add Peery estimator

* Add bulk flow scripts

* Update typs

* Add comment

* Add blank space

* Update submission script

* Update description

* Add barriers

* Update nb

* Update nb

* Rename script

* Move to old

* Update imports

* Add nb

* Update script

* Fix catalogue key

* Update script

* Update submit

* Update comment

* Update .gitignore

* Update nb

* Update for stationary obsrevers

* Update submission

* Add nb

* Add better verbose control

* Update nb

* Update submit

* Update nb

* Add SN errors

* Add draft of the script

* Update verbosity flags

* Add submission script

* Debug script

* Quickfix

* Remove comment

* Update nb

* Update submission

* Update nb

* Processed UPGLADE
This commit is contained in:
Richard Stiskalek 2024-06-20 14:33:00 +01:00 committed by GitHub
parent c447d2e7b0
commit 779f2e76ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 2066 additions and 300 deletions

5
.gitignore vendored
View File

@ -36,4 +36,9 @@ scripts_independent/clear.sh
# Generated plots
plots/*
# Data files
data/*
notebooks/test.ipynb
data/BulkFlowPlot.npy
data/upglade_z_0p05_all.h5

View File

@ -20,7 +20,8 @@ from .utils import (center_of_mass, delta2ncells, number_counts,
binned_statistic, cosine_similarity, fprint, # noqa
hms_to_degrees, dms_to_degrees, great_circle_distance, # noqa
radec_to_cartesian, cartesian_to_radec, # noqa
thin_samples_by_acl, numpyro_gof, radec_to_galactic) # noqa
thin_samples_by_acl, numpyro_gof, radec_to_galactic, # noqa
heliocentric_to_cmb, calculate_acl) # noqa
from .params import (paths_glamdring, simname2boxsize, simname2Omega_m, # noqa
snap2redshift) # noqa

View File

@ -16,8 +16,9 @@ from .density import (DensityField, PotentialField, TidalTensorField,
VelocityField, radial_velocity, power_spectrum, # noqa
overdensity_field) # noqa
from .enclosed_mass import (particles_enclosed_mass, # noqa
particles_enclosed_momentum, field_enclosed_mass) # noqa
from .interp import (evaluate_cartesian_cic, evaluate_sky, evaluate_los, # noqa
particles_enclosed_momentum, field_enclosed_mass, # noqa
bulkflow_peery2018) # noqa
from .interp import (evaluate_cartesian_cic, evaluate_sky, evaluate_los, # noqa
field2rsp, fill_outside, make_sky, # noqa
observer_peculiar_velocity, smoothen_field, # noqa
field_at_distance) # noqa

View File

@ -12,10 +12,13 @@
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import numpy
"""
Code to calculate the enclosed mass, momentum or bulk flow from various
radial-velocity based estimators (that may be flawed, be careful).
"""
import numpy as np
from numba import jit
from tqdm import tqdm
###############################################################################
@ -55,7 +58,7 @@ def particles_enclosed_mass(rdist, mass, distances):
enclosed_mass : 1-dimensional array
Enclosed mass at each distance.
"""
enclosed_mass = numpy.full_like(distances, 0.)
enclosed_mass = np.full_like(distances, 0.)
start_index = 0
for i, dist in enumerate(distances):
if i > 0:
@ -121,9 +124,10 @@ def field_enclosed_mass(field, distances, boxsize):
enclosed_volume : 1-dimensional array
Enclosed grid-like volume at each distance.
"""
enclosed_mass = numpy.zeros_like(distances)
enclosed_volume = numpy.zeros_like(distances)
for i, dist in enumerate(distances):
enclosed_mass = np.zeros_like(distances)
enclosed_volume = np.zeros_like(distances)
for i, dist in enumerate(tqdm(distances)):
enclosed_mass[i], enclosed_volume[i] = _field_enclosed_mass(
field, dist, boxsize)
@ -137,7 +141,7 @@ def field_enclosed_mass(field, distances, boxsize):
@jit(nopython=True, boundscheck=False)
def _enclosed_momentum(rdist, mass, vel, rmax, start_index):
bulk_momentum = numpy.zeros(3, dtype=rdist.dtype)
bulk_momentum = np.zeros(3, dtype=rdist.dtype)
for i in range(start_index, len(rdist)):
if rdist[i] <= rmax:
@ -169,7 +173,7 @@ def particles_enclosed_momentum(rdist, mass, vel, distances):
bulk_momentum : 2-dimensional array
Enclosed momentum at each distance.
"""
bulk_momentum = numpy.zeros((len(distances), 3))
bulk_momentum = np.zeros((len(distances), 3))
start_index = 0
for i, dist in enumerate(distances):
if i > 0:
@ -179,4 +183,68 @@ def particles_enclosed_momentum(rdist, mass, vel, distances):
start_index)
bulk_momentum[i] += v
return bulk_momentum
return bulk_momentum
###############################################################################
# Bulk flow estimators #
###############################################################################
def bulkflow_peery2018(rdist, mass, pos, vel, distances, weights,
verbose=True):
"""
Calculate the bulk flow from a set of particles using the estimator from
Peery+2018. Supports either `1/r^2` or `constant` weights. Particles
are assumed to be sorted by distance from the center of the box.
Parameters
----------
rdist : 1-dimensional array
Sorted distance of particles from the center of the box.
mass : 1-dimensional array
Sorted mass of particles.
pos : 2-dimensional array
Sorted position of particles.
vel : 2-dimensional array
Sorted velocity of particles.
distances : 1-dimensional array
Distances at which to calculate the bulk flow.
weights : str
Weights to use in the estimator, either `1/r^2` or `constant`.
verbose : bool
Verbosity flag.
Returns
-------
bulk_flow : 2-dimensional array
"""
# Select only the particles within the maximum distance to speed up the
# calculation.
if verbose:
print("Selecting particles within the maximum distance...")
kmax = np.searchsorted(rdist, np.max(distances))
rdist = rdist[:kmax]
mass = mass[:kmax]
pos = pos[:kmax]
vel = vel[:kmax]
if verbose:
print("Computing the cumulative quantities...")
if weights == "1/r^2":
cumulative_x = np.cumsum(mass[:, np.newaxis] * np.sum(vel * pos, axis=1)[:, np.newaxis] * pos / rdist[:, np.newaxis]**4, axis=0) # noqa
norm = lambda R: R**2 # noqa
elif weights == "constant":
cumulative_x = np.cumsum(mass[:, np.newaxis] * np.sum(vel * pos, axis=1)[:, np.newaxis] * pos / rdist[:, np.newaxis]**2, axis=0) # noqa
norm = lambda R: 3. # noqa
else:
raise ValueError("Invalid weights.")
cumulative_x /= np.cumsum(mass)[:, np.newaxis]
B = np.zeros((len(distances), 3))
for i in range(3):
for j, R in enumerate(distances):
k = np.searchsorted(rdist, R)
B[j, i] = norm(R) * cumulative_x[k - 1, i]
return B

View File

@ -48,7 +48,6 @@ H0 = 100 # km / s / Mpc
def t():
"""Shortcut to get the current time."""
return datetime.now().strftime("%H:%M:%S")
@ -79,21 +78,26 @@ class DataLoader:
store_full_velocity : bool, optional
Whether to store the full 3D velocity field. Otherwise stores only
the radial velocity.
verbose : bool, optional
Verbose flag.
"""
def __init__(self, simname, ksim, catalogue, catalogue_fpath, paths,
ksmooth=None, store_full_velocity=False):
print(f"{t()}: reading the catalogue.")
ksmooth=None, store_full_velocity=False, verbose=True):
if verbose:
print(f"{t()}: reading the catalogue.", flush=True)
self._cat = self._read_catalogue(catalogue, catalogue_fpath)
self._catname = catalogue
print(f"{t()}: reading the interpolated field.")
if verbose:
print(f"{t()}: reading the interpolated field.", flush=True)
self._field_rdist, self._los_density, self._los_velocity = self._read_field( # noqa
simname, ksim, catalogue, ksmooth, paths)
if len(self._field_rdist) % 2 == 0:
warn(f"The number of radial steps is even. Skipping the first "
f"step at {self._field_rdist[0]} because Simpson's rule "
"requires an odd number of steps.")
if verbose:
warn(f"The number of radial steps is even. Skipping the first "
f"step at {self._field_rdist[0]} because Simpson's rule "
"requires an odd number of steps.")
self._field_rdist = self._field_rdist[1:]
self._los_density = self._los_density[..., 1:]
self._los_velocity = self._los_velocity[..., 1:]
@ -102,7 +106,8 @@ class DataLoader:
raise ValueError("The number of objects in the catalogue does not "
"match the number of objects in the field.")
print(f"{t()}: calculating the radial velocity.")
if verbose:
print(f"{t()}: calculating the radial velocity.", flush=True)
nobject = len(self._los_density)
dtype = self._los_density.dtype
@ -231,9 +236,7 @@ class DataLoader:
return rdist, los_density, los_velocity
def _read_catalogue(self, catalogue, catalogue_fpath):
"""
Read in the distance indicator catalogue.
"""
"""Read in the distance indicator catalogue."""
if catalogue == "A2":
with File(catalogue_fpath, 'r') as f:
dtype = [(key, np.float32) for key in f.keys()]
@ -256,10 +259,18 @@ class DataLoader:
arr[key] = grp[key][:]
elif "CB2_" in catalogue:
with File(catalogue_fpath, 'r') as f:
dtype = [(key, np.float32) for key in f.keys()]
arr = np.empty(len(f["RA"]), dtype=dtype)
for key in f.keys():
arr[key] = f[key][:]
elif "UPGLADE" in catalogue:
with File(catalogue_fpath, 'r') as f:
dtype = [(key, np.float32) for key in f.keys()]
arr = np.empty(len(f["RA"]), dtype=dtype)
for key in f.keys():
if key == "mask":
continue
arr[key] = f[key][:]
else:
raise ValueError(f"Unknown catalogue: `{catalogue}`.")
@ -916,6 +927,8 @@ class SN_PV_validation_model(BaseFlowValidationModel):
Right ascension and declination in degrees.
z_obs : 1-dimensional array of shape (n_objects)
Observed redshifts.
e_zobs : 1-dimensional array of shape (n_objects)
Errors on the observed redshifts.
mB, x1, c : 1-dimensional arrays of shape (n_objects)
SALT2 light curve parameters.
e_mB, e_x1, e_c : 1-dimensional arrays of shape (n_objects)
@ -927,7 +940,7 @@ class SN_PV_validation_model(BaseFlowValidationModel):
"""
def __init__(self, los_density, los_velocity, RA, dec, z_obs,
mB, x1, c, e_mB, e_x1, e_c, r_xrange, Omega_m):
e_zobs, mB, x1, c, e_mB, e_x1, e_c, r_xrange, Omega_m):
dt = jnp.float32
# Convert everything to JAX arrays.
self._los_density = jnp.asarray(los_density, dtype=dt)
@ -936,6 +949,11 @@ class SN_PV_validation_model(BaseFlowValidationModel):
self._RA = jnp.asarray(np.deg2rad(RA), dtype=dt)
self._dec = jnp.asarray(np.deg2rad(dec), dtype=dt)
self._z_obs = jnp.asarray(z_obs, dtype=dt)
if e_zobs is not None:
self._e2_cz_obs = jnp.asarray(
(SPEED_OF_LIGHT * e_zobs)**2, dtype=dt)
else:
self._e2_cz_obs = jnp.zeros_like(self._z_obs)
self._mB = jnp.asarray(mB, dtype=dt)
self._x1 = jnp.asarray(x1, dtype=dt)
@ -1121,6 +1139,7 @@ class SN_PV_validation_model(BaseFlowValidationModel):
alpha_cal = numpyro.sample("alpha_cal", self._alpha_cal)
beta_cal = numpyro.sample("beta_cal", self._beta_cal)
cz_err = jnp.sqrt(sigma_v**2 + self._e2_cz_obs)
Vext_rad = project_Vext(Vx, Vy, Vz, self._RA, self._dec)
mu = self.mu(mag_cal, alpha_cal, beta_cal)
@ -1137,7 +1156,7 @@ class SN_PV_validation_model(BaseFlowValidationModel):
# Calculate p(z_obs) and multiply it by p(r)
zobs_pred = self._f_zobs(beta, Vext_rad[i], self._los_velocity[i])
ptilde *= calculate_likelihood_zobs(
self._z_obs[i], zobs_pred, sigma_v)
self._z_obs[i], zobs_pred, cz_err[i])
return ll + jnp.log(self._f_simps(ptilde) / pnorm), None
@ -1385,17 +1404,19 @@ def get_model(loader, zcmb_max=None, verbose=True):
if kind in ["LOSS", "Foundation"]:
keys = ["RA", "DEC", "z_CMB", "mB", "x1", "c", "e_mB", "e_x1", "e_c"]
RA, dec, zCMB, mB, x1, c, e_mB, e_x1, e_c = (loader.cat[k] for k in keys) # noqa
e_zCMB = None
mask = (zCMB < zcmb_max)
model = SN_PV_validation_model(
los_overdensity[mask], los_velocity[mask], RA[mask], dec[mask],
zCMB[mask], mB[mask], x1[mask], c[mask], e_mB[mask], e_x1[mask],
e_c[mask], loader.rdist, loader._Omega_m)
zCMB[mask], e_zCMB, mB[mask], x1[mask], c[mask], e_mB[mask],
e_x1[mask], e_c[mask], loader.rdist, loader._Omega_m)
elif "Pantheon+" in kind:
keys = ["RA", "DEC", "zCMB", "mB", "x1", "c", "biasCor_m_b", "mBERR",
"x1ERR", "cERR", "biasCorErr_m_b", "zCMB_SN", "zCMB_Group"]
"x1ERR", "cERR", "biasCorErr_m_b", "zCMB_SN", "zCMB_Group",
"zCMBERR"]
RA, dec, zCMB, mB, x1, c, bias_corr_mB, e_mB, e_x1, e_c, e_bias_corr_mB, zCMB_SN, zCMB_Group = (loader.cat[k] for k in keys) # noqa
RA, dec, zCMB, mB, x1, c, bias_corr_mB, e_mB, e_x1, e_c, e_bias_corr_mB, zCMB_SN, zCMB_Group, e_zCMB = (loader.cat[k] for k in keys) # noqa
mB -= bias_corr_mB
e_mB = np.sqrt(e_mB**2 + e_bias_corr_mB**2)
@ -1413,8 +1434,8 @@ def get_model(loader, zcmb_max=None, verbose=True):
model = SN_PV_validation_model(
los_overdensity[mask], los_velocity[mask], RA[mask], dec[mask],
zCMB[mask], mB[mask], x1[mask], c[mask], e_mB[mask], e_x1[mask],
e_c[mask], loader.rdist, loader._Omega_m)
zCMB[mask], e_zCMB[mask], mB[mask], x1[mask], c[mask], e_mB[mask],
e_x1[mask], e_c[mask], loader.rdist, loader._Omega_m)
elif kind in ["SFI_gals", "2MTF", "SFI_gals_masked"]:
keys = ["RA", "DEC", "z_CMB", "mag", "eta", "e_mag", "e_eta"]
RA, dec, zCMB, mag, eta, e_mag, e_eta = (loader.cat[k] for k in keys)

View File

@ -15,7 +15,7 @@
from .catalogue import (CSiBORG1Catalogue, CSiBORG2Catalogue, # noqa
CSiBORG2SUBFINDCatalogue, # noqa
CSiBORG2MergerTreeReader, QuijoteCatalogue, # noqa
MDPL2Catalogue) # noqa
MDPL2Catalogue, fiducial_observers) # noqa
from .snapshot import (CSiBORG1Snapshot, CSiBORG2Snapshot, QuijoteSnapshot, # noqa
CSiBORG1Field, CSiBORG2Field, QuijoteField, BORG2Field, # noqa
BORG1Field, TNG300_1Field) # noqa

View File

@ -1372,7 +1372,7 @@ class QuijoteCatalogue(BaseCatalogue):
@property
def totmass(self):
return self._read_fof_catalogue("group_mass")
return self._read_fof_catalogue("GroupMass")
@property
def index(self):

View File

@ -413,6 +413,47 @@ def real2redshift(pos, vel, observer_location, observer_velocity, boxsize,
return pos
def heliocentric_to_cmb(z_helio, RA, dec, e_z_helio=None):
"""
Convert heliocentric redshift to CMB redshift using the Planck 2018 CMB
dipole.
"""
# CMB dipole Planck 2018 values
vsun_mag = 369 # km/s
RA_sun = 167.942
dec_sun = -6.944
SPEED_OF_LIGHT = 299792.458 # km / s
theta_sun = np.pi / 2 - np.deg2rad(dec_sun)
phi_sun = np.deg2rad(RA_sun)
# Convert to theat/phi in radians
theta = np.pi / 2 - np.deg2rad(dec)
phi = np.deg2rad(RA)
# Unit vector in the direction of each galaxy
n = np.asarray([np.sin(theta) * np.cos(phi),
np.sin(theta) * np.sin(phi),
np.cos(theta)]).T
# CMB dipole unit vector
vsun_normvect = np.asarray([np.sin(theta_sun) * np.cos(phi_sun),
np.sin(theta_sun) * np.sin(phi_sun),
np.cos(theta_sun)])
# Project the CMB dipole onto the line of sight and normalize
vsun_projected = vsun_mag * np.dot(n, vsun_normvect) / SPEED_OF_LIGHT
zsun_tilde = np.sqrt((1 - vsun_projected) / (1 + vsun_projected))
zcmb = (1 + z_helio) / zsun_tilde - 1
# Optional linear error propagation
if e_z_helio is not None:
e_zcmb = np.abs(e_z_helio / zsun_tilde)
return zcmb, e_zcmb
return zcmb
###############################################################################
# Statistics #
###############################################################################

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@ -38,7 +38,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@ -63,7 +63,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
@ -86,9 +86,17 @@
},
{
"cell_type": "code",
"execution_count": 138,
"execution_count": 5,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<KeysViewHDF5 ['DEGdeg', 'DEHdeg', 'DEJ2000', 'Host', 'IAUC', 'RAGdeg', 'RAHdeg', 'RAJ2000', 'SNID', 'SimbadName', 'e_vpec', 'e_zHD', 'e_zhel', 'recno', 'vpec', 'vpecG', 'zGHD', 'zGcmb', 'zGhel', 'zHD', 'zcmb', 'zhel']>\n"
]
}
],
"source": [
"fpath_full = \"/mnt/extraspace/rstiskalek/catalogs/PV/Pantheon+SH0ES.dat\"\n",
"fpath_group = \"/mnt/extraspace/rstiskalek/catalogs/PV/pantheon+_groups.hdf5\"\n",
@ -96,22 +104,28 @@
"data_full = np.genfromtxt(fpath_full, names=True, dtype=None, encoding=None)\n",
"data_group = {}\n",
"\n",
"# Read in the groups\n",
"with File(fpath_group, \"r\") as f:\n",
" print(f.keys())\n",
" for key in f.keys():\n",
" data_group[key] = f[key][:]\n",
" try:\n",
" data_group[key] = f[key][...]\n",
" except IndexError:\n",
" print(f\"Failed to read {key}\")\n",
" # data[key] = f[key][...]\n",
"\n",
"# data = data[data[\"zCMB\"] < 0.1]\n",
"\n",
"keys = [\"zCMB\", \"mB\", \"mBERR\", \"x1\", \"x1ERR\", \"c\", \"cERR\", \"RA\", \"DEC\",\n",
" \"VPEC\", \"VPECERR\", \"biasCor_m_b\", \"biasCorErr_m_b\"]\n",
"keys = [\"zCMB\", \"zCMBERR\", \"mB\", \"mBERR\", \"x1\", \"x1ERR\", \"c\", \"cERR\", \"RA\",\n",
" \"DEC\", \"VPEC\", \"VPECERR\", \"biasCor_m_b\", \"biasCorErr_m_b\"]\n",
"pantheon_data = {}\n",
"for key in keys:\n",
" pantheon_data[key] = data[key]\n"
" pantheon_data[key] = data_full[key]\n"
]
},
{
"cell_type": "code",
"execution_count": 139,
"execution_count": 25,
"metadata": {},
"outputs": [
{
@ -133,7 +147,7 @@
},
{
"cell_type": "code",
"execution_count": 142,
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
@ -150,7 +164,7 @@
},
{
"cell_type": "code",
"execution_count": 145,
"execution_count": 27,
"metadata": {},
"outputs": [
{
@ -186,7 +200,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
@ -212,7 +226,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
@ -236,7 +250,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
@ -260,7 +274,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 31,
"metadata": {},
"outputs": [
{
@ -278,7 +292,7 @@
" 2.0177503] deg>"
]
},
"execution_count": 14,
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
@ -294,7 +308,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 32,
"metadata": {},
"outputs": [
{
@ -320,13 +334,6 @@
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
@ -336,7 +343,7 @@
},
{
"cell_type": "code",
"execution_count": 149,
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
@ -360,7 +367,7 @@
},
{
"cell_type": "code",
"execution_count": 151,
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
@ -428,7 +435,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.4"
}
},
"nbformat": 4,

File diff suppressed because one or more lines are too long

View File

@ -160,7 +160,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.4"
}
},
"nbformat": 4,

View File

@ -0,0 +1,404 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Matching of haloes to clusters"
]
},
{
"cell_type": "code",
"execution_count": 144,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The autoreload extension is already loaded. To reload it, use:\n",
" %reload_ext autoreload\n"
]
}
],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from astropy.cosmology import FlatLambdaCDM\n",
"\n",
"import pandas as pd\n",
"\n",
"%load_ext autoreload\n",
"%autoreload 2\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load in the data\n",
"Harry: the exact routine may not work, I had to edit the raw .txt file a little"
]
},
{
"cell_type": "code",
"execution_count": 124,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[34.14606699 9.28692846 11.11279198 16.85641068 3.71636485 33.43032196\n",
" 24.65595192 29.91007806 40.31604335 9.346801 ]\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>halo_ID</th>\n",
" <th>KIND</th>\n",
" <th>l[deg]</th>\n",
" <th>b[deg]</th>\n",
" <th>d[kpc]</th>\n",
" <th>z</th>\n",
" <th>Rdelta[kpc]</th>\n",
" <th>rhos[Msol/kpc^3]</th>\n",
" <th>rs[kpc]</th>\n",
" <th>prof[keywrd]</th>\n",
" <th>#1</th>\n",
" <th>#2</th>\n",
" <th>#3</th>\n",
" <th>FOVDiam[deg]</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>halo_647110</td>\n",
" <td>CLUSTER</td>\n",
" <td>-47.66</td>\n",
" <td>29.96</td>\n",
" <td>-1</td>\n",
" <td>0.01142</td>\n",
" <td>4523.71</td>\n",
" <td>643822.01573</td>\n",
" <td>663.92743</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>37.74875</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>halo_10128802</td>\n",
" <td>CLUSTER</td>\n",
" <td>-90.76</td>\n",
" <td>25.97</td>\n",
" <td>-1</td>\n",
" <td>0.00310</td>\n",
" <td>1975.98</td>\n",
" <td>611499.11522</td>\n",
" <td>294.56973</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>60.00762</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>halo_1338057</td>\n",
" <td>CLUSTER</td>\n",
" <td>-35.42</td>\n",
" <td>-6.15</td>\n",
" <td>-1</td>\n",
" <td>0.00371</td>\n",
" <td>2738.50</td>\n",
" <td>593219.40743</td>\n",
" <td>413.73423</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>69.19885</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>halo_20419495</td>\n",
" <td>CLUSTER</td>\n",
" <td>87.42</td>\n",
" <td>88.09</td>\n",
" <td>-1</td>\n",
" <td>0.00563</td>\n",
" <td>3082.73</td>\n",
" <td>596355.51967</td>\n",
" <td>465.36921</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>51.83070</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>halo_20355327</td>\n",
" <td>CLUSTER</td>\n",
" <td>-94.48</td>\n",
" <td>75.29</td>\n",
" <td>-1</td>\n",
" <td>0.00124</td>\n",
" <td>1644.94</td>\n",
" <td>635981.23866</td>\n",
" <td>240.83028</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>119.66328</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>halo_2503990</td>\n",
" <td>CLUSTER</td>\n",
" <td>-35.24</td>\n",
" <td>-12.06</td>\n",
" <td>-1</td>\n",
" <td>0.01118</td>\n",
" <td>3164.45</td>\n",
" <td>600754.77263</td>\n",
" <td>478.21044</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>27.04669</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>halo_21251859</td>\n",
" <td>CLUSTER</td>\n",
" <td>31.15</td>\n",
" <td>44.45</td>\n",
" <td>-1</td>\n",
" <td>0.00824</td>\n",
" <td>2731.34</td>\n",
" <td>595715.63380</td>\n",
" <td>413.32640</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>31.59913</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>halo_745775</td>\n",
" <td>CLUSTER</td>\n",
" <td>-47.49</td>\n",
" <td>36.08</td>\n",
" <td>-1</td>\n",
" <td>0.01000</td>\n",
" <td>2878.14</td>\n",
" <td>597011.32933</td>\n",
" <td>435.71418</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>27.49495</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>halo_3003328</td>\n",
" <td>CLUSTER</td>\n",
" <td>39.76</td>\n",
" <td>-46.41</td>\n",
" <td>-1</td>\n",
" <td>0.01349</td>\n",
" <td>3172.97</td>\n",
" <td>602266.09230</td>\n",
" <td>479.82208</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>22.50342</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>halo_4200359</td>\n",
" <td>CLUSTER</td>\n",
" <td>-28.67</td>\n",
" <td>-22.77</td>\n",
" <td>-1</td>\n",
" <td>0.00312</td>\n",
" <td>1826.88</td>\n",
" <td>621061.51007</td>\n",
" <td>270.55674</td>\n",
" <td>kZHAO</td>\n",
" <td>1.0</td>\n",
" <td>3.0</td>\n",
" <td>1.0</td>\n",
" <td>55.35257</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" halo_ID KIND l[deg] b[deg] d[kpc] z Rdelta[kpc] \\\n",
"0 halo_647110 CLUSTER -47.66 29.96 -1 0.01142 4523.71 \n",
"1 halo_10128802 CLUSTER -90.76 25.97 -1 0.00310 1975.98 \n",
"2 halo_1338057 CLUSTER -35.42 -6.15 -1 0.00371 2738.50 \n",
"3 halo_20419495 CLUSTER 87.42 88.09 -1 0.00563 3082.73 \n",
"4 halo_20355327 CLUSTER -94.48 75.29 -1 0.00124 1644.94 \n",
"5 halo_2503990 CLUSTER -35.24 -12.06 -1 0.01118 3164.45 \n",
"6 halo_21251859 CLUSTER 31.15 44.45 -1 0.00824 2731.34 \n",
"7 halo_745775 CLUSTER -47.49 36.08 -1 0.01000 2878.14 \n",
"8 halo_3003328 CLUSTER 39.76 -46.41 -1 0.01349 3172.97 \n",
"9 halo_4200359 CLUSTER -28.67 -22.77 -1 0.00312 1826.88 \n",
"\n",
" rhos[Msol/kpc^3] rs[kpc] prof[keywrd] #1 #2 #3 FOVDiam[deg] \n",
"0 643822.01573 663.92743 kZHAO 1.0 3.0 1.0 37.74875 \n",
"1 611499.11522 294.56973 kZHAO 1.0 3.0 1.0 60.00762 \n",
"2 593219.40743 413.73423 kZHAO 1.0 3.0 1.0 69.19885 \n",
"3 596355.51967 465.36921 kZHAO 1.0 3.0 1.0 51.83070 \n",
"4 635981.23866 240.83028 kZHAO 1.0 3.0 1.0 119.66328 \n",
"5 600754.77263 478.21044 kZHAO 1.0 3.0 1.0 27.04669 \n",
"6 595715.63380 413.32640 kZHAO 1.0 3.0 1.0 31.59913 \n",
"7 597011.32933 435.71418 kZHAO 1.0 3.0 1.0 27.49495 \n",
"8 602266.09230 479.82208 kZHAO 1.0 3.0 1.0 22.50342 \n",
"9 621061.51007 270.55674 kZHAO 1.0 3.0 1.0 55.35257 "
]
},
"execution_count": 124,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"cosmo = FlatLambdaCDM(H0=100, Om0=0.307)\n",
"\n",
"data0 = pd.read_csv(\"/mnt/users/rstiskalek/csiborgtools/data/top10_pwave_coords.txt\", sep='\\s+')\n",
"data = {}\n",
"\n",
"data[\"id\"] = np.array([int(x.split(\"_\")[-1]) for x in data0[\"halo_ID\"].values])\n",
"data[\"l\"] = data0[\"l[deg]\"].values\n",
"data[\"b\"] = data0[\"b[deg]\"].values\n",
"data[\"dist\"] = cosmo.comoving_distance(data0[\"z\"].values).value\n",
"\n",
"print(data[\"dist\"])\n",
"data0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load in the halo catalogue"
]
},
{
"cell_type": "code",
"execution_count": 126,
"metadata": {},
"outputs": [],
"source": [
"boxsize = 677.7\n",
"\n",
"halos = np.load(\"/users/hdesmond/Mmain/Mmain_9844.npy\")\n",
"names = [\"id\", \"x\", \"y\", \"z\", \"M\"]\n",
"halos = {k: halos[:, i] for i, k in enumerate(names)}\n",
"halos[\"id\"] = halos[\"id\"].astype(int)\n",
"# Coordinates are in box units. Convert to Mpc/h\n",
"for p in (\"x\", \"y\", \"z\"):\n",
" halos[p] = halos[p] * boxsize\n",
"\n",
"halos[\"dist\"] = np.sqrt((halos[\"x\"] - boxsize/2)**2 + (halos[\"y\"] - boxsize/2)**2 + (halos[\"z\"] - boxsize/2)**2)\n"
]
},
{
"cell_type": "code",
"execution_count": 142,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5791\n"
]
}
],
"source": [
"# Find which item in the catalogue matches the nth halo in the .txt file\n",
"n = 0\n",
"k = np.where(data[\"id\"][n] == halos[\"id\"])[0][0]\n",
"print(k)"
]
},
{
"cell_type": "code",
"execution_count": 143,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(34.14606698507264, 149.24046381654668)"
]
},
"execution_count": 143,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data[\"dist\"][n], halos[\"dist\"][k]"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "venv_csiborg",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -77,9 +77,17 @@ def get_los(catalogue_name, simname, comm):
with File(fname, 'r') as f:
RA = f["RA"][:]
dec = f["DEC"][:]
elif catalogue_name == "UPGLADE":
fname = "/mnt/users/rstiskalek/csiborgtools/data/upglade_z_0p05_all_PROCESSED.h5" # noqa
with File(fname, 'r') as f:
RA = f["RA"][:]
dec = f["DEC"][:]
else:
raise ValueError(f"Unknown field name: `{catalogue_name}`.")
if comm.Get_rank() == 0:
print(f"The dataset contains {len(RA)} objects.")
# The Carrick+2015 is in galactic coordinates, so we need to convert
# the RA/dec to galactic coordinates.
if simname == "Carrick2015":
@ -210,7 +218,7 @@ def combine_from_simulations(catalogue_name, simname, nsims, outfolder,
def interpolate_field(pos, simname, nsim, MAS, grid, dump_folder, rmax,
dr, smooth_scales):
dr, smooth_scales, verbose=False):
"""
Interpolate the density and velocity fields along the line of sight.
@ -243,11 +251,13 @@ def interpolate_field(pos, simname, nsim, MAS, grid, dump_folder, rmax,
fname_out = join(dump_folder, f"los_{simname}_{nsim}.hdf5")
# First do the density field.
if verbose:
print(f"Interpolating density field for IC realisation `{nsim}`.",
flush=True)
density = get_field(simname, nsim, "density", MAS, grid)
rdist, finterp = csiborgtools.field.evaluate_los(
density, sky_pos=pos, boxsize=boxsize, rmax=rmax, dr=dr,
smooth_scales=smooth_scales, verbose=False)
smooth_scales=smooth_scales, verbose=verbose)
print(f"Writing temporary file `{fname_out}`.")
with File(fname_out, 'w') as f:
@ -257,11 +267,14 @@ def interpolate_field(pos, simname, nsim, MAS, grid, dump_folder, rmax,
del density, rdist, finterp
collect()
if verbose:
print(f"Interpolating velocity field for IC realisation `{nsim}`.",
flush=True)
velocity = get_field(simname, nsim, "velocity", MAS, grid)
rdist, finterp = csiborgtools.field.evaluate_los(
velocity[0], velocity[1], velocity[2],
sky_pos=pos, boxsize=boxsize, rmax=rmax, dr=dr,
smooth_scales=smooth_scales, verbose=False)
smooth_scales=smooth_scales, verbose=verbose)
with File(fname_out, 'a') as f:
f.create_dataset("velocity", data=finterp)
@ -308,7 +321,8 @@ if __name__ == "__main__":
def main(nsim):
interpolate_field(pos, args.simname, nsim, args.MAS, args.grid,
dump_folder, rmax, dr, smooth_scales)
dump_folder, rmax, dr, smooth_scales,
verbose=comm.Get_size() == 1)
work_delegation(main, nsims, comm, master_verbose=True)
comm.Barrier()

View File

@ -1,5 +1,5 @@
nthreads=6
memory=42
nthreads=1
memory=32
on_login=0
queue="berg"
env="/mnt/users/rstiskalek/csiborgtools/venv_csiborg/bin/python"

View File

@ -7,8 +7,9 @@ queue="berg"
env="/mnt/users/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="flow_validation.py"
#"Pantheon+_zSN"
catalogue="Pantheon+_groups"
simname="csiborg2_varysmall"
simname="Carrick2015"
pythoncm="$env $file --catalogue $catalogue --simname $simname --ksmooth $ksmooth"

View File

@ -0,0 +1,165 @@
# Copyright (C) 2023 Richard Stiskalek
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
A script to calculate the bulk flow in Quijote to compare the volume average
definition to various estimators that rely on radial velocities (e.g. Nusser
2014 and Peery+2018).
"""
from argparse import ArgumentParser
from datetime import datetime
from os import remove
from os.path import join
import csiborgtools
import numpy as np
from mpi4py import MPI
from taskmaster import work_delegation # noqa
###############################################################################
# Read in information about the simulation #
###############################################################################
def t():
return datetime.now()
def get_reader(simname, paths, nsim):
"""Get the appropriate snaspshot reader for the simulation."""
# We only want Quijote because it has all particles of the same mass.
if simname == "quijote":
# We want the z = 0 snapshots
reader = csiborgtools.read.QuijoteSnapshot(nsim, 4, paths)
else:
raise ValueError(f"Unknown simname: `{simname}`.")
return reader
def get_particles(reader, verbose=True):
"""
Get the distance of particles from the center of the box and their masses.
"""
if verbose:
print(f"{t()},: reading coordinates and calculating radial distance.")
pos = reader.coordinates().astype(np.float64)
vel = reader.velocities().astype(np.float64)
return pos, vel
###############################################################################
# Main & command line interface #
###############################################################################
def main(simname, nsim, folder, Rmax):
observers = csiborgtools.read.fiducial_observers(boxsize, Rmax)
distances = np.linspace(0, Rmax, 101)[1:]
reader = get_reader(simname, paths, nsim)
pos, vel = get_particles(reader, verbose=False)
mass = np.ones(len(pos)) # Quijote has equal masses
bf_volume = np.full((len(observers), len(distances), 3), np.nan)
bf_peery = np.full_like(bf_volume, np.nan)
bf_const = np.full_like(bf_volume, np.nan)
for i in range(len(observers)):
print(f"{t()}: Calculating bulk flow for observer {i + 1} of simulation {nsim}.") # noqa
# Subtract the observer position.
pos_current = pos - observers[i]
# Get the distance of each particle from the observer and sort it.
rdist = np.linalg.norm(pos_current, axis=1)
indxs = np.argsort(rdist)
pos_current = pos_current[indxs]
vel_current = vel[indxs]
rdist = rdist[indxs]
# Volume average
bf_volume[i, ...] = csiborgtools.field.particles_enclosed_momentum(
rdist, mass, vel_current, distances)
bf_volume[i, ...] /= csiborgtools.field.particles_enclosed_mass(
rdist, mass, distances)[:, np.newaxis]
# Peery 2018 1 / r^2 weighted
bf_peery[i, ...] = csiborgtools.field.bulkflow_peery2018(
rdist, mass, pos_current, vel_current, distances, "1/r^2",
verbose=False)
# Constant weight
bf_const[i, ...] = csiborgtools.field.bulkflow_peery2018(
rdist, mass, pos_current, vel_current, distances, "constant",
verbose=False)
# Finally save the output
fname = join(folder, f"bf_estimators_addconstant_{simname}_{nsim}.npz")
print(f"Saving to `{fname}`.")
np.savez(fname, bf_volume=bf_volume, bf_peery=bf_peery, bf_const=bf_const,
distances=distances)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("--simname", type=str, help="Simulation name.",
choices=["quijote"]) # noqa
args = parser.parse_args()
Rmax = 150
folder = "/mnt/extraspace/rstiskalek/csiborg_postprocessing/field_shells"
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
boxsize = csiborgtools.simname2boxsize(args.simname)
def main_wrapper(nsim):
main(args.simname, nsim, folder, Rmax)
nsims = list(paths.get_ics(args.simname))
if rank == 0:
print(f"Running with {len(nsims)} Quijote simulations.")
comm.Barrier()
work_delegation(main_wrapper, nsims, comm, master_verbose=True)
comm.Barrier()
# Collect the results
if rank == 0:
for i, nsim in enumerate(nsims):
fname = join(folder, f"bf_estimators_{args.simname}_{nsim}.npz")
data = np.load(fname)
if i == 0:
bf_volume = np.empty((len(nsims), *data["bf_volume"].shape))
bf_peery = np.empty_like(bf_volume)
bf_const = np.empty_like(bf_volume)
distances = data["distances"]
bf_volume[i, ...] = data["bf_volume"]
bf_peery[i, ...] = data["bf_peery"]
bf_const[i, ...] = data["bf_const"]
# Remove file from this rank
remove(fname)
# Save the results
fname = join(folder, f"bf_estimators_{args.simname}.npz")
print(f"Saving final results to `{fname}`.")
np.savez(fname, bf_volume=bf_volume, bf_peery=bf_peery,
bf_const=bf_const, distances=distances)

View File

@ -0,0 +1,21 @@
nthreads=20
memory=24
on_login=0
queue="berg"
env="/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="field_bulk_estimator.py"
simname="quijote"
pythoncm="$env $file --simname $simname"
if [ $on_login -eq 1 ]; then
echo $pythoncm
$pythoncm
else
cm="addqueue -q $queue -n $nthreads -m $memory $pythoncm"
echo "Submitting:"
echo $cm
echo
eval $cm
fi

162
scripts/post_upglade.py Normal file
View File

@ -0,0 +1,162 @@
# Copyright (C) 2024 Richard Stiskalek
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Script to calculate cosmological redshifts from observed redshifts assuming
the Carrick+2015 peculiar velocity model. In the future this may be extended
to include other peculiar velocity models.
"""
from datetime import datetime
from os import remove
from os.path import join
import csiborgtools
import numpy as np
from h5py import File
from mpi4py import MPI
from taskmaster import work_delegation # noqa
from tqdm import tqdm
SPEED_OF_LIGHT = 299792.458 # km / s
def t():
return datetime.now().strftime("%H:%M:%S")
def load_calibration(catalogue, simname, nsim, ksmooth, verbose=False):
"""Load the pre-computed calibration samples."""
fname = f"/mnt/extraspace/rstiskalek/csiborg_postprocessing/peculiar_velocity/flow_samples_{catalogue}_{simname}_smooth_{ksmooth}.hdf5" # noqa
keys = ["Vext_x", "Vext_y", "Vext_z", "alpha", "beta", "sigma_v"]
calibration_samples = {}
with File(fname, 'r') as f:
for key in keys:
# NOTE: here the posterior samples are down-sampled
calibration_samples[key] = f[f"sim_{nsim}/{key}"][:][::10]
if verbose:
k = list(calibration_samples.keys())[0]
nsamples = len(calibration_samples[k])
print(f"{t()}: found {nsamples} calibration posterior samples.",
flush=True)
return calibration_samples
def main(loader, model, indxs, fdir, fname, num_split, verbose):
out = np.full(
len(indxs), np.nan,
dtype=[("mean_zcosmo", float), ("std_zcosmo", float)])
# Process each galaxy in this split
for i, n in enumerate(tqdm(indxs, desc=f"Split {num_split}",
disable=not verbose)):
x, y = model.posterior_zcosmo(
loader.cat["zcmb"][n], loader.cat["RA"][n], loader.cat["DEC"][n],
loader.los_density[n], loader.los_radial_velocity[n],
extra_sigma_v=loader.cat["e_zcmb"][n] * SPEED_OF_LIGHT,
verbose=False)
mu, std = model.posterior_mean_std(x, y)
out["mean_zcosmo"][i], out["std_zcosmo"][i] = mu, std
# Save the results of this rank
fname = join(fdir, f"{fname}_{num_split}.hdf5")
with File(fname, 'w') as f:
f.create_dataset("mean_zcosmo", data=out["mean_zcosmo"])
f.create_dataset("std_zcosmo", data=out["std_zcosmo"])
f.create_dataset("indxs", data=indxs)
###############################################################################
# Command line interface #
###############################################################################
if __name__ == "__main__":
comm = MPI.COMM_WORLD
rank, size = comm.Get_rank(), comm.Get_size()
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
# Calibration parameters
simname = "Carrick2015"
ksmooth = 0
nsim = 0
catalogue_calibration = "Pantheon+_zSN"
# Galaxy sample parameters
catalogue = "UPGLADE"
fpath_data = "/mnt/users/rstiskalek/csiborgtools/data/upglade_z_0p05_all_PROCESSED.h5" # noqa
# Number of splits for MPI
nsplits = 1000
# Folder to save the results
fdir = "/mnt/extraspace/rstiskalek/csiborg_postprocessing/peculiar_velocity/UPGLADE" # noqa
fname = f"zcosmo_{catalogue}"
# Load in the data, calibration samples and the model
loader = csiborgtools.flow.DataLoader(
simname, nsim, catalogue, fpath_data, paths, ksmooth=ksmooth,
verbose=rank == 0)
calibration_samples = load_calibration(
catalogue_calibration, simname, nsim, ksmooth, verbose=rank == 0)
model = csiborgtools.flow.Observed2CosmologicalRedshift(
calibration_samples, loader.rdist, loader._Omega_m)
if rank == 0:
print(f"{t()}: the catalogue size is {loader.cat['zcmb'].size}.")
print(f"{t()}: loaded calibration samples and model.", flush=True)
# Decide how to split up the job
if rank == 0:
indxs = np.arange(loader.cat["zcmb"].size)
split_indxs = np.array_split(indxs, nsplits)
else:
indxs = None
split_indxs = None
indxs = comm.bcast(indxs, root=0)
split_indxs = comm.bcast(split_indxs, root=0)
# Process all splits with MPI, the rank 0 delegates the jobs.
def main_wrapper(n):
main(loader, model, split_indxs[n], fdir, fname, n, verbose=size == 1)
comm.Barrier()
work_delegation(
main_wrapper, list(range(nsplits)), comm, master_verbose=True)
comm.Barrier()
# Combine the results to a single file
if rank == 0:
print("Combining results from all ranks.", flush=True)
mean_zcosmo = np.full(loader.cat["zcmb"].size, np.nan)
std_zcosmo = np.full_like(mean_zcosmo, np.nan)
for n in range(nsplits):
fname_current = join(fdir, f"{fname}_{n}.hdf5")
with File(fname_current, 'r') as f:
mask = f["indxs"][:]
mean_zcosmo[mask] = f["mean_zcosmo"][:]
std_zcosmo[mask] = f["std_zcosmo"][:]
remove(fname_current)
# Save the results
fname = join(fdir, f"{fname}.hdf5")
print(f"Saving results to `{fname}`.")
with File(fname, 'w') as f:
f.create_dataset("mean_zcosmo", data=mean_zcosmo)
f.create_dataset("std_zcosmo", data=std_zcosmo)
f.create_dataset("indxs", data=indxs)

31
scripts/post_upglade.sh Executable file
View File

@ -0,0 +1,31 @@
nthreads=${1}
on_login=${2}
memory=4
queue="redwood"
env="/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="post_upglade.py"
if [[ "$on_login" != "0" && "$on_login" != "1" ]]
then
echo "Error: on_login must be either 0 or 1."
exit 1
fi
if ! [[ "$nthreads" =~ ^[0-9]+$ ]] || [ "$nthreads" -le 0 ]; then
echo "Error: nthreads must be an integer larger than 0."
exit 1
fi
pythoncm="$env $file"
if [ $on_login -eq 1 ]; then
echo $pythoncm
$pythoncm
else
cm="addqueue -q $queue -n $nthreads -m $memory $pythoncm"
echo "Submitting:"
echo $cm
echo
eval $cm
fi

199
scripts/quijote_bulkflow.py Normal file
View File

@ -0,0 +1,199 @@
# Copyright (C) 2023 Richard Stiskalek
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
A script to calculate the bulk flow in Quijote simulations from either
particles or FoF haloes and to also save the resulting smaller halo catalogues.
"""
from datetime import datetime
from os.path import join
import csiborgtools
import numpy as np
from mpi4py import MPI
from taskmaster import work_delegation # noqa
from warnings import catch_warnings, simplefilter
from h5py import File
from sklearn.neighbors import NearestNeighbors
###############################################################################
# Read in information about the simulation #
###############################################################################
def t():
return datetime.now()
def get_data(nsim, verbose=True):
if verbose:
print(f"{t()}: reading particles of simulation `{nsim}`.")
reader = csiborgtools.read.QuijoteSnapshot(nsim, 4, paths)
part_pos = reader.coordinates().astype(np.float64)
part_vel = reader.velocities().astype(np.float64)
if verbose:
print(f"{t()}: reading haloes of simulation `{nsim}`.")
reader = csiborgtools.read.QuijoteCatalogue(nsim)
halo_pos = reader.coordinates
halo_vel = reader.velocities
halo_mass = reader.totmass
return part_pos, part_vel, halo_pos, halo_vel, halo_mass
def volume_bulk_flow(rdist, mass, vel, distances):
out = csiborgtools.field.particles_enclosed_momentum(
rdist, mass, vel, distances)
with catch_warnings():
simplefilter("ignore", category=RuntimeWarning)
out /= csiborgtools.field.particles_enclosed_mass(
rdist, mass, distances)[:, np.newaxis]
return out
###############################################################################
# Main & command line interface #
###############################################################################
def main(nsim, folder, fname_basis, Rmax, subtract_observer_velocity,
verbose=True):
boxsize = csiborgtools.simname2boxsize("quijote")
observers = csiborgtools.read.fiducial_observers(boxsize, Rmax)
distances = np.linspace(0, Rmax, 101)[1:]
part_pos, part_vel, halo_pos, halo_vel, halo_mass = get_data(nsim, verbose)
if verbose:
print(f"{t()}: Fitting the particle and halo trees of simulation `{nsim}`.") # noqa
part_tree = NearestNeighbors().fit(part_pos)
halo_tree = NearestNeighbors().fit(halo_pos)
samples = {}
bf_volume_part = np.full((len(observers), len(distances), 3), np.nan)
bf_volume_halo = np.full_like(bf_volume_part, np.nan)
bf_volume_halo_uniform = np.full_like(bf_volume_part, np.nan)
bf_vrad_weighted_part = np.full_like(bf_volume_part, np.nan)
bf_vrad_weighted_halo_uniform = np.full_like(bf_volume_part, np.nan)
bf_vrad_weighted_halo = np.full_like(bf_volume_part, np.nan)
for i in range(len(observers)):
print(f"{t()}: Calculating bulk flow for observer {i + 1} of simulation {nsim}.") # noqa
# Select particles within Rmax of the observer
rdist_part, indxs = part_tree.radius_neighbors(
np.asarray(observers[i]).reshape(1, -1), Rmax,
return_distance=True, sort_results=True)
rdist_part, indxs = rdist_part[0], indxs[0]
part_pos_current = part_pos[indxs] - observers[i]
part_vel_current = part_vel[indxs]
# Quijote particle masses are all equal
part_mass = np.ones_like(rdist_part)
# Select haloes within Rmax of the observer
rdist_halo, indxs = halo_tree.radius_neighbors(
np.asarray(observers[i]).reshape(1, -1), Rmax,
return_distance=True, sort_results=True)
rdist_halo, indxs = rdist_halo[0], indxs[0]
halo_pos_current = halo_pos[indxs] - observers[i]
halo_vel_current = halo_vel[indxs]
halo_mass_current = halo_mass[indxs]
# Subtract the observer velocity
if subtract_observer_velocity:
rscale = 0.5 # Mpc / h
weights = np.exp(-0.5 * (rdist_part / rscale)**2)
obs_vel_x = np.average(part_vel_current[:, 0], weights=weights)
obs_vel_y = np.average(part_vel_current[:, 1], weights=weights)
obs_vel_z = np.average(part_vel_current[:, 2], weights=weights)
part_vel_current[:, 0] -= obs_vel_x
part_vel_current[:, 1] -= obs_vel_y
part_vel_current[:, 2] -= obs_vel_z
halo_vel_current[:, 0] -= obs_vel_x
halo_vel_current[:, 1] -= obs_vel_y
halo_vel_current[:, 2] -= obs_vel_z
# Calculate the volume average bulk flows
bf_volume_part[i, ...] = volume_bulk_flow(
rdist_part, part_mass, part_vel_current, distances)
bf_volume_halo[i, ...] = volume_bulk_flow(
rdist_halo, halo_mass_current, halo_vel_current, distances)
bf_volume_halo_uniform[i, ...] = volume_bulk_flow(
rdist_halo, np.ones_like(halo_mass_current), halo_vel_current,
distances)
bf_vrad_weighted_part[i, ...] = csiborgtools.field.bulkflow_peery2018(
rdist_part, part_mass, part_pos_current, part_vel_current,
distances, weights="1/r^2", verbose=False)
# Calculate the bulk flow from projected velocities w. 1/r^2 weights
bf_vrad_weighted_halo_uniform[i, ...] = csiborgtools.field.bulkflow_peery2018( # noqa
rdist_halo, np.ones_like(halo_mass_current), halo_pos_current,
halo_vel_current, distances, weights="1/r^2", verbose=False)
bf_vrad_weighted_halo[i, ...] = csiborgtools.field.bulkflow_peery2018(
rdist_halo, halo_mass_current, halo_pos_current,
halo_vel_current, distances, weights="1/r^2", verbose=False)
# Store the haloes around this observer
samples[i] = {
"halo_pos": halo_pos_current,
"halo_vel": halo_vel_current,
"halo_mass": halo_mass_current}
# Finally save the output
fname = join(folder, f"{fname_basis}_{nsim}.hdf5")
if verbose:
print(f"Saving to `{fname}`.")
with File(fname, 'w') as f:
f["distances"] = distances
f["bf_volume_part"] = bf_volume_part
f["bf_volume_halo"] = bf_volume_halo
f["bf_vrad_weighted_part"] = bf_vrad_weighted_part
f["bf_volume_halo_uniform"] = bf_volume_halo_uniform
f["bf_vrad_weighted_halo_uniform"] = bf_vrad_weighted_halo_uniform
f["bf_vrad_weighted_halo"] = bf_vrad_weighted_halo
for i in range(len(observers)):
g = f.create_group(f"obs_{str(i)}")
g["halo_pos"] = samples[i]["halo_pos"]
g["halo_vel"] = samples[i]["halo_vel"]
g["halo_mass"] = samples[i]["halo_mass"]
if __name__ == "__main__":
Rmax = 150
subtract_observer_velocity = True
folder = "/mnt/extraspace/rstiskalek/quijote/BulkFlow_fiducial"
fname_basis = "sBF_nsim" if subtract_observer_velocity else "BF_nsim"
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
nsims = list(paths.get_ics("quijote"))
def main_wrapper(nsim):
main(nsim, folder, fname_basis, Rmax, subtract_observer_velocity,
verbose=rank == 0)
if rank == 0:
print(f"Running with {len(nsims)} Quijote simulations.")
comm.Barrier()
work_delegation(main_wrapper, nsims, comm, master_verbose=True)

19
scripts/quijote_bulkflow.sh Executable file
View File

@ -0,0 +1,19 @@
nthreads=20
memory=24
on_login=0
queue="berg"
env="/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="quijote_bulkflow.py"
pythoncm="$env $file"
if [ $on_login -eq 1 ]; then
echo $pythoncm
$pythoncm
else
cm="addqueue -q $queue -n $nthreads -m $memory $pythoncm"
echo "Submitting:"
echo $cm
echo
eval $cm
fi

View File

@ -14,6 +14,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from os import system
if __name__ == "__main__":
# chains = [15717, 15817, 15917, 16017, 16117, 16217, 16317, 16417, 16517,
# 16617, 16717, 16817, 16917, 17017, 17117, 17217, 17317, 17417]
@ -28,12 +29,15 @@ if __name__ == "__main__":
# simname = "csiborg2_random"
# mode = 1
chains = [7444 + n * 24 for n in range(101)]
simname = "csiborg1"
mode = 2
# chains = [7444 + n * 24 for n in range(101)]
# simname = "csiborg1"
# mode = 2
chains = [i for i in range(41, 50 + 1)]
simname = "quijote"
mode = 0
env = "/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
memory = 64
memory = 32
for chain in chains:
out = f"output_{simname}_{chain}_%j.out"