Add CLONES support (#145)

* Add submit script

* Add support for gadget2

* Add OMP

* Lower resolution

* Update resolution again

* Add selection on galactic latitude

* Update name

* Update nb

* Update nb

* Add CLONES params

* Add import

* Add CLONES path

* Add CLONES reader

* Quick fix

* Add CLONES

* Update slice nb

* Update nb

* Update nb

* Tiny updates

* Update nb

* Add name

* Add CLONES support

* Add CF4 field

* Add CLONES

* Update script

* Update nb

* Update nb
This commit is contained in:
Richard Stiskalek 2024-09-12 17:04:25 +02:00 committed by GitHub
parent a4d02b4cc4
commit 32e36afdc3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 874 additions and 214 deletions

View file

@ -93,7 +93,7 @@ class DataLoader:
if simname in ["Carrick2015", "Lilow2024"]:
# Carrick+2015 and Lilow+2024 are in galactic coordinates
d1, d2 = radec_to_galactic(self._cat["RA"], self._cat["DEC"])
elif "CF4" in simname:
elif simname in ["CF4", "CLONES"]:
# CF4 is in supergalactic coordinates
d1, d2 = radec_to_supergalactic(self._cat["RA"], self._cat["DEC"])
else:
@ -117,8 +117,8 @@ class DataLoader:
self._Omega_m = simname2Omega_m(simname)
# Normalize the CSiBORG density by the mean matter density
if "csiborg" in simname:
# Normalize the CSiBORG & CLONES density by the mean matter density
if "csiborg" in simname or simname == "CLONES":
cosmo = FlatLambdaCDM(H0=H0, Om0=self._Omega_m)
mean_rho_matter = cosmo.critical_density0.to("Msun/kpc^3").value
mean_rho_matter *= self._Omega_m
@ -1013,6 +1013,7 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None):
"not_matched_to_2MTF_or_SFI", "Qs", "Qw"]
RA, dec, z_obs, mag, eta, e_eta, not_matched_to_2MTF_or_SFI, Qs, Qw = (
loader.cat[k] for k in keys)
l, b = radec_to_galactic(RA, dec)
not_matched_to_2MTF_or_SFI = not_matched_to_2MTF_or_SFI.astype(bool)
# NOTE: fiducial uncertainty until we can get the actual values.
@ -1023,6 +1024,8 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None):
fprint("selecting only galaxies with mag > 5 and eta > -0.3.")
mask = (mag > 5) & (eta > -0.3)
fprint("selecting only galaxies with |b| > 7.5.")
mask &= np.abs(b) > 7.5
mask &= (z_obs < zcmb_max) & (z_obs > zcmb_min)
if "not2MTForSFI" in kind:

View file

@ -80,6 +80,7 @@ def simname2boxsize(simname):
"CF4": 1000., # These need to be checked with Helene Courtois.
"CF4gp": 1000.,
"Lilow2024": 400.,
"CLONES": 500.,
}
boxsize = d.get(simname, None)
@ -106,6 +107,7 @@ def simname2Omega_m(simname):
"IndranilVoid_exp": 0.3,
"IndranilVoid_gauss": 0.3,
"no_field": 0.3,
"CLONES": 0.307115,
}
omega_m = d.get(simname, None)

View file

@ -19,7 +19,8 @@ from .catalogue import (CSiBORG1Catalogue, CSiBORG2Catalogue,
from .snapshot import (CSiBORG1Snapshot, CSiBORG2Snapshot, QuijoteSnapshot, # noqa
CSiBORG1Field, CSiBORG2Field, CSiBORG2XField, # noqa
QuijoteField, BORG2Field, BORG1Field, TNG300_1Field, # noqa
Carrick2015Field, Lilow2024Field) # noqa
Carrick2015Field, Lilow2024Field, CLONESField, # noqa
CF4Field) # noqa
from .obs import (SDSS, MCXCClusters, PlanckClusters, TwoMPPGalaxies, # noqa
TwoMPPGroups, ObservedCluster, match_array_to_no_masking, # noqa
cols_to_structured, read_pantheonplus_data) # noqa

