Multiple fit regions in RooFit


 Well, I would like to fit a histogram using two regions (sideband regions).  I have looked on the web, the forums, and underneath my desk for information on how to do this using RooFit.  I have put together the following code based on the information that I was able to put together.  
#include <iostream>
#include <string>
#include <TFile.h>
#include <TH1D.h>
#include <RooGlobalFunc.h>
#include <RooPlot.h>
#include <RooDataHist.h>
#include <RooRealVar.h>
#include <TCanvas.h>
#include "roothreshold.h"
#include <RooFitResult.h>
#include <RooCategory.h>

using namespace std;
using namespace RooFit;

typedef struct {
  double delta;
  double exp;
  double exp_err;
  double pull;
  int fit_status;
} Result;

Result doFit(TH1*);

int main() {
  TFile input("output_histos.root");
  TH1D *input_hist = (TH1D*) input.FindObjectAny("data_0tag_rev1_nocuts_jj");

  // Ok, lets make a RooFit thingy here

  Result tmpres = doFit(input_hist);

  cout << "The exp is: " << tmpres.exp << endl;

Result doFit(TH1 *input_histo) {
  Result res;

  double signal_count = input_histo->Integral(input_histo->FindBin(50), input_histo->FindBin(100));

  RooRealVar x("x", "M(jj)", 0, 400, "GeV/c^{2}");

  RooRealVar norm("norm", "norm", 1.0, 0.0, 100.0);
  RooRealVar offset("offset", "offset", 10.849, 0, 30);
  RooRealVar power("power", "power", 2.4653, 0, 10);
  RooRealVar coeff1("coeff1", "coeff1", -0.0829876, -2, 2);
  RooRealVar coeff2("coeff2", "coeff2", 0.000133946, -1, 1);
  RooThreshold thresh("thresh", "MN_FIT Threshold Function", x, norm, offset, power, coeff1, coeff2);

  RooDataHist data("data", "Yhea", x, input_histo);

  RooCategory modes("modes","modes");
  modes.defineType("1", 1);
  modes.defineType("2", 2);

  // Set the regions
  x.setRange("low", 0, 50);
  x.setRange("signal", 50, 100);
  x.setRange("high", 100, 300);

  x.setRange("fit_1", 30, 50);
  x.setRange("fit_2", 100, 200);

  // Get the original integral
  RooAbsReal *preInt         = thresh.createIntegral(x);
  RooAbsReal *preIntSignal   = thresh.createIntegral(x, Range("signal"));
  RooAbsReal *preIntSideband = thresh.createIntegral(x, Range("low"), Range("high"));


  cout << "The int is: " << preInt->getVal() << endl;
  cout << "The signal region is: " << preIntSignal->getVal() << endl;
  cout << "The sideband region is: " << preIntSideband->getVal() << endl;
  cout << "The sum of the two is: " << preIntSignal->getVal() + preIntSideband->getVal() << endl;

  // Do the fit
  RooFitResult *fitResult = thresh.fitTo(data, Range("fit"), SplitRange(kTRUE), Verbose(kTRUE), Save(kTRUE), PrintLevel(3));

  int status = fitResult->status();
  int covQual = fitResult->covQual();
  cout << "The fit status was: " << status << " with a covariance quality code of: " << covQual << endl;

  RooAbsReal *postInt         = thresh.createIntegral(x);
  RooAbsReal *postIntSignal   = thresh.createIntegral(x, Range("signal"));
  RooAbsReal *postIntSideband = thresh.createIntegral(x, Range("low"), Range("high"));

  cout << "The post fit signal integral is: " << postIntSignal->getVal() << endl;
  cout << "The number of signal events is : " << signal_count << endl;

  TCanvas *can = new TCanvas("mycanvas");

  RooPlot *frame = x.frame();
  frame->SetTitle("M(jj) Fit with a Threshold Function");


I have been looking in the output but I can not seem to find a way to verify that it is using just the fit_* regions. It looks like it is using the entire region. Thanks for any help here. I may have this right, if I do please let me know. I am using root version 5.18/00d.



This is in principle relatively straightforward to do in ROOT >= 5.20.

In the upcoming ROOT 5.21 release (out in 2 days) I have provided a couple of
example on how to fit in subranges and on how to fit in multiple disjoint regions in roofit
they are


You can already find them in the SVN head of the repository. These macro will very likely also run with 5.20 but probably not with 5.18.