Skip to content

Commit e95f0e0

Browse files
m-aguenahsinfan1996
andcommitted
Issue/628/rad min max in ensemble (#631)
* add radius min/max in ensamble and validation for its consistency * pass rmin/max to ClusterEnsemble.stacked_data * Update version to 1.13.0 --------- Co-authored-by: Hsin Fan <[email protected]>
1 parent 4068b53 commit e95f0e0

12 files changed

+210
-44
lines changed

clmm/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@
2626
)
2727
from . import support
2828

29-
__version__ = "1.12.5"
29+
__version__ = "1.13.0"

clmm/clusterensemble.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from .gcdata import GCData
99
from .dataops import make_stacked_radial_profile
10+
from .utils import DiffArray
1011

1112

1213
class ClusterEnsemble:
@@ -27,7 +28,7 @@ class ClusterEnsemble:
2728
2829
* "tan_sc" : tangential component computed with sample covariance
2930
* "cross_sc" : cross component computed with sample covariance
30-
* "tan_jk" : tangential component computed with bootstrap
31+
* "tan_bs" : tangential component computed with bootstrap
3132
* "cross_bs" : cross component computed with bootstrap
3233
* "tan_jk" : tangential component computed with jackknife
3334
* "cross_jk" : cross component computed with jackknife
@@ -46,7 +47,7 @@ def __init__(self, unique_id, gc_list=None, **kwargs):
4647
else:
4748
raise TypeError(f"unique_id incorrect type: {type(unique_id)}")
4849
self.unique_id = unique_id
49-
self.data = GCData(meta={"bin_units": None})
50+
self.data = GCData(meta={"bin_units": None, "radius_min": None, "radius_max": None})
5051
if gc_list is not None:
5152
self._add_values(gc_list, **kwargs)
5253
self.stacked_data = None
@@ -198,6 +199,9 @@ def add_individual_radial_profile(
198199
"""
199200
cl_bin_units = profile_table.meta.get("bin_units", None)
200201
self.data.update_info_ext_valid("bin_units", self.data, cl_bin_units, overwrite=False)
202+
for col in ("radius_min", "radius_max"):
203+
value = DiffArray(profile_table[col])
204+
self.data.update_info_ext_valid(col, self.data, value, overwrite=False)
201205

202206
cl_cosmo = profile_table.meta.get("cosmo", None)
203207
self.data.update_info_ext_valid("cosmo", self.data, cl_cosmo, overwrite=False)
@@ -248,9 +252,14 @@ def make_stacked_radial_profile(self, tan_component="gt", cross_component="gx",
248252
[self.data[tan_component], self.data[cross_component]],
249253
)
250254
self.stacked_data = GCData(
251-
[radius, *components],
252-
meta=self.data.meta,
253-
names=("radius", tan_component, cross_component),
255+
[
256+
self.data.meta["radius_min"].value,
257+
self.data.meta["radius_max"].value,
258+
radius,
259+
*components,
260+
],
261+
meta={k: v for k, v in self.data.meta.items() if k not in ("radius_min", "radius_max")},
262+
names=("radius_min", "radius_max", "radius", tan_component, cross_component),
254263
)
255264

256265
def compute_sample_covariance(self, tan_component="gt", cross_component="gx"):

clmm/dataops/__init__.py

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
"""Functions to compute polar/azimuthal averages in radial bins"""
2-
1+
"""Data operation for polar/azimuthal averages in radial bins and weights"""
32
import warnings
43
import numpy as np
5-
import scipy
64
from astropy.coordinates import SkyCoord
75
from astropy import units as u
86
from ..gcdata import GCData
@@ -17,11 +15,7 @@
1715
_validate_is_deltasigma_sigma_c,
1816
_validate_coordinate_system,
1917
)
20-
from ..redshift import (
21-
_integ_pzfuncs,
22-
compute_for_good_redshifts,
23-
)
24-
from ..theory import compute_critical_surface_density_eff
18+
from ..redshift import _integ_pzfuncs
2519

2620

2721
def compute_tangential_and_cross_components(

clmm/gcdata.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def update_info_ext_valid(self, key, gcdata, ext_value, overwrite=False):
150150
key: str
151151
Name of key to compare and update.
152152
gcdata: GCData
153-
Table to check if same cosmology.
153+
Table to check if same cosmology and ensemble bins.
154154
ext_value:
155155
Value to be compared to.
156156
overwrite: bool

clmm/utils/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
_validate_dec,
4242
_validate_is_deltasigma_sigma_c,
4343
_validate_coordinate_system,
44+
DiffArray,
4445
)
4546

4647
from .units import (

clmm/utils/validation.py

+34-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ def _validate_is_deltasigma_sigma_c(is_deltasigma, sigma_c):
226226
if not is_deltasigma and sigma_c is not None:
227227
raise TypeError(f"sigma_c (={sigma_c}) must be None when is_deltasigma=False")
228228

229-
230229
def _validate_coordinate_system(loc, coordinate_system, valid_type):
231230
r"""Validate the coordinate system.
232231
@@ -245,3 +244,37 @@ def _validate_coordinate_system(loc, coordinate_system, valid_type):
245244
validate_argument(loc, coordinate_system, valid_type)
246245
if loc[coordinate_system] not in ["celestial", "euclidean"]:
247246
raise ValueError(f"{coordinate_system} must be 'celestial' or 'euclidean'.")
247+
248+
class DiffArray:
249+
"""Array where arr1==arr2 is actually all(arr1==arr)"""
250+
251+
def __init__(self, array):
252+
self.value = np.array(array)
253+
254+
def __eq__(self, other):
255+
# pylint: disable=unidiomatic-typecheck
256+
if type(other) != type(self):
257+
return False
258+
if self.value.size != other.value.size:
259+
return False
260+
return (self.value == other.value).all()
261+
262+
def __repr__(self):
263+
out = str(self.value)
264+
if self.value.size > 4:
265+
out = self._get_lim_str(out) + " ... " + self._get_lim_str(out[::-1])[::-1]
266+
return out
267+
268+
def _get_lim_str(self, out):
269+
# pylint: disable=undefined-loop-variable
270+
# get count starting point
271+
for init_index, char in enumerate(out):
272+
if all(char != _char for _char in "[]() "):
273+
break
274+
# get str
275+
sep = 0
276+
for i, char in enumerate(out[init_index + 1 :]):
277+
sep += int(char == " " and out[i + init_index] != " ")
278+
if sep == 2:
279+
break
280+
return out[: i + init_index + 1]

examples/demo_mock_ensemble.ipynb

+48-1
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,43 @@
320320
},
321321
{
322322
"cell_type": "markdown",
323+
"id": "84bd786f",
324+
"metadata": {},
325+
"source": [
326+
"The individual cluster data and profiles are stored at the `.data` table of the `ClusterEnsemble`:"
327+
]
328+
},
329+
{
330+
"cell_type": "code",
331+
"execution_count": null,
332+
"id": "864f3acb",
333+
"metadata": {},
334+
"outputs": [],
335+
"source": [
336+
"clusterensemble.data[:3]"
337+
]
338+
},
339+
{
340+
"cell_type": "markdown",
341+
"id": "6ea533b0",
342+
"metadata": {},
343+
"source": [
344+
"The edges of the radial bins, their units, and the cosmology are stored on the metadata of this table:"
345+
]
346+
},
347+
{
348+
"cell_type": "code",
349+
"execution_count": null,
350+
"id": "39723fb1",
351+
"metadata": {},
352+
"outputs": [],
353+
"source": [
354+
"clusterensemble.data.meta"
355+
]
356+
},
357+
{
358+
"cell_type": "markdown",
359+
"id": "99e3fe18",
323360
"metadata": {},
324361
"source": [
325362
"## Stacked profile of the cluster ensemble\n",
@@ -335,6 +372,16 @@
335372
"clusterensemble.make_stacked_radial_profile(tan_component=\"DS_t\", cross_component=\"DS_x\")"
336373
]
337374
},
375+
{
376+
"cell_type": "code",
377+
"execution_count": null,
378+
"id": "98b9fa63",
379+
"metadata": {},
380+
"outputs": [],
381+
"source": [
382+
"clusterensemble.stacked_data"
383+
]
384+
},
338385
{
339386
"cell_type": "markdown",
340387
"metadata": {},
@@ -601,7 +648,7 @@
601648
"name": "python",
602649
"nbconvert_exporter": "python",
603650
"pygments_lexer": "ipython3",
604-
"version": "3.6.9"
651+
"version": "3.10.8"
605652
}
606653
},
607654
"nbformat": 4,

