void decayAndFill(int const kf, TLorentzVector* b, double const weight, TClonesArray& daughters)
{
   pydecay->Decay(kf, b);
   pydecay->ImportParticles(&daughters);

   TLorentzVector p1Mom;
   TLorentzVector p2Mom;
   TVector3 v00;

   int nTrk = daughters.GetEntriesFast();
   for (int iTrk = 0; iTrk < nTrk; ++iTrk)
   {
     TParticle* ptl0 = (TParticle*)daughters.At(iTrk);

     switch (ptl0->GetPdgCode())
     {
       //Will only have pions
       case 211:
         ptl0->Momentum(p1Mom);
         v00.SetXYZ(ptl0->Vx() * 1000., ptl0->Vy() * 1000., ptl0->Vz() * 1000.); // converted to μm
         break;
       case -211:
         ptl0->Momentum(p2Mom);
         break;
       default:
         break;
     }
   }
   daughters.Clear();

   fill(kf, b, weight, p1Mom, p2Mom, v00);
}
Exemple #2
0
int main(int argc, char* argv[])
{ 
  //Upload the file with the data
  TFile* file = TFile::Open("/Users/Fer/Documents/traajo/samples/NeroNtuples_9.root"); // TFile::Open() instead of a constructor since it works over xrootd etc.
  //Upload the tree with the event data
  TTree *tree=(TTree*)file->Get("nero/events");

  //Create the vector to store all the particle identifiers
  std::vector<Int_t> * lepPdgId;

  //Create a variable to store all the lepton event data
  TClonesArray *leptondata = new TClonesArray("leptondata");

  //Specify where all the lepton event data will be stores
  tree->SetBranchAddress("lepP4", &leptondata);
  //Specify where all the lepton identifiers will be stored
  tree->SetBranchAddress("lepPdgId", &lepPdgId);

  //Get how many events we have to loop through
  int nentries = tree->GetEntries();

  //Loop through all the events
  for(int ientry = 0; ientry < nentries; ientry++) 
  {
    //Reset the lepton data 
    leptondata->Clear();
    //This line stores the proper data both in "leptondata" and in "lepPdgId"
    tree->GetEntry(ientry);
    
    //Only if "leptondata" is not empty continue, this is to avoid segmentation errors
    if(leptondata->GetSize() == 0) continue;

    //Loop through all the entries in the current event 
    for(int j=0; j<leptondata->GetEntriesFast()-1; j++) 
    {
        //Only if the identifier of the particle is + or - 11 (electron or antielectron) store the data in electrondata
        if(abs(lepPdgId->at(j))==11) continue;
        //Store all the data of the electron in this variable
        TLorentzVector *electrondata = (TLorentzVector *)leptondata->At(j);
        //Get some specific property such as momentum, position or energy
        cout << electrondata->E() << endl;
    }
  }
  return 0; 
}
Exemple #3
0
Fichier : tcl.C Projet : Y--/root
void tclread()
{
// read file generated by tclwrite
// loop on all entries.
// histogram center of lines
   TFile *f = new TFile("tcl.root");
   TTree *T = (TTree*)f->Get("T");
   TH2F *h2 = new TH2F("h2","center of lines",40,0,1,40,0,1);

   TClonesArray *arr = new TClonesArray("TLine");
   T->GetBranch("tcl")->SetAutoDelete(kFALSE);
   T->SetBranchAddress("tcl",&arr);
   Long64_t nentries = T->GetEntries();
   for (Long64_t ev=0;ev<nentries;ev++) {
      arr->Clear();
      T->GetEntry(ev);
      Int_t nlines = arr->GetEntriesFast();
      for (Int_t i=0;i<nlines;i++) {
         TLine *line = (TLine*)arr->At(i);
         h2->Fill(0.5*(line->GetX1()+line->GetX2()), 0.5*(line->GetY1()+line->GetY2()));
      }
   }
   h2->Draw("lego");
}
Exemple #4
0
//  -------------------------------------------------------------------------
//
//   ----- General Macro for R3B CALIFA S438 Data Display
//         Author: Hector Alvarez <*****@*****.**>
//         Last Update: 30/09/14
//         Comments:
//         MAIN DISPLAY OF S438 CALIFA CRYSTALHIT
//	
//  -------------------------------------------------------------------------
//
//   Usage: 
//      > root -l 
//      ROOT> .L plotAll.C
//      ROOT> plot("inputFile")
//     
//     where inputFile is the input file :) 
//  -------------------------------------------------------------------------
void plot(TString inputFile) {

  // CONFIGURATION
  ifstream input1;
  input1.open("./angles/petals_angels_angles.txt"); 
  Double_t polar[128]; Double_t azimuthal[128]; Int_t number=0;
  for(Int_t i=0;i<128;i++) input1 >> number >> polar[i] >> azimuthal[i]; 
  //

  gROOT->SetStyle("Default");
  //gStyle->SetOptTitle(0);
  gStyle->SetOptStat(0);
  gStyle->SetOptFit(0);

  TFile *file1 = TFile::Open(inputFile);

  //SETTINGS: reduce memory by disabling those canvas that you do not want!
  Bool_t plotMultiplicities=kTRUE; Bool_t plotEnergyvsAngle=kTRUE; Bool_t plotProtonCorr=kTRUE; Bool_t plotAddBack=kTRUE;

  //HISTOGRAMS DEFINITION FOR CRYSTALHITS
  TH1F* hMult; TH1F* hMult2; TH2F* hEnergyvsId; TH2F* hToT_EnergyvsId;
  if(plotMultiplicities) {
    hMult = new TH1F("hMult","Total CrystalHits vs crystalId",128,0,127);
    hMult2 = new TH1F("hMult2","Number of CrystalHit with max. E of the event vs crystalId",128,0,127);
    hEnergyvsId = new TH2F("hEnergyvsId","Energy vs crystalId",128,0,127,3000,-100,29900);
    hToT_EnergyvsId = new TH2F("hToT_EnergyvsId","ToT_Energy vs crystalId",128,0,127,3000,-1000,299000);
  }  
  TH2F* hP1EnergyvsPolar; TH2F* hP2EnergyvsPolar; TH2F* hP1ToT_EnergyvsPolar; TH2F* hP2ToT_EnergyvsPolar;
  if(plotEnergyvsAngle) {
    hP1EnergyvsPolar = new TH2F("hP1EnergyvsPolar","PETAL1: Energy vs polar",50,22,68,3000,-100,29900);
    hP2EnergyvsPolar = new TH2F("hP2EnergyvsPolar","PETAL2: Energy vs polar",50,22,68,3000,-100,29900);
    hP1ToT_EnergyvsPolar = new TH2F("hP1ToT_EnergyvsPolar","PETAL1: ToT_Energy vs polar",50,22,68,3000,-1000,299000);
    hP2ToT_EnergyvsPolar = new TH2F("hP2ToT_EnergyvsPolar","PETAL2: ToT_Energy vs polar",50,22,68,3000,-1000,299000);
  }
  TH2F* hToT_EnergyCorr; TH2F* hAngleCorr; TH2F* hToT_EnergyCorrLarge; TH2F* hAngleCorrLarge;
  if(plotProtonCorr) {
    hToT_EnergyCorr = new TH2F("hToT_EnergyCorr","ToT_Energy Petal1 vs ToT_Energy Petal2 (FULL COMBINATORIAL)",3000,-100,29900,3000,-100,29900);
    hEnergyCorr = new TH2F("hEnergyCorr","Energy Petal1 vs Energy Petal2 (FULL COMBINATORIAL)",3000,-100,29900,3000,-100,29900);
    hAngleCorr = new TH2F("hAngleCorr","Polar Petal1 vs polar Petal2 (FULL COMBINATORIAL)",50,22,68,50,22,68);
    hToT_EnergyCorrLarge = new TH2F("hToT_EnergyCorrLarge","ToT_Energy Petal1 vs ToT_Energy Petal2 (ONLY LARGEST ENERGY HIT)",3000,-100,29900,3000,-100,29900);
    hEnergyCorrLarge = new TH2F("hEnergyCorrLarge","Energy Petal1 vs Energy Petal2 (ONLY LARGEST ENERGY HIT)",3000,-100,29900,3000,-100,29900);
    hAngleCorrLarge = new TH2F("hAngleCorrLarge","Polar Petal1 vs polar Petal2 (ONLY LARGEST ENERGY HIT)",50,22,68,50,22,68);
  }  
  TH2F* hP1ABEnergy; TH2F* hP2ABEnergy; TH2F* hP1ABToT_Energy; TH2F* hP2ABToT_Energy;
  if(plotAddBack) {
    hP1ABEnergy= new TH2F("hP1ABEnergy","AddBack Energy in Petal1: second largest Energy vs largest Energy",3000,-100,29900,3000,-100,29900);
    hP2ABEnergy = new TH2F("hP2ABEnergy","AddBack Energy in Petal2: second largest Energy vs largest Energy",3000,-100,29900,3000,-100,29900);
    hP1ABToT_Energy = new TH2F("hP1ABToT_Energy","AddBack ToT_Energy in Petal1: second largest ToT_Energy vs largest ToT_Energy",3000,-1000,299000,3000,-1000,299000);
    hP2ABToT_Energy = new TH2F("hP2ABToT_Energy","AddBack ToT_Energy in Petal2: second largest ToT_Energy vs largest ToT_Energy",3000,-1000,299000,3000,-1000,299000);
  }

  TTree* caloTree = (TTree*)file1->Get("cbmsim");
 
  //Crystal Hits
  TClonesArray* crystalHitCA;  
  R3BCaloCrystalHit** crystalHit;
  crystalHitCA = new TClonesArray("R3BCaloCrystalHit",5);
  TBranch *branchCrystalHit = caloTree->GetBranch("CaloCrystalHit");
  if(branchCrystalHit) branchCrystalHit->SetAddress(&crystalHitCA);
  
  Int_t* crystalId; 
  Double_t* energies;
  Double_t* ToT_energies;
  Double_t maxEnergyP1=0; Double_t maxEnergyP2=0; Double_t maxToT_EnergyP1=0; Double_t maxToT_EnergyP2=0; 
  Int_t winnerEnergyP1=0; Int_t winnerEnergyP2=0; Int_t winnerToT_EnergyP1=0; Int_t winnerToT_EnergyP2=0;
  Int_t secondEnergyP1=0; Int_t secondEnergyP2=0; Int_t secondToT_EnergyP1=0; Int_t secondToT_EnergyP2=0;

  Long64_t nevents = caloTree->GetEntries();
  Int_t crystalHitsPerEvent =0;

  for(Int_t i=0;i<nevents;i++){
    if(i%100000 == 0) printf("Event:%i\n",i);
    crystalHitCA->Clear();
    caloTree->GetEvent(i);
    crystalHitsPerEvent = crystalHitCA->GetEntries(); 
    maxEnergyP1=-1; maxEnergyP2=-1; maxToT_EnergyP1=-1; maxToT_EnergyP2=-1; 
    winnerEnergyP1=-1; winnerEnergyP2=-1; winnerToT_EnergyP1=-1; winnerToT_EnergyP2=-1;
    secondEnergyP1=-1; secondEnergyP2=-1; secondToT_EnergyP1=-1; secondToT_EnergyP2=-1;

    if(crystalHitsPerEvent>0) {
      crystalHit = new R3BCaloCrystalHit*[crystalHitsPerEvent];
      crystalId = new Int_t[crystalHitsPerEvent]; 
      energies = new Double_t[crystalHitsPerEvent];
      ToT_energies = new Double_t[crystalHitsPerEvent];

      for(Int_t h=0;h<crystalHitsPerEvent;h++) {
	crystalHit[h] = (R3BCaloCrystalHit*) crystalHitCA->At(h);      
	//filling info
	if(plotMultiplicities) {
	  hMult->Fill(crystalHit[h]->GetCrystalId());
	  hMult2->Fill(crystalHit[h]->GetCrystalId()); //TO BE DONE BELOW! REMEMBER!!!
	  hEnergyvsId->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetEnergy());
	  hToT_EnergyvsId->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetToT_Energy());
	}
	if(plotEnergyvsAngle) {
	  if(crystalHit[h]->GetCrystalId()<64){//PETAL1
	    hP1EnergyvsPolar->Fill(polar[crystalHit[h]->GetCrystalId()],crystalHit[h]->GetEnergy());  //TO BE DONE BELOW! REMEMBER!!!
	    //hP1EnergyvsPolar->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetEnergy());
	    hP1ToT_EnergyvsPolar->Fill(polar[crystalHit[h]->GetCrystalId()],crystalHit[h]->GetEnergy()); //TO BE DONE BELOW! REMEMBER!!!
	    //hP1ToT_EnergyvsPolar->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetEnergy());
	  }
	  else{//PETAL2
	    hP2EnergyvsPolar->Fill(polar[crystalHit[h]->GetCrystalId()],crystalHit[h]->GetEnergy()); //TO BE DONE BELOW! REMEMBER!!!
	    //hP2EnergyvsPolar->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetEnergy());
	    hP2ToT_EnergyvsPolar->Fill(polar[crystalHit[h]->GetCrystalId()],crystalHit[h]->GetEnergy()); //TO BE DONE BELOW! REMEMBER!!!
	    //hP2ToT_EnergyvsPolar->Fill(crystalHit[h]->GetCrystalId(),crystalHit[h]->GetEnergy());
	  }
	}
	
	//FILLING FOR ORDERING
	crystalId[h] = crystalHit[h]->GetCrystalId(); 
	energies[h] = crystalHit[h]->GetEnergy(); 
	ToT_energies[h] = crystalHit[h]->GetToT_Energy();
      }
      //TAKING THE LARGEST ENERGY IN EACH PETAL
      for(Int_t h=0;h<crystalHitsPerEvent;h++) {      
	if(crystalHit[h]->GetCrystalId()<64) {//PETAL1
	  if(maxEnergyP1<energies[h]){ secondEnergyP1=winnerEnergyP1; winnerEnergyP1=h; maxEnergyP1=energies[h];}  
	  if(maxToT_EnergyP1<ToT_energies[h]){ secondToT_EnergyP1=winnerToT_EnergyP1; winnerToT_EnergyP1=h; maxToT_EnergyP1=ToT_energies[h];}  
	}  
	else {//PETAL2
	  if(maxEnergyP2<energies[h]) { secondEnergyP2=winnerEnergyP2; winnerEnergyP2=h; maxEnergyP2=energies[h];} 
	  if(maxToT_EnergyP2<ToT_energies[h]){ secondToT_EnergyP2=winnerToT_EnergyP2; winnerToT_EnergyP2=h; maxToT_EnergyP2=ToT_energies[h];}   
	} 
      } 
      
      if(plotProtonCorr) {
	for(Int_t h=0;h<crystalHitsPerEvent;h++) {      
	  if(crystalHit[h]->GetCrystalId()<64) { //PETAL1
	    for(Int_t k=0;k<crystalHitsPerEvent;k++) {     
	      if(crystalHit[k]->GetCrystalId()>63) { //PETAL2
		hToT_EnergyCorr->Fill(ToT_energies[k],ToT_energies[h]); //FULL COMBINATORIAL!!
		hEnergyCorr->Fill(energies[k],energies[h]); //FULL COMBINATORIAL!!
		hAngleCorr->Fill(polar[crystalId[k]],polar[crystalId[h]]); 
	      }
	    }
	  }
	}
	if(winnerToT_EnergyP2>-1 && winnerToT_EnergyP1>-1) hToT_EnergyCorrLarge->Fill(ToT_energies[winnerToT_EnergyP2],ToT_energies[winnerToT_EnergyP1]);
	if(winnerEnergyP2>-1 && winnerEnergyP1>-1) hEnergyCorrLarge->Fill(energies[winnerEnergyP2],energies[winnerEnergyP1]);
	if(winnerToT_EnergyP2>-1 && winnerToT_EnergyP1>-1) hAngleCorrLarge->Fill(polar[crystalId[winnerToT_EnergyP2]],polar[crystalId[winnerToT_EnergyP1]]);
      }
      
      if(plotAddBack) {
	if(winnerEnergyP1>-1 && secondEnergyP1>-1) hP1ABEnergy->Fill(energies[winnerEnergyP1],energies[secondEnergyP1]);
	if(winnerToT_EnergyP1>-1 && secondToT_EnergyP1>-1) hP1ABToT_Energy->Fill(ToT_energies[winnerToT_EnergyP1],ToT_energies[secondToT_EnergyP1]);
	if(winnerEnergyP2>-1 && secondEnergyP2>-1) hP2ABEnergy->Fill(energies[winnerEnergyP2],energies[secondEnergyP2]);
	if(winnerToT_EnergyP2>-1 && secondToT_EnergyP2>-1) hP2ABToT_Energy->Fill(ToT_energies[winnerToT_EnergyP2],ToT_energies[secondToT_EnergyP2]);
      }
      
    }  
    if(crystalHitsPerEvent) delete [] crystalHit;
  }

  TCanvas* cMult;  TCanvas* cEnerg; TCanvas* cEneCorr; TCanvas* cAB;
  if(plotMultiplicities) {
    cMult= new TCanvas("cMult","Info on multiplicities and energies per crystalID",0,0,800,800);
    cMult->SetFillColor(0);    cMult->SetFrameFillColor(0);    cMult->Divide(2,2);
    cMult->cd(1);  hMult->Draw();
    cMult->cd(2);  hMult2->Draw();
    cMult->cd(3);  hEnergyvsId->Draw("COLZ");
    cMult->cd(4);  hToT_EnergyvsId->Draw("COLZ");
  }
  if(plotEnergyvsAngle) {
    cEnerg= new TCanvas("cEnerg","Info on energies per polar angle",0,0,800,800);
    cEnerg->SetFillColor(0);    cEnerg->SetFrameFillColor(0);    cEnerg->Divide(2,2);
    cEnerg->cd(1);  hP1EnergyvsPolar->Draw("COLZ");
    cEnerg->cd(2);  hP2EnergyvsPolar->Draw("COLZ");
    cEnerg->cd(3);  hP1ToT_EnergyvsPolar->Draw("COLZ");
    cEnerg->cd(4);  hP2ToT_EnergyvsPolar->Draw("COLZ");
  } 
  if(plotProtonCorr) {
    cEneCorr= new TCanvas("cEneCorr","Info on energy correlation between petals",0,0,1200,800);
    cEneCorr->SetFillColor(0);    cEneCorr->SetFrameFillColor(0);    cEneCorr->Divide(3,2);
    cEneCorr->cd(1);  hToT_EnergyCorr->Draw("COLZ");
    cEneCorr->cd(2);  hEnergyCorr->Draw("COLZ");
    cEneCorr->cd(3);  hAngleCorr->Draw("COLZ");
    cEneCorr->cd(4);  hToT_EnergyCorrLarge->Draw("COLZ");
    cEneCorr->cd(5);  hEnergyCorrLarge->Draw("COLZ");
    cEneCorr->cd(6);  hAngleCorrLarge->Draw("COLZ");
  }
  if(plotAddBack) {
    cAB= new TCanvas("cAB","Info on AddBack in each petal",0,0,800,800);
    cAB->SetFillColor(0);    cAB->SetFrameFillColor(0);    cAB->Divide(2,2);
    cAB->cd(1);  hP1ABEnergy->Draw("COLZ");
    cAB->cd(2);  hP2ABEnergy->Draw("COLZ");
    cAB->cd(3);  hP1ABToT_Energy->Draw("COLZ");
    cAB->cd(4);  hP2ABToT_Energy->Draw("COLZ");
  } 
}
Exemple #5
0
void PHPythia8::fillPythiaNode(Pythia8::Pythia *pythia)
{

  Int_t numpart = pythia->event.size() - 1;
  TClonesArray *fParticles = new TClonesArray("TParticle",1000);
  fParticles->Clear();
  TClonesArray &a = *((TClonesArray*)fParticles);
  
  if(verbosity > 2) cout << "PHPythia8::process_event - numparticles: " << numpart << endl;
  for (Int_t i = 1; i <= numpart; i++) 
    {
      /* This would require changing all of the container
	 new(a[i]) TParticle(pythia->event[i].id(),
	 pythia->event[i].isFinal(),
	 pythia->event[i].mother1()  - 1,
	 pythia->event[i].mother2()  - 1,
	 pythia->event[i].daughter1() - 1,
	 pythia->event[i].daughter2() - 1,
	 pythia->event[i].px(),       // [GeV/c]
	 pythia->event[i].py(),       // [GeV/c] 
	 pythia->event[i].pz(),       // [GeV/c]
	 pythia->event[i].e(),        // [GeV]
	 pythia->event[i].xProd(),    // [mm] 
	 pythia->event[i].yProd(),    // [mm]
	 pythia->event[i].zProd(),    // [mm] 
	 pythia->event[i].tProd());   // [mm/c]
      */
      new(a[i-1]) TMCParticle(pythia->event[i].status(),
			      pythia->event[i].id(),
			      pythia->event[i].mother1(), //TMC is old and has no space for mother2...
			      pythia->event[i].daughter1(),
			      pythia->event[i].daughter2(),
			      pythia->event[i].px(),       // [GeV/c]
			      pythia->event[i].py(),       // [GeV/c] 
			      pythia->event[i].pz(),       // [GeV/c]
			      pythia->event[i].e(),        // [GeV]
			      pythia->event[i].m(),
			      pythia->event[i].xProd(),    // [mm]
			      pythia->event[i].yProd(),    // [mm]
			      pythia->event[i].zProd(),    // [mm] 
			      pythia->event[i].tProd(),
			      pythia->event[i].tau());   // [mm/c]
      
      if (verbosity > 8) cout << "particle: " << i << "  " << pythia->event[i].id() << endl;
      
    }
  
  if (verbosity > 3) cout << "PHPythia8::process_event - finished filling TClonesArray" << endl;
  
  Int_t numParticles = a.GetLast() + 1;	
  int nstable = 0;
  for (Int_t ipart=0; ipart<numParticles; ipart++)
    { 
      // get the particle information
      TMCParticle *particle = (TMCParticle*)a.At(ipart);	
      phpythia->addParticle(*particle);
      if ( phpythia->isStable(ipart) ) ++nstable;
    }
  
  if (verbosity > 3) cout << "PHPythia8::process_event - nstable: " << nstable << endl;
  
  phpythiaheader->SetEvt(eventcount);		// Event number
  phpythiaheader->SetNpart(numpart);	// Number of particle entries in entire history
  phpythiaheader->SetProcessid(pythia->info.code());	// Process ID
  phpythiaheader->SetParId_1(pythia->info.id1());	// KF codes for partons participating in hard scattering
  phpythiaheader->SetParId_2(pythia->info.id2());	// KF codes for partons participating in hard scattering
  phpythiaheader->SetX1(pythia->info.x1());		// Bjorken x1,x2
  phpythiaheader->SetX2(pythia->info.x2());
  phpythiaheader->SetSvar(pythia->info.sHat());	// partonic s,t,u
  phpythiaheader->SetTvar(pythia->info.tHat());
  phpythiaheader->SetUvar(pythia->info.uHat());
  phpythiaheader->SetQsqr(pythia->info.Q2Ren());	// Q squared
  phpythiaheader->SetPt(pythia->info.pTHat());		// transverse momentum
  
  // primary vertex information. Assume position is at zero by default
  phpythiaheader->SetPrimaryVertexX(0);
  phpythiaheader->SetPrimaryVertexY(0);
  phpythiaheader->SetPrimaryVertexZ(0);
  
  // rapidity of parton parton com frame
  phpythiaheader->SetYcom(pythia->info.y());	
   
  
}
int main(int argc, char* argv[])
{ 
  //Essentials

  //Upload the file with the data, make sure the adress of the file matches the one in your computer
  TFile* file = TFile::Open("/Users/Fer/Documents/traajo/samples/NeroNtuples_9.root"); // TFile::Open() instead of a constructor since it works over xrootd etc. =D
  
  //Upload the tree with the event data
  TTree *tree=(TTree*)file->Get("nero/events");

/////////////////////////////////////////////////////

  //Lepton criteria

  //Create a variable to store all the lepton event data
  TClonesArray *leptondata = new TClonesArray("leptondata");

  //Create the vector to store all the particle identifiers
  std::vector<Int_t> * lepPdgId= 0;

  //Specify where all the lepton event data will be stored
  tree->SetBranchAddress("lepP4", &leptondata);

  //Specify where all the lepton identifiers will be stored
  tree->SetBranchAddress("lepPdgId", &lepPdgId);

  //Histogram to plot the distribution of lepton mass 
  TH1F *lepmass = new TH1F("lepmass", "Lepton mass", 50, 0, 150);

/////////////////////////////////////////////////////

  //MET criteria

  //Create a variable to store all the "met" data
  TClonesArray *metdata = new TClonesArray("metdata");

  //Specify where all the "met" data will be stored
  tree->SetBranchAddress("metP4", &metdata);

  //Histogram to plot the distribution of the transverse mass 
  TH1F *metmass = new TH1F("metmass", "Missing transverse mass", 50, 0, 150);

/////////////////////////////////////////////////////

  //Eta criteria

  //Create the variable for Eta
  Double_t eta;

/////////////////////////////////////////////////////

  //Jet criteria

  //Create a variable to store all the jet event data
  TClonesArray *jetdata = new TClonesArray("jetdata");

  //Specify where all the jet event data will be stored
  tree->SetBranchAddress("jetP4", &jetdata);

  //Histogram to plot the distribution of jet mass 
  TH1F *jetmass = new TH1F("jetmass", "Jet mass", 50, 0, 150);

  //Variable to store the amount of jets
  Double_t size;

/////////////////////////////////////////////////////

  //Histogram to plot the distribution of the whole mass 
  TH1F *wholemass = new TH1F("wholemass", "Whole mass", 50, 0, 150);  

/////////////////////////////////////////////////////

  //Histogram variables

  //Create the canvas were the histograms will be ploted
  TCanvas* c1 = new TCanvas("c1", "Masses", 600, 600);

  //Divide that canvas to plot all histograms together
  c1->Divide(2,2);

/////////////////////////////////////////////////////

  //Variables for the for loop

  //Get how many events we have to loop through
  int nentries = tree->GetEntries();

  //Create a variable to store the mass values
  Double_t mass;

  //Loop through all the events
  for(int ientry = 0; ientry < nentries; ientry++) 
  {

    //Variable of the whole data
    TLorentzVector addable_lorentz_wholedata;

    //Reset the lepton data 
    leptondata->Clear();

    //Reset the met data 
    metdata->Clear();

    //Reset the jet data 
    jetdata->Clear();

    //This line stores the proper data in the variables qe specified
    tree->GetEntry(ientry);

/////////////////////////////////////////////////////

//Implementation of lepton criteria 

    //If "leptondata" is empty it skips and the for loop continues, this is to avoid segmentation errors
    if(leptondata->GetSize() != 1) continue;

      //Only if the identifier of the particle is ±11 or ± 13 (electrons muons or their anti particles) we use the data
      if((abs(lepPdgId->at(0))!=11)&&(abs(lepPdgId->at(0))!=13)) continue; 

      //Store all the data of the electron in this lorentz vector
      TLorentzVector * lorentz_leptondata = (TLorentzVector *)leptondata->At(0);

      //We create another lorentz vector that isn't a pointer for the same reasons that before
      TLorentzVector addable_lorentz_leptondata = *lorentz_leptondata;

      //Get the Eta value of that Lorentz vector
      eta=addable_lorentz_leptondata.Eta();

      //Get the transverse mass of that lorentz vector
      mass=addable_lorentz_leptondata.Mt();

      //Implementing slection criteria
      if (mass<40 || abs(eta)>2.5) continue;

      //Fill the histogram with the current data
      lepmass->Fill(mass);

/////////////////////////////////////////////////////
    
//Implementation of met criteria 

    //Create a lorentz vector with the matdata of the current entry
    TLorentzVector * lorentz_metdata = (TLorentzVector *) metdata->At(0);

    //We cannot use math with pointers for some reason, so we create a lorentz vectors that isn't a pointers
    TLorentzVector addable_lorentz_metdata = *lorentz_metdata;

    //Get the invariant transverse mass of that lorentz vector
    mass=addable_lorentz_metdata.Mt();
    
    //Implementing slection criteria
    if (mass<60) continue;
  
    metmass->Fill(mass);

/////////////////////////////////////////////////////
    
//Implementation of jet criteria 

    //If "jetdata" is empty it skips and the for loop continues, this is to avoid segmentation errors
    if(jetdata->GetSize() == 0) continue;

    size=jetdata->GetSize();

    if (size != 3) continue; 

      for (int i = 0; i < jetdata->GetSize()-1; ++i)
      {
      
        //Store all the data of the electron in this lorentz vector
        TLorentzVector * lorentz_jetdata = (TLorentzVector *)jetdata->At(i);

        //We create another lorentz vector that isn't a pointer for the same reasons that before
        TLorentzVector addable_lorentz_jetdata = *lorentz_jetdata;

        //Get the Eta value of that Lorentz vector
        eta=addable_lorentz_jetdata.Eta();

        //Get the transverse mass of that lorentz vector
        mass=addable_lorentz_jetdata.Mt();

        //Implementing slection criteria
        if (mass<30 || abs(eta)>2.4) continue;

        //Fill the histogram with the current data
        jetmass->Fill(mass);

        //We add the mass of each jet
        addable_lorentz_wholedata= addable_lorentz_jetdata+addable_lorentz_wholedata;
      }

      //Finally we add the MET mass and the lepton mass
      addable_lorentz_wholedata=addable_lorentz_metdata+addable_lorentz_leptondata;

      //Get the transverse mass of that lorentz vector
      mass=addable_lorentz_wholedata.Mt();

      //Fill the histogram with the current data
      wholemass->Fill(mass);
  }

  //Activate the first section of the canvas
  c1->cd(1);

  //Make the histogram
  metmass->Draw("H");

  //Put it in the canvas
  c1->Update();

  //Repeat
  c1->cd(2);
  lepmass->Draw("H");
  c1->Update();

  c1->cd(3);
  jetmass->Draw("H");
  c1->Update();

  c1->cd(4);
  wholemass->Draw("H");
  c1->Update();

  //Save the image
  c1->SaveAs("chargedHiggs_masses.pdf");
  c1->Close();

  // cleanup
  delete file; // automatically deletes "tree" too
  delete lepPdgId;
  delete leptondata;
  delete metdata;
  delete jetdata;
  return 0; 
}
void selectEleHZZHCP2012IDGivenIsoWithTightTagPerFile(const string inputfile,          // input file
                              const string outputfile,         // output directory
                              const Bool_t  matchGen = kFALSE, // match to generator muons
                              Int_t dataType = 0,              // del = 0, sel = 1, mc = -1
                              Int_t DataEraInput = 2
  ) {
  gBenchmark->Start("selectEleMVAIsoTightGivenID");

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 
  UInt_t DataEra = kDataEra_NONE;
  if (DataEraInput == 1) DataEra = kDataEra_2011_MC;
  if (DataEraInput == 2) DataEra = kDataEra_2012_MC;
  if (DataEraInput == 11) DataEra = kDataEra_2011_Data;
  if (DataEraInput == 12) DataEra = kDataEra_2012_Data;

  //*****************************************************************************************
  //Setup MVA
  //*****************************************************************************************
  EGammaMvaEleEstimator *eleIDMVA = new EGammaMvaEleEstimator();
  vector<string> weightFiles;

  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat1.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat2.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat3.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat4.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat5.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat6.weights.xml")).c_str());
  eleIDMVA->initialize( "BDT", EGammaMvaEleEstimator::kNonTrig,  kTRUE, weightFiles);
  

  // mass region
  Double_t massLo = 40;
  Double_t massHi = 200;

  
  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  Double_t nProbes = 0;
  
  //
  // Set up output ntuple
  //
  TFile *outFile = new TFile(outputfile.c_str(),"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:rho/F");

  TFile *infile=0;
  TTree *eventTree=0;
  
  // Data structures to store info from TTrees
  higgsana::TEventInfo *info  = new higgsana::TEventInfo();
  higgsana::TGenInfo *gen     = new higgsana::TGenInfo();
  TClonesArray *electronArr = new TClonesArray("higgsana::TElectron");
  TClonesArray *pfcandidateArr = new TClonesArray("higgsana::TPFCandidate");
  TClonesArray *muonArr = new TClonesArray("higgsana::TMuon");

  // Read input file and get the TTrees
  cout << "Processing " << inputfile << "..." << endl;
  infile = TFile::Open(inputfile.c_str(),"read");
  assert(infile);



  //********************************************************
  // Good RunLumi Selection
  //********************************************************
  Bool_t hasJSON = kFALSE;
  mithep::RunLumiRangeMap rlrm;
  if (!matchGen) {
    hasJSON = kTRUE;
    rlrm.AddJSONFile("/afs/cern.ch/work/s/sixie/public/HZZ4l/auxiliar/2012/Cert_Full2012_53X_JSON.txt"); 
    rlrm.AddJSONFile("/afs/cern.ch/work/s/sixie/public/HZZ4l/auxiliar/2011/2011Combined.json");
  }
    
  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("Muon", &muonArr);         TBranch *muonBr = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("PFCandidate", &pfcandidateArr);  TBranch *pfcandidateBr = eventTree->GetBranch("PFCandidate");
  cout << "NEvents = " << eventTree->GetEntries() << endl;

  TBranch *genBr = 0;
  if(matchGen) {
    eventTree->SetBranchAddress("Gen", &gen);
    genBr = eventTree->GetBranch("Gen");
  }
    
  Double_t weight = 1;

  // loop over events
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
    if (ientry % 100000 == 0) cout << "Processed Event " << ientry << endl;
    infoBr->GetEntry(ientry);

    // check for certified runs
    mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
    if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  
 
    //***********************************************************
    // Definition of Pileup Energy density
    //***********************************************************
    Double_t rhoEleIso = 0;
    UInt_t EleEAEra = 0;
    if (DataEra == kDataEra_2011_MC) {
        
      if (!(isnan(info->RhoKt6PFJetsForIso25) || 
            isinf(info->RhoKt6PFJetsForIso25))) {
        rhoEleIso = info->RhoKt6PFJetsForIso25;
      }
      EleEAEra = kDataEra_2011_Data;
        
    } else if (DataEra == kDataEra_2012_MC) {
        
      if (!(isnan(info->RhoKt6PFJets) || 
            isinf(info->RhoKt6PFJets))) {
        rhoEleIso = info->RhoKt6PFJets;
      }
      EleEAEra = kDataEra_2012_Data;
    }

    //use only odd numbered events to evaluate efficiency for data. even numbered events were used for training
    //if (info->evtNum % 2 == 0 && !matchGen) continue;


    // trigger requirement               
    Bool_t passTrigger = kFALSE;
    if(dataType == 0) {
      if ((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) == kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) == kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) == kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) passTrigger = kTRUE;
    } else if(dataType == 1) {
      if(DataEraInput == 2) {
        if(info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50)  continue;
        if(info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30)  continue;
        if(info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17)                         continue;
      }
        
      if ((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) == kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) passTrigger = kTRUE;
    }
    if(dataType != -1 && !passTrigger) continue;     
      
    // good vertex requirement
    if(!(info->hasGoodPV)) continue;

    if(matchGen) genBr->GetEntry(ientry);
      
    electronArr->Clear();
    muonArr->Clear(); 
    pfcandidateArr->Clear(); 
    electronBr->GetEntry(ientry);
    muonBr->GetEntry(ientry);
    pfcandidateBr->GetEntry(ientry);

    //********************************************************
    //Low Met Requirement
    //********************************************************
    TVector3 met;        
    if(info->pfMEx!=0 || info->pfMEy!=0) {       
      met.SetXYZ(info->pfMEx, info->pfMEy, 0);
    }
    if (met.Pt() > 25) continue;
      

    //********************************************************
    //Loop over TAG electrons
    //********************************************************
    for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {

      const higgsana::TElectron *tag = (higgsana::TElectron*)((*electronArr)[i]);
	
      if(matchGen) {
        Bool_t match1 = (higgsana::deltaR(tag->eta, tag->phi, gen->eta_1, gen->phi_1) < 0.5);
        Bool_t match2 = (higgsana::deltaR(tag->eta, tag->phi, gen->eta_2, gen->phi_2) < 0.5);
        if(!match1 && !match2)
          continue;
      }

      if(tag->pt          < 20)  continue;
      if(fabs(tag->scEta) > 2.5) continue;

      if (!PassEleSimpleCutsVeryTight(tag,pfcandidateArr,rhoEleIso,EleEAEra)) continue;

      if(dataType == 0 &&
         !((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) && (tag->hltMatchBits & kHLTObject_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT)) &&
         !((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) && (tag->hltMatchBits & kHLTObject_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT)) &&
         !((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdL_CaloIsoVL)) &&
         !((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdT_CaloIsoT_TrkIdT_TrkIsoT)) &&
         !((info->triggerBits & kHLT_Ele17_CaloIdL_CaloIsoVL) && (tag->hltMatchBits & kHLTObject_Ele17_CaloIdL_CaloIsoVL)) ) 
        continue;
      
      if (dataType == 1) {
        if(dataType == 1 &&
           !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && tag->pt > 30) &&
           !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && tag->pt > 35) &&
           !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele52_CaloIdVT_TrkIdT) && tag->pt > 60) &&
           !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele27_WP80) && tag->pt > 30) && 
           !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele32_WP70) && tag->pt > 35)  
          )
          continue;       
      }

      const Double_t m = 0.000511;
      TLorentzVector vtag;
      vtag.SetPtEtaPhiM(tag->pt, tag->eta, tag->phi, m);
        
      for(Int_t j=0; j<electronArr->GetEntriesFast(); j++) {
        if(i==j) continue;
	  
        const higgsana::TElectron *probe = (higgsana::TElectron*)((*electronArr)[j]);
        if(probe->q == tag->q) continue;
	  
// 	  if(typev[ifile]==eDiEl &&
// 	     !((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) && (probe->hltMatchBits & kHLTObject_SC8)) &&
// 	     !((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) && (probe->hltMatchBits & kHLTObject_Ele8)) &&
// 	     !((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) && (probe->hltMatchBits & kHLTObject_SC17)))
// 	    continue;
	  
        if(matchGen) {
          Bool_t match1 = (higgsana::deltaR(probe->eta, probe->phi, gen->eta_1, gen->phi_1) < 0.5);
          Bool_t match2 = (higgsana::deltaR(probe->eta, probe->phi, gen->eta_2, gen->phi_2) < 0.5);
          if(!match1 && !match2)
            continue;
        }
	  
        if(fabs(probe->scEta) > 2.5) continue;

        TLorentzVector vprobe;
        vprobe.SetPtEtaPhiM(probe->pt, probe->eta, probe->phi, m);
	  
        TLorentzVector vdielectron = vtag + vprobe;
        if((vdielectron.M()<massLo) || (vdielectron.M()>massHi)) continue;	  	  

        //for probes with pT < 10, require the Ele20_SC4 trigger
        if (probe->pt < 10) {
          if(dataType == 0) {

            if (!((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) == kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50)) continue;
            if (!((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) && (tag->hltMatchBits & kHLTObject_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT))) continue;
          }
        }

        nProbes++;

        Bool_t passID = (PassEleHZZ4lPreselection(probe) && PassEleHZZ4lICHEP2012ID(probe, eleIDMVA));
        
        vector<const higgsana::TPFCandidate*> photonsToVeto;
        Bool_t passIsolation = PassEleHZZ4lICHEP2012Iso(probe,j,pfcandidateArr,rhoEleIso,EleEAEra,photonsToVeto);
        if (!passIsolation) continue;

        //******************
        //PASS
        //******************
        Bool_t pass = passID && passIsolation;

        // Fill tree
        data.mass   = vdielectron.M();
        data.pt     = probe->pt;
        data.eta    = probe->scEta;
        data.phi    = probe->phi;
        data.weight = weight;
        data.q      = probe->q;
        data.npv    = info->nPV0;
        data.npu    = info->nPUEvents;
        data.pass   = (pass) ? 1 : 0;
        data.rho    = rhoEleIso;
        data.runNum = info->runNum;
        data.lumiSec = info->lumiSec;
        data.evtNum = info->evtNum;

        outTree->Fill();	  
      }
    }
  }

  delete infile;
  infile=0, eventTree=0;      
  delete info;
  delete gen;
  delete electronArr;
  
     
  //--------------------------------------------------------------------------------------------------------------
  // 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 " << outputfile << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectEleLHEffTP"); 
}
void computeAccSelZeeBinned(const TString conf,            // input file
                            const TString outputDir,        // output directory
			    const Int_t   doPU
) {
  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;

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 11;
  
  // efficiency files
  const TString dataHLTEffName     = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MG/eff.root";
  const TString dataHLTEffName_pos = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MG/eff.root";
  const TString dataHLTEffName_neg = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MG/eff.root";

  const TString zeeHLTEffName      = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CT/eff.root";
  const TString zeeHLTEffName_pos  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CT/eff.root";
  const TString zeeHLTEffName_neg  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CT/eff.root";
  
  const TString dataGsfSelEffName     = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MG/eff.root";
  const TString dataGsfSelEffName_pos = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MG/eff.root";
  const TString dataGsfSelEffName_neg = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MG/eff.root";

  const TString zeeGsfSelEffName      = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CT/eff.root";
  const TString zeeGsfSelEffName_pos  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CT/eff.root";
  const TString zeeGsfSelEffName_neg  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CT/eff.root";

  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/pileup_rw_76X.root", "read");
  TH1D *h_rw = (TH1D*) f_rw->Get("h_rw_golden");


  //--------------------------------------------------------------------------------------------------------------
  // 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
  baconhep::TEventInfo   *info = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *electronArr    = new TClonesArray("baconhep::TElectron");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");

  TFile *infile=0;
  TTree *eventTree=0;
  
  // Variables to store acceptances and uncertainties (per input file)
  vector<Double_t> nEvtsv, nSelv;
  vector<Double_t> nSelCorrv, nSelCorrVarv;
  vector<Double_t> accv, accCorrv;
  vector<Double_t> accErrv, accErrCorrv;

  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  //
  // 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 = TFile::Open(fnamev[ifile]); 
    assert(infile);

    eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
    eventTree->SetBranchAddress("Info",              &info); TBranch *infoBr     = eventTree->GetBranch("Info");
    eventTree->SetBranchAddress("GenEvtInfo",         &gen); TBranch *genBr      = eventTree->GetBranch("GenEvtInfo");
    eventTree->SetBranchAddress("GenParticle", &genPartArr); TBranch *genPartBr  = eventTree->GetBranch("GenParticle");
    eventTree->SetBranchAddress("Electron",   &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
    eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");

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

    //
    // loop over events
    //
    for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
      genBr->GetEntry(ientry);
      genPartArr->Clear(); genPartBr->GetEntry(ientry);
      infoBr->GetEntry(ientry);

      Int_t glepq1=-99;
      Int_t glepq2=-99;

      if (fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
      TLorentzVector *vec=new TLorentzVector(0,0,0,0);
      TLorentzVector *lep1=new TLorentzVector(0,0,0,0);
      TLorentzVector *lep2=new TLorentzVector(0,0,0,0);
      toolbox::fillGen(genPartArr, BOSON_ID, vec, lep1, lep2,&glepq1,&glepq2,1);
      if(vec->M()<MASS_LOW || vec->M()>MASS_HIGH) continue;      
      delete vec; delete lep1; delete lep2;

      vertexArr->Clear();
      vertexBr->GetEntry(ientry);
      double npv  = vertexArr->GetEntries();
      Double_t weight=gen->weight;
      if(doPU>0) weight*=h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));

      nEvtsv[ifile]+=weight;        

      // trigger requirement               
      if (!isEleTrigger(triggerMenu, info->triggerBits, kFALSE)) continue;
      
      // good vertex requirement
      if(!(info->hasGoodPV)) continue;
      
      electronArr->Clear();
      electronBr->GetEntry(ientry);

      for(Int_t i1=0; i1<electronArr->GetEntriesFast(); i1++) {
  	const baconhep::TElectron *ele1 = (baconhep::TElectron*)((*electronArr)[i1]);
	
	// check ECAL gap
	if(fabs(ele1->scEta)>=ETA_BARREL && fabs(ele1->scEta)<=ETA_ENDCAP) continue;
	
	//double ele1_pt = gRandom->Gaus(ele1->pt*getEleScaleCorr(ele1->scEta,0), getEleResCorr(ele1->scEta,0));

	if(ele1->pt	     < PT_CUT && ele1->scEt < PT_CUT)	  continue;  // lepton pT cut
        if(fabs(ele1->scEta) > ETA_CUT && fabs(ele1->eta) > ETA_CUT)	  continue;  // lepton |eta| cut
        if(!passEleID(ele1,info->rhoIso)) continue;  // lepton selection
	//if(!isEleTriggerObj(triggerMenu, ele1->hltMatchBits, kFALSE, kFALSE)) continue;

        TLorentzVector vEle1(0,0,0,0);
	vEle1.SetPtEtaPhiM(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 baconhep::TElectron *ele2 = (baconhep::TElectron*)((*electronArr)[i2]);
	  
	  // check ECAL gap
	  if(fabs(ele2->scEta)>=ETA_BARREL && fabs(ele2->scEta)<=ETA_ENDCAP) continue;
	  //double ele2_pt = gRandom->Gaus(ele2->scEt*getEleScaleCorr(ele2->scEta,0), getEleResCorr(ele2->scEta,0));
	  if(ele1->q == ele2->q)	continue;
          if(ele2->pt        < PT_CUT && ele2->scEt < PT_CUT)    continue;  // lepton pT cut
          if(fabs(ele2->scEta) > ETA_CUT && fabs(ele2->eta) > ETA_CUT)   continue;  // lepton |eta| cut
	  if(!passEleID(ele2,info->rhoIso)) continue;  // lepton selection

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

	  if(!isEleTriggerObj(triggerMenu, ele1->hltMatchBits, kFALSE, kFALSE) && !isEleTriggerObj(triggerMenu, ele2->hltMatchBits, kFALSE, kFALSE)) continue;
	  
	  // mass window
          TLorentzVector 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 sceta1 = ele1->scEta;
          //Double_t sceta2 = (fabs(ele2->scEta)<2.5) ? ele2->scEta : 0.99*(ele2->scEta);
    	  Double_t sceta2 = 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(sceta1, ele1->scEt); 
            effmc   *= zeeGsfSelEff_pos.getEff(sceta1, ele1->scEt); 
          } else {
            effdata *= dataGsfSelEff_neg.getEff(sceta1, ele1->scEt); 
            effmc   *= zeeGsfSelEff_neg.getEff(sceta1, ele1->scEt); 
          }
          if(ele2->q>0) {
            effdata *= dataGsfSelEff_pos.getEff(sceta2, ele2->scEt); 
            effmc   *= zeeGsfSelEff_pos.getEff(sceta2, ele2->scEt);
          } else {
            effdata *= dataGsfSelEff_neg.getEff(sceta2, ele2->scEt); 
            effmc   *= zeeGsfSelEff_neg.getEff(sceta2, ele2->scEt);
          }
          corr *= effdata/effmc;
	  
	  // scale factor uncertainties
	  if(ele1->q>0) {	    
	    Double_t effdata = dataGsfSelEff_pos.getEff(sceta1, ele1->scEt);
	    Double_t errdata = TMath::Max(dataGsfSelEff_pos.getErrLow(sceta1, ele1->scEt), dataGsfSelEff_pos.getErrHigh(sceta1, ele1->scEt));
            Double_t effmc   = zeeGsfSelEff_pos.getEff(sceta1, ele1->scEt); 
	    Double_t errmc   = TMath::Max(zeeGsfSelEff_pos.getErrLow(sceta1, ele1->scEt), zeeGsfSelEff_pos.getErrHigh(sceta1, ele1->scEt));
	    Double_t errGsfSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    hGsfSelErr_pos->Fill(sceta1, ele1->scEt, errGsfSel);
	  } else {
	    Double_t effdata = dataGsfSelEff_neg.getEff(sceta1, ele1->scEt);
	    Double_t errdata = TMath::Max(dataGsfSelEff_neg.getErrLow(sceta1, ele1->scEt), dataGsfSelEff_neg.getErrHigh(sceta1, ele1->scEt));
            Double_t effmc   = zeeGsfSelEff_neg.getEff(sceta1, ele1->scEt); 
	    Double_t errmc   = TMath::Max(zeeGsfSelEff_neg.getErrLow(sceta1, ele1->scEt), zeeGsfSelEff_neg.getErrHigh(sceta1, ele1->scEt));
	    Double_t errGsfSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    hGsfSelErr_neg->Fill(sceta1, ele1->scEt, errGsfSel);
	  }

	  if(ele2->q>0) {	    
	    Double_t effdata = dataHLTEff_pos.getEff(sceta2, ele2->scEt);
	    Double_t errdata = TMath::Max(dataHLTEff_pos.getErrLow(sceta2, ele2->scEt), dataHLTEff_pos.getErrHigh(sceta2, ele2->scEt));
            Double_t effmc   = zeeHLTEff_pos.getEff(sceta2, ele2->scEt); 
	    Double_t errmc   = TMath::Max(zeeHLTEff_pos.getErrLow(sceta2, ele2->scEt), zeeHLTEff_pos.getErrHigh(sceta2, ele2->scEt));
	    Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    hHLTErr_pos->Fill(sceta2, ele2->scEt, errHLT);
	  } else {
	    Double_t effdata = dataHLTEff_neg.getEff(sceta2, ele2->scEt);
	    Double_t errdata = TMath::Max(dataHLTEff_neg.getErrLow(sceta2, ele2->scEt), dataHLTEff_neg.getErrHigh(sceta2, ele2->scEt));
            Double_t effmc   = zeeHLTEff_neg.getEff(sceta2, ele2->scEt); 
	    Double_t errmc   = TMath::Max(zeeHLTEff_neg.getErrLow(sceta2, ele2->scEt), zeeHLTEff_neg.getErrHigh(sceta2, ele2->scEt));
	    Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    hHLTErr_neg->Fill(sceta2, ele2->scEt, errHLT);
	  }

	  nSelv[ifile]+=weight;
	  nSelCorrv[ifile]+=weight*corr;
	  nSelCorrVarv[ifile]+=weight*weight*corr*corr;
	}
      }
    }
    
    Double_t var=0;
    for(Int_t iy=0; iy<=hHLTErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr_pos->GetNbinsX(); ix++) {
	Double_t err=hHLTErr_pos->GetBinContent(ix,iy);
	var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hHLTErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr_neg->GetNbinsX(); ix++) {
	Double_t err=hHLTErr_neg->GetBinContent(ix,iy);
	var+=err*err;
      }
    }
    cout << "var1: " << var << endl;
    for(Int_t iy=0; iy<=hGsfSelErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hGsfSelErr_pos->GetNbinsX(); ix++) {
	Double_t err=hGsfSelErr_pos->GetBinContent(ix,iy);
	var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hGsfSelErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hGsfSelErr_neg->GetNbinsX(); ix++) {
	Double_t err=hGsfSelErr_neg->GetBinContent(ix,iy);
	var+=err*err;
      }
    }
    cout << "var2: " << var << endl;

    nSelCorrVarv[ifile]+=var;

    // compute acceptances
    std::cout << nEvtsv[ifile] << " " << nSelv[ifile] << std::endl;
    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]); accErrCorrv.push_back(accCorrv[ifile]*sqrt((nSelCorrVarv[ifile])/(nSelCorrv[ifile]*nSelCorrv[ifile]) + 1./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] << " +/- " << accErrCorrv[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] << " +/- " << accErrCorrv[ifile] << endl;
    txtfile << endl;
  }
  txtfile.close();
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("computeAccSelZeeBinned"); 
}
Exemple #9
0
void compare(TString filenameA, TString filenameB)
{
    TFile *fileA = TFile::Open(filenameA);
    TTree *tree = (TTree *)fileA->Get("cbmsim");
    tree->AddFriend("cbmsimB = cbmsim", filenameB);

    TClonesArray *digisA = new TClonesArray("R3BLandDigi");
    tree->GetBranch("LandDigi")->SetAutoDelete(kFALSE);
    tree->SetBranchAddress("LandDigi", &digisA);

    TClonesArray *digisB = new TClonesArray("R3BLandDigi");
    tree->GetBranch("cbmsimB.LandDigi")->SetAutoDelete(kFALSE);
    tree->SetBranchAddress("cbmsimB.LandDigi", &digisB);



    TH1D *hNumLandDigis = new TH1D("hNumLandDigis", "N(LandDigis, A) - N(LandDigis, B)", 51, -25., 25.);
    TH1D *hEtot  = new TH1D("hEtot", "E(tot, A) - E(tot, B)", 201, -100., 100.);
    TH1D *hEtotA = new TH1D("hEtotA", "E(tot, A)", 2000, 1., 2001.);
    TH1D *hEtotB = new TH1D("hEtotB", "E(tot, B)", 2000, 1., 2001.);
    TH1D *hTmin  = new TH1D("hTmin", "T(min, A) - T(min, B)", 201, -10., 10.);

    UInt_t nentries = tree->GetEntries();
    for (UInt_t ev = 0; ev < nentries; ev++) {
        digisA->Clear();
        digisB->Clear();

        tree->GetEntry(ev);


        int nA = digisA->GetEntries();
        int nB = digisB->GetEntries();
        hNumLandDigis->Fill(nA - nB);


        R3BLandDigi *digi;
        double EtotA = 0.;
        for (int i = 0; i < nA; i++) {
            digi = (R3BLandDigi *)digisA->At(i);
            EtotA += digi->GetQdc();
        }
        hEtotA->Fill(EtotA);
        double EtotB = 0.;
        for (int i = 0; i < nB; i++) {
            digi = (R3BLandDigi *)digisB->At(i);
            EtotB += digi->GetQdc();
        }
        hEtotB->Fill(EtotB);
        hEtot->Fill(EtotA - EtotB);


        double TminA = 1000;
        for (int i = 0; i < nA; i++) {
            digi = (R3BLandDigi *)digisA->At(i);
            if (digi->GetTdc() < TminA) {
                TminA = digi->GetTdc();
            }
        }
        double TminB = 1000;
        for (int i = 0; i < nB; i++) {
            digi = (R3BLandDigi *)digisB->At(i);
            if (digi->GetTdc() < TminB) {
                TminB = digi->GetTdc();
            }
        }
        hTmin->Fill(TminA - TminB);
    }


    TCanvas *c1 = new TCanvas("c1", "", 900, 700);
    c1->Divide(2, 2);
    c1->cd(1);
    hNumLandDigis->Draw();
    c1->cd(2);
    hEtot->Draw();
    c1->cd(3);
    hTmin->Draw();
    c1->cd(4);
    hEtotA->Draw();
    hEtotB->SetLineColor(kRed);
    hEtotB->Draw("same");

}
void selectEleHZZRun1LegacyPaperIsoGivenIDWithZeeGammaPerFile(const string inputfile,          // input file
                                                const string outputfile,         // output directory
                                                const Bool_t  matchGen = kFALSE, // match to generator muons
                                                Int_t dataType = 0,              // del = 0, sel = 1, mc sig = -1, mc bkg = -2
                                                Int_t DataEraInput = 2
  ) {

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 
  UInt_t DataEra = kDataEra_NONE;
  if (DataEraInput == 1) DataEra = kDataEra_2011_MC;
  if (DataEraInput == 2) DataEra = kDataEra_2012_MC;
  if (DataEraInput == 11) DataEra = kDataEra_2011_Data;
  if (DataEraInput == 12) DataEra = kDataEra_2012_Data;

  //*****************************************************************************************
  //Setup MVA
  //*****************************************************************************************
  EGammaMvaEleEstimator *eleIDMVA = new EGammaMvaEleEstimator();
  vector<string> weightFiles;

  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat1.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat2.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat3.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat4.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat5.weights.xml")).c_str());
  weightFiles.push_back((string(getenv("CMSSW_BASE"))+string("/src/HiggsAna/HZZ4l/data/ElectronIDMVAWeights/Electrons_BDTG_NonTrigV0_Cat6.weights.xml")).c_str());
  eleIDMVA->initialize( "BDT", EGammaMvaEleEstimator::kNonTrig,  kTRUE, weightFiles);
  

  // mass region
  Double_t massLo = 40;
  Double_t massHi = 200;

  
  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  Double_t nProbes = 0;
  
  //
  // Set up output ntuple
  //
  TFile *outFile = new TFile(outputfile.c_str(),"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:rho/F");

  TFile *infile=0;
  TTree *eventTree=0;
  
  // Data structures to store info from TTrees
  higgsana::TEventInfo *info  = new higgsana::TEventInfo();
  TClonesArray *genparticleArr = new TClonesArray("higgsana::TGenParticle");
  TClonesArray *electronArr = new TClonesArray("higgsana::TElectron");
  TClonesArray *photonArr = new TClonesArray("higgsana::TPhoton");
  TClonesArray *pfcandidateArr = new TClonesArray("higgsana::TPFCandidate");
  TClonesArray *muonArr = new TClonesArray("higgsana::TMuon");

  // Read input file and get the TTrees
  cout << "Processing " << inputfile << "..." << endl;
  infile = TFile::Open(inputfile.c_str(),"read");
  assert(infile);



  //********************************************************
  // Good RunLumi Selection
  //********************************************************
  Bool_t hasJSON = kFALSE;
  mithep::RunLumiRangeMap rlrm;
  if (!matchGen) {
    hasJSON = kTRUE;
    rlrm.AddJSONFile("/afs/cern.ch/work/s/sixie/public/HZZ4l/auxiliar/2012/Cert_Full2012_53X_JSON.txt"); 
  }
    
  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", &photonArr); TBranch *photonBr = eventTree->GetBranch("Photon");
  eventTree->SetBranchAddress("Muon", &muonArr);         TBranch *muonBr = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("PFCandidate", &pfcandidateArr);  TBranch *pfcandidateBr = eventTree->GetBranch("PFCandidate");
  cout << "NEvents = " << eventTree->GetEntries() << endl;

  TBranch *genparticleBr;
  if(matchGen) {
    eventTree->SetBranchAddress("GenParticle", &genparticleArr);
    genparticleBr = eventTree->GetBranch("GenParticle");
  }
    
  Double_t weight = 1;

  // loop over events
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
    if (ientry % 100000 == 0) cout << "Processed Event " << ientry << endl;
    infoBr->GetEntry(ientry);
    
    // check for certified runs
    mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
    if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  

    //***********************************************************
    // Definition of Pileup Energy density
    //***********************************************************
    Double_t rhoEleIso = 0;
    UInt_t EleEAEra = 0;
    if (DataEra == kDataEra_2011_MC) {
        
      if (!(isnan(info->RhoKt6PFJetsForIso25) || 
            isinf(info->RhoKt6PFJetsForIso25))) {
        rhoEleIso = info->RhoKt6PFJetsForIso25;
      }
      EleEAEra = kDataEra_2011_Data;
        
    } else if (DataEra == kDataEra_2012_MC) {
        
      if (!(isnan(info->RhoKt6PFJets) || 
            isinf(info->RhoKt6PFJets))) {
        rhoEleIso = info->RhoKt6PFJets;
      }
      EleEAEra = kDataEra_2012_Data;
    }

    //use only odd numbered events to evaluate efficiency for data. even numbered events were used for training
    //Don't need this for zee gamma
    //if (info->evtNum % 2 == 0 && !matchGen) continue;

    // trigger requirement               
    Bool_t passTrigger = kFALSE;
    if(dataType == 0 ) {
      if ((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) == kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) == kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) == kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) passTrigger = kTRUE;
    } else if(dataType == 1 ) {
      if(info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50)  continue;
      if(info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30)  continue;
      if(info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17)                         continue;
 
      if ((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) == kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) passTrigger = kTRUE;
    } else if (dataType < 0) {
      if ((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) == kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) == kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) == kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) passTrigger = kTRUE;
      if ((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) == kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) passTrigger = kTRUE;
    }
    if(!passTrigger) continue;     



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

    electronArr->Clear();
    muonArr->Clear(); 
    pfcandidateArr->Clear(); 
    genparticleArr->Clear(); 
    electronBr->GetEntry(ientry);
    photonBr->GetEntry(ientry);
    muonBr->GetEntry(ientry);
    pfcandidateBr->GetEntry(ientry);
    if(matchGen) {
      genparticleBr->GetEntry(ientry);
    }  


    //********************************************************
    //Loop over TAG electrons
    //********************************************************
    vector<Int_t> probeAlreadyUsed;
    for(Int_t i=0; i<electronArr->GetEntriesFast(); ++i) {
      probeAlreadyUsed.push_back(kFALSE);
    }

    for(Int_t i=0; i<electronArr->GetEntriesFast(); ++i) {

      const higgsana::TElectron *tag = (higgsana::TElectron*)((*electronArr)[i]);
	
      Bool_t TagIsEle = MatchedToStatus1Ele(tag, genparticleArr);

      if(tag->pt          < 20)  continue;
      if(fabs(tag->scEta) > 2.5) continue;
//       if(dataType == 1) {
//         if(tag->pt          < 30)  continue;
//       }

      if (!passCutBasedEleID(tag, ComputeElePFIso04(tag,pfcandidateArr,rhoEleIso,EleEAEra))) continue;

      if(dataType == 0 &&
         !((info->triggerBits & kHLT_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC4_Mass50) && (tag->hltMatchBits & kHLTObject_Ele20_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT)) &&
         !((info->triggerBits & kHLT_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT_SC8_Mass30) && (tag->hltMatchBits & kHLTObject_Ele17_CaloIdVT_CaloIsoVT_TrkIdT_TrkIsoVT)) &&
         !((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdL_CaloIsoVL)) &&
         !((info->triggerBits & kHLT_Ele32_CaloIdL_CaloIsoVL_SC17) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdT_CaloIsoT_TrkIdT_TrkIsoT))         
        )
        continue;
      
      if(dataType == 1 &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele32_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele52_CaloIdVT_TrkIdT)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele65_CaloIdVT_TrkIdT)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele80_CaloIdVT_TrkIdT)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele27_WP80)) &&
         !((info->triggerBits & kHLT_Ele27_CaloIdVT_CaloIsoT_TrkIdT_TrkIsoT) && (tag->hltMatchBits & kHLTObject_Ele32_WP70))
        ) 
        continue;
        

      const Double_t m = 0.000511;
      TLorentzVector vtag;
      vtag.SetPtEtaPhiM(tag->pt, tag->eta, tag->phi, m);
        
      //Find Photon
      for(Int_t j=0; j<photonArr->GetEntriesFast(); ++j) {
      
        const higgsana::TPhoton *pho = (higgsana::TPhoton*)((*photonArr)[j]);
        TLorentzVector vpho;
        vpho.SetPtEtaPhiM(pho->et, pho->eta, pho->phi, 0);
        
        if (pho->et < 10) continue;
        if (fabs(pho->eta) > 2.5) continue;
    
        if (!passPhotonSimpleCuts(pho)) continue;        

        Bool_t PhotonIsReal = MatchedToStatus1Photon(pho, genparticleArr);

        if (fabs(tag->eta - pho->eta) < 0.15 && higgsana::deltaR( tag->eta, tag->phi, pho->eta, pho->phi) < 0.7) continue;                

        //Find Probes
        for(Int_t k=0; k<electronArr->GetEntriesFast(); ++k) {

          //no duplicates
          if(k==i) continue;    
          if (probeAlreadyUsed[k]) continue;

          const higgsana::TElectron *probe = (higgsana::TElectron*)((*electronArr)[k]);
          if(probe->q == tag->q) continue;
          TLorentzVector vprobe;
          vprobe.SetPtEtaPhiM(probe->pt, probe->eta, probe->phi, m);

          Bool_t ProbeIsEle = MatchedToStatus1Ele(probe, genparticleArr);


          //High Efficiency Pixel Veto
          double minDEta = fmin( fabs(tag->eta - pho->eta) , fabs(probe->eta - pho->eta ));
          double minDPhi = fmin( higgsana::deltaPhi(tag->phi, pho->phi) , higgsana::deltaPhi( probe->phi, pho->phi));
          double minDR = fmin( higgsana::deltaR(tag->eta,tag->phi, pho->eta, pho->phi) , higgsana::deltaR( probe->eta, probe->phi, pho->eta, pho->phi));
          Bool_t passPixelVeto = kTRUE;
          if (fabs(pho->eta) < 1.479) {
            if (minDEta > 0.04 || minDPhi > 0.3) {
              if (pho->hasPixelSeed) passPixelVeto = kFALSE;
            }
          } else {
            if (minDEta > 0.08 || minDPhi > 0.3) {
              if (pho->hasPixelSeed) passPixelVeto = kFALSE;
            }
          }

          //more eegamma selection cuts          
          if (fabs( probe->eta - pho->eta) < 0.15 && higgsana::deltaR( probe->eta, probe->phi, pho->eta, pho->phi) < 0.7) continue;

          //Selection cuts
          if (!((vtag + vpho + vprobe).M() + (vtag+vprobe).M() < 180)) continue;
          if (!((vtag+vprobe).M() > 40)) continue;
          if (!(higgsana::deltaR(probe->eta, probe->phi, pho->eta, pho->phi) < 1.5)) continue;
          if (!passPixelVeto) continue;

          //cut to emulate trigger.
          if (!((vtag+vpho).M() > 50)) continue;


          //optional cuts for tighter selection
          if (dataType == 0 || dataType == 1) {
            if (!(higgsana::deltaR(probe->eta, probe->phi, pho->eta, pho->phi) < 0.7)) continue;
          }
            
          //gen matching for MC
          if (matchGen) {
            if (dataType == -1) {
              if (!(TagIsEle && PhotonIsReal && ProbeIsEle)) continue;
              if (!(higgsana::deltaR(probe->eta, probe->phi, pho->eta, pho->phi) < 0.7)) continue;
            }
            if (dataType == -2) {
              if ((TagIsEle && PhotonIsReal && ProbeIsEle)) continue;
            }
          }

          TLorentzVector vdielectrongamma = vtag + vpho + vprobe;
          if((vdielectrongamma.M()<massLo) || (vdielectrongamma.M()>massHi)) continue;	  	  
 

          //find pfphotons to remove the photon footprint
          vector<const higgsana::TPFCandidate*> photonsToVeto;

          Double_t pfphotonMinDR = 9999;
          const higgsana::TPFCandidate *photonPFCandidate = 0;
          for( uint p=0; p< uint(pfcandidateArr->GetEntries()); ++p ) {
            const higgsana::TPFCandidate *pf = (higgsana::TPFCandidate*)((*pfcandidateArr)[p]);
            if (higgsana::deltaR(pho->eta,pho->phi,pf->eta,pf->phi) < pfphotonMinDR) {
              photonPFCandidate = pf;
              pfphotonMinDR = higgsana::deltaR(pho->eta,pho->phi,pf->eta,pf->phi);
            }
          }
          if (pfphotonMinDR < 0.1) photonsToVeto.push_back(photonPFCandidate);

          for( uint p=0; p< uint(pfcandidateArr->GetEntries()); ++p ) {
            const higgsana::TPFCandidate *pf = (higgsana::TPFCandidate*)((*pfcandidateArr)[p]);
            if (pf->pfType != eGamma) continue;
            if (fabs(pho->eta) < 1.479) {
              if (fabs(pho->eta - pf->eta) < 0.015) {
                photonsToVeto.push_back(pf);
              }
            } else {
              if (higgsana::deltaR(pho->eta,pho->phi,pf->eta,pf->phi) < 0.07) {
                photonsToVeto.push_back(pf);
              }
            }
          }


          //Fill probe
          nProbes++;
          Bool_t passID = (PassEleHZZ4lPreselection(probe) && PassEleHZZ4lRun1LegacyPaperID(probe, eleIDMVA));
          Bool_t passIsolation = PassEleHZZ4lICHEP2012Iso(probe,j,pfcandidateArr,rhoEleIso,EleEAEra,photonsToVeto);
          if (!passID) continue;

          //******************
          //PASS
          //******************
          Bool_t pass = passID && passIsolation;

          // Fill tree
          data.mass   = vdielectrongamma.M();
          data.pt     = probe->pt;
          data.eta    = probe->scEta;
          data.phi    = probe->phi;
          data.weight = weight;
          data.q      = probe->q;
          data.npv    = info->nPV0;
          data.npu    = info->nPUEvents;
          data.pass   = (pass) ? 1 : 0;
          data.rho    = rhoEleIso;

          outTree->Fill();	  
          probeAlreadyUsed[k] = kTRUE;
          
        }


      }


    }
  }

  delete infile;
  infile=0, eventTree=0;      
  delete info;
  delete genparticleArr;
  delete electronArr;
  delete photonArr;
  delete muonArr;
  
     
  //--------------------------------------------------------------------------------------------------------------
  // 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 " << outputfile << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectEleLHEffTP"); 
}
void HHToBBGGSelectionCCOneFakePhoton(const string inputfile,          // input file
                       const string outputfile,         // output directory
                       Int_t SampleType = 1
  ) {
  
  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 
  bool printdebug = false;


  //*****************************************************************************************
  //Setup Jet Energy Corrections
  //*****************************************************************************************
  std::vector<cmsana::JetCorrectorParameters> correctionParameters;
  correctionParameters.push_back(cmsana::JetCorrectorParameters( ( getenv("CMSSW_BASE") + string("/src/CMSAna/JetEnergyCorrections/data/GR_R_52_V9_L1FastJet_AK5PF.txt")).c_str()));
  correctionParameters.push_back(cmsana::JetCorrectorParameters( ( getenv("CMSSW_BASE") + string("/src/CMSAna/JetEnergyCorrections/data/GR_R_52_V9_L2Relative_AK5PF.txt")).c_str()));
  correctionParameters.push_back(cmsana::JetCorrectorParameters( ( getenv("CMSSW_BASE") + string("/src/CMSAna/JetEnergyCorrections/data/GR_R_52_V9_L3Absolute_AK5PF.txt")).c_str()));
  cmsana::FactorizedJetCorrector *JetCorrector = new cmsana::FactorizedJetCorrector(correctionParameters);


  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  Double_t nEvents = 0;

  
  //*****************************************************************************************
  // Set up output ntuple
  //*****************************************************************************************
  TFile *outFile = new TFile(outputfile.c_str(),"RECREATE"); 
  TH1F *NEvents =  new TH1F("NEvents",";;",1,-0.5,0.5);
  TH1F *N2bjets = new TH1F("N2bjets","Number of Events w/ 2 bjets",1,-0.5,0.5); // Count the number of events that have two real cjets
  TH1F *N4genjets = new TH1F("N4genjets", "Number of Events w/ at 2 bjets and >=2 genjets", 1, -0.5, 0.5); // Count the number of events that have two real bjets + at least two other jets
  TH1F *NPUMean = new TH1F("NPUMean",";NPUMean;Number of Events", 100, -0.5, 99.5);
  cmsana::HHToBBGGEventTree *outputEventTree = new cmsana::HHToBBGGEventTree;
  outputEventTree->CreateTree();


  //*****************************************************************************************
  // Set up input
  //*****************************************************************************************
  TFile *infile=0;
  TTree *eventTree=0;
  
  // Data structures to store info from TTrees
  cmsana::TEventInfo *info  = new cmsana::TEventInfo();
  TClonesArray *genparticleArr = new TClonesArray("cmsana::TGenParticle");
  TClonesArray *genjetArr = new TClonesArray("cmsana::TGenJet");
  TClonesArray *photonArr = new TClonesArray("cmsana::TPhoton");
  TClonesArray *muonArr = new TClonesArray("cmsana::TMuon");
  TClonesArray *electronArr = new TClonesArray("cmsana::TElectron");
  TClonesArray *jetArr = new TClonesArray("cmsana::TJet");
  TClonesArray *pfcandidateArr = new TClonesArray("cmsana::TPFCandidate");

  // Read input file and get the TTrees
  cout << "Processing " << inputfile << "..." << endl;
  infile = TFile::Open(inputfile.c_str(),"read");
  assert(infile);

    
  eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
  eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("GenParticle", &genparticleArr); TBranch *genparticleBr = eventTree->GetBranch("GenParticle");
  eventTree->SetBranchAddress("GenJet", &genjetArr); TBranch *genjetBr = eventTree->GetBranch("GenJet");
  cout << "NEvents = " << eventTree->GetEntries() << endl;

  // Read efficiency file for Fake Photon Rate
  TFile *glu = TFile::Open("/afs/cern.ch/work/v/vlambert/public/releases/CMSSW_5_3_9_patch3/src/PhotonEfficiencies/Efficiencies/PhotonMistagRate_gluon.root");
  TH2F *gluon_efficiencies = (TH2F*)glu->Get("MistagRate_CSVMedium_PtEta");  // access 2D histogram with efficiency weights for gluons
  TFile *qk = TFile::Open("/afs/cern.ch/work/v/vlambert/public/releases/CMSSW_5_3_9_patch3/src/PhotonEfficiencies/Efficiencies/PhotonMistagRate_quark.root");
  TH2F *quark_efficiencies = (TH2F*)qk->Get("MistagRate_CSVMedium_PtEta");  // access 2D histogram with efficiency weights for quarks
  
  // Efficiencies for charm jets faking bjets
  TFile *file4Weight = TFile::Open("/afs/cern.ch/work/v/vlambert/public/releases/CMSSW_5_3_9_patch3/src/PhotonEfficiencies/Efficiencies/BJetMistagRate_type4_nocuts.root");
  TH2F *type4Weight = (TH2F*)file4Weight->Get("MistagRate_CSVMedium_Pt_Eta");

  // Efficiencies for Photons
  TFile *FakePhoton = TFile::Open("/afs/cern.ch/work/v/vlambert/public/releases/CMSSW_5_3_9_patch3/src/PhotonEfficiencies/Efficiencies/PhotonEfficiency_PromptPhoton.root");
  TH2F *Photon_efficiency = (TH2F*)FakePhoton->Get("Efficiency_PtEta");
  
  // null vector for default four vectors
  cmsana::FourVector null(0.0,0.0,0.0,0.0);

  // loop over events
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
    if (ientry % 1000 == 0) cout << "Processed Event " << ientry << endl;
    infoBr->GetEntry(ientry);

    NEvents->Fill(0);
    NPUMean->Fill(info->nPUMean);

    //***********************************************************
    // Definition of Pileup Energy density
    //***********************************************************
    Double_t rho = info->RhoKt6PFJets;

    genparticleArr->Clear(); 
    genjetArr->Clear(); 

    genparticleBr->GetEntry(ientry);
    genjetBr->GetEntry(ientry);

    //***********************************************************
    // Find Gen-Level particles
    //***********************************************************
    const cmsana::TGenParticle *genPhoton1 = 0;
    const cmsana::TGenParticle *genPhoton2 = 0;
    const cmsana::TGenParticle* photon1 = 0;
    const cmsana::TGenParticle *genB1 = 0;
    const cmsana::TGenParticle *genB2 = 0;
    const cmsana::TGenJet* genBJet1 = 0;
    const cmsana::TGenJet* genBJet2 = 0;
    const cmsana::TGenJet* bjet1 = 0;
    const cmsana::TGenJet* bjet2 = 0;
    Float_t FakeRate3 = 0;
    Float_t FakeRate4 = 0;
    for(Int_t i=0; i<genparticleArr->GetEntriesFast(); i++) {
      const cmsana::TGenParticle *p = (cmsana::TGenParticle*)((*genparticleArr)[i]);
//       cout << p->pdgid << " " << p->status << " " << p->pt << " " << p->eta << " " << p->phi 
//            << " | " << p->motherPdgID << "\n";

      if ( SampleType == cmsana::HHToBBGGEventTree::HHToBBGG) {
        if (abs(p->pdgid) == 5 && p->motherPdgID == 25 && p->status == 2) {
          if (!genB1) {
            genB1 = p;
          } else {
            if (!genB2) genB2 = p;
          }
        }
      }
      if ( SampleType == cmsana::HHToBBGGEventTree::ttHgg 
           || SampleType == cmsana::HHToBBGGEventTree::ttbar
        ) {
        if (abs(p->pdgid) == 5 && abs(p->motherPdgID) == 6 && p->status == 2) {
          if (!genB1) {
            genB1 = p;
          } else {
            if (!genB2) genB2 = p;
          }
        }
      }
      if ( SampleType == cmsana::HHToBBGGEventTree::ZHgg 
        ) {
        if (abs(p->pdgid) == 5 && p->motherPdgID == 23 && p->status == 2) {
          if (!genB1) {
            genB1 = p;
          } else {
            if (!genB2) genB2 = p;
          }
        }
      }
      //********************************************************
      // Find Photon
      //********************************************************
      if (abs(p->pdgid) == 22
	  && ( p->motherPdgID == 25 || abs(p->motherPdgID) <= 6 ||
	       (abs(p->motherPdgID) >= 11 && abs(p->motherPdgID) <= 14) ||
	       abs(p->motherPdgID) == 23 || abs(p->motherPdgID) == 24 || 
	       abs(p->motherPdgID) == 21)) {
	if (p->pt < 20) continue;
	if (fabs(p->eta) > 2.5) continue;
	if (!genPhoton1) {
	  genPhoton1 = p;
	  photon1 = p;
	} else {
	  if (!genPhoton2) {
	    if (cmsana::deltaR(p->eta, p->phi, photon1->eta, photon1->phi) < 0.1) continue;   
	    genPhoton2 = p;
	  }
	}
      }
    }
    //********************************************************
    // Assigning charm jets as B jets
    //********************************************************
    for(Int_t gen=0; gen<genjetArr->GetEntriesFast(); gen++) {
      const cmsana::TGenJet *genJ = (cmsana::TGenJet*)((*genjetArr)[gen]);
      if (fabs(genJ->matchedPdgId) == 4) { 
	if (genJ->pt <30) continue;
	if (fabs(genJ->eta) >2.4) continue;
	if (!genBJet1) {
	  genBJet1 = genJ;
	  bjet1 = genJ;
	} else {
	  if (!genBJet2) {
	    genBJet2 = genJ;
	    bjet2 = genJ;
	  }
	}
      }
    }
    // Check for real bjets
    Int_t realB = 0;
    for(Int_t rb=0; rb<genjetArr->GetEntriesFast(); rb++) {
      const cmsana::TGenJet *bcand = (cmsana::TGenJet*)((*genjetArr)[rb]);
      if (fabs(bcand->matchedPdgId) == 5) { 
	if (bcand->pt >20) realB++;
      }
    }
    // Discount all events with more than two photons and real bjets
    if (!genPhoton1) continue;
    if (genPhoton2) continue;
    if (realB !=0) continue;
    // Cut out events without 2 bjets faked by charm jets
    if (!(bjet1 && bjet2)) continue;
    
    // Count the number of events with 2 bjets
    N2bjets->Fill(0);

    //sampleType
    cmsana::HHToBBGGEventTree::SampleType stype = cmsana::HHToBBGGEventTree::none;
    if (SampleType == 0) stype = cmsana::HHToBBGGEventTree::data;
    if (SampleType == 1) stype = cmsana::HHToBBGGEventTree::HHToBBGG;
    if (SampleType == 2) stype = cmsana::HHToBBGGEventTree::ttHgg;
    if (SampleType == 3) stype = cmsana::HHToBBGGEventTree::ZHgg;
    if (SampleType == 4) stype = cmsana::HHToBBGGEventTree::bbHgg;
    if (SampleType == 5) stype = cmsana::HHToBBGGEventTree::ttbar;
    if (SampleType == 6) stype = cmsana::HHToBBGGEventTree::BBGG;
    if (SampleType == 7) stype = cmsana::HHToBBGGEventTree::GGPlusTwoMistag;
    if (SampleType == 8) stype = cmsana::HHToBBGGEventTree::BBPlusTwoFakePhotons;
    if (SampleType == 9) stype = cmsana::HHToBBGGEventTree::CCMistagPlusTwoFakePhotons;
    if (SampleType == 10) stype = cmsana::HHToBBGGEventTree::TwoLightJetsMistagPlusTwoFakePhotons;
    if (SampleType == 11) stype = cmsana::HHToBBGGEventTree::BBJG;
    if (SampleType == 12) stype = cmsana::HHToBBGGEventTree::CCJG;
    if (SampleType == 13) stype = cmsana::HHToBBGGEventTree::JJJG;


    outputEventTree->sampletype = stype;
    outputEventTree->run = info->runNum;
    outputEventTree->lumi = info->lumiSec;
    outputEventTree->event = info->evtNum;
    outputEventTree->npu = info->nPU;
    outputEventTree->rho = info->RhoKt6PFJets;
    outputEventTree->nvtx = info->nGoodPV;

    cmsana::FourVectorM genpho1v;
    cmsana::FourVectorM genpho2v;
    outputEventTree->genpho1 = null;
    outputEventTree->genpho2 = null;
    if (genPhoton1) {
      genpho1v.SetPt(genPhoton1->pt);
      genpho1v.SetEta(genPhoton1->eta);
      genpho1v.SetPhi(genPhoton1->phi);
      genpho1v.SetM(0);
      outputEventTree->genpho1 = genpho1v;
    }
    if (genPhoton2) {
      genpho2v.SetPt(genPhoton2->pt);
      genpho2v.SetEta(genPhoton2->eta);
      genpho2v.SetPhi(genPhoton2->phi);
      genpho2v.SetM(0);   
      outputEventTree->genpho2 = genpho2v;    
    }
        
    cmsana::FourVectorM genb1v;
    cmsana::FourVectorM genb2v;
    outputEventTree->genb1 = null;
    outputEventTree->genb2 = null;
    if (genB1) {
      genb1v.SetPt(genB1->pt);
      genb1v.SetEta(genB1->eta);
      genb1v.SetPhi(genB1->phi);
      genb1v.SetM(0);
      outputEventTree->genb1 = genb1v;
    }
    if (genB2) {
      genb2v.SetPt(genB2->pt);
      genb2v.SetEta(genB2->eta);
      genb2v.SetPhi(genB2->phi);
      genb2v.SetM(0);   
      outputEventTree->genb2 = genb2v;
    }
    
    //Fill the event bjets and genbjets
    cmsana::FourVectorM bjet1v;
    cmsana::FourVectorM bjet2v;
    cmsana::FourVectorM dibjetv;
    outputEventTree->bjet1 = null;      //default 4-vector
    outputEventTree->bjet2 = null;
    outputEventTree->dibjet = null;    
    
    bjet1v.SetPt(bjet1->pt);
    bjet1v.SetEta(bjet1->eta);
    bjet1v.SetPhi(bjet1->phi);
    bjet1v.SetM(bjet1->mass);
    outputEventTree->bjet1 = bjet1v;
    
    bjet2v.SetPt(bjet2->pt);
    bjet2v.SetEta(bjet2->eta);
    bjet2v.SetPhi(bjet2->phi);
    bjet2v.SetM(bjet2->mass);
    outputEventTree->bjet2 = bjet2v;
    
    dibjetv = bjet1v + bjet2v;
    outputEventTree->dibjet = dibjetv;
    
    cmsana::FourVectorM genbjet1v;
    cmsana::FourVectorM genbjet2v;
    outputEventTree->genbjet1 = null;    
    outputEventTree->genbjet2 = null;    
    
    genbjet1v.SetPt(genBJet1->pt);
    genbjet1v.SetEta(genBJet1->eta);
    genbjet1v.SetPhi(genBJet1->phi);
    genbjet1v.SetM(genBJet1->mass);
    outputEventTree->genbjet1 = genbjet1v;
    
    genbjet2v.SetPt(genBJet2->pt);
    genbjet2v.SetEta(genBJet2->eta);
    genbjet2v.SetPhi(genBJet2->phi);
    genbjet2v.SetM(genBJet2->mass);   
    outputEventTree->genbjet2 = genbjet2v; 
    
    // count other genjets
    Int_t addgenjets = 0;
    for(Int_t c=0; c<genjetArr->GetEntriesFast(); c++) {
      const cmsana::TGenJet *counterjet = (cmsana::TGenJet*)((*genjetArr)[c]);
      if (counterjet == genBJet1 || counterjet == genBJet2) continue;
      addgenjets++;
    }
    if (addgenjets > 1) {
      N4genjets->Fill(0);
    }

    //Assign efficiencies for bjets
    FakeRate3 = type4Weight->GetBinContent(type4Weight->FindBin(fmax(fmin(bjet1->pt,119.9),30.1),fmax(fmin(bjet1->eta, 2.39),-2.39)));
    FakeRate4 = type4Weight->GetBinContent(type4Weight->FindBin(fmax(fmin(bjet2->pt,119.9),30.1),fmax(fmin(bjet2->eta, 2.39),-2.39)));
    
    //********************************************************
    // Assign Photons
    //********************************************************

    //Assubg the real photon as photon1
    Float_t photonsPt = 0;
    Float_t FakeRate1 = 0;
    cmsana::FourVectorM photon1v;
    outputEventTree->pho1 = null;  
    //Assign efficiency for photon 1
    FakeRate1 = Photon_efficiency->GetBinContent(Photon_efficiency->FindBin(fmax(fmin(photon1->pt,99.9),20.1),fmax(fmin(photon1->eta, 2.49),-2.49)));
    photon1v.SetPt(photon1->pt);
    photon1v.SetEta(photon1->eta);
    photon1v.SetPhi(photon1->phi);
    photon1v.SetM(0);
    photonsPt+=photon1->pt;
    outputEventTree->pho1 = photon1v;
    
    // Define the second photon
    Float_t FakeRate2 = 0;
    const cmsana::TGenJet* photon2 = 0;
    // Store as photons
    cmsana::FourVectorM photon2v;
    cmsana::FourVectorM diphotonv;
    UInt_t njets = 0;
    UInt_t ncentraljets = 0;
    Float_t goodjetsPt = 0;
    
    //select genjet
    for(Int_t j=0; j<genjetArr->GetEntriesFast(); j++) {
      const cmsana::TGenJet *genjet2 = (cmsana::TGenJet*)((*genjetArr)[j]);
      if (cmsana::deltaR(photon1->eta, photon1->phi, genjet2->eta, genjet2->phi) < 0.5) continue;
      if (genjet2 == genBJet1 || genjet2 == genBJet2) continue;
      if (genjet2->pt < 20) continue;
      if (fabs(genjet2->eta) >2.5) continue;
      
      //Assign these two genjets as fake photons
      outputEventTree->pho2 = null;
      outputEventTree->diphoton = null; 
      FakeRate2 = 0;
      
      //Assign fake rates for photon 2
      if (fabs(genjet2->matchedPdgId) == 21) { // jet corresponds to a gluon
	FakeRate2 = gluon_efficiencies->GetBinContent(gluon_efficiencies->FindBin(fmax(fmin(genjet2->pt,99.9),20.1),fmax(fmin(genjet2->eta, 2.49),-2.49)));
      }
      else { // jet corresponds to a quark
	FakeRate2 = quark_efficiencies->GetBinContent(quark_efficiencies->FindBin(fmax(fmin(genjet2->pt,99.9),20.1),fmax(fmin(genjet2->eta, 2.49),-2.49)));
      }
      photon2 = genjet2;	
      photon2v.SetPt(genjet2->pt);
      photon2v.SetEta(genjet2->eta);
      photon2v.SetPhi(genjet2->phi);
      photon2v.SetM(0);
      photonsPt+=genjet2->pt;
      
      outputEventTree->pho2 = photon2v;
      diphotonv = photon1v + photon2v;
      outputEventTree->diphoton = diphotonv;
      
      // count additional jets
      njets = 0;
      ncentraljets = 0;
      goodjetsPt = 0;
      
      for(Int_t k=0; k<genjetArr->GetEntriesFast(); k++) {
	const cmsana::TGenJet *othergenjet = (cmsana::TGenJet*)((*genjetArr)[k]);
	
	// look only at the genjets that are not bjets or photons
	if (othergenjet == photon2 || othergenjet == genBJet1 ||othergenjet == genBJet2) continue;
	if (cmsana::deltaR(photon1->eta, photon1->phi, othergenjet->eta, othergenjet->phi) < 0.5) continue;
	if (!(othergenjet->pt >30)) continue;
	njets++;
	goodjetsPt += othergenjet->pt;
	if (fabs(othergenjet->eta) < 2.5) ncentraljets++;  
      }
      
      //********************************************************
      //bbgg system
      //********************************************************    
      cmsana::FourVectorM bbggSystemv;
      outputEventTree->bbgg = null;
      if (bjet1 && bjet2 && photon1 && photon2) {
	bbggSystemv = (photon1v + photon2v + bjet1v + bjet2v);
	outputEventTree->bbgg = bbggSystemv;
      }
      
      //********************************************************
      //NJets
      //********************************************************    
      outputEventTree->njets = njets;
      outputEventTree->ncentraljets = ncentraljets;
      
      if (bjet1 && bjet2 && photon1 && photon2 && njets >= 4) printdebug = true;
      
      //********************************************************
      //Count Additional Leptons
      //********************************************************    
      Int_t NLeptons = 0;
      Float_t ElectronsPt = 0;
      Float_t MuonsPt = 0;
      for(Int_t i=0; i<muonArr->GetEntriesFast(); i++) {
	const cmsana::TMuon *mu = (cmsana::TMuon*)((*muonArr)[i]);
	
	if (!(mu->pt > 10)) continue;
	if (!(fabs(mu->eta) < 2.4)) continue;
	
	//pass loose veto cuts
	if (!PassMuonIDVeto(mu)) continue;
	if (!(ComputeMuonPFIsoRings(mu,pfcandidateArr, rho,
				    kDataEra_2012_MC, kPFIso, 0.0, 0.3, false) / mu->pt < 0.2)) continue;
	
	//make sure the lepton doesn't overlap with bjets or photons
	if (bjet1 && cmsana::deltaR(mu->eta, mu->phi, bjet1->eta, bjet1->phi) < 0.5) continue;
	if (bjet2 && cmsana::deltaR(mu->eta, mu->phi, bjet2->eta, bjet2->phi) < 0.5) continue;
	if (photon1 && cmsana::deltaR(mu->eta, mu->phi, photon1->eta, photon1->phi) < 0.3) continue;
	if (photon2 && cmsana::deltaR(mu->eta, mu->phi, photon2->eta, photon2->phi) < 0.3) continue;
	MuonsPt+= mu->pt;
	NLeptons++;
      }
      for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
	const cmsana::TElectron *ele = (cmsana::TElectron*)((*electronArr)[i]);
	
	if (!(ele->pt > 20)) continue;
	if (!(fabs(ele->scEta) < 2.5)) continue;
	
	//pass loose veto cuts
	if (!PassEleSimpleCutsVeto( ele, pfcandidateArr, rho,
				    kDataEra_2012_MC, false)) continue;
	
	//make sure the lepton doesn't overlap with bjets or photons
	if (bjet1 && cmsana::deltaR(ele->eta, ele->phi, bjet1->eta, bjet1->phi) < 0.5) continue;
	if (bjet2 && cmsana::deltaR(ele->eta, ele->phi, bjet2->eta, bjet2->phi) < 0.5) continue;
	if (photon1 && cmsana::deltaR(ele->eta, ele->phi, photon1->eta, photon1->phi) < 0.3) continue;
	if (photon2 && cmsana::deltaR(ele->eta, ele->phi, photon2->eta, photon2->phi) < 0.3) continue;
	ElectronsPt+= ele->pt;
	NLeptons++;
      }
      
      outputEventTree->nlep = NLeptons;
      
      //********************************************************
      //Some kinematic variables
      //********************************************************
      outputEventTree->DRgg = -1;
      outputEventTree->DRbb = -1;
      outputEventTree->minDRgb = -1;
      outputEventTree->HT = 0;
      outputEventTree->MET = 0;
      outputEventTree->pfTrackMET = 0;
      if (photon1 && photon2 && bjet1 && bjet2 ) {
	outputEventTree->DRgg = cmsana::deltaR(photon1->eta, photon1->phi, photon2->eta, photon2->phi);
	outputEventTree->DRbb = cmsana::deltaR(bjet1->eta, bjet1->phi, bjet2->eta, bjet2->phi);
	outputEventTree->minDRgb = fmin(fmin(fmin( cmsana::deltaR(photon1->eta, photon1->phi, bjet1->eta, bjet1->phi), 
						   cmsana::deltaR(photon1->eta, photon1->phi, bjet2->eta, bjet2->phi)),
					     cmsana::deltaR(photon2->eta, photon2->phi, bjet1->eta, bjet1->phi)),
					cmsana::deltaR(photon2->eta, photon2->phi, bjet2->eta, bjet2->phi));
      };     
      outputEventTree->HT = photonsPt + goodjetsPt + ElectronsPt + MuonsPt;
      outputEventTree->MET = sqrt( info->pfMEx*info->pfMEx + info->pfMEy*info->pfMEy);
      outputEventTree->pfTrackMET = sqrt( info->pfTrackMEx*info->pfTrackMEx + info->pfTrackMEy*info->pfTrackMEy);
      
      
      outputEventTree->pfmet = sqrt( info->pfMEx*info->pfMEx + info->pfMEy*info->pfMEy);
      
      //********************************************************
      //Fill Output Tree
      //********************************************************
      //Temporary Measure:Reduce Fake-rate by factor of 4 when we use Tight Photon selection instead of Loose
      FakeRate2 = FakeRate2 / 4;

      //reduction from pileup;
      FakeRate1 = FakeRate1 * (0.85/0.95)*(0.85/0.95);
      FakeRate3 = FakeRate3 * (0.10/0.15);
      FakeRate4 = FakeRate4 * (0.10/0.15);
      
      outputEventTree->weight = FakeRate1 * FakeRate2 * FakeRate3 * FakeRate4;
      outputEventTree->tree_->Fill();
      nEvents++;
      
      // Debug for Fake Rates
      //cout<< "weight = " << FakeRate1*FakeRate2*FakeRate3*FakeRate4<<endl;
      if (FakeRate1*FakeRate2*FakeRate3*FakeRate4 ==0) {
	cout<< "FakeRate 1 = "<< FakeRate1 <<endl;
	cout<< "FakeRate 2 = "<< FakeRate2 <<endl;
	cout<< "FakeRate 3 = "<< FakeRate3 <<endl;
	cout<< "FakeRate 4 = "<< FakeRate4 <<endl;
      }
    }
  }
  delete infile;
  infile=0, eventTree=0;      
  delete info;
  delete photonArr;
  delete jetArr;
  delete genparticleArr;
  delete genjetArr;
     
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
 
  outFile->Write();
  outFile->Close();
  delete outFile;
  
  cout << " Number of events selected: " << nEvents << endl;
  cout << endl;
  cout << "  <> Output saved in " << outputfile << endl;    
  cout << endl;  
  
  
}
void computeAccSelWe_Charge(const TString conf,       // input file
                     const TString outputDir,  // output directory
		     const Int_t   charge,      // 0 = inclusive, +1 = W+, -1 = W-
		     const Int_t   doPU,
		     const Int_t   doScaleCorr,
		     const Int_t   sigma
) {
  gBenchmark->Start("computeAccSelWe");

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

  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;

  const Double_t VETO_PT   = 10;
  const Double_t VETO_ETA  = 2.5;

  const Double_t ECAL_GAP_LOW  = 1.4442;
  const Double_t ECAL_GAP_HIGH = 1.566;

  const Int_t BOSON_ID  = 24;
  const Int_t LEPTON_ID = 11;
 
  // efficiency files
  TString dataHLTEffName(   "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MG/eff.root");
  TString zeeHLTEffName(    "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CT/eff.root");
  TString dataGsfSelEffName("/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MG/eff.root");
  TString zeeGsfSelEffName( "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CT/eff.root");
  if(charge==1) {
    dataHLTEffName    = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MGpositive/eff.root";
    zeeHLTEffName     = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CTpositive/eff.root"; 
    dataGsfSelEffName = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MGpositive_FineBin/eff.root";
    zeeGsfSelEffName  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CTpositive/eff.root"; 
  }
  if(charge==-1) {
    dataHLTEffName    = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/MGnegative/eff.root";
    zeeHLTEffName     = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/CTnegative/eff.root";
    dataGsfSelEffName = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/MGnegative_FineBin/eff.root";
    zeeGsfSelEffName  = "/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleGsfSelEff/CTnegative/eff.root";
  }

  const TString corrFiles = "../EleScale/76X_16DecRereco_2015_Etunc";

  EnergyScaleCorrection_class eleCorr( corrFiles.Data()); eleCorr.doScale= true; eleCorr.doSmearings =true;

  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/puWeights_76x.root", "read");
  TH1D *h_rw = (TH1D*) f_rw->Get("puWeights");

  TFile *f_r9 = TFile::Open("../EleScale/transformation.root","read");
  TGraph* gR9EB = (TGraph*) f_r9->Get("transformR90");
  TGraph* gR9EE = (TGraph*) f_r9->Get("transformR91");

  TFile *f_hlt_data;
  TFile *f_hlt_mc;

  if(charge==1){
    f_hlt_data = TFile::Open("/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/Nominal/EleTriggerTF1_Data_Positive.root");
    f_hlt_mc   = TFile::Open("/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/Nominal/EleTriggerTF1_MC_Positive.root");
  }
  if(charge==-1){
    f_hlt_data = TFile::Open("/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/Nominal/EleTriggerTF1_Data_Negative.root");
    f_hlt_mc   = TFile::Open("/afs/cern.ch/work/x/xniu/public/WZXSection/wz-efficiency/EleHLTEff/Nominal/EleTriggerTF1_MC_Negative.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);
  
  //
  // Get efficiency
  //
  TFile *dataHLTEffFile = new TFile(dataHLTEffName);
  CEffUser2D dataHLTEff;
  TH2D *hHLTErr=0, *hHLTErrB=0, *hHLTErrE=0;
  if(dataHLTEffName) {
    dataHLTEff.loadEff((TH2D*)dataHLTEffFile->Get("hEffEtaPt"),
                       (TH2D*)dataHLTEffFile->Get("hErrlEtaPt"),
                       (TH2D*)dataHLTEffFile->Get("hErrhEtaPt"));
    
    TH2D* h =(TH2D*)dataHLTEffFile->Get("hEffEtaPt");
    hHLTErr  = new TH2D("hHLTErr", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
    hHLTErrB = new TH2D("hHLTErrB","",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
    hHLTErrE = new TH2D("hHLTErrE","",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  }
  
  TFile *zeeHLTEffFile = new TFile(zeeHLTEffName);
  CEffUser2D zeeHLTEff;
  if(zeeHLTEffName) {
    zeeHLTEff.loadEff((TH2D*)zeeHLTEffFile->Get("hEffEtaPt"),
                      (TH2D*)zeeHLTEffFile->Get("hErrlEtaPt"),
                      (TH2D*)zeeHLTEffFile->Get("hErrhEtaPt"));
  }
  
  TFile *dataGsfSelEffFile = new TFile(dataGsfSelEffName);
  CEffUser2D dataGsfSelEff;
  TH2D *hGsfSelErr=0, *hGsfSelErrB=0, *hGsfSelErrE=0;
  if(dataGsfSelEffName) {
    dataGsfSelEff.loadEff((TH2D*)dataGsfSelEffFile->Get("hEffEtaPt"),
                       (TH2D*)dataGsfSelEffFile->Get("hErrlEtaPt"),
                       (TH2D*)dataGsfSelEffFile->Get("hErrhEtaPt"));
    
    TH2D* h =(TH2D*)dataGsfSelEffFile->Get("hEffEtaPt");
    hGsfSelErr  = new TH2D("hGsfSelErr", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
    hGsfSelErrB = new TH2D("hGsfSelErrB","",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
    hGsfSelErrE = new TH2D("hGsfSelErrE","",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
                                      h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  }
  
  TFile *zeeGsfSelEffFile = new TFile(zeeGsfSelEffName);
  CEffUser2D zeeGsfSelEff;
  if(zeeGsfSelEffName) {
    zeeGsfSelEff.loadEff((TH2D*)zeeGsfSelEffFile->Get("hEffEtaPt"),
                      (TH2D*)zeeGsfSelEffFile->Get("hErrlEtaPt"),
                      (TH2D*)zeeGsfSelEffFile->Get("hErrhEtaPt"));
  }
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo    *info = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen  = new baconhep::TGenEventInfo();
  TClonesArray *electronArr = new TClonesArray("baconhep::TElectron");
  TClonesArray *genPartArr  = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;

  // Variables to store acceptances and uncertainties (per input file)
  vector<Double_t> nEvtsv, nSelv, nSelBv, nSelEv;
  vector<Double_t> accv, accBv, accEv;
  vector<Double_t> accErrv, accErrBv, accErrEv;
  vector<Double_t> nSelCorrv, nSelBCorrv, nSelECorrv;
  vector<Double_t> nSelCorrVarv, nSelBCorrVarv, nSelECorrVarv;
  vector<Double_t> accCorrv, accBCorrv, accECorrv;
  vector<Double_t> accErrCorrv, accErrBCorrv, accErrECorrv;

  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");
 
  // 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 = TFile::Open(fnamev[ifile]); 
    assert(infile);
  
    eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
    eventTree->SetBranchAddress("Info",             &info); TBranch *infoBr     = eventTree->GetBranch("Info");
    eventTree->SetBranchAddress("GenEvtInfo",        &gen); TBranch *genBr      = eventTree->GetBranch("GenEvtInfo");
    eventTree->SetBranchAddress("GenParticle",&genPartArr); TBranch *genPartBr  = eventTree->GetBranch("GenParticle");
    eventTree->SetBranchAddress("Electron",  &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
    eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");

    nEvtsv.push_back(0);
    nSelv.push_back(0);
    nSelBv.push_back(0);
    nSelEv.push_back(0);
    nSelCorrv.push_back(0);
    nSelBCorrv.push_back(0);
    nSelECorrv.push_back(0);
    nSelCorrVarv.push_back(0);
    nSelBCorrVarv.push_back(0);
    nSelECorrVarv.push_back(0);
    
    for(Int_t iy=0; iy<=hHLTErr->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr->GetNbinsX(); ix++) {
        hHLTErr ->SetBinContent(ix,iy,0);
        hHLTErrB->SetBinContent(ix,iy,0);
        hHLTErrE->SetBinContent(ix,iy,0);
      }
    }
    for(Int_t iy=0; iy<=hGsfSelErr->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hGsfSelErr->GetNbinsX(); ix++) {
        hGsfSelErr ->SetBinContent(ix,iy,0);
        hGsfSelErrB->SetBinContent(ix,iy,0);
        hGsfSelErrE->SetBinContent(ix,iy,0);
      }
    }

    //
    // loop over events
    //
    for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
//      if(ientry==10000) break;
      infoBr->GetEntry(ientry);
      genBr->GetEntry(ientry);      
      genPartArr->Clear(); genPartBr->GetEntry(ientry);
  
      if (charge==-1 && toolbox::flavor(genPartArr, -BOSON_ID)!=LEPTON_ID) continue;
      if (charge==1 && toolbox::flavor(genPartArr, BOSON_ID)!=-LEPTON_ID) continue;
      if (charge==0 && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
    
      vertexArr->Clear();
      vertexBr->GetEntry(ientry);
      double npv  = vertexArr->GetEntries();
      Double_t weight=gen->weight;
      if(doPU>0) weight*=h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));

      nEvtsv[ifile]+=weight;
      
      // trigger requirement                
      if (!isEleTrigger(triggerMenu, info->triggerBits, kFALSE)) continue;
      
      // good vertex requirement
      if(!(info->hasGoodPV)) continue;
      
      electronArr->Clear();
      electronBr->GetEntry(ientry);
      Int_t nLooseLep=0;
      const baconhep::TElectron *goodEle=0;
      TLorentzVector vEle(0,0,0,0);
      TLorentzVector vElefinal(0,0,0,0);
      Bool_t passSel=kFALSE;
     
      for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
        const baconhep::TElectron *ele = (baconhep::TElectron*)((*electronArr)[i]);
	vEle.SetPtEtaPhiM(ele->pt, ele->eta, ele->phi, ELE_MASS);
	
	//double ele_pt = gRandom->Gaus(ele->scEt*getEleScaleCorr(ele->scEta,0), getEleResCorr(ele->scEta,0));
        //double ele_pt = gRandom->Gaus(ele->scEt*getEleScaleCorr(ele->scEta,0), getEleResCorr(ele->scEta,0));

        // check ECAL gap
//        if(fabs(ele->scEta)>=ETA_BARREL && fabs(ele->scEta)<=ETA_ENDCAP) continue;
	if(fabs(vEle.Eta())>=ECAL_GAP_LOW && fabs(vEle.Eta())<=ECAL_GAP_HIGH) continue;
        if(doScaleCorr && (ele->r9 < 1.)){
            float eleSmear = 0.;

            float eleAbsEta   = fabs(vEle.Eta());
            float eleEt       = vEle.E() / cosh(eleAbsEta);
            bool  eleisBarrel = eleAbsEta < 1.4442;

            float eleR9Prime = ele->r9; // r9 corrections MC only
            if(eleisBarrel){
                      eleR9Prime = gR9EB->Eval(ele->r9);}
            else {
                      eleR9Prime = gR9EE->Eval(ele->r9);
            }

            double eleRamdom = gRandom->Gaus(0,1);
            eleSmear = eleCorr.getSmearingSigma(info->runNum, eleisBarrel, eleR9Prime, eleAbsEta, eleEt, 0., 0.);
            float eleSmearEP = eleCorr.getSmearingSigma(info->runNum, eleisBarrel, eleR9Prime, eleAbsEta, eleEt, 1., 0.);
            float eleSmearEM = eleCorr.getSmearingSigma(info->runNum, eleisBarrel, eleR9Prime, eleAbsEta, eleEt, -1., 0.);

            if(sigma==0){
              (vEle) *= 1. + eleSmear * eleRamdom;
            }else if(sigma==1){
              (vEle) *= 1. + eleSmearEP * eleRamdom;
            }else if(sigma==-1){
              (vEle) *= 1.  + eleSmearEM * eleRamdom;
            }
        }

        
//        if(fabs(ele->scEta) > VETO_ETA) continue;             // loose lepton |eta| cut
//        if(ele->scEt < VETO_PT)  continue;             // loose lepton pT cut
//        if(passEleLooseID(ele,info->rhoIso)) nLooseLep++;     // loose lepton selection
        if(fabs(vEle.Eta())    > VETO_ETA) continue;
        if(vEle.Pt()           < VETO_PT)  continue;
        if(passEleLooseID(ele, vEle, info->rhoIso)) nLooseLep++;

        if(nLooseLep>1) {  // extra lepton veto
          passSel=kFALSE;
          break;
        }

//        if(fabs(ele->scEta) > ETA_CUT && fabs(ele->eta) > ETA_CUT)       continue;  // lepton |eta| cut
//        if(ele->pt < PT_CUT && ele->scEt < PT_CUT)  	     continue;  // lepton pT cut
//        if(!passEleID(ele,info->rhoIso))     continue;  // lepton selection
        if(vEle.Pt()           < PT_CUT)     continue;  // lepton pT cut
        if(fabs(vEle.Eta())    > ETA_CUT)    continue;  // lepton |eta| cut
        if(!passEleID(ele, vEle, info->rhoIso))     continue;  // lepton selection

	if(!isEleTriggerObj(triggerMenu, ele->hltMatchBits, kFALSE, kFALSE)) continue;
        //if(!(ele->hltMatchBits[trigObjHLT])) continue;  // check trigger matching

	if(charge!=0 && ele->q!=charge) continue;  // check charge (if necessary)
        
	passSel=kTRUE;
        goodEle = ele;  
	vElefinal = vEle;
      }
      
      if(passSel) {
        
	/******** We have a W candidate! HURRAY! ********/
        Bool_t isBarrel = (fabs(vElefinal.Eta())<ETA_BARREL) ? kTRUE : kFALSE;

        Double_t corr=1;
        if(dataHLTEffFile && zeeHLTEffFile) {
//          Double_t effdata = dataHLTEff.getEff(vElefinal.Eta(), vElefinal.Pt());
//          Double_t effmc   = zeeHLTEff.getEff(vElefinal.Eta(), vElefinal.Pt());

	  char funcname[20];
	  sprintf(funcname, "fitfcn_%d", getEtaBinLabel(vElefinal.Eta()));
	  TF1 *fdt = (TF1*)f_hlt_data->Get(funcname);
	  TF1 *fmc = (TF1*)f_hlt_mc  ->Get(funcname);
	  Double_t effdata = fdt->Eval(TMath::Min(vElefinal.Pt(),119.0));
	  Double_t effmc   = fmc->Eval(TMath::Min(vElefinal.Pt(),119.0));
	  delete fdt;
	  delete fmc;

	  corr *= effdata/effmc;
        }
        if(dataGsfSelEffFile && zeeGsfSelEffFile) {
          Double_t effdata = dataGsfSelEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          Double_t effmc   = zeeGsfSelEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          corr *= effdata/effmc;
        }

        if(dataHLTEffFile && zeeHLTEffFile) {
          Double_t effdata = dataHLTEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          Double_t effmc   = zeeHLTEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          Double_t errdata = TMath::Max(dataHLTEff.getErrLow(vElefinal.Eta(), vElefinal.Pt()),dataHLTEff.getErrHigh(vElefinal.Eta(), vElefinal.Pt()));
          Double_t errmc   = TMath::Max(zeeHLTEff.getErrLow(vElefinal.Eta(), vElefinal.Pt()), zeeHLTEff.getErrHigh(vElefinal.Eta(), vElefinal.Pt()));
          Double_t err     = corr*sqrt(errdata*errdata/effdata/effdata+errmc*errmc/effmc/effmc);
          hHLTErr->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
          if(isBarrel) hHLTErrB->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
          else         hHLTErrE->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
        }
        if(dataGsfSelEffFile && zeeGsfSelEffFile) {
          Double_t effdata = dataGsfSelEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          Double_t effmc   = zeeGsfSelEff.getEff(vElefinal.Eta(), vElefinal.Pt());
          Double_t errdata = TMath::Max(dataGsfSelEff.getErrLow(vElefinal.Eta(), vElefinal.Pt()),dataGsfSelEff.getErrHigh(vElefinal.Eta(), vElefinal.Pt()));
          Double_t errmc   = TMath::Max(zeeGsfSelEff.getErrLow(vElefinal.Eta(), vElefinal.Pt()), zeeGsfSelEff.getErrHigh(vElefinal.Eta(), vElefinal.Pt()));
          Double_t err     = corr*sqrt(errdata*errdata/effdata/effdata+errmc*errmc/effmc/effmc);
          hGsfSelErr->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
          if(isBarrel) hGsfSelErrB->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
          else         hGsfSelErrE->Fill(vElefinal.Eta(),vElefinal.Pt(),err);
        }
        
	nSelv[ifile]+=weight;
	nSelCorrv[ifile]+=weight*corr;
	nSelCorrVarv[ifile]+=weight*weight*corr*corr;

  	if(isBarrel) { 
	  nSelBv[ifile]+=weight;
	  nSelBCorrv[ifile]+=weight*corr;
	  nSelBCorrVarv[ifile]+=weight*weight*corr*corr;
	  	
	} else { 
	  nSelEv[ifile]+=weight;
	  nSelECorrv[ifile]+=weight*corr;
	  nSelECorrVarv[ifile]+=weight*weight*corr*corr;
	}
      }
    }
    
    Double_t var=0, varB=0, varE=0;
    for(Int_t iy=0; iy<=hHLTErr->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr->GetNbinsX(); ix++) {
        Double_t err;
	err=hHLTErr->GetBinContent(ix,iy);  var+=err*err;
        err=hHLTErrB->GetBinContent(ix,iy); varB+=err*err;
        err=hHLTErrE->GetBinContent(ix,iy); varE+=err*err;
      }
    }

    for(Int_t iy=0; iy<=hGsfSelErr->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hGsfSelErr->GetNbinsX(); ix++) {
        Double_t err;
	err=hGsfSelErr->GetBinContent(ix,iy);  var+=err*err;
	err=hGsfSelErrB->GetBinContent(ix,iy); varB+=err*err;
	err=hGsfSelErrE->GetBinContent(ix,iy); varE+=err*err;
      }
    }

    nSelCorrVarv[ifile]+=var;
    nSelBCorrVarv[ifile]+=varB;
    nSelECorrVarv[ifile]+=varE;
    
    // compute acceptances
    accv.push_back(nSelv[ifile]/nEvtsv[ifile]);   accErrv.push_back(sqrt(accv[ifile]*(1.+accv[ifile])/nEvtsv[ifile]));
    accBv.push_back(nSelBv[ifile]/nEvtsv[ifile]); accErrBv.push_back(sqrt(accBv[ifile]*(1.+accBv[ifile])/nEvtsv[ifile]));
    accEv.push_back(nSelEv[ifile]/nEvtsv[ifile]); accErrEv.push_back(sqrt(accEv[ifile]*(1.+accEv[ifile])/nEvtsv[ifile]));
    
    accCorrv.push_back(nSelCorrv[ifile]/nEvtsv[ifile]);   accErrCorrv.push_back(accCorrv[ifile]*sqrt(nSelCorrVarv[ifile]/nSelCorrv[ifile]/nSelCorrv[ifile] + 1./nEvtsv[ifile]));
    accBCorrv.push_back(nSelBCorrv[ifile]/nEvtsv[ifile]); accErrBCorrv.push_back(accBCorrv[ifile]*sqrt(nSelBCorrVarv[ifile]/nSelBCorrv[ifile]/nSelBCorrv[ifile] + 1./nEvtsv[ifile]));
    accECorrv.push_back(nSelECorrv[ifile]/nEvtsv[ifile]); accErrECorrv.push_back(accECorrv[ifile]*sqrt(nSelECorrVarv[ifile]/nSelECorrv[ifile]/nSelECorrv[ifile] + 1./nEvtsv[ifile]));
    
    delete infile;
    infile=0, eventTree=0;  
  }
  delete info;
  delete gen;
  delete electronArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  if(charge== 0) cout << " W -> e nu"  << endl;
  if(charge==-1) cout << " W- -> e nu" << endl;
  if(charge== 1) cout << " W+ -> e nu" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << "  Barrel definition: |eta| < " << ETA_BARREL << endl;
  cout << "  Endcap definition: |eta| > " << ETA_ENDCAP << 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 << "     barrel: " << setw(12) << nSelBv[ifile] << " / " << nEvtsv[ifile] << " = " << accBv[ifile] << " +/- " << accErrBv[ifile];
    cout << "  ==eff corr==> " << accBCorrv[ifile] << " +/- " << accErrBCorrv[ifile] << endl;
    cout << "     endcap: " << setw(12) << nSelEv[ifile] << " / " << nEvtsv[ifile] << " = " << accEv[ifile] << " +/- " << accErrEv[ifile];
    cout << "  ==eff corr==> " << accECorrv[ifile] << " +/- " << accErrECorrv[ifile] << endl;
    cout << "      total: " << setw(12) << nSelv[ifile]  << " / " << nEvtsv[ifile] << " = " << accv[ifile]  << " +/- " << accErrv[ifile];
    cout << "  ==eff corr==> " << accCorrv[ifile]  << " +/- " << accErrCorrv[ifile] << endl;
    cout << endl;
  }
  
  char txtfname[100];
  sprintf(txtfname,"%s/sel.txt",outputDir.Data());
  ofstream txtfile;
  txtfile.open(txtfname);
  txtfile << "*" << endl;
  txtfile << "* SUMMARY" << endl;
  txtfile << "*--------------------------------------------------" << endl;
  if(charge== 0) txtfile << " W -> e nu"  << endl;
  if(charge==-1) txtfile << " W- -> e nu" << endl;
  if(charge== 1) txtfile << " W+ -> e nu" << endl;
  txtfile << "  pT > " << PT_CUT << endl;
  txtfile << "  |eta| < " << ETA_CUT << endl;
  txtfile << "  Barrel definition: |eta| < " << ETA_BARREL << endl;
  txtfile << "  Endcap definition: |eta| > " << ETA_ENDCAP << 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 << "     barrel: " << setw(12) << nSelBv[ifile] << " / " << nEvtsv[ifile] << " = " << accBv[ifile] << " +/- " << accErrBv[ifile];
    txtfile << "  ==eff corr==> " << accBCorrv[ifile] << " +/- " << accErrBCorrv[ifile] << endl;
    txtfile << "     endcap: " << setw(12) << nSelEv[ifile] << " / " << nEvtsv[ifile] << " = " << accEv[ifile] << " +/- " << accErrEv[ifile];
    txtfile << "  ==eff corr==> " << accECorrv[ifile] << " +/- " << accErrECorrv[ifile] << endl;
    txtfile << "      total: " << setw(12) << nSelv[ifile]  << " / " << nEvtsv[ifile] << " = " << accv[ifile]  << " +/- " << accErrv[ifile];
    txtfile << "  ==eff corr==> " << accCorrv[ifile]  << " +/- " << accErrCorrv[ifile] << endl;
    txtfile << endl;
  }
  txtfile.close();  
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("computeAccSelWe"); 
}
Exemple #13
0
int getSimulatedDigits(TString digitdir)
{

    AliRunLoader *rl = AliRunLoader::Open(digitdir+TString("/galice.root"));

    AliPHOSLoader *prl = (AliPHOSLoader*)rl->GetDetectorLoader("PHOS");

    prl->LoadSDigits();
    prl->LoadDigits();

    Int_t nSimEvents = rl->GetNumberOfEvents();
    TFile *mydigitsFile = new TFile("mydigits.root", "RECREATE");
    TTree *mydigitTree = new TTree("mydigitTree", "mydigitTree");
    TClonesArray * mydigits = new TClonesArray(AliPHOSDigit::Class());
    mydigitTree->Branch("Digits", &mydigits);

    for (Int_t ev = 0; ev < nSimEvents; ev++)
    {
        rl->GetEvent(ev);

        Int_t nPhosDigits = prl->SDigits()->GetEntries();


        Int_t nDigsFound = 0;

        for (Int_t iDig = 0; iDig < nPhosDigits; iDig++)
        {
            const AliPHOSDigit *digit = prl->SDigit(iDig);

            Int_t id = digit->GetId();
            if (id > 3*geom->GetNPhi()*geom->GetNZ()) continue;

            for (Int_t n = 0; n < nDigsFound; n++)
            {
                AliPHOSDigit *tmpDig = (AliPHOSDigit*)mydigits->At(n);
                if (id == tmpDig->GetId())
                {
                    *tmpDig += *digit;
                    digit = 0;
                    break;
                }
            }
            if (digit)
            {
                AliPHOSDigit *newDig = new((*mydigits)[nDigsFound]) AliPHOSDigit(-1, id, (float)0.0, (float)0.0);
                *newDig += *digit;

                nDigsFound++;
            }
        }
        for(int i = 0; i <nDigsFound; i++)
        {

            AliPHOSDigit *tmpDig = (AliPHOSDigit*)mydigits->At(i);
            Int_t relId[4];
            geom->AbsToRelNumbering(tmpDig->GetId(), relId);

            // Some necessary ugly hacks needed at the moment, need to get these numbers from OCDB
            tmpDig->SetEnergy((float)((int)(tmpDig->GetEnergy()/phosCalibData->GetADCchannelEmc(relId[0], relId[3], relId[2]))));
            //std::cout << "Sample time step: " << phosCalibData->GetSampleTimeStep() << " " << phosCalibData->GetTimeShiftEmc(relId[0], relId[3], relId[2]) << geom << std::endl;
            tmpDig->SetTime(1.5e-8);
            tmpDig->SetTimeR(1.5e-8);
        }
        mydigitTree->Fill();
        mydigits->Clear("C");
    }
    mydigitsFile->Write();
    simTree = mydigitTree;
    //mydigit
    //mydigitsFile->Close();
    return 0;
}
// Main macro function
//--------------------------------------------------------------------------------------------------
void SkimTightPlusRecoPerFile(string inputFilename, string outputFilename) 
{
  gBenchmark->Start("SkimNtuples");
    
  TTree::SetMaxTreeSize(kMaxLong64);
  

  mithep::MuonIDMVA *muonIDMVA = new mithep::MuonIDMVA();
  muonIDMVA->Initialize("BDTG method",
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/BarrelPtBin0_IDIsoCombined_BDTG.weights.xml", 
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/EndcapPtBin0_IDIsoCombined_BDTG.weights.xml", 
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/BarrelPtBin1_IDIsoCombined_BDTG.weights.xml", 
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/EndcapPtBin1_IDIsoCombined_BDTG.weights.xml", 
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/BarrelPtBin2_IDIsoCombined_BDTG.weights.xml", 
                        "/home/sixie/CMSSW_analysis/src/MitPhysics/data/MuonMVAWeights/EndcapPtBin2_IDIsoCombined_BDTG.weights.xml",
                        mithep::MuonIDMVA::kIDIsoCombinedDetIso);
  
  mithep::ElectronIDMVA *electronIDMVA = new mithep::ElectronIDMVA();
  electronIDMVA->Initialize("BDTG method",
                            "MitPhysics/data/ElectronMVAWeights/Subdet0LowPt_IDIsoCombined_BDTG.weights.xml", 
                            "MitPhysics/data/ElectronMVAWeights/Subdet1LowPt_IDIsoCombined_BDTG.weights.xml", 
                            "MitPhysics/data/ElectronMVAWeights/Subdet2LowPt_IDIsoCombined_BDTG.weights.xml", 
                            "MitPhysics/data/ElectronMVAWeights/Subdet0HighPt_IDIsoCombined_BDTG.weights.xml", 
                            "MitPhysics/data/ElectronMVAWeights/Subdet1HighPt_IDIsoCombined_BDTG.weights.xml", 
                            "MitPhysics/data/ElectronMVAWeights/Subdet2HighPt_IDIsoCombined_BDTG.weights.xml",
                            mithep::ElectronIDMVA::kIDIsoCombined);



  // Don't write TObject part of the objects
  mithep::TEventInfo::Class()->IgnoreTObjectStreamer();
  mithep::TMuon::Class()->IgnoreTObjectStreamer();
  mithep::TElectron::Class()->IgnoreTObjectStreamer();
  mithep::TJet::Class()->IgnoreTObjectStreamer();
  mithep::TPhoton::Class()->IgnoreTObjectStreamer();

  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  TClonesArray *muonArr     = new TClonesArray("mithep::TMuon");
  TClonesArray *electronArr     = new TClonesArray("mithep::TElectron");
  TClonesArray *jetArr    = new TClonesArray("mithep::TJet");
  TClonesArray *photonArr     = new TClonesArray("mithep::TPhoton");
    
  UInt_t nInputEvts = 0;
  UInt_t nPassEvts  = 0;
  UInt_t nEventsTotal = 0;

  TFile* outfile = new TFile(outputFilename.c_str(), "RECREATE");
  
  //
  // Initialize data trees and structs
  // 
  TTree *outEventTree = new TTree("Events","Events"); 
  outEventTree->Branch("Info",     &info);
  outEventTree->Branch("Muon",     &muonArr);
  outEventTree->Branch("Electron", &electronArr);
  outEventTree->Branch("PFJet",    &jetArr);
  outEventTree->Branch("Photon",   &photonArr);

  cout << "Skimming " << inputFilename << "..." << endl;
  TTree *eventTree = getTreeFromFile(inputFilename.c_str(),"Events"); 
  nEventsTotal += getNEvents(inputFilename.c_str()); 
  assert(eventTree);
    
  // Set branch address to structures that will store the info  
  eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("Muon",     &muonArr);     TBranch *muonBr     = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
  eventTree->SetBranchAddress("PFJet",    &jetArr);      TBranch *jetBr      = eventTree->GetBranch("PFJet");
  eventTree->SetBranchAddress("Photon",    &photonArr);  TBranch *photonBr   = eventTree->GetBranch("Photon");
     
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) { 
    infoBr->GetEntry(ientry);
    muonArr->Clear();     muonBr->GetEntry(ientry);
    electronArr->Clear(); electronBr->GetEntry(ientry);      
    jetArr->Clear(); jetBr->GetEntry(ientry);
    photonArr->Clear(); photonBr->GetEntry(ientry);
     
    if (ientry % 100000 == 0) cout << "Events: " << ientry << endl;

    nInputEvts++;
      
    Bool_t keep = kTRUE;
    
    Double_t rho = 0;
    if (!(TMath::IsNaN(info->PileupEnergyDensity) || isinf(info->PileupEnergyDensity))) rho = info->PileupEnergyDensity;

    Int_t NTightMuons = 0;
    Int_t NRecoMuons = 0;
    for(Int_t i=0; i<muonArr->GetEntries(); i++) {
      const mithep::TMuon *mu = (mithep::TMuon*)((*muonArr)[i]);      
      if ( fabs(mu->eta) < 2.4
           && 
           mu->pt > 10.0
        ) {
        NRecoMuons++;

//         if ( passMuonCuts(mu)) NTightMuons++;
        if ( passMuonMVAIDIsoCombined(mu, muonIDMVA->MVAValue(
                                          mu->pt, mu->eta,
                                          mu->tkNchi2,
                                          mu->muNchi2,
                                          mu->nValidHits,
                                          mu->nTkHits,
                                          mu->nPixHits,
                                          mu->nMatch,
                                          mu->d0,
                                          mu->ip3d,
                                          mu->ip3dSig,
                                          mu->TrkKink,
                                          mu->SegmentCompatibility,
                                          mu->CaloCompatilibity,
                                          (mu->HadEnergy - rho*MuonEffectiveArea(kMuHadEnergy,mu->eta))/mu->pt,
                                          (mu->HoEnergy - rho*MuonEffectiveArea(kMuHoEnergy,mu->eta))/mu->pt,
                                          (mu->EmEnergy - rho*MuonEffectiveArea(kMuEmEnergy,mu->eta))/mu->pt,
                                          (mu->HadS9Energy - rho*MuonEffectiveArea(kMuHadS9Energy,mu->eta))/mu->pt,
                                          (mu->HoS9Energy - rho*MuonEffectiveArea(kMuHoS9Energy,mu->eta))/mu->pt,
                                          (mu->EmS9Energy - rho*MuonEffectiveArea(kMuEmS9Energy,mu->eta))/mu->pt,
                                          (mu->trkIso03 - rho*MuonEffectiveArea(kMuTrkIso03,mu->eta))/mu->pt,
                                          (mu->emIso03 - rho*MuonEffectiveArea(kMuEMIso03,mu->eta))/mu->pt,
                                          (mu->hadIso03 - rho*MuonEffectiveArea(kMuHadIso03,mu->eta))/mu->pt,
                                          (mu->trkIso05 - rho*MuonEffectiveArea(kMuTrkIso05,mu->eta))/mu->pt,
                                          (mu->emIso05 - rho*MuonEffectiveArea(kMuEMIso05,mu->eta))/mu->pt,
                                          (mu->hadIso05 - rho*MuonEffectiveArea(kMuHadIso05,mu->eta))/mu->pt
                                        ), rho)) NTightMuons++;
      }
    }
    Int_t NTightElectrons = 0;
    Int_t NRecoElectrons = 0;
    for(Int_t i=0; i<electronArr->GetEntries(); i++) {
      const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i]);
      if ( fabs(ele->eta) < 2.5
           && 
           ele->pt > 10.0
        ) {
        NRecoElectrons++;

//         if (passElectronCuts(ele)) NTightElectrons++;
        if (passElectronMVAIDIsoCombined(ele, 
                                         electronIDMVA->MVAValue(
                                           ele->pt,ele->scEta,rho,
                                           ele->sigiEtaiEta, 
                                           ele->deltaEtaIn,
                                           ele->deltaPhiIn, 
                                           ele->HoverE,
                                           ele->d0,
                                           ele->dz, 
                                           ele->fBrem,
                                           ele->EOverP,
                                           ele->ESeedClusterOverPout,
                                           TMath::Sqrt(ele->sigiPhiiPhi),
                                           ele->nBrem,
                                           (1.0/(ele->scEt * TMath::CosH(ele->scEta)) - 1/ele->p), 
                                           ele->ESeedClusterOverPIn,
                                           ele->ip3d,
                                           ele->ip3dSig,
                                           ele->GsfTrackChi2OverNdof,
                                           ele->dEtaCalo,
                                           ele->dPhiCalo,
                                           ele->R9,
                                           ele->SCEtaWidth,
                                           ele->SCPhiWidth,
                                           ele->CovIEtaIPhi,
                                           ele->PreShowerOverRaw,
                                           ele->ChargedIso03,
                                           (ele->NeutralHadronIso03_05Threshold - ele->NeutralHadronIso007_05Threshold),
                                           (ele->GammaIso03_05Threshold - ele->GammaIsoVetoEtaStrip03_05Threshold),
                                           ele->ChargedIso04 ,
                                           (ele->NeutralHadronIso04_05Threshold - ele->NeutralHadronIso007_05Threshold),
                                           (ele->GammaIso04_05Threshold - ele->GammaIsoVetoEtaStrip04_05Threshold) 
                                           ), 
                                         0)) NTightElectrons++;



      }
    }

    //One Tight AND Two Loose
    if (!( NTightElectrons + NTightMuons >= 1  
           && NRecoElectrons + NRecoMuons >= 2
          ) ) {
      keep = kFALSE;
    }
      
    if(keep) {
      outEventTree->Fill();
      nPassEvts++;
    }
  }
  outfile->Write();
  outfile->Close();
  
  delete info;
  delete muonArr;
  delete electronArr;
  delete jetArr;
    
  std::cout << outputFilename << " created!" << std::endl;
  std::cout << " >>> Total Number of Events: " << nEventsTotal << std::endl;
  std::cout << " >>> Events processed: " << nInputEvts << std::endl;
  std::cout << " >>>   Events passing: " << nPassEvts << std::endl;

  gBenchmark->Show("SkimNtuples");
}  
Exemple #15
0
void HwwDYBkgEstimate(const string inputFilename, Double_t mHiggs,
                 const string Label) 
{  
  gBenchmark->Start("WWTemplate");

  
  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //==============================================================================================================
  
  Double_t lumi = 35.5;              // luminosity (pb^-1)
  Int_t ChargeSelection = 0;
//   ChargeSelection = 1;
    
  Double_t fPtMaxLowerCut;
  Double_t fPtMinLowerCut;
  Double_t fDileptonMassUpperCut;
  Double_t fDeltaPhiCut;

  Double_t fHiggsMass = mHiggs;

  //Configure Higgs Mass Dependant Cuts
  if (fHiggsMass == 120) { fPtMaxLowerCut = 20.0;        fPtMinLowerCut = 20.0; 
                           fDileptonMassUpperCut = 40.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 130) { fPtMaxLowerCut = 25.0;        fPtMinLowerCut = 20.0;
                           fDileptonMassUpperCut = 45.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 140) { fPtMaxLowerCut = 25.0;        fPtMinLowerCut = 20.0;
                           fDileptonMassUpperCut = 45.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 150) { fPtMaxLowerCut = 27.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 160) { fPtMaxLowerCut = 30.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 170) { fPtMaxLowerCut = 34.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 50.0; fDeltaPhiCut = 60.0;
  }
  if (fHiggsMass == 180) { fPtMaxLowerCut = 36.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 60.0; fDeltaPhiCut = 70.0;
  }
  if (fHiggsMass == 190) { fPtMaxLowerCut = 38.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 80.0; fDeltaPhiCut = 90.0;
  }
  if (fHiggsMass == 200) { fPtMaxLowerCut = 40.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 90.0; fDeltaPhiCut = 100.0;
  }
  if (fHiggsMass == 210) { fPtMaxLowerCut = 44.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 110.0; fDeltaPhiCut = 110.0;
  }
  if (fHiggsMass == 220) { fPtMaxLowerCut = 48.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 120.0; fDeltaPhiCut = 120.0;
  }
  if (fHiggsMass == 230) { fPtMaxLowerCut = 52.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 130.0; fDeltaPhiCut = 130.0;
  }
  if (fHiggsMass == 250) { fPtMaxLowerCut = 55.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 150.0; fDeltaPhiCut = 140.0;
  }
  if (fHiggsMass == 300) { fPtMaxLowerCut = 70.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 200.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 350) { fPtMaxLowerCut = 80.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 250.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 400) { fPtMaxLowerCut = 90.0;         fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 300.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 450) { fPtMaxLowerCut = 110.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 350.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 500) { fPtMaxLowerCut = 120.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 400.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 550) { fPtMaxLowerCut = 130.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 450.0; fDeltaPhiCut = 175.0;
  }
  if (fHiggsMass == 600) { fPtMaxLowerCut = 140.0;        fPtMinLowerCut = 25.0;
                           fDileptonMassUpperCut = 500.0; fDeltaPhiCut = 175.0;
  }


  //--------------------------------------------------------------------------------------------------------------
  // Histograms
  //==============================================================================================================  
  TH1D *DileptonMass_allOtherCuts_ee = new TH1D("DileptonMass_allOtherCuts_ee", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCuts_emu = new TH1D("DileptonMass_allOtherCuts_emu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCuts_mumu = new TH1D("DileptonMass_allOtherCuts_mumu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_ee = new TH1D("DileptonMass_allOtherCutsExceptMetCut_ee", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_emu = new TH1D("DileptonMass_allOtherCutsExceptMetCut_emu", ";Mass_{ll};Number of Events",150,0.,300.);
  TH1D *DileptonMass_allOtherCutsExceptMetCut_mumu = new TH1D("DileptonMass_allOtherCutsExceptMetCut_mumu", ";Mass_{ll};Number of Events",150,0.,300.);

  Double_t NEventsIn_BeforeMetCut_ee = 0;
  Double_t NEventsIn_BeforeMetCut_em = 0;
  Double_t NEventsIn_BeforeMetCut_mm = 0;
  Double_t NEventsOut_BeforeMetCut_ee = 0;
  Double_t NEventsOut_BeforeMetCut_em = 0;
  Double_t NEventsOut_BeforeMetCut_mm = 0;
  Double_t NEventsIn_AfterMetCut_ee = 0;
  Double_t NEventsIn_AfterMetCut_em = 0;
  Double_t NEventsIn_AfterMetCut_mm = 0;
  Double_t NEventsOut_AfterMetCut_ee = 0;
  Double_t NEventsOut_AfterMetCut_em = 0;
  Double_t NEventsOut_AfterMetCut_mm = 0;


  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  //
  // Access samples and fill histograms
  TFile *inputFile=0;
  TTree *eventTree=0;  
   
  // Data structures to store info from TTrees
  mithep::TEventInfo *info    = new mithep::TEventInfo();
  TClonesArray *electronArr = new TClonesArray("mithep::TElectron");
  TClonesArray *muonArr = new TClonesArray("mithep::TMuon");
  TClonesArray *jetArr = new TClonesArray("mithep::TJet");
  
  //********************************************************
  // Good RunLumi Selection
  //********************************************************
  Bool_t hasJSON = kTRUE;
  mithep::RunLumiRangeMap rlrm;
//   rlrm.AddJSONFile("Cert_TopOct22_Merged_135821-148058_allPVT.txt"); 
   rlrm.AddJSONFile("Cert_136033-149442_7TeV_Dec22ReReco_Collisions10_JSON_v3.txt"); 
   hasJSON = kFALSE;

  //********************************************************
  // Get Tree
  //********************************************************
  eventTree = getTreeFromFile(inputFilename.c_str(),"Events"); 
  TBranch *infoBr;
  TBranch *electronBr;
  TBranch *muonBr;
  TBranch *jetBr;


  //*****************************************************************************************
  //Loop over muon Data Tree
  //*****************************************************************************************
  // Set branch address to structures that will store the info  
  eventTree->SetBranchAddress("Info",       &info);      infoBr       = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("Electron", &electronArr); electronBr = eventTree->GetBranch("Electron");
  eventTree->SetBranchAddress("Muon", &muonArr);         muonBr = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("PFJet", &jetArr);         jetBr = eventTree->GetBranch("PFJet");
  
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {       	
    infoBr->GetEntry(ientry);
    if (ientry % 100000 == 0) cout << "Event " << ientry << endl;
		
    mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
    if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  // not certified run? Skip to next event...
     
    //for the skimmed input, I already required the HLT bits.
    //    if (!passHLT(info->triggerBits, info->runNum, kTRUE)) continue;

    //********************************************************
    // Load the branches
    //********************************************************
    electronArr->Clear(); 
    muonArr->Clear(); 
    jetArr->Clear(); 
    electronBr->GetEntry(ientry);
    muonBr->GetEntry(ientry);
    jetBr->GetEntry(ientry);

    //event weight
    Double_t eventweight = info->eventweight * lumi;

    //********************************************************
    // TcMet
    //********************************************************
    TVector3 met;        
    if(info->tcMEx!=0 || info->tcMEy!=0) {       
      met.SetXYZ(info->tcMEx, info->tcMEy, 0);
    }

    //********************************************************
    // TcMet
    //********************************************************

    Int_t NSoftMuons = 0;
    Int_t NLeptons = 0;
    vector<Int_t> leptonType;
    vector<Int_t> leptonIndex;
    vector<Double_t> leptonPt;
    vector<Double_t> leptonEta;
    vector<Double_t> leptonPhi;
    vector<Int_t> leptonCharge;

    Int_t NJets = 0;
    const mithep::TJet *leadingJet = 0;
    
    for(Int_t i=0; i<muonArr->GetEntries(); i++) {
      const mithep::TMuon *mu = (mithep::TMuon*)((*muonArr)[i]);      
      if ( (0==0)
           &&
           passMuonCuts(mu)
           &&
           fabs(mu->eta) < 2.4
           && 
           mu->pt > 10.0
        ) {
        leptonPt.push_back(mu->pt);
        leptonEta.push_back(mu->eta);
        leptonPhi.push_back(mu->phi);
        leptonType.push_back(13);
        leptonIndex.push_back(i);  
        leptonCharge.push_back(mu->q);
      }
    }
    //soft muons
    for(Int_t i=0; i<muonArr->GetEntries(); i++) {
      const mithep::TMuon *mu = (mithep::TMuon*)((*muonArr)[i]);
      Bool_t isCleanMuon = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if ( leptonType[k] == 13 
             && mithep::MathUtils::DeltaR(mu->phi, mu->eta, leptonPhi[k],leptonEta[k]) < 0.1
          ) {
          isCleanMuon = kTRUE; 
          break;
        }
      }
      if ( mu->pt > 3.0
           && (mu->qualityBits & kTMLastStationAngTight)
           && mu->nTkHits > 10
           && fabs(mu->d0) < 0.2
           && (mu->typeBits & kTracker)
           && !isCleanMuon
        ) {
        NSoftMuons++;
      }
    }
    for(Int_t i=0; i<electronArr->GetEntries(); i++) {
      const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i]);
      Bool_t isMuonOverlap = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if ( leptonType[k] == 13 
             && mithep::MathUtils::DeltaR(ele->phi, ele->eta, leptonPhi[k],leptonEta[k]) < 0.1
          ) {
          isMuonOverlap = kTRUE; 
          break;
        }        
      }

      if ( (0==0)
           && 
           passElectronCuts(ele)
           &&
           fabs(ele->eta) < 2.5
           && 
           ele->pt > 10.0
           &&
           !isMuonOverlap
        ) {
        leptonPt.push_back(ele->pt);
        leptonEta.push_back(ele->eta);
        leptonPhi.push_back(ele->phi);
        leptonType.push_back(11);
        leptonIndex.push_back(i);
        leptonCharge.push_back(ele->q);
      }
    }


    //sort leptons
    Int_t tempType;
    Int_t tempIndex;
    Double_t tempPt;
    Double_t tempEta;
    Double_t tempPhi;
    Int_t tempCharge;
    for (int l=0; l<leptonIndex.size(); l++) {
      for (int k=0; k < leptonIndex.size() - 1; k++) {
        if (leptonPt[k+1] > leptonPt[k]) {
          tempType = leptonType[k];
          tempIndex = leptonIndex[k];
          tempPt = leptonPt[k];
          tempEta = leptonEta[k];
          tempPhi = leptonPhi[k];
          tempCharge = leptonCharge[k];
          
          leptonType[k] = leptonType[k+1];
          leptonIndex[k] = leptonIndex[k+1];
          leptonPt[k] = leptonPt[k+1];
          leptonEta[k] = leptonEta[k+1];
          leptonPhi[k] = leptonPhi[k+1];
          leptonCharge[k] = leptonCharge[k+1];

          leptonType[k+1] = tempType;
          leptonIndex[k+1] = tempIndex;
          leptonPt[k+1] = tempPt;
          leptonEta[k+1] = tempEta;
          leptonPhi[k+1] = tempPhi;
          leptonCharge[k+1] = tempCharge;
          
        }
      }
    }

    double maxBtag = -99999;
    for(Int_t i=0; i<jetArr->GetEntries(); i++) {
      const mithep::TJet *jet = (mithep::TJet*)((*jetArr)[i]);

      Bool_t leptonOverlap = kFALSE;
      for (int k=0; k<leptonPt.size(); ++k) {
        if (mithep::MathUtils::DeltaR(jet->phi, jet->eta, leptonPhi[k],leptonEta[k]) < 0.3) {
          leptonOverlap = kTRUE;
        }
      }

      if (!leptonOverlap) {
        if (jet->pt > 25 && fabs(jet->eta) < 5.0 ) {
          if (!leadingJet || jet->pt > leadingJet->pt) {
            leadingJet = jet;
          }
          NJets++;
        } else {
          if (jet->TrackCountingHighEffBJetTagsDisc > maxBtag ) maxBtag = jet->TrackCountingHighEffBJetTagsDisc;
        }
      }
    }


    //******************************************************************************
    //dilepton preselection
    //******************************************************************************
    if (leptonPt.size() < 2) continue;
    if (!(leptonPt[0] > 20.0 && leptonPt[1] > 10.0)) continue;

    for(int i = 0; i < leptonPt.size(); ++i) {
      for(int j = i+1; j < leptonPt.size(); ++j) {

        //require opposite sign
        if ((ChargeSelection == 0 && leptonCharge[i] == leptonCharge[j]) || (ChargeSelection == 1 && leptonCharge[0] != leptonCharge[j])) continue;


        Int_t finalState = -1;
        if (leptonType[i] == 11 && leptonType[j] == 11) {
          finalState = 0;
        } else if (leptonType[i] == 13 && leptonType[j] == 13) {
          finalState = 1;
        } else if (leptonType[i] == 11 && leptonType[j] == 13) {
          finalState = 2;
        } else if (leptonType[i] == 13 && leptonType[j] == 11) {
          finalState = 3;
        }


        //***********************************************************************************************
        //|Z_vert-Z_l| maximum
        //***********************************************************************************************
        double zDiffMax = 0.0;
       
        double dz_i = 0;
        if (leptonType[0] == 11) {
          dz_i = ((mithep::TElectron*)((*electronArr)[leptonIndex[i]]))->dz;
        } else {
          dz_i = ((mithep::TMuon*)((*muonArr)[leptonIndex[i]]))->dz;
        }
        if (dz_i > zDiffMax) zDiffMax = dz_i;
    
        double dz_j;
        if (leptonType[j] == 11) {
          dz_j = ((mithep::TElectron*)((*electronArr)[leptonIndex[j]]))->dz;
        } else {
          dz_j = ((mithep::TMuon*)((*muonArr)[leptonIndex[j]]))->dz;
        }
        if (dz_j > zDiffMax) zDiffMax = dz_j;
        //szDiffMax = fabs(dz_i - dz_j);

        //******************************************************************************
        //construct event variables
        //******************************************************************************
        mithep::FourVectorM lepton1;
        mithep::FourVectorM lepton2;
        if (leptonType[i] == 11) {
          lepton1.SetCoordinates(leptonPt[i], leptonEta[i], leptonPhi[i], 0.51099892e-3 );
        } else {
          lepton1.SetCoordinates(leptonPt[i], leptonEta[i], leptonPhi[i], 105.658369e-3 );
        }
        if (leptonType[j] == 11) {
          lepton2.SetCoordinates(leptonPt[j], leptonEta[j], leptonPhi[j], 0.51099892e-3 );
        } else {
          lepton2.SetCoordinates(leptonPt[j], leptonEta[j], leptonPhi[j], 105.658369e-3 );
        }
        mithep::FourVectorM dilepton = lepton1+lepton2;

        double deltaPhiLeptons = mithep::MathUtils::DeltaPhi(lepton1.Phi(), 
                                                             lepton2.Phi())* 180.0 / TMath::Pi();    
        double deltaPhiDileptonMet = mithep::MathUtils::DeltaPhi(met.Phi(), 
                                                                 dilepton.Phi())*180.0 / TMath::Pi();    
        double mtHiggs = TMath::Sqrt(2.0*dilepton.Pt() * met.Phi()*
                                     (1.0 - cos(deltaPhiDileptonMet * TMath::Pi() / 180.0)));

        //angle between MET and closest lepton
        double deltaPhiMetLepton[2] = {mithep::MathUtils::DeltaPhi(met.Phi(), lepton1.Phi()),
                                       mithep::MathUtils::DeltaPhi(met.Phi(), lepton2.Phi())};
  
        double mTW[2] = {TMath::Sqrt(2.0*lepton1.Pt()*met.Pt()*
                                     (1.0 - cos(deltaPhiMetLepton[0]))),
                         TMath::Sqrt(2.0*lepton2.Pt()*met.Pt()*
                                     (1.0 - cos(deltaPhiMetLepton[1])))};

        double minDeltaPhiMetLepton = (deltaPhiMetLepton[0] < deltaPhiMetLepton[1])?
          deltaPhiMetLepton[0]:deltaPhiMetLepton[1];

        double METdeltaPhilEt = met.Pt();
        if(minDeltaPhiMetLepton < TMath::Pi()/2.)
          METdeltaPhilEt = METdeltaPhilEt * sin(minDeltaPhiMetLepton);

    
        //*********************************************************************************************
        //Define Cuts
        //*********************************************************************************************
        const int nCuts = 14;
        bool passCut[nCuts] = {false, false, false, false, false, false, false, false, false, false,
                               false, false, false, false};
  
        if(lepton1.Pt() >  20.0 &&
           lepton2.Pt() >= 10.0) passCut[0] = true;

        if(zDiffMax < 1.0)                    passCut[1] = true;
  
        if(met.Pt()    > 20.0)               passCut[2] = true;
  
        if(dilepton.M() > 12.0)            passCut[3] = true;
   
        if (finalState == 0 || finalState == 1){ // mumu/ee
          if(fabs(dilepton.M()-91.1876)   > 15.0)   passCut[4] = true;
          if(METdeltaPhilEt > 35) passCut[5] = true;
        }
        else if(finalState == 2 ||finalState == 3 ) { // emu
          passCut[4] = true;
          if(METdeltaPhilEt > 35) passCut[5] = true;
        }

        if(NJets     < 1)              passCut[6] = true;
        
        if (NSoftMuons == 0 )      passCut[7] = true;

        if (!(leptonPt.size() >= 3 && leptonPt[2] > 10.0)) passCut[8] = true;

        if(maxBtag < 2.1)                     passCut[9] = true;

        if (lepton1.Pt() > fPtMaxLowerCut) passCut[10] = true;
        if (lepton2.Pt() > fPtMinLowerCut) passCut[11] = true;
        if (dilepton.M() < fDileptonMassUpperCut)   passCut[12] = true;
        if (deltaPhiLeptons < fDeltaPhiCut) passCut[13] = true;

        //*********************************************************************************************
        //Make Selection Histograms. Number of events passing each level of cut
        //*********************************************************************************************  
        bool passAllCuts = true;
        for(int c=0; c<nCuts; c++) passAllCuts = passAllCuts & passCut[c];
    
  
        //*****************************************************************************************
        //Make Histograms Before Met Cut
        //*****************************************************************************************
        if (passCut[0] && passCut[1] && passCut[3] && passCut[6] &&passCut[7] && passCut[8] && passCut[9] 
//             && passCut[10] && passCut[11] && passCut[13] 
          ) {

          if (finalState == 0) {
            DileptonMass_allOtherCutsExceptMetCut_ee->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_ee++;
            } else {
              NEventsIn_BeforeMetCut_ee++;
            }

          } else if (finalState == 1) {
            DileptonMass_allOtherCutsExceptMetCut_mumu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_mm++;
            } else {
              NEventsIn_BeforeMetCut_mm++;
            }

          } else {
            DileptonMass_allOtherCutsExceptMetCut_emu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_BeforeMetCut_em++;
            } else {
              NEventsIn_BeforeMetCut_em++;
            }
          }        
        }

        //*****************************************************************************************
        //Make Histograms  
        //*****************************************************************************************
        if (passCut[0] && passCut[1] && passCut[2] && passCut[3] && passCut[5] &&passCut[6] &&passCut[7] && passCut[8] && passCut[9] 
//             && passCut[10] && passCut[11] && passCut[13] 
          ) {

          if (finalState == 0) {
            DileptonMass_allOtherCuts_ee->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_ee++;
            } else {
              NEventsIn_AfterMetCut_ee++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          } else if (finalState == 1) {
            DileptonMass_allOtherCuts_mumu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_mm++;
            } else {
              NEventsIn_AfterMetCut_mm++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          } else {
            DileptonMass_allOtherCuts_emu->Fill(dilepton.M());
            if(fabs(dilepton.M()-91.1876)   > 15.0) {
              NEventsOut_AfterMetCut_em++;
            } else {
              NEventsIn_AfterMetCut_em++;
              cout << info->runNum << " " << info->lumiSec << " " << info->evtNum << " : " << dilepton.M() << " " 
                   << finalState << " : " << lepton1.Pt() << " " << lepton1.Eta() << " " << lepton1.Phi() << " : " 
                   << " : " << lepton2.Pt() << " " << lepton2.Eta() << " " << lepton2.Phi() << " \n" ;
            }
          }        
        }



      }
    }
  

  } //end loop over data     



  delete info;
  delete electronArr;
  delete muonArr;
  delete jetArr;


  //--------------------------------------------------------------------------------------------------------------
  // Make plots
  //==============================================================================================================
  TCanvas *cv = new TCanvas("cv","cv", 800,600);

  //--------------------------------------------------------------------------------------------------------------
  // Summary print out
  //============================================================================================================== 



  cout << "Before Met Cut\n";
  cout << "Number of Events in Z window : (ee) " << NEventsIn_BeforeMetCut_ee << " (mm) " << NEventsIn_BeforeMetCut_mm << endl;
  cout << "Number of Events out of Z window : (ee) " << NEventsOut_BeforeMetCut_ee << " (mm) " << NEventsOut_BeforeMetCut_mm << endl;
  cout << "Ratio Out/In : (ee) " << NEventsOut_BeforeMetCut_ee / NEventsIn_BeforeMetCut_ee << " (mm) "
       << NEventsOut_BeforeMetCut_mm / NEventsIn_BeforeMetCut_mm << endl; 


  cout << "After Met Cut\n";
  cout << "Number of Events in Z window : (ee) " << NEventsIn_AfterMetCut_ee << " (mm) " 
       << NEventsIn_AfterMetCut_mm << " (em) " << NEventsIn_AfterMetCut_em << endl;
  cout << "Number of Events out of Z window : (ee) " << NEventsOut_AfterMetCut_ee << " (mm) " 
       << NEventsOut_AfterMetCut_mm << " (em) " << NEventsOut_AfterMetCut_em << endl;








  //--------------------------------------------------------------------------------------------------------------
  // Save Histograms;
  //============================================================================================================== 
  TFile *file = new TFile("HwwSelectionPlots.root", "RECREATE");
  
  
  file->WriteTObject(DileptonMass_allOtherCuts_ee ,DileptonMass_allOtherCuts_ee->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCuts_mumu ,DileptonMass_allOtherCuts_mumu->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCuts_emu ,DileptonMass_allOtherCuts_emu->GetName(), "WriteDelete");

  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_ee ,DileptonMass_allOtherCutsExceptMetCut_ee->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_mumu ,DileptonMass_allOtherCutsExceptMetCut_mumu->GetName(), "WriteDelete");
  file->WriteTObject(DileptonMass_allOtherCutsExceptMetCut_emu ,DileptonMass_allOtherCutsExceptMetCut_emu->GetName(), "WriteDelete");
  file->Close();
  delete file;

        
  gBenchmark->Show("WWTemplate");       
} 
void fill(int const kf, TLorentzVector* b, double const weight, TClonesArray& daughters)
{
   TLorentzVector kMom;
   TLorentzVector p1Mom;
   TLorentzVector p2Mom;

   int nTrk = daughters.GetEntriesFast();
   for (int iTrk = 0; iTrk < nTrk; ++iTrk)
   {
      TParticle* ptl0 = (TParticle*)daughters.At(iTrk);

      switch(abs(ptl0->GetPdgCode()))
      {
        case 321:
          ptl0->Momentum(kMom);
          break;
        case 211:
          if(!p1Mom.P()) ptl0->Momentum(p1Mom);
          else ptl0->Momentum(p2Mom);
          break;
        default:
          break;
      }
   }
   daughters.Clear();

   // smear and get total momentum
   TLorentzVector kRMom = smearMom(kMom,fKaonMomResolution);
   TLorentzVector p1RMom = smearMom(p1Mom,fPionMomResolution);
   TLorentzVector p2RMom = smearMom(p2Mom,fPionMomResolution);
   TLorentzVector rMom = kRMom + p1RMom + p2RMom;

   // save
   float arr[100];
   int iArr = 0;
   arr[iArr++] = kf;
   arr[iArr++] = weight;
   arr[iArr++] = b->M();
   arr[iArr++] = b->Perp();
   arr[iArr++] = b->PseudoRapidity();
   arr[iArr++] = b->Rapidity();
   arr[iArr++] = b->Phi();

   arr[iArr++] = rMom.M();
   arr[iArr++] = rMom.Perp();
   arr[iArr++] = rMom.PseudoRapidity();
   arr[iArr++] = rMom.Rapidity();
   arr[iArr++] = rMom.Phi();

   arr[iArr++] = kMom.M();
   arr[iArr++] = kMom.Perp();
   arr[iArr++] = kMom.PseudoRapidity();
   arr[iArr++] = kMom.Rapidity();
   arr[iArr++] = kMom.Phi();

   arr[iArr++] = kRMom.M();
   arr[iArr++] = kRMom.Perp();
   arr[iArr++] = kRMom.PseudoRapidity();
   arr[iArr++] = kRMom.Rapidity();
   arr[iArr++] = kRMom.Phi();

   arr[iArr++] = p1Mom.M();
   arr[iArr++] = p1Mom.Perp();
   arr[iArr++] = p1Mom.PseudoRapidity();
   arr[iArr++] = p1Mom.Rapidity();
   arr[iArr++] = p1Mom.Phi();

   arr[iArr++] = p1RMom.M();
   arr[iArr++] = p1RMom.Perp();
   arr[iArr++] = p1RMom.PseudoRapidity();
   arr[iArr++] = p1RMom.Rapidity();
   arr[iArr++] = p1RMom.Phi();

   arr[iArr++] = p2Mom.M();
   arr[iArr++] = p2Mom.Perp();
   arr[iArr++] = p2Mom.PseudoRapidity();
   arr[iArr++] = p2Mom.Rapidity();
   arr[iArr++] = p2Mom.Phi();

   arr[iArr++] = p2RMom.M();
   arr[iArr++] = p2RMom.Perp();
   arr[iArr++] = p2RMom.PseudoRapidity();
   arr[iArr++] = p2RMom.Rapidity();
   arr[iArr++] = p2RMom.Phi();
   
   nt->Fill(arr);
}
Exemple #17
0
    void fill(const JMETree& jme) {
        eventinfo.runNum = jme.run;
        eventinfo.evtNum = jme.evt;
        eventinfo.lumiSec = jme.lumi;
        eventinfo.nPU =  jme.npus->size() ? (*jme.npus)[0] : 0;
        eventinfo.nPUmean = jme.tnpus->size() ? (*jme.tnpus)[0] : 0;
        eventinfo.rhoIso = 0;
        eventinfo.rhoJet = jme.rho;
        eventinfo.triggerBits = 0;
        for(auto i = jme.paths->cbegin() ;  i != jme.paths->cend() ; ++i) {
            //cout << "testing " << *i << endl;
            for(auto i2 = triggernames->cbegin(); i2 != triggernames->cend() ; ++i2) {
                if(*i2 > *i) break;
                //cout << "trying " << *i2 << endl;
                if(i->compare(0,min(i->size(),i2->size()),*i2) == 0) {
                    //std::cout << "setting" << *i << ", " << *i2 << " " << i2-triggernames->cbegin() << endl;
                    eventinfo.triggerBits[i2-triggernames->cbegin()] = true;
                }
            }
            //std::cout << *i << endl;
        }
        //eventinfo.triggerBits = jme.prescales->size();
        eventinfo.pfMET =  (*jme.met_p4)[0].Pt();// not stored atm, to be done later
        eventinfo.pfMETphi = (*jme.met_p4)[0].Phi();
        geneventinfo.id_1 = jme.pdf_id->first;
        geneventinfo.id_2 = jme.pdf_id->second;
        geneventinfo.x_1 = jme.pdf_x->first;
        geneventinfo.x_2 = jme.pdf_x->second;
        geneventinfo.weight = jme.weight;
        //geneventinfo.pthat = jme.pthat; // is missing in the header - but anyway not needed (at the moment)


        vertices->Clear();
        jets->Clear();
        addjets->Clear();


        for(unsigned int j = 0 ; j < jme.position->size() ; ++j) {
            assert(vertices->GetEntries() < vertices->GetSize());
            const int index = vertices->GetEntries();
            new((*vertices)[index]) baconhep::TVertex();
            baconhep::TVertex    *pVertex = (baconhep::TVertex*)(*vertices)[index];
            //pVertex->nTracksFit =
            pVertex->ndof = (*jme.ndof)[j];
            pVertex->chi2 = (*jme.normalizedChi2)[j];
            pVertex->x = (*jme.position)[j].X();
            pVertex->y = (*jme.position)[j].Y();
            pVertex->z = (*jme.position)[j].Z();
        }



        for(unsigned int j = 0 ; j < jme.p4->size() ; ++j) {
            assert(jets->GetEntries() < jets->GetSize());
            const int index = jets->GetEntries();
            new((*jets)[index]) baconhep::TJet();
            baconhep::TJet    *pJet = (baconhep::TJet*)(*jets)[index];
            pJet->pt    = (*jme.p4)[j].pt();
            pJet->eta   = (*jme.p4)[j].eta();
            pJet->phi   = (*jme.p4)[j].phi();
            pJet->mass  = (*jme.p4)[j].mass();
            pJet->ptRaw = (*jme.p4)[j].pt() * (*jme.jec_toraw)[j];
            //pJet->csv = (*jme.pfCombinedSecondaryVertexV2BJetTags)[j];  // only stored in AK4PFCHS, to be done later
            pJet->area  = (*jme.jtarea)[j];
            pJet->genpt    = (*jme.gen_p4)[j].pt();
            pJet->geneta   = (*jme.gen_p4)[j].eta();
            pJet->genphi   = (*jme.gen_p4)[j].phi();
            pJet->genm  = (*jme.gen_p4)[j].mass();
            pJet->betaStar = (*jme.betaStar)[j];
            //std::cout << pJet->pt << std::endl;
        }


        tree->Fill();

    }
