Skip to content

Commit

Permalink
Warnings verbosity (#1213)
Browse files Browse the repository at this point in the history
* Implemented control over CCL warning verbosity
  • Loading branch information
damonge authored Dec 4, 2024
1 parent d3c0055 commit 5273ca6
Show file tree
Hide file tree
Showing 20 changed files with 142 additions and 46 deletions.
4 changes: 1 addition & 3 deletions benchmarks/test_ptpk.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import pyccl as ccl
import pyccl.nl_pt as pt
import pytest
from contextlib import nullcontext

# Set cosmology
COSMO = ccl.Cosmology(Omega_c=0.25, Omega_b=0.05,
Expand Down Expand Up @@ -50,8 +49,7 @@ def test_pt_pk(comb):
ptt1 = ptt[t1]
ptt2 = ptt[t2]

with pytest.warns(ccl.CCLWarning) if comb[1] == "gi" else nullcontext():
pk = ptc.get_biased_pk2d(ptt1, tracer2=ptt2, return_ia_bb=return_bb)
pk = ptc.get_biased_pk2d(ptt1, tracer2=ptt2, return_ia_bb=return_bb)

for iz, z in enumerate(zs):
a = 1./(1+z)
Expand Down
6 changes: 3 additions & 3 deletions pyccl/_nonlimber_FKEM.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
(https://jila.colorado.edu/~ajsh/FFTLog/fftlog.pdf)
to compute integrals over spherical bessel functions
"""
import warnings
import numpy as np
from . import lib, check
from .pyutils import integ_types
from scipy.interpolate import interp1d
from pyccl.pyutils import _fftlog_transform_general
import pyccl as ccl
from . import CCLWarning
from . import CCLWarning, warnings


def _get_general_params(b):
Expand Down Expand Up @@ -66,7 +65,8 @@ def _nonlimber_FKEM(
warnings.warn(
"p_of_k_a and p_of_k_a_lin must be of the same "
"type: a str in cosmo or a Pk2D object. "
"Defaulting to Limber calculation. ", CCLWarning)
"Defaulting to Limber calculation. ",
category=CCLWarning, importance='high')
return -1, np.array([]), status

psp_lin = cosmo.parse_pk2d(p_of_k_a_lin, is_linear=True)
Expand Down
12 changes: 6 additions & 6 deletions pyccl/baryons/baccoemu_baryons.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import numpy as np
from copy import deepcopy
from warnings import warn

from .. import Pk2D
from .. import Pk2D, CCLDeprecationWarning
from . import Baryons


Expand Down Expand Up @@ -216,8 +215,9 @@ class BaccoemuBaryons(BaryonsBaccoemu):

def __init__(self, *args, **kwargs):
"""This throws a deprecation warning on initialization."""
warn(f"Class {self.__class__.__name__} will be deprecated. " +
f"Please use {BaryonsBaccoemu.__name__} instead.",
DeprecationWarning, stacklevel=2)
from .. import warnings
warnings.warn(f"Class {self.__class__.__name__} will be deprecated. " +
f"Please use {BaryonsBaccoemu.__name__} instead.",
CCLDeprecationWarning, stacklevel=2,
importance='low')
super().__init__(*args, **kwargs)
pass
2 changes: 1 addition & 1 deletion pyccl/ccl.i
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ from .errors import CCLError
%init %{
import_array();
// Tell CCL to not print to stdout/stderr for debugging.
ccl_set_debug_policy(CCL_DEBUG_MODE_ON);
ccl_set_debug_policy(CCL_DEBUG_MODE_OFF);
%}

// Automatically document arguments and output types of all functions
Expand Down
11 changes: 4 additions & 7 deletions pyccl/cells.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
__all__ = ("angular_cl",)

import warnings

import numpy as np

from . import DEFAULT_POWER_SPECTRUM, CCLWarning, check, lib
from . import DEFAULT_POWER_SPECTRUM, CCLWarning, check, lib, warnings
from .pyutils import integ_types
from ._nonlimber_FKEM import _nonlimber_FKEM

Expand Down Expand Up @@ -56,15 +54,15 @@ def angular_cl(
the kernels are defined will be used (capped to 1E-6 Mpc if this
value is zero). Users are encouraged to experiment with this parameter
and ``fkem_Nchi`` to ensure the robustness of the output
:math:`C_\\ell`s.
:math:`C_\\ell` s.
fkem_Nchi: Number of values of the comoving distance over which `FKEM`
will interpolate the radial kernels. If ``None`` the smallest number
over which the kernels are currently sampled will be used. Note that
`FKEM` will use a logarithmic sampling for distances between
``fkem_chi_min`` and the maximum distance over which the tracers
are defined. Users are encouraged to experiment with this parameter
and ``fkem_chi_min`` to ensure the robustness of the output
:math:`C_\\ell`s.
:math:`C_\\ell` s.
p_of_k_a_lin (:class:`~pyccl.pk2d.Pk2D`, :obj:`str` or :obj:`None`):
3D linear Power spectrum to project, for special use in
PT calculations using the FKEM non-limber integration technique.
Expand All @@ -84,8 +82,7 @@ def angular_cl(
warnings.warn(
"CCL does not properly use the hyperspherical Bessel functions "
"when computing angular power spectra in non-flat cosmologies!",
category=CCLWarning,
)
category=CCLWarning, importance='low')

if limber_integration_method not in integ_types:
raise ValueError(
Expand Down
52 changes: 48 additions & 4 deletions pyccl/errors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
__all__ = ("CCLError", "CCLWarning", "CCLDeprecationWarning",)
__all__ = ("CCLError", "CCLWarning", "CCLDeprecationWarning",
"warnings", "update_warning_verbosity")

import warnings
import warnings as warnings_builtin


_warning_importance = {'high': 10, 'low': 1}
_verbosity_thresholds = {'none': 100, 'low': 10, 'high': 1}


class warnings:
_CCL_WARN_THRESHOLD = 10 # Equivalent to "low" verbosity

def warn(*args, **kwargs):
category = kwargs.get('category')
importance = _warning_importance[kwargs.pop('importance', 'low')]

if ((category in (CCLWarning, CCLDeprecationWarning)) and
(importance < warnings._CCL_WARN_THRESHOLD)):
return

warnings_builtin.warn(*args, **kwargs)


def update_warning_verbosity(verbosity):
""" Update the level of verbosity of the CCL warnings. Available
levels are "none", "low", and "high". More warning messages will
be output for higher verbosity levels. If "none", no CCL-level
warnings will be shown. The default verbosity is "low". Note that
unless the verbosity level is "high", all C-level warnings will
be omitted.
Args:
verbosity (str): one of ``'none'``, ``'low'`` or ``'high'``.
"""

if not (verbosity in ['none', 'low', 'high']):
raise KeyError("`verbosity` must be one of {'none', 'low', 'high'}")
warnings._CCL_WARN_THRESHOLD = _verbosity_thresholds[verbosity]

# Remove C-level warnings
from . import debug_mode

if verbosity == 'high':
debug_mode(True)
else:
debug_mode(False)


class CCLError(RuntimeError):
Expand Down Expand Up @@ -40,8 +84,8 @@ def __hash__(self):

@classmethod
def enable(cls):
warnings.simplefilter("always")
warnings_builtin.simplefilter("always")

@classmethod
def disable(cls):
warnings.filterwarnings(action="ignore", category=cls)
warnings_builtin.filterwarnings(action="ignore", category=cls)
7 changes: 3 additions & 4 deletions pyccl/halos/pk_4pt.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
"halomod_Tk3D_SSC_linear_bias", "halomod_Tk3D_SSC",
"halomod_Tk3D_cNG")

import warnings

import numpy as np
import scipy

from .. import CCLWarning, Tk3D, Pk2D
from .. import CCLWarning, warnings, Tk3D, Pk2D
from . import HaloProfileNFW, Profile2pt


Expand Down Expand Up @@ -607,7 +605,8 @@ def _logged_output(*arrs, log):
is_negative = [(arr <= 0).any() for arr in arrs]
if any(is_negative):
warnings.warn("Some values were non-positive. "
"Interpolating linearly.", CCLWarning)
"Interpolating linearly.",
category=CCLWarning, importance='high')
return *arrs, False
return *[np.log(arr) for arr in arrs], log

Expand Down
6 changes: 3 additions & 3 deletions pyccl/halos/profiles/ia.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import warnings
import pyccl
import numpy as np
from .hod import HaloProfileHOD
from ... import warnings


__all__ = ("SatelliteShearHOD",)
Expand Down Expand Up @@ -100,12 +100,12 @@ def __init__(self, *, mass_def, concentration, a1h=0.001, b=-2,
lmax = 12
warnings.warn(
'Maximum l provided too high. Using lmax=12.',
category=pyccl.CCLWarning)
category=pyccl.CCLWarning, importance='high')
elif lmax < 2:
lmax = 2
warnings.warn(
'Maximum l provided too low. Using lmax=2.',
category=pyccl.CCLWarning)
category=pyccl.CCLWarning, importance='high')
self.a1h = a1h
self.b = b
if integration_method not in ['FFTLog',
Expand Down
6 changes: 2 additions & 4 deletions pyccl/nl_pt/ept.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
__all__ = ("EulerianPTCalculator",)

import warnings

import numpy as np

from .. import (CCLAutoRepr, CCLError, CCLWarning, Pk2D,
get_pk_spline_a, unlock_instance)
get_pk_spline_a, unlock_instance, warnings)


# All valid Pk pair labels and their aliases
Expand Down Expand Up @@ -375,7 +373,7 @@ def _get_pgi(self, trg, tri):
warnings.warn(
"EulerianPTCalculators assume linear galaxy bias "
"when computing galaxy-IA cross-correlations.",
category=CCLWarning)
category=CCLWarning, importance='low')
c1 = tri.c1(self.z_s)
c2 = tri.c2(self.z_s)
cd = tri.cdelta(self.z_s)
Expand Down
10 changes: 5 additions & 5 deletions pyccl/pk2d.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
__all__ = ("Pk2D", "parse_pk2d", "parse_pk",)

import warnings

import numpy as np

from . import (
CCLObject, DEFAULT_POWER_SPECTRUM, UnlockInstance, check, get_pk_spline_a,
get_pk_spline_lk, lib, unlock_instance)
from . import CCLWarning, CCLError
from . import CCLWarning, CCLError, warnings
from .pyutils import _get_spline1d_arrays, _get_spline2d_arrays


Expand Down Expand Up @@ -375,7 +373,8 @@ def _get_binary_operator_arrays(self, other):
"Operands defined over different ranges. "
"The result will be interpolated and clipped to "
f"{self.psp.lkmin} <= log k <= {self.psp.lkmax} and "
f"{self.psp.amin} <= a <= {self.psp.amax}.", CCLWarning)
f"{self.psp.amin} <= a <= {self.psp.amax}.",
category=CCLWarning, importance='low')
pk_arr_b = other(np.exp(lk_arr_a), a_arr_a)

return a_arr_a, lk_arr_a, pk_arr_a, pk_arr_b
Expand Down Expand Up @@ -449,7 +448,8 @@ def __pow__(self, exponent):
if np.any(pk_arr_a < 0) and exponent % 1 != 0:
warnings.warn(
"Taking a non-positive Pk2D object to a non-integer "
"power may lead to unexpected results", CCLWarning)
"power may lead to unexpected results",
category=CCLWarning, importance='high')

pk_arr_new = pk_arr_a**exponent

Expand Down
40 changes: 40 additions & 0 deletions pyccl/tests/test_cclerror.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import pyccl
import pytest
import numpy as np
import warnings


def test_cclerror_repr():
Expand Down Expand Up @@ -62,3 +65,40 @@ def test_ccl_deprecationwarning_switch():

# switch back on
pyccl.CCLDeprecationWarning.enable()


def test_ccl_warning_verbosity_error():
with pytest.raises(KeyError):
pyccl.update_warning_verbosity("hihg")


def test_ccl_warning_verbosity():

# The code below will trigger an unimportant warning
# about the N(z) sampling

# Switch to high verbosity
pyccl.update_warning_verbosity("high")
cosmo = pyccl.CosmologyVanillaLCDM()
numz = 32
zm = 0.7
sz = 0.01
z = np.linspace(0, 1.5, numz)
nz = np.exp(-0.5*((z-zm)/sz)**2)
with pytest.warns(pyccl.CCLWarning):
pyccl.WeakLensingTracer(cosmo, dndz=(z, nz))

# Now test that no warning is triggered if back to low verbosity
pyccl.update_warning_verbosity("low")

with warnings.catch_warnings():
warnings.simplefilter("error")
pyccl.WeakLensingTracer(cosmo, dndz=(z, nz))


def test_ccl_deprecation_warning():
# Switch to high verbosity to catch it
pyccl.update_warning_verbosity("high")
with pytest.warns(pyccl.CCLDeprecationWarning):
pyccl.baryons.BaccoemuBaryons()
pyccl.update_warning_verbosity("low")
1 change: 0 additions & 1 deletion pyccl/tests/test_cosmology_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import numpy as np
import pytest
import pyccl as ccl
# import warnings # TODO: Uncomment for CCLv3.


def test_parameters_lcdmDefaultParams():
Expand Down
6 changes: 6 additions & 0 deletions pyccl/tests/test_ept_power.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ def test_ept_get_pk2d_smoke(tr1, tr2, bb, sub_lowk):
sub_lowk=sub_lowk, cosmo=COSMO)

will_warn = set([tr1, tr2]) == set(["TG", "TI"])
ccl.update_warning_verbosity('high')
with pytest.warns(ccl.CCLWarning) if will_warn else nullcontext():
pk = ptc.get_biased_pk2d(TRS[tr1], tracer2=t2, return_ia_bb=bb)
ccl.update_warning_verbosity('low')
assert isinstance(pk, ccl.Pk2D)


Expand Down Expand Up @@ -118,8 +120,10 @@ def get_tr(tn):

is_nl = tn1 in ["b2", "bs", "bk2", "b3nl"]
is_g = tn2 in ["c1", "c2", "cdelta"]
ccl.update_warning_verbosity('high')
with pytest.warns(ccl.CCLWarning) if is_nl and is_g else nullcontext():
pk2 = ptc.get_biased_pk2d(t1, tracer2=t2)
ccl.update_warning_verbosity('low')
if pk1 is None:
assert pk2(0.5, 1.0, cosmo=COSMO) == 0.0
else:
Expand Down Expand Up @@ -237,11 +241,13 @@ def test_ept_calculator_raises():
ptc.get_pk2d_template('b1:b3')

# Warning when computing IA-gal correlation
ccl.update_warning_verbosity('high')
with pytest.warns(ccl.CCLWarning):
ptc = ccl.nl_pt.EulerianPTCalculator(with_NC=True, with_IA=True,
cosmo=COSMO)
tg = ccl.nl_pt.PTNumberCountsTracer(b1=1.0, b2=1.0)
ptc.get_biased_pk2d(tg, tracer2=TRS['TI'])
ccl.update_warning_verbosity('low')


def test_ept_template_swap():
Expand Down
Loading

0 comments on commit 5273ca6

Please sign in to comment.