Local and Global Shape Estimation
Shape Profiles
Shape profiles depict the ellipsoidal shape of a point cloud as a function of the ellipsoidal radius
where \((x_{\text{ell}},y_{\text{ell}},z_{\text{ell}})\) are the coordinates of a point cloud particle in the eigenvector coordinate system of the ellipsoid (= principal frame), i.e., \(r_{\text{ell}}\) corresponds to the semi-major axis \(a\) of the ellipsoidal surface on which that particle lies.
The shape as a function of ellipsoidal radius can be described by the axis ratios
where \(b\) and \(c\) are the eigenvalues corresponding to the intermediate and minor axes, respectively. The ratio of the minor-to-major axis \(s\) has traditionally been used as a canonical measure of the distribution’s sphericity. A frequently quoted shape parameter is the triaxiality
which measures the prolateness/oblateness of a halo. \(T = 1\) describes a completely prolate halo, while \(T = 0\) describes a completely oblate halo. Halos with \(0.33 < T < 0.67\) are said to be triaxial. The axis ratios can be computed from the shape tensor \(S_{ij}\), which is the second moment of the mass distribution divided by the total mass:
Here, \(m_k\) is the mass of the \(k\)-th particle, and \(r_{k} = (x_{k},y_{k},z_{k})^t\) is the position vector with respect to the distribution’s center (either mode or center of mass). The weight \(w_k\) allows to define the most common shape tensors by choosing
\(w_k = 1\), in which case each particle gets the same weight, or
\(w_k = \frac{1}{r_k^2}\) where \(r_k^2 = (x_{k})^2+(y_{k})^2+(z_{k})^2\) is the distance squared of particle \(k\) from the center of the cloud, or
\(w_k = \frac{1}{r_{\text{ell},k}^2}\) where \(r_{\text{ell},k}^2 = x_{\text{ell},k}^2+y_{\text{ell},k}^2+z_{\text{ell},k}^2\) is the ellipsoidal radius, where \((x_{\text{ell},k}, y_{\text{ell},k}, z_{\text{ell},k})\) are the coordinates of particle \(k\) in the eigenvector coordinate system of the ellipsoid. The shape tensor with \(w_k = \frac{1}{r_{\text{ell},k}^2}\) is also called the reduced shape tensor, a variant that penalizes particles at large radii.
Since the second weighting scheme with \(w_k = \frac{1}{r_k^2}\) has fallen out of favour, see Zemp et al. 2011, the other two schemes will be available by switching the boolean REDUCED
, see below.
After instantiating an object cprofiles
as outlined in Data Structures section, one can calculate and retrieve the local (i.e. as a function of \(r_{\text{ell}}\)) halo shape catalogue by:
shapes = cprofiles.getShapeCatLocal(obj_numbers, katz_config = default_katz_config).
The morphological information in the structured numpy array shapes
can be retrieved by dictionary-like semantics. d = shapes['d']
, q = shapes['q']
, s = shapes['s']
, minor = shapes['minor']
, inter = shapes['inter']
and major = shapes['major']
represents the shape profiles. The obj_numbers
argument expects a list of integers indicating for which objects to estimate the density profile.
If e.g. obj_numbers = np.arange(10)
, only the first 10 objects that have sufficient resolution will be considered. Typically, the ordering of objects internally is such that this will select the 10 most massive objects.
CosmicProfiles uses the iterative Katz 1991 algorithm to calculate the shape profiles. The default configuration
parameters are:
default_katz_config = {'ROverR200': np.logspace(-1.5,0,70), 'IT_TOL': 1e-2, 'IT_WALL': 100, 'IT_MIN': 10, 'REDUCED': False, 'SHELL_BASED': False},
where ROverR200
contains the normalized ellipsoidal radii of interest, in units of R200 or Rvir (depending on RVIR_OR_R200
) of parent halo, at which the shape profiles should be calculated.
The float IT_TOL
is the convergence tolerance in the shape estimation algorithm: eigenvalue fractions must differ by less than IT_TOL
for the algorithm to halt.
The integer IT_WALL
is the maximum permissible number of iterations in shape estimation algorithm. The integer IT_MIN
is the minimum number of particles (DM, gas or star particles depending on OBJ_TYPE
) in any iteration. If undercut, the shape remains unclassified (NaNs).
The boolean REDUCED
allows to select between the reduced shape tensor with weight \(w_k = \frac{1}{r_{\text{ell},k}^2}\) and the regular shape tensor with \(w_k = 1\).
The boolean SHELL_BASED
allows to run the iterative shape identifier on ellipsoidal shells (= homoeoids) rather than ellipsoids.
Note that SHELL_BASED = True
should only be set if the number of particles resolving the objects is \(> \mathcal{O}(10^5)\). The dictionary default_katz_config
can be imported via from cosmic_profiles import default_katz_config
.
Warning
The arrays d
, q
, s
, minor
, inter
and major
that can be retrieved from the structured numpy array shapes
will contain NaNs whenever the shape determination does not converge.
Note
We consider the shape determination at a specific \(r_{\text{ell}}\) to be converged if the fractional difference between consecutive eigenvalue fractions falls below IT_TOL
and the maximum number of iterations IT_WALL
is not yet achieved.
The shapes
structured array contains a field is_conv
which is True
whenever the shape calculation converged, True
otherwise. If you wanted to do some analysis on the e.g. 21st halo but wanted to remove unconverged bins, one could do something like:
shape = shapes[20]
is_conv = shapes[20]['is_conv']
shape = shape[is_conv]
...
If \(N_{\text{pass}}\) stands for the number of objects that have been selected with the obj_numbers
argument and in addition are sufficiently resolved, then the 1D and 2D shape profile arrays will have the following format:
d
of shape (\(N_{\text{pass}}\),D_BINS
+ 1): ellipsoidal radiiq
of shape (\(N_{\text{pass}}\),D_BINS
+ 1): q shape parameters
of shape (\(N_{\text{pass}}\),D_BINS
+ 1): s shape parameterminor
of shape (\(N_{\text{pass}}\),D_BINS
+ 1, 3): minor axes vs \(r_{\text{ell}}\)inter
of shape (\(N_{\text{pass}}\),D_BINS
+ 1, 3): intermediate axes vs \(r_{\text{ell}}\)major
of shape (\(N_{\text{pass}}\),D_BINS
+ 1, 3): major axes vs \(r_{\text{ell}}\)obj_centers
of shape (\(N_{\text{pass}}\),3): centers of objectsobj_masses
of shape (\(N_{\text{pass}}\),): masses of objects.
For post-processing purposes, one can dump the shape profiles via:
cprofiles.dumpShapeCatLocal(obj_numbers, katz_config = default_katz_config),
which will save the shape profiles in a destination of choice self.CAT_DEST
(a string describing the absolute (or relative with respect to Python working diretory) path to the destination folder, e.g. /path/to/cat
, will be created if missing) that has been provided during object instantiation.
Shape Profiles, Dumped Files
d_local_x.txt
(x
being the snap stringSNAP
) of shape (\(N_{\text{pass}}\),D_BINS
+ 1): ellipsoidal radiiq_local_x.txt
of shape (\(N_{\text{pass}}\),D_BINS
+ 1): q shape parameters_local_x.txt
of shape (\(N_{\text{pass}}\),D_BINS
+ 1): s shape parameterminor_local_x.txt
of shape (\(N_{\text{pass}}\), (D_BINS
+ 1) * 3): minor axes vs \(r_{\text{ell}}\), have to applyminor_local_x.reshape(minor_local_x.shape[0], minor_local_x.shape[1]//3, 3)
after loading with np.loadtxt()inter_local_x.txt
of shape (\(N_{\text{pass}}\), (D_BINS
+ 1) * 3): intermediate axes vs \(r_{\text{ell}}\), same heremajor_local_x.txt
of shape (\(N_{\text{pass}}\), (D_BINS
+ 1) * 3): major axes vs \(r_{\text{ell}}\), same herem_x.txt
of shape (\(N_{\text{pass}}\),): masses of haloscenters_x.txt
of shape (\(N_{\text{pass}}\),3): centers of halos
Note
In case of a Gadget-style I, II or HDF5 snapshot output, specify OBJ_TYPE = 'dm'
to calculate local dark matter halo shapes (only the dark matter component of halos), OBJ_TYPE = 'gas'
to calculate the local shapes of gas particles inside halos and OBJ_TYPE = 'stars'
to calculate the local shapes of star particles inside halos. The suffix of the output files will be modified accordingly to e.g. d_local_gas_x.txt
.
Global Shapes
Instead of shape profiles one might also be interested in obtaining the shape parameters and principal axes of the point clouds as a whole. This information can be obtained by calling:
shapes = cprofiles.getShapeCatGlobal(obj_numbers, katz_config = default_katz_config).
If a global shape calculations does not converge (which is rare), the corresponding entry in q = shapes['q']
etc. will feature a NaN. As with shape profiles, we can dump the global shape catalogue in a destination self.CAT_DEST
of choice via:
cprofiles.dumpShapeCatGlobal(obj_numbers, katz_config = default_katz_config),
which will save some files in the destination folder.
Global Shapes, Dumped Files
d_global_x.txt
(x
being the snap stringSNAP
) of shape (\(N_{\text{pass}}\),): ellipsoidal radiiq_global_x.txt
of shape (\(N_{\text{pass}}\),): q shape parameters_global_x.txt
of shape (\(N_{\text{pass}}\),): s shape parameterminor_global_x.txt
of shape (\(N_{\text{pass}}\), 3): minor axisinter_global_x.txt
of shape (\(N_{\text{pass}}\), 3): intermediate axismajor_global_x.txt
of shape (\(N_{\text{pass}}\), 3): major axism_x.txt
of shape (\(N_{\text{pass}}\),): masses of haloscenters_x.txt
of shape (\(N_{\text{pass}}\),3): centers of halos
Note
As previously, \(N_{\text{pass}}\) denotes the number of halos that have been selected with the obj_numbers
argument and pass the MIN_NUMBER_PTCS
-threshold. If the global shape determination for a sufficiently resolved object does not converge, it will appear as NaNs in the output.
Velocity Dispersion Tensor Eigenaxes
For Gadget-style I, II, or HDF5 snapshot outputs one can calculate the velocity dispersion tensor eigenaxes by calling:
shapes = cprofiles.getShapeCatVelLocal(obj_numbers, katz_config = default_katz_config)
for local velocity shapes or cprofiles.getShapeCatVelGlobal(obj_numbers, katz_config = default_katz_config)
for global velocity shapes. When calling e.g. cprofiles.dumpShapeCatVelGlobal(obj_numbers, katz_config = default_katz_config)
, the overall halo velocity dispersion tensor shapes of the following format will be added to self.CAT_DEST
.
Velocity Shapes, Dumped Files
d_global_vdm_x.txt
(x
being the snap stringSNAP
) of shape (\(N_{\text{pass}}\),): ellipsoidal radiiq_global_vdm_x.txt
of shape (\(N_{\text{pass}}\),): q shape parameters_global_vdm_x.txt
of shape (\(N_{\text{pass}}\),): s shape parameterminor_global_vdm_x.txt
of shape (\(N_{\text{pass}}\), 3): minor axisinter_global_vdm_x.txt
of shape (\(N_{\text{pass}}\), 3): intermediate axismajor_global_vdm_x.txt
of shape (\(N_{\text{pass}}\), 3): major axism_vdm_x.txt
of shape (\(N_{\text{pass}}\),): masses of haloscenters_vdm_x.txt
of shape (\(N_{\text{pass}}\),3): centers of halos
The cprofiles.dumpShapeCatVelLocal(obj_numbers, katz_config = default_katz_config)
command will dump files named d_local_vdm_x.txt
etc.
Visualizations
Shape profiles can be visualized using:
cprofiles.plotShapeProfs(nb_bins = 2, obj_numbers, katz_config = default_katz_config)
which draws median shape profiles and also mass bin-decomposed ones. nb_bins
stand for the number of mass bins to plot density profiles for. 3D visualizations of individual halos can be accomplished using:
cprofiles.vizLocalShapes(obj_numbers = [0,1,2], katz_config = default_katz_config)
which for instance would visualize the 3D distribution of particles as well as the eigenaxes at two different ellipsoidal radii in the first three objects that have sufficient resolution. The shape visualizations will be saved to the object’s attribute self.VIZ_DEST
(string describing the absolute (or relative with respect to Python working diretory) path to the visualization folder, e.g. /path/to/viz
, will be created if missing) that has been provided during object instantiation.