void analysisClassL1::loop(){

  std::string MyTrigger="HLT_Any";

  L1Tree * l1Tree = getTree<L1Tree>("l1Tree");
  L1ExtraTree * l1ExtraTree = getTree<L1ExtraTree>("l1ExtraTree");

  int n_events = l1Tree -> fChain -> GetEntries();

  l1Tree -> fChain -> SetBranchStatus("*", kFALSE);

  l1ExtraTree -> fChain -> SetBranchStatus("*", kFALSE);
  l1ExtraTree -> fChain -> SetBranchStatus("nFwdJets", kTRUE);
  l1ExtraTree -> fChain -> SetBranchStatus("fwdJetEt", kTRUE);
  l1ExtraTree -> fChain -> SetBranchStatus("fwdJetBx", kTRUE);

  l1ExtraTree -> fChain -> SetBranchStatus("nCenJets", kTRUE);
  l1ExtraTree -> fChain -> SetBranchStatus("cenJetEt", kTRUE); 
  l1ExtraTree -> fChain -> SetBranchStatus("cenJetBx", kTRUE);

  TH1F * h_cenJetPt = makeTH1F("h_cenJetPt",250,-0.5,249.5);
  TH1F * h_fwdJetPt = makeTH1F("h_fwdJetPt",250,-0.5,249.5);
  TH1F * h_leadingCenJetPt = makeTH1F("h_leadingCenJetPt",250,-0.5,249.5);
  TH1F * h_leadingFwdJetPt = makeTH1F("h_leadingFwdJetPt",250,-0.5,249.5);
  TH1F * h_leadingFwdJetPt_BxM1 = makeTH1F("h_leadingFwdJetPt_BxM1",250,-0.5,249.5);
  TH2F * h_leadingFwdJet_Bx0_BxM1 = makeTH2F("h_leadingFwdJet_BxM1_Bx0",100,-0.5,249.5,100,-0.5,249.5);
  TH2F * h_leadingFwdJet_Bx0_BxM1_CenJetPt50 = makeTH2F("h_leadingFwdJet_Bx0_BxM1_CenJetPt50",100,-0.5,249.5,100,-0.5,249.5);

  TH1F * h_fwdJetBx = makeTH1F("h_fwdJetBx",10,-5.5,4.5);

  double leadingCenJetPt;
  double leadingFwdJetPt;
  double leadingFwdJetPt_BxM1;

  for (int i = 0; i < n_events; ++i){
    l1Tree -> GetEntry(i);
    l1ExtraTree -> GetEntry(i);
    if ( (i + 1) % 10000 == 0 ) std::cout << "Processing event " << i + 1 << "/" << n_events << std::endl;

    if ((l1ExtraTree -> cenJetEt.size() == 0) && (l1ExtraTree -> fwdJetEt.size() == 0) ) continue;

    leadingCenJetPt = 0.;
    for (int j = 0; j != l1ExtraTree -> cenJetEt.size(); j++){
      h_cenJetPt -> Fill(l1ExtraTree -> cenJetEt[j]);
      if ((leadingCenJetPt < l1ExtraTree -> cenJetEt[j]) && (l1ExtraTree -> cenJetBx[j] == 0) ){
        leadingCenJetPt = l1ExtraTree -> cenJetEt[j];
      };
    };
    h_leadingCenJetPt -> Fill(leadingCenJetPt);

    leadingFwdJetPt = 0.;
    leadingFwdJetPt_BxM1 = 0.;
    for (int j = 0; j != l1ExtraTree -> fwdJetEt.size(); j++){
      h_fwdJetPt -> Fill(l1ExtraTree -> fwdJetEt[j]);
      h_fwdJetBx -> Fill(l1ExtraTree -> fwdJetBx[j]);
      if ((leadingFwdJetPt < l1ExtraTree -> fwdJetEt[j]) && (l1ExtraTree -> fwdJetBx[j] == 0) ){
        leadingFwdJetPt = l1ExtraTree -> fwdJetEt[j];
      };
      if ((leadingFwdJetPt_BxM1 < l1ExtraTree -> fwdJetEt[j]) && (l1ExtraTree -> fwdJetBx[j] == -1) ){
        leadingFwdJetPt_BxM1 = l1ExtraTree -> fwdJetEt[j];
      };
    };
    h_leadingFwdJetPt -> Fill(leadingFwdJetPt);
    h_leadingFwdJetPt_BxM1 -> Fill(leadingFwdJetPt_BxM1);

    h_leadingFwdJet_Bx0_BxM1 -> Fill(leadingFwdJetPt,leadingFwdJetPt_BxM1);
    if (leadingCenJetPt > 50.){
      h_leadingFwdJet_Bx0_BxM1_CenJetPt50 -> Fill(leadingFwdJetPt,leadingFwdJetPt_BxM1);
    };
  };

    h_leadingFwdJet_Bx0_BxM1 -> SetTitle(" ; leading Fwd Jet E_{T} (Bx = 0) GeV ; leading Fwd Jet E_{T} (Bx = -1) GeV ");
    h_leadingFwdJet_Bx0_BxM1_CenJetPt50 -> SetTitle("Leading Cen Jet pT > 50 GeV ; leading Fwd Jet E_{T} (Bx = 0) GeV ; leading Fwd Jet E_{T} (Bx = -1) GeV ");

}
void analysisClass::loop() {

    //--------------------------------------------------------------------------------
    // Configurables
    //--------------------------------------------------------------------------------
    const int nSample = 10;
    const double min_charge = 20.;

    //--------------------------------------------------------------------------------
    // Declare HCAL tree(s)
    //--------------------------------------------------------------------------------

    HcalTupleTree * utca_tree = getTree<HcalTupleTree>("tuple_tree","utca_file");
    HcalTupleTree * vme_tree = getTree<HcalTupleTree>("tuple_tree","vme_file");

    //--------------------------------------------------------------------------------
    // Check number of events
    //--------------------------------------------------------------------------------

    int n_utca_events = utca_tree -> fChain -> GetEntries();
    std::cout << "n events in utca tree = " << n_utca_events << std::endl;
    int n_vme_events = vme_tree -> fChain -> GetEntries();
    std::cout << "n events in vme tree = " << n_vme_events << std::endl;

    if (n_utca_events != n_vme_events) {
        std::cout << "Number of events in utca trees not equal to number of vme trees" << std::endl;
        return;
    };

    int n_events = n_utca_events;
    std::map<std::string,HcalTupleTree*> treeMap;
    treeMap["utca"] = utca_tree;
    treeMap["vme"] = vme_tree;

    //--------------------------------------------------------------------------------
    // Turn on/off branches
    //--------------------------------------------------------------------------------

    std::map<std::string,HcalTupleTree*>::iterator it = treeMap.begin();
    for (; it != treeMap.end(); ++it) {
        it -> second -> fChain -> SetBranchStatus("*"                 , kFALSE);
        it -> second -> fChain -> SetBranchStatus("run"               , kTRUE);
        it -> second -> fChain -> SetBranchStatus("event"             , kTRUE);
        it -> second -> fChain -> SetBranchStatus("ls"                , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiFC"        , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiADC"       , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiIEta"      , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiIPhi"      , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiDepth"     , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HBHEDigiSize"      , kTRUE);
        it -> second -> fChain -> SetBranchStatus("HcalTriggerPrimitiveCompressedEtSOI",kTRUE);
        it -> second -> fChain -> SetBranchStatus("HcalTriggerPrimitiveIEta",kTRUE);
        it -> second -> fChain -> SetBranchStatus("HcalTriggerPrimitiveIPhi",kTRUE);
    };

    //--------------------------------------------------------------------------------
    // Basic Histograms
    //--------------------------------------------------------------------------------

    char histName[100];
    char titleName[100];

    TH2F * h_utcaOccp = makeTH2F("h_utcaOccp",81,-40.5,40.5,72,0.5,72.5);
    h_utcaOccp -> SetTitle(" ; uTCA i#eta ; uTCA i#phi ");

    TH2F * h_vmeOccp = makeTH2F("h_vmeOccp",81,-40.5,40.5,72,0.5,72.5);
    h_vmeOccp -> SetTitle(" ; VME i#eta ; VME i#phi ");

    TH2F * h_fcTotal = makeTH2F("h_fcTotal",100,0.,200.,100.,0.,200.);
    h_fcTotal -> SetTitle(" ; uTCA Total fC ; VME Total fC ");

    std::map <int,TH2F*> h_fc;
    std::map <int,TH1F*> h_uTCAfC;
    std::map <int,TH1F*> h_vmefC;

    for (int ifc = 0; ifc != nSample; ifc++) {
        sprintf(histName,"h_fc%d",ifc);
        h_fc[ifc] = makeTH2F(histName,50,0.,50.,50,0.,50.);
        sprintf(titleName," ; uTCA fC at TS %d ; VME fC at TS %d ",ifc,ifc);
        h_fc[ifc] -> SetTitle(titleName);

        sprintf(histName,"h_uTCAfc%d",ifc);
        h_uTCAfC[ifc] = makeTH1F(histName,50,0.,50.);
        sprintf(titleName," ; uTCA fC at TS %d ; ",ifc);
        h_uTCAfC[ifc] -> SetTitle(titleName);

        sprintf(histName,"h_vmefc%d",ifc);
        h_vmefC[ifc] = makeTH1F(histName,50,0.,50.);
        sprintf(titleName," ; vme fC at TS %d ; ",ifc);
        h_vmefC[ifc] -> SetTitle(titleName);
    };

    TH2F * h_adcTotal = makeTH2F("h_adcTotal",201,-0.5,200.5,201,-0.5,200.5);
    h_adcTotal -> SetTitle(" ; uTCA Total ADC ; VME Total ADC ");

    TH2F * h_tpEt = makeTH2F("h_tpEt",50,0.,100.,50,0.,100.);
    h_tpEt -> SetTitle(" ; uTCA TP ET ; VME TP ET");

    //--------------------------------------------------------------------------------
    // Custom Histograms
    //--------------------------------------------------------------------------------
    TH2F * h_utcaOccp_cut = makeTH2F("h_utcaOccp_cut",81,-40.5,40.5,72,0.5,72.5);
    h_utcaOccp_cut -> SetTitle("Cut ; uTCA i#eta ; uTCA i#phi ");

    TH2F * h_vmeOccp_cut = makeTH2F("h_vmeOccp_cut",81,-40.5,40.5,72,0.5,72.5);
    h_vmeOccp_cut -> SetTitle("Cut ; VME i#eta ; VME i#phi ");


    //--------------------------------------------------------------------------------
    // Loop
    //--------------------------------------------------------------------------------
    for (int i = 0; i < n_events; ++i) {

        utca_tree -> GetEntry(i);
        vme_tree -> GetEntry(i);

        if ( (i + 1) % 100 == 0 ) std::cout << "Processing event " << i + 1 << "/" << n_events << std::endl;

        // HBHE Digi
        CollectionPtr utcaDigis (new Collection(*utca_tree, utca_tree -> HBHEDigiIEta -> size()));
        CollectionPtr vmeDigis (new Collection(*vme_tree, vme_tree -> HBHEDigiIEta -> size()));

        int n_utcaDigis = utcaDigis -> GetSize();
        int n_vmeDigis = vmeDigis -> GetSize();

        //--------------------------------------------------------------------------------
        // uTCA Digis
        //--------------------------------------------------------------------------------

        for (int i_utcaDigis = 0; i_utcaDigis < n_utcaDigis; i_utcaDigis++) {
            HBHEDigi utcaDigi = utcaDigis -> GetConstituent<HBHEDigi>(i_utcaDigis);
            h_utcaOccp -> Fill( utcaDigi.ieta() , utcaDigi.iphi() );

            if ( utcaDigi.fc(4) + utcaDigi.fc(5) > min_charge) {
                h_utcaOccp_cut -> Fill( utcaDigi.ieta() , utcaDigi.iphi() );
            };

            for (int ifc = 0; ifc != nSample; ifc++) {
                h_uTCAfC[ifc] -> Fill( utcaDigi.fc(ifc) );
            };
        };

        //--------------------------------------------------------------------------------
        // VME Digis
        //--------------------------------------------------------------------------------

        for (int i_vmeDigis = 0; i_vmeDigis < n_vmeDigis; i_vmeDigis++) {
            HBHEDigi vmeDigi = vmeDigis -> GetConstituent<HBHEDigi>(i_vmeDigis);
            h_vmeOccp -> Fill( vmeDigi.ieta() , vmeDigi.iphi() );

            if ( vmeDigi.fc(4) + vmeDigi.fc(5) > min_charge) {
                h_vmeOccp_cut -> Fill( vmeDigi.ieta() , vmeDigi.iphi() );
            };

            for (int ifc = 0; ifc != nSample; ifc++) {
                h_vmefC[ifc] -> Fill( vmeDigi.fc(ifc) );
            };
        };

        //--------------------------------------------------------------------------------
        // Matching uTCA and VME Digis
        //--------------------------------------------------------------------------------

        for (int i_utcaDigis = 0; i_utcaDigis < n_utcaDigis; i_utcaDigis++) {

            HBHEDigi utcaDigi = utcaDigis -> GetConstituent<HBHEDigi>(i_utcaDigis);

            for (int i_vmeDigis = 0; i_vmeDigis < n_vmeDigis; i_vmeDigis++) {

                HBHEDigi vmeDigi = vmeDigis -> GetConstituent<HBHEDigi>(i_vmeDigis);

                if ( ( utcaDigi.ieta() != vmeDigi.ieta() ) || ( utcaDigi.iphi() != vmeDigi.iphi() ) || ( utcaDigi.depth() != vmeDigi.depth() ) ) continue;

                h_fcTotal -> Fill( utcaDigi.fcTotal() , vmeDigi.fcTotal() );
                h_adcTotal -> Fill( utcaDigi.adcTotal() , vmeDigi.adcTotal() );

                for (int ifc = 0; ifc != nSample; ifc++) {
                    h_fc[ifc] -> Fill( utcaDigi.fc(ifc) , vmeDigi.fc(ifc) );
                };
            };
        };

        //--------------------------------------------------------------------------------
        // TPs
        //--------------------------------------------------------------------------------

        CollectionPtr utcaTPs (new Collection(*utca_tree, utca_tree -> HcalTriggerPrimitiveIEta -> size()));
        CollectionPtr vmeTPs (new Collection(*vme_tree, vme_tree -> HcalTriggerPrimitiveIEta -> size()));

        int n_uTCATPs = utcaTPs -> GetSize();
        int n_vmeTPs = vmeTPs -> GetSize();

        for (int i_uTCATP = 0; i_uTCATP < n_uTCATPs; i_uTCATP++) {
            HcalTP utcaTP = utcaTPs -> GetConstituent<HcalTP>(i_uTCATP);

            for (int i_vmeTP = 0; i_vmeTP < n_vmeTPs; i_vmeTP++) {
                HcalTP vmeTP = vmeTPs -> GetConstituent<HcalTP>(i_vmeTP);

                if ( ( utcaTP.ieta() != vmeTP.ieta() ) || ( utcaTP.iphi() != vmeTP.iphi() )  ) continue;

                h_tpEt -> Fill( utcaTP.Et() , vmeTP.Et() );

            };
        };

    };
}
void analysisClass::loop(){

  //--------------------------------------------------------------------------------
  // Store important variables
  //--------------------------------------------------------------------------------

  for (int i_radius = 1; i_radius <= n_radii; ++i_radius){
    radii[i_radius-1] = min_radius + i_radius * (max_radius - min_radius) / double(n_radii);
  }
  
  //--------------------------------------------------------------------------------
  // Declare tree(s)
  //--------------------------------------------------------------------------------
  
  HgcalTupleTree * tree = getTree<HgcalTupleTree>("hgcal_tree");
  int n_events = tree -> fChain -> GetEntries();
  // int n_events = 200;
  
  std::vector<std::string> * rcut_values = new std::vector<std::string>();
  rcut_values -> push_back ("R5"); 
  rcut_values -> push_back ("R4"); 
  rcut_values -> push_back ("R3"); 
  rcut_values -> push_back ("R2"); 
  rcut_values -> push_back ("R1"); 
  rcut_values -> push_back ("R05"); 
  rcut_values -> push_back ("R04"); 
  rcut_values -> push_back ("R03"); 
  rcut_values -> push_back ("R02"); 
  rcut_values -> push_back ("R01"); 
  rcut_values -> push_back ("R008"); 
  rcut_values -> push_back ("R005"); 
  rcut_values -> push_back ("R003"); 
  rcut_values -> push_back ("R001");
  
  //--------------------------------------------------------------------------------
  // Likelihood getter
  //--------------------------------------------------------------------------------

  int n_rcut_variables = rcut_values -> size();

  std::vector<std::string> likelihood_variables;
  likelihood_variables.push_back ( "nDaught" );
  likelihood_variables.push_back ( "width"   );
  likelihood_variables.push_back ( "multi"   );
  likelihood_variables.push_back ( "ptd"     );
  likelihood_variables.push_back ( "nsubj"   );
  likelihood_variables.push_back ( "mass"    );
  likelihood_variables.push_back ( "profile50" );
  likelihood_variables.push_back ( "leadCoreJetFraction" );
  likelihood_variables.push_back ("leadCoreJetDR");
  
  std::string file_name ("likelihood_hists_fromWJet.root");

  std::vector<likelihoodGetter> likelihoods;

  for (int ircut = 0; ircut < n_rcut_variables; ++ircut){
    std::string signal("quarkPruned");
    signal = signal + (*rcut_values)[ircut];
    signal = signal + std::string("Jets");
    std::vector<std::string> signals;
    signals.push_back ( signal );
    likelihoodGetter l ( file_name,(*rcut_values)[ircut] , likelihood_variables, signals );
    likelihoods.push_back (l);
  }
  
  //--------------------------------------------------------------------------------
  // Make histograms
  //--------------------------------------------------------------------------------

  TH2F * all_tau_ptVsPull      = makeTH2F("all_tau_ptVsPull" ,  100, 0, 500,  100, -2, 2);
  TH2F * fid_tau_ptVsPull      = makeTH2F("fid_tau_ptVsPull" ,  100, 0, 500,  100, -2, 2);
  TH2F * all_vbfq_ptVsPull     = makeTH2F("all_vbfq_ptVsPull",  100, 0, 500,   100, -2, 2);
  TH2F * fid_vbfq_ptVsPull     = makeTH2F("fid_vbfq_ptVsPull",  100, 0, 500,   100, -2, 2);

  TH1F * all_vbfq_matchDR = makeTH1F( "all_vbfq_matchDR", 100, 0, 2 );
  TH1F * fid_vbfq_matchDR = makeTH1F( "fid_vbfq_matchDR", 100, 0, 2 );

  TH1F * all_recojet_matched_matchDR = makeTH1F("all_recojet_matched_matchDR", 100, 0, 2 );
  TH1F * all_recojet_matched_eta     = makeTH1F("all_recojet_matched_eta", 100, -5., 5.);
  TH1F * all_recojet_matched_pt      = makeTH1F("all_recojet_matched_pt", 100, 0, 200 );
	                             
  TH1F * fid_recojet_matched_matchDR = makeTH1F("fid_recojet_matched_matchDR", 100, 0, 2 );
  TH1F * fid_recojet_matched_eta     = makeTH1F("fid_recojet_matched_eta", 100, -5., 5.);
  TH1F * fid_recojet_matched_pt      = makeTH1F("fid_recojet_matched_pt", 100, 0, 200 );
  
  TH1F* all_tau_pull      = makeTH1F("all_tau_pull"     , 100, -2, 2);
  TH1F* fid_tau_pull      = makeTH1F("fid_tau_pull"     , 100, -2, 2);
  TH1F* all_vbfq_pull     = makeTH1F("all_vbfq_pull"     , 100, -2, 2);
  TH1F* fid_vbfq_pull     = makeTH1F("fid_vbfq_pull"     , 100, -2, 2);

  TH1F* all_tau_rawPull      = makeTH1F("all_tau_rawPull"     , 100, -2, 2);
  TH1F* fid_tau_rawPull      = makeTH1F("fid_tau_rawPull"     , 100, -2, 2);
  TH1F* all_vbfq_rawPull     = makeTH1F("all_vbfq_rawPull"     , 100, -2, 2);
  TH1F* fid_vbfq_rawPull     = makeTH1F("fid_vbfq_rawPull"     , 100, -2, 2);
  
  TH1F* all_tau_gen_pt    = makeTH1F("all_tau_gen_pt"   , 100, 0, 500);
  TH1F* all_tau_reco_pt   = makeTH1F("all_tau_reco_pt"  , 100, 0, 500);
  TH1F* fid_tau_gen_pt    = makeTH1F("fid_tau_gen_pt"   , 100, 0, 500);
  TH1F* fid_tau_reco_pt   = makeTH1F("fid_tau_reco_pt"  , 100, 0, 500);

  TH1F* all_vbfq_gen_pt   = makeTH1F("all_vbfq_gen_pt"  , 100, 0, 500);
  TH1F* all_vbfq_reco_pt  = makeTH1F("all_vbfq_reco_pt" , 100, 0, 500);
  TH1F* fid_vbfq_gen_pt   = makeTH1F("fid_vbfq_gen_pt"  , 100, 0, 500);
  TH1F* fid_vbfq_reco_pt  = makeTH1F("fid_vbfq_reco_pt" , 100, 0, 500);

  TH1F* all_tau_gen_eta   = makeTH1F("all_tau_gen_eta"  , 100, -5., 5.);
  TH1F* all_tau_reco_eta  = makeTH1F("all_tau_reco_eta" , 100, -5., 5.);
  TH1F* fid_tau_gen_eta   = makeTH1F("fid_tau_gen_eta"  , 100, -5., 5.);
  TH1F* fid_tau_reco_eta  = makeTH1F("fid_tau_reco_eta" , 100, -5., 5.);

  TH1F* all_vbfq_gen_eta  = makeTH1F("all_vbfq_gen_eta" , 100, -5., 5.);
  TH1F* all_vbfq_reco_eta = makeTH1F("all_vbfq_reco_eta", 100, -5., 5.);
  TH1F* fid_vbfq_gen_eta  = makeTH1F("fid_vbfq_gen_eta" , 100, -5., 5.);
  TH1F* fid_vbfq_reco_eta = makeTH1F("fid_vbfq_reco_eta", 100, -5., 5.);

  TH1F * fid_vbfq_reco_chargedFraction = makeTH1F("fid_vbfq_reco_chargedFraction", 100, 0, 1.);
  TH1F * fid_vbfq_reco_neutralFraction = makeTH1F("fid_vbfq_reco_neutralFraction", 100, 0, 1.);

  std::vector<TH1F*> th1_templates;
  th1_templates.push_back ( makeTH1F ("nsubj"                 , 20  ,  0. ,     1.  )); // 0
  th1_templates.push_back ( makeTH1F ("mass"                  , 40 ,  0. , 200000.  )); // 1
  th1_templates.push_back ( makeTH1F ("nDaught"               , 50  , -0.5,    49.5 )); // 2
  th1_templates.push_back ( makeTH1F ("multi"                 , 100 , -0.5,   999.5 ));	// 3
  th1_templates.push_back ( makeTH1F ("width"                 , 200 ,  0. ,     1.  ));	// 4
  th1_templates.push_back ( makeTH1F ("chargedWidth"          , 200 ,  0. ,     1.  ));	// 5
  th1_templates.push_back ( makeTH1F ("neutralWidth"          , 200 ,  0. ,     1.  ));	// 6
  th1_templates.push_back ( makeTH1F ("depth"                 , 200 ,  0. ,  1000.  ));	// 7
  th1_templates.push_back ( makeTH1F ("depth_noEE"            , 200 ,  0. ,  1000.  ));	// 8
  th1_templates.push_back ( makeTH1F ("ptd"                   ,  20 ,  0. ,     1.  ));	// 9
  th1_templates.push_back ( makeTH1F ("like"                  , 100 ,  0. ,     1.1 ));	// 10
  th1_templates.push_back ( makeTH1F ("ee_energy_fraction"    , 100 ,  0. ,     1.  ));	// 11
  th1_templates.push_back ( makeTH1F ("ee015_energy_fraction" , 100 ,  0. ,     1.  ));	// 12
  th1_templates.push_back ( makeTH1F ("ee1631_energy_fraction", 100 ,  0. ,     1.  )); // 13
  th1_templates.push_back ( makeTH1F ("heb_energy_fraction"   , 100 ,  0. ,     1.  ));	// 14
  th1_templates.push_back ( makeTH1F ("hef_energy_fraction"   , 100 ,  0. ,     1.  ));	// 15
  th1_templates.push_back ( makeTH1F ("hef11_energy_fraction" , 100 ,  0. ,     1.  ));	// 16
  th1_templates.push_back ( makeTH1F ("hef22_energy_fraction" , 100 ,  0. ,     1.  ));	// 17
  th1_templates.push_back ( makeTH1F ("hef34_energy_fraction" , 100 ,  0. ,     1.  ));	// 18
  th1_templates.push_back ( makeTH1F ("hef56_energy_fraction" , 100 ,  0. ,     1.  ));	// 19
  th1_templates.push_back ( makeTH1F ("hef712_energy_fraction", 100 ,  0. ,     1.  )); // 20
  th1_templates.push_back ( makeTH1F ("profile"               , n_radii + 1 ,  min_radius, max_radius )); // 21
  th1_templates.push_back ( makeTH1F ("profile50"             , n_radii + 1 ,  min_radius, max_radius )); // 22
  th1_templates.push_back ( makeTH1F ("profile90"             , n_radii + 1 ,  min_radius, max_radius )); // 23
  th1_templates.push_back ( makeTH1F ("profile95"             , n_radii + 1 ,  min_radius, max_radius )); // 24
  th1_templates.push_back ( makeTH1F ("profile99"             , n_radii + 1 ,  min_radius, max_radius )); // 25
  th1_templates.push_back ( makeTH1F ("nCoreJets"             , 10, -0.5, 9.5 )); // 26
  th1_templates.push_back ( makeTH1F ("leadCoreJetDR"         , 100, 0., 0.4 )); // 27
  th1_templates.push_back ( makeTH1F ("leadCoreJetFraction"   , 100, 0., 1.  )); // 28
  th1_templates.push_back ( makeTH1F ("volume"                , 100, -10, 10)); // 29
  th1_templates.push_back ( makeTH1F ("length"                , 100, -10, 10)); // 30
  
  std::vector<TH2F*> th2_templates;
  th2_templates.push_back ( makeTH2F ("jetPt_vs_depth"      , 100, 0, 250, 200 ,  0. ,  1000.  ));
  th2_templates.push_back ( makeTH2F ("jetPt_vs_maxRHDepth" , 100, 0, 250, 200 ,  0. ,  1000.  ));
  th2_templates.push_back ( makeTH2F ("NPFCands_vs_NSubJets", 51 , -0.5, 50.5, 5 , -0.5, 4.5 ));

  std::map<std::string, std::vector<TH1F*> > m_quark_rcut_th1;
  std::map<std::string, std::vector<TH1F*> > m_gluon_rcut_th1;
  std::map<std::string, std::vector<TH2F*> > m_quark_rcut_th2;
  std::map<std::string, std::vector<TH2F*> > m_gluon_rcut_th2;
  
  int n_th1_templates = th1_templates.size();
  int n_th2_templates = th2_templates.size();
  int n_rcutValues    = rcut_values -> size();
  char quark_hist_name[100];
  char gluon_hist_name[100];

  for (int i_th1_template = 0; i_th1_template < n_th1_templates; ++i_th1_template){
    for (int i_rcutValue = 0; i_rcutValue < n_rcutValues; ++i_rcutValue ){
      
      TH1F * hist_template = th1_templates[i_th1_template];
      
      sprintf(quark_hist_name, "%s_quarkPruned%sJets", hist_template -> GetName(), (*rcut_values)[i_rcutValue].c_str());
      sprintf(gluon_hist_name, "%s_gluonPruned%sJets", hist_template -> GetName(), (*rcut_values)[i_rcutValue].c_str());
      
      TH1F * quark_hist = makeTH1F(quark_hist_name, 
				   hist_template -> GetNbinsX(), 
				   hist_template -> GetXaxis() -> GetXmin(),
				   hist_template -> GetXaxis() -> GetXmax() );
				   
      TH1F * gluon_hist = makeTH1F(gluon_hist_name, 
				   hist_template -> GetNbinsX(), 
				   hist_template -> GetXaxis() -> GetXmin(),
				   hist_template -> GetXaxis() -> GetXmax() );

      m_quark_rcut_th1[(*rcut_values)[i_rcutValue]].push_back(quark_hist);
      m_gluon_rcut_th1[(*rcut_values)[i_rcutValue]].push_back(gluon_hist);
      
    }
  }

  
  for (int i_th2_template = 0; i_th2_template < n_th2_templates; ++i_th2_template){
    for (int i_rcutValue = 0; i_rcutValue < n_rcutValues; ++i_rcutValue ){
      
      TH2F * hist_template = th2_templates[i_th2_template];
      
      sprintf(quark_hist_name, "%s_quarkPruned%sJets", hist_template -> GetName(), (*rcut_values)[i_rcutValue].c_str());
      sprintf(gluon_hist_name, "%s_gluonPruned%sJets", hist_template -> GetName(), (*rcut_values)[i_rcutValue].c_str());
      
      TH2F * quark_hist = makeTH2F(quark_hist_name, 
				   hist_template -> GetNbinsX(), 
				   hist_template -> GetXaxis() -> GetXmin(),
				   hist_template -> GetXaxis() -> GetXmax(),
				   hist_template -> GetNbinsY(), 
				   hist_template -> GetYaxis() -> GetXmin(),
				   hist_template -> GetYaxis() -> GetXmax());
				   
      TH2F * gluon_hist = makeTH2F(gluon_hist_name, 
				   hist_template -> GetNbinsX(), 
				   hist_template -> GetXaxis() -> GetXmin(),
				   hist_template -> GetXaxis() -> GetXmax(),
				   hist_template -> GetNbinsY(), 
				   hist_template -> GetYaxis() -> GetXmin(),
				   hist_template -> GetYaxis() -> GetXmax());
				   
      m_quark_rcut_th2[(*rcut_values)[i_rcutValue]].push_back(quark_hist);
      m_gluon_rcut_th2[(*rcut_values)[i_rcutValue]].push_back(gluon_hist);
      
    }
  }

  
  
  //--------------------------------------------------------------------------------
  // Loop over the events
  //--------------------------------------------------------------------------------
  
  for (int iEvent = 0; iEvent < n_events; ++iEvent){

    //--------------------------------------------------------------------------------
    // Tell the user where we are
    //--------------------------------------------------------------------------------

    if ( (iEvent + 1) <= 10 || (iEvent + 1) % 100 == 0 ) 
      std::cout << "Processing event " << (iEvent + 1) << "/" << n_events << std::endl;
    
    //--------------------------------------------------------------------------------
    // Get each entry in the event
    //--------------------------------------------------------------------------------

    tree -> GetEntry (iEvent);

    //--------------------------------------------------------------------------------
    // GEN particle collections
    //--------------------------------------------------------------------------------
    
    // All GEN particles
    CollectionPtr c_gen_all  ( new Collection(*tree, tree -> GenParticlePt -> size()));

    // std::cout << "------------------------------------------------------------" << std::endl;
    // c_gen_all ->  examine <GenParticle> ( "All GEN particles" );
    // 
    // continue;

    // GEN particles for jet matching
    CollectionPtr c_partons  = c_gen_all -> SkimByID<GenParticle>(GEN_PARTICLE_IS_FINAL_STATE_PARTON);
    CollectionPtr c_gen_vbfq = c_gen_all -> SkimByID<GenParticle>(GEN_PARTICLE_IS_HARD_SCATTER_VBF_QUARK);
    CollectionPtr c_gen_tau  = c_gen_all -> SkimByID<GenParticle>(GEN_PARTICLE_IS_HARD_SCATTER_TAU);

    //--------------------------------------------------------------------------------
    // PFJet collections
    //--------------------------------------------------------------------------------

    CollectionPtr c_pfjet_all  ( new Collection(*tree, tree -> PFCA4JetPt -> size()));
    CollectionPtr c_pfjet_minPt       = c_pfjet_all   -> SkimByMinPt<PFPrunedJet> ( pfjet_pt_minimum ) ;
    CollectionPtr c_pfjet_fid         = c_pfjet_all   -> SkimByAbsEtaRange<PFPrunedJet> ( HGCAL_abseta_min, HGCAL_abseta_max );
    CollectionPtr c_pfjet_minPtAndFid = c_pfjet_minPt -> SkimByAbsEtaRange<PFPrunedJet> ( HGCAL_abseta_min, HGCAL_abseta_max );

    CollectionPtr c_pfcorejet_all  ( new Collection(*tree, tree -> PFAK1p5JetPt -> size()));
    CollectionPtr c_pfcorejet_minPt       = c_pfcorejet_all   -> SkimByMinPt<PFCoreJet> ( pfcorejet_pt_minimum ) ;
    CollectionPtr c_pfcorejet_minPtAndFid = c_pfcorejet_minPt -> SkimByAbsEtaRange<PFCoreJet> ( HGCAL_abseta_min, HGCAL_abseta_max );

    //--------------------------------------------------------------------------------
    // Clusters
    //--------------------------------------------------------------------------------

    CollectionPtr c_hgceeClusters_all  ( new Collection (*tree, tree -> HGCEEPFClusterPt  -> size()));
    CollectionPtr c_hgchefClusters_all ( new Collection (*tree, tree -> HGCHEFPFClusterPt -> size()));
    CollectionPtr c_hgchebClusters_all ( new Collection (*tree, tree -> HGCHEBPFClusterPt -> size()));
    
    //--------------------------------------------------------------------------------
    // GenJet collections
    //--------------------------------------------------------------------------------

    /*
    CollectionPtr c_genjet_all ( new Collection(*tree, tree -> GenJetPt -> size()));
    int n_genjet = c_genjet_all -> GetSize();

    for (int i_genjet = 0; i_genjet < n_genjet; ++i_genjet){
      GenJet genjet = c_genjet_all -> GetConstituent<GenJet>(i_genjet);
      int flavor = getFlavor( genjet, c_partons );
      if ( flavor == 0 ) continue;
      PFPrunedJet jet_matched_reco = c_pfjet_all -> GetClosestInDR<PFPrunedJet, GenJet>(genjet);
      double deltaR = jet_matched_reco.DeltaR( &genjet );
      double eta    = jet_matched_reco.Eta();
      double pt     = jet_matched_reco.Pt();
      
      all_recojet_matched_matchDR  -> Fill ( deltaR );
      all_recojet_matched_eta      -> Fill ( eta    );
      all_recojet_matched_pt       -> Fill ( pt     );
                                  
      if ( abs(genjet.Eta()) > HGCAL_abseta_min && 
	   abs(genjet.Eta()) < HGCAL_abseta_max ){
	
	fid_recojet_matched_matchDR -> Fill ( deltaR ) ;
	fid_recojet_matched_eta     -> Fill ( eta    ) ;
	fid_recojet_matched_pt      -> Fill ( pt     ) ;
      }
    }
    */

    //--------------------------------------------------------------------------------
    // Match PFJets 
    //--------------------------------------------------------------------------------

    int n_gen_vbfq = c_gen_vbfq -> GetSize();

    for (int i_gen_vbfq = 0; i_gen_vbfq < n_gen_vbfq; ++i_gen_vbfq){

      GenParticle vbfq_gen  = c_gen_vbfq    -> GetConstituent<GenParticle> (i_gen_vbfq);
      PFPrunedJet vbfq_reco = c_pfjet_minPt -> GetClosestInDR<PFPrunedJet, GenParticle>(vbfq_gen);      

      if ( vbfq_reco.GetRawIndex() < 0 ) continue;
      double pull, rawPull;
      if ( vbfq_gen.Pt() > 0. ) pull    = (vbfq_reco.Pt()    - vbfq_gen.Pt()) / vbfq_gen.Pt();
      if ( vbfq_gen.Pt() > 0. ) rawPull = (vbfq_reco.PtRaw() - vbfq_gen.Pt()) / vbfq_gen.Pt();
      else continue;
      
      bool isFid = ( fabs(vbfq_gen.Eta()) >= HGCAL_abseta_min &&
		     fabs(vbfq_gen.Eta()) <= HGCAL_abseta_max );

      double deltaR = vbfq_reco.DeltaR(&vbfq_gen);
      if ( deltaR > maximum_deltaR_match ) continue;

      all_vbfq_ptVsPull -> Fill ( vbfq_gen.Pt(), pull );
      all_vbfq_pull     -> Fill ( pull );
      all_vbfq_rawPull  -> Fill ( rawPull );
      all_vbfq_gen_pt   -> Fill ( vbfq_gen.Pt() );
      all_vbfq_reco_pt  -> Fill ( vbfq_reco.Pt() );
      all_vbfq_gen_eta  -> Fill ( vbfq_gen.Eta() );
      all_vbfq_reco_eta -> Fill ( vbfq_reco.Eta() );
      all_vbfq_matchDR  -> Fill ( deltaR );

      if ( isFid ){
	fid_vbfq_reco_chargedFraction -> Fill ( vbfq_reco.getChargedFraction() );
	fid_vbfq_reco_neutralFraction -> Fill ( vbfq_reco.getNeutralFraction() );
	fid_vbfq_ptVsPull -> Fill ( vbfq_gen.Pt(), pull );
	fid_vbfq_pull     -> Fill ( pull );
	fid_vbfq_rawPull  -> Fill ( rawPull );
	fid_vbfq_gen_pt   -> Fill ( vbfq_gen.Pt() );
	fid_vbfq_reco_pt  -> Fill ( vbfq_reco.Pt() );
	fid_vbfq_gen_eta  -> Fill ( vbfq_gen.Eta() );
	fid_vbfq_reco_eta -> Fill ( vbfq_reco.Eta() );
	fid_vbfq_matchDR  -> Fill ( vbfq_reco.DeltaR(&vbfq_gen));
      }
    }

    int n_gen_tau = c_gen_tau -> GetSize();
    for (int i_gen_tau = 0; i_gen_tau < n_gen_tau; ++i_gen_tau){
      GenParticle tau_gen  = c_gen_tau  -> GetConstituent<GenParticle> (i_gen_tau);
      PFPrunedJet tau_reco = c_pfjet_all -> GetClosestInDR<PFPrunedJet, GenParticle>(tau_gen);
      if ( tau_reco.GetRawIndex() < 0 ) continue;
      double pull, rawPull;
      if ( tau_gen.Pt() > 0. ) pull    = (tau_reco.Pt()    - tau_gen.Pt()) / tau_gen.Pt();
      if ( tau_gen.Pt() > 0. ) rawPull = (tau_reco.PtRaw() - tau_gen.Pt()) / tau_gen.Pt();
      bool isFid = ( fabs(tau_gen.Eta()) >= HGCAL_abseta_min &&
		     fabs(tau_gen.Eta()) <= HGCAL_abseta_max );


      all_tau_ptVsPull -> Fill ( tau_gen.Pt(), pull );
      all_tau_pull     -> Fill ( pull );
      all_tau_rawPull  -> Fill ( rawPull );
      all_tau_gen_pt   -> Fill ( tau_gen.Pt() );
      all_tau_reco_pt  -> Fill ( tau_reco.Pt() );
      all_tau_gen_eta   -> Fill ( tau_gen.Eta() );
      all_tau_reco_eta  -> Fill ( tau_reco.Eta() );

      if ( isFid ){
	fid_tau_ptVsPull -> Fill ( tau_gen.Pt(), pull );
	fid_tau_pull     -> Fill ( pull );
	fid_tau_rawPull  -> Fill ( rawPull );
	fid_tau_gen_pt   -> Fill ( tau_gen.Pt() );
	fid_tau_reco_pt  -> Fill ( tau_reco.Pt() );
	fid_tau_gen_eta   -> Fill ( tau_gen.Eta() );
	fid_tau_reco_eta  -> Fill ( tau_reco.Eta() );
      }
    }

    //--------------------------------------------------------------------------------
    // Loop over rcut values
    //--------------------------------------------------------------------------------

    for (int i_rcutValue = 0; i_rcutValue < n_rcutValues; ++i_rcutValue){

      fillPlots<PFPrunedJet> ( c_pfjet_minPtAndFid, c_pfcorejet_minPtAndFid , c_partons,
			       c_hgceeClusters_all, c_hgchefClusters_all, c_hgchebClusters_all, 
			       likelihoods[i_rcutValue], i_rcutValue,
    			       m_quark_rcut_th1[(*rcut_values)[i_rcutValue]], 
    			       m_gluon_rcut_th1[(*rcut_values)[i_rcutValue]], 
    			       m_quark_rcut_th2[(*rcut_values)[i_rcutValue]], 
    			       m_gluon_rcut_th2[(*rcut_values)[i_rcutValue]] );
      
    }
    // end loop over r-cut values
  } // end loop over events
} // end loop function
void analysisClass::loop(){

  //--------------------------------------------------------------------------------
  // Declare HCAL tree(s)
  //--------------------------------------------------------------------------------

  HcalNoiseTree * noise_tree = getTree<HcalNoiseTree>("noise_tree");
  int n_events = noise_tree -> fChain -> GetEntries();

  //--------------------------------------------------------------------------------
  // Clean branches we don't need
  //--------------------------------------------------------------------------------

  noise_tree -> fChain -> SetBranchStatus("*"         , kFALSE);
  noise_tree -> fChain -> SetBranchStatus("PulseCount", kTRUE );
  noise_tree -> fChain -> SetBranchStatus("IEta"      , kTRUE );
  noise_tree -> fChain -> SetBranchStatus("IPhi"      , kTRUE );
  noise_tree -> fChain -> SetBranchStatus("Depth"     , kTRUE );
  noise_tree -> fChain -> SetBranchStatus("Energy"    , kTRUE );
  noise_tree -> fChain -> SetBranchStatus("Charge"    , kTRUE );
  noise_tree -> fChain -> SetBranchStatus("OfficialDecision", kTRUE);
  noise_tree -> fChain -> SetBranchStatus("NumberOfGoodPrimaryVertices", kTRUE);

  //--------------------------------------------------------------------------------
  // Declare some important quantities
  //--------------------------------------------------------------------------------
  
  const int nrings = 6;

  //--------------------------------------------------------------------------------
  // Declare histograms
  //--------------------------------------------------------------------------------

  TH1F * h_npv = makeTH1F("npv",5,-0.5,4.5);
  TH1F * h_ieta= makeTH1F("ieta", 59, -29.5, 29.5 );
  TH1F * h_iphi= makeTH1F("iphi", 73, -0.5, 72.5 );
  TH2F * h_ieta_iphi = makeTH2F("ieta_iphi", 59, -29.5, 29.5, 73, -0.5, 72.5 );
  
  char hist_name[100];
  std::vector<TH2F*> a0_histograms, a1_histograms, a2_histograms, a3_histograms;
  for (int iring = 0; iring < nrings; ++iring){
    sprintf(hist_name, "a0_ring%d", iring); a0_histograms.push_back(makeTH2F(hist_name, 3000, 0, 3000, 10000, -10.0, 10.0));
    sprintf(hist_name, "a1_ring%d", iring); a1_histograms.push_back(makeTH2F(hist_name, 3000, 0, 3000, 10000, -10.0, 10.0));
    sprintf(hist_name, "a2_ring%d", iring); a2_histograms.push_back(makeTH2F(hist_name, 3000, 0, 3000, 10000, -10.0, 10.0));
    sprintf(hist_name, "a3_ring%d", iring); a3_histograms.push_back(makeTH2F(hist_name, 3000, 0, 3000, 10000, -10.0, 10.0));
  }

  TH2F* a0_histogram_hb = makeTH2F("a0_hb", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a1_histogram_hb = makeTH2F("a1_hb", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a2_histogram_hb = makeTH2F("a2_hb", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a3_histogram_hb = makeTH2F("a3_hb", 3000, 0, 3000, 100, -10.0, 10.0);

  TH2F* a0_histogram_he = makeTH2F("a0_he", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a1_histogram_he = makeTH2F("a1_he", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a2_histogram_he = makeTH2F("a2_he", 3000, 0, 3000, 100, -10.0, 10.0);
  TH2F* a3_histogram_he = makeTH2F("a3_he", 3000, 0, 3000, 100, -10.0, 10.0);
  
  //--------------------------------------------------------------------------------
  // Loop over the events
  //--------------------------------------------------------------------------------
  
  for (int iEvent = 0; iEvent < n_events; ++iEvent){

    //--------------------------------------------------------------------------------
    // Tell the user where we are
    //--------------------------------------------------------------------------------

    if (iEvent%1000 == 0) std::cout << "Processing event " << iEvent << "/" << n_events << std::endl;
    
    //--------------------------------------------------------------------------------
    // Get each entry in the event
    //--------------------------------------------------------------------------------

    noise_tree -> GetEntry(iEvent);

    //--------------------------------------------------------------------------------
    // Event-level selection
    // Note: "official selection" variable is always zero for MC?
    //--------------------------------------------------------------------------------

    // if ( noise_tree -> OfficialDecision ) continue;
    if ( noise_tree -> NumberOfGoodPrimaryVertices == 0 ) continue;

    //--------------------------------------------------------------------------------
    // Loop over the cells
    //--------------------------------------------------------------------------------
    
    int nHBHE = noise_tree -> PulseCount;
    
    h_npv -> Fill(noise_tree -> NumberOfGoodPrimaryVertices);

    for (int iHBHE = 0; iHBHE < nHBHE; ++iHBHE){

      //--------------------------------------------------------------------------------
      // Store some important values for selection
      //--------------------------------------------------------------------------------

      int     ieta   = noise_tree -> IEta  [iHBHE];
      int     iphi   = noise_tree -> IPhi  [iHBHE];
      int    depth   = noise_tree -> Depth [iHBHE];
      bool     bad   = isBadChannel(0, ieta, iphi, depth);
      int     ring   = getRing(ieta);
      
      //--------------------------------------------------------------------------------
      // Cell-level selection
      //--------------------------------------------------------------------------------
      
      if (ring < 0) continue;
      if (noise_tree -> Energy[iHBHE]    < 1.0) continue;
      if (noise_tree -> Charge[iHBHE][4] < 5.0) continue;
      if (bad) continue;

      //--------------------------------------------------------------------------------
      // Store some important values for plotting
      //--------------------------------------------------------------------------------
      
      double TS1 = noise_tree -> Charge[iHBHE][1];
      double TS2 = noise_tree -> Charge[iHBHE][2];
      double TS3 = noise_tree -> Charge[iHBHE][3];
      double TS4 = noise_tree -> Charge[iHBHE][4];
      double TS5 = noise_tree -> Charge[iHBHE][5];
      double TS6 = noise_tree -> Charge[iHBHE][6];
      double TS7 = noise_tree -> Charge[iHBHE][7];

      /*
      std::cout << "-------------------------------------------------------------------------------------------------------------------------------" << std::endl;
      for (int i = 0; i < 10; i++){
	std::cout << i << "\t";
      }
      std::cout << std::endl;
      for (int i = 0; i < 10; i++){
	std::cout << std::setprecision(2) <<  noise_tree -> Charge[iHBHE][i] << "\t";
      }
      std::cout << std::endl;
      */
      
      double a0  = TS3/TS4;
      double a1  = TS5/TS4;
      double a2  = TS6/TS4;
      double a3  = TS7/TS4;
      
      //--------------------------------------------------------------------------------
      // Fill histograms
      //--------------------------------------------------------------------------------

      h_ieta      -> Fill ( ieta );
      h_iphi      -> Fill ( iphi );
      h_ieta_iphi -> Fill ( ieta, iphi );

      a0_histograms[ring] -> Fill(TS4, a0);
      a1_histograms[ring] -> Fill(TS4, a1);
      a2_histograms[ring] -> Fill(TS4, a2);
      a3_histograms[ring] -> Fill(TS4, a3);

      if ( ring == 0 ){
	a0_histogram_hb -> Fill(TS4, a0);
	a1_histogram_hb -> Fill(TS4, a1);
	a2_histogram_hb -> Fill(TS4, a2);
	a3_histogram_hb -> Fill(TS4, a3);
      }

      else { 
      	a0_histogram_he -> Fill(TS4, a0);
      	a1_histogram_he -> Fill(TS4, a1);
	a2_histogram_he -> Fill(TS4, a2);
	a3_histogram_he -> Fill(TS4, a3);
      }
      
    }      
  }
}
void analysisClassL1::loop(){

  std::string MyTrigger="HLT_Any";

  std::vector<std::string> triggerList =  {"L1_SingleJet092","L1_SingleJet128","L1_SingleJet176","L1_SingleJet200","L1_SingleJet240"};
  std::vector<std::string> preTriggerList =  {"L1_SingleJet092","L1_SingleJet128","L1_SingleJet176","L1_SingleJet200","L1_SingleJet240"};

  L1Tree * l1Tree = getTree<L1Tree>("l1Tree");

  int n_events = l1Tree -> fChain -> GetEntries();

  l1Tree -> fChain -> SetBranchStatus("*", kFALSE);
  l1Tree -> fChain -> SetBranchStatus("lumi",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Njet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Bxjet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Rankjet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Etajet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Phijet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("Fwdjet",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("tw1",kTRUE);
  l1Tree -> fChain -> SetBranchStatus("tw2",kTRUE);
  
  std::map<std::string,TH1F*> etaHistList;
  std::map<std::string,TH2F*> etaPhiHistList;
  std::map<std::string,TH1F*> l1BitHistList;
  std::map<std::string,std::map<std::string,TH1F*>> preFireEtaHistList;
  std::map<std::string,std::map<std::string,TH2F*>> prePreFireEtaPhiHistList;
  std::map<std::string,std::map<std::string,TH2F*>> preFireEtaPhiHistList;
  std::map<std::string,std::map<std::string,TH2F*>> postFireEtaPhiHistList;
  std::map<std::string,std::map<std::string,TH2F*>> postPostFireEtaPhiHistList;
  std::map<std::string,std::map<std::string,TH1F*>> deltaRHistList;
  std::map<std::string,std::map<std::string,TH1F*>> postDeltaRHistList;
  std::map<std::string,std::map<std::string,TH1F*>> postPostDeltaRHistList;
  std::map<std::string,std::map<std::string,TH1F*>> prePreDeltaRHistList;
  char histName[100];
  for (std::vector<std::string>::iterator it = triggerList.begin(); it != triggerList.end(); it++){
    sprintf(histName,"h_etaBin_%s",it->c_str());
    etaHistList[*it] = makeTH1F(histName,22,-0.5,21.5);
    sprintf(histName,"h_etaPhiBin_%s",it->c_str());
    etaPhiHistList[*it] = makeTH2F(histName,22,-0.5,21.5,18,-0.5,17.5);
    sprintf(histName,"h_l1Bit_%s",it->c_str());
    l1BitHistList[*it] = makeTH1F(histName,2,-0.5,1.5);
    preFireEtaHistList[*it] = std::map<std::string,TH1F*>();
    for (std::vector<std::string>::iterator it2 = preTriggerList.begin(); it2 != preTriggerList.end(); it2++){
      sprintf(histName,"h_preFireEtaBin%s_%s",it->c_str(),it2->c_str());
      preFireEtaHistList[*it][*it2] = makeTH1F(histName,22,-0.5,21.5);
      sprintf(histName,"h_prePreFireEtaPhiBin%s_%s",it->c_str(),it2->c_str());
      prePreFireEtaPhiHistList[*it][*it2] = makeTH2F(histName,22,-0.5,21.5,18,-0.5,17.5);
      sprintf(histName,"h_preFireEtaPhiBin%s_%s",it->c_str(),it2->c_str());
      preFireEtaPhiHistList[*it][*it2] = makeTH2F(histName,22,-0.5,21.5,18,-0.5,17.5);
      sprintf(histName,"h_postFireEtaPhiBin%s_%s",it->c_str(),it2->c_str());
      postFireEtaPhiHistList[*it][*it2] = makeTH2F(histName,22,-0.5,21.5,18,-0.5,17.5);
      sprintf(histName,"h_postPostFireEtaPhiBin%s_%s",it->c_str(),it2->c_str());
      postPostFireEtaPhiHistList[*it][*it2] = makeTH2F(histName,22,-0.5,21.5,18,-0.5,17.5);
      sprintf(histName,"h_deltaR%s_%s",it->c_str(),it2->c_str());
      deltaRHistList[*it][*it2] = makeTH1F(histName,50,-0.5,5.5);
      sprintf(histName,"h_postDeltaR%s_%s",it->c_str(),it2->c_str());
      postDeltaRHistList[*it][*it2] = makeTH1F(histName,50,-0.5,5.5);
      sprintf(histName,"h_prePreDeltaR%s_%s",it->c_str(),it2->c_str());
      prePreDeltaRHistList[*it][*it2] = makeTH1F(histName,50,-0.5,5.5);
      sprintf(histName,"h_postPostDeltaR%s_%s",it->c_str(),it2->c_str());
      postPostDeltaRHistList[*it][*it2] = makeTH1F(histName,50,-0.5,5.5);
    };
  };

  loadPrescaleMap();
  loadBitMap();

  for (int i = 0; i < n_events; ++i){
    l1Tree -> GetEntry(i);
    if ( (i + 1) % 10000 == 0 ) std::cout << "Processing event " << i + 1 << "/" << n_events << std::endl;

    int lumi = l1Tree -> lumi;
    if (lumi < 126) continue;
    int prescaleIndex;
    if (lumi < 317){
      prescaleIndex = 6;
    }else{
      prescaleIndex = 7;
    };

    tw1 = l1Tree -> tw1;
    tw2 = l1Tree -> tw2;
    Njet = l1Tree -> Njet;
    Bxjet = l1Tree -> Bxjet;
    Rankjet = l1Tree -> Rankjet;
    Etajet = l1Tree -> Etajet;
    Phijet = l1Tree -> Phijet;
    Fwdjet = l1Tree -> Fwdjet;
    tw1 = l1Tree -> tw1;
    tw2 = l1Tree -> tw2;

    for (std::vector<std::string>::iterator it = triggerList.begin(); it != triggerList.end(); it++){
      bool Bx2Fired = checkTriggerBit(BitMap[*it],2);
      float ptThreshold = (float)std::stoi(it -> substr(12)); 
      int jetEtaBin = SingleJetEtaBin(ptThreshold,0);
      int jetPhiBin = SingleJetPhiBin(ptThreshold,0);
      if (Bx2Fired){
        l1BitHistList[*it] -> Fill(1,PrescaleMap[prescaleIndex][*it]);
      };

      if ((jetEtaBin != -10) && (jetPhiBin != -10)){
        etaHistList[*it] -> Fill(jetEtaBin,PrescaleMap[prescaleIndex][*it]);
	etaPhiHistList[*it] -> Fill(jetEtaBin,jetPhiBin,PrescaleMap[prescaleIndex][*it]);
        for (std::vector<std::string>::iterator it2 = preTriggerList.begin(); it2 != preTriggerList.end(); it2++){
	  float ptThreshold_OtherBx = (float)std::stoi(it2 -> substr(12));
	  int jetEtaBin_BxM1 = SingleJetEtaBin(ptThreshold_OtherBx,-1);
	  int jetPhiBin_BxM1 = SingleJetPhiBin(ptThreshold_OtherBx,-1);
          if ((jetEtaBin_BxM1 != -10) && (jetPhiBin_BxM1 != -10)){
            preFireEtaHistList[*it][*it2] -> Fill(jetEtaBin_BxM1,PrescaleMap[prescaleIndex][*it2]);
	    preFireEtaPhiHistList[*it][*it2] -> Fill(jetEtaBin_BxM1,jetPhiBin_BxM1,PrescaleMap[prescaleIndex][*it2]);
            double jetEta_BxM1 = SingleJetEta(ptThreshold_OtherBx,-1);
            double jetPhi_BxM1 = SingleJetPhi(ptThreshold_OtherBx,-1);
            double jetEta = SingleJetEta(ptThreshold,0);
            double jetPhi = SingleJetPhi(ptThreshold,0);
	    deltaRHistList[*it][*it2] -> Fill(DeltaR(jetEta_BxM1,jetEta,jetPhi_BxM1,jetPhi));
	  };
	  int jetEtaBin_BxP1 = SingleJetEtaBin(ptThreshold_OtherBx,1);
	  int jetPhiBin_BxP1 = SingleJetPhiBin(ptThreshold_OtherBx,1);
	  if ((jetEtaBin_BxP1 != -10) && (jetPhiBin_BxP1 != -10)){
	    double jetEta = SingleJetEta(ptThreshold,0);
            double jetPhi = SingleJetPhi(ptThreshold,0);
	    postFireEtaPhiHistList[*it][*it2] -> Fill(jetEtaBin_BxP1,jetPhiBin_BxP1,PrescaleMap[prescaleIndex][*it2]);
            postDeltaRHistList[*it][*it2] -> Fill(DeltaR(jetEtaBin_BxP1,jetEta,jetPhiBin_BxP1,jetPhi));
	  };
	  int jetEtaBin_BxM2 = SingleJetEtaBin(ptThreshold_OtherBx,-2);
	  int jetPhiBin_BxM2 = SingleJetPhiBin(ptThreshold_OtherBx,-2);
	  if ((jetEtaBin_BxM2 != -10) && (jetPhiBin_BxM2 != -10)){
	    double jetEta = SingleJetEta(ptThreshold,0);
            double jetPhi = SingleJetPhi(ptThreshold,0);
	    prePreFireEtaPhiHistList[*it][*it2] -> Fill(jetEtaBin_BxM2,jetPhiBin_BxM2,PrescaleMap[prescaleIndex][*it2]);
            prePreDeltaRHistList[*it][*it2] -> Fill(DeltaR(jetEtaBin_BxM2,jetEta,jetPhiBin_BxM2,jetPhi));
	  };
	  int jetEtaBin_BxP2 = SingleJetEtaBin(ptThreshold_OtherBx,2);
	  int jetPhiBin_BxP2 = SingleJetPhiBin(ptThreshold_OtherBx,2);
	  if ((jetEtaBin_BxP2 != -10) && (jetPhiBin_BxP2 != -10)){
	    double jetEta = SingleJetEta(ptThreshold,0);
            double jetPhi = SingleJetPhi(ptThreshold,0);
	    postPostFireEtaPhiHistList[*it][*it2] -> Fill(jetEtaBin_BxP2,jetPhiBin_BxP2,PrescaleMap[prescaleIndex][*it2]);
            postPostDeltaRHistList[*it][*it2] -> Fill(DeltaR(jetEtaBin_BxP2,jetEta,jetPhiBin_BxP2,jetPhi));
	  };

	};
      };
    };
  };

  char titleName[100];
  for (std::map<std::string,TH1F*>::iterator itr = etaHistList.begin(); itr != etaHistList.end(); ++itr){
    sprintf(titleName,"%s, L1Object:%4.0f, L1Bit:%4.0f ; Eta Bin ( 0 - 21 ); Number of Event",itr->first.c_str(),itr -> second -> Integral(),l1BitHistList[itr->first]->Integral());
    itr -> second -> SetTitle(titleName);
    sprintf(titleName,"%s, L1Object:%4.0f, L1Bit:%4.0f ; Eta Bin ( 0 - 21 ); Phi Bin ( 0 - 17 )",itr->first.c_str(),etaPhiHistList[itr -> first],l1BitHistList[itr->first]->Integral());
    etaPhiHistList[itr -> first] -> SetTitle(titleName);
    for (std::vector<std::string>::iterator it2 = preTriggerList.begin(); it2 != preTriggerList.end(); it2++){
      sprintf(titleName,"Bx2: %s, Bx1: %s, Prefire Rate: %4.3f ; Eta Bin ( 0 - 21 ); Number of Event",itr->first.c_str(),it2->c_str(),preFireEtaHistList[itr->first][*it2]->Integral()/itr->second->Integral());
      preFireEtaHistList[itr->first][*it2] -> SetTitle(titleName);
      sprintf(titleName,"Bx2: %s, Bx1: %s, Prefire Rate: %4.3f ; Eta Bin ( 0 - 21 ); Phi Bin (0 - 17)",itr->first.c_str(),it2->c_str(),preFireEtaHistList[itr->first][*it2]->Integral()/itr->second->Integral());
      preFireEtaPhiHistList[itr->first][*it2] -> SetTitle(titleName);
      sprintf(titleName,"Bx2: %s, Bx1: %s, Prefire Rate: %4.3f ; Eta Bin ( 0 - 21 ); Phi Bin (0 - 17)",itr->first.c_str(),it2->c_str(),preFireEtaHistList[itr->first][*it2]->Integral()/itr->second->Integral());
      postFireEtaPhiHistList[itr->first][*it2] -> SetTitle(titleName);
    };
  };
}
void analysisClass::loop(){


  
  //--------------------------------------------------------------------------------
  // Configurables
  //--------------------------------------------------------------------------------
  std::vector<int> selectIPhis = {19,21,23,25};
 
  //--------------------------------------------------------------------------------
  // Declare HCAL tree(s)
  //--------------------------------------------------------------------------------

  HcalTupleTree * tuple_tree = getTree<HcalTupleTree>("tuple_tree");
  int n_events = tuple_tree -> fChain -> GetEntries();
  std::cout << "n events = " << n_events << std::endl;

  //--------------------------------------------------------------------------------
  // Turn on/off branches
  //--------------------------------------------------------------------------------
  
  tuple_tree -> fChain -> SetBranchStatus("*"               , kFALSE);
  tuple_tree -> fChain -> SetBranchStatus("run", kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("event", kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("ls", kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalTriggerPrimitiveCompressedEtSOI",kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalEmulTriggerPrimitiveCompressedEtSOI",kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalTriggerPrimitiveIEta",kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalEmulTriggerPrimitiveIEta",kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalTriggerPrimitiveIPhi",kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HcalEmulTriggerPrimitiveIPhi",kTRUE);

  //--------------------------------------------------------------------------------
  // Make histograms
  //--------------------------------------------------------------------------------
  char histName[100];
  std::map<int,std::map<int,TH2F*>> h_emulTPEt_vs_TPEt;
  h_emulTPEt_vs_TPEt[1] = std::map<int,TH2F*>();
  h_emulTPEt_vs_TPEt[2] = std::map<int,TH2F*>();
  
  for (int iIPhi = 0; iIPhi != selectIPhis.size(); ++iIPhi){
    sprintf(histName,"h_emulTPEt_vs_TPEt_1_%d",selectIPhis[iIPhi]);
    h_emulTPEt_vs_TPEt[1][selectIPhis[iIPhi]] = makeTH2F(histName,50,0.,100.,50,0.,100.);
    sprintf(histName,"h_emulTPEt_vs_TPEt_2_%d",selectIPhis[iIPhi]);
    h_emulTPEt_vs_TPEt[2][selectIPhis[iIPhi]] = makeTH2F(histName,50,0.,100.,50,0.,100.);
  };
  TH1F * h_lumiSection = makeTH1F("h_lumiSection",497,0.5,497.5);  

  //--------------------------------------------------------------------------------
  // Loop
  //--------------------------------------------------------------------------------
  int lumiSectionIndex;
  for (int i = 0; i < n_events; ++i){
    
    tuple_tree -> GetEntry(i);
    if ( (i + 1) % 10000 == 0 ) std::cout << "Processing event " << i + 1 << "/" << n_events << std::endl;
    
    //-----------------------------------------------------------------
    // Collections of Hcal Trigger Primitive 
    //-----------------------------------------------------------------
    int lumiSection = tuple_tree -> ls;

    h_lumiSection -> Fill(lumiSection);
    if (lumiSection < 400){
      lumiSectionIndex = 1;
    } else {
      lumiSectionIndex = 2;
    };

    CollectionPtr hcalTPs (new Collection(*tuple_tree, tuple_tree -> HcalTriggerPrimitiveIEta -> size()));
    CollectionPtr hcalEmulTPs (new Collection(*tuple_tree, tuple_tree -> HcalEmulTriggerPrimitiveIEta -> size()));


    int nHcalTPs = hcalTPs -> GetSize();
    int nHcalEmulTPs = hcalEmulTPs -> GetSize();
    for (int iHcalTP = 0; iHcalTP < nHcalTPs; ++iHcalTP){
       HcalTP hcalTP = hcalTPs -> GetConstituent<HcalTP>(iHcalTP);
       if( std::find( selectIPhis.begin() , selectIPhis.end() , hcalTP.iphi() ) == selectIPhis.end() ) continue;
       for (int iHcalEmulTP = 0; iHcalEmulTP  < nHcalEmulTPs; ++iHcalEmulTP){
         HcalEmulTP hcalEmulTP = hcalEmulTPs -> GetConstituent<HcalEmulTP>(iHcalEmulTP);
         if ( (hcalEmulTP.ieta() == hcalTP.ieta() && (hcalEmulTP.iphi() == hcalTP.iphi()) ) ){
	   h_emulTPEt_vs_TPEt[lumiSectionIndex][hcalTP.iphi()] -> Fill(hcalEmulTP.Et(),hcalTP.Et());
	 };	 
       };
    };
  };
};
void analysisClass::loop(){
  
  //--------------------------------------------------------------------------------
  // Declare HCAL tree(s)
  //--------------------------------------------------------------------------------

  HcalTupleTree * tuple_tree = getTree<HcalTupleTree>("tuple_tree");
  int n_events = tuple_tree -> fChain -> GetEntries();
  std::cout << "n events = " << n_events << std::endl;
  
  //--------------------------------------------------------------------------------
  // Turn on/off branches
  //--------------------------------------------------------------------------------
  
  tuple_tree -> fChain -> SetBranchStatus("*"               , kFALSE);
  tuple_tree -> fChain -> SetBranchStatus("run"             , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("event"           , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("ls"              , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiFC"        , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiDepth"     , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiIEta"      , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiIPhi"      , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiSize"      , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiRecEnergy" , kTRUE);
  tuple_tree -> fChain -> SetBranchStatus("HFDigiRecTime"   , kTRUE);

  
  //--------------------------------------------------------------------------------
  // Loop
  //--------------------------------------------------------------------------------
  int nHFDigis;

  float pedestalThreshold = 20;

  TH2F * badChannel_depth1 = makeTH2F("shift_depth1", 85, -42.5, 42.5, 72, 0.5, 72.5 );
  TH2F * badChannel_depth2 = makeTH2F("shift_depth2", 85, -42.5, 42.5, 72, 0.5, 72.5 );
  TH2F * averageTiming =  makeTH2F("averageTiming", 85, -42.5, 42.5, 72, 0.5, 72.5 );
  TH2F * count =  makeTH2F("count", 85, -42.5, 42.5, 72, 0.5, 72.5 );

  for (int i = 0; i < n_events; ++i){
    
    tuple_tree -> GetEntry(i);
    if ( (i + 1) % 1000 == 0 ) std::cout << "Processing event " << i + 1 << "/" << n_events << std::endl;

    CollectionPtr hfDigis (new Collection(*tuple_tree, tuple_tree -> HFDigiIEta -> size()));
    
    nHFDigis = hfDigis -> GetSize();

    for (int iHFDigi = 0; iHFDigi < nHFDigis; ++iHFDigi){
      HFDigi hfDigi = hfDigis -> GetConstituent<HFDigi>(iHFDigi);

      // averageTiming -> Fill(hfDigi.ieta(),hfDigi.iphi(),hfDigi.recHitTime());
      count -> Fill(hfDigi.ieta(),hfDigi.iphi());

      if ( (hfDigi.fc(0) > pedestalThreshold) or (hfDigi.fc(3) > pedestalThreshold ) ){
        if (hfDigi.depth() == 1){
          badChannel_depth1 -> Fill(hfDigi.ieta(),hfDigi.iphi());
        };
        if (hfDigi.depth() == 2){
          badChannel_depth2 -> Fill(hfDigi.ieta(),hfDigi.iphi());
        };
	


      };
      
      
    }
  }
  
  averageTiming -> Divide(count);

}