View file

@ -125,7 +125,7 @@ class Paths:
files = [int(file) for file in files]
# Downsample to only 20 realisations
files = files[::5]
elif simname in ["Carrick2015", "Lilow2024", "no_field"]:
elif simname in ["Carrick2015", "Lilow2024", "no_field", "CLONES"]:
files = [0]
elif "IndranilVoid" in simname:
kind = simname.split("_")[-1]
@ -411,6 +411,18 @@ class Paths:
else:
raise ValueError(f"Unsupported Lilow2024 field: `{kind}`.")
if simname == "CF4":
basedir = "/mnt/extraspace/rstiskalek/catalogs/CF4"
if kind == "overdensity":
return join(
basedir, f"CF4_new_128-z008_realization{nsim}_delta.fits")
elif kind == "velocity":
return join(
basedir,
f"CF4_new_128-z008_realization{nsim}_velocity.fits")
else:
raise ValueError(f"Unsupported CF4 field: `{kind}`.")
if MAS == "SPH" and kind in ["density", "velocity"]:
if simname == "csiborg1":
return join(self.csiborg1_srcdir, "field",
@ -426,6 +438,13 @@ class Paths:
f"chain_{nsim}_{grid}.hdf5")
elif simname == "quijote":
raise ValueError("SPH field not available for CSiBORG1.")
elif simname == "CLONES":
# NOTE eventually stop using local paths
basedir = "/mnt/extraspace/rstiskalek/CLONES/s8"
fname = "cf2gvpecc1pt5elmo73_sig6distribsbvoldi_RZA3Derrv2_512_500_ss8_zinit60_000.hdf5" # noqa
return join(basedir, fname)
else:
raise ValueError(f"Unsupported simulation name `{simname}`.")
fdir = join(self.postdir, "environment")
try_create_directory(fdir)

View file

@ -21,6 +21,7 @@ from abc import ABC, abstractmethod
from os.path import join
import numpy as np
from astropy.io import fits
from h5py import File
from ..params import paths_glamdring, simname2boxsize, simname2Omega_m
@ -813,6 +814,55 @@ class CSiBORG2XField(BaseField):
raise RuntimeError("The radial velocity field is not available.")
###############################################################################
# CLONES field #
###############################################################################
class CLONESField(BaseField):
"""
CLONES `z = 0` field class in supergalactic Cartesian coordinates.
Parameters
----------
nsim : int
Simulation index.
paths : Paths, optional
Paths object. By default, the paths are set to the `glamdring` paths.
"""
def __init__(self, nsim, paths=None):
super().__init__(nsim, paths, flip_xz=False)
def density_field(self, MAS, grid):
fpath = self.paths.field("density", MAS, grid, self.nsim, "CLONES")
if MAS == "SPH":
with File(fpath, "r") as f:
field = f["density"][:]
field /= (500 * 1e3 / grid)**3 # Convert to h^2 Msun / kpc^3
else:
field = np.load(fpath)
return field
def velocity_field(self, MAS, grid):
fpath = self.paths.field("velocity", MAS, grid, self.nsim, "CLONES")
if MAS == "SPH":
with File(fpath, "r") as f:
density = f["density"][:]
v0 = f["p0"][:] / density
v1 = f["p1"][:] / density
v2 = f["p2"][:] / density
field = np.array([v0, v1, v2])
else:
field = np.load(fpath)
return field
def radial_velocity_field(self, MAS, grid):
raise RuntimeError("The radial velocity field is not available.")
###############################################################################
# BORG1 field class #
###############################################################################
@ -1008,7 +1058,7 @@ class Lilow2024Field(BaseField):
def overdensity_field(self, **kwargs):
fpath = self.paths.field(
"overdensity", None, None, self.nsim, "Lilow2024")
"overdensity", None, None, self.nsim, "CF4")
return np.load(fpath) - 1
def density_field(self, **kwargs):
@ -1033,6 +1083,47 @@ class Lilow2024Field(BaseField):
raise RuntimeError("The radial velocity field is not available.")
class CF4Field(BaseField):
"""
CF4 Courtois+2023 `z = 0` field class. The field is in supergalactic
coordinates.
Parameters
----------
nsim : int
Simulation index.
paths : Paths, optional
Paths object. By default, the paths are set to the `glamdring` paths.
"""
def __init__(self, nsim, paths=None):
super().__init__(nsim, paths, False)
def overdensity_field(self, **kwargs):
fpath = self.paths.field(
"overdensity", None, None, self.nsim, "CF4")
return fits.open(fpath)[0].data.astype(np.float32)
def density_field(self, **kwargs):
field = self.overdensity_field()
omega0 = simname2Omega_m("CF4")
rho_mean = omega0 * 277.53662724583074 # Msun / kpc^3
field += 1
field *= rho_mean
return field
def velocity_field(self, **kwargs):
fpath = self.paths.field(
"velocity", None, None, self.nsim, "CF4")
field = fits.open(fpath)[0].data
# https://projets.ip2i.in2p3.fr//cosmicflows/ says to multiply by 52
field *= 52
return field.astype(np.float32)
def radial_velocity_field(self, **kwargs):
raise RuntimeError("The radial velocity field is not available.")
###############################################################################
# Supplementary functions #
###############################################################################

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -154,8 +154,9 @@ def simname_to_pretty(simname):
"csiborg1": "CB1",
"csiborg2_main": "CB2",
"csiborg2X": "Manticore",
"CF4": "CF4",
"CF4": "Courtois+23",
"CF4gp": "CF4group",
"CLONES": "Sorce+2018",
}
if isinstance(simname, list):

