Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
HistoToWorkspaceFactoryFast.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id: cranmer $
2// Author: Kyle Cranmer, Akira Shibata
3/*************************************************************************
4 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11////////////////////////////////////////////////////////////////////////////////
12
13/** \class RooStats::HistFactory::HistoToWorkspaceFactoryFast
14 * \ingroup HistFactory
15 * This class provides helper functions for creating likelihood models from histograms.
16 * It is used by RooStats::HistFactory::MakeModelAndMeasurementFast.
17 *
18 * A tutorial showing how to create a HistFactory model is hf001_example.C
19 */
20
21
22#include <RooAddition.h>
23#include <RooBinWidthFunction.h>
24#include <RooBinning.h>
25#include <RooCategory.h>
26#include <RooConstVar.h>
27#include <RooDataHist.h>
28#include <RooDataSet.h>
29#include <RooFit/ModelConfig.h>
30#include <RooFitResult.h>
31#include <RooFormulaVar.h>
32#include <RooGamma.h>
33#include <RooGaussian.h>
34#include <RooGlobalFunc.h>
35#include <RooHelpers.h>
36#include <RooHistFunc.h>
37#include <RooMultiVarGaussian.h>
38#include <RooNumIntConfig.h>
39#include <RooPoisson.h>
40#include <RooPolyVar.h>
41#include <RooProdPdf.h>
42#include <RooProduct.h>
43#include <RooProfileLL.h>
44#include <RooRandom.h>
45#include <RooRealSumPdf.h>
46#include <RooRealVar.h>
47#include <RooSimultaneous.h>
48#include <RooWorkspace.h>
49
54
55#include "HFMsgService.h"
56
57#include "TH1.h"
58#include "TStopwatch.h"
59#include "TVectorD.h"
60#include "TMatrixDSym.h"
61
62// specific to this package
69
70#include <algorithm>
71#include <memory>
72#include <utility>
73
74constexpr double alphaLow = -5.0;
75constexpr double alphaHigh = 5.0;
76
77std::vector<double> histToVector(TH1 const &hist)
78{
79 // Must get the full size of the TH1 (No direct method to do this...)
80 int numBins = hist.GetNbinsX() * hist.GetNbinsY() * hist.GetNbinsZ();
81 std::vector<double> out(numBins);
82 int histIndex = 0;
83 for (int i = 0; i < numBins; ++i) {
84 while (hist.IsBinUnderflow(histIndex) || hist.IsBinOverflow(histIndex)) {
85 ++histIndex;
86 }
87 out[i] = hist.GetBinContent(histIndex);
88 ++histIndex;
89 }
90 return out;
91}
92
93// use this order for safety on library loading
94using namespace RooStats;
95using std::string, std::vector, std::make_unique, std::pair, std::unique_ptr, std::map;
96
97using namespace RooStats::HistFactory::Detail;
99
100
101namespace RooStats{
102namespace HistFactory{
103
106
108 Configuration const& cfg) :
109 fSystToFix( measurement.GetConstantParams() ),
110 fParamValues( measurement.GetParamValues() ),
111 fNomLumi( measurement.GetLumi() ),
112 fLumiError( measurement.GetLumi()*measurement.GetLumiRelErr() ),
113 fLowBin( measurement.GetBinLow() ),
114 fHighBin( measurement.GetBinHigh() ),
115 fCfg{cfg} {
116
117 // Set Preprocess functions
118 SetFunctionsToPreprocess( measurement.GetPreprocessFunctions() );
119
120 }
121
123
124 // Configure a workspace by doing any
125 // necessary post-processing and by
126 // creating a ModelConfig
127
128 // Make a ModelConfig and configure it
129 ModelConfig * proto_config = static_cast<ModelConfig *>(ws_single->obj("ModelConfig"));
130 if( proto_config == nullptr ) {
131 std::cout << "Error: Did not find 'ModelConfig' object in file: " << ws_single->GetName()
132 << std::endl;
133 throw hf_exc();
134 }
135
136 if( measurement.GetPOIList().empty() ) {
137 cxcoutWHF << "No Parametetrs of interest are set" << std::endl;
138 }
139
140
141 std::stringstream sstream;
142 sstream << "Setting Parameter(s) of Interest as: ";
143 for(auto const& item : measurement.GetPOIList()) {
144 sstream << item << " ";
145 }
146 cxcoutIHF << sstream.str() << std::endl;
147
148 RooArgSet params;
149 for(auto const& poi_name : measurement.GetPOIList()) {
150 if(RooRealVar* poi = (RooRealVar*) ws_single->var(poi_name)){
151 params.add(*poi);
152 }
153 else {
154 std::cout << "WARNING: Can't find parameter of interest: " << poi_name
155 << " in Workspace. Not setting in ModelConfig." << std::endl;
156 //throw hf_exc();
157 }
158 }
159 proto_config->SetParametersOfInterest(params);
160
161 // Name of an 'edited' model, if necessary
162 std::string NewModelName = "newSimPdf"; // <- This name is hard-coded in HistoToWorkspaceFactoryFast::EditSyt. Probably should be changed to : std::string("new") + ModelName;
163
164 // Set the ModelConfig's Params of Interest
165 RooAbsData* expData = ws_single->data("asimovData");
166 if( !expData ) {
167 std::cout << "Error: Failed to find dataset: " << expData
168 << " in workspace" << std::endl;
169 throw hf_exc();
170 }
171 if(!measurement.GetPOIList().empty()){
172 proto_config->GuessObsAndNuisance(*expData, RooMsgService::instance().isActive(nullptr, RooFit::HistFactory, RooFit::INFO));
173 }
174
175 // Now, let's loop over any additional asimov datasets
176 // that we need to make
177
178 // Get the pdf
179 // Notice that we get the "new" pdf, this is the one that is
180 // used in the creation of these asimov datasets since they
181 // are fitted (or may be, at least).
182 RooAbsPdf* pdf = ws_single->pdf(NewModelName);
183 if( !pdf ) pdf = ws_single->pdf( ModelName );
184 const RooArgSet* observables = ws_single->set("observables");
185
186 // Create a SnapShot of the nominal values
187 std::string SnapShotName = "NominalParamValues";
188 ws_single->saveSnapshot(SnapShotName, ws_single->allVars());
189
190 for( unsigned int i=0; i<measurement.GetAsimovDatasets().size(); ++i) {
191
192 // Set the variable values and "const" ness with the workspace
193 RooStats::HistFactory::Asimov& asimov = measurement.GetAsimovDatasets().at(i);
194 std::string AsimovName = asimov.GetName();
195
196 cxcoutPHF << "Generating additional Asimov Dataset: " << AsimovName << std::endl;
198 std::unique_ptr<RooAbsData> asimov_dataset{AsymptoticCalculator::GenerateAsimovData(*pdf, *observables)};
199
200 cxcoutPHF << "Importing Asimov dataset" << std::endl;
201 bool failure = ws_single->import(*asimov_dataset, RooFit::Rename(AsimovName.c_str()));
202 if( failure ) {
203 std::cout << "Error: Failed to import Asimov dataset: " << AsimovName
204 << std::endl;
205 throw hf_exc();
206 }
207
208 // Load the snapshot at the end of every loop iteration
209 // so we start each loop with a "clean" snapshot
210 ws_single->loadSnapshot(SnapShotName.c_str());
211 }
212
213 // Cool, we're done
214 return; // ws_single;
215 }
216
217
218 // We want to eliminate this interface and use the measurement directly
220
221 // This is a pretty light-weight wrapper function
222 //
223 // Take a fully configured measurement as well as
224 // one of its channels
225 //
226 // Return a workspace representing that channel
227 // Do this by first creating a vector of EstimateSummary's
228 // and this by configuring the workspace with any post-processing
229
230 // Get the channel's name
231 string ch_name = channel.GetName();
232
233 // Create a workspace for a SingleChannel from the Measurement Object
234 std::unique_ptr<RooWorkspace> ws_single{this->MakeSingleChannelWorkspace(measurement, channel)};
235 if( ws_single == nullptr ) {
236 cxcoutF(HistFactory) << "Error: Failed to make Single-Channel workspace for channel: " << ch_name
237 << " and measurement: " << measurement.GetName() << std::endl;
238 throw hf_exc();
239 }
240
241 // Finally, configure that workspace based on
242 // properties of the measurement
244
245 return RooFit::makeOwningPtr(std::move(ws_single));
246
247 }
248
250
251 // This function takes a fully configured measurement
252 // which may contain several channels and returns
253 // a workspace holding the combined model
254 //
255 // This can be used, for example, within a script to produce
256 // a combined workspace on-the-fly
257 //
258 // This is a static function (for now) to make
259 // it a one-liner
260
261
262 Configuration config;
263 return MakeCombinedModel(measurement,config);
264 }
265
267
268 // This function takes a fully configured measurement
269 // which may contain several channels and returns
270 // a workspace holding the combined model
271 //
272 // This can be used, for example, within a script to produce
273 // a combined workspace on-the-fly
274 //
275 // This is a static function (for now) to make
276 // it a one-liner
277
279
280 // First, we create an instance of a HistFactory
282
283 // Loop over the channels and create the individual workspaces
286
287 for(HistFactory::Channel& channel : measurement.GetChannels()) {
288
289 if( ! channel.CheckHistograms() ) {
290 cxcoutFHF << "MakeModelAndMeasurementsFast: Channel: " << channel.GetName()
291 << " has uninitialized histogram pointers" << std::endl;
292 throw hf_exc();
293 }
294
295 string ch_name = channel.GetName();
296 channel_names.push_back(ch_name);
297
298 // GHL: Renaming to 'MakeSingleChannelWorkspace'
299 channel_workspaces.emplace_back(histFactory.MakeSingleChannelModel(measurement, channel));
300 }
301
302
303 // Now, combine the individual channel workspaces to
304 // form the combined workspace
305 std::unique_ptr<RooWorkspace> ws{histFactory.MakeCombinedModel( channel_names, channel_workspaces )};
306
307
308 // Configure the workspace
310
311 // Done. Return the pointer
312 return RooFit::makeOwningPtr(std::move(ws));
313
314 }
315
316namespace {
317
318template <class Arg_t, typename... Args_t>
319Arg_t &emplace(RooWorkspace &ws, std::string const &name, Args_t &&...args)
320{
321 Arg_t arg{name.c_str(), name.c_str(), std::forward<Args_t>(args)...};
323 return *dynamic_cast<Arg_t *>(ws.arg(name));
324}
325
326} // namespace
327
328/// Create observables of type RooRealVar. Creates 1 to 3 observables, depending on the type of the histogram.
330 RooArgList observables;
331
332 for (unsigned int idx=0; idx < fObsNameVec.size(); ++idx) {
333 if (!proto.var(fObsNameVec[idx])) {
334 const TAxis *axis = (idx == 0) ? hist->GetXaxis() : (idx == 1 ? hist->GetYaxis() : hist->GetZaxis());
335 int nbins = axis->GetNbins();
336 // create observable
337 RooRealVar &obs = emplace<RooRealVar>(proto, fObsNameVec[idx], axis->GetXmin(), axis->GetXmax());
338 if(strlen(axis->GetTitle())>0) obs.SetTitle(axis->GetTitle());
339 obs.setBins(nbins);
340 if (axis->IsVariableBinSize()) {
341 RooBinning binning(nbins, axis->GetXbins()->GetArray());
342 obs.setBinning(binning);
343 }
344 }
345
346 observables.add(*proto.var(fObsNameVec[idx]));
347 }
348
349 return observables;
350}
351
352 /// Create the nominal hist function from `hist`, and register it in the workspace.
354 const RooArgList& observables) const {
355 if(hist) {
356 cxcoutI(HistFactory) << "processing hist " << hist->GetName() << std::endl;
357 } else {
358 cxcoutF(HistFactory) << "hist is empty" << std::endl;
359 R__ASSERT(hist != nullptr);
360 return nullptr;
361 }
362
363 // determine histogram dimensionality
364 unsigned int histndim(1);
365 std::string classname = hist->ClassName();
366 if (classname.find("TH1")==0) { histndim=1; }
367 else if (classname.find("TH2")==0) { histndim=2; }
368 else if (classname.find("TH3")==0) { histndim=3; }
369 R__ASSERT( histndim==fObsNameVec.size() );
370
371 prefix += "_Hist_alphanominal";
372
373 RooDataHist histDHist(prefix + "DHist","",observables,hist);
374
375 return &emplace<RooHistFunc>(proto, prefix, observables,histDHist,0);
376 }
377
378 namespace {
379
380 void makeGaussianConstraint(RooAbsArg& param, RooWorkspace& proto, bool isUniform,
381 std::vector<std::string> & constraintTermNames) {
382 std::string paramName = param.GetName();
383 std::string nomName = "nom_" + paramName;
384 std::string constraintName = paramName + "Constraint";
385
386 // do nothing if the constraint term already exists
387 if(proto.pdf(constraintName)) return;
388
389 // case systematic is uniform (assume they are like a Gaussian but with
390 // a large width (100 instead of 1)
391 const double gaussSigma = isUniform ? 100. : 1.0;
392 if (isUniform) {
393 cxcoutIHF << "Added a uniform constraint for " << paramName << " as a Gaussian constraint with a very large sigma " << std::endl;
394 }
395
399 nomParam.setConstant();
401 paramVar.setError(gaussSigma); // give param initial error to match gaussSigma
402 const_cast<RooArgSet*>(proto.set("globalObservables"))->add(nomParam);
403 }
404
405 /// Make list of abstract parameters that interpolate in space of variations.
407 RooArgList params( ("alpha_Hist") );
408
409 for(auto const& histoSys : histoSysList) {
410 params.add(getOrCreate<RooRealVar>(proto, "alpha_" + histoSys.GetName(), alphaLow, alphaHigh));
411 }
412
413 return params;
414 }
415
416 /// Create a linear interpolation object that holds nominal and systematics, import it into the workspace,
417 /// and return a pointer to it.
420 RooWorkspace& proto, const std::vector<HistoSys>& histoSysList,
421 const string& prefix,
422 const RooArgList& obsList) {
423
424 // now make function that linearly interpolates expectation between variations
425 // get low/high variations to interpolate between
426 std::vector<double> low;
427 std::vector<double> high;
430 for(unsigned int j=0; j<histoSysList.size(); ++j){
431 std::string str = prefix + "_" + std::to_string(j);
432
433 const HistoSys& histoSys = histoSysList.at(j);
434 auto lowDHist = std::make_unique<RooDataHist>(str+"lowDHist","",obsList, histoSys.GetHistoLow());
435 auto highDHist = std::make_unique<RooDataHist>(str+"highDHist","",obsList, histoSys.GetHistoHigh());
436 lowSet.addOwned(std::make_unique<RooHistFunc>((str+"low").c_str(),"",obsList,std::move(lowDHist),0));
437 highSet.addOwned(std::make_unique<RooHistFunc>((str+"high").c_str(),"",obsList,std::move(highDHist),0));
438 }
439
440 // this is sigma(params), a piece-wise linear interpolation
442 interp.setPositiveDefinite();
443 interp.setAllInterpCodes(4); // LM: change to 4 (piece-wise linear to 6th order polynomial interpolation + linear extrapolation )
444 // KC: interpo codes 1 etc. don't have proper analytic integral.
446 interp.setBinIntegrator(obsSet);
447 interp.forceNumInt();
448
449 proto.import(interp, RooFit::RecycleConflictNodes()); // individual params have already been imported in first loop of this function
450
451 return proto.arg(prefix);
452 }
453
454 }
455
456 // GHL: Consider passing the NormFactor list instead of the entire sample
457 std::unique_ptr<RooProduct> HistoToWorkspaceFactoryFast::CreateNormFactor(RooWorkspace& proto, string& channel, string& sigmaEpsilon, Sample& sample, bool doRatio){
458
459 std::vector<string> prodNames;
460
461 vector<NormFactor> normList = sample.GetNormFactorList();
464
465 string overallNorm_times_sigmaEpsilon = sample.GetName() + "_" + channel + "_scaleFactors";
466 auto sigEps = proto.arg(sigmaEpsilon);
467 assert(sigEps);
468 auto normFactor = std::make_unique<RooProduct>(overallNorm_times_sigmaEpsilon.c_str(), overallNorm_times_sigmaEpsilon.c_str(), RooArgList(*sigEps));
469
470 if(!normList.empty()){
471
472 for(NormFactor &norm : normList) {
473 string varname = norm.GetName();
474 if(doRatio) {
475 varname += "_" + channel;
476 }
477
478 // GHL: Check that the NormFactor doesn't already exist
479 // (it may have been created as a function expression
480 // during preprocessing)
481 std::stringstream range;
482 range << "[" << norm.GetVal() << "," << norm.GetLow() << "," << norm.GetHigh() << "]";
483
484 if( proto.obj(varname) == nullptr) {
485 cxcoutI(HistFactory) << "making normFactor: " << norm.GetName() << std::endl;
486 // remove "doRatio" and name can be changed when ws gets imported to the combined model.
487 emplace<RooRealVar>(proto, varname, norm.GetVal(), norm.GetLow(), norm.GetHigh());
488 proto.var(varname)->setError(0); // ensure factor is assigned an initial error, even if its zero
489 }
490
491 prodNames.push_back(varname);
492 rangeNames.push_back(range.str());
493 normFactorNames.push_back(varname);
494 }
495
496
497 for (const auto& name : prodNames) {
498 auto arg = proto.arg(name);
499 assert(arg);
500 normFactor->addTerm(arg);
501 }
502
503 }
504
505 unsigned int rangeIndex=0;
506 for( vector<string>::iterator nit = normFactorNames.begin(); nit!=normFactorNames.end(); ++nit){
507 if( count (normFactorNames.begin(), normFactorNames.end(), *nit) > 1 ){
508 cxcoutI(HistFactory) <<"<NormFactor Name =\""<<*nit<<"\"> is duplicated for <Sample Name=\""
509 << sample.GetName() << "\">, but only one factor will be included. \n Instead, define something like"
510 << "\n\t<Function Name=\""<<*nit<<"Squared\" Expression=\""<<*nit<<"*"<<*nit<<"\" Var=\""<<*nit<<rangeNames.at(rangeIndex)
511 << "\"> \nin your top-level XML's <Measurement> entry and use <NormFactor Name=\""<<*nit<<"Squared\" in your channel XML file."<< std::endl;
512 }
513 ++rangeIndex;
514 }
515
516 return normFactor;
517 }
518
520 string interpName,
521 std::vector<OverallSys>& systList,
524
525 // add variables for all the relative overall uncertainties we expect
526 totSystTermNames.push_back(prefix);
527
528 RooArgSet params(prefix.c_str());
531
532 std::map<std::string, double>::iterator itconstr;
533 for(unsigned int i = 0; i < systList.size(); ++i) {
534
535 OverallSys& sys = systList.at(i);
536 std::string strname = sys.GetName();
537 const char * name = strname.c_str();
538
539 // case of no systematic (is it possible)
540 if (meas.GetNoSyst().count(sys.GetName()) > 0 ) {
541 cxcoutI(HistFactory) << "HistoToWorkspaceFast::AddConstraintTerm - skip systematic " << sys.GetName() << std::endl;
542 continue;
543 }
544 // case systematic is a gamma constraint
545 if (meas.GetGammaSyst().count(sys.GetName()) > 0 ) {
546 double relerr = meas.GetGammaSyst().find(sys.GetName() )->second;
547 if (relerr <= 0) {
548 cxcoutI(HistFactory) << "HistoToWorkspaceFast::AddConstraintTerm - zero uncertainty assigned - skip systematic " << sys.GetName() << std::endl;
549 continue;
550 }
551 const double tauVal = 1./(relerr*relerr);
552 const double sqtau = 1./relerr;
553 RooRealVar &beta = emplace<RooRealVar>(proto, "beta_" + strname, 1., 0., 10.);
554 // the global observable (y_s)
555 RooRealVar &yvar = emplace<RooRealVar>(proto, "nom_" + std::string{beta.GetName()}, tauVal, 0., 10.);
556 // the rate of the gamma distribution (theta)
557 RooRealVar &theta = emplace<RooRealVar>(proto, "theta_" + strname, 1./tauVal);
558 // find alpha as function of beta
560
561 // add now the constraint itself Gamma_beta_constraint(beta, y+1, tau, 0 )
562 // build the gamma parameter k = as y_s + 1
563 RooAddition &kappa = emplace<RooAddition>(proto, "k_" + std::string{yvar.GetName()}, RooArgList{yvar, 1.0});
564 RooGamma &gamma = emplace<RooGamma>(proto, std::string{beta.GetName()} + "Constraint", beta, kappa, theta, RooFit::RooConst(0.0));
566 alphaOfBeta.Print("t");
567 gamma.Print("t");
568 }
569 constraintTermNames.push_back(gamma.GetName());
570 // set global observables
571 yvar.setConstant(true);
572 const_cast<RooArgSet*>(proto.set("globalObservables"))->add(yvar);
573
574 // add alphaOfBeta in the list of params to interpolate
575 params.add(alphaOfBeta);
576 cxcoutI(HistFactory) << "Added a gamma constraint for " << name << std::endl;
577
578 }
579 else {
580 RooRealVar& alpha = getOrCreate<RooRealVar>(proto, prefix + sys.GetName(), 0, alphaLow, alphaHigh);
581 // add the Gaussian constraint part
582 const bool isUniform = meas.GetUniformSyst().count(sys.GetName()) > 0;
584
585 // check if exists a log-normal constraint
586 if (meas.GetLogNormSyst().count(sys.GetName()) == 0 && meas.GetGammaSyst().count(sys.GetName()) == 0 ) {
587 // just add the alpha for the parameters of the FlexibleInterpVar function
588 params.add(alpha);
589 }
590 // case systematic is a log-normal constraint
591 if (meas.GetLogNormSyst().count(sys.GetName()) > 0 ) {
592 // log normal constraint for parameter
593 const double relerr = meas.GetLogNormSyst().find(sys.GetName() )->second;
594
596 proto, "alphaOfBeta_" + sys.GetName(), "x[0]*(pow(x[1],x[2])-1.)",
597 RooArgList{emplace<RooRealVar>(proto, "tau_" + sys.GetName(), 1. / relerr),
598 emplace<RooRealVar>(proto, "kappa_" + sys.GetName(), 1. + relerr), alpha});
599
600 cxcoutI(HistFactory) << "Added a log-normal constraint for " << name << std::endl;
602 alphaOfBeta.Print("t");
603 }
604 params.add(alphaOfBeta);
605 }
606
607 }
608 // add low/high vectors
609 lowVec.push_back(sys.GetLow());
610 highVec.push_back(sys.GetHigh());
611
612 } // end sys loop
613
614 if(!systList.empty()){
615 // this is epsilon(alpha_j), a piece-wise linear interpolation
616 // LinInterpVar interp( (interpName).c_str(), "", params, 1., lowVec, highVec);
617
618 assert(!params.empty());
619 assert(lowVec.size() == params.size());
620
621 FlexibleInterpVar interp( (interpName).c_str(), "", params, 1., lowVec, highVec);
622 interp.setAllInterpCodes(4); // LM: change to 4 (piece-wise exponential to 6th order polynomial interpolation + exponential extrapolation )
623 //interp.setAllInterpCodes(0); // simple linear interpolation
624 proto.import(interp); // params have already been imported in first loop of this function
625 } else{
626 // some strange behavior if params,lowVec,highVec are empty.
627 //cout << "WARNING: No OverallSyst terms" << std::endl;
628 emplace<RooConstVar>(proto, interpName, 1.); // params have already been imported in first loop of this function
629 }
630 }
631
632
635 assert(sampleScaleFactors.size() == sampleHistFuncs.size());
636
637 // for ith bin calculate totN_i = lumi * sum_j expected_j * syst_j
638
639 if (fObsNameVec.empty() && !fObsName.empty())
640 throw std::logic_error("HistFactory didn't process the observables correctly. Please file a bug report.");
641
642 auto firstHistFunc = dynamic_cast<const RooHistFunc*>(sampleHistFuncs.front().front());
643 if (!firstHistFunc) {
644 auto piecewiseInt = dynamic_cast<const PiecewiseInterpolation*>(sampleHistFuncs.front().front());
645 firstHistFunc = dynamic_cast<const RooHistFunc*>(piecewiseInt->nominalHist());
646 }
648
649 // Prepare a function to divide all bin contents by bin width to get a density:
650 auto &binWidth = emplace<RooBinWidthFunction>(proto, totName + "_binWidth", *firstHistFunc, true);
651
652 // Loop through samples and create products of their functions:
653 RooArgSet coefList;
655 for (unsigned int i=0; i < sampleHistFuncs.size(); ++i) {
656 assert(!sampleHistFuncs[i].empty());
657 coefList.add(*sampleScaleFactors[i]);
658
659 std::vector<RooAbsArg*>& thisSampleHistFuncs = sampleHistFuncs[i];
660 thisSampleHistFuncs.push_back(&binWidth);
661
662 if (thisSampleHistFuncs.size() == 1) {
663 // Just one function. Book it.
664 shapeList.add(*thisSampleHistFuncs.front());
665 } else {
666 // Have multiple functions. We need to multiply them.
667 std::string name = thisSampleHistFuncs.front()->GetName();
668 auto pos = name.find("Hist_alpha");
669 if (pos != std::string::npos) {
670 name = name.substr(0, pos) + "shapes";
671 } else if ( (pos = name.find("nominal")) != std::string::npos) {
672 name = name.substr(0, pos) + "shapes";
673 }
674
677 shapeList.add(*proto.function(name));
678 }
679 }
680
681 // Sum all samples
682 RooRealSumPdf tot(totName.c_str(), totName.c_str(), shapeList, coefList, true);
683 tot.specialIntegratorConfig(true)->method1D().setLabel("RooBinIntegrator") ;
684 tot.specialIntegratorConfig(true)->method2D().setLabel("RooBinIntegrator") ;
685 tot.specialIntegratorConfig(true)->methodND().setLabel("RooBinIntegrator") ;
686 tot.forceNumInt();
687
688 // for mixed generation in RooSimultaneous
689 tot.setAttribute("GenerateBinned"); // for use with RooSimultaneous::generate in mixed mode
690
691 // Enable the binned likelihood optimization
692 if(fCfg.binnedFitOptimization) {
693 tot.setAttribute("BinnedLikelihood");
694 }
695
697 }
698
699 //////////////////////////////////////////////////////////////////////////////
700
702
703 FILE* covFile = fopen ((filename).c_str(),"w");
704 fprintf(covFile," ") ;
705 for (auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
706 if(myargi->isConstant()) continue;
707 fprintf(covFile," & %s", myargi->GetName());
708 }
709 fprintf(covFile,"\\\\ \\hline \n" );
710 for (auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
711 if(myargi->isConstant()) continue;
712 fprintf(covFile,"%s", myargi->GetName());
713 for (auto const *myargj : static_range_cast<RooRealVar *>(*params)) {
714 if(myargj->isConstant()) continue;
715 std::cout << myargi->GetName() << "," << myargj->GetName();
716 fprintf(covFile, " & %.2f", result->correlation(*myargi, *myargj));
717 }
718 std::cout << std::endl;
719 fprintf(covFile, " \\\\\n");
720 }
722
723 }
724
725
726 ///////////////////////////////////////////////
728
729 // check inputs (see JIRA-6890 )
730
731 if (channel.GetSamples().empty()) {
732 Error("MakeSingleChannelWorkspace",
733 "The input Channel does not contain any sample - return a nullptr");
734 return nullptr;
735 }
736
737 const TH1* channel_hist_template = channel.GetSamples().front().GetHisto();
738 if (channel_hist_template == nullptr) {
739 channel.CollectHistograms();
740 channel_hist_template = channel.GetSamples().front().GetHisto();
741 }
742 if (channel_hist_template == nullptr) {
743 std::ostringstream stream;
744 stream << "The sample " << channel.GetSamples().front().GetName()
745 << " in channel " << channel.GetName() << " does not contain a histogram. This is the channel:\n";
746 channel.Print(stream);
747 Error("MakeSingleChannelWorkspace", "%s", stream.str().c_str());
748 return nullptr;
749 }
750
751 if( ! channel.CheckHistograms() ) {
752 std::cout << "MakeSingleChannelWorkspace: Channel: " << channel.GetName()
753 << " has uninitialized histogram pointers" << std::endl;
754 throw hf_exc();
755 }
756
757
758
759 // Set these by hand inside the function
760 vector<string> systToFix = measurement.GetConstantParams();
761 bool doRatio=false;
762
763 // to time the macro
764 TStopwatch t;
765 t.Start();
766 //ES// string channel_name=summary[0].channel;
767 string channel_name = channel.GetName();
768
769 /// MB: reset observable names for each new channel.
770 fObsNameVec.clear();
771
772 /// MB: label observables x,y,z, depending on histogram dimensionality
773 /// GHL: Give it the first sample's nominal histogram as a template
774 /// since the data histogram may not be present
776
777 for ( unsigned int idx=0; idx<fObsNameVec.size(); ++idx ) {
778 fObsNameVec[idx] = "obs_" + fObsNameVec[idx] + "_" + channel_name ;
779 }
780
781 if (fObsNameVec.empty()) {
782 fObsName= "obs_" + channel_name; // set name ov observable
783 fObsNameVec.push_back( fObsName );
784 }
785
786 if (fObsNameVec.empty() || fObsNameVec.size() > 3) {
787 throw hf_exc("HistFactory is limited to 1- to 3-dimensional histograms.");
788 }
789
790 cxcoutP(HistFactory) << "\n-----------------------------------------\n"
791 << "\tStarting to process '"
792 << channel_name << "' channel with " << fObsNameVec.size() << " observables"
793 << "\n-----------------------------------------\n" << std::endl;
794
795 //
796 // our main workspace that we are using to construct the model
797 //
798 auto protoOwner = std::make_unique<RooWorkspace>(channel_name.c_str(), (channel_name+" workspace").c_str());
800 auto proto_config = make_unique<ModelConfig>("ModelConfig", &proto);
801 proto_config->SetWorkspace(proto);
802
803 // preprocess functions
804 for(auto const& func : fPreprocessFunctions){
805 cxcoutI(HistFactory) << "will preprocess this line: " << func << std::endl;
806 proto.factory(func);
807 proto.Print();
808 }
809
810 RooArgSet likelihoodTerms("likelihoodTerms");
811 RooArgSet constraintTerms("constraintTerms");
815 // All histogram functions to be multiplied in each sample
816 std::vector<std::vector<RooAbsArg*>> allSampleHistFuncs;
817 std::vector<RooProduct*> sampleScaleFactors;
818
819 std::vector< pair<string,string> > statNamePairs;
820 std::vector< pair<const TH1*, std::unique_ptr<TH1>> > statHistPairs; // <nominal, error>
821 const std::string statFuncName = "mc_stat_" + channel_name;
822
823 string prefix;
824 string range;
825
826 /////////////////////////////
827 // shared parameters
828 // this is ratio of lumi to nominal lumi. We will include relative uncertainty in model
829 auto &lumiVar = getOrCreate<RooRealVar>(proto, "Lumi", fNomLumi, 0.0, 10 * fNomLumi);
830
831 // only include a lumiConstraint if there's a lumi uncert, otherwise just set the lumi constant
832 if(fLumiError != 0) {
833 auto &nominalLumiVar = emplace<RooRealVar>(proto, "nominalLumi", fNomLumi, 0., fNomLumi + 10. * fLumiError);
835 proto.var("Lumi")->setError(fLumiError/fNomLumi); // give initial error value
836 proto.var("nominalLumi")->setConstant();
837 proto.defineSet("globalObservables","nominalLumi");
838 //likelihoodTermNames.push_back("lumiConstraint");
839 constraintTermNames.push_back("lumiConstraint");
840 } else {
841 proto.var("Lumi")->setConstant();
842 proto.defineSet("globalObservables",RooArgSet()); // create empty set as is assumed it exists later
843 }
844 ///////////////////////////////////
845 // loop through estimates, add expectation, floating bin predictions,
846 // and terms that constrain floating to expectation via uncertainties
847 // GHL: Loop over samples instead, which doesn't contain the data
848 for (Sample& sample : channel.GetSamples()) {
849 string overallSystName = sample.GetName() + "_" + channel_name + "_epsilon";
850
851 string systSourcePrefix = "alpha_";
852
853 // constraintTermNames and totSystTermNames are vectors that are passed
854 // by reference and filled by this method
856 sample.GetOverallSysList(), constraintTermNames , totSystTermNames);
857
858 allSampleHistFuncs.emplace_back();
859 std::vector<RooAbsArg*>& sampleHistFuncs = allSampleHistFuncs.back();
860
861 // GHL: Consider passing the NormFactor list instead of the entire sample
864
865 // Create the string for the object
866 // that is added to the RooRealSumPdf
867 // for this channel
868// string syst_x_expectedPrefix = "";
869
870 // get histogram
871 //ES// TH1* nominal = it->nominal;
872 const TH1* nominal = sample.GetHisto();
873
874 // MB : HACK no option to have both non-hist variations and hist variations ?
875 // get histogram
876 // GHL: Okay, this is going to be non-trivial.
877 // We will loop over histosys's, which contain both
878 // the low hist and the high hist together.
879
880 // Logic:
881 // - If we have no HistoSys's, do part A
882 // - else, if the histo syst's don't match, return (we ignore this case)
883 // - finally, we take the syst's and apply the linear interpolation w/ constraint
884 string expPrefix = sample.GetName() + "_" + channel_name;
885 // create roorealvar observables
886 RooArgList observables = createObservables(sample.GetHisto(), proto);
889
890 if(sample.GetHistoSysList().empty()) {
891 // If no HistoSys
892 cxcoutI(HistFactory) << sample.GetName() + "_" + channel_name + " has no variation histograms " << std::endl;
893
895 } else {
896 // If there ARE HistoSys(s)
897 // name of source for variation
898 string constraintPrefix = sample.GetName() + "_" + channel_name + "_Hist_alpha";
899
900 // make list of abstract parameters that interpolate in space of variations
902
903 // next, create the constraint terms
904 for(std::size_t i = 0; i < interpParams.size(); ++i) {
905 bool isUniform = measurement.GetUniformSyst().count(sample.GetHistoSysList()[i].GetName()) > 0;
907 }
908
909 // finally, create the interpolated function
911 sample.GetHistoSysList(), constraintPrefix, observables) );
912 }
913
914 sampleHistFuncs.front()->SetTitle( (nominal && strlen(nominal->GetTitle())>0) ? nominal->GetTitle() : sample.GetName().c_str() );
915
916 ////////////////////////////////////
917 // Add StatErrors to this Channel //
918 ////////////////////////////////////
919
920 if( sample.GetStatError().GetActivate() ) {
921
922 if( fObsNameVec.size() > 3 ) {
923 cxcoutF(HistFactory) << "Cannot include Stat Error for histograms of more than 3 dimensions."
924 << std::endl;
925 throw hf_exc();
926 } else {
927
928 // If we are using StatUncertainties, we multiply this object
929 // by the ParamHistFunc and then pass that to the
930 // RooRealSumPdf by appending it's name to the list
931
932 cxcoutI(HistFactory) << "Sample: " << sample.GetName() << " to be included in Stat Error "
933 << "for channel " << channel_name
934 << std::endl;
935
936 string UncertName = sample.GetName() + "_" + channel_name + "_StatAbsolUncert";
937 std::unique_ptr<TH1> statErrorHist;
938
939 if( sample.GetStatError().GetErrorHist() == nullptr ) {
940 // Make the absolute stat error
941 cxcoutI(HistFactory) << "Making Statistical Uncertainty Hist for "
942 << " Channel: " << channel_name
943 << " Sample: " << sample.GetName()
944 << std::endl;
946 } else {
947 // clone the error histograms because in case the sample has not error hist
948 // it is created in MakeAbsolUncertainty
949 // we need later to clean statErrorHist
950 statErrorHist.reset(static_cast<TH1*>(sample.GetStatError().GetErrorHist()->Clone()));
951 // We assume the (relative) error is provided.
952 // We must turn it into an absolute error
953 // using the nominal histogram
954 cxcoutI(HistFactory) << "Using external histogram for Stat Errors for "
955 << "\tChannel: " << channel_name
956 << "\tSample: " << sample.GetName()
957 << "\tError Histogram: " << statErrorHist->GetName() << std::endl;
958 // Multiply the relative stat uncertainty by the
959 // nominal to get the overall stat uncertainty
960 statErrorHist->Multiply( nominal );
961 statErrorHist->SetName( UncertName.c_str() );
962 }
963
964 // Save the nominal and error hists
965 // for the building of constraint terms
966 statHistPairs.emplace_back(nominal, std::move(statErrorHist));
967
968 // To do the 'conservative' version, we would need to do some
969 // intervention here. We would probably need to create a different
970 // ParamHistFunc for each sample in the channel. The would nominally
971 // use the same gamma's, so we haven't increased the number of parameters
972 // However, if a bin in the 'nominal' histogram is 0, we simply need to
973 // change the parameter in that bin in the ParamHistFunc for this sample.
974 // We also need to add a constraint term.
975 // Actually, we'd probably not use the ParamHistFunc...?
976 // we could remove the dependence in this ParamHistFunc on the ith gamma
977 // and then create the poisson term: Pois(tau | n_exp)Pois(data | n_exp)
978
979
980 // Next, try to get the common ParamHistFunc (it may have been
981 // created by another sample in this channel)
982 // or create it if it doesn't yet exist:
983 RooAbsReal* paramHist = dynamic_cast<ParamHistFunc*>(proto.function(statFuncName) );
984 if( paramHist == nullptr ) {
985
986 // Get a RooArgSet of the observables:
987 // Names in the list fObsNameVec:
989 std::vector<std::string>::iterator itr = fObsNameVec.begin();
990 for (int idx=0; itr!=fObsNameVec.end(); ++itr, ++idx ) {
991 theObservables.add( *proto.var(*itr) );
992 }
993
994 // Create the list of terms to
995 // control the bin heights:
996 std::string ParamSetPrefix = "gamma_stat_" + channel_name;
1001
1004
1006
1007 paramHist = proto.function( statFuncName);
1008 }
1009
1010 // apply stat function to sample
1011 sampleHistFuncs.push_back(paramHist);
1012 }
1013 } // END: if DoMcStat
1014
1015
1016 ///////////////////////////////////////////
1017 // Create a ShapeFactor for this channel //
1018 ///////////////////////////////////////////
1019
1020 if( !sample.GetShapeFactorList().empty() ) {
1021
1022 if( fObsNameVec.size() > 3 ) {
1023 cxcoutF(HistFactory) << "Cannot include Stat Error for histograms of more than 3 dimensions."
1024 << std::endl;
1025 throw hf_exc();
1026 } else {
1027
1028 cxcoutI(HistFactory) << "Sample: " << sample.GetName() << " in channel: " << channel_name
1029 << " to be include a ShapeFactor."
1030 << std::endl;
1031
1032 for(ShapeFactor& shapeFactor : sample.GetShapeFactorList()) {
1033
1034 std::string funcName = channel_name + "_" + shapeFactor.GetName() + "_shapeFactor";
1035 RooAbsArg *paramHist = proto.function(funcName);
1036 if( paramHist == nullptr ) {
1037
1039 for(std::string const& varName : fObsNameVec) {
1040 theObservables.add( *proto.var(varName) );
1041 }
1042
1043 // Create the Parameters
1044 std::string funcParams = "gamma_" + shapeFactor.GetName();
1045
1046 // GHL: Again, we are putting hard ranges on the gamma's
1047 // We should change this to range from 0 to /inf
1049 funcParams,
1051
1052 // Create the Function
1053 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1055
1056 // Set an initial shape, if requested
1057 if( shapeFactor.GetInitialShape() != nullptr ) {
1058 TH1* initialShape = static_cast<TH1*>(shapeFactor.GetInitialShape()->Clone());
1059 cxcoutI(HistFactory) << "Setting Shape Factor: " << shapeFactor.GetName()
1060 << " to have initial shape from hist: "
1061 << initialShape->GetName()
1062 << std::endl;
1063 shapeFactorFunc.setShape( initialShape );
1064 }
1065
1066 // Set the variables constant, if requested
1067 if( shapeFactor.IsConstant() ) {
1068 cxcoutI(HistFactory) << "Setting Shape Factor: " << shapeFactor.GetName()
1069 << " to be constant" << std::endl;
1070 shapeFactorFunc.setConstant(true);
1071 }
1072
1074 paramHist = proto.function(funcName);
1075
1076 } // End: Create ShapeFactor ParamHistFunc
1077
1078 sampleHistFuncs.push_back(paramHist);
1079 } // End loop over ShapeFactor Systematics
1080 }
1081 } // End: if ShapeFactorName!=""
1082
1083
1084 ////////////////////////////////////////
1085 // Create a ShapeSys for this channel //
1086 ////////////////////////////////////////
1087
1088 if( !sample.GetShapeSysList().empty() ) {
1089
1090 if( fObsNameVec.size() > 3 ) {
1091 cxcoutF(HistFactory) << "Cannot include Stat Error for histograms of more than 3 dimensions."
1092 << std::endl;
1093 throw hf_exc();
1094 }
1095
1096 // List of ShapeSys ParamHistFuncs
1097 std::vector<string> ShapeSysNames;
1098
1099 for(RooStats::HistFactory::ShapeSys& shapeSys : sample.GetShapeSysList()) {
1100
1101 // Create the ParamHistFunc's
1102 // Create their constraint terms and add them
1103 // to the list of constraint terms
1104
1105 // Create a single RooProduct over all of these
1106 // paramHistFunc's
1107
1108 // Send the name of that product to the RooRealSumPdf
1109
1110 cxcoutI(HistFactory) << "Sample: " << sample.GetName() << " in channel: " << channel_name
1111 << " to include a ShapeSys." << std::endl;
1112
1113 std::string funcName = channel_name + "_" + shapeSys.GetName() + "_ShapeSys";
1114 ShapeSysNames.push_back( funcName );
1115 auto paramHist = static_cast<ParamHistFunc*>(proto.function(funcName));
1116 if( paramHist == nullptr ) {
1117
1118 //std::string funcParams = "gamma_" + it->shapeFactorName;
1119 //paramHist = CreateParamHistFunc( proto, fObsNameVec, funcParams, funcName );
1120
1122 for(std::string const& varName : fObsNameVec) {
1123 theObservables.add( *proto.var(varName) );
1124 }
1125
1126 // Create the Parameters
1127 std::string funcParams = "gamma_" + shapeSys.GetName();
1129 funcParams,
1131
1132 // Create the Function
1133 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1135
1137 paramHist = static_cast<ParamHistFunc*>(proto.function(funcName));
1138
1139 } // End: Create ShapeFactor ParamHistFunc
1140
1141 // Create the constraint terms and add
1142 // them to the workspace (proto)
1143 // as well as the list of constraint terms (constraintTermNames)
1144
1145 // The syst should be a fractional error
1146 const TH1* shapeErrorHist = shapeSys.GetErrorHist();
1147
1148 // Constraint::Type shapeConstraintType = Constraint::Gaussian;
1149 Constraint::Type systype = shapeSys.GetConstraintType();
1152 }
1153 if( systype == Constraint::Poisson ) {
1155 }
1156
1158 paramHist->paramList(), histToVector(*shapeErrorHist),
1160 systype);
1161 for (auto const& term : shapeConstraintsInfo.constraints) {
1163 constraintTermNames.emplace_back(term->GetName());
1164 }
1165 // Add the "observed" value to the list of global observables:
1166 RooArgSet *globalSet = const_cast<RooArgSet *>(proto.set("globalObservables"));
1167 for (RooAbsArg * glob : shapeConstraintsInfo.globalObservables) {
1168 globalSet->add(*proto.var(glob->GetName()));
1169 }
1170
1171
1172 } // End: Loop over ShapeSys vector in this EstimateSummary
1173
1174 // Now that we have the list of ShapeSys ParamHistFunc names,
1175 // we create the total RooProduct
1176 // we multiply the expected function
1177
1178 for(std::string const& name : ShapeSysNames) {
1179 sampleHistFuncs.push_back(proto.function(name));
1180 }
1181
1182 } // End: !GetShapeSysList.empty()
1183
1184
1185 // GHL: This was pretty confusing before,
1186 // hopefully using the measurement directly
1187 // will improve it
1188 RooAbsArg *lumi = proto.arg("Lumi");
1189 if( !sample.GetNormalizeByTheory() ) {
1190 if (!lumi) {
1191 lumi = &emplace<RooRealVar>(proto, "Lumi", measurement.GetLumi());
1192 } else {
1193 static_cast<RooAbsRealLValue*>(lumi)->setVal(measurement.GetLumi());
1194 }
1195 }
1196 assert(lumi);
1197 normFactors->addTerm(lumi);
1198
1199 // Append the name of the "node"
1200 // that is to be summed with the
1201 // RooRealSumPdf
1203 auto normFactorsInWS = dynamic_cast<RooProduct*>(proto.arg(normFactors->GetName()));
1205
1207 } // END: Loop over EstimateSummaries
1208
1209 // If a non-zero number of samples call for
1210 // Stat Uncertainties, create the statFactor functions
1211 if(!statHistPairs.empty()) {
1212
1213 // Create the histogram of (binwise)
1214 // stat uncertainties:
1216 if( fracStatError == nullptr ) {
1217 cxcoutE(HistFactory) << "Error: Failed to make ScaledUncertaintyHist for: "
1218 << channel_name + "_StatUncert" + "_RelErr" << std::endl;
1219 throw hf_exc();
1220 }
1221
1222 // Using this TH1* of fractinal stat errors,
1223 // create a set of constraint terms:
1224 auto chanStatUncertFunc = static_cast<ParamHistFunc*>(proto.function( statFuncName ));
1225 cxcoutI(HistFactory) << "About to create Constraint Terms from: "
1226 << chanStatUncertFunc->GetName()
1227 << " params: " << chanStatUncertFunc->paramList()
1228 << std::endl;
1229
1230 // Get the constraint type and the
1231 // rel error threshold from the (last)
1232 // EstimateSummary looped over (but all
1233 // should be the same)
1234
1235 // Get the type of StatError constraint from the channel
1238 cxcoutI(HistFactory) << "Using Gaussian StatErrors in channel: " << channel.GetName() << std::endl;
1239 }
1241 cxcoutI(HistFactory) << "Using Poisson StatErrors in channel: " << channel.GetName() << std::endl;
1242 }
1243
1249 for (auto const& term : statConstraintsInfo.constraints) {
1251 constraintTermNames.emplace_back(term->GetName());
1252 }
1253 // Add the "observed" value to the list of global observables:
1254 RooArgSet *globalSet = const_cast<RooArgSet *>(proto.set("globalObservables"));
1255 for (RooAbsArg * glob : statConstraintsInfo.globalObservables) {
1256 globalSet->add(*proto.var(glob->GetName()));
1257 }
1258
1259 } // END: Loop over stat Hist Pairs
1260
1261
1262 ///////////////////////////////////
1263 // for ith bin calculate totN_i = lumi * sum_j expected_j * syst_j
1266 likelihoodTermNames.push_back(channel_name+"_model");
1267
1268 //////////////////////////////////////
1269 // fix specified parameters
1270 for(unsigned int i=0; i<systToFix.size(); ++i){
1271 RooRealVar* temp = proto.var(systToFix.at(i));
1272 if(!temp) {
1273 cxcoutW(HistFactory) << "could not find variable " << systToFix.at(i)
1274 << " could not set it to constant" << std::endl;
1275 } else {
1276 // set the parameter constant
1277 temp->setConstant();
1278 }
1279 }
1280
1281 //////////////////////////////////////
1282 // final proto model
1283 for(unsigned int i=0; i<constraintTermNames.size(); ++i){
1285 if( proto_arg==nullptr ) {
1286 cxcoutF(HistFactory) << "Error: Cannot find arg set: " << constraintTermNames.at(i)
1287 << " in workspace: " << proto.GetName() << std::endl;
1288 throw hf_exc();
1289 }
1290 constraintTerms.add( *proto_arg );
1291 // constraintTerms.add(* proto_arg(proto.arg(constraintTermNames[i].c_str())) );
1292 }
1293 for(unsigned int i=0; i<likelihoodTermNames.size(); ++i){
1295 if( proto_arg==nullptr ) {
1296 cxcoutF(HistFactory) << "Error: Cannot find arg set: " << likelihoodTermNames.at(i)
1297 << " in workspace: " << proto.GetName() << std::endl;
1298 throw hf_exc();
1299 }
1300 likelihoodTerms.add( *proto_arg );
1301 }
1302 proto.defineSet("constraintTerms",constraintTerms);
1303 proto.defineSet("likelihoodTerms",likelihoodTerms);
1304
1305 // list of observables
1306 RooArgList observables;
1307 std::string observablesStr;
1308
1309 for(std::string const& name : fObsNameVec) {
1310 observables.add( *proto.var(name) );
1311 if (!observablesStr.empty()) { observablesStr += ","; }
1313 }
1314
1315 // We create two sets, one for backwards compatibility
1316 // The other to make a consistent naming convention
1317 // between individual channels and the combined workspace
1318 proto.defineSet("observables", observablesStr.c_str());
1319 proto.defineSet("observablesSet", observablesStr.c_str());
1320
1321 // Create the ParamHistFunc
1322 // after observables have been made
1323 cxcoutP(HistFactory) << "\n-----------------------------------------\n"
1324 << "\timport model into workspace"
1325 << "\n-----------------------------------------\n" << std::endl;
1326
1327 auto model = make_unique<RooProdPdf>(
1328 ("model_"+channel_name).c_str(), // MB : have changed this into conditional pdf. Much faster for toys!
1329 "product of Poissons across bins for a single channel",
1331 // can give channel a title by setting title of corresponding data histogram
1332 if (channel.GetData().GetHisto() && strlen(channel.GetData().GetHisto()->GetTitle())>0) {
1333 model->SetTitle(channel.GetData().GetHisto()->GetTitle());
1334 }
1335 proto.import(*model,RooFit::RecycleConflictNodes());
1336
1337 proto_config->SetPdf(*model);
1338 proto_config->SetObservables(observables);
1339 proto_config->SetGlobalObservables(*proto.set("globalObservables"));
1340 // proto.writeToFile(("results/model_"+channel+".root").c_str());
1341 // fill out nuisance parameters in model config
1342 // proto_config->GuessObsAndNuisance(*proto.data("asimovData"));
1343 proto.import(*proto_config,proto_config->GetName());
1344 proto.importClassCode();
1345
1346 ///////////////////////////
1347 // make data sets
1348 // THis works and is natural, but the memory size of the simultaneous dataset grows exponentially with channels
1349 // New Asimov Generation: Use the code in the Asymptotic calculator
1350 // Need to get the ModelConfig...
1351 int asymcalcPrintLevel = 0;
1356 proto.import(*asimov_dataset, RooFit::Rename("asimovData"));
1357
1358 // GHL: Determine to use data if the hist isn't 'nullptr'
1359 if(TH1 const* mnominal = channel.GetData().GetHisto()) {
1360 // This works and is natural, but the memory size of the simultaneous
1361 // dataset grows exponentially with channels.
1362 std::unique_ptr<RooDataSet> dataset;
1363 if(!fCfg.storeDataError){
1364 dataset = std::make_unique<RooDataSet>("obsData","",*proto.set("observables"), RooFit::WeightVar("weightVar"));
1365 } else {
1366 const char* weightErrName="weightErr";
1367 proto.factory(TString::Format("%s[0,-1e10,1e10]",weightErrName));
1368 dataset = std::make_unique<RooDataSet>("obsData","",*proto.set("observables"), RooFit::WeightVar("weightVar"), RooFit::StoreError(*proto.var(weightErrName)));
1369 }
1371 proto.import(*dataset);
1372 } // End: Has non-null 'data' entry
1373
1374
1375 for(auto const& data : channel.GetAdditionalData()) {
1376 if(data.GetName().empty()) {
1377 cxcoutF(HistFactory) << "Error: Additional Data histogram for channel: " << channel.GetName()
1378 << " has no name! The name always needs to be set for additional datasets, "
1379 << "either via the \"Name\" tag in the XML or via RooStats::HistFactory::Data::SetName()." << std::endl;
1380 throw hf_exc();
1381 }
1382 std::string const& dataName = data.GetName();
1383 TH1 const* mnominal = data.GetHisto();
1384 if( !mnominal ) {
1385 cxcoutF(HistFactory) << "Error: Additional Data histogram for channel: " << channel.GetName()
1386 << " with name: " << dataName << " is nullptr" << std::endl;
1387 throw hf_exc();
1388 }
1389
1390 // THis works and is natural, but the memory size of the simultaneous dataset grows exponentially with channels
1391 RooDataSet dataset{dataName, "", *proto.set("observables"), RooFit::WeightVar("weightVar")};
1393 proto.import(dataset);
1394
1395 }
1396
1397 if (RooMsgService::instance().isActive(nullptr, RooFit::HistFactory, RooFit::INFO)) {
1398 proto.Print();
1399 }
1400
1401 return protoOwner;
1402 }
1403
1404
1406 TH1 const& mnominal,
1408 std::vector<std::string> const& obsNameVec) {
1409
1410 // Take a RooDataSet and fill it with the entries
1411 // from a TH1*, using the observable names to
1412 // determine the columns
1413
1414 if (obsNameVec.empty() ) {
1415 Error("ConfigureHistFactoryDataset","Invalid input - return");
1416 return;
1417 }
1418
1419 TAxis const* ax = mnominal.GetXaxis();
1420 TAxis const* ay = mnominal.GetYaxis();
1421 TAxis const* az = mnominal.GetZaxis();
1422
1423 // check whether the dataset needs the errors stored explicitly
1424 const bool storeWeightErr = obsDataUnbinned.weightVar()->getAttribute("StoreError");
1425
1426 for (int i=1; i<=ax->GetNbins(); ++i) { // 1 or more dimension
1427
1428 double xval = ax->GetBinCenter(i);
1429 proto.var( obsNameVec[0] )->setVal( xval );
1430
1431 if(obsNameVec.size()==1) {
1432 double fval = mnominal.GetBinContent(i);
1433 double ferr = storeWeightErr ? mnominal.GetBinError(i) : 0.;
1434 obsDataUnbinned.add( *proto.set("observables"), fval, ferr );
1435 } else { // 2 or more dimensions
1436
1437 for(int j=1; j<=ay->GetNbins(); ++j) {
1438 double yval = ay->GetBinCenter(j);
1439 proto.var( obsNameVec[1] )->setVal( yval );
1440
1441 if(obsNameVec.size()==2) {
1442 double fval = mnominal.GetBinContent(i,j);
1443 double ferr = storeWeightErr ? mnominal.GetBinError(i, j) : 0.;
1444 obsDataUnbinned.add( *proto.set("observables"), fval, ferr );
1445 } else { // 3 dimensions
1446
1447 for(int k=1; k<=az->GetNbins(); ++k) {
1448 double zval = az->GetBinCenter(k);
1449 proto.var( obsNameVec[2] )->setVal( zval );
1450 double fval = mnominal.GetBinContent(i,j,k);
1451 double ferr = storeWeightErr ? mnominal.GetBinError(i, j, k) : 0.;
1452 obsDataUnbinned.add( *proto.set("observables"), fval, ferr );
1453 }
1454 }
1455 }
1456 }
1457 }
1458 }
1459
1461 {
1462 fObsNameVec = std::vector<string>{"x", "y", "z"};
1463 fObsNameVec.resize(hist->GetDimension());
1464 }
1465
1466
1469 std::vector<std::unique_ptr<RooWorkspace>> &chs)
1470 {
1472
1473 // check first the inputs (see JIRA-6890)
1474 if (ch_names.empty() || chs.empty() ) {
1475 Error("MakeCombinedModel","Input vectors are empty - return a nullptr");
1476 return nullptr;
1477 }
1478 if (chs.size() < ch_names.size() ) {
1479 Error("MakeCombinedModel","Input vector of workspace has an invalid size - return a nullptr");
1480 return nullptr;
1481 }
1482
1483 //
1484 /// These things were used for debugging. Maybe useful in the future
1485 //
1486
1489
1491 for(unsigned int i = 0; i< ch_names.size(); ++i){
1492 obsList.add(*static_cast<ModelConfig *>(chs[i]->obj("ModelConfig"))->GetObservables());
1493 }
1494 cxcoutI(HistFactory) <<"full list of observables:\n" << obsList << std::endl;
1495
1497 std::map<std::string, int> channelMap;
1498 for(unsigned int i = 0; i< ch_names.size(); ++i){
1499 string channel_name=ch_names[i];
1500 if (i == 0 && isdigit(channel_name[0])) {
1501 throw std::invalid_argument("The first channel name for HistFactory cannot start with a digit. Got " + channel_name);
1502 }
1503 if (channel_name.find(',') != std::string::npos) {
1504 throw std::invalid_argument("Channel names for HistFactory cannot contain ','. Got " + channel_name);
1505 }
1506
1508 RooWorkspace * ch=chs[i].get();
1509
1510 RooAbsPdf* model = ch->pdf("model_"+channel_name);
1511 if(!model) std::cout <<"failed to find model for channel"<< std::endl;
1512 // std::cout << "int = " << model->createIntegral(*obsN)->getVal() << std::endl;
1513 models.push_back(model);
1514 globalObs.add(*ch->set("globalObservables"), /*silent=*/true); // silent because observables might exist in other channel.
1515
1516 // constrainedParams->add( * ch->set("constrainedParams") );
1517 pdfMap[channel_name]=model;
1518 }
1519
1520 cxcoutP(HistFactory) << "\n-----------------------------------------\n"
1521 << "\tEntering combination"
1522 << "\n-----------------------------------------\n" << std::endl;
1523 auto combined = std::make_unique<RooWorkspace>("combined");
1524
1525
1527
1528 auto simPdf= std::make_unique<RooSimultaneous>("simPdf","",pdfMap, channelCat);
1529 auto combined_config = std::make_unique<ModelConfig>("ModelConfig", combined.get());
1530 combined_config->SetWorkspace(*combined);
1531 // combined_config->SetNuisanceParameters(*constrainedParams);
1532
1533 combined->import(globalObs);
1534 combined->defineSet("globalObservables",globalObs);
1535 combined_config->SetGlobalObservables(*combined->set("globalObservables"));
1536
1537 combined->defineSet("observables",{obsList, channelCat}, /*importMissing=*/true);
1538 combined_config->SetObservables(*combined->set("observables"));
1539
1540
1541 // Now merge the observable datasets across the channels
1542 for(RooAbsData * data : chs[0]->allData()) {
1543 // We are excluding the Asimov data, because it needs to be regenerated
1544 // later after the parameter values are set.
1545 if(std::string("asimovData") == data->GetName()) {
1546 continue;
1547 }
1548 // Loop through channels, get their individual datasets,
1549 // and add them to the combined dataset
1550 std::map<std::string, RooAbsData*> dataMap;
1551 for(unsigned int i = 0; i < ch_names.size(); ++i){
1552 dataMap[ch_names[i]] = chs[i]->data(data->GetName());
1553 }
1554 combined->import(RooDataSet{data->GetName(), "", obsList, RooFit::Index(channelCat),
1555 RooFit::WeightVar("weightVar"), RooFit::Import(dataMap)});
1556 }
1557
1558
1560 combined->Print();
1561
1562 cxcoutP(HistFactory) << "\n-----------------------------------------\n"
1563 << "\tImporting combined model"
1564 << "\n-----------------------------------------\n" << std::endl;
1566
1567 for(auto const& param_itr : fParamValues) {
1568 // make sure they are fixed
1569 std::string paramName = param_itr.first;
1570 double paramVal = param_itr.second;
1571
1572 if(RooRealVar* temp = combined->var( paramName )) {
1573 temp->setVal( paramVal );
1574 cxcoutI(HistFactory) <<"setting " << paramName << " to the value: " << paramVal << std::endl;
1575 } else
1576 cxcoutE(HistFactory) << "could not find variable " << paramName << " could not set its value" << std::endl;
1577 }
1578
1579
1580 for(unsigned int i=0; i<fSystToFix.size(); ++i){
1581 // make sure they are fixed
1582 if(RooRealVar* temp = combined->var(fSystToFix[i])) {
1583 temp->setConstant();
1584 cxcoutI(HistFactory) <<"setting " << fSystToFix.at(i) << " constant" << std::endl;
1585 } else
1586 cxcoutE(HistFactory) << "could not find variable " << fSystToFix.at(i) << " could not set it to constant" << std::endl;
1587 }
1588
1589 ///
1590 /// writing out the model in graphViz
1591 ///
1592 // RooAbsPdf* customized=combined->pdf("simPdf");
1593 //combined_config->SetPdf(*customized);
1594 combined_config->SetPdf(*simPdf);
1595 // combined_config->GuessObsAndNuisance(*simData);
1596 // customized->graphVizTree(("results/"+fResultsPrefixStr.str()+"_simul.dot").c_str());
1597 combined->import(*combined_config,combined_config->GetName());
1598 combined->importClassCode();
1599 // combined->writeToFile("results/model_combined.root");
1600
1601
1602 ////////////////////////////////////////////
1603 // Make toy simultaneous dataset
1604 cxcoutP(HistFactory) << "\n-----------------------------------------\n"
1605 << "\tcreate toy data"
1606 << "\n-----------------------------------------\n" << std::endl;
1607
1608
1609 // now with weighted datasets
1610 // First Asimov
1611
1612 // Create Asimov data for the combined dataset
1614 *combined->pdf("simPdf"),
1615 obsList)};
1616 if( asimov_combined ) {
1617 combined->import( *asimov_combined, RooFit::Rename("asimovData"));
1618 }
1619 else {
1620 std::cout << "Error: Failed to create combined asimov dataset" << std::endl;
1621 throw hf_exc();
1622 }
1623
1624 return RooFit::makeOwningPtr(std::move(combined));
1625 }
1626
1627
1629
1630 // Take a nominal TH1* and create
1631 // a TH1 representing the binwise
1632 // errors (taken from the nominal TH1)
1633
1634 auto ErrorHist = static_cast<TH1*>(Nominal->Clone( Name.c_str() ));
1635 ErrorHist->Reset();
1636
1637 int numBins = Nominal->GetNbinsX()*Nominal->GetNbinsY()*Nominal->GetNbinsZ();
1638 int binNumber = 0;
1639
1640 // Loop over bins
1641 for( int i_bin = 0; i_bin < numBins; ++i_bin) {
1642
1643 binNumber++;
1644 // Ignore underflow / overflow
1645 while( Nominal->IsBinUnderflow(binNumber) || Nominal->IsBinOverflow(binNumber) ){
1646 binNumber++;
1647 }
1648
1649 double histError = Nominal->GetBinError( binNumber );
1650
1651 // Check that histError != NAN
1652 if( histError != histError ) {
1653 std::cout << "Warning: In histogram " << Nominal->GetName()
1654 << " bin error for bin " << i_bin
1655 << " is NAN. Not using Error!!!"
1656 << std::endl;
1657 throw hf_exc();
1658 //histError = sqrt( histContent );
1659 //histError = 0;
1660 }
1661
1662 // Check that histError ! < 0
1663 if( histError < 0 ) {
1664 std::cout << "Warning: In histogram " << Nominal->GetName()
1665 << " bin error for bin " << binNumber
1666 << " is < 0. Setting Error to 0"
1667 << std::endl;
1668 //histError = sqrt( histContent );
1669 histError = 0;
1670 }
1671
1672 ErrorHist->SetBinContent( binNumber, histError );
1673
1674 }
1675
1676 return ErrorHist;
1677
1678 }
1679
1680 // Take a list of < nominal, absolError > TH1* pairs
1681 // and construct a single histogram representing the
1682 // total fractional error as:
1683
1684 // UncertInQuad(bin i) = Sum: absolUncert*absolUncert
1685 // Total(bin i) = Sum: Value
1686 //
1687 // TotalFracError(bin i) = Sqrt( UncertInQuad(i) ) / TotalBin(i)
1688 std::unique_ptr<TH1> HistoToWorkspaceFactoryFast::MakeScaledUncertaintyHist( const std::string& Name, std::vector< std::pair<const TH1*, std::unique_ptr<TH1>> > const& HistVec ) const {
1689
1690
1691 unsigned int numHists = HistVec.size();
1692
1693 if( numHists == 0 ) {
1694 cxcoutE(HistFactory) << "Warning: Empty Hist Vector, cannot create total uncertainty" << std::endl;
1695 return nullptr;
1696 }
1697
1698 const TH1* HistTemplate = HistVec.at(0).first;
1699 int numBins = HistTemplate->GetNbinsX()*HistTemplate->GetNbinsY()*HistTemplate->GetNbinsZ();
1700
1701 // Check that all histograms
1702 // have the same bins
1703 for( unsigned int i = 0; i < HistVec.size(); ++i ) {
1704
1705 const TH1* nominal = HistVec.at(i).first;
1706 const TH1* error = HistVec.at(i).second.get();
1707
1708 if( nominal->GetNbinsX()*nominal->GetNbinsY()*nominal->GetNbinsZ() != numBins ) {
1709 cxcoutE(HistFactory) << "Error: Provided hists have unequal bins" << std::endl;
1710 return nullptr;
1711 }
1712 if( error->GetNbinsX()*error->GetNbinsY()*error->GetNbinsZ() != numBins ) {
1713 cxcoutE(HistFactory) << "Error: Provided hists have unequal bins" << std::endl;
1714 return nullptr;
1715 }
1716 }
1717
1718 std::vector<double> TotalBinContent( numBins, 0.0);
1719 std::vector<double> HistErrorsSqr( numBins, 0.0);
1720
1721 int binNumber = 0;
1722
1723 // Loop over bins
1724 for( int i_bins = 0; i_bins < numBins; ++i_bins) {
1725
1726 binNumber++;
1727 while( HistTemplate->IsBinUnderflow(binNumber) || HistTemplate->IsBinOverflow(binNumber) ){
1728 binNumber++;
1729 }
1730
1731 for( unsigned int i_hist = 0; i_hist < numHists; ++i_hist ) {
1732
1733 const TH1* nominal = HistVec.at(i_hist).first;
1734 const TH1* error = HistVec.at(i_hist).second.get();
1735
1736 //int binNumber = i_bins + 1;
1737
1738 double histValue = nominal->GetBinContent( binNumber );
1739 double histError = error->GetBinContent( binNumber );
1740
1741 if( histError != histError ) {
1742 cxcoutE(HistFactory) << "In histogram " << error->GetName()
1743 << " bin error for bin " << binNumber
1744 << " is NAN. Not using error!!";
1745 throw hf_exc();
1746 }
1747
1749 HistErrorsSqr.at(i_bins) += histError*histError; // Add in quadrature
1750
1751 }
1752 }
1753
1754 binNumber = 0;
1755
1756 // Creat the output histogram
1757 TH1* ErrorHist = static_cast<TH1*>(HistTemplate->Clone( Name.c_str() ));
1758 ErrorHist->Reset();
1759
1760 // Fill the output histogram
1761 for( int i = 0; i < numBins; ++i) {
1762
1763 // int binNumber = i + 1;
1764 binNumber++;
1765 while( ErrorHist->IsBinUnderflow(binNumber) || ErrorHist->IsBinOverflow(binNumber) ){
1766 binNumber++;
1767 }
1768
1769 double ErrorsSqr = HistErrorsSqr.at(i);
1770 double TotalVal = TotalBinContent.at(i);
1771
1772 if( TotalVal <= 0 ) {
1773 cxcoutW(HistFactory) << "Warning: Sum of histograms for bin: " << binNumber
1774 << " is <= 0. Setting error to 0"
1775 << std::endl;
1776
1777 ErrorHist->SetBinContent( binNumber, 0.0 );
1778 continue;
1779 }
1780
1781 double RelativeError = sqrt(ErrorsSqr) / TotalVal;
1782
1783 // If we otherwise get a NAN
1784 // it's an error
1785 if( RelativeError != RelativeError ) {
1786 cxcoutE(HistFactory) << "Error: bin " << i << " error is NAN\n"
1787 << " HistErrorsSqr: " << ErrorsSqr
1788 << " TotalVal: " << TotalVal;
1789 throw hf_exc();
1790 }
1791
1792 // 0th entry in vector is
1793 // the 1st bin in TH1
1794 // (we ignore underflow)
1795
1796 // Error and bin content are interchanged because for some reason, the other functions
1797 // use the bin content to convey the error ...
1798 ErrorHist->SetBinError(binNumber, TotalVal);
1799 ErrorHist->SetBinContent(binNumber, RelativeError);
1800
1801 cxcoutI(HistFactory) << "Making Total Uncertainty for bin " << binNumber
1802 << " Error = " << sqrt(ErrorsSqr)
1803 << " CentralVal = " << TotalVal
1804 << " RelativeError = " << RelativeError << "\n";
1805
1806 }
1807
1808 return std::unique_ptr<TH1>(ErrorHist);
1809}
1810
1811
1812} // namespace RooStats
1813} // namespace HistFactory
1814
#define cxcoutPHF
#define cxcoutFHF
#define cxcoutIHF
#define cxcoutWHF
std::vector< double > histToVector(TH1 const &hist)
constexpr double alphaHigh
constexpr double alphaLow
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define cxcoutI(a)
#define cxcoutW(a)
#define cxcoutF(a)
#define cxcoutE(a)
#define cxcoutP(a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
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 filename
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
char name[80]
Definition TGX11.cxx:110
const char * proto
Definition civetweb.c:17535
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
static RooArgList createParamSet(RooWorkspace &w, const std::string &, const RooArgList &Vars)
Create the list of RooRealVar parameters which represent the height of the histogram bins.
The PiecewiseInterpolation is a class that can morph distributions into each other,...
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
Abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:57
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
void setConstant(bool value=true)
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
Definition RooBinning.h:27
Object to represent discrete states.
Definition RooCategory.h:28
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
Container class to hold unbinned data.
Definition RooDataSet.h:34
RooFitResult is a container class to hold the input and output of a PDF fit to a dataset.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
Implementation of the Gamma PDF for RooFit/RooStats.
Definition RooGamma.h:20
Switches the message service to a different level while the instance is alive.
Definition RooHelpers.h:37
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
static RooMsgService & instance()
Return reference to singleton instance.
A RooAbsReal implementing a polynomial in terms of a list of RooAbsReal coefficients.
Definition RooPolyVar.h:25
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
Implements a PDF constructed from a sum of functions:
Variable that can be changed from the outside.
Definition RooRealVar.h:37
void setBinning(const RooAbsBinning &binning, const char *name=nullptr)
Add given binning under name 'name' with this variable.
void setBins(Int_t nBins, const char *name=nullptr)
Create a uniform binning under name 'name' for this variable.
static void SetPrintLevel(int level)
set print level (static function)
static RooAbsData * GenerateAsimovData(const RooAbsPdf &pdf, const RooArgSet &observables)
generate the asimov data for the observables (not the global ones) need to deal with the case of a si...
TODO Here, we are missing some documentation.
Definition Asimov.h:22
void ConfigureWorkspace(RooWorkspace *)
Definition Asimov.cxx:22
This class encapsulates all information for the statistical interpretation of one experiment.
Definition Channel.h:30
std::vector< RooStats::HistFactory::Data > & GetAdditionalData()
retrieve vector of additional data objects
Definition Channel.h:64
void Print(std::ostream &=std::cout)
Definition Channel.cxx:58
HistFactory::StatErrorConfig & GetStatErrorConfig()
get information about threshold for statistical uncertainties and constraint term
Definition Channel.h:71
RooStats::HistFactory::Data & GetData()
get data object
Definition Channel.h:58
std::vector< RooStats::HistFactory::Sample > & GetSamples()
get vector of samples for this channel
Definition Channel.h:76
std::string GetName() const
get name of channel
Definition Channel.h:42
This class provides helper functions for creating likelihood models from histograms.
std::unique_ptr< RooProduct > CreateNormFactor(RooWorkspace &proto, std::string &channel, std::string &sigmaEpsilon, Sample &sample, bool doRatio)
std::unique_ptr< RooWorkspace > MakeSingleChannelWorkspace(Measurement &measurement, Channel &channel)
void MakeTotalExpected(RooWorkspace &proto, const std::string &totName, const std::vector< RooProduct * > &sampleScaleFactors, std::vector< std::vector< RooAbsArg * > > &sampleHistFuncs) const
std::unique_ptr< TH1 > MakeScaledUncertaintyHist(const std::string &Name, std::vector< std::pair< const TH1 *, std::unique_ptr< TH1 > > > const &HistVec) const
RooHistFunc * MakeExpectedHistFunc(const TH1 *hist, RooWorkspace &proto, std::string prefix, const RooArgList &observables) const
Create the nominal hist function from hist, and register it in the workspace.
void SetFunctionsToPreprocess(std::vector< std::string > lines)
RooFit::OwningPtr< RooWorkspace > MakeSingleChannelModel(Measurement &measurement, Channel &channel)
RooFit::OwningPtr< RooWorkspace > MakeCombinedModel(std::vector< std::string >, std::vector< std::unique_ptr< RooWorkspace > > &)
TH1 * MakeAbsolUncertaintyHist(const std::string &Name, const TH1 *Hist)
static void ConfigureWorkspaceForMeasurement(const std::string &ModelName, RooWorkspace *ws_single, Measurement &measurement)
void AddConstraintTerms(RooWorkspace &proto, Measurement &measurement, std::string prefix, std::string interpName, std::vector< OverallSys > &systList, std::vector< std::string > &likelihoodTermNames, std::vector< std::string > &totSystTermNames)
void ConfigureHistFactoryDataset(RooDataSet &obsData, TH1 const &nominal, RooWorkspace &proto, std::vector< std::string > const &obsNameVec)
static void PrintCovarianceMatrix(RooFitResult *result, RooArgSet *params, std::string filename)
RooArgList createObservables(const TH1 *hist, RooWorkspace &proto) const
Create observables of type RooRealVar. Creates 1 to 3 observables, depending on the type of the histo...
The RooStats::HistFactory::Measurement class can be used to construct a model by combining multiple R...
Definition Measurement.h:31
Configuration for an un- constrained overall systematic to scale sample normalisations.
Definition Systematics.h:62
Configuration for a constrained overall systematic to scale sample normalisations.
Definition Systematics.h:34
*Un*constrained bin-by-bin variation of affected histogram.
Constrained bin-by-bin variation of affected histogram.
Constraint::Type GetConstraintType() const
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
Definition ModelConfig.h:35
Persistable container for RooFit projects.
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
const RooArgSet * set(RooStringView name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
bool import(const RooAbsArg &arg, 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={})
Import a RooAbsArg object, e.g.
Class to manage histogram axis.
Definition TAxis.h:32
Bool_t IsVariableBinSize() const
Definition TAxis.h:144
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
TAxis * GetZaxis()
Definition TH1.h:342
virtual Int_t GetNbinsY() const
Definition TH1.h:314
virtual Int_t GetNbinsZ() const
Definition TH1.h:315
virtual Int_t GetDimension() const
Definition TH1.h:299
TAxis * GetXaxis()
Definition TH1.h:340
virtual Int_t GetNbinsX() const
Definition TH1.h:313
TAxis * GetYaxis()
Definition TH1.h:341
Bool_t IsBinUnderflow(Int_t bin, Int_t axis=0) const
Return true if the bin is underflow.
Definition TH1.cxx:5212
Bool_t IsBinOverflow(Int_t bin, Int_t axis=0) const
Return true if the bin is overflow.
Definition TH1.cxx:5180
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5059
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1005
Stopwatch class.
Definition TStopwatch.h:28
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
RooCmdArg RecycleConflictNodes(bool flag=true)
RooCmdArg Rename(const char *suffix)
RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool depsAreCond=false)
RooConstVar & RooConst(double val)
RooCmdArg Index(RooCategory &icat)
RooCmdArg StoreError(const RooArgSet &aset)
RooCmdArg WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RooCmdArg Import(const char *state, TH1 &histo)
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35
@ ObjectHandling
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:40
CreateGammaConstraintsOutput createGammaConstraints(RooArgList const &paramList, std::span< const double > relSigmas, double minSigma, Constraint::Type type)
Namespace for the RooStats classes.
Definition CodegenImpl.h:58