<jupyter_start><jupyter_text>Measure a Profile  NoteAll functions in this section can be used passing the explicit arguments but are also internal functions of the cluster object, and should be used as such. They are just explicitely used here for clarity.Ex:```theta, g_t, g_x = compute_tangential_and_cross_components(ra_lens, dec_lens,                ra_source, dec_source, shear1, shear2)```should be done by the user as:```theta, g_t, g_x = cl.compute_tangential_and_cross_components()```<jupyter_code>import matplotlib.pyplot as plt
import numpy as np
import clmm
import clmm.dataops
from clmm.dataops import compute_tangential_and_cross_components, make_radial_profile, make_bins
from clmm.galaxycluster import GalaxyCluster
import clmm.utils as u
from clmm import Cosmology
from clmm.support import mock_data as mock<jupyter_output><empty_output><jupyter_text>Make sure we know which version we're using<jupyter_code>clmm.__version__<jupyter_output><empty_output><jupyter_text>Define cosmology object<jupyter_code>mock_cosmo = Cosmology(H0 = 70.0, Omega_dm0 = 0.27 - 0.045, Omega_b0 = 0.045, Omega_k0 = 0.0)<jupyter_output><empty_output><jupyter_text>1. Generate cluster object from mock dataIn this example, the mock data includes: shape noise, galaxies drawn from redshift distribution and photoz errors. Define toy cluster parameters for mock data generation<jupyter_code>cosmo = mock_cosmo
cluster_id = "Awesome_cluster"
cluster_m = 1.e15
cluster_z = 0.3
concentration = 4
ngals = 10000

cluster_ra = 0.
cluster_dec = 90.

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, 
                                            cluster_ra=cluster_ra, cluster_dec=cluster_dec)<jupyter_output><empty_output><jupyter_text>Loading this into a CLMM cluster object centered on (0,0)<jupyter_code>cl = GalaxyCluster(cluster_id, cluster_ra, cluster_dec, 
                               cluster_z, noisy_data_z)<jupyter_output><empty_output><jupyter_text>2. Load cluster object containing:> Lens properties (ra_l, dec_l, z_l)> Source properties (ra_s, dec_s, e1, e2) Note, if loading from mock data, use: > cl = gc.GalaxyCluster.load("GC_from_mock_data.pkl")<jupyter_code>print("Cluster info = ID:", cl.unique_id, "; ra:", cl.ra,
      "; dec:", cl.dec, "; z_l :", cl.z)
print("The number of source galaxies is :", len(cl.galcat))<jupyter_output><empty_output><jupyter_text>2. Basic checks and plots - galaxy positions- redshift distribution<jupyter_code>f, ax = plt.subplots(1, 2, figsize=(12, 4))

ax[0].scatter(cl.galcat['ra'], cl.galcat['dec'], color='blue', s=1, alpha=0.3)
ax[0].plot(cl.ra, cl.dec, 'ro')
ax[0].set_ylabel('dec', fontsize="large")
ax[0].set_xlabel('ra', fontsize="large")

hist = ax[1].hist(cl.galcat['z'], bins=40)[0]
ax[1].axvline(cl.z, c='r', ls='--')
ax[1].set_xlabel('$z_{source}$', fontsize="large")
xt = {t:f'{t}' for t in ax[1].get_xticks() if t!=0}
xt[cl.z] ='$z_{cl}$'
xto = sorted(list(xt.keys())+[cl.z])
ax[1].set_xticks(xto)
ax[1].set_xticklabels(xt[t] for t in xto)
ax[1].get_xticklabels()[xto.index(cl.z)].set_color('red')
plt.xlim(0, max(xto))
plt.show()<jupyter_output><empty_output><jupyter_text>- Check ellipticities<jupyter_code>fig, ax1 = plt.subplots(1, 1)

ax1.scatter(cl.galcat['e1'], cl.galcat['e2'], s=1, alpha=0.2)
ax1.set_xlabel('e1')
ax1.set_ylabel('e2')
ax1.set_aspect('equal', 'datalim')
ax1.axvline(0, linestyle='dotted', color='black')
ax1.axhline(0, linestyle='dotted', color='black')<jupyter_output><empty_output><jupyter_text>3. Compute and plot shear profiles  3.1 Compute angular separation, cross and tangential shear for each source galaxy<jupyter_code>theta, e_t, e_x = compute_tangential_and_cross_components(
                ra_lens=cl.ra, dec_lens=cl.dec,
                ra_source=cl.galcat['ra'], dec_source=cl.galcat['dec'],
                shear1=cl.galcat['e1'], shear2=cl.galcat['e2'])<jupyter_output><empty_output><jupyter_text>3.1.1 Using `GalaxyCluster` object- You can also call the function directly from the `GalaxyCluster` object- By defaut, `compute_tangential_and_cross_components` uses columns named `e1` and `e2` of the `galcat` table<jupyter_code>cl.compute_tangential_and_cross_components(add=True)
