81 std::vector<double> out(numBins);
83 for (
int i = 0; i < numBins; ++i) {
95using std::cout, std::endl, std::string, std::vector, std::make_unique, std::pair, std::unique_ptr, std::map;
110 fSystToFix( measurement.GetConstantParams() ),
111 fParamValues( measurement.GetParamValues() ),
112 fNomLumi( measurement.GetLumi() ),
113 fLumiError( measurement.GetLumi()*measurement.GetLumiRelErr() ),
114 fLowBin( measurement.GetBinLow() ),
115 fHighBin( measurement.GetBinHigh() ),
131 if( proto_config ==
nullptr ) {
132 std::cout <<
"Error: Did not find 'ModelConfig' object in file: " << ws_single->
GetName()
138 cxcoutWHF <<
"No Parametetrs of interest are set" << std::endl;
142 std::stringstream sstream;
143 sstream <<
"Setting Parameter(s) of Interest as: ";
144 for(
auto const& item : measurement.
GetPOIList()) {
145 sstream << item <<
" ";
150 for(
auto const& poi_name : measurement.
GetPOIList()) {
155 std::cout <<
"WARNING: Can't find parameter of interest: " << poi_name
156 <<
" in Workspace. Not setting in ModelConfig." << std::endl;
163 std::string NewModelName =
"newSimPdf";
168 std::cout <<
"Error: Failed to find dataset: " << expData
169 <<
" in workspace" << std::endl;
184 if( !pdf ) pdf = ws_single->
pdf( ModelName );
185 const RooArgSet* observables = ws_single->
set(
"observables");
188 std::string SnapShotName =
"NominalParamValues";
195 std::string AsimovName = asimov.
GetName();
197 cxcoutPHF <<
"Generating additional Asimov Dataset: " << AsimovName << std::endl;
201 cxcoutPHF <<
"Importing Asimov dataset" << std::endl;
204 std::cout <<
"Error: Failed to import Asimov dataset: " << AsimovName
232 string ch_name = channel.
GetName();
236 if( ws_single ==
nullptr ) {
237 cxcoutF(HistFactory) <<
"Error: Failed to make Single-Channel workspace for channel: " << ch_name
238 <<
" and measurement: " << measurement.
GetName() << std::endl;
268 vector<std::unique_ptr<RooWorkspace>> channel_workspaces;
269 vector<string> channel_names;
273 if( ! channel.CheckHistograms() ) {
274 cxcoutFHF <<
"MakeModelAndMeasurementsFast: Channel: " << channel.GetName()
275 <<
" has uninitialized histogram pointers" << std::endl;
279 string ch_name = channel.GetName();
280 channel_names.push_back(ch_name);
289 std::unique_ptr<RooWorkspace> ws{histFactory.
MakeCombinedModel( channel_names, channel_workspaces )};
302template <
class Arg_t,
typename... Args_t>
305 Arg_t arg{
name.c_str(),
name.c_str(), std::forward<Args_t>(args)...};
307 return *
dynamic_cast<Arg_t *
>(ws.
arg(
name));
316 for (
unsigned int idx=0; idx <
fObsNameVec.size(); ++idx) {
340 cxcoutI(HistFactory) <<
"processing hist " << hist->
GetName() << endl;
342 cxcoutF(HistFactory) <<
"hist is empty" << endl;
348 unsigned int histndim(1);
349 std::string classname = hist->
ClassName();
350 if (classname.find(
"TH1")==0) { histndim=1; }
351 else if (classname.find(
"TH2")==0) { histndim=2; }
352 else if (classname.find(
"TH3")==0) { histndim=3; }
355 prefix +=
"_Hist_alphanominal";
357 RooDataHist histDHist(prefix +
"DHist",
"",observables,hist);
359 return &emplace<RooHistFunc>(
proto, prefix, observables,histDHist,0);
365 std::vector<std::string> & constraintTermNames) {
366 std::string paramName = param.
GetName();
367 std::string nomName =
"nom_" + paramName;
368 std::string constraintName = paramName +
"Constraint";
371 if(
proto.pdf(constraintName))
return;
375 const double gaussSigma = isUniform ? 100. : 1.0;
377 cxcoutIHF <<
"Added a uniform constraint for " << paramName <<
" as a Gaussian constraint with a very large sigma " << std::endl;
380 constraintTermNames.emplace_back(constraintName);
382 RooRealVar &nomParam = emplace<RooRealVar>(
proto, nomName, 0., -10., 10.);
384 emplace<RooGaussian>(
proto, constraintName, paramVar, nomParam, gaussSigma);
386 const_cast<RooArgSet*
>(
proto.set(
"globalObservables"))->add(nomParam);
393 for(
auto const& histoSys : histoSysList) {
405 const string& prefix,
410 std::vector<double> low;
411 std::vector<double> high;
414 for(
unsigned int j=0; j<histoSysList.size(); ++j){
415 std::string str = prefix +
"_" + std::to_string(j);
417 const HistoSys& histoSys = histoSysList.at(j);
418 auto lowDHist = std::make_unique<RooDataHist>(str+
"lowDHist",
"",obsList, histoSys.
GetHistoLow());
419 auto highDHist = std::make_unique<RooDataHist>(str+
"highDHist",
"",obsList, histoSys.
GetHistoHigh());
420 lowSet.
addOwned(std::make_unique<RooHistFunc>((str+
"low").c_str(),
"",obsList,std::move(lowDHist),0));
421 highSet.
addOwned(std::make_unique<RooHistFunc>((str+
"high").c_str(),
"",obsList,std::move(highDHist),0));
426 interp.setPositiveDefinite();
427 interp.setAllInterpCodes(4);
430 interp.setBinIntegrator(obsSet);
431 interp.forceNumInt();
435 return proto.arg(prefix);
443 std::vector<string> prodNames;
446 vector<string> normFactorNames;
447 vector<string> rangeNames;
449 string overallNorm_times_sigmaEpsilon = sample.
GetName() +
"_" + channel +
"_scaleFactors";
450 auto sigEps =
proto.arg(sigmaEpsilon);
452 auto normFactor = std::make_unique<RooProduct>(overallNorm_times_sigmaEpsilon.c_str(), overallNorm_times_sigmaEpsilon.c_str(),
RooArgList(*sigEps));
454 if(!normList.empty()){
457 string varname = norm.GetName();
459 varname +=
"_" + channel;
465 std::stringstream range;
466 range <<
"[" << norm.GetVal() <<
"," << norm.GetLow() <<
"," << norm.GetHigh() <<
"]";
468 if(
proto.obj(varname) ==
nullptr) {
469 cxcoutI(HistFactory) <<
"making normFactor: " << norm.GetName() << endl;
471 emplace<RooRealVar>(
proto, varname, norm.GetVal(), norm.GetLow(), norm.GetHigh());
472 proto.var(varname)->setError(0);
475 prodNames.push_back(varname);
476 rangeNames.push_back(range.str());
477 normFactorNames.push_back(varname);
481 for (
const auto&
name : prodNames) {
484 normFactor->addTerm(arg);
489 unsigned int rangeIndex=0;
490 for( vector<string>::iterator nit = normFactorNames.begin(); nit!=normFactorNames.end(); ++nit){
491 if( count (normFactorNames.begin(), normFactorNames.end(), *nit) > 1 ){
492 cxcoutI(HistFactory) <<
"<NormFactor Name =\""<<*nit<<
"\"> is duplicated for <Sample Name=\""
493 << sample.
GetName() <<
"\">, but only one factor will be included. \n Instead, define something like"
494 <<
"\n\t<Function Name=\""<<*nit<<
"Squared\" Expression=\""<<*nit<<
"*"<<*nit<<
"\" Var=\""<<*nit<<rangeNames.at(rangeIndex)
495 <<
"\"> \nin your top-level XML's <Measurement> entry and use <NormFactor Name=\""<<*nit<<
"Squared\" in your channel XML file."<< endl;
505 std::vector<OverallSys>& systList,
506 vector<string>& constraintTermNames,
507 vector<string>& totSystTermNames) {
510 totSystTermNames.push_back(prefix);
513 vector<double> lowVec;
514 vector<double> highVec;
516 std::map<std::string, double>::iterator itconstr;
517 for(
unsigned int i = 0; i < systList.size(); ++i) {
520 std::string strname = sys.
GetName();
521 const char *
name = strname.c_str();
525 cxcoutI(HistFactory) <<
"HistoToWorkspaceFast::AddConstraintTerm - skip systematic " << sys.
GetName() << std::endl;
532 cxcoutI(HistFactory) <<
"HistoToWorkspaceFast::AddConstraintTerm - zero uncertainty assigned - skip systematic " << sys.
GetName() << std::endl;
535 const double tauVal = 1./(relerr*relerr);
536 const double sqtau = 1./relerr;
537 RooRealVar &beta = emplace<RooRealVar>(
proto,
"beta_" + strname, 1., 0., 10.);
539 RooRealVar &yvar = emplace<RooRealVar>(
proto,
"nom_" + std::string{beta.GetName()}, tauVal, 0., 10.);
541 RooRealVar &theta = emplace<RooRealVar>(
proto,
"theta_" + strname, 1./tauVal);
550 alphaOfBeta.
Print(
"t");
553 constraintTermNames.push_back(gamma.GetName());
556 const_cast<RooArgSet*
>(
proto.set(
"globalObservables"))->add(yvar);
559 params.
add(alphaOfBeta);
560 cxcoutI(HistFactory) <<
"Added a gamma constraint for " <<
name << std::endl;
567 makeGaussianConstraint(alpha,
proto, isUniform, constraintTermNames);
580 proto,
"alphaOfBeta_" + sys.
GetName(),
"x[0]*(pow(x[1],x[2])-1.)",
581 RooArgList{emplace<RooRealVar>(proto,
"tau_" + sys.GetName(), 1. / relerr),
582 emplace<RooRealVar>(proto,
"kappa_" + sys.GetName(), 1. + relerr), alpha});
584 cxcoutI(HistFactory) <<
"Added a log-normal constraint for " <<
name << std::endl;
586 alphaOfBeta.
Print(
"t");
588 params.
add(alphaOfBeta);
593 lowVec.push_back(sys.
GetLow());
594 highVec.push_back(sys.
GetHigh());
598 if(!systList.empty()){
602 assert(!params.
empty());
603 assert(lowVec.size() == params.
size());
605 FlexibleInterpVar interp( (interpName).c_str(),
"", params, 1., lowVec, highVec);
608 proto.import(interp);
612 emplace<RooConstVar>(
proto, interpName, 1.);
618 const vector<RooProduct*>& sampleScaleFactors, std::vector<vector<RooAbsArg*>>& sampleHistFuncs)
const {
619 assert(sampleScaleFactors.size() == sampleHistFuncs.size());
624 throw std::logic_error(
"HistFactory didn't process the observables correctly. Please file a bug report.");
626 auto firstHistFunc =
dynamic_cast<const RooHistFunc*
>(sampleHistFuncs.front().front());
627 if (!firstHistFunc) {
629 firstHistFunc =
dynamic_cast<const RooHistFunc*
>(piecewiseInt->nominalHist());
631 assert(firstHistFunc);
634 auto &binWidth = emplace<RooBinWidthFunction>(
proto, totName +
"_binWidth", *firstHistFunc,
true);
639 for (
unsigned int i=0; i < sampleHistFuncs.size(); ++i) {
640 assert(!sampleHistFuncs[i].empty());
641 coefList.
add(*sampleScaleFactors[i]);
643 std::vector<RooAbsArg*>& thisSampleHistFuncs = sampleHistFuncs[i];
644 thisSampleHistFuncs.push_back(&binWidth);
646 if (thisSampleHistFuncs.size() == 1) {
648 shapeList.
add(*thisSampleHistFuncs.front());
651 std::string
name = thisSampleHistFuncs.front()->GetName();
652 auto pos =
name.find(
"Hist_alpha");
653 if (pos != std::string::npos) {
654 name =
name.substr(0, pos) +
"shapes";
655 }
else if ( (pos =
name.find(
"nominal")) != std::string::npos) {
656 name =
name.substr(0, pos) +
"shapes";
659 RooProduct shapeProduct(
name.c_str(), thisSampleHistFuncs.front()->GetTitle(),
RooArgSet(thisSampleHistFuncs.begin(), thisSampleHistFuncs.end()));
666 RooRealSumPdf tot(totName.c_str(), totName.c_str(), shapeList, coefList,
true);
687 FILE* covFile = fopen ((
filename).c_str(),
"w");
688 fprintf(covFile,
" ") ;
689 for (
auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
690 if(myargi->isConstant())
continue;
691 fprintf(covFile,
" & %s", myargi->GetName());
693 fprintf(covFile,
"\\\\ \\hline \n" );
694 for (
auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
695 if(myargi->isConstant())
continue;
696 fprintf(covFile,
"%s", myargi->GetName());
697 for (
auto const *myargj : static_range_cast<RooRealVar *>(*params)) {
698 if(myargj->isConstant())
continue;
699 cout << myargi->GetName() <<
"," << myargj->GetName();
700 fprintf(covFile,
" & %.2f",
result->correlation(*myargi, *myargj));
703 fprintf(covFile,
" \\\\\n");
716 Error(
"MakeSingleChannelWorkspace",
717 "The input Channel does not contain any sample - return a nullptr");
721 const TH1* channel_hist_template = channel.
GetSamples().front().GetHisto();
722 if (channel_hist_template ==
nullptr) {
724 channel_hist_template = channel.
GetSamples().front().GetHisto();
726 if (channel_hist_template ==
nullptr) {
727 std::ostringstream stream;
728 stream <<
"The sample " << channel.
GetSamples().front().GetName()
729 <<
" in channel " << channel.
GetName() <<
" does not contain a histogram. This is the channel:\n";
730 channel.
Print(stream);
731 Error(
"MakeSingleChannelWorkspace",
"%s", stream.str().c_str());
736 std::cout <<
"MakeSingleChannelWorkspace: Channel: " << channel.
GetName()
737 <<
" has uninitialized histogram pointers" << std::endl;
751 string channel_name = channel.
GetName();
761 for (
unsigned int idx=0; idx<
fObsNameVec.size(); ++idx ) {
771 throw hf_exc(
"HistFactory is limited to 1- to 3-dimensional histograms.");
774 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
775 <<
"\tStarting to process '"
776 << channel_name <<
"' channel with " <<
fObsNameVec.size() <<
" observables"
777 <<
"\n-----------------------------------------\n" << endl;
782 auto protoOwner = std::make_unique<RooWorkspace>(channel_name.c_str(), (channel_name+
" workspace").c_str());
784 auto proto_config = make_unique<ModelConfig>(
"ModelConfig", &
proto);
785 proto_config->SetWorkspace(
proto);
789 cxcoutI(HistFactory) <<
"will preprocess this line: " << func <<endl;
794 RooArgSet likelihoodTerms(
"likelihoodTerms");
795 RooArgSet constraintTerms(
"constraintTerms");
796 vector<string> likelihoodTermNames;
797 vector<string> constraintTermNames;
798 vector<string> totSystTermNames;
800 std::vector<std::vector<RooAbsArg*>> allSampleHistFuncs;
801 std::vector<RooProduct*> sampleScaleFactors;
803 std::vector< pair<string,string> > statNamePairs;
804 std::vector< pair<const TH1*, std::unique_ptr<TH1>> > statHistPairs;
805 const std::string statFuncName =
"mc_stat_" + channel_name;
818 emplace<RooGaussian>(
proto,
"lumiConstraint", lumiVar, nominalLumiVar,
fLumiError);
820 proto.var(
"nominalLumi")->setConstant();
821 proto.defineSet(
"globalObservables",
"nominalLumi");
823 constraintTermNames.push_back(
"lumiConstraint");
825 proto.var(
"Lumi")->setConstant();
833 string overallSystName = sample.GetName() +
"_" + channel_name +
"_epsilon";
835 string systSourcePrefix =
"alpha_";
840 sample.GetOverallSysList(), constraintTermNames , totSystTermNames);
842 allSampleHistFuncs.emplace_back();
843 std::vector<RooAbsArg*>& sampleHistFuncs = allSampleHistFuncs.back();
856 const TH1* nominal = sample.GetHisto();
868 string expPrefix = sample.
GetName() +
"_" + channel_name;
872 assert(nominalHistFunc);
874 if(sample.GetHistoSysList().empty()) {
876 cxcoutI(HistFactory) << sample.GetName() +
"_" + channel_name +
" has no variation histograms " << endl;
878 sampleHistFuncs.push_back(nominalHistFunc);
882 string constraintPrefix = sample.GetName() +
"_" + channel_name +
"_Hist_alpha";
885 RooArgList interpParams = makeInterpolationParameters(sample.GetHistoSysList(),
proto);
888 for(std::size_t i = 0; i < interpParams.
size(); ++i) {
889 bool isUniform = measurement.
GetUniformSyst().count(sample.GetHistoSysList()[i].GetName()) > 0;
890 makeGaussianConstraint(interpParams[i],
proto, isUniform, constraintTermNames);
894 sampleHistFuncs.push_back( makeLinInterp(interpParams, nominalHistFunc,
proto,
895 sample.GetHistoSysList(), constraintPrefix, observables) );
898 sampleHistFuncs.front()->SetTitle( (nominal && strlen(nominal->
GetTitle())>0) ? nominal->
GetTitle() : sample.GetName().c_str() );
904 if( sample.GetStatError().GetActivate() ) {
907 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
916 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" to be included in Stat Error "
917 <<
"for channel " << channel_name
920 string UncertName = sample.GetName() +
"_" + channel_name +
"_StatAbsolUncert";
921 std::unique_ptr<TH1> statErrorHist;
923 if( sample.GetStatError().GetErrorHist() ==
nullptr ) {
925 cxcoutI(HistFactory) <<
"Making Statistical Uncertainty Hist for "
926 <<
" Channel: " << channel_name
927 <<
" Sample: " << sample.GetName()
934 statErrorHist.reset(
static_cast<TH1*
>(sample.GetStatError().GetErrorHist()->Clone()));
938 cxcoutI(HistFactory) <<
"Using external histogram for Stat Errors for "
939 <<
"\tChannel: " << channel_name
940 <<
"\tSample: " << sample.GetName()
941 <<
"\tError Histogram: " << statErrorHist->GetName() << std::endl;
944 statErrorHist->Multiply( nominal );
945 statErrorHist->SetName( UncertName.c_str() );
950 statHistPairs.emplace_back(nominal, std::move(statErrorHist));
968 if( paramHist ==
nullptr ) {
974 for (
int idx=0; itr!=
fObsNameVec.end(); ++itr, ++idx ) {
975 theObservables.
add( *
proto.var(*itr) );
980 std::string ParamSetPrefix =
"gamma_stat_" + channel_name;
986 ParamHistFunc statUncertFunc(statFuncName.c_str(), statFuncName.c_str(),
987 theObservables, statFactorParams );
991 paramHist =
proto.function( statFuncName);
995 sampleHistFuncs.push_back(paramHist);
1004 if( !sample.GetShapeFactorList().empty() ) {
1007 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
1012 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" in channel: " << channel_name
1013 <<
" to be include a ShapeFactor."
1016 for(
ShapeFactor& shapeFactor : sample.GetShapeFactorList()) {
1018 std::string funcName = channel_name +
"_" + shapeFactor.GetName() +
"_shapeFactor";
1020 if( paramHist ==
nullptr ) {
1024 theObservables.
add( *
proto.var(varName) );
1028 std::string funcParams =
"gamma_" + shapeFactor.GetName();
1037 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1038 theObservables, shapeFactorParams );
1041 if( shapeFactor.GetInitialShape() !=
nullptr ) {
1042 TH1* initialShape =
static_cast<TH1*
>(shapeFactor.GetInitialShape()->Clone());
1043 cxcoutI(HistFactory) <<
"Setting Shape Factor: " << shapeFactor.
GetName()
1044 <<
" to have initial shape from hist: "
1047 shapeFactorFunc.
setShape( initialShape );
1051 if( shapeFactor.IsConstant() ) {
1052 cxcoutI(HistFactory) <<
"Setting Shape Factor: " << shapeFactor.GetName()
1053 <<
" to be constant" << std::endl;
1058 paramHist =
proto.function(funcName);
1062 sampleHistFuncs.push_back(paramHist);
1072 if( !sample.GetShapeSysList().empty() ) {
1075 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
1081 std::vector<string> ShapeSysNames;
1094 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" in channel: " << channel_name
1095 <<
" to include a ShapeSys." << std::endl;
1097 std::string funcName = channel_name +
"_" + shapeSys.GetName() +
"_ShapeSys";
1098 ShapeSysNames.push_back( funcName );
1100 if( paramHist ==
nullptr ) {
1107 theObservables.
add( *
proto.var(varName) );
1111 std::string funcParams =
"gamma_" + shapeSys.GetName();
1117 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1118 theObservables, shapeFactorParams );
1130 const TH1* shapeErrorHist = shapeSys.GetErrorHist();
1145 for (
auto const& term : shapeConstraintsInfo.constraints) {
1147 constraintTermNames.emplace_back(term->GetName());
1151 for (
RooAbsArg * glob : shapeConstraintsInfo.globalObservables) {
1152 globalSet->
add(*
proto.var(glob->GetName()));
1162 for(std::string
const&
name : ShapeSysNames) {
1163 sampleHistFuncs.push_back(
proto.function(
name));
1173 if( !sample.GetNormalizeByTheory() ) {
1175 lumi = &emplace<RooRealVar>(
proto,
"Lumi", measurement.
GetLumi());
1181 normFactors->addTerm(lumi);
1187 auto normFactorsInWS =
dynamic_cast<RooProduct*
>(
proto.arg(normFactors->GetName()));
1188 assert(normFactorsInWS);
1190 sampleScaleFactors.push_back(normFactorsInWS);
1195 if(!statHistPairs.empty()) {
1200 if( fracStatError ==
nullptr ) {
1201 cxcoutE(HistFactory) <<
"Error: Failed to make ScaledUncertaintyHist for: "
1202 << channel_name +
"_StatUncert" +
"_RelErr" << std::endl;
1208 auto chanStatUncertFunc =
static_cast<ParamHistFunc*
>(
proto.function( statFuncName ));
1209 cxcoutI(HistFactory) <<
"About to create Constraint Terms from: "
1210 << chanStatUncertFunc->
GetName()
1211 <<
" params: " << chanStatUncertFunc->paramList()
1222 cxcoutI(HistFactory) <<
"Using Gaussian StatErrors in channel: " << channel.
GetName() << std::endl;
1225 cxcoutI(HistFactory) <<
"Using Poisson StatErrors in channel: " << channel.
GetName() << std::endl;
1230 chanStatUncertFunc->paramList(),
histToVector(*fracStatError),
1231 statRelErrorThreshold,
1232 statConstraintType);
1233 for (
auto const& term : statConstraintsInfo.constraints) {
1235 constraintTermNames.emplace_back(term->GetName());
1239 for (
RooAbsArg * glob : statConstraintsInfo.globalObservables) {
1240 globalSet->
add(*
proto.var(glob->GetName()));
1249 sampleScaleFactors, allSampleHistFuncs);
1250 likelihoodTermNames.push_back(channel_name+
"_model");
1254 for(
unsigned int i=0; i<systToFix.size(); ++i){
1257 cxcoutW(HistFactory) <<
"could not find variable " << systToFix.at(i)
1258 <<
" could not set it to constant" << endl;
1267 for(
unsigned int i=0; i<constraintTermNames.size(); ++i){
1269 if( proto_arg==
nullptr ) {
1270 cxcoutF(HistFactory) <<
"Error: Cannot find arg set: " << constraintTermNames.at(i)
1274 constraintTerms.
add( *proto_arg );
1277 for(
unsigned int i=0; i<likelihoodTermNames.size(); ++i){
1279 if( proto_arg==
nullptr ) {
1280 cxcoutF(HistFactory) <<
"Error: Cannot find arg set: " << likelihoodTermNames.at(i)
1284 likelihoodTerms.
add( *proto_arg );
1286 proto.defineSet(
"constraintTerms",constraintTerms);
1287 proto.defineSet(
"likelihoodTerms",likelihoodTerms);
1291 std::string observablesStr;
1295 if (!observablesStr.empty()) { observablesStr +=
","; }
1296 observablesStr +=
name;
1302 proto.defineSet(
"observables", observablesStr.c_str());
1303 proto.defineSet(
"observablesSet", observablesStr.c_str());
1307 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1308 <<
"\timport model into workspace"
1309 <<
"\n-----------------------------------------\n" << endl;
1311 auto model = make_unique<RooProdPdf>(
1312 (
"model_"+channel_name).c_str(),
1313 "product of Poissons across bins for a single channel",
1321 proto_config->SetPdf(*model);
1322 proto_config->SetObservables(observables);
1323 proto_config->SetGlobalObservables(*
proto.set(
"globalObservables"));
1327 proto.import(*proto_config,proto_config->GetName());
1328 proto.importClassCode();
1335 int asymcalcPrintLevel = 0;
1348 proto.import(dataset);
1353 if(
data.GetName().empty()) {
1354 cxcoutF(HistFactory) <<
"Error: Additional Data histogram for channel: " << channel.
GetName()
1355 <<
" has no name! The name always needs to be set for additional datasets, "
1356 <<
"either via the \"Name\" tag in the XML or via RooStats::HistFactory::Data::SetName()." << std::endl;
1359 std::string
const& dataName =
data.GetName();
1360 TH1 const* mnominal =
data.GetHisto();
1362 cxcoutF(HistFactory) <<
"Error: Additional Data histogram for channel: " << channel.
GetName()
1363 <<
" with name: " << dataName <<
" is nullptr" << std::endl;
1370 proto.import(dataset);
1383 TH1 const& mnominal,
1385 std::vector<std::string>
const& obsNameVec) {
1391 if (obsNameVec.empty() ) {
1392 Error(
"ConfigureHistFactoryDataset",
"Invalid input - return");
1400 for (
int i=1; i<=ax->
GetNbins(); ++i) {
1403 proto.var( obsNameVec[0] )->setVal( xval );
1405 if(obsNameVec.size()==1) {
1407 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1410 for(
int j=1; j<=ay->
GetNbins(); ++j) {
1412 proto.var( obsNameVec[1] )->setVal( yval );
1414 if(obsNameVec.size()==2) {
1416 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1419 for(
int k=1; k<=az->
GetNbins(); ++k) {
1421 proto.var( obsNameVec[2] )->setVal( zval );
1423 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1440 std::vector<std::unique_ptr<RooWorkspace>> &chs)
1445 if (ch_names.empty() || chs.empty() ) {
1446 Error(
"MakeCombinedModel",
"Input vectors are empty - return a nullptr");
1449 if (chs.size() < ch_names.size() ) {
1450 Error(
"MakeCombinedModel",
"Input vector of workspace has an invalid size - return a nullptr");
1458 map<string, RooAbsPdf*> pdfMap;
1459 vector<RooAbsPdf*> models;
1462 for(
unsigned int i = 0; i< ch_names.size(); ++i){
1463 obsList.
add(*
static_cast<ModelConfig *
>(chs[i]->obj(
"ModelConfig"))->GetObservables());
1465 cxcoutI(HistFactory) <<
"full list of observables:\n" << obsList << std::endl;
1468 std::map<std::string, int> channelMap;
1469 for(
unsigned int i = 0; i< ch_names.size(); ++i){
1470 string channel_name=ch_names[i];
1471 if (i == 0 && isdigit(channel_name[0])) {
1472 throw std::invalid_argument(
"The first channel name for HistFactory cannot start with a digit. Got " + channel_name);
1474 if (channel_name.find(
',') != std::string::npos) {
1475 throw std::invalid_argument(
"Channel names for HistFactory cannot contain ','. Got " + channel_name);
1478 channelMap[channel_name] = i;
1482 if(!model) cout <<
"failed to find model for channel"<<endl;
1484 models.push_back(model);
1485 globalObs.
add(*ch->
set(
"globalObservables"),
true);
1488 pdfMap[channel_name]=model;
1491 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1492 <<
"\tEntering combination"
1493 <<
"\n-----------------------------------------\n" << endl;
1494 auto combined = std::make_unique<RooWorkspace>(
"combined");
1497 RooCategory& channelCat = emplace<RooCategory>(*combined,
"channelCat", channelMap);
1499 auto simPdf= std::make_unique<RooSimultaneous>(
"simPdf",
"",pdfMap, channelCat);
1500 auto combined_config = std::make_unique<ModelConfig>(
"ModelConfig", combined.get());
1501 combined_config->SetWorkspace(*combined);
1504 combined->import(globalObs);
1505 combined->defineSet(
"globalObservables",globalObs);
1506 combined_config->SetGlobalObservables(*combined->set(
"globalObservables"));
1508 combined->defineSet(
"observables",{obsList, channelCat},
true);
1509 combined_config->SetObservables(*combined->set(
"observables"));
1516 if(std::string(
"asimovData") ==
data->GetName()) {
1521 std::map<std::string, RooAbsData*> dataMap;
1522 for(
unsigned int i = 0; i < ch_names.size(); ++i){
1523 dataMap[ch_names[i]] = chs[i]->data(
data->GetName());
1533 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1534 <<
"\tImporting combined model"
1535 <<
"\n-----------------------------------------\n" << endl;
1540 std::string paramName = param_itr.first;
1541 double paramVal = param_itr.second;
1543 if(
RooRealVar* temp = combined->var( paramName )) {
1544 temp->setVal( paramVal );
1545 cxcoutI(HistFactory) <<
"setting " << paramName <<
" to the value: " << paramVal << endl;
1547 cxcoutE(HistFactory) <<
"could not find variable " << paramName <<
" could not set its value" << endl;
1551 for(
unsigned int i=0; i<
fSystToFix.size(); ++i){
1554 temp->setConstant();
1557 cxcoutE(HistFactory) <<
"could not find variable " <<
fSystToFix.at(i) <<
" could not set it to constant" << endl;
1565 combined_config->SetPdf(*simPdf);
1568 combined->import(*combined_config,combined_config->GetName());
1569 combined->importClassCode();
1575 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1576 <<
"\tcreate toy data"
1577 <<
"\n-----------------------------------------\n" << endl;
1585 *combined->pdf(
"simPdf"),
1587 if( asimov_combined ) {
1588 combined->import( *asimov_combined,
RooFit::Rename(
"asimovData"));
1591 std::cout <<
"Error: Failed to create combined asimov dataset" << std::endl;
1605 auto ErrorHist =
static_cast<TH1*
>(Nominal->
Clone( Name.c_str() ));
1612 for(
int i_bin = 0; i_bin < numBins; ++i_bin) {
1620 double histError = Nominal->
GetBinError( binNumber );
1623 if( histError != histError ) {
1624 std::cout <<
"Warning: In histogram " << Nominal->
GetName()
1625 <<
" bin error for bin " << i_bin
1626 <<
" is NAN. Not using Error!!!"
1634 if( histError < 0 ) {
1635 std::cout <<
"Warning: In histogram " << Nominal->
GetName()
1636 <<
" bin error for bin " << binNumber
1637 <<
" is < 0. Setting Error to 0"
1643 ErrorHist->SetBinContent( binNumber, histError );
1662 unsigned int numHists = HistVec.size();
1664 if( numHists == 0 ) {
1665 cxcoutE(HistFactory) <<
"Warning: Empty Hist Vector, cannot create total uncertainty" << std::endl;
1669 const TH1* HistTemplate = HistVec.at(0).first;
1674 for(
unsigned int i = 0; i < HistVec.size(); ++i ) {
1676 const TH1* nominal = HistVec.at(i).first;
1677 const TH1* error = HistVec.at(i).second.get();
1680 cxcoutE(HistFactory) <<
"Error: Provided hists have unequal bins" << std::endl;
1684 cxcoutE(HistFactory) <<
"Error: Provided hists have unequal bins" << std::endl;
1689 std::vector<double> TotalBinContent( numBins, 0.0);
1690 std::vector<double> HistErrorsSqr( numBins, 0.0);
1695 for(
int i_bins = 0; i_bins < numBins; ++i_bins) {
1702 for(
unsigned int i_hist = 0; i_hist < numHists; ++i_hist ) {
1704 const TH1* nominal = HistVec.at(i_hist).first;
1705 const TH1* error = HistVec.at(i_hist).second.get();
1712 if( histError != histError ) {
1714 <<
" bin error for bin " << binNumber
1715 <<
" is NAN. Not using error!!";
1719 TotalBinContent.at(i_bins) += histValue;
1720 HistErrorsSqr.at(i_bins) += histError*histError;
1728 TH1* ErrorHist =
static_cast<TH1*
>(HistTemplate->
Clone( Name.c_str() ));
1732 for(
int i = 0; i < numBins; ++i) {
1740 double ErrorsSqr = HistErrorsSqr.at(i);
1741 double TotalVal = TotalBinContent.at(i);
1743 if( TotalVal <= 0 ) {
1744 cxcoutW(HistFactory) <<
"Warning: Sum of histograms for bin: " << binNumber
1745 <<
" is <= 0. Setting error to 0"
1752 double RelativeError = sqrt(ErrorsSqr) / TotalVal;
1756 if( RelativeError != RelativeError ) {
1757 cxcoutE(HistFactory) <<
"Error: bin " << i <<
" error is NAN\n"
1758 <<
" HistErrorsSqr: " << ErrorsSqr
1759 <<
" TotalVal: " << TotalVal;
1772 cxcoutI(HistFactory) <<
"Making Total Uncertainty for bin " << binNumber
1773 <<
" Error = " << sqrt(ErrorsSqr)
1774 <<
" CentralVal = " << TotalVal
1775 <<
" RelativeError = " << RelativeError <<
"\n";
1779 return std::unique_ptr<TH1>(ErrorHist);
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 R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
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
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
void setConstant(bool constant)
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.
void setShape(TH1 *shape)
The PiecewiseInterpolation is a class that can morph distributions into each other,...
Common abstract base class for objects that represent a value and a "shape" in RooFit.
void Print(Option_t *options=nullptr) const override
Print the object to the defaultPrintStream().
void setAttribute(const Text_t *name, bool value=true)
Set (default) or clear a named boolean attribute of this object.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Storage_t::size_type size() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
const_iterator begin() const
Abstract base class for binned and unbinned datasets.
Abstract interface for all probability density functions.
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...
RooNumIntConfig * specialIntegratorConfig() const
Returns the specialized integrator configuration for this RooAbsReal.
virtual void forceNumInt(bool flag=true)
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
RooArgList is a container object that can hold multiple RooAbsArg objects.
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Implements a RooAbsBinning in terms of an array of boundary values, posing no constraints on the choi...
Object to represent discrete states.
bool setLabel(const char *label, bool printError=true) override
Set value by specifying the name of the desired state.
Container class to hold N-dimensional binned data.
Container class to hold unbinned data.
void add(const RooArgSet &row, double weight, double weightError)
Add one ore more rows of data.
RooFitResult is a container class to hold the input and output of a PDF fit to a dataset.
Implementation of the Gamma PDF for RooFit/RooStats.
Switches the message service to a different level while the instance is alive.
A real-valued function sampled from a multidimensional histogram.
static RooMsgService & instance()
Return reference to singleton instance.
bool isActive(T self, RooFit::MsgTopic topic, RooFit::MsgLevel level)
Check if logging is active for given object/topic/RooFit::MsgLevel combination.
A RooAbsReal implementing a polynomial in terms of a list of RooAbsReal coefficients.
Represents the product of a given set of RooAbsReal objects.
Implements a PDF constructed from a sum of functions:
Variable that can be changed from the outside.
void setError(double value)
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.
void ConfigureWorkspace(RooWorkspace *)
This class encapsulates all information for the statistical interpretation of one experiment.
std::vector< RooStats::HistFactory::Data > & GetAdditionalData()
retrieve vector of additional data objects
void Print(std::ostream &=std::cout)
HistFactory::StatErrorConfig & GetStatErrorConfig()
get information about threshold for statistical uncertainties and constraint term
RooStats::HistFactory::Data & GetData()
get data object
bool CheckHistograms() const
std::vector< RooStats::HistFactory::Sample > & GetSamples()
get vector of samples for this channel
std::string GetName() const
get name of channel
void setAllInterpCodes(int code)
Configuration for a constrained, coherent shape variation of affected samples.
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)
void GuessObsNameVec(const TH1 *hist)
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
std::vector< std::string > fPreprocessFunctions
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)
std::vector< std::string > fObsNameVec
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)
std::map< std::string, double > fParamValues
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)
std::vector< std::string > fSystToFix
HistoToWorkspaceFactoryFast()
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...
const TH1 * GetHistoHigh() const
const TH1 * GetHistoLow() const
The RooStats::HistFactory::Measurement class can be used to construct a model by combining multiple R...
std::map< std::string, double > & GetGammaSyst()
std::map< std::string, double > & GetLogNormSyst()
std::map< std::string, double > & GetNoSyst()
std::vector< std::string > & GetPOIList()
get vector of PoI names
std::map< std::string, double > & GetUniformSyst()
std::vector< std::string > & GetConstantParams()
get vector of all constant parameters
std::vector< RooStats::HistFactory::Channel > & GetChannels()
std::vector< RooStats::HistFactory::Asimov > & GetAsimovDatasets()
get vector of defined Asimov Datasets
std::vector< std::string > GetPreprocessFunctions() const
Returns a list of defined preprocess function expressions.
double GetLumi()
retrieve integrated luminosity
Configuration for an un- constrained overall systematic to scale sample normalisations.
Configuration for a constrained overall systematic to scale sample normalisations.
const std::string & GetName() const
std::string GetName() const
get name of sample
std::vector< RooStats::HistFactory::NormFactor > & GetNormFactorList()
*Un*constrained bin-by-bin variation of affected histogram.
Constrained bin-by-bin variation of affected histogram.
double GetRelErrorThreshold() const
Constraint::Type GetConstraintType() const
ModelConfig is a simple class that holds configuration information specifying how a model should be u...
void GuessObsAndNuisance(const RooAbsData &data, bool printModelConfig=true)
Makes sensible guesses of observables, parameters of interest and nuisance parameters if one or multi...
virtual void SetParametersOfInterest(const RooArgSet &set)
Specify parameters of interest.
Persistable container for RooFit projects.
TObject * obj(RooStringView name) const
Return any type of object (RooAbsArg, RooAbsData or generic object) with given name)
RooAbsPdf * pdf(RooStringView name) const
Retrieve p.d.f (RooAbsPdf) with given name. A null pointer is returned if not found.
RooArgSet allVars() const
Return set with all variable objects.
const RooArgSet * set(RooStringView name)
Return pointer to previously defined named set with given nmame If no such set is found a null pointe...
bool saveSnapshot(RooStringView, const char *paramNames)
Save snapshot of values and attributes (including "Constant") of given parameters.
RooAbsArg * arg(RooStringView name) const
Return RooAbsArg with given name. A null pointer is returned if none is found.
RooRealVar * var(RooStringView name) const
Retrieve real-valued variable (RooRealVar) with given name. A null pointer is returned if not found.
RooAbsData * data(RooStringView name) const
Retrieve dataset (binned or unbinned) with given name. A null pointer is returned if not found.
bool loadSnapshot(const char *name)
Load the values and attributes of the parameters in the snapshot saved with the given name.
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.
const Double_t * GetArray() const
Class to manage histogram axis.
Bool_t IsVariableBinSize() const
const char * GetTitle() const override
Returns title of object.
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
const TArrayD * GetXbins() const
TH1 is the base class of all histogram classes in ROOT.
virtual Int_t GetNbinsY() const
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
virtual Int_t GetNbinsZ() const
virtual Int_t GetDimension() const
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
virtual Int_t GetNbinsX() const
virtual void SetBinError(Int_t bin, Double_t error)
Set the bin Error Note that this resets the bin eror option to be of Normal Type and for the non-empt...
Bool_t IsBinUnderflow(Int_t bin, Int_t axis=0) const
Return true if the bin is underflow.
Bool_t IsBinOverflow(Int_t bin, Int_t axis=0) const
Return true if the bin is overflow.
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
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 WeightVar(const char *name="weight", bool reinterpretAsWeight=false)
RooCmdArg Import(const char *state, TH1 &histo)
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
constexpr double defaultShapeSysGammaMax
constexpr double minShapeUncertainty
constexpr double defaultShapeFactorGammaMax
constexpr double defaultStatErrorGammaMax
constexpr double defaultGammaMin
CreateGammaConstraintsOutput createGammaConstraints(RooArgList const ¶mList, std::span< const double > relSigmas, double minSigma, Constraint::Type type)
Namespace for the RooStats classes.
bool binnedFitOptimization