// @(#)root/roostats:$Id: cranmer $ // Author: Kyle Cranmer, Akira Shibata /************************************************************************* * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //_________________________________________________ /* BEGIN_HTML

END_HTML */ // #ifndef __CINT__ #include "RooGlobalFunc.h" #endif // Roofit/Roostat include #include "RooDataSet.h" #include "RooRealVar.h" #include "RooConstVar.h" #include "RooAddition.h" #include "RooProduct.h" #include "RooProdPdf.h" #include "RooAddPdf.h" #include "RooGaussian.h" #include "RooExponential.h" #include "RooRandom.h" #include "RooCategory.h" #include "RooSimultaneous.h" #include "RooMultiVarGaussian.h" #include "RooNumIntConfig.h" #include "RooMinuit.h" #include "RooNLLVar.h" #include "RooProfileLL.h" #include "RooFitResult.h" #include "RooDataHist.h" #include "RooHistPdf.h" #include "RooProduct.h" #include "RooWorkspace.h" #include "RooCustomizer.h" #include "RooPlot.h" #include "RooMsgService.h" #include "RooStats/RooStatsUtils.h" #include "RooStats/ModelConfig.h" #include "TH2F.h" #include "TH3F.h" #include "TFile.h" #include "TCanvas.h" #include "TH1.h" #include "TLine.h" #include "TTree.h" #include "TMarker.h" #include "TStopwatch.h" #include "TROOT.h" #include "TStyle.h" #include "TVectorD.h" #include "TMatrixDSym.h" // specific to this package //#include "RooStats/HistFactory/Helper.h" #include "RooStats/HistFactory/LinInterpVar.h" #include "RooStats/HistFactory/HistoToWorkspaceFactory.h" #include "Helper.h" #define VERBOSE #define alpha_Low "-5" #define alpha_High "5" #define NoHistConst_Low "0" #define NoHistConst_High "2000" // use this order for safety on library loading using namespace RooFit ; using namespace RooStats ; using namespace std ; //using namespace RooMsgService ; ClassImp(RooStats::HistFactory::HistoToWorkspaceFactory) namespace RooStats{ namespace HistFactory{ HistoToWorkspaceFactory::HistoToWorkspaceFactory() : fNomLumi(0), fLumiError(0), fLowBin(0), fHighBin(0), fOut_f(0), pFile(0) { } HistoToWorkspaceFactory::~HistoToWorkspaceFactory(){ fclose(pFile); } HistoToWorkspaceFactory::HistoToWorkspaceFactory(string filePrefix, string row, vector syst, double nomL, double lumiE, int low, int high, TFile* f): fFileNamePrefix(filePrefix), fRowTitle(row), fSystToFix(syst), fNomLumi(nomL), fLumiError(lumiE), fLowBin(low), fHighBin(high), fOut_f(f) { // fResultsPrefixStr<<"results" << "_" << fNomLumi<< "_" << fLumiError<< "_" << fLowBin<< "_" << fHighBin; fResultsPrefixStr<< "_" << fRowTitle; while(fRowTitle.find("\\ ")!=string::npos){ int pos=fRowTitle.find("\\ "); fRowTitle.replace(pos, 1, ""); } pFile = fopen ((filePrefix+"_results.table").c_str(),"a"); //RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ; } string HistoToWorkspaceFactory::FilePrefixStr(string prefix){ stringstream ss; ss << prefix << "_" << fNomLumi<< "_" << fLumiError<< "_" << fLowBin<< "_" << fHighBin<< "_"<GetName() << endl; else cout << "hist is empty" << endl; RooArgSet argset(prefix.c_str()); string highStr = "inf"; for(Int_t i=lowBin; iGetBinContent(i+1) << "," << low << "," << highStr << "]"; else range<<"["<< low << "," << high << "]"; cout << "for bin N"+str.str() << " var " << prefix+str.str()+" with range " << range.str() << endl; RooRealVar* var = (RooRealVar*) proto->factory((prefix+str.str()+range.str()).c_str()); // now create the product of the overall efficiency times the sigma(params) for this estimate if(! (productPrefix.empty() || systTerm.empty()) ) proto->factory(("prod:"+productPrefix+str.str()+"("+prefix+str.str()+","+systTerm+")").c_str() ); var->setConstant(); argset.add(* var ); } proto->defineSet(prefix.c_str(),argset); // proto->Print(); } void HistoToWorkspaceFactory::AddMultiVarGaussConstraint(RooWorkspace* proto, string prefix,int lowBin, int highBin, vector& likelihoodTermNames){ // these are the nominal predictions: eg. the mean of some space of variations // later fill these in a loop over histogram bins TVectorD mean(highBin-lowBin); cout << "a" << endl; for(Int_t i=lowBin; ivar((prefix+str.str()).c_str()); mean(i) = temp->getVal(); } TMatrixDSym Cov(highBin-lowBin); for(int i=lowBin; iset(prefix.c_str() ) ) ); RooMultiVarGaussian constraint((prefix+"Constraint").c_str(),"", floating, mean, Cov); proto->import(constraint); likelihoodTermNames.push_back(constraint.GetName()); } void HistoToWorkspaceFactory::LinInterpWithConstraint(RooWorkspace* proto, TH1* nominal, vector lowHist, vector highHist, vector sourceName, string prefix, string productPrefix, string systTerm, int lowBin, int highBin, vector& likelihoodTermNames){ // these are the nominal predictions: eg. the mean of some space of variations // later fill these in a loop over histogram bins // make list of abstract parameters that interpolate in space of variations RooArgList params( ("alpha_Hist") ); // range is set using defined macro (see top of the page) string range=string("[")+alpha_Low+","+alpha_High+"]"; for(unsigned int j=0; jvar(("alpha_"+sourceName.at(j)).c_str()); if(!temp){ temp = (RooRealVar*) proto->factory(("alpha_"+sourceName.at(j)+range).c_str()); // now add a constraint term for these parameters string command=("Gaussian::alpha_"+sourceName.at(j)+"Constraint(alpha_"+sourceName.at(j)+",nom_"+sourceName.at(j)+"[0.,-10,10],1.)"); cout << command << endl; likelihoodTermNames.push_back( proto->factory( command.c_str() )->GetName() ); proto->var(("nom_"+sourceName.at(j)).c_str())->setConstant(); const_cast(proto->set("globalObservables"))->add(*proto->var(("nom_"+sourceName.at(j)).c_str())); } params.add(* temp ); } // now make function that linearly interpolates expectation between variations for(Int_t i=lowBin; i low, high; for(unsigned int j=0; jGetBinContent(i+1) ); high.push_back( highHist.at(j)->GetBinContent(i+1) ); cout << "for "+prefix+" bin "+str.str()+" creating linear interp of nominal " << nominal->GetBinContent(i+1) << " in parameter " << sourceName.at(j) << " between " << low.back() << " - " << high.back() << " about " << 100.*fabs(low.back() - high.back() )/nominal->GetBinContent(i+1) << " % error" << endl; } // this is sigma(params), a piece-wise linear interpolation LinInterpVar interp( (prefix+str.str()).c_str(), "", params, nominal->GetBinContent(i+1), low, high); // cout << "check: " << interp.getVal() << endl; proto->import(interp); // individual params have already been imported in first loop of this function // now create the product of the overall efficiency times the sigma(params) for this estimate proto->factory(("prod:"+productPrefix+str.str()+"("+prefix+str.str()+","+systTerm+")").c_str() ); } } string HistoToWorkspaceFactory::AddNormFactor(RooWorkspace * proto, string & channel, string & sigmaEpsilon, EstimateSummary & es, bool doRatio){ string overallNorm_times_sigmaEpsilon ; string prodNames; vector norm=es.normFactor; if(norm.size()){ for(vector::iterator itr=norm.begin(); itr!=norm.end(); ++itr){ cout << "making normFactor: " << itr->name << endl; // remove "doRatio" and name can be changed when ws gets imported to the combined model. std::stringstream range; range<<"["<val<<","<low<<","<high<<"]"; //RooRealVar* var = 0; string varname; if(!prodNames.empty()) prodNames+=","; if(doRatio) { varname=itr->name+"_"+channel; } else { varname=itr->name; } proto->factory((varname+range.str()).c_str()); if(itr->constant){ // proto->var(varname.c_str())->setConstant(); // cout <<"setting " << varname << " constant"< tag is deprecated, will ignore."<< " Instead, add \n\t"<\n"<< " to your top-level XML's entry"<< endl; } prodNames+=varname; } overallNorm_times_sigmaEpsilon = es.name+"_"+channel+"_overallNorm_x_sigma_epsilon"; proto->factory(("prod::"+overallNorm_times_sigmaEpsilon+"("+prodNames+","+sigmaEpsilon+")").c_str()); } if(!overallNorm_times_sigmaEpsilon.empty()) return overallNorm_times_sigmaEpsilon; else return sigmaEpsilon; } void HistoToWorkspaceFactory::AddEfficiencyTerms(RooWorkspace* proto, string prefix, string interpName, map > systMap, vector& likelihoodTermNames, vector& totSystTermNames){ // add variables for all the relative overall uncertainties we expect // range is set using defined macro (see top of the page) string range=string("[0,")+alpha_Low+","+alpha_High+"]"; //string range="[0,-1,1]"; totSystTermNames.push_back(prefix); //bool first=true; RooArgSet params(prefix.c_str()); vector lowVec, highVec; for(map >::iterator it=systMap.begin(); it!=systMap.end(); ++it){ // add efficiency term RooRealVar* temp = (RooRealVar*) proto->var((prefix+ it->first).c_str()); if(!temp){ temp = (RooRealVar*) proto->factory((prefix+ it->first +range).c_str()); string command=("Gaussian::"+prefix+it->first+"Constraint("+prefix+it->first+",nom_"+prefix+it->first+"[0.,-10,10],1.)"); cout << command << endl; likelihoodTermNames.push_back( proto->factory( command.c_str() )->GetName() ); proto->var(("nom_"+prefix+it->first).c_str())->setConstant(); const_cast(proto->set("globalObservables"))->add(*proto->var(("nom_"+prefix+it->first).c_str())); } params.add(*temp); // add constraint in terms of bifrucated gauss with low/high as sigmas std::stringstream lowhigh; double low = it->second.first; double high = it->second.second; lowVec.push_back(low); highVec.push_back(high); } if(systMap.size()>0){ // this is epsilon(alpha_j), a piece-wise linear interpolation LinInterpVar interp( (interpName).c_str(), "", params, 1., lowVec, highVec); proto->import(interp); // params have already been imported in first loop of this function } else{ // some strange behavior if params,lowVec,highVec are empty. //cout << "WARNING: No OverallSyst terms" << endl; RooConstVar interp( (interpName).c_str(), "", 1.); proto->import(interp); // params have already been imported in first loop of this function } } void HistoToWorkspaceFactory::MakeTotalExpected(RooWorkspace* proto, string totName, string /**/, string /**/, int lowBin, int highBin, vector& syst_x_expectedPrefixNames, vector& normByNames){ // for ith bin calculate totN_i = lumi * sum_j expected_j * syst_j for(Int_t i=lowBin; i::iterator it=syst_x_expectedPrefixNames.begin(); string prepend=""; for(unsigned int j=0; jfactory(command.c_str()); } } void HistoToWorkspaceFactory::AddPoissonTerms(RooWorkspace* proto, string prefix, string obsPrefix, string expPrefix, int lowBin, int highBin, vector& likelihoodTermNames){ ///////////////////////////////// // Relate observables to expected for each bin // later modify variable named expPrefix_i to be product of terms RooArgSet Pois(prefix.c_str()); for(Int_t i=lowBin; ifactory( command.c_str() ) ); // output cout << "Poisson Term " << command << endl; ((RooAbsPdf*) temp)->setEvalErrorLoggingMode(RooAbsReal::PrintErrors); //cout << temp << endl; likelihoodTermNames.push_back( temp->GetName() ); Pois.add(* temp ); } proto->defineSet(prefix.c_str(),Pois); // add argset to workspace } void HistoToWorkspaceFactory::SetObsToExpected(RooWorkspace* proto, string obsPrefix, string expPrefix, int lowBin, int highBin){ ///////////////////////////////// // set observed to expected TTree* tree = new TTree(); Double_t* obsForTree = new Double_t[highBin-lowBin]; RooArgList obsList("obsList"); for(Int_t i=lowBin; ivar((obsPrefix+str.str()).c_str()); cout << "expected number of events called: " << expPrefix << endl; RooAbsReal* exp = proto->function((expPrefix+str.str()).c_str()); if(obs && exp){ //proto->Print(); obs->setVal( exp->getVal() ); cout << "setting obs"+str.str()+" to expected = " << exp->getVal() << " check: " << obs->getVal() << endl; // add entry to array and attach to tree obsForTree[i] = exp->getVal(); tree->Branch((obsPrefix+str.str()).c_str(), obsForTree+i ,(obsPrefix+str.str()+"/D").c_str()); obsList.add(*obs); }else{ cout << "problem retrieving obs or exp " << obsPrefix+str.str() << obs << " " << expPrefix+str.str() << exp << endl; } } tree->Fill(); RooDataSet* data = new RooDataSet("expData","", tree, obsList); // one experiment proto->import(*data); } void HistoToWorkspaceFactory::Customize(RooWorkspace* proto, const char* pdfNameChar, map renameMap) { cout << "in customizations" << endl; string pdfName(pdfNameChar); map::iterator it; string edit="EDIT::customized("+pdfName+","; string precede=""; for(it=renameMap.begin(); it!=renameMap.end(); ++it) { cout << it->first + "=" + it->second << endl; edit+=precede + it->first + "=" + it->second; precede=","; } edit+=")"; cout << edit<< endl; proto->factory( edit.c_str() ); } //_____________________________________________________________ void HistoToWorkspaceFactory::EditSyst(RooWorkspace* proto, const char* pdfNameChar, map gammaSyst, map uniformSyst,map logNormSyst) { // cout << "in edit, gammamap.size = " << gammaSyst.size() << ", unimap.size = " << uniformSyst.size() << endl; string pdfName(pdfNameChar); ModelConfig * combined_config = (ModelConfig *) proto->obj("ModelConfig"); // const RooArgSet * constrainedParams=combined_config->GetNuisanceParameters(); // RooArgSet temp(*constrainedParams); string edit="EDIT::newSimPdf("+pdfName+","; string editList; string lastPdf=pdfName; string precede=""; unsigned int numReplacements = 0; unsigned int nskipped = 0; map::iterator it; // add gamma terms and their constraints for(it=gammaSyst.begin(); it!=gammaSyst.end(); ++it) { //cout << "edit for " << it->first << "with rel uncert = " << it->second << endl; if(! proto->var(("alpha_"+it->first).c_str())){ //cout << "systematic not there" << endl; nskipped++; continue; } numReplacements++; double relativeUncertainty = it->second; double scale = 1/sqrt((1+1/pow(relativeUncertainty,2))); // this is the Gamma PDF and in a form that doesn't have roundoff problems like the Poisson does proto->factory(Form("beta_%s[1,0,10]",it->first.c_str())); proto->factory(Form("y_%s[%f]",it->first.c_str(),1./pow(relativeUncertainty,2))) ; proto->factory(Form("theta_%s[%f]",it->first.c_str(),pow(relativeUncertainty,2))) ; proto->factory(Form("Gamma::beta_%sConstraint(beta_%s,sum::k_%s(y_%s,one[1]),theta_%s,zero[0])", it->first.c_str(), it->first.c_str(), it->first.c_str(), it->first.c_str(), it->first.c_str())) ; /* // this has some problems because N in poisson is rounded to nearest integer proto->factory(Form("Poisson::beta_%sConstraint(y_%s[%f],prod::taub_%s(taus_%s[%f],beta_%s[1,0,5]))", it->first.c_str(), it->first.c_str(), 1./pow(relativeUncertainty,2), it->first.c_str(), it->first.c_str(), 1./pow(relativeUncertainty,2), it->first.c_str() ) ) ; */ // combined->factory(Form("expr::alphaOfBeta('(beta-1)/%f',beta)",scale)); // combined->factory(Form("expr::alphaOfBeta_%s('(beta_%s-1)/%f',beta_%s)",it->first.c_str(),it->first.c_str(),scale,it->first.c_str())); proto->factory(Form("PolyVar::alphaOfBeta_%s(beta_%s,{%f,%f})",it->first.c_str(),it->first.c_str(),-1./scale,1./scale)); // set beta const status to be same as alpha if(proto->var(Form("alpha_%s",it->first.c_str()))->isConstant()) proto->var(Form("beta_%s",it->first.c_str()))->setConstant(true); else proto->var(Form("beta_%s",it->first.c_str()))->setConstant(false); // set alpha const status to true // proto->var(Form("alpha_%s",it->first.c_str()))->setConstant(true); // replace alphas with alphaOfBeta and replace constraints //cout << "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint" << endl; editList+=precede + "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint"; precede=","; // cout << "alpha_"+it->first+"=alphaOfBeta_"+ it->first << endl; editList+=precede + "alpha_"+it->first+"=alphaOfBeta_"+ it->first; /* if( proto->pdf(("alpha_"+it->first+"Constraint").c_str()) && proto->var(("alpha_"+it->first).c_str()) ) cout << " checked they are there" << proto->pdf(("alpha_"+it->first+"Constraint").c_str()) << " " << proto->var(("alpha_"+it->first).c_str()) << endl; else cout << "NOT THERE" << endl; */ // EDIT seems to die if the list of edits is too long. So chunck them up. if(numReplacements%10 == 0 && numReplacements+nskipped!=gammaSyst.size()){ edit="EDIT::"+lastPdf+"_("+lastPdf+","+editList+")"; lastPdf+="_"; // append an underscore for the edit editList=""; // reset edit list precede=""; cout << "Going to issue this edit command\n" << edit<< endl; proto->factory( edit.c_str() ); RooAbsPdf* newOne = proto->pdf(lastPdf.c_str()); if(!newOne) cout << "\n\n ---------------------\n WARNING: failed to make EDIT\n\n" << endl; } } // add uniform terms and their constraints for(it=uniformSyst.begin(); it!=uniformSyst.end(); ++it) { cout << "edit for " << it->first << "with rel uncert = " << it->second << endl; if(! proto->var(("alpha_"+it->first).c_str())){ cout << "systematic not there" << endl; nskipped++; continue; } numReplacements++; // this is the Uniform PDF proto->factory(Form("beta_%s[1,0,10]",it->first.c_str())); proto->factory(Form("Uniform::beta_%sConstraint(beta_%s)",it->first.c_str(),it->first.c_str())); proto->factory(Form("PolyVar::alphaOfBeta_%s(beta_%s,{-1,1})",it->first.c_str(),it->first.c_str())); // set beta const status to be same as alpha if(proto->var(Form("alpha_%s",it->first.c_str()))->isConstant()) proto->var(Form("beta_%s",it->first.c_str()))->setConstant(true); else proto->var(Form("beta_%s",it->first.c_str()))->setConstant(false); // set alpha const status to true // proto->var(Form("alpha_%s",it->first.c_str()))->setConstant(true); // replace alphas with alphaOfBeta and replace constraints cout << "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint" << endl; editList+=precede + "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint"; precede=","; cout << "alpha_"+it->first+"=alphaOfBeta_"+ it->first << endl; editList+=precede + "alpha_"+it->first+"=alphaOfBeta_"+ it->first; if( proto->pdf(("alpha_"+it->first+"Constraint").c_str()) && proto->var(("alpha_"+it->first).c_str()) ) cout << " checked they are there" << proto->pdf(("alpha_"+it->first+"Constraint").c_str()) << " " << proto->var(("alpha_"+it->first).c_str()) << endl; else cout << "NOT THERE" << endl; // EDIT seems to die if the list of edits is too long. So chunck them up. if(numReplacements%10 == 0 && numReplacements+nskipped!=gammaSyst.size()){ edit="EDIT::"+lastPdf+"_("+lastPdf+","+editList+")"; lastPdf+="_"; // append an underscore for the edit editList=""; // reset edit list precede=""; cout << edit<< endl; proto->factory( edit.c_str() ); RooAbsPdf* newOne = proto->pdf(lastPdf.c_str()); if(!newOne) cout << "\n\n ---------------------\n WARNING: failed to make EDIT\n\n" << endl; } } ///////////////////////////////////////// //////////////////////////////////// // add lognormal terms and their constraints for(it=logNormSyst.begin(); it!=logNormSyst.end(); ++it) { cout << "edit for " << it->first << "with rel uncert = " << it->second << endl; if(! proto->var(("alpha_"+it->first).c_str())){ cout << "systematic not there" << endl; nskipped++; continue; } numReplacements++; double relativeUncertainty = it->second; double kappa = 1+relativeUncertainty; // when transforming beta -> alpha, need alpha=1 to be +1sigma value. // the P(beta>kappa*\hat(beta)) = 16% // and \hat(beta) is 1, thus double scale = relativeUncertainty; //double scale = kappa; // this is the LogNormal proto->factory(Form("beta_%s[1,0,10]",it->first.c_str())); proto->factory(Form("kappa_%s[%f]",it->first.c_str(),kappa)); proto->factory(Form("Lognormal::beta_%sConstraint(beta_%s,one[1],kappa_%s)", it->first.c_str(), it->first.c_str(), it->first.c_str())) ; proto->factory(Form("PolyVar::alphaOfBeta_%s(beta_%s,{%f,%f})",it->first.c_str(),it->first.c_str(),-1./scale,1./scale)); // proto->factory(Form("PolyVar::alphaOfBeta_%s(beta_%s,{%f,%f})",it->first.c_str(),it->first.c_str(),-1.,1./scale)); // set beta const status to be same as alpha if(proto->var(Form("alpha_%s",it->first.c_str()))->isConstant()) proto->var(Form("beta_%s",it->first.c_str()))->setConstant(true); else proto->var(Form("beta_%s",it->first.c_str()))->setConstant(false); // set alpha const status to true // proto->var(Form("alpha_%s",it->first.c_str()))->setConstant(true); // replace alphas with alphaOfBeta and replace constraints cout << "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint" << endl; editList+=precede + "alpha_"+it->first+"Constraint=beta_" + it->first+ "Constraint"; precede=","; cout << "alpha_"+it->first+"=alphaOfBeta_"+ it->first << endl; editList+=precede + "alpha_"+it->first+"=alphaOfBeta_"+ it->first; if( proto->pdf(("alpha_"+it->first+"Constraint").c_str()) && proto->var(("alpha_"+it->first).c_str()) ) cout << " checked they are there" << proto->pdf(("alpha_"+it->first+"Constraint").c_str()) << " " << proto->var(("alpha_"+it->first).c_str()) << endl; else cout << "NOT THERE" << endl; // EDIT seems to die if the list of edits is too long. So chunck them up. if(numReplacements%10 == 0 && numReplacements+nskipped!=gammaSyst.size()){ edit="EDIT::"+lastPdf+"_("+lastPdf+","+editList+")"; lastPdf+="_"; // append an underscore for the edit editList=""; // reset edit list precede=""; cout << edit<< endl; proto->factory( edit.c_str() ); RooAbsPdf* newOne = proto->pdf(lastPdf.c_str()); if(!newOne) cout << "\n\n ---------------------\n WARNING: failed to make EDIT\n\n" << endl; } } ///////////////////////////////////////// //////////////////////////////////// // commit last bunch of edits edit="EDIT::newSimPdf("+lastPdf+","+editList+")"; cout << edit<< endl; proto->factory( edit.c_str() ); // proto->writeToFile(("results/model_"+fRowTitle+"_edited.root").c_str()); RooAbsPdf* newOne = proto->pdf("newSimPdf"); if(newOne){ // newOne->graphVizTree(("results/"+pdfName+"_"+fRowTitle+"newSimPdf.dot").c_str()); combined_config->SetPdf(*newOne); } else{ cout << "\n\n ---------------------\n WARNING: failed to make EDIT\n\n" << endl; } } void HistoToWorkspaceFactory::PrintCovarianceMatrix(RooFitResult* result, RooArgSet* params, string filename){ // FILE * pFile; pFile = fopen ((filename).c_str(),"w"); TIter iti = params->createIterator(); TIter itj = params->createIterator(); RooRealVar *myargi, *myargj; fprintf(pFile," ") ; while ((myargi = (RooRealVar *)iti.Next())) { if(myargi->isConstant()) continue; fprintf(pFile," & %s", myargi->GetName()); } fprintf(pFile,"\\\\ \\hline \n" ); iti.Reset(); while ((myargi = (RooRealVar *)iti.Next())) { if(myargi->isConstant()) continue; fprintf(pFile,"%s", myargi->GetName()); itj.Reset(); while ((myargj = (RooRealVar *)itj.Next())) { if(myargj->isConstant()) continue; cout << myargi->GetName() << "," << myargj->GetName(); fprintf(pFile, " & %.2f", result->correlation(*myargi, *myargj)); } cout << endl; fprintf(pFile, " \\\\\n"); } fclose(pFile); } /////////////////////////////////////////////// RooWorkspace* HistoToWorkspaceFactory::MakeSingleChannelModel(vector summary, vector systToFix, bool doRatio) { // to time the macro TStopwatch t; t.Start(); string channel=summary[0].channel; cout << "\n\n-------------------\nStarting to process " << channel << " channel" << endl; // // our main workspace that we are using to construct the model // RooWorkspace* proto = new RooWorkspace("proto","proto workspace"); ModelConfig * proto_config = new ModelConfig("ModelConfig", proto); proto_config->SetWorkspace(*proto); RooArgSet likelihoodTerms("likelihoodTerms"); vector likelihoodTermNames, totSystTermNames,syst_x_expectedPrefixNames, normalizationNames; string prefix, range; ///////////////////////////// // Make observables, set values to observed data if data is specified, // otherwise use expected "Asimov" data if (summary.at(0).name=="Data") { ProcessExpectedHisto(summary.at(0).nominal,proto,"obsN","","",0,100000,fLowBin,fHighBin); } else { cout << "Will use expected (\"Asimov\") data set" << endl; ProcessExpectedHisto(NULL,proto,"obsN","","",0,100000,fLowBin,fHighBin); } ///////////////////////////// // shared parameters // this is ratio of lumi to nominal lumi. We will include relative uncertainty in model std::stringstream lumiStr; // lumi range lumiStr<<"["<factory(("Lumi"+lumiStr.str()).c_str()); cout << "lumi str = " << lumiStr.str() << endl; std::stringstream lumiErrorStr; // lumiErrorStr << "nominalLumi["<factory(("Gaussian::lumiConstraint(Lumi,"+lumiErrorStr.str()+")").c_str()); proto->var("nominalLumi")->setConstant(); proto->defineSet("globalObservables","nominalLumi"); likelihoodTermNames.push_back("lumiConstraint"); cout << "lumi Error str = " << lumiErrorStr.str() << endl; //proto->factory((string("SigXsecOverSM[1.,0.5,1..8]").c_str())); /////////////////////////////////// // loop through estimates, add expectation, floating bin predictions, // and terms that constrain floating to expectation via uncertainties vector::iterator it = summary.begin(); for(; it!=summary.end(); ++it){ if(it->name=="Data") continue; string overallSystName = it->name+"_"+it->channel+"_epsilon"; string systSourcePrefix = "alpha_"; AddEfficiencyTerms(proto,systSourcePrefix, overallSystName, it->overallSyst, likelihoodTermNames, totSystTermNames); overallSystName=AddNormFactor(proto, channel, overallSystName, *it, doRatio); // get histogram TH1* nominal = it->nominal; if(it->lowHists.size() == 0){ cout << it->name+"_"+it->channel+" has no variation histograms " <name+"_"+it->channel+"_expN"; string syst_x_expectedPrefix=it->name+"_"+it->channel+"_overallSyst_x_Exp"; ProcessExpectedHisto(nominal,proto,expPrefix,syst_x_expectedPrefix,overallSystName,atoi(NoHistConst_Low),atoi(NoHistConst_High),fLowBin,fHighBin); syst_x_expectedPrefixNames.push_back(syst_x_expectedPrefix); } else if(it->lowHists.size() != it->highHists.size()){ cout << "problem in "+it->name+"_"+it->channel << " number of low & high variation histograms don't match" << endl; return 0; } else { string constraintPrefix = it->name+"_"+it->channel+"_Hist_alpha"; // name of source for variation string syst_x_expectedPrefix = it->name+"_"+it->channel+"_overallSyst_x_HistSyst"; LinInterpWithConstraint(proto, nominal, it->lowHists, it->highHists, it->systSourceForHist, constraintPrefix, syst_x_expectedPrefix, overallSystName, fLowBin, fHighBin, likelihoodTermNames); syst_x_expectedPrefixNames.push_back(syst_x_expectedPrefix); } // AddMultiVarGaussConstraint(proto, "exp"+it->first+"N", fLowBin, fHighBin, likelihoodTermNames); if(it->normName=="") normalizationNames.push_back( "Lumi" ); else normalizationNames.push_back( it->normName); } //proto->Print(); /////////////////////////////////// // for ith bin calculate totN_i = lumi * sum_j expected_j * syst_j MakeTotalExpected(proto,channel+"_totN",channel+"_expN","Lumi",fLowBin,fHighBin, syst_x_expectedPrefixNames, normalizationNames); ///////////////////////////////// // Relate observables to expected for each bin AddPoissonTerms(proto, "Pois_"+channel, "obsN", channel+"_totN", fLowBin, fHighBin, likelihoodTermNames); ///////////////////////////////// // if no data histogram provided, make asimov data if(summary.at(0).name!="Data"){ SetObsToExpected(proto, "obsN",channel+"_totN", fLowBin, fHighBin); cout << " using asimov data" << endl; } else{ SetObsToExpected(proto, "obsN","obsN", fLowBin, fHighBin); cout << " using input data histogram" << endl; } ////////////////////////////////////// // fix specified parameters for(unsigned int i=0; ivar((systToFix.at(i)).c_str()); if(temp) temp->setConstant(); else cout << "could not find variable " << systToFix.at(i) << " could not set it to constant" << endl; } ////////////////////////////////////// // final proto model for(unsigned int i=0; iarg(likelihoodTermNames[i].c_str())) ); } // likelihoodTerms.Print(); proto->defineSet("likelihoodTerms",likelihoodTerms); // proto->Print(); cout <<"-----------------------------------------"<import(*model,RecycleConflictNodes()); proto_config->SetPdf(*model); proto_config->SetGlobalObservables(*proto->set("globalObservables")); proto->import(*proto_config,proto_config->GetName()); proto->importClassCode(); // proto->writeToFile(("results/model_"+channel+".root").c_str()); return proto; } RooWorkspace* HistoToWorkspaceFactory::MakeCombinedModel(vector ch_names, vector chs) { // /// These things were used for debugging. Maybe useful in the future // // RooAbsReal::defaultIntegratorConfig()->setEpsAbs(1e-8) ; // RooAbsReal::defaultIntegratorConfig()->setEpsRel(1e-8) ; // RooMsgService::instance().setGlobalKillBelow(RooMsgService::WARNING); // RooMsgService::instance().setGlobalKillBelow(RooMsgService::WARNING) ; // cout << "MsgSvc: " << RooMsgService::instance().globalKillBelow() << " INFO " // << RooMsgService::INFO << " WARNING " << RooMsgService::WARNING << endl; // RooArgSet* constrainedParams= new RooArgSet("constrainedParams"); map pdfMap; vector models; stringstream ss; RooArgSet globalObs; for(unsigned int i = 0; i< ch_names.size(); ++i){ string channel_name=ch_names[i]; if (ss.str().empty()) ss << channel_name ; else ss << ',' << channel_name ; RooWorkspace * ch=chs[i]; RooAbsPdf* model = ch->pdf(("model_"+channel_name).c_str()); models.push_back(model); globalObs.add(*ch->set("globalObservables")); // constrainedParams->add( * ch->set("constrainedParams") ); pdfMap[channel_name]=model; } //constrainedParams->Print(); cout << "\n\n------------------\n Entering combination" << endl; RooWorkspace* combined = new RooWorkspace("combined"); RooCategory* channelCat = (RooCategory*) combined->factory(("channelCat["+ss.str()+"]").c_str()); RooSimultaneous * simPdf= new RooSimultaneous("simPdf","",pdfMap, *channelCat); ModelConfig * combined_config = new ModelConfig("ModelConfig", combined); combined_config->SetWorkspace(*combined); // combined_config->SetNuisanceParameters(*constrainedParams); combined->import(globalObs); combined->defineSet("globalObservables",globalObs); combined_config->SetGlobalObservables(*combined->set("globalObservables")); //////////////////////////////////////////// // Make toy simultaneous dataset cout <<"-----------------------------------------"<set("obsN"); RooDataSet * simData=new RooDataSet("simData","master dataset", *obsN, Index(*channelCat), Import(ch_names[0].c_str(),*((RooDataSet*)chs[0]->data("expData")))); for(unsigned int i = 1; i< ch_names.size(); ++i){ RooDataSet * simData_ch=new RooDataSet("simData","master dataset", *obsN, Index(*channelCat), Import(ch_names[i].c_str(),*((RooDataSet*)chs[i]->data("expData")))); simData->append(*simData_ch); } //for(int i=0; inumEntries(); ++i) // simData->get(i)->Print("v"); combined->import(*simData,RecycleConflictNodes()); cout << "\n\n----------------\n Importing combined model" << endl; combined->import(*simPdf,RecycleConflictNodes()); //combined->import(*simPdf, RenameVariable("SigXsecOverSM","SigXsecOverSM_comb")); cout << "check pointer " << simPdf << endl; for(unsigned int i=0; ivar((fSystToFix.at(i)).c_str()); if(temp) { temp->setConstant(); cout <<"setting " << fSystToFix.at(i) << " constant" << endl; } else cout << "could not find variable " << fSystToFix.at(i) << " could not set it to constant" << endl; } /// /// writing out the model in graphViz /// // RooAbsPdf* customized=combined->pdf("simPdf"); //combined_config->SetPdf(*customized); combined_config->SetPdf(*simPdf); // customized->graphVizTree(("results/"+fResultsPrefixStr.str()+"_simul.dot").c_str()); combined->import(*combined_config,combined_config->GetName()); combined->importClassCode(); // combined->writeToFile("results/model_combined.root"); return combined; } /////////////////////////////////////////////// void HistoToWorkspaceFactory::FitModel(RooWorkspace * combined, string channel, string /*model_name*/, string data_name, bool /*doParamInspect*/) { ModelConfig * combined_config = (ModelConfig *) combined->obj("ModelConfig"); RooDataSet * simData = (RooDataSet *) combined->obj(data_name.c_str()); // const RooArgSet * constrainedParams=combined_config->GetNuisanceParameters(); const RooArgSet * POIs=combined_config->GetParametersOfInterest(); /* RooRealVar* poi = (RooRealVar*) combined->var("SigXsecOverSM"); RooArgSet * params= new RooArgSet; params->add(*poi); combined_config->SetParameters(*params); RooAbsData* expData = combined->data("expData"); RooArgSet* temp = (RooArgSet*) combined->set("obsN")->Clone("temp"); temp->add(*poi); RooAbsPdf* model=combined_config->GetPdf(); RooArgSet* constrainedParams = model->getParameters(temp); combined->defineSet("constrainedParams", *constrainedParams); */ //RooAbsPdf* model=combined->pdf(model_name.c_str()); RooAbsPdf* model=combined_config->GetPdf(); // RooArgSet* allParams = model->getParameters(*simData); /////////////////////////////////////// //Do combined fit //RooMsgService::instance().setGlobalKillBelow(RooMsgService::INFO) ; cout << "\n\n---------------" << endl; cout << "---------------- Doing "<< channel << " Fit" << endl; cout << "---------------\n\n" << endl; // RooFitResult* result = model->fitTo(*simData, Minos(kTRUE), Save(kTRUE), PrintLevel(1)); model->fitTo(*simData, Minos(kTRUE), PrintLevel(1)); // PrintCovarianceMatrix(result, allParams, "results/"+FilePrefixStr(channel)+"_corrMatrix.table" ); // // assuming there is only on poi // RooRealVar* poi = 0; // (RooRealVar*) POIs->first(); // for results tables TIterator* params_itr=POIs->createIterator(); TObject* params_obj=0; while((params_obj=params_itr->Next())){ poi = (RooRealVar*) params_obj; cout << "printing results for " << poi->GetName() << " at " << poi->getVal()<< " high " << poi->getErrorLo() << " low " << poi->getErrorHi()<getErrorLo(), poi->getErrorHi()); RooAbsReal* nll = model->createNLL(*simData); RooAbsReal* profile = nll->createProfile(*poi); RooPlot* frame = poi->frame(); FormatFrameForLikelihood(frame); TCanvas* c1 = new TCanvas( channel.c_str(), "",800,600); nll->plotOn(frame, ShiftToZero(), LineColor(kRed), LineStyle(kDashed)); profile->plotOn(frame); frame->SetMinimum(0); frame->SetMaximum(2.); frame->Draw(); // c1->SaveAs( ("results/"+FilePrefixStr(channel)+"_profileLR.eps").c_str() ); c1->SaveAs( (fFileNamePrefix+"_"+channel+"_"+fRowTitle+"_profileLR.eps").c_str() ); fOut_f->mkdir(channel.c_str())->mkdir("Summary")->cd(); // an example of calculating profile for a nuisance parameter not poi /* RooRealVar* alpha_isrfsr = (RooRealVar*) combined->var("alpha_isrfsr"); RooAbsReal* profile_isrfsr = nll->createProfile(*alpha_isrfsr); poi->setVal(0.55); poi->setConstant(); RooPlot* frame_isrfsr = alpha_isrfsr->frame(); profile_isrfsr->plotOn(frame_isrfsr, Precision(0.1)); TCanvas c_isrfsr = new TCanvas( "combined", "",800,600); FormatFrameForLikelihood(frame_isrfsr, "alpha_{isrfsr}"); frame_isrfsr->Draw(); fOut_f->cd("Summary"); c1->Write((FilePrefixStr(channel).str()+"_profileLR_alpha_isrfsr").c_str() ); delete frame; delete c1; poi->setConstant(kFALSE); */ RooCurve* curve=frame->getCurve(); Int_t curve_N=curve->GetN(); Double_t* curve_x=curve->GetX(); delete frame; delete c1; // // Verbose output from MINUIT // /* RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ; profile->getVal(); RooMinuit* minuit = ((RooProfileLL*) profile)->minuit(); minuit->setPrintLevel(5) ; // Print MINUIT messages minuit->setVerbose(5) ; // Print RooMinuit messages with parameter // changes (corresponds to the Verbose() option of fitTo() */ Double_t * x_arr = new Double_t[curve_N]; Double_t * y_arr_nll = new Double_t[curve_N]; // Double_t y_arr_prof_nll[curve_N]; // Double_t y_arr_prof[curve_N]; for(int i=0; isetVal(f); x_arr[i]=f; y_arr_nll[i]=nll->getVal(); } TGraph * g = new TGraph(curve_N, x_arr, y_arr_nll); g->SetName((FilePrefixStr(channel)+"_nll").c_str()); g->Write(); delete g; delete [] x_arr; delete [] y_arr_nll; /** find out what's inside the workspace **/ //combined->Print(); } void HistoToWorkspaceFactory::FormatFrameForLikelihood(RooPlot* frame, string /*XTitle*/, string YTitle){ gStyle->SetCanvasBorderMode(0); gStyle->SetPadBorderMode(0); gStyle->SetPadColor(0); gStyle->SetCanvasColor(255); gStyle->SetTitleFillColor(255); gStyle->SetFrameFillColor(0); gStyle->SetStatColor(255); RooAbsRealLValue* var = frame->getPlotVar(); double xmin = var->getMin(); double xmax = var->getMax(); frame->SetTitle(""); // frame->GetXaxis()->SetTitle(XTitle.c_str()); frame->GetXaxis()->SetTitle(var->GetTitle()); frame->GetYaxis()->SetTitle(YTitle.c_str()); frame->SetMaximum(2.); frame->SetMinimum(0.); TLine * line = new TLine(xmin,.5,xmax,.5); line->SetLineColor(kGreen); TLine * line90 = new TLine(xmin,2.71/2.,xmax,2.71/2.); line90->SetLineColor(kGreen); TLine * line95 = new TLine(xmin,3.84/2.,xmax,3.84/2.); line95->SetLineColor(kGreen); frame->addObject(line); frame->addObject(line90); frame->addObject(line95); } TDirectory * HistoToWorkspaceFactory::Makedirs( TDirectory * file, vector names ){ if(! file) return file; string path=""; TDirectory* ptr=0; for(vector::iterator itr=names.begin(); itr != names.end(); ++itr){ if( ! path.empty() ) path+="/"; path+=(*itr); ptr=file->GetDirectory(path.c_str()); if( ! ptr ) ptr=file->mkdir((*itr).c_str()); file=file->GetDirectory(path.c_str()); } return ptr; } TDirectory * HistoToWorkspaceFactory::Mkdir( TDirectory * file, string name ){ if(! file) return file; TDirectory* ptr=0; ptr=file->GetDirectory(name.c_str()); if( ! ptr ) ptr=file->mkdir(name.c_str()); return ptr; } } }