File diff suppressed because one or more lines are too long

View file

@ -189,20 +189,29 @@ def main_from_field(args, folder):
for i, nsim in enumerate(tqdm(nsims, desc="Simulations")):
if args.simname == "csiborg2X":
reader = csiborgtools.read.CSiBORG2XField(nsim, paths)
kwargs = {}
elif args.simname == "CF4":
reader = csiborgtools.read.CF4Field(nsim, paths)
kwargs = {}
elif args.simname == "CLONES":
reader = csiborgtools.read.CLONESField(nsim, paths)
kwargs = {"MAS": "SPH", "grid": 1024}
elif args.simname == "Carrick2015":
reader = csiborgtools.read.Carrick2015Field(paths)
kwargs = {}
elif args.simname == "Lilow2024":
reader = csiborgtools.read.Lilow2024Field(paths)
kwargs = {}
else:
raise ValueError(f"Unknown simname: `{args.simname}`.")
density_field = reader.density_field()
density_field = reader.density_field(**kwargs)
cumulative_mass[i, :], cumulative_volume[i, :] = field_enclosed_mass(
density_field, distances, boxsize, verbose=False)
del density_field
collect()
velocity_field = reader.velocity_field()
velocity_field = reader.velocity_field(**kwargs)
radial_velocity_field = csiborgtools.field.radial_velocity(
velocity_field, [0., 0., 0.])
@ -235,6 +244,19 @@ def main_from_field(args, folder):
cumulative_vel_y = icrs_cartesian.y.to(u.km/u.s).value
cumulative_vel_z = icrs_cartesian.z.to(u.km/u.s).value
if args.simname in ["CLONES", "CF4"]:
# CLONES is in supergalactic coordinates.
supergalactic_cartesian = CartesianRepresentation(
cumulative_vel_x, cumulative_vel_y, cumulative_vel_z,
unit=u.km/u.s)
supergalactic_coord = SkyCoord(
supergalactic_cartesian, frame='supergalactic')
icrs_cartesian = supergalactic_coord.icrs.cartesian
cumulative_vel_x = icrs_cartesian.x.to(u.km/u.s).value
cumulative_vel_y = icrs_cartesian.y.to(u.km/u.s).value
cumulative_vel_z = icrs_cartesian.z.to(u.km/u.s).value
cumulative_vel = np.stack(
[cumulative_vel_x, cumulative_vel_y, cumulative_vel_z], axis=-1)
cumulative_vel /= cumulative_volume[..., None]
@ -260,11 +282,12 @@ if __name__ == "__main__":
parser.add_argument("--simname", type=str, help="Simulation name.",
choices=["csiborg1", "csiborg2_main", "csiborg2_varysmall", "csiborg2_random", # noqa
"borg1", "borg2", "borg2_all", "csiborg2X", "Carrick2015", # noqa
"Lilow2024"]) # noqa
"Lilow2024", "CLONES", "CF4"]) # noqa
args = parser.parse_args()
folder = "/mnt/extraspace/rstiskalek/csiborg_postprocessing/field_shells"
if args.simname in ["csiborg2X", "Carrick2015", "Lilow2024"]:
if args.simname in ["csiborg2X", "Carrick2015", "Lilow2024",
"CLONES", "CF4"]:
main_from_field(args, folder)
elif "csiborg" in args.simname:
main_csiborg(args, folder)

