Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooSimultaneous.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooSimultaneous.cxx
19\class RooSimultaneous
20\ingroup Roofitcore
21
22RooSimultaneous facilitates simultaneous fitting of multiple PDFs
23to subsets of a given dataset.
24The class takes an index category, which is used as a selector
25for PDFs, and a list of PDFs, each associated
26with a state of the index category. RooSimultaneous always returns
27the value of the PDF that is associated with the current value
28of the index category.
29
30Extended likelihood fitting is supported if all components support
31extended likelihood mode. The expected number of events by a RooSimultaneous
32is that of the component p.d.f. selected by the index category.
33
34The index category can be accessed using indexCategory().
35
36###Generating events
37When generating events from a RooSimultaneous, the index category has to be added to
38the dataset. Further, the PDF needs to know the relative probabilities of each category, i.e.,
39how many events are in which category. This can be achieved in two ways:
40- Generating with proto data that have category entries: An event from the same category as
41in the proto data is created for each event in the proto data.
42See RooAbsPdf::generate(const RooArgSet&,const RooDataSet&,Int_t,bool,bool,bool) const.
43- No proto data: A category is chosen randomly.
44\note This requires that the PDFs building the simultaneous are extended. In this way,
45the relative probability of each category can be calculated from the number of events
46in each category.
47**/
48
49#include "RooSimultaneous.h"
51#include "RooPlot.h"
52#include "RooRealVar.h"
53#include "RooAddPdf.h"
54#include "RooAbsData.h"
55#include "Roo1DTable.h"
56#include "RooSimGenContext.h"
58#include "RooDataSet.h"
59#include "RooCmdConfig.h"
60#include "RooNameReg.h"
61#include "RooGlobalFunc.h"
62#include "RooMsgService.h"
63#include "RooCategory.h"
64#include "RooSuperCategory.h"
65#include "RooDataHist.h"
66#include "RooRandom.h"
67#include "RooArgSet.h"
68#include "RooBinSamplingPdf.h"
69
70#include "ROOT/StringUtils.hxx"
71
72#include <iostream>
73
74namespace {
75
76std::map<std::string, RooAbsPdf *> createPdfMap(const RooArgList &inPdfList, RooAbsCategoryLValue &inIndexCat)
77{
78 std::map<std::string, RooAbsPdf *> pdfMap;
79 auto indexCatIt = inIndexCat.begin();
80 for (unsigned int i = 0; i < inPdfList.size(); ++i) {
81 auto pdf = static_cast<RooAbsPdf *>(&inPdfList[i]);
82 const auto &nameIdx = (*indexCatIt++);
83 pdfMap[nameIdx.first] = pdf;
84 }
85 return pdfMap;
86}
87
88} // namespace
89
91
92void RooSimultaneous::InitializationOutput::addPdf(const RooAbsPdf &pdf, std::string const &catLabel)
93{
94 finalPdfs.push_back(&pdf);
95 finalCatLabels.emplace_back(catLabel);
96}
97
98using namespace std;
99
101
102
103
104////////////////////////////////////////////////////////////////////////////////
105/// Constructor with index category. PDFs associated with indexCat
106/// states can be added after construction with the addPdf() function.
107///
108/// RooSimultaneous can function without having a PDF associated
109/// with every single state. The normalization in such cases is taken
110/// from the number of registered PDFs, but getVal() will assert if
111/// when called for an unregistered index state.
112
113RooSimultaneous::RooSimultaneous(const char *name, const char *title,
114 RooAbsCategoryLValue& inIndexCat) :
115 RooSimultaneous{name, title, std::map<std::string, RooAbsPdf*>{}, inIndexCat}
116{
117}
118
119
120////////////////////////////////////////////////////////////////////////////////
121/// Constructor from index category and full list of PDFs.
122/// In this constructor form, a PDF must be supplied for each indexCat state
123/// to avoid ambiguities. The PDFs are associated with the states of the
124/// index category as they appear when iterating through the category states
125/// with RooAbsCategory::begin() and RooAbsCategory::end(). This usually means
126/// they are associated by ascending index numbers.
127///
128/// PDFs may not overlap (i.e. share any variables) with the index category (function)
129
130RooSimultaneous::RooSimultaneous(const char *name, const char *title,
131 const RooArgList& inPdfList, RooAbsCategoryLValue& inIndexCat) :
132 RooSimultaneous{name, title, createPdfMap(inPdfList, inIndexCat), inIndexCat}
133{
134 if (inPdfList.size() != inIndexCat.size()) {
135 std::stringstream errMsg;
136 errMsg << "RooSimultaneous::ctor(" << GetName()
137 << " ERROR: Number PDF list entries must match number of index category states, no PDFs added";
138 coutE(InputArguments) << errMsg.str() << std::endl;
139 throw std::invalid_argument(errMsg.str());
140 }
141}
142
143
144////////////////////////////////////////////////////////////////////////////////
145
146RooSimultaneous::RooSimultaneous(const char *name, const char *title, std::map<string, RooAbsPdf *> pdfMap,
147 RooAbsCategoryLValue &inIndexCat)
148 : RooSimultaneous(name, title, std::move(*initialize(name ? name : "", inIndexCat, pdfMap)))
149{
150}
151
153 : RooAbsPdf(name, title),
154 _plotCoefNormSet("!plotCoefNormSet", "plotCoefNormSet", this, false, false),
155 _partIntMgr(this, 10),
156 _indexCat("indexCat", "Index category", this, *initInfo.indexCat)
157{
158 for (std::size_t i = 0; i < initInfo.finalPdfs.size(); ++i) {
159 addPdf(*initInfo.finalPdfs[i], initInfo.finalCatLabels[i].c_str());
160 }
161
162 // Take ownership of eventual super category
163 if (initInfo.superIndex) {
164 addOwnedComponents(std::move(initInfo.superIndex));
165 }
166}
167
168/// \cond ROOFIT_INTERNAL
169
170// This class cannot be locally defined in initialize as it cannot be
171// used as a template argument in that case
172namespace RooSimultaneousAux {
173 struct CompInfo {
174 RooAbsPdf* pdf ;
175 RooSimultaneous* simPdf ;
176 const RooAbsCategoryLValue* subIndex ;
177 std::unique_ptr<RooArgSet> subIndexComps;
178 } ;
179}
180
181/// \endcond
182
183std::unique_ptr<RooSimultaneous::InitializationOutput>
185 std::map<std::string, RooAbsPdf *> const& pdfMap)
186
187{
188 auto out = std::make_unique<RooSimultaneous::InitializationOutput>();
189 out->indexCat = &inIndexCat;
190
191 // First see if there are any RooSimultaneous input components
192 bool simComps(false) ;
193 for (auto const& item : pdfMap) {
194 if (dynamic_cast<RooSimultaneous*>(item.second)) {
195 simComps = true ;
196 break ;
197 }
198 }
199
200 // If there are no simultaneous component p.d.f. do simple processing through addPdf()
201 if (!simComps) {
202 for (auto const& item : pdfMap) {
203 out->addPdf(*item.second,item.first);
204 }
205 return out;
206 }
207
208 std::string msgPrefix = "RooSimultaneous::initialize(" + name + ") ";
209
210 // Issue info message that we are about to do some rearranging
211 oocoutI(nullptr, InputArguments) << msgPrefix << "INFO: one or more input component of simultaneous p.d.f.s are"
212 << " simultaneous p.d.f.s themselves, rewriting composite expressions as one-level simultaneous p.d.f. in terms of"
213 << " final constituents and extended index category" << std::endl;
214
215
216 RooArgSet allAuxCats ;
217 std::map<string,RooSimultaneousAux::CompInfo> compMap ;
218 for (auto const& item : pdfMap) {
219 RooSimultaneousAux::CompInfo ci ;
220 ci.pdf = item.second ;
221 RooSimultaneous* simComp = dynamic_cast<RooSimultaneous*>(item.second) ;
222 if (simComp) {
223 ci.simPdf = simComp ;
224 ci.subIndex = &simComp->indexCat() ;
225 ci.subIndexComps = simComp->indexCat().isFundamental()
226 ? std::make_unique<RooArgSet>(simComp->indexCat())
227 : std::unique_ptr<RooArgSet>(simComp->indexCat().getVariables());
228 allAuxCats.add(*ci.subIndexComps,true) ;
229 } else {
230 ci.simPdf = nullptr;
231 ci.subIndex = nullptr;
232 }
233 compMap[item.first] = std::move(ci);
234 }
235
236 // Construct the 'superIndex' from the nominal index category and all auxiliary components
237 RooArgSet allCats(inIndexCat) ;
238 allCats.add(allAuxCats) ;
239 std::string siname = name + "_index";
240 out->superIndex = std::make_unique<RooSuperCategory>(siname.c_str(),siname.c_str(),allCats) ;
241 auto *superIndex = out->superIndex.get();
242 out->indexCat = superIndex;
243
244 // Now process each of original pdf/state map entries
245 for (auto const& citem : compMap) {
246
247 RooArgSet repliCats(allAuxCats) ;
248 if (citem.second.subIndexComps) {
249 repliCats.remove(*citem.second.subIndexComps) ;
250 }
251 inIndexCat.setLabel(citem.first.c_str()) ;
252
253 if (!citem.second.simPdf) {
254
255 // Entry is a plain p.d.f. assign it to every state permutation of the repliCats set
256 RooSuperCategory repliSuperCat("tmp","tmp",repliCats) ;
257
258 // Iterator over all states of repliSuperCat
259 for (const auto& nameIdx : repliSuperCat) {
260 // Set value
261 repliSuperCat.setLabel(nameIdx.first) ;
262 // Retrieve corresponding label of superIndex
263 string superLabel = superIndex->getCurrentLabel() ;
264 out->addPdf(*citem.second.pdf,superLabel);
265 oocxcoutD(static_cast<RooAbsArg*>(nullptr), InputArguments) << msgPrefix
266 << "assigning pdf " << citem.second.pdf->GetName() << " to super label " << superLabel << endl ;
267 }
268 } else {
269
270 // Entry is a simultaneous p.d.f
271
272 if (repliCats.empty()) {
273
274 // Case 1 -- No replication of components of RooSim component are required
275
276 for (const auto& type : *citem.second.subIndex) {
277 const_cast<RooAbsCategoryLValue*>(citem.second.subIndex)->setLabel(type.first.c_str());
278 string superLabel = superIndex->getCurrentLabel() ;
279 RooAbsPdf* compPdf = citem.second.simPdf->getPdf(type.first);
280 if (compPdf) {
281 out->addPdf(*compPdf,superLabel);
282 oocxcoutD(static_cast<RooAbsArg*>(nullptr), InputArguments) << msgPrefix
283 << "assigning pdf " << compPdf->GetName() << "(member of " << citem.second.pdf->GetName()
284 << ") to super label " << superLabel << endl ;
285 } else {
286 oocoutW(nullptr, InputArguments) << msgPrefix << "WARNING: No p.d.f. associated with label "
287 << type.second << " for component RooSimultaneous p.d.f " << citem.second.pdf->GetName()
288 << "which is associated with master index label " << citem.first << endl ;
289 }
290 }
291
292 } else {
293
294 // Case 2 -- Replication of components of RooSim component are required
295
296 // Make replication supercat
297 RooSuperCategory repliSuperCat("tmp","tmp",repliCats) ;
298
299 for (const auto& stype : *citem.second.subIndex) {
300 const_cast<RooAbsCategoryLValue*>(citem.second.subIndex)->setLabel(stype.first.c_str());
301
302 for (const auto& nameIdx : repliSuperCat) {
303 repliSuperCat.setLabel(nameIdx.first) ;
304 const string superLabel = superIndex->getCurrentLabel() ;
305 RooAbsPdf* compPdf = citem.second.simPdf->getPdf(stype.first);
306 if (compPdf) {
307 out->addPdf(*compPdf,superLabel);
308 oocxcoutD(static_cast<RooAbsArg*>(nullptr), InputArguments) << msgPrefix
309 << "assigning pdf " << compPdf->GetName() << "(member of " << citem.second.pdf->GetName()
310 << ") to super label " << superLabel << endl ;
311 } else {
312 oocoutW(nullptr, InputArguments) << msgPrefix << "WARNING: No p.d.f. associated with label "
313 << stype.second << " for component RooSimultaneous p.d.f " << citem.second.pdf->GetName()
314 << "which is associated with master index label " << citem.first << endl ;
315 }
316 }
317 }
318 }
319 }
320 }
321
322 return out;
323}
324
325
326////////////////////////////////////////////////////////////////////////////////
327/// Copy constructor
328
330 RooAbsPdf(other,name),
331 _plotCoefNormSet("!plotCoefNormSet",this,other._plotCoefNormSet),
332 _plotCoefNormRange(other._plotCoefNormRange),
333 _partIntMgr(other._partIntMgr,this),
334 _indexCat("indexCat",this,other._indexCat),
335 _numPdf(other._numPdf)
336{
337 // Copy proxy list
338 for(auto* proxy : static_range_cast<RooRealProxy*>(other._pdfProxyList)) {
339 _pdfProxyList.Add(new RooRealProxy(proxy->GetName(),this,*proxy)) ;
340 }
341}
342
343
344
345////////////////////////////////////////////////////////////////////////////////
346/// Destructor
347
349{
351}
352
353
354
355////////////////////////////////////////////////////////////////////////////////
356/// Return the p.d.f associated with the given index category name
357
359{
360 RooRealProxy* proxy = static_cast<RooRealProxy*>(_pdfProxyList.FindObject(catName.c_str()));
361 return proxy ? static_cast<RooAbsPdf*>(proxy->absArg()) : nullptr;
362}
363
364
365
366////////////////////////////////////////////////////////////////////////////////
367/// Associate given PDF with index category state label 'catLabel'.
368/// The name state must be already defined in the index category.
369///
370/// RooSimultaneous can function without having a PDF associated
371/// with every single state. The normalization in such cases is taken
372/// from the number of registered PDFs, but getVal() will fail if
373/// called for an unregistered index state.
374///
375/// PDFs may not overlap (i.e. share any variables) with the index category (function).
376/// \param[in] pdf PDF to be added.
377/// \param[in] catLabel Name of the category state to be associated to the PDF.
378/// \return `true` in case of failure.
379
380bool RooSimultaneous::addPdf(const RooAbsPdf& pdf, const char* catLabel)
381{
382 // PDFs cannot overlap with the index category
383 if (pdf.dependsOn(_indexCat.arg())) {
384 coutE(InputArguments) << "RooSimultaneous::addPdf(" << GetName() << "): PDF '" << pdf.GetName()
385 << "' overlaps with index category '" << _indexCat.arg().GetName() << "'."<< endl ;
386 return true ;
387 }
388
389 // Each index state can only have one PDF associated with it
390 if (_pdfProxyList.FindObject(catLabel)) {
391 coutE(InputArguments) << "RooSimultaneous::addPdf(" << GetName() << "): index state '"
392 << catLabel << "' has already an associated PDF." << endl ;
393 return true ;
394 }
395
396 const RooSimultaneous* simPdf = dynamic_cast<const RooSimultaneous*>(&pdf) ;
397 if (simPdf) {
398
399 coutE(InputArguments) << "RooSimultaneous::addPdf(" << GetName()
400 << ") ERROR: you cannot add a RooSimultaneous component to a RooSimultaneous using addPdf()."
401 << " Use the constructor with RooArgList if input p.d.f.s or the map<string,RooAbsPdf&> instead." << endl ;
402 return true ;
403
404 } else {
405
406 // Create a proxy named after the associated index state
407 TObject* proxy = new RooRealProxy(catLabel,catLabel,this,const_cast<RooAbsPdf&>(pdf));
408 _pdfProxyList.Add(proxy) ;
409 _numPdf += 1 ;
410 }
411
412 return false ;
413}
414
415
416
417
418
419////////////////////////////////////////////////////////////////////////////////
420/// Examine the pdf components and check if one of them can be extended or must be extended.
421/// It is enough to have one component that can be extended or must be extended to return the flag in
422/// the total simultaneous pdf.
423
425{
426 bool anyCanExtend(false) ;
427 bool anyMustExtend(false) ;
428
429 for (Int_t i=0 ; i<_numPdf ; i++) {
431 if (proxy) {
432 RooAbsPdf* pdf = (RooAbsPdf*) proxy->absArg() ;
433 //cout << " now processing pdf " << pdf->GetName() << endl;
434 if (pdf->canBeExtended()) {
435 //cout << "RooSim::extendedMode(" << GetName() << ") component " << pdf->GetName() << " can be extended"
436 // << endl;
437 anyCanExtend = true;
438 }
439 if (pdf->mustBeExtended()) {
440 //cout << "RooSim::extendedMode(" << GetName() << ") component " << pdf->GetName() << " MUST be extended" << endl;
441 anyMustExtend = true;
442 }
443 }
444 }
445 if (anyMustExtend) {
446 //cout << "RooSim::extendedMode(" << GetName() << ") returning MustBeExtended" << endl ;
447 return MustBeExtended ;
448 }
449 if (anyCanExtend) {
450 //cout << "RooSim::extendedMode(" << GetName() << ") returning CanBeExtended" << endl ;
451 return CanBeExtended ;
452 }
453 //cout << "RooSim::extendedMode(" << GetName() << ") returning CanNotBeExtended" << endl ;
454 return CanNotBeExtended ;
455}
456
457
458
459
460////////////////////////////////////////////////////////////////////////////////
461/// Return the current value:
462/// the value of the PDF associated with the current index category state
463
465{
466 // Retrieve the proxy by index name
468
469 //assert(proxy!=0) ;
470 if (proxy==nullptr) return 0 ;
471
472 // Calculate relative weighting factor for sim-pdfs of all extendable components
473 double catFrac(1) ;
474 if (canBeExtended()) {
475 double nEvtCat = ((RooAbsPdf*)(proxy->absArg()))->expectedEvents(_normSet) ;
476
477 double nEvtTot(0) ;
478 for(auto * proxy2 : static_range_cast<RooRealProxy*>(_pdfProxyList)) {
479 nEvtTot += ((RooAbsPdf*)(proxy2->absArg()))->expectedEvents(_normSet) ;
480 }
481 catFrac=nEvtCat/nEvtTot ;
482 }
483
484 // Return the selected PDF value, normalized by the number of index states
485 return ((RooAbsPdf*)(proxy->absArg()))->getVal(_normSet)*catFrac ;
486}
487
488
489
490////////////////////////////////////////////////////////////////////////////////
491/// Return the number of expected events: If the index is in nset,
492/// then return the sum of the expected events of all components,
493/// otherwise return the number of expected events of the PDF
494/// associated with the current index category state
495
497{
498 if (nset->contains(_indexCat.arg())) {
499
500 double sum(0) ;
501
502 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdfProxyList)) {
503 sum += ((RooAbsPdf*)(proxy->absArg()))->expectedEvents(nset) ;
504 }
505
506 return sum ;
507
508 } else {
509
510 // Retrieve the proxy by index name
512
513 //assert(proxy!=0) ;
514 if (proxy==nullptr) return 0 ;
515
516 // Return the selected PDF value, normalized by the number of index states
517 return ((RooAbsPdf*)(proxy->absArg()))->expectedEvents(nset);
518 }
519}
520
521
522
523////////////////////////////////////////////////////////////////////////////////
524/// Forward determination of analytical integration capabilities to component p.d.f.s
525/// A unique code is assigned to the combined integration capabilities of all associated
526/// p.d.f.s
527
529 const RooArgSet* normSet, const char* rangeName) const
530{
531 // Declare that we can analytically integrate all requested observables
532 analVars.add(allVars) ;
533
534 // Retrieve (or create) the required partial integral list
535 Int_t code ;
536
537 // Check if this configuration was created before
538 CacheElem* cache = (CacheElem*) _partIntMgr.getObj(normSet,&analVars,nullptr,RooNameReg::ptr(rangeName)) ;
539 if (cache) {
540 code = _partIntMgr.lastIndex() ;
541 return code+1 ;
542 }
543 cache = new CacheElem ;
544
545 // Create the partial integral set for this request
546 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdfProxyList)) {
547 cache->_partIntList.addOwned(std::unique_ptr<RooAbsReal>{proxy->arg().createIntegral(analVars,normSet,nullptr,rangeName)});
548 }
549
550 // Store the partial integral list and return the assigned code ;
551 code = _partIntMgr.setObj(normSet,&analVars,cache,RooNameReg::ptr(rangeName)) ;
552
553 return code+1 ;
554}
555
556
557
558////////////////////////////////////////////////////////////////////////////////
559/// Return analytical integration defined by given code
560
561double RooSimultaneous::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* /*rangeName*/) const
562{
563 // No integration scenario
564 if (code==0) {
565 return getVal(normSet) ;
566 }
567
568 // Partial integration scenarios, rangeName already encoded in 'code'
569 CacheElem* cache = (CacheElem*) _partIntMgr.getObjByIndex(code-1) ;
570
572 Int_t idx = _pdfProxyList.IndexOf(proxy) ;
573 return ((RooAbsReal*)cache->_partIntList.at(idx))->getVal(normSet) ;
574}
575
576
577
578
579
580
581////////////////////////////////////////////////////////////////////////////////
582/// Back-end for plotOn() implementation on RooSimultaneous which
583/// needs special handling because a RooSimultaneous PDF cannot
584/// project out its index category via integration. plotOn() will
585/// abort if this is requested without providing a projection dataset.
586
588{
589 // Sanity checks
590 if (plotSanityChecks(frame)) return frame ;
591
592 // Extract projection configuration from command list
593 RooCmdConfig pc("RooSimultaneous::plotOn(" + std::string(GetName()) + ")");
594 pc.defineString("sliceCatState","SliceCat",0,"",true) ;
595 pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
596 pc.defineInt("scaleType","Normalization",0,RooAbsPdf::Relative) ;
597 pc.defineObject("sliceCatList","SliceCat",0,nullptr,true) ;
598 // This dummy is needed for plotOn to recognize the "SliceCatMany" command.
599 // It is not used directly, but the "SliceCat" commands are nested in it.
600 // Removing this dummy definition results in "ERROR: unrecognized command: SliceCatMany".
601 pc.defineObject("dummy1","SliceCatMany",0) ;
602 pc.defineSet("projSet","Project",0) ;
603 pc.defineSet("sliceSet","SliceVars",0) ;
604 pc.defineSet("projDataSet","ProjData",0) ;
605 pc.defineObject("projData","ProjData",1) ;
606 pc.defineMutex("Project","SliceVars") ;
607 pc.allowUndefined() ; // there may be commands we don't handle here
608
609 // Process and check varargs
610 pc.process(cmdList) ;
611 if (!pc.ok(true)) {
612 return frame ;
613 }
614
615 const RooAbsData* projData = (const RooAbsData*) pc.getObject("projData") ;
616 const RooArgSet* projDataSet = pc.getSet("projDataSet");
617 const RooArgSet* sliceSetTmp = pc.getSet("sliceSet") ;
618 std::unique_ptr<RooArgSet> sliceSet( sliceSetTmp ? ((RooArgSet*) sliceSetTmp->Clone()) : nullptr );
619 const RooArgSet* projSet = pc.getSet("projSet") ;
620 double scaleFactor = pc.getDouble("scaleFactor") ;
621 ScaleType stype = (ScaleType) pc.getInt("scaleType") ;
622
623
624 // Look for category slice arguments and add them to the master slice list if found
625 const char* sliceCatState = pc.getString("sliceCatState",nullptr,true) ;
626 const RooLinkedList& sliceCatList = pc.getObjectList("sliceCatList") ;
627 if (sliceCatState) {
628
629 // Make the master slice set if it doesnt exist
630 if (!sliceSet) {
631 sliceSet = std::make_unique<RooArgSet>();
632 }
633
634 // Prepare comma separated label list for parsing
635 auto catTokens = ROOT::Split(sliceCatState, ",");
636
637 // Loop over all categories provided by (multiple) Slice() arguments
638 unsigned int tokenIndex = 0;
639 for(auto * scat : static_range_cast<RooCategory*>(sliceCatList)) {
640 const char* slabel = tokenIndex >= catTokens.size() ? nullptr : catTokens[tokenIndex++].c_str();
641
642 if (slabel) {
643 // Set the slice position to the value indicated by slabel
644 scat->setLabel(slabel) ;
645 // Add the slice category to the master slice set
646 sliceSet->add(*scat,false) ;
647 }
648 }
649 }
650
651 // Check if we have a projection dataset
652 if (!projData) {
653 coutE(InputArguments) << "RooSimultaneous::plotOn(" << GetName() << ") ERROR: must have a projection dataset for index category" << endl ;
654 return frame ;
655 }
656
657 // Make list of variables to be projected
658 RooArgSet projectedVars ;
659 if (sliceSet) {
660 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
661
662 // Take out the sliced variables
663 for (const auto sliceArg : *sliceSet) {
664 RooAbsArg* arg = projectedVars.find(sliceArg->GetName()) ;
665 if (arg) {
666 projectedVars.remove(*arg) ;
667 } else {
668 coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") slice variable "
669 << sliceArg->GetName() << " was not projected anyway" << endl ;
670 }
671 }
672 } else if (projSet) {
673 makeProjectionSet(frame->getPlotVar(),projSet,projectedVars,false) ;
674 } else {
675 makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,true) ;
676 }
677
678 bool projIndex(false) ;
679
680 if (!_indexCat.arg().isDerived()) {
681 // *** Error checking for a fundamental index category ***
682 //cout << "RooSim::plotOn: index is fundamental" << endl ;
683
684 // Check that the provided projection dataset contains our index variable
685 if (!projData->get()->find(_indexCat.arg().GetName())) {
686 coutE(Plotting) << "RooSimultaneous::plotOn(" << GetName() << ") ERROR: Projection over index category "
687 << "requested, but projection data set doesn't contain index category" << endl ;
688 return frame ;
689 }
690
691 if (projectedVars.find(_indexCat.arg().GetName())) {
692 projIndex=true ;
693 }
694
695 } else {
696 // *** Error checking for a composite index category ***
697
698 // Determine if any servers of the index category are in the projectedVars
699 RooArgSet projIdxServers ;
700 bool anyServers(false) ;
701 for (const auto server : flattenedCatList()) {
702 if (projectedVars.find(server->GetName())) {
703 anyServers=true ;
704 projIdxServers.add(*server) ;
705 }
706 }
707
708 // Check that the projection dataset contains all the
709 // index category components we're projecting over
710
711 // Determine if all projected servers of the index category are in the projection dataset
712 bool allServers(true) ;
713 std::string missing;
714 for (const auto server : projIdxServers) {
715 if (!projData->get()->find(server->GetName())) {
716 allServers=false ;
717 missing = server->GetName();
718 }
719 }
720
721 if (!allServers) {
722 coutE(Plotting) << "RooSimultaneous::plotOn(" << GetName()
723 << ") ERROR: Projection dataset doesn't contain complete set of index categories to do projection."
724 << "\n\tcategory " << missing << " is missing." << endl ;
725 return frame ;
726 }
727
728 if (anyServers) {
729 projIndex = true ;
730 }
731 }
732
733 // Calculate relative weight fractions of components
734 std::unique_ptr<Roo1DTable> wTable( projData->table(_indexCat.arg()) );
735
736 // Clone the index category to be able to cycle through the category states for plotting without
737 // affecting the category state of our instance
738 RooArgSet idxCloneSet;
739 RooArgSet(*_indexCat).snapshot(idxCloneSet, true);
740 auto idxCatClone = static_cast<RooAbsCategoryLValue*>( idxCloneSet.find(_indexCat->GetName()) );
741 assert(idxCatClone);
742
743 // Make list of category columns to exclude from projection data
744 std::unique_ptr<RooArgSet> idxCompSliceSet( idxCatClone->getObservables(frame->getNormVars()) );
745
746 // If we don't project over the index, just do the regular plotOn
747 if (!projIndex) {
748
749 coutI(Plotting) << "RooSimultaneous::plotOn(" << GetName() << ") plot on " << frame->getPlotVar()->GetName()
750 << " represents a slice in the index category (" << _indexCat.arg().GetName() << ")" << endl ;
751
752 // Reduce projData: take out fitCat (component) columns and entries that don't match selected slice
753 // Construct cut string to only select projection data event that match the current slice
754
755 // Make cut string to exclude rows from projection data
756 TString cutString ;
757 bool first(true) ;
758 for (const auto arg : *idxCompSliceSet) {
759 auto idxComp = static_cast<RooCategory*>(arg);
760 RooAbsArg* slicedComponent = nullptr;
761 if (sliceSet && (slicedComponent = sliceSet->find(*idxComp)) != nullptr) {
762 auto theCat = static_cast<const RooAbsCategory*>(slicedComponent);
763 idxComp->setIndex(theCat->getCurrentIndex(), false);
764 }
765
766 if (!first) {
767 cutString.Append("&&") ;
768 } else {
769 first=false ;
770 }
771 cutString.Append(Form("%s==%d",idxComp->GetName(),idxComp->getCurrentIndex())) ;
772 }
773
774 // Make temporary projData without RooSim index category components
775 RooArgSet projDataVars(*projData->get()) ;
776 projDataVars.remove(*idxCompSliceSet,true,true) ;
777
778 std::unique_ptr<RooAbsData> projDataTmp( const_cast<RooAbsData*>(projData)->reduce(projDataVars,cutString) );
779
780 // Override normalization and projection dataset
781 RooCmdArg tmp1 = RooFit::Normalization(scaleFactor*wTable->getFrac(idxCatClone->getCurrentLabel()),stype) ;
782 RooCmdArg tmp2 = RooFit::ProjWData(*projDataSet,*projDataTmp) ;
783
784 // WVE -- do not adjust normalization for asymmetry plots
785 RooLinkedList cmdList2(cmdList) ;
786 if (!cmdList.find("Asymmetry")) {
787 cmdList2.Add(&tmp1) ;
788 }
789 cmdList2.Add(&tmp2) ;
790
791 // Plot single component
792 RooPlot* retFrame = getPdf(idxCatClone->getCurrentLabel())->plotOn(frame,cmdList2);
793 return retFrame ;
794 }
795
796 // If we project over the index, plot using a temporary RooAddPdf
797 // using the weights from the data as coefficients
798
799 // Build the list of indexCat components that are sliced
800 idxCompSliceSet->remove(projectedVars,true,true) ;
801
802 // Make a new expression that is the weighted sum of requested components
803 RooArgList pdfCompList ;
804 RooArgList wgtCompList ;
805//RooAbsPdf* pdf ;
806 double sumWeight(0) ;
807 for(auto * proxy : static_range_cast<RooRealProxy*>(_pdfProxyList)) {
808
809 idxCatClone->setLabel(proxy->name()) ;
810
811 // Determine if this component is the current slice (if we slice)
812 bool skip(false) ;
813 for (const auto idxSliceCompArg : *idxCompSliceSet) {
814 const auto idxSliceComp = static_cast<RooAbsCategory*>(idxSliceCompArg);
815 RooAbsCategory* idxComp = (RooAbsCategory*) idxCloneSet.find(idxSliceComp->GetName()) ;
816 if (idxComp->getCurrentIndex()!=idxSliceComp->getCurrentIndex()) {
817 skip=true ;
818 break ;
819 }
820 }
821 if (skip) continue ;
822
823 // Instantiate a RRV holding this pdfs weight fraction
824 wgtCompList.addOwned(std::make_unique<RooRealVar>(proxy->name(),"coef",wTable->getFrac(proxy->name())));
825 sumWeight += wTable->getFrac(proxy->name()) ;
826
827 // Add the PDF to list list
828 pdfCompList.add(proxy->arg()) ;
829 }
830
831 TString plotVarName(GetName()) ;
832 RooAddPdf plotVar{plotVarName,"weighted sum of RS components",pdfCompList,wgtCompList};
833
834 // Fix appropriate coefficient normalization in plot function
835 if (!_plotCoefNormSet.empty()) {
836 plotVar.fixAddCoefNormalization(_plotCoefNormSet) ;
837 }
838
839 std::unique_ptr<RooAbsData> projDataTmp;
840 RooArgSet projSetTmp ;
841 if (projData) {
842
843 // Construct cut string to only select projection data event that match the current slice
844 TString cutString ;
845 if (!idxCompSliceSet->empty()) {
846 bool first(true) ;
847 for (const auto idxSliceCompArg : *idxCompSliceSet) {
848 const auto idxSliceComp = static_cast<RooAbsCategory*>(idxSliceCompArg);
849 if (!first) {
850 cutString.Append("&&") ;
851 } else {
852 first=false ;
853 }
854 cutString.Append(Form("%s==%d",idxSliceComp->GetName(),idxSliceComp->getCurrentIndex())) ;
855 }
856 }
857
858 // Make temporary projData without RooSim index category components
859 RooArgSet projDataVars(*projData->get()) ;
860 RooArgSet idxCatServers;
861 _indexCat.arg().getObservables(frame->getNormVars(), idxCatServers) ;
862
863 projDataVars.remove(idxCatServers,true,true) ;
864
865 if (!idxCompSliceSet->empty()) {
866 projDataTmp = std::unique_ptr<RooAbsData>{const_cast<RooAbsData*>(projData)->reduce(projDataVars,cutString)};
867 } else {
868 projDataTmp = std::unique_ptr<RooAbsData>{const_cast<RooAbsData*>(projData)->reduce(projDataVars)};
869 }
870
871
872
873 if (projSet) {
874 projSetTmp.add(*projSet) ;
875 projSetTmp.remove(idxCatServers,true,true);
876 }
877 }
878
879
880 if (_indexCat.arg().isDerived() && !idxCompSliceSet->empty()) {
881 coutI(Plotting) << "RooSimultaneous::plotOn(" << GetName() << ") plot on " << frame->getPlotVar()->GetName()
882 << " represents a slice in index category components " << *idxCompSliceSet << endl ;
883
884 RooArgSet idxCompProjSet;
885 _indexCat.arg().getObservables(frame->getNormVars(), idxCompProjSet) ;
886 idxCompProjSet.remove(*idxCompSliceSet,true,true) ;
887 if (!idxCompProjSet.empty()) {
888 coutI(Plotting) << "RooSimultaneous::plotOn(" << GetName() << ") plot on " << frame->getPlotVar()->GetName()
889 << " averages with data index category components " << idxCompProjSet << endl ;
890 }
891 } else {
892 coutI(Plotting) << "RooSimultaneous::plotOn(" << GetName() << ") plot on " << frame->getPlotVar()->GetName()
893 << " averages with data index category (" << _indexCat.arg().GetName() << ")" << endl ;
894 }
895
896
897 // Override normalization and projection dataset
898 RooLinkedList cmdList2(cmdList) ;
899
900 RooCmdArg tmp1 = RooFit::Normalization(scaleFactor*sumWeight,stype) ;
901 RooCmdArg tmp2 = RooFit::ProjWData(*projDataSet,*projDataTmp) ;
902 // WVE -- do not adjust normalization for asymmetry plots
903 if (!cmdList.find("Asymmetry")) {
904 cmdList2.Add(&tmp1) ;
905 }
906 cmdList2.Add(&tmp2) ;
907
908 RooPlot* frame2 ;
909 if (!projSetTmp.empty()) {
910 // Plot temporary function
911 RooCmdArg tmp3 = RooFit::Project(projSetTmp) ;
912 cmdList2.Add(&tmp3) ;
913 frame2 = plotVar.plotOn(frame,cmdList2) ;
914 } else {
915 // Plot temporary function
916 frame2 = plotVar.plotOn(frame,cmdList2) ;
917 }
918
919 return frame2 ;
920}
921
922
923////////////////////////////////////////////////////////////////////////////////
924/// Interface function used by test statistics to freeze choice of observables
925/// for interpretation of fraction coefficients. Needed here because a RooSimultaneous
926/// works like a RooAddPdf when plotted
927
928void RooSimultaneous::selectNormalization(const RooArgSet* normSet, bool /*force*/)
929{
931 if (normSet) _plotCoefNormSet.add(*normSet) ;
932}
933
934
935////////////////////////////////////////////////////////////////////////////////
936/// Interface function used by test statistics to freeze choice of range
937/// for interpretation of fraction coefficients. Needed here because a RooSimultaneous
938/// works like a RooAddPdf when plotted
939
940void RooSimultaneous::selectNormalizationRange(const char* normRange2, bool /*force*/)
941{
942 _plotCoefNormRange = RooNameReg::ptr(normRange2) ;
943}
944
945
946
947
948////////////////////////////////////////////////////////////////////////////////
949
951 const RooArgSet* auxProto, bool verbose, bool autoBinned, const char* binnedTag) const
952{
953 const char* idxCatName = _indexCat.arg().GetName() ;
954
955 if (vars.find(idxCatName) && prototype==nullptr
956 && (auxProto==nullptr || auxProto->empty())
957 && (autoBinned || (binnedTag && strlen(binnedTag)))) {
958
959 // Return special generator config that can also do binned generation for selected states
960 return new RooSimSplitGenContext(*this,vars,verbose,autoBinned,binnedTag) ;
961
962 } else {
963
964 // Return regular generator config ;
965 return genContext(vars,prototype,auxProto,verbose) ;
966 }
967}
968
969
970
971////////////////////////////////////////////////////////////////////////////////
972/// Return specialized generator context for simultaneous p.d.f.s
973
975 const RooArgSet* auxProto, bool verbose) const
976{
977 RooArgSet allVars{vars};
978 if(prototype) allVars.add(*prototype->get());
979
980 RooArgSet catsAmongAllVars;
981 allVars.selectCommon(flattenedCatList(), catsAmongAllVars);
982
983 // Not generating index cat: return context for pdf associated with present index state
984 if(catsAmongAllVars.empty()) {
985 auto* proxy = static_cast<RooRealProxy*>(_pdfProxyList.FindObject(_indexCat->getCurrentLabel()));
986 if (!proxy) {
987 coutE(InputArguments) << "RooSimultaneous::genContext(" << GetName()
988 << ") ERROR: no PDF associated with current state ("
989 << _indexCat.arg().GetName() << "=" << _indexCat.arg().getCurrentLabel() << ")" << endl ;
990 return nullptr;
991 }
992 return static_cast<RooAbsPdf*>(proxy->absArg())->genContext(vars,prototype,auxProto,verbose) ;
993 }
994
995 RooArgSet catsAmongProtoVars;
996 if(prototype) {
997 prototype->get()->selectCommon(flattenedCatList(), catsAmongProtoVars);
998
999 if(!catsAmongProtoVars.empty() && catsAmongProtoVars.size() != flattenedCatList().size()) {
1000 // Abort if we have only part of the servers
1001 coutE(Plotting) << "RooSimultaneous::genContext: ERROR: prototype must include either all "
1002 << " components of the RooSimultaneous index category or none " << std::endl;
1003 return nullptr;
1004 }
1005 }
1006
1007 return new RooSimGenContext(*this,vars,prototype,auxProto,verbose) ;
1008}
1009
1010
1011
1012
1013////////////////////////////////////////////////////////////////////////////////
1014
1016 const RooArgSet* nset,
1017 double scaleFactor,
1018 bool correctForBinVolume,
1019 bool showProgress) const
1020{
1021 if (RooAbsReal::fillDataHist (hist, nset, scaleFactor,
1022 correctForBinVolume, showProgress) == nullptr)
1023 return nullptr;
1024
1025 const double sum = hist->sumEntries();
1026 if (sum != 0) {
1027 for (int i=0 ; i<hist->numEntries() ; i++) {
1028 hist->set(i, hist->weight(i) / sum, 0.);
1029 }
1030 }
1031
1032 return hist;
1033}
1034
1035
1036
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Special generator interface for generation of 'global observables' -- for RooStats tools
1040
1042{
1043 // Make set with clone of variables (placeholder for output)
1044 RooArgSet globClone;
1045 whatVars.snapshot(globClone);
1046
1047 auto data = std::make_unique<RooDataSet>("gensimglobal","gensimglobal",whatVars);
1048
1049 for (Int_t i=0 ; i<nEvents ; i++) {
1050 for (const auto& nameIdx : indexCat()) {
1051
1052 // Get pdf associated with state from simpdf
1053 RooAbsPdf* pdftmp = getPdf(nameIdx.first);
1054
1055 // Generate only global variables defined by the pdf associated with this state
1056 RooArgSet globtmp;
1057 pdftmp->getObservables(&whatVars, globtmp) ;
1058 std::unique_ptr<RooDataSet> tmp{pdftmp->generate(globtmp,1)};
1059
1060 // Transfer values to output placeholder
1061 globClone.assign(*tmp->get(0)) ;
1062 }
1063 data->add(globClone) ;
1064 }
1065
1066 return RooFit::Detail::owningPtr(std::move(data));
1067}
1068
1069
1070/// Wraps the components of this RooSimultaneous in RooBinSamplingPdfs.
1071/// \param[in] data The dataset to be used in the eventual fit, used to figure
1072/// out the observables and whether the dataset is binned.
1073/// \param[in] precision Precision argument for all created RooBinSamplingPdfs.
1075
1076 if (precision < 0.) return;
1077
1078 RooArgSet newSamplingPdfs;
1079
1080 for (auto const &item : this->indexCat()) {
1081
1082 auto const &catName = item.first;
1083 auto &pdf = *this->getPdf(catName);
1084
1085 if (auto newSamplingPdf = RooBinSamplingPdf::create(pdf, data, precision)) {
1086 // Set the "ORIGNAME" attribute the indicate to
1087 // RooAbsArg::redirectServers() which pdf should be replaced by this
1088 // RooBinSamplingPdf in the RooSimultaneous.
1089 newSamplingPdf->setAttribute(
1090 (std::string("ORIGNAME:") + pdf.GetName()).c_str());
1091 newSamplingPdfs.addOwned(std::move(newSamplingPdf));
1092 }
1093 }
1094
1095 this->redirectServers(newSamplingPdfs, false, true);
1096 this->addOwnedComponents(std::move(newSamplingPdfs));
1097}
1098
1099
1100/// Wraps the components of this RooSimultaneous in RooBinSamplingPdfs, with a
1101/// different precision parameter for each component.
1102/// \param[in] data The dataset to be used in the eventual fit, used to figure
1103/// out the observables and whether the dataset is binned.
1104/// \param[in] precisions The map that gives the precision argument for each
1105/// component in the RooSimultaneous. The keys are the pdf names. If
1106/// there is no value for a given component, it will not use the bin
1107/// integration. Otherwise, the value has the same meaning than in
1108/// the IntegrateBins() command argument for RooAbsPdf::fitTo().
1109/// \param[in] useCategoryNames If this flag is set, the category names will be
1110/// used to look up the precision in the precisions map instead of
1111/// the pdf names.
1113 std::map<std::string, double> const& precisions,
1114 bool useCategoryNames /*=false*/) {
1115
1116 constexpr double defaultPrecision = -1.;
1117
1118 RooArgSet newSamplingPdfs;
1119
1120 for (auto const &item : this->indexCat()) {
1121
1122 auto const &catName = item.first;
1123 auto &pdf = *this->getPdf(catName);
1124 std::string pdfName = pdf.GetName();
1125
1126 auto found = precisions.find(useCategoryNames ? catName : pdfName);
1127 const double precision =
1128 found != precisions.end() ? found->second : defaultPrecision;
1129 if (precision < 0.)
1130 continue;
1131
1132 if (auto newSamplingPdf = RooBinSamplingPdf::create(pdf, data, precision)) {
1133 // Set the "ORIGNAME" attribute the indicate to
1134 // RooAbsArg::redirectServers() which pdf should be replaced by this
1135 // RooBinSamplingPdf in the RooSimultaneous.
1136 newSamplingPdf->setAttribute(
1137 (std::string("ORIGNAME:") + pdf.GetName()).c_str());
1138 newSamplingPdfs.addOwned(std::move(newSamplingPdf));
1139 }
1140 }
1141
1142 this->redirectServers(newSamplingPdfs, false, true);
1143 this->addOwnedComponents(std::move(newSamplingPdfs));
1144}
1145
1146/// Internal utility function to get a list of all category components for this
1147/// RooSimultaneous. The output contains only the index category if it is a
1148/// RooCategory, or the list of all category components if it is a
1149/// RooSuperCategory.
1151{
1152 // Note that the index category of a RooSimultaneous can only be of type
1153 // RooCategory or RooSuperCategory, because these are the only classes that
1154 // inherit from RooAbsCategoryLValue.
1155 if (auto superCat = dynamic_cast<RooSuperCategory const*>(&_indexCat.arg())) {
1156 return superCat->inputCatList();
1157 }
1158
1159 if(!_indexCatSet) {
1160 _indexCatSet = std::make_unique<RooArgSet>(_indexCat.arg());
1161 }
1162 return *_indexCatSet;
1163}
1164
1165namespace {
1166
1167void prefixArgs(RooAbsArg *arg, std::string const &prefix, RooArgSet const &normSet)
1168{
1169 if (!arg->getStringAttribute("__prefix__")) {
1170 arg->SetName((prefix + arg->GetName()).c_str());
1171 arg->setStringAttribute("__prefix__", prefix.c_str());
1172 }
1173 for (RooAbsArg *server : arg->servers()) {
1174 if (server->isFundamental() && normSet.find(*server)) {
1175 prefixArgs(server, prefix, normSet);
1176 server->setAttribute("__obs__");
1177 } else if (!server->isFundamental()) {
1178 prefixArgs(server, prefix, normSet);
1179 }
1180 }
1181}
1182
1183} // namespace
1184
1185std::unique_ptr<RooAbsArg>
1187{
1188 std::unique_ptr<RooSimultaneous> newSimPdf{static_cast<RooSimultaneous *>(this->Clone())};
1189
1190 const char *rangeName = this->getStringAttribute("RangeName");
1191 bool splitRange = this->getAttribute("SplitRange");
1192
1193 RooArgSet newPdfs;
1194 std::vector<std::string> catNames;
1195
1196 for (auto *proxy : static_range_cast<RooRealProxy *>(newSimPdf->_pdfProxyList)) {
1197 catNames.emplace_back(proxy->GetName());
1198 std::string const &catName = catNames.back();
1199 const std::string prefix = "_" + catName + "_";
1200
1201 const std::string origname = proxy->arg().GetName();
1202
1203 auto pdfClone = RooHelpers::cloneTreeWithSameParameters(static_cast<RooAbsPdf const &>(proxy->arg()), &normSet);
1204
1205 prefixArgs(pdfClone.get(), prefix, normSet);
1206
1207 std::unique_ptr<RooArgSet> pdfNormSet(
1208 static_cast<RooArgSet *>(std::unique_ptr<RooArgSet>(pdfClone->getVariables())->selectByAttrib("__obs__", true)));
1209
1210 if (rangeName) {
1211 pdfClone->setNormRange(RooHelpers::getRangeNameForSimComponent(rangeName, splitRange, catName).c_str());
1212 }
1213
1214 RooFit::Detail::CompileContext pdfContext{*pdfNormSet};
1215 pdfContext.setLikelihoodMode(ctx.likelihoodMode());
1216 auto *pdfFinal = pdfContext.compile(*pdfClone, *newSimPdf, *pdfNormSet);
1217
1218 pdfFinal->fixAddCoefNormalization(*pdfNormSet, false);
1219
1220 pdfClone->SetName((std::string("_") + pdfClone->GetName()).c_str());
1221 pdfFinal->addOwnedComponents(std::move(pdfClone));
1222
1223 pdfFinal->setAttribute(("ORIGNAME:" + origname).c_str());
1224 newPdfs.add(*pdfFinal);
1225
1226 // We will remove the old pdf server because we will fill the new ones by
1227 // hand via the creation of new proxies.
1228 newSimPdf->removeServer(const_cast<RooAbsReal &>(proxy->arg()), true);
1229 }
1230
1231 // Replace pdfs with compiled pdfs. Don't use RooAbsArg::redirectServers()
1232 // here, because it doesn't support replacing two servers with the same name
1233 // (it can happen in a RooSimultaneous that two pdfs have the same name).
1234
1235 // First delete old proxies (we have already removed the servers before).
1236 newSimPdf->_pdfProxyList.Delete();
1237
1238 // Recreate the _pdfProxyList with the compiled pdfs
1239 for (std::size_t i = 0; i < newPdfs.size(); ++i) {
1240 const char *label = catNames[i].c_str();
1241 newSimPdf->_pdfProxyList.Add(
1242 new RooRealProxy(label, label, newSimPdf.get(), *static_cast<RooAbsReal *>(newPdfs[i])));
1243 }
1244
1245 ctx.compileServers(*newSimPdf, normSet); // to trigger compiling also the index category
1246
1247 return newSimPdf;
1248}
#define coutI(a)
#define oocoutW(o, a)
#define oocxcoutD(o, a)
#define oocoutI(o, a)
#define coutE(a)
RooTemplateProxy< RooAbsReal > RooRealProxy
Compatibility typedef replacing the old RooRealProxy class.
#define ClassImp(name)
Definition Rtypes.h:377
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 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
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2468
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:80
bool dependsOn(const RooAbsCollection &serverList, const RooAbsArg *ignoreArg=nullptr, bool valueOnly=false) const
Test whether we depend on (ie, are served by) any object in the specified collection.
void setStringAttribute(const Text_t *key, const Text_t *value)
Associate string 'value' to this object under key 'key'.
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
void SetName(const char *name) override
Set the name of the TNamed.
bool addOwnedComponents(const RooAbsCollection &comps)
Take ownership of the contents of 'comps'.
const Text_t * getStringAttribute(const Text_t *key) const
Get string attribute mapped under key 'key'.
bool redirectServers(const RooAbsCollection &newServerList, bool mustReplaceAll=false, bool nameChange=false, bool isRecursionStep=false)
Replace all direct servers of this object with the new servers in newServerList.
virtual bool isDerived() const
Does value or shape of this arg depend on any other arg?
Definition RooAbsArg.h:100
bool getAttribute(const Text_t *name) const
Check if a named attribute is set. By default, all attributes are unset.
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:92
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:252
RooAbsCategoryLValue is the common abstract base class for objects that represent a discrete value th...
virtual bool setLabel(const char *label, bool printError=true)=0
Change category state by specifying a state name.
A space to attach TBranches.
virtual value_type getCurrentIndex() const
Return index number of current state.
virtual const char * getCurrentLabel() const
Return label string of current state.
std::map< std::string, value_type >::const_iterator begin() const
Iterator for category state names. Points to pairs of index and name.
std::size_t size() const
Number of states defined.
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
bool contains(const RooAbsArg &var) const
Check if collection contains an argument with the same name as var.
const char * GetName() const override
Returns name of object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
Storage_t::size_type size() const
RooAbsArg * first() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
bool selectCommon(const RooAbsCollection &refColl, RooAbsCollection &outColl) const
Create a subset of the current collection, consisting only of those elements that are contained as we...
RooAbsArg * find(const char *name) const
Find object with given name in list.
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
virtual const RooArgSet * get() const
Definition RooAbsData.h:101
virtual Roo1DTable * table(const RooArgSet &catSet, const char *cuts="", const char *opts="") const
Construct table for product of categories in catSet.
virtual Int_t numEntries() const
Return number of entries in dataset, i.e., count unweighted entries.
RooAbsGenContext is the abstract base class for generator contexts of RooAbsPdf objects.
bool mustBeExtended() const
If true PDF must provide extended likelihood term.
Definition RooAbsPdf.h:222
RooArgSet const * _normSet
Normalization integral (owned by _normMgr)
Definition RooAbsPdf.h:320
RooPlot * plotOn(RooPlot *frame, const RooCmdArg &arg1={}, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const override
Helper calling plotOn(RooPlot*, RooLinkedList&) const.
Definition RooAbsPdf.h:123
bool canBeExtended() const
If true, PDF can provide extended likelihood term.
Definition RooAbsPdf.h:218
@ CanBeExtended
Definition RooAbsPdf.h:212
@ MustBeExtended
Definition RooAbsPdf.h:212
@ CanNotBeExtended
Definition RooAbsPdf.h:212
RooFit::OwningPtr< RooDataSet > generate(const RooArgSet &whatVars, Int_t nEvents, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={})
See RooAbsPdf::generate(const RooArgSet&,const RooCmdArg&,const RooCmdArg&,const RooCmdArg&,...
Definition RooAbsPdf.h:57
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition RooAbsReal.h:59
RooDataHist * fillDataHist(RooDataHist *hist, const RooArgSet *nset, double scaleFactor, bool correctForBinVolume=false, bool showProgress=false) const
Fill a RooDataHist with values sampled from this function at the bin centers.
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
bool plotSanityChecks(RooPlot *frame) const
Utility function for plotOn(), perform general sanity check on frame to ensure safe plotting operatio...
void makeProjectionSet(const RooAbsArg *plotVar, const RooArgSet *allVars, RooArgSet &projectedVars, bool silent) const
Utility function for plotOn() that constructs the set of observables to project when plotting ourselv...
RooAddPdf is an efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
RooArgSet * snapshot(bool deepCopy=true) const
Use RooAbsCollection::snapshot(), but return as RooArgSet.
Definition RooArgSet.h:178
static std::unique_ptr< RooAbsPdf > create(RooAbsPdf &pdf, RooAbsData const &data, double precision)
Creates a wrapping RooBinSamplingPdf if appropriate.
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
Int_t lastIndex() const
Return index of slot used in last get or set operation.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
RooCategory is an object to represent discrete states.
Definition RooCategory.h:28
RooCmdArg is a named container for two doubles, two integers two object points and three string point...
Definition RooCmdArg.h:26
Class RooCmdConfig is a configurable parser for RooCmdArg named arguments.
void defineMutex(const char *head, Args_t &&... tail)
Define arguments where any pair is mutually exclusive.
bool process(const RooCmdArg &arg)
Process given RooCmdArg.
double getDouble(const char *name, double defaultValue=0.0) const
Return double property registered with name 'name'.
bool defineDouble(const char *name, const char *argName, int doubleNum, double defValue=0.0)
Define double property name 'name' mapped to double in slot 'doubleNum' in RooCmdArg with name argNam...
RooArgSet * getSet(const char *name, RooArgSet *set=nullptr) const
Return RooArgSet property registered with name 'name'.
bool defineSet(const char *name, const char *argName, int setNum, const RooArgSet *set=nullptr)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
bool ok(bool verbose) const
Return true of parsing was successful.
bool defineObject(const char *name, const char *argName, int setNum, const TObject *obj=nullptr, bool isArray=false)
Define TObject property name 'name' mapped to object in slot 'setNum' in RooCmdArg with name argName ...
const char * getString(const char *name, const char *defaultValue="", bool convEmptyToNull=false) const
Return string property registered with name 'name'.
bool defineString(const char *name, const char *argName, int stringNum, const char *defValue="", bool appendMode=false)
Define double property name 'name' mapped to double in slot 'stringNum' in RooCmdArg with name argNam...
const RooLinkedList & getObjectList(const char *name) const
Return list of objects registered with name 'name'.
bool defineInt(const char *name, const char *argName, int intNum, int defValue=0)
Define integer property name 'name' mapped to integer in slot 'intNum' in RooCmdArg with name argName...
void allowUndefined(bool flag=true)
If flag is true the processing of unrecognized RooCmdArgs is not considered an error.
int getInt(const char *name, int defaultValue=0) const
Return integer property registered with name 'name'.
TObject * getObject(const char *name, TObject *obj=nullptr) const
Return TObject property registered with name 'name'.
void removeAll() override
Remove all argument inset using remove(const RooAbsArg&).
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
The RooDataHist is a container class to hold N-dimensional binned data.
Definition RooDataHist.h:39
double weight(std::size_t i) const
Return weight of i-th bin.
void set(std::size_t binNumber, double weight, double wgtErr)
Set bin content of bin that was last loaded with get(std::size_t).
double sumEntries() const override
Sum the weights of all bins.
RooDataSet is a container class to hold unbinned data.
Definition RooDataSet.h:57
const RooArgSet * get(Int_t index) const override
Return RooArgSet with coordinates of event 'index'.
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
TObject * find(const char *name) const
Return pointer to object with given name in collection.
virtual void Add(TObject *arg)
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
A RooPlot is a plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:43
void remove(const char *name=nullptr, bool deleteToo=true)
Remove object with given name, or last object added if no name is given.
Definition RooPlot.cxx:883
const RooArgSet * getNormVars() const
Definition RooPlot.h:146
RooAbsRealLValue * getPlotVar() const
Definition RooPlot.h:137
RooSimultaneous facilitates simultaneous fitting of multiple PDFs to subsets of a given dataset.
void selectNormalization(const RooArgSet *depSet=nullptr, bool force=false) override
Interface function used by test statistics to freeze choice of observables for interpretation of frac...
double evaluate() const override
Return the current value: the value of the PDF associated with the current index category state.
Int_t _numPdf
Number of registered PDFs.
void selectNormalizationRange(const char *rangeName=nullptr, bool force=false) override
Interface function used by test statistics to freeze choice of range for interpretation of fraction c...
TList _pdfProxyList
List of PDF proxies (named after applicable category state)
RooObjCacheManager _partIntMgr
! Component normalization manager
~RooSimultaneous() override
Destructor.
RooFit::OwningPtr< RooDataSet > generateSimGlobal(const RooArgSet &whatVars, Int_t nEvents) override
Special generator interface for generation of 'global observables' – for RooStats tools.
RooArgSet const & flattenedCatList() const
Internal utility function to get a list of all category components for this RooSimultaneous.
RooPlot * plotOn(RooPlot *frame, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}, const RooCmdArg &arg9={}, const RooCmdArg &arg10={}) const override
ExtendMode extendMode() const override
Examine the pdf components and check if one of them can be extended or must be extended.
RooCategoryProxy _indexCat
Index category.
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Return analytical integration defined by given code.
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &numVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Forward determination of analytical integration capabilities to component p.d.f.s A unique code is as...
double expectedEvents(const RooArgSet *nset) const override
Return the number of expected events: If the index is in nset, then return the sum of the expected ev...
friend class RooSimGenContext
RooAbsGenContext * autoGenContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false, bool autoBinned=true, const char *binnedTag="") const override
RooAbsPdf * getPdf(RooStringView catName) const
Return the p.d.f associated with the given index category name.
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
static std::unique_ptr< RooSimultaneous::InitializationOutput > initialize(std::string const &name, RooAbsCategoryLValue &inIndexCat, std::map< std::string, RooAbsPdf * > const &pdfMap)
void wrapPdfsInBinSamplingPdfs(RooAbsData const &data, double precision)
Wraps the components of this RooSimultaneous in RooBinSamplingPdfs.
const TNamed * _plotCoefNormRange
RooAbsGenContext * genContext(const RooArgSet &vars, const RooDataSet *prototype=nullptr, const RooArgSet *auxProto=nullptr, bool verbose=false) const override
Return specialized generator context for simultaneous p.d.f.s.
std::unique_ptr< RooArgSet > _indexCatSet
! Index category wrapped in a RooArgSet if needed internally
bool addPdf(const RooAbsPdf &pdf, const char *catLabel)
Associate given PDF with index category state label 'catLabel'.
RooSetProxy _plotCoefNormSet
const RooAbsCategoryLValue & indexCat() const
friend class RooSimSplitGenContext
virtual RooDataHist * fillDataHist(RooDataHist *hist, const RooArgSet *nset, double scaleFactor, bool correctForBinVolume=false, bool showProgress=false) const
The RooStringView is a wrapper around a C-style string that can also be constructed from a std::strin...
const char * c_str() const
The RooSuperCategory can join several RooAbsCategoryLValue objects into a single category.
bool setLabel(const char *label, bool printError=true) override
Set the value of the super category by specifying the state name.
const char * label() const
Get the label of the current category state. This function only makes sense for category proxies.
const T & arg() const
Return reference to object held in proxy.
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
Basic string class.
Definition TString.h:139
TString & Append(const char *cs)
Definition TString.h:576
RooCmdArg ProjWData(const RooAbsData &projData, bool binData=false)
RooCmdArg Project(const RooArgSet &projSet)
RooCmdArg Normalization(double scaleFactor)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
OwningPtr< T > owningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:50
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:43
std::unique_ptr< T > cloneTreeWithSameParameters(T const &arg, RooArgSet const *observables=nullptr)
Clone RooAbsArg object and reattach to original parameters.
Definition RooHelpers.h:149
std::string getRangeNameForSimComponent(std::string const &rangeName, bool splitRange, std::string const &catName)
Definition first.py:1
Internal struct used for initialization.
std::vector< RooAbsPdf const * > finalPdfs
std::vector< std::string > finalCatLabels
void addPdf(const RooAbsPdf &pdf, std::string const &catLabel)
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345