Boost factors
=============
.. code:: ipython3
import clmm
from clmm import Cosmology
from clmm.support import mock_data as mock
from clmm.galaxycluster import GalaxyCluster
import matplotlib.pyplot as plt
import sys
import clmm.utils as u
Make sure we know which version we’re using
.. code:: ipython3
clmm.__version__
.. parsed-literal::
'1.12.0'
Define cosmology object
~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
mock_cosmo = Cosmology(H0=70.0, Omega_dm0=0.27 - 0.045, Omega_b0=0.045, Omega_k0=0.0)
First, we want to generate a :math:`\Delta\Sigma` (excess surface
density) profile from mock data, to which we can apply boost factors.
The mock data is generated in the following cells.
Generate cluster object from mock data
.. code:: ipython3
cosmo = mock_cosmo
cluster_id = "Awesome_cluster"
cluster_m = 1.0e15
cluster_z = 0.3
concentration = 4
ngals = 1000
zsrc_min = cluster_z + 0.1 # we only want to draw background galaxies
noisy_data_z = mock.generate_galaxy_catalog(
cluster_m,
cluster_z,
concentration,
cosmo,
"chang13",
zsrc_min=zsrc_min,
shapenoise=0.005,
photoz_sigma_unscaled=0.05,
ngals=ngals,
)
Loading this into a CLMM cluster object centered on (0,0)
.. code:: ipython3
cluster_ra = 0.0
cluster_dec = 0.0
cl = GalaxyCluster(cluster_id, cluster_ra, cluster_dec, cluster_z, noisy_data_z)
Compute cross and tangential excess surface density for each source
galaxy
.. code:: ipython3
_ = cl.compute_tangential_and_cross_components(
geometry="flat",
shape_component1="e1",
shape_component2="e2",
tan_component="DeltaSigma_tan",
cross_component="DeltaSigma_cross",
add=True,
cosmo=cosmo,
is_deltasigma=True,
)
.. parsed-literal::
/global/homes/a/aguena/.local/perlmutter/python-3.11/lib/python3.11/site-packages/clmm-1.12.0-py3.11.egg/clmm/cosmology/parent_class.py:110: UserWarning:
Some source redshifts are lower than the cluster redshift.
Sigma_crit = np.inf for those galaxies.
Calculate the binned profile
.. code:: ipython3
cl.make_radial_profile(
"kpc",
cosmo=cosmo,
tan_component_in="DeltaSigma_tan",
cross_component_in="DeltaSigma_cross",
tan_component_out="DeltaSigma_tan",
cross_component_out="DeltaSigma_cross",
table_name="DeltaSigma_profile",
)
# Format columns for display
for col in cl.DeltaSigma_profile.colnames:
fmt = cl.DeltaSigma_profile[col].info.format
if "DeltaSigma" in col:
fmt = ".2e"
elif any(typ in col for typ in ("z", "radius")):
fmt = ".2f"
cl.DeltaSigma_profile[col].info.format = fmt
# Show
cl.DeltaSigma_profile.show_in_notebook()
.. raw:: html
GCData length=10
idx | radius_min | radius | radius_max | DeltaSigma_tan | DeltaSigma_tan_err | DeltaSigma_cross | DeltaSigma_cross_err | z | z_err | n_src | W_l |
0 | 116.87 | 441.96 | 652.82 | 2.38e+14 | 3.64e+13 | -1.24e+13 | 1.62e+13 | 1.19 | 0.14 | 18 | 18.0 |
1 | 652.82 | 967.93 | 1188.77 | 1.16e+14 | 3.55e+12 | 1.56e+11 | 2.06e+12 | 1.17 | 0.10 | 47 | 47.0 |
2 | 1188.77 | 1480.84 | 1724.72 | 7.26e+13 | 2.05e+12 | 2.97e+12 | 2.51e+12 | 1.37 | 0.09 | 67 | 67.0 |
3 | 1724.72 | 1989.06 | 2260.67 | 5.70e+13 | 2.01e+12 | -3.14e+11 | 1.72e+12 | 1.30 | 0.08 | 92 | 92.0 |
4 | 2260.67 | 2531.03 | 2796.62 | 4.57e+13 | 1.80e+12 | -1.45e+12 | 1.38e+12 | 1.41 | 0.07 | 139 | 139.0 |
5 | 2796.62 | 3077.13 | 3332.57 | 3.94e+13 | 2.97e+12 | 3.13e+11 | 1.77e+12 | 1.27 | 0.06 | 167 | 167.0 |
6 | 3332.57 | 3598.82 | 3868.52 | 3.03e+13 | 2.02e+12 | 2.58e+12 | 3.69e+12 | 1.21 | 0.05 | 196 | 196.0 |
7 | 3868.52 | 4127.03 | 4404.48 | 2.58e+13 | 1.56e+12 | 1.54e+12 | 1.26e+12 | 1.21 | 0.05 | 163 | 163.0 |
8 | 4404.48 | 4659.49 | 4940.43 | 2.26e+13 | 1.80e+12 | 3.08e+12 | 1.74e+12 | 1.37 | 0.09 | 76 | 76.0 |
9 | 4940.43 | 5184.62 | 5476.38 | 2.37e+13 | 9.03e+12 | -2.74e+11 | 3.98e+12 | 1.14 | 0.13 | 35 | 35.0 |
Plot the :math:`\Delta\Sigma` profile
.. code:: ipython3
plt.errorbar(
cl.DeltaSigma_profile["radius"],
cl.DeltaSigma_profile["DeltaSigma_tan"],
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
)
plt.title("DeltaSigma profile")
plt.xlabel("Radius [kpc]")
plt.ylabel("$\Delta\Sigma [M_\odot\; Mpc^{-2}]$")
plt.show()
.. image:: demo_boost_factors_files/demo_boost_factors_16_0.png
Boost Factors
-------------
CLMM offers two boost models, the NFW boost model, and a powerlaw boost
model.
Note that ``compute_nfw_boost`` requires two parameters to be specified,
``rs`` and ``b0``, and ``compute_powerlaw_boost`` requires three
paramters, ``rs``, ``b0`` and ``alpha``. The default values are in kpc.
Details on these boost models can be found
`here `__
First, we can calculate the boost factors from the two models.
.. code:: ipython3
nfw_boost = u.compute_nfw_boost(cl.DeltaSigma_profile["radius"], rscale=1000, boost0=0.1)
powerlaw_boost = u.compute_powerlaw_boost(
cl.DeltaSigma_profile["radius"], rscale=1000, boost0=0.1, alpha=-1.0
)
Plot the two boost factors, :math:`B(R)`
.. code:: ipython3
plt.plot(cl.DeltaSigma_profile["radius"], nfw_boost, label="NFW boost factor")
plt.plot(cl.DeltaSigma_profile["radius"], powerlaw_boost, label="Powerlaw boost factor")
plt.xlabel("Radius [kpc]")
plt.ylabel("$B(R)$")
plt.legend()
plt.show()
.. image:: demo_boost_factors_files/demo_boost_factors_21_0.png
The :math:`\Delta\Sigma` profiles can be corrected with the boost factor
using ``correct_sigma_with_boost_values`` or
``correct_sigma_with_boost_model``.
``correct_sigma_with_boost_values`` requires us to precompute the boost
factor, e.g. using ``compute_nfw_boost``.
``correct_sigma_with_boost_model`` simply requires us to specify the
boost model.
Note that the boost factor can be used in one of two ways.
Either the boost factor can be applied to the observed data vector to
correct for the dilution of the signal by cluster member galaxies. In
this case the amplitude of the corrected profile will increase.
Or the boost factor can be applied to the model prediction. In this case
it behaves as a dilution factor, and the resulting model prediction will
be lower than the original one.
Both scenarios will improve the agreement between the mock data and
observed data, by accounting for cluster member galaxy contamination.
In this notebook, we use the second approach, where the data is
generated using mock data that does not account for dilution until the
boost factor is applied. The corrected profiles from the mock data are
lower than the uncorrected one.
Essentially we are diluting the mock profile to mimick the effect of
contamination by cluster members.
First we will apply the boost factor with
``correct_sigma_with_boost_values``
.. code:: ipython3
Sigma_corrected_powerlaw_boost = u.correct_sigma_with_boost_values(
cl.DeltaSigma_profile["DeltaSigma_tan"], powerlaw_boost
)
Sigma_corrected_nfw_boost = u.correct_sigma_with_boost_values(
cl.DeltaSigma_profile["DeltaSigma_tan"], nfw_boost
)
Plot the result
.. code:: ipython3
plt.errorbar(
cl.DeltaSigma_profile["radius"],
Sigma_corrected_nfw_boost,
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="$\Delta \Sigma$ / NFW boost factor",
)
plt.errorbar(
cl.DeltaSigma_profile["radius"],
Sigma_corrected_powerlaw_boost,
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="$\Delta \Sigma$ / Powerlaw boost factor",
)
plt.errorbar(
cl.DeltaSigma_profile["radius"],
cl.DeltaSigma_profile["DeltaSigma_tan"],
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="uncorrected $\Delta \Sigma$",
color="grey",
)
# plt.loglog()
plt.title("DeltaSigma profile")
plt.xlabel("Radius [kpc]")
plt.ylabel("$\Delta\Sigma [M_\odot\; Mpc^{-2}]$")
plt.legend()
plt.show()
.. image:: demo_boost_factors_files/demo_boost_factors_27_0.png
Now the same again but with ``correct_sigma_with_boost_model``
.. code:: ipython3
Sigma_corrected_powerlaw_boost = u.correct_sigma_with_boost_model(
cl.DeltaSigma_profile["radius"],
cl.DeltaSigma_profile["DeltaSigma_tan"],
boost_model="powerlaw_boost",
)
Sigma_corrected_nfw_boost = u.correct_sigma_with_boost_model(
cl.DeltaSigma_profile["radius"],
cl.DeltaSigma_profile["DeltaSigma_tan"],
boost_model="nfw_boost",
)
plt.errorbar(
cl.DeltaSigma_profile["radius"],
Sigma_corrected_nfw_boost,
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="$\Delta \Sigma$ / NFW boost factor",
)
plt.errorbar(
cl.DeltaSigma_profile["radius"],
Sigma_corrected_powerlaw_boost,
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="$\Delta \Sigma$ / Powerlaw boost factor",
)
plt.errorbar(
cl.DeltaSigma_profile["radius"],
cl.DeltaSigma_profile["DeltaSigma_tan"],
cl.DeltaSigma_profile["DeltaSigma_tan_err"],
marker="o",
label="uncorrected $\Delta \Sigma$",
color="grey",
)
# plt.loglog()
plt.title("DeltaSigma profile")
plt.xlabel("Radius [kpc]")
plt.ylabel("$\Delta\Sigma [M_\odot\; Mpc^{-2}]$")
plt.legend()
plt.show()
.. image:: demo_boost_factors_files/demo_boost_factors_29_0.png