How to make a 2 dimensional likelihood profile

Hi experts,

I am trying to perform a 2D likelihood profile vs 2 fitting variables.
The fit is minimizing let’s say var1, and var2, which are used and expected to correlate in some extent via Multi-Dimensional constraints applied to other variables in the fit dependent from var1,var2.

Our fitter, is creating from say N datasets, N likelihoods and then they are all summed up and External - or Multi-D gauss constraints are added to the likelihood.

The code we have looks like this :

//make a list of likelihoods to sum
RooArgSet _nLL;
//Create and fill ArgSet
//Sum up the Likelihoods
RooAddition  _nllSimultaneous("nllCombined", "-log(likelihood)", _nLL);
//Invoke the minimizer
RooMinimizer _minimizer(_nllSimultaneous);
//Configure the Minimizer
ConfigureMinimizer(_minimizer, m_name + "_PlotContour.log");
//Run migrad and HESSE
 FittingProcedure(_minimizer, &_nllSimultaneous);

Let’s say i have now 2 observables ( var1,var2) ;
And i want to make a 2D likelihood profile.
Is this code executed afterwards correct?

    if( _nllSimultaneous.dependsOn( _var1) && _nllSimultaneous.dependsOn( _var2) ){
         _var1.setRange(_var1.getVal() - _var1.getError() * 3.5, _var1.getVal() + _var1.getError() * 3.5);
        _var2.setRange(_var2.getVal() - _var2.getError() * 3.5, _var2.getVal() + _var2.getError() * 3.5);
        _minimizer.minos(RooArgSet(_var1, _var2));
        RooPlot * _frame = _minimizer.contour(_var1, _var2, 1, 2, 3);

I.e to make the 2D 1,2,3 sigma level contour, do i need to run Minos on both observables ?
Am i missing something basic here?
To be clear, i saw that there is now a ProfileLikelihood root class available, however we are not using RooStats and i am not sure if I can easily/fastly port our fitter to use RooWorkSpaces and if in the fact we keep list<1model, 1dataset> summation in our fitter, can be problematic to use that class.
Any suggestion/help is more than welcome.

Hi ,
Minos will compute 1D intervals for the parameters you pass and not the 2D contours. To make the desired contours you need to use RooMinimizer::contour(...) or if you need the lower level function minimizer.fitter().GetMinimizer().Contour(..) after having defined the wanted level with Minimizer::SetErrorDef(..)


Hi @moneta
Thanks for the reply.
I am using as reference this example here :

Minos is run over only 1 of the 2 observables, and the contour on both.
Do I understand correctly that then the call to Minos() [ if before one has run Migrad and Hesse ] is useless?

I tried all cases, no changes. So i conclude execute Minos to get a contour beforehand is useless, except if one wants to get the asymmetric errors on the parameter of interest.
Thanks again @moneta. Just a last question, is there a way to control the speed of the contour method ?
I.e let’s say, if my default takes 2 hours, and i want to do a fast test, how can i control it?
I am failing to understand what SetErrorDef does :

set scale for calculating the errors

, if i set to 2 is it going to be faster than 1 ?
Apologize for the dummy question.


Minos is for 1D and it is not needed before making a contour. Internally they use the same Minuit class, MnFunctionCross, to find the profile likelihood values.

SetErrorDef affacts only the level of the function, not the speed. This can be tuned using less points for the contour, the parameter npoints in Minimizer::Contour.
However you cannot do a 2d contour with too few points. Unfortunately we don’t have yet a parallel implementation and making a contour requires several minimizations, which can take a log time in a big model


1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.