mirror of
https://github.com/Richard-Sti/csiborgtools_public.git
synced 2025-06-08 09:51:12 +00:00
Particle init CM separation (#17)
* Rename * rename module * add new_ic_ids * Add to_new support * rm unnecessary comment * Remove JUlia! * add new package attempt * add dump script * simplify positions getter * Remove unused code * change dumpdirs * update project * Add sorting * fix indexing bug * add comment * Add particle dumping * Delete blank line * Delete Julia things * Update README * add working script * fix assignment bug * fix bug * save temp to temp folder * fix indexing bug & path * do not always crreate folder * Rename file * add initcm reader * add x0, y0, z0 transforms * add initcm to halo cat * docs update * add initial KNN * add attempt at init match * add initial fiducial radius * rm blank space * Add further KNN Init pos support * Add init radius support * Remove message about the bug * Get rid of an error msg * purge mention of knn_init * Add init CM distance calc
This commit is contained in:
parent
c3c686fa60
commit
13a9d11afe
12 changed files with 409 additions and 525 deletions
|
@ -14,7 +14,7 @@
|
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
import numpy
|
||||
from tqdm import tqdm
|
||||
from tqdm import (tqdm, trange)
|
||||
from astropy.coordinates import SkyCoord
|
||||
from ..read import CombinedHaloCatalogue
|
||||
|
||||
|
@ -125,7 +125,7 @@ class RealisationsMatcher:
|
|||
def cosine_similarity(self, x, y):
|
||||
r"""
|
||||
Calculate the cosine similarity between two Cartesian vectors. Defined
|
||||
as :math:`\Sum_{i} x_i y_{i} / (|x| |y|)`.
|
||||
as :math:`\Sum_{i} x_i y_{i} / (|x| * |y|)`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
@ -152,8 +152,8 @@ class RealisationsMatcher:
|
|||
return out[0]
|
||||
return out
|
||||
|
||||
def cross_knn_position_single(self, n_sim, nmult=5, dlogmass=2,
|
||||
verbose=True):
|
||||
def cross_knn_position_single(self, n_sim, nmult=5, dlogmass=None,
|
||||
init_dist=False, verbose=True):
|
||||
r"""
|
||||
Find all neighbours within :math:`n_{\rm mult} R_{200c}` of halos in
|
||||
the `nsim`th simulation. Also enforces that the neighbours'
|
||||
|
@ -168,21 +168,28 @@ class RealisationsMatcher:
|
|||
Multiple of :math:`R_{200c}` within which to return neighbours. By
|
||||
default 5.
|
||||
dlogmass : float, optional
|
||||
Tolerance on mass logarithmic mass difference. By default 2 dex.
|
||||
Tolerance on mass logarithmic mass difference. By default `None`.
|
||||
init_dist : bool, optional
|
||||
Whether to calculate separation of the initial CMs. By default
|
||||
`False`.
|
||||
verbose : bool, optional
|
||||
Iterator verbosity flag. By default `True`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
matches : composite array
|
||||
Array, indices are `(n_sims - 1, 2, n_halos, n_matches)`. The
|
||||
2nd axis is `index` of the neighbouring halo in its catalogue and
|
||||
Array, indices are `(n_sims - 1, 3, n_halos, n_matches)`. The
|
||||
2nd axis is `index` of the neighbouring halo in its catalogue,
|
||||
`dist`, which is the 3D distance to the halo whose neighbours are
|
||||
searched.
|
||||
searched, and `dist0` which is the separation of the initial CMs.
|
||||
The latter is calculated only if `init_dist` is `True`.
|
||||
"""
|
||||
# R200c, M200c and positions of halos in `n_sim` IC realisation
|
||||
r200 = self.cats[n_sim]["r200"]
|
||||
# Radius, M200c and positions of halos in `n_sim` IC realisation
|
||||
logm200 = numpy.log10(self.cats[n_sim]["m200"])
|
||||
R = self.cats[n_sim]["r200"]
|
||||
pos = self.cats[n_sim].positions
|
||||
|
||||
if init_dist:
|
||||
pos0 = self.cats[n_sim].positions0 # These are CM positions
|
||||
matches = [None] * (self.cats.N - 1)
|
||||
# Verbose iterator
|
||||
if verbose:
|
||||
|
@ -191,19 +198,30 @@ class RealisationsMatcher:
|
|||
iters = enumerate(self.search_sim_indices(n_sim))
|
||||
# Search for neighbours in the other simulations
|
||||
for count, i in iters:
|
||||
dist, indxs = self.cats[i].radius_neigbours(pos, r200 * nmult)
|
||||
dist, indxs = self.cats[i].radius_neigbours(pos, R * nmult)
|
||||
# Get rid of neighbors whose mass is too off
|
||||
for j, indx in enumerate(indxs):
|
||||
match_logm200 = numpy.log10(self.cats[i][indx]["m200"])
|
||||
mask = numpy.abs(match_logm200 - logm200[j]) < dlogmass
|
||||
dist[j] = dist[j][mask]
|
||||
indxs[j] = indx[mask]
|
||||
if dlogmass is not None:
|
||||
for j, indx in enumerate(indxs):
|
||||
match_logm200 = numpy.log10(self.cats[i]["m200"][indx])
|
||||
mask = numpy.abs(match_logm200 - logm200[j]) < dlogmass
|
||||
dist[j] = dist[j][mask]
|
||||
indxs[j] = indx[mask]
|
||||
# Find distance to the between the initial CM
|
||||
dist0 = [numpy.asanyarray([], dtype=numpy.float64)] * dist.size
|
||||
if init_dist:
|
||||
with_neigbours = numpy.where([ii.size > 0 for ii in indxs])[0]
|
||||
# Fill the pre-allocated array on positions with neighbours
|
||||
for k in with_neigbours:
|
||||
dist0[k] = numpy.linalg.norm(
|
||||
pos0[k] - self.cats[i].positions0[indxs[k]], axis=1)
|
||||
|
||||
# Append as a composite array
|
||||
matches[count] = numpy.asarray([indxs, dist], dtype=object)
|
||||
matches[count] = numpy.asarray([indxs, dist, dist0], dtype=object)
|
||||
|
||||
return numpy.asarray(matches, dtype=object)
|
||||
|
||||
def cross_knn_position_all(self, nmult=5, dlogmass=2):
|
||||
def cross_knn_position_all(self, nmult=5, dlogmass=None,
|
||||
init_dist=False, verbose=True):
|
||||
r"""
|
||||
Find all neighbours within :math:`n_{\rm mult} R_{200c}` of halos in
|
||||
all simulations listed in `self.cats`. Also enforces that the
|
||||
|
@ -215,7 +233,12 @@ class RealisationsMatcher:
|
|||
Multiple of :math:`R_{200c}` within which to return neighbours. By
|
||||
default 5.
|
||||
dlogmass : float, optional
|
||||
Tolerance on mass logarithmic mass difference. By default 2 dex.
|
||||
Tolerance on mass logarithmic mass difference. By default `None`.
|
||||
init_dist : bool, optional
|
||||
Whether to calculate separation of the initial CMs. By default
|
||||
`False`.
|
||||
verbose : bool, optional
|
||||
Iterator verbosity flag. By default `True`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
@ -226,6 +249,7 @@ class RealisationsMatcher:
|
|||
N = self.cats.N # Number of catalogues
|
||||
matches = [None] * N
|
||||
# Loop over each catalogue
|
||||
for i in range(N):
|
||||
matches[i] = self.cross_knn_position_single(i, nmult, dlogmass)
|
||||
for i in trange(N) if verbose else range(N):
|
||||
matches[i] = self.cross_knn_position_single(
|
||||
i, nmult, dlogmass, init_dist)
|
||||
return matches
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
from .readsim import (CSiBORGPaths, ParticleReader, read_mmain, get_positions) # noqa
|
||||
from .readsim import (CSiBORGPaths, ParticleReader, read_mmain, read_initcm, get_positions) # noqa
|
||||
from .make_cat import (HaloCatalogue, CombinedHaloCatalogue) # noqa
|
||||
from .readobs import (PlanckClusters, MCXCClusters, TwoMPPGalaxies, # noqa
|
||||
TwoMPPGroups, SDSS) # noqa
|
||||
|
|
|
@ -15,13 +15,12 @@
|
|||
"""
|
||||
Functions to read in the particle and clump files.
|
||||
"""
|
||||
|
||||
import numpy
|
||||
from os.path import join
|
||||
from tqdm import trange
|
||||
from copy import deepcopy
|
||||
from sklearn.neighbors import NearestNeighbors
|
||||
from .readsim import read_mmain
|
||||
from .readsim import (read_mmain, read_initcm)
|
||||
from ..utils import (flip_cols, add_columns)
|
||||
from ..units import (BoxUnits, cartesian_to_radec)
|
||||
|
||||
|
@ -45,6 +44,7 @@ class HaloCatalogue:
|
|||
_data = None
|
||||
_knn = None
|
||||
_positions = None
|
||||
_positions0 = None
|
||||
|
||||
def __init__(self, paths, min_m500=None, max_dist=None):
|
||||
self._box = BoxUnits(paths)
|
||||
|
@ -117,7 +117,7 @@ class HaloCatalogue:
|
|||
@property
|
||||
def n_sim(self):
|
||||
"""
|
||||
The initiali condition (IC) realisation ID.
|
||||
The initial condition (IC) realisation ID.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
@ -142,6 +142,12 @@ class HaloCatalogue:
|
|||
# Cut on number of particles and finite m200
|
||||
data = data[(data["npart"] > 100) & numpy.isfinite(data["m200"])]
|
||||
|
||||
# Now also load the initial positions
|
||||
initcm = read_initcm(self.n_sim, self.paths.initmatch_path)
|
||||
if initcm is not None:
|
||||
data = self.merge_initmatch_to_clumps(data, initcm)
|
||||
flip_cols(data, "x0", "z0")
|
||||
|
||||
# Calculate redshift
|
||||
pos = [data["peak_{}".format(p)] - 0.5 for p in ("x", "y", "z")]
|
||||
vel = [data["v{}".format(p)] for p in ("x", "y", "z")]
|
||||
|
@ -171,9 +177,14 @@ class HaloCatalogue:
|
|||
# Cut on separation
|
||||
data = data[data["dist"] < max_dist]
|
||||
|
||||
# Pre-allocate the positions array
|
||||
# Pre-allocate the positions arrays
|
||||
self._positions = numpy.vstack(
|
||||
[data["peak_{}".format(p)] for p in ("x", "y", "z")]).T
|
||||
# And do the unit transform
|
||||
if initcm is not None:
|
||||
data = self.box.convert_from_boxunits(data, ["x0", "y0", "z0"])
|
||||
self._positions0 = numpy.vstack(
|
||||
[data["{}0".format(p)] for p in ("x", "y", "z")]).T
|
||||
|
||||
self._data = data
|
||||
|
||||
|
@ -203,10 +214,39 @@ class HaloCatalogue:
|
|||
X[mask, 1] = mmain["sub_frac"]
|
||||
return add_columns(clumps, X, ["mass_mmain", "sub_frac"])
|
||||
|
||||
def merge_initmatch_to_clumps(self, clumps, initcat):
|
||||
"""
|
||||
Merge columns from the `init_cm` files to the `clump` file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
clumps : structured array
|
||||
Clumps structured array.
|
||||
initcat : structured array
|
||||
Catalog with the clumps initial centre of mass at z = 70.
|
||||
|
||||
Returns
|
||||
-------
|
||||
out : structured array
|
||||
"""
|
||||
# There are more initcat clumps, so check which ones have z = 0
|
||||
# and then downsample
|
||||
mask = numpy.isin(initcat["ID"], clumps["index"])
|
||||
initcat = initcat[mask]
|
||||
# Now the index ordering should match
|
||||
if not numpy.alltrue(initcat["ID"] == clumps["index"]):
|
||||
raise ValueError(
|
||||
"Ordering of `initcat` and `clumps` is inconsistent.")
|
||||
|
||||
X = numpy.full((clumps.size, 3), numpy.nan)
|
||||
for i, p in enumerate(['x', 'y', 'z']):
|
||||
X[:, i] = initcat[p]
|
||||
return add_columns(clumps, X, ["x0", "y0", "z0"])
|
||||
|
||||
@property
|
||||
def positions(self):
|
||||
"""
|
||||
3D positions of halos.
|
||||
3D positions of halos in comoving units of Mpc.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
@ -216,6 +256,21 @@ class HaloCatalogue:
|
|||
"""
|
||||
return self._positions
|
||||
|
||||
@property
|
||||
def positions0(self):
|
||||
r"""
|
||||
3D positions of halos in the initial snapshot in comoving units of Mpc.
|
||||
|
||||
Returns
|
||||
-------
|
||||
X : 2-dimensional array
|
||||
Array of shape `(n_halos, 3)`, where the latter axis represents
|
||||
`x`, `y` and `z`.
|
||||
"""
|
||||
if self._positions0 is None:
|
||||
raise RuntimeError("Initial positions are not set!")
|
||||
return self._positions0
|
||||
|
||||
@property
|
||||
def velocities(self):
|
||||
"""
|
||||
|
@ -240,6 +295,26 @@ class HaloCatalogue:
|
|||
"""
|
||||
return numpy.vstack([self["L{}".format(p)] for p in ("x", "y", "z")]).T
|
||||
|
||||
@property
|
||||
def init_radius(self):
|
||||
r"""
|
||||
A fiducial initial radius of particles that are identified as a single
|
||||
halo in the final snapshot. Estimated to be
|
||||
|
||||
..math:
|
||||
R = (3 N / 4 \pi)^{1 / 3} * \Delta
|
||||
|
||||
where :math:`N` is the number of particles and `Delta` is the initial
|
||||
inter-particular distance :math:`Delta = 1 / 2^{11}` in box units. The
|
||||
output fiducial radius is in comoving units of Mpc.
|
||||
|
||||
Returns
|
||||
-------
|
||||
R : float
|
||||
"""
|
||||
delta = self.box.box2mpc(1 / 2**11)
|
||||
return (3 * self["npart"] / (4 * numpy.pi))**(1/3) * delta
|
||||
|
||||
def radius_neigbours(self, X, radius):
|
||||
"""
|
||||
Return sorted nearest neigbours within `radius` or `X`.
|
||||
|
@ -272,6 +347,9 @@ class HaloCatalogue:
|
|||
return self.data.dtype.names
|
||||
|
||||
def __getitem__(self, key):
|
||||
initpars = ["x0", "y0", "z0"]
|
||||
if key in initpars and key not in self.keys:
|
||||
raise RuntimeError("Initial positions are not set!")
|
||||
return self._data[key]
|
||||
|
||||
|
||||
|
@ -299,8 +377,9 @@ class CombinedHaloCatalogue:
|
|||
|
||||
def __init__(self, paths, min_m500=None, max_dist=None, verbose=True):
|
||||
# Read simulations and their maximum snapshots
|
||||
# NOTE remove this later and take all cats
|
||||
self._n_sims = paths.ic_ids[:10]
|
||||
# NOTE later change this back to all simulations
|
||||
self._n_sims = [7468, 7588, 8020, 8452, 8836]
|
||||
# self._n_sims = paths.ic_ids
|
||||
n_snaps = [paths.get_maximum_snapshot(i) for i in self._n_sims]
|
||||
self._n_snaps = numpy.asanyarray(n_snaps)
|
||||
|
||||
|
|
|
@ -18,10 +18,11 @@ Functions to read in the particle and clump files.
|
|||
|
||||
import numpy
|
||||
from scipy.io import FortranFile
|
||||
from os import listdir
|
||||
import gc
|
||||
from os.path import (join, isfile, isdir)
|
||||
from glob import glob
|
||||
from tqdm import tqdm
|
||||
from warnings import warn
|
||||
from ..utils import (cols_to_structured, extract_from_structured)
|
||||
|
||||
|
||||
|
@ -56,22 +57,40 @@ class CSiBORGPaths:
|
|||
mmain_path : str, optional
|
||||
Path to where mmain files are stored. By default
|
||||
`/mnt/zfsusers/hdesmond/Mmain`.
|
||||
initmatch_path : str, optional
|
||||
Path to where match between the first and final snapshot is stored. By
|
||||
default `/mnt/extraspace/rstiskalek/csiborg/initmatch/`.
|
||||
to_new : bool, optional
|
||||
Whether the paths should point to `new` files, for example
|
||||
`ramses_out_8452_new`.
|
||||
"""
|
||||
_srcdir = None
|
||||
_n_sim = None
|
||||
_n_snap = None
|
||||
_dumpdir = None
|
||||
_mmain_path = None
|
||||
_initmatch_path = None
|
||||
_to_new = None
|
||||
|
||||
def __init__(self, n_sim=None, n_snap=None,
|
||||
srcdir="/mnt/extraspace/hdesmond/",
|
||||
dumpdir="/mnt/extraspace/rstiskalek/csiborg/",
|
||||
mmain_path="/mnt/zfsusers/hdesmond/Mmain"):
|
||||
# NOTE deuglify this stuff
|
||||
def __init__(self, n_sim=None, n_snap=None, srcdir=None, dumpdir=None,
|
||||
mmain_path=None, initmatch_path=None, to_new=False):
|
||||
if srcdir is None:
|
||||
srcdir = "/mnt/extraspace/hdesmond/"
|
||||
self.srcdir = srcdir
|
||||
if dumpdir is None:
|
||||
dumpdir = "/mnt/extraspace/rstiskalek/csiborg/"
|
||||
self.dumpdir = dumpdir
|
||||
if mmain_path is None:
|
||||
mmain_path = "/mnt/zfsusers/hdesmond/Mmain"
|
||||
self.mmain_path = mmain_path
|
||||
if initmatch_path is None:
|
||||
initmatch_path = "/mnt/extraspace/rstiskalek/csiborg/initmatch/"
|
||||
self.initmatch_path = initmatch_path
|
||||
self.to_new = to_new
|
||||
if n_sim is not None and n_snap is not None:
|
||||
self.set_info(n_sim, n_snap)
|
||||
# "/mnt/extraspace/rstiskalek/csiborg/initmatch/clump_cm_7468.npy"
|
||||
|
||||
@property
|
||||
def srcdir(self):
|
||||
|
@ -147,6 +166,45 @@ class CSiBORGPaths:
|
|||
raise IOError("Invalid directory `{}`!".format(mmain_path))
|
||||
self._mmain_path = mmain_path
|
||||
|
||||
@property
|
||||
def initmatch_path(self):
|
||||
"""
|
||||
Path to where match between the first and final snapshot is stored.
|
||||
|
||||
Returns
|
||||
-------
|
||||
initmach_path : str
|
||||
"""
|
||||
return self._initmatch_path
|
||||
|
||||
@initmatch_path.setter
|
||||
def initmatch_path(self, initmatch_path):
|
||||
"""
|
||||
Set `initmatch_path`, check that the directory exists.
|
||||
"""
|
||||
if not isdir(initmatch_path):
|
||||
raise IOError("Invalid directory `{}`!".format(initmatch_path))
|
||||
self._initmatch_path = initmatch_path
|
||||
|
||||
@property
|
||||
def to_new(self):
|
||||
"""
|
||||
Flag whether paths should point to `new` files, for example
|
||||
`ramses_out_8452_new`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
to_new : bool
|
||||
"""
|
||||
return self._to_new
|
||||
|
||||
@to_new.setter
|
||||
def to_new(self, to_new):
|
||||
"""Set `to_new`."""
|
||||
if not isinstance(to_new, bool):
|
||||
raise TypeError("`to_new` must be be a bool")
|
||||
self._to_new = to_new
|
||||
|
||||
@property
|
||||
def n_sim(self):
|
||||
"""
|
||||
|
@ -236,14 +294,26 @@ class CSiBORGPaths:
|
|||
def ic_ids(self):
|
||||
"""
|
||||
CSiBORG initial condition (IC) simulation IDs from the list of folders
|
||||
in `self.srcdir`. Assumes that the folders look like `ramses_out_X`
|
||||
and extracts the `X` integer. Removes `5511` from the list of IDs.
|
||||
in `self.srcdir`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ids : 1-dimensional array
|
||||
Array of CSiBORG simulation IDs.
|
||||
"""
|
||||
if self.to_new:
|
||||
return self._ic_ids_new
|
||||
return self._ic_ids
|
||||
|
||||
@property
|
||||
def _ic_ids(self):
|
||||
"""
|
||||
IC simulation IDs.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ids : 1-dimensional array
|
||||
"""
|
||||
files = glob(join(self.srcdir, "ramses_out*"))
|
||||
# Select only file names
|
||||
files = [f.split("/")[-1] for f in files]
|
||||
|
@ -260,6 +330,25 @@ class CSiBORGPaths:
|
|||
pass
|
||||
return numpy.sort(ids)
|
||||
|
||||
@property
|
||||
def _ic_ids_new(self):
|
||||
"""
|
||||
ICs simulation IDs denoted as `new` with recoved :math:`z = 70`
|
||||
particle information.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ids : 1-dimensional array
|
||||
"""
|
||||
files = glob(join(self.srcdir, "ramses_out*"))
|
||||
# Select only file names
|
||||
files = [f.split("/")[-1] for f in files]
|
||||
# Only _new files
|
||||
files = [f for f in files if "_new" in f]
|
||||
# Take the ICs
|
||||
ids = [int(f.split("_")[2]) for f in files]
|
||||
return numpy.sort(ids)
|
||||
|
||||
def ic_path(self, n_sim=None):
|
||||
"""
|
||||
Path to `n_sim`th CSiBORG IC realisation.
|
||||
|
@ -276,6 +365,8 @@ class CSiBORGPaths:
|
|||
"""
|
||||
n_sim = self.get_n_sim(n_sim)
|
||||
fname = "ramses_out_{}"
|
||||
if self.to_new:
|
||||
fname += "_new"
|
||||
return join(self.srcdir, fname.format(n_sim))
|
||||
|
||||
def get_snapshots(self, n_sim=None):
|
||||
|
@ -291,7 +382,6 @@ class CSiBORGPaths:
|
|||
Returns
|
||||
-------
|
||||
snapshots : 1-dimensional array
|
||||
Array of snapshot IDs.
|
||||
"""
|
||||
n_sim = self.get_n_sim(n_sim)
|
||||
simpath = self.ic_path(n_sim)
|
||||
|
@ -314,7 +404,6 @@ class CSiBORGPaths:
|
|||
Returns
|
||||
-------
|
||||
maxsnap : float
|
||||
Maximum snapshot.
|
||||
"""
|
||||
n_sim = self.get_n_sim(n_sim)
|
||||
return max(self.get_snapshots(n_sim))
|
||||
|
@ -332,7 +421,6 @@ class CSiBORGPaths:
|
|||
Returns
|
||||
-------
|
||||
minsnap : float
|
||||
Minimum snapshot.
|
||||
"""
|
||||
n_sim = self.get_n_sim(n_sim)
|
||||
return min(self.get_snapshots(n_sim))
|
||||
|
@ -353,7 +441,6 @@ class CSiBORGPaths:
|
|||
Returns
|
||||
-------
|
||||
snappath : str
|
||||
Path to the CSiBORG IC realisation snapshot.
|
||||
"""
|
||||
n_snap = self.get_n_snap(n_snap)
|
||||
n_sim = self.get_n_sim(n_sim)
|
||||
|
@ -455,15 +542,6 @@ class ParticleReader:
|
|||
print("Reading in output `{}` with ncpu = `{}`."
|
||||
.format(nout, ncpu))
|
||||
|
||||
# Check whether the unbinding file exists.
|
||||
snapdirlist = listdir(snappath)
|
||||
unbinding_file = "unbinding_{}.out00001".format(nout)
|
||||
if unbinding_file not in snapdirlist:
|
||||
raise FileNotFoundError(
|
||||
"Couldn't find `{}` in `{}`. Use mergertreeplot.py -h or "
|
||||
"--help to print help message."
|
||||
.format(unbinding_file, snappath))
|
||||
|
||||
# First read the headers. Reallocate arrays and fill them.
|
||||
nparts = numpy.zeros(ncpu, dtype=int)
|
||||
partfiles = [None] * ncpu
|
||||
|
@ -761,25 +839,46 @@ def read_mmain(n, srcdir, fname="Mmain_{}.npy"):
|
|||
return out
|
||||
|
||||
|
||||
def get_positions(n_sim, n_snap, get_clumpid, verbose=True,
|
||||
srcdir="/mnt/extraspace/hdesmond/"):
|
||||
def read_initcm(n, srcdir, fname="clump_cm_{}.npy"):
|
||||
"""
|
||||
Read `clump_cm`, i.e. the center of mass of a clump at redshift z = 70.
|
||||
If the file does not exist returns `None`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n : int
|
||||
The index of the initial conditions (IC) realisation.
|
||||
srcdir : str
|
||||
The path to the folder containing the files.
|
||||
fname : str, optional
|
||||
The file name convention. By default `clump_cm_{}.npy`, where the
|
||||
substituted value is `n`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
out : structured array
|
||||
"""
|
||||
fpath = join(srcdir, fname.format(n))
|
||||
try:
|
||||
return numpy.load(fpath)
|
||||
except FileNotFoundError:
|
||||
warn("File {} does not exist.".format(fpath))
|
||||
return None
|
||||
|
||||
|
||||
def get_positions(paths, get_clumpid, verbose=True):
|
||||
"""
|
||||
Shortcut to get particle IDs, positions, masses and optionally clump
|
||||
indices.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_sim : int
|
||||
CSiBORG IC realisation index.
|
||||
n_snap : int
|
||||
Snapshot index.
|
||||
paths : py:class`csiborgtools.read.CSiBORGPaths`
|
||||
CSiBORG paths-handling object with set `n_sim` and `n_snap`.
|
||||
get_clumpid : bool
|
||||
Whether to also return the clump indices.
|
||||
verbose : bool, optional
|
||||
Verbosity flag. By default `True`.
|
||||
srcdir : str, optional
|
||||
The file path to the folder where realisations of the ICs are stored.
|
||||
By default `/mnt/extraspace/hdesmond/`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
@ -793,9 +892,6 @@ def get_positions(n_sim, n_snap, get_clumpid, verbose=True,
|
|||
Particles' clump IDs of shape `(n_particles, )`. Returned only if
|
||||
`get_clumpid` is `True`.
|
||||
"""
|
||||
# Setup the paths
|
||||
paths = CSiBORGPaths(srcdir)
|
||||
paths.set_info(n_sim, n_snap)
|
||||
# Extract particles
|
||||
reader = ParticleReader(paths)
|
||||
pars_extract = ["ID", "x", "y", "z", "M"]
|
||||
|
@ -805,8 +901,10 @@ def get_positions(n_sim, n_snap, get_clumpid, verbose=True,
|
|||
pids = extract_from_structured(particles, "ID")
|
||||
ppos = extract_from_structured(particles, ["x", "y", "z"])
|
||||
pmass = extract_from_structured(particles, "M")
|
||||
|
||||
# Force early memory release
|
||||
del particles
|
||||
gc.collect()
|
||||
|
||||
out = (pids, ppos, pmass)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ from ..read import ParticleReader
|
|||
# Map of unit conversions
|
||||
CONV_NAME = {
|
||||
"length": ["peak_x", "peak_y", "peak_z", "Rs", "rmin", "rmax", "r200",
|
||||
"r500"],
|
||||
"r500", "x0", "y0", "z0"],
|
||||
"mass": ["mass_cl", "totpartmass", "m200", "m500", "mass_mmain"],
|
||||
"density": ["rho0"]
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ class BoxUnits:
|
|||
"Conversion of `{}` is not defined.".format(name))
|
||||
|
||||
# Center at the observer
|
||||
if name in ["peak_x", "peak_y", "peak_z"]:
|
||||
if name in ["peak_x", "peak_y", "peak_z", "x0", "y0", "z0"]:
|
||||
data[name] -= transforms["length"](0.5)
|
||||
|
||||
return data
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue