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 <<
" ";
147 cxcoutIHF << sstream.str() << endl;
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());
474 prodNames.push_back(varname);
475 rangeNames.push_back(range.str());
476 normFactorNames.push_back(varname);
480 for (
const auto&
name : prodNames) {
483 normFactor->addTerm(arg);
488 unsigned int rangeIndex=0;
489 for( vector<string>::iterator nit = normFactorNames.begin(); nit!=normFactorNames.end(); ++nit){
490 if( count (normFactorNames.begin(), normFactorNames.end(), *nit) > 1 ){
491 cxcoutI(HistFactory) <<
"<NormFactor Name =\""<<*nit<<
"\"> is duplicated for <Sample Name=\""
492 << sample.
GetName() <<
"\">, but only one factor will be included. \n Instead, define something like"
493 <<
"\n\t<Function Name=\""<<*nit<<
"Squared\" Expression=\""<<*nit<<
"*"<<*nit<<
"\" Var=\""<<*nit<<rangeNames.at(rangeIndex)
494 <<
"\"> \nin your top-level XML's <Measurement> entry and use <NormFactor Name=\""<<*nit<<
"Squared\" in your channel XML file."<< endl;
504 std::vector<OverallSys>& systList,
505 vector<string>& constraintTermNames,
506 vector<string>& totSystTermNames) {
509 totSystTermNames.push_back(prefix);
512 vector<double> lowVec;
513 vector<double> highVec;
515 std::map<std::string, double>::iterator itconstr;
516 for(
unsigned int i = 0; i < systList.size(); ++i) {
519 std::string strname = sys.
GetName();
520 const char *
name = strname.c_str();
524 cxcoutI(HistFactory) <<
"HistoToWorkspaceFast::AddConstraintTerm - skip systematic " << sys.
GetName() << std::endl;
531 cxcoutI(HistFactory) <<
"HistoToWorkspaceFast::AddConstraintTerm - zero uncertainty assigned - skip systematic " << sys.
GetName() << std::endl;
534 const double tauVal = 1./(relerr*relerr);
535 const double sqtau = 1./relerr;
536 RooRealVar &beta = emplace<RooRealVar>(
proto,
"beta_" + strname, 1., 0., 10.);
538 RooRealVar &yvar = emplace<RooRealVar>(
proto,
"nom_" + std::string{beta.GetName()}, tauVal, 0., 10.);
540 RooRealVar &theta = emplace<RooRealVar>(
proto,
"theta_" + strname, 1./tauVal);
549 alphaOfBeta.
Print(
"t");
552 constraintTermNames.push_back(gamma.GetName());
555 const_cast<RooArgSet*
>(
proto.set(
"globalObservables"))->add(yvar);
558 params.
add(alphaOfBeta);
559 cxcoutI(HistFactory) <<
"Added a gamma constraint for " <<
name << std::endl;
566 makeGaussianConstraint(alpha,
proto, isUniform, constraintTermNames);
579 proto,
"alphaOfBeta_" + sys.
GetName(),
"x[0]*(pow(x[1],x[2])-1.)",
580 RooArgList{emplace<RooRealVar>(proto,
"tau_" + sys.GetName(), 1. / relerr),
581 emplace<RooRealVar>(proto,
"kappa_" + sys.GetName(), 1. + relerr), alpha});
583 cxcoutI(HistFactory) <<
"Added a log-normal constraint for " <<
name << std::endl;
585 alphaOfBeta.
Print(
"t");
587 params.
add(alphaOfBeta);
592 lowVec.push_back(sys.
GetLow());
593 highVec.push_back(sys.
GetHigh());
597 if(!systList.empty()){
601 assert(!params.
empty());
602 assert(lowVec.size() == params.
size());
604 FlexibleInterpVar interp( (interpName).c_str(),
"", params, 1., lowVec, highVec);
607 proto.import(interp);
611 emplace<RooConstVar>(
proto, interpName, 1.);
617 const vector<RooProduct*>& sampleScaleFactors, std::vector<vector<RooAbsArg*>>& sampleHistFuncs)
const {
618 assert(sampleScaleFactors.size() == sampleHistFuncs.size());
623 throw std::logic_error(
"HistFactory didn't process the observables correctly. Please file a bug report.");
625 auto firstHistFunc =
dynamic_cast<const RooHistFunc*
>(sampleHistFuncs.front().front());
626 if (!firstHistFunc) {
628 firstHistFunc =
dynamic_cast<const RooHistFunc*
>(piecewiseInt->nominalHist());
630 assert(firstHistFunc);
633 auto &binWidth = emplace<RooBinWidthFunction>(
proto, totName +
"_binWidth", *firstHistFunc,
true);
638 for (
unsigned int i=0; i < sampleHistFuncs.size(); ++i) {
639 assert(!sampleHistFuncs[i].empty());
640 coefList.
add(*sampleScaleFactors[i]);
642 std::vector<RooAbsArg*>& thisSampleHistFuncs = sampleHistFuncs[i];
643 thisSampleHistFuncs.push_back(&binWidth);
645 if (thisSampleHistFuncs.size() == 1) {
647 shapeList.
add(*thisSampleHistFuncs.front());
650 std::string
name = thisSampleHistFuncs.front()->GetName();
651 auto pos =
name.find(
"Hist_alpha");
652 if (pos != std::string::npos) {
653 name =
name.substr(0, pos) +
"shapes";
654 }
else if ( (pos =
name.find(
"nominal")) != std::string::npos) {
655 name =
name.substr(0, pos) +
"shapes";
658 RooProduct shapeProduct(
name.c_str(), thisSampleHistFuncs.front()->GetTitle(),
RooArgSet(thisSampleHistFuncs.begin(), thisSampleHistFuncs.end()));
665 RooRealSumPdf tot(totName.c_str(), totName.c_str(), shapeList, coefList,
true);
686 FILE* covFile = fopen ((
filename).c_str(),
"w");
687 fprintf(covFile,
" ") ;
688 for (
auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
689 if(myargi->isConstant())
continue;
690 fprintf(covFile,
" & %s", myargi->GetName());
692 fprintf(covFile,
"\\\\ \\hline \n" );
693 for (
auto const *myargi : static_range_cast<RooRealVar *>(*params)) {
694 if(myargi->isConstant())
continue;
695 fprintf(covFile,
"%s", myargi->GetName());
696 for (
auto const *myargj : static_range_cast<RooRealVar *>(*params)) {
697 if(myargj->isConstant())
continue;
698 cout << myargi->GetName() <<
"," << myargj->GetName();
699 fprintf(covFile,
" & %.2f",
result->correlation(*myargi, *myargj));
702 fprintf(covFile,
" \\\\\n");
715 Error(
"MakeSingleChannelWorkspace",
716 "The input Channel does not contain any sample - return a nullptr");
720 const TH1* channel_hist_template = channel.
GetSamples().front().GetHisto();
721 if (channel_hist_template ==
nullptr) {
723 channel_hist_template = channel.
GetSamples().front().GetHisto();
725 if (channel_hist_template ==
nullptr) {
726 std::ostringstream stream;
727 stream <<
"The sample " << channel.
GetSamples().front().GetName()
728 <<
" in channel " << channel.
GetName() <<
" does not contain a histogram. This is the channel:\n";
729 channel.
Print(stream);
730 Error(
"MakeSingleChannelWorkspace",
"%s", stream.str().c_str());
735 std::cout <<
"MakeSingleChannelWorkspace: Channel: " << channel.
GetName()
736 <<
" has uninitialized histogram pointers" << std::endl;
750 string channel_name = channel.
GetName();
760 for (
unsigned int idx=0; idx<
fObsNameVec.size(); ++idx ) {
770 throw hf_exc(
"HistFactory is limited to 1- to 3-dimensional histograms.");
773 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
774 <<
"\tStarting to process '"
775 << channel_name <<
"' channel with " <<
fObsNameVec.size() <<
" observables"
776 <<
"\n-----------------------------------------\n" << endl;
781 auto protoOwner = std::make_unique<RooWorkspace>(channel_name.c_str(), (channel_name+
" workspace").c_str());
783 auto proto_config = make_unique<ModelConfig>(
"ModelConfig", &
proto);
784 proto_config->SetWorkspace(
proto);
788 cxcoutI(HistFactory) <<
"will preprocess this line: " << func <<endl;
793 RooArgSet likelihoodTerms(
"likelihoodTerms");
794 RooArgSet constraintTerms(
"constraintTerms");
795 vector<string> likelihoodTermNames;
796 vector<string> constraintTermNames;
797 vector<string> totSystTermNames;
799 std::vector<std::vector<RooAbsArg*>> allSampleHistFuncs;
800 std::vector<RooProduct*> sampleScaleFactors;
802 std::vector< pair<string,string> > statNamePairs;
803 std::vector< pair<const TH1*, std::unique_ptr<TH1>> > statHistPairs;
804 const std::string statFuncName =
"mc_stat_" + channel_name;
817 emplace<RooGaussian>(
proto,
"lumiConstraint", lumiVar, nominalLumiVar,
fLumiError);
819 proto.var(
"nominalLumi")->setConstant();
820 proto.defineSet(
"globalObservables",
"nominalLumi");
822 constraintTermNames.push_back(
"lumiConstraint");
824 proto.var(
"Lumi")->setConstant();
832 string overallSystName = sample.GetName() +
"_" + channel_name +
"_epsilon";
834 string systSourcePrefix =
"alpha_";
839 sample.GetOverallSysList(), constraintTermNames , totSystTermNames);
841 allSampleHistFuncs.emplace_back();
842 std::vector<RooAbsArg*>& sampleHistFuncs = allSampleHistFuncs.back();
855 const TH1* nominal = sample.GetHisto();
867 string expPrefix = sample.
GetName() +
"_" + channel_name;
871 assert(nominalHistFunc);
873 if(sample.GetHistoSysList().empty()) {
875 cxcoutI(HistFactory) << sample.GetName() +
"_" + channel_name +
" has no variation histograms " << endl;
877 sampleHistFuncs.push_back(nominalHistFunc);
881 string constraintPrefix = sample.GetName() +
"_" + channel_name +
"_Hist_alpha";
884 RooArgList interpParams = makeInterpolationParameters(sample.GetHistoSysList(),
proto);
887 for(std::size_t i = 0; i < interpParams.
size(); ++i) {
888 bool isUniform = measurement.
GetUniformSyst().count(sample.GetHistoSysList()[i].GetName()) > 0;
889 makeGaussianConstraint(interpParams[i],
proto, isUniform, constraintTermNames);
893 sampleHistFuncs.push_back( makeLinInterp(interpParams, nominalHistFunc,
proto,
894 sample.GetHistoSysList(), constraintPrefix, observables) );
897 sampleHistFuncs.front()->SetTitle( (nominal && strlen(nominal->
GetTitle())>0) ? nominal->
GetTitle() : sample.GetName().c_str() );
903 if( sample.GetStatError().GetActivate() ) {
906 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
915 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" to be included in Stat Error "
916 <<
"for channel " << channel_name
919 string UncertName = sample.GetName() +
"_" + channel_name +
"_StatAbsolUncert";
920 std::unique_ptr<TH1> statErrorHist;
922 if( sample.GetStatError().GetErrorHist() ==
nullptr ) {
924 cxcoutI(HistFactory) <<
"Making Statistical Uncertainty Hist for "
925 <<
" Channel: " << channel_name
926 <<
" Sample: " << sample.GetName()
933 statErrorHist.reset(
static_cast<TH1*
>(sample.GetStatError().GetErrorHist()->Clone()));
937 cxcoutI(HistFactory) <<
"Using external histogram for Stat Errors for "
938 <<
"\tChannel: " << channel_name
939 <<
"\tSample: " << sample.GetName()
940 <<
"\tError Histogram: " << statErrorHist->GetName() << std::endl;
943 statErrorHist->Multiply( nominal );
944 statErrorHist->SetName( UncertName.c_str() );
949 statHistPairs.emplace_back(nominal, std::move(statErrorHist));
967 if( paramHist ==
nullptr ) {
973 for (
int idx=0; itr!=
fObsNameVec.end(); ++itr, ++idx ) {
974 theObservables.
add( *
proto.var(*itr) );
979 std::string ParamSetPrefix =
"gamma_stat_" + channel_name;
985 ParamHistFunc statUncertFunc(statFuncName.c_str(), statFuncName.c_str(),
986 theObservables, statFactorParams );
990 paramHist =
proto.function( statFuncName);
994 sampleHistFuncs.push_back(paramHist);
1003 if( !sample.GetShapeFactorList().empty() ) {
1006 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
1011 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" in channel: " << channel_name
1012 <<
" to be include a ShapeFactor."
1015 for(
ShapeFactor& shapeFactor : sample.GetShapeFactorList()) {
1017 std::string funcName = channel_name +
"_" + shapeFactor.GetName() +
"_shapeFactor";
1019 if( paramHist ==
nullptr ) {
1023 theObservables.
add( *
proto.var(varName) );
1027 std::string funcParams =
"gamma_" + shapeFactor.GetName();
1036 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1037 theObservables, shapeFactorParams );
1040 if( shapeFactor.GetInitialShape() !=
nullptr ) {
1041 TH1* initialShape =
static_cast<TH1*
>(shapeFactor.GetInitialShape()->Clone());
1042 cxcoutI(HistFactory) <<
"Setting Shape Factor: " << shapeFactor.
GetName()
1043 <<
" to have initial shape from hist: "
1046 shapeFactorFunc.
setShape( initialShape );
1050 if( shapeFactor.IsConstant() ) {
1051 cxcoutI(HistFactory) <<
"Setting Shape Factor: " << shapeFactor.GetName()
1052 <<
" to be constant" << std::endl;
1057 paramHist =
proto.function(funcName);
1061 sampleHistFuncs.push_back(paramHist);
1071 if( !sample.GetShapeSysList().empty() ) {
1074 cxcoutF(HistFactory) <<
"Cannot include Stat Error for histograms of more than 3 dimensions."
1080 std::vector<string> ShapeSysNames;
1093 cxcoutI(HistFactory) <<
"Sample: " << sample.GetName() <<
" in channel: " << channel_name
1094 <<
" to include a ShapeSys." << std::endl;
1096 std::string funcName = channel_name +
"_" + shapeSys.GetName() +
"_ShapeSys";
1097 ShapeSysNames.push_back( funcName );
1099 if( paramHist ==
nullptr ) {
1106 theObservables.
add( *
proto.var(varName) );
1110 std::string funcParams =
"gamma_" + shapeSys.GetName();
1116 ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
1117 theObservables, shapeFactorParams );
1129 const TH1* shapeErrorHist = shapeSys.GetErrorHist();
1144 for (
auto const& term : shapeConstraintsInfo.constraints) {
1146 constraintTermNames.emplace_back(term->GetName());
1150 for (
RooAbsArg * glob : shapeConstraintsInfo.globalObservables) {
1151 globalSet->
add(*
proto.var(glob->GetName()));
1161 for(std::string
const&
name : ShapeSysNames) {
1162 sampleHistFuncs.push_back(
proto.function(
name));
1172 if( !sample.GetNormalizeByTheory() ) {
1174 lumi = &emplace<RooRealVar>(
proto,
"Lumi", measurement.
GetLumi());
1180 normFactors->addTerm(lumi);
1186 auto normFactorsInWS =
dynamic_cast<RooProduct*
>(
proto.arg(normFactors->GetName()));
1187 assert(normFactorsInWS);
1189 sampleScaleFactors.push_back(normFactorsInWS);
1194 if(!statHistPairs.empty()) {
1199 if( fracStatError ==
nullptr ) {
1200 cxcoutE(HistFactory) <<
"Error: Failed to make ScaledUncertaintyHist for: "
1201 << channel_name +
"_StatUncert" +
"_RelErr" << std::endl;
1207 auto chanStatUncertFunc =
static_cast<ParamHistFunc*
>(
proto.function( statFuncName ));
1208 cxcoutI(HistFactory) <<
"About to create Constraint Terms from: "
1209 << chanStatUncertFunc->
GetName()
1210 <<
" params: " << chanStatUncertFunc->paramList()
1221 cxcoutI(HistFactory) <<
"Using Gaussian StatErrors in channel: " << channel.
GetName() << std::endl;
1224 cxcoutI(HistFactory) <<
"Using Poisson StatErrors in channel: " << channel.
GetName() << std::endl;
1229 chanStatUncertFunc->paramList(),
histToVector(*fracStatError),
1230 statRelErrorThreshold,
1231 statConstraintType);
1232 for (
auto const& term : statConstraintsInfo.constraints) {
1234 constraintTermNames.emplace_back(term->GetName());
1238 for (
RooAbsArg * glob : statConstraintsInfo.globalObservables) {
1239 globalSet->
add(*
proto.var(glob->GetName()));
1248 sampleScaleFactors, allSampleHistFuncs);
1249 likelihoodTermNames.push_back(channel_name+
"_model");
1253 for(
unsigned int i=0; i<systToFix.size(); ++i){
1256 cxcoutW(HistFactory) <<
"could not find variable " << systToFix.at(i)
1257 <<
" could not set it to constant" << endl;
1266 for(
unsigned int i=0; i<constraintTermNames.size(); ++i){
1268 if( proto_arg==
nullptr ) {
1269 cxcoutF(HistFactory) <<
"Error: Cannot find arg set: " << constraintTermNames.at(i)
1273 constraintTerms.
add( *proto_arg );
1276 for(
unsigned int i=0; i<likelihoodTermNames.size(); ++i){
1278 if( proto_arg==
nullptr ) {
1279 cxcoutF(HistFactory) <<
"Error: Cannot find arg set: " << likelihoodTermNames.at(i)
1283 likelihoodTerms.
add( *proto_arg );
1285 proto.defineSet(
"constraintTerms",constraintTerms);
1286 proto.defineSet(
"likelihoodTerms",likelihoodTerms);
1290 std::string observablesStr;
1294 if (!observablesStr.empty()) { observablesStr +=
","; }
1295 observablesStr +=
name;
1301 proto.defineSet(
"observables", observablesStr.c_str());
1302 proto.defineSet(
"observablesSet", observablesStr.c_str());
1306 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1307 <<
"\timport model into workspace"
1308 <<
"\n-----------------------------------------\n" << endl;
1310 auto model = make_unique<RooProdPdf>(
1311 (
"model_"+channel_name).c_str(),
1312 "product of Poissons across bins for a single channel",
1320 proto_config->SetPdf(*model);
1321 proto_config->SetObservables(observables);
1322 proto_config->SetGlobalObservables(*
proto.set(
"globalObservables"));
1326 proto.import(*proto_config,proto_config->GetName());
1327 proto.importClassCode();
1334 int asymcalcPrintLevel = 0;
1347 proto.import(dataset);
1352 if(
data.GetName().empty()) {
1353 cxcoutF(HistFactory) <<
"Error: Additional Data histogram for channel: " << channel.
GetName()
1354 <<
" has no name! The name always needs to be set for additional datasets, "
1355 <<
"either via the \"Name\" tag in the XML or via RooStats::HistFactory::Data::SetName()." << std::endl;
1358 std::string
const& dataName =
data.GetName();
1359 TH1 const* mnominal =
data.GetHisto();
1361 cxcoutF(HistFactory) <<
"Error: Additional Data histogram for channel: " << channel.
GetName()
1362 <<
" with name: " << dataName <<
" is nullptr" << std::endl;
1369 proto.import(dataset);
1382 TH1 const& mnominal,
1384 std::vector<std::string>
const& obsNameVec) {
1390 if (obsNameVec.empty() ) {
1391 Error(
"ConfigureHistFactoryDataset",
"Invalid input - return");
1399 for (
int i=1; i<=ax->
GetNbins(); ++i) {
1402 proto.var( obsNameVec[0] )->setVal( xval );
1404 if(obsNameVec.size()==1) {
1406 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1409 for(
int j=1; j<=ay->
GetNbins(); ++j) {
1411 proto.var( obsNameVec[1] )->setVal( yval );
1413 if(obsNameVec.size()==2) {
1415 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1418 for(
int k=1; k<=az->
GetNbins(); ++k) {
1420 proto.var( obsNameVec[2] )->setVal( zval );
1422 obsDataUnbinned.
add( *
proto.set(
"observables"), fval );
1439 std::vector<std::unique_ptr<RooWorkspace>> &chs)
1444 if (ch_names.empty() || chs.empty() ) {
1445 Error(
"MakeCombinedModel",
"Input vectors are empty - return a nullptr");
1448 if (chs.size() < ch_names.size() ) {
1449 Error(
"MakeCombinedModel",
"Input vector of workspace has an invalid size - return a nullptr");
1457 map<string, RooAbsPdf*> pdfMap;
1458 vector<RooAbsPdf*> models;
1461 for(
unsigned int i = 0; i< ch_names.size(); ++i){
1462 obsList.
add(*
static_cast<ModelConfig *
>(chs[i]->obj(
"ModelConfig"))->GetObservables());
1464 cxcoutI(HistFactory) <<
"full list of observables:\n" << obsList << std::endl;
1467 std::map<std::string, int> channelMap;
1468 for(
unsigned int i = 0; i< ch_names.size(); ++i){
1469 string channel_name=ch_names[i];
1470 if (i == 0 && isdigit(channel_name[0])) {
1471 throw std::invalid_argument(
"The first channel name for HistFactory cannot start with a digit. Got " + channel_name);
1473 if (channel_name.find(
',') != std::string::npos) {
1474 throw std::invalid_argument(
"Channel names for HistFactory cannot contain ','. Got " + channel_name);
1477 channelMap[channel_name] = i;
1481 if(!model) cout <<
"failed to find model for channel"<<endl;
1483 models.push_back(model);
1484 globalObs.
add(*ch->
set(
"globalObservables"),
true);
1487 pdfMap[channel_name]=model;
1490 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1491 <<
"\tEntering combination"
1492 <<
"\n-----------------------------------------\n" << endl;
1493 auto combined = std::make_unique<RooWorkspace>(
"combined");
1496 RooCategory& channelCat = emplace<RooCategory>(*combined,
"channelCat", channelMap);
1498 auto simPdf= std::make_unique<RooSimultaneous>(
"simPdf",
"",pdfMap, channelCat);
1499 auto combined_config = std::make_unique<ModelConfig>(
"ModelConfig", combined.get());
1500 combined_config->SetWorkspace(*combined);
1503 combined->import(globalObs);
1504 combined->defineSet(
"globalObservables",globalObs);
1505 combined_config->SetGlobalObservables(*combined->set(
"globalObservables"));
1507 combined->defineSet(
"observables",{obsList, channelCat},
true);
1508 combined_config->SetObservables(*combined->set(
"observables"));
1515 if(std::string(
"asimovData") ==
data->GetName()) {
1520 std::map<std::string, RooAbsData*> dataMap;
1521 for(
unsigned int i = 0; i < ch_names.size(); ++i){
1522 dataMap[ch_names[i]] = chs[i]->data(
data->GetName());
1532 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1533 <<
"\tImporting combined model"
1534 <<
"\n-----------------------------------------\n" << endl;
1539 std::string paramName = param_itr.first;
1540 double paramVal = param_itr.second;
1542 if(
RooRealVar* temp = combined->var( paramName )) {
1543 temp->setVal( paramVal );
1544 cxcoutI(HistFactory) <<
"setting " << paramName <<
" to the value: " << paramVal << endl;
1546 cxcoutE(HistFactory) <<
"could not find variable " << paramName <<
" could not set its value" << endl;
1550 for(
unsigned int i=0; i<
fSystToFix.size(); ++i){
1553 temp->setConstant();
1556 cxcoutE(HistFactory) <<
"could not find variable " <<
fSystToFix.at(i) <<
" could not set it to constant" << endl;
1564 combined_config->SetPdf(*simPdf);
1567 combined->import(*combined_config,combined_config->GetName());
1568 combined->importClassCode();
1574 cxcoutP(HistFactory) <<
"\n-----------------------------------------\n"
1575 <<
"\tcreate toy data"
1576 <<
"\n-----------------------------------------\n" << endl;
1584 *combined->pdf(
"simPdf"),
1586 if( asimov_combined ) {
1587 combined->import( *asimov_combined,
RooFit::Rename(
"asimovData"));
1590 std::cout <<
"Error: Failed to create combined asimov dataset" << std::endl;
1604 auto ErrorHist =
static_cast<TH1*
>(Nominal->
Clone( Name.c_str() ));
1611 for(
int i_bin = 0; i_bin < numBins; ++i_bin) {
1619 double histError = Nominal->
GetBinError( binNumber );
1622 if( histError != histError ) {
1623 std::cout <<
"Warning: In histogram " << Nominal->
GetName()
1624 <<
" bin error for bin " << i_bin
1625 <<
" is NAN. Not using Error!!!"
1633 if( histError < 0 ) {
1634 std::cout <<
"Warning: In histogram " << Nominal->
GetName()
1635 <<
" bin error for bin " << binNumber
1636 <<
" is < 0. Setting Error to 0"
1642 ErrorHist->SetBinContent( binNumber, histError );
1661 unsigned int numHists = HistVec.size();
1663 if( numHists == 0 ) {
1664 cxcoutE(HistFactory) <<
"Warning: Empty Hist Vector, cannot create total uncertainty" << std::endl;
1668 const TH1* HistTemplate = HistVec.at(0).first;
1673 for(
unsigned int i = 0; i < HistVec.size(); ++i ) {
1675 const TH1* nominal = HistVec.at(i).first;
1676 const TH1* error = HistVec.at(i).second.get();
1679 cxcoutE(HistFactory) <<
"Error: Provided hists have unequal bins" << std::endl;
1683 cxcoutE(HistFactory) <<
"Error: Provided hists have unequal bins" << std::endl;
1688 std::vector<double> TotalBinContent( numBins, 0.0);
1689 std::vector<double> HistErrorsSqr( numBins, 0.0);
1694 for(
int i_bins = 0; i_bins < numBins; ++i_bins) {
1701 for(
unsigned int i_hist = 0; i_hist < numHists; ++i_hist ) {
1703 const TH1* nominal = HistVec.at(i_hist).first;
1704 const TH1* error = HistVec.at(i_hist).second.get();
1711 if( histError != histError ) {
1713 <<
" bin error for bin " << binNumber
1714 <<
" is NAN. Not using error!!";
1718 TotalBinContent.at(i_bins) += histValue;
1719 HistErrorsSqr.at(i_bins) += histError*histError;
1727 TH1* ErrorHist =
static_cast<TH1*
>(HistTemplate->
Clone( Name.c_str() ));
1731 for(
int i = 0; i < numBins; ++i) {
1739 double ErrorsSqr = HistErrorsSqr.at(i);
1740 double TotalVal = TotalBinContent.at(i);
1742 if( TotalVal <= 0 ) {
1743 cxcoutW(HistFactory) <<
"Warning: Sum of histograms for bin: " << binNumber
1744 <<
" is <= 0. Setting error to 0"
1751 double RelativeError = sqrt(ErrorsSqr) / TotalVal;
1755 if( RelativeError != RelativeError ) {
1756 cxcoutE(HistFactory) <<
"Error: bin " << i <<
" error is NAN\n"
1757 <<
" HistErrorsSqr: " << ErrorsSqr
1758 <<
" TotalVal: " << TotalVal;
1771 cxcoutI(HistFactory) <<
"Making Total Uncertainty for bin " << binNumber
1772 <<
" Error = " << sqrt(ErrorsSqr)
1773 <<
" CentralVal = " << TotalVal
1774 <<
" RelativeError = " << RelativeError <<
"\n";
1778 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
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 data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
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.
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.
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.
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.
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