View file

@ -1,6 +1,6 @@
nthreads=1
memory=48
on_login=0
on_login=1
queue="berg"
env="/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="field_bulk.py"

View file

@ -107,8 +107,8 @@ def get_los(catalogue_name, simname, comm):
# we need to convert the RA/dec to galactic coordinates.
c = SkyCoord(ra=RA*u.degree, dec=dec*u.degree, frame='icrs')
pos = np.vstack((c.galactic.l, c.galactic.b)).T
elif "CF4" in simname:
# CF4 fields are in supergalactic coordinates.
elif simname in ["CF4", "CLONES"]:
# CF4 and CLONES fields are in supergalactic coordinates.
c = SkyCoord(ra=RA*u.degree, dec=dec*u.degree, frame='icrs')
pos = np.vstack((c.supergalactic.sgl, c.supergalactic.sgb)).T
else:
@ -148,6 +148,8 @@ def get_field(simname, nsim, kind, MAS, grid):
field_reader = csiborgtools.read.CSiBORG2Field(nsim, simkind)
elif simname == "csiborg2X":
field_reader = csiborgtools.read.CSiBORG2XField(nsim)
elif simname == "CLONES":
field_reader = csiborgtools.read.CLONESField(nsim)
elif simname == "Carrick2015":
folder = "/mnt/extraspace/rstiskalek/catalogs"
warn(f"Using local paths from `{folder}`.", RuntimeWarning)

View file

@ -1,5 +1,5 @@
nthreads=1
memory=64
memory=48
on_login=${1}
queue="berg"
env="/mnt/users/rstiskalek/csiborgtools/venv_csiborg/bin/python"
@ -19,8 +19,9 @@ fi
# for simname in "csiborg1" "csiborg2_main" "csiborg2X" "Lilow2024" "Carrick2015" "CF4"; do
for simname in "csiborg2_main"; do
for catalogue in "2MTF" "SFI_gals" "CF4_TFR"; do
for simname in "CLONES"; do
# for catalogue in "2MTF" "SFI_gals" "CF4_TFR"; do
for catalogue in "Foundation" "2MTF" "SFI_gals" "CF4_TFR"; do
pythoncm="$env $file --catalogue $catalogue --nsims $nsims --simname $simname --MAS $MAS --grid $grid"
if [ $on_login -eq 1 ]; then
echo $pythoncm

View file

