Skip to content

Commit

Permalink
Merge pull request #367 from LSSTDESC/improve_cls_tests
Browse files Browse the repository at this point in the history
Improve test coverage in cls.py and other files, start caching gsl build in Travis.
  • Loading branch information
philbull committed Apr 11, 2018
2 parents fbcafa8 + c24b50e commit e95fcd4
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ python:
cache:
apt: true
pip: true
directories:
- $TRAVIS_BUILD_DIR/gsl-2.4

sudo: required

Expand Down
11 changes: 8 additions & 3 deletions install-gsl.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#!/bin/sh
set -ex
wget ftp://ftp.gnu.org/gnu/gsl/gsl-2.4.tar.gz
tar -xzf gsl-2.4.tar.gz
cd gsl-2.4 && ./configure --prefix=/usr && make && sudo make install
if [ -d "gsl-2.4/gsl" ]
then
cd gsl-2.4 && sudo make install
else
wget ftp://ftp.gnu.org/gnu/gsl/gsl-2.4.tar.gz
tar -xzf gsl-2.4.tar.gz
cd gsl-2.4 && ./configure --prefix=/usr && make && sudo make install
fi
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib
export LD_RUN_PATH=$LD_RUN_PATH:/usr/lib
71 changes: 38 additions & 33 deletions pyccl/cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,58 +122,63 @@ def __init__(self, cosmo, tracer_type=None, has_rsd=False,
self.has_cltracer = True
self.cltracer, status = return_val

def get_internal_function(self,cosmo,function,a) :
def get_internal_function(self, cosmo, function, a):
"""
Method to evaluate any internal function of redshift for this tracer.
Args:
cosmo (:obj:`Cosmology`): Cosmology object.
function (:obj:`str`): Specifies which function to evaluate. Must be one of the types specified in the `function_types` dict in `cls.py`.
a (:obj: float or array-like): list of scale factors at which to evaluate the function.
specified. Must be one of the types specified in the
`tracer_types` dict in `cls.py`.
has_rsd (bool, optional): Flag for whether the tracer has a
redshift-space distortion term. Defaults to False.
has_magnification (bool, optional): Flag for whether the tracer has
a magnification term. Defaults to False.
has_intrinsic_alignment (bool, optional): Flag for whether the
tracer has an intrinsic alignment term. Defaults to False.
function (:obj:`str`): Specifies which function to evaluate. Must
be one of the types specified in the `pyccl.cls.function_types`
dictionary.
a (:obj: float or array-like): list of scale factors at which to
evaluate the function.
Returns:
Array of function values at the input scale factors.
"""
# Access ccl_cosmology object
cosmo_in=cosmo
cosmo=_cosmology_obj(cosmo)
cosmo_in = cosmo
cosmo = _cosmology_obj(cosmo)

# Access CCL_ClTracer objects
clt=self.cltracer
clt = self.cltracer

status=0
is_scalar=False
if isinstance(a,float) :
is_scalar=True
aarr=np.array([a])
na=1
elif isinstance(a,np.ndarray) :
aarr=a
na=a.size
else :
aarr=a
na=len(a)

farr,status=lib.clt_fa_vec(cosmo,self.cltracer,function_types[function],aarr,na,status)
check(status,cosmo_in)
if is_scalar :
# Check that specified function type exists
if function not in function_types.keys():
raise KeyError("Internal function type '%s' not recognized."
% function)

# Check input types
status = 0
is_scalar = False
if isinstance(a, float):
is_scalar = True
aarr = np.array([a])
na = 1
elif isinstance(a, np.ndarray):
aarr = a
na = a.size
else:
aarr = a
na = len(a)

# Evaluate function
farr, status = lib.clt_fa_vec(cosmo, self.cltracer,
function_types[function], aarr, na, status)
check(status, cosmo_in)
if is_scalar:
return farr[0]
else :
else:
return farr

def __del__(self):
"""Free memory associated with CCL_ClTracer object.
"""
if self.has_cltracer==True:
lib.cl_tracer_free(self.cltracer)
if hasattr(self, 'has_cltracer'):
if self.has_cltracer:
lib.cl_tracer_free(self.cltracer)


class ClTracerNumberCounts(ClTracer):
Expand Down
14 changes: 6 additions & 8 deletions pyccl/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def __setitem__(self, key, val):
"""
raise NotImplementedError("Parameters objects are immutable; create a "
"new Parameters() instance instead.")

"""
try:
# First check if the key already exists (otherwise the parameter
# would be silently added to the ccl_parameters class instance)
Expand All @@ -243,6 +243,7 @@ def __setitem__(self, key, val):
# Set value of parameter
setattr(self.parameters, key, val)
# TODO: Should update/replace CCL objects appropriately
"""

def __del__(self):
"""
Expand Down Expand Up @@ -297,9 +298,6 @@ def __init__(self,
mass_function='tinker10', emulator_neutrinos='strict'):
"""Creates a wrapper for ccl_cosmology.
TODO: enumerate transfer_function and
matter_power_spectrum options.
Args:
params (:obj:`Parameters`): Cosmological parameters object.
config (:obj:`ccl_configuration`, optional): Configuration for how
Expand Down Expand Up @@ -374,22 +372,22 @@ def __init__(self,

# Check validity of configuration-related arguments
if transfer_function not in transfer_function_types.keys():
raise ValueError( "'%s' is not a valid transfer_function type. "
raise KeyError( "'%s' is not a valid transfer_function type. "
"Available options are: %s" \
% (transfer_function,
transfer_function_types.keys()) )
if matter_power_spectrum not in matter_power_spectrum_types.keys():
raise ValueError( "'%s' is not a valid matter_power_spectrum "
raise KeyError( "'%s' is not a valid matter_power_spectrum "
"type. Available options are: %s" \
% (matter_power_spectrum,
matter_power_spectrum_types.keys()) )
if baryons_power_spectrum not in baryons_power_spectrum_types.keys():
raise ValueError( "'%s' is not a valid baryons_power_spectrum "
raise KeyError( "'%s' is not a valid baryons_power_spectrum "
"type. Available options are: %s" \
% (baryons_power_spectrum,
baryons_power_spectrum_types.keys()) )
if mass_function not in mass_function_types.keys():
raise ValueError( "'%s' is not a valid mass_function type. "
raise KeyError( "'%s' is not a valid mass_function type. "
"Available options are: %s" \
% (mass_function,
mass_function_types.keys()) )
Expand Down
11 changes: 11 additions & 0 deletions tests/ccl_test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,20 @@ def test_cosmology_init():

# Make sure error raised if incorrect type of Parameters object passed
assert_raises(TypeError, ccl.Cosmology, params=params.parameters)
assert_raises(TypeError, ccl.Cosmology, params="x")

# Make sure error raised if wrong config type passed
assert_raises(TypeError, ccl.Cosmology, params=params, config="string")

# Make sure error raised if invalid transfer/power spectrum etc. type passed
assert_raises(KeyError, ccl.Cosmology, params=params,
matter_power_spectrum='x')
assert_raises(KeyError, ccl.Cosmology, params=params,
transfer_function='x')
assert_raises(KeyError, ccl.Cosmology, params=params,
baryons_power_spectrum='x')
assert_raises(KeyError, ccl.Cosmology, params=params,
mass_function='x')


def test_cosmology_output():
Expand Down
80 changes: 70 additions & 10 deletions tests/ccl_test_pyccl_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ def check_background(cosmo):
assert_( all_finite(ccl.comoving_radial_distance(cosmo, a_lst)) )
assert_( all_finite(ccl.comoving_radial_distance(cosmo, a_arr)) )

# comoving_angular_distance
assert_( all_finite(ccl.comoving_angular_distance(cosmo, a_scl)) )
assert_( all_finite(ccl.comoving_angular_distance(cosmo, a_lst)) )
assert_( all_finite(ccl.comoving_angular_distance(cosmo, a_arr)) )

# h_over_h0
assert_( all_finite(ccl.h_over_h0(cosmo, a_scl)) )
assert_( all_finite(ccl.h_over_h0(cosmo, a_lst)) )
Expand All @@ -131,6 +136,16 @@ def check_background(cosmo):
assert_( all_finite(ccl.omega_x(cosmo, a_lst, 'matter')) )
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'matter')) )

# Fractional density of different types of fluid
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'dark_energy')) )
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'radiation')) )
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'curvature')) )
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'neutrinos_rel')) )
assert_( all_finite(ccl.omega_x(cosmo, a_arr, 'neutrinos_massive')) )

# Check that omega_x fails if invalid component type is passed
assert_raises(ValueError, ccl.omega_x, cosmo, a_scl, 'xyz')

# rho_crit_a
assert_( all_finite(ccl.rho_x(cosmo, a_scl, 'critical', is_comoving)) )
assert_( all_finite(ccl.rho_x(cosmo, a_lst, 'critical', is_comoving)) )
Expand All @@ -140,13 +155,13 @@ def check_background(cosmo):
assert_( all_finite(ccl.rho_x(cosmo, a_scl, 'matter', is_comoving)) )
assert_( all_finite(ccl.rho_x(cosmo, a_lst, 'matter', is_comoving)) )
assert_( all_finite(ccl.rho_x(cosmo, a_arr, 'matter', is_comoving)) )



def check_background_nu(cosmo):
"""
Check that background functions can be run and that the growth functions
exit gracefully in functions with massive neutrinos (not implemented yet).
"""

# Types of scale factor input (scalar, list, array)
a_scl = 0.5
a_lst = [0.2, 0.4, 0.6, 0.8, 1.]
Expand Down Expand Up @@ -279,11 +294,16 @@ def check_massfunc(cosmo):
assert_raises(TypeError, ccl.sigmaM, cosmo, mhalo_lst, a_arr)
assert_raises(TypeError, ccl.sigmaM, cosmo, mhalo_arr, a_arr)

# halo_bias
assert_( all_finite(ccl.halo_bias(cosmo, mhalo_scl, a)) )
assert_( all_finite(ccl.halo_bias(cosmo, mhalo_lst, a)) )
assert_( all_finite(ccl.halo_bias(cosmo, mhalo_arr, a)) )


def check_massfunc_nu(cosmo):
"""
Check that mass function and supporting functions can be run.
"""

z = 0.
z_arr = np.linspace(0., 2., 10)
a = 1.
Expand Down Expand Up @@ -317,6 +337,7 @@ def check_massfunc_nu(cosmo):
assert_raises(TypeError, ccl.sigmaM, cosmo, mhalo_lst, a_arr)
assert_raises(TypeError, ccl.sigmaM, cosmo, mhalo_arr, a_arr)


def check_neutrinos():
"""
Check that neutrino-related functions can be run.
Expand Down Expand Up @@ -368,6 +389,7 @@ def pz1(z_ph, z_s, args):
# PhotoZFunction classes
PZ1 = ccl.PhotoZFunction(pz1)
PZ2 = ccl.PhotoZFunction(pz2)
PZ3 = ccl.PhotoZGaussian(sigma_z0=0.1)

# bias_clustering
assert_( all_finite(ccl.bias_clustering(cosmo, a_scl)) )
Expand Down Expand Up @@ -599,6 +621,27 @@ def check_cls_nu(cosmo):
assert_( all_finite(ccl.angular_cl(cosmo, nc1, lens1, ell_arr)) )
assert_( all_finite(ccl.angular_cl(cosmo, nc1, lens2, ell_arr)) )

# Check get_internal_function()
a_scl = 0.5
a_lst = [0.2, 0.4, 0.6, 0.8, 1.]
a_arr = np.linspace(0.2, 1., 5)
assert_( all_finite(nc1.get_internal_function(cosmo, 'dndz', a_scl)) )
assert_( all_finite(nc1.get_internal_function(cosmo, 'dndz', a_lst)) )
assert_( all_finite(nc1.get_internal_function(cosmo, 'dndz', a_arr)) )

# Check that invalid options raise errors
assert_raises(KeyError, nc1.get_internal_function, cosmo, 'x', a_arr)
assert_raises(ValueError, ccl.ClTracerNumberCounts, cosmo, True, True,
n=(z,n), bias=(z,b))
assert_raises(KeyError, ccl.ClTracer, cosmo, 'x', True, True,
n=(z,n), bias=(z,b))
assert_raises(ValueError, ccl.ClTracerLensing, cosmo,
has_intrinsic_alignment=True, n=(z,n), bias_ia=(z,n))
assert_no_warnings(ccl.cls._cltracer_obj, nc1)
assert_no_warnings(ccl.cls._cltracer_obj, nc1.cltracer)
assert_raises(TypeError, ccl.cls._cltracer_obj, None)


def check_corr(cosmo):

# Number density input
Expand All @@ -609,13 +652,30 @@ def check_corr(cosmo):
lens1 = ccl.ClTracerLensing(cosmo, False, n=n, z=z)
lens2 = ccl.ClTracerLensing(cosmo, True, n=(z,n), bias_ia=(z,n), f_red=(z,n))

ells=np.arange(3000)
cls=ccl.angular_cl(cosmo,lens1,lens2,ells)

t=np.logspace(-2,np.log10(5.),20) #degrees
corrfunc=ccl.correlation(cosmo,ells,cls,t,corr_type='L+',method='FFTLog')
assert_( all_finite(corrfunc))

ells = np.arange(3000)
cls = ccl.angular_cl(cosmo, lens1, lens2, ells)

t_arr = np.logspace(-2., np.log10(5.), 20) # degrees
t_lst = [t for t in t_arr]
t_scl = 2.

# Make sure correlation functions work for valid inputs
corr1 = ccl.correlation(cosmo, ells, cls, t_arr, corr_type='L+',
method='FFTLog')
corr2 = ccl.correlation(cosmo, ells, cls, t_lst, corr_type='L+',
method='FFTLog')
corr3 = ccl.correlation(cosmo, ells, cls, t_scl, corr_type='L+',
method='FFTLog')
assert_( all_finite(corr1))
assert_( all_finite(corr2))
assert_( all_finite(corr3))

# Check that exceptions are raised for invalid input
assert_raises(KeyError, ccl.correlation, cosmo, ells, cls, t_arr,
corr_type='xx', method='FFTLog')
assert_raises(KeyError, ccl.correlation, cosmo, ells, cls, t_arr,
corr_type='L+', method='xx')


def test_valid_transfer_combos():
"""
Expand Down

0 comments on commit e95fcd4

Please sign in to comment.