void analysisClass::Loop()
{
   std::cout << "analysisClass::Loop() begins" <<std::endl;   
   TStopwatch time;
   frame("Starting the analysis");
   time.Start(true);
   setTDRStyle();
   if (fChain == 0) return;
   
   //////////book histos here

   // TH1F *h_nJetFinal = new TH1F ("h_nJetFinal","",10,0,10);
   // h_nJetFinal->Sumw2();      
   // TH1F *h_nVtx = new TH1F ("h_nVtx","",30,0,30);
   // h_nVtx->Sumw2(); 
   // TH1F *h_trueVtx = new TH1F ("h_trueVtx","",40,0,40);
   // h_trueVtx->Sumw2();  
   // TH1F *h_pT1stJet = new TH1F ("h_pT1stJet","",100,0,3000);
   // h_pT1stJet->Sumw2();
   // TH1F *h_pT2ndJet = new TH1F ("h_pT2ndJet","",100,0,3000);
   // h_pT2ndJet->Sumw2();
   // TH1F *h_eta1stJet = new TH1F ("h_eta1stJet","",5,-2.5,2.5);
   // h_eta1stJet->Sumw2();
   // TH1F *h_eta2ndJet = new TH1F ("h_eta2ndJet","",5,-2.5,2.5);
   // h_eta2ndJet->Sumw2();
   // TH1F *h_DijetMass = new TH1F ("h_DijetMass","",600,0,6000);
   // h_DijetMass->Sumw2();
   // TH1F *h_DeltaETAjj = new TH1F ("h_DeltaETAjj","",120,0,3.);
   // h_DeltaETAjj->Sumw2();

   /////////initialize variables

   Long64_t nentries = fChain->GetEntriesFast();
   std::cout << "analysisClass::Loop(): nentries = " << nentries << std::endl;   

   double lepton_mass;
   std::vector <int> goodLepton, looseLepton, goodAK08, goodAK04, goodAK08_lep, goodAK04_lep, goodAK08Pruned, goodEle, goodMuon, looseEle, looseMuon;
   TLorentzVector genW, ak04, ak08, ak08Pruned, lepton, leptonLoose, W, MET, wGenQ1, wGenQ2, wGenSumi, subjet1, subjet2, subjetSum, wGenSum, bGen1, bGen2;
   int btag_ak04_loose, btag_ak04_medium, btag_ak04_tight;
   int subjet_index1, subjet_index2;
   ////// The following ~7 lines have been taken from rootNtupleClass->Loop() /////
   ////// If the root version is updated and rootNtupleClass regenerated,     /////
   ////// these lines may need to be updated.                                 /////    
   Long64_t nbytes = 0, nb = 0;
   for (Long64_t jentry=0; jentry<nentries;jentry++) {
   //for (Long64_t jentry=0; jentry<1000;jentry++) {
     Long64_t ientry = LoadTree(jentry);
     if (ientry < 0) break;
     nb = fChain->GetEntry(jentry);   nbytes += nb;
     if(jentry < 10 || jentry%1000 == 0) std::cout << "analysisClass::Loop(): jentry = " << jentry << std::endl;   
     // if (Cut(ientry) < 0) continue;

     ////////////////////// User's code starts here ///////////////////////

     ///Stuff to be done for every event
     btag_ak04_loose=0;
     btag_ak04_medium=0;
     btag_ak04_tight=0;
     goodLepton.clear();
     looseLepton.clear();
     goodAK04.clear();
     goodAK08.clear();
     goodAK08_lep.clear();
     goodAK04_lep.clear();
     goodAK08Pruned.clear();
     goodEle.clear();
     goodMuon.clear();
     looseEle.clear();
     looseMuon.clear();

     resetCuts();
   

//=== Forse da inserire ===

/*     fillVariableWithValue("run",runNo);     
     fillVariableWithValue("event",evtNo);     
     fillVariableWithValue("lumi",lumi);     
     fillVariableWithValue("nVtx",nvtx);     
     fillVariableWithValue("nJet",widejets.size());
*/
    

    for(int i=0; i<nselLeptons; ++i){
      if((abs(selLeptons_pdgId[i])==11 && selLeptons_isMyGoodElectron[i]==1 && selLeptons_pt[i]>30 && (abs(selLeptons_eta[i])<1.442 || (abs(selLeptons_eta[i])>1.56 && abs(selLeptons_eta[i])<2.5))) || (abs(selLeptons_pdgId[i])==13 && selLeptons_isMyGoodMuon[i]==1 && selLeptons_pt[i]>30 && abs(selLeptons_eta[i])<2.1)){// && selLeptons_relIso03[0]<0.1)){
        goodLepton.push_back(i);
        //std::cout<<"Passing tight selection"<<std::endl;
        CreateAndFillUserTH1D("goodEleTightSelection", 2,-.5,1.5, 1);
      }//end if 'good' lepton cuts
      else if(((abs(selLeptons_pdgId[i])==11 && selLeptons_isMyGoodElectron[i]==1 && selLeptons_pt[i]>35 && (abs(selLeptons_eta[i])<1.442 || (abs(selLeptons_eta[i])>1.56 && abs(selLeptons_eta[i])<2.5))) || (abs(selLeptons_pdgId[i])==13 && selLeptons_isMyGoodMuon[i]==1 && selLeptons_pt[i]>20 && abs(selLeptons_eta[i])<2.1))){// && selLeptons_relIso03[i]<0.1))){
        looseLepton.push_back(i);
        //if(abs(selLeptons_pdgId[i])==11) lepton_mass=e_mass;
        //if(abs(selLeptons_pdgId[i])==13) lepton_mass=mu_mass;
        //leptonLoose.SetPtEtaPhiM(selLeptons_pt[i],selLeptons_eta[i],selLeptons_phi[i], lepton_mass);
      }//end if loose lepton
      if(abs(selLeptons_pdgId[i])==13 && selLeptons_isMyGoodMuon[i]==1 && selLeptons_pt[i]>53 && abs(selLeptons_eta[i])<2.1 && (selLeptons_muTrackIso[i]/selLeptons_pt[i])<0.1){
        goodMuon.push_back(i);
      }
      else if(abs(selLeptons_pdgId[i])==13 && selLeptons_isMyGoodMuon[i]==1 && selLeptons_pt[i]>20 && abs(selLeptons_eta[i])<2.4 && (selLeptons_muTrackIso[i]/selLeptons_pt[i])<0.1){
        // if(abs(selLeptons_pdgId[i])==13 && selLeptons_isMyGoodMuon[i]==1 && selLeptons_pt[i]>53 && abs(selLeptons_eta[i])<2.1 && (selLeptons_muTrackIso[i]/selLeptons_pt[i])<0.1){
        looseMuon.push_back(i);
        
      }
      if(abs(selLeptons_pdgId[i])==11 && selLeptons_isMyGoodElectron[i]==1 && selLeptons_pt[i]>120 && abs(selLeptons_eta[i])<2.1){
        goodEle.push_back(i);
      }else if((abs(selLeptons_pdgId[i])==11 && selLeptons_isMyGoodElectron[i]==1 && selLeptons_pt[i]>35 && abs(selLeptons_eta[i])<2.4)){
        looseEle.push_back(i);
      }
    }//end if nselLeptons

    for(int i=0; i<nFatjetAK08ungroomed;++i){
      if((((FatjetAK08ungroomed_neHEFrac[i]<0.99 && FatjetAK08ungroomed_neEmEFrac[i]<0.99 && (FatjetAK08ungroomed_chMult[i]+FatjetAK08ungroomed_neMult[i])>1) && ((abs(FatjetAK08ungroomed_eta[i])<=2.4 && FatjetAK08ungroomed_chHEFrac[i]>0 && FatjetAK08ungroomed_chMult[i]>0 && FatjetAK08ungroomed_chEmEFrac[i]<0.99) || abs(FatjetAK08ungroomed_eta[i])>2.4) && abs(FatjetAK08ungroomed_eta[i])<=3.0)||((FatjetAK08ungroomed_neEmEFrac[i]<0.90 && FatjetAK08ungroomed_neMult[i]>10 && abs(FatjetAK08ungroomed_eta[i])>3.0 ))) && FatjetAK08ungroomed_pt[i]>100 && abs(FatjetAK08ungroomed_eta[i])<2.4){
        goodAK08.push_back(i);
      }//end if good AK08
    }//end loop over nFatjetAK08ungroomed

    for(int i=0; i<nJet; ++i){
      if((((Jet_neHEF[i]<0.99 && Jet_neEmEF[i]<0.99 && (Jet_chMult[i]+Jet_neMult[i])>1) && ((abs(Jet_eta[i])<=2.4 && Jet_chHEF[i]>0 && Jet_chMult[i]>0 && Jet_chEmEF[i]<0.99) || abs(Jet_eta[i])>2.4) && abs(Jet_eta[i])<=3.0)||((Jet_neEmEF[i]<0.90 && Jet_neMult[i]>10 && abs(Jet_eta[i])>3.0 ))) && Jet_pt[i]>30 && abs(Jet_eta[i])<2.4){
        CreateAndFillUserTH1D("goodAk04LooseSelection", 2,-.5,1.5, 1);
        goodAK04.push_back(i);
      }
    }//end loop over nJet

    fillVariableWithValue("lepton_goodNumber", goodLepton.size());
    fillVariableWithValue("lepton_looseNumber", looseLepton.size());
    fillVariableWithValue("ak08_goodNumber", goodAK08.size());
    fillVariableWithValue("nLepton",nselLeptons);
    fillVariableWithValue("nGoodEle", goodEle.size());
    fillVariableWithValue("nLooseEle", looseEle.size());
    fillVariableWithValue("nGoodMuon", goodMuon.size());
    fillVariableWithValue("nLooseMuon", looseMuon.size());
    if(goodAK08.size()>=1){
      fillVariableWithValue("ak08Ungroomed_1_pt", FatjetAK08ungroomed_pt[goodAK08[0]]);
      fillVariableWithValue("ak08Ungroomed_1_eta", FatjetAK08ungroomed_eta[goodAK08[0]]);
      fillVariableWithValue("ak08Ungroomed_1_phi", FatjetAK08ungroomed_phi[goodAK08[0]]);
      fillVariableWithValue("ak08Ungroomed_1_mass", FatjetAK08ungroomed_mass[goodAK08[0]]);
      fillVariableWithValue("ak08Ungroomed_1_tau21", FatjetAK08ungroomed_tau2[goodAK08[0]]/FatjetAK08ungroomed_tau1[goodAK08[0]]);
      ak08.SetPtEtaPhiM(FatjetAK08ungroomed_pt[goodAK08[0]], FatjetAK08ungroomed_eta[goodAK08[0]], FatjetAK08ungroomed_phi[goodAK08[0]], FatjetAK08ungroomed_mass[goodAK08[0]]);
      double minDR_subjetJet=999.;
      subjet_index1=subjet_index2=0;
      for(int s=0; s<nSubjetAK08pruned; ++s){
        subjet1.SetPtEtaPhiM(SubjetAK08pruned_pt[s], SubjetAK08pruned_eta[s], SubjetAK08pruned_phi[s], SubjetAK08pruned_mass[s]);
        for(int ss=0; ss<nSubjetAK08pruned; ++ss){
          if(ss!=s){
            subjet2.SetPtEtaPhiM(SubjetAK08pruned_pt[ss], SubjetAK08pruned_eta[ss], SubjetAK08pruned_phi[ss], SubjetAK08pruned_mass[ss]);
            subjetSum=subjet1+subjet2;
            if(subjetSum.DeltaR(ak08)){
              minDR_subjetJet=subjetSum.DeltaR(ak08);
              subjet_index1=s;
              subjet_index2=ss;
            }
          }
        }
      }//end loop over subjets
      fillVariableWithValue("ak08_subjetDR", minDR_subjetJet);
      if(nSubjetAK08pruned>0){
        subjet1.SetPtEtaPhiM(SubjetAK08pruned_pt[subjet_index1], SubjetAK08pruned_eta[subjet_index1], SubjetAK08pruned_phi[subjet_index1], SubjetAK08pruned_mass[subjet_index1]);
        subjet2.SetPtEtaPhiM(SubjetAK08pruned_pt[subjet_index2], SubjetAK08pruned_eta[subjet_index2], SubjetAK08pruned_phi[subjet_index2], SubjetAK08pruned_mass[subjet_index2]);
        if(SubjetAK08pruned_btag[subjet_index1]>0.605) fillVariableWithValue("subjet1_btagLoose", 1);
        if(SubjetAK08pruned_btag[subjet_index1]>0.89) fillVariableWithValue("subjet1_btagMedium", 1);
        if(SubjetAK08pruned_btag[subjet_index1]>0.97) fillVariableWithValue("subjet1_btagTight", 1);
        if(SubjetAK08pruned_btag[subjet_index2]>0.605) fillVariableWithValue("subjet2_btagLoose", 1);
        if(SubjetAK08pruned_btag[subjet_index2]>0.89) fillVariableWithValue("subjet2_btagMedium", 1);
        if(SubjetAK08pruned_btag[subjet_index2]>0.97) fillVariableWithValue("subjet2_btagTight", 1);
        fillVariableWithValue("subjetDR", subjet1.DeltaR(subjet2));
        fillVariableWithValue("subjet1_pt", SubjetAK08pruned_pt[subjet_index1]);
        fillVariableWithValue("subjet1_eta", SubjetAK08pruned_eta[subjet_index1]);
        fillVariableWithValue("subjet1_phi", SubjetAK08pruned_phi[subjet_index1]);
        fillVariableWithValue("subjet2_pt", SubjetAK08pruned_pt[subjet_index2]);
        fillVariableWithValue("subjet2_eta", SubjetAK08pruned_eta[subjet_index2]);
        fillVariableWithValue("subjet2_phi", SubjetAK08pruned_phi[subjet_index2]);

      }
      double minDR_W=999;
      int w_counter=0;
      if(isData==0){
        if(nGenWZQuark==2){
          wGenQ1.SetPtEtaPhiM(GenWZQuark_pt[0], GenWZQuark_eta[0], GenWZQuark_phi[0], GenWZQuark_mass[0]);
          wGenQ2.SetPtEtaPhiM(GenWZQuark_pt[1], GenWZQuark_eta[1], GenWZQuark_phi[1], GenWZQuark_mass[1]);
          fillVariableWithValue("genQ1_pt", GenWZQuark_pt[0]);
          fillVariableWithValue("genQ1_eta", GenWZQuark_eta[0]);
          fillVariableWithValue("genQ1_phi", GenWZQuark_phi[0]);
          fillVariableWithValue("genQ2_pt", GenWZQuark_pt[1]);
          fillVariableWithValue("genQ2_eta", GenWZQuark_eta[1]);
          fillVariableWithValue("genQ2_phi", GenWZQuark_phi[1]);
          fillVariableWithValue("genQ_DR", wGenQ1.DeltaR(wGenQ2));
          if(nSubjetAK08pruned>0){
            fillVariableWithValue("subjet1_qGen1_DR", TMath::Min(wGenQ1.DeltaR(subjet1), wGenQ2.DeltaR(subjet1)));
            fillVariableWithValue("subjet2_qGen2_DR", TMath::Min(wGenQ1.DeltaR(subjet2), wGenQ2.DeltaR(subjet2)));
            //std::cout<<"1. "<<TMath::Min(wGenQ1.DeltaR(subjet1), wGenQ2.DeltaR(subjet1))<<std::endl;
            //std::cout<<"2. "<<TMath::Min(wGenQ1.DeltaR(subjet2), wGenQ2.DeltaR(subjet2))<<std::endl;
          }else{
            fillVariableWithValue("subjet1_qGen1_DR", -1);
            fillVariableWithValue("subjet2_qGen2_DR", -1);
          }
          wGenSum=wGenQ1+wGenQ2;
          for (int w=0; w<nGenVbosons; ++w){
            if(abs(GenVbosons_pdgId[w])==24){
              genW.SetPtEtaPhiM(GenVbosons_pt[w], GenVbosons_eta[w], GenVbosons_phi[w], W_mass);
              if(goodLepton.size()>=1){
                if(abs(selLeptons_pdgId[goodLepton[0]])==11) lepton_mass=e_mass;
                if(abs(selLeptons_pdgId[goodLepton[0]])==13) lepton_mass=mu_mass;
                  lepton.SetPtEtaPhiM(selLeptons_pt[goodLepton[0]],selLeptons_eta[goodLepton[0]],selLeptons_phi[goodLepton[0]], lepton_mass);
              } 
              if(wGenSum.DeltaR(genW)<minDR_W){
                minDR_W=wGenSum.DeltaR(genW);
                w_counter=w;
              }
           }//if gen Boson==W
          }
          genW.SetPtEtaPhiM(GenVbosons_pt[w_counter], GenVbosons_eta[w_counter], GenVbosons_phi[w_counter], W_mass);
          fillVariableWithValue("ak08Ungroomed_WGen_DR",ak08.DeltaR(genW));
          fillVariableWithValue("WGen_quark_DR", minDR_W);
          fillVariableWithValue("W_Gen_pt", GenVbosons_pt[w_counter]);
          fillVariableWithValue("W_Gen_eta", GenVbosons_eta[w_counter]);
          fillVariableWithValue("W_Gen_phi", GenVbosons_phi[w_counter]);
          fillVariableWithValue("lepton_WGen_DR", lepton.DeltaR(genW));
          bGen1.SetPtEtaPhiM(GenBQuarkFromTop_pt[0],GenBQuarkFromTop_eta[0],GenBQuarkFromTop_phi[0],GenBQuarkFromTop_mass[0]);
          bGen2.SetPtEtaPhiM(GenBQuarkFromTop_pt[1],GenBQuarkFromTop_eta[1],GenBQuarkFromTop_phi[1],GenBQuarkFromTop_mass[1]);
          fillVariableWithValue("genW_genBquark1_DR", genW.DeltaR(bGen1));
          fillVariableWithValue("genW_genBquarkMin_DR", TMath::Min(genW.DeltaR(bGen1), genW.DeltaR(bGen2)));
          fillVariableWithValue("genW_genBquarkMax_DR", TMath::Max(genW.DeltaR(bGen1), genW.DeltaR(bGen2)));
          //std::cout<<"1. "<<genW.DeltaR(bGen1)<<std::endl;
          fillVariableWithValue("genW_genBquark2_DR", genW.DeltaR(bGen2));
         // std::cout<<"2. "<<genW.DeltaR(bGen2)<<std::endl;
        }else{//end if 2 quarks from VBosons
          fillVariableWithValue("subjet1_qGen1_DR", -1);
          fillVariableWithValue("subjet2_qGen2_DR", -1);
        }
      }//end if isData
      else{
        fillVariableWithValue("ak08Ungroomed_WGen_DR",minDR_W);
        fillVariableWithValue("lepton_WGen_DR", minDR_W);
      }
      double dr_tmp=99;
      int index=0;
      for(int ii=0; ii<nFatjetAK08pruned; ++ii){
        ak08Pruned.SetPtEtaPhiM(FatjetAK08pruned_pt[ii],FatjetAK08pruned_eta[ii], FatjetAK08pruned_phi[ii], FatjetAK08pruned_mass[ii]);
        if(ak08.DeltaR(ak08Pruned)<dr_tmp){
          dr_tmp=ak08.DeltaR(ak08Pruned);
          index=ii;
        }//matched good pruned AK08
        goodAK08Pruned.push_back(index);
      }//end loop over nFatjetAK08pruned

    }//end if ak08GoodUngroomed jet
    else{
      fillVariableWithValue("ak08Ungroomed_WGen_DR",999);
    }

    if(goodLepton.size()>=1){
      if(abs(selLeptons_pdgId[goodLepton[0]])==11) lepton_mass=e_mass;
      if(abs(selLeptons_pdgId[goodLepton[0]])==13) lepton_mass=mu_mass;
      lepton.SetPtEtaPhiM(selLeptons_pt[goodLepton[0]],selLeptons_eta[goodLepton[0]],selLeptons_phi[goodLepton[0]], lepton_mass);
      fillVariableWithValue("lepton_pt", selLeptons_pt[goodLepton[0]]);
      fillVariableWithValue("lepton_eta", selLeptons_eta[goodLepton[0]]);
      fillVariableWithValue("lepton_phi", selLeptons_phi[goodLepton[0]]);
      fillVariableWithValue("lepton_pdgID", selLeptons_pdgId[goodLepton[0]]);
      fillVariableWithValue("muonRelIso03", selLeptons_relIso03[0]);
      fillVariableWithValue("muontrkIso", selLeptons_muTrackIso[0]);
      MET.SetPtEtaPhiM(met_pt, met_eta, met_phi, 0);
      W=lepton+MET;
      fillVariableWithValue("W_pt", W.Pt());
      fillVariableWithValue("W_eta",W.Eta());
      fillVariableWithValue("W_phi",W.Phi());
      fillVariableWithValue("W_mT", 2*abs(MET.Pt())*abs(lepton.Pt())*(1-cos(lepton.DeltaPhi(MET))));
      //fillVariableWithValue("W_mT",W.Mt());
      MET.SetPtEtaPhiM(metType1p2_pt, met_eta, met_phi, 0);
      W=lepton+MET;
      fillVariableWithValue("WType1_pt", W.Pt());
      fillVariableWithValue("WType1_eta",W.Eta());
      fillVariableWithValue("WType1_phi",W.Phi());
      fillVariableWithValue("W_mT", 2*abs(MET.Pt())*abs(lepton.Pt())*(1-cos(lepton.DeltaPhi(MET))));
      //fillVariableWithValue("WType1_mT",W.Mt());
      //MET.SetPtEtaPhiM(metPuppi_pt, met_eta, met_phi, 0); 
      //W=lepton+MET;
      //fillVariableWithValue("WPuppi_pt", W.Pt());
      //fillVariableWithValue("WPuppi_eta",W.Eta());
      //fillVariableWithValue("WPuppi_phi",W.Phi());
      //fillVariableWithValue("W_mT", 2*abs(MET.Pt())*abs(lepton.Pt())*(1-cos(lepton.DeltaPhi(MET))));
      //fillVariableWithValue("WPuppi_mT",W.Mt());

      if(goodAK08.size()>1) fillVariableWithValue("ak08Ungroomed_lepton_DR", lepton.DeltaR(ak08));
      fillVariableWithValue("nAK04", goodAK04.size());
        for(int j=0; j<goodAK04.size(); ++j){
          ak04.SetPtEtaPhiM(Jet_pt[goodAK04[j]], Jet_eta[goodAK04[j]], Jet_phi[goodAK04[j]], Jet_mass[goodAK04[j]]);
          if(ak04.DeltaR(ak08)>.8 && ak04.DeltaR(lepton)>.3){
            CreateAndFillUserTH1D("Ak04_lepton&AK08_DRCut", 2,-.5,1.5, 1);
            goodAK04_lep.push_back(goodAK04[j]);
            if(Jet_btagCSV[goodAK04[j]]>0.605){
              ++btag_ak04_loose;
            }
            if(Jet_btagCSV[goodAK04[j]]>0.890){
              ++btag_ak04_medium;
            }
            if(Jet_btagCSV[goodAK04[j]]>0.97){
              ++btag_ak04_tight;
            }//end if for CSV medium working point
          }//end if ak04 without leptons and ak08 nearby
        }//end loop over goodAK04.size()

      }//end loop over goodLepton.size()
      if(goodLepton.size()>=2){
        fillVariableWithValue("lepton2_pt", selLeptons_pt[goodLepton[1]]);
        fillVariableWithValue("lepton2_eta", selLeptons_eta[goodLepton[1]]);
        fillVariableWithValue("lepton2_phi", selLeptons_phi[goodLepton[1]]);
        fillVariableWithValue("lepton2_pdgID", selLeptons_pdgId[goodLepton[1]]);
      }
      fillVariableWithValue("btag_loose",btag_ak04_loose);
      fillVariableWithValue("btag_medium",btag_ak04_medium);
      fillVariableWithValue("btag_tight",btag_ak04_tight);
      if(goodAK08Pruned.size()>=1){
        fillVariableWithValue("ak08Pruned_1_pt", FatjetAK08pruned_pt[goodAK08Pruned[0]]);
        fillVariableWithValue("ak08Pruned_1_eta", FatjetAK08pruned_eta[goodAK08Pruned[0]]);
        fillVariableWithValue("ak08Pruned_1_phi", FatjetAK08pruned_phi[goodAK08Pruned[0]]);
        fillVariableWithValue("ak08Pruned_1_mass", FatjetAK08pruned_mass[goodAK08Pruned[0]]);
      }
      if(goodAK08Pruned.size()>=2){
        fillVariableWithValue("ak08Pruned_2_pt", FatjetAK08pruned_pt[goodAK08Pruned[1]]);
        fillVariableWithValue("ak08Pruned_2_eta", FatjetAK08pruned_eta[goodAK08Pruned[1]]);
        fillVariableWithValue("ak08Pruned_2_phi", FatjetAK08pruned_phi[goodAK08Pruned[1]]);
        fillVariableWithValue("ak08Pruned_2_mass", FatjetAK08pruned_mass[goodAK08Pruned[1]]);
      }
      if(goodAK04_lep.size()>=1){
        fillVariableWithValue("ak04_1_pt", Jet_pt[goodAK04_lep[0]]);
        fillVariableWithValue("ak04_1_eta", Jet_eta[goodAK04_lep[0]]);
        fillVariableWithValue("ak04_1_phi", Jet_phi[goodAK04_lep[0]]);
        fillVariableWithValue("ak04_1_mass", Jet_mass[goodAK04_lep[0]]);
        //=== TH1D to check the fillReduceSkim procedure ===
        CreateAndFillUserTH1D("ak04_first_pt", 1000,0,500, Jet_pt[goodAK04_lep[0]]);
      }
      if(goodAK04_lep.size()>=2){
        fillVariableWithValue("ak04_2_pt", Jet_pt[goodAK04_lep[1]]);
        fillVariableWithValue("ak04_2_eta", Jet_eta[goodAK04_lep[1]]);
        fillVariableWithValue("ak04_2_phi", Jet_phi[goodAK04_lep[1]]);
        fillVariableWithValue("ak04_2_mass", Jet_mass[goodAK04_lep[1]]);
      }
      //fillVariableWithValue("metPuppi",metPuppi_pt);
      fillVariableWithValue("metType1", metType1p2_pt);
      fillVariableWithValue("met",met_pt);
      fillVariableWithValue("nPrimaryVertexes", nPVs);
      fillVariableWithValue("Mu45_TRG", HLT_HLT_Mu45_eta2p1);
      fillVariableWithValue("Mu50_TRG", HLT_HLT_Mu50);
      fillVariableWithValue("HBHE", Flag_HBHENoiseFilter);
      fillVariableWithValue("HBHE_IsoFilter", Flag_hbheIsoFilter);
      fillVariableWithValue("CSC_filter",Flag_CSCTightHaloFilter);
      fillVariableWithValue("eeBADFilter", Flag_eeBadScFilter);
      fillVariableWithValue("run", run);
      fillVariableWithValue("nBtag_gen",nGenBQuarkFromTop); 



     // Evaluate cuts (but do not apply them)
     evaluateCuts();
     //fillReducedSkimTree(); 

     // optional call to fill a skim with the full content of the input roottuple
     //if( passedCut("nJetFinal") ) fillSkimTree();
     
     // optional call to fill a skim with a subset of the variables defined in the cutFile (use flag SAVE)
     //if( passedAllPreviousCuts("mjj") && passedCut("mjj") ) 
     if( passedCut("met"))//passedAllPreviousCuts("eeBADFilter") && passedCut("eeBADFilter"))
       {
         //frame("Beware! This part can be set outside the if -Passed cuts-");
	 fillReducedSkimTree();
	 
	 // ===== Take a look at this =====
	 // //Example on how to investigate quickly the data
 	 // if(getVariableValue("mjj")>4000)
	 //   {
	 //     //fast creation and filling of histograms
	 //     CreateAndFillUserTH1D("h_dphijj_mjjgt4000", 100, 0, 3.15, getVariableValue("deltaPHIjj"));
	 //     CreateAndFillUserTH1D("h_htak4_mjjgt4000", 1000, 0, 10000, getVariableValue("HTAK4"));
	 //     CreateAndFillUserTH1D("h_nvtx_mjjgt4000", 31, -0.5, 30.5, getVariableValue("nVtx"));
	 //   }

       }

     // ===== Example of mjj spectrum after HLT selection =====
     // if( passedAllPreviousCuts("mjj") )
     //   {
     // 	 if(getVariableValue("passHLT")>0)
     // 	   {
     // 	     //fast creation and filling of histograms
     // 	     CreateAndFillUserTH1D("h_mjj_passHLT", getHistoNBins("mjj"), getHistoMin("mjj"), getHistoMax("mjj"), getVariableValue("mjj"));
     // 	   }
     //   }

     // reject events that did not pass level 0 cuts
     //if( !passedCut("0") ) continue;
     // ......
     
     // reject events that did not pass level 1 cuts
     //if( !passedCut("1") ) continue;
     // ......

     // reject events that did not pass the full cut list
     //if( !passedCut("all") ) continue;
     // ......

     // if( widejets.size() >= 2) {
     //  h_nJetFinal->Fill(widejets.size());
     //  h_DijetMass->Fill(wdijet.M());
     //  h_pT1stJet->Fill(widejets[0].Pt());
     //  h_pT2ndJet->Fill(widejets[1].Pt());
     //  h_eta1stJet->Fill(widejets[0].Eta());
     //  h_eta2ndJet->Fill(widejets[1].Eta());
     // }
     ////////////////////// User's code ends here ///////////////////////

   } // End loop over events

   //////////write histos 

   // h_nVtx->Write();
   // h_trueVtx->Write();
   // h_nJetFinal->Write();
   // h_pT1stJet->Write();
   // h_pT2ndJet->Write();
   // h_DijetMass->Write();
   // h_eta1stJet->Write();
   // h_eta2ndJet->Write();

   // //pT of both jets, to be built using the histograms produced automatically by baseClass
   // TH1F * h_pTJets = new TH1F ("h_pTJets","", getHistoNBins("pT1stJet"), getHistoMin("pT1stJet"), getHistoMax("pT1stJet"));
   // h_pTJets->Add( & getHisto_noCuts_or_skim("pT1stJet") ); // all histos can be retrieved, see other getHisto_xxxx methods in baseClass.h
   // h_pTJets->Add( & getHisto_noCuts_or_skim("pT2ndJet") );
   // //one could also do:  *h_pTJets = getHisto_noCuts_or_skim("pT1stJet") + getHisto_noCuts_or_skim("pT2ndJet");
   // h_pTJets->Write();
   // //one could also do:   const TH1F& h = getHisto_noCuts_or_skim// and use h

   std::cout << "analysisClass::Loop() ends" <<std::endl;   
   std::cout<<""<<std::endl;
   std::cout << "------ TIME ELAPSED DURING ANALYSIS  ----- " << time.RealTime() << " s" <<std::endl;
   std::cout<<""<<std::endl;
}
void analysisClass::Loop()
{
   std::cout << "analysisClass::Loop() begins" <<std::endl;   
    
   if (fChain == 0) return;
   
   //////////book histos here

  //////////book histos here

   TH1F *h_nJetFinal = new TH1F ("h_nJetFinal","",10,0,10);
   h_nJetFinal->Sumw2();      
   TH1F *h_nVtx = new TH1F ("h_nVtx","",30,0,30);
   h_nVtx->Sumw2();   
   TH1F *h_pT1stJet = new TH1F ("h_pT1stJet","",100,0,3000);
   h_pT1stJet->Sumw2();
   TH1F *h_pT2ndJet = new TH1F ("h_pT2ndJet","",100,0,3000);
   h_pT2ndJet->Sumw2();
   TH1F *h_eta1stJet = new TH1F ("h_eta1stJet","",5,-2.5,2.5);
   h_eta1stJet->Sumw2();
   TH1F *h_eta2ndJet = new TH1F ("h_eta2ndJet","",5,-2.5,2.5);
   h_eta2ndJet->Sumw2();
   TH1F *h_DijetMass = new TH1F ("h_DijetMass","",600,0,6000);
   h_DijetMass->Sumw2();
   TH1F *h_DeltaETAjj = new TH1F ("h_DeltaETAjj","",120,0,3.);
   h_DeltaETAjj->Sumw2();


   /////////initialize variables

   Long64_t nentries = fChain->GetEntriesFast();
   std::cout << "analysisClass::Loop(): nentries = " << nentries << std::endl;   

   ////// The following ~7 lines have been taken from rootNtupleClass->Loop() /////
   ////// If the root version is updated and rootNtupleClass regenerated,     /////
   ////// these lines may need to be updated.                                 /////    
   Long64_t nbytes = 0, nb = 0;
   for (Long64_t jentry=0; jentry<nentries;jentry++) {
     Long64_t ientry = LoadTree(jentry);
     if (ientry < 0) break;
     nb = fChain->GetEntry(jentry);   nbytes += nb;
     if(jentry < 10 || jentry%1000 == 0) std::cout << "analysisClass::Loop(): jentry = " << jentry << std::endl;   
     // if (Cut(ientry) < 0) continue;

     ////////////////////// User's code starts here ///////////////////////

     ///Stuff to be done every event
 
     Int_t no_jets_ak4=jetPtAK4->size();
     Int_t no_jets_ak8=jetPtAK8->size();
     vector<TLorentzVector> widejets;
     TLorentzVector currentJet, wj1_tmp, wj1, wj2_tmp, wj2, v_jet_ak4,wdijet,wj1math,wj2math;
     ////cone size wide 1.1
     double wideJetDeltaR_ = 1.1;

     resetCuts();
  
     //Eirini wide jet
     // if(no_jets_ak4>=2){
     //   if( fabs(jetEtaAK4->at(0)) < getPreCutValue1("jetFidRegion") && idTAK4->at(0) == getPreCutValue1("tightJetID")){
     // 	 if( fabs(jetEtaAK4->at(1)) < getPreCutValue1("jetFidRegion") && idTAK4->at(1) == getPreCutValue1("tightJetID")){
     // 	   TLorentzVector jet1, jet2;
     // 	   jet1.SetPtEtaPhiM(jetPtAK4->at(0),jetEtaAK4->at(0),jetPhiAK4->at(0),jetMassAK4->at(0));
     // 	   jet2.SetPtEtaPhiM(jetPtAK4->at(1),jetEtaAK4->at(1),jetPhiAK4->at(1),jetMassAK4->at(1));
	   
     // 	   for(Long64_t ijet=0; ijet<no_jets_ak4; ijet++){ //jet loop for ak4
     // 	     TLorentzVector currentJet;
	     
     // 	     if( fabs(jetEtaAK4->at(ijet)) < getPreCutValue1("jetFidRegion") && idTAK4->at(ijet) == getPreCutValue1("tightJetID")){
     // 	       TLorentzVector currentJet;
     // 	       currentJet.SetPtEtaPhiM(jetPtAK4->at(ijet),jetEtaAK4->at(ijet),jetPhiAK4->at(ijet),jetMassAK4->at(ijet));          
     // 	       double DeltaR1 = currentJet.DeltaR(jet1);
     // 	       double DeltaR2 = currentJet.DeltaR(jet2);

     // 	       if(DeltaR1 < DeltaR2 && DeltaR1 < wideJetDeltaR_){
     // 		 wj1_tmp += currentJet;
     // 	       }
     // 	       else if(DeltaR2 < wideJetDeltaR_){
     // 		 wj2_tmp += currentJet;
     // 	       }
	       
	       
     // 	     } // if AK4 jet passes fid and jetid.
     // 	   } //end of ak4 jet loop

     // 	   if(wj1_tmp.Pt()==0 && wj2_tmp.Pt() ==0) 
     // 	     std::cout << " wj1_tmp.Pt() IN  " <<wj1_tmp.Pt()  << " wj2_tmp.Pt() " <<  wj2_tmp.Pt()  << std::endl;
	   
     // 	 } //fid and jet id
     //   } //fid and jet id
     // } // end of two jets.

     // -------- Start Giulia Wide jet  --------------------- 
/////////////giulia
//use only jets pt>30, fiducial region and looseId
     
     if(no_jets_ak4>=2){
       if(!(jetPtAK4->at(0)>getPreCutValue1("jetPtCut") && fabs(jetEtaAK4->at(0)) < getPreCutValue1("jetFidRegion") && idLAK4->at(0) == getPreCutValue1("looseJetID"))){
     	 std::cout << " JET 0 FAIL " <<  jetEtaAK4->at(0) << " JET 0  ID " << idLAK4->at(0) << std::endl;

       }
       if(!(jetPtAK4->at(1)>getPreCutValue1("jetPtCut") && fabs(jetEtaAK4->at(1)) < getPreCutValue1("jetFidRegion") && idLAK4->at(1) == getPreCutValue1("looseJetID"))){
     	 std::cout << " JET 1 FAIL " << jetEtaAK4->at(1) << " JET 1  ID " << idTAK4->at(1) << std::endl;

       }  
     }
     //////////////////////////

     
     //code to create wide jets : use ak4 passing loose ID
     if(no_jets_ak4>=2){

       if( fabs(jetEtaAK4->at(0)) < getPreCutValue1("jetFidRegion") && idLAK4->at(0) == getPreCutValue1("looseJetID") && jetPtAK4->at(0)>getPreCutValue1("jetPtCut")){
     	 if( fabs(jetEtaAK4->at(1)) < getPreCutValue1("jetFidRegion") && idLAK4->at(1) == getPreCutValue1("looseJetID") && jetPtAK4->at(1)>getPreCutValue1("jetPtCut")){
     	   TLorentzVector jet1, jet2;
     	   jet1.SetPtEtaPhiM(jetPtAK4->at(0),jetEtaAK4->at(0),jetPhiAK4->at(0),jetMassAK4->at(0));
     	   jet2.SetPtEtaPhiM(jetPtAK4->at(1),jetEtaAK4->at(1),jetPhiAK4->at(1),jetMassAK4->at(1));
        
     	   for(Long64_t ijet=0; ijet<no_jets_ak4; ijet++){ //jet loop for ak4
     	     TLorentzVector currentJet;
          
     	     if( fabs(jetEtaAK4->at(ijet)) < getPreCutValue1("jetFidRegion") && idLAK4->at(ijet) == 1){
     	       TLorentzVector currentJet;
     	       currentJet.SetPtEtaPhiM(jetPtAK4->at(ijet),jetEtaAK4->at(ijet),jetPhiAK4->at(ijet),jetMassAK4->at(ijet));          
     	       double DeltaR1 = currentJet.DeltaR(jet1);
     	       double DeltaR2 = currentJet.DeltaR(jet2);
            
     	       if(DeltaR1 < DeltaR2 && DeltaR1 < wideJetDeltaR_){
     		 wj1_tmp += currentJet;
     	       }
     	       else if(DeltaR2 < wideJetDeltaR_){
     		 wj2_tmp += currentJet;
     	       }
            
            
     	     } // if AK4 jet passes fid and jetid.
     	   } //end of ak4 jet loop
        
     	   if(wj1_tmp.Pt()==0 && wj2_tmp.Pt() ==0) 
     	     std::cout << " wj1_tmp.Pt() IN  " <<wj1_tmp.Pt()  << " wj2_tmp.Pt() " <<  wj2_tmp.Pt()  << std::endl;
        
     	 } //fid and jet id j2
       } //fid and jet id j1
     } // end of two jets.
     //-------------- end Giulia Wide jet --------------------------     


     //
     if(wj1_tmp.Pt()==0 && wj2_tmp.Pt() ==0)     std::cout << " wj1_tmp.Pt()  " <<wj1_tmp.Pt()  << " wj2_tmp.Pt() " << wj2_tmp.Pt()  << "  no_jets_ak4 " << no_jets_ak4 << std::endl;
     //
     double MJJWide,DeltaEtaJJWide,DeltaPhiJJWide;
     
     if( wj1_tmp.Pt()>0 && wj2_tmp.Pt() >0 ){
       // Re-order the wide jets in pt
       if( wj1_tmp.Pt() > wj2_tmp.Pt()){
	 wj1 = wj1_tmp;
	 wj2 = wj2_tmp;
       }
       else{
	 wj1 = wj2_tmp;
	 wj2 = wj1_tmp;
       }
       
       // Create dijet system
       wdijet = wj1 + wj2;
       MJJWide = wdijet.M();
       DeltaEtaJJWide = fabs(wj1.Eta()-wj2.Eta());
       DeltaPhiJJWide = fabs(wj1.DeltaPhi(wj2));
       
       // Put widejets in the container
       wj1math.SetPtEtaPhiM(wj1.Pt(), wj1.Eta(), wj1.Phi(), wj1.M());
       wj2math.SetPtEtaPhiM(wj2.Pt(), wj2.Eta(), wj2.Phi(), wj2.M());  
       widejets.push_back( wj1math );
       widejets.push_back( wj2math );
     }
     


     fillVariableWithValue("nJetFinal",widejets.size()) ;
     fillVariableWithValue("nVtx",nvtx) ;
     fillVariableWithValue("ptHat", ptHat);    
     fillVariableWithValue("neutralHadronEnergyFraction_j1", jetNhfAK4->at(0));    
     fillVariableWithValue("photonEnergyFraction_j1", jetPhfAK4->at(0));    
     fillVariableWithValue("electronEnergyFraction_j1", jetElfAK4->at(0));         
     fillVariableWithValue("muonEnergyFraction_j1", jetMufAK4->at(0));    
     fillVariableWithValue("chargedHadronMultiplicity_j1", jetChfAK4->at(0));    
     fillVariableWithValue("neutralHadronEnergyFraction_j2", jetNhfAK4->at(1));    
     fillVariableWithValue("photonEnergyFraction_j2", jetPhfAK4->at(1));    
     fillVariableWithValue("electronEnergyFraction_j2", jetElfAK4->at(1));         
     fillVariableWithValue("muonEnergyFraction_j2", jetMufAK4->at(1));    
     fillVariableWithValue("chargedHadronMultiplicity_j2", jetChfAK4->at(1));    
     fillVariableWithValue("jetIdT1",idTAK4->at(0)) ;
     fillVariableWithValue("jetIdT2",idTAK4->at(1)) ;

     if( widejets.size() >= 1 )
       
       {
	 fillVariableWithValue( "pT1stJet", widejets[0].Pt() );
	 fillVariableWithValue( "eta1stJet", widejets[0].Eta());

	 
       }
     
     if( widejets.size() >= 2 )
       {
         fillVariableWithValue( "pT2ndJet", widejets[1].Pt() );
         fillVariableWithValue( "eta2ndJet", widejets[1].Eta());

	 
         // Calculate deltaETAjj
	 //giulia 
	 fillVariableWithValue( "deltaETAjj", DeltaEtaJJWide ) ;
	 
         // Calculate Mjj
         fillVariableWithValue( "Dijet_MassW", wdijet.M() ) ;
         fillVariableWithValue( "Dijet_MassAK8", mjjAK8 ) ;  
	 fillVariableWithValue( "Dijet_MassAK4", mjjAK4 ) ;  
	 //giulia - test
	 //fillVariableWithValue( "Dijet_MassC", mjjCA8 ) ;
	 if(wdijet.M()<1){
	   std::cout << " INV MASS IS " << wdijet.M() << std::endl;
	   std::cout << " Delta Eta IS " << DeltaEtaJJWide << " n is  " << widejets.size() << std::endl;
	   std::cout << " INV MASS FROM NTUPLE AK8 " << mjjAK8 << std::endl;
	   //std::cout << " INV MASS FROM NTUPLE CA8 " << mjjCA8 << std::endl;
	 }
       }
     
     // Evaluate cuts (but do not apply them)
     evaluateCuts();
     
     // optional call to fill a skim with the full content of the input roottuple
     if( passedCut("nJetFinal") ) fillSkimTree();
     
     // optional call to fill a skim with a subset of the variables defined in the cutFile (use flag SAVE)
     if( passedCut("nJetFinal") ) fillReducedSkimTree();

     // reject events that did not pass level 0 cuts
     if( !passedCut("0") ) continue;
     // ......
     
     // reject events that did not pass level 1 cuts
     if( !passedCut("1") ) continue;
     // ......

     // reject events that did not pass the full cut list
     if( !passedCut("all") ) continue;
     // ......

     if( widejets.size() >= 2) {
      h_nJetFinal->Fill(widejets.size());
      h_DijetMass->Fill(wdijet.M());
      h_pT1stJet->Fill(widejets[0].Pt());
      h_pT2ndJet->Fill(widejets[1].Pt());
      h_eta1stJet->Fill(widejets[0].Eta());
      h_eta2ndJet->Fill(widejets[0].Eta());
     }
     ////////////////////// User's code ends here ///////////////////////
     
   } // End loop over events
   
   //////////write histos 
   
   h_nVtx->Write();
   h_nJetFinal->Write();
   h_pT1stJet->Write();
   h_pT2ndJet->Write();
   h_DijetMass->Write();
   h_DeltaETAjj->Write();
   h_eta1stJet->Write();
   h_eta2ndJet->Write();

   //pT of both jets, to be built using the histograms produced automatically by baseClass
   TH1F * h_pTJets = new TH1F ("h_pTJets","", getHistoNBins("pT1stJet"), getHistoMin("pT1stJet"), getHistoMax("pT1stJet"));
   h_pTJets->Add( & getHisto_noCuts_or_skim("pT1stJet") ); // all histos can be retrieved, see other getHisto_xxxx methods in baseClass.h
   h_pTJets->Add( & getHisto_noCuts_or_skim("pT2ndJet") );
   //one could also do:  *h_pTJets = getHisto_noCuts_or_skim("pT1stJet") + getHisto_noCuts_or_skim("pT2ndJet");
   h_pTJets->Write();
   //one could also do:   const TH1F& h = getHisto_noCuts_or_skim// and use h

   std::cout << "analysisClass::Loop() ends" <<std::endl;   
}
void analysisClass::Loop()
{
  std::cout << "analysisClass::Loop() begins" <<std::endl;   

  srand48( time(0) );    
  if (fChain == 0) return;
   
  //////////book histos here


  /////////initialize variables

  Long64_t nentries = fChain->GetEntriesFast();
  std::cout << "analysisClass::Loop(): nentries = " << nentries << std::endl;   

  ////// The following ~7 lines have been taken from rootNtupleClass->Loop() /////
  ////// If the root version is updated and rootNtupleClass regenerated,     /////
  ////// these lines may need to be updated.                                 /////    
  Long64_t nbytes = 0, nb = 0;
  for (Long64_t jentry=0; jentry<nentries;jentry++) { // running over all events
    //   for (Long64_t jentry=0; jentry<25;jentry++) { //runnig over few events for test
    Long64_t ientry = LoadTree(jentry);
    if (ientry < 0) break;
    nb = fChain->GetEntry(jentry);   nbytes += nb;
    if(jentry < 10 || jentry%1000 == 0) std::cout << "analysisClass::Loop(): jentry = " << jentry << std::endl;   
    //std::cout << "analysisClass::Loop(): jentry = " << jentry << std::endl;   
    // if (Cut(ientry) < 0) continue;
   
    ////////////////////// User's code starts here ///////////////////////

    //     verbose = true;

    if(verbose){
      std::cout<< std::endl;
      std::cout<<"Start"<< std::endl;
      std::cout<<"PassJSON "<< PassJSON<<std::endl;

      std::cout<<"RECO"<< std::endl;
      std::cout<<"AK4 jet1"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_recoj1<<" eta: "<<etaAK4_recoj1<<" phi: "<<phiAK4_recoj1<< std::endl;
      std::cout<<"AK4 jet2"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_recoj2<<" eta: "<<etaAK4_recoj2<<" phi: "<<phiAK4_recoj2<< std::endl;
      std::cout<<"AK4 jet3"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_recoj3<<" eta: "<<etaAK4_recoj3<<" phi: "<<phiAK4_recoj3<< std::endl;

      std::cout<<"HLT"<< std::endl;
      std::cout<<"AK4 jet1"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_j1<<" eta: "<<etaAK4_j1<<" phi: "<<phiAK4_j1<< std::endl;
      std::cout<<"AK4 jet2"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_j2<<" eta: "<<etaAK4_j2<<" phi: "<<phiAK4_j2<< std::endl;
      std::cout<<"AK4 jet3"<< std::endl;
      std::cout<<"Pt: "<< pTAK4_j3<<" eta: "<<etaAK4_j3<<" phi: "<<phiAK4_j3<< std::endl;
    }
     
    //     if(PassJSON) 	   std::cout<<"Passed JSON"<< std::endl;
    //     if( mjjreco > MJJCut_ && mjj > MJJCut_ ) 	   std::cout<<"Passed MJJ"<< std::endl;
    //     if( deltaETAjjreco < DeltaEtaJJ_ && deltaETAjj < DeltaEtaJJ_) std::cout<<"Passed deltaEta"<< std::endl;

    //  if( passHLT_ZeroBias_BtagSeq || passHLT_ZeroBias || passHLT_L1DoubleMu_BtagSeq || passHLT_L1DoubleMu || passHLT_CaloJet40_BtagSeq || passHLT_CaloJet40 || passHLT_L1HTT150_BtagSeq || passHLT_L1HTT150 || passHLT_CaloScoutingHT250 || passHLT_HT450_BtagSeq || passHLT_HT450 || passHLT_PFHT800 || passHLT_PFHT650MJJ950 || passHLT_PFHT650MJJ900 ){

    if( PassJSON){
      // trigger selected
      //   if( passHLT_ZeroBias_BtagSeq || passHLT_ZeroBias ){ // #1
      //   if( passHLT_L1DoubleMu_BtagSeq || passHLT_L1DoubleMu ){ // #2
      //   if( passHLT_CaloJet40_BtagSeq || passHLT_CaloJet40 ){ // #3
      //   if( passHLT_L1HTT150_BtagSeq || passHLT_L1HTT150 ){ // #4
      //   if( passHLT_CaloScoutingHT250 ){ // #5
      if( passHLT_HT450_BtagSeq || passHLT_HT450 ){ // #6
	 
	// AK4 Jets
	vector<TLorentzVector> AK4recojets;
	TLorentzVector ak4j1Reco, ak4j2Reco, ak4dijetReco;             
	TLorentzVector ak4j3Reco ;
	   
	vector<TLorentzVector> AK4jets;
	TLorentzVector ak4j1, ak4j2, ak4dijet;      
	TLorentzVector ak4j3 ; 
       
	// Reco
	ak4j1Reco.SetPtEtaPhiM(pTAK4_recoj1, etaAK4_recoj1, phiAK4_recoj1, massAK4_recoj1);
	ak4j2Reco.SetPtEtaPhiM(pTAK4_recoj2, etaAK4_recoj2, phiAK4_recoj2, massAK4_recoj2);
	ak4j3Reco.SetPtEtaPhiM(pTAK4_recoj3, etaAK4_recoj3, phiAK4_recoj3, massAK4_recoj3);
	AK4recojets.push_back( ak4j1Reco );
	AK4recojets.push_back( ak4j2Reco );	 
	AK4recojets.push_back( ak4j3Reco );	 
       
	// HLT
	ak4j1.SetPtEtaPhiM(pTAK4_j1, etaAK4_j1, phiAK4_j1, massAK4_j1);
	ak4j2.SetPtEtaPhiM(pTAK4_j2, etaAK4_j2, phiAK4_j2, massAK4_j2);
	ak4j3.SetPtEtaPhiM(pTAK4_j3, etaAK4_j3, phiAK4_j3, massAK4_j3);
	AK4jets.push_back( ak4j1 );
	AK4jets.push_back( ak4j2 );
	AK4jets.push_back( ak4j3 );

	//////////// matching	 
	double DeltaReco1HLT1 = AK4recojets[0].DeltaR(AK4jets[0]);
	double DeltaReco1HLT2 = AK4recojets[0].DeltaR(AK4jets[1]);
	double DeltaReco2HLT1 = AK4recojets[1].DeltaR(AK4jets[0]);
	double DeltaReco2HLT2 = AK4recojets[1].DeltaR(AK4jets[1]);
	     
	if(verbose){
	  //	   cout << endl;
	  cout << "AK4: " << endl;
	  cout << "deltaR Reco1-HLT1 " <<  DeltaReco1HLT1 << endl;
	  cout << "deltaR Reco1-HLT2 " <<  DeltaReco1HLT2 << endl;
	  cout << "deltaR Reco2-HLT1 " <<  DeltaReco2HLT1 << endl;
	  cout << "deltaR Reco2-HLT2 " <<  DeltaReco2HLT2 << endl;
	}       
	     
	vector<int> IdxMatched;
	vector<double> deltaR_min;
	if( DeltaReco1HLT1 <= DeltaReco2HLT1 )
	  {
	    IdxMatched.push_back(0) ; // index Reco jets
	    IdxMatched.push_back(1) ; // index Reco jets
	    deltaR_min.push_back( DeltaReco1HLT1);
	    deltaR_min.push_back( DeltaReco2HLT2);
	  }else
	  {
	    IdxMatched.push_back(1) ; // index Reco jets
	    IdxMatched.push_back(0) ; // index Reco jets
	    deltaR_min.push_back( DeltaReco2HLT1);
	    deltaR_min.push_back( DeltaReco1HLT2);
	  }

	// HLT-Reco Matched : AK4
	if(verbose) cout << "deltaR_min_1_1 " << deltaR_min.at(0)  << endl;
	if(verbose) cout << "deltaR_min_2_2 " << deltaR_min.at(1)  << endl;

	// Asymmetry
	if(deltaR_min.at(0) < DeltaR_ && deltaR_min.at(1) < DeltaR_ ){   

	  int random;
	  random = lrand48()%(2);
	  if(verbose) std::cout<< "random = " <<random << std::endl;
	       
	  double pTaveReco = ( ak4j1Reco.Pt() + ak4j2Reco.Pt() ) / 2;
	  if(verbose) std::cout<< "Average pT Reco = " << pTaveReco << std::endl;
	  CreateAndFillUserTH1D("pTaveReco", 30 , 0, 3000, pTaveReco);	     
	  double alphaReco = ak4j3Reco.Pt() / pTaveReco ;
	  if(verbose) std::cout<< "alpha Reco = " << alphaReco << std::endl;
	  CreateAndFillUserTH1D("alphaReco", 100 , 0, 2, alphaReco);
	  double AsymmetryReco;

	  EtaBinning mEtaBinning;                                                                                                               
	  PtBinning mPtBinning; 
	     
	  int etaBin_j1Reco = mEtaBinning.getBin( fabs(ak4j1Reco.Eta()) );
	  int etaBin_j2Reco = mEtaBinning.getBin( fabs(ak4j2Reco.Eta()) );
	  int ptBin_Reco = mPtBinning.getPtBin( pTaveReco );
	  std::pair<float, float> ptBins_Reco = mPtBinning.getBinValue(ptBin_Reco);

	  if(verbose){       
	    cout<<"|Eta_ak4j1Reco| =   "<<fabs(ak4j1Reco.Eta())<<endl;
	    cout<<"|Eta_ak4j2Reco| =   "<<fabs(ak4j2Reco.Eta())<<endl;

	    std::pair<float, float> etaBins_j1 = mEtaBinning.getBinValue(etaBin_j1Reco);
	    std::pair<float, float> etaBins_j2 = mEtaBinning.getBinValue(etaBin_j2Reco);
	    cout<<"EtaBin_j1 =   "<<etaBin_j1Reco<<endl;
	    cout<<"EtaBin_j2 =   "<<etaBin_j2Reco<<endl;
	    cout<<"pTBin =   "<<ptBin_Reco<<endl;
	    cout<<"j1: etaBin.first  "<< etaBins_j1.first << "    etaBin.second   "<<etaBins_j1.second<<endl;
	    cout<<"j2: etaBin.first  "<< etaBins_j2.first << "    etaBin.second   "<<etaBins_j2.second<<endl;
	    cout<<"ptBin.first  "<< ptBins_Reco.first << "    ptBin.second   "<<ptBins_Reco.second<<endl;
	  }

	  /// HLT
	  double pTave = ( ak4j1.Pt() + ak4j2.Pt() ) /2;
	  if(verbose) std::cout<< "Average pT = " << pTave << std::endl;
	  CreateAndFillUserTH1D("pTave", 30 , 0, 3000, pTave);
	  double alpha = ak4j3.Pt() / pTave ;
	  if(verbose) std::cout<< "alpha = " << alpha << std::endl;
	  CreateAndFillUserTH1D("alpha", 100 , 0, 2, alpha);
	  double Asymmetry;
	       
	  int etaBin_j1 = mEtaBinning.getBin( fabs(ak4j1.Eta()) );
	  int etaBin_j2 = mEtaBinning.getBin( fabs(ak4j2.Eta()) );
	  int ptBin = mPtBinning.getPtBin( pTave );
	  std::pair<float, float> ptBins = mPtBinning.getBinValue(ptBin);	       
	   
	  if(verbose){
	    cout<<"|Eta_ak4j1| =   "<<fabs(ak4j1.Eta())<<endl;
	    cout<<"|Eta_ak4j2| =   "<<fabs(ak4j2.Eta())<<endl;
	       
	    std::pair<float, float> etaBins_j1 = mEtaBinning.getBinValue(etaBin_j1);
	    std::pair<float, float> etaBins_j2 = mEtaBinning.getBinValue(etaBin_j2);
	    cout<<"EtaBin_j1 =   "<<etaBin_j1<<endl;
	    cout<<"EtaBin_j2 =   "<<etaBin_j2<<endl;
	    cout<<"pTBin =   "<<ptBin <<endl;
	    cout<<"j1: etaBin.first  "<< etaBins_j1.first << "    etaBin.second   "<<etaBins_j1.second<<endl;
	    cout<<"j2: etaBin.first  "<< etaBins_j2.first << "    etaBin.second   "<<etaBins_j2.second<<endl;
	    cout<<"ptBin.first  "<< ptBins.first << "    ptBin.second   "<<ptBins.second<<endl;
	  }

      	  // seleziono gli stessi eventi	     
	  if(etaBin_j1Reco == etaBin_j2Reco){ // same eta bin RECO
	    std::string etaNameReco = mEtaBinning.getBinName(etaBin_j1Reco);	     
	    if(etaBin_j1 == etaBin_j2){ // same eta bin HLT
	      std::string etaName = mEtaBinning.getBinName(etaBin_j1);	     
	      if(alphaReco < alphacut_ ){	// alpha cut RECO
		if(alpha < alphacut_ ){	// alpha cut HLT		    

		  cout<< "PASSED"<< endl;
		  /// HLT
		  // introduco uno smearing 
		  /*
		    Devi cambiare il pT di tutti i jet che usi.
		    pTnew = pTold * smear
		    dove smear e’ un numero generato random secondo una distribuzione Gaussiana
		    di media=1 e sigma usuale allo smearing che vuoi mettere (es. 10%=0.1)
		  */
		  vector<TLorentzVector> AK4jetsSmeared;
		  // for(int ii = 0; ii < AK4jets.size(); ii++){
		  for(int ii = 0; ii < 2; ii++){
		    TLorentzVector ak4jetSmeared;      
		    double PtSmeared;      
		    double smear;      
		    TRandom *factor=new TRandom3(0);  //factor -> SetSeed(0);
		    smear = factor -> Gaus(1, 0.1);
		    PtSmeared= AK4jets[ii].Pt() * smear;
		    
		    ak4jetSmeared.SetPtEtaPhiM(PtSmeared, AK4jets[ii].Eta(), AK4jets[ii].Phi(), AK4jets[ii].M() );
		    AK4jetsSmeared.push_back(ak4jetSmeared);
		    
		    if(verbose){
		      std::cout<<"smearing factor = "<< smear << std::endl;
		      std::cout<<"HLT SMEARED"<< std::endl;
		      std::cout<<"AK4 smeared "<< ii << std::endl;
		      std::cout<<"Pt: "<< AK4jetsSmeared[ii].Pt() <<" eta: "<< AK4jetsSmeared[ii].Eta() <<" phi: "<< AK4jetsSmeared[ii].Phi() << std::endl;
		    }
		  } // end smearing
		  
		  double pTaveSmeared = ( AK4jetsSmeared[0].Pt() + AK4jetsSmeared[1].Pt() ) /2;
		  if(verbose) std::cout<< "Average pT = " << pTaveSmeared << std::endl;
		  CreateAndFillUserTH1D("pTaveSmeared", 300 , 0, 3000, pTaveSmeared);
		  //	    double alphaSmeared = AK4jetsSmeared[2].Pt() / pTaveSmeared ;
		  //	    if(verbose) std::cout<< "alpha Smeared = " << alphaSmeared << std::endl;
		  //	    CreateAndFillUserTH1D("alphaSmeared", 100 , 0, 2, alphaSmeared);
		  double AsymmetrySmeared;
		  
		  if(random == 0){
		    AsymmetryReco = ( ak4j1Reco.Pt() - ak4j2Reco.Pt() ) / ( ak4j1Reco.Pt() + ak4j2Reco.Pt() ) ;
		    Asymmetry        = ( ak4j1.Pt() - ak4j2.Pt() ) / ( ak4j1.Pt() + ak4j2.Pt() ) ;
		    AsymmetrySmeared = ( AK4jetsSmeared[0].Pt() - AK4jetsSmeared[1].Pt() ) / ( AK4jetsSmeared[0].Pt() + AK4jetsSmeared[1].Pt() ) ;
		  }else if(random == 1){
		    AsymmetryReco = ( ak4j2Reco.Pt() - ak4j1Reco.Pt() ) / ( ak4j1Reco.Pt() + ak4j2Reco.Pt() ) ; 
		    Asymmetry        = ( ak4j2.Pt() - ak4j1.Pt() ) / ( ak4j1.Pt() + ak4j2.Pt() ) ; 
		    AsymmetrySmeared = ( AK4jetsSmeared[1].Pt() - AK4jetsSmeared[0].Pt() ) / ( AK4jetsSmeared[0].Pt() + AK4jetsSmeared[1].Pt() ) ; 
		  }
		  std::string HistoNameReco = TString::Format("AsymmetryReco_%s_pT_%i_%i", etaNameReco.c_str(), (int) ptBins_Reco.first, (int) ptBins_Reco.second ).Data();	 	     
		  if(verbose) std::cout << HistoNameReco.c_str()<< std::endl;
		  if(verbose) std::cout<< "Asymmetry Reco = " << AsymmetryReco << std::endl; 
		  CreateAndFillUserTH1D(HistoNameReco.c_str(), 300, -2, 2, AsymmetryReco);
		  std::string HistoName = TString::Format("Asymmetry_%s_pT_%i_%i", etaName.c_str(), (int) ptBins.first, (int) ptBins.second ).Data();	 	     
		  if(verbose) std::cout << HistoName.c_str()<< std::endl;
		  if(verbose) std::cout<< "Asymmetry  = " << Asymmetry << std::endl; 
		  CreateAndFillUserTH1D(HistoName.c_str(), 300, -2, 2, Asymmetry);
		  std::string HistoNameSmeared = TString::Format("AsymmetrySmeared_%s_pT_%i_%i", etaName.c_str(), (int) ptBins.first, (int) ptBins.second ).Data();	 	     
		  if(verbose) std::cout << HistoNameSmeared.c_str()<< std::endl;
		  if(verbose) std::cout<< "Asymmetry Smeared  = " << AsymmetrySmeared << std::endl; 
		  CreateAndFillUserTH1D(HistoNameSmeared.c_str(), 300, -2, 2, AsymmetrySmeared);

		}else{//alpha cut HLT
		  if(verbose) std::cout<< "HLT: alpha too large = "<<alpha<<std::endl;
		}
	      }else{
		if(verbose) std::cout<< "Reco: alpha too large = "<<alphaReco<<std::endl;
	      }
	    }// eta bin HLT
	  } // eta bin Reco

	}// both jet matched
      }// trigger
    }// pass json
     
    /////////////////////////////////////////////////////////////////
     
    //== Fill Variables ==
    fillVariableWithValue("PassJSON", PassJSON);     
    fillVariableWithValue("MJJ_reco", mjjreco);     
    fillVariableWithValue("MJJ", mjj);     
    fillVariableWithValue("deltaETAjj_reco", deltaETAjjreco);     
    fillVariableWithValue("deltaETAjj", deltaETAjj);     
    
    ////////////////////////////////////////

    //no cuts on these variables, just to store in output
    // if(!isData)
    //   fillVariableWithValue("trueVtx",PileupInteractions->at(idx_InTimeBX));
    // else if(isData)
    //   fillVariableWithValue("trueVtx",999);     

    // Trigger
    //int NtriggerBits = triggerResult->size();
    /*   
	 if (isData)
	 {
	 fillVariableWithValue("passHLT_ZeroBias_BtagSeq",triggerResult->at(8));// DST_ZeroBias_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_ZeroBias",triggerResult->at(7));// DST_ZeroBias_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_L1DoubleMu_BtagSeq",triggerResult->at(9));// DST_L1DoubleMu_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_L1DoubleMu",triggerResult->at(10));// DST_L1DoubleMu_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_CaloJet40_BtagSeq",triggerResult->at(0));//  DST_CaloJet40_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	 //  OR DST_CaloJet40_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_CaloJet40",triggerResult->at(1));// DST_CaloJet40_CaloScouting_PFScouting_v*  (run>=259636)

	 fillVariableWithValue("passHLT_L1HTT150_BtagSeq",triggerResult->at(2));// DST_L1HTT125ORHTT150ORHTT175_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	 // OR DST_L1HTT_BTagScouting_v* (run>=259636)    
	 fillVariableWithValue("passHLT_L1HTT150",triggerResult->at(3));// DST_L1HTT_CaloScouting_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_HT450_BtagSeq",triggerResult->at(5));// DST_HT450_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	 // OR DST_HT450_BTagScouting_v* (run>=259636)    
	 fillVariableWithValue("passHLT_HT450",triggerResult->at(6));// DST_HT450_PFScouting_v* (run>=259636)        

	 fillVariableWithValue("passHLT_PFHT800",triggerResult->at(13));// HLT_PFHT800_v* (all runs)   
	 fillVariableWithValue("passHLT_PFHT650MJJ950",triggerResult->at(22));// HLT_PFHT650_WideJetMJJ950DEtaJJ1p5_v* (all runs)        
	 fillVariableWithValue("passHLT_PFHT650MJJ900",triggerResult->at(23));// HLT_PFHT650_WideJetMJJ900DEtaJJ1p5_v* (all runs)        
	 }
    */
    // Evaluate cuts (but do not apply them)
    evaluateCuts();
     
    // optional call to fill a skim with the full content of the input roottuple
    //if( passedCut("nJetFinal") ) fillSkimTree();
    /*
      if( passedCut("PassJSON")
      && passedCut("nVtx") 
      && passedCut("IdTight_j1")
      && passedCut("IdTight_j2")
      && passedCut("nJet")
      && passedCut("pTWJ_j1")
      && passedCut("etaWJ_j1")
      && passedCut("pTWJ_j2")
      && passedCut("etaWJ_j2")
      && getVariableValue("deltaETAjj") <  getPreCutValue1("DetaJJforTrig") ){

      h_mjj_NoTrigger -> Fill(MJJWideReco); 
       
      if( (getVariableValue("passHLT_ZeroBias_BtagSeq")||getVariableValue("passHLT_ZeroBias")) )
      h_mjj_HLTpass_ZeroBias -> Fill(MJJWideReco);  
      if( (getVariableValue("passHLT_ZeroBias_BtagSeq")||getVariableValue("passHLT_ZeroBias")) 
      && (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) )
      h_mjj_HLTpass_ZeroBias_L1HTT150 -> Fill(MJJWideReco);  

      if( (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) )
      h_mjj_HLTpass_L1HTT150 -> Fill(MJJWideReco);  

      if( (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) 
      && (getVariableValue("passHLT_HT450_BtagSeq")||getVariableValue("passHLT_HT450")) )
      h_mjj_HLTpass_L1HTT150_HT450 -> Fill(MJJWideReco);  
       
      }
    */
    // optional call to fill a skim with a subset of the variables defined in the cutFile (use flag SAVE)

    //     if( passedAllPreviousCuts("mjj") && passedCut("mjj") ) 
    //       {
    fillReducedSkimTree();

    // ===== Take a look at this =====
    // //Example on how to investigate quickly the data
    // if(getVariableValue("mjj")>4000)
    //   {
    //     //fast creation and filling of histograms
    //     CreateAndFillUserTH1D("h_dphijj_mjjgt4000", 100, 0, 3.15, getVariableValue("deltaPHIjj"));
    //     CreateAndFillUserTH1D("h_htak4_mjjgt4000", 1000, 0, 10000, getVariableValue("HTAK4reco"));
    //     CreateAndFillUserTH1D("h_nvtx_mjjgt4000", 31, -0.5, 30.5, getVariableValue("nVtx"));
    //   }

    //       }

    // ===== Example of mjj spectrum after HLT selection =====
    // if( passedAllPreviousCuts("mjj") )
    //   {
    // 	 if(getVariableValue("passHLT")>0)
    // 	   {
    // 	     //fast creation and filling of histograms
    // 	     CreateAndFillUserTH1D("h_mjj_passHLT", getHistoNBins("mjj"), getHistoMin("mjj"), getHistoMax("mjj"), getVariableValue("mjj"));
    // 	   }
    //   }

    // reject events that did not pass level 0 cuts
    //if( !passedCut("0") ) continue;
    // ......
     
    // reject events that did not pass level 1 cuts
    //if( !passedCut("1") ) continue;
    // ......

    // reject events that did not pass the full cut list
    //if( !passedCut("all") ) continue;
    // ......

    // if( widejets.size() >= 2) {
    //  h_nJetFinal->Fill(widejets.size());
    //  h_DijetMass->Fill(wdijet.M());
    //  h_pT1stJet->Fill(widejets[0].Pt());
    //  h_pT2ndJet->Fill(widejets[1].Pt());
    //  h_eta1stJet->Fill(widejets[0].Eta());
    //  h_eta2ndJet->Fill(widejets[1].Eta());
    // }
    ////////////////////// User's code ends here ///////////////////////

  } // End loop over events

  //////////write histos 


  //  h_mjj_NoTrigger -> Write();
  //  h_mjj_HLTpass_ZeroBias -> Write();
  //  h_mjj_HLTpass_ZeroBias_L1HTT150 -> Write();
  //  h_mjj_HLTpass_L1HTT150 -> Write();
  //  h_mjj_HLTpass_L1HTT150_HT450 -> Write();

  // h_nVtx->Write();
  // h_trueVtx->Write();
  // h_nJetFinal->Write();
  // h_pT1stJet->Write();
  // h_pT2ndJet->Write();
  // h_DijetMass->Write();
  // h_eta1stJet->Write();
  // h_eta2ndJet->Write();

  // //pT of both jets, to be built using the histograms produced automatically by baseClass
  // TH1F * h_pTJets = new TH1F ("h_pTJets","", getHistoNBins("pT1stJet"), getHistoMin("pT1stJet"), getHistoMax("pT1stJet"));
  // h_pTJets->Add( & getHisto_noCuts_or_skim("pT1stJet") ); // all histos can be retrieved, see other getHisto_xxxx methods in baseClass.h
  // h_pTJets->Add( & getHisto_noCuts_or_skim("pT2ndJet") );
  // //one could also do:  *h_pTJets = getHisto_noCuts_or_skim("pT1stJet") + getHisto_noCuts_or_skim("pT2ndJet");
  // h_pTJets->Write();
  // //one could also do:   const TH1F& h = getHisto_noCuts_or_skim// and use h


  std::cout << "analysisClass::Loop() ends" <<std::endl;   
}
void analysisClass::Loop()
{
   std::cout << "analysisClass::Loop() begins" <<std::endl;   
    
   if (fChain == 0) return;
   
   //////////book histos here

   // TH1F *h_nJetFinal = new TH1F ("h_nJetFinal","",10,0,10);
   // h_nJetFinal->Sumw2();      
   // TH1F *h_nVtx = new TH1F ("h_nVtx","",30,0,30);
   // h_nVtx->Sumw2(); 
   // TH1F *h_trueVtx = new TH1F ("h_trueVtx","",40,0,40);
   // h_trueVtx->Sumw2();  
   // TH1F *h_pT1stJet = new TH1F ("h_pT1stJet","",100,0,3000);
   // h_pT1stJet->Sumw2();
   // TH1F *h_pT2ndJet = new TH1F ("h_pT2ndJet","",100,0,3000);
   // h_pT2ndJet->Sumw2();
   // TH1F *h_eta1stJet = new TH1F ("h_eta1stJet","",5,-2.5,2.5);
   // h_eta1stJet->Sumw2();
   // TH1F *h_eta2ndJet = new TH1F ("h_eta2ndJet","",5,-2.5,2.5);
   // h_eta2ndJet->Sumw2();
   // TH1F *h_DijetMass = new TH1F ("h_DijetMass","",600,0,6000);
   // h_DijetMass->Sumw2();
   // TH1F *h_DeltaETAjj = new TH1F ("h_DeltaETAjj","",120,0,3.);
   // h_DeltaETAjj->Sumw2();

   // variable binning for mjj trigger efficiency plots
   const int nMassBins = 103;

   double massBoundaries[nMassBins+1] = {1, 3, 6, 10, 16, 23, 31, 40, 50, 61, 74, 88, 103, 119, 137, 156, 176, 197, 220, 244, 270, 296, 325,
     354, 386, 419, 453, 489, 526, 565, 606, 649, 693, 740, 788, 838, 890, 944, 1000, 1058, 1118, 1181, 1246, 1313, 1383, 1455, 1530, 1607, 1687,
     1770, 1856, 1945, 2037, 2132, 2231, 2332, 2438, 2546, 2659, 2775, 2895, 3019, 3147, 3279, 3416, 3558, 3704, 3854, 4010, 4171, 4337, 4509,
     4686, 4869, 5058, 5253, 5455, 5663, 5877, 6099, 6328, 6564, 6808, 7060, 7320, 7589, 7866, 8152, 8447, 8752, 9067, 9391, 9726, 10072, 10430, 
     10798, 11179, 11571, 11977, 12395, 12827, 13272, 13732, 14000};

   // char* HLTname[50] = {"noTrig","PFHT475","PFHT800","PFHT650MJJ900","PFHT800_OR_PFHT650MJJ900","PFHT800_noPFHT475", 
   //                      "Mu45Eta2p1", "PFHT800AndMu45Eta2p1"};
   // TH1F* h_mjj_HLTpass[8];
   // char name_histoHLT[50];
   // for (int i=0; i<8; i++){  
   //   sprintf(name_histoHLT,"h_mjj_HLTpass_%s",HLTname[i]);
   //   h_mjj_HLTpass[i]= new TH1F(name_histoHLT,"",103,massBoundaries);
   // }

   //For trigger efficiency measurements
   //No trigger selection applied (full offline selection applied)
   TH1F* h_mjj_NoTrigger_1GeVbin = new TH1F("h_mjj_NoTrigger_1GeVbin","",14000,0,14000);
   TH1F* h_mjj_NoTrigger = new TH1F("h_mjj_NoTrigger","",103,massBoundaries);
   //L1
   //TH1F* h_mjj_HLTpass_ZeroBias = new TH1F("h_mjj_HLTpass_ZeroBias","",103,massBoundaries);
   //TH1F* h_mjj_HLTpass_ZeroBias_L1HTT150 = new TH1F("h_mjj_HLTpass_ZeroBias_L1HTT150","",103,massBoundaries);  
   //HLT
   //TH1F* h_mjj_HLTpass_L1HTT150 = new TH1F("h_mjj_HLTpass_L1HTT150","",103,massBoundaries);
   //TH1F* h_mjj_HLTpass_L1HTT150_HT450 = new TH1F("h_mjj_HLTpass_L1HTT150_HT450","",103,massBoundaries);


   /////////initialize variables

   Long64_t nentries = fChain->GetEntriesFast();
   std::cout << "analysisClass::Loop(): nentries = " << nentries << std::endl;   

   ////// The following ~7 lines have been taken from rootNtupleClass->Loop() /////
   ////// If the root version is updated and rootNtupleClass regenerated,     /////
   ////// these lines may need to be updated.                                 /////    
   Long64_t nbytes = 0, nb = 0;
   for (Long64_t jentry=0; jentry<nentries;jentry++) {
   //for (Long64_t jentry=0; jentry<2000;jentry++) {
     Long64_t ientry = LoadTree(jentry);
     if (ientry < 0) break;
     nb = fChain->GetEntry(jentry);   nbytes += nb;
     if(jentry < 10 || jentry%1000 == 0) std::cout << "analysisClass::Loop(): jentry = " << jentry << std::endl;   
     // if (Cut(ientry) < 0) continue;

     ////////////////////// User's code starts here ///////////////////////

     ///Stuff to be done for every event

     size_t no_jets_ak4=jetPtAK4->size();

     vector<TLorentzVector> widejets;
     TLorentzVector wj1, wj2, wdijet; 
     TLorentzVector wj1_shift, wj2_shift, wdijet_shift; 

     vector<TLorentzVector> AK4jets;
     TLorentzVector ak4j1, ak4j2, ak4dijet;      

     resetCuts();

     // //find intime BX
     // int idx_InTimeBX=-1;
     // for(size_t j=0; j<PileupOriginBX->size(); ++j)
     //   {
     // 	 //cout << PileupOriginBX->at(j) << endl;	 
     // 	 if(PileupOriginBX->at(j)==0)
     // 	   {
     // 	     idx_InTimeBX = j;
     // 	     //cout << "idx_InTimeBX: " << idx_InTimeBX << endl; 
     // 	   }
     //   }

     std::vector<double> jecFactors;
     std::vector<double> jecUncertainty;
     // new JECs could change the jet pT ordering. the vector below
     // holds sorted jet indices after the new JECs had been applied
     std::vector<unsigned> sortedJetIdx;

     if( int(getPreCutValue1("useJECs"))==1 )
       {
	 // sort jets by increasing pT
	 std::multimap<double, unsigned> sortedJets;
	 for(size_t j=0; j<no_jets_ak4; ++j)
	   {
	     JetCorrector->setJetEta(jetEtaAK4->at(j));
	     JetCorrector->setJetPt(jetPtAK4->at(j)/jetJecAK4->at(j)); //pTraw
	     JetCorrector->setJetA(jetAreaAK4->at(j));
	     JetCorrector->setRho(rho);

  	     JetCorrector_data->setJetEta(jetEtaAK4->at(j));
	     JetCorrector_data->setJetPt(jetPtAK4->at(j)/jetJecAK4->at(j)); //pTraw
	     JetCorrector_data->setJetA(jetAreaAK4->at(j));
	     JetCorrector_data->setRho(rho);


  	     //nominal value of JECs
	     double correction;//, old_correction, nominal_correction;
	     //if( int(getPreCutValue1("shiftJECs"))==0 ){
	     if (isData == 1) correction = JetCorrector_data->getCorrection();
	     else correction = JetCorrector->getCorrection();
	     //nominal_correction=correction;
	     //old_correction = jetJecAK4->at(j);
	     //}
	     //JEC uncertainties
	     unc->setJetEta(jetEtaAK4->at(j));
	     unc->setJetPt(jetPtAK4->at(j)/jetJecAK4->at(j)*correction);
	     double uncertainty = unc->getUncertainty(true);
	     jecUncertainty.push_back(uncertainty); 

	     // std::cout << "run:" << runNo << "    lumi:" << lumi << "   event:" << evtNo << "   jet pt:" << jetPtAK4->at(j)/jetJecAK4->at(j)*correction << "   correction:" << correction <<   "   uncertainty:" <<  uncertainty  << "  nominal correction:" << nominal_correction  << " old correction: " << old_correction << std::endl;
	     //use "shifted" JECs for study of systematic uncertainties 
	     if( int(getPreCutValue1("shiftJECs"))==1 ){
	       //flat shift
	       //if (isData == 1) correction = JetCorrector_data->getCorrection() * getPreCutValue2("shiftJECs");
	       //else correction = JetCorrector->getCorrection() * getPreCutValue2("shiftJECs");
	       //shift of the corresponding unc
	       correction = correction + getPreCutValue2("shiftJECs")*uncertainty*correction;
	       //  std::cout << "run:" << runNo << "    lumi:" << lumi << "   event:" << evtNo << "   jet pt:" << jetPtAK3->at(j)/jetJecAK4->at(j)*correction << "   correction:" << correction << "   uncertainty:" <<  uncertainty  << std::endl << std::endl;
	       
	   }

	 jecFactors.push_back(correction);
	 sortedJets.insert(std::make_pair((jetPtAK4->at(j)/jetJecAK4->at(j))*correction, j));

       }
     // get jet indices in decreasing pT order
     for(std::multimap<double, unsigned>::const_reverse_iterator it = sortedJets.rbegin(); it != sortedJets.rend(); ++it)
	 sortedJetIdx.push_back(it->second);
     
     }
     else if( int(getPreCutValue1("noJECs"))==1  )
       {
	 // sort jets by increasing pT
	 std::multimap<double, unsigned> sortedJets;
	 for(size_t j=0; j<no_jets_ak4; ++j) //same ordering of original root trees
	   {
	     jecUncertainty.push_back(0.); 
	     jecFactors.push_back(1.);
	     sortedJets.insert(std::make_pair((jetPtAK4->at(j)/jetJecAK4->at(j)), j)); //raw
	   }       
	 // get jet indices in decreasing pT order
	 for(std::multimap<double, unsigned>::const_reverse_iterator it = sortedJets.rbegin(); it != sortedJets.rend(); ++it)
	   sortedJetIdx.push_back(it->second);
       }
     else
       {
	 for(size_t j=0; j<no_jets_ak4; ++j) //same ordering of original root trees
	   {
	     jecFactors.push_back(jetJecAK4->at(j));
	     jecUncertainty.push_back(0.); 
	     sortedJetIdx.push_back(j);
	   }
       }


     //#############################################################
     //########## NOTE: from now on sortedJetIdx[ijet] should be used
     //#############################################################

     // if(no_jets_ak4>=2){
     //  if(!(fabs(jetEtaAK4->at(0)) < getPreCutValue1("jetFidRegion") && idTAK4->at(0) == getPreCutValue1("tightJetID"))){
     //    std::cout << " JET 0 FAIL " << jetEtaAK4->at(0) << " JET 0  ID " << idTAK4->at(0) << std::endl;
     //  }
     //  if(!(fabs(jetEtaAK4->at(1)) < getPreCutValue1("jetFidRegion") && idTAK4->at(1) == getPreCutValue1("tightJetID"))){
     //    std::cout << " JET 1 FAIL " << jetEtaAK4->at(1) << " JET 1  ID " << idTAK4->at(1) << std::endl;
     //  }  
     // }

     //count ak4 jets passing pt threshold and id criteria
     int Nak4 = 0;
     double HTak4 = 0;

     for(size_t ijet=0; ijet<no_jets_ak4; ++ijet)
       {	 
	 //cout << "evtNo: " << evtNo << endl;	 
	 // cout << "ijet=" << ijet << " , sortedJetIdx[ijet]=" << sortedJetIdx[ijet] 
	 //      << " , raw pT=" << jetPtAK4->at(sortedJetIdx[ijet])/jetJecAK4->at(sortedJetIdx[ijet]) 
	 //      << " , final corrected pT - old =" << jetPtAK4->at(sortedJetIdx[ijet] ) 
	 //      << " , final corrected pT - new =" << (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet]))*jetPtAK4->at(sortedJetIdx[ijet])
	 //      << endl;

	 //////////////cout << "id Tight jet" << sortedJetIdx[1] << " = " << idTAK4->at(sortedJetIdx[1]) << endl;
	 if(fabs(jetEtaAK4->at(sortedJetIdx[ijet])) < getPreCutValue1("jetFidRegion")
	    && idTAK4->at(sortedJetIdx[ijet]) == getPreCutValue1("tightJetID")
	    && (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet]))*jetPtAK4->at(sortedJetIdx[ijet]) > getPreCutValue1("ptCut"))
	   {
	     Nak4 += 1;
	     HTak4 += (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet]))*jetPtAK4->at(sortedJetIdx[ijet]);
	   }
       }


     if( int(getPreCutValue1("useFastJet"))==1 )
     {
       // vector of ak4 jets used for wide jet clustering
       std::vector<fastjet::PseudoJet> fjInputs, fjInputs_shift;

       for(size_t j=0; j<no_jets_ak4; ++j)
       {
	 if( !(jetEtaAK4->at(sortedJetIdx[j]) < getPreCutValue1("jetFidRegion")
	       && idTAK4->at(sortedJetIdx[j]) == getPreCutValue1("tightJetID")) ) continue;

	 double rescale = (jecFactors[sortedJetIdx[j]]/jetJecAK4->at(sortedJetIdx[j]));

	 if( j==0 && !( rescale*jetPtAK4->at(sortedJetIdx[j]) > getPreCutValue1("pt0Cut")) ) continue;
	 else if( j==1 && !( rescale*jetPtAK4->at(sortedJetIdx[j]) > getPreCutValue1("pt1Cut")) ) continue;
	 else if( !( rescale*jetPtAK4->at(sortedJetIdx[j]) > getPreCutValue1("ptCut")) ) continue;

	 TLorentzVector tempJet, tempJet_shift;

	 tempJet.SetPtEtaPhiM( rescale*jetPtAK4->at(sortedJetIdx[j]) , jetEtaAK4->at(sortedJetIdx[j]) , jetPhiAK4->at(sortedJetIdx[j]) , rescale*jetMassAK4->at(sortedJetIdx[j]));
	 tempJet_shift.SetPtEtaPhiM( (1+jecUncertainty[sortedJetIdx[j]])* rescale*jetPtAK4->at(sortedJetIdx[j]) , jetEtaAK4->at(sortedJetIdx[j]) , jetPhiAK4->at(sortedJetIdx[j]) ,  (1+jecUncertainty[sortedJetIdx[j]])* rescale*jetMassAK4->at(sortedJetIdx[j]));

	 fjInputs.push_back(fastjet::PseudoJet(tempJet.Px(),tempJet.Py(),tempJet.Pz(),tempJet.E()));
	 fjInputs_shift.push_back(fastjet::PseudoJet(tempJet_shift.Px(),tempJet_shift.Py(),tempJet_shift.Pz(),tempJet_shift.E()));
       }

       fjClusterSeq = ClusterSequencePtr( new fastjet::ClusterSequence( fjInputs, *fjJetDefinition ) );
       fjClusterSeq_shift = ClusterSequencePtr( new fastjet::ClusterSequence( fjInputs_shift, *fjJetDefinition ) );

       std::vector<fastjet::PseudoJet> inclusiveWideJets = fastjet::sorted_by_pt( fjClusterSeq->inclusive_jets(0.) );
       std::vector<fastjet::PseudoJet> inclusiveWideJets_shift = fastjet::sorted_by_pt( fjClusterSeq_shift->inclusive_jets(0.) );

       if( inclusiveWideJets.size()>1 )
       {
	 wj1.SetPxPyPzE(inclusiveWideJets.at(0).px(), inclusiveWideJets.at(0).py(), inclusiveWideJets.at(0).pz(), inclusiveWideJets.at(0).e());
	 wj2.SetPxPyPzE(inclusiveWideJets.at(1).px(), inclusiveWideJets.at(1).py(), inclusiveWideJets.at(1).pz(), inclusiveWideJets.at(1).e());
	 wj1_shift.SetPxPyPzE(inclusiveWideJets_shift.at(0).px(), inclusiveWideJets_shift.at(0).py(), inclusiveWideJets_shift.at(0).pz(), inclusiveWideJets_shift.at(0).e());
	 wj2_shift.SetPxPyPzE(inclusiveWideJets_shift.at(1).px(), inclusiveWideJets_shift.at(1).py(), inclusiveWideJets_shift.at(1).pz(), inclusiveWideJets_shift.at(1).e());
       }
     }
     else
     {
       TLorentzVector wj1_tmp, wj2_tmp;
       TLorentzVector wj1_shift_tmp, wj2_shift_tmp;
       double wideJetDeltaR_ = getPreCutValue1("DeltaR");

       if(no_jets_ak4>=2)
	 {
	   if(fabs(jetEtaAK4->at(sortedJetIdx[0])) < getPreCutValue1("jetFidRegion") 
	      && (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0]))*jetPtAK4->at(sortedJetIdx[sortedJetIdx[0]]) > getPreCutValue1("pt0Cut"))
	     {
	       if(fabs(jetEtaAK4->at(sortedJetIdx[1])) < getPreCutValue1("jetFidRegion") 
		  && (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1]))*jetPtAK4->at(sortedJetIdx[1]) > getPreCutValue1("pt1Cut"))
		 {
		   TLorentzVector jet1, jet2, jet1_shift, jet2_shift;
		   jet1.SetPtEtaPhiM( (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetPtAK4->at(sortedJetIdx[0])
				      ,jetEtaAK4->at(sortedJetIdx[0]),jetPhiAK4->at(sortedJetIdx[0])
				      , (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) * jetMassAK4->at(sortedJetIdx[0]));
		   jet2.SetPtEtaPhiM( (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) *jetPtAK4->at(sortedJetIdx[1])
				      ,jetEtaAK4->at(sortedJetIdx[1]),jetPhiAK4->at(sortedJetIdx[1])
				      , (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) * jetMassAK4->at(sortedJetIdx[1]));
		   jet1_shift.SetPtEtaPhiM( (1+jecUncertainty[sortedJetIdx[0]])*(jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetPtAK4->at(sortedJetIdx[0])
				      ,jetEtaAK4->at(sortedJetIdx[0]),jetPhiAK4->at(sortedJetIdx[0])
				      , (1+jecUncertainty[sortedJetIdx[0]])*(jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) * jetMassAK4->at(sortedJetIdx[0]));
		   jet2_shift.SetPtEtaPhiM( (1+jecUncertainty[sortedJetIdx[1]])* (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) *jetPtAK4->at(sortedJetIdx[1])
				      ,jetEtaAK4->at(sortedJetIdx[1]),jetPhiAK4->at(sortedJetIdx[1])
				      , (1+jecUncertainty[sortedJetIdx[0]])*(jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) * jetMassAK4->at(sortedJetIdx[1]));
		   
		   for(Long64_t ijet=0; ijet<no_jets_ak4; ijet++)
		     { //jet loop for ak4
		       TLorentzVector currentJet;
		       
		       if(fabs(jetEtaAK4->at(sortedJetIdx[ijet])) < getPreCutValue1("jetFidRegion") 
			  && idTAK4->at(sortedJetIdx[ijet]) == getPreCutValue1("tightJetID") 
			  && (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet]))*jetPtAK4->at(sortedJetIdx[ijet]) > getPreCutValue1("ptCut"))
			 {
			   TLorentzVector currentJet, currentJet_shift;
			   currentJet.SetPtEtaPhiM( (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet])) *jetPtAK4->at(sortedJetIdx[ijet])
						    ,jetEtaAK4->at(sortedJetIdx[ijet]),jetPhiAK4->at(sortedJetIdx[ijet])
						    , (jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet])) *jetMassAK4->at(sortedJetIdx[ijet]));   
			   currentJet_shift.SetPtEtaPhiM( (1+jecUncertainty[sortedJetIdx[ijet]])*(jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet])) *jetPtAK4->at(sortedJetIdx[ijet])
						    ,jetEtaAK4->at(sortedJetIdx[ijet]),jetPhiAK4->at(sortedJetIdx[ijet])
						    , (1+jecUncertainty[sortedJetIdx[ijet]])*(jecFactors[sortedJetIdx[ijet]]/jetJecAK4->at(sortedJetIdx[ijet])) *jetMassAK4->at(sortedJetIdx[ijet]));   
			   
			   double DeltaR1 = currentJet.DeltaR(jet1);
			   double DeltaR2 = currentJet.DeltaR(jet2);
			   
			   if(DeltaR1 < DeltaR2 && DeltaR1 < wideJetDeltaR_)
			     {
			       wj1_tmp += currentJet;
			       wj1_shift_tmp += currentJet_shift;
			     }
			   else if(DeltaR2 < wideJetDeltaR_)
			     {
			       wj2_tmp += currentJet;
			       wj2_shift_tmp += currentJet_shift;
			     }			 
			 } // if AK4 jet passes fid and jetid.
		     } //end of ak4 jet loop		     

		   // if(wj1_tmp.Pt()==0 && wj2_tmp.Pt() ==0) 
		   // std::cout << " wj1_tmp.Pt() IN  " <<wj1_tmp.Pt()  << " wj2_tmp.Pt() " <<  wj2_tmp.Pt()  << std::endl;		     

		 } //fid, jet id, pt cut
	     } //fid, jet id, pt cut
	 } // end of two jets.
	 
       // Re-order the wide jets in pt
       if( wj1_tmp.Pt() > wj2_tmp.Pt())
	 {
	   wj1 = wj1_tmp;
	   wj2 = wj2_tmp;
	   wj1_shift = wj1_shift_tmp;
	   wj2_shift = wj2_shift_tmp;
	 }
       else
	 {
	   wj1 = wj2_tmp;
	   wj2 = wj1_tmp;
	   wj1_shift = wj2_shift_tmp;
	   wj2_shift = wj1_shift_tmp;
	 }
     }


     double MJJWide = 0; 
     double DeltaEtaJJWide = 0;
     double DeltaPhiJJWide = 0;
     double MJJWide_shift = 0; 
     if( wj1.Pt()>0 && wj2.Pt()>0 )
     {
       // Create dijet system
       wdijet = wj1 + wj2;
       MJJWide = wdijet.M();
       DeltaEtaJJWide = fabs(wj1.Eta()-wj2.Eta());
       DeltaPhiJJWide = fabs(wj1.DeltaPhi(wj2));
       
       wdijet_shift = wj1_shift + wj2_shift;
       MJJWide_shift = wdijet_shift.M();

       // Put widejets in the container
       widejets.push_back( wj1 );
       widejets.push_back( wj2 );
     }

     //AK4 jets
     if(no_jets_ak4>=2)
       //cout << "eta j1 " << jetEtaAK4->at(sortedJetIdx[0]) << endl;
       //cout << "pt j1 " << (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetPtAK4->at(sortedJetIdx[0]) << endl;
       {
	 if(fabs(jetEtaAK4->at(sortedJetIdx[0])) < getPreCutValue1("jetFidRegion") 
	    && (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0]))*jetPtAK4->at(sortedJetIdx[0]) > getPreCutValue1("pt0Cut"))
	   {
	     if(fabs(jetEtaAK4->at(sortedJetIdx[1])) < getPreCutValue1("jetFidRegion") 
		&& (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1]))*jetPtAK4->at(sortedJetIdx[1]) > getPreCutValue1("pt1Cut"))
	       {
		 //cout << "filling ak4j1 and ak4j2" << endl;
		 //cout << "pt ak4 j1 = " << (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetPtAK4->at(sortedJetIdx[0]) << endl;
		 ak4j1.SetPtEtaPhiM( (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetPtAK4->at(sortedJetIdx[0])
				     ,jetEtaAK4->at(sortedJetIdx[0])
				     ,jetPhiAK4->at(sortedJetIdx[0])
				     , (jecFactors[sortedJetIdx[0]]/jetJecAK4->at(sortedJetIdx[0])) *jetMassAK4->at(sortedJetIdx[0]));
		 ak4j2.SetPtEtaPhiM( (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) *jetPtAK4->at(sortedJetIdx[1])
				     ,jetEtaAK4->at(sortedJetIdx[1])
				     ,jetPhiAK4->at(sortedJetIdx[1])
				     , (jecFactors[sortedJetIdx[1]]/jetJecAK4->at(sortedJetIdx[1])) *jetMassAK4->at(sortedJetIdx[1]));
	       }
	   }
       }   

     double MJJAK4 = 0; 
     double DeltaEtaJJAK4 = 0;
     double DeltaPhiJJAK4 = 0;
     
     //std::cout << "ak4j1.Pt()=" << ak4j1.Pt() << "   ak4j2.Pt()=" << ak4j2.Pt() << std::endl;
     if( ak4j1.Pt()>0 && ak4j2.Pt()>0 )
     {
       // Create dijet system
       ak4dijet = ak4j1 + ak4j2;
       MJJAK4 = ak4dijet.M();
       DeltaEtaJJAK4 = fabs(ak4j1.Eta()-ak4j2.Eta());
       DeltaPhiJJAK4 = fabs(ak4j1.DeltaPhi(ak4j2));

       // Put widejets in the container
       AK4jets.push_back( ak4j1 );
       AK4jets.push_back( ak4j2 );
     }

     // GenJets
     double gen_mjj = -9999.0;
     double gen_deltaETAjj = -9999.0;
     TLorentzVector gen_wj1, gen_wj2;
     double pTGenAK4_j1 = -9999.0;
     double pTGenAK4_j2 = -9999.0;
     if (!isData) {
         double gen_wideJetDeltaR_ = getPreCutValue1("DeltaR");
         if (nGenJetsAK4 >= 2) {
             if (fabs(jetEtaGenAK4->at(0)) < getPreCutValue1("jetFidRegion")
                 && jetPtGenAK4->at(0) > getPreCutValue1("pt0Cut")
                 && fabs(jetEtaGenAK4->at(1)) < getPreCutValue1("jetFidRegion")
                 && jetPtGenAK4->at(1) > getPreCutValue1("pt1Cut")) {
                 TLorentzVector jet1, jet2;
                 jet1.SetPtEtaPhiM(jetPtGenAK4->at(0), jetEtaGenAK4->at(0),
                                   jetPhiGenAK4->at(0), jetMassGenAK4->at(0));
                 jet2.SetPtEtaPhiM(jetPtGenAK4->at(1), jetEtaGenAK4->at(1),
                                   jetPhiGenAK4->at(1), jetMassGenAK4->at(1));
                 for (int i=0; i<nGenJetsAK4; ++i) {
                     if(fabs(jetEtaGenAK4->at(i)) < getPreCutValue1("jetFidRegion")
                        && jetPtGenAK4->at(i) > getPreCutValue1("ptCut")) {
                         TLorentzVector currentJet;
                         currentJet.SetPtEtaPhiM(jetPtGenAK4->at(i),
                                                 jetEtaGenAK4->at(i),
                                                 jetPhiGenAK4->at(i),
                                                 jetMassGenAK4->at(i));
                         double DeltaR1 = currentJet.DeltaR(jet1);
                         double DeltaR2 = currentJet.DeltaR(jet2);

                         if (DeltaR1 < DeltaR2 && DeltaR1 < gen_wideJetDeltaR_)
                             gen_wj1 += currentJet;
                         else if (DeltaR2 < gen_wideJetDeltaR_)
                             gen_wj2 += currentJet;
                     }
                 }
             }
         }

         if (gen_wj1.Pt() > 0.0 && gen_wj2.Pt() > 0.0) {
             TLorentzVector gen_wdijet = gen_wj1 + gen_wj2;
             gen_mjj = gen_wdijet.M();
             gen_deltaETAjj = fabs(gen_wj1.Eta() - gen_wj2.Eta());
         }

         double gen_minDeltaR_j1 = 9999.0;
         double gen_minDeltaR_j2 = 9999.0;
         double gen_maxDeltaR = 0.4;
         if (AK4jets.size() > 1) {
             for (int i=0; i<nGenJetsAK4; ++i) {
                 TLorentzVector currentJet;
                 currentJet.SetPtEtaPhiM(jetPtGenAK4->at(i), jetEtaGenAK4->at(i),
                                         jetPhiGenAK4->at(i), jetMassGenAK4->at(i));
                 double DeltaR1 = currentJet.DeltaR(AK4jets[0]);
                 double DeltaR2 = currentJet.DeltaR(AK4jets[1]);

                 if (DeltaR1 < DeltaR2 && DeltaR1 < gen_maxDeltaR) {
                     if (DeltaR1 < gen_minDeltaR_j1) {
                         pTGenAK4_j1 = currentJet.Pt();
                         gen_minDeltaR_j1 = DeltaR1;
                     } else if (DeltaR2 < gen_minDeltaR_j2 && DeltaR2 < gen_maxDeltaR) {
                         pTGenAK4_j2 = currentJet.Pt();
                         gen_minDeltaR_j2 = DeltaR2;
                     }
                 } else { // DeltaR2 > DeltaR1
                     if (DeltaR2 < gen_maxDeltaR && DeltaR2 < gen_minDeltaR_j2) {
                         pTGenAK4_j2 = currentJet.Pt();
                         gen_minDeltaR_j2 = DeltaR2;
                     } else if (DeltaR1 < gen_minDeltaR_j1 && DeltaR1 < gen_maxDeltaR) {
                         pTGenAK4_j1 = currentJet.Pt();
                         gen_minDeltaR_j1 = DeltaR1;
                     }
                 }
             }
         }
     }

     //== Fill Variables ==
     fillVariableWithValue("isData",isData);     
     fillVariableWithValue("run",runNo);     
     fillVariableWithValue("event",evtNo);     
     fillVariableWithValue("lumi",lumi);     
     fillVariableWithValue("nVtx",nvtx);     
     fillVariableWithValue("nJet",widejets.size());
     fillVariableWithValue("Nak4",Nak4);
     fillVariableWithValue ( "PassJSON", passJSON (runNo, lumi, isData));

     //directly taken from big root tree (i.e. jec not reapplied)
     fillVariableWithValue("htAK4",htAK4); // summing all jets with minimum pT cut and no jetid cut (jec not reapplied)
     fillVariableWithValue("mhtAK4",mhtAK4); //summing all jets with minimum pT cut and no jetid cut (jec not reapplied)
     fillVariableWithValue("mhtAK4Sig",mhtAK4Sig); // mhtAK4/htAK4 summing all jets with minimum pT cut and no jetid cut (jec not reapplied)
     fillVariableWithValue("offMet",offMet); //recomputed from PF candidates (off=offline)
     fillVariableWithValue("offMetSig",offMetSig); // offMet/offSumEt recomputed from PF candidates (off=offline)
     fillVariableWithValue("met",met); //directly taken from event
     fillVariableWithValue("metSig",metSig); // met/offMetSig (to be substituted with met/SumEt from event in future)

     if( AK4jets.size() >=1 ){
       //cout << "AK4jets.size() " <<  AK4jets.size() << endl;
       //cout << "IdTight_j1 : " << idTAK4->at(sortedJetIdx[0]) << endl;
       fillVariableWithValue( "IdTight_j1",idTAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "pTAK4_j1", AK4jets[0].Pt());
       fillVariableWithValue( "etaAK4_j1", AK4jets[0].Eta());
       fillVariableWithValue( "phiAK4_j1", AK4jets[0].Phi());
       //fillVariableWithValue( "jetPtAK4matchCaloJet_j1", jetPtAK4matchCaloJet->at(sortedJetIdx[0]));
       fillVariableWithValue( "jetJecAK4_j1", jecFactors[sortedJetIdx[0]] );
       fillVariableWithValue( "jetJecUncAK4_j1", jecUncertainty[sortedJetIdx[0]] );
       //jetID
       fillVariableWithValue( "neutrHadEnFrac_j1", jetNhfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "chargedHadEnFrac_j1", jetChfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "photonEnFrac_j1", jetPhfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "eleEnFract_j1", jetElfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "muEnFract_j1", jetMufAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "neutrElectromFrac_j1", jetNemfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "chargedElectromFrac_j1", jetCemfAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "chargedMult_j1", chMultAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "neutrMult_j1", neMultAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "photonMult_j1", phoMultAK4->at(sortedJetIdx[0]));
       fillVariableWithValue( "jetCSVAK4_j1", jetCSVAK4->at(sortedJetIdx[0]) );
     }
     if( AK4jets.size() >=2 ){
       //cout << "IdTight_j2 : " << idTAK4->at(sortedJetIdx[1]) << endl << endl;
       fillVariableWithValue( "IdTight_j2",idTAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "pTAK4_j2", AK4jets[1].Pt() );
       fillVariableWithValue( "etaAK4_j2", AK4jets[1].Eta());
       fillVariableWithValue( "phiAK4_j2", AK4jets[1].Phi());
       //fillVariableWithValue( "jetPtAK4matchCaloJet_j2", jetPtAK4matchCaloJet->at(sortedJetIdx[1]));
       fillVariableWithValue( "jetJecAK4_j2", jecFactors[sortedJetIdx[1]]); 
       fillVariableWithValue( "jetJecUncAK4_j2", jecUncertainty[sortedJetIdx[1]] );
       //jetID
       fillVariableWithValue( "neutrHadEnFrac_j2", jetNhfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "chargedHadEnFrac_j2", jetChfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "photonEnFrac_j2", jetPhfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "eleEnFract_j2", jetElfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "muEnFract_j2", jetMufAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "neutrElectromFrac_j2", jetNemfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "chargedElectromFrac_j2", jetCemfAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "chargedMult_j2", chMultAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "neutrMult_j2", neMultAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "photonMult_j2", phoMultAK4->at(sortedJetIdx[1]));
       fillVariableWithValue( "jetCSVAK4_j2", jetCSVAK4->at(sortedJetIdx[1]) );
       //dijet
       fillVariableWithValue( "Dijet_MassAK4", MJJAK4) ; 
       fillVariableWithValue( "CosThetaStarAK4", TMath::TanH( (AK4jets[0].Eta()-AK4jets[1].Eta())/2 )); 
       fillVariableWithValue( "deltaETAjjAK4", DeltaEtaJJAK4 ) ;
       fillVariableWithValue( "deltaPHIjjAK4", DeltaPhiJJAK4 ) ;
     }

     if( widejets.size() >= 1 ){
         fillVariableWithValue( "pTWJ_j1", widejets[0].Pt() );
         fillVariableWithValue( "etaWJ_j1", widejets[0].Eta());
	 //no cuts on these variables, just to store in output
         fillVariableWithValue( "massWJ_j1", widejets[0].M());
         fillVariableWithValue( "phiWJ_j1", widejets[0].Phi());
       }

     if( widejets.size() >= 2 ){
         fillVariableWithValue( "pTWJ_j2", widejets[1].Pt() );
         fillVariableWithValue( "etaWJ_j2", widejets[1].Eta());
	 fillVariableWithValue( "deltaETAjj", DeltaEtaJJWide ) ;
         fillVariableWithValue( "mjj", MJJWide ) ;
         fillVariableWithValue( "mjj_shiftJEC", MJJWide_shift ) ;
	 //no cuts on these variables, just to store in output
         fillVariableWithValue( "massWJ_j2", widejets[1].M());
         fillVariableWithValue( "phiWJ_j2", widejets[1].Phi());	
	 //dijet
         fillVariableWithValue( "CosThetaStarWJ", TMath::TanH( (widejets[0].Eta()-widejets[1].Eta())/2 )); 
	 fillVariableWithValue( "deltaPHIjj", DeltaPhiJJWide ) ;
	 //fillVariableWithValue( "Dijet_MassAK8", mjjAK8 ) ;  
	 //fillVariableWithValue( "Dijet_MassC", mjjCA8 ) ;
	 // if(wdijet.M()<1){
	 //    std::cout << " INV MASS IS " << wdijet.M() << std::endl;
	 //    std::cout << " Delta Eta IS " << DeltaEtaJJWide << " n is  " << widejets.size() << std::endl;
	 //    std::cout << " INV MASS FROM NTUPLE AK8 " << mjjAK8 << std::endl;
	 //    //std::cout << " INV MASS FROM NTUPLE CA8 " << mjjCA8 << std::endl;
       }

     if (!isData) {
         fillVariableWithValue("gen_mjj", gen_mjj);
         fillVariableWithValue("gen_deltaETAjj", gen_deltaETAjj);
         fillVariableWithValue("pTGenAK4_j1", pTGenAK4_j1);
         fillVariableWithValue("pTGenAK4_j2", pTGenAK4_j2);
     }

     //no cuts on these variables, just to store in output
     // if(!isData)
     //   fillVariableWithValue("trueVtx",PileupInteractions->at(idx_InTimeBX));
     // else if(isData)
     //   fillVariableWithValue("trueVtx",999);     

     // Trigger
     //int NtriggerBits = triggerResult->size();
     /*if (isData)
       {
	 fillVariableWithValue("passHLT_ZeroBias_BtagSeq",triggerResult->at(8));// DST_ZeroBias_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_ZeroBias",triggerResult->at(7));// DST_ZeroBias_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_L1DoubleMu_BtagSeq",triggerResult->at(9));// DST_L1DoubleMu_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_L1DoubleMu",triggerResult->at(10));// DST_L1DoubleMu_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_CaloJet40_BtagSeq",triggerResult->at(0));//  DST_CaloJet40_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	                                                                        //  OR DST_CaloJet40_BTagScouting_v* (run>=259636)
	 fillVariableWithValue("passHLT_CaloJet40",triggerResult->at(1));// DST_CaloJet40_CaloScouting_PFScouting_v*  (run>=259636)

	 fillVariableWithValue("passHLT_L1HTT150_BtagSeq",triggerResult->at(2));// DST_L1HTT125ORHTT150ORHTT175_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	                                                                        // OR DST_L1HTT_BTagScouting_v* (run>=259636)    
	 fillVariableWithValue("passHLT_L1HTT150",triggerResult->at(3));// DST_L1HTT_CaloScouting_PFScouting_v* (run>=259636)

	 fillVariableWithValue("passHLT_HT450_BtagSeq",triggerResult->at(5));// DST_HT450_PFReco_PFBTagCSVReco_PFScouting_v* (257933<=run<259636) 
	                                                                     // OR DST_HT450_BTagScouting_v* (run>=259636)    
	 fillVariableWithValue("passHLT_HT450",triggerResult->at(6));// DST_HT450_PFScouting_v* (run>=259636)        

	 fillVariableWithValue("passHLT_PFHT800",triggerResult->at(13));// HLT_PFHT800_v* (all runs)   
	 fillVariableWithValue("passHLT_PFHT650MJJ950",triggerResult->at(22));// HLT_PFHT650_WideJetMJJ950DEtaJJ1p5_v* (all runs)        
	 fillVariableWithValue("passHLT_PFHT650MJJ900",triggerResult->at(23));// HLT_PFHT650_WideJetMJJ900DEtaJJ1p5_v* (all runs)        
       }*/

     // Evaluate cuts (but do not apply them)
     evaluateCuts();
     
     // optional call to fill a skim with the full content of the input roottuple
     //if( passedCut("nJetFinal") ) fillSkimTree();
     if( passedCut("PassJSON")
	 && passedCut("nVtx") 
	 && passedCut("IdTight_j1")
	 && passedCut("IdTight_j2")
	 && passedCut("nJet")
	 && passedCut("pTWJ_j1")
	 && passedCut("etaWJ_j1")
	 && passedCut("pTWJ_j2")
	 && passedCut("etaWJ_j2")
	 && getVariableValue("deltaETAjj") <  getPreCutValue1("DetaJJforTrig") ){

       h_mjj_NoTrigger_1GeVbin -> Fill(MJJWide); 
       h_mjj_NoTrigger -> Fill(MJJWide); 
       
       /*if( (getVariableValue("passHLT_ZeroBias_BtagSeq")||getVariableValue("passHLT_ZeroBias")) )
	 h_mjj_HLTpass_ZeroBias -> Fill(MJJWide);  

       if( (getVariableValue("passHLT_ZeroBias_BtagSeq")||getVariableValue("passHLT_ZeroBias")) 
	   && (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) )
	 h_mjj_HLTpass_ZeroBias_L1HTT150 -> Fill(MJJWide);  

       if( (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) )
	 h_mjj_HLTpass_L1HTT150 -> Fill(MJJWide);  

       if( (getVariableValue("passHLT_L1HTT150_BtagSeq")||getVariableValue("passHLT_L1HTT150")) 
	   && (getVariableValue("passHLT_HT450_BtagSeq")||getVariableValue("passHLT_HT450")) )
           h_mjj_HLTpass_L1HTT150_HT450 -> Fill(MJJWide);  */
       
     }

     // optional call to fill a skim with a subset of the variables defined in the cutFile (use flag SAVE)
     if( passedAllPreviousCuts("mjj") && passedCut("mjj") ) 
       {
	 fillReducedSkimTree();

	 // ===== Take a look at this =====
	 // //Example on how to investigate quickly the data
	 // if(getVariableValue("mjj")>4000)
	 //   {
	 //     //fast creation and filling of histograms
	 //     CreateAndFillUserTH1D("h_dphijj_mjjgt4000", 100, 0, 3.15, getVariableValue("deltaPHIjj"));
	 //     CreateAndFillUserTH1D("h_htak4_mjjgt4000", 1000, 0, 10000, getVariableValue("HTAK4"));
	 //     CreateAndFillUserTH1D("h_nvtx_mjjgt4000", 31, -0.5, 30.5, getVariableValue("nVtx"));
	 //   }

       }

     // ===== Example of mjj spectrum after HLT selection =====
     // if( passedAllPreviousCuts("mjj") )
     //   {
     // 	 if(getVariableValue("passHLT")>0)
     // 	   {
     // 	     //fast creation and filling of histograms
     // 	     CreateAndFillUserTH1D("h_mjj_passHLT", getHistoNBins("mjj"), getHistoMin("mjj"), getHistoMax("mjj"), getVariableValue("mjj"));
     // 	   }
     //   }

     // reject events that did not pass level 0 cuts
     //if( !passedCut("0") ) continue;
     // ......
     
     // reject events that did not pass level 1 cuts
     //if( !passedCut("1") ) continue;
     // ......

     // reject events that did not pass the full cut list
     //if( !passedCut("all") ) continue;
     // ......

     // if( widejets.size() >= 2) {
     //  h_nJetFinal->Fill(widejets.size());
     //  h_DijetMass->Fill(wdijet.M());
     //  h_pT1stJet->Fill(widejets[0].Pt());
     //  h_pT2ndJet->Fill(widejets[1].Pt());
     //  h_eta1stJet->Fill(widejets[0].Eta());
     //  h_eta2ndJet->Fill(widejets[1].Eta());
     // }
     ////////////////////// User's code ends here ///////////////////////

   } // End loop over events

   //////////write histos 

   h_mjj_NoTrigger_1GeVbin -> Write();
   h_mjj_NoTrigger -> Write();
   /*h_mjj_HLTpass_ZeroBias -> Write();
   h_mjj_HLTpass_ZeroBias_L1HTT150 -> Write();
   h_mjj_HLTpass_L1HTT150 -> Write();
   h_mjj_HLTpass_L1HTT150_HT450 -> Write();*/

   // h_nVtx->Write();
   // h_trueVtx->Write();
   // h_nJetFinal->Write();
   // h_pT1stJet->Write();
   // h_pT2ndJet->Write();
   // h_DijetMass->Write();
   // h_eta1stJet->Write();
   // h_eta2ndJet->Write();

   // //pT of both jets, to be built using the histograms produced automatically by baseClass
   // TH1F * h_pTJets = new TH1F ("h_pTJets","", getHistoNBins("pT1stJet"), getHistoMin("pT1stJet"), getHistoMax("pT1stJet"));
   // h_pTJets->Add( & getHisto_noCuts_or_skim("pT1stJet") ); // all histos can be retrieved, see other getHisto_xxxx methods in baseClass.h
   // h_pTJets->Add( & getHisto_noCuts_or_skim("pT2ndJet") );
   // //one could also do:  *h_pTJets = getHisto_noCuts_or_skim("pT1stJet") + getHisto_noCuts_or_skim("pT2ndJet");
   // h_pTJets->Write();
   // //one could also do:   const TH1F& h = getHisto_noCuts_or_skim// and use h

   std::cout << "analysisClass::Loop() ends" <<std::endl;   
   }