Exemple #1
0
void chain(int cem = 8, int nsel = 0, double mh = 125, int mode = 0){

  char plotName[300];
  sprintf(plotName,"test");
  bool isBackground = true;
  bool isData = false;
		  
  if (nsel == 0)                	{sprintf(plotName,"Data");	isBackground = false;	isData = true;}
  else if (nsel == 1)   		{sprintf(plotName,"ZH");	isBackground = false;}
  else if (nsel == 2)   		{sprintf(plotName,"WZ");}
  else if (nsel == 3)   		{sprintf(plotName,"ZZ");}
  else if (nsel == 4)   		{sprintf(plotName,"VVV");}
  else if (nsel == 5)			{sprintf(plotName,"Wjets");}
  else if (nsel == 6) 			{sprintf(plotName, "all");}
  else if (nsel == 7) 			{sprintf(plotName, "ZH_SM");	isBackground = false;} //no fakes allowed
				  
  char myRootFile[300];
  if (cem != 7 && cem !=8) cem = 8;
  double lumi = lumi8;
 if (cem == 8){
    if (nsel == 0) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/data_3l.root");
    else if (nsel == 7) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/zhww125.root");
    else if (nsel == 1 && (mh == 125 || mh == 124 || mh == 126 || mh == 125.7)) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/zhww125.root");
    else if (nsel == 1 && (mh == 118 || mh == 122)) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/hww120.root");
    else if (nsel == 1 &&  mh == 128) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/hww130.root");
    else if (nsel == 1) sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/hww%g.root", mh);
    else sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/backgroundA_3l.root");
  } else {
    lumi = lumi7;
    if (nsel == 0) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/data_3l.root");
    else if (nsel == 7) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/zhww125.root");
    else if (nsel == 1 && (mh == 125 || mh == 125.7)) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/zhww125.root");
    else if (nsel == 1 && (mh == 110 || mh == 115)) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/vtthww118.root");
    else if (nsel == 1 && mh == 145) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/vtthww140.root");
    else if (nsel == 1) sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/vtthww%g.root", mh);
    else sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/backgroundA_3l.root");
  }
  
  cout << "[Info:] "<< cem <<  "TeV, " << plotName << ", Higgs mass " << mh << ","  ;
  if (mode == 1) cout << " eee channel" << endl ;
  else if (mode == 2) cout << " eem channel" << endl ; 
  else if (mode == 3) cout << " emm channel" << endl ; 
  else if (mode == 4) cout << " mmm channel" << endl ; 
  else cout << " all final states" << endl;
 								    
  //Load datasets
  SmurfTree sample;
  cout << myRootFile << endl;
  sample.LoadTree(myRootFile,-1);
  sample.InitTree(0);

  // Prepare output file
  char rootFile[300];
  if (mode == 1) sprintf(rootFile,"%g/zh3l2j_input_shape_eee_%dTeV.root", mh, cem);
  else if (mode == 2) sprintf(rootFile,"%g/zh3l2j_input_shape_eem_%dTeV.root", mh, cem);
  else if (mode == 3) sprintf(rootFile,"%g/zh3l2j_input_shape_emm_%dTeV.root", mh, cem);
  else if (mode == 4) sprintf(rootFile,"%g/zh3l2j_input_shape_mmm_%dTeV.root", mh, cem);
  else sprintf(rootFile,"%g/zh3l2j_input_shape_%dTeV.root", mh, cem);
  
  TFile f_root(rootFile, "UPDATE");
											      
  // Prepare histograms
  char title[300];
												    
  sprintf(title,"histo_%s",plotName);
  TH1F* histo = new TH1F( title, " ", nbins, nbinlow, nbinhigh);
  histo->Sumw2();

  //Prepare useful things
  double weight = 1;
  double eventsPass = 0;
														  
  int nSample=sample.tree_->GetEntries();
  for (int i=0; i<nSample; ++i) {
														           
    if (i%100000 == 0 && verboseLevel > 0)
      printf("--- reading event %5d of %5d\n",i,nSample);
    sample.tree_->GetEntry(i);
    
    if(nsel == 1 && sample.processId_ != 24) continue;
    if(nsel == 7 && sample.processId_ != 24) continue;

    //Modes, 0 = all, 1 = eee, 2 = eem, 3 = emm, 4 = mmm
    if (mode == 1 && (abs(sample.lid1_)!= 11 || abs(sample.lid2_) != 11 || abs(sample.lid3_) != 11)) continue;
    if (mode == 2 && 
       ((abs(sample.lid1_)!= abs(sample.lid2_) && abs(sample.lid1_) != abs(sample.lid3_) && abs(sample.lid1_) == 11) ||
        (abs(sample.lid2_)!= abs(sample.lid1_) && abs(sample.lid2_) != abs(sample.lid3_) && abs(sample.lid2_) == 11) ||
	(abs(sample.lid3_)!= abs(sample.lid1_) && abs(sample.lid3_) != abs(sample.lid2_) && abs(sample.lid3_) == 11) ||
	(abs(sample.lid1_) == abs(sample.lid2_) && abs(sample.lid1_) == abs(sample.lid3_)))) continue;
    if (mode == 3 && 
       ((abs(sample.lid1_)!= abs(sample.lid2_) && abs(sample.lid1_) != abs(sample.lid3_) && abs(sample.lid1_) == 13) ||
        (abs(sample.lid2_)!= abs(sample.lid1_) && abs(sample.lid2_) != abs(sample.lid3_) && abs(sample.lid2_) == 13) ||
	(abs(sample.lid3_)!= abs(sample.lid1_) && abs(sample.lid3_) != abs(sample.lid2_) && abs(sample.lid3_) == 13) ||
	(abs(sample.lid1_) == abs(sample.lid2_) && abs(sample.lid1_) == abs(sample.lid3_)))) continue;
    if (mode == 4 && (abs(sample.lid1_)!= 13 || abs(sample.lid2_) != 13 || abs(sample.lid3_) != 13)) continue;
   
    				     
    weight = 1;
    if (!isData && sample.dstype_ != SmurfTree::data) weight = lumi*sample.scale1fb_*sample.sfWeightPU_*sample.sfWeightEff_*sample.sfWeightTrig_;    
      
    if (cem == 8 && nsel == 1 && mh == 118) weight *= ((0.472400*0.11800000)/(0.448300*0.14300000));  
    if (cem == 8 && nsel == 1 && mh == 122) weight *= ((0.425700*0.17000000)/(0.448300*0.14300000));  
    if (cem == 8 && nsel == 1 && mh == 124) weight *= ((0.404400*0.200000)/(0.394300*0.216000));    
    if (cem == 8 && nsel == 1 && mh == 126) weight *= ((0.384300*0.233000)/(0.394300*0.216000));   
    if (cem == 8 && nsel == 1 && mh == 128) weight *= ((0.365200*0.26800000)/(0.347300*0.30500000));  
    if (cem == 8 && nsel == 1 && mh == 127.5) weight *= ((0.387300*0.226200)/(0.394300*0.216000)); 
    
    if (cem == 7 && nsel == 1 && mh == 110) weight *= (0.02251917/0.0443547);
    if (cem == 7 && nsel == 1 && mh == 115) weight *= (0.03532622/0.0443547);
    if (cem == 7 && nsel == 1 && mh == 145) weight *= ((0.193000*0.600000)/(0.217200*0.501000));
    if (cem == 7 && nsel == 1 && mh == 125.7) weight *= ((0.215000*0.315800)/(0.226200*0.310100));
    
   
   //Three real leptons MC level
    if (!isData){
      bool isRealLepton = false;
      if((TMath::Abs(sample.lep1McId_) == 11 || TMath::Abs(sample.lep1McId_) == 13) &&
	 (TMath::Abs(sample.lep2McId_) == 11 || TMath::Abs(sample.lep2McId_) == 13) &&
	 (TMath::Abs(sample.lep3McId_) == 11 || TMath::Abs(sample.lep3McId_) == 13)) isRealLepton = true; 
      if (!isRealLepton && !isBackground) continue; //signal
      if (!isRealLepton && sample.dstype_ != SmurfTree::data) continue; //background
    }
																									         
    int ntype = sample.dstype_;
    
    //Check for fakes
    int nFake = 0;
    if(((sample.cuts_ & SmurfTree::Lep1LooseMuV2)  == SmurfTree::Lep1LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep2LooseMuV2)  == SmurfTree::Lep2LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep3LooseMuV2)  == SmurfTree::Lep3LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep1LooseEleV4) == SmurfTree::Lep1LooseEleV4) && (sample.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep2LooseEleV4) == SmurfTree::Lep2LooseEleV4) && (sample.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep3LooseEleV4) == SmurfTree::Lep3LooseEleV4) && (sample.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if (nFake !=0 && !isBackground) continue; 
    if (nFake !=0){ 
      ntype = 61;
      weight*= sample.sfWeightFR_*factor;
      //if (sample.dstype_ != SmurfTree::data) weight *=-1;
    }
    
    
    //2 same flavor, oppposite sign leptons + extra one
    if (sample.lid3_ == sample.lid2_ && sample.lid3_ == sample.lid1_) continue;
    if (sample.lid3_ == sample.lid2_ && fabs(sample.lid3_) != fabs(sample.lid1_)) continue;
    if (sample.lid3_ == sample.lid1_ && fabs(sample.lid3_) != fabs(sample.lid2_)) continue;
    if (sample.lid2_ == sample.lid1_ && fabs(sample.lid2_) != fabs(sample.lid3_)) continue;
    
    // At least 2 jets 
    if (sample.njets_ < 2) continue; 
    if (tau && (sample.jet1McId_ == 100 || sample.jet2McId_ == 100 || sample.jet3McId_ == 100 || sample.jet4McId_ == 100)) continue;

    //Make z-compatible pairs
    double m[3] = {-1, -1, -1};
    LorentzVector pair1, pair2, pair3;
    if (fabs(sample.lid1_) == fabs(sample.lid2_) && sample.lq1_*sample.lq2_ < 0){
      pair1 = sample.lep1_ + sample.lep2_ ;
      m[0] = pair1.M();
      if (m[0] < 12) continue;
    }
    if (fabs(sample.lid2_) == fabs(sample.lid3_) && sample.lq2_*sample.lq3_ < 0){
      pair2 = sample.lep2_ + sample.lep3_ ;
      m[1] = pair2.M();
      if (m[1] < 12) continue;
    }
    if (fabs(sample.lid1_) == fabs(sample.lid3_) && sample.lq1_*sample.lq3_ < 0){
      pair3 = sample.lep1_ + sample.lep3_ ;
      m[2] = pair3.M();
      if (m[2] < 12) continue;
    }
    if ( (m[0] > 0 && m[0] < 12) || (m[1] > 0 && m[1] < 12) || (m[2] > 0 && m[2] < 12)) continue;
    
    LorentzVector trelep = sample.lep1_ + sample.lep2_ + sample.lep3_;
    if (fabs(trelep.M() - mz) < 10) continue; 
																																																	         
    //Get the closest to the Z mass
    double min = TMath::Min(TMath::Min(fabs(mz -m[0]), fabs(mz-m[1])), TMath::Min(fabs(mz -m[0]), fabs(mz-m[2])));
    
    //Select the different things: Z pair, extra lepton, Higgs system
    LorentzVector pair, tlepton, pairjet;
    double mt = 0;
    // double dR = 0; //dR = fabs(ROOT::Math::VectorUtil::DeltaR(sample.lep1_ ,sample.lep2_)) etc
    if (min == fabs(mz - m[0])) {  pair = pair1; mt =  sample.mt3_; tlepton = sample.lep3_;} 
    else if (min == fabs(mz - m[1])){  pair = pair2;  mt =  sample.mt1_; tlepton = sample.lep1_;} 
    else if (min == fabs(mz - m[2])){  pair = pair3;  mt =  sample.mt2_; tlepton = sample.lep2_;} 
    pairjet = sample.jet1_+ sample.jet2_;
    LorentzVector metvector(sample.met_*cos(sample.metPhi_), sample.met_*sin(sample.metPhi_), 0, 0);
    LorentzVector higgsSystem = tlepton + metvector + sample.jet1_+ sample.jet2_;
    LorentzVector lm = tlepton + metvector;
    
    
    double hp[5];
    hp[0] = tlepton.Px() + sample.jet1_.Px()+ sample.jet2_.Px()+ metvector.Px();
    hp[1] = tlepton.Py() + sample.jet1_.Py()+ sample.jet2_.Py()+ metvector.Py();
    hp[2] = tlepton.Pz() + sample.jet1_.Pz()+ sample.jet2_.Pz()+ metvector.Pz();
    
    //Calculate p of the neutrino using Maria's code
    double metp = 0;
    // double otherSol = 0;
    double alpha=(mw*mw-mmu*mmu)/2/tlepton.P()+(tlepton.Px()*sample.met_*cos(sample.metPhi_)+tlepton.Py()*sample.met_*sin(sample.metPhi_))/tlepton.P();
    double A=tlepton.Pz()*tlepton.Pz()/tlepton.P()/tlepton.P()-1;
    double B=2*alpha*tlepton.Pz()/tlepton.P();
    double C=alpha*alpha-(sample.met_*cos(sample.metPhi_)*sample.met_*cos(sample.metPhi_) + sample.met_*sin(sample.metPhi_)*sample.met_*sin(sample.metPhi_));
    // bool isComplex = false;
    double tmproot = B*B - 4.0*A*C;
    if (tmproot<0) { 
      //isComplex= true;
      metp = - B/(2*A); 
      //otherSol = metp;
    } else {
      // isComplex = false;
      double tmpsol1 = (-B + TMath::Sqrt(tmproot))/(2.0*A);
      double tmpsol2 = (-B - TMath::Sqrt(tmproot))/(2.0*A);
      if (TMath::Abs(tmpsol1)<TMath::Abs(tmpsol2) ) {
	metp = tmpsol1; 
	//otherSol = tmpsol2; 
      } else { 
	metp = tmpsol2; 
	//otherSol = tmpsol1; 
      }
    }
    
    
    // hp[3] = tlepton.P() + sample.jet1_.P()+ sample.jet2_.P()+ metvector.P(); //crappy solution
    hp[3] = tlepton.P() + sample.jet1_.P()+ sample.jet2_.P()+ metp;
    hp[4] = tlepton.Pt() + sample.jet1_.Pt()+ sample.jet2_.Pt()+ sample.met_;
    
    double recomh  = hp[3]*hp[3]-hp[0]*hp[0]-hp[1]*hp[1]-hp[2]*hp[2]; if(recomh  > 0) recomh  = sqrt(recomh);else recomh   = 0.0;
    double recomth = hp[4]*hp[4]-hp[0]*hp[0]-hp[1]*hp[1]; if(recomth > 0) recomth = sqrt(recomth); else recomth  = 0.0;
    
    
    //Kinematic cuts
    if (pair.M() < (mz - separation)|| pair.M() > (mz + separation)) continue; 
    if (sample.met_ < metcut) continue;
    if (mt > mtcut) continue;
    if (pairjet.M() < (mw - separationjj) || pairjet.M() > (mw + separationjj)) continue;
    
    //double deltaPhi = fabs(DeltaPhi(pairjet.Phi(),tlepton.Phi()));
    double deltaPhi = fabs(DeltaPhi(pairjet.Phi(),lm.Phi()));
    if (deltaPhi > phicut) continue;
    
    
    if (nsel == 2 && ntype != 49) continue; //WZ
    if (nsel == 3 && ntype != 50) continue; //ZZ
    if (nsel == 4 && ntype != 59) continue; //VVV
    if (nsel == 5 && ntype != 61) continue; //fakes
    if (nsel == 0 && ntype != 0)  continue; //data
    
    
    
      histo->Fill(recomth, weight);
    //histo->Fill(higgsSystem.M(), weight);
    // histo->Fill(1, weight);
    eventsPass+= weight;
    
    
  }    
  
  cout << "[Info:] (" << plotName << ") " <<  eventsPass << " events pass, check " << histo->GetBinContent(1) << endl;
  
  
  f_root.Write();
  f_root.Close();
  
}
void computeAccSelZmmBinned(const TString conf,      // input file
                            const TString outputDir  // output directory
                           ) {
    gBenchmark->Start("computeAccSelZmmBinned");

    //--------------------------------------------------------------------------------------------------------------
    // Settings
    //==============================================================================================================

    const Double_t MASS_LOW   = 60;
    const Double_t MASS_HIGH  = 120;
    const Double_t PT_CUT     = 25;
    const Double_t ETA_CUT    = 2.1;
    const Double_t MUON_MASS  = 0.105658369;

    // efficiency files
    const TString dataHLTEffName_pos = "../Efficiency/May23_MuHLTEff_pos/analysis/eff.root";
    const TString dataHLTEffName_neg = "../Efficiency/May23_MuHLTEff_neg/analysis/eff.root";
    const TString zmmHLTEffName_pos  = "../Efficiency/Zmm_MuHLTEff_pos/analysis/eff.root";
    const TString zmmHLTEffName_neg  = "../Efficiency/Zmm_MuHLTEff_neg/analysis/eff.root";

    const TString dataSelEffName_pos = "../Efficiency/May23_MuSelEff_pos/analysis/eff.root";
    const TString dataSelEffName_neg = "../Efficiency/May23_MuSelEff_neg/analysis/eff.root";
    const TString zmmSelEffName_pos  = "../Efficiency/Zmm_MuSelEff_pos/analysis/eff.root";
    const TString zmmSelEffName_neg  = "../Efficiency/Zmm_MuSelEff_neg/analysis/eff.root";

    const TString dataTrkEffName_pos = "../Efficiency/May23_MuTrkEff_pos/analysis/eff.root";
    const TString dataTrkEffName_neg = "../Efficiency/May23_MuTrkEff_neg/analysis/eff.root";
    const TString zmmTrkEffName_pos  = "../Efficiency/Zmm_MuTrkEff_pos/analysis/eff.root";
    const TString zmmTrkEffName_neg  = "../Efficiency/Zmm_MuTrkEff_neg/analysis/eff.root";

    const TString dataStaEffName_pos = "../Efficiency/May23_MuStaEff_iso_pos/analysis/eff.root";
    const TString dataStaEffName_neg = "../Efficiency/May23_MuStaEff_iso_neg/analysis/eff.root";
    const TString zmmStaEffName_pos  = "../Efficiency/Zmm_MuStaEff_iso_pos/analysis/eff.root";
    const TString zmmStaEffName_neg  = "../Efficiency/Zmm_MuStaEff_iso_neg/analysis/eff.root";


    //--------------------------------------------------------------------------------------------------------------
    // Main analysis code
    //==============================================================================================================

    vector<TString> fnamev;  // file name per input file
    vector<TString> labelv;  // TLegend label per input file
    vector<Int_t>   colorv;  // plot color per input file
    vector<Int_t>   linev;   // plot line style per input file

    //
    // parse .conf file
    //
    ifstream ifs;
    ifs.open(conf.Data());
    assert(ifs.is_open());
    string line;
    while(getline(ifs,line)) {
        if(line[0]=='#') continue;

        string fname;
        Int_t color, linesty;
        stringstream ss(line);
        ss >> fname >> color >> linesty;
        string label = line.substr(line.find('@')+1);
        fnamev.push_back(fname);
        labelv.push_back(label);
        colorv.push_back(color);
        linev.push_back(linesty);
    }
    ifs.close();

    // Create output directory
    gSystem->mkdir(outputDir,kTRUE);


    //
    // HLT efficiency
    //
    cout << "Loading trigger efficiencies..." << endl;

    TFile *dataHLTEffFile_pos = new TFile(dataHLTEffName_pos);
    CEffUser2D dataHLTEff_pos;
    dataHLTEff_pos.loadEff((TH2D*)dataHLTEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataHLTEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataHLTEffFile_pos->Get("hErrhEtaPt"));

    TFile *dataHLTEffFile_neg = new TFile(dataHLTEffName_neg);
    CEffUser2D dataHLTEff_neg;
    dataHLTEff_neg.loadEff((TH2D*)dataHLTEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataHLTEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataHLTEffFile_neg->Get("hErrhEtaPt"));

    TFile *zmmHLTEffFile_pos = new TFile(zmmHLTEffName_pos);
    CEffUser2D zmmHLTEff_pos;
    zmmHLTEff_pos.loadEff((TH2D*)zmmHLTEffFile_pos->Get("hEffEtaPt"), (TH2D*)zmmHLTEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zmmHLTEffFile_pos->Get("hErrhEtaPt"));

    TFile *zmmHLTEffFile_neg = new TFile(zmmHLTEffName_neg);
    CEffUser2D zmmHLTEff_neg;
    zmmHLTEff_neg.loadEff((TH2D*)zmmHLTEffFile_neg->Get("hEffEtaPt"), (TH2D*)zmmHLTEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zmmHLTEffFile_neg->Get("hErrhEtaPt"));

    //
    // Selection efficiency
    //
    cout << "Loading selection efficiencies..." << endl;

    TFile *dataSelEffFile_pos = new TFile(dataSelEffName_pos);
    CEffUser2D dataSelEff_pos;
    dataSelEff_pos.loadEff((TH2D*)dataSelEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataSelEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataSelEffFile_pos->Get("hErrhEtaPt"));

    TFile *dataSelEffFile_neg = new TFile(dataSelEffName_neg);
    CEffUser2D dataSelEff_neg;
    dataSelEff_neg.loadEff((TH2D*)dataSelEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataSelEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataSelEffFile_neg->Get("hErrhEtaPt"));

    TFile *zmmSelEffFile_pos = new TFile(zmmSelEffName_pos);
    CEffUser2D zmmSelEff_pos;
    zmmSelEff_pos.loadEff((TH2D*)zmmSelEffFile_pos->Get("hEffEtaPt"), (TH2D*)zmmSelEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zmmSelEffFile_pos->Get("hErrhEtaPt"));

    TFile *zmmSelEffFile_neg = new TFile(zmmSelEffName_neg);
    CEffUser2D zmmSelEff_neg;
    zmmSelEff_neg.loadEff((TH2D*)zmmSelEffFile_neg->Get("hEffEtaPt"), (TH2D*)zmmSelEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zmmSelEffFile_neg->Get("hErrhEtaPt"));

    //
    // Standalone efficiency
    //
    cout << "Loading standalone efficiencies..." << endl;

    TFile *dataStaEffFile_pos = new TFile(dataStaEffName_pos);
    CEffUser2D dataStaEff_pos;
    dataStaEff_pos.loadEff((TH2D*)dataStaEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataStaEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataStaEffFile_pos->Get("hErrhEtaPt"));

    TFile *dataStaEffFile_neg = new TFile(dataStaEffName_neg);
    CEffUser2D dataStaEff_neg;
    dataStaEff_neg.loadEff((TH2D*)dataStaEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataStaEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataStaEffFile_neg->Get("hErrhEtaPt"));

    TFile *zmmStaEffFile_pos = new TFile(zmmStaEffName_pos);
    CEffUser2D zmmStaEff_pos;
    zmmStaEff_pos.loadEff((TH2D*)zmmStaEffFile_pos->Get("hEffEtaPt"), (TH2D*)zmmStaEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zmmStaEffFile_pos->Get("hErrhEtaPt"));

    TFile *zmmStaEffFile_neg = new TFile(zmmStaEffName_neg);
    CEffUser2D zmmStaEff_neg;
    zmmStaEff_neg.loadEff((TH2D*)zmmStaEffFile_neg->Get("hEffEtaPt"), (TH2D*)zmmStaEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zmmStaEffFile_neg->Get("hErrhEtaPt"));

    //
    // Tracker efficiency
    //
    cout << "Loading track efficiencies..." << endl;

    TFile *dataTrkEffFile_pos = new TFile(dataTrkEffName_pos);
    CEffUser2D dataTrkEff_pos;
    dataTrkEff_pos.loadEff((TH2D*)dataTrkEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataTrkEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataTrkEffFile_pos->Get("hErrhEtaPt"));

    TFile *dataTrkEffFile_neg = new TFile(dataTrkEffName_neg);
    CEffUser2D dataTrkEff_neg;
    dataTrkEff_neg.loadEff((TH2D*)dataTrkEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataTrkEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataTrkEffFile_neg->Get("hErrhEtaPt"));

    TFile *zmmTrkEffFile_pos = new TFile(zmmTrkEffName_pos);
    CEffUser2D zmmTrkEff_pos;
    zmmTrkEff_pos.loadEff((TH2D*)zmmTrkEffFile_pos->Get("hEffEtaPt"), (TH2D*)zmmTrkEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zmmTrkEffFile_pos->Get("hErrhEtaPt"));

    TFile *zmmTrkEffFile_neg = new TFile(zmmTrkEffName_neg);
    CEffUser2D zmmTrkEff_neg;
    zmmTrkEff_neg.loadEff((TH2D*)zmmTrkEffFile_neg->Get("hEffEtaPt"), (TH2D*)zmmTrkEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zmmTrkEffFile_neg->Get("hErrhEtaPt"));


    // Data structures to store info from TTrees
    mithep::TEventInfo *info = new mithep::TEventInfo();
    mithep::TGenInfo   *gen  = new mithep::TGenInfo();
    TClonesArray *muonArr    = new TClonesArray("mithep::TMuon");

    TFile *infile=0;
    TTree *eventTree=0;

    // Variables to store acceptances and uncertainties (per input file)
    vector<Double_t> nEvtsv, nSelv, nSelCorrv;
    vector<Double_t> accv, accCorrv;
    vector<Double_t> accErrv, accCorrErrv;

    //
    // loop through files
    //
    for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {

        // Read input file and get the TTrees
        cout << "Processing " << fnamev[ifile] << " ..." << endl;
        infile = new TFile(fnamev[ifile]);
        assert(infile);

        eventTree = (TTree*)infile->Get("Events");
        assert(eventTree);
        eventTree->SetBranchAddress("Info", &info);
        TBranch *infoBr = eventTree->GetBranch("Info");
        eventTree->SetBranchAddress("Gen",  &gen);
        TBranch *genBr  = eventTree->GetBranch("Gen");
        eventTree->SetBranchAddress("Muon", &muonArr);
        TBranch *muonBr = eventTree->GetBranch("Muon");

        nEvtsv.push_back(0);
        nSelv.push_back(0);
        nSelCorrv.push_back(0);

        //
        // loop over events
        //
        for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
            genBr->GetEntry(ientry);
            if(gen->vmass<MASS_LOW || gen->vmass>MASS_HIGH) continue;

            infoBr->GetEntry(ientry);

            Double_t weight=1;
            nEvtsv[ifile]+=weight;

            // trigger requirement
            ULong_t trigger = kHLT_Mu15_eta2p1;
            ULong_t trigObj = kHLT_Mu15_eta2p1_MuObj;
            if(!(info->triggerBits & trigger)) continue;

            // good vertex requirement
            if(!(info->hasGoodPV)) continue;

            muonArr->Clear();
            muonBr->GetEntry(ientry);
            for(Int_t i1=0; i1<muonArr->GetEntriesFast(); i1++) {
                const mithep::TMuon *mu1 = (mithep::TMuon*)((*muonArr)[i1]);

                if(mu1->pt	  < PT_CUT)  continue;  // lepton pT cut
                if(fabs(mu1->eta) > ETA_CUT) continue;  // lepton |eta| cut
                if(!passMuonID(mu1))	     continue;  // lepton selection

                LorentzVector vMu1(mu1->pt, mu1->eta, mu1->phi, MUON_MASS);

                for(Int_t i2=i1+1; i2<muonArr->GetEntriesFast(); i2++) {
                    const mithep::TMuon *mu2 = (mithep::TMuon*)((*muonArr)[i2]);

                    if(mu1->q == mu2->q)	       continue;  // opposite charge requirement
                    if(mu2->pt        < PT_CUT)  continue;  // lepton pT cut
                    if(fabs(mu2->eta) > ETA_CUT) continue;  // lepton |eta| cut
                    if(!passMuonID(mu2))	       continue;  // lepton selection

                    LorentzVector vMu2(mu2->pt, mu2->eta, mu2->phi, MUON_MASS);

                    // trigger match
                    if(!(mu1->hltMatchBits & trigObj) && !(mu2->hltMatchBits & trigObj)) continue;

                    // mass window
                    LorentzVector vDilep = vMu1 + vMu2;
                    if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;


                    /******** We have a Z candidate! HURRAY! ********/

                    Double_t effdata, effmc;
                    Double_t corr=1;

                    effdata=1;
                    effmc=1;
                    if(mu1->q>0) {
                        effdata *= (1.-dataHLTEff_pos.getEff(mu1->eta, mu1->pt));
                        effmc   *= (1.-zmmHLTEff_pos.getEff(mu1->eta, mu1->pt));
                    } else {
                        effdata *= (1.-dataHLTEff_neg.getEff(mu1->eta, mu1->pt));
                        effmc   *= (1.-zmmHLTEff_neg.getEff(mu1->eta, mu1->pt));
                    }
                    if(mu2->q>0) {
                        effdata *= (1.-dataHLTEff_pos.getEff(mu2->eta, mu2->pt));
                        effmc   *= (1.-zmmHLTEff_pos.getEff(mu2->eta, mu2->pt));
                    } else {
                        effdata *= (1.-dataHLTEff_neg.getEff(mu2->eta, mu2->pt));
                        effmc   *= (1.-zmmHLTEff_neg.getEff(mu2->eta, mu2->pt));
                    }
                    effdata = 1.-effdata;
                    effmc   = 1.-effmc;
                    corr *= effdata/effmc;

                    effdata=1;
                    effmc=1;
                    if(mu1->q>0) {
                        effdata *= dataSelEff_pos.getEff(mu1->eta, mu1->pt);
                        effmc   *= zmmSelEff_pos.getEff(mu1->eta, mu1->pt);
                    } else {
                        effdata *= dataSelEff_neg.getEff(mu1->eta, mu1->pt);
                        effmc   *= zmmSelEff_neg.getEff(mu1->eta, mu1->pt);
                    }
                    if(mu2->q>0) {
                        effdata *= dataSelEff_pos.getEff(mu2->eta, mu2->pt);
                        effmc   *= zmmSelEff_pos.getEff(mu2->eta, mu2->pt);
                    } else {
                        effdata *= dataSelEff_neg.getEff(mu2->eta, mu2->pt);
                        effmc   *= zmmSelEff_neg.getEff(mu2->eta, mu2->pt);
                    }
                    corr *= effdata/effmc;

                    effdata=1;
                    effmc=1;
                    if(mu1->q>0) {
                        effdata *= dataStaEff_pos.getEff(fabs(mu1->eta), mu1->pt);
                        effmc   *= zmmStaEff_pos.getEff(fabs(mu1->eta), mu1->pt);
                    } else {
                        effdata *= dataStaEff_neg.getEff(fabs(mu1->eta), mu1->pt);
                        effmc   *= zmmStaEff_neg.getEff(fabs(mu1->eta), mu1->pt);
                    }
                    if(mu2->q>0) {
                        effdata *= dataStaEff_pos.getEff(fabs(mu2->eta), mu2->pt);
                        effmc   *= zmmStaEff_pos.getEff(fabs(mu2->eta), mu2->pt);
                    } else {
                        effdata *= dataStaEff_neg.getEff(fabs(mu2->eta), mu2->pt);
                        effmc   *= zmmStaEff_neg.getEff(fabs(mu2->eta), mu2->pt);
                    }
                    corr *= effdata/effmc;

                    effdata=1;
                    effmc=1;
                    if(mu1->q>0) {
                        effdata *= dataTrkEff_pos.getEff(fabs(mu1->eta), mu1->pt);
                        effmc   *= zmmTrkEff_pos.getEff(fabs(mu1->eta), mu1->pt);
                    } else {
                        effdata *= dataTrkEff_neg.getEff(fabs(mu1->eta), mu1->pt);
                        effmc   *= zmmTrkEff_neg.getEff(fabs(mu1->eta), mu1->pt);
                    }
                    if(mu2->q>0) {
                        effdata *= dataTrkEff_pos.getEff(fabs(mu2->eta), mu2->pt);
                        effmc   *= zmmTrkEff_pos.getEff(fabs(mu2->eta), mu2->pt);
                    } else {
                        effdata *= dataTrkEff_neg.getEff(fabs(mu2->eta), mu2->pt);
                        effmc   *= zmmTrkEff_neg.getEff(fabs(mu2->eta), mu2->pt);
                    }
                    corr *= effdata/effmc;

                    nSelv[ifile]    +=weight;
                    nSelCorrv[ifile]+=weight*corr;
                }
            }
        }

        // compute acceptances
        accv.push_back(nSelv[ifile]/nEvtsv[ifile]);
        accErrv.push_back(accv[ifile]*sqrt((1.-accv[ifile])/nEvtsv[ifile]));
        accCorrv.push_back(nSelCorrv[ifile]/nEvtsv[ifile]);
        accCorrErrv.push_back(accCorrv[ifile]*sqrt((1.-accCorrv[ifile])/nEvtsv[ifile]));

        delete infile;
        infile=0, eventTree=0;
    }
    delete info;
    delete gen;
    delete muonArr;


    //--------------------------------------------------------------------------------------------------------------
    // Output
    //==============================================================================================================
    cout << "*" << endl;
    cout << "* SUMMARY" << endl;
    cout << "*--------------------------------------------------" << endl;
    cout << " Z -> mu mu" << endl;
    cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
    cout << "  pT > " << PT_CUT << endl;
    cout << "  |eta| < " << ETA_CUT << endl;
    cout << endl;

    for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {
        cout << "   ================================================" << endl;
        cout << "    Label: " << labelv[ifile] << endl;
        cout << "     File: " << fnamev[ifile] << endl;
        cout << endl;
        cout << "    *** Acceptance ***" << endl;
        cout << "          nominal: " << setw(12) << nSelv[ifile]   << " / " << nEvtsv[ifile] << " = " << accv[ifile]   << " +/- " << accErrv[ifile] << endl;
        cout << "     SF corrected: " << accCorrv[ifile] << " +/- " << accCorrErrv[ifile] << endl;
        cout << endl;
    }

    char txtfname[100];
    sprintf(txtfname,"%s/binned.txt",outputDir.Data());
    ofstream txtfile;
    txtfile.open(txtfname);
    txtfile << "*" << endl;
    txtfile << "* SUMMARY" << endl;
    txtfile << "*--------------------------------------------------" << endl;
    txtfile << " Z -> mu mu" << endl;
    txtfile << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
    txtfile << "  pT > " << PT_CUT << endl;
    txtfile << "  |eta| < " << ETA_CUT << endl;
    txtfile << endl;

    for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {
        txtfile << "   ================================================" << endl;
        txtfile << "    Label: " << labelv[ifile] << endl;
        txtfile << "     File: " << fnamev[ifile] << endl;
        txtfile << endl;
        txtfile << "    *** Acceptance ***" << endl;
        txtfile << "          nominal: " << setw(12) << nSelv[ifile]   << " / " << nEvtsv[ifile] << " = " << accv[ifile]   << " +/- " << accErrv[ifile] << endl;
        txtfile << "     SF corrected: " << accCorrv[ifile] << " +/- " << accCorrErrv[ifile] << endl;
        txtfile << endl;
    }
    txtfile.close();

    cout << endl;
    cout << "  <> Output saved in " << outputDir << "/" << endl;
    cout << endl;

    gBenchmark->Show("computeAccSelZmmBinned");
}
int ScanChain( TChain* chain, bool fast = true, int nEvents = -1, string skimFilePrefix = "test") {

  int currentrun = -1;
  bool DCSonly = false;//KEEP THIS FALSE
  // Benchmark
  TBenchmark *bmark = new TBenchmark();
  bmark->Start("benchmark");

  // Example Histograms
  TDirectory *rootdir = gDirectory->GetDirectory("Rint:");

  map<string, TH1F*> histos;
  vector<string> histonames; histonames.clear();
  vector<int> hbins; hbins.clear();
  vector<float> hlow; hlow.clear();
  vector<float> hup; hup.clear();
  histonames.push_back("Mll");                       hbins.push_back(75); hlow.push_back(  15.); hup.push_back(390);
  histonames.push_back("Mud0");                      hbins.push_back(40); hlow.push_back( -0.4); hup.push_back(0.4);
  histonames.push_back("MudZ");                      hbins.push_back(40); hlow.push_back(  -1.); hup.push_back(1. );
  histonames.push_back("MuIP3d");                    hbins.push_back(40); hlow.push_back( -0.5); hup.push_back(0.5);
  histonames.push_back("MuRelIso03");                hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso03EA");              hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso03DB");              hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuMiniIsoEA");               hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuMiniIsoDB");               hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso04");                hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuAnnulus04");               hbins.push_back(25); hlow.push_back(   0.); hup.push_back(1. );
  histonames.push_back("MuRelIso03_MT30");           hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso03EA_MT30");         hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso03DB_MT30");         hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuMiniIsoEA_MT30");          hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuMiniIsoDB_MT30");          hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuRelIso04_MT30");           hbins.push_back(50); hlow.push_back(   0.); hup.push_back(2. );
  histonames.push_back("MuAnnulus04_MT30");          hbins.push_back(25); hlow.push_back(   0.); hup.push_back(1. );
  histonames.push_back("MuID");                      hbins.push_back( 7); hlow.push_back(  -1.); hup.push_back(6. );
  histonames.push_back("MuvalidFraction");           hbins.push_back(25); hlow.push_back(   0.); hup.push_back(1. );
  histonames.push_back("MuisPF");                    hbins.push_back( 5); hlow.push_back(  -1.); hup.push_back(4. );
  histonames.push_back("Mugfit_normchi2");           hbins.push_back(40); hlow.push_back(   0.); hup.push_back(20.);
  histonames.push_back("Mugfit_validSTAHits");       hbins.push_back(10); hlow.push_back(   0.); hup.push_back(10.);
  histonames.push_back("MunumberOfMatchedStations"); hbins.push_back(10); hlow.push_back(   0.); hup.push_back(10.);
  histonames.push_back("Munlayers");                 hbins.push_back(20); hlow.push_back(   0.); hup.push_back(20.);
  histonames.push_back("Muchi2LocalPosition");       hbins.push_back(40); hlow.push_back(   0.); hup.push_back(40.);
  histonames.push_back("MutrkKink");                 hbins.push_back(50); hlow.push_back(   0.); hup.push_back(50.);
  histonames.push_back("MusegmCompatibility");       hbins.push_back(35); hlow.push_back(   0.); hup.push_back(1.4);
  histonames.push_back("MuvalidPixelHits");          hbins.push_back( 5); hlow.push_back(   0.); hup.push_back(5. );
  histonames.push_back("MuPt");                      hbins.push_back(30); hlow.push_back(   0.); hup.push_back(600);
  histonames.push_back("MuEta");                     hbins.push_back(60); hlow.push_back(   3.); hup.push_back(3. );
  histonames.push_back("MuPhi");                     hbins.push_back(32); hlow.push_back( -3.2); hup.push_back(3.2);
  histonames.push_back("MuCharge");                  hbins.push_back( 6); hlow.push_back(  -2.); hup.push_back(4. );
  histonames.push_back("MT");                        hbins.push_back(45); hlow.push_back(   0.); hup.push_back(450);
  histonames.push_back("ZPt");                       hbins.push_back(30); hlow.push_back(   0.); hup.push_back(600);
  histonames.push_back("Z_Pt");                      hbins.push_back(30); hlow.push_back(   0.); hup.push_back(600);
  histonames.push_back("ZEta");                      hbins.push_back(50); hlow.push_back(  -5.); hup.push_back(5. );
  histonames.push_back("ZPhi");                      hbins.push_back(32); hlow.push_back( -3.2); hup.push_back(3.2);
  histonames.push_back("DPhill");                    hbins.push_back(32); hlow.push_back(   0.); hup.push_back(3.2);
  histonames.push_back("DEtall");                    hbins.push_back(50); hlow.push_back(   0.); hup.push_back(5. );
  histonames.push_back("DRll");                      hbins.push_back(32); hlow.push_back(   0.); hup.push_back(6.4);
  histonames.push_back("MyMuPt");                      hbins.push_back(30); hlow.push_back(   0.); hup.push_back(600);
  histonames.push_back("MyMuEta");                     hbins.push_back(60); hlow.push_back(   3.); hup.push_back(3. );
  histonames.push_back("MyMuPhi");                     hbins.push_back(32); hlow.push_back( -3.2); hup.push_back(3.2);
  histonames.push_back("MyMuCharge");                  hbins.push_back( 6); hlow.push_back(  -2.); hup.push_back(4. );
  histonames.push_back("MET");                      hbins.push_back(40); hlow.push_back(   0.); hup.push_back(200);
  histonames.push_back("HT");                      hbins.push_back(40); hlow.push_back(   0.); hup.push_back(400);
  histonames.push_back("NJets");                      hbins.push_back(10); hlow.push_back(   0.); hup.push_back(10);
  histonames.push_back("NBJets");                      hbins.push_back(5); hlow.push_back(   0.); hup.push_back(5);
	      
  for(unsigned int i = 0; i<histonames.size(); ++i){
    int nbins = hbins[i];
    string mapname;
    for(unsigned int j = 0; j<11; ++j){
      string prefix = "";
      if(j==1) prefix = "NJ0_";
      else if(j==2) prefix = "NJ1_";
      else if(j==3) prefix = "NJ2_";
      else if(j==4) prefix = "NJge3_";
      else if(j==5) prefix = "NB0_";
      else if(j==6) prefix = "NBge1_";
      else if(j==7) prefix = "HTge100_";
      else if(j==8) prefix = "METge50_";
      else if(j==9) prefix = "METge25_";
      else if(j==10) prefix = "HTge150_";
      mapname = prefix + histonames[i]+"_"+skimFilePrefix;
      //cout << mapname << endl;
      if(histos.count(mapname) == 0 ) histos[mapname] = new TH1F(mapname.c_str(), "", nbins, hlow[i], hup[i]);
      histos[mapname]->Sumw2(); histos[mapname]->SetDirectory(rootdir);
    }
  }

  // Loop over events to Analyze
  unsigned int nEventsTotal = 0;
  unsigned int nEventsChain = chain->GetEntries();
  if( nEvents >= 0 ) nEventsChain = nEvents;
  TObjArray *listOfFiles = chain->GetListOfFiles();
  TIter fileIter(listOfFiles);
  TFile *currentFile = 0;

  //load json file
  const char* json_fileDCS = "myjsons/json_DCSONLY_Run2015B_snt.txt";
  const char* json_file = "myjsons/json_Golden_246908-251883_snt.txt";
  if(DCSonly) set_goodrun_file(json_fileDCS);
  else        set_goodrun_file(json_file);

  // File Loop
  while ( (currentFile = (TFile*)fileIter.Next()) ) {

    // Get File Content
    TFile *file = new TFile( currentFile->GetTitle() );
    TTree *tree = (TTree*)file->Get("t");
    if(fast) TTreeCache::SetLearnEntries(10);
    if(fast) tree->SetCacheSize(128*1024*1024);
    cms3.Init(tree);

    int nleps = 1;
    myevt p;//previous event
    myevt c;//current event
    resetEvent(p);
    resetEvent(c);
    vector<myevt> mu; mu.clear();

    // Loop over Events in current file
    if( nEventsTotal >= nEventsChain ) continue;
    unsigned int nEventsTree = tree->GetEntriesFast();
    for( unsigned int event = 0; event < nEventsTree; ++event) {
    
      // Get Event Content
      if( nEventsTotal >= nEventsChain ) continue;
      if(fast) tree->LoadTree(event);
      cms3.GetEntry(event);
      ++nEventsTotal;
    
      // Progress
      CMS3::progress(nEventsTotal, nEventsChain );
      if(evt_isRealData()&& !goodrun(evt_run(), evt_lumiBlock()) ) continue;

      //load my struct
      c.evt_pfmet   = evt_pfmet();
      c.evt_pfmetPhi   = evt_pfmetPhi();
      c.evt_trackmet   = evt_trackmet();
      c.evt_trackmetPhi   = evt_trackmetPhi();
      c.evt_pfsumet   = evt_pfsumet();
      c.evt_pfmetSig   = evt_pfmetSig();
      c.evt_event   = evt_event();
      c.evt_lumiBlock   = evt_lumiBlock();
      c.evt_run   = evt_run();
      c.filt_csc   = filt_csc();
      c.filt_hbhe   = filt_hbhe();
      c.filt_hcallaser   = filt_hcallaser();
      c.filt_ecaltp   = filt_ecaltp();
      c.filt_trkfail   = filt_trkfail();
      c.filt_eebadsc   = filt_eebadsc();
      c.evt_isRealData   = evt_isRealData(); 
      c.scale1fb   = scale1fb();
      c.evt_xsec_incl   = evt_xsec_incl();
      c.evt_kfactor   = evt_kfactor();
      c.gen_met   = gen_met();
      c.gen_metPhi   = gen_metPhi();
      c.njets   = njets();
      c.ht   = ht();
      c.jets  = jets();
      c.jets_disc  = jets_disc();
      c.sample  = sample();
      c.nvtx   = nvtx();
      c.HLT_Mu8_TrkIsoVVL   = HLT_Mu8_TrkIsoVVL();
      c.HLT_Mu17_TrkIsoVVL   = HLT_Mu17_TrkIsoVVL();
      c.HLT_Mu24_TrkIsoVVL   = HLT_Mu24_TrkIsoVVL();
      c.HLT_Mu34_TrkIsoVVL   = HLT_Mu34_TrkIsoVVL();
      c.HLT_Mu8   = HLT_Mu8();
      c.HLT_Mu17   = HLT_Mu17();
      c.HLT_Mu24   = HLT_Mu24();
      c.HLT_Mu34   = HLT_Mu34();
      c.HLT_Mu10_CentralPFJet30_BTagCSV0p5PF   = HLT_Mu10_CentralPFJet30_BTagCSV0p5PF();
      c.HLT_IsoMu24_eta2p1   = HLT_IsoMu24_eta2p1();
      c.HLT_IsoTkMu24_eta2p1   = HLT_IsoTkMu24_eta2p1(); 
      c.HLT_IsoMu27   = HLT_IsoMu27();
      c.HLT_IsoTkMu27   = HLT_IsoTkMu27(); 
      c.HLT_Mu45_eta2p1   = HLT_Mu45_eta2p1(); 
      c.HLT_Mu50   = HLT_Mu50();
      c.HLT_Ele8_CaloIdM_TrackIdM_PFJet30   = HLT_Ele8_CaloIdM_TrackIdM_PFJet30();
      c.HLT_Ele12_CaloIdM_TrackIdM_PFJet30   = HLT_Ele12_CaloIdM_TrackIdM_PFJet30();
      c.HLT_Ele18_CaloIdM_TrackIdM_PFJet30   = HLT_Ele18_CaloIdM_TrackIdM_PFJet30();
      c.HLT_Ele23_CaloIdM_TrackIdM_PFJet30   = HLT_Ele23_CaloIdM_TrackIdM_PFJet30();
      c.HLT_Ele33_CaloIdM_TrackIdM_PFJet30   = HLT_Ele33_CaloIdM_TrackIdM_PFJet30();
      c.HLT_Ele12_CaloIdL_TrackIdL_IsoVL_PFJet30   = HLT_Ele12_CaloIdL_TrackIdL_IsoVL_PFJet30();
      c.HLT_Ele18_CaloIdL_TrackIdL_IsoVL_PFJet30   = HLT_Ele18_CaloIdL_TrackIdL_IsoVL_PFJet30();
      c.HLT_Ele23_CaloIdL_TrackIdL_IsoVL_PFJet30   = HLT_Ele23_CaloIdL_TrackIdL_IsoVL_PFJet30();
      c.HLT_Ele33_CaloIdL_TrackIdL_IsoVL_PFJet30   = HLT_Ele33_CaloIdL_TrackIdL_IsoVL_PFJet30();
      c.HLT_Ele10_CaloIdM_TrackIdM_CentralPFJet30_BTagCSV0p5PF   = HLT_Ele10_CaloIdM_TrackIdM_CentralPFJet30_BTagCSV0p5PF();
      c.HLT_Ele27_eta2p1_WP75_Gsf   = HLT_Ele27_eta2p1_WP75_Gsf();
      c.HLT_Ele27_WP85_Gsf   = HLT_Ele27_WP85_Gsf();
      c.HLT_Ele27_eta2p1_WPLoose_Gsf   = HLT_Ele27_eta2p1_WPLoose_Gsf();
      c.HLT_Ele27_eta2p1_WPTight_Gsf   = HLT_Ele27_eta2p1_WPTight_Gsf();
      c.HLT_Ele32_eta2p1_WP75_Gsf   = HLT_Ele32_eta2p1_WP75_Gsf();
      c.HLT_Ele32_eta2p1_WPLoose_Gsf   = HLT_Ele32_eta2p1_WPLoose_Gsf();
      c.HLT_Ele32_eta2p1_WPTight_Gsf   = HLT_Ele32_eta2p1_WPTight_Gsf();
      c.HLT_Mu8_Ele8_CaloIdM_TrackIdM_Mass8_PFHT300   = HLT_Mu8_Ele8_CaloIdM_TrackIdM_Mass8_PFHT300();
      c.HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL   = HLT_Mu23_TrkIsoVVL_Ele12_CaloIdL_TrackIdL_IsoVL();
      c.HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL   = HLT_Mu8_TrkIsoVVL_Ele23_CaloIdL_TrackIdL_IsoVL();
      c.HLT_DoubleMu8_Mass8_PFHT300   = HLT_DoubleMu8_Mass8_PFHT300();
      c.HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL   = HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL();
      c.HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL   = HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL(); 
      c.HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ   = HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ();
      c.HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_DZ   = HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_DZ(); 
      c.HLT_DoubleEle8_CaloIdM_TrackIdM_Mass8_PFHT300   = HLT_DoubleEle8_CaloIdM_TrackIdM_Mass8_PFHT300();
      c.HLT_Ele23_Ele12_CaloIdL_TrackIdL_IsoVL_DZ   = HLT_Ele23_Ele12_CaloIdL_TrackIdL_IsoVL_DZ();
      c.pid_PFMuon   = pid_PFMuon();
      c.gfit_chi2   = gfit_chi2();
      c.gfit_ndof   = gfit_ndof();
      c.gfit_validSTAHits   = gfit_validSTAHits();
      c.numberOfMatchedStations   = numberOfMatchedStations();
      c.validPixelHits   = validPixelHits();
      c.nlayers   = nlayers();
      c.chi2LocalPosition   = chi2LocalPosition();
      c.trkKink   = trkKink();
      c.validHits   = validHits(); 
      c.lostHits   = lostHits();
      c.exp_outerlayers   = exp_outerlayers();
      c.segmCompatibility   = segmCompatibility();
      c.exp_innerlayers   = exp_innerlayers();
      c.passes_POG_vetoID   = passes_POG_vetoID();
      c.passes_POG_looseID   = passes_POG_looseID();
      c.passes_POG_mediumID   = passes_POG_mediumID();
      c.passes_POG_tightID   = passes_POG_tightID();
      c.ip3d   = ip3d();
      c.ip3derr   = ip3derr(); 
      c.type   = type();
      c.mt   = mt();
      c.ptrelv0   = ptrelv0();
      c.ptrelv1   = ptrelv1();
      c.miniiso   = miniiso();
      c.miniisoDB   = miniisoDB(); 
      c.reliso04   = reliso04();
      c.annulus04   = annulus04();
      c.p4  = p4();
      c.tag_p4  = tag_p4();
      c.dilep_p4  = dilep_p4();
      c.mc_p4  = mc_p4();
      c.mc_motherp4  = mc_motherp4();
      c.id   = id();
      c.idx   = idx();
      c.dxyPV   = dxyPV();
      c.dZ   = dZ();
      c.dxyPV_err   = dxyPV_err();
      c.motherID   = motherID();
      c.mc_id   = mc_id();
      c.RelIso03   = RelIso03();
      c.RelIso03EA   = RelIso03EA();
      c.RelIso03DB   = RelIso03DB();
      c.dilep_mass   = dilep_mass();
      c.dilep_p4   = dilep_p4();
      c.passes_SS_tight_noiso_v3 = passes_SS_tight_noiso_v3();
      c.passes_SS_fo_noiso_v3 = passes_SS_fo_noiso_v3();
      c.passes_POG_looseID = passLooseID(c);
      c.passes_POG_mediumID = passMediumID(c);
      c.passes_POG_tightID = passTightID(c);
     

      float weight = p.scale1fb*0.0403;
      if(skimFilePrefix=="DY_M10_50ns") weight *= 1.11;
      if(p.evt_isRealData) weight = 1.;
      if((skimFilePrefix=="SingleMuon"||skimFilePrefix=="DoubleMuon")&&fabs(weight-1.)>=0.001) cout <<__LINE__<< endl;
      // Analysis Code

      if(sameEvent(p,c)) { ++nleps; }


      if(((!sameEvent(p,c))||(nEventsChain==nEventsTotal)) && mu.size()>0) {

	int nbs = 0;
	int njs = 0;
	float HT = 0;
	double muovind[mu.size()];
	for(unsigned int i = 0; i<mu.size();++i){
	  muovind[i] = -1;
	  float minDR = 9999;
	  if(mu[i].jets.size()!=p.jets.size()) cout << "ERROR " << mu[i].jets.size() << " " << p.jets.size() << endl;
	  for(unsigned int j = 0; j<p.jets.size();++j){
	    float myDR = deltaR(mu[i].p4,p.jets[j]);
	    if(myDR<0.4 && myDR<minDR){
	      minDR = myDR;
	      muovind[i] = j;
	    }
	  }
	}
	for(unsigned int i = 0; i<p.jets.size();++i){
	  bool isoverlap = false;
	  for(unsigned int j = 0; j<mu.size();++j){
	    if(muovind[j]==i){
	      isoverlap = true;
	      break;
	    }
	  }
	  if(isoverlap) continue;
	  if(p.jets[i].Pt()<30) continue;
	  if(fabs(p.jets[i].Eta()>2.4)) continue;
	  ++njs;
	  HT += p.jets[i].Pt();
	  if(p.jets_disc[i]>0.890) ++nbs;
	}
      
	bool triggerbool2mu = false;
	bool triggerbool1mu = false;
	//now I reached full event!
	if(mu.size()>1) mu = sortbypt(mu);
	for(unsigned int i = 0; i<mu.size();++i){
	  if(mu[i].evt_isRealData) triggerbool2mu = triggerbool2mu || mu[i].HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ || mu[i].HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_DZ;
	  if(mu[i].evt_isRealData) triggerbool1mu = triggerbool1mu || mu[i].HLT_IsoMu24_eta2p1 || mu[i].HLT_IsoTkMu24_eta2p1 || mu[i].HLT_IsoMu27 || mu[i].HLT_IsoTkMu27 || mu[i].HLT_IsoMu20 || mu[i].HLT_IsoMu20;
	}
	if(!p.evt_isRealData){ triggerbool2mu = true; triggerbool1mu = true;}
	if(mu.size()==2){
	  triggerbool2mu = triggerbool2mu&&mu[0].p4.Pt()>20.&&fabs(mu[0].p4.Eta())<2.1&&mu[0].p4.Pt()>20.&&fabs(mu[0].p4.Eta())<2.1;//two muons passing nominal trigger w/o iso and dZ
	  triggerbool1mu = triggerbool1mu&&((mu[0].p4.Pt()>30.&&fabs(mu[0].p4.Eta())<2.1)||(mu[1].p4.Pt()>30.&&fabs(mu[1].p4.Eta())<2.1));//one muon passing nominal trigger w/o iso
	  LorentzVector Z = (mu[0].p4+mu[1].p4);
	  if((triggerbool1mu||triggerbool2mu)&& mu[0].passes_POG_tightID&&mu[1].passes_POG_tightID&&mu[0].miniisoDB<0.2&&mu[1].miniisoDB<0.2&&
	      fabs(mu[0].dZ)<0.1&&fabs(mu[1].dZ)<0.1&&fabs(mu[0].dxyPV)<0.02&&fabs(mu[1].dxyPV)<0.02){
	    //cout << "have a dilepton event: Z pt " << Z.Pt() << " and mass " << Z.M() << endl;
	    histos["Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(njs==0) histos["NJ0_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    else if(njs==1) histos["NJ1_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    else if(njs==2) histos["NJ2_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    else histos["NJge3_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(nbs==0)  histos["NB0_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    else  histos["NBge1_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(HT>100.) histos["HTge100_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(HT>150.) histos["HTge150_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(p.evt_pfmet>50.) histos["METge50_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(p.evt_pfmet>25.) histos["METge25_Mll_"+skimFilePrefix]->Fill(Z.M(),weight);
	    if(Z.M()>75.&&Z.M()<105){
	      histos["ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
	      histos["ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
	      histos["ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
	      histos["DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
	      histos["DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
	      histos["DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      histos["MET_"+skimFilePrefix]->Fill(p.evt_pfmet,weight);
	      histos["HT_"+skimFilePrefix]->Fill(HT,weight);
	      histos["NJets_"+skimFilePrefix]->Fill(njs,weight);
	      histos["NBJets_"+skimFilePrefix]->Fill(nbs,weight);
	      if(njs==0){
		histos["NJ0_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NJ0_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NJ0_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NJ0_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NJ0_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NJ0_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } else if(njs==1){
		histos["NJ1_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NJ1_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NJ1_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NJ1_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NJ1_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NJ1_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } else if(njs==2){
		histos["NJ2_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NJ2_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NJ2_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NJ2_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NJ2_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NJ2_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } else {
		histos["NJge3_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NJge3_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NJge3_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NJge3_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NJge3_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NJge3_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } if(nbs==0){
		histos["NB0_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NB0_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NB0_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NB0_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NB0_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NB0_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } else {
		histos["NBge1_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["NBge1_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["NBge1_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["NBge1_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["NBge1_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["NBge1_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } if(HT>100.){
		histos["HTge100_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["HTge100_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["HTge100_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["HTge100_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["HTge100_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["HTge100_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } if(HT>150.){
		histos["HTge150_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["HTge150_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["HTge150_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["HTge150_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["HTge150_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["HTge150_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } if(p.evt_pfmet>50.){
		histos["METge50_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["METge50_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["METge50_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["METge50_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["METge50_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["METge50_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);
	      } if(p.evt_pfmet>25.){
		histos["METge25_ZPt_"+skimFilePrefix]->Fill(Z.Pt(),weight);
		histos["METge25_ZEta_"+skimFilePrefix]->Fill(Z.Eta(),weight);
		histos["METge25_ZPhi_"+skimFilePrefix]->Fill(Z.Phi(),weight);
		histos["METge25_DPhill_"+skimFilePrefix]->Fill(getdphi(mu[0].p4.Phi(),mu[1].p4.Phi()),weight);
		histos["METge25_DEtall_"+skimFilePrefix]->Fill(fabs(mu[0].p4.Eta()-mu[1].p4.Eta()),weight);
		histos["METge25_DRll_"+skimFilePrefix]->Fill(dRbetweenVectors(mu[0].p4,mu[1].p4),weight);	
	      }
	      for(unsigned int i = 0; i<mu.size(); ++i){
		float mucharge = 0; if(mu[i].id==13) mucharge = -1; else if(mu[i].id==-13) mucharge = +1; 
		histos["MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		histos["MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		histos["MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		histos["MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		if(njs==0){
		  histos["NJ0_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NJ0_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NJ0_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NJ0_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} else if(njs==1){
		  histos["NJ1_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NJ1_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NJ1_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NJ1_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} else if(njs==2){
		  histos["NJ2_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NJ2_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NJ2_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NJ2_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} else {
		  histos["NJge3_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NJge3_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NJge3_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NJge3_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} if(nbs==0){
		  histos["NB0_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NB0_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NB0_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NB0_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} else {
		  histos["NBge1_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["NBge1_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["NBge1_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["NBge1_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} if(HT>100.){
		  histos["HTge100_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["HTge100_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["HTge100_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["HTge100_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} if(HT>150.){
		  histos["HTge150_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["HTge150_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["HTge150_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["HTge150_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} if(p.evt_pfmet>50.){
		  histos["METge50_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["METge50_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["METge50_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["METge50_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		} if(p.evt_pfmet>25.){
		  histos["METge25_MuPt_"+skimFilePrefix]->Fill(mu[i].p4.Pt(),weight);
		  histos["METge25_MuEta_"+skimFilePrefix]->Fill(mu[i].p4.Eta(),weight);
		  histos["METge25_MuPhi_"+skimFilePrefix]->Fill(mu[i].p4.Phi(),weight);
		  histos["METge25_MuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
		}
	      }
	    }
	  }
	  if((triggerbool1mu||triggerbool2mu)&& mu[0].passes_POG_tightID&&mu[1].passes_POG_tightID&&fabs(mu[0].dZ)<0.1&&fabs(mu[1].dZ)<0.1&&fabs(mu[0].dxyPV)<0.02&&fabs(mu[1].dxyPV)<0.02){
	    if(Z.M()>75.&&Z.M()<105){
	      for(unsigned int i = 0; i<mu.size(); ++i){
		histos["MuRelIso03_"+skimFilePrefix]->Fill(mu[i].RelIso03,weight);
		histos["MuRelIso03EA_"+skimFilePrefix]->Fill(mu[i].RelIso03EA,weight);
		histos["MuRelIso03DB_"+skimFilePrefix]->Fill(mu[i].RelIso03DB,weight);
		histos["MuMiniIsoEA_"+skimFilePrefix]->Fill(mu[i].miniiso,weight);
		histos["MuMiniIsoDB_"+skimFilePrefix]->Fill(mu[i].miniisoDB,weight);
		histos["MuRelIso04_"+skimFilePrefix]->Fill(mu[i].reliso04,weight);
		histos["MuAnnulus04_"+skimFilePrefix]->Fill(mu[i].annulus04,weight);
		if(mu[0].mt>30&&mu[0].mt>30){
		  histos["MuRelIso03_MT30_"+skimFilePrefix]->Fill(mu[i].RelIso03,weight);
		  histos["MuRelIso03EA_MT30_"+skimFilePrefix]->Fill(mu[i].RelIso03EA,weight);
		  histos["MuRelIso03DB_MT30_"+skimFilePrefix]->Fill(mu[i].RelIso03DB,weight);
		  histos["MuMiniIsoEA_MT30_"+skimFilePrefix]->Fill(mu[i].miniiso,weight);
		  histos["MuMiniIsoDB_MT30_"+skimFilePrefix]->Fill(mu[i].miniisoDB,weight);
		  histos["MuRelIso04_MT30_"+skimFilePrefix]->Fill(mu[i].reliso04,weight);
		  histos["MuAnnulus04_MT30_"+skimFilePrefix]->Fill(mu[i].annulus04,weight);
		}
	      }
	    }
	  }
	  if((triggerbool1mu||triggerbool2mu)&& mu[0].passes_POG_tightID&&mu[1].passes_POG_tightID&&mu[0].miniisoDB<0.2&&mu[1].miniisoDB<0.2){
	    if(Z.M()>75.&&Z.M()<105){
	      for(unsigned int i = 0; i<mu.size(); ++i){
		histos["Mud0_"+skimFilePrefix]->Fill(mu[i].dxyPV,weight);
		histos["MudZ_"+skimFilePrefix]->Fill(mu[i].dZ,weight);
		histos["MuIP3d_"+skimFilePrefix]->Fill(mu[i].ip3d,weight);
	      }
	    }
	  }
	  if((triggerbool1mu||triggerbool2mu)&& mu[0].passes_POG_looseID&&mu[1].passes_POG_looseID&&mu[0].miniisoDB<0.2&&mu[1].miniisoDB<0.2&&
	      fabs(mu[0].dZ)<0.1&&fabs(mu[1].dZ)<0.1&&fabs(mu[0].dxyPV)<0.02&&fabs(mu[1].dxyPV)<0.02){
	    if(Z.M()>75.&&Z.M()<105){
	      for(unsigned int i = 0; i<mu.size(); ++i){
		if(mu[i].passes_POG_tightID) histos["MuID_"+skimFilePrefix]->Fill(3.,weight);
		else if(mu[i].passes_POG_mediumID) histos["MuID_"+skimFilePrefix]->Fill(2.,weight);
		else if(mu[i].passes_POG_looseID) histos["MuID_"+skimFilePrefix]->Fill(1.,weight);
		histos["MuvalidFraction_"+skimFilePrefix]->Fill((float)mu[i].validHits/((float)(mu[i].validHits+mu[i].lostHits+mu[i].exp_innerlayers+mu[i].exp_outerlayers)),weight);
		if(mu[i].gfit_ndof>0) histos["Mugfit_normchi2_"+skimFilePrefix]->Fill(mu[i].gfit_chi2/mu[i].gfit_ndof, weight);
		histos["Mugfit_validSTAHits_"+skimFilePrefix]->Fill(mu[i].gfit_validSTAHits,weight);
		histos["MunumberOfMatchedStations_"+skimFilePrefix]->Fill(mu[i].numberOfMatchedStations,weight);
		histos["MuvalidPixelHits_"+skimFilePrefix]->Fill(mu[i].validPixelHits,weight);
		histos["Munlayers_"+skimFilePrefix]->Fill(mu[i].nlayers,weight);
		histos["Muchi2LocalPosition_"+skimFilePrefix]->Fill(mu[i].chi2LocalPosition,weight);
		histos["MutrkKink_"+skimFilePrefix]->Fill(mu[i].trkKink,weight);
		histos["MusegmCompatibility_"+skimFilePrefix]->Fill(mu[i].segmCompatibility,weight);
	      }
	    }
	  }
	}//2 muons
	else if(mu.size()==1){
	  triggerbool1mu = triggerbool1mu&&((mu[0].p4.Pt()>30.&&fabs(mu[0].p4.Eta())<2.1));//one muon passing nominal trigger w/o iso
	  if(triggerbool1mu&&mu[0].passes_POG_tightID&&mu[0].miniisoDB<0.2&&fabs(mu[0].dZ)<0.1&&fabs(mu[0].dxyPV)<0.02&&mu[0].mt>40){//1 mu events.
	    float mucharge = 0; if(mu[0].id==13) mucharge = -1; else if(mu[0].id==-13) mucharge = +1; 
	    histos["MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	    histos["MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	    histos["MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	    histos["MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	    histos["MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
	    if(njs==0){
	      histos["NJ0_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NJ0_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NJ0_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NJ0_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NJ0_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);
	    } else if(njs==1){
	      histos["NJ1_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NJ1_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NJ1_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NJ1_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NJ1_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } else if(njs==2){
	      histos["NJ2_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NJ2_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NJ2_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NJ2_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NJ2_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } else {
	      histos["NJge3_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NJge3_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NJge3_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NJge3_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NJge3_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } if(nbs==0){
	      histos["NB0_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NB0_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NB0_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NB0_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NB0_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } else {
	      histos["NBge1_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["NBge1_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["NBge1_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["NBge1_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["NBge1_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } if(HT>100.){
	      histos["HTge100_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["HTge100_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["HTge100_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["HTge100_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["HTge100_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } if(HT>150.){
	      histos["HTge150_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["HTge150_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["HTge150_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["HTge150_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["HTge150_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } if(p.evt_pfmet>50.){
	      histos["METge50_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["METge50_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["METge50_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["METge50_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["METge50_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    } if(p.evt_pfmet>25.){
	      histos["METge25_MT_"+skimFilePrefix]->Fill(mu[0].mt,weight);
	      histos["METge25_MyMuPt_"+skimFilePrefix]->Fill(mu[0].p4.Pt(),weight);
	      histos["METge25_MyMuEta_"+skimFilePrefix]->Fill(mu[0].p4.Eta(),weight);
	      histos["METge25_MyMuPhi_"+skimFilePrefix]->Fill(mu[0].p4.Phi(),weight);
	      histos["METge25_MyMuCharge_"+skimFilePrefix]->Fill(mucharge,weight);	      
	    }
	  }
	}
      }
      if(!sameEvent(p,c)){
	//finally start new event.
	if(abs(p.id)==13&&p.passes_POG_tightID&&p.miniisoDB<0.2&&fabs(p.dZ)<0.1&&fabs(p.dxyPV)<0.02&&p.dilep_mass>75.&&p.dilep_mass<105&&p.p4.Pt()>20&&fabs(p.p4.Eta())<2.1) {
	  if((p.evt_isRealData&&(p.HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_DZ || p.HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_DZ || p.HLT_IsoMu24_eta2p1 || p.HLT_IsoTkMu24_eta2p1 || p.HLT_IsoMu27 || p.HLT_IsoTkMu27 || p.HLT_IsoMu20 || p.HLT_IsoMu20))||(!p.evt_isRealData)){
	    histos["Z_Pt_"+skimFilePrefix]->Fill(p.dilep_p4.Pt(),weight);
	  }
	}
	mu.clear();
	nleps = 1;
      }
      if(currentrun!=c.evt_run) { cout << "This is run " << c.evt_run << endl; currentrun = c.evt_run; }
      bool skip = false;
      //if(c.evt_run!=251244&&c.evt_run!=251251&&c.evt_run!=251252) skip = true;
      if(abs(c.id)!=13) skip = true;
      else if(c.p4.Pt()<20.) skip = true;
      else if(fabs(c.p4.Eta())>2.1) skip = true;
      else if(!c.passes_POG_looseID) skip = true;
      //else if(fabs(c.dZ)>0.5) skip = true;
      //else if(fabs(c.dxyPV)>0.2) skip = true;
      //else if(c.miniisoDB>0.5) skip = true;
      if(!skip) { mu.push_back(c); }
      p = c;
      resetEvent(c);
    }
  
    // Clean Up
    delete tree;
    file->Close();
    delete file;
  }
  if ( nEventsChain != nEventsTotal ) {
    cout << Form( "ERROR: number of events from files (%d) is not equal to total number of events (%d)", nEventsChain, nEventsTotal ) << endl;
  }
  
  // Example Histograms
  for(map<string,TH1F*>::iterator h=histos.begin(); h!=histos.end();++h){
    h->second->SetBinContent(h->second->GetNbinsX(), h->second->GetBinContent(h->second->GetNbinsX() )+ h->second->GetBinContent(h->second->GetNbinsX()+1) );
    h->second->SetBinError(h->second->GetNbinsX(), sqrt(pow(h->second->GetBinError(h->second->GetNbinsX() ),2)+pow(h->second->GetBinError(h->second->GetNbinsX()+1),2) ) );
  }
  for(map<string,TH1F*>::iterator h=histos.begin(); h!=histos.end();++h){
    h->second->SetBinContent(1, h->second->GetBinContent(1 )+ h->second->GetBinContent(0) );
    h->second->SetBinError(1, sqrt(pow(h->second->GetBinError(1 ),2)+pow(h->second->GetBinError(0),2) ) );
  }
  //string filename = "rootfiles/test/Histos_"+skimFilePrefix+".root";
  string filename = "rootfiles/first_20150727/Histos3_"+skimFilePrefix+".root";
  if(DCSonly) filename = "rootfiles/first_20150727/Histos3DCS_"+skimFilePrefix+".root";
  TFile *f = new TFile(filename.c_str(),"RECREATE");
  f->cd();
  for(map<string,TH1F*>::iterator h=    histos.begin(); h!=    histos.end();++h) h->second->Write();
  f->Close();
  cout << "Saved histos in " << f->GetName() << endl;  
  // return
  bmark->Stop("benchmark");
  cout << endl;
  cout << nEventsTotal << " Events Processed" << endl;
  cout << "------------------------------" << endl;
  cout << "CPU  Time:	" << Form( "%.01f", bmark->GetCpuTime("benchmark")  ) << endl;
  cout << "Real Time:	" << Form( "%.01f", bmark->GetRealTime("benchmark") ) << endl;
  cout << endl;
  delete bmark;
  return 0;
}
Exemple #4
0
void doWZ(int cem = 8, int mode = 0){

  char plotName[300];
  sprintf(plotName,"test");
  
  sprintf(plotName,"WZ");
  bool isBackground = true;
  bool isData = false;
  int nsel = 2;
  
  char myRootFile[300];
  if (cem != 7 && cem !=8) cem = 8;
  double lumi = lumi8;
  if (cem == 8){
    sprintf(myRootFile,"/data/smurf/data/Run2012_Summer12_SmurfV9_53X/mitf-alljets/backgroundA_3l.root");
  } else {
    lumi = lumi7;
    sprintf(myRootFile,"/data/smurf/data/Run2011_Fall11_SmurfV9_42X/mitf-alljets/backgroundA_3l.root");
  }
  //Load datasets
  SmurfTree sample;
  sample.LoadTree(myRootFile,-1);
  sample.InitTree(0);

  // Prepare putput file
  char rootFile[300];
  if (cem == 8) sprintf(rootFile,"WZ8TeV.root");
  else sprintf(rootFile,"WZ7TeV.root");

  TFile f_root(rootFile, "RECREATE");
  
  // Prepare histograms
  char title[300];
  
  sprintf(title,"histogram");
  TH1F* histo = new TH1F( title, " ", nbins, nbinlow, nbinhigh);
  histo->Sumw2();

  //Prepare useful things
  double weight = 1;
  double eventsPass = 0;
  
  int nSample=sample.tree_->GetEntries();
   for (int i=0; i<nSample; ++i) {
    
    if (i%100000 == 0 && verboseLevel > 0)
      printf("--- reading event %5d of %5d\n",i,nSample);
    sample.tree_->GetEntry(i);
    
      //Modes, 0 = all, 1 = eee, 2 = eem, 3 = emm, 4 = mmm
    if (mode == 1 && (abs(sample.lid1_)!= 11 || abs(sample.lid2_) != 11 || abs(sample.lid3_) != 11)) continue;
    if (mode == 2 && 
       ((abs(sample.lid1_)!= abs(sample.lid2_) && abs(sample.lid1_) != abs(sample.lid3_) && abs(sample.lid1_) == 11) ||
        (abs(sample.lid2_)!= abs(sample.lid1_) && abs(sample.lid2_) != abs(sample.lid3_) && abs(sample.lid2_) == 11) ||
	(abs(sample.lid3_)!= abs(sample.lid1_) && abs(sample.lid3_) != abs(sample.lid2_) && abs(sample.lid3_) == 11) ||
	(abs(sample.lid1_) == abs(sample.lid2_) && abs(sample.lid1_) == abs(sample.lid3_)))) continue;
    if (mode == 3 && 
       ((abs(sample.lid1_)!= abs(sample.lid2_) && abs(sample.lid1_) != abs(sample.lid3_) && abs(sample.lid1_) == 13) ||
        (abs(sample.lid2_)!= abs(sample.lid1_) && abs(sample.lid2_) != abs(sample.lid3_) && abs(sample.lid2_) == 13) ||
	(abs(sample.lid3_)!= abs(sample.lid1_) && abs(sample.lid3_) != abs(sample.lid2_) && abs(sample.lid3_) == 13) ||
	(abs(sample.lid1_) == abs(sample.lid2_) && abs(sample.lid1_) == abs(sample.lid3_)))) continue;
    if (mode == 4 && (abs(sample.lid1_)!= 13 || abs(sample.lid2_) != 13 || abs(sample.lid3_) != 13)) continue;
   

    
    weight = 1;
    if (!isData && sample.dstype_ != SmurfTree::data) weight = lumi*sample.scale1fb_*sample.sfWeightPU_*sample.sfWeightEff_*sample.sfWeightTrig_;    
   
   //Three real leptons MC level
    if (!isData){
      bool isRealLepton = false;
      if((TMath::Abs(sample.lep1McId_) == 11 || TMath::Abs(sample.lep1McId_) == 13) &&
         (TMath::Abs(sample.lep2McId_) == 11 || TMath::Abs(sample.lep2McId_) == 13) &&
         (TMath::Abs(sample.lep3McId_) == 11 || TMath::Abs(sample.lep3McId_) == 13)) isRealLepton = true; 
      if (!isRealLepton && !isBackground) continue; //signal
      if (!isRealLepton && sample.dstype_ != SmurfTree::data) continue; //background
    }
    
    int ntype = sample.dstype_;
    
     //Check for fakes
    int nFake = 0;
    if(((sample.cuts_ & SmurfTree::Lep1LooseMuV2)  == SmurfTree::Lep1LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep2LooseMuV2)  == SmurfTree::Lep2LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep3LooseMuV2)  == SmurfTree::Lep3LooseMuV2)  && (sample.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep1LooseEleV4) == SmurfTree::Lep1LooseEleV4) && (sample.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep2LooseEleV4) == SmurfTree::Lep2LooseEleV4) && (sample.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((sample.cuts_ & SmurfTree::Lep3LooseEleV4) == SmurfTree::Lep3LooseEleV4) && (sample.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if (nFake !=0 && !isBackground) continue; 
    if (nFake !=0){ 
      ntype = 61;
      weight*= sample.sfWeightFR_*factor;
      //if (sample.dstype_ != SmurfTree::data) weight *=-1;
    }
    
    if (nsel == 2 && ntype != 49) continue; //WZ
    
    //2 same flavor, oppposite sign leptons + extra one
    if (sample.lid3_ == sample.lid2_ && sample.lid3_ == sample.lid1_) continue;
    if (sample.lid3_ == sample.lid2_ && fabs(sample.lid3_) != fabs(sample.lid1_)) continue;
    if (sample.lid3_ == sample.lid1_ && fabs(sample.lid3_) != fabs(sample.lid2_)) continue;
    if (sample.lid2_ == sample.lid1_ && fabs(sample.lid2_) != fabs(sample.lid3_)) continue;
    
    // At least 2 jets 
    if (sample.njets_ < 2) continue; 
    if (tau && (sample.jet1McId_ == 100 || sample.jet2McId_ == 100 || sample.jet3McId_ == 100 || sample.jet4McId_ == 100)) continue;

       //Make z-compatible pairs
    double m[3] = {-1, -1, -1};
    LorentzVector pair1, pair2, pair3;
    if (fabs(sample.lid1_) == fabs(sample.lid2_) && sample.lq1_*sample.lq2_ < 0){
      pair1 = sample.lep1_ + sample.lep2_ ;
      m[0] = pair1.M();
      if (m[0] < 12) continue;
    }
    if (fabs(sample.lid2_) == fabs(sample.lid3_) && sample.lq2_*sample.lq3_ < 0){
      pair2 = sample.lep2_ + sample.lep3_ ;
      m[1] = pair2.M();
      if (m[1] < 12) continue;
    }
    if (fabs(sample.lid1_) == fabs(sample.lid3_) && sample.lq1_*sample.lq3_ < 0){
      pair3 = sample.lep1_ + sample.lep3_ ;
      m[2] = pair3.M();
      if (m[2] < 12) continue;
    }
    if ( (m[0] > 0 && m[0] < 12) || (m[1] > 0 && m[1] < 12) || (m[2] > 0 && m[2] < 12)) continue;
    				
   LorentzVector trelep = sample.lep1_ + sample.lep2_ + sample.lep3_;
   if (fabs(trelep.M() - mz) < 10) continue; 
						
    //Get the closest to the Z mass
    double min = TMath::Min(TMath::Min(fabs(mz -m[0]), fabs(mz-m[1])), TMath::Min(fabs(mz -m[0]), fabs(mz-m[2])));
   
    //Select the different things: Z pair, extra lepton, Higgs system
    LorentzVector pair, tlepton, pairjet;
    double mt = 0;
   // double dR = 0; //dR = fabs(ROOT::Math::VectorUtil::DeltaR(sample.lep1_ ,sample.lep2_)) etc
    if (min == fabs(mz - m[0])) {  pair = pair1; mt =  sample.mt3_; tlepton = sample.lep3_;} 
    else if (min == fabs(mz - m[1])){  pair = pair2;  mt =  sample.mt1_; tlepton = sample.lep1_;} 
    else if (min == fabs(mz - m[2])){  pair = pair3;  mt =  sample.mt2_; tlepton = sample.lep2_;} 
    pairjet = sample.jet1_+ sample.jet2_;
    LorentzVector metvector(sample.met_*cos(sample.metPhi_), sample.met_*sin(sample.metPhi_), 0, 0);
    LorentzVector higgsSystem = tlepton + metvector + sample.jet1_+ sample.jet2_;
    LorentzVector lm = tlepton + metvector;
   
      
    double hp[5];
    hp[0] = tlepton.Px() + sample.jet1_.Px()+ sample.jet2_.Px()+ metvector.Px();
    hp[1] = tlepton.Py() + sample.jet1_.Py()+ sample.jet2_.Py()+ metvector.Py();
    hp[2] = tlepton.Pz() + sample.jet1_.Pz()+ sample.jet2_.Pz()+ metvector.Pz();
    
    //Calculate p of the neutrino using Maria's code
    double metp = 0;
   // double otherSol = 0;
    double alpha=(mw*mw-mmu*mmu)/2/tlepton.P()+(tlepton.Px()*sample.met_*cos(sample.metPhi_)+tlepton.Py()*sample.met_*sin(sample.metPhi_))/tlepton.P();
    double A=tlepton.Pz()*tlepton.Pz()/tlepton.P()/tlepton.P()-1;
    double B=2*alpha*tlepton.Pz()/tlepton.P();
    double C=alpha*alpha-(sample.met_*cos(sample.metPhi_)*sample.met_*cos(sample.metPhi_) + sample.met_*sin(sample.metPhi_)*sample.met_*sin(sample.metPhi_));
   // bool isComplex = false;
    double tmproot = B*B - 4.0*A*C;
      if (tmproot<0) { 
        //isComplex= true;
        metp = - B/(2*A); 
	//otherSol = metp;
      } else {
       // isComplex = false;
	double tmpsol1 = (-B + TMath::Sqrt(tmproot))/(2.0*A);
	double tmpsol2 = (-B - TMath::Sqrt(tmproot))/(2.0*A);
	if (TMath::Abs(tmpsol1)<TMath::Abs(tmpsol2) ) {
	  metp = tmpsol1; 
	  //otherSol = tmpsol2; 
	} else { 
	  metp = tmpsol2; 
	  //otherSol = tmpsol1; 
	}
     }
   
    
   // hp[3] = tlepton.P() + sample.jet1_.P()+ sample.jet2_.P()+ metvector.P(); //crappy solution
    hp[3] = tlepton.P() + sample.jet1_.P()+ sample.jet2_.P()+ metp;
    hp[4] = tlepton.Pt() + sample.jet1_.Pt()+ sample.jet2_.Pt()+ sample.met_;
    
    double recomh  = hp[3]*hp[3]-hp[0]*hp[0]-hp[1]*hp[1]-hp[2]*hp[2]; if(recomh  > 0) recomh  = sqrt(recomh);else recomh   = 0.0;
    double recomth = hp[4]*hp[4]-hp[0]*hp[0]-hp[1]*hp[1]; if(recomth > 0) recomth = sqrt(recomth); else recomth  = 0.0;
    
   
    //Kinematic cuts
    if (pair.M() < (mz - separation)|| pair.M() > (mz + separation)) continue; 
    if (sample.met_ < metcut) continue;
    if (mt > mtcut) continue;
    if (pairjet.M() < (mw - separationjj) || pairjet.M() > (mw + separationjj)) continue;
    
   //double deltaPhi = fabs(DeltaPhi(pairjet.Phi(),tlepton.Phi()));
    double deltaPhi = fabs(DeltaPhi(pairjet.Phi(),lm.Phi()));
    if (deltaPhi > phicut) continue;
   
    
    histo->Fill(recomth, weight);
    //histo->Fill(higgsSystem.M(), weight);
    eventsPass+= weight;
     
  
  }    
  
   cout << "[Info:] (" << plotName << ") " <<  eventsPass << " events pass " << endl;
  
  
    f_root.Write();
    f_root.Close();
 
}
void computeAccSelZeeBinned(const TString conf,            // input file
                            const TString outputDir        // output directory
) {
  gBenchmark->Start("computeAccSelZeeBinned");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW   = 60;
  const Double_t MASS_HIGH  = 120;
  const Double_t PT_CUT     = 25;
  const Double_t ETA_CUT    = 2.5;
  const Double_t ELE_MASS   = 0.000511;
  const Double_t ETA_BARREL = 1.4442;
  const Double_t ETA_ENDCAP = 1.566;
  
  // efficiency files
  const TString dataHLTEffName     = "../Efficiency/May23_EleHLTEff/analysis/eff.root";
  const TString dataHLTEffName_pos = "../Efficiency/May23_EleHLTEff_pos/analysis/eff.root";
  const TString dataHLTEffName_neg = "../Efficiency/May23_EleHLTEff_neg/analysis/eff.root";
  const TString zeeHLTEffName      = "../Efficiency/Zee_EleHLTEff/analysis/eff.root";
  const TString zeeHLTEffName_pos  = "../Efficiency/Zee_EleHLTEff_pos/analysis/eff.root";
  const TString zeeHLTEffName_neg  = "../Efficiency/Zee_EleHLTEff_neg/analysis/eff.root";
  
  const TString dataGsfSelEffName     = "../Efficiency/May23_EleGsfSelEff/analysis/eff.root";
  const TString dataGsfSelEffName_pos = "../Efficiency/May23_EleGsfSelEff_pos/analysis/eff.root";
  const TString dataGsfSelEffName_neg = "../Efficiency/May23_EleGsfSelEff_neg/analysis/eff.root";
  const TString zeeGsfSelEffName      = "../Efficiency/Zee_EleGsfSelEff/analysis/eff.root";
  const TString zeeGsfSelEffName_pos  = "../Efficiency/Zee_EleGsfSelEff_pos/analysis/eff.root";
  const TString zeeGsfSelEffName_neg  = "../Efficiency/Zee_EleGsfSelEff_neg/analysis/eff.root";
    

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  vector<TString> fnamev;  // file name per input file
  vector<TString> labelv;  // TLegend label per input file
  vector<Int_t>   colorv;  // plot color per input file
  vector<Int_t>   linev;   // plot line style per input file

  //
  // parse .conf file
  //
  ifstream ifs;
  ifs.open(conf.Data());
  assert(ifs.is_open());
  string line;
  while(getline(ifs,line)) {
    if(line[0]=='#') continue;
    
    string fname;
    Int_t color, linesty;
    stringstream ss(line);
    ss >> fname >> color >> linesty;
    string label = line.substr(line.find('@')+1);
    fnamev.push_back(fname);
    labelv.push_back(label);
    colorv.push_back(color);
    linev.push_back(linesty);
  }
  ifs.close();

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  
  TH2D *h=0;
  
  //
  // HLT efficiency
  //
  cout << "Loading trigger efficiencies..." << endl;

  TFile *dataHLTEffFile_pos = new TFile(dataHLTEffName_pos);
  CEffUser2D dataHLTEff_pos;
  dataHLTEff_pos.loadEff((TH2D*)dataHLTEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataHLTEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataHLTEffFile_pos->Get("hErrhEtaPt"));
  
  TFile *dataHLTEffFile_neg = new TFile(dataHLTEffName_neg);
  CEffUser2D dataHLTEff_neg;
  dataHLTEff_neg.loadEff((TH2D*)dataHLTEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataHLTEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataHLTEffFile_neg->Get("hErrhEtaPt"));
  
  TFile *zeeHLTEffFile_pos = new TFile(zeeHLTEffName_pos);
  CEffUser2D zeeHLTEff_pos;
  zeeHLTEff_pos.loadEff((TH2D*)zeeHLTEffFile_pos->Get("hEffEtaPt"), (TH2D*)zeeHLTEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zeeHLTEffFile_pos->Get("hErrhEtaPt"));
  
  TFile *zeeHLTEffFile_neg = new TFile(zeeHLTEffName_neg);
  CEffUser2D zeeHLTEff_neg;
  zeeHLTEff_neg.loadEff((TH2D*)zeeHLTEffFile_neg->Get("hEffEtaPt"), (TH2D*)zeeHLTEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zeeHLTEffFile_neg->Get("hErrhEtaPt"));
  
  h =(TH2D*)dataHLTEffFile_pos->Get("hEffEtaPt");
  TH2D *hHLTErr_pos = new TH2D("hHLTErr_pos", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                                 h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  TH2D *hHLTErr_neg = new TH2D("hHLTErr_neg", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                                 h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  
  //
  // Selection efficiency
  //
  cout << "Loading GSF+selection efficiencies..." << endl;
  
  TFile *dataGsfSelEffFile_pos = new TFile(dataGsfSelEffName_pos);
  CEffUser2D dataGsfSelEff_pos;
  dataGsfSelEff_pos.loadEff((TH2D*)dataGsfSelEffFile_pos->Get("hEffEtaPt"), (TH2D*)dataGsfSelEffFile_pos->Get("hErrlEtaPt"), (TH2D*)dataGsfSelEffFile_pos->Get("hErrhEtaPt"));
  
  TFile *dataGsfSelEffFile_neg = new TFile(dataGsfSelEffName_neg);
  CEffUser2D dataGsfSelEff_neg;
  dataGsfSelEff_neg.loadEff((TH2D*)dataGsfSelEffFile_neg->Get("hEffEtaPt"), (TH2D*)dataGsfSelEffFile_neg->Get("hErrlEtaPt"), (TH2D*)dataGsfSelEffFile_neg->Get("hErrhEtaPt"));

  TFile *zeeGsfSelEffFile_pos = new TFile(zeeGsfSelEffName_pos);
  CEffUser2D zeeGsfSelEff_pos;
  zeeGsfSelEff_pos.loadEff((TH2D*)zeeGsfSelEffFile_pos->Get("hEffEtaPt"), (TH2D*)zeeGsfSelEffFile_pos->Get("hErrlEtaPt"), (TH2D*)zeeGsfSelEffFile_pos->Get("hErrhEtaPt"));

  TFile *zeeGsfSelEffFile_neg = new TFile(zeeGsfSelEffName_neg);
  CEffUser2D zeeGsfSelEff_neg;
  zeeGsfSelEff_neg.loadEff((TH2D*)zeeGsfSelEffFile_neg->Get("hEffEtaPt"), (TH2D*)zeeGsfSelEffFile_neg->Get("hErrlEtaPt"), (TH2D*)zeeGsfSelEffFile_neg->Get("hErrhEtaPt"));
 
  h =(TH2D*)dataGsfSelEffFile_pos->Get("hEffEtaPt");
  TH2D *hGsfSelErr_pos = new TH2D("hGsfSelErr_pos", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                                       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  TH2D *hGsfSelErr_neg = new TH2D("hGsfSelErr_neg", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                                       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  
  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  mithep::TGenInfo   *gen   = new mithep::TGenInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  // Variables to store acceptances and uncertainties (per input file)
  vector<Double_t> nEvtsv, nSelv, nSelCorrv;
  vector<Double_t> statErr2v, effErr2v;
  vector<Double_t> accv, accCorrv;
  vector<Double_t> accErrv, accCorrErrv;
    
  //
  // loop through files
  //
  for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {  

    // Read input file and get the TTrees
    cout << "Processing " << fnamev[ifile] << " ..." << endl;
    infile = new TFile(fnamev[ifile]); 
    assert(infile);
  
    eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
    eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
    eventTree->SetBranchAddress("Gen",      &gen);         TBranch *genBr      = eventTree->GetBranch("Gen");
    eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");

    nEvtsv.push_back(0);
    nSelv.push_back(0);
    nSelCorrv.push_back(0);
    statErr2v.push_back(0);
    
    //
    // loop over events
    //
    for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
      genBr->GetEntry(ientry);
      if(gen->vmass<MASS_LOW || gen->vmass>MASS_HIGH) continue;

      infoBr->GetEntry(ientry);     
    
      Double_t weight=1;
      nEvtsv[ifile]+=weight;
    
      // trigger requirement               
      ULong_t trigger = kHLT_Ele22_CaloIdL_CaloIsoVL;
      ULong_t trigObj = kHLT_Ele22_CaloIdL_CaloIsoVL_EleObj;   
      if(!(info->triggerBits & trigger)) continue;
      
      // good vertex requirement
      if(!(info->hasGoodPV)) continue;
    
      electronArr->Clear();
      electronBr->GetEntry(ientry);
      for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
  	const mithep::TElectron *ele1 = (mithep::TElectron*)((*electronArr)[i1]);
	
	// check ECAL gap
	if(fabs(ele1->scEta)>=ETA_BARREL && fabs(ele1->scEta)<=ETA_ENDCAP) continue;
        
	if(ele1->scEt	     < PT_CUT)	     continue;  // lepton pT cut
        if(fabs(ele1->scEta) > ETA_CUT)	     continue;  // lepton |eta| cut
        if(!passEleID(ele1,info->rhoLowEta)) continue;  // lepton selection

        LorentzVector vEle1(ele1->pt, ele1->eta, ele1->phi, ELE_MASS);
	Bool_t isB1 = (fabs(ele1->scEta)<ETA_BARREL) ? kTRUE : kFALSE;

        for(Int_t i2=i1+1; i2<electronArr->GetEntriesFast(); i2++) {          
	  const mithep::TElectron *ele2 = (mithep::TElectron*)((*electronArr)[i2]);
	  
	  // check ECAL gap
	  if(fabs(ele2->scEta)>=ETA_BARREL && fabs(ele2->scEta)<=ETA_ENDCAP) continue;
        
          if(ele2->scEt        < PT_CUT)       continue;  // lepton pT cut
          if(fabs(ele2->scEta) > ETA_CUT)      continue;  // lepton |eta| cut
	  if(!passEleID(ele2,info->rhoLowEta)) continue;  // lepton selection

          LorentzVector vEle2(ele2->pt, ele2->eta, ele2->phi, ELE_MASS);  
          Bool_t isB2 = (fabs(ele2->scEta)<ETA_BARREL) ? kTRUE : kFALSE;

          // trigger match
	  if(!(ele1->hltMatchBits & trigObj) && !(ele2->hltMatchBits & trigObj)) continue;
	  
	  // mass window
          LorentzVector vDilep = vEle1 + vEle2;
          if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;
          
          
          /******** We have a Z candidate! HURRAY! ********/
       
          Double_t effdata, effmc;
          Double_t sceta1 = (fabs(ele1->scEta)<2.5) ? ele1->scEta : 0.99*(ele1->scEta);
          Double_t sceta2 = (fabs(ele2->scEta)<2.5) ? ele2->scEta : 0.99*(ele2->scEta);
    
          Double_t corr=1;
	  
	  effdata=1; effmc=1;
          if(ele1->q>0) { 
            effdata *= (1.-dataHLTEff_pos.getEff(sceta1, ele1->scEt)); 
            effmc   *= (1.-zeeHLTEff_pos.getEff(sceta1, ele1->scEt)); 
          } else {
            effdata *= (1.-dataHLTEff_neg.getEff(sceta1, ele1->scEt)); 
            effmc   *= (1.-zeeHLTEff_neg.getEff(sceta1, ele1->scEt)); 
          }
          if(ele2->q>0) {
            effdata *= (1.-dataHLTEff_pos.getEff(sceta2, ele2->scEt)); 
            effmc   *= (1.-zeeHLTEff_pos.getEff(sceta2, ele2->scEt));
          } else {
            effdata *= (1.-dataHLTEff_neg.getEff(sceta2, ele2->scEt)); 
            effmc   *= (1.-zeeHLTEff_neg.getEff(sceta2, ele2->scEt));
          }
          effdata = 1.-effdata;
          effmc   = 1.-effmc;
          corr *= effdata/effmc;
    
          effdata=1; effmc=1;
          if(ele1->q>0) { 
            effdata *= dataGsfSelEff_pos.getEff(fabs(sceta1), ele1->scEt); 
            effmc   *= zeeGsfSelEff_pos.getEff(fabs(sceta1), ele1->scEt); 
          } else {
            effdata *= dataGsfSelEff_neg.getEff(fabs(sceta1), ele1->scEt); 
            effmc   *= zeeGsfSelEff_neg.getEff(fabs(sceta1), ele1->scEt); 
          }
          if(ele2->q>0) {
            effdata *= dataGsfSelEff_pos.getEff(fabs(sceta2), ele2->scEt); 
            effmc   *= zeeGsfSelEff_pos.getEff(fabs(sceta2), ele2->scEt);
          } else {
            effdata *= dataGsfSelEff_neg.getEff(fabs(sceta2), ele2->scEt); 
            effmc   *= zeeGsfSelEff_neg.getEff(fabs(sceta2), ele2->scEt);
          }
          corr *= effdata/effmc;
	  
	  nSelv[ifile]+=weight;
	  nSelCorrv[ifile]+=weight*corr;
	  statErr2v[ifile]+=weight*weight*corr*corr;
	  
	  // scale factor uncertainties
//	  Double_t dataerr=0, mcerr=0;
//	  if(ele1->q>0) {	    
//	    effdata = dataGsfSelEff_pos.getEff(fabs(sceta1), ele1->scEt);
//	    errdata = TMath::Max(dataGsfSelEff_pos.getErrl(fabs(sceta1), ele1->scEt), dataGsfSelEff_pos.getErrh(fabs(sceta1), ele1->scEt));
//            effmc   = zeeGsfSelEff_pos.getEff(fabs(sceta1), ele1->scEt); 
//	    errmc   = TMath::Max(zeeGsfSelEff_pos.getErrl(fabs(sceta1), ele1->scEt), zeeGsfSelEff_pos.getErrh(fabs(sceta1), ele1->scEt));
//	    Double_t errGsfSel = weight*corr*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
//	    hGsfSelErr_pos->Fill(fabs(sceta1), ele1->scEt, errGsfSel);
//
//	  } else {
//	    effdata = dataGsfSelEff_neg.getEff(fabs(sceta1), ele1->scEt);
//	    errdata = TMath::Max(dataGsfSelEff_neg.getErrl(fabs(sceta1), ele1->scEt), dataGsfSelEff_neg.getErrh(fabs(sceta1), ele1->scEt));
//            effmc   = zeeGsfSelEff_neg.getEff(fabs(sceta1), ele1->scEt); 
//	    errmc   = TMath::Max(zeeGsfSelEff_neg.getErrl(fabs(sceta1), ele1->scEt), zeeGsfSelEff_neg.getErrh(fabs(sceta1), ele1->scEt));
//	    Double_t errGsfSel = weight*corr*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
//	    hGsfSelErr_neg->Fill(fabs(sceta1), ele1->scEt, errGsfSel);
//	  }
//	  if(ele2->q>0) {	    
//	    effdata = dataGsfSelEff_pos.getEff(fabs(sceta2), ele2->scEt);
//	    errdata = TMath::Max(dataGsfSelEff_pos.getErrl(fabs(sceta2), ele2->scEt), dataGsfSelEff_pos.getErrh(fabs(sceta2), ele2->scEt));
//            effmc   = zeeGsfSelEff_pos.getEff(fabs(sceta2), ele2->scEt); 
//	    errmc   = TMath::Max(zeeGsfSelEff_pos.getErrl(fabs(sceta2), ele2->scEt), zeeGsfSelEff_pos.getErrh(fabs(sceta2), ele2->scEt));
//	    Double_t errGsfSel = weight*corr*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
//	    hGsfSelErr_pos->Fill(fabs(sceta2), ele2->scEt, errGsfSel);
//
//	  } else {
//	    effdata = dataGsfSelEff_neg.getEff(fabs(sceta2), ele2->scEt);
//	    errdata = TMath::Max(dataGsfSelEff_neg.getErrl(fabs(sceta2), ele2->scEt), dataGsfSelEff_neg.getErrh(fabs(sceta2), ele2->scEt));
//            effmc   = zeeGsfSelEff_neg.getEff(fabs(sceta2), ele2->scEt); 
//	    errmc   = TMath::Max(zeeGsfSelEff_neg.getErrl(fabs(sceta2), ele2->scEt), zeeGsfSelEff_neg.getErrh(fabs(sceta2), ele2->scEt));
//	    Double_t errGsfSel = weight*corr*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
//	    hGsfSelErr_neg->Fill(fabs(sceta2), ele2->scEt, errGsfSel);
//	  }
        }
      }      
    }
    
//    Double_t err2=0;
//    for(Int_t iy=0; iy<=hGsfSelErr_pos->GetNbinsY(); iy++) {
//      for(Int_t ix=0; ix<=hGsfSelErr_pos->GetNbinsX(); ix++) {
//	err=hSelErr_pos->GetBinContent(ix,iy);
//	err2+=err*err;
//      }
//    }
//    for(Int_t iy=0; iy<=hGsfSelErr_neg->GetNbinsY(); iy++) {
//      for(Int_t ix=0; ix<=hGsfSelErr_neg->GetNbinsX(); ix++) {
//	err=hSelErr_neg->GetBinContent(ix,iy);
//	err2+=err*err;
//      }
//    }
//    effErr2v.push_back(err2);
    
    // compute acceptances
    accv.push_back(nSelv[ifile]/nEvtsv[ifile]);         accErrv.push_back(sqrt(accv[ifile]*(1.-accv[ifile])/nEvtsv[ifile]));
    accCorrv.push_back(nSelCorrv[ifile]/nEvtsv[ifile]); accCorrErrv.push_back(sqrt(accCorrv[ifile]*(1.-accCorrv[ifile])/nEvtsv[ifile]));
    
    delete infile;
    infile=0, eventTree=0;  
  }  
  delete info;
  delete gen;
  delete electronArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> e e" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << endl;
  
  for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {
    cout << "   ================================================" << endl;
    cout << "    Label: " << labelv[ifile] << endl;
    cout << "     File: " << fnamev[ifile] << endl;
    cout << endl;
    cout << "    *** Acceptance ***" << endl;
    cout << "          nominal: " << setw(12) << nSelv[ifile]   << " / " << nEvtsv[ifile] << " = " << accv[ifile]   << " +/- " << accErrv[ifile] << endl;
    cout << "     SF corrected: " << accCorrv[ifile] << " +/- " << accCorrErrv[ifile] << endl;
    cout << endl;
  }
  
  char txtfname[100];
  sprintf(txtfname,"%s/binned.txt",outputDir.Data());
  ofstream txtfile;
  txtfile.open(txtfname);
  txtfile << "*" << endl;
  txtfile << "* SUMMARY" << endl;
  txtfile << "*--------------------------------------------------" << endl;
  txtfile << " Z -> e e" << endl;
  txtfile << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  txtfile << "  pT > " << PT_CUT << endl;
  txtfile << "  |eta| < " << ETA_CUT << endl;
  txtfile << endl;
  
  for(UInt_t ifile=0; ifile<fnamev.size(); ifile++) {
    txtfile << "   ================================================" << endl;
    txtfile << "    Label: " << labelv[ifile] << endl;
    txtfile << "     File: " << fnamev[ifile] << endl;
    txtfile << endl;
    txtfile << "    *** Acceptance ***" << endl;
    txtfile << "          nominal: " << setw(12) << nSelv[ifile]   << " / " << nEvtsv[ifile] << " = " << accv[ifile]   << " +/- " << accErrv[ifile] << endl;
    txtfile << "     SF corrected: " << accCorrv[ifile] << " +/- " << accCorrErrv[ifile] << endl;
    txtfile << endl;
  }
  txtfile.close();
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("computeAccSelZeeBinned"); 
}
int ScanChain( TChain* chain, bool fast = true, int nEvents = -1, string skimFilePrefix = "test") {

  // Benchmark
  TBenchmark *bmark = new TBenchmark();
  bmark->Start("benchmark");

  // Example Histograms
  TDirectory *rootdir = gDirectory->GetDirectory("Rint:");
  /*
   // This loads the library
   TMVA::Tools::Instance();

   // to get access to the GUI and all tmva macros
   TString thisdir = gSystem->DirName(gInterpreter->GetCurrentMacroName());
   gROOT->SetMacroPath(thisdir + ":" + gROOT->GetMacroPath());
   gROOT->ProcessLine(".L TMVAGui.C");
*/

  map<string, TH1F*> histos; //massive
  vector<string> histonames; histonames.clear();
  vector<string> histonameshelp; histonameshelp.clear();
  vector<int> histobinn; histobinn.clear();
  vector<double> histobinl; histobinl.clear();
  vector<double> histobinu; histobinu.clear();
  map<string, float> value;

  histonames.push_back("MT2W");               histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(500.);
  //histonames.push_back("MT2_b_b");            histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("MT2_lb_b");           histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("MT2_lb_bq");          histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("MT2_lb_bqq");         histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(1000.);
  //histonames.push_back("MT2_l_q");            histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(300.);
  histonames.push_back("MT2_lb_b_mless");     histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("MT2_lb_bq_mless");    histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("MT2_lb_bqq_mless");   histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("MT2_l_qq_mless");     histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("Mlb");                histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("Mlbb");               histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(1000.);
  histonames.push_back("M3b");                histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(1000.);
  histonames.push_back("MTb");                histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("MTq");                histobinn.push_back(20); histobinl.push_back(0.); histobinu.push_back(500.);
  histonames.push_back("MTqmax");             histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(1500.);
  //histonames.push_back("MTq_boostmax");       histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(1500.);
  //histonames.push_back("MTq_boost300");       histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(1500.);
  histonames.push_back("MTq_boostLeadJet");   histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(1500.);
  //histonames.push_back("MTqq");               histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("Topness");            histobinn.push_back(30); histobinl.push_back(-15.); histobinu.push_back(15.);
  histonames.push_back("MT");                 histobinn.push_back(40); histobinl.push_back(0.); histobinu.push_back(400.);
  histonames.push_back("MET");                histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("HT");                 histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(1000.);
  histonames.push_back("METoverSqrtHT");      histobinn.push_back(20); histobinl.push_back(0.); histobinu.push_back(40.);
  histonames.push_back("HTratio");            histobinn.push_back(20); histobinl.push_back(0.); histobinu.push_back(1.);
  histonames.push_back("dRLepBJet");          histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(10.);
  histonames.push_back("dRbb");               histobinn.push_back(25); histobinl.push_back(0.); histobinu.push_back(10.);
  histonames.push_back("chi2");               histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(30.);
  histonames.push_back("NBJets");             histobinn.push_back( 5); histobinl.push_back(0.); histobinu.push_back(5.);
  histonames.push_back("NJets");              histobinn.push_back(10); histobinl.push_back(0.); histobinu.push_back(10.);
  //histonames.push_back("minDPhi");            histobinn.push_back(32); histobinl.push_back(0.); histobinu.push_back(3.2);
  histonames.push_back("minDPhiJ3");          histobinn.push_back(32); histobinl.push_back(0.); histobinu.push_back(3.2);
  //histonames.push_back("minDPhiB");           histobinn.push_back(32); histobinl.push_back(0.); histobinu.push_back(3.2);
  //histonames.push_back("pTlb");               histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(600.);
  histonames.push_back("pTlbb");              histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(600.);
  histonames.push_back("pTl");                histobinn.push_back(27); histobinl.push_back(0.); histobinu.push_back(405.);
  histonames.push_back("pTleadj");            histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("pTleadb");            histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("pTtrailb");           histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  //histonames.push_back("sumak8prunedmass");   histobinn.push_back(30); histobinl.push_back(0.); histobinu.push_back(750.);
  histonames.push_back("DeltaPhiWl");         histobinn.push_back(32); histobinl.push_back(0.); histobinu.push_back(3.2);

  TFile *outfile[3];
  TTree *outtree[3];
  for(unsigned int b = 0; b<histonames.size(); ++b){
    value[histonames[b] ] = -99;
    histonameshelp.push_back(histonames[b]+(string)"/F");
  }
  for(unsigned int b = 0; b<3; ++b){
    string samplename = skimFilePrefix;
    if(skimFilePrefix!="TTbar"&&b>0) continue;
    if(skimFilePrefix=="TTbar"&&b==0) samplename = "TTbar1l";
    if(skimFilePrefix=="TTbar"&&b==1) samplename = "TTbar2l";
    if(skimFilePrefix=="TTbar"&&b==2) samplename = "TTbarH";
    TString fileName = "rootfiles/TestmysmallBDTvartree_"+samplename+".root";
    outfile[b] = new TFile(fileName,"RECREATE");
    outtree[b] = new TTree(samplename.c_str(),"");
    for(unsigned int a = 0; a<histonames.size(); ++a){
      outtree[b]->Branch(histonames[a].c_str(), &value[histonames[a] ], histonameshelp[a].c_str() );
    }
  }



  // Loop over events to Analyze
  unsigned int nEventsTotal = 0;
  unsigned int nEventsChain = chain->GetEntries();
  if( nEvents >= 0 ) nEventsChain = nEvents;
  TObjArray *listOfFiles = chain->GetListOfFiles();
  TIter fileIter(listOfFiles);
  TFile *currentFile = 0;

  // File Loop
  while ( (currentFile = (TFile*)fileIter.Next()) ) {

    // Get File Content
    TFile *file = new TFile( currentFile->GetTitle() );
    TTree *tree = (TTree*)file->Get("t");
    if(fast) TTreeCache::SetLearnEntries(10);
    if(fast) tree->SetCacheSize(128*1024*1024);
    cms3.Init(tree);
    
    // Loop over Events in current file
    if( nEventsTotal >= nEventsChain ) continue;
    unsigned int nEventsTree = tree->GetEntriesFast();
    for( unsigned int event = 0; event < nEventsTree; ++event) {
 
      // Get Event Content
      if( nEventsTotal >= nEventsChain ) continue;
      if(fast) tree->LoadTree(event);
      cms3.GetEntry(event);
      ++nEventsTotal;
   
      // Progress
      CMS3::progress( nEventsTotal, nEventsChain );

      int sampleid = 0;
      string samplename = skimFilePrefix;
      if(skimFilePrefix=="TTbar"){
	if(cms3.gen_nfromtmus_() + cms3.gen_nfromtels_() + cms3.gen_nfromttaus_() ==2) { samplename = "TTbar2l"; sampleid=1; }
	else if(cms3.gen_nfromtmus_() + cms3.gen_nfromtels_() + cms3.gen_nfromttaus_() ==1) { samplename = "TTbar1l"; sampleid=0; }
	else { samplename = "TTbarH"; sampleid=2; }
      }
      // Analysis Code
      float weight = cms3.scale1fb()*10.;
      int NLeps = cms3.ngoodlep();
      string ds = cms3.dataset();
      float MET = cms3.pfmet();
      float METPhi = cms3.pfmet_phi();
      float METx = MET*TMath::Cos(METPhi);
      float METy = MET*TMath::Sin(METPhi);
      float MT2W = cms3.MT2W_lep1();
      float MT = cms3.MT_MET_lep1();
      float dRLepBJet = cms3.dR_lep1_leadb();
      float chi2 = cms3.chi2();
      //float genmet = cms3.genmet();
      //int NJets = cms3.ak4GoodPFJets();
      //int NBJets = cms3.ak4_nBTags_Med();
      float HT = cms3.ak4_HT();
      float HTratio = cms3.ak4_htratiom();
      int nvtxs = cms3.nvtxs();
      float minDPhi = cms3.mindphi_met_j1_j2();
      vector<ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > > jetslv = cms3.ak4pfjets_p4();
      vector<float> jetsbtag = cms3.ak4pfjets_btag_disc();
      vector<bool> jetsID = cms3.ak4pfjets_loose_pfid();
      ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > lep1lv = cms3.lep1_p4();
      float lep1pt = cms3.lep1_pt();
      float lep1eta = cms3.lep1_eta();
      //float lep1dr03isoDB = cms3.lep1_relIso03DB();
      bool lep1eIDl = cms3.lep1_is_eleid_loose();
      bool lep1eIDm = cms3.lep1_is_eleid_medium();
      bool lep1mIDt = cms3.lep1_is_muoid_tight();
      bool lep1ismu = cms3.lep1_is_mu();
      bool lep1isel = cms3.lep1_is_el();
      ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > lep2lv = cms3.lep1_p4();
      float lep2pt = cms3.lep2_pt();
      float lep2eta = cms3.lep2_eta();
      //float lep2dr03isoDB = cms3.lep2_relIso03DB();
      bool lep2eIDl = cms3.lep2_is_eleid_loose();
      bool lep2eIDm = cms3.lep2_is_eleid_medium();
      bool lep2mIDt = cms3.lep2_is_muoid_tight();
      bool lep2ismu = cms3.lep2_is_mu();
      bool lep2isel = cms3.lep2_is_el();
      
      bool trackveto = cms3.PassTrackVeto();
      bool tauveto = cms3.PassTauVeto();

      int NGLeps = 0;
      int NSLeps = 0;
      int NGJets = 0;
      int NGBJets = 0;

      int l1=-1;
      if(lep1ismu){
	//if(lep1pt>20&&fabs(lep1eta)<99&&lep1mIDt) ++NGLeps;
	//if(lep1pt>25&&fabs(lep1eta)<2.1&&lep1mIDt&&lep1dr03isoDB*lep1pt<TMath::Min(5.,0.15*lep1pt)) {++NSLeps; l1 = 1;}
	if(lep1pt>30&&fabs(lep1eta)<2.1&&fabs(cms3.lep1_d0())<0.02&&fabs(cms3.lep1_dz())<0.1&&cms3.lep1_miniRelIsoDB()<0.1) {++NSLeps; l1 = 1; }
      } else if (lep1isel){
	//if(lep1pt>20&&fabs(lep1eta)<99&&lep1eIDl) ++NGLeps;
	//if(lep1pt>30&&fabs(lep1eta)<1.442&&lep1eIDm&&lep1dr03isoDB*lep1pt<TMath::Min(5.,0.15*lep1pt)) {++NSLeps; l1 = 1;}
	if(lep1pt>40&&fabs(lep1eta)<2.1&&cms3.lep1_is_phys14_medium_noIso()&&cms3.lep1_miniRelIsoDB()<0.1) {++NSLeps; l1 = 1; }
      }
      if(lep2ismu){
	//if(lep2pt>20&&fabs(lep2eta)<99&&lep2mIDt) ++NGLeps;
	//if(lep2pt>25&&fabs(lep2eta)<2.1&&lep2mIDt&&lep2dr03isoDB*lep2pt<TMath::Min(5.,0.15*lep2pt)) {++NSLeps; if(l1!=1) l1 = 2; else l1=-2;}
	if(lep2pt>30&&fabs(lep2eta)<2.1&&fabs(cms3.lep2_d0())<0.02&&fabs(cms3.lep2_dz())<0.1&&cms3.lep2_miniRelIsoDB()<0.1) {++NSLeps; l1 = 1; if(l1!=1) l1 = 2; else l1=-2; }
      } else if (lep2isel){
	//if(lep2pt>20&&fabs(lep2eta)<99&&lep2eIDl) ++NGLeps;
	//if(lep2pt>30&&fabs(lep2eta)<1.442&&lep2eIDm&&lep2dr03isoDB*lep2pt<TMath::Min(5.,0.15*lep2pt)) {++NSLeps; if(l1!=1) l1 = 2; else l1=-2;}
	if(lep2pt>40&&fabs(lep2eta)<2.1&&cms3.lep2_is_phys14_medium_noIso()&&cms3.lep2_miniRelIsoDB()<0.1) {++NSLeps; if(l1!=1) l1 = 2; else l1=-2;}
      }
      NGLeps = NLeps;

      ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > leplv;
      if(l1==1) leplv = lep1lv;
      else if(l1==2) leplv = lep2lv;

      ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > metlv;
      metlv.SetPxPyPzE(METx,METy,0.,MET);

      //if(NGLeps != NLeps) cout << "NGLeps = " << NGLeps << " NLeps = " << NLeps << endl;
      //NGLeps = NLeps;
      vector<int> jind;
      vector<int> bind;
      ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > jsumlv;
      vector<ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > > jetlv;
      vector<ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > > boostjetlv;
      vector<ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> > > bjetlv;
      vector<float> btag;
      int jj1(-1), jj2(-1), jj3(-1);// j1(-1), j2(-1), jm(-1);
      float jj1d(-1), jj2d(-1), jj3d(-1);// jjmm(-1);
      for(unsigned int nj = 0; nj<jetsbtag.size(); ++nj){
	if(jetslv[nj].Pt()<30) continue;
	if(fabs(jetslv[nj].Eta())>2.4) continue;
	if(jetsID[nj]==false) continue;
	jind.push_back(nj);
	jetlv.push_back(jetslv[nj]);
	if(jetslv[nj].Pt()>250) boostjetlv.push_back(jetslv[nj]);
	btag.push_back(jetsbtag[nj]);
	++NGJets;
	if(jetsbtag[nj]>0.814) {++NGBJets; bind.push_back(nj); bjetlv.push_back(jetslv[nj]);}
	if(jetslv[nj].Pt()>jj1d){
	  jj3d = jj2d; jj2d = jj1d; jj1d = jetslv[nj].Pt();
	  jj3 = jj2; jj2 = jj1; jj1 = nj;
	} else if(jetslv[nj].Pt()>jj2d){
	  jj3d = jj2d; jj2d = jetslv[nj].Pt();
	  jj3 = jj2; jj2 = nj;
	} else if(jetslv[nj].Pt()>jj3d){
	  jj3d = jetslv[nj].Pt();
	  jj3 = nj;
	}
      }

      if(nvtxs<0) continue; 
      if(NGLeps!=1) continue; 
      if(NSLeps!=1) continue; 
      if(!trackveto) continue; 
      if(!tauveto) continue; 
      if(NGJets<4) continue;
      //if(NGBJets<1) continue; 
      if(MET<30) continue; 
      //if(MT>80) continue;

      for(unsigned int i = 0; i<histonames.size(); ++i){
	value[histonames[i] ] = -99;//reset values
      }
      //vector<LorentzVector > btaggedjets = JetUtil::BJetSelector(jetlv,btag,0.814,2,3,1);
      vector<LorentzVector > btaggedjets = JetUtil::BJetSelector(jetlv,btag,0.814,2,2,2);

      vector<LorentzVector > dummybjets;dummybjets.clear();
      LorentzVector dummybjet; dummybjet.SetPxPyPzE(0.,0.,0.,0.); dummybjets.push_back(dummybjet);dummybjets.push_back(dummybjet);
      
      //value["MT2W"]                  = CalculateMT2W_(btaggedjets,leplv,MET,METPhi,true);
      value["MT2W"] = MT2W;
      value["Topness"]               = Gettopness_(MET,METPhi,leplv,btaggedjets,1);
      value["MT2_b_b"]               = MT2_b_b_(MET,METPhi,btaggedjets,true, 0);
      value["MT2_lb_b_mless"]        = MT2_lb_b_(MET,METPhi,leplv,btaggedjets,false,0);
      value["MT2_lb_b"]              = MT2_lb_b_(MET,METPhi,leplv,btaggedjets,true ,0);
      value["MT2_lb_bq_mless"]       = MT2_lb_bq_( MET,METPhi,leplv,btaggedjets,jetlv,false,0);
      value["MT2_lb_bq"]             = MT2_lb_bq_( MET,METPhi,leplv,btaggedjets,jetlv,true ,0);
      value["MT2_lb_bqq_mless"]      = MT2_lb_bqq_(MET,METPhi,leplv,btaggedjets,jetlv,false,0);
      value["MT2_lb_bqq"]            = MT2_lb_bqq_(MET,METPhi,leplv,btaggedjets,jetlv,true ,0);
      value["MT2_l_q"]               = MT2_lb_bq_( MET,METPhi,leplv,dummybjets,jetlv,true ,0);
      value["MT2_l_qq_mless"]        = MT2_lb_bqq_(MET,METPhi,leplv,dummybjets,jetlv,true ,0);

      int leadb(-1), trailb(-1);
      for(unsigned int n = 0; n<btaggedjets.size();++n){
	if(leadb<0) leadb = n;
	else if(trailb<0) trailb = n;
	else if(btaggedjets[n].Pt() > btaggedjets[leadb].Pt()){ trailb = leadb; leadb = n; }
	else if(btaggedjets[n].Pt() > btaggedjets[trailb].Pt()){ trailb = n; }
	LorentzVector temp = btaggedjets[n]+leplv;
	if(temp.M()<value["Mlb"]) value["Mlb"] = temp.M();  else if(value["Mlb"]<0) value["Mlb"] = temp.M();
	if(temp.Pt()<value["pTlb"]) value["pTlb"] = temp.Pt();  else if(value["pTlb"]<0) value["pTlb"] = temp.Pt();
	float tmp = getMT(btaggedjets[n],metlv);
	if(tmp<value["MTb"]) value["MTb"] = tmp;  else if(value["MTb"]<0) value["MTb"] = tmp;
	tmp = JetUtil::deltaR(btaggedjets[n],leplv);
	tmp = JetUtil::deltaPhi(btaggedjets[n],metlv);
	if(tmp<value["minDPhiB"]) value["minDPhiB"] = tmp;  else if(value["minDPhiB"]<0) value["minDPhiB"] = tmp;
	for(unsigned int m = n+1; m<btaggedjets.size();++m){
	  temp = btaggedjets[n]+btaggedjets[m]+leplv;
	  if(temp.M()<value["Mlbb"]) value["Mlbb"] = temp.M();  else if(value["Mlbb"]<0) value["Mlbb"] = temp.M();
	  if(temp.Pt()<value["pTlbb"]) value["pTlbb"] = temp.Pt();  else if(value["pTlbb"]<0) value["pTlbb"] = temp.Pt();
	  tmp = JetUtil::deltaR(btaggedjets[n],btaggedjets[m]);
	  if(tmp<value["dRbb"]) value["dRbb"] = tmp;  else if(value["dRbb"]<0) value["dRbb"] = tmp;
	}
      }
      float myleadjpt = -1.;
      int bj1(-1), bj2(-1),bj3(-1);
      for(unsigned int n = 0; n<jetlv.size();++n){
	float tmp = getMT(jetlv[n],metlv);
  	if(tmp<value["MTq"]) value["MTq"] = tmp;  else if(value["MTq"]<0) value["MTq"] = tmp;
  	if(tmp>value["MTqmax"]) value["MTqmax"] = tmp;  else if(value["MTqmax"]<0) value["MTqmax"] = tmp;
	if(jetlv[n].Pt()>250.){ if(tmp>value["MTq_boostmax"]) value["MTq_boostmax"] = tmp;  else if(value["MTq_boostmax"]<0) value["MTq_boostmax"] = tmp; }
	if(jetlv[n].Pt()>300.){ if(tmp<value["MTq_boost300"]) value["MTq_boost300"] = tmp;  else if(value["MTq_boost300"]<0) value["MTq_boost300"] = tmp; }
	if(jetlv[n].Pt()>myleadjpt){ value["MTq_boostLeadJet"] = tmp; myleadjpt = jetlv[n].Pt(); }// else if(value["MTq_boostLeadJet"]<0) value["MTq_boostLeadJet"] = tmp;
	for(unsigned int m = n+1; m<jetlv.size();++m){
	  tmp = getMT(jetlv[n]+jetlv[m],metlv);
	  if(tmp<value["MTqq"]) value["MTqq"] = tmp;  else if(value["MTqq"]<0) value["MTqq"] = tmp;
	}
	if(n<3){
	  tmp = JetUtil::deltaPhi(jetlv[n],metlv);
	  if(tmp<value["minDPhiJ3"]) value["minDPhiJ3"] = tmp;  else if(value["minDPhiJ3"]<0) value["minDPhiJ3"] = tmp;
	}
	float dP1l(-1), dP2l(-1), dP3l(-1);
	if(bj1>0) dP1l = JetUtil::deltaPhi(jetlv[bj1],leplv);
	if(bj2>0) dP2l = JetUtil::deltaPhi(jetlv[bj2],leplv);
	if(bj3>0) dP3l = JetUtil::deltaPhi(jetlv[bj3],leplv);
	if(JetUtil::deltaPhi(jetlv[n],leplv)>dP1l){ bj3 = bj2; bj2 = bj1; bj1 = n;}
	else if(JetUtil::deltaPhi(jetlv[n],leplv)>dP2l){ bj3 = bj2; bj2 = n;}
	else if(JetUtil::deltaPhi(jetlv[n],leplv)>dP3l){ bj3 = n;}
      }

      LorentzVector bjsumlep = jetlv[bj1] + jetlv[bj2] + jetlv[bj3];
      value["M3b"] = bjsumlep.M();

      float prune=0.;
      for(unsigned int n = 0; n<cms3.ak8pfjets_pruned_mass().size();++n) prune += cms3.ak8pfjets_pruned_mass()[n];
      
      //cout << __LINE__<<endl;
      value["sumak8prunedmass"]   = prune;
      value["MT"] = MT;
      value["MET"] = MET;
      value["HT"] = HT;
      if(HT>0) {
	value["METoverSqrtHT"] = MET/TMath::Sqrt(HT);
      }
      value["HTratio"] = HTratio;
      value["dRLepBJet"] = dRLepBJet;
      value["chi2"] = chi2;
      value["NBJets"] = NGBJets;
      value["NJets"] = NGJets;
      value["minDPhi"] = minDPhi;
      value["pTl"] = leplv.Pt();
      value["pTleadj"] = myleadjpt;
      value["pTleadb"] = btaggedjets[leadb].Pt();
      value["pTtrailb"] = btaggedjets[trailb].Pt();
      value["DeltaPhiWl"] = JetUtil::deltaPhi(leplv,metlv+leplv);

      outtree[sampleid]->Fill();


      for(unsigned int i = 0; i<histonames.size(); ++i){
	value[histonames[i] ] = -99;//reset values
      }
    }
  
    // Clean Up
    delete tree;
    file->Close();
    delete file;
  }
  if ( nEventsChain != nEventsTotal ) {
    cout << Form( "ERROR: number of events from files (%d) is not equal to total number of events (%d)", nEventsChain, nEventsTotal ) << endl;
  }

  for(unsigned int b = 0; b<3; ++b){
    if(skimFilePrefix!="TTbar"&&b>0) continue;
    outfile[b]->cd();
    outtree[b]->Write();
    outfile[b]->Close();
    cout << "Tree for making BDT saved in " << outfile[b]->GetName() << endl;
  }

  // return
  bmark->Stop("benchmark");
  cout << endl;
  cout << nEventsTotal << " Events Processed" << endl;
  cout << "------------------------------" << endl;
  cout << "CPU  Time:	" << Form( "%.01f", bmark->GetCpuTime("benchmark")  ) << endl;
  cout << "Real Time:	" << Form( "%.01f", bmark->GetRealTime("benchmark") ) << endl;
  cout << endl;
  delete bmark;
  return 0;
}
Exemple #7
0
void Test() {
  
  TString bgdInputFile    = "samples/backgroundA_3l.root";
  TString dataInputFile   = "samples/data_3l.root";
  TString sigInputFile   =  "samples/hww125.root";
  
  SmurfTree background;
  background.LoadTree(bgdInputFile,-1);
  background.InitTree(0);
  
  SmurfTree data;
  data.LoadTree(dataInputFile,-1);
  data.InitTree(0);
  
  SmurfTree signal;
  signal.LoadTree(sigInputFile,-1);
  signal.InitTree(0);
  
  char output[200];
  sprintf(output,"histo_test.root");     
  TFile* outFileNjets = new TFile(output,"recreate");
  
  TH1F* types = new TH1F("types", "types", 80, -0.5 , 79.5);
  types->Sumw2();
  
  TH1D* bckg_met = new TH1D("bckg_met", "MET", 200, 0, 200);
  bckg_met->Sumw2();
  TH1D* bckg_mllz = new TH1D("bckg_mllz", "m_{ll}", 200, 0, 200);
  bckg_mllz->Sumw2();
  TH1D* bckg_mt = new TH1D("bckg_mt", "m_t", 200, 0, 200);
  bckg_mt->Sumw2();
  TH1D* bckg_ptjet = new TH1D("bckg_ptjet", "P_t of leading jet", 200, 0, 200);
  bckg_ptjet->Sumw2();
  TH1D* bckg_mH = new TH1D("bckg_mH", "m_H", 200, 0, 400);
  bckg_mH->Sumw2();
  TH1D* bckg_mjj = new TH1D("bckg_mjj", "m_jj", 200, 0, 400);
  bckg_mjj->Sumw2();
  TH1D* bckg_dphill = new TH1D("bckg_dphill", "#Delta#phi_{ll}", 200, 0, 3.5);
  bckg_dphill->Sumw2();
  
  TH2D* bckg_mll_mh  = new TH2D("bckg_mll_mh", " ", 100, 40, 120, 100, 0, 200);
  
  TH1D* sig_met = new TH1D("sig_met", "MET", 200, 0, 200);
  sig_met->Sumw2();
  TH1D* sig_mllz = new TH1D("sig_mllz", "m_{ll}", 200, 0, 200);
  sig_mllz->Sumw2();
  TH1D* sig_mt = new TH1D("sig_mt", "m_t", 200, 0, 200);
  sig_mt->Sumw2();
  TH1D* sig_ptjet = new TH1D("sig_ptjet", "P_t of leading jet", 200, 0, 200);
  sig_ptjet->Sumw2();
  TH1D* sig_mH = new TH1D("sig_mH", "m_H", 200, 0, 400);
  sig_mH->Sumw2();
  TH1D* sig_mjj = new TH1D("sig_mjj", "m_jj", 200, 0, 400);
  sig_mjj->Sumw2();
  TH1D* sig_dphill = new TH1D("sig_dphill", "#Delta#phi_{ll}", 200, 0, 3.5);
  sig_dphill->Sumw2();

  TH2D* sig_mll_mh  = new TH2D("sig_mll_mh", " ",100, 40, 120, 100, 0, 200);
  

  double lumi = 12.1;
  double weight = 1;
  double eventsPass = 0;
  int nBgd=background.tree_->GetEntries();
  for (int i=0; i<nBgd; ++i) {
    
    if (i%100000 == 0 && verboseLevel > 0)
      printf("--- reading event %5d of %5d\n",i,nBgd);
    background.tree_->GetEntry(i);
    if (background.njets_ <2 )continue;
    if (!((background.cuts_ & SmurfTree::Lep1FullSelection) == SmurfTree::Lep1FullSelection 
	  && (background.cuts_ & SmurfTree::Lep2FullSelection) == SmurfTree::Lep2FullSelection) ) continue;
  
    weight = 1;
    
    int nFake = 0;
    if(((background.cuts_ & SmurfTree::Lep1LooseMuV2)  == SmurfTree::Lep1LooseMuV2)  && (background.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((background.cuts_ & SmurfTree::Lep2LooseMuV2)  == SmurfTree::Lep2LooseMuV2)  && (background.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((background.cuts_ & SmurfTree::Lep3LooseMuV2)  == SmurfTree::Lep3LooseMuV2)  && (background.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if(((background.cuts_ & SmurfTree::Lep1LooseEleV4) == SmurfTree::Lep1LooseEleV4) && (background.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((background.cuts_ & SmurfTree::Lep2LooseEleV4) == SmurfTree::Lep2LooseEleV4) && (background.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((background.cuts_ & SmurfTree::Lep3LooseEleV4) == SmurfTree::Lep3LooseEleV4) && (background.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if (nFake !=0) continue; 
    
    if (nFake > 1) continue; 
    if (nFake == 1) weight = lumi*background.scale1fb_*background.sfWeightPU_*background.sfWeightEff_*background.sfWeightTrig_*background.sfWeightFR_ ;
    else weight = lumi*background.scale1fb_*background.sfWeightPU_*background.sfWeightEff_*background.sfWeightTrig_;
    //weight = lumi*background.scale1fb_*background.sfWeightPU_*background.sfWeightEff_*background.sfWeightTrig_;
  
    if (background.lid3_ == background.lid2_ && background.lid3_ == background.lid1_) continue;
    if (background.lid3_ == background.lid2_ && fabs(background.lid3_) != fabs(background.lid1_)) continue;
    if (background.lid3_ == background.lid1_ && fabs(background.lid3_) != fabs(background.lid2_)) continue;
    if (background.lid2_ == background.lid1_ && fabs(background.lid2_) != fabs(background.lid3_)) continue;
    
    
    double m[3] = {0, 0, 0};
    LorentzVector pair1, pair2, pair3;
    if (fabs(background.lid1_) == fabs(background.lid2_) && background.lq1_*background.lq2_ < 0){
      pair1 = background.lep1_ + background.lep2_ ;
      m[0] = pair1.M();
    }
    if (fabs(background.lid2_) == fabs(background.lid3_) && background.lq2_*background.lq3_ < 0){
      pair2 = background.lep2_ + background.lep3_ ;
      m[1] = pair2.M();
    }
    if (fabs(background.lid1_) == fabs(background.lid3_) && background.lq1_*background.lq3_ < 0){
      pair3 = background.lep1_ + background.lep3_ ;
      m[2] = pair3.M();
    }
    
    if ( (m[0] < 80 || m[0] > 100) &&  (m[1] < 80 || m[1] > 100) &&  (m[2] < 80 || m[2] > 100)) continue;
    //if ( (m[0] < 40 || m[0] > 120) &&  (m[1] < 40 || m[1] > 120) &&  (m[2] < 40 || m[2] > 120)) continue;
    
    double min = TMath::Min(TMath::Min(fabs(mz -m[0]), fabs(mz-m[1])), TMath::Min(fabs(mz -m[0]), fabs(mz-m[2])));
   
    LorentzVector pair, tlepton, pairjet;
    double mt = 0;
    if (min == fabs(mz - m[0])){  pair = pair1; mt =  background.mt3_; tlepton = background.lep3_;} 
    else if (min == fabs(mz - m[1])){  pair = pair2;  mt =  background.mt1_; tlepton = background.lep1_;} 
    else if (min == fabs(mz - m[2])){  pair = pair3;  mt =  background.mt2_; tlepton = background.lep2_;} 
    pairjet = background.jet1_+ background.jet2_;
    
    if (mt < 40 || background.met_ < 25) continue;
    //     if (mt < 40 ) continue;

    // if (pairjet.M() < 65 || pairjet.M() > 95) continue;
  
    types->Fill(background.dstype_);
    bckg_met->Fill(background.met_, weight);
    bckg_mllz->Fill(pair.M(), weight);
    bckg_mt->Fill(mt, weight);
    bckg_ptjet->Fill(background.jet1_.Pt(), weight);
    LorentzVector metvector(background.met_*cos(background.metPhi_), background.met_*sin(background.metPhi_), 0, 0);
    LorentzVector higgsSystem = tlepton + metvector + background.jet1_  + background.jet2_;
    bckg_mH->Fill(higgsSystem.M(), weight);
    bckg_mjj->Fill(pairjet.M(), weight);
    bckg_dphill->Fill(DeltaPhi(pairjet.Phi(),tlepton.Phi()), weight);
    bckg_mll_mh->Fill(pair.M(),higgsSystem.M(), weight); 
    eventsPass += weight;
 
  }
  cout << eventsPass << " background events in " << lumi << " fb" << endl; 
  
  
  int nSig=signal.tree_->GetEntries();
  int nTotal = 0;
  int nZH = 0;
  double eventsPassSig = 0;
  for (int i=0; i<nSig; ++i) {
    
    if (i%100000 == 0 && verboseLevel > 0)
      printf("--- reading event %5d of %5d\n",i,nSig);
    signal.tree_->GetEntry(i);
    
    nTotal++;
    if(signal.processId_==24)  nZH++;
    
    if (signal.njets_ < 2 )continue;

    if(!((signal.cuts_ & SmurfTree::Lep1FullSelection) == SmurfTree::Lep1FullSelection 
	 &&(signal.cuts_ & SmurfTree::Lep2FullSelection) == SmurfTree::Lep2FullSelection)) continue;
     
    
     
    weight = 1;
    
    int nFake = 0;
    if(((signal.cuts_ & SmurfTree::Lep1LooseMuV2)  == SmurfTree::Lep1LooseMuV2)  && (signal.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((signal.cuts_ & SmurfTree::Lep2LooseMuV2)  == SmurfTree::Lep2LooseMuV2)  && (signal.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((signal.cuts_ & SmurfTree::Lep3LooseMuV2)  == SmurfTree::Lep3LooseMuV2)  && (signal.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if(((signal.cuts_ & SmurfTree::Lep1LooseEleV4) == SmurfTree::Lep1LooseEleV4) && (signal.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((signal.cuts_ & SmurfTree::Lep2LooseEleV4) == SmurfTree::Lep2LooseEleV4) && (signal.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((signal.cuts_ & SmurfTree::Lep3LooseEleV4) == SmurfTree::Lep3LooseEleV4) && (signal.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;

    weight = lumi*signal.scale1fb_*signal.sfWeightPU_*signal.sfWeightEff_*signal.sfWeightTrig_;
    
    
    if (signal.lid3_ == signal.lid2_ && signal.lid3_ == signal.lid1_) continue;
    if (signal.lid3_ == signal.lid2_ && fabs(signal.lid3_) != fabs(signal.lid1_)) continue;
    if (signal.lid3_ == signal.lid1_ && fabs(signal.lid3_) != fabs(signal.lid2_)) continue;
    if (signal.lid2_ == signal.lid1_ && fabs(signal.lid2_) != fabs(signal.lid3_)) continue;
    
    double m[3] = {0, 0, 0};
    LorentzVector pair1, pair2, pair3;
    if (fabs(signal.lid1_) == fabs(signal.lid2_) && signal.lq1_*signal.lq2_ < 0){
      pair1 = signal.lep1_ + signal.lep2_ ;
      m[0] = pair1.M();
    }
    if (fabs(signal.lid2_) == fabs(signal.lid3_) && signal.lq2_*signal.lq3_ < 0){
      pair2 = signal.lep2_ + signal.lep3_ ;
      m[1] = pair2.M();
    }
    if (fabs(signal.lid1_) == fabs(signal.lid3_) && signal.lq1_*signal.lq3_ < 0){
      pair3 = signal.lep1_ + signal.lep3_ ;
      m[2] = pair3.M();
    }
    
    if ( (m[0] < 80 || m[0] > 100) &&  (m[1] < 80 || m[1] > 100) &&  (m[2] < 80 || m[2] > 100)) continue;
    //   if ( (m[0] < 40 || m[0] > 120) &&  (m[1] < 40 || m[1] > 120) &&  (m[2] < 40 || m[2] > 120)) continue;
        
    double min = TMath::Min(TMath::Min(fabs(mz -m[0]), fabs(mz-m[1])), TMath::Min(fabs(mz -m[0]), fabs(mz-m[2])));
    
    LorentzVector pair, tlepton, pairjet;
    double mt = 0;
    if (min == fabs(mz - m[0])){  pair = pair1; mt =  signal.mt3_; tlepton = signal.lep3_;} 
    else if (min == fabs(mz - m[1])){  pair = pair2;  mt =  signal.mt1_; tlepton = signal.lep1_;} 
    else if (min == fabs(mz - m[2])){  pair = pair3;  mt =  signal.mt2_; tlepton = signal.lep2_;} 
    pairjet = signal.jet1_+ signal.jet2_;
        
     
    if (mt < 40 || signal.met_ < 25) continue;
    // if (mt < 40 ) continue;
    //if (pairjet.M() < 65 || pairjet.M() > 95) continue;
    
    types->Fill(signal.dstype_);
    sig_met->Fill(signal.met_, weight);
    sig_mllz->Fill(pair.M(), weight);
    sig_mt->Fill(mt, weight);
    sig_ptjet->Fill(signal.jet1_.Pt(), weight);  
    LorentzVector metvector(signal.met_*cos(signal.metPhi_), signal.met_*sin(signal.metPhi_), 0, 0);
    LorentzVector higgsSystem = tlepton + metvector + signal.jet1_  + signal.jet2_;
    sig_mH->Fill(higgsSystem.M(), weight);
    sig_mjj->Fill(pairjet.M(), weight);
    sig_dphill->Fill(DeltaPhi(pairjet.Phi(),tlepton.Phi()), weight);
    sig_mll_mh->Fill(pair.M(),higgsSystem.M(), weight); 
    //    cout << signal.njets_ << " - " ;
    eventsPassSig += weight;
  }
  cout << endl;
  
  cout << eventsPassSig << " signal events in " << lumi << " fb" << endl; 
  cout << nTotal << "events, from which " << nZH << "are ZH" << endl;
  int nData=data.tree_->GetEntries();
  double eventsPassData = 0;
  for (int i=0; i<nData; ++i) {
    
    if (i%100000 == 0 && verboseLevel > 0)
      printf("--- reading event %5d of %5d\n",i,nData);
    data.tree_->GetEntry(i);
    if (data.njets_ < 2 )continue;

    if(!((data.cuts_ & SmurfTree::Lep1FullSelection) == SmurfTree::Lep1FullSelection 
	 && (data.cuts_ & SmurfTree::Lep2FullSelection) == SmurfTree::Lep2FullSelection)) continue;

    
    weight = 1;

    int nFake = 0;
    if(((data.cuts_ & SmurfTree::Lep1LooseMuV2)  == SmurfTree::Lep1LooseMuV2)  && (data.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((data.cuts_ & SmurfTree::Lep2LooseMuV2)  == SmurfTree::Lep2LooseMuV2)  && (data.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((data.cuts_ & SmurfTree::Lep3LooseMuV2)  == SmurfTree::Lep3LooseMuV2)  && (data.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if(((data.cuts_ & SmurfTree::Lep1LooseEleV4) == SmurfTree::Lep1LooseEleV4) && (data.cuts_ & SmurfTree::Lep1FullSelection) != SmurfTree::Lep1FullSelection) nFake++;
    if(((data.cuts_ & SmurfTree::Lep2LooseEleV4) == SmurfTree::Lep2LooseEleV4) && (data.cuts_ & SmurfTree::Lep2FullSelection) != SmurfTree::Lep2FullSelection) nFake++;
    if(((data.cuts_ & SmurfTree::Lep3LooseEleV4) == SmurfTree::Lep3LooseEleV4) && (data.cuts_ & SmurfTree::Lep3FullSelection) != SmurfTree::Lep3FullSelection) nFake++;
    if (nFake !=0) continue; 
 
    if (data.lid3_ == data.lid2_ && data.lid3_ == data.lid1_) continue;
    if (data.lid3_ == data.lid2_ && fabs(data.lid3_) != fabs(data.lid1_)) continue;
    if (data.lid3_ == data.lid1_ && fabs(data.lid3_) != fabs(data.lid2_)) continue;
    if (data.lid2_ == data.lid1_ && fabs(data.lid2_) != fabs(data.lid3_)) continue;
    
    double m[3] = {0, 0, 0};
    LorentzVector pair1, pair2, pair3;
    if (fabs(data.lid1_) == fabs(data.lid2_) && data.lq1_*data.lq2_ < 0){
      pair1 = data.lep1_ + data.lep2_ ;
      m[0] = pair1.M();
    }
    if (fabs(data.lid2_) == fabs(data.lid3_) && data.lq2_*data.lq3_ < 0){
      pair2 = data.lep2_ + data.lep3_ ;
      m[1] = pair2.M();
    }
    if (fabs(data.lid1_) == fabs(data.lid3_) && data.lq1_*data.lq3_ < 0){
      pair3 = data.lep1_ + data.lep3_ ;
      m[2] = pair3.M();
    }
    
    if ( (m[0] < 80 || m[0] > 100) &&  (m[1] < 80 || m[1] > 100) &&  (m[2] < 80 || m[2] > 100)) continue;
    //   if ( (m[0] < 40 || m[0] > 120) &&  (m[1] < 40 || m[1] > 120) &&  (m[2] < 40 || m[2] > 120)) continue;    
    double min = TMath::Min(TMath::Min(fabs(mz -m[0]), fabs(mz-m[1])), TMath::Min(fabs(mz -m[0]), fabs(mz-m[2])));
    
    LorentzVector pair, tlepton, pairjet;
    double mt = 0;
    if (min == fabs(mz - m[0])){  pair = pair1; mt =  data.mt3_; tlepton = data.lep3_;} 
    else if (min == fabs(mz - m[1])){  pair = pair2;  mt =  data.mt1_; tlepton = data.lep1_;} 
    else if (min == fabs(mz - m[2])){  pair = pair3;  mt =  data.mt2_; tlepton = data.lep2_;} 
    pairjet = data.jet1_+ data.jet2_;
        
    
    if (mt < 40 || data.met_ < 25) continue;
    //   if (mt < 40 ) continue;
    //  if (pairjet.M() < 65 || pairjet.M() > 95) continue;

    eventsPassData += weight;
  }
  
  cout << eventsPassData << " data events in " << lumi << " fb" << endl; 

  outFileNjets->Write();
  outFileNjets->Close();
  
  
}
Exemple #8
0
void selectProbesMuEff(const TString infilename,           // input ntuple
                       const TString outputDir, 	   // output directory
		       const Int_t   effType, 	           // type of efficiency to compute
		       const Bool_t  doGenMatch = kFALSE,  // match to generator leptons
		       const Bool_t  doWeighted = kFALSE   // store events with weights
) {
  gBenchmark->Start("selectProbesMuEff");
  
  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //==============================================================================================================   
 
  const Double_t TAG_PT_CUT = 25;
  

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  enum { eHLTEff, eSelEff, eTrkEff, eStaEff, eStaEff_iso, ePOGIDEff, ePOGIsoEff };
  if(effType > ePOGIsoEff) {
    cout << "Invalid effType option! Exiting..." << endl;
    return;
  }
  
  enum { eMuMu2HLT=1, eMuMu1HLT, eMuMuNoSel, eMuSta, eMuTrk };  // event category enum
  
  Double_t nProbes = 0;
  
  //
  // Set up output ntuple
  //
  gSystem->mkdir(outputDir,kTRUE);
  TFile *outFile = new TFile(outputDir+TString("/probes.root"),"RECREATE"); 
  TTree *outTree = new TTree("Events","Events");
  EffData data;
  outTree->Branch("Events",&data.mass,"mass/F:pt:eta:phi:weight:q/I:npv/i:npu:pass:runNum:lumiSec:evtNum");

  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, u1, u2;
  Int_t   q1, q2;
  LorentzVector *dilep=0, *lep1=0, *lep2=0;
  LorentzVector *sta1=0, *sta2=0;
  Float_t pfCombIso1, pfCombIso2;
  Float_t d01, dz1, d02, dz2;
  Float_t muNchi21,  muNchi22;
  UInt_t nPixHits1, nTkLayers1, nPixHits2, nTkLayers2;
  UInt_t nValidHits1, nMatch1, nValidHits2, nMatch2;
  UInt_t typeBits1, typeBits2;

  // Read input file and get the TTrees
  cout << "Processing " << infilename << "..." << endl;
  TFile *infile = new TFile(infilename);	 assert(infile);
  TTree *intree = (TTree*)infile->Get("Events"); assert(intree);

  intree->SetBranchAddress("runNum",     &runNum);      // event run number
  intree->SetBranchAddress("lumiSec",    &lumiSec);     // event lumi section
  intree->SetBranchAddress("evtNum",     &evtNum);      // event number
  intree->SetBranchAddress("matchGen",   &matchGen);    // event has both leptons matched to MC Z->ll
  intree->SetBranchAddress("category",   &category);    // dilepton category
  intree->SetBranchAddress("npv",        &npv);	        // number of primary vertices
  intree->SetBranchAddress("npu",        &npu);	        // number of in-time PU events (MC)
  intree->SetBranchAddress("scale1fb",   &scale1fb);    // event weight per 1/fb (MC)
  intree->SetBranchAddress("met",        &met);	        // MET
  intree->SetBranchAddress("metPhi",     &metPhi);      // phi(MET)
  intree->SetBranchAddress("sumEt",      &sumEt);       // Sum ET
  intree->SetBranchAddress("u1",         &u1);	        // parallel component of recoil
  intree->SetBranchAddress("u2",         &u2);	        // perpendicular component of recoil
  intree->SetBranchAddress("q1",         &q1);	        // charge of tag lepton
  intree->SetBranchAddress("q2",         &q2);	        // charge of probe lepton
  intree->SetBranchAddress("dilep",      &dilep);       // dilepton 4-vector
  intree->SetBranchAddress("lep1",       &lep1);        // tag lepton 4-vector
  intree->SetBranchAddress("lep2",       &lep2);        // probe lepton 4-vector
  intree->SetBranchAddress("sta1",       &sta1);        // tag STA muon 4-vector
  intree->SetBranchAddress("sta2",       &sta2);        // probe STA muon 4-vector 
  intree->SetBranchAddress("pfCombIso1", &pfCombIso1);  // PF combined isolation of tag lepton
  intree->SetBranchAddress("pfCombIso2", &pfCombIso2);  // PF combined isolation of probe lepton    
  intree->SetBranchAddress("d01",        &d01); 	// transverse impact parameter of tag lepton
  intree->SetBranchAddress("d02",	 &d02); 	// transverse impact parameter of probe lepton      
  intree->SetBranchAddress("dz1",	 &dz1); 	// longitudinal impact parameter of tag lepton
  intree->SetBranchAddress("dz2",	 &dz2); 	// longitudinal impact parameter of probe lepton    
  intree->SetBranchAddress("muNchi21",	 &muNchi21);	// muon fit normalized chi^2 of tag lepton
  intree->SetBranchAddress("muNchi22",	 &muNchi22);	// muon fit normalized chi^2 of probe lepton	 
  intree->SetBranchAddress("nPixHits1",  &nPixHits1);   // number of pixel hits of tag muon
  intree->SetBranchAddress("nPixHits2",  &nPixHits2);   // number of pixel hits of probe muon
  intree->SetBranchAddress("nTkLayers1", &nTkLayers1);  // number of tracker layers of tag muon
  intree->SetBranchAddress("nTkLayers2", &nTkLayers2);  // number of tracker layers of probe muon
  intree->SetBranchAddress("nMatch1",	 &nMatch1);	// number of matched segments of tag muon
  intree->SetBranchAddress("nMatch2",	 &nMatch2);	// number of matched segments of probe muon    
  intree->SetBranchAddress("nValidHits1",&nValidHits1); // number of valid muon hits of tag muon
  intree->SetBranchAddress("nValidHits2",&nValidHits2); // number of valid muon hits of probe muon
  intree->SetBranchAddress("typeBits1",  &typeBits1);   // muon type of tag muon
  intree->SetBranchAddress("typeBits2",  &typeBits2);   // muon type of probe muon

  //
  // loop over events
  //
  for(UInt_t ientry=0; ientry<intree->GetEntries(); ientry++) {
    intree->GetEntry(ientry);

    if(lep1->Pt() < TAG_PT_CUT) continue;
    
    // check GEN match if necessary
    if(doGenMatch && !matchGen) continue;
    
    Bool_t  pass=kFALSE;
    Float_t mass=0;
    
    if(effType==eHLTEff) {
      //
      // probe = muon passing selection
      // pass  = matched to HLT
      // * MuMu2HLT event means a passing probe, MuMu1HLT event means a failing probe
      //   all other categories do not satisfy probe requirements
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kFALSE; }
      else if(category==eMuMuNoSel) { continue; }
      else if(category==eMuSta)     { continue; }
      else                          { continue; }
      
      mass = dilep->M();
    
    } else if(effType==eSelEff) {
      //
      // probe = GLB muon
      // pass  = passing selection
      // * MuMu2HLT, MuMu1HLT event means a passing probe, MuMuNoSel event means a failing probe,
      //   all other categories do not satisfy probe requirements
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) { pass=kFALSE; }
      else if(category==eMuSta)     { continue; }
      else                          { continue; }
      
      mass = dilep->M();
    
    } else if(effType==eTrkEff) {
      //
      // probe = STA muon
      // pass  = is also a GLB muon
      // * MuMu2HLT, MuMu1HLT, MuMuNoSel event means a passing probe, MuSta event means a failing probe, 
      //   MuTrk event does not satisfy probe requirements
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) { pass=kTRUE; }
      else if(category==eMuSta)     { pass=kFALSE; }
      else                          { continue; }
      
      // compute mass using probe STA muon pT
      LorentzVector tp = *lep1 + *sta2;
      mass = tp.M();    
    
    } else if(effType==eStaEff) {
      //
      // probe = tracker track
      // pass  = is also a GLB muon
      // * MuMu2HLT, MuMu1HLT, MuMuNoSel event means a passing probe, MuTrk event means a failing probe, 
      //   MuSta event does not satisfy probe requirements
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) { pass=kTRUE; }
      else if(category==eMuSta)     { continue; }
      else                          { pass=kFALSE; }
      
      mass = dilep->M();
    
    } else if(effType==eStaEff_iso) {
      //
      // probe = isolated tracker track
      // pass  = is also a GLB muon
      // * MuMu2HLT, MuMu1HLT, isolated MuMuNoSel event means a passing probe, isolated MuTrk event means a failing probe, 
      //   MuSta, non-isolated MuMuNoSel, and non-isolated MuTrk events do not satisfy probe requirements
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) { if(pfCombIso2>0.12*(lep2->Pt())) continue; else pass=kTRUE; }
      else if(category==eMuSta)     { continue; }
      else                          { if(pfCombIso2>0.12*(lep2->Pt())) continue; else pass=kFALSE; }
      
      mass = dilep->M();
    
    } else if(effType==ePOGIDEff) {
      //
      // probe = tracker track
      // pass  = passes "tight" muon ID
      // * 
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) { 
        
	pass=kTRUE; 
        if(nTkLayers2  < 6)   pass=kFALSE;
        if(nPixHits2   < 1)   pass=kFALSE;
        if(fabs(d02)   > 0.2) pass=kFALSE;
        if(fabs(dz2)   > 0.5) pass=kFALSE;
        if(muNchi22    > 10)  pass=kFALSE;
        if(nMatch2     < 2)   pass=kFALSE;
        if(nValidHits2 < 1)   pass=kFALSE;
        if(!(typeBits2 & 1))  pass=kFALSE;
        if(!(typeBits2 & 8))  pass=kFALSE;
      }
      else if(category==eMuSta)     { continue; }
      else                          { pass=kFALSE; }
      
      mass = dilep->M();    
    
    } else if(effType==ePOGIsoEff) {
      //
      // probe = "tight" muon
      // pass  = passes isolation
      // * 
      //    
      if     (category==eMuMu2HLT)  { pass=kTRUE; }
      else if(category==eMuMu1HLT)  { pass=kTRUE; }
      else if(category==eMuMuNoSel) {
        
	if(nTkLayers2  < 6)   continue;
        if(nPixHits2   < 1)   continue;
        if(fabs(d02)   > 0.2) continue;
        if(fabs(dz2)   > 0.5) continue;
        if(muNchi22    > 10)  continue;
        if(nMatch2     < 2)   continue;
        if(nValidHits2 < 1)   continue;
        if(!(typeBits2 & 1))  continue;
        if(!(typeBits2 & 8))  continue;

	pass = (pfCombIso2 < 0.12*(lep2->Pt()));      
      }
      else if(category==eMuSta)     { continue; }
      else                          { continue; }
      
      mass = dilep->M();    
    }
    
    nProbes += doWeighted ? scale1fb : 1;

    // Fill tree
    data.mass	 = mass;
    data.pt	 = (effType==eTrkEff) ? sta2->Pt()  : lep2->Pt();
    data.eta	 = (effType==eTrkEff) ? sta2->Eta() : lep2->Eta();
    data.phi	 = (effType==eTrkEff) ? sta2->Phi() : lep2->Phi();
    data.weight  = doWeighted ? scale1fb : 1;
    data.q	 = q2;
    data.npv	 = npv;
    data.npu	 = npu;
    data.pass	 = (pass) ? 1 : 0;
    data.runNum  = runNum;
    data.lumiSec = lumiSec;
    data.evtNum  = evtNum;
    outTree->Fill();
    
    if(category==eMuMu2HLT) {
      if(lep2->Pt() < TAG_PT_CUT) continue;

      nProbes += doWeighted ? scale1fb : 1;

      data.mass	   = mass;
      data.pt	   = (effType==eTrkEff) ? sta1->Pt()  : lep1->Pt();
      data.eta	   = (effType==eTrkEff) ? sta1->Eta() : lep1->Eta();
      data.phi	   = (effType==eTrkEff) ? sta1->Phi() : lep1->Phi();
      data.weight  = doWeighted ? scale1fb : 1;
      data.q	   = q1;
      data.npv	   = npv;
      data.npu	   = npu;
      data.pass	   = 1;
      data.runNum  = runNum;
      data.lumiSec = lumiSec;
      data.evtNum  = evtNum;
      outTree->Fill();
    } 
  }  
  delete infile;
  infile=0, intree=0;	   


  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << endl;

  cout << " Number of probes selected: " << nProbes << endl;
  
  outFile->Write();
  outFile->Close();
  delete outFile;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectProbesMuEff"); 
}
Exemple #9
0
void selectZee(const TString conf,        // input file
               const TString outputDir,   // output directory
	       const Bool_t  doScaleCorr  // apply energy scale corrections?
) {
  gBenchmark->Start("selectZee");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 20;
  const Double_t ETA_CUT   = 2.5;
  const Double_t ELE_MASS  = 0.000511;
  
  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;
  
  const Double_t escaleNbins  = 6;
  const Double_t escaleEta[]  = { 0.4,     0.8,     1.2,     1.4442,  2,        2.5 };
  const Double_t escaleCorr[] = { 1.00284, 1.00479, 1.00734, 1.00851, 1.00001,  0.982898 };


  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  

  enum { eEleEle2HLT=1, eEleEle1HLT, eEleEleNoSel, eEleSC };  // event category enum
  
  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
  const Bool_t hasData = (samplev[0]->fnamev.size()>0);

  // Create output directory
  gSystem->mkdir(outputDir,kTRUE);
  const TString ntupDir = outputDir + TString("/ntuples");
  gSystem->mkdir(ntupDir,kTRUE);
  
  //
  // Declare output ntuple variables
  //
  UInt_t  runNum, lumiSec, evtNum;
  UInt_t  matchGen;
  UInt_t  category;
  UInt_t  npv, npu;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, u1, u2;
  Int_t   q1, q2;
  LorentzVector *dilep=0, *lep1=0, *lep2=0;
  ///// electron specific /////
  Float_t trkIso1, emIso1, hadIso1, trkIso2, emIso2, hadIso2;
  Float_t pfChIso1, pfGamIso1, pfNeuIso1, pfCombIso1, pfChIso2, pfGamIso2, pfNeuIso2, pfCombIso2;
  Float_t sigieie1, hovere1, eoverp1, fbrem1, ecalE1, sigieie2, hovere2, eoverp2, fbrem2, ecalE2;
  Float_t dphi1, deta1, dphi2, deta2;
  Float_t d01, dz1, d02, dz2;
  UInt_t  isConv1, nexphits1, typeBits1, isConv2, nexphits2, typeBits2; 
  LorentzVector *sc1=0, *sc2=0;
  
  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  mithep::TGenInfo   *gen   = new mithep::TGenInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  TClonesArray *scArr       = new TClonesArray("mithep::TPhoton");
  TClonesArray *pvArr       = new TClonesArray("mithep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
  
  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume data sample is first sample in .conf file
    // If sample is empty (i.e. contains no ntuple files), skip to next sample
    if(isam==0 && !hasData) continue;
    
    // Assume signal sample is given name "zee"
    // If it's the signal sample, toggle flag to store GEN W kinematics
    Bool_t isSignal = (snamev[isam].CompareTo("zee",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.root");
    if(isam==0 && !doScaleCorr) outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.raw.root");
    TFile *outFile = new TFile(outfilename,"RECREATE"); 
    TTree *outTree = new TTree("Events","Events");

    outTree->Branch("runNum",   &runNum,   "runNum/i");     // event run number
    outTree->Branch("lumiSec",  &lumiSec,  "lumiSec/i");    // event lumi section
    outTree->Branch("evtNum",   &evtNum,   "evtNum/i");     // event number
    outTree->Branch("matchGen", &matchGen, "matchGen/i");   // event has both leptons matched to MC Z->ll
    outTree->Branch("category", &category, "category/i");   // dilepton category
    outTree->Branch("npv",      &npv,      "npv/i");        // number of primary vertices
    outTree->Branch("npu",      &npu,      "npu/i");        // number of in-time PU events (MC)
    outTree->Branch("genVPt",   &genVPt,   "genVPt/F");     // GEN boson pT (signal MC)
    outTree->Branch("genVPhi",  &genVPhi,  "genVPhi/F");    // GEN boson phi (signal MC)
    outTree->Branch("genVy",    &genVy,    "genVy/F");      // GEN boson rapidity (signal MC)
    outTree->Branch("genVMass", &genVMass, "genVMass/F");   // GEN boson mass (signal MC)
    outTree->Branch("scale1fb", &scale1fb, "scale1fb/F");   // event weight per 1/fb (MC)
    outTree->Branch("met",      &met,      "met/F");        // MET
    outTree->Branch("metPhi",   &metPhi,   "metPhi/F");     // phi(MET)
    outTree->Branch("sumEt",    &sumEt,    "sumEt/F");      // Sum ET
    outTree->Branch("u1",       &u1,       "u1/F");         // parallel component of recoil
    outTree->Branch("u2",       &u2,       "u2/F");         // perpendicular component of recoil
    outTree->Branch("q1",       &q1,       "q1/I");         // charge of tag lepton
    outTree->Branch("q2",       &q2,       "q2/I");         // charge of probe lepton
    outTree->Branch("dilep", "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &dilep);  // dilepton 4-vector
    outTree->Branch("lep1",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep1);   // tag lepton 4-vector
    outTree->Branch("lep2",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep2);   // probe lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso1",    &trkIso1,    "trkIso1/F");     // track isolation of tag lepton
    outTree->Branch("trkIso2",    &trkIso2,    "trkIso2/F");     // track isolation of probe lepton
    outTree->Branch("emIso1",     &emIso1,     "emIso1/F");      // ECAL isolation of tag lepton
    outTree->Branch("emIso2",     &emIso2,     "emIso2/F");      // ECAL isolation of probe lepton
    outTree->Branch("hadIso1",    &hadIso1,    "hadIso1/F");     // HCAL isolation of tag lepton
    outTree->Branch("hadIso2",    &hadIso2,    "hadIso2/F");     // HCAL isolation of probe lepton
    outTree->Branch("pfChIso1",   &pfChIso1,   "pfChIso1/F");    // PF charged hadron isolation of tag lepton
    outTree->Branch("pfChIso2",   &pfChIso2,   "pfChIso2/F");    // PF charged hadron isolation of probe lepton
    outTree->Branch("pfGamIso1",  &pfGamIso1,  "pfGamIso1/F");   // PF photon isolation of tag lepton
    outTree->Branch("pfGamIso2",  &pfGamIso2,  "pfGamIso2/F");   // PF photon isolation of probe lepton
    outTree->Branch("pfNeuIso1",  &pfNeuIso1,  "pfNeuIso1/F");   // PF neutral hadron isolation of tag lepton
    outTree->Branch("pfNeuIso2",  &pfNeuIso2,  "pfNeuIso2/F");   // PF neutral hadron isolation of probe lepton
    outTree->Branch("pfCombIso1", &pfCombIso1, "pfCombIso1/F");  // PF combine isolation of tag lepton
    outTree->Branch("pfCombIso2", &pfCombIso2, "pfCombIso2/F");  // PF combined isolation of probe lepton    
    outTree->Branch("sigieie1",   &sigieie1,   "sigieie1/F");    // sigma-ieta-ieta of tag
    outTree->Branch("sigieie2",   &sigieie2,   "sigieie2/F");    // sigma-ieta-ieta of probe
    outTree->Branch("hovere1",    &hovere1,    "hovere1/F");     // H/E of tag
    outTree->Branch("hovere2",    &hovere2,    "hovere2/F");     // H/E of probe
    outTree->Branch("eoverp1",    &eoverp1,    "eoverp1/F");     // E/p of tag
    outTree->Branch("eoverp2",    &eoverp2,    "eoverp2/F");     // E/p of probe	 
    outTree->Branch("fbrem1",     &fbrem1,     "fbrem1/F");      // brem fraction of tag
    outTree->Branch("fbrem2",     &fbrem2,     "fbrem2/F");      // brem fraction of probe
    outTree->Branch("dphi1",      &dphi1,      "dphi1/F");       // GSF track - ECAL dphi of tag
    outTree->Branch("dphi2",      &dphi2,      "dphi2/F");       // GSF track - ECAL dphi of probe 	
    outTree->Branch("deta1",      &deta1,      "deta1/F");       // GSF track - ECAL deta of tag
    outTree->Branch("deta2",      &deta2,      "deta2/F");       // GSF track - ECAL deta of probe
    outTree->Branch("ecalE1",     &ecalE1,     "ecalE1/F");      // ECAL energy of tag
    outTree->Branch("ecalE2",     &ecalE2,     "ecalE2/F");      // ECAL energy of probe
    outTree->Branch("d01",        &d01,        "d01/F");	 // transverse impact parameter of tag
    outTree->Branch("d02",        &d02,        "d02/F");	 // transverse impact parameter of probe	  
    outTree->Branch("dz1",        &dz1,        "dz1/F");	 // longitudinal impact parameter of tag
    outTree->Branch("dz2",        &dz2,        "dz2/F");	 // longitudinal impact parameter of probe
    outTree->Branch("isConv1",    &isConv1,    "isConv1/i");     // conversion filter flag of tag lepton
    outTree->Branch("isConv2",    &isConv2,    "isConv2/i");     // conversion filter flag of probe lepton
    outTree->Branch("nexphits1",  &nexphits1,  "nexphits1/i");   // number of missing expected inner hits of tag lepton
    outTree->Branch("nexphits2",  &nexphits2,  "nexphits2/i");   // number of missing expected inner hits of probe lepton
    outTree->Branch("typeBits1",  &typeBits1,  "typeBits1/i");   // electron type of tag lepton
    outTree->Branch("typeBits2",  &typeBits2,  "typeBits2/i");   // electron type of probe lepton
    outTree->Branch("sc1",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc1);   // tag Supercluster 4-vector
    outTree->Branch("sc2",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc2);   // probe Supercluster 4-vector 
    
    //
    // loop through files
    //
    const UInt_t nfiles = samp->fnamev.size();
    for(UInt_t ifile=0; ifile<nfiles; ifile++) {  

      // Read input file and get the TTrees
      cout << "Processing " << samp->fnamev[ifile] << " [xsec = " << samp->xsecv[ifile] << " pb] ... "; cout.flush();
      infile = new TFile(samp->fnamev[ifile]); 
      assert(infile);

      Bool_t hasJSON = kFALSE;
      mithep::RunLumiRangeMap rlrm;
      if(samp->jsonv[ifile].CompareTo("NONE")!=0) { 
        hasJSON = kTRUE;
        rlrm.AddJSONFile(samp->jsonv[ifile].Data()); 
      }
  
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
      eventTree->SetBranchAddress("Photon",   &scArr);       TBranch *scBr       = eventTree->GetBranch("Photon");
      eventTree->SetBranchAddress("PV",       &pvArr);       TBranch *pvBr       = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("Gen");
      TBranch *genBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("Gen", &gen);
	genBr = eventTree->GetBranch("Gen");
      }
      
      // Compute MC event weight per 1/fb
      Double_t weight = 1;
      const Double_t xsec = samp->xsecv[ifile];
      if(xsec>0) weight = 1000.*xsec/(Double_t)eventTree->GetEntries();     

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);
	
	if(genBr) genBr->GetEntry(ientry);
     
        // check for certified lumi (if applicable)
        mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  

        // trigger requirement               
        ULong64_t trigger = kHLT_Ele22_CaloIdL_CaloIsoVL;
	ULong64_t trigObj = kHLT_Ele22_CaloIdL_CaloIsoVL_EleObj;  
        if(!(info->triggerBits & trigger)) continue;      
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;
        pvArr->Clear();
        pvBr->GetEntry(ientry);
      
        //
	// SELECTION PROCEDURE:
	//  (1) Find a good electron matched to trigger -> this will be the "tag"
	//  (2) Pair the tag with Supercluster probes which form a tag+probe mass inside 
	//      the Z window and divide candidates into exclusive categories as follows:
	//      (a) if probe SC is part of a good electron matched to trigger     -> EleEle2HLT category
	//      (b) if probe SC is part of a good electron not matched to trigger -> EleEle1HLT category
	//      (c) if probe SC is part of an electron failing selection cuts     -> EleEleNoSel category
	//      (d) if probe SC is not part of an ECAL driven electron            -> EleSC category
	//	
	electronArr->Clear();
        electronBr->GetEntry(ientry);
	scArr->Clear();
	scBr->GetEntry(ientry);
        for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
          const mithep::TElectron *tag = (mithep::TElectron*)((*electronArr)[i1]);
	  
	  // check ECAL gap
	  if(fabs(tag->scEta)>=ECAL_GAP_LOW && fabs(tag->scEta)<=ECAL_GAP_HIGH) continue;
	  
	  Double_t escale1=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(tag->scEta)<escaleEta[ieta]) {
	        escale1 = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  if(escale1*(tag->scEt) < PT_CUT)    continue;  // lepton pT cut
	  if(fabs(tag->scEta)    > ETA_CUT)   continue;  // lepton |eta| cut
	  if(!passEleID(tag,info->rhoLowEta)) continue;  // lepton selection
	  if(!(tag->hltMatchBits & trigObj))  continue;  // check trigger matching
	  
	  LorentzVector vTag(escale1*(tag->pt), tag->eta, tag->phi, ELE_MASS);
	  LorentzVector vTagSC(escale1*(tag->scEt), tag->scEta, tag->scPhi, ELE_MASS);
	
	  for(Int_t j=0; j<scArr->GetEntriesFast(); j++) {
	    const mithep::TPhoton *scProbe = (mithep::TPhoton*)((*scArr)[j]);
	    if(scProbe->scID == tag->scID) continue;
	    
	    // check ECAL gap
	    if(fabs(scProbe->scEta)>=ECAL_GAP_LOW && fabs(scProbe->scEta)<=ECAL_GAP_HIGH) continue;
	    
	   Double_t escale2=1;
	    if(doScaleCorr && isam==0) {
	      for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	        if(fabs(scProbe->scEta)<escaleEta[ieta]) {
	          escale2 = escaleCorr[ieta];
		  break;
	        }
	      }
	    }
	    
	    if(escale2*(scProbe->pt) < PT_CUT)  continue;  // Supercluster ET cut ("pt" = corrected by PV position)
	    if(fabs(scProbe->scEta)  > ETA_CUT) continue;  // Supercluster |eta| cuts
	    
	    const mithep::TElectron *eleProbe=0;
	    Int_t iprobe=-1;
	    for(Int_t i2=0; i2<electronArr->GetEntriesFast(); i2++) {
	      if(i1==i2) continue;
	      const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i2]);
	      if(!(ele->typeBits & kEcalDriven)) continue;
	      if(scProbe->scID==ele->scID) { 
	        eleProbe = ele; 
		iprobe   = i2;
		break; 
	      }
            }
	    
	    LorentzVector vProbe((eleProbe) ? escale2*(eleProbe->pt) : escale2*(scProbe->pt), 
	                         (eleProbe) ? eleProbe->eta : scProbe->eta, 
				 (eleProbe) ? eleProbe->phi : scProbe->phi, 
				 ELE_MASS);
	    LorentzVector vProbeSC((eleProbe) ? escale2*(eleProbe->scEt) : escale2*(scProbe->pt), 
	                           scProbe->scEta, scProbe->scPhi, ELE_MASS);
	    
	    // mass window
	    LorentzVector vDilep = vTag + vProbe;
	    if((vDilep.M()<MASS_LOW) || (vDilep.M()>MASS_HIGH)) continue;
	    
	    // determine event category
	    UInt_t icat=0;
	    if(eleProbe) {
	      if(passEleID(eleProbe,info->rhoLowEta)) {
	        if(eleProbe->hltMatchBits & trigObj) {
		  if(i1>iprobe) continue;  // make sure we don't double count EleEle2HLT category
		  icat=eEleEle2HLT;
		
		} else {
		  icat=eEleEle1HLT;
		}	      
	      } else { 
	        icat=eEleEleNoSel;
	      } 
	    } else { 
	      icat=eEleSC;
	    }
	    if(icat==0) continue;
	    
	    
	    /******** We have a Z candidate! HURRAY! ********/
	    
	    nsel+=weight;
            nselvar+=weight*weight;
	    
	    // Perform matching of dileptons to GEN leptons from Z decay
	    Bool_t hasGenMatch = kFALSE;
	    if(isSignal) {
	      Bool_t match1 = ( (abs(gen->id_1)==EGenType::kElectron) && ((toolbox::deltaR(tag->eta, tag->phi, gen->eta_1, gen->phi_1) < 0.5)) )
	                      || ( (abs(gen->id_2)==EGenType::kElectron) && ((toolbox::deltaR(tag->eta, tag->phi, gen->eta_2, gen->phi_2) < 0.5)) );
	      Bool_t match2 = ( (abs(gen->id_1)==EGenType::kElectron) && ((toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), gen->eta_1, gen->phi_1) < 0.5)) )
	                      || ( (abs(gen->id_2)==EGenType::kElectron) && ((toolbox::deltaR(vProbe.Eta(), vProbe.Phi(), gen->eta_2, gen->phi_2) < 0.5)) );
	      if(match1 && match2) hasGenMatch = kTRUE;
	    };
	    
	    //
	    // Fill tree
	    //
	    runNum   = info->runNum;
	    lumiSec  = info->lumiSec;
	    evtNum   = info->evtNum;
	    matchGen = hasGenMatch ? 1 : 0;
	    category = icat;
	    npv      = pvArr->GetEntriesFast();
	    npu      = info->nPU;
	    genVPt   = (hasGen) ? gen->vpt   : 0;
	    genVPhi  = (hasGen) ? gen->vphi  : 0;
	    genVy    = (hasGen) ? gen->vy    : 0;
	    genVMass = (hasGen) ? gen->vmass : 0;
	    scale1fb = weight;
	    met      = info->pfMET;
	    metPhi   = info->pfMETphi;
	    sumEt    = info->pfSumET;
	    
	    lep1 = &vTag;
	    q1   = tag->q;
	    
	    lep2 = &vProbe;
	    q2   = (eleProbe) ? eleProbe->q : -(tag->q);
	    
	    dilep = &vDilep;
	    
	    TVector2 vZPt((vDilep.Pt())*cos(vDilep.Phi()),(vDilep.Pt())*sin(vDilep.Phi()));        
            TVector2 vMet((info->pfMET)*cos(info->pfMETphi), (info->pfMET)*sin(info->pfMETphi));        
            TVector2 vU = -1.0*(vMet+vZPt);
            u1 = ((vDilep.Px())*(vU.Px()) + (vDilep.Py())*(vU.Py()))/(vDilep.Pt());  // u1 = (pT . u)/|pT|
            u2 = ((vDilep.Px())*(vU.Py()) - (vDilep.Py())*(vU.Px()))/(vDilep.Pt());  // u2 = (pT x u)/|pT|
	  
	    ///// electron specific /////
	    sc1        = &vTagSC;
	    trkIso1    = tag->trkIso03;
	    emIso1     = tag->emIso03;
	    hadIso1    = tag->hadIso03;
	    pfChIso1   = tag->pfChIso03;
	    pfGamIso1  = tag->pfGamIso03;	    
	    pfNeuIso1  = tag->pfNeuIso03;
	    pfCombIso1 = tag->pfChIso03 + TMath::Max(tag->pfNeuIso03 + tag->pfGamIso03 - (info->rhoLowEta)*getEffArea(tag->scEta), 0.);
	    sigieie1   = tag->sigiEtaiEta;
	    hovere1    = tag->HoverE;
	    eoverp1    = tag->EoverP;
	    fbrem1     = tag->fBrem;
	    dphi1      = tag->deltaPhiIn;
	    deta1      = tag->deltaEtaIn;
	    ecalE1     = tag->ecalE;
	    d01        = tag->d0;
	    dz1        = tag->dz;
	    isConv1    = tag->isConv;
	    nexphits1  = tag->nExpHitsInner;
	    typeBits1  = tag->typeBits;
	    
	    sc2        = &vProbeSC;
	    trkIso2    = (eleProbe) ? eleProbe->trkIso03      : -1;
	    emIso2     = (eleProbe) ? eleProbe->emIso03       : -1;
	    hadIso2    = (eleProbe) ? eleProbe->hadIso03      : -1;
	    pfChIso2   = (eleProbe) ? eleProbe->pfChIso03     : -1;
	    pfGamIso2  = (eleProbe) ? eleProbe->pfGamIso03    : -1;
	    pfNeuIso2  = (eleProbe) ? eleProbe->pfNeuIso03    : -1;
	    
	    pfCombIso2 = (eleProbe) ? 
	                 eleProbe->pfChIso03 + TMath::Max(eleProbe->pfNeuIso03 + eleProbe->pfGamIso03 - (info->rhoLowEta)*getEffArea(eleProbe->scEta), 0.) : 
			 -1;
	    
	    sigieie2   = (eleProbe) ? eleProbe->sigiEtaiEta   : scProbe->sigiEtaiEta;
	    hovere2    = (eleProbe) ? eleProbe->HoverE        : scProbe->HoverE;
	    eoverp2    = (eleProbe) ? eleProbe->EoverP        : -1;
	    fbrem2     = (eleProbe) ? eleProbe->fBrem         : -1;
	    dphi2      = (eleProbe) ? eleProbe->deltaPhiIn    : -999;
	    deta2      = (eleProbe) ? eleProbe->deltaEtaIn    : -999;
	    ecalE2     = (eleProbe) ? eleProbe->ecalE         : -999;
	    d02        = (eleProbe) ? eleProbe->d0            : -999;
	    dz2        = (eleProbe) ? eleProbe->dz            : -999;
	    isConv2    = (eleProbe) ? eleProbe->isConv        : 0;
	    nexphits2  = (eleProbe) ? eleProbe->nExpHitsInner : 0;
	    typeBits2  = (eleProbe) ? eleProbe->typeBits      : 0; 
	    
	    outTree->Fill();
	  }
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete info;
  delete gen;
  delete electronArr;
  delete scArr;
  delete pvArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " Z -> e e" << endl;
  cout << "  Mass window: [" << MASS_LOW << ", " << MASS_HIGH << "]" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  if(doScaleCorr)
    cout << "  *** Scale corrections applied ***" << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZee"); 
}