examples/demo_mock_ensemble_realistic.ipynb

+49-3
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
"source": [
176176
"Ncm.cfg_init()\n",
177177
"# cosmo_nc = Nc.HICosmoDEXcdm()\n",
178-
"cosmo_nc = Nc.HICosmo.new_from_name(Nc.HICosmo, \"NcHICosmoDECpl{'massnu-length':<1>}\")\n",
178+
"cosmo_nc = Nc.HICosmoDECpl(massnu_length=1)\n",
179179
"cosmo_nc.omega_x2omega_k()\n",
180180
"cosmo_nc.param_set_by_name(\"w0\", -1.0)\n",
181181
"cosmo_nc.param_set_by_name(\"w1\", 0.0)\n",
@@ -201,7 +201,7 @@
201201
"\n",
202202
"dist = Nc.Distance.new(2.0)\n",
203203
"dist.prepare_if_needed(cosmo_nc)\n",
204-
"tf = Nc.TransferFunc.new_from_name(\"NcTransferFuncEH\")\n",
204+
"tf = Nc.TransferFuncEH()\n",
205205
"\n",
206206
"psml = Nc.PowspecMLTransfer.new(tf)\n",
207207
"psml.require_kmin(1.0e-6)\n",
@@ -903,6 +903,42 @@
903903
" )"
904904
]
905905
},
906+
{
907+
"cell_type": "markdown",
908+
"id": "b5e17ee0",
909+
"metadata": {},
910+
"source": [
911+
"The individual cluster data and profiles are stored at the `.data` table of the `ClusterEnsemble`:"
912+
]
913+
},
914+
{
915+
"cell_type": "code",
916+
"execution_count": null,
917+
"id": "4a970edb",
918+
"metadata": {},
919+
"outputs": [],
920+
"source": [
921+
"clusterensemble.data[:3]"
922+
]
923+
},
924+
{
925+
"cell_type": "markdown",
926+
"id": "7320e899",
927+
"metadata": {},
928+
"source": [
929+
"The edges of the radial bins, their units, and the cosmology are stored on the metadata of this table:"
930+
]
931+
},
932+
{
933+
"cell_type": "code",
934+
"execution_count": null,
935+
"id": "f9ea8436",
936+
"metadata": {},
937+
"outputs": [],
938+
"source": [
939+
"clusterensemble.data.meta"
940+
]
941+
},
906942
{
907943
"cell_type": "markdown",
908944
"id": "9091de7c",
@@ -922,6 +958,16 @@
922958
"clusterensemble.make_stacked_radial_profile(tan_component=\"DS_t\", cross_component=\"DS_x\")"
923959
]
924960
},
961+
{
962+
"cell_type": "code",
963+
"execution_count": null,
964+
"id": "e4125570",
965+
"metadata": {},
966+
"outputs": [],
967+
"source": [
968+
"clusterensemble.stacked_data"
969+
]
970+
},
925971
{
926972
"cell_type": "markdown",
927973
"id": "771c1382",
@@ -1193,7 +1239,7 @@
11931239
"name": "python",
11941240
"nbconvert_exporter": "python",
11951241
"pygments_lexer": "ipython3",
1196-
"version": "3.9.0"
1242+
"version": "3.11.9"
11971243
}
11981244
},
11991245
"nbformat": 4,