# With the option add the cl object has theta, et and ex new columns 
# (default: takes in columns named 'e1' and 'e2' and save the results in 'et' and 'ex')
cl.galcat['et', 'ex'].pprint(max_width=-1)<jupyter_output><empty_output><jupyter_text>- But it's also possible to choose which columns to use for input and output, e.g. Below we're storing the results in `e_tan` and `e_cross` instead (explicitely taking `e1` and `e2` as input)<jupyter_code>cl.compute_tangential_and_cross_components(shape_component1='e1', shape_component2='e2', 
                                           tan_component='e_tan', cross_component='e_cross',
                                           add=True)
cl.galcat['e_tan', 'e_cross'].pprint(max_width=-1)<jupyter_output><empty_output><jupyter_text>Plot tangential and cross ellipticity distributions for verification, which can be accessed in the galaxy cluster object, cl.<jupyter_code>f, ax = plt.subplots(1, 2, figsize=(10, 4))

ax[0].hist(cl.galcat['et'],bins=50)
ax[0].set_xlabel('$\\epsilon_t$',fontsize='xx-large')

ax[1].hist(cl.galcat['ex'],bins=50)
ax[1].set_xlabel('$\\epsilon_x$',fontsize='xx-large')
ax[1].set_yscale('log')<jupyter_output><empty_output><jupyter_text>Compute transversal and cross shear profiles in units defined by user, using defaults binning   3.2 Compute shear profile in radial binsGiven the separations in "radians" computed in the previous step, the user may ask for a binned profile in various projected distance units. 3.2.1 Default binning- default binning using kpc:<jupyter_code>profiles = make_radial_profile([cl.galcat['et'], cl.galcat['ex'], cl.galcat['z']],
                                    angsep=cl.galcat['theta'], angsep_units="radians",
                                    bin_units="kpc", cosmo=cosmo, z_lens=cl.z)
#profiles.pprint(max_width=-1)
profiles.show_in_notebook()<jupyter_output><empty_output><jupyter_text>Note that, because this function bins a generic number of quantities in the radial profile, its output table names the quantities as `p_i` and errors as `p_i_err`.  3.1.2 Using `GalaxyCluster` objectThe output `GCData` corresponding to the binning profiled is attached as a new attribute of the galaxy cluster object.<jupyter_code>cl.make_radial_profile("kpc", cosmo=cosmo)
#cl.profile.pprint(max_width=-1)
cl.profile.show_in_notebook()<jupyter_output><empty_output><jupyter_text>You can see that this `profile` table contains metadata regarding the comology and bin units<jupyter_code>print('Cosmology:', cl.profile.meta['cosmo'])
print('bin units:', cl.profile.meta['bin_units'])<jupyter_output><empty_output><jupyter_text>Use function to plot the profiles<jupyter_code>fig, ax = cl.plot_profiles(xscale='log')<jupyter_output><empty_output><jupyter_text>- default binning using degrees:<jupyter_code>new_profiles = cl.make_radial_profile("degrees",cosmo=cosmo)
fig1, ax1 = cl.plot_profiles()<jupyter_output><empty_output><jupyter_text>3.2.2 User-defined binning The users may also provide their own binning, in user-defined units, to compute the transversal and cross shear profiles. The `make_bins` function is provided in `utils.py` and allow for various options. - e.g., generate 20 bins between 1 and 6 Mpc, linearly spaced.<jupyter_code>new_bins = make_bins(1, 6, nbins=20, method='evenwidth')

# Make the shear profile in this binning
new_profiles = cl.make_radial_profile("Mpc",
                                  bins=new_bins, cosmo=cosmo)

fig1, ax1 = cl.plot_profiles()<jupyter_output><empty_output><jupyter_text>- e.g., generate 20 bins between 1 and 6 Mpc, evenly spaced in log space.<jupyter_code>new_bins = make_bins(1, 6, nbins=20, method='evenlog10width')

new_profiles = cl.make_radial_profile("Mpc",
                                  bins=new_bins, cosmo=cosmo)
fig1, ax1 = cl.plot_profiles()
ax1.set_xscale('log')<jupyter_output><empty_output><jupyter_text>- e.g., generate 20 bins between 1 and 6 Mpc, each contaning the same number of galaxies<jupyter_code># First, convert the source separation table to Mpc
seps = u.convert_units(cl.galcat["theta"], "radians", "Mpc", redshift=cl.z, cosmo=cosmo)

