RooAbsReal: how to transform the function or get the value of each points

After using ‘createNLL’, I can get an object of ‘RooAbsReal’ class and a -log(L) curve.But I need to know the upper limit,so I need to transform the -log(L) into log(L) or get the value of each points from the curve.So how can I do the transformation or get the value of each points of ‘RooAbsReal’ class.My code is in attachment. Thanks for your advice.

rf605_study.C (1.5 KB)

Maybe @jonas can help here?

Can you @jonas give some advice? Thanks.

Hi @Eagle_Lu, thanks for the reminder!

Indeed there is no high-level RooFit interface to do that, but you can iterate over the dataset yourself. The key is to use RooAbsArg::attachDataSet() to connect your PDF to the dataset. I have written a little function that does this, and then iterates over the dataset to do the evaluations:

std::vector<double> getValues(RooAbsReal const& absReal,
                              RooAbsData const& data)
{
   // We clone the original RooAbsReal so we don't mess with the its
   // state. Let's use a smart pointer so we don't have to remember
   // calling "delete".
   std::unique_ptr<RooAbsReal> absRealClone{
      static_cast<RooAbsReal *>(absReal.cloneTree()
   )};

   // Attach computation graph of the RooAbsReal to the dataset
   absRealClone->attachDataSet(data);

   // Normalize PDFs over the observables in the dataset
   RooArgSet observables{*data.get()};

   // Output vector
   std::vector<double> out(data.numEntries());

   // Do the evaluations
   for(int iEvent = 0; iEvent < data.numEntries(); ++iEvent) {
     // Load column in dataset and evaluate the absRealClone,
     // which will have updated its value because it is
     // attached to the dataset.
     data.get(iEvent);
     out[iEvent] = absRealClone->getVal(observables);
   }

   return out;
}

You might have to change the function a bit if the set of normalization observables is not the same as the set of columns in the dataset.

Then you can use the function and check the values like this:

std::vector<double> vals = getValues(pdf, *data);
for(auto val : vals) {
   std::cout << val << std::endl;
}

For future ROOT releases, we also plan to have such a function as part of RooFit itself.

I hope this helps!

Jonas

1 Like

Hi @jonas , Really thanks for your detailed notes and suggestions!
But I’m still a little confused about how to get the value of each points from the blue curve,whose Xaxis is the parameter mean or sigma,not the data variable x.

Another thing is that I don’t know why I just 10,000 constant values using getValues(*nll_g2x, *data_g2x);.


rf605_study_v2.C (2.6 KB)

Hello!

Another thing is that I don’t know why I just 10,000 constant values using getValues(*nll_g2x, *data_g2x);.

Because the data_g2x only contains the variable “x”, and the NLL doesn’t depend on the values of x anymore, because it already does the summing over the dataset internally.

How to get the value of each points from the blue curve,whose Xaxis is the parameter mean or sigma,not the data variable x.

If you don’t mind using the “getValues()” function I already wrote, all you need to do is to pass a different RooDataSet that actually containts different values for the parameter mean or the parameter sigma.

You can write maybe a little helper to define such a dataset object:

/// Create a RooDataSet containing only "var", with iPoints equidistant
/// points from the minimium to the maximum of the variable.
std::unique_ptr<RooDataSet> createLinspaceDataSet(RooRealVar & var,
                                                  std::size_t iPoints)
{
   auto dataset = std::make_unique<RooDataSet>("dataset", "dataset", var);

   double step = (var.getMax() - var.getMin())  / (iPoints - 1.0);

   // Remember original value of the variable
   double orig = var.getVal();

   // Do fill the dataset
   for(std::size_t i = 0; i < iPoints; ++i) {
      var.setVal(var.getMin() + i * step);
      dataset->add(var);
   }

   var.setVal(orig); // Reset original values

   return dataset;
}

Then you can use the two little functions you have now to evaluate your NLL for the linear space of mean and sigma:

std::vector<double> nllValsMean = getValues(
   *nll_g2x, *createLinspaceDataSet(mean, 200)
);
std::vector<double> nllValsSigma_g2 = getValues(
   *nll_g2x, *createLinspaceDataSet(sigma_g2, 200)
);

I hope this works for you, and sorry again that it is so cumbersome! For the next RooFit release, there needs to be a simple interface to do that without defining your own helper functions.

Cheers,
Jonas

1 Like

Hi, @jonas , I finally draw the curve I wanted. I’m very grateful for your patience and detailed explanation. You really give me many help and I learn a lot from your reply. Thanks very much!

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