Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realization from Galacticus output #43

Merged
merged 19 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
bb924ca
Implemented TNFWFromParams class and a new preset model DMFromGalacticus
cgannonucm Sep 1, 2023
f00dd12
Fixed bug with difference in definition between rho_s in galacticus a…
cgannonucm Sep 2, 2023
7659d4a
Additional comment on definition of rho_s
cgannonucm Sep 2, 2023
50bbb7a
Improved density comparison plots
cgannonucm Sep 2, 2023
0649f78
Aditional documentation, improved graphs.
cgannonucm Sep 2, 2023
16b9d6b
Now excludes subhalos that are outside of rendering volume.
cgannonucm Sep 3, 2023
d8a214f
Simplified reading of galacticus output hdf5 files
cgannonucm Sep 6, 2023
4453d52
Minor changes to comments
cgannonucm Sep 6, 2023
0067369
Minor updates to documentation
cgannonucm Sep 6, 2023
b54398a
Removed unused file
cgannonucm Sep 6, 2023
e553045
Implemented changes requested by Daniel Gilman in pyHalo/Halos/HaloMo…
cgannonucm Sep 9, 2023
234ca0c
Added new parameters to DMFromGalacticus module, simplified documenta…
cgannonucm Sep 11, 2023
43f88e1
Removed type hints
cgannonucm Sep 11, 2023
afe7a07
Fixed bug with isinstance
cgannonucm Sep 11, 2023
f126bdf
Merge branch 'master' into import_galacticus_subhalos
cgannonucm Sep 19, 2023
0d27495
Moved DMFromGalacticus from preset_models.py -> PresetModels/externa…
cgannonucm Sep 19, 2023
461e3ce
Removed explicit loop in nodedata_filter_virialized function
cgannonucm Sep 19, 2023
44fcd47
Spellcheck
cgannonucm Sep 19, 2023
4a2cd0f
Fixed issue in tests/test_realization_extensions.py with import names
cgannonucm Sep 20, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added example_notebooks/data/TNFW_example.hdf5
Binary file not shown.
97 changes: 97 additions & 0 deletions pyHalo/Halos/HaloModels/TNFWFromParams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from pyHalo.Halos.halo_base import Halo
from lenstronomy.LensModel.Profiles.tnfw import TNFW as TNFWLenstronomy
import numpy as np
from pyHalo.Halos.tnfw_halo_util import tnfw_mass_fraction
from pyHalo.Halos.HaloModels.TNFW import TNFWSubhalo
from lenstronomy.LensModel.Profiles.tnfw import TNFW

class TNFWFromParams(TNFWSubhalo):
"""
Creates a TNFW halo based on physical params.
"""

KEY_RT = "r_trunc_kpc"
KEY_RS = "rs"
KEY_RHO_S = "rho_s"
KEY_RV = "rv"

def __init__(self, mass, x_kpc, y_kpc, r3d, z,
sub_flag, lens_cosmo_instance, args, unique_tag=None):
"""
Defines a TNFW subhalo with physical params r_trunc_kpc, rs, rhos passed in the args argument
"""

self._lens_cosmo = lens_cosmo_instance

self._kpc_per_arcsec_at_z = self._lens_cosmo.cosmo.kpc_proper_per_asec(z)

x = x_kpc / self._kpc_per_arcsec_at_z

y = y_kpc / self._kpc_per_arcsec_at_z

keys_physical = (self.KEY_RV,self.KEY_RS,self.KEY_RHO_S,self.KEY_RV,self.KEY_RT)
self._params_physical = {key:args[key] for key in keys_physical}

self._c = self._params_physical[self.KEY_RV] / self._params_physical[self.KEY_RS]

super(TNFWFromParams, self).__init__(mass,x,y,r3d,z,sub_flag,lens_cosmo_instance,args,None,None,unique_tag)

def density_profile_3d(self, r, params_physical=None):
"""
Computes the 3-D density profile of the halo
:param r: distance from center of halo [kpc]
:return: the density profile in units M_sun / kpc^3
"""

_params = self._params_physical if params_physical is None else params_physical

r_t = _params[self.KEY_RT]
r_s = _params[self.KEY_RS]
rho_s = _params[self.KEY_RHO_S]

n = 1

x = r / r_s
tau = r_t / r_s

density_nfw = (rho_s / ((x)*(1+x)**2))

return density_nfw * (tau**2 / (tau**2 + x**2))**n


@property
def profile_args(self):
"""
See documentation in base class (Halos/halo_base.py)
"""
if not hasattr(self, '_profile_args'):
truncation_radius_kpc = self.params_physical[self.KEY_RT]
self._profile_args = (self.c, truncation_radius_kpc)
return self._profile_args


