Periodic neighbours (#84)

* Edit the HMF plot

* Add periodic dist 2 points

* Add boxsize to RVSSphere

* Add periodic distance

* Adding periodic distance

* Add imports

* Change arguments

* Update bounds

* Lower min number of particles

* Change kwargs

* Add paths overlap quijote

* Add some comments
This commit is contained in:
Richard Stiskalek 2023-08-08 12:19:40 +02:00 committed by GitHub
parent c7e447df01
commit c7b600d0ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 196 additions and 61 deletions

View File

@ -13,7 +13,9 @@
# 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.
from csiborgtools import clustering, field, match, read # noqa from csiborgtools import clustering, field, match, read # noqa
from .utils import (center_of_mass, delta2ncells, periodic_distance, number_counts) # noqa
from .utils import (center_of_mass, delta2ncells, number_counts,
periodic_distance, periodic_distance_two_points) # noqa
# Arguments to csiborgtools.read.Paths. # Arguments to csiborgtools.read.Paths.
paths_glamdring = {"srcdir": "/mnt/extraspace/hdesmond/", paths_glamdring = {"srcdir": "/mnt/extraspace/hdesmond/",

View File

@ -51,16 +51,20 @@ class BaseRVS(ABC):
class RVSinsphere(BaseRVS): class RVSinsphere(BaseRVS):
""" """
Generator of uniform RVS in a sphere of radius `R` in Cartesian Generator of uniform RVS in a sphere of radius `R` in Cartesian
coordinates centered at the origin. coordinates centered at the centre of the box.
Parameters Parameters
---------- ----------
R : float R : float
Radius of the sphere. Radius of the sphere.
boxsize : float
Box size
""" """
def __init__(self, R): def __init__(self, R, boxsize):
assert R > 0, "Radius must be positive." assert R > 0, "Radius must be positive."
assert boxsize > 0, "Box size must be positive."
self.R = R self.R = R
self.boxsize = boxsize
BaseRVS.__init__(self) BaseRVS.__init__(self)
def __call__(self, nsamples, random_state=42, dtype=numpy.float32): def __call__(self, nsamples, random_state=42, dtype=numpy.float32):
@ -73,7 +77,7 @@ class RVSinsphere(BaseRVS):
x = r * numpy.sin(theta) * numpy.cos(phi) x = r * numpy.sin(theta) * numpy.cos(phi)
y = r * numpy.sin(theta) * numpy.sin(phi) y = r * numpy.sin(theta) * numpy.sin(phi)
z = r * numpy.cos(theta) z = r * numpy.cos(theta)
return numpy.vstack([x, y, z]).T return numpy.vstack([x, y, z]).T + self.boxsize / 2
class RVSinbox(BaseRVS): class RVSinbox(BaseRVS):

View File

@ -239,7 +239,8 @@ class RealisationsMatcher(BaseMatcher):
if verbose: if verbose:
print(f"{datetime.now()}: querying the KNN.", flush=True) print(f"{datetime.now()}: querying the KNN.", flush=True)
match_indxs = radius_neighbours( match_indxs = radius_neighbours(
catx.knn(in_initial=True), cat0.position(in_initial=True), catx.knn(in_initial=True, subtract_observer=False, periodic=True),
cat0.position(in_initial=True),
radiusX=cat0["lagpatch_size"], radiusKNN=catx["lagpatch_size"], radiusX=cat0["lagpatch_size"], radiusKNN=catx["lagpatch_size"],
nmult=self.nmult, enforce_int32=True, verbose=verbose) nmult=self.nmult, enforce_int32=True, verbose=verbose)
@ -515,7 +516,7 @@ class ParticleOverlap(BaseMatcher):
Minimun and maximum cell numbers along each dimension of `halo1`. Minimun and maximum cell numbers along each dimension of `halo1`.
Optional. Optional.
mins2, maxs2 : 1-dimensional arrays of shape `(3,)` mins2, maxs2 : 1-dimensional arrays of shape `(3,)`
Minimun and maximum cell numbers along each dimension of `halo2`. Minimum and maximum cell numbers along each dimension of `halo2`.
Optional. Optional.
smooth_kwargs : kwargs, optional smooth_kwargs : kwargs, optional
Kwargs to be passed to :py:func:`scipy.ndimage.gaussian_filter`. Kwargs to be passed to :py:func:`scipy.ndimage.gaussian_filter`.
@ -1014,7 +1015,8 @@ def radius_neighbours(knn, X, radiusX, radiusKNN, nmult=1.0,
def find_neighbour(nsim0, cats): def find_neighbour(nsim0, cats):
""" """
Find the nearest neighbour of halos from a reference catalogue indexed Find the nearest neighbour of halos from a reference catalogue indexed
`nsim0` in the remaining simulations. `nsim0` in the remaining simulations. Note that this must be the same
simulation suite.
Parameters Parameters
---------- ----------
@ -1030,8 +1032,10 @@ def find_neighbour(nsim0, cats):
cross_hindxs : 2-dimensional array of shape `(nhalos, len(cats) - 1)` cross_hindxs : 2-dimensional array of shape `(nhalos, len(cats) - 1)`
Halo indices of the nearest neighbour. Halo indices of the nearest neighbour.
""" """
assert all(isinstance(cat, type(cats[nsim0])) for cat in cats.values())
cat0 = cats[nsim0] cat0 = cats[nsim0]
X = cat0.position(in_initial=False, subtract_observer=True) X = cat0.position(in_initial=False)
nhalos = X.shape[0] nhalos = X.shape[0]
num_cats = len(cats) - 1 num_cats = len(cats) - 1

View File

@ -33,6 +33,7 @@ from .paths import Paths
from .readsim import CSiBORGReader from .readsim import CSiBORGReader
from .utils import (add_columns, cartesian_to_radec, cols_to_structured, from .utils import (add_columns, cartesian_to_radec, cols_to_structured,
flip_cols, radec_to_cartesian, real2redshift) flip_cols, radec_to_cartesian, real2redshift)
from ..utils import periodic_distance_two_points
class BaseCatalogue(ABC): class BaseCatalogue(ABC):
@ -73,6 +74,17 @@ class BaseCatalogue(ABC):
""" """
pass pass
@abstractproperty
def simname(self):
"""
Simulation name.
Returns
-------
simname : str
"""
pass
@property @property
def paths(self): def paths(self):
""" """
@ -327,7 +339,7 @@ class BaseCatalogue(ABC):
return numpy.vstack([self["L{}".format(p)] for p in ("x", "y", "z")]).T return numpy.vstack([self["L{}".format(p)] for p in ("x", "y", "z")]).T
@lru_cache(maxsize=2) @lru_cache(maxsize=2)
def knn(self, in_initial): def knn(self, in_initial, subtract_observer, periodic):
r""" r"""
kNN object for catalogue objects with caching. Positions are centered kNN object for catalogue objects with caching. Positions are centered
on the observer. on the observer.
@ -336,14 +348,32 @@ class BaseCatalogue(ABC):
---------- ----------
in_initial : bool in_initial : bool
Whether to define the kNN on the initial or final snapshot. Whether to define the kNN on the initial or final snapshot.
subtract_observer : bool
Whether to subtract the observer's location from the positions.
periodic : bool
Whether to use periodic boundary conditions.
Returns Returns
------- -------
knn : :py:class:`sklearn.neighbors.NearestNeighbors` knn : :py:class:`sklearn.neighbors.NearestNeighbors`
kNN object fitted with object positions. kNN object fitted with object positions.
""" """
pos = self.position(in_initial=in_initial) if subtract_observer and periodic:
return NearestNeighbors().fit(pos) raise ValueError("Subtracting observer is not supported for "
"periodic boundary conditions.")
pos = self.position(in_initial=in_initial,
subtract_observer=subtract_observer)
if periodic:
L = self.box.boxsize
knn = NearestNeighbors(
metric=lambda a, b: periodic_distance_two_points(a, b, L))
else:
knn = NearestNeighbors()
knn.fit(pos)
return knn
def nearest_neighbours(self, X, radius, in_initial, knearest=False, def nearest_neighbours(self, X, radius, in_initial, knearest=False,
return_mass=False, mass_key=None): return_mass=False, mass_key=None):
@ -382,7 +412,8 @@ class BaseCatalogue(ABC):
if return_mass and not mass_key: if return_mass and not mass_key:
raise ValueError("`mass_key` must be provided if `return_mass`.") raise ValueError("`mass_key` must be provided if `return_mass`.")
knn = self.knn(in_initial) knn = self.knn(in_initial, subtract_observer=False, periodic=True)
if knearest: if knearest:
dist, indxs = knn.kneighbors(X, radius) dist, indxs = knn.kneighbors(X, radius)
else: else:
@ -564,6 +595,10 @@ class CSiBORGHaloCatalogue(BaseCatalogue):
""" """
return CSiBORGBox(self.nsnap, self.nsim, self.paths) return CSiBORGBox(self.nsnap, self.nsim, self.paths)
@property
def simname(self):
return "csiborg"
############################################################################### ###############################################################################
# Quijote halo catalogue # # Quijote halo catalogue #
@ -661,6 +696,10 @@ class QuijoteHaloCatalogue(BaseCatalogue):
assert nsnap in [0, 1, 2, 3, 4] assert nsnap in [0, 1, 2, 3, 4]
self._nsnap = nsnap self._nsnap = nsnap
@property
def simname(self):
return "quijote"
@property @property
def redshift(self): def redshift(self):
""" """

View File

@ -47,6 +47,10 @@ class PairOverlap:
_data = None _data = None
def __init__(self, cat0, catx, paths, maxdist=None): def __init__(self, cat0, catx, paths, maxdist=None):
if cat0.simname != catx.simname:
raise ValueError("The two catalogues must be from the same "
"simulation.")
self._cat0 = cat0 self._cat0 = cat0
self._catx = catx self._catx = catx
self.load(cat0, catx, paths, maxdist) self.load(cat0, catx, paths, maxdist)
@ -77,8 +81,8 @@ class PairOverlap:
# We first load in the output files. We need to find the right # We first load in the output files. We need to find the right
# combination of the reference and cross simulation. # combination of the reference and cross simulation.
fname = paths.overlap(nsim0, nsimx, smoothed=False) fname = paths.overlap(cat0.simname, nsim0, nsimx, smoothed=False)
fname_inv = paths.overlap(nsimx, nsim0, smoothed=False) fname_inv = paths.overlap(cat0.simname, nsimx, nsim0, smoothed=False)
if isfile(fname): if isfile(fname):
data_ngp = numpy.load(fname, allow_pickle=True) data_ngp = numpy.load(fname, allow_pickle=True)
to_invert = False to_invert = False
@ -89,7 +93,8 @@ class PairOverlap:
else: else:
raise FileNotFoundError(f"No file found for {nsim0} and {nsimx}.") raise FileNotFoundError(f"No file found for {nsim0} and {nsimx}.")
fname_smooth = paths.overlap(cat0.nsim, catx.nsim, smoothed=True) fname_smooth = paths.overlap(cat0.simname, cat0.nsim, catx.nsim,
smoothed=True)
data_smooth = numpy.load(fname_smooth, allow_pickle=True) data_smooth = numpy.load(fname_smooth, allow_pickle=True)
# Create mapping from halo indices to array positions in the catalogue. # Create mapping from halo indices to array positions in the catalogue.
@ -764,13 +769,15 @@ class NPairsOverlap:
############################################################################### ###############################################################################
def get_cross_sims(nsim0, paths, smoothed): def get_cross_sims(simname, nsim0, paths, smoothed):
""" """
Get the list of cross simulations for a given reference simulation for Get the list of cross simulations for a given reference simulation for
which the overlap has been calculated. which the overlap has been calculated.
Parameters Parameters
---------- ----------
simname : str
Simulation name.
nsim0 : int nsim0 : int
Reference simulation number. Reference simulation number.
paths : :py:class:`csiborgtools.paths.Paths` paths : :py:class:`csiborgtools.paths.Paths`
@ -782,8 +789,8 @@ def get_cross_sims(nsim0, paths, smoothed):
for nsimx in paths.get_ics("csiborg"): for nsimx in paths.get_ics("csiborg"):
if nsimx == nsim0: if nsimx == nsim0:
continue continue
f1 = paths.overlap(nsim0, nsimx, smoothed) f1 = paths.overlap(simname, nsim0, nsimx, smoothed)
f2 = paths.overlap(nsimx, nsim0, smoothed) f2 = paths.overlap(simname, nsimx, nsim0, smoothed)
if isfile(f1) or isfile(f2): if isfile(f1) or isfile(f2):
nsimxs.append(nsimx) nsimxs.append(nsimx)
return nsimxs return nsimxs

View File

@ -462,12 +462,14 @@ class Paths:
fname = f"out_{str(nsim).zfill(5)}_{str(nsnap).zfill(5)}.npy" fname = f"out_{str(nsim).zfill(5)}_{str(nsnap).zfill(5)}.npy"
return join(fdir, fname) return join(fdir, fname)
def overlap(self, nsim0, nsimx, smoothed): def overlap(self, simname, nsim0, nsimx, smoothed):
""" """
Path to the overlap files between two CSiBORG simulations. Path to the overlap files between two CSiBORG simulations.
Parameters Parameters
---------- ----------
simname : str
Simulation name. Must be one of `csiborg` or `quijote`.
nsim0 : int nsim0 : int
IC realisation index of the first simulation. IC realisation index of the first simulation.
nsimx : int nsimx : int
@ -479,7 +481,12 @@ class Paths:
------- -------
path : str path : str
""" """
fdir = join(self.postdir, "overlap") if simname == "csiborg":
fdir = join(self.postdir, "overlap")
elif simname == "quijote":
fdir = join(self.quijote_dir, "overlap")
else:
raise ValueError(f"Unknown simulation name `{simname}`.")
try_create_directory(fdir) try_create_directory(fdir)

View File

@ -92,6 +92,39 @@ def periodic_distance(points, reference, boxsize):
return dist return dist
@jit(nopython=True, fastmath=True, boundscheck=False)
def periodic_distance_two_points(p1, p2, boxsize):
"""
Compute the 3D distance between two points using periodic boundary
conditions. This is an optimized JIT implementation.
Parameters
----------
p1 : 1-dimensional array of shape `(3, )`
First point.
p2 : 1-dimensional array of shape `(3, )`
Second point.
boxsize : float
Box size.
Returns
-------
dist : 1-dimensional array of shape `(n_points, )`
"""
half_box = boxsize / 2
dist = 0
for i in range(3):
dist_1d = abs(p1[i] - p2[i])
if dist_1d > (half_box):
dist_1d = boxsize - dist_1d
dist += dist_1d**2
return dist**0.5
@jit(nopython=True, fastmath=True, boundscheck=False) @jit(nopython=True, fastmath=True, boundscheck=False)
def delta2ncells(delta): def delta2ncells(delta):
""" """

View File

@ -59,10 +59,10 @@ def do_auto(args, config, cats, nsim, paths):
------- -------
None None
""" """
rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax)
knncdf = csiborgtools.clustering.kNN_1DCDF()
cat = cats[nsim] cat = cats[nsim]
knn = cat.knn(in_initial=False) rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax, cat.boxsize)
knncdf = csiborgtools.clustering.kNN_1DCDF()
knn = cat.knn(in_initial=False, subtract_observer=False, periodic=True)
rs, cdf = knncdf( rs, cdf = knncdf(
knn, rvs_gen=rvs_gen, nneighbours=config["nneighbours"], knn, rvs_gen=rvs_gen, nneighbours=config["nneighbours"],
rmin=config["rmin"], rmax=config["rmax"], rmin=config["rmin"], rmax=config["rmax"],
@ -97,9 +97,9 @@ def do_cross_rand(args, config, cats, nsim, paths):
------- -------
None None
""" """
rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax)
cat = cats[nsim] cat = cats[nsim]
knn1 = cat.knn(in_initial=False) rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax, cat.boxsize)
knn1 = cat.knn(in_initial=False, subtract_observer=False, periodic=True)
knn2 = NearestNeighbors() knn2 = NearestNeighbors()
pos2 = rvs_gen(len(cat).shape[0]) pos2 = rvs_gen(len(cat).shape[0])
@ -126,7 +126,7 @@ if __name__ == "__main__":
help="Simulation name") help="Simulation name")
parser.add_argument("--nsims", type=int, nargs="+", default=None, parser.add_argument("--nsims", type=int, nargs="+", default=None,
help="Indices of simulations to cross. If `-1` processes all simulations.") # noqa help="Indices of simulations to cross. If `-1` processes all simulations.") # noqa
parser.add_argument("--Rmax", type=float, default=155/0.705, parser.add_argument("--Rmax", type=float, default=155,
help="High-resolution region radius") # noqa help="High-resolution region radius") # noqa
parser.add_argument("--verbose", type=lambda x: bool(strtobool(x)), parser.add_argument("--verbose", type=lambda x: bool(strtobool(x)),
default=False) default=False)

View File

@ -37,12 +37,12 @@ except ModuleNotFoundError:
def do_auto(args, config, cats, nsim, paths): def do_auto(args, config, cats, nsim, paths):
cat = cats[nsim]
tpcf = csiborgtools.clustering.Mock2PCF() tpcf = csiborgtools.clustering.Mock2PCF()
rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax) rvs_gen = csiborgtools.clustering.RVSinsphere(args.Rmax, cat.boxsize)
bins = numpy.logspace( bins = numpy.logspace(
numpy.log10(config["rpmin"]), numpy.log10(config["rpmax"]), numpy.log10(config["rpmin"]), numpy.log10(config["rpmax"]),
config["nrpbins"] + 1,) config["nrpbins"] + 1,)
cat = cats[nsim]
pos = cat.position(in_initial=False, cartesian=True) pos = cat.position(in_initial=False, cartesian=True)
nrandom = int(config["randmult"] * pos.shape[0]) nrandom = int(config["randmult"] * pos.shape[0])
@ -59,7 +59,7 @@ if __name__ == "__main__":
help="Simulation name") help="Simulation name")
parser.add_argument("--nsims", type=int, nargs="+", default=None, parser.add_argument("--nsims", type=int, nargs="+", default=None,
help="Indices of simulations to cross. If `-1` processes all simulations.") # noqa help="Indices of simulations to cross. If `-1` processes all simulations.") # noqa
parser.add_argument("--Rmax", type=float, default=155/0.705, parser.add_argument("--Rmax", type=float, default=155,
help="High-resolution region radius.") help="High-resolution region radius.")
parser.add_argument("--verbose", type=lambda x: bool(strtobool(x)), parser.add_argument("--verbose", type=lambda x: bool(strtobool(x)),
default=False, help="Verbosity flag.") default=False, help="Verbosity flag.")

View File

@ -14,8 +14,9 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
""" """
Script to calculate the particle centre of mass, Lagrangian patch size in the Script to calculate the particle centre of mass, Lagrangian patch size in the
initial snapshot. The initial snapshot particles are read from the sorted initial snapshot.
files.
The initial snapshot particles are read from the sorted files.
""" """
from argparse import ArgumentParser from argparse import ArgumentParser
from datetime import datetime from datetime import datetime
@ -74,7 +75,7 @@ def _main(nsim, simname, verbose):
# Initialise the overlapper. # Initialise the overlapper.
if simname == "csiborg": if simname == "csiborg":
kwargs = {"box_size": 2048, "bckg_halfsize": 475} kwargs = {"box_size": 2048, "bckg_halfsize": 512}
else: else:
kwargs = {"box_size": 512, "bckg_halfsize": 256} kwargs = {"box_size": 512, "bckg_halfsize": 256}
overlapper = csiborgtools.match.ParticleOverlap(**kwargs) overlapper = csiborgtools.match.ParticleOverlap(**kwargs)
@ -86,7 +87,7 @@ def _main(nsim, simname, verbose):
hid2map) hid2map)
# Skip if the halo has no particles or is too small. # Skip if the halo has no particles or is too small.
if part is None or part.size < 100: if part is None or part.size < 40:
continue continue
pos, mass = part[:, :3], part[:, 3] pos, mass = part[:, :3], part[:, 3]