tests/test_dataops.py

+7
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ def test_compute_lensing_angles_flatsky():
145145
ra_l, dec_l, ra_s, dec_s, coordinate_system="celestial"
146146
)
147147

148+
assert_allclose(
149+
da._compute_lensing_angles_flatsky(-180, dec_l, np.array([180.1, 179.7]), dec_s),
150+
[[0.0012916551296819666, 0.003424250083245557], [-2.570568636904587, 0.31079754672944354]],
151+
TOLERANCE["rtol"],
152+
err_msg="Failure when ra_l and ra_s are the same but one is defined negative",
153+
)
154+
148155
assert_allclose(
149156
thetas_celestial,
150157
thetas_euclidean,

tests/test_mockdata.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,17 @@ def test_shapenoise():
264264

265265
# Verify that the shape noise is Gaussian around 0 (for the very small shear here)
266266
sigma = 0.25
267-
data = mock.generate_galaxy_catalog(10**12.0, 0.3, 4, cosmo, 0.8, ngals=50000, shapenoise=sigma)
267+
data = mock.generate_galaxy_catalog(
268+
10**12.0, 0.3, 4, cosmo, 0.8, ngals=50000, shapenoise=sigma
269+
)
268270
# Check that there are no galaxies with |e|>1
269271
assert_equal(np.count_nonzero((data["e1"] > 1) | (data["e1"] < -1)), 0)
270272
assert_equal(np.count_nonzero((data["e2"] > 1) | (data["e2"] < -1)), 0)
271273
# Check that shape noise is Guassian with correct std dev
272274
bins = np.arange(-1, 1.1, 0.1)
273-
gauss = 5000 * np.exp(-0.5 * (bins[:-1] + 0.05) ** 2 / sigma**2) / (sigma * np.sqrt(2 * np.pi))
275+
gauss = (
276+
5000 * np.exp(-0.5 * (bins[:-1] + 0.05) ** 2 / sigma**2) / (sigma * np.sqrt(2 * np.pi))
277+
)
274278
assert_allclose(np.histogram(data["e1"], bins=bins)[0], gauss, atol=50, rtol=0.05)
275279
assert_allclose(np.histogram(data["e2"], bins=bins)[0], gauss, atol=50, rtol=0.05)
276280

0 commit comments

Comments
 (0)