void analyzePFGammaJetTree(TString inpFileName,
			   Long64_t maxEntries=-1,
			   double extraWeightFactor=-1.) {

  // book histograms
  double cPI= 4*atan(1);
  int show_dPhi=0;
  TH1D *h1_dPhi= new TH1D("h1_dPhi","#Delta#Phi",100,-2*cPI,2*cPI);
  prepareHisto(h1_dPhi);

  int show_dPt_PF=0;
  TH1D *h1_dPt_PF= new TH1D("h1_dPt_PF","#Deltap_{T}^{PF}",100,-1000,1000);
  prepareHisto(h1_dPt_PF);

  int show_pho2D_pt=1;
  TH2D *h2_pho_pt= new TH2D("h2_pho_pt","Photon p_{T};gen p_{T};reco p_{T}",
			    100,0.,1000.,
			    100,0.,1000.);
  prepareHisto(h2_pho_pt);

  int show_pho2D_ptMap=1;
  TH2D *h2_pho_ptMap= (TH2D*)h2_pho_pt->Clone("h2_pho_ptMap");
  h2_pho_ptMap->SetTitle("Photon average quality");
  TH2D *h2_pho_ptMapCount= (TH2D*)h2_pho_pt->Clone("h2_pho_ptMapCount");
  prepareHisto(h2_pho_ptMap);
  prepareHisto(h2_pho_ptMapCount);

  int show_jet2D_ptPF=1;
  TH2D *h2_jet_ptPF= new TH2D("h2_jet_pt",
			      "Leading jet p_{T};gen p_{T};reco p_{T}^{PF}",
			      100,0.,1000.,
			      100,0.,1000.);
  prepareHisto(h2_jet_ptPF);

  int show_pho_vs_jet_genPt=1;
  TH2D *h2_pho_vs_jet_genPt= new TH2D("h2_pho_vs_jet_genPt",
				   "Gen p_{T};#gamma gen p_{T};jet gen p_{T}",
				   100,0.,1000.,
				   100,0.,1000.);
  prepareHisto(h2_pho_vs_jet_genPt);

  int show_pho_vs_jet_recoPtPF=1;
  TH2D *h2_pho_vs_jet_recoPtPF= new TH2D("h2_pho_vs_jet_recoPtPF",
			   "Reco p_{T};#gamma p_{T};jet p_{T}^{PF}",
				   100,0.,1000.,
				   100,0.,1000.);
  prepareHisto(h2_pho_vs_jet_recoPtPF);


  // process the data
  pf_gammajettree inpData(inpFileName);

  inpData.DeactivateBranches();
  inpData.ActivateBranches_forFitSkim();
  inpData.ActivateBranches(1,"ppfjet_pt");
  inpData.ActivateBranches_genBasicSet();

  GammaJetEvent_t *dt= new GammaJetEvent_t();
  GammaJetEventAuxInfo_t aux;

  // read in the file
  Long64_t nEntries= inpData.fChain->GetEntries();
  if (maxEntries<0) maxEntries=nEntries;
  Long64_t nBytes=0, passedCount=0;

  for (Long64_t iEntry=0; (iEntry<nEntries) && (iEntry<maxEntries);
       iEntry++) {
    if (inpData.LoadTree(iEntry) < 0) break;
    Long64_t nb = inpData.GetEntry(iEntry);
    nBytes += nb;
    if (iEntry%10000==0) std::cout << " ... reading entry " << iEntry << "\n";
    std::cout << "ientry=" << iEntry << "\n";

    if (!passCuts(inpData,0)) continue;

    passedCount++;

    double ecalE= inpData.getSumEcalE(0,1);
    double hcalE_noRecHits= inpData.getSumHcalE_trackDiffEcal(1);

    aux.SetEventNo(inpData.EventNumber);
    aux.SetRunNo(inpData.RunNumber);
    aux.SetProbeHcalENoRecHits(hcalE_noRecHits);
    dt->SetAuxInfo(aux);

    double w=inpData.EventWeight;
    if (extraWeightFactor>0) w*= extraWeightFactor;
    dt->SetWeight(w);

    dt->SetTagEEtaPhi(inpData.tagPho_energy,
		      inpData.tagPho_eta, inpData.tagPho_phi);

    dt->SetProbeEtaPhiEn(inpData.ppfjet_eta, inpData.ppfjet_phi,
			 ecalE+hcalE_noRecHits, inpData.getHcalEMap(1,1e-4));

    h1_dPhi->Fill( dt->GetTagPhi() - dt->GetProbePhi() , w);
    h1_dPt_PF->Fill( inpData.tagPho_pt - inpData.ppfjet_pt , w);
    h2_pho_pt->Fill( inpData.tagPho_genPt, inpData.tagPho_pt, w);
    h2_jet_ptPF->Fill( inpData.ppfjet_genpt, inpData.ppfjet_pt, w);
    h2_pho_vs_jet_genPt->Fill( inpData.tagPho_genPt, inpData.ppfjet_genpt, w);
    h2_pho_vs_jet_recoPtPF->Fill( inpData.tagPho_pt, inpData.ppfjet_pt, w);

    int cathegory=0;
    if (inpData.tagPho_idTight) cathegory=2;
    else if (inpData.tagPho_idLoose) cathegory=1;
    h2_pho_ptMap->Fill( inpData.tagPho_genPt, inpData.tagPho_pt, cathegory);
    h2_pho_ptMapCount->Fill( inpData.tagPho_genPt, inpData.tagPho_pt, 1);
  }

  std::cout << "nEntries=" << nEntries << ", passedCount=" << passedCount << "\n";

  if (show_dPhi) displayHisto(h1_dPhi,"dPhi","LPE");
  if (show_dPt_PF) displayHisto(h1_dPt_PF, "dPt_PF","LPE");
  if (show_pho2D_pt) displayHisto(h2_pho_pt,"pho2D_pt","COLZ");
  if (show_jet2D_ptPF) displayHisto(h2_jet_ptPF,"jet2D_ptPF","COLZ");
  if (show_pho_vs_jet_genPt) displayHisto(h2_pho_vs_jet_genPt,"pho_vs_jet_genPt","COLZ");
  if (show_pho_vs_jet_recoPtPF) displayHisto(h2_pho_vs_jet_recoPtPF,"pho_vs_jet_recoPtPF","COLZ");

  if (show_pho2D_ptMap) {
    for (int ibin=1; ibin<=h2_pho_ptMapCount->GetNbinsX(); ++ibin) {
      for (int jbin=1; jbin<=h2_pho_ptMapCount->GetNbinsY(); ++jbin) {
	double cnt= h2_pho_ptMapCount->GetBinContent(ibin,jbin);
	if (cnt==double(0)) continue;
	double sum= h2_pho_ptMap->GetBinContent(ibin,jbin);
	h2_pho_ptMap->SetBinContent(ibin,jbin, sum/cnt);
      }
    }
    displayHisto(h2_pho_ptMap,"pho_ptMap","COLZ");
  }

  return;
}
void analyzeQCD_PFGammaJetTree(TString inpFileName,
			       int flatQCD=0,
			       Long64_t maxEntries=-1,
			       double extraWeightFactor=-1.,
			       TString plotOutDir_user="",
			       int saveCollection_user=-1) {

  std::cout << "inpFileName=<" << inpFileName << ">\n";

#ifdef helper_HH
  if (plotOutDir_user.Length()>0) plotOutDir= plotOutDir_user;
#endif
  if (saveCollection_user>=0) saveCollection=saveCollection_user;

  double flat_ptMin=0, flat_ptMax=0;
  if (flatQCD==1) { flat_ptMin=80; flat_ptMax=120; }
  else if (flatQCD==2) { flat_ptMin=120; flat_ptMax=170; }
  else if (flatQCD==3) { flat_ptMin=170; flat_ptMax=300; }
  if (flatQCD && (extraWeightFactor<0)) {
    std::cout << "flatQCD requires extraWeightFactor\n";
    return;
  }

  collector.Clear();

  // book histograms
  //double cPI= 4*atan(1);
  int show_evweight=1;
  TH1D *h1_evWeight= new TH1D("h1_evWeight","Event weight;w;count",1000,0,10);
  TH1D *h1_evPtHat= new TH1D("h1_evPtHat","Event #hat p_{T};#hat p_{T};count",100,0,500);
  TH1D *h1_evPtHatEvWeighted= new TH1D("h1_evPtHatEvWeighted","Event #hat p_{T};#hat p_{T};gen-weighted count",100,0,500);
  TH1D *h1_evPtHatWeighted= new TH1D("h1_evPtHatWeighted","Event #hat p_{T};#hat p_{T};weighted count",100,0,500);
  prepareHisto(h1_evWeight);
  prepareHisto(h1_evPtHat);
  prepareHisto(h1_evPtHatEvWeighted);
  prepareHisto(h1_evPtHatWeighted);

  double c_pt_max=500;
  double c_energy_max=1500;


  int show_jet_energy=1;
  TH1D* h1_jet_energyGen= new TH1D("h1_jet_energyGen",
				   "jet energy Gen;E_{gen};count",
				   100,0.,c_energy_max);
  TH1D* h1_jet_energyPF = new TH1D("h1_jet_energyPF",
				   "jet energy PF;E_{PF};count",
				   100,0.,c_energy_max);
  prepareHisto(h1_jet_energyGen,1);
  prepareHisto(h1_jet_energyPF,1);

  int show_jet_pT=1;
  TH1D* h1_jet_pTGen= new TH1D("h1_jet_pTGen",
				   "jet pT Gen;p_{T,gen};count",
				   100,0.,c_pt_max);
  TH1D* h1_jet_pTPF = new TH1D("h1_jet_pTPF",
				   "jet pT PF;p_{T,PF};count",
				   100,0.,c_pt_max);
  prepareHisto(h1_jet_pTGen,1);
  prepareHisto(h1_jet_pTPF,1);

  int show_jet_pT_window=(1 && flatQCD) ? 1:0;
  TH1D* h1_jet_pTGen_window= new TH1D("h1_jet_pTGen_window",
	       Form("jet pT Gen window %2.0lf-%2.0lf;p_{T,gen};count",
		   flat_ptMin,flat_ptMax),
				   100,0.,c_pt_max);
  TH1D* h1_jet_pTPF_window= new TH1D("h1_jet_pTPF_window",
	       Form("jet pT PFreco window %2.0lf-%2.0lf;p_{T,PF};count",
		   flat_ptMin,flat_ptMax),
				   100,0.,c_pt_max);
  prepareHisto(h1_jet_pTGen_window,1);
  prepareHisto(h1_jet_pTPF_window,1);

  int show_jet_energy_PF_over_Gen=1;
  TH1D *h1_jet_energy_PFoverGen= new TH1D("h1_jet_energy_PFoverGen",
		       "Jet energy ratio (PF div gen);E_{PF}/E_{gen};count",
					  100,0.,2.5);
  prepareHisto(h1_jet_energy_PFoverGen,1);

  int show_jet_pT_PF_over_Gen=1;
  TH1D *h1_jet_pT_PFoverGen= new TH1D("h1_jet_pT_PFoverGen",
	       "Jet p_{T} ratio (PF div gen);p_{T}^{PF}/p_{T}^{gen};count",
					  100,0.,2.5);
  prepareHisto(h1_jet_pT_PFoverGen,1);

  int show_jet2D_ptPF=1;
  TH2D *h2_jet_ptPF= new TH2D("h2_jet_ptPF",
			      "Leading jet p_{T};gen p_{T};reco p_{T}^{PF}",
			      100,0.,c_pt_max,
			      100,0.,c_pt_max);
  prepareHisto(h2_jet_ptPF);

  int show_photon_pt=1;
  TH1D* h1_photon_pTreco = new TH1D("h1_photon_pTreco",
				    "photon pT;p_{T}^{#gamma};count",
				   100,0.,c_pt_max);
  prepareHisto(h1_photon_pTreco,1);



  // process the data
  pf_gammajettree inpData(inpFileName);

  inpData.DeactivateBranches();
  //inpData.ActivateBranches_forFitSkim();
  inpData.ActivateBranches(2,"EventWeight","EventPtHat");
  inpData.ActivateBranches(2,"ppfjet_pt","ppfjet_E");
  inpData.ActivateBranches(2,"ppfjet_genpt","ppfjet_genE");
  inpData.ActivateBranches(1,"tagPho_pt");
  //inpData.ActivateBranches_genBasicSet();

  // read in the file
  Long64_t nEntries= inpData.fChain->GetEntries();
  std::cout << "nEntries=" << nEntries << "\n";
  if (nEntries==0) return;
  if (maxEntries<0) maxEntries=nEntries;
  Long64_t nBytes=0, passedCount=0;
  Double_t sum_evWeight_window=0;
  Double_t sum_finalW_window=0;

  for (Long64_t iEntry=0; (iEntry<nEntries) && (iEntry<maxEntries);
       iEntry++) {
    if (inpData.LoadTree(iEntry) < 0) break;
    Long64_t nb = inpData.GetEntry(iEntry);
    nBytes += nb;
    if (iEntry%10000==0) std::cout << " ... reading entry " << iEntry << "\n";
    //std::cout << "ientry=" << iEntry << "\n";

    //if (!inpData.passCuts(1,2)) continue; // recommended use

    passedCount++;

    double w=inpData.EventWeight;
    if (0 && flatQCD) {
      // It seems this factor is already included in the gen.event weight
      //w /= pow(inpData.EventPtHat/double(15.), double(4.5));
    }
    if (extraWeightFactor>0) w*= extraWeightFactor;

    h1_evWeight->Fill( w, 1. );
    h1_evPtHat->Fill( inpData.EventPtHat, 1. );
    h1_evPtHatEvWeighted->Fill( inpData.EventPtHat, inpData.EventWeight );
    h1_evPtHatWeighted->Fill( inpData.EventPtHat, w );
    h1_jet_energyGen->Fill( inpData.ppfjet_genE, w);
    h1_jet_energyPF->Fill( inpData.ppfjet_E, w);
    h1_jet_energy_PFoverGen->Fill( inpData.ppfjet_E/inpData.ppfjet_genE, w);
    h1_jet_pTGen->Fill( inpData.ppfjet_genpt, w);
    h1_jet_pTPF->Fill( inpData.ppfjet_pt, w);
    if ((inpData.EventPtHat>flat_ptMin) &&
	(inpData.EventPtHat<flat_ptMax)) {
      sum_evWeight_window+= inpData.EventWeight;
      sum_finalW_window+= w;
      h1_jet_pTGen_window->Fill( inpData.ppfjet_genpt, w);
      h1_jet_pTPF_window->Fill( inpData.ppfjet_pt, w);
    }
    h1_jet_pT_PFoverGen->Fill( inpData.ppfjet_pt/inpData.ppfjet_genpt, w);
    h2_jet_ptPF->Fill( inpData.ppfjet_genpt, inpData.ppfjet_pt, w);

    h1_photon_pTreco->Fill( inpData.tagPho_pt, w );

    int gen_debug=0;
    if (gen_debug==1) {
      std::cout << "iEntry=" << iEntry << ",    leading jet genE=" << inpData.ppfjet_genE << ", pfE=" << inpData.ppfjet_E << "\n";

      /*
      std::cout << "  ppfjet_twr_ieta " << (inpData.ppfjet_twr_ieta) << "\n";
      std::cout << "  ppfjet_twr_hade " << (inpData.ppfjet_twr_hade) << "\n";
      std::cout << "  ppfjet_twr_frac " << (inpData.ppfjet_twr_frac) << "\n";
      std::cout << "  ppfjet_twr_clusterind " << (inpData.ppfjet_twr_clusterind) << "\n";
      std::cout << "  ppfjet_cluster_dR " << (inpData.ppfjet_cluster_dR) << "\n";
      */
    }
    else if (gen_debug==2) {
      std::cout << "genE=" << inpData.ppfjet_genE << ", pfE=" << inpData.ppfjet_E << "\n";
    }

  }

  std::cout << "nEntries=" << nEntries << ", passedCount=" << passedCount << "\n";

  displayHisto(show_evweight, h1_evWeight,"evWeight","LPE");
  displayHisto(show_evweight, h1_evPtHat, "evPtHat", "LPE");
  displayHisto(show_evweight, h1_evPtHatEvWeighted,"evPtHatEvWeighted", "LPE");
  displayHisto(show_evweight, h1_evPtHatWeighted, "evPtHatWeighted", "LPE");

  displayHisto(show_jet_energy, h1_jet_energyGen, "jet_E_gen","LPE");
  displayHisto(show_jet_energy, h1_jet_energyPF, "jet_E_recoPF","LPE");
  displayHisto(show_jet_energy_PF_over_Gen, h1_jet_energy_PFoverGen,"e_PFoverGen","hist");

  displayHisto(show_jet_pT, h1_jet_pTGen, "jet_pT_gen","LPE");
  displayHisto(show_jet_pT, h1_jet_pTPF, "jet_pT_recoPF","LPE");
  displayHisto(show_jet_pT_PF_over_Gen, h1_jet_pT_PFoverGen,"pT_PFoverGen","hist");
  //if (sum_window!=Double_t(0)) h1_jet_pTGen_window->Scale(1/sum_window);
  displayHisto(show_jet_pT_window, h1_jet_pTGen_window, "jet_pT_gen_window","LPE");
  displayHisto(show_jet_pT_window, h1_jet_pTPF_window, "jet_pT_reco_window","LPE");

  displayHisto(show_jet2D_ptPF, h2_jet_ptPF, "jet2D_ptPF","COLZ");

  displayHisto(show_photon_pt, h1_photon_pTreco, "photon_pTreco","LPE");

  if (saveCollection) {
    TString outFName=TString("saved_") + plotOutDir + TString(".root");
    collector.Add("producedBy_analyzePFGammaJetTree");
    collector.SaveToFile(outFName);
  }

  if (flatQCD) {
    std::cout << "flatQCD pt window : " << flat_ptMin << " .. "
	      << flat_ptMax << "\n";
    std::cout << "sum_window. evWeight=" << sum_evWeight_window
	      << ", finalW=" << sum_finalW_window << "\n";
  }

  return;
}