Topic Overview

This is a tutorial for the 'Hands-on: Fitting smoothly falling backgrounds' session at the ATLAS Exotics Workshop 2018 Several techniques and software packages exist in order to model smoothly falling backgrounds via a fit to the data, for more details about the techniques and packages utilised in the Exotics group please see FunctionalFormsInExotics. The common gitlab space for the functional form based tools utilised in the Exotics group can be found here the RooSwift code will soon join the other frameworks in this space.

In this tutorial demonstrations of fitting smoothly falling spectra will be given using the RooSwift sliding window fitting package developed by the di-lepton resonance search team. RooSwift performs a sliding window fit in which a parametric signal model is utilised (typically a Breit-Wigner convoluted with a resolution model). However, it also supports a BumpHunter -like mode where window configurations are looped over and the Poisson p-value calculated for each window using the expected vs. observed yields.

Fitting Smoothly Falling Spectra with RooSwift

The RooSwift framework is based on the RooFit /RooStats framework, for an introduction to RooStats please see LearningRoostats. The RooSwift framework can be found at, instructions for downloading and running the framework are provided below.

I. Setting up

Download the project from gitlab (showing only ssh), go to RooSwift directory, and check out the tag supported by this tutorial:

git clone ssh://
cd RooSwift/
git checkout tags/tutorial

Build the project:

On lxplus...


... or if running on a local ROOT install, complete the one-line changes indicated by comments in both and source/RooSwift/CMakeLists.txt before running the above.

Let me introduce you to the 36.1/fb di-electron spectrum and its background MC counterpart:

root input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root
> _file0->ls()
> new TBrowser


II. SWiFt on data

Note: if you have a local install, the executable is probably


whereas for the rest of the tutorial we'll be using the path for an lxplus build


The above command without arguments will run a default SWiFt configuration on a subrange of the di-electron spectrum. Browse output:

root output/RooSwiftResults.root
> wksp->Print()
> new TBrowser
> //look around

The wksp contains all the RooFit objects created during the run. Have a look at the following:

  • "windowPlot" illustrates the windows used
  • "canvasHat"shows the fit fit corresponding to the highest signal significanccanvasHat1.png
  • "swiftBkg" shows the fit and residuals of the stitched background estimates of the sliding window fit
  • "zValueScan" shows a scan of the significance

The scan can be configured by passing command line arguments which directly modify RooFit objects in the workspace or simply turn on options.

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -m[0.3,0.8] -doPlot -printPlots -anchor[0.7]

In the following case, the boundaries of the pole mass scan are specified as well as an option to enable to plotting of the fits in each window. The fit plots are printed to a pdf which we can flip through: printPlots_muFreeParameters.pdf .

The final argument specifies the value of a RooRealVar in the workspace which determines the maximum value of the sliding window's left edge (take a look at the windowPlot).


Let's have some fun by scanning a toy thrown from background MC with two injected signals:

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -data[10*input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root:DY_Mass_Template+200000*input/Moriond_2017/SearchBinning/ZPTemplates_532Search_E6Chi_EE_13TeV_1pb.root:template:120+350000*input/Moriond_2017/SearchBinning/ZPTemplates_532Search_E6Chi_EE_13TeV_1pb.root:template:160] -toy[1,1.2] -m[0.2,0.9] -doPlot


Notice the syntax for adding datasets and specifying their location.

III. Global fit on data

RooSwift allows different parameterization of the windows including a global fit whose fixed edges are given by RooRealVars "left" and "right":

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -m[0.5,0.6] -left[0.2] -right[1.0] -globalWindow -pdf[diphoton5PLUSvoigtian]


Including more bins slows the fitter down! By throwing a big toy (x100 stats) from the MC we can try to "break" the global fit:

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -data[100*input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root:DY_Mass_Template] -toy[1] -m[0.5,0.502] -left[0.15] -right[5.0] -globalWindow -pdf[diphoton5] -doPlot -seed[123]


The SWiFt is more robust though, let's try on the same toy (same seed):

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -data[100*input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root:DY_Mass_Template] -toy[1] -m[0.2,4] -pdf[expow] -seed[123] -anchor[1.7]


IV. Spurious signal

Fitting a (presumably) background-only distribution measures the spurious signal induced by an imperfect background model.

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -data[input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root:DY_Mass_Template] -m[0.2,1] -measureSpurSig -path[output/RooSwiftResults_spurSig.root]

You can browse the distribution of spurious signal shown in "spurSigCanvas"


To see where it comes from, we can plot it directly from the tuple containing the fit results:

root output/RooSwiftResults_spurSig.root
> _file0->ls()
> wksp->Print()
> pTuple->Draw("TMath::Abs(mu*sigN):m","muFree")


This information from MC can now be used to constrain the spurious signal systematic uncertainty in a fit on data. Essentially, the spurious signal yield as a function of pole mass is taken as the width of the gaussian constraint profiling the spurious signal nuisance parameter.

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -inTuple output/RooSwiftResults_spurSig.root -doSyst -measureSpurSig

Now "canvasHat" shows the signal-like flexing in the background-only curve (solid blue). Compare the following two plots to their counterparts in the first (default, no arguments) scan.


V. Optimization

To find the optimal SWiFt configuration.

There is also basic support for looping over different functions...

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -pdf[expolylog1,expolylog2,expolylog3] -m[0.2,0.9]

Here we may want to compare the SWiFt templates from the different functions; that's shown in the "stackedSwift" plot in the output:


... and there's also basic support for looping over different parameter values:

./build/x86_64-slc6-gcc62-opt/bin/RooSwift -data[input/Moriond_2017/SearchBinning/DataBackground_EE_13TeV_36p5fb_Search.root:DY_Mass_Template] -nResL[6,8,10,12,14,16,18,20,22,24,26,28,30,32,34] -nResR[14] -m[0.5,0.502] -doPlot -doExpectedSignificance

In the above, the values passed to nResL (= the multiple of invariant mass resolution to the left of the pole mass in the window configuration) all were tested in series so that the performance of the different configurations could be compared. In this quick example, just for one mass point. Let's browse it:

root output/RooSwiftResults.root
> wksp->Print()
> new TBrowser
  • look at window fits on data (see how the left edge is varying)


  • look at window fits on Asimov datasets with injected signal for expected significance (which will have a higher expected significance?)
  • compare chi2 for different configurations (plot as function of window size)


  • compare expected significance for different configurations (plot as function of window size)


-- LydiaBeresford - 2018-05-18

This topic: Sandbox > WebPreferences > FunctionalFormsInExoticsSearches > RooSwiftTutorial
Topic revision: r15 - 2018-09-17 - EtienneDreyer
This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback