Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warnings verbosity #1213

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Start reviewing here.


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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the deprecation warnings covered by the verbosity filter as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, but let me check

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they are not. Do you think they should?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My gut feeling is yes - they're good to know while building a model but you probably don't want them in an MCMC log.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they mute them and CCL's deprecation cycle completes, their MCMC will simply stop working, and they won't be able to figure out why. I don't think it's a good idea muting those.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, but deprecation warnings have to do with CCL functionality whereas CCLWarnings mostly have to do with numerical stability, so they represent different things. At the very least I'd add a different flag to separate the verbosity level for deprecation-specific warnings. BTW now that v3 is out, is CCLDeprecationWarning used at all?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and also, deprecation warnings should be on my default, contrary to other, informative-only warnings, because that's how you tell people that the API will change.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CCLDeprecationWarnings are not used right now. I'll leave them there for the future in any case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As developers we can decide what the priority of the different warnings are. If we decide that specific deprecation warnings are sufficiently important, we can just tag them as "high", and they'll go through the filter.

@tilmantroester I've now added the CCLDeprecationWarnings to the list of warnings that can be suppressed if desired.

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
Loading