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
43
45
46/// Check if there are non-const parameters so it is worth to do the minimization.
53
54std::pair<double, int> RooStats::ProfileLikelihoodTestStat::minimizeNLL(std::string const &prefix)
55{
56 // minimize and count eval errors
57 fNll->clearEvalErrorLog();
58 std::unique_ptr<RooFitResult> result{GetMinNLL()};
59 if (!result) {
60 // this should not really happen
61 throw std::runtime_error("ProfileLikelihoodTestStat: minimization unexpectedly failed!");
62 }
63 double minNll = result->minNll();
64 double status = result->status();
65
66 // save this snapshot
67 if (fDetailedOutputEnabled) {
68 std::unique_ptr<RooArgSet> detOutput{
69 DetailedOutputAggregator::GetAsArgSet(result.get(), prefix, fDetailedOutputWithErrorsAndPulls)};
70 fDetailedOutput->addOwned(*detOutput);
71 }
72
73 return {minNll, status};
74}
75
76////////////////////////////////////////////////////////////////////////////////
77/// internal function to evaluate test statistics
78/// can do depending on type:
79/// - type = 0 standard evaluation,
80/// - type = 1 find only unconditional NLL minimum,
81/// - type = 2 conditional MLL
82
84
85 if (fDetailedOutputEnabled) {
86 fDetailedOutput = std::make_unique<RooArgSet>();
87 }
88
89 //data.Print("V");
90
92 tsw.Start();
93
94 double initial_mu_value = 0;
95 RooRealVar* firstPOI = dynamic_cast<RooRealVar*>(paramsOfInterest.first());
96 if (firstPOI) initial_mu_value = firstPOI->getVal();
97 //paramsOfInterest.getRealValue(firstPOI->GetName());
98 if (fPrintLevel > 1) {
99 std::cout << "POIs: " << std::endl;
100 paramsOfInterest.Print("v");
101 }
102
104 if (fPrintLevel < 3) RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
105
106 // simple
107 bool reuse=(fReuseNll || fgAlwaysReuseNll) ;
108
109 bool created(false) ;
110 if (!reuse || fNll==nullptr) {
111 std::unique_ptr<RooArgSet> allParams{fPdf->getParameters(data)};
113
114 // need to call constrain for RooSimultaneous until stripDisconnected problem fixed
115 fNll = std::unique_ptr<RooAbsReal>{fPdf->createNLL(data, RooFit::CloneData(false),RooFit::Constrain(*allParams),
116 RooFit::GlobalObservables(fGlobalObs), RooFit::ConditionalObservables(fConditionalObs), RooFit::Offset(fLOffset))};
117
118 if (fPrintLevel > 0) {
119 std::cout << "ProfileLikelihoodTestStat::Evaluate - Use Offset mode \""
120 << fLOffset << "\" in creating NLL" << std::endl;
121 }
122
123 created = true ;
124 if (fPrintLevel > 1) std::cout << "creating NLL " << &*fNll << " with data = " << &data << std::endl ;
125 }
126 if (reuse && !created) {
127 if (fPrintLevel > 1) std::cout << "reusing NLL " << &*fNll << " new data = " << &data << std::endl ;
128 fNll->setData(data,false) ;
129 }
130 // print data in case of number counting (simple data sets)
131 if (fPrintLevel > 1 && data.numEntries() == 1) {
132 std::cout << "Data set used is: ";
133 RooStats::PrintListContent(*data.get(0), std::cout);
134 }
135
136
137 // make sure we set the variables attached to this nll
138 std::unique_ptr<RooArgSet> attachedSet{fNll->getVariables()};
139
142
143 ///////////////////////////////////////////////////////////////////////
144 // New profiling based on RooMinimizer (allows for Minuit2)
145 // based on major speed increases seen by CMS for complex problems
146
147
148 // other order
149 // get the numerator
151
152 tsw.Stop();
153 double createTime = tsw.CpuTime();
154 tsw.Start();
155
156 // get the denominator
157 double uncondML = 0;
158 double fit_favored_mu = 0;
159 int statusD = 0;
160 if (type != 2) {
161 if (!minimizationNeeded(*attachedSet)) {
162 uncondML = fNll->getVal();
163 } else {
164 if (fPrintLevel>1) std::cout << "Do unconditional fit" << std::endl;
165 std::tie(uncondML, statusD) = minimizeNLL("fitUncond_");
166 }
167
168 // get best fit value for one-sided interval
169 if (firstPOI) fit_favored_mu = attachedSet->getRealValue(firstPOI->GetName()) ;
170 }
171 tsw.Stop();
172 double fitTime1 = tsw.CpuTime();
173
174 //double ret = 0;
175 int statusN = 0;
176 tsw.Start();
177
178 double condML = 0;
179
180 bool doConditionalFit = (type != 1);
181
182 // skip the conditional ML (the numerator) only when fit value is smaller than test value
183 if (!fSigned && type==0 &&
184 ((fLimitType==oneSided && fit_favored_mu >= initial_mu_value) ||
185 (fLimitType==oneSidedDiscovery && fit_favored_mu <= initial_mu_value))) {
186 doConditionalFit = false;
188 }
189
190 if (doConditionalFit) {
191
192 if (fPrintLevel>1) std::cout << "Do conditional fit " << std::endl;
193
194
195 // std::cout <<" reestablish snapshot"<< std::endl;
196 attachedSet->assign(*snap);
197
198
199 // set the POI to constant
200 for (auto *tmpPar : paramsOfInterest) {
201 RooRealVar *tmpParA = dynamic_cast<RooRealVar *>(attachedSet->find(tmpPar->GetName()));
202 if (tmpParA) tmpParA->setConstant();
203 }
204
205
206 // in case no nuisance parameters are present
207 // no need to minimize just evaluate the nll
208 if (!minimizationNeeded(*attachedSet)) {
209 // be sure to evaluate with offsets
210 if (fLOffset == "initial") RooAbsReal::setHideOffset(false);
211 condML = fNll->getVal();
212 if (fLOffset == "initial") RooAbsReal::setHideOffset(true);
213 }
214 else {
215 std::tie(condML, statusN) = minimizeNLL("fitCond_");
216 }
217
218 }
219
220 tsw.Stop();
221 double fitTime2 = tsw.CpuTime();
222
223 double pll = 0;
224 if (type != 0) {
225 // for conditional only or unconditional fits
226 // need to compute nll value without the offset
227 if (fLOffset == "initial") {
229 pll = fNll->getVal();
230 }
231 else {
232 if (type == 1) {
233 pll = uncondML;
234 } else if (type == 2) {
235 pll = condML;
236 }
237 }
238 }
239 else { // type == 0
240 // for standard profile likelihood evaluations
241 pll = condML-uncondML;
242
243 if (fSigned) {
244 if (pll<0.0) {
245 if (fPrintLevel > 0) std::cout << "pll is negative - setting it to zero " << std::endl;
246 pll = 0.0; // bad fit
247 }
248 if (fLimitType==oneSidedDiscovery ? (fit_favored_mu < initial_mu_value)
250 pll = -pll;
251 }
252 }
253
254 if (fPrintLevel > 0) {
255 std::cout << "EvaluateProfileLikelihood - ";
256 if (type <= 1)
257 std::cout << "mu hat = " << fit_favored_mu << ", uncond ML = " << uncondML;
258 if (type != 1)
259 std::cout << ", cond ML = " << condML;
260 if (type == 0)
261 std::cout << " pll = " << pll;
262 std::cout << " time (create/fit1/2) " << createTime << " , " << fitTime1 << " , " << fitTime2
263 << std::endl;
264 }
265
266
267 // need to restore the values ?
269
270 delete origAttachedSet;
271 delete snap;
272
273 if (!reuse) {
274 fNll.reset();
275 }
276
277 RooMsgService::instance().setGlobalKillBelow(msglevel);
278
279 if(statusN!=0 || statusD!=0) {
280 return -1; // indicate failed fit (WVE is not used anywhere yet)
281 }
282
283 return pll;
284
285 }
286
287////////////////////////////////////////////////////////////////////////////////
288/// find minimum of NLL using RooMinimizer
289
290std::unique_ptr<RooFitResult> RooStats::ProfileLikelihoodTestStat::GetMinNLL() {
291
292 const auto& config = GetGlobalRooStatsConfig();
293 RooMinimizer minim(*fNll);
294 minim.setStrategy(fStrategy);
295 minim.setEvalErrorWall(config.useEvalErrorWall);
296 //LM: RooMinimizer.setPrintLevel has +1 offset - so subtract here -1 + an extra -1
297 int level = (fPrintLevel == 0) ? -1 : fPrintLevel -2;
298 minim.setPrintLevel(level);
299 minim.setEps(fTolerance);
300 // this causes a memory leak
301 minim.optimizeConst(2);
302 TString minimizer = fMinimizer;
304 if (algorithm == "Migrad") algorithm = "Minimize"; // prefer to use Minimize instead of Migrad
305 int status;
306 for (int tries = 1, maxtries = 4; tries <= maxtries; ++tries) {
307 status = minim.minimize(minimizer,algorithm);
308 if (status%1000 == 0) { // ignore errors from Improve
309 break;
310 } else if (tries < maxtries) {
311 std::cout << " ----> Doing a re-scan first" << std::endl;
312 minim.minimize(minimizer,"Scan");
313 if (tries == 2) {
314 if (fStrategy == 0 ) {
315 std::cout << " ----> trying with strategy = 1" << std::endl;
316 minim.setStrategy(1);
317 }
318 else
319 tries++; // skip this trial if strategy is already 1
320 }
321 if (tries == 3) {
322 std::cout << " ----> trying with improve" << std::endl;
323 minimizer = "Minuit";
324 algorithm = "migradimproved";
325 }
326 }
327 }
328
329 //how to get cov quality faster?
330 return std::unique_ptr<RooFitResult>{minim.save()};
331 //minim.optimizeConst(false);
332}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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()
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
static void setHideOffset(bool flag)
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Wrapper class around ROOT::Math::Minimizer that provides a seamless interface between the minimizer f...
static RooMsgService & instance()
Return reference to singleton instance.
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.
std::pair< double, int > minimizeNLL(std::string const &prefix)
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...
bool minimizationNeeded(RooArgSet allParams) const
Check if there are non-const parameters so it is worth to do the minimization.
std::unique_ptr< RooFitResult > GetMinNLL()
find minimum of NLL using RooMinimizer
Stopwatch class.
Definition TStopwatch.h:28
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