Dear experts,
I am trying to fit my data in RooFit with a pdf that describes both a signal and a background component. Both components are modelled as RooHistPdf from a MC. The strategy for the fit is to prefit the background in a region away from the signal, then fix the background normalisation and extend the fit to the whole region, extracting the signal normalisation.
I am struggling with the background normalisation: after the prefit, I get the normalisation value and extend it to the full range. Here is the code I use for this step.
def prefit_background(self, h_data:TH1F,range_limits:tuple=None, range_name:str=None, use_chi2_method:bool=True, save_normalisation_value=True):
xvar = self._roo_workspace.obj(self._xvar_name)
old_limits = (xvar.getMin(), xvar.getMax())
range_limits = range_limits if range_limits is not None else old_limits
if range_limits is not None:
xvar.setRange(range_limits[0], range_limits[1])
if range_name is not None and range_limits is not None:
xvar.setRange(range_name, range_limits[0], range_limits[1])
fit_options = [RooFit.Save(), RooFit.Extended(True)]
if range_name is not None:
fit_options.append(RooFit.Range(range_name))
for signal_name in self._signal_pdfs.keys():
if signal_name in self.fractions.keys():
self.fractions[signal_name].setVal(0)
self.fractions[signal_name].setConstant(True)
datahist = RooDataHist(h_data.GetName()+'_datahist', h_data.GetName()+'_datahist', [xvar], Import=h_data)
if use_chi2_method:
self._model_pdf.chi2FitTo(datahist, *fit_options)
else:
self._model_pdf.fitTo(datahist, *fit_options)
frame = xvar.frame()
self.plot_model(frame, datahist, 'prefit_bkg')
xvar.setRange('full', old_limits[0], old_limits[1])
xvar.setRange('prefit', range_limits[0], range_limits[1])
for bkg_name in self._bkg_pdfs.keys():
if bkg_name in self.fractions.keys():
bkg_pdf = self._bkg_pdfs[bkg_name]
I_full = bkg_pdf.createIntegral([xvar], Range='full').getVal()
I_side = bkg_pdf.createIntegral([xvar], Range='prefit').getVal()
bkg_full_correction = (I_full / I_side)
norm = self.fractions[bkg_name].getVal()
self.fractions[bkg_name].setVal(norm * bkg_full_correction)
self.fractions[bkg_name].setConstant(True)
for signal_name in self._signal_pdfs.keys():
if signal_name in self.fractions.keys():
self.fractions[signal_name].setConstant(False)
xvar.setRange(old_limits[0], old_limits[1])
del datahist
However, even though the normalisation value for the background is fixed, the values of the background contribution in the prefit and in the full fit are significantly different, as reported in the screenshots. Am I missing something?
I leave attached the relevant code. (edit: apparently, as a new user, I am not allowed to upload code)
Thanks in advance,
Giorgio Alberto