View File

@ -57,12 +57,13 @@ def pair_match(nsim0, nsimx, simname, sigma, verbose):
None None
""" """
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring) paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
smooth_kwargs = {"sigma": sigma, "mode": "wrap"} smooth_kwargs = {"sigma": sigma, "mode": "constant", "cval": 0}
if simname == "csiborg": if simname == "csiborg":
overlapper_kwargs = {"box_size": 2048, "bckg_halfsize": 475} overlapper_kwargs = {"box_size": 2048, "bckg_halfsize": 512}
mass_kind = "fof_totpartmass" mass_kind = "fof_totpartmass"
bounds = {mass_kind: (1e13, None)} bounds = {"dist": (0, 155), mass_kind: (10**13.25, None)}
cat0 = csiborgtools.read.CSiBORGHaloCatalogue( cat0 = csiborgtools.read.CSiBORGHaloCatalogue(
nsim0, paths, bounds=bounds, load_fitted=False, nsim0, paths, bounds=bounds, load_fitted=False,
with_lagpatch=True) with_lagpatch=True)
@ -72,11 +73,14 @@ def pair_match(nsim0, nsimx, simname, sigma, verbose):
elif simname == "quijote": elif simname == "quijote":
overlapper_kwargs = {"box_size": 512, "bckg_halfsize": 256} overlapper_kwargs = {"box_size": 512, "bckg_halfsize": 256}
mass_kind = "group_mass" mass_kind = "group_mass"
bounds = {mass_kind: (1e14, None)} bounds = {mass_kind: (10**13.25, None)}
cat0 = csiborgtools.read.QuijoteHaloCatalogue( cat0 = csiborgtools.read.QuijoteHaloCatalogue(
nsim0, paths, 4, load_fitted=False, with_lagpatch=True) nsim0, paths, 4, bounds=bounds, load_fitted=False,
with_lagpatch=True)
catx = csiborgtools.read.QuijoteHaloCatalogue( catx = csiborgtools.read.QuijoteHaloCatalogue(
nsimx, paths, 4, load_fitted=False, with_lagpatch=True) nsimx, paths, 4, bounds=bounds, load_fitted=False,
with_lagpatch=True)
else: else:
raise ValueError(f"Unknown simulation name: `{simname}`.") raise ValueError(f"Unknown simulation name: `{simname}`.")
@ -116,7 +120,7 @@ def pair_match(nsim0, nsimx, simname, sigma, verbose):
for j, match in enumerate(matches): for j, match in enumerate(matches):
match_hids[i][j] = catx["index"][match] match_hids[i][j] = catx["index"][match]
fout = paths.overlap(nsim0, nsimx, smoothed=False) fout = paths.overlap(simname, nsim0, nsimx, smoothed=False)
if verbose: if verbose:
print(f"{datetime.now()}: saving to ... `{fout}`.", flush=True) print(f"{datetime.now()}: saving to ... `{fout}`.", flush=True)
numpy.savez(fout, ref_hids=cat0["index"], match_hids=match_hids, numpy.savez(fout, ref_hids=cat0["index"], match_hids=match_hids,
@ -135,7 +139,7 @@ def pair_match(nsim0, nsimx, simname, sigma, verbose):
match_indxs, smooth_kwargs, match_indxs, smooth_kwargs,
verbose=verbose) verbose=verbose)
fout = paths.overlap(nsim0, nsimx, smoothed=True) fout = paths.overlap(simname, nsim0, nsimx, smoothed=True)
if verbose: if verbose:
print(f"{datetime.now()}: saving to ... `{fout}`.", flush=True) print(f"{datetime.now()}: saving to ... `{fout}`.", flush=True)
numpy.savez(fout, smoothed_overlap=smoothed_overlap, sigma=sigma) numpy.savez(fout, smoothed_overlap=smoothed_overlap, sigma=sigma)