@property
def lenstronomy_params(self):
"""
See documentation in base class (Halos/halo_base.py)
"""
if not hasattr(self, '_kwargs_lenstronomy'):

r_t = self.params_physical[self.KEY_RT]
r_s = self.params_physical[self.KEY_RS]
rho_s = self.params_physical[self.KEY_RHO_S]

Rs_angle, theta_Rs = self.nfw_physical2angle_fromNFWparams(rho_s,r_s,self.z)

x, y = np.round(self.x, 4), np.round(self.y, 4)

Rs_angle = np.round(Rs_angle, 10)
theta_Rs = np.round(theta_Rs, 10)
r_trunc_arcsec = r_t / self._lens_cosmo.cosmo.kpc_proper_per_asec(self.z)

kwargs = [{'alpha_Rs': self._rescale_norm * theta_Rs, 'Rs': Rs_angle,
'center_x': x, 'center_y': y, 'r_trunc': r_trunc_arcsec}]

self._kwargs_lenstronomy = kwargs

return self._kwargs_lenstronomy, None
Empty file.
97 changes: 97 additions & 0 deletions pyHalo/Halos/galacticus_util/galacticus_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from pyHalo.Halos.galacticus_util.galacticus_util import GalacticusUtil
import numpy as np

def nodedata_apply_filter(nodedata,filter,galacticus_util = None):
"""Takes a dictionary with numpy arrays as values and apply as boolean filter to all.
Returns a dictionary with same keys, but a filter applied to all arrays."""

return {key:val[filter] for key,val in nodedata.items()}

def nodedata_filter_tree(nodedata, treenum,galacticus_util = None):
"""Returns a filter that excludes all nodes but nodes in the specified tree"""
gutil = GalacticusUtil() if galacticus_util is None else galacticus_util
return nodedata[gutil.PARAM_TREE_INDEX] == treenum

def nodedata_filter_subhalos(nodedata,galacticus_util= None):
"""Returns a filter that excludes all but subhalos (excludes host halos)"""
gutil = GalacticusUtil() if galacticus_util is None else galacticus_util
return nodedata[gutil.PARAM_ISOLATED] == 0

def nodedata_filter_halos(nodedata,galacticus_util = None):
"""Returns a filter that excludes all but halo (excludes sub-halos)"""
return np.logical_not(nodedata_filter_subhalos(nodedata))

def nodedata_filter_range(nodedata,range,key,galacticus_util=None):
"""Returns a filter that excludes nodes not within the given range for a specified parameter"""
return (nodedata[key] > range[0]) & (nodedata[key] < range[1])

def nodedata_filter_virialized(nodedata,galacticus_util= None):
"""
Returns a filter that excludes everything outside of the host halos virial radius
WARNING: Current implementation only works if there is only one host halo per tree,
IE we are looking at the last output from galacticus.
"""
gutil = GalacticusUtil() if galacticus_util is None else galacticus_util

#Get radial position of halos
rvec = np.asarray((nodedata[gutil.PARAM_X],nodedata[gutil.PARAM_Y],nodedata[gutil.PARAM_Z]))
r = np.linalg.norm(rvec,axis=0)

#Filter halos and get there virial radii
filtered_halos = nodedata_filter_halos(nodedata)
rv_halos = nodedata[gutil.PARAM_RADIUS_VIRIAL][filtered_halos]
halo_output_n = nodedata[gutil.PARAM_TREE_ORDER]

filter_virialized = r < rv_halos[halo_output_n]

return filter_virialized

def nodedata_filter_r2d(nodedata,r2d_max,plane_normal,
galacticus_util= None):

"""
Filters based on projected radii.
"""
gutil = GalacticusUtil() if galacticus_util is None else galacticus_util

r = np.asarray((nodedata[gutil.PARAM_X],nodedata[gutil.PARAM_Y],nodedata[gutil.PARAM_Z]))

r2d = project_r2d(*r,plane_normal)

return r2d < r2d_max

def project_r2d(x,y,z,plane_normal):
"""
Takes in arrays of coordinates, calculates the projected radius on the plane.


:param x: An array of x coordinates
:param y: An array of y coordinates
:param z: An array of z coordinates
:plane_normal: Normal vector of the plane to project onto
"""
coords = np.asarray((x,y,z))

#Reshape so if scalers are passed for x,y,z we do not encounter issue
if coords.ndim == 1:
coords.reshape((3,1))

#convert to unit normal
un = plane_normal / np.linalg.norm(plane_normal)

#Project distance to plane
#Projected distance to plane is sqrt(r.r - (r.un)^2)
rdotr = np.linalg.norm(coords,axis=0)**2
rdotun = np.dot(un,coords)
return np.sqrt(rdotr - rdotun**2)











Loading