Apply the PU profile reweighting to the simulation. 
   47     cout << __func__ << 
' ' << slice << 
" start" << endl;
 
   50     auto tIn = flow.GetInputTree(slice);
 
   51     auto [fOut, tOut] = flow.GetOutput(output);
 
   55     auto isMC = metainfo.Get<
bool>(
"flags", 
"isMC");
 
   56     if (!
isMC) BOOST_THROW_EXCEPTION( 
DE::BadInput(
"Only MC may be used as input.",
 
   57                                       make_unique<TFile>(
inputs.front().c_str() )) );
 
   59     auto genEvt = flow.GetBranchReadOnly<GenEvent>(
"genEvent");
 
   60     auto recEvt = flow.GetBranchReadOnly<RecEvent>(
"recEvent");
 
   61     auto pu     = flow.GetBranchReadOnly<PileUp  >(
"pileup"  );
 
   62     auto genJets = flow.GetBranchReadWrite<vector<GenJet>>(
"genJets");
 
   63     auto recJets = flow.GetBranchReadWrite<vector<RecJet>>(
"recJets");
 
   66     ControlPlots raw(
"raw");
 
   67     bool applySyst = steering & 
DT::syst;
 
   68     vector<ControlPlots> calib { ControlPlots(
"nominal") };
 
   70         metainfo.Set<
string>(
"variations", RecEvent::WeightVar, 
"PU" + 
SysUp);
 
   71         metainfo.Set<
string>(
"variations", RecEvent::WeightVar, 
"PU" + 
SysDown);
 
   73         calib.push_back(ControlPlots(
"PU" + 
SysUp));
 
   74         calib.push_back(ControlPlots(
"PU" + 
SysDown));
 
   77     auto turnon_file = 
config.get<fs::path>(
"corrections.normalisation.turnons");
 
   78     auto DataProf = 
config.get<fs::path>(
"corrections.PUprofile.Data");
 
   79     auto MCprof = 
config.get<fs::path>(
"corrections.PUprofile.MC");
 
   80     for (
auto& file: {turnon_file, DataProf, MCprof})
 
   81         if (!fs::exists(file))
 
   82             BOOST_THROW_EXCEPTION( fs::filesystem_error(
"Input file could not be found",
 
   83                                 file, make_error_code(errc::no_such_file_or_directory)));
 
   86     pt::read_info(turnon_file.c_str(), turnons);
 
   88     auto fMCprof = TFile::Open(MCprof.c_str(), 
"READ"),
 
   89          fDataProf = TFile::Open(DataProf.c_str(), 
"READ");
 
   90     map<float, PUprofile::Correction> corrections;
 
   91     auto maxWeight = 
config.get<
float>(
"corrections.PUprofile.maxWeight");
 
   92     for (
auto& turnon: turnons) {
 
   93         auto threshold = atoi(turnon.first.c_str());
 
   94         auto trigger = [
threshold](
const char * variation, 
bool global) {
 
   95             return global ? Form(
"%s/intPU"            , variation)
 
   96                           : Form(
"%s/HLT_PFJet%d/intPU", variation, 
threshold);
 
   98         auto pt = turnon.second.get_value<
float>();
 
   99         PUprofile::Correction correction(fMCprof, fDataProf, trigger, maxWeight);
 
  100         corrections.insert( {
pt, correction} );
 
  102     const bool hasZB = fDataProf->GetDirectory(
"nominal/ZB") && 
dynamic_cast<TH1*
>(fDataProf->Get(
"nominal/ZB/intPU"))->Integral() > 0;
 
  105         auto trigger = [](
const char * variation, 
bool global) {
 
  106             return global ? Form(
"%s/intPU"   , variation)
 
  107                           : Form(
"%s/ZB/intPU", variation);
 
  109         PUprofile::Correction correction(fMCprof, fDataProf, trigger, maxWeight);
 
  110         corrections.insert( {0, correction} );
 
  115     metainfo.Set<fs::path>(
"corrections", 
"normalisation", 
"turnons", turnon_file);
 
  116     metainfo.Set<fs::path>(
"corrections", 
"PUprofile", 
"Data", DataProf);
 
  117     metainfo.Set<fs::path>(
"corrections", 
"PUprofile", 
"MC", MCprof);
 
  118     metainfo.Set<
float>(
"corrections", 
"PUprofile", 
"maxWeight", maxWeight);
 
  120     PileUp::r3.SetSeed(metainfo.Seed<756347956>(slice));
 
  121     for (
DT::Looper looper(tIn); looper(); ++looper) {
 
  125         int intpu = pu->intpu;
 
  126         auto weight_raw = recEvt->weights.front(); 
 
  129         auto pt0 = corrections.begin()->first; 
 
  130         auto InTk = [](
const auto& jet) { 
return jet.AbsRap() < 3.0; };
 
  131         auto leadRecJetInTk = find_if(recJets->begin(), recJets->end(), InTk);
 
  132         if (leadRecJetInTk != recJets->end())
 
  133             pt0 = leadRecJetInTk->CorrPt();
 
  135             auto leadGenJetInTk = find_if(genJets->begin(), genJets->end(), InTk);
 
  136             if (leadGenJetInTk != genJets->end())
 
  137                 pt0 = leadGenJetInTk->p4.Pt();
 
  140         auto it = find_if(corrections.rbegin(), prev(corrections.rend()),
 
  141                 [&pt0](
const auto& th_corr) { return pt0 > th_corr.first; });
 
  142         const auto& correction = it->second;
 
  143         cout << pt0 << 
' ' << it->first << endl;
 
  146         auto nominal_correction = correction(intpu, 
'0');
 
  147         recEvt->weights *= nominal_correction;
 
  149         auto weight_nominal = recEvt->weights.front();
 
  152         raw          (*genJets, genEvt->weights.front());
 
  153         calib.front()(*genJets, genEvt->weights.front());
 
  156         raw          (*recJets, genEvt->weights.front() * weight_raw    );
 
  157         calib.front()(*recJets, genEvt->weights.front() * weight_nominal);
 
  161             auto weight_upper   = weight_raw*correction(intpu, 
'+'),
 
  162                  weight_lower   = weight_raw*correction(intpu, 
'-');
 
  163             recEvt->weights.push_back(Weight{weight_upper});
 
  164             recEvt->weights.push_back(Weight{weight_lower});
 
  165             calib.at(1)(*genJets, genEvt->weights.front());
 
  166             calib.at(2)(*genJets, genEvt->weights.front());
 
  167             calib.at(1)(*recJets, genEvt->weights.front() * weight_upper);
 
  168             calib.at(2)(*recJets, genEvt->weights.front() * weight_lower);
 
  172         if (steering & 
DT::fill) tOut->Fill();
 
  175     auto d = fOut->mkdir(
"corrections");
 
  176     for (
auto& correction: corrections) {
 
  179         auto it = turnons.begin();
 
  180         while (it != turnons.end()) {
 
  181             if (it->second.get_value<
int>() == 
threshold) 
break;
 
  186         if (it != turnons.end()) {
 
  187             auto dd = d->mkdir(Form(
"HLT_PFJet%d", atoi(it->first.c_str())));
 
  188             bool reset = slice.second > 0;
 
  189             correction.second.Write(dd, 
reset);
 
  192             auto dd = d->mkdir(
"ZB");
 
  193             bool reset = slice.second > 0;
 
  194             correction.second.Write(dd, 
reset);
 
  202     metainfo.Set<
bool>(
"git", 
"complete", 
true);
 
  204     cout << __func__ << 
' ' << slice << 
" end" << endl;