View File

@ -178,6 +178,7 @@ def plot_hmf(pdf=False):
csiborg5511[x > 3e15] = numpy.nan csiborg5511[x > 3e15] = numpy.nan
with plt.style.context(plt_utils.mplstyle): with plt.style.context(plt_utils.mplstyle):
cols = plt.rcParams["axes.prop_cycle"].by_key()["color"]
fig, ax = plt.subplots(nrows=2, sharex=True, fig, ax = plt.subplots(nrows=2, sharex=True,
figsize=(3.5, 2.625 * 1.25), figsize=(3.5, 2.625 * 1.25),
gridspec_kw={"height_ratios": [1, 0.45]}) gridspec_kw={"height_ratios": [1, 0.45]})
@ -186,15 +187,15 @@ def plot_hmf(pdf=False):
# Upper panel data # Upper panel data
mean_csiborg = numpy.mean(csiborg_counts, axis=0) mean_csiborg = numpy.mean(csiborg_counts, axis=0)
std_csiborg = numpy.std(csiborg_counts, axis=0) std_csiborg = numpy.std(csiborg_counts, axis=0)
ax[0].plot(x, mean_csiborg, label="CSiBORG") ax[0].plot(x, mean_csiborg, label="CSiBORG", c=cols[0])
ax[0].fill_between(x, mean_csiborg - std_csiborg, ax[0].fill_between(x, mean_csiborg - std_csiborg,
mean_csiborg + std_csiborg, alpha=0.5) mean_csiborg + std_csiborg, alpha=0.5, color=cols[0])
mean_quijote = numpy.mean(quijote_counts, axis=0) mean_quijote = numpy.mean(quijote_counts, axis=0)
std_quijote = numpy.std(quijote_counts, axis=0) std_quijote = numpy.std(quijote_counts, axis=0)
ax[0].plot(x, mean_quijote, label="Quijote") ax[0].plot(x, mean_quijote, label="Quijote", c=cols[1])
ax[0].fill_between(x, mean_quijote - std_quijote, ax[0].fill_between(x, mean_quijote - std_quijote,
mean_quijote + std_quijote, alpha=0.5) mean_quijote + std_quijote, alpha=0.5, color=cols[1])
ax[0].plot(x, csiborg5511, label="CSiBORG 5511", c="k", ls="--") ax[0].plot(x, csiborg5511, label="CSiBORG 5511", c="k", ls="--")
std5511 = numpy.sqrt(csiborg5511) std5511 = numpy.sqrt(csiborg5511)
@ -204,9 +205,11 @@ def plot_hmf(pdf=False):
log_y = numpy.log10(mean_csiborg / mean_quijote) log_y = numpy.log10(mean_csiborg / mean_quijote)
err = numpy.sqrt((std_csiborg / mean_csiborg / numpy.log(10))**2 err = numpy.sqrt((std_csiborg / mean_csiborg / numpy.log(10))**2
+ (std_quijote / mean_quijote / numpy.log(10))**2) + (std_quijote / mean_quijote / numpy.log(10))**2)
ax[1].plot(x, 10**log_y, c="gray") ax[1].plot(x, 10**log_y, c=cols[0])
ax[1].fill_between(x, 10**(log_y - err), 10**(log_y + err), alpha=0.5, ax[1].fill_between(x, 10**(log_y - err), 10**(log_y + err), alpha=0.5,
color="gray") color=col[0])
ax[1].plot(x, csiborg5511 / mean_quijote, c="k", ls="--")
# Labels and accesories # Labels and accesories
ax[1].axhline(1, color="k", ls="--", ax[1].axhline(1, color="k", ls="--",

View File

@ -143,13 +143,15 @@ def plot_mass_vs_maxpairoverlap(nsim0, nsimx):
@cache_to_disk(7) @cache_to_disk(7)
def get_overlap(nsim0): def get_overlap(simname, nsim0):
""" """
Calculate the summed overlap and probability of no match for a single Calculate the summed overlap and probability of no match for a single
reference simulation. reference simulation.
Parameters Parameters
---------- ----------
simname : str
Simulation name.
nsim0 : int nsim0 : int
Simulation index. Simulation index.
@ -167,7 +169,8 @@ def get_overlap(nsim0):
Probability of no match for each halo in the reference simulation. Probability of no match for each halo in the reference simulation.
""" """
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring) paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
nsimxs = csiborgtools.read.get_cross_sims(nsim0, paths, smoothed=True) nsimxs = csiborgtools.read.get_cross_sims(simname, nsim0, paths,
smoothed=True)
cat0 = open_cat(nsim0) cat0 = open_cat(nsim0)
catxs = [] catxs = []
@ -195,7 +198,7 @@ def plot_mass_vsmedmaxoverlap(nsim0):
nsim0 : int nsim0 : int
Reference simulation index. Reference simulation index.
""" """
x, __, max_overlap, __, __ = get_overlap(nsim0) x, __, max_overlap, __, __ = get_overlap("csiborg", nsim0)
for i in trange(max_overlap.shape[0]): for i in trange(max_overlap.shape[0]):
if numpy.sum(numpy.isnan(max_overlap[i, :])) > 0: if numpy.sum(numpy.isnan(max_overlap[i, :])) > 0:
@ -255,7 +258,7 @@ def plot_summed_overlap_vs_mass(nsim0):
------- -------
None None
""" """
x, __, __, summed_overlap, prob_nomatch = get_overlap(nsim0) x, __, __, summed_overlap, prob_nomatch = get_overlap("csiborg", nsim0)
del __ del __
collect() collect()
@ -389,12 +392,14 @@ def plot_mass_vs_separation(nsim0, nsimx, plot_std=False, min_overlap=0.0):
@cache_to_disk(7) @cache_to_disk(7)
def get_max_key(nsim0, key): def get_max_key(simname, nsim0, key):
""" """
Get the value of a maximum overlap halo's property. Get the value of a maximum overlap halo's property.
Parameters Parameters
---------- ----------
simname : str
Simulation name.
nsim0 : int nsim0 : int
Reference simulation index. Reference simulation index.
key : str key : str
@ -412,7 +417,8 @@ def get_max_key(nsim0, key):
Value of the property of the maximum overlap halo. Value of the property of the maximum overlap halo.
""" """
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring) paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
nsimxs = csiborgtools.read.get_cross_sims(nsim0, paths, smoothed=True) nsimxs = csiborgtools.read.get_cross_sims(simname, nsim0, paths,
smoothed=True)
nsimxs = nsimxs nsimxs = nsimxs
cat0 = open_cat(nsim0) cat0 = open_cat(nsim0)
@ -440,7 +446,7 @@ def plot_maxoverlap_mass(nsim0):
nsim0 : int nsim0 : int
Reference simulation index. Reference simulation index.
""" """
mass0, __, __, stat = get_max_key(nsim0, "totpartmass") mass0, __, __, stat = get_max_key("csiborg", nsim0, "totpartmass")
mu = numpy.mean(stat, axis=1) mu = numpy.mean(stat, axis=1)
std = numpy.std(numpy.log10(stat), axis=1) std = numpy.std(numpy.log10(stat), axis=1)
@ -463,8 +469,10 @@ def plot_maxoverlap_mass(nsim0):
axs[0].set_xlabel(r"$\log M_{\rm tot} ~ [M_\odot / h]$") axs[0].set_xlabel(r"$\log M_{\rm tot} ~ [M_\odot / h]$")
axs[1].set_xlabel(r"$\log M_{\rm tot} ~ [M_\odot / h]$") axs[1].set_xlabel(r"$\log M_{\rm tot} ~ [M_\odot / h]$")
axs[0].set_ylabel(r"Max. overlap mean of $\log M_{\rm tot} ~ [M_\odot / h]$") axs[0].set_ylabel(
axs[1].set_ylabel(r"Max. overlap std. of $\log M_{\rm tot} ~ [M_\odot / h]$") r"Max. overlap mean of $\log M_{\rm tot} ~ [M_\odot / h]$")
axs[1].set_ylabel(
r"Max. overlap std. of $\log M_{\rm tot} ~ [M_\odot / h]$")
ims = [im0, im1] ims = [im0, im1]
for i in range(2): for i in range(2):
@ -498,7 +506,7 @@ def plot_maxoverlapstat(nsim0, key):
Property to get. Property to get.
""" """
assert key != "totpartmass" assert key != "totpartmass"
mass0, key_val, __, stat = get_max_key(nsim0, key) mass0, key_val, __, stat = get_max_key("csiborg", nsim0, key)
xlabels = {"lambda200c": r"\log \lambda_{\rm 200c}"} xlabels = {"lambda200c": r"\log \lambda_{\rm 200c}"}
key_label = xlabels.get(key, key) key_label = xlabels.get(key, key)
@ -546,13 +554,15 @@ def plot_maxoverlapstat(nsim0, key):
@cache_to_disk(7) @cache_to_disk(7)
def get_expected_mass(nsim0, min_overlap): def get_expected_mass(simname, nsim0, min_overlap):
""" """
Get the expected mass of a reference halo given its overlap with halos Get the expected mass of a reference halo given its overlap with halos
from other simulations. from other simulations.
Parameters Parameters
---------- ----------
simname : str
Simulation name.
nsim0 : int nsim0 : int
Reference simulation index. Reference simulation index.
min_overlap : float min_overlap : float
@ -570,7 +580,8 @@ def get_expected_mass(nsim0, min_overlap):
Probability of not matching the reference halo. Probability of not matching the reference halo.
""" """
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring) paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
nsimxs = csiborgtools.read.get_cross_sims(nsim0, paths, smoothed=True) nsimxs = csiborgtools.read.get_cross_sims(simname, nsim0, paths,
smoothed=True)
nsimxs = nsimxs nsimxs = nsimxs
cat0 = open_cat(nsim0) cat0 = open_cat(nsim0)
@ -602,7 +613,8 @@ def plot_mass_vs_expected_mass(nsim0, min_overlap=0, max_prob_nomatch=1):
max_prob_nomatch : float, optional max_prob_nomatch : float, optional
Maximum probability of no match to consider. Maximum probability of no match to consider.
""" """
mass, mu, std, prob_nomatch = get_expected_mass(nsim0, min_overlap) mass, mu, std, prob_nomatch = get_expected_mass("csiborg", nsim0,
min_overlap)
std = std / mu / numpy.log(10) std = std / mu / numpy.log(10)
mass = numpy.log10(mass) mass = numpy.log10(mass)
@ -1343,7 +1355,7 @@ def plot_kl_vs_overlap(runs, nsim, kwargs, runs_to_mass, plot_std=True,
for run in runs: for run in runs:
nn_data = nn_reader.read_single("csiborg", run, nsim, nobs=None) nn_data = nn_reader.read_single("csiborg", run, nsim, nobs=None)
nn_hindxs = nn_data["ref_hindxs"] nn_hindxs = nn_data["ref_hindxs"]
mass, overlap_hindxs, __, summed_overlap, prob_nomatch = get_overlap(nsim) # noqa mass, overlap_hindxs, __, summed_overlap, prob_nomatch = get_overlap("csiborg", nsim) # noqa
# We need to match the hindxs between the two. # We need to match the hindxs between the two.
hind2overlap_array = {hind: i for i, hind in enumerate(overlap_hindxs)} hind2overlap_array = {hind: i for i, hind in enumerate(overlap_hindxs)}

View File

@ -1,5 +1,24 @@
from setuptools import find_packages, setup from setuptools import find_packages, setup
# List of dependencies:
# - Corrfunc -> To be moved to a separate package.
# - NumPy
# - SciPy
# - Numba
# - Pylians
# - tqdm
# - healpy
# - astropy
# - scikit-learn
# - joblib
# - h5py
# - MPI
# - pyyaml
# - taskmaster
# - matplotlib
# - scienceplots
# - cache_to_disk
BUILD_REQ = ["numpy", "scipy"] BUILD_REQ = ["numpy", "scipy"]
INSTALL_REQ = BUILD_REQ INSTALL_REQ = BUILD_REQ