Skip to content

Commit

Permalink
Merge branch 'issue/591/triaxiality' of https://github.com/LSSTDESC/CLMM
Browse files Browse the repository at this point in the history
 into issue/591/triaxiality
  • Loading branch information
tae-h-shin committed Jul 17, 2024
2 parents 8cef454 + 2f39979 commit 2223c3b
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 5 deletions.
2 changes: 1 addition & 1 deletion clmm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .gcdata import GCData
from .galaxycluster import GalaxyCluster
from .clusterensemble import ClusterEnsemble
from .dataops import compute_tangential_and_cross_components, make_radial_profile
from .dataops import compute_tangential_and_cross_components, make_radial_profile, make_binned_estimators_triaxiality
from .utils import compute_radial_averages, make_bins, convert_units
from .theory import (
compute_reduced_shear_from_convergence,
Expand Down
187 changes: 187 additions & 0 deletions clmm/dataops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import warnings
import numpy as np
import scipy
from scipy.stats import binned_statistic
from astropy.coordinates import SkyCoord
from astropy import units as u
from ..gcdata import GCData
Expand Down Expand Up @@ -708,3 +709,189 @@ def make_stacked_radial_profile(angsep, weights, components):
np.average(component, axis=0, weights=weights) for component in components
]
return staked_angsep, stacked_components

def measure_Delta_Sigma_const_triaxiality(w, gamma1, Sigma_crit) :
"""Measure Delta sigma const quadrupole value for individual galaxies.
Parameters
----------
w: float or array
Weight computed for each galaxy by the descrition as given in Shin et al. (https://doi.org/10.1093/mnras/stx3366)
gamma1: float or array
Shear component gamma 1
Sigma_crit: float
Critical surface mass density in M_{sun}/Mpc^{2}
Returns
-------
dsconst_data: The measured "4theta" quadrupole component from the input shear measurements for each galaxy
"""
dsconst_data = w * Sigma_crit * gamma1 / w
return dsconst_data

def measure_Delta_Sigma_4theta_triaxiality(w1, w2, gamma1, gamma2, theta, Sigma_crit) :
"""Measure Delta sigma 4theta quadrupole value for individual galaxies.
Parameters
----------
w1: float or array
Weight computed for each galaxy by the descrition as given in Shin et al. (https://doi.org/10.1093/mnras/stx3366)
w2: float or array
Weight computed for each galaxy by the descrition as given in Shin et al. (https://doi.org/10.1093/mnras/stx3366)
gamma1: float or array
Shear component gamma 1
gamma2: float or array
Shear component gamma 2
theta: float or array
Position Angle of galaxy measured counter-clockwise from the gamma1 direction
Sigma_crit: float
Critical surface mass density in M_{sun}/Mpc^{2}
Returns
-------
ds4theta_data: The measured "const" quadrupole component from the input shear measurements for each galaxy
"""
ds4theta_data = Sigma_crit * (w1*gamma1/np.cos(4*theta) + w2*gamma2/np.sin(4*theta)) / (w1 + w2)
return ds4theta_data

def measure_weights_triaxiality(Sigma_crit, theta, Sigma_shape=0.0001, Sigma_meas=0) :
"""Measure weight values for quadrupole measurement of individual galaxies.
Using Equations 35, 32, 33 from Shin et al. 2018 (https://doi.org/10.1093/mnras/stx3366)
Parameters
----------
Sigma_crit: float
Critical surface mass density in M_{sun}/Mpc^{2}
theta: float or array
Position Angle of galaxy measured counter-clockwise from the gamma1 direction
Sigma_shape: Float, optional
Scatter in the shape measurement from shape noise
Sigma_meas: Float, optional
Measurement error for shapes
Returns
-------
w, w1, w2: float or array
Weights for each galaxy
"""

w = 1 / (Sigma_crit**2 * (Sigma_shape**2 + Sigma_meas**2))
w1 = np.cos(4*theta)**2 * w
w2 = np.sin(4*theta)**2 * w
return w, w1, w2

