RooDataHist: Setting my own error bars

I have a RooDataHist data which I fit to a RooAddPdf signal+background distribution. Now I want to draw only my signal distribution, by subtracting the background (known from the fit) from my original data. In addition I do want to preserve the error bars size on the resulting histogram, so only a bin amplitude should change, but not its error bar.
And the last point: original histogram cannot have negative bin contents, but after a background subtraction negative values are allowed, and also error bars can go to negative region. My code (where I use RooDataHist::set()) does not do this.

Please, help!! What do I misss?

Here is my function:

RooDataHist *remove_data(RooRealVar &mass,RooDataHist &dh,const RooArgList &pdf,const RooArgList &frac)

    RooArgSet margs(mass);
    RooDataHist *dh_new = dynamic_cast<RooDataHist*>(dh.emptyClone("no_bkg"));
    for(int i=0; i<dh.numEntries(); i++ )
        const RooArgSet *args = dh.get(i);

        const RooAbsArg *x = args->first();
        const RooAbsReal *xx = dynamic_cast<const RooAbsReal *>(x);
        mass = xx->getVal();
            weight       = dh.weight(margs,1,true),
            weight_error = dh.weightError(RooAbsData::SumW2);

        //printf("bin=%2d   mass=%g   weight = %g +/- %g\n",i,xx->getVal(),weight,weight_error);

        double v=0;
        for( int j=0; j<pdf.getSize(); j++ )
            const RooAbsPdf  *f = dynamic_cast<const RooAbsPdf *>(&pdf [j]);
            const RooRealVar *c = dynamic_cast<const RooRealVar*>(&frac[j]);
            //printf("expected signal (%s): pdf=%g  coef=%g\n",f->GetName(),f->getVal(args),c->getVal());
            v += f->getVal(args) * c->getVal();

        // printf("  %g : %g\n",weight,v);
        double new_val = weight-v;
    return dh_new;
} (35.6 KB)


You do not show the line of code where you make the RooDataHist::plotOn() call,
but to show the ‘sum-of-weights’ error you should have do this

hist->plotOn(frame,DataError(RooAbsData::SumW2)) ;

Did you do that?


Absolutely!!! Without DataError(RooAbsData::SumW2) option RooFit correctly complains that my entries are not integers. Moreover the error bars are discrete (I believe because the bin contents are rounded to integer values).


I’ve looked into this with the debugger and I have discovered a bug in RooDataHist::set() for this use case. A fix has been applied to the SVN trunk and will appear in the next ROOT development release. If you have source distribution of ROOT you could apply
the one line fix yourself.

— RooDataHist.cxx (revision 26874)
+++ RooDataHist.cxx (working copy)
@@ -1217,6 +1217,7 @@
_wgt[_curIndex] = wgt ;
_errLo[_curIndex] = wgtErr ;
_errHi[_curIndex] = wgtErr ;

  • _sumw2[_curIndex] = wgtErr*wgtErr ;

I’m afraid I see no easy workaround other than getting this fix for what you are doing.


Dear Wouter,
thanks for looking into the problem!!

Your fix was not enough: after adding the line

_sumw2[_curIndex] = wgtErr*wgtErr ;
I still had my funny error bars. But then in analogy to your line
I added another one to the method
void RooDataHist::set(const RooArgSet& row, Double_t wgt, Double_t wgtErr) :

_sumw2[idx] = wgtErr*wgtErr ;

Now the error bars look reasonable!

Please check it…


Thanks. That one is also needed indeed (I used another set method in my test job so I missed that one). I will commit your fix in SVN as well.


The bug is not yet fixed in ROOT 5.24/00. RooFit v3.00!!! :frowning:


Oops. I just looked into what happened. I had applied your second fix in my dev branch, but then I accidentally overwrote in in a later merging with the trunk when I was finalizing the reorganization of the data classes for 3.00. I have now applied your fix correctly again so it should go out in both trunk and dev later today. Sorry about this silly mistake.


PS: Meanwhile you can work around this in 3.00 as follows
data.set(row,wgt,wgtError) ; data.set(wgt,wgtError) ;