Python wrapper

baudren edited this page Mar 13, 2014 · 2 revisions

Inside the directory python/, accessible from the root directory of CLASS, lives a Python wrapper written in Cython. This page will detail how to install it, and use it. It will also contain instructions on how to use the testing suite that make use of the wrapper, which might help you debugging a modification of CLASS.

Note that, beyond the installation part, you do not need to understand how the wrapper works if you intend to use CLASS only through the parameter extraction code Monte Python. This page is only here to help people wanting to use the Python wrapper to other ends.

Installation of the wrapper

First, you must do a step more than for running CLASS traditionally. If you simply did

class]$ make class

when compiling, you did not create the library (libclass.a file). You should do rather a

class]$ make

Now, go to the python subfolder, and run the installation script:

class]$ cd python/
python]$ python setup.py install --user

You might get some warnings about error messages, which are harmless. As long as you do not get any errors here, you are good to proceed. To check that the installation truly succeeded, simply run:

python]$ python -c 'from classy import Class'

If it succeeds (and does not return any error), the Python wrapper is installed.

Basic Usage

As a first note on the names, writing a wrapper for a code called CLASS in an object-oriented framework required some thought. CLASS in all-caps designate the code in C, class is the standard keyword for classes in Python, and Class is the Python class that wraps CLASS. There you go.

The wrapper is designed to follow as closely as possible the behaviour of the underlying code. The main differences are the following:

  • there is no file something.ini to read from, instead, you will use a Python dictionary.
  • the main routine of CLASS is actually separated into two methods of the class Class: compute and struct_cleanup. The former doing all the structure_init() calls, and the latter all the structure_free() calls.

The basic flow to call CLASS through this interface, in a python script is the following

  1. import the module
  2. Create an instance of Class
  3. Define a dict holding the parameters you want to test
  4. Set the parameters to the Class instance
  5. Initialise the structures with the compute method
  6. Do stuff with what is inside (access the C_l, the power spectrum, thermodynamics quantities, what have you)
  7. Free the structures with the struct_cleanup method
  8. Delete the parameters inside the instance, with the empty method.
  9. Restart from step 3) with another set of parameters.

Here follows an example of such a python script. Create a file temp.py, and copy paste the following lines:

from classy import Class

# Define your cosmology (what is not specified will be set to CLASS default parameters)
params = {
    'output': 'tCl lCl',
    'l_max_scalars': 2000,
    'lensing': 'yes',
    'A_s': 2.3e-9,
    'n_s': 0.9624, 
    'h': 0.6711,
    'omega_b': 0.022068,
    'omega_cdm': 0.12029}

# Create an instance of the CLASS wrapper
cosmo = Class()

# Set the parameters to the cosmological code
cosmo.set(params)

# Run the whole code. Depending on your output, it will call the
# CLASS modules more or less fast. For instance, without any
# output asked, CLASS will only compute background quantities,
# thus running almost instantaneously.
# This is equivalent to the beginning of the `main` routine of CLASS,
# with all the struct_init() methods called.
cosmo.compute()

# Access the lensed cl until l=2000
cls = cosmo.lensed_cl(2000)

# Print on screen to see the output
print cls
# It is a dictionnary that contains the fields: tt, te, ee, bb, pp, tp

# plot something with matplotlib...

# Clean CLASS (the equivalent of the struct_free() in the `main`
# of CLASS. This step is primordial when running in a loop over different
# cosmologies, as you will saturate your memory very fast if you ommit
# it.
cosmo.struct_cleanup()

# If you want to change completely the cosmology, you should also
# clean the arguments, otherwise, if you are simply running on a loop
# of different values for the same parameters, this step is not needed
cosmo.empty()

Automated testing

Finally, a file test_class.py is present in this python/ subfolder. It makes use of Python techniques to automatize tests. It loops over many different cosmological scenarios, combining them with different output, with or without non-linearities, in synchronous or newtonian gauge. More will be added over-time, but already the execution is fairly long (roughly 100 tests cases as this current version).

To run it, you need to install the Python module nose, which provides the command nosetests, and nose-parameterized to loop over the different scenarios, as explained below. You would then simply call

python]$ nosetests test_class.py

and go grab yourself a coffee.

The key part of the code are the following lines (which might be expanded with more cases now, but the principle is the same).

    @parameterized.expand(
        itertools.product(
            ('LCDM',
             'Mnu',
             'Positive_Omega_k',
             'Negative_Omega_k'),
            ({}, {'output': 'mPk'}, {'output': 'tCl'},
             {'output': 'tCl lCl'}, {'output': 'mPk tCl lCl'},
             {'output': 'nCl sCl'}, {'output': 'mPk nCl sCl'}),
            ({'gauge': 'newtonian'}, {'gauge': 'sync'}),
            ({}, {'non linear': 'halofit'})))
    def test_parameters(self, name, scenario, gauge, nonlinear):
        ....

The decorator @parameterized.expand takes what comes after, the itertools.product and will create as many methods as needed, which will be fed the proper arguments. There are four arguments of the method, hence there are four tuples that are multiplied together by the itertools.product. Think of it as a Cartesian product. For instance, the first set of arguments, fed to the first function, will be:

    name=`LCDM`, scenario={}, gauge='newtonian', nonlinear={}

the name keyword defines what the cosmological parameters will be. The keyword scenario manages the different possible outputs, then gauge and nonlinear are pretty self-explanatory.

Note that this test suite tests both the underlying code and the wrapper. An error during the run is not necessarily a fault in CLASS.

When the code fails, it will output to a stdout the parameters which were used to provoke the error. Simply try them out in CLASS to identify if your modification broke something inside CLASS, or inside the wrapper.

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.