def make_binned_estimators_triaxiality(gamma1, gamma2, x_arcsec, y_arcsec, z_cluster, z_source, cosmo, monopole_bins=15,
quadrupole_bins=15, r_min=0.3, r_max=2.5):
"""
Makes radially binned profiles for Monopole, Quadrupole (4theta and const) as described in Shin et al. 2018
Parameters
----------
gamma1: float or array
Shear component gamma 1
gamma2: float or array
Shear component gamma 2
x_arcsec: float or array
X position in arcsec when cluster center is at 0.0 and x axis is assumed to be along the major axis of the cluster
y_arcsec: float or array
Y position in arcsec when cluster center is at 0.0
z_cluster: float
Redshift of lens cluster
cosmo: clmm.cosmology.Cosmology object
CLMM Cosmology object
monopole_bins: float, optional
Number of bins for monopole lensing profile
quadrupole_bins: float, optional
Number of bins for quadrupole lensing profiles (4theta, const)
r_min: Float, optional
Minimum radial distance to measure monopole and quadrupole shear profiles in Mpc (Default is 0.3 Mpc)
r_max: Float, optional
Maximum radial distance to measure monopole and quadrupole shear profiles in Mpc (Default is 2.5 Mpc)
Returns
-------
ds_mono: float or array
Binned monopole lensing profile
ds_mono_err: float or array
Uncertainty for the binned monopole lensing shear profile
r_mono: float or array
Bin centers for the monopole lensing shear profile
ds_4theta: float or array
Binned binned quadrupole 4-theta lensing shear profile
ds_4theta_err: float or array
Uncertainty for the binned quadrupole 4-theta lensing shear profile
ds_const: float or array
Binned binned quadrupole const lensing shear profile
ds_const_err: float or array
Uncertainty for the binned quadrupole const lensing shear profile
r_quad: float or array
Bin centers for the quadrupole lensing shear profiles (4theta and const)
"""

sigma_crit = cosmo.eval_sigma_crit(z_cluster,z_source)
r = np.sqrt((x_arcsec**2 + y_arcsec**2)) #In arcsecs
theta = np.arctan2(y_arcsec, x_arcsec)
r_mpc = r*cosmo.eval_da(z_cluster) * np.pi/180.0 * 1/3600 #In Mpc

w, w1, w2 = measure_weights_triaxiality(sigma_crit, theta)
DS4theta = measure_Delta_Sigma_4theta_triaxiality(w1, w2, gamma1, gamma2, theta, sigma_crit)
DSconst = measure_Delta_Sigma_const_triaxiality(w, gamma1, sigma_crit)

#Binning for Quadrupole measurements DS4theta and DSconst
bins=quadrupole_bins
r_min = r_min
r_max = r_max

bin_edges = np.logspace(np.log10(r_min), np.log10(r_max), bins)
N_i = []
for i in np.arange(bins-1):
N_i.append(len(r_mpc[(r_mpc > bin_edges[i]) & (r_mpc < bin_edges[i+1])]))
N_i=np.array(N_i)


result = binned_statistic(r_mpc, gamma1, statistic='mean', bins=bin_edges)
gamma1_i = result.statistic
res = binned_statistic(r_mpc, gamma2, statistic='mean', bins=bin_edges)
gamma2_i = res.statistic
res = binned_statistic(r_mpc, DS4theta, statistic='mean', bins=bin_edges)
DS4theta_i_err = binned_statistic(r_mpc, DS4theta, statistic='std', bins=bin_edges).statistic/np.sqrt(N_i)
DS4theta_i = res.statistic
res = binned_statistic(r_mpc, DSconst, statistic='mean', bins=bin_edges)
DSconst_i = res.statistic
DSconst_i_err = binned_statistic(r_mpc, DSconst, statistic='std', bins=bin_edges).statistic/np.sqrt(N_i)
r_i = bin_edges