new_bins = make_bins(1, 6, nbins=20, method='equaloccupation', source_seps=seps)
new_profiles = cl.make_radial_profile("Mpc",bins=new_bins, cosmo=cosmo)

print(f"number of galaxies in each bin: {list(cl.profile['n_src'])}")
fig1, ax1 = cl.plot_profiles()<jupyter_output><empty_output><jupyter_text>3.2.3 Other individual profile quantities may also be accessed<jupyter_code>plt.title('Average redshift in radial bins')
plt.errorbar(new_profiles['radius'], new_profiles['z'],
             new_profiles['z_err'], marker = 'o')
plt.axhline(cl.z, linestyle='dotted', color='r')
plt.text(1, cl.z*1.1, '$z_{cl}$', color='r')
plt.xlabel("Radius [Mpc]")
plt.ylabel('$\langle z\\rangle$')
plt.show()<jupyter_output><empty_output><jupyter_text>4. Focus on some options 4.1. `gal_ids_in_bins` option adds a `gal_id` field to the profile GCData. For each bin of the profile, this is filled with the list of galaxy IDs for the galaxies that have fallen in that bin.<jupyter_code>cl.make_radial_profile("Mpc", cosmo=cosmo, gal_ids_in_bins=True);
# Here the list of galaxy IDs that are in the first bin of the tangential shear profile
gal_list = cl.profile['gal_id'][0]
print(gal_list)<jupyter_output><empty_output><jupyter_text>4.2. User-defined naming schemeThe user may specify which columns to use from the `galcat` table to perform the binned average. If none is specified, the code looks for columns names `et` and `ex`. Below, we average in bins the columns`e_tan` and `e_cross` of `galcat` and store the results in the columns `g_tan` and `g_cross` of the `profile` table of the cluster object.<jupyter_code>cl.make_radial_profile("kpc", cosmo=cosmo, 
                       tan_component_in='e_tan', cross_component_in='e_cross',
                       tan_component_out='g_tan', cross_component_out='g_cross');
#cl.profile.pprint(max_width=-1)
cl.profile.show_in_notebook()<jupyter_output><empty_output><jupyter_text>The user may also define the name of the output table attribute. Below, we asked the binned profile to be saved into the `reduced_shear_profile` attribute<jupyter_code>cl.make_radial_profile("kpc", cosmo=cosmo, 
                       tan_component_in='e_tan', cross_component_in='e_cross',
                       tan_component_out='g_tan', cross_component_out='g_cross',
                       table_name='reduced_shear_profile');
#cl.reduced_shear_profile.pprint(max_width=-1)
cl.reduced_shear_profile.show_in_notebook()<jupyter_output><empty_output><jupyter_text>4.3 Compute a DeltaSigma profile instead of a shear profileThe `is_deltasigma` option allows the user to return a cross and tangential $\Delta\Sigma$ (excess surface density) value for each galaxy in the catalog, provided `galcat` contains the redshifts of the galaxies and provided a cosmology is passed to the function. The columns `DeltaSigma_tan` and `DeltaSigma_cross` are added to the `galcat` table.<jupyter_code>cl.compute_tangential_and_cross_components(shape_component1='e1', shape_component2='e2', 
                                           tan_component='DeltaSigma_tan', cross_component='DeltaSigma_cross',
                                            add=True, cosmo=cosmo, is_deltasigma=True)
cl.galcat.colnames<jupyter_output><empty_output><jupyter_text>Because this operation required a Cosmology, it was added to `galcat` metadata:<jupyter_code>cl.galcat.meta['cosmo']<jupyter_output><empty_output><jupyter_text>The binned profile is obtained, as before. Below, we use the values obtained from the previous step to compute the binned profile. The latter is saved in a new `DeltaSigma_profile` table of the GalaxyCluster object.<jupyter_code>'''
cl.make_radial_profile("Mpc", 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').pprint(max_width=-1)
'''
cl.make_radial_profile("Mpc", 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').show_in_notebook()
#cl.DeltaSigma_profile.pprint(max_width=-1)
cl.DeltaSigma_profile.show_in_notebook()
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 [Mpc]")
plt.ylabel('$\Delta\Sigma [M_\odot\; Mpc^{-2}]$')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1167173703346442, 'fraction_numerical': 0.015062699413816131, 'mean_word_length': 4.507968941561095, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 112, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '27', 'dir': 'jupyter-structured-clean-dedup', 'id': '246787', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 4624, 'n_tokens_neox': 4401, 'n_words': 1063, 'path': 'examples/demo_dataops_functionality.ipynb', 'repo_name': 'nicolahunfeld/CLMM', 'size': '13477'}