void MakeNtuple(const string inputFilename, const string outputFilename, Int_t Option)
{  
  gBenchmark->Start("WWTemplate");

  //*****************************************************************************************
  //Setup
  //*****************************************************************************************
  TFile *outputFile = new TFile(outputFilename.c_str(), "RECREATE");
  ElectronTree *eleTree = new ElectronTree;
  eleTree->CreateTree();
  eleTree->tree_->SetAutoFlush(0);

  UInt_t NElectronsFilled = 0;
  //--------------------------------------------------------------------------------------------------------------
  // Main analysis code 
  //==============================================================================================================  
  
  //
  // Access samples and fill histograms
  TTree *eventTree=0;  
   
  // Data structures to store info from TTrees
  higgsana::TEventInfo *info    = new higgsana::TEventInfo();
  TClonesArray *electronArr = new TClonesArray("higgsana::TElectron");
  TClonesArray *muonArr = new TClonesArray("higgsana::TMuon");
  TClonesArray *jetArr = new TClonesArray("higgsana::TJet");
  TClonesArray *photonArr = new TClonesArray("higgsana::TPhoton");
  TClonesArray *pfcandidateArr = new TClonesArray("higgsana::TPFCandidate");
  
  //********************************************************
  // Good RunLumi Selection
  //********************************************************
  Bool_t hasJSON = kTRUE;
  mithep::RunLumiRangeMap rlrm;
  rlrm.AddJSONFile("/data/smurf/data/Winter11_4700ipb/auxiliar/hww.Full2011.json"); 
  rlrm.AddJSONFile("/data/blue/sixie/HZZ4l/auxiliar/2012/Cert_190456-196531_8TeV_PromptReco_Collisions12_JSON.txt");

  Int_t NEvents = 0;

  UInt_t DataEra = kDataEra_NONE;

  vector<string> inputfiles;
  if (inputFilename == "LIST") {
    inputfiles.push_back("/home/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r11a-del-m10-v1.FakeTriggerSkim.root");
    inputfiles.push_back("/home/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r11a-del-pr-v4.FakeTriggerSkim.root");
    inputfiles.push_back("/home/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r11a-del-a05-v1.FakeTriggerSkim.root");
    inputfiles.push_back("/home/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r11a-del-o03-v1.FakeTriggerSkim.root");
    inputfiles.push_back("/home/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r11b-del-pr-v1.FakeTriggerSkim.root");    
  } 
  else if (inputFilename == "2012Data") {
    inputfiles.push_back("/data/smurf/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r12a-del-pr-v1_FakeRateTriggerSkimmed.root");
    inputfiles.push_back("/data/smurf/sixie/hist/HZZ4lNtuples/data/AllNtuple_HZZ4lNtuple_r12b-del-pr-v1_FakeRateTriggerSkimmed.root");
    DataEra = kDataEra_2012_MC;
  }
  else {
    inputfiles.push_back(inputFilename);
  }

  for (UInt_t f = 0; f < inputfiles.size(); ++f) {

    //********************************************************
    // Get Tree
    //********************************************************
    eventTree = getTreeFromFile(inputfiles[f].c_str(),"Events"); 
    TBranch *infoBr;
    TBranch *electronBr;
    TBranch *muonBr;
    TBranch *jetBr;
    TBranch *photonBr;
    TBranch *pfcandidateBr;


    //*****************************************************************************************
    //Loop over 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("Photon", &photonArr);     photonBr = eventTree->GetBranch("Photon");
    eventTree->SetBranchAddress("PFJet", &jetArr);         jetBr = eventTree->GetBranch("PFJet");
    eventTree->SetBranchAddress("PFCandidate", &pfcandidateArr); pfcandidateBr = eventTree->GetBranch("PFCandidate");

    cout << "InputFile " << inputfiles[f] << " --- Total Events : " << eventTree->GetEntries() << endl;
    for(UInt_t ientry=0; ientry < eventTree->GetEntries(); ientry++) {       	
      infoBr->GetEntry(ientry);
		
      if (ientry % 100000 == 0) cout << "Event " << ientry << endl;

      Double_t eventweight = info->eventweight;

      mithep::RunLumiRangeMap::RunLumiPairType rl(info->runNum, info->lumiSec);      
      if(hasJSON && !rlrm.HasRunLumi(rl)) continue;  // not certified run? Skip to next event...

      NEvents++;

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


      //********************************************************
      // 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;
      }

      //********************************************************
      // TcMet
      //********************************************************
      TVector3 pfMet;        
      if(info->pfMEx!=0 || info->pfMEy!=0) {       
        pfMet.SetXYZ(info->pfMEx, info->pfMEy, 0);
      }
      Double_t met = pfMet.Pt();

      Int_t NElectrons = electronArr->GetEntries();
 

      //********************************************************
      // Event Selection Cuts
      //********************************************************
      //veto events with more than 1 reco electron
      if (NElectrons > 1) continue;
      //met cut removed W events
      if (met > 20) continue;


      //******************************************************************************
      //loop over electrons 
      //******************************************************************************
      for(Int_t i=0; i<electronArr->GetEntries(); i++) {
        const higgsana::TElectron *ele = (higgsana::TElectron*)((*electronArr)[i]);
 

        //make cut on dz
        if (fabs(ele->dz) > 0.1) continue;

        //protect against pathologies
        if (TMath::IsNaN(ele->sigiPhiiPhi)) {
          cout << "Pathological SigmaIPhiIPhi : " 
               << info->runNum << " " << info->lumiSec << " " << info->evtNum << endl;
          continue;
        }
        
        //********************************************************
        //find leading jet in the event
        //********************************************************
        Double_t leadingJetPt = -1;
        //pass event selection     
        for(Int_t j=0; j<jetArr->GetEntries(); j++) {
          const higgsana::TJet *jet = (higgsana::TJet*)((*jetArr)[j]);        
          if (jet->pt > leadingJetPt &&
              higgsana::deltaR(jet->eta, jet->phi, ele->eta, ele->phi) > 1.0) {
            leadingJetPt = jet->pt;          
          }
        }
      
        //Fill These Electrons
        NElectronsFilled++;
        
        if (Option == 0) {
          FillElectronTree( eleTree, ele, pfcandidateArr, rhoEleIso, EleEAEra, 
                            info->nPV0, info->runNum, info->lumiSec, info->evtNum);
        } else if (Option == 1) {
          FillElectronTree( eleTree, ele, pfcandidateArr, rhoEleIso, kDataEra_NONE, 
                            info->nPV0, info->runNum, info->lumiSec, info->evtNum);
        }

      } //loop over electrons

    } //end loop over data  

    cout << "Total Electrons: " << NElectronsFilled << endl;

  } //end loop over files

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


  cout << "Total Electrons: " << NElectronsFilled << endl;
  outputFile->Write();
  outputFile->Close();

  gBenchmark->Show("WWTemplate");       
} 
//*************************************************************************************************
//Fill Lepton Pt Spectrum
//*************************************************************************************************
void MakeElectronIDMVAPerformancePlots(string InputFile, string Label, Int_t Option)
{  

  string label = "";
  if (Label != "") label = "_" + Label;


  //*****************************************************************************************
  //Plotting Setup
  //*****************************************************************************************
//   vector<Int_t> markers;
//   vector<Int_t> colors;
//   colors.push_back(kRed);     markers.push_back(20);
//   colors.push_back(kCyan);    markers.push_back(21);
// //   colors.push_back(kBlue);    markers.push_back(21);
//   colors.push_back(kMagenta); markers.push_back(22);
//   colors.push_back(kCyan);    markers.push_back(34);
//   colors.push_back(kBlack);   markers.push_back(29);
//   colors.push_back(kGreen);   markers.push_back(33);
//   colors.push_back(kRed-2);   markers.push_back(33);
//   colors.push_back(kOrange);   markers.push_back(33);
//   colors.push_back(kBlue-2);   markers.push_back(33);
//   colors.push_back(kGreen-2);   markers.push_back(33);
//   colors.push_back(kMagenta-2);   markers.push_back(33);


  //--------------------------------------------------------------------------------------------------------------
  // Histograms
  //==============================================================================================================  
  TH1F *EleIDMVATrig_Real = new TH1F(("EleIDMVATrig_Real"+label).c_str(), "; IDMVATrig ; Number of Events ",  10000, -2 , 2);
  TH1F *EleIDMVANonTrig_Real = new TH1F(("EleIDMVANonTrig_Real"+label).c_str(), "; IDMVANonTrig ; Number of Events ",  10000, -2 , 2);
  TH1F *EleIDMVATrig_Fake = new TH1F(("EleIDMVATrig_Fake"+label).c_str(), "; IDMVATrig ; Number of Events ",  10000, -2 , 2);
  TH1F *EleIDMVANonTrig_Fake = new TH1F(("EleIDMVANonTrig_Fake"+label).c_str(), "; IDMVANonTrig ; Number of Events ",  10000, -2 , 2);

  Double_t RealElectrons = 0;
  Double_t FakeElectrons = 0;
  Double_t RealElectronPassCSA14Tight = 0;
  Double_t FakeElectronPassCSA14Tight = 0;
  Double_t RealElectronPassCSA14Loose = 0;
  Double_t FakeElectronPassCSA14Loose = 0;
  Double_t RealElectronPassCSA14Veto = 0;
  Double_t FakeElectronPassCSA14Veto = 0;

  Double_t RealElectronPassIDMVANonTrigVeto = 0;
  Double_t FakeElectronPassIDMVANonTrigVeto = 0;
  Double_t RealElectronPassIDMVATrigTight = 0;
  Double_t FakeElectronPassIDMVATrigTight = 0;

  //*****************************************************************************************
  //EleTree
  //*****************************************************************************************
  ElectronTree *EleTree = new ElectronTree;
  EleTree->LoadTree(InputFile.c_str());
  EleTree->InitTree(ElectronTree::kEleTreeLight);

  cout << "Total Entries: " << EleTree->tree_->GetEntries() << "\n";
  int nentries = EleTree->tree_->GetEntries();
  nentries = 5000000;
  for(UInt_t ientry=0; ientry < EleTree->tree_->GetEntries(); ientry++) {       	
    EleTree->tree_->GetEntry(ientry);
    
    if (ientry % 100000 == 0) cout << "Event " << ientry << endl;
        
    
    if (abs(EleTree->fPdgId) == 11 && RealElectrons >= nentries) continue;
    if ( (abs(EleTree->fPdgId) > 50 || EleTree->fPdgId == 0) && FakeElectrons >= nentries) continue;

    //don't evaluate performance using training events
    if (EleTree->fElePt < 5) continue;


    //classify by eta and pt bins
    Int_t subdet = 0;
    if (fabs(EleTree->fEleEta) < 1.485) subdet = 0;
    else subdet = 1;

    Int_t ptBin = 0;
    if (EleTree->fElePt > 10.0) ptBin = 1;
    if (EleTree->fElePt > 20.0) ptBin = 2;

    Bool_t passCuts = kFALSE;
    if (Option == 0) passCuts = (subdet == 0 && ptBin == 0);
    if (Option == 1) passCuts = (subdet == 1 && ptBin == 0);
    if (Option == 2) passCuts = (subdet == 0 && ptBin == 1);
    if (Option == 3) passCuts = (subdet == 1 && ptBin == 1);    
    if (Option == 4) passCuts = (subdet == 0 && ptBin == 2);
    if (Option == 5) passCuts = (subdet == 1 && ptBin == 2);    
    if (Option == 10) passCuts = (ptBin == 0 );

    if (Option == -1) passCuts = kTRUE;
    if (!passCuts) continue;    


    //Some Preselection cuts
    //if (!passCSA14Preselection(EleTree)) continue;
    //if (!EleTree->fElePassConversion) continue;
    if (!(fabs(EleTree->fEleDZ) < 1)) continue;
    //if (!(EleTree->fElePFIso04 < 0.2)) continue;
    if (!passImprovedIso(EleTree)) continue;
    //if (!(fabs(EleTree->fEleD0) < 0.0166)) continue;

    //Real Electron
    if (abs(EleTree->fPdgId) == 11) {
      RealElectrons += EleTree->fWeight;
      if (passCSA14Tight(EleTree)) RealElectronPassCSA14Tight += EleTree->fWeight;
      if (passCSA14Loose(EleTree)) RealElectronPassCSA14Loose += EleTree->fWeight;
      if (passCSA14Veto(EleTree)) RealElectronPassCSA14Veto += EleTree->fWeight;
      if (passIDMVANonTrigVeto(EleTree)) RealElectronPassIDMVANonTrigVeto += EleTree->fWeight;
      if (passIDMVATrigTight(EleTree)) RealElectronPassIDMVATrigTight += EleTree->fWeight;      

      if ( EleTree->fElePFIso04 < 0.2 ) {
	EleIDMVATrig_Real->Fill(EleTree->fIDMVATrig, EleTree->fWeight);
      } else {
	EleIDMVATrig_Real->Fill(-1, EleTree->fWeight);
      }

      if ( EleTree->fElePFIso04 < 99 &&  
	   ( (fabs(EleTree->fEleSCEta) < 1.479 && fabs(EleTree->fEleD0) < 0.0166)
	     ||
	     (fabs(EleTree->fEleSCEta) >= 1.479 && fabs(EleTree->fEleD0) < 0.098)
	     )
	   ) {
	EleIDMVANonTrig_Real->Fill(EleTree->fIDMVANonTrig, EleTree->fWeight);
      } else {
	EleIDMVANonTrig_Real->Fill(-1, EleTree->fWeight);
      }

    } 
    //FakeElectron
    else if ( abs(EleTree->fPdgId) > 50 || EleTree->fPdgId == 0) {
      FakeElectrons += EleTree->fWeight;
      if (passCSA14Tight(EleTree)) FakeElectronPassCSA14Tight += EleTree->fWeight;
      if (passCSA14Loose(EleTree)) FakeElectronPassCSA14Loose += EleTree->fWeight;
      if (passCSA14Veto(EleTree)) FakeElectronPassCSA14Veto += EleTree->fWeight;
      if (passIDMVANonTrigVeto(EleTree)) FakeElectronPassIDMVANonTrigVeto += EleTree->fWeight;
      if (passIDMVATrigTight(EleTree)) FakeElectronPassIDMVATrigTight += EleTree->fWeight;
      
      if ( EleTree->fElePFIso04 < 0.2 ) {
	EleIDMVATrig_Fake->Fill(EleTree->fIDMVATrig, EleTree->fWeight);
      } else {
	EleIDMVATrig_Real->Fill(-1, EleTree->fWeight);
      }

      if ( EleTree->fElePFIso04 < 99 &&  
	   ( (fabs(EleTree->fEleSCEta) < 1.479 && fabs(EleTree->fEleD0) < 0.0166)
	     ||
	     (fabs(EleTree->fEleSCEta) >= 1.479 && fabs(EleTree->fEleD0) < 0.098)
	     )
	   ) {
	EleIDMVANonTrig_Fake->Fill(EleTree->fIDMVANonTrig, EleTree->fWeight);
      } else {
	EleIDMVANonTrig_Fake->Fill(-1, EleTree->fWeight);
      }
    }

  } 
  
  
  //*****************************************************************************************
  //Current Working Points
  //*****************************************************************************************
  cout << "CSA14 Tight Real Electron Efficiency : " << RealElectronPassCSA14Tight << " / " << RealElectrons << " = " << RealElectronPassCSA14Tight/RealElectrons << endl;
  cout << "CSA14 Tight Fake Electron Efficiency : " << FakeElectronPassCSA14Tight << " / " << FakeElectrons << " = " << FakeElectronPassCSA14Tight/FakeElectrons << endl;
  TGraphAsymmErrors* ROC_CSA14TightWP = MakeCurrentWPSigEffVsBkgEffGraph(RealElectronPassCSA14Tight/RealElectrons , FakeElectronPassCSA14Tight/FakeElectrons, "ROC_CSA14TightWP"+label);

  cout << "CSA14 Loose Real Electron Efficiency : " << RealElectronPassCSA14Loose << " / " << RealElectrons << " = " << RealElectronPassCSA14Loose/RealElectrons << endl;
  cout << "CSA14 Loose Fake Electron Efficiency : " << FakeElectronPassCSA14Loose << " / " << FakeElectrons << " = " << FakeElectronPassCSA14Loose/FakeElectrons << endl;
  TGraphAsymmErrors* ROC_CSA14LooseWP = MakeCurrentWPSigEffVsBkgEffGraph(RealElectronPassCSA14Loose/RealElectrons , FakeElectronPassCSA14Loose/FakeElectrons, "ROC_CSA14LooseWP"+label);

  cout << "CSA14 Veto Real Electron Efficiency : " << RealElectronPassCSA14Veto << " / " << RealElectrons << " = " << RealElectronPassCSA14Veto/RealElectrons << endl;
  cout << "CSA14 Veto Fake Electron Efficiency : " << FakeElectronPassCSA14Veto << " / " << FakeElectrons << " = " << FakeElectronPassCSA14Veto/FakeElectrons << endl;
  TGraphAsymmErrors* ROC_CSA14VetoWP = MakeCurrentWPSigEffVsBkgEffGraph(RealElectronPassCSA14Veto/RealElectrons , FakeElectronPassCSA14Veto/FakeElectrons, "ROC_CSA14VetoWP"+label);



  Double_t BkgEffCSA14Tight = FakeElectronPassCSA14Tight/FakeElectrons;
  Double_t SigEffCSA14Tight = RealElectronPassCSA14Tight/RealElectrons;
  Double_t BkgEffCSA14Veto = FakeElectronPassCSA14Veto/FakeElectrons;
  Double_t SigEffCSA14Veto = RealElectronPassCSA14Veto/RealElectrons;

  cout << "**********************\n";
  Double_t SigEffIDMVATrig_AtTightBkgEff = FindSigEffAtFixedBkgEfficiency(EleIDMVATrig_Real, EleIDMVATrig_Fake, BkgEffCSA14Tight);
  Double_t SigEffIDMVANonTrig_AtTightBkgEff = FindSigEffAtFixedBkgEfficiency(EleIDMVANonTrig_Real, EleIDMVANonTrig_Fake, BkgEffCSA14Tight);
  Double_t BkgEffIDMVATrig_AtTightSigEff = FindBkgEffAtFixedSignalEfficiency(EleIDMVATrig_Real, EleIDMVATrig_Fake, SigEffCSA14Tight);
  Double_t BkgEffIDMVANonTrig_AtTightSigEff = FindBkgEffAtFixedSignalEfficiency(EleIDMVANonTrig_Real, EleIDMVANonTrig_Fake, SigEffCSA14Tight);
  cout << "Signal Efficiency (wrt CSA14Tight Cut-based) for : same bkg \n";
  cout << "IDMVATrig : " << SigEffIDMVATrig_AtTightBkgEff/SigEffCSA14Tight <<  endl;
  cout << "IDMVANonTrig : " << SigEffIDMVANonTrig_AtTightBkgEff/SigEffCSA14Tight <<  endl;
  cout << "Bkg Efficiency (wrt CSA14Veto Cut-based) for same sig eff \n";
  cout << "IDMVATrig : " << BkgEffIDMVATrig_AtTightSigEff/BkgEffCSA14Tight << endl;
  cout << "IDMVANonTrig : " << BkgEffIDMVANonTrig_AtTightSigEff/BkgEffCSA14Tight << endl;
  cout << "**********************\n";

  cout << "**********************\n";
  Double_t BkgEffIDMVATrig_AtVetoSigEff = FindBkgEffAtFixedSignalEfficiency(EleIDMVATrig_Real, EleIDMVATrig_Fake, SigEffCSA14Veto);
  Double_t BkgEffIDMVANonTrig_AtVetoSigEff = FindBkgEffAtFixedSignalEfficiency(EleIDMVANonTrig_Real, EleIDMVANonTrig_Fake, SigEffCSA14Veto);
  Double_t SigEffIDMVATrig_AtVetoBkgEff = FindSigEffAtFixedBkgEfficiency(EleIDMVATrig_Real, EleIDMVATrig_Fake, BkgEffCSA14Veto);
  Double_t SigEffIDMVANonTrig_AtVetoBkgEff = FindSigEffAtFixedBkgEfficiency(EleIDMVANonTrig_Real, EleIDMVANonTrig_Fake, BkgEffCSA14Veto);
  cout << "Sig Efficiency (wrt CSA14Veto Cut-based) for same bkg eff \n";
  cout << "IDMVATrig : " << SigEffIDMVATrig_AtVetoBkgEff/SigEffCSA14Veto << endl;
  cout << "IDMVANonTrig : " << SigEffIDMVANonTrig_AtVetoBkgEff/SigEffCSA14Veto << endl;
  cout << "Bkg Efficiency (wrt CSA14Veto Cut-based) for same sig eff \n";
  cout << "IDMVATrig : " << BkgEffIDMVATrig_AtVetoSigEff/BkgEffCSA14Veto << endl;
  cout << "IDMVANonTrig : " << BkgEffIDMVANonTrig_AtVetoSigEff/BkgEffCSA14Veto << endl;
  cout << "**********************\n";


  cout << "IDMVANonTrig Veto Real Electron Efficiency : " << RealElectronPassIDMVANonTrigVeto << " / " << RealElectrons << " = " << RealElectronPassIDMVANonTrigVeto/RealElectrons << endl;
  cout << "IDMVANonTrig Veto Fake Electron Efficiency : " << FakeElectronPassIDMVANonTrigVeto << " / " << FakeElectrons << " = " << FakeElectronPassIDMVANonTrigVeto/FakeElectrons << endl;
  TGraphAsymmErrors* ROC_IDMVANonTrigVetoWP = MakeCurrentWPSigEffVsBkgEffGraph(RealElectronPassIDMVANonTrigVeto/RealElectrons , FakeElectronPassIDMVANonTrigVeto/FakeElectrons, "ROC_IDMVANonTrigVetoWP"+label);


  cout << "IDMVATrig Tight Real Electron Efficiency : " << RealElectronPassIDMVATrigTight << " / " << RealElectrons << " = " << RealElectronPassIDMVATrigTight/RealElectrons << endl;
  cout << "IDMVATrig Tight Veto Fake Electron Efficiency : " << FakeElectronPassIDMVATrigTight << " / " << FakeElectrons << " = " << FakeElectronPassIDMVATrigTight/FakeElectrons << endl;
  TGraphAsymmErrors* ROC_IDMVATrigTightWP = MakeCurrentWPSigEffVsBkgEffGraph(RealElectronPassIDMVATrigTight/RealElectrons , FakeElectronPassIDMVATrigTight/FakeElectrons, "ROC_IDMVATrigTightWP"+label);



  //*****************************************************************************************
  //Make ROC curves
  //*****************************************************************************************
  TGraphAsymmErrors* ROC_IDMVATrig = MakeSigEffVsBkgEffGraph(EleIDMVATrig_Real, EleIDMVATrig_Fake, "ROC_IDMVATrig"+label );
  TGraphAsymmErrors* ROC_IDMVANonTrig = MakeSigEffVsBkgEffGraph(EleIDMVANonTrig_Real, EleIDMVANonTrig_Fake, "ROC_IDMVANonTrig"+label );


  //*****************************************************************************************
  //Find Cut with same signal efficiency Make ROC curves
  //*****************************************************************************************
  Double_t CutValue_IDMVATrig_SameSig = FindCutValueAtFixedEfficiency(EleIDMVATrig_Real, SigEffCSA14Tight );
  Double_t CutValue_IDMVATrig_SameBkg = FindCutValueAtFixedEfficiency(EleIDMVATrig_Fake, BkgEffCSA14Tight );
  cout << "IDMVATrig Cut Value @ Same Cut-Based Tight Sig Eff: " << CutValue_IDMVATrig_SameSig << endl;
  cout << "IDMVATrig Cut Value @ Same Cut-Based Tight Bkg Eff: " << CutValue_IDMVATrig_SameBkg << endl;

  Double_t CutValue_IDMVANonTrig_SameSig = FindCutValueAtFixedEfficiency(EleIDMVANonTrig_Real, SigEffCSA14Veto );
  Double_t CutValue_IDMVANonTrig_SameBkg = FindCutValueAtFixedEfficiency(EleIDMVANonTrig_Fake, BkgEffCSA14Veto );
  cout << "IDMVANonTrig Cut Value @ Same Cut-Based Veto Sig Eff: " << CutValue_IDMVANonTrig_SameSig << endl;
  cout << "IDMVANonTrig Cut Value @ Same Cut-Based Veto Bkg Eff: " << CutValue_IDMVANonTrig_SameBkg << endl;

  Double_t CutValue_IDMVANonTrig_HalfBkg = FindCutValueAtFixedEfficiency(EleIDMVANonTrig_Fake, 0.5*FakeElectronPassIDMVANonTrigVeto/FakeElectrons );
  cout << "IDMVANonTrig Cut Value @ 50% IDMVA NonTrig Veto Bkg Eff: " << CutValue_IDMVANonTrig_HalfBkg << endl;

  TLegend* legend;
  TCanvas* cv;
  string plotname;

  //*****************************************************************************************
  //Plot ROC Curves
  //*****************************************************************************************
  vector<TGraphAsymmErrors*> ROCGraphs;
  vector<string> GraphLabels;
  vector<Int_t> colors;

  //*****************************************************************************************
  //*****************************************************************************************
  ROCGraphs.clear();
  GraphLabels.clear();
  plotname = "ElectronIDMVA"+label;

  // ROCGraphs.push_back(ROC_IDMVATrig);
  // GraphLabels.push_back("IDMVATrig");
  // colors.push_back(kBlue);
  
  ROCGraphs.push_back(ROC_IDMVANonTrig);
  GraphLabels.push_back("IDMVANonTrig");
  colors.push_back(kGreen+2);
  


  //*****************************************************************************************
  Double_t xmin = 0.0;
  Double_t xmax = 1.0;
  Double_t ymin = 0.0;
  Double_t ymax = 1.0;




  cv = new TCanvas("cv", "cv", 800, 600);

//    legend = new TLegend(0.45,0.20,0.75,0.50);
  legend = new TLegend(0.54,0.14,0.94,0.44);
  legend->SetTextSize(0.03);
  legend->SetBorderSize(0);
  legend->SetFillStyle(0);
  for (UInt_t i=0; i<GraphLabels.size(); ++i) {
    legend->AddEntry(ROCGraphs[i],GraphLabels[i].c_str(), "LP");

    ROCGraphs[i]->SetMarkerColor(colors[i]);
    ROCGraphs[i]->SetLineColor(colors[i]);
    ROCGraphs[i]->SetMarkerSize(0.5);
   
    ROCGraphs[i]->GetXaxis()->SetRangeUser(xmin,xmax);    
    ROCGraphs[i]->GetYaxis()->SetRangeUser(ymin,ymax);    
    if (i==0) {
      ROCGraphs[i]->Draw("AP");
    } else {
      ROCGraphs[i]->Draw("Psame");
    }
  }

  // legend->AddEntry(ROC_CSA14TightWP, "CSA14Tight WP", "P");
  // ROC_CSA14TightWP->SetFillColor(kRed);
  // ROC_CSA14TightWP->SetMarkerColor(kRed);
  // ROC_CSA14TightWP->SetMarkerStyle(34);
  // ROC_CSA14TightWP->SetMarkerSize(2.5);
  // ROC_CSA14TightWP->Draw("Psame");

  legend->AddEntry(ROC_CSA14LooseWP, "CSA14Loose WP", "P");
  ROC_CSA14LooseWP->SetFillColor(kBlue);
  ROC_CSA14LooseWP->SetMarkerColor(kBlue);
  ROC_CSA14LooseWP->SetMarkerStyle(34);
  ROC_CSA14LooseWP->SetMarkerSize(2.5);
  ROC_CSA14LooseWP->Draw("Psame");

  legend->AddEntry(ROC_CSA14VetoWP, "CSA14Veto WP", "P");
  ROC_CSA14VetoWP->SetFillColor(kGreen+3);
  ROC_CSA14VetoWP->SetMarkerColor(kGreen+3);
  ROC_CSA14VetoWP->SetMarkerStyle(34);
  ROC_CSA14VetoWP->SetMarkerSize(2.5);
  ROC_CSA14VetoWP->Draw("Psame");

   legend->AddEntry(ROC_IDMVANonTrigVetoWP, "IDMVANonTrigVeto WP", "P");
   ROC_IDMVANonTrigVetoWP->SetFillColor(kBlack);
   ROC_IDMVANonTrigVetoWP->SetMarkerColor(kBlack);
   ROC_IDMVANonTrigVetoWP->SetMarkerStyle(34);
   ROC_IDMVANonTrigVetoWP->SetMarkerSize(2.5);
   ROC_IDMVANonTrigVetoWP->Draw("Psame");

  // legend->AddEntry(ROC_IDMVATrigTightWP, "IDMVATrigTight WP", "P");
  // ROC_IDMVATrigTightWP->SetFillColor(kRed);
  // ROC_IDMVATrigTightWP->SetMarkerColor(kRed);
  // ROC_IDMVATrigTightWP->SetMarkerStyle(34);
  // ROC_IDMVATrigTightWP->SetMarkerSize(2.5);
  // ROC_IDMVATrigTightWP->Draw("Psame");


  legend->Draw();
  
  cv->SaveAs(("ROCGraphs_" + plotname + ".gif").c_str());

  gBenchmark->Show("WWTemplate");       
} 
void ProduceElectronEfficiencyPlots(const string inputfile, int wp, int option = -1, string label = "") {
 
  string Label = "";
  if (label != "") Label = "_" + label;

  //--------------------------------------------------------------------------------------------------------------
  // Settings 
  //============================================================================================================== 
  bool printdebug = false;


  //*****************************************************************************************
  //Make some histograms
  //*****************************************************************************************
  TH1F *histDenominatorPt = new TH1F ("histDenominatorPt",";Electron p_{T} [GeV/c^{2}]; Number of Events", 50, 0 , 100);
  TH1F *histNumeratorPt = new TH1F ("histNumeratorPt",";Electron p_{T} [GeV/c^{2}]; Number of Events", 50, 0 , 100);
  TH1F *histDenominatorEta = new TH1F ("histDenominatorEta",";Electron Eta; Number of Events", 50, -2.5 , 2.5);
  TH1F *histNumeratorEta = new TH1F ("histNumeratorEta",";Electron Eta; Number of Events", 50, -2.5 , 2.5);
  TH1F *histDenominatorPhi = new TH1F ("histDenominatorPhi",";Electron Phi; Number of Events", 50, 0 , 3.2);
  TH1F *histNumeratorPhi = new TH1F ("histNumeratorPhi",";Electron Phi; Number of Events", 50, 0 , 3.2);
  TH1F *histDenominatorRho = new TH1F ("histDenominatorRho",";Electron Rho; Number of Events", 50, 0 , 100);
  TH1F *histNumeratorRho = new TH1F ("histNumeratorRho",";Electron Rho; Number of Events", 50, 0 , 100);
  TH1F *histDenominatorNpv = new TH1F ("histDenominatorNpv",";Electron Npv; Number of Events", 50, 0 , 100);
  TH1F *histNumeratorNpv = new TH1F ("histNumeratorNpv",";Electron Npv; Number of Events", 50, 0 , 100);
  TH1F *histDenominatorNpu = new TH1F ("histDenominatorNpu",";Electron Npu; Number of Events", 50, 0 , 100);
  TH1F *histNumeratorNpu = new TH1F ("histNumeratorNpu",";Electron Npu; Number of Events", 50, 0 , 100);

  TH2F *histDenominatorPtEta = new TH2F ("histDenominatorPtEta",";Photon p_{T} [GeV/c] ; Photon #eta; Number of Events", 50, 0 , 200, 50, -3.0, 3.0);
  TH2F *histNumeratorPtEta = new TH2F ("histNumeratorPtEta",";Photon p_{T} [GeV/c] ; Photon #eta; Number of Events", 50, 0 , 200, 50, -3.0, 3.0);

  //*******************************************************************************************
  //Read file
  //*******************************************************************************************                
  ElectronTree *EleTree = new ElectronTree;
  EleTree->LoadTree(inputfile.c_str());
  EleTree->InitTree(ElectronTree::kEleTreeLight);

  cout << "Total Entries: " << EleTree->tree_->GetEntries() << "\n";
  int nentries = EleTree->tree_->GetEntries();
  for(UInt_t ientry=0; ientry < EleTree->tree_->GetEntries(); ientry++) {       	
    EleTree->tree_->GetEntry(ientry);

    if (ientry % 100000 == 0) cout << "Event " << ientry << endl;

    //Cuts
    if (EleTree->fEleGenPt < 5) continue;
    if (abs(EleTree->fEleGenEta) > 2.4) continue;

    //if (!(EleTree->fElePt > 5)) continue;
    //if (option == 1 && !passPreselection(EleTree)) continue;

    //for isolation efficiency, require that it passes ID first
    if (wp == 11) {
      if (!passIDMVANonTrigVeto(EleTree)) continue;
    }

    //for trigger require pass Tight
    if (wp >= 100) {
      if (!(EleTree->fPassTightSelection)) continue;
    }


    if (option == 0) {
      //**** PT - ETA ****
      histDenominatorPtEta->Fill(EleTree->fEleGenPt,EleTree->fEleGenEta);
      if(PassSelection(EleTree,wp)) {
	histNumeratorPtEta->Fill(EleTree->fEleGenPt,EleTree->fEleGenEta);
      }


      //**** PT ****
      histDenominatorPt->Fill(EleTree->fEleGenPt);

      //Numerator
      if(PassSelection(EleTree,wp)) {
        histNumeratorPt->Fill(EleTree->fEleGenPt);        
      }


      //**** Eta ****
      if (fabs(EleTree->fEleGenPt) > 30) {
	histDenominatorEta->Fill(EleTree->fEleGenEta);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorEta->Fill(EleTree->fEleGenEta);        
	}

      }

      //**** Phi ****
      if (fabs(EleTree->fEleGenEta) < 2.4) {
	histDenominatorPhi->Fill(EleTree->fEleGenPhi);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorPhi->Fill(EleTree->fEleGenPhi);        
	}

      }

      //**** Rho ****
      if (fabs(EleTree->fEleGenEta) < 2.4) {
	histDenominatorRho->Fill(EleTree->fRho);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorRho->Fill(EleTree->fRho);        
	}

      }
      //**** Npv ****
      if (fabs(EleTree->fEleGenEta) < 2.4) {
	histDenominatorNpv->Fill(EleTree->fNVertices);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorNpv->Fill(EleTree->fNVertices);        
	}

      }

      // //**** Npu ****
      // if (fabs(EleTree->fEleGenEta) < 2.4) {
      //   histDenominatorNpu->Fill(EleTree->);

      //   //Numerator
      //   if(PassSelection(EleTree,wp)) {
      //     histNumeratorNpu->Fill(EleTree->);        
      //   }

      // }
    }

    if (option == 1) {

      if (!(EleTree->fElePt > 0)) continue;

      //**** PT - ETA ****
      histDenominatorPtEta->Fill(EleTree->fElePt,EleTree->fEleEta);
      if(PassSelection(EleTree,wp)) {
	histNumeratorPtEta->Fill(EleTree->fElePt,EleTree->fEleEta);
      }


      //**** PT ****
      histDenominatorPt->Fill(EleTree->fElePt);

      //Numerator
      if(PassSelection(EleTree,wp)) {
        histNumeratorPt->Fill(EleTree->fElePt);        
      }


      //**** Eta ****
      if (fabs(EleTree->fElePt) > 30) {
	histDenominatorEta->Fill(EleTree->fEleEta);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorEta->Fill(EleTree->fEleEta);        
	}

      }

      //**** Phi ****
      if (fabs(EleTree->fEleEta) < 2.4) {
	histDenominatorPhi->Fill(EleTree->fElePhi);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorPhi->Fill(EleTree->fElePhi);        
	}

      }

      //**** Rho ****
      if (fabs(EleTree->fEleEta) < 2.4) {
	histDenominatorRho->Fill(EleTree->fRho);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorRho->Fill(EleTree->fRho);        
	}

      }
      //**** Npv ****
      if (fabs(EleTree->fEleEta) < 2.4) {
	histDenominatorNpv->Fill(EleTree->fNVertices);

	//Numerator
	if(PassSelection(EleTree,wp)) {
	  histNumeratorNpv->Fill(EleTree->fNVertices);        
	}

      }

      // //**** Npu ****
      // if (fabs(EleTree->fEleEta) < 2.4) {
      //   histDenominatorNpu->Fill(EleTree->);

      //   //Numerator
      //   if(PassSelection(EleTree,wp)) {
      //     histNumeratorNpu->Fill(EleTree->);        
      //   }

      // }
    }


  }


  //--------------------------------------------------------------------------------------------------------------
  // Make Efficiency Plots
  //==============================================================================================================

  TGraphAsymmErrors *efficiency_pt = createEfficiencyGraph(histNumeratorPt, histDenominatorPt, "Efficiency_Pt" , vector<double>() ,  -99, -99, 0, 1);
  TGraphAsymmErrors *efficiency_eta = createEfficiencyGraph(histNumeratorEta, histDenominatorEta, "Efficiency_Eta" , vector<double>() ,  -99, -99, 0, 1);
  TGraphAsymmErrors *efficiency_phi = createEfficiencyGraph(histNumeratorPhi, histDenominatorPhi, "Efficiency_Phi" , vector<double>() ,  -99, -99, 0, 1);
  TGraphAsymmErrors *efficiency_rho = createEfficiencyGraph(histNumeratorRho, histDenominatorRho, "Efficiency_Rho" , vector<double>() ,  -99, -99, 0, 1);
  TGraphAsymmErrors *efficiency_npv = createEfficiencyGraph(histNumeratorNpv, histDenominatorNpv, "Efficiency_Npv" , vector<double>() ,  -99, -99, 0, 1);
  TGraphAsymmErrors *efficiency_npu = createEfficiencyGraph(histNumeratorNpu, histDenominatorNpu, "Efficiency_Npu" , vector<double>() ,  -99, -99, 0, 1);  
  TH2F *efficiency_pteta = createEfficiencyHist2D(histNumeratorPtEta, histDenominatorPtEta, "Efficiency_PtEta" , vector<double>() ,vector<double>());  


  //--------------------------------------------------------------------------------------------------------------
  // Draw
  //==============================================================================================================
  TCanvas *cv =0;

  cv = new TCanvas("cv","cv",800,600);
  efficiency_pt->Draw("AP");
  efficiency_pt->SetTitle("");
  efficiency_pt->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_pt->GetXaxis()->SetTitle("Electron p_{T} [GeV/c]");
  efficiency_pt->GetYaxis()->SetTitle("Efficiency");
  efficiency_pt->GetYaxis()->SetTitleOffset(1.2);
  efficiency_pt->SetLineWidth(3);  
  cv->SaveAs(("Efficiency"+Label+"_Pt.gif").c_str());

  cv = new TCanvas("cv","cv",800,600);
  efficiency_eta->Draw("AP");
  efficiency_eta->SetTitle("");
  efficiency_eta->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_eta->GetXaxis()->SetTitle("Electron #eta");
  efficiency_eta->GetYaxis()->SetTitle("Efficiency");
  efficiency_eta->GetYaxis()->SetTitleOffset(1.2);
  efficiency_eta->SetLineWidth(3);  
  cv->SaveAs(("Efficiency"+Label+"_Eta.gif").c_str());

  cv = new TCanvas("cv","cv",800,600);
  efficiency_phi->Draw("AP");
  efficiency_phi->SetTitle("");
  efficiency_phi->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_phi->GetXaxis()->SetTitle("Electron #phi");
  efficiency_phi->GetYaxis()->SetTitle("Efficiency");
  efficiency_phi->GetYaxis()->SetTitleOffset(1.2);
  cv->SaveAs(("Efficiency"+Label+"_Phi.gif").c_str());

  cv = new TCanvas("cv","cv",800,600);
  efficiency_rho->Draw("AP");
  efficiency_rho->SetTitle("");
  efficiency_rho->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_rho->GetXaxis()->SetTitle("#rho");
  efficiency_rho->GetYaxis()->SetTitle("Efficiency");
  efficiency_rho->GetYaxis()->SetTitleOffset(1.2);
  cv->SaveAs(("Efficiency"+Label+"_Rho.gif").c_str());

  cv = new TCanvas("cv","cv",800,600);
  efficiency_npv->Draw("AP");
  efficiency_npv->SetTitle("");
  efficiency_npv->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_npv->GetXaxis()->SetTitle("Number of Reconstructed Primary Vertices");
  efficiency_npv->GetYaxis()->SetTitle("Efficiency");
  efficiency_npv->GetYaxis()->SetTitleOffset(1.2);
  efficiency_npv->SetLineWidth(3);  
  efficiency_npv->GetXaxis()->SetRangeUser(0,40);
  cv->SaveAs(("Efficiency"+Label+"_Npv.gif").c_str());

  cv = new TCanvas("cv","cv",800,600);
  efficiency_npu->Draw("AP");
  efficiency_npu->SetTitle("");
  efficiency_npu->GetYaxis()->SetRangeUser(0.0,1.0);
  efficiency_npu->GetXaxis()->SetTitle("Number of Pileup Interactions");
  efficiency_npu->GetYaxis()->SetTitle("Efficiency");
  efficiency_npu->GetYaxis()->SetTitleOffset(1.2);
  cv->SaveAs(("Efficiency"+Label+"_Npu.gif").c_str());


  //--------------------------------------------------------------------------------------------------------------
  // Output
  //==============================================================================================================
  TFile *file = TFile::Open(("Efficiency"+Label+".root").c_str(), "UPDATE");
  file->cd();
  file->WriteTObject(efficiency_pt, "Efficiency_Pt", "WriteDelete");
  file->WriteTObject(efficiency_eta, "Efficiency_Eta", "WriteDelete");
  file->WriteTObject(efficiency_phi, "Efficiency_Phi", "WriteDelete");
  file->WriteTObject(efficiency_rho, "Efficiency_Rho", "WriteDelete");
  file->WriteTObject(efficiency_npv, "Efficiency_NPV", "WriteDelete");
  file->WriteTObject(efficiency_npu, "Efficiency_NPU", "WriteDelete");
  file->WriteTObject(efficiency_pteta, "Efficiency_PtEta", "WriteDelete");

  file->Close();
  delete file;       

}