Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ProfileLikelihoodTestStat.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id$
2// Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke
3// Additional Contributions: Giovanni Petrucciani
4/*************************************************************************
5 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class RooStats::ProfileLikelihoodTestStat
13 \ingroup Roostats
14
15ProfileLikelihoodTestStat is an implementation of the TestStatistic interface
16that calculates the profile likelihood ratio at a particular parameter point
17given a dataset. It does not constitute a statistical test, for that one may
18either use:
19
20 - the ProfileLikelihoodCalculator that relies on asymptotic properties of the
21 Profile Likelihood Ratio
22 - the NeymanConstruction class with this class as a test statistic
23 - the HybridCalculator class with this class as a test statistic
24
25
26*/
27
29#include "RooFitResult.h"
30#include "RooPullVar.h"
32
33#include "RooProfileLL.h"
34#include "RooMsgService.h"
35#include "RooMinimizer.h"
36#include "RooArgSet.h"
37#include "RooDataSet.h"
38#include "TStopwatch.h"
39
41
42using std::cout, std::endl;
43
45
47
48////////////////////////////////////////////////////////////////////////////////
49/// internal function to evaluate test statistics
50/// can do depending on type:
51/// - type = 0 standard evaluation,
52/// - type = 1 find only unconditional NLL minimum,
53/// - type = 2 conditional MLL
54
56
57 if (fDetailedOutputEnabled) {
58 fDetailedOutput = std::make_unique<RooArgSet>();
59 }
60
61 //data.Print("V");
62
63 TStopwatch tsw;
64 tsw.Start();
65
66 double initial_mu_value = 0;
67 RooRealVar* firstPOI = dynamic_cast<RooRealVar*>(paramsOfInterest.first());
68 if (firstPOI) initial_mu_value = firstPOI->getVal();
69 //paramsOfInterest.getRealValue(firstPOI->GetName());
70 if (fPrintLevel > 1) {
71 cout << "POIs: " << endl;
72 paramsOfInterest.Print("v");
73 }
74
77
78 // simple
79 bool reuse=(fReuseNll || fgAlwaysReuseNll) ;
80
81 bool created(false) ;
82 if (!reuse || fNll==nullptr) {
83 std::unique_ptr<RooArgSet> allParams{fPdf->getParameters(data)};
85
86 // need to call constrain for RooSimultaneous until stripDisconnected problem fixed
87 fNll = std::unique_ptr<RooAbsReal>{fPdf->createNLL(data, RooFit::CloneData(false),RooFit::Constrain(*allParams),
88 RooFit::GlobalObservables(fGlobalObs), RooFit::ConditionalObservables(fConditionalObs), RooFit::Offset(fLOffset))};
89
90 if (fPrintLevel > 0 && fLOffset) cout << "ProfileLikelihoodTestStat::Evaluate - Use Offset in creating NLL " << endl ;
91
92 created = true ;
93 if (fPrintLevel > 1) cout << "creating NLL " << &*fNll << " with data = " << &data << endl ;
94 }
95 if (reuse && !created) {
96 if (fPrintLevel > 1) cout << "reusing NLL " << &*fNll << " new data = " << &data << endl ;
97 fNll->setData(data,false) ;
98 }
99 // print data in case of number counting (simple data sets)
100 if (fPrintLevel > 1 && data.numEntries() == 1) {
101 std::cout << "Data set used is: ";
102 RooStats::PrintListContent(*data.get(0), std::cout);
103 }
104
105
106 // make sure we set the variables attached to this nll
107 std::unique_ptr<RooArgSet> attachedSet{fNll->getVariables()};
108
109 attachedSet->assign(paramsOfInterest);
110 RooArgSet* origAttachedSet = (RooArgSet*) attachedSet->snapshot();
111
112 ///////////////////////////////////////////////////////////////////////
113 // New profiling based on RooMinimizer (allows for Minuit2)
114 // based on major speed increases seen by CMS for complex problems
115
116
117 // other order
118 // get the numerator
119 RooArgSet* snap = (RooArgSet*)paramsOfInterest.snapshot();
120
121 tsw.Stop();
122 double createTime = tsw.CpuTime();
123 tsw.Start();
124
125 // get the denominator
126 double uncondML = 0;
127 double fit_favored_mu = 0;
128 int statusD = 0;
129 RooArgSet * detOutput = nullptr;
130 if (type != 2) {
131 // minimize and count eval errors
132 fNll->clearEvalErrorLog();
133 if (fPrintLevel>1) std::cout << "Do unconditional fit" << std::endl;
134 std::unique_ptr<RooFitResult> result{GetMinNLL()};
135 if (result) {
136 uncondML = result->minNll();
137 statusD = result->status();
138
139 // get best fit value for one-sided interval
140 if (firstPOI) fit_favored_mu = attachedSet->getRealValue(firstPOI->GetName()) ;
141
142 // save this snapshot
143 if( fDetailedOutputEnabled ) {
144 detOutput = DetailedOutputAggregator::GetAsArgSet(result.get(), "fitUncond_", fDetailedOutputWithErrorsAndPulls);
145 fDetailedOutput->addOwned(*detOutput);
146 delete detOutput;
147 }
148 }
149 else {
150 return TMath::SignalingNaN(); // this should not really happen
151 }
152 }
153 tsw.Stop();
154 double fitTime1 = tsw.CpuTime();
155
156 //double ret = 0;
157 int statusN = 0;
158 tsw.Start();
159
160 double condML = 0;
161
162 bool doConditionalFit = (type != 1);
163
164 // skip the conditional ML (the numerator) only when fit value is smaller than test value
165 if (!fSigned && type==0 &&
166 ((fLimitType==oneSided && fit_favored_mu >= initial_mu_value) ||
167 (fLimitType==oneSidedDiscovery && fit_favored_mu <= initial_mu_value))) {
168 doConditionalFit = false;
169 condML = uncondML;
170 }
171
172 if (doConditionalFit) {
173
174 if (fPrintLevel>1) std::cout << "Do conditional fit " << std::endl;
175
176
177 // cout <<" reestablish snapshot"<<endl;
178 attachedSet->assign(*snap);
179
180
181 // set the POI to constant
182 for (auto *tmpPar : paramsOfInterest) {
183 RooRealVar *tmpParA = dynamic_cast<RooRealVar *>(attachedSet->find(tmpPar->GetName()));
184 if (tmpParA) tmpParA->setConstant();
185 }
186
187
188 // check if there are non-const parameters so it is worth to do the minimization
189 RooArgSet allParams(*attachedSet);
191
192 // in case no nuisance parameters are present
193 // no need to minimize just evaluate the nll
194 if (allParams.empty() ) {
195 // be sure to evaluate with offsets
196 if (fLOffset) RooAbsReal::setHideOffset(false);
197 condML = fNll->getVal();
198 if (fLOffset) RooAbsReal::setHideOffset(true);
199 }
200 else {
201 fNll->clearEvalErrorLog();
202 std::unique_ptr<RooFitResult> result{GetMinNLL()};
203 if (result) {
204 condML = result->minNll();
205 statusN = result->status();
206 if( fDetailedOutputEnabled ) {
207 detOutput = DetailedOutputAggregator::GetAsArgSet(result.get(), "fitCond_", fDetailedOutputWithErrorsAndPulls);
208 fDetailedOutput->addOwned(*detOutput);
209 delete detOutput;
210 }
211 }
212 else {
213 return TMath::SignalingNaN(); // this should not really happen
214 }
215 }
216
217 }
218
219 tsw.Stop();
220 double fitTime2 = tsw.CpuTime();
221
222 double pll = 0;
223 if (type != 0) {
224 // for conditional only or unconditional fits
225 // need to compute nll value without the offset
226 if (fLOffset) {
228 pll = fNll->getVal();
229 }
230 else {
231 if (type == 1) {
232 pll = uncondML;
233 } else if (type == 2) {
234 pll = condML;
235 }
236 }
237 }
238 else { // type == 0
239 // for standard profile likelihood evaluations
240 pll = condML-uncondML;
241
242 if (fSigned) {
243 if (pll<0.0) {
244 if (fPrintLevel > 0) std::cout << "pll is negative - setting it to zero " << std::endl;
245 pll = 0.0; // bad fit
246 }
247 if (fLimitType==oneSidedDiscovery ? (fit_favored_mu < initial_mu_value)
248 : (fit_favored_mu > initial_mu_value))
249 pll = -pll;
250 }
251 }
252
253 if (fPrintLevel > 0) {
254 std::cout << "EvaluateProfileLikelihood - ";
255 if (type <= 1)
256 std::cout << "mu hat = " << fit_favored_mu << ", uncond ML = " << uncondML;
257 if (type != 1)
258 std::cout << ", cond ML = " << condML;
259 if (type == 0)
260 std::cout << " pll = " << pll;
261 std::cout << " time (create/fit1/2) " << createTime << " , " << fitTime1 << " , " << fitTime2
262 << std::endl;
263 }
264
265
266 // need to restore the values ?
267 attachedSet->assign(*origAttachedSet);
268
269 delete origAttachedSet;
270 delete snap;
271
272 if (!reuse) {
273 fNll.reset();
274 }
275
277
278 if(statusN!=0 || statusD!=0) {
279 return -1; // indicate failed fit (WVE is not used anywhere yet)
280 }
281
282 return pll;
283
284 }
285
286////////////////////////////////////////////////////////////////////////////////
287/// find minimum of NLL using RooMinimizer
288
289std::unique_ptr<RooFitResult> RooStats::ProfileLikelihoodTestStat::GetMinNLL() {
290
291 const auto& config = GetGlobalRooStatsConfig();
292 RooMinimizer minim(*fNll);
293 minim.setStrategy(fStrategy);
294 minim.setEvalErrorWall(config.useEvalErrorWall);
295 //LM: RooMinimizer.setPrintLevel has +1 offset - so subtract here -1 + an extra -1
296 int level = (fPrintLevel == 0) ? -1 : fPrintLevel -2;
297 minim.setPrintLevel(level);
298 minim.setEps(fTolerance);
299 // this causes a memory leak
300 minim.optimizeConst(2);
301 TString minimizer = fMinimizer;
303 if (algorithm == "Migrad") algorithm = "Minimize"; // prefer to use Minimize instead of Migrad
304 int status;
305 for (int tries = 1, maxtries = 4; tries <= maxtries; ++tries) {
306 status = minim.minimize(minimizer,algorithm);
307 if (status%1000 == 0) { // ignore errors from Improve
308 break;
309 } else if (tries < maxtries) {
310 cout << " ----> Doing a re-scan first" << endl;
311 minim.minimize(minimizer,"Scan");
312 if (tries == 2) {
313 if (fStrategy == 0 ) {
314 cout << " ----> trying with strategy = 1" << endl;
315 minim.setStrategy(1);
316 }
317 else
318 tries++; // skip this trial if strategy is already 1
319 }
320 if (tries == 3) {
321 cout << " ----> trying with improve" << endl;
322 minimizer = "Minuit";
323 algorithm = "migradimproved";
324 }
325 }
326 }
327
328 //how to get cov quality faster?
329 return std::unique_ptr<RooFitResult>{minim.save()};
330 //minim.optimizeConst(false);
331}
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
static const std::string & DefaultMinimizerAlgo()
RooAbsArg * first() const
void Print(Option_t *options=nullptr) const override
This method must be overridden when a class wants to print itself.
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
void setConstant(bool value=true)
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
static void setHideOffset(bool flag)
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:154
Wrapper class around ROOT::Math::Minimizer that provides a seamless interface between the minimizer f...
void optimizeConst(int flag)
If flag is true, perform constant term optimization on function being minimized.
RooFit::OwningPtr< RooFitResult > save(const char *name=nullptr, const char *title=nullptr)
Save and return a RooFitResult snapshot of current minimizer status.
void setEvalErrorWall(bool flag)
void setEps(double eps)
Change MINUIT epsilon.
void setPrintLevel(int newLevel)
Change the MINUIT internal printing level.
int minimize(const char *type, const char *alg=nullptr)
Minimise the function passed in the constructor.
void setStrategy(int istrat)
Change MINUIT strategy to istrat.
static RooMsgService & instance()
Return reference to singleton instance.
void setGlobalKillBelow(RooFit::MsgLevel level)
RooFit::MsgLevel globalKillBelow() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
static RooArgSet * GetAsArgSet(RooFitResult *result, TString prefix="", bool withErrorsAndPulls=false)
Translate the given fit result to a RooArgSet in a generic way.
virtual double EvaluateProfileLikelihood(int type, RooAbsData &data, RooArgSet &paramsOfInterest)
evaluate the profile likelihood ratio (type = 0) or the minimum of likelihood (type=1) or the conditi...
std::unique_ptr< RooFitResult > GetMinNLL()
find minimum of NLL using RooMinimizer
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Stopwatch class.
Definition TStopwatch.h:28
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
Double_t CpuTime()
Stop the stopwatch (if it is running) and return the cputime (in seconds) passed between the start an...
void Stop()
Stop the stopwatch.
Basic string class.
Definition TString.h:139
RooCmdArg Offset(std::string const &mode)
RooCmdArg Constrain(const RooArgSet &params)
RooCmdArg GlobalObservables(Args_t &&... argsOrArgSet)
RooCmdArg CloneData(bool flag)
RooCmdArg ConditionalObservables(Args_t &&... argsOrArgSet)
Create a RooCmdArg to declare conditional observables.
MsgLevel
Verbosity level for RooMsgService::StreamConfig in RooMsgService.
void RemoveConstantParameters(RooArgSet *set)
RooStatsConfig & GetGlobalRooStatsConfig()
Retrieve the config object which can be used to set flags for things like offsetting the likelihood o...
void PrintListContent(const RooArgList &l, std::ostream &os=std::cout)
useful function to print in one line the content of a set with their values
Double_t SignalingNaN()
Returns a signaling NaN as defined by IEEE 754](http://en.wikipedia.org/wiki/NaN#Signaling_NaN).
Definition TMath.h:910