Exemple #18
0
// Main macro function
//--------------------------------------------------------------------------------------------------
void NormalizeNtuple(string inputFilename, string datasetName, string outputFilename) 
{
  gBenchmark->Start("NormalizeNtuple");
    
  TTree::SetMaxTreeSize(kMaxLong64);
  
  // Don't write TObject part of the objects
  mithep::TEventInfo::Class()->IgnoreTObjectStreamer();
  mithep::TMuon::Class()->IgnoreTObjectStreamer();
  mithep::TElectron::Class()->IgnoreTObjectStreamer();
  mithep::TJet::Class()->IgnoreTObjectStreamer();
  mithep::TPhoton::Class()->IgnoreTObjectStreamer();

  // Data structures to store info from TTrees
  mithep::TEventInfo *info  = new mithep::TEventInfo();
  TClonesArray *muonArr     = new TClonesArray("mithep::TMuon");
  TClonesArray *electronArr     = new TClonesArray("mithep::TElectron");
  TClonesArray *jetArr    = new TClonesArray("mithep::TJet");
  TClonesArray *photonArr     = new TClonesArray("mithep::TPhoton");

  UInt_t nInputEvts = 0;
  UInt_t nPassEvts  = 0;
  
  TFile* outfile = new TFile(outputFilename.c_str(), "RECREATE");

  //
  // Initialize data trees and structs
  // 
  TTree *outEventTree = new TTree("Events","Events"); 
  outEventTree->Branch("Info",     &info);
  outEventTree->Branch("Muon",     &muonArr);
  outEventTree->Branch("Electron", &electronArr);
  outEventTree->Branch("PFJet",    &jetArr);
  outEventTree->Branch("Photon",   &photonArr);

  TTree *eventTree = getTreeFromFile(inputFilename.c_str(),"Events"); 
   assert(eventTree);
    
  // Set branch address to structures that will store the info  
  eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("Muon",     &muonArr);     TBranch *muonBr     = eventTree->GetBranch("Muon");
  eventTree->SetBranchAddress("Electron", &electronArr); TBranch *electronBr = eventTree->GetBranch("Electron");
  eventTree->SetBranchAddress("PFJet",    &jetArr);      TBranch *jetBr    = eventTree->GetBranch("PFJet");
  eventTree->SetBranchAddress("Photon",    &photonArr);  TBranch *photonBr   = eventTree->GetBranch("Photon");

  Double_t normalizationWeight = getNormalizationWeight(inputFilename, datasetName);

  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) { 
    infoBr->GetEntry(ientry);
    muonArr->Clear();     muonBr->GetEntry(ientry);
    electronArr->Clear(); electronBr->GetEntry(ientry);
    photonArr->Clear(); photonBr->GetEntry(ientry);
    jetArr->Clear();      jetBr->GetEntry(ientry);
      
    if (ientry % 100000 == 0) cout << "Events: " << ientry << endl;

    nInputEvts++;
     
    info->eventweight = info->eventweight * normalizationWeight;
   outEventTree->Fill();
    nPassEvts++;
  }
  
  outfile->Write();
  outfile->Close();
  
  delete info;
  delete muonArr;
  delete electronArr;
  delete jetArr;
    
  std::cout << outputFilename << " created!" << std::endl;
  std::cout << " >>> Events processed: " << nInputEvts << std::endl;
  std::cout << " >>>   Events passing: " << nPassEvts << std::endl;
  
  gBenchmark->Show("NormalizeNtuple");
}  
Exemple #19
0
void selectZmmGen(const TString conf="zmmgen.conf", // input file
                  const TString outputDir="."   // output directory
	          ) {
  gBenchmark->Start("selectZmmGen");

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

  const Double_t MASS_LOW  = 40;
  const Double_t MASS_HIGH = 200;
  const Double_t PT_CUT    = 22;
  const Double_t ETA_CUT   = 2.4;
  const Double_t MUON_MASS = 0.105658369;

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 13;

  // load trigger menu                                                                                                  
  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  // load pileup reweighting file  

  TFile *f_rw = TFile::Open("../Tools/pileup_rw_baconDY.root", "read"); 
  
  // for systematics we need 3
  TH1D *h_rw = (TH1D*) f_rw->Get("h_rw_golden");
  TH1D *h_rw_up = (TH1D*) f_rw->Get("h_rw_up_golden");
  TH1D *h_rw_down = (TH1D*) f_rw->Get("h_rw_down_golden"); 

  if (h_rw==NULL) cout<<"WARNIG h_rw == NULL"<<endl;
  if (h_rw_up==NULL) cout<<"WARNIG h_rw == NULL"<<endl;
  if (h_rw_down==NULL) cout<<"WARNIG h_rw == NULL"<<endl;

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

  vector<TString>  snamev;      // sample name (for output files)  
  vector<CSample*> samplev;     // data/MC samples

  //
  // parse .conf file
  //
  confParse(conf, snamev, samplev);
 
  // 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  npv, npu;
  UInt_t  triggerDec;
  UInt_t  goodPV;
  UInt_t  matchTrigger;
  UInt_t  ngenlep;
  TLorentzVector *genlep1=0, *genlep2=0;
  Int_t   genq1, genq2;
  UInt_t nlep;
  TLorentzVector *lep1=0, *lep2=0;
  Int_t   q1, q2;
  Float_t scale1fbGen,scale1fb,scale1fbUp,scale1fbDown;

  std::vector<float> *lheweight = new std::vector<float>();

 // Data structures to store info from TTrees
  baconhep::TEventInfo *info   = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *muonArr    = new TClonesArray("baconhep::TMuon");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;

  //
  // loop over samples
  //  
  for(UInt_t isam=0; isam<samplev.size(); isam++) {
    
    // Assume signal sample is given name "zmm" - flag to store GEN Z kinematics
    Bool_t isSignal = snamev[isam].Contains("zmm",TString::kIgnoreCase);
    
    // flag to reject Z->mm events when selecting at wrong-flavor background events
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("zxx",TString::kIgnoreCase)==0);
    
    CSample* samp = samplev[isam];

    //
    // Set up output ntuple
    //
    TString 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("npv",        &npv,        "npv/i");         // number of primary vertices
    outTree->Branch("npu",        &npu,        "npu/i");         // number of in-time PU events (MC)
    outTree->Branch("triggerDec",   &triggerDec,   "triggerDec/i");    // event pass the trigger
    outTree->Branch("goodPV",   &goodPV,   "goodPV/i");    // event has a good PV
    outTree->Branch("matchTrigger",   &matchTrigger,   "matchTrigger/i");    // event has at least one lepton matched to the trigger
    outTree->Branch("ngenlep",     &ngenlep,     "ngenlep/i");      // number of gen leptons
    outTree->Branch("genlep1",   "TLorentzVector",  &genlep1);     // gen lepton1 4-vector
    outTree->Branch("genlep2",   "TLorentzVector",  &genlep2);     // gen lepton2 4-vector
    outTree->Branch("genq1",          &genq1,         "genq1/I");          // charge of lepton1
    outTree->Branch("genq2",          &genq2,         "genq2/I");          // charge of lepton2
    outTree->Branch("nlep",     &nlep,     "nlep/i");      // number of leptons
    outTree->Branch("lep1",       "TLorentzVector",  &lep1);     // lepton1 4-vector
    outTree->Branch("lep2",       "TLorentzVector",  &lep2);     // lepton2 4-vector
    outTree->Branch("q1",          &q1,         "q1/I");          // charge of lepton1
    outTree->Branch("q2",          &q2,         "q2/I");          // charge of lepton2
    outTree->Branch("scale1fbGen",   &scale1fbGen,   "scale1fbGen/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbUp",    &scale1fbUp,   "scale1fbUp/F");    // event weight per 1/fb (MC)
    outTree->Branch("scale1fbDown",    &scale1fbDown,   "scale1fbDown/F");    // event weight per 1/fb (MC)
    outTree->Branch("lheweight",  &lheweight);

    //
    // 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] ... " << endl; cout.flush();
      infile = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);
      
      eventTree = (TTree*)infile->Get("Events");
      assert(eventTree);  
      eventTree->SetBranchAddress("Info",     &info);        TBranch *infoBr     = eventTree->GetBranch("Info");
      eventTree->SetBranchAddress("Muon", &muonArr);   TBranch *muonBr = eventTree->GetBranch("Muon");
      eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
	eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }

      // Compute MC event weight per 1/fb
      const Double_t xsec = samp->xsecv[ifile];
      Double_t totalWeightGen=0;
      Double_t totalWeight=0;
      Double_t totalWeightUp=0;
      Double_t totalWeightDown=0;
      Double_t puWeight=0;
      Double_t puWeightUp=0;
      Double_t puWeightDown=0;
      if (hasGen) {
	for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	  infoBr->GetEntry(ientry);
	  genBr->GetEntry(ientry);
	  puWeight = h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));
	  puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean));
	  puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean));
	  totalWeightGen+=gen->weight;
	  totalWeight+=gen->weight*puWeight;
	  totalWeightUp+=gen->weight*puWeightUp;
	  totalWeightDown+=gen->weight*puWeightDown;
	}
      }


      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
	infoBr->GetEntry(ientry);

        if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

	Double_t weightGen=1;
	Double_t weight=1;
	Double_t weightUp=1;
	Double_t weightDown=1;
	if(xsec>0 && totalWeightGen>0) weightGen = xsec/totalWeightGen;
        if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
	if(xsec>0 && totalWeightUp>0) weightUp = xsec/totalWeightUp;
	if(xsec>0 && totalWeightDown>0) weightDown = xsec/totalWeightDown;
	if(hasGen) {
	  genPartArr->Clear();
	  genBr->GetEntry(ientry);
	  genPartBr->GetEntry(ientry);
	  puWeight = h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));
	  puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(info->nPUmean));
	  puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(info->nPUmean));
	  weightGen*=gen->weight;
	  weight*=gen->weight*puWeight;
	  weightUp*=gen->weight*puWeightUp;
	  weightDown*=gen->weight*puWeightDown;
	}

	// veto z -> xx decays for signal and z -> mm for bacground samples (needed for inclusive DYToLL sample)
        if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
        else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
     

	// trigger requirement
	Bool_t passMuTrigger = kFALSE;
	if (isMuonTrigger(triggerMenu, info->triggerBits)) passMuTrigger=kTRUE;
	
        // good vertex requirement
	Bool_t hasGoodPV = kFALSE;
        if((info->hasGoodPV)) hasGoodPV=kTRUE;

	muonArr->Clear();
        muonBr->GetEntry(ientry);

	Int_t n_mu=0;
	TLorentzVector vlep1(0., 0., 0., 0.);
	TLorentzVector vlep2(0., 0., 0., 0.);
	Bool_t hasTriggerMatch = kFALSE;

	for(Int_t i1=0; i1<muonArr->GetEntriesFast(); i1++) {
          const baconhep::TMuon *mu = (baconhep::TMuon*)((*muonArr)[i1]);

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

          if(isMuonTriggerObj(triggerMenu, mu->hltMatchBits, kFALSE)) hasTriggerMatch=kTRUE;
	  
	  if(Mu_Pt>vlep1.Pt())
	    {
	      vlep2=vlep1;
	      vlep1.SetPtEtaPhiM(Mu_Pt, mu->eta, mu->phi, MUON_MASS);
	      q2=q1;
	      q1=mu->q;
	    }
	  else if(Mu_Pt<=vlep1.Pt()&&Mu_Pt>vlep2.Pt())
	    {
	      vlep2.SetPtEtaPhiM(Mu_Pt, mu->eta, mu->phi, MUON_MASS);
	      q2=mu->q;
	    }
	 
	  n_mu++;
	}

	Int_t n_genmu=0;
	Int_t glepq1=-99;
	Int_t glepq2=-99;
	TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
	TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
	TLorentzVector *gph=new TLorentzVector(0,0,0,0);
	Bool_t hasGenMatch = kFALSE;
	if(isSignal && hasGen) {
	  toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,&glepq1,&glepq2,1);
	  
	  Bool_t match1 = ( ((glep1) && toolbox::deltaR(vlep1.Eta(), vlep1.Phi(), glep1->Eta(), glep1->Phi())<0.5) ||
			    ((glep2) && toolbox::deltaR(vlep1.Eta(), vlep1.Phi(), glep2->Eta(), glep2->Phi())<0.5) );
	      
	  Bool_t match2 = ( ((glep1) && toolbox::deltaR(vlep2.Eta(), vlep2.Phi(), glep1->Eta(), glep1->Phi())<0.5) ||
                                ((glep2) && toolbox::deltaR(vlep2.Eta(), vlep2.Phi(), glep2->Eta(), glep2->Phi())<0.5) );

	  for(Int_t i=0; i<genPartArr->GetEntriesFast(); i++) {
	    const baconhep::TGenParticle* genloop = (baconhep::TGenParticle*) ((*genPartArr)[i]);
	    if(fabs(genloop->pdgId)!=22) continue;
	    gph->SetPtEtaPhiM(genloop->pt, genloop->eta, genloop->phi, genloop->mass);
	    if(toolbox::deltaR(gph->Eta(),gph->Phi(),glep1->Eta(),glep1->Phi())<0.1)
	      {
		glep1->operator+=(*gph);
	      }
	    if(toolbox::deltaR(gph->Eta(),gph->Phi(),glep2->Eta(),glep2->Phi())<0.1)
	      {
		glep2->operator+=(*gph);
	      }
	  }

	  if(glep1->Pt() >= PT_CUT && fabs(glep1->Eta())< ETA_CUT)
	    {
	      genlep1=glep1;
	      genq1=glepq1;
	      n_genmu++;
	    }
	  if(glep2->Pt() >= PT_CUT && fabs(glep2->Eta())< ETA_CUT)
	    {
	      genlep2=glep2;
	      genq2=glepq2;
	      n_genmu++;
	    }
	  
	  if(match1 && match2) hasGenMatch = kTRUE;
	}

	//
	// Fill tree
	//
	runNum   = info->runNum;
	lumiSec  = info->lumiSec;
	evtNum   = info->evtNum;

	if (hasGenMatch) matchGen=1;
	else matchGen=0;
	if (passMuTrigger) triggerDec=1;
	else triggerDec=0;
	if (hasGoodPV) goodPV=1;
	else goodPV=0;
	if (hasTriggerMatch) matchTrigger=1;
	else matchTrigger=0;
	
	vertexArr->Clear();
	vertexBr->GetEntry(ientry);
	
	npv      = vertexArr->GetEntries();
	npu      = info->nPUmean;
	scale1fbGen = weightGen;
	scale1fb = weight;
	scale1fbUp = weightUp;
	scale1fbDown = weightDown;

	lheweight->clear();
	for (int j = 0; j<=110; j++)
	  {
	    lheweight->push_back(gen->lheweight[j]);
	  }

	ngenlep=n_genmu;

	nlep=n_mu;
	lep1=&vlep1;
        lep2=&vlep2;
	
	nsel+=weight;
	nselvar+=weight*weight;

	outTree->Fill();

	delete gvec;
	delete glep1;
	delete glep2;
	delete gph;
	lep1=0, lep2=0;
	genlep1=0, genlep2=0;
      }
      delete infile;
      infile=0, eventTree=0;    
      
      cout << nsel  << " +/- " << sqrt(nselvar);
      cout << endl;
    }
    outFile->Write();
    outFile->Close(); 
  }
  delete h_rw;
  delete h_rw_up;
  delete h_rw_down;
  delete f_rw;
  delete info;
  delete gen;
  delete genPartArr;
  delete muonArr;
  delete vertexArr;
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectZmmGen"); 
}
void HHToBBGGSelectionMistags(const string inputfile,          // input file
                              const string outputfile,         // output directory
                              Int_t SampleType = 7,
                              Bool_t applyExtrapWeightTo140PU = kFALSE
  ) {
  
  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 
  bool printdebug = false;

  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  Double_t nEvents = 0;
  Double_t nEventsTwoRealPho = 0;
  
  //*****************************************************************************************
  // Set up output ntuple
  //*****************************************************************************************
  TFile *outFile = new TFile(outputfile.c_str(),"RECREATE"); 
  TH1F *NEvents =  new TH1F("NEvents",";;",1,-0.5,0.5);
  //edit
  TH1F *NEventsTwoRealPho =  new TH1F("NEventsTwoRealPho",";;",1,-0.5,0.5);
  TH1F *NPUMean = new TH1F("NPUMean",";NPUMean;Number of Events", 100, -0.5, 99.5);
  cmsana::HHToBBGGEventTree *outputEventTree = new cmsana::HHToBBGGEventTree;
  outputEventTree->CreateTree();


  //*****************************************************************************************
  // Set up input
  //*****************************************************************************************
  TFile *infile=0;
  TTree *eventTree=0;
  
  // Data structures to store info from TTrees
  cmsana::TEventInfo *info  = new cmsana::TEventInfo();
  TClonesArray *genparticleArr = new TClonesArray("cmsana::TGenParticle");
  TClonesArray *genjetArr = new TClonesArray("cmsana::TGenJet");

  TFile *BJetMistagRateLightJetsFile = TFile::Open("/afs/cern.ch/work/s/sixie/public/releases/analysis/CMSSW_5_3_9_patch3/src/CMSAna/HHToBBGG/data/BTaggingEfficiency_LightJetsMistagRate.root");
  TFile *BJetMistagRateCharmJetsFile = TFile::Open("/afs/cern.ch/work/s/sixie/public/releases/analysis/CMSSW_5_3_9_patch3/src/CMSAna/HHToBBGG/data/BTaggingEfficiency_CharmJetsMistagRate.root");
  TFile *PhotonEfficiencyFile = TFile::Open("/afs/cern.ch/work/s/sixie/public/releases/analysis/CMSSW_5_3_9_patch3/src/CMSAna/HHToBBGG/data/PhotonEfficiency_PromptPhoton.root");
  TH2F *BJetMistagRateLightJetsHist = (TH2F*)BJetMistagRateLightJetsFile->Get("MistagRate_CSVMedium_Pt_Eta");
  TH2F *BJetMistagRateCharmJetsHist = (TH2F*)BJetMistagRateCharmJetsFile->Get("MistagRate_CSVMedium_Pt_Eta");
  TH2F *PhotonEfficiencyHist = (TH2F*)PhotonEfficiencyFile->Get("Efficiency_PtEta");
  TH2F *bjet1FakeRateHist = 0;
  TH2F *bjet2FakeRateHist = 0;
  double bjet1Eff = 0;
  double bjet2Eff = 0;

  // Read input file and get the TTrees
  cout << "Processing " << inputfile << "..." << endl;
  infile = TFile::Open(inputfile.c_str(),"read");
  assert(infile);

    
  eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
  eventTree->SetBranchAddress("Info", &info); TBranch *infoBr = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("GenParticle", &genparticleArr); TBranch *genparticleBr = eventTree->GetBranch("GenParticle");
  eventTree->SetBranchAddress("GenJet", &genjetArr); TBranch *genjetBr = eventTree->GetBranch("GenJet");
  cout << "NEvents = " << eventTree->GetEntries() << endl;

  
  Double_t weight = 1;

  // null vector for default four vectors
  cmsana::FourVector null(0.0,0.0,0.0,0.0);

  // loop over events
  for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
    if (ientry % 1000 == 0) cout << "Processed Event " << ientry << endl;
    infoBr->GetEntry(ientry);

    NEvents->Fill(0);
    NEventsTwoRealPho->Fill(0);
    NPUMean->Fill(info->nPUMean);

    //***********************************************************
    // Definition of Pileup Energy density
    //***********************************************************
    Double_t rho = info->RhoKt6PFJets;

    genparticleArr->Clear();
    genjetArr->Clear(); 

    genparticleBr->GetEntry(ientry);
    genjetBr->GetEntry(ientry);

    double tmpHT = 0;

    //***********************************************************
    // Find Gen-Level particles
    //***********************************************************
    const cmsana::TGenParticle *genPhoton1 = 0;
    const cmsana::TGenParticle *genPhoton2 = 0;
    for(Int_t i=0; i<genparticleArr->GetEntriesFast(); i++) {
      const cmsana::TGenParticle *p = (cmsana::TGenParticle*)((*genparticleArr)[i]);

      //***********************************************************
      // Find Gen Photons
      //***********************************************************
      if ( SampleType == cmsana::HHToBBGGEventTree::GGPlusTwoMistag) {
        if (p->pdgid == 22 && ( p->motherPdgID == 21 || (abs(p->motherPdgID) >= 1 && abs(p->motherPdgID) <= 6) ) ) {
          if (!genPhoton1) {
            genPhoton1 = p;
          } else if (!genPhoton2) {
            genPhoton2 = p;
          }
        }
      }

    }
    
    //sampleType
    cmsana::HHToBBGGEventTree::SampleType stype = cmsana::HHToBBGGEventTree::none;
    if (SampleType == 7) stype = cmsana::HHToBBGGEventTree::GGPlusTwoMistag;

    outputEventTree->sampletype = stype;
    outputEventTree->run = info->runNum;
    outputEventTree->lumi = info->lumiSec;
    outputEventTree->event = info->evtNum;
    outputEventTree->npu = info->nPU;
    outputEventTree->rho = info->RhoKt6PFJets;
    outputEventTree->nvtx = info->nGoodPV;

    cmsana::FourVectorM genpho1v;
    cmsana::FourVectorM genpho2v;
    outputEventTree->genpho1 = null;
    outputEventTree->genpho2 = null;
    if (genPhoton1) {
      genpho1v.SetPt(genPhoton1->pt);
      genpho1v.SetEta(genPhoton1->eta);
      genpho1v.SetPhi(genPhoton1->phi);
      genpho1v.SetM(0);
      outputEventTree->genpho1 = genpho1v;
    }
    if (genPhoton2) {
      genpho2v.SetPt(genPhoton2->pt);
      genpho2v.SetEta(genPhoton2->eta);
      genpho2v.SetPhi(genPhoton2->phi);
      genpho2v.SetM(0);   
      outputEventTree->genpho2 = genpho2v;    
    }

    cmsana::FourVectorM genb1v;
    cmsana::FourVectorM genb2v;
    outputEventTree->genb1 = null;
    outputEventTree->genb2 = null;

    //****************************************************************
    // Loop over genjets to make collection of eligible denominators
    //****************************************************************   
    UInt_t njets = 0;
    UInt_t ncentraljets = 0;
    vector<const cmsana::TGenJet*> goodBJets;
    for(Int_t i=0; i<genjetArr->GetEntriesFast(); i++) {
      const cmsana::TGenJet *genjet = (cmsana::TGenJet*)((*genjetArr)[i]);

      bool passBJetCuts = true;
//       if ( !(genPhoton1 && genPhoton2) ) passBJetCuts = false; //Si: not sure this is useful

      //***************************************************
      //bjet cuts
      //***************************************************
      if (!(genjet->pt > 30)) passBJetCuts = false;
      if (!(fabs(genjet->eta) < 2.4)) passBJetCuts = false;
      if (passBJetCuts) {      
        //save good bjets
        goodBJets.push_back((cmsana::TGenJet*)genjet->Clone()); //new object created
      }

      //***************************************************
      //jet counting
      //***************************************************
      if (genjet->pt > 30) {
        tmpHT += genjet->pt;
        njets++;
        if (fabs(genjet->eta) < 2.5) ncentraljets++;
      }
    }


    //***************************************************
    //No real bjets in this sample
    //***************************************************
    cmsana::FourVectorM genbjet1v;
    cmsana::FourVectorM genbjet2v;
    outputEventTree->genbjet1 = null;    
    outputEventTree->genbjet2 = null;    
    
    
    //***************************************************
    //selected photons
    //***************************************************
    const cmsana::TGenParticle *photon1 = 0;
    const cmsana::TGenParticle *photon2 = 0;

    if (genPhoton1) photon1 = genPhoton1;
    if (genPhoton2) photon2 = genPhoton2;

    cmsana::FourVectorM photon1v;
    cmsana::FourVectorM photon2v;
    cmsana::FourVectorM diphotonv;
    double pho1eff = 0;
    double pho2eff = 0;
    outputEventTree->pho1 = null;      //default 4-vector
    outputEventTree->pho2 = null;
    outputEventTree->diphoton = null;    

    if (photon1) {
      photon1v.SetPt(photon1->pt);
      photon1v.SetEta(photon1->eta);
      photon1v.SetPhi(photon1->phi);
      photon1v.SetM(0);
      outputEventTree->pho1 = photon1v;
      pho1eff = PhotonEfficiencyHist->GetBinContent(PhotonEfficiencyHist->FindFixBin(fmax(fmin(photon1->pt,99.9),0.01),
                                                                    fmax(fmin(photon1->eta,2.49),-2.49)));
    } 

    if (photon2) {
      photon2v.SetPt(photon2->pt);
      photon2v.SetEta(photon2->eta);
      photon2v.SetPhi(photon2->phi);
      photon2v.SetM(0);
      outputEventTree->pho2 = photon2v;
      pho2eff = PhotonEfficiencyHist->GetBinContent(PhotonEfficiencyHist->FindFixBin(fmax(fmin(photon2->pt,99.9),0.01),
                                                                    fmax(fmin(photon2->eta,2.49),-2.49)));
    }
    
    if (photon1 && photon2) {
      diphotonv = photon1v + photon2v;
      outputEventTree->diphoton = diphotonv;
    }
    
    if (photon1) tmpHT += photon1->pt;
    if (photon2) tmpHT += photon2->pt;

    //cout << " Number of good BJets: " << goodBJets.size() << endl;

    //***************************************************************************************************************
    // now that I have all the possible goodBJets, loop through them and choose two pairwise unique goodBJets to
    // promote to bjet1 and bjet2 and store this event into the tree (don't forget to weight the event)
    //
    //***************************************************************************************************************
    //Select all pairwise goodBJets (i.e. possible bjets)
    //***************************************************************************************************************
    if (goodBJets.size() > 1) {
      for (UInt_t i=0; i<goodBJets.size()-1; i++) {
        for (UInt_t j=i+1; j<goodBJets.size(); j++) {
          const cmsana::TGenJet* bjet1 = 0;
          const cmsana::TGenJet* bjet2 = 0;
          bjet1 = goodBJets[i];
          bjet2 = goodBJets[j];
          if (bjet2->pt > bjet1->pt) {
            const cmsana::TGenJet* tmp = bjet2;
            bjet2 = bjet1;
            bjet1 = tmp;
          }

          //**************************************************
          //skip any jet pairs that have real b jets
          //**************************************************
          if ( abs(bjet1->matchedPdgId) == 5 || abs(bjet2->matchedPdgId) == 5) continue;

          //**************************************************
          //assign mistag rates for light jets and charm
          //**************************************************          
          if ( abs(bjet1->matchedPdgId) == 4) bjet1FakeRateHist = BJetMistagRateCharmJetsHist;
          else bjet1FakeRateHist = BJetMistagRateLightJetsHist;
          if ( abs(bjet2->matchedPdgId) == 4) bjet2FakeRateHist = BJetMistagRateCharmJetsHist;
          else bjet2FakeRateHist = BJetMistagRateLightJetsHist;
          bjet1Eff = bjet1FakeRateHist->GetBinContent(bjet1FakeRateHist->FindBin(fmax(fmin(bjet1->pt,119.9),0.01),fmax(fmin(bjet1->eta,2.49),-2.49)));
          bjet2Eff = bjet2FakeRateHist->GetBinContent(bjet2FakeRateHist->FindBin(fmax(fmin(bjet1->pt,119.9),0.01),fmax(fmin(bjet1->eta,2.49),-2.49)));
      
          cmsana::FourVectorM bjet1v;
          cmsana::FourVectorM bjet2v;
          cmsana::FourVectorM dibjetv;
          outputEventTree->bjet1 = null;      //default 4-vector
          outputEventTree->bjet2 = null;
          outputEventTree->dibjet = null;    
      
          if (bjet1) {
            bjet1v.SetPt(bjet1->pt);
            bjet1v.SetEta(bjet1->eta);
            bjet1v.SetPhi(bjet1->phi);
            bjet1v.SetM(bjet1->mass);
      
            outputEventTree->bjet1 = bjet1v;
          }
      
          if (bjet2) {
            bjet2v.SetPt(bjet2->pt);
            bjet2v.SetEta(bjet2->eta);
            bjet2v.SetPhi(bjet2->phi);
            bjet2v.SetM(bjet2->mass);
            outputEventTree->bjet2 = bjet2v;
          }

          if (bjet1 && bjet2) {
            dibjetv = bjet1v + bjet2v;
            outputEventTree->dibjet = dibjetv;
          }

          //********************************************************
          //bbgg system
          //********************************************************    
          cmsana::FourVectorM bbggSystemv;
          outputEventTree->bbgg = null;
          if (bjet1 && bjet2 && photon1 && photon2) {
            bbggSystemv = (photon1v + photon2v + bjet1v + bjet2v);
            outputEventTree->bbgg = bbggSystemv;
          }
      
      
      
          //********************************************************
          //NJets
          //********************************************************    
          outputEventTree->njets = njets;
          outputEventTree->ncentraljets = ncentraljets;      
          outputEventTree->nlep = 0;

          //********************************************************
          //Some kinematic variables
          //********************************************************
          outputEventTree->DRgg = -1;
          outputEventTree->DRbb = -1;
          outputEventTree->minDRgb = -1;
          if (photon1 && photon2 && bjet1 && bjet2 ) {
            outputEventTree->DRgg = cmsana::deltaR(photon1->eta, photon1->phi, photon2->eta, photon2->phi);
            outputEventTree->DRbb = cmsana::deltaR(bjet1->eta, bjet1->phi, bjet2->eta, bjet2->phi);
            outputEventTree->minDRgb = fmin(fmin(fmin( cmsana::deltaR(photon1->eta, photon1->phi, bjet1->eta, bjet1->phi), 
                                                       cmsana::deltaR(photon1->eta, photon1->phi, bjet2->eta, bjet2->phi)),
                                                 cmsana::deltaR(photon2->eta, photon2->phi, bjet1->eta, bjet1->phi)),
                                            cmsana::deltaR(photon2->eta, photon2->phi, bjet2->eta, bjet2->phi));      
          }
      
          outputEventTree->pfmet = 0;
          outputEventTree->pfTrackMET = 0;          
          outputEventTree->HT = tmpHT;
          
          //Note: currently not computing HT. we may add it later.

          //*******************************************************
          //Apply mistag and photon selection efficiencies
          //*******************************************************
          outputEventTree->weight = bjet1Eff * bjet2Eff * pho1eff * pho2eff;

          //************************************
          //Extrapolation to 140 Pileup
          //************************************
          double pho1EffScalingForPU140 = 1.0;
          double pho2EffScalingForPU140 = 1.0;
          double bjet1EffScalingForPU140 = 1.0;
          double bjet2EffScalingForPU140 = 1.0;
          pho1EffScalingForPU140 = (0.85/0.95)*(0.85/0.95);
          pho2EffScalingForPU140 = (0.85/0.95)*(0.85/0.95);

          //Don't do extrapolation for mistag rate at this point in time
//           if ( abs(bjet1->matchedPdgId) == 4) {
//             bjet1EffScalingForPU140 = 0.15/0.10;
//           } else {
//             bjet1EffScalingForPU140 = 0.03/0.015;
//           }
//           if ( abs(bjet2->matchedPdgId) == 4) {
//             bjet2EffScalingForPU140 = 0.15/0.10;
//           } else {
//             bjet2EffScalingForPU140 = 0.03/0.015;
//           }

          if (applyExtrapWeightTo140PU) {
            outputEventTree->weight = outputEventTree->weight * pho1EffScalingForPU140*pho2EffScalingForPU140*bjet1EffScalingForPU140*bjet2EffScalingForPU140;
          }


          //********************************************************
          //Fill Output Tree
          //********************************************************
          outputEventTree->tree_->Fill();
          nEventsTwoRealPho++;
        }
      }
    }


    //********************************************************
    //Clean up Memory
    //********************************************************
    for (uint k=0; k<goodBJets.size(); ++k) {
      if (goodBJets[k]) delete goodBJets[k];
    }
    nEvents++;

  } //loop over all events


  delete infile;
  infile=0, eventTree=0;      
  delete info;
  delete genparticleArr;
  delete genjetArr;
  
     
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  
  outFile->Write();
  outFile->Close();
  delete outFile;
  
  cout << " Number of events selected: " << nEvents << endl;
  cout << endl;
  cout << " Number of events with two real photons: " << nEventsTwoRealPho << endl;
  cout << endl;
  cout << "  <> Output saved in " << outputfile << endl;    
  cout << endl;  
      

}
Exemple #21
0
void renderHLTClusters(TTree* clustersTree)
{
    
    /**************************
     *  Visualization of Clusters
     **************************/
    const Int_t kMaxCl=100*160;
    Int_t fNColorBins = 5;
    
    TEvePointSet* clusters = new TEvePointSet(kMaxCl);
    clusters->SetOwnIds(kTRUE);
    
    TEvePointSetArray * cc = new TEvePointSetArray("TPC Clusters Colorized");
    cc->SetMainColor(kRed);
    cc->SetMarkerStyle(8);
    cc->SetMarkerSize(1.0);
    cc->InitBins("Cluster Charge", fNColorBins, 0., fNColorBins*60.);
    
    cc->GetBin(0)->SetMainColor(kGray);
    cc->GetBin(0)->SetMarkerSize(1.0);
    cc->GetBin(1)->SetMainColor(kBlue);
    cc->GetBin(1)->SetMarkerSize(1.0);
    cc->GetBin(2)->SetMainColor(kCyan);
    cc->GetBin(2)->SetMarkerSize(1.0);
    cc->GetBin(3)->SetMainColor(kGreen);
    cc->GetBin(3)->SetMarkerSize(1.0);
    cc->GetBin(4)->SetMainColor(kYellow);
    cc->GetBin(4)->SetMarkerSize(1.0);
    cc->GetBin(5)->SetMainColor(kRed);
    cc->GetBin(5)->SetMarkerSize(1.0);
    cc->GetBin(6)->SetMainColor(kMagenta);
    cc->GetBin(6)->SetMarkerSize(1.0);
    
    
    // Loop over clusters
    Int_t nentries = clustersTree->GetEntriesFast();
    
    AliTPCClustersRow *clrow = new AliTPCClustersRow();
    clrow->SetClass("AliTPCclusterMI");
    //clrow->SetArray(kMaxCl);
    clustersTree->SetBranchAddress("Segment", &clrow);
    
    for (Int_t i=0; i<nentries; i++) {
        if (!clustersTree->GetEvent(i)) continue;
        
        TClonesArray *cl = clrow->GetArray();
        Int_t ncl = cl->GetEntriesFast();
        
        while (ncl--)
        {
            AliTPCclusterMI* clusterMI = (AliTPCclusterMI*) cl->At(ncl);
            
            AliCluster *c = (AliCluster*) cl->UncheckedAt(ncl);
            Float_t g[3]; //global coordinates
            c->GetGlobalXYZ(g);
            cout<<g[0]<<"\t"<<g[1]<<"\t"<<g[2]<<endl;
            cc->Fill(g[0], g[1], g[2], clusterMI->GetQ());
            clusters->SetNextPoint(g[0], g[1], g[2]);
            AliCluster *atp = new AliCluster(*clusterMI);
            clusters->SetPointId(atp);
            
        }
        cl->Clear();
    }
    
//    delete clrow;
    
    clusters->SetName("TPC Clusters");
    clusters->SetTitle(Form("N=%d", clusters->Size()));
    
//    const TString viz_tag("REC Clusters TPC"); // to be changed
//    clusters->ApplyVizTag(viz_tag, "Clusters");
    
    cc->SetRnrSelf(kTRUE);
    
    gEve->AddElement(cc);
    
    return;
}
Exemple #22
0
void selectWe(const TString conf="we.conf", // input file
              const TString outputDir=".",  // output directory
              const Bool_t  doScaleCorr=0   // apply energy scale corrections?
             ) {
    gBenchmark->Start("selectWe");

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

    const Double_t PT_CUT   = 25;
    const Double_t ETA_CUT  = 2.5;
    const Double_t ELE_MASS = 0.000511;

    const Double_t VETO_PT   = 10;
    const Double_t VETO_ETA  = 2.5;

    const Double_t ECAL_GAP_LOW  = 1.4442;
    const Double_t ECAL_GAP_HIGH = 1.566;

    const Double_t escaleNbins  = 2;
    const Double_t escaleEta[]  = { 1.4442, 2.5   };
    const Double_t escaleCorr[] = { 0.992,  1.009 };

    const Int_t BOSON_ID  = 24;
    const Int_t LEPTON_ID = 11;

    // load trigger menu
    const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

    // load pileup reweighting file
    TFile *f_rw = TFile::Open("../Tools/pileup_rw_Golden.root", "read");
    TH1D *h_rw = (TH1D*) f_rw->Get("h_rw_golden");
    TH1D *h_rw_up = (TH1D*) f_rw->Get("h_rw_up_golden");
    TH1D *h_rw_down = (TH1D*) f_rw->Get("h_rw_down_golden");

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

    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  npv, npu;
    UInt_t  id_1, id_2;
    Double_t x_1, x_2, xPDF_1, xPDF_2;
    Double_t scalePDF, weightPDF;
    TLorentzVector *genV=0, *genLep=0;
    Float_t genVPt, genVPhi, genVy, genVMass;
    Float_t genLepPt, genLepPhi;
    Float_t scale1fb, puWeight, puWeightUp, puWeightDown;
    Float_t met, metPhi, sumEt, mt, u1, u2;
    Float_t tkMet, tkMetPhi, tkSumEt, tkMt, tkU1, tkU2;
    Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaMt, mvaU1, mvaU2;
    Float_t puppiMet, puppiMetPhi, puppiSumEt, puppiMt, puppiU1, puppiU2;
    Int_t   q;
    TLorentzVector *lep=0;
    Int_t lepID;
    ///// electron specific /////
    Float_t trkIso, emIso, hadIso;
    Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
    Float_t sigieie, hovere, eoverp, fbrem, ecalE;
    Float_t dphi, deta;
    Float_t d0, dz;
    UInt_t  isConv, nexphits, typeBits;
    TLorentzVector *sc=0;

    // Data structures to store info from TTrees
    baconhep::TEventInfo *info   = new baconhep::TEventInfo();
    baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
    TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
    TClonesArray *electronArr    = new TClonesArray("baconhep::TElectron");
    TClonesArray *scArr          = new TClonesArray("baconhep::TPhoton");
    TClonesArray *vertexArr      = new TClonesArray("baconhep::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
        Bool_t isData=kFALSE;
        if(isam==0 && !hasData) continue;
        else if (isam==0) isData=kTRUE;

        // Assume signal sample is given name "we" -- flag to store GEN W kinematics
        Bool_t isSignal = (snamev[isam].CompareTo("we",TString::kIgnoreCase)==0);
        // flag to reject W->enu events when selecting at wrong-flavor background events
        Bool_t isWrongFlavor = (snamev[isam].CompareTo("wx",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("npv",        &npv,        "npv/i");         // number of primary vertices
        outTree->Branch("npu",        &npu,        "npu/i");         // number of in-time PU events (MC)
        outTree->Branch("id_1",       &id_1,       "id_1/i");        // PDF info -- parton ID for parton 1
        outTree->Branch("id_2",       &id_2,       "id_2/i");        // PDF info -- parton ID for parton 2
        outTree->Branch("x_1",        &x_1,        "x_1/d");         // PDF info -- x for parton 1
        outTree->Branch("x_2",        &x_2,        "x_2/d");         // PDF info -- x for parton 2
        outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");      // PDF info -- x*F for parton 1
        outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");      // PDF info -- x*F for parton 2
        outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");    // PDF info -- energy scale of parton interaction
        outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");   // PDF info -- PDF weight
        outTree->Branch("genV",      "TLorentzVector", &genV);       // GEN boson 4-vector (signal MC)
        outTree->Branch("genLep",    "TLorentzVector", &genLep);     // GEN lepton 4-vector (signal 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("genLepPt",   &genLepPt,   "genLepPt/F");    // GEN lepton pT (signal MC)
        outTree->Branch("genLepPhi",  &genLepPhi,  "genLepPhi/F");   // GEN lepton phi (signal MC)
        outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");    // event weight per 1/fb (MC)
        outTree->Branch("puWeight",   &puWeight,   "puWeight/F");    // scale factor for pileup reweighting (MC)
        outTree->Branch("puWeightUp",    &puWeightUp,   "puWeightUp/F");    // scale factor for pileup reweighting (MC)
        outTree->Branch("puWeightDown",    &puWeightDown,   "puWeightDown/F");    // scale factor for pileup reweighting (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("mt",         &mt,         "mt/F");          // transverse mass
        outTree->Branch("u1",         &u1,         "u1/F");          // parallel component of recoil
        outTree->Branch("u2",         &u2,         "u2/F");          // perpendicular component of recoil
        outTree->Branch("tkMet",      &tkMet,      "tkMet/F");       // MET (track MET)
        outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");    // phi(MET) (track MET)
        outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");     // Sum ET (track MET)
        outTree->Branch("tkMt",       &tkMt,       "tkMt/F");        // transverse mass (track MET)
        outTree->Branch("tkU1",       &tkU1,       "tkU1/F");        // parallel component of recoil (track MET)
        outTree->Branch("tkU2",       &tkU2,       "tkU2/F");        // perpendicular component of recoil (track MET)
        outTree->Branch("mvaMet",     &mvaMet,     "mvaMet/F");      // MVA MET
        outTree->Branch("mvaMetPhi",  &mvaMetPhi,  "mvaMetPhi/F");   // phi(MVA MET)
        outTree->Branch("mvaSumEt",   &mvaSumEt,   "mvaSumEt/F");    // Sum ET (mva MET)
        outTree->Branch("mvaMt",      &mvaMt,      "mvaMt/F");       // transverse mass (mva MET)
        outTree->Branch("mvaU1",      &mvaU1,      "mvaU1/F");       // parallel component of recoil (mva MET)
        outTree->Branch("mvaU2",      &mvaU2,      "mvaU2/F");       // perpendicular component of recoil (mva MET)
        outTree->Branch("puppiMet",    &puppiMet,   "puppiMet/F");      // Puppi MET
        outTree->Branch("puppiMetPhi", &puppiMetPhi,"puppiMetPhi/F");   // phi(Puppi MET)
        outTree->Branch("puppiSumEt",  &puppiSumEt, "puppiSumEt/F");    // Sum ET (Puppi MET)
        outTree->Branch("puppiU1",     &puppiU1,    "puppiU1/F");       // parallel component of recoil (Puppi MET)
        outTree->Branch("puppiU2",     &puppiU2,    "puppiU2/F");       // perpendicular component of recoil (Puppi MET)
        outTree->Branch("q",          &q,          "q/I");           // lepton charge
        outTree->Branch("lep",       "TLorentzVector", &lep);        // lepton 4-vector
        outTree->Branch("lepID",      &lepID,      "lepID/I");       // lepton PDG ID
        ///// electron specific /////
        outTree->Branch("trkIso",     &trkIso,     "trkIso/F");      // track isolation of tag lepton
        outTree->Branch("emIso",      &emIso,      "emIso/F");       // ECAL isolation of tag lepton
        outTree->Branch("hadIso",     &hadIso,     "hadIso/F");      // HCAL isolation of tag lepton
        outTree->Branch("pfChIso",    &pfChIso,    "pfChIso/F");     // PF charged hadron isolation of lepton
        outTree->Branch("pfGamIso",   &pfGamIso,   "pfGamIso/F");    // PF photon isolation of lepton
        outTree->Branch("pfNeuIso",   &pfNeuIso,   "pfNeuIso/F");    // PF neutral hadron isolation of lepton
        outTree->Branch("pfCombIso",  &pfCombIso,  "pfCombIso/F");   // PF combined isolation of electron
        outTree->Branch("sigieie",    &sigieie,    "sigieie/F");     // sigma-ieta-ieta of electron
        outTree->Branch("hovere",     &hovere,     "hovere/F");      // H/E of electron
        outTree->Branch("eoverp",     &eoverp,     "eoverp/F");      // E/p of electron
        outTree->Branch("fbrem",      &fbrem,      "fbrem/F");       // brem fraction of electron
        outTree->Branch("dphi",       &dphi,       "dphi/F");        // GSF track - ECAL dphi of electron
        outTree->Branch("deta",       &deta,       "deta/F");        // GSF track - ECAL deta of electron
        outTree->Branch("ecalE",      &ecalE,      "ecalE/F");       // ECAL energy of electron
        outTree->Branch("d0",         &d0,         "d0/F");          // transverse impact parameter of electron
        outTree->Branch("dz",         &dz,         "dz/F");          // longitudinal impact parameter of electron
        outTree->Branch("isConv",     &isConv,     "isConv/i");      // conversion filter flag of electron
        outTree->Branch("nexphits",   &nexphits,   "nexphits/i");    // number of missing expected inner hits of electron
        outTree->Branch("typeBits",   &typeBits,   "typeBits/i");    // electron type of electron
        outTree->Branch("sc",        "TLorentzVector", &sc);         // 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 = TFile::Open(samp->fnamev[ifile]);
            assert(infile);

            Bool_t hasJSON = kFALSE;
            baconhep::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("PV",   &vertexArr);
            TBranch *vertexBr = eventTree->GetBranch("PV");

            Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
            TBranch *genBr=0, *genPartBr=0;
            if(hasGen) {
                eventTree->SetBranchAddress("GenEvtInfo", &gen);
                genBr = eventTree->GetBranch("GenEvtInfo");
                eventTree->SetBranchAddress("GenParticle",&genPartArr);
                genPartBr = eventTree->GetBranch("GenParticle");
            }

            // Compute MC event weight per 1/fb
            const Double_t xsec = samp->xsecv[ifile];
            Double_t totalWeight=0;

            if (hasGen) {
                TH1D *hall = new TH1D("hall", "", 1,0,1);
                eventTree->Draw("0.5>>hall", "GenEvtInfo->weight");
                totalWeight=hall->Integral();
                delete hall;
                hall=0;
            }

            //
            // loop over events
            //
            Double_t nsel=0, nselvar=0;
            for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
                infoBr->GetEntry(ientry);

                if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

                Double_t weight=1;
                if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
                if(hasGen) {
                    genPartArr->Clear();
                    genBr->GetEntry(ientry);
                    genPartBr->GetEntry(ientry);
                    weight*=gen->weight;
                }

                // veto w -> xv decays for signal and w -> ev for bacground samples (needed for inclusive WToLNu sample)
                if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
                else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;

                // check for certified lumi (if applicable)
                baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);
                if(hasJSON && !rlrm.hasRunLumi(rl)) continue;

                // trigger requirement
                if (!isEleTrigger(triggerMenu, info->triggerBits, isData)) continue;

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

                //
                // SELECTION PROCEDURE:
                //  (1) Look for 1 good electron matched to trigger
                //  (2) Reject event if another electron is present passing looser cuts
                //
                electronArr->Clear();
                electronBr->GetEntry(ientry);

                Int_t nLooseLep=0;
                const baconhep::TElectron *goodEle=0;
                Bool_t passSel=kFALSE;

                for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
                    const baconhep::TElectron *ele = (baconhep::TElectron*)((*electronArr)[i]);

                    // check ECAL gap
                    if(fabs(ele->scEta)>=ECAL_GAP_LOW && fabs(ele->scEta)<=ECAL_GAP_HIGH) continue;

                    // apply scale and resolution corrections to MC
                    Double_t elescEt_corr = ele->scEt;
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
                        elescEt_corr = gRandom->Gaus(ele->scEt*getEleScaleCorr(ele->scEta,0),getEleResCorr(ele->scEta,0));

                    if(fabs(ele->scEta)   > VETO_ETA) continue;        // loose lepton |eta| cut
                    if(elescEt_corr       < VETO_PT)  continue;        // loose lepton pT cut
                    if(passEleLooseID(ele,info->rhoIso)) nLooseLep++;  // loose lepton selection
                    if(nLooseLep>1) {  // extra lepton veto
                        passSel=kFALSE;
                        break;
                    }

                    if(fabs(ele->scEta)   > ETA_CUT)     continue;  // lepton |eta| cut
                    if(elescEt_corr       < PT_CUT)      continue;  // lepton pT cut
                    if(!passEleID(ele,info->rhoIso))     continue;  // lepton selection
                    if(!isEleTriggerObj(triggerMenu, ele->hltMatchBits, kFALSE, isData)) continue;

                    passSel=kTRUE;
                    goodEle = ele;
                }

                if(passSel) {

                    //******* We have a W candidate! HURRAY! ********
                    nsel+=weight;
                    nselvar+=weight*weight;

                    // apply scale and resolution corrections to MC
                    Double_t goodElept_corr = goodEle->pt;
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0)
                        goodElept_corr = gRandom->Gaus(goodEle->pt*getEleScaleCorr(goodEle->scEta,0),getEleResCorr(goodEle->scEta,0));

                    TLorentzVector vLep(0,0,0,0);
                    TLorentzVector vSC(0,0,0,0);
                    // apply scale and resolution corrections to MC
                    if(doScaleCorr && snamev[isam].CompareTo("data",TString::kIgnoreCase)!=0) {
                        vLep.SetPtEtaPhiM(goodElept_corr, goodEle->eta, goodEle->phi, ELE_MASS);
                        vSC.SetPtEtaPhiM(gRandom->Gaus(goodEle->scEt*getEleScaleCorr(goodEle->scEta,0),getEleResCorr(goodEle->scEta,0)), goodEle->scEta, goodEle->scPhi, ELE_MASS);
                    } else {
                        vLep.SetPtEtaPhiM(goodEle->pt,goodEle->eta,goodEle->phi,ELE_MASS);
                        vSC.SetPtEtaPhiM(goodEle->scEt,goodEle->scEta,goodEle->scPhi,ELE_MASS);
                    }

                    //
                    // Fill tree
                    //
                    runNum    = info->runNum;
                    lumiSec   = info->lumiSec;
                    evtNum    = info->evtNum;

                    vertexArr->Clear();
                    vertexBr->GetEntry(ientry);

                    npv      = vertexArr->GetEntries();
                    npu	    = info->nPUmean;
                    genV      = new TLorentzVector(0,0,0,0);
                    genLep    = new TLorentzVector(0,0,0,0);
                    genVPt    = -999;
                    genVPhi   = -999;
                    genVy     = -999;
                    genVMass  = -999;
                    genLepPt  = -999;
                    genLepPhi = -999;
                    u1        = -999;
                    u2        = -999;
                    tkU1      = -999;
                    tkU2      = -999;
                    mvaU1     = -999;
                    mvaU2     = -999;
                    puppiU1     = -999;
                    puppiU2     = -999;
                    id_1      = -999;
                    id_2      = -999;
                    x_1       = -999;
                    x_2       = -999;
                    xPDF_1    = -999;
                    xPDF_2    = -999;
                    scalePDF  = -999;
                    weightPDF = -999;

                    if(isSignal && hasGen) {
                        TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
                        TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
                        TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
                        toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,1);

                        if (gvec && glep1) {
                            genV      = new TLorentzVector(0,0,0,0);
                            genV->SetPtEtaPhiM(gvec->Pt(),gvec->Eta(),gvec->Phi(),gvec->M());
                            genLep    = new TLorentzVector(0,0,0,0);
                            genLep->SetPtEtaPhiM(glep1->Pt(),glep1->Eta(),glep1->Phi(),glep1->M());
                            genVPt    = gvec->Pt();
                            genVPhi   = gvec->Phi();
                            genVy     = gvec->Rapidity();
                            genVMass  = gvec->M();
                            genLepPt  = glep1->Pt();
                            genLepPhi = glep1->Phi();

                            TVector2 vWPt((genVPt)*cos(genVPhi),(genVPt)*sin(genVPhi));
                            TVector2 vLepPt(vLep.Px(),vLep.Py());

                            TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
                            TVector2 vU = -1.0*(vMet+vLepPt);
                            u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));
                            TVector2 vTkU = -1.0*(vTkMet+vLepPt);
                            tkU1 = ((vWPt.Px())*(vTkU.Px()) + (vWPt.Py())*(vTkU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            tkU2 = ((vWPt.Px())*(vTkU.Py()) - (vWPt.Py())*(vTkU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
                            TVector2 vMvaU = -1.0*(vMvaMet+vLepPt);
                            mvaU1 = ((vWPt.Px())*(vMvaU.Px()) + (vWPt.Py())*(vMvaU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            mvaU2 = ((vWPt.Px())*(vMvaU.Py()) - (vWPt.Py())*(vMvaU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                            TVector2 vPuppiMet((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
                            TVector2 vPuppiU = -1.0*(vPuppiMet+vLepPt);
                            puppiU1 = ((vWPt.Px())*(vPuppiU.Px()) + (vWPt.Py())*(vPuppiU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
                            puppiU2 = ((vWPt.Px())*(vPuppiU.Py()) - (vWPt.Py())*(vPuppiU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

                        }
                        id_1      = gen->id_1;
                        id_2      = gen->id_2;
                        x_1       = gen->x_1;
                        x_2       = gen->x_2;
                        xPDF_1    = gen->xPDF_1;
                        xPDF_2    = gen->xPDF_2;
                        scalePDF  = gen->scalePDF;
                        weightPDF = gen->weight;

                        delete gvec;
                        delete glep1;
                        delete glep2;
                        gvec=0;
                        glep1=0;
                        glep2=0;
                    }
                    scale1fb = weight;
                    puWeight = h_rw->GetBinContent(h_rw->FindBin(npu));
                    puWeightUp = h_rw_up->GetBinContent(h_rw_up->FindBin(npu));
                    puWeightDown = h_rw_down->GetBinContent(h_rw_down->FindBin(npu));
                    met	   = info->pfMETC;
                    metPhi   = info->pfMETCphi;
                    sumEt    = 0;
                    mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMETC) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETCphi))) );
                    tkMet	   = info->trkMET;
                    tkMetPhi = info->trkMETphi;
                    tkSumEt  = 0;
                    tkMt     = sqrt( 2.0 * (vLep.Pt()) * (info->trkMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->trkMETphi))) );
                    mvaMet   = info->mvaMET;
                    mvaMetPhi = info->mvaMETphi;
                    mvaSumEt  = 0;
                    mvaMt     = sqrt( 2.0 * (vLep.Pt()) * (info->mvaMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->mvaMETphi))) );
// 	  TVector2 vLepPt(vLep.Px(),vLep.Py());
// 	  TVector2 vPuppi((info->puppET)*cos(info->puppETphi), (info->puppET)*sin(info->puppETphi));
// 	  TVector2 vpp; vpp=vPuppi-vLepPt;
                    puppiMet   = info->puppET;
                    puppiMetPhi = info->puppETphi;
                    puppiSumEt  = 0;
                    puppiMt     = sqrt( 2.0 * (vLep.Pt()) * (info->puppET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->puppETphi))) );
                    q        = goodEle->q;
                    lep      = &vLep;

                    ///// electron specific /////
                    sc       = &vSC;
                    trkIso    = goodEle->trkIso;
                    emIso     = goodEle->ecalIso;
                    hadIso    = goodEle->hcalIso;
                    pfChIso   = goodEle->chHadIso;
                    pfGamIso  = goodEle->gammaIso;
                    pfNeuIso  = goodEle->neuHadIso;
                    pfCombIso = goodEle->chHadIso + TMath::Max(goodEle->neuHadIso + goodEle->gammaIso -
                                (info->rhoIso)*getEffAreaEl(goodEle->scEta), 0.);
                    sigieie   = goodEle->sieie;
                    hovere    = goodEle->hovere;
                    eoverp    = goodEle->eoverp;
                    fbrem     = goodEle->fbrem;
                    dphi      = goodEle->dPhiIn;
                    deta      = goodEle->dEtaIn;
                    ecalE     = goodEle->ecalEnergy;
                    d0        = goodEle->d0;
                    dz        = goodEle->dz;
                    isConv    = goodEle->isConv;
                    nexphits  = goodEle->nMissingHits;
                    typeBits  = goodEle->typeBits;

                    outTree->Fill();
                    delete genV;
                    delete genLep;
                    genV=0, genLep=0, lep=0, sc=0;
                }
            }
            delete infile;
            infile=0, eventTree=0;

            cout << nsel  << " +/- " << sqrt(nselvar);
            if(isam!=0) cout << " per 1/pb";
            cout << endl;
        }
        outFile->Write();
        outFile->Close();
    }
    delete h_rw;
    delete h_rw_up;
    delete h_rw_down;
    delete f_rw;
    delete info;
    delete gen;
    delete genPartArr;
    delete electronArr;
    delete vertexArr;

    //--------------------------------------------------------------------------------------------------------------
    // Output
    //==============================================================================================================

    cout << "*" << endl;
    cout << "* SUMMARY" << endl;
    cout << "*--------------------------------------------------" << endl;
    cout << " W -> e nu" << 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("selectWe");
}
Exemple #23
0
// Main macro function
//--------------------------------------------------------------------------------------------------
void SkimNtuples(const TString input = "skim.input") 
{
  gBenchmark->Start("SkimNtuples");
  
  TString outfilename;          // output of skimming 
  vector<TString> infilenames;  // list input ntuple files to be skimmed
  TString sample;
  
  // 
  // parse input file
  //  
  ifstream ifs;
  ifs.open(input.Data()); 
  assert(ifs.is_open());
  string line;
  // First line should be DATA or SIGNALMC or BGMC
  getline(ifs,line); 
  sample = line;
  // Second line is the OUTPUT skim file name
  getline(ifs,line); 
  outfilename = line;
  // All subsequent lines are names of INPUT root files
  while(getline(ifs,line)) { infilenames.push_back(line); }
  ifs.close();
  
  bool isGenPresent = true;
  if( sample == "DATA" || sample == "BGMC")
    isGenPresent = false;
  else if( sample == "SIGNALMC" )
    isGenPresent = true;
  else{
    printf("Unknown sample type: use DATA or SIGNALMC or BGMC only in the input configuration file.\n");
    return;
  }
  if( isGenPresent)
    printf("Generator block will be written: signal MC indicated in config file\n");

  TTree::SetMaxTreeSize(kMaxLong64);
  
  // Don't write TObject part of the objects
  mithep::TEventInfo::Class()->IgnoreTObjectStreamer();
  mithep::TGenInfo::Class()->IgnoreTObjectStreamer();
  mithep::TElectron::Class()->IgnoreTObjectStreamer();
  mithep::TDielectron::Class()->IgnoreTObjectStreamer();
  mithep::TMuon::Class()->IgnoreTObjectStreamer();
  mithep::TJet::Class()->IgnoreTObjectStreamer();
  mithep::TPhoton::Class()->IgnoreTObjectStreamer();
  mithep::TVertex::Class()->IgnoreTObjectStreamer();
  
  // 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 *dielectronArr = new TClonesArray("mithep::TDielectron");
  TClonesArray *muonArr       = new TClonesArray("mithep::TMuon");
  TClonesArray *pfJetArr      = new TClonesArray("mithep::TJet");
  TClonesArray *photonArr     = new TClonesArray("mithep::TPhoton");
  TClonesArray *pvArr         = new TClonesArray("mithep::TVertex");
  
  UInt_t nInputEvts = 0;
  UInt_t nPassEvts  = 0;
  
  TFile* outfile = new TFile(outfilename, "RECREATE");
  
  //
  // Initialize data trees and structs
  // 
  TTree *outEventTree = new TTree("Events","Events"); 
  outEventTree->Branch("Info",       &info);
  if( isGenPresent )
    outEventTree->Branch("Gen",       &gen);
  outEventTree->Branch("Electron",   &electronArr);
  outEventTree->Branch("Dielectron", &dielectronArr);
  outEventTree->Branch("Muon",       &muonArr);
  outEventTree->Branch("PFJet",      &pfJetArr);
  outEventTree->Branch("Photon",     &photonArr);
  outEventTree->Branch("PV",         &pvArr);

  for(UInt_t ifile=0; ifile<infilenames.size(); ifile++) {
    cout << "Skimming " << infilenames[ifile] << "..." << endl;
    TFile *infile = new TFile(infilenames[ifile]);
    assert(infile);
    
    TTree *eventTree = (TTree*)infile->Get("Events");
    assert(eventTree);
    
    // Set branch address to structures that will store the info  
    eventTree->SetBranchAddress("Info",       &info);          TBranch *infoBr       = eventTree->GetBranch("Info");
    TBranch *genBr = 0;
    if(isGenPresent){
      eventTree->SetBranchAddress("Gen" ,       &gen);
      genBr        = eventTree->GetBranch("Gen");
      if( !genBr ){
	printf("MC info is not found in signal MC file\n");
	assert(0);
      }
    }
    eventTree->SetBranchAddress("Electron",   &electronArr);   TBranch *electronBr   = eventTree->GetBranch("Electron");
    eventTree->SetBranchAddress("Dielectron", &dielectronArr); TBranch *dielectronBr = eventTree->GetBranch("Dielectron");
    eventTree->SetBranchAddress("Muon",       &muonArr);       TBranch *muonBr       = eventTree->GetBranch("Muon");
    eventTree->SetBranchAddress("PFJet",      &pfJetArr);      TBranch *pfJetBr      = eventTree->GetBranch("PFJet");
    eventTree->SetBranchAddress("Photon",     &photonArr);     TBranch *photonBr     = eventTree->GetBranch("Photon");
    eventTree->SetBranchAddress("PV",         &pvArr);         TBranch *pvBr         = eventTree->GetBranch("PV");
    
     for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) { 
//      for(UInt_t ientry=0; ientry< 100000; ientry++) { // For testing
      infoBr->GetEntry(ientry);
      if( isGenPresent)
	genBr->GetEntry(ientry);

      electronArr->Clear();   
      dielectronArr->Clear(); 
      muonArr->Clear();       
      pfJetArr->Clear();      
      photonArr->Clear();     
      pvArr->Clear();         
      
      nInputEvts++;
            
      Bool_t keep = kFALSE;

      dielectronBr->GetEntry(ientry);

      // Require at least one dielectron
      if(dielectronArr->GetEntriesFast() > 0) {
	// Apply cuts on the dielectron
	int nDielectronsPass = 0;
	for(Int_t i=0; i<dielectronArr->GetEntriesFast(); i++) {
	  mithep::TDielectron *dielectron = (mithep::TDielectron*)((*dielectronArr)[i]);
	  // Require at least one dielectron above 19 GeV and the other above 9 GeV
	  bool etCut = false;
	  if( (dielectron->scEt_1 > 19 && dielectron->scEt_2 > 9) ||
	      (dielectron->scEt_1 > 9 && dielectron->scEt_2 > 19) )
	    etCut = true;
	  // Require at least one dielectron to pass full ID
	  bool idCut = false;
// 	  if( passSmurf(extractElectron(dielectron,1)) ||
// 	      passSmurf(extractElectron(dielectron,2)) )
	  if( DYTools::energy8TeV == 1 ){
	    if( passEGMID2012( DYTools::extractElectron(dielectron,1), WP_MEDIUM, info->rhoLowEta)
		|| passEGMID2012(DYTools::extractElectron(dielectron,2), WP_MEDIUM, info->rhoLowEta) )
	      idCut = true;
	  }else{
	    if( passEGMID2011( DYTools::extractElectron(dielectron,1), WP_MEDIUM, info->rhoLowEta)
		|| passEGMID2011(DYTools::extractElectron(dielectron,2), WP_MEDIUM, info->rhoLowEta) )
	      idCut = true;
	  }
	  if( etCut && idCut )
	    nDielectronsPass++;
	}
	if(nDielectronsPass > 0)
	  keep = kTRUE;
      }
      
      if(keep) {
	// Some of the objects are dropped for skimmed events
// 	electronBr->GetEntry(ientry);
// 	muonBr->GetEntry(ientry);
// 	pfJetBr->GetEntry(ientry);
// 	photonBr->GetEntry(ientry);
// Fill only those branches that we want to write out
	pvBr->GetEntry(ientry);
        nPassEvts++;
      }else{
// Clear branches which we filled to make the pass/fail check,
// but do not want to write out for failed events
	dielectronArr->Clear();
      }

      outEventTree->Fill();

    }
  }
  
  outfile->Write();
  outfile->Close();
  
  delete info;
  delete electronArr;
  delete dielectronArr;
  delete muonArr;
  delete pfJetArr;
  delete photonArr;
  delete pvArr;
    
  std::cout << outfilename << " created!" << std::endl;
  std::cout << " >>> Events processed: " << nInputEvts << std::endl;
  std::cout << " >>>   Events passing: " << nPassEvts << std::endl;
  
  gBenchmark->Show("SkimNtuples");
}  
Exemple #24
0
//  -------------------------------------------------------------------------
//
//   ----- General Macro for R3B CALIFA Data Display
//         Author: Hector Alvarez <*****@*****.**>
//         Last Update: 26/09/14
//         Comments:
//         THAT IS A TEMPLATE FOR OTHER DISPLAY/ANALYSIS MACRO. COPY AND USE.
//         CAN DISPLAY RAWHITs OR CRYSTALHITs 
//	
//  -------------------------------------------------------------------------
//
//   Usage: 
//      > root -l 
//      ROOT> .L plot.C
//      ROOT> plot("inputFile")
//     
//     where inputFile is the input file :) 
//     Define histograms and fill them in the loop!
//  -------------------------------------------------------------------------
void plot(TString inputFile="") {

  gROOT->SetStyle("Default");
  //gStyle->SetOptTitle(0);
  gStyle->SetOptStat(0);
  gStyle->SetOptFit(0);
  
  TFile *file1 = TFile::Open(inputFile);
  
  //HISTOGRAMS DEFINITION
  TH1F* hEnergy = new TH1F("hEnergy","Energy",1000,0,2000);
  TH2F* hEnergyvsID = new TH2F("hEnergyvsID","EnergyvsID",500,0,2500,128,0,127);
  TH2F* hTimevsID = new TH2F("hTimevsID","TimevsID",500,1450000000000,1460000000000,128,0,127);
  TH2F* hEnergyvsTime = new TH2F("hEnergyvsTime","EnergyvsTime",500,0,2500,500,1450000000000,1650000000000);



  TTree* caloTree = (TTree*)file1->Get("cbmsim");
 
  //Raw Hits (input)
  TClonesArray* rawHitCA;  
  R3BCaloRawHit** rawHit;
  rawHitCA = new TClonesArray("R3BCaloRawHit",5);
  TBranch *branchRawHit = caloTree->GetBranch("CaloRawHit");
  if(branchRawHit) branchRawHit->SetAddress(&rawHitCA);
  
  //Crystal Hits
  TClonesArray* crystalHitCA;  
  R3BCaloCrystalHit** crystalHit;
  crystalHitCA = new TClonesArray("R3BCaloCrystalHit",5);
  TBranch *branchCrystalHit = caloTree->GetBranch("CaloCrystalHit");
  if(branchCrystalHit) branchCrystalHit->SetAddress(&crystalHitCA);
  
  Long64_t nevents = caloTree->GetEntries();
  Int_t rawHitsPerEvent =0;
  Int_t crystalHitsPerEvent =0;
  
  for(Int_t i=0;i<nevents;i++){
    if(i%100000 == 0) printf("Event:%i\n",i);
    
    rawHitCA->Clear();
    crystalHitCA->Clear();

    caloTree->GetEvent(i);
    rawHitsPerEvent = rawHitCA->GetEntries(); 
    crystalHitsPerEvent = crystalHitCA->GetEntries(); 
    
    if(rawHitsPerEvent>0) {
      rawHit = new R3BCaloRawHit*[rawHitsPerEvent];
      for(Int_t j=0;j<rawHitsPerEvent;j++){
	//rawHit[j] = new R3BCaloRawHit;
	rawHit[j] = (R3BCaloRawHit*) rawHitCA->At(j);      
      }
    }
    if(crystalHitsPerEvent>0) {
      crystalHit = new R3BCaloCrystalHit*[crystalHitsPerEvent];
      for(Int_t j=0;j<crystalHitsPerEvent;j++){
	//crystalHit[j] = new R3BCaloCrystalHit;
	crystalHit[j] = (R3BCaloCrystalHit*) crystalHitCA->At(j);      
      }
    }
    
    //filling info
    if(rawHitsPerEvent>0) {
      for(Int_t h=0;h<rawHitsPerEvent;h++){
	hEnergy->Fill(rawHit[h]->GetEnergy());
	hEnergyvsID->Fill(rawHit[h]->GetEnergy(),rawHit[h]->GetCrystalId());
	hTimevsID->Fill(rawHit[h]->GetTime(),rawHit[h]->GetCrystalId());
	hEnergyvsTime->Fill(rawHit[h]->GetEnergy(),rawHit[h]->GetTime());
      }
    }    
    if(crystalHitsPerEvent>0) {
      for(Int_t h=0;h<crystalHitsPerEvent;h++){
	hEnergy->Fill(crystalHit[h]->GetEnergy());
      }
    }  

    
    if(rawHitsPerEvent) delete [] rawHit;
    if(crystalHitsPerEvent) delete [] crystalHit;
    
  }
  
  TCanvas* c1 = new TCanvas("Info","Info",0,0,780,1200);
	c1->SetFillColor(0);
	c1->SetFrameFillColor(0);
	c1->Divide(2,2);
	//MC TRACK CANVAS
	c1->cd(1);
	hEnergy->Draw();
	c1->cd(2);
	hEnergyvsID->Draw("COLZ");
	c1->cd(3);
	hEnergyvsTime->Draw("COLZ");
	c1->cd(4);
	hTimevsID->Draw("COLZ");
}
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");
}
void computeAccSelZmmBinned_PileupSys(const TString conf,      // input file
			    const TString inputDir,
                            const TString outputDir,  // output directory
			    const Int_t   doPU,
			    const TString PUtype
) {
  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.4;
  const Double_t MUON_MASS  = 0.105658369;

  const Int_t BOSON_ID  = 23;
  const Int_t LEPTON_ID = 13;
  
  // efficiency files
  const TString dataHLTEffName_pos = inputDir + "MuHLTEff/MGpositive/eff.root";
  const TString dataHLTEffName_neg = inputDir + "MuHLTEff/MGnegative/eff.root";
  const TString zmmHLTEffName_pos  = inputDir + "MuHLTEff/CTpositive/eff.root";
  const TString zmmHLTEffName_neg  = inputDir + "MuHLTEff/CTnegative/eff.root";

  const TString dataSelEffName_pos = inputDir + "MuSITEff/MGpositive_FineBin/eff.root";
  const TString dataSelEffName_neg = inputDir + "MuSITEff/MGnegative_FineBin/eff.root";
  const TString zmmSelEffName_pos  = inputDir + "MuSITEff/CTpositive/eff.root";
  const TString zmmSelEffName_neg  = inputDir + "MuSITEff/CTnegative/eff.root";

  const TString dataTrkEffName_pos = inputDir + "MuSITEff/MGpositive_FineBin/eff.root";
  const TString dataTrkEffName_neg = inputDir + "MuSITEff/MGnegative_FineBin/eff.root";
  const TString zmmTrkEffName_pos  = inputDir + "MuSITEff/CTpositive/eff.root";
  const TString zmmTrkEffName_neg  = inputDir + "MuSITEff/CTnegative/eff.root";

  const TString dataStaEffName_pos = inputDir + "MuStaEff/MGpositive/eff.root";
  const TString dataStaEffName_neg = inputDir + "MuStaEff/MGnegative/eff.root";
  const TString zmmStaEffName_pos  = inputDir + "MuStaEff/CTpositive/eff.root";
  const TString zmmStaEffName_neg  = inputDir + "MuStaEff/CTnegative/eff.root";
  
  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/puWeights_76x.root", "read");
  TH1D *h_rw = (TH1D*) f_rw->Get(PUtype.Data());
 
  //--------------------------------------------------------------------------------------------------------------
  // 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 *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"));

  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 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"));

  h =(TH2D*)dataSelEffFile_pos->Get("hEffEtaPt");
  TH2D *hSelErr_pos = new TH2D("hSelErr_pos", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  TH2D *hSelErr_neg = new TH2D("hSelErr_neg", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());

  //
  // 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"));

  h =(TH2D*)dataStaEffFile_pos->Get("hEffEtaPt");
  TH2D *hStaErr_pos = new TH2D("hStaErr_pos", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  TH2D *hStaErr_neg = new TH2D("hStaErr_neg", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());

  //
  // 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"));

  h =(TH2D*)dataTrkEffFile_pos->Get("hEffEtaPt");
  TH2D *hTrkErr_pos = new TH2D("hTrkErr_pos", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());
  TH2D *hTrkErr_neg = new TH2D("hTrkErr_neg", "",h->GetNbinsX(),h->GetXaxis()->GetXmin(),h->GetXaxis()->GetXmax(),
			       h->GetNbinsY(),h->GetYaxis()->GetXmin(),h->GetYaxis()->GetXmax());

  // Data structures to store info from TTrees
  baconhep::TEventInfo *info   = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr     = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *muonArr        = new TClonesArray("baconhep::TMuon");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::TVertex");
  
  TFile *infile=0;
  TTree *eventTree=0;
   
  // Variables to store acceptances and uncertainties (per input file)
  vector<Double_t> nEvtsv, nSelv;
  vector<Double_t> nSelCorrv, nSelCorrVarv;
  vector<Double_t> accv, accCorrv;
  vector<Double_t> accErrv, accErrCorrv;

  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");
  
  //
  // 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 = TFile::Open(fnamev[ifile]); 
    assert(infile);
  
    eventTree = (TTree*)infile->Get("Events"); assert(eventTree);  
    eventTree->SetBranchAddress("Info",             &info); TBranch *infoBr = eventTree->GetBranch("Info");
    eventTree->SetBranchAddress("GenEvtInfo",        &gen); TBranch *genBr  = eventTree->GetBranch("GenEvtInfo");
    eventTree->SetBranchAddress("GenParticle",&genPartArr); TBranch* genPartBr = eventTree->GetBranch("GenParticle");
    eventTree->SetBranchAddress("Muon",          &muonArr); TBranch *muonBr = eventTree->GetBranch("Muon");   
    eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");

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

    //
    // loop over events
    //      
    for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
      genBr->GetEntry(ientry);
      genPartArr->Clear(); genPartBr->GetEntry(ientry);
      infoBr->GetEntry(ientry);

      Int_t glepq1=-99;
      Int_t glepq2=-99;

      if (fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
      TLorentzVector *vec=new TLorentzVector(0,0,0,0);
      TLorentzVector *lep1=new TLorentzVector(0,0,0,0);
      TLorentzVector *lep2=new TLorentzVector(0,0,0,0);
      toolbox::fillGen(genPartArr, BOSON_ID, vec, lep1, lep2,&glepq1,&glepq2,1);
      if(vec->M()<MASS_LOW || vec->M()>MASS_HIGH) continue;
      delete vec; delete lep1; delete lep2;

      vertexArr->Clear();
      vertexBr->GetEntry(ientry);
      double npv  = vertexArr->GetEntries();
      Double_t weight=gen->weight;
      if(doPU>0) weight*=h_rw->GetBinContent(h_rw->FindBin(info->nPUmean));

      nEvtsv[ifile]+=weight;
      
      // trigger requirement               
      if (!isMuonTrigger(triggerMenu, info->triggerBits)) continue;

      // good vertex requirement
      if(!(info->hasGoodPV)) continue;
    
      muonArr->Clear();
      muonBr->GetEntry(ientry);

      for(Int_t i1=0; i1<muonArr->GetEntriesFast(); i1++) {
  	const baconhep::TMuon *mu1 = (baconhep::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
	
	TLorentzVector vMu1(0,0,0,0);
	vMu1.SetPtEtaPhiM(mu1->pt, mu1->eta, mu1->phi, MUON_MASS);

        for(Int_t i2=i1+1; i2<muonArr->GetEntriesFast(); i2++) {
          const baconhep::TMuon *mu2 = (baconhep::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

          TLorentzVector vMu2(0,0,0,0);
	  vMu2.SetPtEtaPhiM(mu2->pt, mu2->eta, mu2->phi, MUON_MASS);  

          // trigger match
	  if(!isMuonTriggerObj(triggerMenu, mu1->hltMatchBits, kFALSE) && !isMuonTriggerObj(triggerMenu, mu2->hltMatchBits, kFALSE)) continue;
	  
	  // mass window
          TLorentzVector 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(mu1->eta, mu1->pt); 
            effmc   *= zmmStaEff_pos.getEff(mu1->eta, mu1->pt); 
          } else {
            effdata *= dataStaEff_neg.getEff(mu1->eta, mu1->pt); 
            effmc   *= zmmStaEff_neg.getEff(mu1->eta, mu1->pt); 
          }
          if(mu2->q>0) {
            effdata *= dataStaEff_pos.getEff(mu2->eta, mu2->pt); 
            effmc   *= zmmStaEff_pos.getEff(mu2->eta, mu2->pt);
          } else {
            effdata *= dataStaEff_neg.getEff(mu2->eta, mu2->pt); 
            effmc   *= zmmStaEff_neg.getEff(mu2->eta, mu2->pt);
          }
          corr *= effdata/effmc;
    
          effdata=1; effmc=1;
          if(mu1->q>0) { 
            effdata *= dataTrkEff_pos.getEff(mu1->eta, mu1->pt); 
            effmc   *= zmmTrkEff_pos.getEff(mu1->eta, mu1->pt); 
          } else {
            effdata *= dataTrkEff_neg.getEff(mu1->eta, mu1->pt); 
            effmc   *= zmmTrkEff_neg.getEff(mu1->eta, mu1->pt); 
          }
          if(mu2->q>0) {
            effdata *= dataTrkEff_pos.getEff(mu2->eta, mu2->pt); 
            effmc   *= zmmTrkEff_pos.getEff(mu2->eta, mu2->pt);
          } else {
            effdata *= dataTrkEff_neg.getEff(mu2->eta, mu2->pt); 
            effmc   *= zmmTrkEff_neg.getEff(mu2->eta, mu2->pt);
          }
          //corr *= effdata/effmc;
	  
	  // scale factor uncertainties                                                                                                                                         
	  // TRACKER
          if(mu1->q>0) {
            Double_t effdata = dataTrkEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataTrkEff_pos.getErrLow(mu1->eta, mu1->pt), dataTrkEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmTrkEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmTrkEff_pos.getErrLow(mu1->eta, mu1->pt), zmmTrkEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t errTrk = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hTrkErr_pos->Fill(mu1->eta, mu1->pt, errTrk);
          } else {
            Double_t effdata = dataTrkEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataTrkEff_neg.getErrLow(mu1->eta, mu1->pt), dataTrkEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmTrkEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmTrkEff_neg.getErrLow(mu1->eta, mu1->pt), zmmTrkEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t errTrk = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hTrkErr_neg->Fill(mu1->eta, mu1->pt, errTrk);
          }

          if(mu2->q>0) {
            Double_t effdata = dataTrkEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataTrkEff_pos.getErrLow(mu2->eta, mu2->pt), dataTrkEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmTrkEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmTrkEff_pos.getErrLow(mu2->eta, mu2->pt), zmmTrkEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t errTrk = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    /*   if(mu2->eta>1.2 && mu2->eta<2.1) 
	      {
		errTrk=0.0013;
		}*/
            hTrkErr_pos->Fill(mu2->eta, mu2->pt, errTrk);
          } else {
            Double_t effdata = dataTrkEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataTrkEff_neg.getErrLow(mu2->eta, mu2->pt), dataTrkEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmTrkEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmTrkEff_neg.getErrLow(mu2->eta, mu2->pt), zmmTrkEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t errTrk = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
	    /*  if(mu2->eta>1.2 && mu2->eta<2.1) 
	      {
		errTrk=0.0013;
	      }
	      hTrkErr_neg->Fill(mu2->eta, mu2->pt, errTrk);*/
          }
	  // STANDALONE
          if(mu1->q>0) {
            Double_t effdata = dataStaEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataStaEff_pos.getErrLow(mu1->eta, mu1->pt), dataStaEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmStaEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmStaEff_pos.getErrLow(mu1->eta, mu1->pt), zmmStaEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t errSta = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hStaErr_pos->Fill(mu1->eta, mu1->pt, errSta);
          } else {
            Double_t effdata = dataStaEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataStaEff_neg.getErrLow(mu1->eta, mu1->pt), dataStaEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmStaEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmStaEff_neg.getErrLow(mu1->eta, mu1->pt), zmmStaEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t errSta = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hStaErr_neg->Fill(mu1->eta, mu1->pt, errSta);
          }

          if(mu2->q>0) {
            Double_t effdata = dataStaEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataStaEff_pos.getErrLow(mu2->eta, mu2->pt), dataStaEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmStaEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmStaEff_pos.getErrLow(mu2->eta, mu2->pt), zmmStaEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t errSta = ((effdata/effmc))*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hStaErr_pos->Fill(mu2->eta, mu2->pt, errSta);
          } else {
            Double_t effdata = dataStaEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataStaEff_neg.getErrLow(mu2->eta, mu2->pt), dataStaEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmStaEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmStaEff_neg.getErrLow(mu2->eta, mu2->pt), zmmStaEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t errSta = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hStaErr_neg->Fill(mu2->eta, mu2->pt, errSta);
	  }

	  // SELECTION
          if(mu1->q>0) {
            Double_t effdata = dataSelEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataSelEff_pos.getErrLow(mu1->eta, mu1->pt), dataSelEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmSelEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmSelEff_pos.getErrLow(mu1->eta, mu1->pt), zmmSelEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t errSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hSelErr_pos->Fill(mu1->eta, mu1->pt, errSel);
          } else {
            Double_t effdata = dataSelEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataSelEff_neg.getErrLow(mu1->eta, mu1->pt), dataSelEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmSelEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmSelEff_neg.getErrLow(mu1->eta, mu1->pt), zmmSelEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t errSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hSelErr_neg->Fill(mu1->eta, mu1->pt, errSel);
          }

          if(mu2->q>0) {
            Double_t effdata = dataSelEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataSelEff_pos.getErrLow(mu2->eta, mu2->pt), dataSelEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmSelEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmSelEff_pos.getErrLow(mu2->eta, mu2->pt), zmmSelEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t errSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hSelErr_pos->Fill(mu2->eta, mu2->pt, errSel);
          } else {
            Double_t effdata = dataSelEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataSelEff_neg.getErrLow(mu2->eta, mu2->pt), dataSelEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmSelEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmSelEff_neg.getErrLow(mu2->eta, mu2->pt), zmmSelEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t errSel = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hSelErr_neg->Fill(mu2->eta, mu2->pt, errSel);
	  }

	  //HLT
          if(mu1->q>0) {
            Double_t effdata = dataHLTEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataHLTEff_pos.getErrLow(mu1->eta, mu1->pt), dataHLTEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmHLTEff_pos.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmHLTEff_pos.getErrLow(mu1->eta, mu1->pt), zmmHLTEff_pos.getErrHigh(mu1->eta, mu1->pt));
            Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hHLTErr_pos->Fill(mu1->eta, mu1->pt, errHLT);
          } else {
            Double_t effdata = dataHLTEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errdata = TMath::Max(dataHLTEff_neg.getErrLow(mu1->eta, mu1->pt), dataHLTEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t effmc   = zmmHLTEff_neg.getEff(mu1->eta, mu1->pt);
            Double_t errmc   = TMath::Max(zmmHLTEff_neg.getErrLow(mu1->eta, mu1->pt), zmmHLTEff_neg.getErrHigh(mu1->eta, mu1->pt));
            Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hHLTErr_neg->Fill(mu1->eta, mu1->pt, errHLT);
          }

          if(mu2->q>0) {
            Double_t effdata = dataHLTEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataHLTEff_pos.getErrLow(mu2->eta, mu2->pt), dataHLTEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmHLTEff_pos.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmHLTEff_pos.getErrLow(mu2->eta, mu2->pt), zmmHLTEff_pos.getErrHigh(mu2->eta, mu2->pt));
            Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hHLTErr_pos->Fill(mu2->eta, mu2->pt, errHLT);
          } else {
            Double_t effdata = dataHLTEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errdata = TMath::Max(dataHLTEff_neg.getErrLow(mu2->eta, mu2->pt), dataHLTEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t effmc   = zmmHLTEff_neg.getEff(mu2->eta, mu2->pt);
            Double_t errmc   = TMath::Max(zmmHLTEff_neg.getErrLow(mu2->eta, mu2->pt), zmmHLTEff_neg.getErrHigh(mu2->eta, mu2->pt));
            Double_t errHLT = (effdata/effmc)*sqrt(errdata*errdata/effdata/effdata + errmc*errmc/effmc/effmc);
            hHLTErr_neg->Fill(mu2->eta, mu2->pt, errHLT);
          }
	  
	  nSelv[ifile]    +=weight;
	  nSelCorrv[ifile]+=weight*corr;
	  nSelCorrVarv[ifile]+=weight*weight*corr*corr;
        }
      }      
    }

    Double_t var=0;
    for(Int_t iy=0; iy<=hHLTErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr_pos->GetNbinsX(); ix++) {
        Double_t err=hHLTErr_pos->GetBinContent(ix,iy);
        var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hHLTErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hHLTErr_neg->GetNbinsX(); ix++) {
        Double_t err=hHLTErr_neg->GetBinContent(ix,iy);
        var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hSelErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hSelErr_pos->GetNbinsX(); ix++) {
        Double_t err=hSelErr_pos->GetBinContent(ix,iy);
        var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hSelErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hSelErr_neg->GetNbinsX(); ix++) {
        Double_t err=hSelErr_neg->GetBinContent(ix,iy);
        var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hTrkErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hTrkErr_pos->GetNbinsX(); ix++) {
        Double_t err=hTrkErr_pos->GetBinContent(ix,iy);
        //var+=err*err;
	var+=0.0;
      }
    }
    for(Int_t iy=0; iy<=hTrkErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hTrkErr_neg->GetNbinsX(); ix++) {
        Double_t err=hTrkErr_neg->GetBinContent(ix,iy);
	var+=0.0;
        //var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hStaErr_pos->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hStaErr_pos->GetNbinsX(); ix++) {
        Double_t err=hStaErr_pos->GetBinContent(ix,iy);
	var+=err*err;
      }
    }
    for(Int_t iy=0; iy<=hStaErr_neg->GetNbinsY(); iy++) {
      for(Int_t ix=0; ix<=hStaErr_neg->GetNbinsX(); ix++) {
        Double_t err=hStaErr_neg->GetBinContent(ix,iy);
	var+=err*err;
      }
    }

    nSelCorrVarv[ifile]+=var;

    // 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]); accErrCorrv.push_back(accCorrv[ifile]*sqrt((nSelCorrVarv[ifile])/(nSelCorrv[ifile]*nSelCorrv[ifile]) + 1./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] << " +/- " << accErrCorrv[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] << " +/- " << accErrCorrv[ifile] << endl;
    txtfile << endl;
  }
  txtfile.close();
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("computeAccSelZmmBinned"); 
}
Exemple #27
0
// Main macro function
//--------------------------------------------------------------------------------------------------
void SkimNtuples(const TString input = "skim.input") 
{
  gBenchmark->Start("SkimNtuples");
  
  TString outfilename;          // output of skimming 
  vector<TString> infilenames;  // list input ntuple files to be skimmed
  
  // 
  // parse input file
  //  
  ifstream ifs;
  ifs.open(input.Data()); 
  assert(ifs.is_open());
  string line;
  getline(ifs,line); 
  outfilename = line;
  while(getline(ifs,line)) { infilenames.push_back(line); }
  ifs.close();

  TTree::SetMaxTreeSize(kMaxLong64);
  
  // Don't write TObject part of the objects
  mithep::TEventInfo::Class()->IgnoreTObjectStreamer();
  mithep::TElectron::Class()->IgnoreTObjectStreamer();
  mithep::TDielectron::Class()->IgnoreTObjectStreamer();
  mithep::TMuon::Class()->IgnoreTObjectStreamer();
  mithep::TJet::Class()->IgnoreTObjectStreamer();
  mithep::TPhoton::Class()->IgnoreTObjectStreamer();
  mithep::TVertex::Class()->IgnoreTObjectStreamer();
  
  // Data structures to store info from TTrees
  mithep::TEventInfo *info    = new mithep::TEventInfo();
  TClonesArray *electronArr   = new TClonesArray("mithep::TElectron");
  TClonesArray *dielectronArr = new TClonesArray("mithep::TDielectron");
  TClonesArray *muonArr       = new TClonesArray("mithep::TMuon");
  TClonesArray *pfJetArr      = new TClonesArray("mithep::TJet");
  TClonesArray *photonArr     = new TClonesArray("mithep::TPhoton");
  TClonesArray *pvArr         = new TClonesArray("mithep::TVertex");
  
  UInt_t nInputEvts = 0;
  UInt_t nPassEvts  = 0;
  
  TFile* outfile = new TFile(outfilename, "RECREATE");
  
  //
  // Initialize data trees and structs
  // 
  TTree *outEventTree = new TTree("Events","Events"); 
  outEventTree->Branch("Info",       &info);
  outEventTree->Branch("Electron",   &electronArr);
  outEventTree->Branch("Dielectron", &dielectronArr);
  outEventTree->Branch("Muon",       &muonArr);
  outEventTree->Branch("PFJet",      &pfJetArr);
  outEventTree->Branch("Photon",     &photonArr);
  outEventTree->Branch("PV",         &pvArr);

  for(UInt_t ifile=0; ifile<infilenames.size(); ifile++) {
    cout << "Skimming " << infilenames[ifile] << "..." << endl;
    TFile *infile = new TFile(infilenames[ifile]);
    assert(infile);
    
    TTree *eventTree = (TTree*)infile->Get("Events");
    assert(eventTree);
    
    // Set branch address to structures that will store the info  
    eventTree->SetBranchAddress("Info",       &info);          TBranch *infoBr       = eventTree->GetBranch("Info");
    eventTree->SetBranchAddress("Electron",   &electronArr);   TBranch *electronBr   = eventTree->GetBranch("Electron");
    eventTree->SetBranchAddress("Dielectron", &dielectronArr); TBranch *dielectronBr = eventTree->GetBranch("Dielectron");
    eventTree->SetBranchAddress("Muon",       &muonArr);       TBranch *muonBr       = eventTree->GetBranch("Muon");
    eventTree->SetBranchAddress("PFJet",      &pfJetArr);      TBranch *pfJetBr      = eventTree->GetBranch("PFJet");
    eventTree->SetBranchAddress("Photon",     &photonArr);     TBranch *photonBr     = eventTree->GetBranch("Photon");
    eventTree->SetBranchAddress("PV",         &pvArr);         TBranch *pvBr         = eventTree->GetBranch("PV");
    
    for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) { 
      infoBr->GetEntry(ientry);

      electronArr->Clear();   electronBr->GetEntry(ientry);
      dielectronArr->Clear(); dielectronBr->GetEntry(ientry);
      muonArr->Clear();       muonBr->GetEntry(ientry);
      pfJetArr->Clear();      pfJetBr->GetEntry(ientry);
      photonArr->Clear();     photonBr->GetEntry(ientry);
      pvArr->Clear();         pvBr->GetEntry(ientry);
      
      nInputEvts++;
            
      Bool_t keep = kFALSE;

      if(dielectronArr->GetEntriesFast() > 0)
        keep = kTRUE;
  
      if(keep) {
        outEventTree->Fill();
        nPassEvts++;
      }
    }
  }
  
  outfile->Write();
  outfile->Close();
  
  delete info;
  delete electronArr;
  delete dielectronArr;
  delete muonArr;
  delete pfJetArr;
  delete photonArr;
  delete pvArr;
    
  std::cout << outfilename << " created!" << std::endl;
  std::cout << " >>> Events processed: " << nInputEvts << std::endl;
  std::cout << " >>>   Events passing: " << nPassEvts << std::endl;
  
  gBenchmark->Show("SkimNtuples");
}  
Exemple #28
0
void selectAntiWm(const TString conf="wm.conf", // input file
              const TString outputDir="."       // output directory
) {
  gBenchmark->Start("selectAntiWm");

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

  const Double_t PT_CUT    = 25;
  const Double_t ETA_CUT   = 2.4;
  const Double_t MUON_MASS = 0.105658369;

  const Double_t VETO_PT   = 10;
  const Double_t VETO_ETA  = 2.4;

  const Int_t BOSON_ID  = 24;
  const Int_t LEPTON_ID = 13;

  // load trigger menu
  const baconhep::TTrigger triggerMenu("../../BaconAna/DataFormats/data/HLT_50nsGRun");

  // load pileup reweighting file
  TFile *f_rw = TFile::Open("../Tools/pileup_weights_2015B.root", "read");
  TH1D *h_rw = (TH1D*) f_rw->Get("npv_rw");

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

  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  npv, npu;
  UInt_t  id_1, id_2;
  Double_t x_1, x_2, xPDF_1, xPDF_2;
  Double_t scalePDF, weightPDF;
  TLorentzVector *genV=0, *genLep=0;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genLepPt, genLepPhi;
  Float_t scale1fb, puWeight;
  Float_t met, metPhi, sumEt, mt, u1, u2;
  Float_t tkMet, tkMetPhi, tkSumEt, tkMt, tkU1, tkU2;
  Float_t mvaMet, mvaMetPhi, mvaSumEt, mvaMt, mvaU1, mvaU2;
  Int_t   q;
  TLorentzVector *lep=0;
  ///// muon specific /////
  Float_t trkIso, emIso, hadIso;
  Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
  Float_t d0, dz;
  Float_t muNchi2;
  UInt_t nPixHits, nTkLayers, nValidHits, nMatch, typeBits;
  
  // Data structures to store info from TTrees
  baconhep::TEventInfo *info  = new baconhep::TEventInfo();
  baconhep::TGenEventInfo *gen  = new baconhep::TGenEventInfo();
  TClonesArray *genPartArr = new TClonesArray("baconhep::TGenParticle");
  TClonesArray *muonArr    = new TClonesArray("baconhep::TMuon");
  TClonesArray *vertexArr  = new TClonesArray("baconhep::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
    Bool_t isData=kFALSE;
    if(isam==0 && !hasData) continue;
    else if (isam==0) isData=kTRUE;
    
    // Assume signal sample is given name "wm"
    Bool_t isSignal = (snamev[isam].CompareTo("wm",TString::kIgnoreCase)==0);
    // flag to reject W->mnu events when selecting wrong-flavor background events
    Bool_t isWrongFlavor = (snamev[isam].CompareTo("wx",TString::kIgnoreCase)==0);  
    
    CSample* samp = samplev[isam];
  
    //
    // Set up output ntuple
    //
    TString outfilename = ntupDir + TString("/") + snamev[isam] + TString("_select.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("npv",        &npv,        "npv/i");        // number of primary vertices
    outTree->Branch("npu",        &npu,        "npu/i");        // number of in-time PU events (MC)
    outTree->Branch("id_1",       &id_1,       "id_1/i");       // PDF info -- parton ID for parton 1
    outTree->Branch("id_2",       &id_2,       "id_2/i");       // PDF info -- parton ID for parton 2
    outTree->Branch("x_1",        &x_1,        "x_1/d");        // PDF info -- x for parton 1
    outTree->Branch("x_2",        &x_2,        "x_2/d");        // PDF info -- x for parton 2
    outTree->Branch("xPDF_1",     &xPDF_1,     "xPDF_1/d");     // PDF info -- x*F for parton 1
    outTree->Branch("xPDF_2",     &xPDF_2,     "xPDF_2/d");     // PDF info -- x*F for parton 2
    outTree->Branch("scalePDF",   &scalePDF,   "scalePDF/d");   // PDF info -- energy scale of parton interaction
    outTree->Branch("weightPDF",  &weightPDF,  "weightPDF/d");  // PDF info -- PDF weight
    outTree->Branch("genV",       "TLorentzVector", &genV);     // GEN boson 4-vector (signal MC)
    outTree->Branch("genLep",     "TLorentzVector", &genLep);   // GEN lepton 4-vector (signal 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("genLepPt",   &genLepPt,   "genLepPt/F");   // GEN lepton pT (signal MC)
    outTree->Branch("genLepPhi",  &genLepPhi,  "genLepPhi/F");  // GEN lepton phi (signal MC)
    outTree->Branch("scale1fb",   &scale1fb,   "scale1fb/F");   // event weight per 1/fb (MC)
    outTree->Branch("puWeight",   &puWeight,   "puWeight/F");    // scale factor for pileup reweighting (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("mt",         &mt,         "mt/F");         // transverse mass
    outTree->Branch("u1",         &u1,         "u1/F");         // parallel component of recoil
    outTree->Branch("u2",         &u2,         "u2/F");         // perpendicular component of recoil
    outTree->Branch("tkMet",      &tkMet,      "tkMet/F");      // MET (track MET)
    outTree->Branch("tkMetPhi",   &tkMetPhi,   "tkMetPhi/F");   // phi(MET) (track MET)
    outTree->Branch("tkSumEt",    &tkSumEt,    "tkSumEt/F");    // Sum ET (track MET)
    outTree->Branch("tkMt",       &tkMt,       "tkMt/F");       // transverse mass (track MET)
    outTree->Branch("tkU1",       &tkU1,       "tkU1/F");       // parallel component of recoil (track MET)
    outTree->Branch("tkU2",       &tkU2,       "tkU2/F");       // perpendicular component of recoil (track MET)
    outTree->Branch("mvaMet",     &mvaMet,     "mvaMet/F");     // MVA MET
    outTree->Branch("mvaMetPhi",  &mvaMetPhi,  "mvaMetPhi/F");  // phi(MVA MET)
    outTree->Branch("mvaSumEt",   &mvaSumEt,   "mvaSumEt/F");   // Sum ET (MVA MET)
    outTree->Branch("mvaMt",      &mvaMt,      "mvaMt/F");      // transverse mass (MVA MET)
    outTree->Branch("mvaU1",      &mvaU1,      "mvaU1/F");      // parallel component of recoil (mva MET)
    outTree->Branch("mvaU2",      &mvaU2,      "mvaU2/F");      // perpendicular component of recoil (mva MET)
    outTree->Branch("q",          &q,          "q/I");          // lepton charge
    outTree->Branch("lep",        "TLorentzVector", &lep);      // lepton 4-vector
    ///// muon specific /////
    outTree->Branch("trkIso",     &trkIso,     "trkIso/F");     // track isolation of lepton
    outTree->Branch("emIso",      &emIso,      "emIso/F");      // ECAL isolation of lepton
    outTree->Branch("hadIso",     &hadIso,     "hadIso/F");     // HCAL isolation of lepton
    outTree->Branch("pfChIso",    &pfChIso,    "pfChIso/F");    // PF charged hadron isolation of lepton
    outTree->Branch("pfGamIso",   &pfGamIso,   "pfGamIso/F");   // PF photon isolation of lepton
    outTree->Branch("pfNeuIso",   &pfNeuIso,   "pfNeuIso/F");   // PF neutral hadron isolation of lepton
    outTree->Branch("pfCombIso",  &pfCombIso,  "pfCombIso/F");  // PF combined isolation of lepton
    outTree->Branch("d0",         &d0,         "d0/F");         // transverse impact parameter of lepton
    outTree->Branch("dz",         &dz,         "dz/F");         // longitudinal impact parameter of lepton
    outTree->Branch("muNchi2",    &muNchi2,    "muNchi2/F");    // muon fit normalized chi^2 of lepton
    outTree->Branch("nPixHits",   &nPixHits,   "nPixHits/i");   // number of pixel hits of muon
    outTree->Branch("nTkLayers",  &nTkLayers,  "nTkLayers/i");  // number of tracker layers of muon
    outTree->Branch("nMatch",     &nMatch,     "nMatch/i");     // number of matched segments of muon	 
    outTree->Branch("nValidHits", &nValidHits, "nValidHits/i"); // number of valid muon hits of muon 
    outTree->Branch("typeBits",   &typeBits,   "typeBits/i");   // number of valid muon hits of muon 
    
    //
    // 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 = TFile::Open(samp->fnamev[ifile]); 
      assert(infile);
      
      Bool_t hasJSON = kFALSE;
      baconhep::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("Muon", &muonArr); TBranch *muonBr = eventTree->GetBranch("Muon");
      eventTree->SetBranchAddress("PV",   &vertexArr); TBranch *vertexBr = eventTree->GetBranch("PV");
      Bool_t hasGen = eventTree->GetBranchStatus("GenEvtInfo");
      TBranch *genBr=0, *genPartBr=0;
      if(hasGen) {
        eventTree->SetBranchAddress("GenEvtInfo", &gen); genBr = eventTree->GetBranch("GenEvtInfo");
        eventTree->SetBranchAddress("GenParticle",&genPartArr); genPartBr = eventTree->GetBranch("GenParticle");
      }
    
      // Compute MC event weight per 1/fb
      const Double_t xsec = samp->xsecv[ifile];
      Double_t totalWeight=0;

      if (hasGen) {
	TH1D *hall = new TH1D("hall", "", 1,0,1);
	eventTree->Draw("0.5>>hall", "GenEvtInfo->weight");
	totalWeight=hall->Integral();
	delete hall;
	hall=0;
      }

      //
      // loop over events
      //
      Double_t nsel=0, nselvar=0;
      for(UInt_t ientry=0; ientry<eventTree->GetEntries(); ientry++) {
        infoBr->GetEntry(ientry);

	if(ientry%1000000==0) cout << "Processing event " << ientry << ". " << (double)ientry/(double)eventTree->GetEntries()*100 << " percent done with this file." << endl;

        Double_t weight=1;
        if(xsec>0 && totalWeight>0) weight = xsec/totalWeight;
	if(hasGen) {
          genPartArr->Clear();
          genBr->GetEntry(ientry);
          genPartBr->GetEntry(ientry);
	  weight*=gen->weight;
        }

        // veto w -> xv decays for signal and w -> mv for bacground samples (needed for inclusive WToLNu sample)
        if (isWrongFlavor && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))==LEPTON_ID) continue;
	else if (isSignal && hasGen && fabs(toolbox::flavor(genPartArr, BOSON_ID))!=LEPTON_ID) continue;
        
	// check for certified lumi (if applicable)
        baconhep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
        if(hasJSON && !rlrm.hasRunLumi(rl)) continue;  

        // trigger requirement               
	if (!isMuonTrigger(triggerMenu, info->triggerBits)) continue;
      
        // good vertex requirement
        if(!(info->hasGoodPV)) continue;

        //
	// SELECTION PROCEDURE:
	//  (1) Look for 1 good muon matched to trigger
	//  (2) Reject event if another muon is present passing looser cuts
	//
	muonArr->Clear();
        muonBr->GetEntry(ientry);

	Int_t nLooseLep=0;
	const baconhep::TMuon *goodMuon=0;
	Bool_t passSel=kFALSE;

        for(Int_t i=0; i<muonArr->GetEntriesFast(); i++) {
          const baconhep::TMuon *mu = (baconhep::TMuon*)((*muonArr)[i]);

          if(fabs(mu->eta) > VETO_PT)  continue; // loose lepton |eta| cut
          if(mu->pt        < VETO_ETA) continue; // loose lepton pT cut
//          if(passMuonLooseID(mu)) nLooseLep++; // loose lepton selection
          if(nLooseLep>1) {  // extra lepton veto
            passSel=kFALSE;
            break;
          }
          
          if(fabs(mu->eta) > ETA_CUT)         continue; // lepton |eta| cut
          if(mu->pt < PT_CUT)                 continue; // lepton pT cut   
          if(!passAntiMuonID(mu))             continue; // lepton anti-selection
          if(!isMuonTriggerObj(triggerMenu, mu->hltMatchBits, kFALSE)) continue;
	  
	  passSel=kTRUE;
	  goodMuon = mu;
	}

	if(passSel) {	  
	  /******** We have a W candidate! HURRAY! ********/
	  nsel+=weight;
          nselvar+=weight*weight;
	  
	  TLorentzVector vLep; 
	  vLep.SetPtEtaPhiM(goodMuon->pt, goodMuon->eta, goodMuon->phi, MUON_MASS);

	  //
	  // Fill tree
	  //
	  runNum   = info->runNum;
	  lumiSec  = info->lumiSec;
	  evtNum   = info->evtNum;
	  
	  vertexArr->Clear();
	  vertexBr->GetEntry(ientry);

	  npv      = vertexArr->GetEntries();
	  npu	   = info->nPUmean;
	  genV      = new TLorentzVector(0,0,0,0);
          genLep    = new TLorentzVector(0,0,0,0);
	  genVPt    = -999;
          genVPhi   = -999;
          genVy     = -999;
          genVMass  = -999;
          u1        = -999;
          u2        = -999;
          tkU1      = -999;
          tkU2      = -999;
	  mvaU1     = -999;
          mvaU2     = -999;
          id_1      = -999;
          id_2      = -999;
          x_1       = -999;
          x_2       = -999;
          xPDF_1    = -999;
          xPDF_2    = -999;
          scalePDF  = -999;
          weightPDF = -999;

	  if(isSignal && hasGen) {
	    TLorentzVector *gvec=new TLorentzVector(0,0,0,0);
            TLorentzVector *glep1=new TLorentzVector(0,0,0,0);
            TLorentzVector *glep2=new TLorentzVector(0,0,0,0);
	    toolbox::fillGen(genPartArr, BOSON_ID, gvec, glep1, glep2,1);

            if (gvec && glep1) {
	      genV      = new TLorentzVector(0,0,0,0);
              genV->SetPtEtaPhiM(gvec->Pt(),gvec->Eta(),gvec->Phi(),gvec->M());
              genLep    = new TLorentzVector(0,0,0,0);
              genLep->SetPtEtaPhiM(glep1->Pt(),glep1->Eta(),glep1->Phi(),glep1->M());
              genVPt    = gvec->Pt();
              genVPhi   = gvec->Phi();
              genVy     = gvec->Rapidity();
              genVMass  = gvec->M();
              genLepPt  = glep1->Pt();
              genLepPhi = glep1->Phi();

	      TVector2 vWPt((genVPt)*cos(genVPhi),(genVPt)*sin(genVPhi));
	      TVector2 vLepPt(vLep.Px(),vLep.Py());
	      
	      TVector2 vMet((info->pfMETC)*cos(info->pfMETCphi), (info->pfMETC)*sin(info->pfMETCphi));
	      TVector2 vU = -1.0*(vMet+vLepPt);
	      u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|

	      TVector2 vTkMet((info->trkMET)*cos(info->trkMETphi), (info->trkMET)*sin(info->trkMETphi));
	      TVector2 vTkU = -1.0*(vTkMet+vLepPt);
	      tkU1 = ((vWPt.Px())*(vTkU.Px()) + (vWPt.Py())*(vTkU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      tkU2 = ((vWPt.Px())*(vTkU.Py()) - (vWPt.Py())*(vTkU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|
	      
	      TVector2 vMvaMet((info->mvaMET)*cos(info->mvaMETphi), (info->mvaMET)*sin(info->mvaMETphi));
	      TVector2 vMvaU = -1.0*(vMvaMet+vLepPt);
	      mvaU1 = ((vWPt.Px())*(vMvaU.Px()) + (vWPt.Py())*(vMvaU.Py()))/(genVPt);  // u1 = (pT . u)/|pT|
	      mvaU2 = ((vWPt.Px())*(vMvaU.Py()) - (vWPt.Py())*(vMvaU.Px()))/(genVPt);  // u2 = (pT x u)/|pT|
          
            }
	    id_1      = gen->id_1;
            id_2      = gen->id_2;
            x_1       = gen->x_1;
            x_2       = gen->x_2;
            xPDF_1    = gen->xPDF_1;
            xPDF_2    = gen->xPDF_2;
            scalePDF  = gen->scalePDF;
            weightPDF = gen->weight;

	    delete gvec;
            delete glep1;
            delete glep2;
            gvec=0; glep1=0; glep2=0;
	  }
	  scale1fb = weight;
	  puWeight = h_rw->GetBinContent(info->nPUmean+1);
	  met	   = info->pfMETC;
	  metPhi   = info->pfMETCphi;
	  sumEt    = 0;
	  mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMETC) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETCphi))) );
	  tkMet    = info->trkMET;
          tkMetPhi = info->trkMETphi;
          tkSumEt  = 0;
          tkMt     = sqrt( 2.0 * (vLep.Pt()) * (info->trkMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->trkMETphi))) );
	  mvaMet   = info->mvaMET;
          mvaMetPhi = info->mvaMETphi;
          mvaSumEt  = 0;
          mvaMt     = sqrt( 2.0 * (vLep.Pt()) * (info->mvaMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->mvaMETphi))) );
	  q        = goodMuon->q;
	  lep      = &vLep;
	  
	  ///// muon specific /////
	  trkIso     = goodMuon->trkIso;
          emIso      = goodMuon->ecalIso;
          hadIso     = goodMuon->hcalIso;
          pfChIso    = goodMuon->chHadIso;
          pfGamIso   = goodMuon->gammaIso;
          pfNeuIso   = goodMuon->neuHadIso;
          pfCombIso  = goodMuon->chHadIso + TMath::Max(goodMuon->neuHadIso + goodMuon->gammaIso -
						       0.5*(goodMuon->puIso),Double_t(0));
	  d0         = goodMuon->d0;
	  dz         = goodMuon->dz;
	  muNchi2    = goodMuon->muNchi2;
	  nPixHits   = goodMuon->nPixHits;
	  nTkLayers  = goodMuon->nTkLayers;
	  nMatch     = goodMuon->nMatchStn;
	  nValidHits = goodMuon->nValidHits;
	  typeBits   = goodMuon->typeBits;

	  outTree->Fill();
	  delete genV;
	  delete genLep;
	  genV=0, genLep=0, lep=0;
        }
      }
      delete infile;
      infile=0, eventTree=0;    

      cout << nsel  << " +/- " << sqrt(nselvar);
      if(isam!=0) cout << " per 1/fb";
      cout << endl;
    }
    outFile->Write();
    outFile->Close();
  }
  delete h_rw;
  delete f_rw;
  delete info;
  delete gen;
  delete genPartArr;
  delete muonArr;
  delete vertexArr;
      
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " W -> mu nu" << endl;
  cout << "  pT > " << PT_CUT << endl;
  cout << "  |eta| < " << ETA_CUT << endl;
  cout << endl;
  
  cout << endl;
  cout << "  <> Output saved in " << outputDir << "/" << endl;    
  cout << endl;  
      
  gBenchmark->Show("selectAntiWm"); 
}
Exemple #29
0
void selectWe(const TString conf,        // input file
              const TString outputDir,   // output directory
	      const Bool_t  doScaleCorr  // apply energy scale corrections?
) {
  gBenchmark->Start("selectWe");

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

  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 
  //==============================================================================================================  

  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  npv, npu;
  Float_t genVPt, genVPhi, genVy, genVMass;
  Float_t genLepPt, genLepPhi;
  Float_t scale1fb;
  Float_t met, metPhi, sumEt, mt, u1, u2;
  Int_t   q;
  LorentzVector *lep=0;
  ///// electron specific /////
  Float_t trkIso, emIso, hadIso;
  Float_t pfChIso, pfGamIso, pfNeuIso, pfCombIso;
  Float_t sigieie, hovere, eoverp, fbrem, ecalE;
  Float_t dphi, deta;
  Float_t d0, dz;
  UInt_t  isConv, nexphits, typeBits;
  LorentzVector *sc=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 *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;
  
    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("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("genLepPt", &genLepPt, "genLepPt/F");   // GEN lepton pT (signal MC)
    outTree->Branch("genLepPhi",&genLepPhi,"genLepPhi/F");  // GEN lepton phi (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("mt",       &mt,       "mt/F");         // transverse mass
    outTree->Branch("u1",       &u1,       "u1/F");         // parallel component of recoil
    outTree->Branch("u2",       &u2,       "u2/F");         // perpendicular component of recoil
    outTree->Branch("q",        &q,        "q/I");          // lepton charge
    outTree->Branch("lep", "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &lep);  // lepton 4-vector
    ///// electron specific /////
    outTree->Branch("trkIso",    &trkIso,    "trkIso/F");     // track isolation of tag lepton
    outTree->Branch("emIso",     &emIso,     "emIso/F");      // ECAL isolation of tag lepton
    outTree->Branch("hadIso",    &hadIso,    "hadIso/F");     // HCAL isolation of tag lepton
    outTree->Branch("pfChIso",   &pfChIso,   "pfChIso/F");    // PF charged hadron isolation of lepton
    outTree->Branch("pfGamIso",  &pfGamIso,  "pfGamIso/F");   // PF photon isolation of lepton
    outTree->Branch("pfNeuIso",  &pfNeuIso,  "pfNeuIso/F");   // PF neutral hadron isolation of lepton
    outTree->Branch("pfCombIso", &pfCombIso, "pfCombIso/F");  // PF combined isolation of electron
    outTree->Branch("sigieie",   &sigieie,   "sigieie/F");    // sigma-ieta-ieta of electron
    outTree->Branch("hovere",    &hovere,    "hovere/F");     // H/E of electron
    outTree->Branch("eoverp",    &eoverp,    "eoverp/F");     // E/p of electron
    outTree->Branch("fbrem",     &fbrem,     "fbrem/F");      // brem fraction of electron
    outTree->Branch("dphi",      &dphi,	     "dphi/F");       // GSF track - ECAL dphi of electron
    outTree->Branch("deta",      &deta,      "deta/F");       // GSF track - ECAL deta of electron
    outTree->Branch("ecalE",     &ecalE,     "ecalE/F");      // ECAL energy of electron
    outTree->Branch("d0",        &d0,        "d0/F");         // transverse impact parameter of electron
    outTree->Branch("dz",        &dz,        "dz/F");         // longitudinal impact parameter of electron
    outTree->Branch("isConv",    &isConv,    "isConv/i");     // conversion filter flag of electron
    outTree->Branch("nexphits",  &nexphits,  "nexphits/i");   // number of missing expected inner hits of electron
    outTree->Branch("typeBits",  &typeBits,  "typeBits/i");   // electron type of electron
    outTree->Branch("sc",  "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >", &sc);   // electron 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("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) Look for 1 good electron matched to trigger
	//  (2) Reject event if another electron is present passing looser cuts
	//
	electronArr->Clear();
        electronBr->GetEntry(ientry);
	Int_t nLooseLep=0;
	const mithep::TElectron *goodEle=0;
	Bool_t passSel=kFALSE;	
        for(Int_t i=0; i<electronArr->GetEntriesFast(); i++) {
          const mithep::TElectron *ele = (mithep::TElectron*)((*electronArr)[i]);
	  
	  // check ECAL gap
	  if(fabs(ele->scEta)>=ECAL_GAP_LOW && fabs(ele->scEta)<=ECAL_GAP_HIGH) continue;
	  
	  Double_t escale=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(ele->scEta)<escaleEta[ieta]) {
	        escale = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  if(fabs(ele->scEta)   > 2.5) continue;                // loose lepton |eta| cut
          if(escale*(ele->scEt) < 20)  continue;                // loose lepton pT cut
          if(passEleLooseID(ele,info->rhoLowEta)) nLooseLep++;  // loose lepton selection
          if(nLooseLep>1) {  // extra lepton veto
            passSel=kFALSE;
            break;
          }
          
          if(fabs(ele->scEta)   > ETA_CUT)    continue;  // lepton |eta| cut
          if(escale*(ele->scEt) < PT_CUT)     continue;  // lepton pT cut
          if(!passEleID(ele,info->rhoLowEta)) continue;  // lepton selection
          if(!(ele->hltMatchBits & trigObj))  continue;  // check trigger matching
	  
	  passSel=kTRUE;
	  goodEle = ele;  
	}
	
	if(passSel) {
	  
	  /******** We have a W candidate! HURRAY! ********/
	    
	  nsel+=weight;
          nselvar+=weight*weight;
	  
	  Double_t escale=1;
	  if(doScaleCorr && isam==0) {
	    for(UInt_t ieta=0; ieta<escaleNbins; ieta++) {
	      if(fabs(goodEle->scEta)<escaleEta[ieta]) {
	        escale = escaleCorr[ieta];
		break;
	      }
	    }
	  }
	  
	  LorentzVector vLep(escale*(goodEle->pt), goodEle->eta, goodEle->phi, ELE_MASS);  
	  LorentzVector vSC(escale*(goodEle->scEt), goodEle->scEta, goodEle->scPhi, ELE_MASS); 	  
	  
	  //
	  // Fill tree
	  //
	  runNum   = info->runNum;
	  lumiSec  = info->lumiSec;
	  evtNum   = info->evtNum;
	  npv	   = pvArr->GetEntriesFast();
	  npu	   = info->nPU;
	  genVPt   = 0;
	  genVPhi  = 0;
	  genVy    = 0;
	  genVMass = 0;
	  genLepPt = 0;
	  genLepPhi= 0;
	  u1       = 0;
	  u2       = 0;
	  if(hasGen) {
	    genVPt   = gen->vpt;
            genVPhi  = gen->vphi;
	    genVy    = gen->vy;
	    genVMass = gen->vmass;
	    TVector2 vWPt((gen->vpt)*cos(gen->vphi),(gen->vpt)*sin(gen->vphi));
	    TVector2 vLepPt(vLep.Px(),vLep.Py());      
            TVector2 vMet((info->pfMET)*cos(info->pfMETphi), (info->pfMET)*sin(info->pfMETphi));        
            TVector2 vU = -1.0*(vMet+vLepPt);
            u1 = ((vWPt.Px())*(vU.Px()) + (vWPt.Py())*(vU.Py()))/(gen->vpt);  // u1 = (pT . u)/|pT|
            u2 = ((vWPt.Px())*(vU.Py()) - (vWPt.Py())*(vU.Px()))/(gen->vpt);  // u2 = (pT x u)/|pT|
	    
	    if(abs(gen->id_1)==EGenType::kElectron) { genLepPt = gen->vpt_1; genLepPhi = gen->vphi_1; }
	    if(abs(gen->id_2)==EGenType::kElectron) { genLepPt = gen->vpt_2; genLepPhi = gen->vphi_2; }
	  }
	  scale1fb = weight;
	  met	   = info->pfMET;
	  metPhi   = info->pfMETphi;
	  sumEt    = info->pfSumET;
	  mt       = sqrt( 2.0 * (vLep.Pt()) * (info->pfMET) * (1.0-cos(toolbox::deltaPhi(vLep.Phi(),info->pfMETphi))) );
	  q        = goodEle->q;	  
	  lep      = &vLep;	  
	  
	  ///// electron specific /////
	  sc	    = &vSC;
	  trkIso    = goodEle->trkIso03;
	  emIso     = goodEle->emIso03;
	  hadIso    = goodEle->hadIso03;
	  pfChIso   = goodEle->pfChIso03;
	  pfGamIso  = goodEle->pfGamIso03;
	  pfNeuIso  = goodEle->pfNeuIso03;	
	  pfCombIso = goodEle->pfChIso03 + TMath::Max(goodEle->pfNeuIso03 + goodEle->pfGamIso03 - (info->rhoLowEta)*getEffArea(goodEle->scEta), 0.);
	  sigieie   = goodEle->sigiEtaiEta;
	  hovere    = goodEle->HoverE;
	  eoverp    = goodEle->EoverP;
	  fbrem     = goodEle->fBrem;
	  dphi      = goodEle->deltaPhiIn;
	  deta      = goodEle->deltaEtaIn;
	  d0        = goodEle->d0;
	  dz        = goodEle->dz;
	  isConv    = goodEle->isConv;
	  nexphits  = goodEle->nExpHitsInner;
	  typeBits  = goodEle->typeBits;
	   
	  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 pvArr;
  
    
  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
   
  cout << "*" << endl;
  cout << "* SUMMARY" << endl;
  cout << "*--------------------------------------------------" << endl;
  cout << " W -> e nu" << 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("selectWe"); 
}
void MakeBJetEfficiencyNtuple(const string inputFilename, const string outputFilename, int denominatorType = 0)
{  
  gBenchmark->Start("WWTemplate");

  //*****************************************************************************************
  //Define Data Era
  //*****************************************************************************************
  UInt_t DataEra = kDataEra_NONE;
  DataEra = kDataEra_2012_MC;

  cout << "using DataEra = " << DataEra << endl;


  //*****************************************************************************************
  //Setup Output Tree
  //*****************************************************************************************
  TFile *outputFile = new TFile(outputFilename.c_str(), "RECREATE");
  cmsana::EfficiencyTree *effTree = new cmsana::EfficiencyTree;
  effTree->CreateTree();
  effTree->tree_->SetAutoFlush(0);

  UInt_t NDenominatorsFilled = 0;
  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  //
  // Access samples and fill histograms
  TTree *eventTree=0;  
   
  // Data structures to store info from TTrees
  cmsana::TEventInfo *info    = new cmsana::TEventInfo();
  TClonesArray *jetArr = new TClonesArray("cmsana::TJet");
  TClonesArray *pfcandidateArr = new TClonesArray("cmsana::TPFCandidate");
  TClonesArray *genparticleArr = new TClonesArray("cmsana::TGenParticle");
  TClonesArray *genjetArr = new TClonesArray("cmsana::TGenJet");

  Int_t NEvents = 0;



  //********************************************************
  // Get Tree
  //********************************************************
  eventTree = getTreeFromFile(inputFilename.c_str(),"Events"); 
  TBranch *infoBr;
  TBranch *jetBr;
  TBranch *pfcandidateBr;
  TBranch *genparticleBr;
  TBranch *genjetBr;
  
  
  //*****************************************************************************************
  //Loop over Data Tree
  //*****************************************************************************************
  // Set branch address to structures that will store the info  
  eventTree->SetBranchAddress("Info",       &info);  infoBr       = eventTree->GetBranch("Info");
  eventTree->SetBranchAddress("PFJet", &jetArr); jetBr  = eventTree->GetBranch("PFJet");
  eventTree->SetBranchAddress("PFCandidate", &pfcandidateArr); pfcandidateBr = eventTree->GetBranch("PFCandidate");
  eventTree->SetBranchAddress("GenParticle", &genparticleArr); genparticleBr = eventTree->GetBranch("GenParticle");
  eventTree->SetBranchAddress("GenJet", &genjetArr); genjetBr = eventTree->GetBranch("GenJet");

  cout << "InputFile " << inputFilename << " --- Total Events : " << eventTree->GetEntries() << endl;
  for(UInt_t ientry=0; ientry < eventTree->GetEntries(); ientry++) {       	
    infoBr->GetEntry(ientry);
		
    if (ientry % 100 == 0) cout << "Event " << ientry << endl;

    Double_t eventweight = info->eventweight;

    //********************************************************
    // Load the branches
    //********************************************************
    jetArr->Clear(); 
    pfcandidateArr->Clear(); 
    genparticleArr->Clear(); 
    genjetArr->Clear(); 
    jetBr->GetEntry(ientry);
    pfcandidateBr->GetEntry(ientry);
    genparticleBr->GetEntry(ientry);
    genjetBr->GetEntry(ientry);
 

    //********************************************************
    // Pileup Energy Density
    //********************************************************
    Double_t rho = info->RhoKt6PFJets;
    UInt_t EAEra = kDataEra_2012_Data;


    if (denominatorType == 0) {
    //********************************************************
    // genjets denominator
    //********************************************************
      for(Int_t k=0; k<genjetArr->GetEntries(); k++) {
        const cmsana::TGenJet *genjet = (cmsana::TGenJet*)((*genjetArr)[k]);

        //some kinematic cuts to save ntupling time
        if (!(genjet->pt > 30)) continue;
        if (!(fabs(genjet->eta) < 2.5)) continue;        

        bool pass = false;
        //Find matching jet
        for(Int_t i=0; i<jetArr->GetEntriesFast(); i++) {
          const cmsana::TJet *jet = (cmsana::TJet*)((*jetArr)[i]);
          if (!(jet->pt > 20)) continue;
          if (!(fabs(jet->eta) < 2.5)) continue;
          
          //match in dR?
          double DR = cmsana::deltaR(jet->eta,jet->phi,genjet->eta,genjet->phi);
          if (!(DR < 0.5)) continue;

          if (!(jet->CombinedSecondaryVertexBJetTagsDisc > 0.679)) continue;
          
          pass = true;
          break;
        }
        
        effTree->weight = eventweight;
        effTree->mass = 0;
        effTree->pt = genjet->pt;
        effTree->eta = genjet->eta;
        effTree->phi = genjet->phi;
        effTree->rho = info->RhoKt6PFJets;
        effTree->q = 0;
        effTree->npv = info->nGoodPV;
        effTree->npu = info->nPU;
        effTree->matchedPdgId = genjet->matchedPdgId;
        effTree->run = info->runNum;
        effTree->lumi = info->lumiSec;
        effTree->event = info->evtNum;
        effTree->pass = pass;

        //***********************
        //Fill Denominator
        //***********************
        NDenominatorsFilled++;
        effTree->tree_->Fill();

      }//loop over genjet denominators
    } //if denominatorType == 0

  } //loop over events
  
  cout << "Total Denominators: " << NDenominatorsFilled << endl;

  delete info;
  delete jetArr;
  delete pfcandidateArr;
  delete genparticleArr;
  delete genjetArr;

  outputFile->Write();
  outputFile->Close();
  
  delete outputFile;
  if (effTree) delete effTree;
}