Add snapshots optionally directly to catalogue (#101)

* Add isinstance check

* Add snapshot to cat

* Rename mass_kind to mass_key

* Remove import

* Fix compatiblility

* Remove old export

* Rename import

* Fix calling

* Remove paths dependence

* Update match script

* Add check if halo has no particles
This commit is contained in:
Richard Stiskalek 2023-12-20 16:28:26 +01:00 committed by GitHub
parent 7d5141cf7f
commit a08109b997
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 158 additions and 105 deletions

View file

@ -13,4 +13,4 @@
# 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 .match import (ParticleOverlap, RealisationsMatcher, calculate_overlap, # noqa from .match import (ParticleOverlap, RealisationsMatcher, calculate_overlap, # noqa
pos2cell, find_neighbour, matching_max) # noqa find_neighbour, matching_max) # noqa

View file

@ -92,22 +92,18 @@ class RealisationsMatcher(BaseMatcher):
dlogmass : float, optional dlogmass : float, optional
Tolerance on the absolute logarithmic mass difference of potential Tolerance on the absolute logarithmic mass difference of potential
matches. matches.
mass_kind : str, optional
Mass kind whose similarity is to be checked. Must be a valid key in the
halo catalogue.
""" """
_nmult = None _nmult = None
_dlogmass = None _dlogmass = None
_mass_kind = None _mass_key = None
_overlapper = None _overlapper = None
def __init__(self, box_size, bckg_halfsize, nmult=1.0, dlogmass=2.0, def __init__(self, box_size, bckg_halfsize, nmult=1.0, dlogmass=2.0):
mass_kind="totpartmass"):
self.box_size = box_size self.box_size = box_size
self.bckg_halfsize = bckg_halfsize self.bckg_halfsize = bckg_halfsize
self.nmult = nmult self.nmult = nmult
self.dlogmass = dlogmass self.dlogmass = dlogmass
self.mass_kind = mass_kind self.mass_key = "totmass"
self._overlapper = ParticleOverlap(box_size, bckg_halfsize) self._overlapper = ParticleOverlap(box_size, bckg_halfsize)
@ -116,6 +112,10 @@ class RealisationsMatcher(BaseMatcher):
""" """
Multiplier of the sum of the initial Lagrangian patch sizes of a halo Multiplier of the sum of the initial Lagrangian patch sizes of a halo
pair. Determines the range within which neighbors are returned. pair. Determines the range within which neighbors are returned.
Returns
-------
float
""" """
return self._nmult return self._nmult
@ -130,6 +130,10 @@ class RealisationsMatcher(BaseMatcher):
""" """
Tolerance on the absolute logarithmic mass difference of potential Tolerance on the absolute logarithmic mass difference of potential
matches. matches.
Returns
-------
float
""" """
return self._dlogmass return self._dlogmass
@ -140,18 +144,22 @@ class RealisationsMatcher(BaseMatcher):
self._dlogmass = float(value) self._dlogmass = float(value)
@property @property
def mass_kind(self): def mass_key(self):
""" """
Mass kind whose similarity is to be checked. Must be a valid key in the Mass key whose similarity is to be checked. Must be a valid key in the
halo catalogue. halo catalogue.
"""
return self._mass_kind
@mass_kind.setter Returns
def mass_kind(self, value): -------
str
"""
return self._mass_key
@mass_key.setter
def mass_key(self, value):
if not isinstance(value, str): if not isinstance(value, str):
raise ValueError("`mass_kind` must be a string.") raise ValueError("`mass_key` must be a string.")
self._mass_kind = value self._mass_key = value
@property @property
def overlapper(self): def overlapper(self):
@ -195,15 +203,15 @@ class RealisationsMatcher(BaseMatcher):
# snapshot. # snapshot.
match_indxs = radius_neighbours( match_indxs = radius_neighbours(
catx.knn(in_initial=True, subtract_observer=False, periodic=True), catx.knn(in_initial=True, subtract_observer=False, periodic=True),
cat0.position(in_initial=True), cat0["lagpatch_coordinates"], radiusX=cat0["lagpatch_radius"],
radiusX=cat0["lagpatch_size"], radiusKNN=catx["lagpatch_size"], radiusKNN=catx["lagpatch_radius"], nmult=self.nmult,
nmult=self.nmult, enforce_int32=True, verbose=verbose) enforce_int32=True, verbose=verbose)
# We next remove neighbours whose mass is too large/small. # We next remove neighbours whose mass is too large/small.
if self.dlogmass is not None: if self.dlogmass is not None:
for i, indx in enumerate(match_indxs): for i, indx in enumerate(match_indxs):
# |log(M1 / M2)| # |log(M1 / M2)|
p = self.mass_kind p = self.mass_key
aratio = numpy.abs(numpy.log10(catx[p][indx] / cat0[p][i])) aratio = numpy.abs(numpy.log10(catx[p][indx] / cat0[p][i]))
match_indxs[i] = match_indxs[i][aratio < self.dlogmass] match_indxs[i] = match_indxs[i][aratio < self.dlogmass]
@ -372,11 +380,17 @@ class ParticleOverlap(BaseMatcher):
disable=not verbose disable=not verbose
) )
for hid in iterator: for hid in iterator:
pos = cat.halo_particles(hid, "pos", in_initial=True) try:
if pos is None: pos = cat.snapshot.halo_coordinates(hid, is_group=True)
except ValueError as e:
# If not particles found for this halo, just skip it.
if str(e).startswith("Halo "):
continue continue
else:
# If the error does not start with "Halo ", re-raise it
raise
mass = cat.halo_particles(hid, "mass", in_initial=True) mass = cat.snapshot.halo_masses(hid, is_group=True)
pos = pos2cell(pos, self.box_size) pos = pos2cell(pos, self.box_size)
@ -835,8 +849,8 @@ def load_processed_halo(hid, cat, ncells, nshift):
maxs : len-3 tuple maxs : len-3 tuple
Maximum cell indices of the halo. Maximum cell indices of the halo.
""" """
pos = cat.halo_particles(hid, "pos", in_initial=True) pos = cat.snapshot.halo_coordinates(hid, is_group=True)
mass = cat.halo_particles(hid, "mass", in_initial=True) mass = cat.snapshot.halo_masses(hid, is_group=True)
pos = pos2cell(pos, ncells) pos = pos2cell(pos, ncells)
mins, maxs = get_halo_cell_limits(pos, ncells=ncells, nshift=nshift) mins, maxs = get_halo_cell_limits(pos, ncells=ncells, nshift=nshift)
@ -921,7 +935,7 @@ def find_neighbour(nsim0, cats):
assert all(isinstance(cat, type(cats[nsim0])) for cat in cats.values()) assert all(isinstance(cat, type(cats[nsim0])) for cat in cats.values())
cat0 = cats[nsim0] cat0 = cats[nsim0]
X = cat0.position(in_initial=False) X = cat0["lagpatch_coordinates"]
nhalos = X.shape[0] nhalos = X.shape[0]
num_cats = len(cats) - 1 num_cats = len(cats) - 1
@ -946,7 +960,7 @@ def find_neighbour(nsim0, cats):
############################################################################### ###############################################################################
def matching_max(cat0, catx, mass_kind, mult, periodic, overlap=None, def matching_max(cat0, catx, mass_key, mult, periodic, overlap=None,
match_indxs=None, verbose=True): match_indxs=None, verbose=True):
""" """
Halo matching algorithm based on [1]. Halo matching algorithm based on [1].
@ -957,7 +971,7 @@ def matching_max(cat0, catx, mass_kind, mult, periodic, overlap=None,
Halo catalogue of the reference simulation. Halo catalogue of the reference simulation.
catx : instance of :py:class:`csiborgtools.read.BaseCatalogue` catx : instance of :py:class:`csiborgtools.read.BaseCatalogue`
Halo catalogue of the cross simulation. Halo catalogue of the cross simulation.
mass_kind : str mass_key : str
Name of the mass column. Name of the mass column.
mult : float mult : float
Multiple of R200c below which to consider a match. Multiple of R200c below which to consider a match.
@ -985,13 +999,13 @@ def matching_max(cat0, catx, mass_kind, mult, periodic, overlap=None,
Monthly Notices of the Royal Astronomical Society, Volume 516, Issue 3, Monthly Notices of the Royal Astronomical Society, Volume 516, Issue 3,
November 2022, Pages 35923601, https://doi.org/10.1093/mnras/stac2407 November 2022, Pages 35923601, https://doi.org/10.1093/mnras/stac2407
""" """
pos0 = cat0.position(in_initial=False) pos0 = cat0["cartesian_pos"]
knnx = catx.knn(in_initial=False, subtract_observer=False, knnx = catx.knn(in_initial=False, subtract_observer=False,
periodic=periodic) periodic=periodic)
rad0 = cat0["r200c"] rad0 = cat0["r200c"]
mass0 = numpy.log10(cat0[mass_kind]) mass0 = numpy.log10(cat0[mass_key])
massx = numpy.log10(catx[mass_kind]) massx = numpy.log10(catx[mass_key])
assert numpy.all(numpy.isfinite(mass0)) & numpy.all(numpy.isfinite(massx)) assert numpy.all(numpy.isfinite(mass0)) & numpy.all(numpy.isfinite(massx))

View file

@ -32,6 +32,8 @@ from ..params import paths_glamdring
from ..utils import (cartesian_to_radec, great_circle_distance, number_counts, from ..utils import (cartesian_to_radec, great_circle_distance, number_counts,
periodic_distance_two_points, real2redshift) periodic_distance_two_points, real2redshift)
from .paths import Paths from .paths import Paths
from .snapshot import is_instance_of_base_snapshot_subclass
############################################################################### ###############################################################################
# Base catalogue # # Base catalogue #
@ -61,6 +63,7 @@ class BaseCatalogue(ABC):
self._simname = None self._simname = None
self._nsim = None self._nsim = None
self._nsnap = None self._nsnap = None
self._snapshot = None
self._paths = None self._paths = None
@ -76,9 +79,9 @@ class BaseCatalogue(ABC):
self._custom_keys = [] self._custom_keys = []
def init_with_snapshot(self, simname, nsim, nsnap, paths, bounds, boxsize, def init_with_snapshot(self, simname, nsim, nsnap, paths, snapshot,
observer_location, observer_velocity, bounds, boxsize, observer_location,
cache_maxsize=64): observer_velocity, cache_maxsize=64):
self.simname = simname self.simname = simname
self.nsim = nsim self.nsim = nsim
self.nsnap = nsnap self.nsnap = nsnap
@ -89,6 +92,8 @@ class BaseCatalogue(ABC):
self.cache_maxsize = cache_maxsize self.cache_maxsize = cache_maxsize
self.snapshot = snapshot
if bounds is not None: if bounds is not None:
self._make_mask(bounds) self._make_mask(bounds)
@ -149,6 +154,31 @@ class BaseCatalogue(ABC):
raise TypeError("`nsnap` must be an integer.") raise TypeError("`nsnap` must be an integer.")
self._nsnap = int(nsnap) self._nsnap = int(nsnap)
@property
def snapshot(self):
"""
Corresponding particle snapshot. Can be either the final or initial
one, depending on `which_snapshot`.
Returns
-------
subclass of py:class:`csiborgtools.read.snapshot.BaseSnapshot`
"""
if self._snapshot is None:
raise RuntimeError("`snapshot` is not set!")
return self._snapshot
@snapshot.setter
def snapshot(self, snapshot):
if snapshot is None:
self._snapshot = None
return
if not is_instance_of_base_snapshot_subclass(snapshot):
raise TypeError("`snapshot` must be a subclass of `BaseSnapshot`.")
self._snapshot = snapshot
@property @property
def paths(self): def paths(self):
""" """
@ -351,7 +381,7 @@ class BaseCatalogue(ABC):
volume : float volume : float
Volume in :math:`(cMpc / h)^3`. Volume in :math:`(cMpc / h)^3`.
mass_key : str, optional mass_key : str, optional
Mass key of the catalogue. Mass key to get the halo masses.
Returns Returns
------- -------
@ -613,6 +643,8 @@ class CSiBORG1Catalogue(BaseCatalogue):
IC realisation index. IC realisation index.
paths : py:class`csiborgtools.read.Paths`, optional paths : py:class`csiborgtools.read.Paths`, optional
Paths object. Paths object.
snapshot : subclass of py:class:`BaseSnapshot`, optional
Snapshot object corresponding to the catalogue.
bounds : dict, optional bounds : dict, optional
Parameter bounds; keys as parameter names, values as (min, max) or Parameter bounds; keys as parameter names, values as (min, max) or
a boolean. a boolean.
@ -621,13 +653,13 @@ class CSiBORG1Catalogue(BaseCatalogue):
cache_maxsize : int, optional cache_maxsize : int, optional
Maximum number of cached arrays. Maximum number of cached arrays.
""" """
def __init__(self, nsim, paths=None, bounds=None, observer_velocity=None, def __init__(self, nsim, paths=None, snapshot=None, bounds=None,
cache_maxsize=64): observer_velocity=None, cache_maxsize=64):
super().__init__() super().__init__()
super().init_with_snapshot( super().init_with_snapshot(
"csiborg1", nsim, max(paths.get_snapshots(nsim, "csiborg1")), "csiborg1", nsim, max(paths.get_snapshots(nsim, "csiborg1")),
paths, bounds, 677.7, [338.85, 338.85, 338.85], observer_velocity, paths, snapshot, bounds, 677.7, [338.85, 338.85, 338.85],
cache_maxsize) observer_velocity, cache_maxsize)
self._custom_keys = [] self._custom_keys = []
@ -691,6 +723,8 @@ class CSiBORG2Catalogue(BaseCatalogue):
Simulation kind. Must be one of 'main', 'varysmall', or 'random'. Simulation kind. Must be one of 'main', 'varysmall', or 'random'.
paths : py:class`csiborgtools.read.Paths`, optional paths : py:class`csiborgtools.read.Paths`, optional
Paths object. Paths object.
snapshot : subclass of py:class:`BaseSnapshot`, optional
Snapshot object corresponding to the catalogue.
bounds : dict, optional bounds : dict, optional
Parameter bounds; keys as parameter names, values as (min, max) or Parameter bounds; keys as parameter names, values as (min, max) or
a boolean. a boolean.
@ -699,12 +733,12 @@ class CSiBORG2Catalogue(BaseCatalogue):
cache_maxsize : int, optional cache_maxsize : int, optional
Maximum number of cached arrays. Maximum number of cached arrays.
""" """
def __init__(self, nsim, nsnap, kind, paths=None, bounds=None, def __init__(self, nsim, nsnap, kind, paths=None, snapshot=None,
observer_velocity=None, cache_maxsize=64): bounds=None, observer_velocity=None, cache_maxsize=64):
super().__init__() super().__init__()
super().init_with_snapshot( super().init_with_snapshot(
f"csiborg2_{kind}", nsim, nsnap, paths, bounds, 676.6, f"csiborg2_{kind}", nsim, nsnap, paths, snapshot, bounds,
[338.3, 338.3, 338.3], observer_velocity, cache_maxsize) 676.6, [338.3, 338.3, 338.3], observer_velocity, cache_maxsize)
self._custom_keys = ["GroupFirstSub", "GroupContamination", self._custom_keys = ["GroupFirstSub", "GroupContamination",
"GroupNsubs"] "GroupNsubs"]
@ -726,14 +760,14 @@ class CSiBORG2Catalogue(BaseCatalogue):
@property @property
def coordinates(self): def coordinates(self):
# We flip x and z to undo MUSIC bug. # Loading directly the Gadget4 output, flip x and z to undo MUSIC bug.
out = self._read_fof_catalogue("GroupPos") out = self._read_fof_catalogue("GroupPos")
out[:, [0, 2]] = out[:, [2, 0]] out[:, [0, 2]] = out[:, [2, 0]]
return out return out
@property @property
def velocities(self): def velocities(self):
# We flip x and z to undo MUSIC bug. # Loading directly the Gadget4 output, flip x and z to undo MUSIC bug.
out = self._read_fof_catalogue("GroupVel") out = self._read_fof_catalogue("GroupVel")
out[:, [0, 2]] = out[:, [2, 0]] out[:, [0, 2]] = out[:, [2, 0]]
return out return out
@ -789,6 +823,8 @@ class QuijoteCatalogue(BaseCatalogue):
IC realisation index. IC realisation index.
paths : py:class`csiborgtools.read.Paths`, optional paths : py:class`csiborgtools.read.Paths`, optional
Paths object. Paths object.
snapshot : subclass of py:class:`BaseSnapshot`, optional
Snapshot object corresponding to the catalogue.
bounds : dict bounds : dict
Parameter bounds; keys as parameter names, values as (min, max) Parameter bounds; keys as parameter names, values as (min, max)
tuples. Use `dist` for radial distance, `None` for no bound. tuples. Use `dist` for radial distance, `None` for no bound.
@ -797,12 +833,13 @@ class QuijoteCatalogue(BaseCatalogue):
cache_maxsize : int, optional cache_maxsize : int, optional
Maximum number of cached arrays. Maximum number of cached arrays.
""" """
def __init__(self, nsim, paths=None, bounds=None, observer_velocity=None, def __init__(self, nsim, paths=None, snapshot=None, bounds=None,
observer_velocity=None,
cache_maxsize=64): cache_maxsize=64):
super().__init__() super().__init__()
super().init_with_snapshot( super().init_with_snapshot(
"quijote", nsim, 4, paths, bounds, 1000, [500., 500., 500.,], "quijote", nsim, 4, paths, snapshot, bounds, 1000,
observer_velocity, cache_maxsize) [500., 500., 500.,], observer_velocity, cache_maxsize)
self._custom_keys = [] self._custom_keys = []
self._bounds = bounds self._bounds = bounds

View file

@ -718,3 +718,17 @@ class QuijoteField(CSiBORG1Field):
""" """
def __init__(self, nsim, paths): def __init__(self, nsim, paths):
super().__init__(nsim, paths) super().__init__(nsim, paths)
###############################################################################
# Supplementary functions #
###############################################################################
def is_instance_of_base_snapshot_subclass(obj):
"""
Check if `obj` is an instance of a subclass of `BaseSnapshot`.
"""
return isinstance(obj, BaseSnapshot) and any(
issubclass(cls, BaseSnapshot) for cls in obj.__class__.__bases__
)

View file

@ -62,8 +62,6 @@ class PairOverlap:
Halo catalogue corresponding to the reference simulation. Halo catalogue corresponding to the reference simulation.
catx : :py:class:`csiborgtools.read.CSiBORGHaloCatalogue` catx : :py:class:`csiborgtools.read.CSiBORGHaloCatalogue`
Halo catalogue corresponding to the cross simulation. Halo catalogue corresponding to the cross simulation.
paths : py:class`csiborgtools.read.Paths`
CSiBORG paths object.
min_logmass : float min_logmass : float
Minimum halo mass in :math:`\log_{10} M_\odot / h` to consider. Minimum halo mass in :math:`\log_{10} M_\odot / h` to consider.
maxdist : float, optional maxdist : float, optional
@ -75,15 +73,15 @@ class PairOverlap:
_data = None _data = None
_paths = None _paths = None
def __init__(self, cat0, catx, paths, min_logmass, maxdist=None): def __init__(self, cat0, catx, min_logmass, maxdist=None):
if cat0.simname != catx.simname: if cat0.simname != catx.simname:
raise ValueError("The two catalogues must be from the same " raise ValueError("The two catalogues must be from the same "
"simulation.") "simulation.")
self._cat0 = cat0 self._cat0 = cat0
self._catx = catx self._catx = catx
self._paths = paths self._paths = cat0.paths
self.load(cat0, catx, paths, min_logmass, maxdist) self.load(cat0, catx, min_logmass, maxdist)
def load(self, cat0, catx, paths, min_logmass, maxdist=None): def load(self, cat0, catx, paths, min_logmass, maxdist=None):
r""" r"""
@ -96,8 +94,6 @@ class PairOverlap:
Halo catalogue corresponding to the reference simulation. Halo catalogue corresponding to the reference simulation.
catx : instance of :py:class:`csiborgtools.read.BaseCatalogue` catx : instance of :py:class:`csiborgtools.read.BaseCatalogue`
Halo catalogue corresponding to the cross simulation. Halo catalogue corresponding to the cross simulation.
paths : py:class`csiborgtools.read.Paths`
CSiBORG paths object.
min_logmass : float min_logmass : float
Minimum halo mass in :math:`\log_{10} M_\odot / h` to consider. Minimum halo mass in :math:`\log_{10} M_\odot / h` to consider.
maxdist : float, optional maxdist : float, optional
@ -110,6 +106,7 @@ class PairOverlap:
""" """
nsim0 = cat0.nsim nsim0 = cat0.nsim
nsimx = catx.nsim nsimx = catx.nsim
paths = cat0.paths
# 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.
@ -473,7 +470,7 @@ class PairOverlap:
############################################################################### ###############################################################################
def max_overlap_agreement(cat0, catx, min_logmass, maxdist, paths): def max_overlap_agreement(cat0, catx, min_logmass, maxdist):
r""" r"""
Calculate whether for a halo `A` from catalogue `cat0` that has a maximum Calculate whether for a halo `A` from catalogue `cat0` that has a maximum
overlap with halo `B` from catalogue `catx` it is also `B` that has a overlap with halo `B` from catalogue `catx` it is also `B` that has a
@ -490,14 +487,12 @@ def max_overlap_agreement(cat0, catx, min_logmass, maxdist, paths):
maxdist : float, optional maxdist : float, optional
Maximum halo distance in :math:`\mathrm{Mpc} / h` from the centre Maximum halo distance in :math:`\mathrm{Mpc} / h` from the centre
of the high-resolution region. of the high-resolution region.
paths : py:class`csiborgtools.read.Paths`
CSiBORG paths object.
Returns Returns
------- -------
agreement : 1-dimensional array of shape `(nhalos, )` agreement : 1-dimensional array of shape `(nhalos, )`
""" """
kwargs = {"paths": paths, "min_logmass": min_logmass, "maxdist": maxdist} kwargs = {"min_logmass": min_logmass, "maxdist": maxdist}
pair_forward = PairOverlap(cat0, catx, **kwargs) pair_forward = PairOverlap(cat0, catx, **kwargs)
pair_backward = PairOverlap(catx, cat0, **kwargs) pair_backward = PairOverlap(catx, cat0, **kwargs)
@ -522,8 +517,7 @@ def max_overlap_agreement(cat0, catx, min_logmass, maxdist, paths):
return agreement return agreement
def max_overlap_agreements(cat0, catxs, min_logmass, maxdist, paths, def max_overlap_agreements(cat0, catxs, min_logmass, maxdist, verbose=True):
verbose=True):
""" """
Repeat `max_overlap_agreement` for many cross simulations. Repeat `max_overlap_agreement` for many cross simulations.
@ -538,8 +532,7 @@ def max_overlap_agreements(cat0, catxs, min_logmass, maxdist, paths,
agreements = [None] * len(catxs) agreements = [None] * len(catxs)
desc = "Calculating maximum overlap agreement" desc = "Calculating maximum overlap agreement"
for i, catx in enumerate(tqdm(catxs, desc=desc, disable=not verbose)): for i, catx in enumerate(tqdm(catxs, desc=desc, disable=not verbose)):
agreements[i] = max_overlap_agreement(cat0, catx, min_logmass, agreements[i] = max_overlap_agreement(cat0, catx, min_logmass, maxdist)
maxdist, paths)
return numpy.asanyarray(agreements) return numpy.asanyarray(agreements)
@ -596,8 +589,6 @@ class NPairsOverlap:
Single reference simulation halo catalogue. Single reference simulation halo catalogue.
catxs : list of :py:class:`csiborgtools.read.CSiBORGHaloCatalogue` catxs : list of :py:class:`csiborgtools.read.CSiBORGHaloCatalogue`
List of cross simulation halo catalogues. List of cross simulation halo catalogues.
paths : py:class`csiborgtools.read.Paths`
CSiBORG paths object.
min_logmass : float min_logmass : float
Minimum log mass of halos to consider. Minimum log mass of halos to consider.
verbose : bool, optional verbose : bool, optional
@ -605,11 +596,11 @@ class NPairsOverlap:
""" """
_pairs = None _pairs = None
def __init__(self, cat0, catxs, paths, min_logmass, verbose=True): def __init__(self, cat0, catxs, min_logmass, verbose=True):
pairs = [None] * len(catxs) pairs = [None] * len(catxs)
for i, catx in enumerate(tqdm(catxs, desc="Loading overlap objects", for i, catx in enumerate(tqdm(catxs, desc="Loading overlap objects",
disable=not verbose)): disable=not verbose)):
pairs[i] = PairOverlap(cat0, catx, paths, min_logmass) pairs[i] = PairOverlap(cat0, catx, min_logmass)
self._pairs = pairs self._pairs = pairs

View file

@ -22,7 +22,7 @@ from mpi4py import MPI
from taskmaster import work_delegation from taskmaster import work_delegation
import csiborgtools import csiborgtools
from match_singlematch import pair_match, pair_match_max from match_overlap_single import pair_match, pair_match_max
def get_combs(simname): def get_combs(simname):

View file

@ -43,39 +43,30 @@ def pair_match_max(nsim0, nsimx, simname, min_logmass, mult, verbose):
verbose : bool verbose : bool
Verbosity flag. Verbosity flag.
""" """
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring) if simname == "csiborg1":
if simname == "csiborg":
mass_kind = "fof_totpartmass"
maxdist = 155 maxdist = 155
periodic = False periodic = False
bounds = {"dist": (0, maxdist), mass_kind: (10**min_logmass, None)} bounds = {"dist": (0, maxdist), "totmass": (10**min_logmass, None)}
cat0 = csiborgtools.read.CSiBORGHaloCatalogue( cat0 = csiborgtools.read.CSiBORG1Catalogue(nsim0, bounds=bounds)
nsim0, paths, bounds=bounds, load_fitted=True, load_initial=False) catx = csiborgtools.read.CSiBORG1Catalogue(nsimx, bounds=bounds)
catx = csiborgtools.read.CSiBORGHaloCatalogue( elif "csiborg2" in simname:
nsimx, paths, bounds=bounds, load_fitted=True, load_initial=False) raise RuntimeError("CSiBORG2 currently not implemented..")
elif simname == "quijote": elif simname == "quijote":
mass_kind = "group_mass"
maxdist = None maxdist = None
periodic = True periodic = True
bounds = {mass_kind: (10**min_logmass, None)} bounds = {"totmass": (10**min_logmass, None)}
cat0 = csiborgtools.read.QuijoteHaloCatalogue( cat0 = csiborgtools.read.QuijoteCatalogue(nsim0, bounds=bounds)
nsim0, paths, 4, bounds=bounds, load_fitted=True, catx = csiborgtools.read.QuijoteHaloCatalogue(nsimx, bounds=bounds)
load_initial=False)
catx = csiborgtools.read.QuijoteHaloCatalogue(
nsimx, paths, 4, bounds=bounds, load_fitted=True,
load_initial=False)
else: else:
raise ValueError(f"Unknown simulation `{simname}`.") raise ValueError(f"Unknown simulation `{simname}`.")
reader = csiborgtools.summary.PairOverlap(cat0, catx, paths, min_logmass, reader = csiborgtools.summary.PairOverlap(cat0, catx, min_logmass, maxdist)
maxdist=maxdist)
out = csiborgtools.match.matching_max( out = csiborgtools.match.matching_max(
cat0, catx, mass_kind, mult=mult, periodic=periodic, cat0, catx, "totmass", mult=mult, periodic=periodic,
overlap=reader.overlap(from_smoothed=True), overlap=reader.overlap(from_smoothed=True),
match_indxs=reader["match_indxs"], verbose=verbose) match_indxs=reader["match_indxs"], verbose=verbose)
fout = paths.match_max(simname, nsim0, nsimx, min_logmass, mult) fout = cat0.paths.match_max(simname, nsim0, nsimx, min_logmass, mult)
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, **{p: out[p] for p in out.dtype.names}) numpy.savez(fout, **{p: out[p] for p in out.dtype.names})
@ -108,23 +99,30 @@ def pair_match(nsim0, nsimx, simname, min_logmass, sigma, verbose):
smooth_kwargs = {"sigma": sigma, "mode": "constant", "cval": 0} smooth_kwargs = {"sigma": sigma, "mode": "constant", "cval": 0}
bounds = {"lagpatch_size": (0, None)} bounds = {"lagpatch_size": (0, None)}
if simname == "csiborg": if simname == "csiborg1":
overlapper_kwargs = {"box_size": 2048, "bckg_halfsize": 512} overlapper_kwargs = {"box_size": 2048, "bckg_halfsize": 512}
mass_kind = "fof_totpartmass" bounds |= {"dist": (0, 150), "totmass": (10**min_logmass, None)}
bounds |= {"dist": (0, 155), mass_kind: (10**min_logmass, None)}
cat0 = csiborgtools.read.CSiBORGCatalogue( snap0 = csiborgtools.read.CSIBORG1Snapshot(nsim0, 0)
nsim0, paths, "halo_catalogue", "FOF", mass_kind, bounds) cat0 = csiborgtools.read.CSiBORG1Catalogue(nsim0, snapshot=snap0,
catx = csiborgtools.read.CSiBORGCatalogue( bounds=bounds)
nsimx, paths, "halo_catalogue", "FOF", mass_kind, bounds)
snapx = csiborgtools.read.CSIBORG1Snapshot(nsimx, 0)
catx = csiborgtools.read.CSiBORGCatalogue(nsimx, snapshot=snapx,
bounds=bounds)
elif "csiborg2" in simname:
raise RuntimeError("CSiBORG2 currently not implemented..")
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" bounds |= {"totmass": (10**min_logmass, None)}
bounds |= {mass_kind: (10**min_logmass, None)}
cat0 = csiborgtools.read.QuijoteCatalogue( snap0 = csiborgtools.read.QuijoteSnapshot(nsim0, "ICs")
nsim0, paths, "halo_catalogue", "FOF", mass_kind, bounds=bounds) cat0 = csiborgtools.read.QuijoteCatalogue(nsim0, snapshot=snap0,
catx = csiborgtools.read.QuijoteCatalogue( bounds=bounds)
nsimx, paths, "halo_catalogue", "FOF", mass_kind, bounds=bounds)
snapx = csiborgtools.read.QuijoteSnapshot(nsimx, "ICs")
catx = csiborgtools.read.QuijoteCatalogue(nsimx, snapshot=snapx,
bounds=bounds)
else: else:
raise ValueError(f"Unknown simulation name: `{simname}`.") raise ValueError(f"Unknown simulation name: `{simname}`.")
@ -133,8 +131,7 @@ def pair_match(nsim0, nsimx, simname, min_logmass, sigma, verbose):
delta_bckg = overlapper.make_bckg_delta(catx, delta=delta_bckg, delta_bckg = overlapper.make_bckg_delta(catx, delta=delta_bckg,
verbose=verbose) verbose=verbose)
matcher = csiborgtools.match.RealisationsMatcher(mass_kind=mass_kind, matcher = csiborgtools.match.RealisationsMatcher(**overlapper_kwargs)
**overlapper_kwargs)
match_indxs, ngp_overlap = matcher.cross(cat0, catx, delta_bckg, match_indxs, ngp_overlap = matcher.cross(cat0, catx, delta_bckg,
verbose=verbose) verbose=verbose)