#Binning for Monopole Measurements:
bins_mono=monopole_bins
bin_edges = np.logspace(np.log10(r_min), np.log10(r_max), bins_mono)
N_i = []
for i in np.arange(bins_mono-1):
N_i.append(len(r_mpc[(r_mpc > bin_edges[i]) & (r_mpc < bin_edges[i+1])]))
N_i=np.array(N_i)

r_mono = bin_edges
res = binned_statistic(r_mpc, -gamma1*np.cos(2*theta)-gamma2*np.sin(2*theta), statistic='mean', bins=bin_edges)
gammat_mono = res.statistic
ds_mono_err = binned_statistic(r_mpc, -gamma1*np.cos(2*theta)-gamma2*np.sin(2*theta), statistic='std',
bins=bin_edges).statistic/np.sqrt(N_i)*sigma_crit
ds_mono = gammat_mono*sigma_crit

# SAFEGUARD AGAINST BINS WITH NANs and 0.0s

ind = np.invert(np.isnan(ds_mono) | np.isnan(ds_mono_err))
ds_mono = ds_mono[ind]
ds_mono_err = ds_mono_err[ind]
r_mono = np.sqrt(r_mono[:-1]*r_mono[1:])[ind]
ind = (ds_mono!= 0.0) & (ds_mono_err!= 0.0)
ds_mono = ds_mono[ind]
ds_mono_err = np.abs(ds_mono_err[ind])
r_mono = r_mono[ind]

ind = np.invert(np.isnan(DS4theta_i) | np.isnan(DS4theta_i_err) | np.isnan(DSconst_i) | np.isnan(DSconst_i_err))
ds_4theta = DS4theta_i[ind]
ds_4theta_err = np.abs(DS4theta_i_err[ind])
ds_const = DSconst_i[ind]
ds_const_err = np.abs(DSconst_i_err[ind])
r_quad = np.sqrt(r_i[:-1]*r_i[1:])[ind]

return ds_mono,ds_mono_err,r_mono,ds_4theta,ds_4theta_err,ds_const,ds_const_err,r_quad

9 changes: 5 additions & 4 deletions clmm/theory/func_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@ def compute_delta_sigma_4theta_triaxiality(
verbose=False,
validate_input=True,
):
r"""Compute the "4-theta"-quadrupole value
r"""Compute the "4-theta" component of quadrupole shear as given in Shin et al. 2018 (https://doi.org/10.1093/mnras/stx3366)
Parameters
----------
Expand Down Expand Up @@ -1351,7 +1351,7 @@ def compute_delta_sigma_4theta_triaxiality(
Returns
-------
ds4theta: array
Delta sigma 4-theta value at a position for the elliptical halo specified
Delta sigma 4-theta component value at a position for the elliptical halo specified
"""
### DEFINING INTEGRALS:
r_arr = np.linspace(0.01, 3*np.max(r_source), sample_N)
Expand Down Expand Up @@ -1390,7 +1390,7 @@ def compute_delta_sigma_const_triaxiality(
verbose=False,
validate_input=True,
):
r"""Compute the excess surface density lensing profile for "const"-quadrupole value
r"""Compute the "const" component of quadrupole shear as given in Shin et al. 2018 (https://doi.org/10.1093/mnras/stx3366)
Parameters
----------
Expand Down Expand Up @@ -1474,7 +1474,8 @@ def compute_delta_sigma_excess_triaxiality(
verbose=False,
validate_input=True,
):
r"""Compute the excess surface density lensing profile for the monopole component along with second order expansion term (e**2)
r"""Compute the excess surface density lensing profile for the monopole component along
with second order expansion term (e**2) as given in Shin et al. 2018 (https://doi.org/10.1093/mnras/stx3366)
Parameters
----------
Expand Down

0 comments on commit 2223c3b

Please sign in to comment.