8 #include "boost/format.hpp" 
    9 #include "RooFitResult.h" 
   10 #include "RooRealVar.h" 
   11 #include "RooDataHist.h" 
   12 #include "RooAbsReal.h" 
   13 #include "RooAbsData.h" 
   20   std::cout<<
"Systematic "<<syst->
name()<<
" for process "<<syst->
process()<<
" in region "<<syst->
bin()<<
" :";
 
   24   std::cout<<
"Process "<<proc->
process()<<
" in region "<<proc->
bin()<<
" :";
 
   32       jsobj[
"uncertVarySameDirect"][sys->name()][sys->bin()][sys->process()]={{
"value_u",sys->value_u()},{
"value_d",sys->value_d()}};
 
   41       std::cout<<
" Up/Down normalisations go in the same direction: up variation: "<<sys->value_u()<<
", down variation: "<<sys->value_d()<<std::endl;
 
   51       hist_u = sys->shape_u();
 
   52       hist_d = sys->shape_d();
 
   54       for(int i=1;i<=hist_u->GetNbinsX();i++){
 
   55         if(fabs(hist_u->GetBinContent(i))+fabs(hist_d->GetBinContent(i))>0){
 
   56           if(2*double(fabs(hist_u->GetBinContent(i)-hist_d->GetBinContent(i)))/(fabs(hist_u->GetBinContent(i))+fabs(hist_d->GetBinContent(i)))>0.001) is_same = 0;
 
   60         jsobj[
"uncertTemplSame"][sys->name()][sys->bin()][sys->process()]={{
"value_u",sys->value_u()},{
"value_d",sys->value_d()}};
 
   71       hist_u = sys->shape_u();
 
   72       hist_d = sys->shape_d();
 
   74       for(int i=1;i<=hist_u->GetNbinsX();i++){
 
   75         if(fabs(hist_u->GetBinContent(i))+fabs(hist_d->GetBinContent(i))>0){
 
   76           if(2*double(fabs(hist_u->GetBinContent(i)-hist_d->GetBinContent(i)))/(fabs(hist_u->GetBinContent(i))+fabs(hist_d->GetBinContent(i)))>0.001) is_same = 0;
 
   81         std::cout<<
"Up/Down templates are identical: up variation: "<<sys->value_u()<<
", down variation: "<<sys->value_d()<<std::endl;
 
   90   std::vector<ch::Process*> empty_procs;
 
   94       empty_procs.push_back(proc); 
 
   95       if (jsobj[
"emptyProcessShape"][proc->bin()] !=NULL){
 
   96         jsobj[
"emptyProcessShape"][proc->bin()].push_back(proc->process());
 
   98         jsobj[
"emptyProcessShape"][proc->bin()] = {proc->process()};
 
  104     for( 
unsigned int i=0; i< empty_procs.size(); i++){
 
  109         jsobj[
"emptySystematicShape"][sys->name()][sys->bin()][sys->process()]={{
"value_u",sys->value_u()},{
"value_d",sys->value_d()}};
 
  116   std::vector<ch::Process*> empty_procs;
 
  118     if(proc->
rate()==0.){
 
  119       empty_procs.push_back(proc); 
 
  121       std::cout<<
" has 0 yield"<<std::endl;
 
  126     for( 
unsigned int i=0; i< empty_procs.size(); i++){
 
  131         PrintSystematic(sys);
 
  132         std::cout<<
" At least one empty histogram: up variation: "<<sys->value_u()<<
" Down variation: "<<sys->value_d()<<std::endl;
 
  139   std::vector<ch::Process*> empty_procs;
 
  141     if(proc->
rate()==0.){
 
  142       empty_procs.push_back(proc); 
 
  147     for( 
unsigned int i=0; i< empty_procs.size(); i++){
 
  150     if(!no_check && ((sys->
type()==
"shape" &&  (sys->
value_u()-1 > maxNormEff || sys->
value_u()-1 < -maxNormEff  || sys->
value_d()-1>maxNormEff || sys->
value_d()-1< -maxNormEff)) || (sys->
type()==
"lnN" && (sys->
value_u()-1 > maxNormEff || sys->
value_u()-1 < - maxNormEff) ))){
 
  151       PrintSystematic(sys);
 
  152       std::cout<<
"Uncertainty has a large normalisation effect: up variation: "<<sys->value_u()<<
" Down variation: "<<sys->value_d()<<std::endl;
 
  158   std::vector<ch::Process*> empty_procs;
 
  160     if(proc->
rate()==0.){
 
  161       empty_procs.push_back(proc); 
 
  166     for( 
unsigned int i=0; i< empty_procs.size(); i++){
 
  169     if(!no_check && ((sys->
type()==
"shape" &&  (std::abs(sys->
value_u()-1) > maxNormEff || std::abs(sys->
value_d()-1)>maxNormEff)) || (sys->
type()==
"lnN" && (std::abs(sys->
value_u()-1) > maxNormEff) ))){
 
  170       jsobj[
"largeNormEff"][sys->name()][sys->bin()][sys->process()]={{
"value_u",sys->value_u()},{
"value_d",sys->value_d()}};
 
  179     auto cb_bin_backgrounds = cb.
cp().
bin({b}).backgrounds();
 
  180     tothist = cb_bin_backgrounds.
GetShape();
 
  181     for(
int i=1;i<=tothist.GetNbinsX();i++){
 
  182       if(tothist.GetBinContent(i)<=0){ 
 
  183         std::cout<<
"Channel "<<b<<
" bin "<<i<<
" of the templates is empty in background"<<std::endl;
 
  193     auto cb_bin_backgrounds = cb.
cp().
bin({b}).backgrounds();
 
  194     tothist = cb_bin_backgrounds.
GetShape();
 
  195     for(
int i=1;i<=tothist.GetNbinsX();i++){
 
  196       if(tothist.GetBinContent(i)<=0){ 
 
  197         if (jsobj[
"emptyBkgBin"][b] !=NULL){
 
  198           jsobj[
"emptyBkgBin"][b].push_back(i);
 
  200           jsobj[
"emptyBkgBin"][b] = {i};
 
  209   double diff_lim=0.001;
 
  214     if(sys->
type()==
"shape"){
 
  215       hist_u = sys->shape_u();
 
  216       hist_d = sys->shape_d();
 
  217       hist_nom=cb.cp().bin({sys->bin()}).process({sys->
process()}).GetShape();
 
  218       hist_nom.Scale(1./hist_nom.Integral());
 
  221       for(
int i=1;i<=hist_u->GetNbinsX();i++){
 
  222         if(fabs(hist_u->GetBinContent(i))+fabs(hist_nom.GetBinContent(i))>0){
 
  223           up_diff+=2*double(fabs(hist_u->GetBinContent(i)-hist_nom.GetBinContent(i)))/(fabs(hist_u->GetBinContent(i))+fabs(hist_nom.GetBinContent(i)));
 
  225         if(fabs(hist_d->GetBinContent(i))+fabs(hist_nom.GetBinContent(i))>0){
 
  226           down_diff+=2*double(fabs(hist_d->GetBinContent(i)-hist_nom.GetBinContent(i)))/(fabs(hist_d->GetBinContent(i))+fabs(hist_nom.GetBinContent(i)));
 
  229       if(up_diff<diff_lim && down_diff<diff_lim){
 
  231         std::cout<<
"Uncertainty probably has no genuine shape effect. Summed relative difference per bin between normalised nominal and up shape: "<<up_diff<<
" between normalised nominal and down shape: "<<down_diff<<std::endl;
 
  239   double diff_lim=0.001;
 
  244     if(sys->
type()==
"shape"){
 
  245       hist_u = sys->shape_u();
 
  246       hist_d = sys->shape_d();
 
  247       hist_nom=cb.cp().bin({sys->bin()}).process({sys->
process()}).GetShape();
 
  248       hist_nom.Scale(1./hist_nom.Integral());
 
  251       for(
int i=1;i<=hist_u->GetNbinsX();i++){
 
  252         if(fabs(hist_u->GetBinContent(i))+fabs(hist_nom.GetBinContent(i))>0){
 
  253           up_diff+=2*double(fabs(hist_u->GetBinContent(i)-hist_nom.GetBinContent(i)))/(fabs(hist_u->GetBinContent(i))+fabs(hist_nom.GetBinContent(i)));
 
  255         if(fabs(hist_d->GetBinContent(i))+fabs(hist_nom.GetBinContent(i))>0){
 
  256           down_diff+=2*double(fabs(hist_d->GetBinContent(i)-hist_nom.GetBinContent(i)))/(fabs(hist_d->GetBinContent(i))+fabs(hist_nom.GetBinContent(i)));
 
  259       if(up_diff<diff_lim && down_diff<diff_lim) jsobj[
"smallShapeEff"][sys->
name()][sys->
bin()][sys->
process()]={{
"diff_u",up_diff},{
"diff_d",down_diff}};
 
  267     auto cb_bin_signals = cb.
cp().
bin({b}).signals();
 
  268     auto cb_bin_backgrounds = cb.
cp().
bin({b}).backgrounds();
 
  269     auto cb_bin = cb.
cp().
bin({b}); 
 
  270     double sigrate = cb_bin_signals.
GetRate();
 
  271     for(
auto p : cb_bin_signals.process_set()){
 
  272       if(cb_bin_signals.cp().process({p}).GetRate() < minSigFrac*sigrate){
 
  273         std::cout<<
"Very small signal process. In bin "<<b<<
" signal process "<<p<<
" has yield "<<cb_bin_signals.cp().process({p}).GetRate()<<
". Total signal rate in this bin is "<<sigrate<<std::endl;
 
  283     auto cb_bin_signals = cb.
cp().
bin({b}).signals();
 
  284     auto cb_bin_backgrounds = cb.
cp().
bin({b}).backgrounds();
 
  285     auto cb_bin = cb.
cp().
bin({b}); 
 
  286     double sigrate = cb_bin_signals.
GetRate();
 
  287     for(
auto p : cb_bin_signals.process_set()){
 
  288       if(cb_bin_signals.cp().process({p}).GetRate() < minSigFrac*sigrate){
 
  289         jsobj[
"smallSignalProc"][b][p]={{
"sigrate_tot",sigrate},{
"procrate",cb_bin_signals.cp().process({p}).GetRate()}};
 
  298  bool is_shape_card=1;
 
  310    std::cout<<
"Not a shape-based datacard / shape-based datacard using RooDataHist. Skipping checks on systematic shapes."<<std::endl;
 
  315  std::ofstream outfile(filename);
 
  316  outfile <<std::setw(4)<<output_js<<std::endl;
 
void ForEachSyst(Function func)
 
void ForEachProc(Function func)
 
CombineHarvester & bin(std::vector< std::string > const &vec, bool cond=true)
 
std::set< std::string > bin_set()
 
CombineHarvester cp()
Creates and returns a shallow copy of the CombineHarvester instance.
 
virtual std::string const  & process() const
 
virtual std::string const  & bin() const
 
RooAbsReal const  * pdf() const
 
TH1 const  * shape() const
 
std::string const  & type() const
 
std::string const  & name() const
 
void ValidateShapeTemplates(CombineHarvester &cb, json &jsobj)
 
void ValidateShapeUncertaintyDirection(CombineHarvester &cb, json &jsobj)
 
void CheckNormEff(CombineHarvester &cb, double maxNormEff, json &jsobj)
 
void PrintProc(ch::Process *proc)
 
void CheckSizeOfShapeEffect(CombineHarvester &cb, json &jsobj)
 
void ValidateCards(CombineHarvester &cb, std::string const &filename, double maxNormEff, double minSigFrac)
 
void CheckEmptyBins(CombineHarvester &cb, json &jsobj)
 
void CheckEmptyShapes(CombineHarvester &cb, json &jsobj)
 
bool MatchingProcess(T const &first, U const &second)
 
void CheckSmallSignals(CombineHarvester &cb, double minSigFrac, json &jsobj)
 
void PrintSystematic(ch::Systematic *syst)