@ -44,9 +44,7 @@ def interpolate_indranil_void(kind, nsims, RA, dec, rmax, dr, dump_folder,
# The grid is in Mpc
r_grid = np.arange(0, 251)
# NOTE: The shape of the files is no longer (181, 251). It is now
# (180, 251), asked Sergij about this. He will produce new files.
phi_grid = np.arange(0, len(data))
phi_grid = np.arange(0, 181)
# The input is in Mpc/h, so we need to convert to Mpc
r_eval = np.arange(0, rmax, dr).astype(float) / 0.674
@ -83,7 +81,7 @@ def interpolate_indranil_void(kind, nsims, RA, dec, rmax, dr, dump_folder,
if __name__ == "__main__":
kind = "exp"
kind = "gauss"
rmax = 165
dr = 1
@ -93,7 +91,7 @@ if __name__ == "__main__":
out_folder = "/mnt/extraspace/rstiskalek/csiborg_postprocessing/field_los"
for catalogue in ["LOSS", "Foundation", "2MTF", "SFI_gals", "CF4_TFR", "CF4_GroupAll"]: # noqa
for catalogue in ["LOSS", "Foundation", "2MTF", "SFI_gals", "CF4_TFR"]:
print(f"Running kind `{kind}` for catalogue `{catalogue}`.")
RA, dec = get_los(catalogue, "", comm).T

View file

@ -37,24 +37,27 @@ else
fi
for simname in "IndranilVoid_gauss"; do
# for simname in "CLONES"; do
# for simname in "csiborg2_main" "csiborg2X" ; do
# for simname in "Carrick2015" "Lilow2024" "csiborg2_main" "csiborg2X" "CF4"; do
# for simname in "carrick2015" "lilow2024" "csiborg2_main" "csiborg2x" "cf4" "clones"; do
for simname in "Carrick2015" "csiborg2_main"; do
# for simname in "Carrick2015" "csiborg2X" "csiborg2_main"; do
# for simname in "Carrick2015"; do
# for catalogue in "LOSS" "Foundation" "2MTF" "SFI_gals" "CF4_TFR_i" "CF4_TFR_w1"; do
for catalogue in "LOSS"; do
for catalogue in "SFI_gals" "2MTF" "CF4_TFR_i"; do
# for catalogue in "CF4_TFR_i" "CF4_TFR_w1"; do
# for catalogue in "2MTF" "SFI" "CF4_TFR_not2MTForSFI_i"; do
# for catalogue in "2MTF" "SFI_gals" "CF4_TFR_i"; do
# for catalogue in "CF4_TFR_w1"; do
# for catalogue in "CF4_GroupAll"; do
for ksmooth in 1 2 3 4; do
for ksim in "none"; do
# for ksim in {0..500}; do
pythoncm="$env $file --catalogue $catalogue --simname $simname --ksim $ksim --ksmooth $ksmooth --ndevice $ndevice --device $device"
if [ "$on_login" == "1" ]; then
echo $pythoncm
# eval $pythoncm
eval $pythoncm
else
if [ "$device" == "gpu" ]; then
cm="addqueue -q $queue -s -m $memory --gpus 1 --gputype $gputype $pythoncm"
@ -63,7 +66,7 @@ for simname in "IndranilVoid_gauss"; do
fi
echo "Submitting:"
echo $cm
# eval $cm
eval $cm
fi
echo
@ -71,4 +74,5 @@ for simname in "IndranilVoid_gauss"; do
done
done
done
done

View file

@ -23,6 +23,7 @@ from os import remove
from os.path import exists, join
import hdf5plugin # noqa
import readgadget
import numpy as np
from h5py import File
@ -84,6 +85,28 @@ def prepare_gadget(snapshot_path, temporary_output_path):
return boxsize
def prepara_gadget2(snapshot_path, temporary_output_path):
ptype = [1]
header = readgadget.header(snapshot_path)
boxsize = header.boxsize / 1000
npart = header.nall[1]
mpart = header.massarr[1] * 1e10
print(f"{'Boxsize':<20}: {boxsize}")
print(f"{'Npart':<20}: {npart}")
print(f"{'Mpart':<20}: {mpart}")
with File(temporary_output_path, 'w') as target:
dset = target.create_dataset("particles", (npart, 7), dtype=np.float32)
dset[:, :3] = readgadget.read_block(snapshot_path, "POS ", ptype) / 1000 # noqa
dset[:, 3:6] = readgadget.read_block(snapshot_path, "VEL ", ptype)
dset[:, 6] = np.ones(npart, dtype=np.float32) * mpart
return boxsize
def run_sph_filter(particles_path, output_path, boxsize, resolution,
SPH_executable):
"""
@ -148,7 +171,7 @@ def main(snapshot_path, output_path, resolution, scratch_space, SPH_executable,
[1] https://bitbucket.org/glavaux/cosmotool/src/master/sample/simple3DFilter.cpp # noqa
"""
# First get the temporary file path.
if snapshot_kind == "gadget4":
if snapshot_kind in ["gadget2", "gadget4"]:
temporary_output_path = join(
scratch_space, generate_unique_id(snapshot_path))
elif snapshot_kind == "ramses":
@ -158,9 +181,10 @@ def main(snapshot_path, output_path, resolution, scratch_space, SPH_executable,
"snapshots are supported.")
if not temporary_output_path.endswith(".hdf5"):
raise RuntimeError("Temporary output path must end with `.hdf5`.")
temporary_output_path += ".hdf5"
# Print the job information.
print()
print("---------- SPH Density & Velocity Field Job Information ----------")
print(f"Snapshot path: {snapshot_path}")
print(f"Output path: {output_path}")
@ -178,6 +202,10 @@ def main(snapshot_path, output_path, resolution, scratch_space, SPH_executable,
boxsize = prepare_gadget(snapshot_path, temporary_output_path)
print(f"{now()}: wrote temporary data to {temporary_output_path}.",
flush=True)
elif snapshot_kind == "gadget2":
print(f"{now()}: preparing snapshot...", flush=True)
boxsize = prepara_gadget2(snapshot_path, temporary_output_path)
print(f"{now()}: wrote temporary data to {temporary_output_path}.")
else:
boxsize = 677.7 # Mpc/h
print(f"{now()}: CAREFUL, forcefully setting the boxsize to {boxsize} Mpc / h.", # noqa
@ -209,9 +237,12 @@ if __name__ == "__main__":
parser.add_argument("--SPH_executable", type=str, required=True,
help="Path to the `simple3DFilter` executable.")
parser.add_argument("--snapshot_kind", type=str, required=True,
choices=["gadget4", "ramses"],
choices=["gadget4", "gadget2", "ramses"],
help="Kind of the simulation snapshot.")
args = parser.parse_args()
if not args.output_path.endswith(".hdf5"):
raise RuntimeError("Output path must end with `.hdf5`.")
main(args.snapshot_path, args.output_path, args.resolution,
args.scratch_space, args.SPH_executable, args.snapshot_kind)

View file

@ -0,0 +1,39 @@
#!/bin/bash
nthreads=28
memory=7
on_login=${1}
queue="berg"
env="/mnt/zfsusers/rstiskalek/csiborgtools/venv_csiborg/bin/python"
file="field_sph_gadget.py"
# Guilhem says higher resolution is better
resolution=1024
SPH_executable="/mnt/users/rstiskalek/cosmotool/bld/sample/simple3DFilter"
scratch_space="/mnt/extraspace/rstiskalek/dump/"
snapshot_kind="gadget2"
snapshot_path="/mnt/extraspace/rstiskalek/CLONES/s8/cf2gvpecc1pt5elmo73_sig6distribsbvoldi_RZA3Derrv2_512_500_ss8_zinit60_000"
output_path="/mnt/extraspace/rstiskalek/CLONES/s8/cf2gvpecc1pt5elmo73_sig6distribsbvoldi_RZA3Derrv2_512_500_ss8_zinit60_000.hdf5"
# Check if `on_login` is either 0 or 1
# Check if on_login is not empty and is a valid integer (0 or 1)
if [ -z "$on_login" ] || ! [[ "$on_login" =~ ^[0-1]$ ]]; then
echo "First argument must be either 0 or 1. Received: $on_login"
exit 1
fi
export OMP_NUM_THREADS={nthreads}
export OMP_NESTED=true
pythoncm="$env $file --snapshot_path $snapshot_path --output_path $output_path --resolution $resolution --scratch_space $scratch_space --SPH_executable $SPH_executable --snapshot_kind $snapshot_kind"
if [ $on_login -eq 1 ]; then
echo $pythoncm
$pythoncm
else
cm="addqueue -s -q $queue -n 1x$nthreads -m $memory $pythoncm"
echo "Submitting:"
echo $cm
echo
eval $cm
fi