mirror of
https://github.com/Richard-Sti/csiborgtools.git
synced 2024-12-22 16:38:02 +00:00
Update evaluate density scripts (#105)
* Edit docs * Updated interpolated field paths * Update field sampling script * Add comments about flipping fields * Fix little typo * Edit docs * Edit hard-coded values * Fix paths issue * Add docs * Switch uncorrected dist to corrected * Improve error message * Convert numpy int to Python int * Add flip of x and z * Update README * Edit README * Fix bug in velocity field calculation * Fix simple bug * Add checked axes flipping * Fix field units * Update README
This commit is contained in:
parent
f61f69dfab
commit
1a5477805a
6 changed files with 268 additions and 167 deletions
49
README.md
49
README.md
|
@ -1,26 +1,41 @@
|
||||||
# CSiBORG Tools
|
# CSiBORG Tools
|
||||||
|
|
||||||
Tools for analysing the suite of Constrained Simulations in BORG (CSiBORG) simulations. The interface is designed to work with the following suites of simulations:
|
Tools for analysing the suite of Constrained Simulations in BORG (CSiBORG) simulations. The interface is designed to work with the following suites of simulations: *CSiBORG1* (dark matter-only RAMSES), *CSiBORG2* (dark matter-only Gadget4), *Quijote* (dark-matter only Gadget2), however with little effort it can support other simulations as well.
|
||||||
- CSiBORG1 dark matter-only RAMSES simulations (full support),
|
|
||||||
- CSiBORG2 dark matter-only Gadget4 simulations (planned full support),
|
## Ongoing projects
|
||||||
- Quijote dark matter-only Gadget2 simulations (partial support),
|
|
||||||
however with little effort it can support other simulations as well.
|
### Consistent halo reconstruction
|
||||||
|
- [ ] Make a sketch of the overlap definition and add it to the paper.
|
||||||
|
- [ ] Improve the storage system for overlaps and calculate it for all simulations.
|
||||||
|
|
||||||
|
### Enviromental dependence of galaxy properties
|
||||||
|
- [ ] Calculate the SPH density field for CSiBORG1.
|
||||||
|
- [x] Check that the velocity-field flipping of x and z coordinates is correct.
|
||||||
|
- [ ] Evaluate and share the density field for SDSS & SDSSxALFALFA for both CSiBORG2 and random fields.
|
||||||
|
- [ ] Check and verify the density field of galaxy colours (cannot do this now! Glamdring is super slow.)
|
||||||
|
|
||||||
|
#### Calculated data
|
||||||
|
##### SPH-density & velocity field:
|
||||||
|
- *CSiBORG2_main*, *CSiBORG2_random*, *CSiBORG2_varysmall*
|
||||||
|
- Evaluated for SDSS and SDSSxALFALFA in: *CSiBORG2_main*, *CSiBORG2_random*
|
||||||
|
|
||||||
|
|
||||||
## TODO
|
### Mass-assembly of massive clusters
|
||||||
- [x] Prune old CSiBORG1 merger tree things.
|
- [ ] Make a list of nearby most-massive clusters.
|
||||||
- [x] Add visualiastion of the density field.
|
- [ ] Write code to identify a counterpart of such clusters.
|
||||||
- [ ] Clear out `density` support.
|
- [ ] Write code to make a plot of mass-assembly of all clusters within a certain mass range from the random simulations.
|
||||||
- [ ] Add sorting of Gadget4 initial snapshot like final snapshot.
|
- [ ] Write code to compare mass-assembly of a specific cluster with respect to random ones.
|
||||||
- [ ] Add full support for CSiBORG2 suite of simulations.
|
|
||||||
- [ ] Add SPH field calculation from cosmotools.
|
|
||||||
|
|
||||||
|
|
||||||
## Adding a new simulation suite
|
### Effect of small-scale noise
|
||||||
|
- [ ] Study how the small-scale noise variation affects the overlap measure, halo concentration and spin.
|
||||||
|
|
||||||
box units
|
### Gravitational-wave and large-scale structure
|
||||||
paths
|
- [ ] Make the velocity field data available.
|
||||||
readsim
|
|
||||||
halo_cat
|
|
||||||
|
|
||||||
|
### CSiBORG meets X-ray
|
||||||
|
- [ ] Make available one example snapshot from the simulation. Mention the issue with x- and z-coordinates.
|
||||||
|
|
||||||
|
### CSiBORG advertising
|
||||||
|
- [ ] Decide on the webpage design and what to store there.
|
||||||
|
- [ ] Write a short letter describing the simulations.
|
||||||
|
|
|
@ -249,17 +249,18 @@ class VelocityField(BaseField):
|
||||||
batch_vel = force_single_precision(batch_vel)
|
batch_vel = force_single_precision(batch_vel)
|
||||||
batch_mass = force_single_precision(batch_mass)
|
batch_mass = force_single_precision(batch_mass)
|
||||||
|
|
||||||
vel *= mass.reshape(-1, 1)
|
batch_vel *= batch_mass.reshape(-1, 1)
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
MASL.MA(pos, rho_vel[i], self.boxsize, self.MAS, W=vel[:, i],
|
MASL.MA(batch_pos, rho_vel[i], self.boxsize, self.MAS,
|
||||||
verbose=False)
|
W=batch_vel[:, i], verbose=False)
|
||||||
|
|
||||||
MASL.MA(pos, cellcounts, self.boxsize, self.MAS, W=mass,
|
MASL.MA(batch_pos, cellcounts, self.boxsize, self.MAS,
|
||||||
verbose=False)
|
W=batch_mass, verbose=False)
|
||||||
|
|
||||||
if end == nparts:
|
if end == nparts:
|
||||||
break
|
break
|
||||||
|
|
||||||
start = end
|
start = end
|
||||||
|
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
|
@ -272,7 +273,7 @@ class VelocityField(BaseField):
|
||||||
def radial_velocity(rho_vel, observer_velocity):
|
def radial_velocity(rho_vel, observer_velocity):
|
||||||
"""
|
"""
|
||||||
Calculate the radial velocity field around the observer in the centre
|
Calculate the radial velocity field around the observer in the centre
|
||||||
of the box.
|
of the box, such that the observer velocity is 0.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -367,10 +367,7 @@ class Paths:
|
||||||
-------
|
-------
|
||||||
str
|
str
|
||||||
"""
|
"""
|
||||||
if MAS == "SPH":
|
if MAS == "SPH" and kind in ["density", "velocity"]:
|
||||||
if kind not in ["density", "velocity"]:
|
|
||||||
raise ValueError("SPH field must be either `density` or `velocity`.") # noqa
|
|
||||||
|
|
||||||
if simname == "csiborg1":
|
if simname == "csiborg1":
|
||||||
raise ValueError("SPH field not available for CSiBORG1.")
|
raise ValueError("SPH field not available for CSiBORG1.")
|
||||||
elif simname == "csiborg2_main":
|
elif simname == "csiborg2_main":
|
||||||
|
@ -416,7 +413,7 @@ class Paths:
|
||||||
fname = f"observer_peculiar_velocity_{simname}_{MAS}_{str(nsim).zfill(5)}_{grid}.npz" # noqa
|
fname = f"observer_peculiar_velocity_{simname}_{MAS}_{str(nsim).zfill(5)}_{grid}.npz" # noqa
|
||||||
return join(fdir, fname)
|
return join(fdir, fname)
|
||||||
|
|
||||||
def field_interpolated(self, survey, kind, MAS, grid, nsim, in_rsp):
|
def field_interpolated(self, survey, simname, nsim, kind, MAS, grid):
|
||||||
"""
|
"""
|
||||||
Path to the files containing the CSiBORG interpolated field for a given
|
Path to the files containing the CSiBORG interpolated field for a given
|
||||||
survey.
|
survey.
|
||||||
|
@ -425,35 +422,32 @@ class Paths:
|
||||||
----------
|
----------
|
||||||
survey : str
|
survey : str
|
||||||
Survey name.
|
Survey name.
|
||||||
|
simname : str
|
||||||
|
Simulation name.
|
||||||
|
nsim : int
|
||||||
|
IC realisation index.
|
||||||
kind : str
|
kind : str
|
||||||
Field type. Must be one of: `density`, `velocity`, `potential`,
|
Field type.
|
||||||
`radvel`, `environment`.
|
|
||||||
MAS : str
|
MAS : str
|
||||||
Mass-assignment scheme.
|
Mass-assignment scheme.
|
||||||
grid : int
|
grid : int
|
||||||
Grid size.
|
Grid size.
|
||||||
nsim : int
|
|
||||||
IC realisation index.
|
|
||||||
in_rsp : bool
|
|
||||||
Whether the calculation is performed in redshift space.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
str
|
str
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("This function is not implemented yet.")
|
if "csiborg" not in simname:
|
||||||
assert kind in ["density", "velocity", "potential", "radvel",
|
raise ValueError("Interpolated field only available for CSiBORG.")
|
||||||
"environment"]
|
|
||||||
fdir = join(self.postdir, "environment_interpolated")
|
|
||||||
|
|
||||||
|
if kind not in ["density", "potential", "radvel"]:
|
||||||
|
raise ValueError("Unsupported field type.")
|
||||||
|
|
||||||
|
fdir = join(self.postdir, "field_interpolated")
|
||||||
try_create_directory(fdir)
|
try_create_directory(fdir)
|
||||||
|
|
||||||
if in_rsp:
|
nsim = str(nsim).zfill(5)
|
||||||
kind = kind + "_rsp"
|
return join(fdir, f"{survey}_{simname}_{kind}_{MAS}_{nsim}_{grid}.npz")
|
||||||
|
|
||||||
fname = f"{survey}_{kind}_{MAS}_{str(nsim).zfill(5)}_grid{grid}.npz"
|
|
||||||
|
|
||||||
return join(fdir, fname)
|
|
||||||
|
|
||||||
def cross_nearest(self, simname, run, kind, nsim=None, nobs=None):
|
def cross_nearest(self, simname, run, kind, nsim=None, nobs=None):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -516,10 +516,12 @@ class BaseField(ABC):
|
||||||
Base class for reading fields such as density or velocity fields.
|
Base class for reading fields such as density or velocity fields.
|
||||||
"""
|
"""
|
||||||
def __init__(self, nsim, paths):
|
def __init__(self, nsim, paths):
|
||||||
|
if isinstance(nsim, numpy.integer):
|
||||||
|
nsim = int(nsim)
|
||||||
if not isinstance(nsim, int):
|
if not isinstance(nsim, int):
|
||||||
raise TypeError("`nsim` must be an integer")
|
raise TypeError(f"`nsim` must be an integer. Received `{type(nsim)}`.") # noqa
|
||||||
self._nsim = nsim
|
|
||||||
|
|
||||||
|
self._nsim = nsim
|
||||||
self._paths = paths
|
self._paths = paths
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -542,6 +544,8 @@ class BaseField(ABC):
|
||||||
-------
|
-------
|
||||||
Paths
|
Paths
|
||||||
"""
|
"""
|
||||||
|
if self._paths is None:
|
||||||
|
self._paths = Paths(**paths_glamdring)
|
||||||
return self._paths
|
return self._paths
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -594,11 +598,12 @@ class CSiBORG1Field(BaseField):
|
||||||
----------
|
----------
|
||||||
nsim : int
|
nsim : int
|
||||||
Simulation index.
|
Simulation index.
|
||||||
paths : Paths
|
paths : Paths, optional
|
||||||
Paths object.
|
Paths object. By default, the paths are set to the `glamdring` paths.
|
||||||
"""
|
"""
|
||||||
def __init__(self, nsim, paths):
|
def __init__(self, nsim, paths=None):
|
||||||
super().__init__(nsim, paths)
|
super().__init__(nsim, paths)
|
||||||
|
self._simname = "csiborg1"
|
||||||
|
|
||||||
def density_field(self, MAS, grid):
|
def density_field(self, MAS, grid):
|
||||||
fpath = self.paths.field("density", MAS, grid, self.nsim, "csiborg1")
|
fpath = self.paths.field("density", MAS, grid, self.nsim, "csiborg1")
|
||||||
|
@ -606,9 +611,14 @@ class CSiBORG1Field(BaseField):
|
||||||
if MAS == "SPH":
|
if MAS == "SPH":
|
||||||
with File(fpath, "r") as f:
|
with File(fpath, "r") as f:
|
||||||
field = f["density"][:]
|
field = f["density"][:]
|
||||||
|
field /= (677.7 * 1e3 / grid)**3 # Convert to h^2 Msun / kpc^3
|
||||||
else:
|
else:
|
||||||
field = numpy.load(fpath)
|
field = numpy.load(fpath)
|
||||||
|
|
||||||
|
# Flip x- and z-axes
|
||||||
|
if self._simname == "csiborg1":
|
||||||
|
field = field.T
|
||||||
|
|
||||||
return field
|
return field
|
||||||
|
|
||||||
def velocity_field(self, MAS, grid):
|
def velocity_field(self, MAS, grid):
|
||||||
|
@ -624,6 +634,13 @@ class CSiBORG1Field(BaseField):
|
||||||
else:
|
else:
|
||||||
field = numpy.load(fpath)
|
field = numpy.load(fpath)
|
||||||
|
|
||||||
|
# Flip x- and z-axes
|
||||||
|
if self._simname == "csiborg1":
|
||||||
|
field[0, ...] = field[0, ...].T
|
||||||
|
field[1, ...] = field[1, ...].T
|
||||||
|
field[2, ...] = field[2, ...].T
|
||||||
|
field[[0, 2], ...] = field[[2, 0], ...]
|
||||||
|
|
||||||
return field
|
return field
|
||||||
|
|
||||||
|
|
||||||
|
@ -640,13 +657,13 @@ class CSiBORG2Field(BaseField):
|
||||||
----------
|
----------
|
||||||
nsim : int
|
nsim : int
|
||||||
Simulation index.
|
Simulation index.
|
||||||
paths : Paths
|
|
||||||
Paths object.
|
|
||||||
kind : str
|
kind : str
|
||||||
CSiBORG2 run kind. One of `main`, `random`, or `varysmall`.
|
CSiBORG2 run kind. One of `main`, `random`, or `varysmall`.
|
||||||
|
paths : Paths, optional
|
||||||
|
Paths object. By default, the paths are set to the `glamdring` paths.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, nsim, paths, kind):
|
def __init__(self, nsim, kind, paths=None):
|
||||||
super().__init__(nsim, paths)
|
super().__init__(nsim, paths)
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
|
|
||||||
|
@ -675,11 +692,11 @@ class CSiBORG2Field(BaseField):
|
||||||
with File(fpath, "r") as f:
|
with File(fpath, "r") as f:
|
||||||
field = f["density"][:]
|
field = f["density"][:]
|
||||||
field *= 1e10 # Convert to Msun / h
|
field *= 1e10 # Convert to Msun / h
|
||||||
field /= (676.6 * 1e3 / 1024)**3 # Convert to h^2 Msun / kpc^3
|
field /= (676.6 * 1e3 / grid)**3 # Convert to h^2 Msun / kpc^3
|
||||||
field = field.T # Flip x- and z-axes
|
|
||||||
else:
|
else:
|
||||||
field = numpy.load(fpath)
|
field = numpy.load(fpath)
|
||||||
|
|
||||||
|
field = field.T # Flip x- and z-axes
|
||||||
return field
|
return field
|
||||||
|
|
||||||
def velocity_field(self, MAS, grid):
|
def velocity_field(self, MAS, grid):
|
||||||
|
@ -688,7 +705,6 @@ class CSiBORG2Field(BaseField):
|
||||||
|
|
||||||
if MAS == "SPH":
|
if MAS == "SPH":
|
||||||
with File(fpath, "r") as f:
|
with File(fpath, "r") as f:
|
||||||
# TODO: the x and z still have to be flipped.
|
|
||||||
density = f["density"][:]
|
density = f["density"][:]
|
||||||
v0 = f["p0"][:] / density
|
v0 = f["p0"][:] / density
|
||||||
v1 = f["p1"][:] / density
|
v1 = f["p1"][:] / density
|
||||||
|
@ -697,6 +713,12 @@ class CSiBORG2Field(BaseField):
|
||||||
else:
|
else:
|
||||||
field = numpy.load(fpath)
|
field = numpy.load(fpath)
|
||||||
|
|
||||||
|
# Flip x- and z-axes
|
||||||
|
field[0, ...] = field[0, ...].T
|
||||||
|
field[1, ...] = field[1, ...].T
|
||||||
|
field[2, ...] = field[2, ...].T
|
||||||
|
field[[0, 2], ...] = field[[2, 0], ...]
|
||||||
|
|
||||||
return field
|
return field
|
||||||
|
|
||||||
|
|
||||||
|
@ -718,6 +740,7 @@ class QuijoteField(CSiBORG1Field):
|
||||||
"""
|
"""
|
||||||
def __init__(self, nsim, paths):
|
def __init__(self, nsim, paths):
|
||||||
super().__init__(nsim, paths)
|
super().__init__(nsim, paths)
|
||||||
|
self._simname = "quijote"
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
|
@ -30,7 +30,21 @@ from utils import get_nsims
|
||||||
|
|
||||||
|
|
||||||
def density_field(nsim, parser_args):
|
def density_field(nsim, parser_args):
|
||||||
"""Calculate the density field."""
|
"""
|
||||||
|
Calculate and save the density field from the particle positions and
|
||||||
|
masses.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
nsim : int
|
||||||
|
Simulation index.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
density_field : 3-dimensional array
|
||||||
|
"""
|
||||||
if parser_args.MAS == "SPH":
|
if parser_args.MAS == "SPH":
|
||||||
raise NotImplementedError("SPH is not implemented here. Use cosmotool")
|
raise NotImplementedError("SPH is not implemented here. Use cosmotool")
|
||||||
|
|
||||||
|
@ -70,7 +84,21 @@ def density_field(nsim, parser_args):
|
||||||
|
|
||||||
|
|
||||||
def velocity_field(nsim, parser_args):
|
def velocity_field(nsim, parser_args):
|
||||||
"""Calculate the velocity field."""
|
"""
|
||||||
|
Calculate and save the velocity field from the particle positions,
|
||||||
|
velocities and masses.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
nsim : int
|
||||||
|
Simulation index.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
velocity_field : 4-dimensional array
|
||||||
|
"""
|
||||||
if parser_args.MAS == "SPH":
|
if parser_args.MAS == "SPH":
|
||||||
raise NotImplementedError("SPH is not implemented here. Use cosmotool")
|
raise NotImplementedError("SPH is not implemented here. Use cosmotool")
|
||||||
|
|
||||||
|
@ -81,7 +109,7 @@ def velocity_field(nsim, parser_args):
|
||||||
snapshot = csiborgtools.read.CSIBORG1Snapshot(nsim, nsnap, paths)
|
snapshot = csiborgtools.read.CSIBORG1Snapshot(nsim, nsnap, paths)
|
||||||
elif "csiborg2" in parser_args.simname:
|
elif "csiborg2" in parser_args.simname:
|
||||||
kind = parser_args.simname.split("_")[-1]
|
kind = parser_args.simname.split("_")[-1]
|
||||||
snapshot = csiborgtools.read.CSIBORG2Snapshot(nsim, nsnap, paths, kind)
|
snapshot = csiborgtools.read.CSIBORG2Snapshot(nsim, nsnap, kind, paths)
|
||||||
elif parser_args.simname == "quijote":
|
elif parser_args.simname == "quijote":
|
||||||
snapshot = csiborgtools.read.QuijoteSnapshot(nsim, nsnap, paths)
|
snapshot = csiborgtools.read.QuijoteSnapshot(nsim, nsnap, paths)
|
||||||
else:
|
else:
|
||||||
|
@ -108,14 +136,27 @@ def velocity_field(nsim, parser_args):
|
||||||
|
|
||||||
|
|
||||||
def radvel_field(nsim, parser_args):
|
def radvel_field(nsim, parser_args):
|
||||||
"""Calculate the radial velocity field."""
|
"""
|
||||||
|
Calculate and save the radial velocity field.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
nsim : int
|
||||||
|
Simulation index.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
radvel_field : 3-dimensional array
|
||||||
|
"""
|
||||||
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
||||||
|
|
||||||
if parser_args.simname == "csiborg1":
|
if parser_args.simname == "csiborg1":
|
||||||
field = csiborgtools.read.CSiBORG1Field(nsim, paths)
|
field = csiborgtools.read.CSiBORG1Field(nsim, paths)
|
||||||
elif "csiborg2" in parser_args.simname:
|
elif "csiborg2" in parser_args.simname:
|
||||||
kind = parser_args.simname.split("_")[-1]
|
kind = parser_args.simname.split("_")[-1]
|
||||||
field = csiborgtools.read.CSiBORG2Field(nsim, paths, kind)
|
field = csiborgtools.read.CSiBORG2Field(nsim, kind, paths)
|
||||||
elif parser_args.simname == "quijote":
|
elif parser_args.simname == "quijote":
|
||||||
field = csiborgtools.read.QuijoteField(nsim, paths)
|
field = csiborgtools.read.QuijoteField(nsim, paths)
|
||||||
else:
|
else:
|
||||||
|
@ -136,11 +177,22 @@ def radvel_field(nsim, parser_args):
|
||||||
def observer_peculiar_velocity(nsim, parser_args):
|
def observer_peculiar_velocity(nsim, parser_args):
|
||||||
"""
|
"""
|
||||||
Calculate the peculiar velocity of an observer in the centre of the box
|
Calculate the peculiar velocity of an observer in the centre of the box
|
||||||
for several smoothing scales.
|
for several hard-coded smoothing scales.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
nsim : int
|
||||||
|
Simulation index.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
observer_vp : 4-dimensional array
|
||||||
"""
|
"""
|
||||||
boxsize = csiborgtools.simname2boxsize(parser_args.simname)
|
boxsize = csiborgtools.simname2boxsize(parser_args.simname)
|
||||||
# NOTE thevse values are hard-coded.
|
# NOTE these values are hard-coded.
|
||||||
smooth_scales = numpy.array([0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
|
smooth_scales = numpy.array([0., 2.0, 4.0, 8.0, 16.])
|
||||||
smooth_scales /= boxsize
|
smooth_scales /= boxsize
|
||||||
|
|
||||||
if parser_args.simname == "csiborg1":
|
if parser_args.simname == "csiborg1":
|
||||||
|
|
|
@ -13,12 +13,13 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
"""
|
"""
|
||||||
Sample a CSiBORG field at galaxy positions and save the result to disk.
|
Script to sample a CSiBORG field at galaxy positions and save the result.
|
||||||
|
Supports additional smoothing of the field as well.
|
||||||
"""
|
"""
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from distutils.util import strtobool
|
|
||||||
from os.path import join
|
from os.path import join
|
||||||
|
|
||||||
|
import csiborgtools
|
||||||
import numpy
|
import numpy
|
||||||
from astropy.cosmology import FlatLambdaCDM
|
from astropy.cosmology import FlatLambdaCDM
|
||||||
from h5py import File
|
from h5py import File
|
||||||
|
@ -26,54 +27,42 @@ from mpi4py import MPI
|
||||||
from taskmaster import work_delegation
|
from taskmaster import work_delegation
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
import csiborgtools
|
|
||||||
from utils import get_nsims
|
from utils import get_nsims
|
||||||
|
|
||||||
# TODO get rid of this.
|
|
||||||
# MPC2BOX = 1 / 677.7
|
|
||||||
SIM2BOXSIZE = {"csiborg1": 677.7,
|
|
||||||
"csiborg2_main": None,
|
|
||||||
"csiborg2_random": None,
|
|
||||||
"csiborg2_varysmall": None,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def steps(cls, survey_name):
|
|
||||||
"""Make a list of selection criteria to apply to a survey."""
|
|
||||||
if survey_name == "SDSS":
|
|
||||||
return [
|
|
||||||
# (lambda x: cls[x], ("IN_DR7_LSS",)),
|
|
||||||
# (lambda x: cls[x] < 17.6, ("ELPETRO_APPMAG_r", )),
|
|
||||||
(lambda x: cls[x] < 155.5, ("DIST", ))
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(f"Survey `{survey_name}` not implemented.")
|
|
||||||
|
|
||||||
|
|
||||||
def open_galaxy_positions(survey_name, comm):
|
def open_galaxy_positions(survey_name, comm):
|
||||||
"""
|
"""
|
||||||
Load the survey galaxy positions and indices, broadcasting them to all
|
Load the survey's galaxy positions , broadcasting them to all ranks.
|
||||||
ranks.
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
survey_name : str
|
||||||
|
Name of the survey.
|
||||||
|
comm : mpi4py.MPI.Comm
|
||||||
|
MPI communicator.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
pos : 2-dimensional array
|
||||||
|
Galaxy positions in the form of (distance, RA, DEC).
|
||||||
"""
|
"""
|
||||||
rank, size = comm.Get_rank(), comm.Get_size()
|
rank, size = comm.Get_rank(), comm.Get_size()
|
||||||
|
|
||||||
if rank == 0:
|
if rank == 0:
|
||||||
if survey_name == "SDSS":
|
if survey_name == "SDSS":
|
||||||
survey = csiborgtools.SDSS()()
|
survey = csiborgtools.SDSS()()
|
||||||
pos = numpy.vstack([survey["DIST_UNCORRECTED"],
|
pos = numpy.vstack([survey["DIST"],
|
||||||
survey["RA"],
|
survey["RA"],
|
||||||
survey["DEC"]],
|
survey["DEC"]],
|
||||||
).T
|
).T
|
||||||
pos = pos.astype(numpy.float32)
|
pos = pos.astype(numpy.float32)
|
||||||
indxs = survey["INDEX"]
|
elif survey_name == "SDSSxALFALFA":
|
||||||
if survey_name == "SDSSxALFALFA":
|
|
||||||
survey = csiborgtools.SDSSxALFALFA()()
|
survey = csiborgtools.SDSSxALFALFA()()
|
||||||
pos = numpy.vstack([survey["DIST_UNCORRECTED"],
|
pos = numpy.vstack([survey["DIST"],
|
||||||
survey["RA_1"],
|
survey["RA_1"],
|
||||||
survey["DEC_1"]],
|
survey["DEC_1"]],
|
||||||
).T
|
).T
|
||||||
pos = pos.astype(numpy.float32)
|
pos = pos.astype(numpy.float32)
|
||||||
indxs = survey["INDEX"]
|
|
||||||
elif survey_name == "GW170817":
|
elif survey_name == "GW170817":
|
||||||
samples = File("/mnt/extraspace/rstiskalek/GWLSS/H1L1V1-EXTRACT_POSTERIOR_GW170817-1187008600-400.hdf", 'r')["samples"] # noqa
|
samples = File("/mnt/extraspace/rstiskalek/GWLSS/H1L1V1-EXTRACT_POSTERIOR_GW170817-1187008600-400.hdf", 'r')["samples"] # noqa
|
||||||
cosmo = FlatLambdaCDM(H0=100, Om0=0.3175)
|
cosmo = FlatLambdaCDM(H0=100, Om0=0.3175)
|
||||||
|
@ -82,121 +71,155 @@ def open_galaxy_positions(survey_name, comm):
|
||||||
samples["ra"][:] * 180 / numpy.pi,
|
samples["ra"][:] * 180 / numpy.pi,
|
||||||
samples["dec"][:] * 180 / numpy.pi],
|
samples["dec"][:] * 180 / numpy.pi],
|
||||||
).T
|
).T
|
||||||
indxs = numpy.arange(pos.shape[0])
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f"Survey `{survey_name}` not "
|
raise NotImplementedError(f"Survey `{survey_name}` not "
|
||||||
"implemented.")
|
"implemented.")
|
||||||
else:
|
else:
|
||||||
pos = None
|
pos = None
|
||||||
indxs = None
|
|
||||||
|
|
||||||
comm.Barrier()
|
comm.Barrier()
|
||||||
|
|
||||||
if size > 1:
|
if size > 1:
|
||||||
pos = comm.bcast(pos, root=0)
|
pos = comm.bcast(pos, root=0)
|
||||||
indxs = comm.bcast(indxs, root=0)
|
|
||||||
|
|
||||||
return pos, indxs
|
return pos
|
||||||
|
|
||||||
|
|
||||||
def evaluate_field(field, pos, nrand, smooth_scales=None, seed=42,
|
def evaluate_field(field, pos, boxsize, smooth_scales, verbose=True):
|
||||||
verbose=True):
|
|
||||||
"""
|
"""
|
||||||
Evaluate the field at the given sky positions. Additionally, evaluate the
|
Evaluate the field at the given galaxy positions.
|
||||||
field at `nrand` random positions.
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
field : 3-dimensional array
|
||||||
|
Cartesian field to be evaluated.
|
||||||
|
pos : 2-dimensional array
|
||||||
|
Galaxy positions in the form of (distance, RA, DEC).
|
||||||
|
boxsize : float
|
||||||
|
Box size in `Mpc / h`.
|
||||||
|
smooth_scales : list
|
||||||
|
List of smoothing scales in `Mpc / h`.
|
||||||
|
verbose : bool
|
||||||
|
Verbosity flag.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
val : 2-dimensional array
|
||||||
|
Evaluated field.
|
||||||
"""
|
"""
|
||||||
if smooth_scales is None:
|
mpc2box = 1. / boxsize
|
||||||
smooth_scales = [0.]
|
val = numpy.full((pos.shape[0], len(smooth_scales)), numpy.nan,
|
||||||
|
dtype=field.dtype)
|
||||||
nsample = pos.shape[0]
|
|
||||||
nsmooth = len(smooth_scales)
|
|
||||||
|
|
||||||
val = numpy.full((nsample, nsmooth), numpy.nan, dtype=field.dtype)
|
|
||||||
if nrand > 0:
|
|
||||||
rand_val = numpy.full((nsample, nsmooth, nrand), numpy.nan,
|
|
||||||
dtype=field.dtype)
|
|
||||||
else:
|
|
||||||
rand_val = None
|
|
||||||
|
|
||||||
for i, scale in enumerate(tqdm(smooth_scales, desc="Smoothing",
|
for i, scale in enumerate(tqdm(smooth_scales, desc="Smoothing",
|
||||||
disable=not verbose)):
|
disable=not verbose)):
|
||||||
if scale > 0:
|
if scale > 0:
|
||||||
field_smoothed = csiborgtools.field.smoothen_field(
|
field_smoothed = csiborgtools.field.smoothen_field(
|
||||||
field, scale * MPC2BOX, boxsize=1, make_copy=True)
|
field, scale * mpc2box, boxsize=1, make_copy=True)
|
||||||
else:
|
else:
|
||||||
field_smoothed = numpy.copy(field)
|
field_smoothed = numpy.copy(field)
|
||||||
|
|
||||||
val[:, i] = csiborgtools.field.evaluate_sky(
|
val[:, i] = csiborgtools.field.evaluate_sky(
|
||||||
field_smoothed, pos=pos, mpc2box=MPC2BOX)
|
field_smoothed, pos=pos, mpc2box=mpc2box)
|
||||||
|
|
||||||
if nrand == 0:
|
return val
|
||||||
continue
|
|
||||||
|
|
||||||
for j in range(nrand):
|
|
||||||
gen = numpy.random.default_rng(seed + j)
|
|
||||||
pos_rand = numpy.vstack([
|
|
||||||
gen.permutation(pos[:, 0]),
|
|
||||||
gen.uniform(0, 360, nsample),
|
|
||||||
90 - numpy.rad2deg(numpy.arccos(gen.uniform(-1, 1, nsample))),
|
|
||||||
]).T
|
|
||||||
|
|
||||||
rand_val[:, i, j] = csiborgtools.field.evaluate_sky(
|
|
||||||
field_smoothed, pos=pos_rand, mpc2box=MPC2BOX)
|
|
||||||
|
|
||||||
return val, rand_val, smooth_scales
|
|
||||||
|
|
||||||
|
|
||||||
def match_to_no_selection(val, rand_val, parser_args):
|
def match_to_no_selection(val, parser_args):
|
||||||
if parser_args.survey == "SDSSxALFALFA":
|
"""
|
||||||
|
Match the shape of the evaluated field to the shape of the survey without
|
||||||
|
any masking. Missing values are filled with `numpy.nan`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
val : n-dimensional array
|
||||||
|
Evaluated field.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
n-dimensional array
|
||||||
|
"""
|
||||||
|
if parser_args.survey == "SDSS":
|
||||||
|
survey = csiborgtools.SDSS()()
|
||||||
|
elif parser_args.survey == "SDSSxALFALFA":
|
||||||
survey = csiborgtools.SDSSxALFALFA()()
|
survey = csiborgtools.SDSSxALFALFA()()
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
f"Survey `{parser_args.survey}` not implemented for matching to no selection.") # noqa
|
f"Survey `{parser_args.survey}` not implemented for matching to no selection.") # noqa
|
||||||
|
|
||||||
if val is not None:
|
return csiborgtools.read.match_array_to_no_masking(val, survey)
|
||||||
val = csiborgtools.read.match_array_to_no_masking(val, survey)
|
|
||||||
if rand_val is not None:
|
|
||||||
rand_val = csiborgtools.read.match_array_to_no_masking(rand_val,
|
|
||||||
survey)
|
|
||||||
|
|
||||||
return val, rand_val
|
|
||||||
|
|
||||||
|
|
||||||
def main(nsim, parser_args, pos, indxs, paths, verbose):
|
def main(nsim, parser_args, pos, verbose):
|
||||||
"""Load the field, interpolate it and save it to disk."""
|
"""
|
||||||
fpath_field = paths.field(parser_args.kind, parser_args.MAS,
|
Main function to load the field, interpolate (and smooth it) it and save
|
||||||
parser_args.grid, nsim, parser_args.in_rsp)
|
the results to the disk.
|
||||||
field = numpy.load(fpath_field)
|
|
||||||
|
|
||||||
val, rand_val, smooth_scales = evaluate_field(
|
Parameters
|
||||||
field, pos, nrand=parser_args.nrand,
|
----------
|
||||||
smooth_scales=parser_args.smooth_scales, verbose=verbose)
|
nsim : int
|
||||||
|
IC realisation.
|
||||||
|
parser_args : argparse.Namespace
|
||||||
|
Command line arguments.
|
||||||
|
pos : numpy.ndarray
|
||||||
|
Galaxy coordinates in the form of (distance, RA, DEC) where to evaluate
|
||||||
|
the field.
|
||||||
|
verbose : bool
|
||||||
|
Verbosity flag.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
||||||
|
boxsize = csiborgtools.simname2boxsize(parser_args.simname)
|
||||||
|
|
||||||
|
# Get the appropriate field loader
|
||||||
|
if parser_args.simname == "csiborg1":
|
||||||
|
freader = csiborgtools.read.CSiBORG1Field(nsim)
|
||||||
|
elif "csiborg2" in parser_args.simname:
|
||||||
|
kind = parser_args.simname.split("_")[-1]
|
||||||
|
freader = csiborgtools.read.CSiBORG2Field(nsim, kind)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"Simulation `{parser_args.simname}` is not supported.") # noqa
|
||||||
|
|
||||||
|
# Get the appropriate field
|
||||||
|
if parser_args.kind == "density":
|
||||||
|
field = freader.density_field(parser_args.MAS, parser_args.grid)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"Field `{parser_args.kind}` is not supported.") # noqa
|
||||||
|
|
||||||
|
val = evaluate_field(field, pos, boxsize, parser_args.smooth_scales,
|
||||||
|
verbose=verbose)
|
||||||
|
|
||||||
if parser_args.survey == "GW170817":
|
if parser_args.survey == "GW170817":
|
||||||
kind = parser_args.kind
|
|
||||||
kind = kind + "_rsp" if parser_args.in_rsp else kind
|
|
||||||
|
|
||||||
fout = join(
|
fout = join(
|
||||||
"/mnt/extraspace/rstiskalek/GWLSS/",
|
"/mnt/extraspace/rstiskalek/GWLSS/",
|
||||||
f"{kind}_{parser_args.MAS}_{parser_args.grid}_{nsim}_H1L1V1-EXTRACT_POSTERIOR_GW170817-1187008600-400.npz") # noqa
|
f"{parser_args.kind}_{parser_args.MAS}_{parser_args.grid}_{nsim}_H1L1V1-EXTRACT_POSTERIOR_GW170817-1187008600-400.npz") # noqa
|
||||||
else:
|
else:
|
||||||
fout = paths.field_interpolated(parser_args.survey, parser_args.kind,
|
fout = paths.field_interpolated(
|
||||||
parser_args.MAS, parser_args.grid,
|
parser_args.survey, parser_args.simname, nsim, parser_args.kind,
|
||||||
nsim, parser_args.in_rsp)
|
parser_args.MAS, parser_args.grid)
|
||||||
|
|
||||||
# The survey above had some cuts, however for compatibility we want
|
# The survey above had some cuts, however for compatibility we want
|
||||||
# the same shape as the `uncut` survey
|
# the same shape as the `uncut` survey
|
||||||
val, rand_val = match_to_no_selection(val, rand_val, parser_args)
|
val = match_to_no_selection(val, parser_args)
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"Saving to ... `{fout}`.")
|
print(f"Saving to ... `{fout}`.")
|
||||||
numpy.savez(fout, val=val, rand_val=rand_val, indxs=indxs,
|
|
||||||
smooth_scales=smooth_scales)
|
numpy.savez(fout, val=val, smooth_scales=parser_args.smooth_scales)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
parser.add_argument("--nsims", type=int, nargs="+", default=None,
|
parser.add_argument("--nsims", type=int, nargs="+", default=None,
|
||||||
help="IC realisations. If `-1` processes all.")
|
help="IC realisations. If `-1` processes all.")
|
||||||
|
parser.add_argument("--simname", type=str, default="csiborg1",
|
||||||
|
choices=["csiborg1", "csiborg2_main", "csiborg2_random", "csiborg2_varysmall"], # noqa
|
||||||
|
help="Simulation name")
|
||||||
parser.add_argument("--survey", type=str, required=True,
|
parser.add_argument("--survey", type=str, required=True,
|
||||||
choices=["SDSS", "SDSSxALFALFA", "GW170817"],
|
choices=["SDSS", "SDSSxALFALFA", "GW170817"],
|
||||||
help="Galaxy survey")
|
help="Galaxy survey")
|
||||||
|
@ -207,24 +230,17 @@ if __name__ == "__main__":
|
||||||
"potential"],
|
"potential"],
|
||||||
help="What field to interpolate.")
|
help="What field to interpolate.")
|
||||||
parser.add_argument("--MAS", type=str,
|
parser.add_argument("--MAS", type=str,
|
||||||
choices=["NGP", "CIC", "TSC", "PCS"],
|
choices=["NGP", "CIC", "TSC", "PCS", "SPH"],
|
||||||
help="Mass assignment scheme.")
|
help="Mass assignment scheme.")
|
||||||
parser.add_argument("--grid", type=int, help="Grid resolution.")
|
parser.add_argument("--grid", type=int, help="Grid resolution.")
|
||||||
parser.add_argument("--in_rsp", type=lambda x: bool(strtobool(x)),
|
|
||||||
help="Field in RSP?")
|
|
||||||
parser.add_argument("--nrand", type=int, required=True,
|
|
||||||
help="Number of rand. positions to evaluate the field")
|
|
||||||
parser.add_argument("--simname", type=str, default="csiborg1",
|
|
||||||
choices=["csiborg1"], help="Simulation name")
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
||||||
nsims = get_nsims(args, paths)
|
nsims = get_nsims(args, paths)
|
||||||
|
|
||||||
pos, indxs = open_galaxy_positions(args.survey, MPI.COMM_WORLD)
|
pos = open_galaxy_positions(args.survey, MPI.COMM_WORLD)
|
||||||
|
|
||||||
def _main(nsim):
|
def _main(nsim):
|
||||||
main(nsim, args, pos, indxs, paths,
|
main(nsim, args, pos, verbose=MPI.COMM_WORLD.Get_size() == 1)
|
||||||
verbose=MPI.COMM_WORLD.Get_size() == 1)
|
|
||||||
|
|
||||||
work_delegation(_main, nsims, MPI.COMM_WORLD)
|
work_delegation(_main, nsims, MPI.COMM_WORLD)
|
||||||
|
|
Loading…
Reference in a new issue