DataDev

Here is what you have to do to add your own Likelihood to CAMEL. After reading this page, you can take a look at some implementations (asthe JLALikelihood

It must be very clear that what we call sometimes "Likelihood" is, for numerical reasons, in the form of an " effective Chi2" which by definition is Chi2=-2 ln(lik)

It is not a-priori parabolic nor follows a "chi2" law. Just think of it as a function of a "model" (a vector of cosmological+nuisance parameters). This function must return some real number which says if the model "agrees" or not with your data. You don't have to touch the model (this is performed by CAMEL): just consider it is given and return a number.

1.  Create your own class

For your new observable, you must create a dedicated C++ class that inherits from Chi2Data. so first:

 
cd src/camel

you may stay at this level or go into one of the sub-directories or create a new one.

Then create your class (let's call it "MyAwasomeChi2").

Your interface should look like this (MyAwasomeChi2.hh):

#ifndef MyAwasomeChi2_hh
#define MyAwasomeChi2_hh


#include "Chi2Data.hh"
#include "Engine.hh"
#include "Variables.hh"

#include<vector>
#include<string>


class MyAwasomeChi2 : public Chi2Data
{

public:

  //constructor: creates the object, store all that is needed in private variables, 
  // and stores a pointer to the Engine state (in Chi2Data)
  MyAwasomeChi2(const std::string& likfile,  
                const Variables& par, Engine *engine);

  // destructor
  ~MyAwasomeChi2();

  //this is mandatory (see Chi2Data)- "const" means it should not modify the class.
  //name of nuisance parameters:
  std::vector<std::string> requires() const;

  //chi2 computation for this vector of par and engine state
  double chi2_eff(const std::vector<double>& par) const;

private:

  //here you may store all the variables/methods you need to compute chi2_eff

};

#endif

Then here is a commented example of implementation (MyAwasomeChi2.cc)

//-----------------------
#include "MyAwasomeChi2.hh"
// ------------------------
// Collaborating classes --
//-------------------------
//--------------------
// C++
//--------------------
#include<iostream>
using namespace std;
//--------------------
// C 
//----------------

//---------------
// Constructors --
//----------------
MyAwasomeChi2::MyAwasomeChi2(const std::string& likfile, const Variables& par, Engine *engine) :Chi2Data(par,engine) 
//always trasmit par and Engine to teh super-class (Chi2Data)
{
  //you can define the name of our likelihood here:
  _name="MyAwasomeChi2";

  //you open you lik file and store whatever you need in your private variables.

  //if you will need to know in chi2_eff(vector) where a given prameter is located inside the vector
  // you shoudl add here:
  buildIndex();
  // or loop on the Variables and store indices that interest you 
  // (the order is preserved in chi2_eff)

}
//--------------
// Destructor --
//--------------
MyAwasomeChi2::~MyAwasomeChi2()
{
  //does nothing but you mya want to clean some allocations you did in the constructor

}

//-----------------
// Member functions --
//-----------------
std::vector<std::string> MyAwasomeChi2:: requires() const 
{
  //here nothing (but put your nuisance names)
  return std::vector<std::string>();
}

double 
MyAwasomeChi2:: chi2_eff(const std::vector<double>& par) const{

  //here you can access any variable from your private region

  //if you need to identify the position in the vector of some values 
  //(and if you built the index in the constructor) use the Chi2Data::index() function, for instance
  double omega_b=par[index("omega_b")];

  //you can also access any Engine quantity (it is up-to-date with the vector of parameters)
  //from Chi2Data::engine, for instance:
  double H0=engine->get_H0();

  //you now have all in hands to  do your complicated stuff now and return the chi2
  //...

  return H0/omega_b; 

}

Then recompile in cmt/. (all src/camel/*.cc files are automatically compiled including sub-directories, if you created a new one update macro camelsrc in the requirements file):

 
make 

If you don't see your code being compiled. you should update the cmt configuration with:

cmt config
source camel_setup.sh

2.  Define your parameters in a lik file

So what is the "likfile" that appears in the previous constructor?

This is your parameter file that contains everything you need to construct your likelihood. It is opened and decoded in the constructor where you initialise and store all the quantities you need. This file can be in any format you like, but we suggest it to be in the form of "keyword=value" lines, since then you can take advantage of the param class (in cxxutils) to easily parse it. For instance:

paramfile params(likfile)
double tol=params.find<double>("tol",0.00001);
...

(it is templated, you can use it for all types).

If your likelihood has a heavy part of data (for instance a large fits file), it is better to put it in t he lik/camel_data/ and reference the path in the likfile as a string. For instance likfile:

map=/.../camel_data/amazing_map.fits

and in the constructor:

paramfile params(likfile)
string fitsname=params.find<string>("map","");
..//open it and store things

Put you new likfile in the lik/ directory (or inside a sub-directory): this is because when the master parameter file is scanned the relative path is wrt to $CAMELROOT/lik. Tis allows to write parFiles that are site-independent.

A last remartk: you have sevral tools in cxxutils/ to deal with fits IO.

3.  Register your likelihood in the Chi2Factory

Your class is ready: you must now instanciate it according to a keyword in the parameter file.

Edit: Chi2Factory.cc]

add your header at the beginning

#include"MyAwasomeChi2.hh"

Then in the gimeChi2 method, near the end (it is indicated where) add the following code that will add your Likelihood depending on the existence of your chosen keyword.

  if (parser.params.param_present("MyAwasomeChi2")){
    const string likfile=Parser::CheckPath(parser.params.find<string>("MyAwasomeChi2",""));
    MyAwasomeChi2* b = new  MyAwasomeChi2(likfile,parser.vars(),e);
    comb->add (b);
  }
  • the 1st line checks the keyword "MyAwasomeChi2" existence
  • then it retrieves the name of the value which is the name of your lik-file. CheckPath tries a relative path wrt to the directory /lik

if nothing found in the absolute path

  • then you instanciate your likelihood: parser.vars() refers to the list of Variables specified in teh parameter file, e is the engine
  • you add your object to comb which is a Chi2Combiner object (that sums the Chi2's)

Recompile+link

 make
make exec

You may now add such a line to your prefered parameter file

MyAwasomeChi2=/path/to/my/lik/file

And enjoy all the usual CAMEL functionalities with it (as always begin by a writeChi2 /path/to/parfile test...)