Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:11:15

0001 //our base code
0002 #include "cemcReco.h"
0003 
0004 //Fun4all stuff
0005 #include <fun4all/Fun4AllReturnCodes.h>
0006 #include <fun4all/Fun4AllServer.h>
0007 #include <fun4all/Fun4AllHistoManager.h>
0008 #include <phool/PHCompositeNode.h>
0009 #include <phool/getClass.h>
0010 #include <phool/phool.h>
0011 #include <ffaobjects/EventHeader.h>
0012 
0013 //ROOT stuff
0014 #include <TH1F.h>
0015 #include <TH2F.h>
0016 #include <TH3F.h>
0017 #include <TFile.h>
0018 #include <TLorentzVector.h>
0019 
0020 //for emc clusters
0021 #include <calobase/RawCluster.h>
0022 #include <calobase/RawClusterContainer.h>
0023 #include <calobase/RawClusterUtility.h>
0024 #include <calobase/RawTowerGeomContainer.h>
0025 #include <calobase/RawTower.h>
0026 #include <calobase/RawTowerContainer.h>
0027 
0028 //caloEvalStack for cluster to truth matching
0029 #include <g4eval/CaloEvalStack.h>
0030 #include <g4eval/CaloRawClusterEval.h>
0031 
0032 //for vetex information
0033 #include <g4vertex/GlobalVertex.h>
0034 #include <g4vertex/GlobalVertexMap.h>
0035 
0036 //tracking
0037 #include <trackbase_historic/SvtxTrack.h>
0038 #include <trackbase_historic/SvtxTrackMap.h>
0039 #include <trackbase_historic/SvtxVertex.h>
0040 #include <trackbase_historic/SvtxVertexMap.h>
0041 
0042 //truth information
0043 #include <g4main/PHG4TruthInfoContainer.h>
0044 #include <g4main/PHG4Particle.h>
0045 #include </gpfs/mnt/gpfs02/sphenix/user/ahodges/macros_git/coresoftware/generators/phhepmc/PHHepMCGenEvent.h>
0046 #include </gpfs/mnt/gpfs02/sphenix/user/ahodges/macros_git/coresoftware/generators/phhepmc/PHHepMCGenEventMap.h>
0047 #include <g4main/PHG4VtxPoint.h>
0048 //#include <phhepmc/PHHepMCParticleSelectorDecayProductChain.h>
0049 #include <HepMC/GenEvent.h>
0050 #include <HepMC/GenParticle.h>
0051 #include <HepMC/GenVertex.h>
0052 #include <HepMC/IteratorRange.h>
0053 #include <HepMC/SimpleVector.h> 
0054 #include <HepMC/GenParticle.h>
0055 #include <CLHEP/Geometry/Point3D.h>
0056 
0057 
0058 
0059 //____________________________________________________________________________..
0060 cemcReco::cemcReco(const std::string &name, const std::string &outName):
0061 SubsysReco(name),
0062   nEvent(0),
0063   Outfile(outName),
0064   trackErrorCount(0)
0065 {
0066   std::cout << "cemcReco::cemcReco(const std::string &name) Constructor" << std::endl;  
0067   out = 0;
0068 
0069   //histos
0070   photonE = 0;
0071   clusterDisp = 0;
0072   clusterChi2 = 0;
0073   clusterProbPhoton = 0;
0074   isoPhoE = 0;
0075   isoPhoChi2 = 0;
0076   isoPhoProb = 0;
0077   deltaR_E_invMass = 0;
0078   tsp_E = 0;
0079   tsp_E_iso = 0;
0080   for(int i = 0; i < nEtaBins; i++) truth_pi0_E[i] = 0;
0081   truth_eta_E = 0;
0082   truth_dpho_E = 0; 
0083   pi0E_truth_reco = 0;
0084   invMass_eta = 0;
0085   eFrac_dr_primary = 0;
0086   eFrac_dr_secondary = 0;
0087  
0088   for(int i = 0; i < 2; i++)
0089     {
0090       for(int j = 0; j < nEtaBins; j++)
0091     {
0092       ePi0InvMassEcut[i][j] = 0;
0093     }
0094     }
0095   dPhoChi2 = 0;
0096   dPhoProb = 0;
0097   pi0Chi2 = 0;
0098   pi0Prob = 0;
0099   etaChi2 = 0;
0100   etaProb = 0;
0101   electronChi2 = 0;
0102   electronProb = 0; 
0103   hadronChi2 = 0;
0104   hadronProb = 0;
0105   etaFrac = 0;   
0106   pi0Frac = 0;
0107   unmatchedLocale = 0;
0108   unmatchedE = 0;
0109   invMassPhoPi0 = 0;
0110   invMassEPhi = 0;
0111   //caloevalstack = NULL;
0112 }
0113 
0114 //____________________________________________________________________________..
0115 cemcReco::~cemcReco()
0116 {
0117   std::cout << "cemcReco::~cemcReco() Calling dtor" << std::endl;
0118 }
0119 
0120 //____________________________________________________________________________..
0121 int cemcReco::Init(PHCompositeNode *topNode)
0122 {
0123   std::cout << "cemcReco::Init(PHCompositeNode *topNode) Initializing Histos" << std::endl;
0124 
0125   //histo initialization
0126   photonE = new TH1F("photonE_Reco","Reco Energy",200,0,20);
0127 
0128   clusterChi2 = new TH2F("clusterChi2","Cluster chi2",100,0,20,200,0,20);
0129 
0130   clusterProbPhoton = new TH2F("clusterProbPhoton","Cluster template probability",100,0,1,200,0,20);
0131 
0132   isoPhoE = new TH1F("isoPhotonE_Reco_Tru","Isolated Photon Energy",200,0,20);
0133 
0134   isoPhoChi2 = new TH2F("isoPhotonChi2","Isolated Photon Chi2 v. E",100,0,20,200,0,20);
0135 
0136   isoPhoProb = new TH2F("isoPhotonProb2","Isolated Photon Prob v. E",100,0,1,200,0,20);
0137 
0138   deltaR_E_invMass = new TH3F("deltaREinvMass","Opening Angle v. E v. InvMass",100,0,1,200,0,20,100,0,1);
0139 
0140   tsp_E = new TH2F("tspE","Transverse Shower Profile v. E",100,0,1,200,0,20);
0141 
0142   tsp_E_iso = new TH2F("tspEiso","Transverse Shower Profile Iso v. E",100,0,1,200,0,20);
0143 
0144   asym_E_invMass = new TH3F("asymEinvMass","Asymmetry v. E v. Invariant Mass",100,0,1,200,0,20,100,0,1);
0145 
0146   for(int i = 0; i < nEtaBins; i++)truth_pi0_E[i] = new TH1F(Form("truthPi0E_Eta%d",i),"truth pi0 energy",200,0,20);
0147 
0148   truth_eta_E = new TH1F("truthEtaE","truth eta energy",200,0,20);
0149 
0150   truth_dpho_E = new TH1F("truthDphoE","truth direct photon energy",200,0,20); 
0151 
0152   deltaR_E_truth_pi0 = new TH2F("deltaREtruthpi0","Opening angle truth pi0",100,0,1,500,0,50);
0153 
0154   asym_E_truth_pi0 = new TH2F("asymEtruthpi0","Photon asymmetry truth pi0",100,0,1,200,0,20);
0155 
0156   pi0E_truth_reco = new TH1F("pi0ETruthReco","Reco pi0/truth",100,0,2);
0157 
0158   invMass_eta = new TH3F("invMassEtaE","Invariant Mass vs. psuedorapidity bin",100,0,1,200,-1.2,1.2,200,0,20);
0159 
0160   eFrac_dr_primary = new TH2F("eFrac_dr_primary","Reco/Truth vs dr. primary",100,0,1,100,0,4);
0161 
0162   eFrac_dr_secondary = new TH2F("eFrac_dr_secondary","Reco/Truth vs dr. secondary",100,0,1,100,0,4);
0163 
0164   //ePi0InvMassEcut[0] = new TH3F("ePi0InvMassEcut0","Pi0 energy vs. Inv Mass vs. Min pho Energy Raw",500,0,50,500,-0.1,1,200,0,20);
0165   //ePi0InvMassEcut[1] = new TH3F("ePi0InvMassEcut1","Pi0 energy vs. Inv Mass vs. Min pho Energy Matched",500,0,50,500,-0.1,1,200,0,20);
0166   
0167   for(int i = 0; i < 2; i++)
0168     {
0169       for(int j = 0; j < nEtaBins; j++)
0170     {
0171       ePi0InvMassEcut[i][j] = new TH3F(Form("ePi0InvMassEcut_%dMatch_Eta%d",i,j),Form("Pi0 energy vs. Inv Mass vs. Min pho Energy %dMatched Eta%d",i, j), 500,0,50,500,-0.1,1,200,0,20);
0172     }
0173     }
0174   
0175   dPhoChi2 = new TH3F("dphoChi2","Direct Photon Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
0176   dPhoProb = new TH3F("dphoProb","Direct Photon Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
0177 
0178   pi0Chi2 = new TH3F("pi0Chi2","Pi0 Daughter Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
0179   pi0Prob = new TH3F("pi0Prob","Pi0 Daughter Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
0180 
0181   etaChi2 = new TH3F("etaChi2","Eta Daughter Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
0182   etaProb = new TH3F("etaProb","Eta Daughter Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
0183 
0184   electronChi2 = new TH3F("eChi2","Electron  Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
0185   electronProb = new TH3F("eProb","Electron  Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
0186 
0187   hadronChi2 = new TH3F("hChi2","Hadron  Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
0188   hadronProb = new TH3F("hProb","Hadron  Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
0189    
0190   etaFrac = new TH2F("etaClusterEFrac","clusters from eta fractional energy",200,0,1.5,500,0,50);
0191    
0192   pi0Frac = new TH2F("pi0ClusterEFrac","clusters from pi0 fractional energy",200,0,1.5,500,0,50);
0193 
0194   invMassEPhi = new TH3F("invMassEPhi","invariant mass vs. Truth Energy vs. phi",500,-0.1,1,500,0,50,200,-M_PI,M_PI);
0195   
0196   unmatchedLocale = new TH3F("unmatchedLocale","location of unmatched truth photons",200,-5,5,180,-M_PI,M_PI,500,0,50);
0197   unmatchedE = new TH1F("unmatchedE","energy of unmatched truth photons",250,0,50);
0198   
0199   invMassPhoPi0 = new TH3F("invMassPhoPi0","invariant mass vs. Photon energy scale vs. pi0 energy scale",500,-0.1,1,100,0,2,100,0,2);
0200   
0201   //so that the histos actually get written out
0202   Fun4AllServer *se = Fun4AllServer::instance();
0203   se -> Print("NODETREE"); 
0204   hm = new Fun4AllHistoManager("MYHISTOS");
0205 
0206   se -> registerHistoManager(hm);
0207 
0208   se -> registerHisto(photonE -> GetName(),photonE);
0209   se -> registerHisto(clusterChi2 -> GetName(), clusterChi2);
0210   se -> registerHisto(clusterProbPhoton -> GetName(), clusterProbPhoton);
0211   se -> registerHisto(isoPhoE -> GetName(), isoPhoE);
0212   se -> registerHisto(isoPhoChi2 -> GetName(), isoPhoChi2);
0213   se -> registerHisto(isoPhoProb -> GetName(), isoPhoProb);
0214   se -> registerHisto(deltaR_E_invMass -> GetName(), deltaR_E_invMass);
0215   se -> registerHisto(asym_E_invMass -> GetName(), asym_E_invMass);
0216   se -> registerHisto(pi0E_truth_reco -> GetName(), pi0E_truth_reco);
0217   se -> registerHisto(invMass_eta -> GetName(), invMass_eta);
0218   //se -> registerHisto(ePi0InvMassEcut[0] -> GetName(), ePi0InvMassEcut[0]);
0219   //se -> registerHisto(ePi0InvMassEcut[1] -> GetName(), ePi0InvMassEcut[1]);
0220   for(int i = 0; i < 2; i++)
0221     {
0222       for(int j = 0; j < 2; j++)
0223     {
0224       se -> registerHisto(ePi0InvMassEcut[i][j] -> GetName(), ePi0InvMassEcut[i][j]);
0225     }
0226     }
0227   se -> registerHisto(eFrac_dr_secondary -> GetName(), eFrac_dr_secondary);
0228   se -> registerHisto(eFrac_dr_primary -> GetName(), eFrac_dr_primary);
0229   se -> registerHisto(dPhoChi2 -> GetName(), dPhoChi2);
0230   se -> registerHisto(dPhoProb -> GetName(), dPhoProb);
0231   se -> registerHisto(pi0Chi2 -> GetName(), pi0Chi2);
0232   se -> registerHisto(pi0Prob -> GetName(), pi0Prob);
0233   se -> registerHisto(etaChi2 -> GetName(), etaChi2);
0234   se -> registerHisto(etaProb -> GetName(), etaProb);
0235   se -> registerHisto(electronChi2 -> GetName(), electronChi2);
0236   se -> registerHisto(electronProb -> GetName(), electronProb);
0237   se -> registerHisto(hadronChi2 -> GetName(), hadronChi2);
0238   se -> registerHisto(hadronProb -> GetName(), hadronProb);
0239   se -> registerHisto(unmatchedLocale -> GetName(), unmatchedLocale);
0240   se -> registerHisto(unmatchedE -> GetName(), unmatchedE);
0241   
0242   se -> registerHisto(invMassPhoPi0 -> GetName(), invMassPhoPi0);
0243   se -> registerHisto(invMassEPhi -> GetName(), invMassEPhi);
0244   
0245   
0246   out = new TFile(Outfile.c_str(),"RECREATE");
0247 
0248 
0249   //Call sumw2() on everything
0250   //letsSumw2();
0251   return Fun4AllReturnCodes::EVENT_OK;
0252 }
0253 
0254 //____________________________________________________________________________..
0255 int cemcReco::InitRun(PHCompositeNode *topNode)
0256 {
0257   std::cout << "cemcReco::InitRun(PHCompositeNode *topNode) No run dependence, doing nothing." << std::endl;
0258   return Fun4AllReturnCodes::EVENT_OK;
0259 }
0260 
0261 //____________________________________________________________________________..
0262 int cemcReco::process_event(PHCompositeNode *topNode)
0263 {
0264 
0265 
0266   if(!nEvent%100)
0267     {
0268       std::cout << "Processing Event: " << nEvent << std::endl;
0269     }
0270 
0271   //event-level information
0272   EventHeader *evtInfo = findNode::getClass<EventHeader>(topNode,"EventHeader");
0273   if(!evtInfo)
0274     {
0275       std::cout << PHWHERE << "cemc::process_event: EventHeader not in node tree" << std::endl;
0276       return 0;
0277     }
0278 
0279   //Information on clusters
0280   RawClusterContainer *clusterContainer = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_POS_COR_CEMC");
0281   //RawClusterContainer *clusterContainer = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_CEMC");
0282   if(!clusterContainer)
0283     {
0284       std::cout << PHWHERE << "cemc::process_event - Fatal Error - CLUSTER_POS_COR_CEMC node is missing. " << std::endl;
0285 
0286       return 0;
0287     }
0288 
0289 
0290   //Vertex information
0291   GlobalVertexMap *vtxContainer = findNode::getClass<GlobalVertexMap>(topNode,"GlobalVertexMap");
0292   if (!vtxContainer)
0293     {
0294       std::cout << PHWHERE << "cemc::process_event - Fatal Error - GlobalVertexMap node is missing. Please turn on the do_global flag in the main macro in order to reconstruct the global vertex." << std::endl;
0295       assert(vtxContainer);  // force quit
0296 
0297       return 0;
0298     }
0299 
0300   if (vtxContainer->empty())
0301     {
0302       std::cout << PHWHERE << "cemc::process_event - Fatal Error - GlobalVertexMap node is empty. Please turn on the do_global flag in the main macro in order to reconstruct the global vertex." << std::endl;
0303       return 0;
0304     }
0305 
0306   //More vertex information
0307   GlobalVertex *vtx = vtxContainer->begin()->second;
0308   if(!vtx)
0309     {
0310 
0311       std::cout << PHWHERE << "cemc::process_event Could not find vtx from vtxContainer"  << std::endl;
0312       return Fun4AllReturnCodes::ABORTEVENT;
0313     }
0314 
0315   //Tracks for the isolation cone
0316   SvtxTrackMap *trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
0317   if(!trackmap) 
0318     {
0319       if(trackErrorCount < 4)std::cout << PHWHERE << "cemc::process_event Could not find node SvtxTrackMap, not aborting, but reco direct photon information will not be available"  << std::endl;
0320       if(trackErrorCount == 4)std::cout << PHWHERE << "cemc::process_event Could not find node SvtxTrackMap for four events, it's probably missing from your file list, this message will no longer display" << std::endl;
0321       trackErrorCount++;
0322       //return Fun4AllReturnCodes::ABORTEVENT;
0323     }
0324 
0325   //Tower geometry node for location information
0326   RawTowerGeomContainer *towergeom = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_CEMC");
0327   if (!towergeom)
0328     {
0329       std::cout << PHWHERE << "cemc::process_event Could not find node TOWERGEOM_CEMC"  << std::endl;
0330       return Fun4AllReturnCodes::ABORTEVENT;
0331     }
0332 
0333   //Raw tower information
0334   RawTowerContainer *towerContainer = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_CEMC");
0335   if(!towerContainer)
0336     {
0337       std::cout << PHWHERE << "cemc::process_event Could not find node TOWER_CALIB_CEMC"  << std::endl;
0338       return Fun4AllReturnCodes::ABORTEVENT;
0339     }
0340 
0341   //truth particle information
0342   PHG4TruthInfoContainer *truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
0343   if(!truthinfo)
0344     {
0345       std::cout << PHWHERE << "cemc::process_event Could not find node G4TruthInfo"  << std::endl;
0346       return Fun4AllReturnCodes::ABORTEVENT;
0347     }
0348 
0349   //For pythia ancestory information
0350   PHHepMCGenEventMap *genEventMap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
0351   if(!genEventMap)
0352     {
0353       std::cout << PHWHERE << "cemc::process_event Could not find PHHepMCGenEventMap"  << std::endl;
0354       return Fun4AllReturnCodes::ABORTEVENT;
0355     }
0356   //event level information of the above
0357   PHHepMCGenEvent *genEvent = genEventMap -> get(1);
0358   if(!genEvent)
0359     {
0360       std::cout << PHWHERE << "cemc::process_event Could not find PHHepMCGenEvent"  << std::endl;
0361       return Fun4AllReturnCodes::ABORTEVENT;
0362     }
0363    
0364   HepMC::GenEvent *theEvent = genEvent -> getEvent();
0365 
0366   CaloEvalStack caloevalstack(topNode, "CEMC");
0367   CaloRawClusterEval *clustereval = caloevalstack.get_rawcluster_eval();
0368   if(!clustereval)
0369     {
0370       std::cout << PHWHERE << "cemc::process_event cluster eval not available"  << std::endl;
0371       return Fun4AllReturnCodes::ABORTEVENT;
0372     } 
0373   
0374   float mesonEtaMax = 0.3;
0375   float photonEtaMax = 1.1;
0376   PHG4Particle *maxPrimary = NULL;
0377   //This is how we iterate over items in the container.
0378   RawClusterContainer::ConstRange clusterEnd = clusterContainer -> getClusters();
0379   RawClusterContainer::ConstIterator clusterIter;
0380 
0381   //general pass over photons for info with only a mild energy cut to reduce noise
0382   std::vector<RawCluster*> goodRecoCluster;
0383   float minE = 0.3;
0384   float minDirpT = 4.;
0385   float isoConeRadius = 3;
0386   for(clusterIter = clusterEnd.first; clusterIter != clusterEnd.second; clusterIter++)
0387     {
0388       RawCluster *recoCluster = clusterIter -> second;
0389 
0390       CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
0391       CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*recoCluster, vertex);
0392       float clusE = E_vec_cluster.mag();
0393       float clus_eta = E_vec_cluster.pseudoRapidity();
0394       float clus_pt = E_vec_cluster.perp();
0395       //float clus_phi = E_vec_cluster.getPhi();
0396 
0397       if(clusE < minE) continue;
0398        
0399       maxPrimary = clustereval -> max_truth_primary_particle_by_energy(recoCluster);
0400       if(maxPrimary) 
0401     {
0402       
0403       if(maxPrimary -> get_pid() == 11 || maxPrimary -> get_pid() == -11)
0404         {
0405           electronChi2 -> Fill(recoCluster -> get_chi2(), clusE, maxPrimary -> get_e());
0406           electronProb -> Fill(recoCluster -> get_prob(), clusE, maxPrimary -> get_e());
0407         }
0408       else if(maxPrimary -> get_pid() == 211 || maxPrimary -> get_pid() == -211)
0409         {
0410           hadronChi2 -> Fill(recoCluster -> get_chi2(), clusE, maxPrimary -> get_e());
0411           hadronProb -> Fill(recoCluster -> get_prob(), clusE, maxPrimary -> get_e());
0412         }
0413       if(maxPrimary -> get_pid() == 22)
0414         {
0415           for(HepMC::GenEvent::particle_const_iterator p = theEvent -> particles_begin(); p != theEvent -> particles_end(); ++p)
0416         {
0417           assert(*p);
0418        
0419           if((*p) -> barcode() == maxPrimary -> get_barcode())
0420             {
0421               for(HepMC::GenVertex::particle_iterator mother = (*p)->production_vertex()->particles_begin(HepMC::parents);
0422               mother != (*p)->production_vertex()->particles_end(HepMC::parents); ++mother)
0423             {
0424               HepMC::FourVector moMomentum = (*mother) -> momentum();
0425               float e = moMomentum.e();
0426               //float eta = moMomentum.pseudoRapidity();
0427               if((*mother) -> pdg_id() == 22)
0428                 {
0429                   dPhoChi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
0430                   dPhoProb -> Fill(recoCluster -> get_prob(), clusE, e);
0431                 }
0432               else if((*mother) -> pdg_id() == 111)
0433                 {
0434                   pi0Chi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
0435                   pi0Prob -> Fill(recoCluster -> get_prob(), clusE, e);
0436                   pi0Frac -> Fill(clusE/e, e);
0437                 }
0438               else if((*mother) -> pdg_id() == 221)
0439                 {
0440                   etaChi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
0441                   etaProb -> Fill(recoCluster -> get_prob(), clusE, e);
0442                   etaFrac -> Fill(clusE/e, e);
0443 
0444                 }
0445                
0446             }
0447             }
0448         }
0449         }
0450     }
0451                         
0452                
0453 
0454       photonE -> Fill(clusE);
0455       //clusterChi2 -> Fill(recoCluster -> get_chi2(), clusE);
0456       //clusterProbPhoton -> Fill(recoCluster -> get_prob(), clusE);
0457 
0458       //Calculate the transverse shower profile, how spread out the energy in the cluster is
0459       //more spread out -> Most likely pi0 or other meson decay
0460       //less spread out -> iso photon 
0461       float tsp = calculateTSP(recoCluster, clusterContainer, towerContainer, towergeom, vtx);
0462 
0463       tsp_E -> Fill(tsp, clusE);
0464 
0465 
0466       //check to see if this is a high p_T isolate photon -> possibly a direct photon
0467       if(clus_pt > minDirpT) 
0468     {
0469 
0470 
0471       //make sure entire isocone is contained within sPHENIX acceptance
0472       if((fabs(clus_eta) < 1.0 - isoConeRadius) && trackmap)
0473         {
0474           float energyInCone = coneSum(recoCluster,clusterContainer, trackmap, isoConeRadius, vtx);
0475 
0476           if(energyInCone < 0.1*clusE)
0477         {
0478           isoPhoChi2 -> Fill(recoCluster -> get_chi2(), clusE);
0479           isoPhoProb -> Fill(recoCluster -> get_prob(), clusE);
0480           isoPhoE -> Fill(clusE);
0481           tsp_E_iso -> Fill(tsp, clusE);
0482           //isIso = true;
0483         }
0484         }
0485     }
0486       goodRecoCluster.push_back(recoCluster);
0487     }
0488 
0489   //And now we'll loop over all the good clusters to reconstruct pi0's and etas
0490   CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
0491   for(int i = 0; i < (int)goodRecoCluster.size(); i++)
0492     {
0493 
0494       
0495       CLHEP::Hep3Vector E_vec_cluster1 = RawClusterUtility::GetECoreVec(*goodRecoCluster[i], vertex);
0496 
0497       TLorentzVector pho1, pho2, pi0; 
0498       pho1.SetPtEtaPhiE(E_vec_cluster1.perp(), E_vec_cluster1.pseudoRapidity(), E_vec_cluster1.getPhi(),  E_vec_cluster1.mag());
0499 
0500 
0501 
0502       for(int j = 0; j <(int)goodRecoCluster.size(); j++)
0503     {
0504      
0505       if(j <= i) continue; 
0506       CLHEP::Hep3Vector E_vec_cluster2 = RawClusterUtility::GetECoreVec(*goodRecoCluster[j], vertex);
0507 
0508       pho2.SetPtEtaPhiE(E_vec_cluster2.perp(), E_vec_cluster2.pseudoRapidity(), E_vec_cluster2.getPhi(),  E_vec_cluster2.mag());
0509 
0510       pi0 = pho1 + pho2; 
0511 
0512       deltaR_E_invMass -> Fill(pho1.DeltaR(pho2), pi0.Energy(), pi0.M());
0513 
0514       float asym = abs(pho1.Energy() - pho2.Energy())/pi0.Energy();
0515 
0516       asym_E_invMass -> Fill(asym, pi0.Energy(), pi0.M());
0517 
0518       invMass_eta -> Fill(pi0.M(), pi0.Eta(), pi0.Energy());
0519 
0520       if(abs(pho2.PseudoRapidity()) < photonEtaMax && abs(pho1.PseudoRapidity()) < photonEtaMax &&  pi0.PseudoRapidity() < mesonEtaMax)
0521         {
0522           int etaBin = -1;
0523           if(pho1.Energy() >= pho2.Energy()) etaBin = getEtaBin(pho1.PseudoRapidity());
0524           else etaBin = getEtaBin(pho2.PseudoRapidity());
0525           if(etaBin>=0)ePi0InvMassEcut[0][etaBin] -> Fill(pi0.Energy(), pi0.M(),std::min(pho1.Energy(), pho2.Energy()));
0526           ePi0InvMassEcut[0][nEtaBins-1] -> Fill(pi0.Energy(), pi0.M(),std::min(pho1.Energy(), pho2.Energy()));
0527         }
0528     }
0529     }
0530 
0531   //truth pi0 reconstruction handled via the PHHepMCGenEventMap
0532   //This accounts for/bypasses the fact that pi0 decay is handled
0533   //in general by the event generator. This method is fine for things like
0534   //purity and kinematic studies, but if you need to get the *total* 
0535   //yield of pi0's, it isn't enough, see the primary and secondary 
0536   //particle loops below
0537 
0538 
0539   std::vector<PHG4Particle*> phoPi0;
0540   std::vector<PHG4Particle*> phoEta;
0541 
0542   std::vector<int> mBarCodePi0;
0543   std::vector<HepMC::GenVertex*> vtxIDpi0;
0544 
0545   std::vector<int> mBarCodeEta;
0546   std::vector<HepMC::GenVertex*> vtxIDEta;
0547 
0548   PHG4TruthInfoContainer::Range truthRange = truthinfo->GetPrimaryParticleRange();
0549   PHG4TruthInfoContainer::ConstIterator truthIter;
0550   //Here's where we link decay photons categorized as "primary" to their parent pi0's
0551   //from the HepMC event log
0552   for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
0553     {
0554       PHG4Particle *truthPar = truthIter->second;
0555       if(truthPar -> get_pid() != 22) continue;
0556       if(truthinfo -> isEmbeded(truthPar -> get_track_id()) != 1) continue;
0557     
0558       for(HepMC::GenEvent::particle_const_iterator p = theEvent -> particles_begin(); p != theEvent -> particles_end(); ++p)
0559     {
0560       assert(*p);
0561       if((*p) -> pdg_id()  != 22) continue;
0562           
0563       if((*p) -> barcode() == truthPar -> get_barcode())
0564         {
0565             
0566           for (HepMC::GenVertex::particle_iterator mother = (*p)->production_vertex()->particles_begin(HepMC::parents);
0567            mother != (*p)->production_vertex()->particles_end(HepMC::parents); ++mother)
0568         {
0569            
0570           HepMC::FourVector moMomentum = (*mother) -> momentum();
0571           float e = moMomentum.e();
0572           float eta = moMomentum.pseudoRapidity();
0573           if((*mother) -> pdg_id() == 22 && abs(eta) < photonEtaMax) 
0574             {
0575               
0576               truth_dpho_E -> Fill(e);
0577               
0578             }
0579           else if((*mother) -> pdg_id() == 111 )
0580             {
0581 
0582               phoPi0.push_back(truthPar);//these photons will be unique
0583               vtxIDpi0.push_back((*mother) -> production_vertex());
0584               
0585               mBarCodePi0.push_back((*mother) -> barcode());//barcodes will not be unique, as they'll be added per photon
0586             }
0587           else if((*mother) -> pdg_id() == 221 )
0588             {
0589               
0590               if(abs(eta) < mesonEtaMax &&  abs(getEta(truthPar)) < photonEtaMax && !checkBarcode((*mother) -> barcode(),mBarCodeEta))truth_eta_E -> Fill(e);
0591               phoEta.push_back(truthPar);
0592               vtxIDEta.push_back((*mother) -> production_vertex());
0593               mBarCodeEta.push_back((*mother) -> barcode());
0594             }
0595           
0596         }
0597         }
0598     }
0599     }
0600 
0601   //And then, we have to loop over the photons in the secondary particle list and trace them back to a pi0
0602   truthRange = truthinfo -> GetSecondaryParticleRange();
0603   for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
0604     {
0605       PHG4Particle *truthPar = truthIter -> second;
0606       
0607       while(truthPar -> get_parent_id() != 0)
0608     {
0609       
0610       PHG4Particle *parent = truthinfo -> GetParticle(truthPar -> get_parent_id());
0611       if(parent -> get_parent_id() == 0) break; //this is the decay product we want, so we don't want to reassign it
0612       truthPar = parent;
0613     }
0614     
0615       if(truthPar -> get_pid() != 22 ) 
0616         {
0617           //std::cout << "Killed by final photon pid cut" << std::endl;
0618           continue;
0619         }
0620       PHG4Particle *pi0 = truthinfo -> GetParticle(truthPar -> get_parent_id());
0621       if(pi0 -> get_pid() != 111)
0622     {
0623       //std::cout << "Killed by pi0 pid cut" << std::endl;
0624       continue; //secondary not descendant from pi0
0625     }
0626       if(abs(getEta(pi0)) > mesonEtaMax) 
0627     {
0628       //std::cout << "Killed by pi0 eta cut" << std::endl;
0629       continue;//go ahead and make pi0 kinematic cut
0630     }
0631       if(abs(getEta(truthPar)) > photonEtaMax) continue; //don't cut on photons just yet, save for reconstruction
0632       
0633       //check to see if we've already gotten this photon and we're just at another shower element
0634      
0635       if(checkBarcode(truthPar -> get_barcode(), phoPi0)) 
0636     {
0637       //std::cout << "Killed by photon barcode cut" << std::endl;
0638       continue;
0639     }
0640       //sneaky overload
0641       if(checkBarcode(pi0 -> get_barcode(), mBarCodePi0)) continue;
0642       
0643       mBarCodePi0.push_back(pi0 -> get_barcode());
0644       phoPi0.push_back(truthPar);
0645     }
0646       
0647 
0648   
0649   //Loop over our recovered decay photons and 
0650   //extract kinematic information.
0651   //First for the pi0's
0652   for(int i = 0; i < (int)phoPi0.size(); i++)
0653     {
0654       for(int j = 0; j < (int)phoPi0.size(); j++)
0655     {
0656       if(j <= i) 
0657         {
0658           continue;
0659         }
0660       if(mBarCodePi0.at(i) != mBarCodePi0.at(j))//match mother particles
0661         {
0662           continue;
0663         }
0664       if(abs(getEta(phoPi0.at(i))) >= photonEtaMax || abs(getEta(phoPi0.at(j))) >= photonEtaMax)
0665         {
0666           continue;
0667         }
0668 
0669       
0670       TLorentzVector e1Vec, e2Vec;
0671       e1Vec.SetPxPyPzE(phoPi0.at(i) -> get_px(),phoPi0.at(i) -> get_py(), phoPi0.at(i) -> get_pz(), phoPi0.at(i) -> get_e());
0672       e2Vec.SetPxPyPzE(phoPi0.at(j) -> get_px(),phoPi0.at(j) -> get_py(), phoPi0.at(j) -> get_pz(), phoPi0.at(j) -> get_e());
0673       
0674       
0675       float dr = e1Vec.DeltaR(e2Vec); 
0676         
0677       float e1, e2;
0678       e1 = phoPi0.at(i) -> get_e();
0679       e2 = phoPi0.at(j) -> get_e();
0680       
0681       float asym = abs(e1-e2)/(e1+e2);
0682       
0683       TLorentzVector pi0 = e1Vec + e2Vec;
0684       if(abs(pi0.PseudoRapidity()) >= mesonEtaMax) 
0685         {
0686           continue;
0687         }
0688       int etaBin = -1;
0689       if(e1Vec.Energy() >= e2Vec.Energy()) etaBin = getEtaBin(e1Vec.PseudoRapidity());
0690       else etaBin = getEtaBin(e2Vec.PseudoRapidity());
0691       if(etaBin>=0)truth_pi0_E[etaBin] -> Fill(pi0.Energy());//fill individual eta bin
0692       truth_pi0_E[nEtaBins-1] -> Fill(pi0.Energy());//fill one for all eta bins
0693 
0694       asym_E_truth_pi0 -> Fill(asym, pi0.E());
0695       deltaR_E_truth_pi0 -> Fill(dr, pi0.E());
0696       
0697       RawCluster *best_cluster1 = clustereval -> best_cluster_from(phoPi0.at(i));
0698       RawCluster *best_cluster2 = clustereval -> best_cluster_from(phoPi0.at(j));
0699       
0700       if(!best_cluster1 || !best_cluster2)
0701         {
0702           if(!best_cluster1) 
0703         {
0704           
0705           unmatchedLocale -> Fill(getEta(phoPi0.at(i)), getPhi(phoPi0.at(i)), pi0.E());
0706           unmatchedE -> Fill(phoPi0.at(i) -> get_e());
0707         }
0708           if(!best_cluster2) 
0709         {
0710          
0711           unmatchedLocale -> Fill(getEta(phoPi0.at(j)), getPhi(phoPi0.at(j)), pi0.E());
0712           unmatchedE -> Fill(phoPi0.at(j) -> get_e());
0713         }
0714           int etaBin = -1;
0715           if(e1Vec.Energy() >= e2Vec.Energy()) etaBin = getEtaBin(e1Vec.PseudoRapidity());
0716           else etaBin = getEtaBin(e2Vec.PseudoRapidity());
0717           if(etaBin>=0)ePi0InvMassEcut[1][etaBin] -> Fill(pi0.Energy(), 0., std::min(e1Vec.Energy(), e2Vec.Energy()));
0718           ePi0InvMassEcut[1][nEtaBins-1] -> Fill(pi0.Energy(), 0., std::min(e1Vec.Energy(), e2Vec.Energy()));
0719         }
0720       else
0721         {
0722           if(best_cluster1 -> get_id() == best_cluster2 -> get_id()) continue; 
0723         
0724           
0725           CLHEP::Hep3Vector E_vec_cluster1 = RawClusterUtility::GetECoreVec(*best_cluster1, vertex);
0726           CLHEP::Hep3Vector E_vec_cluster2 = RawClusterUtility::GetECoreVec(*best_cluster2, vertex);
0727       
0728           TLorentzVector clusE1, clusE2, clusPi0;
0729           clusE1.SetPtEtaPhiE(E_vec_cluster1.perp(), E_vec_cluster1.pseudoRapidity(), E_vec_cluster1.getPhi(),  E_vec_cluster1.mag());
0730           clusE2.SetPtEtaPhiE(E_vec_cluster2.perp(), E_vec_cluster2.pseudoRapidity(), E_vec_cluster2.getPhi(),  E_vec_cluster2.mag());
0731 
0732           clusPi0 = clusE1 + clusE2;
0733           
0734           int etaBin = -1;
0735           if(clusE1.Energy() >= clusE2.Energy()) etaBin = getEtaBin(clusE1.PseudoRapidity());
0736           else etaBin = getEtaBin(clusE2.PseudoRapidity());
0737           if(etaBin>=0)ePi0InvMassEcut[1][etaBin] -> Fill(pi0.Energy(), clusPi0.M(),std::min(clusE1.Energy(), clusE2.Energy()));
0738           ePi0InvMassEcut[1][nEtaBins-1] -> Fill(pi0.Energy(), clusPi0.M(),std::min(clusE1.Energy(), clusE2.Energy()));
0739           
0740           invMassEPhi -> Fill(clusPi0.M(), pi0.Energy(), clusE1.Phi());
0741           invMassEPhi -> Fill(clusPi0.M(), pi0.Energy(), clusE2.Phi()); 
0742     
0743           invMassPhoPi0 -> Fill(clusPi0.M(), clusPi0.Energy()/pi0.Energy(), clusE1.Energy()/e1Vec.Energy());
0744           invMassPhoPi0 -> Fill(clusPi0.M(), clusPi0.Energy()/pi0.Energy(), clusE2.Energy()/e2Vec.Energy());
0745               
0746         }
0747     }
0748     }
0749   
0750   //collecting pi0's that enter GEANT's volume. This is actually now handled by 
0751   //collecting photons from the secondary photon list.
0752   /*truthRange = truthinfo->GetPrimaryParticleRange();
0753   for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
0754     {
0755       PHG4Particle *truthPar = truthIter->second;
0756       if(truthPar -> get_pid() == 111 && truthPar -> get_parent_id() == 0)//it's a primary pi0, let's take a look
0757     {
0758       if(abs(getEta(truthPar)) < mesonEtaMax)
0759         {
0760           //truth_pi0_E -> Fill(truthPar -> get_e());
0761         }
0762     }
0763     }*/
0764 
0765   PHG4TruthInfoContainer::Range truthRangeDecay1 = truthinfo->GetSecondaryParticleRange();
0766   PHG4TruthInfoContainer::ConstIterator truthIterDecay1;
0767   
0768  
0769   //Get decays from other particles to pi0's
0770   for(truthIterDecay1 = truthRangeDecay1.first; truthIterDecay1 != truthRangeDecay1.second; truthIterDecay1++)
0771     {
0772       PHG4Particle *truthDecay1 = truthIterDecay1 -> second;
0773 
0774       if(truthDecay1 -> get_parent_id() != 0 && truthDecay1 -> get_pid() == 111 && abs(getEta(truthDecay1)) < mesonEtaMax) //want decay pi0's
0775     {
0776       //truth_pi0_E -> Fill(truthDecay1 -> get_e());
0777     }
0778     }
0779     
0780       
0781 
0782 
0783   nEvent++;
0784   goodRecoCluster.clear();
0785   phoPi0.clear();
0786   phoEta.clear();
0787   mBarCodePi0.clear();
0788   vtxIDpi0.clear();
0789   mBarCodeEta.clear();
0790  
0791   vtxIDEta.clear();
0792   return Fun4AllReturnCodes::EVENT_OK;
0793 }
0794 
0795 //____________________________________________________________________________..
0796 int cemcReco::ResetEvent(PHCompositeNode *topNode)
0797 {
0798   //std::cout << "cemcReco::ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event" << std::endl;
0799   return Fun4AllReturnCodes::EVENT_OK;
0800 }
0801 
0802 //____________________________________________________________________________..
0803 int cemcReco::EndRun(const int runnumber)
0804 {
0805   std::cout << "cemcReco::EndRun(const int runnumber) Ending Run for Run " << runnumber << std::endl;
0806   return Fun4AllReturnCodes::EVENT_OK;
0807 }
0808 
0809 //____________________________________________________________________________..
0810 int cemcReco::End(PHCompositeNode *topNode)
0811 {
0812   std::cout << "cemcReco::End(PHCompositeNode *topNode) This is the End..." << std::endl;
0813   out -> cd();
0814   
0815   photonE -> Write();
0816   clusterChi2 -> Write();
0817   clusterProbPhoton -> Write();
0818   isoPhoE -> Write();
0819   isoPhoChi2 -> Write();
0820   isoPhoProb -> Write();
0821   deltaR_E_invMass -> Write();
0822   tsp_E -> Write();
0823   tsp_E_iso -> Write();
0824   asym_E_truth_pi0 -> Write();
0825   deltaR_E_truth_pi0 -> Write();
0826   for(int i = 0; i < nEtaBins; i++) truth_pi0_E[i] -> Write();
0827   truth_eta_E -> Write();
0828   truth_dpho_E -> Write();
0829   asym_E_invMass -> Write();
0830   pi0E_truth_reco -> Write();
0831   invMass_eta -> Write();
0832   eFrac_dr_secondary -> Write();
0833   eFrac_dr_primary -> Write();
0834   //ePi0InvMassEcut[0] -> Write();
0835   //ePi0InvMassEcut[1] -> Write();
0836   for(int i = 0; i < 2; i++)
0837     {
0838       for(int j = 0; j < nEtaBins; j++)
0839     {
0840       ePi0InvMassEcut[i][j] -> Write();
0841     }
0842     }
0843 
0844   dPhoChi2 -> Write();
0845   dPhoProb -> Write();
0846   pi0Chi2 -> Write();
0847   pi0Prob -> Write();
0848   etaChi2 -> Write();
0849   etaProb -> Write();
0850   electronChi2 -> Write();
0851   electronProb -> Write(); 
0852   hadronChi2 -> Write();
0853   hadronProb -> Write();
0854   pi0Frac -> Write();
0855   etaFrac -> Write();
0856   unmatchedLocale -> Write();
0857   unmatchedE -> Write();
0858   invMassPhoPi0 -> Write();
0859   invMassEPhi -> Write();
0860 
0861   //out -> Close();
0862   
0863   //delete out;
0864   //delete caloevalstack;
0865 
0866   //hm -> dumpHistos(Outfile.c_str(),"UPDATE");
0867   return Fun4AllReturnCodes::EVENT_OK;
0868 }
0869 
0870 //____________________________________________________________________________..
0871 int cemcReco::Reset(PHCompositeNode *topNode)
0872 {
0873   std::cout << "cemcReco::Reset(PHCompositeNode *topNode) being Reset" << std::endl;
0874   return Fun4AllReturnCodes::EVENT_OK;
0875 }
0876 
0877 //____________________________________________________________________________..
0878 void cemcReco::Print(const std::string &what) const
0879 {
0880   std::cout << "cemcReco::Print(const std::string &what) const Printing info for " << what << std::endl;
0881 }
0882 //____________________________________________________________________________..
0883 float cemcReco::coneSum(RawCluster *cluster,
0884             RawClusterContainer *cluster_container,
0885             SvtxTrackMap *trackmap,
0886             float coneradius,
0887             GlobalVertex *vtx)
0888 {
0889   float energyptsum = 0;
0890 
0891   CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
0892   CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
0893 
0894   RawClusterContainer::ConstRange begin_end = cluster_container->getClusters();
0895   RawClusterContainer::ConstIterator clusiter;
0896 
0897   for (clusiter = begin_end.first;
0898        clusiter != begin_end.second;
0899        ++clusiter)
0900     {
0901       RawCluster *conecluster = clusiter->second;
0902 
0903       //check to make sure that the candidate isolated photon isn't being counted in the energy sum
0904       if (conecluster->get_energy() == cluster->get_energy())
0905     if (conecluster->get_phi() == cluster->get_phi())
0906       if (conecluster->get_z() == cluster->get_z())
0907         continue;
0908 
0909       CLHEP::Hep3Vector E_vec_conecluster = RawClusterUtility::GetECoreVec(*conecluster, vertex);
0910 
0911       float cone_pt = E_vec_conecluster.perp();
0912 
0913       if (cone_pt < 0.2)
0914     continue;
0915 
0916       float cone_e = conecluster->get_energy();
0917       float cone_eta = E_vec_conecluster.pseudoRapidity();
0918       float cone_phi = E_vec_conecluster.getPhi();
0919 
0920       float dphi = cluster->get_phi() - cone_phi;
0921       if (dphi < -1 * pi)
0922     dphi += 2. * pi;
0923       if (dphi > pi)
0924     dphi -= 2. * pi;
0925 
0926       float deta = E_vec_cluster.pseudoRapidity() - cone_eta;
0927 
0928       float radius = sqrt(dphi * dphi + deta * deta);
0929 
0930       if (radius < coneradius)
0931     {
0932       energyptsum += cone_e;
0933     }
0934     }
0935 
0936   for (SvtxTrackMap::Iter iter = trackmap->begin(); iter != trackmap->end(); ++iter)
0937     {
0938       SvtxTrack *track = iter->second;
0939 
0940       float trackpx = track->get_px();
0941       float trackpy = track->get_py();
0942       float trackpt = sqrt(trackpx * trackpx + trackpy * trackpy);
0943       if (trackpt < 0.2)
0944     continue;
0945       float trackphi = track->get_phi();
0946       float tracketa = track->get_eta();
0947       float dphi = E_vec_cluster.getPhi() - trackphi;
0948       float deta = E_vec_cluster.pseudoRapidity() - tracketa;
0949       float radius = sqrt(dphi * dphi + deta * deta);
0950 
0951       if (radius < coneradius)
0952     {
0953       energyptsum += trackpt;
0954     }
0955     }
0956 
0957   return energyptsum;
0958 }
0959 
0960 //____________________________________________________________________________..
0961 float cemcReco::calculateTSP(RawCluster *cluster,
0962                  RawClusterContainer *clusterContainer, 
0963                  RawTowerContainer *towerContainer,
0964                  RawTowerGeomContainer *towerGeo,
0965                  GlobalVertex *vtx
0966                  )
0967 {
0968   
0969   CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
0970   CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
0971   float clusE = E_vec_cluster.mag();
0972   float clusEta = E_vec_cluster.pseudoRapidity();
0973   //float clus_pt = E_vec_cluster.perp();
0974   float clusPhi = E_vec_cluster.getPhi();
0975 
0976   RawCluster::TowerConstRange towers = cluster->get_towers();
0977   RawCluster::TowerConstIterator toweriter;
0978 
0979   float denom = 0;
0980   for (toweriter = towers.first; toweriter != towers.second; ++toweriter)
0981     {
0982       
0983       RawTower *tower = towerContainer->getTower(toweriter->first);
0984 
0985       //int towereta = tower->get_bineta();
0986       //int towerphi = tower->get_binphi();
0987       double towerEnergy = tower->get_energy();
0988 
0989       //Get eta and phi bin from the rawTowerContainer
0990       //then transform it to coordinates with the tower geometry object
0991       int phibin = tower->get_binphi();
0992       int etabin = tower->get_bineta();
0993       double phi = towerGeo->get_phicenter(phibin);
0994       double eta = towerGeo->get_etacenter(etabin);
0995 
0996       float r = sqrt(pow(clusEta - eta,2) + pow(clusPhi - phi,2));
0997       denom += towerEnergy*pow(r,1.5);
0998       
0999     }
1000 
1001   return clusE/denom;
1002 }
1003 //____________________________________________________________________________..
1004 /*void cemcReco::letsSumw2()
1005 {
1006   photonE -> Sumw2();
1007   clusterChi2 -> Sumw2();
1008   clusterProbPhoton -> Sumw2();
1009   isoPhoE -> Sumw2();
1010   isoPhoChi2 -> Sumw2();
1011   isoPhoProb -> Sumw2();
1012   deltaR_E_invMass -> Sumw2();
1013   asym_E_invMass -> Sumw2();
1014   tsp_E -> Sumw2();
1015   tsp_E_iso -> Sumw2();
1016   truth_pi0_E -> Sumw2();
1017   truth_eta_E -> Sumw2();
1018   truth_dpho_E -> Sumw2(); 
1019   asym_E_truth_pi0 -> Sumw2();
1020   deltaR_E_truth_pi0  -> Sumw2();
1021   pi0E_truth_reco -> Sumw2();
1022   eFrac_dr_primary -> Sumw2();
1023   eFrac_dr_secondary -> Sumw2();
1024   // ePi0InvMassEcut[0] -> Sumw2();
1025   etaFrac -> Sumw2();
1026   pi0Frac -> Sumw2();
1027   }*/
1028 //____________________________________________________________________________..
1029 bool cemcReco::compareVertices(HepMC::FourVector hepMCvtx, PHG4VtxPoint *g4vtx)
1030 {
1031   float g4vtxz, g4vtxy, g4vtxx;//geant vertices
1032   g4vtxx =  g4vtx -> get_x();
1033   g4vtxy =  g4vtx -> get_y();
1034   g4vtxz =  g4vtx -> get_z();
1035   std::cout << "g4 x: " << g4vtxx << "; g4 y: " << g4vtxy << "; g4 z: " << g4vtxz << std::endl;
1036   
1037   float hepVtxx, hepVtxy, hepVtxz;
1038   hepVtxx = hepMCvtx.x();
1039   hepVtxy = hepMCvtx.y();
1040   hepVtxz = hepMCvtx.z();
1041   std::cout << "hep x: " << hepVtxx << "; hep y: " << hepVtxy << "; hep z: " << hepVtxz << std::endl;
1042 
1043 
1044   if(g4vtxx != hepVtxx  || g4vtxy != hepVtxy  || g4vtxz != hepVtxz ) return false;
1045   
1046   return true;  
1047   
1048 }
1049 //____________________________________________________________________________..
1050 /*float getpT(PHGParticle *particle)
1051   {
1052   float px = particle -> get_px();
1053   float py = particle -> get_py();
1054   
1055   float pt = sqrt(pow(px,2) + pow(py,2));
1056   return pt;
1057   }*/
1058 //____________________________________________________________________________..
1059 float cemcReco::getEta(PHG4Particle *particle)
1060 {
1061   float px = particle -> get_px();
1062   float py = particle -> get_py();
1063   float pz = particle -> get_pz();
1064   float p = sqrt(pow(px,2) + pow(py,2) + pow(pz,2));
1065 
1066   return 0.5*log((p+pz)/(p-pz));
1067 }
1068 //____________________________________________________________________________.. 
1069 float cemcReco::getPhi(PHG4Particle *particle)
1070 {
1071   float phi = atan2(particle -> get_py(),particle -> get_px());
1072   return phi;
1073 }
1074 //____________________________________________________________________________.. 
1075 bool cemcReco::checkBarcode(int motherBarcode, std::vector<int> &motherBarcodes)
1076 {
1077   bool isRepeated = false;
1078   for(int i = 0; i < (int)motherBarcodes.size(); i++)
1079     {
1080       if(motherBarcode == motherBarcodes.at(i)) isRepeated = true;
1081     }
1082   
1083   return isRepeated;
1084 }
1085 //____________________________________________________________________________.. 
1086 bool cemcReco::checkBarcode(int motherBarcode, std::vector<PHG4Particle*> &motherBarcodes)
1087 {
1088   bool isRepeated = false;
1089   
1090   for(int i = 0; i < (int)motherBarcodes.size(); i++)
1091     {
1092       if(motherBarcode == motherBarcodes.at(i) -> get_barcode()) isRepeated = true;
1093     }
1094   
1095   return isRepeated;
1096 }
1097 //____________________________________________________________________________.. 
1098 int cemcReco::getEtaBin(float eta)
1099 {
1100   for(int i = 0; i < nEtaBins-1; i++)//only go up to nEtaBins - 1 because the last bin is for all eta
1101     {
1102       if(abs(eta) < (i+1)/(float)(nEtaBins-1) * 1.1 && abs(eta) >= (i+1-1)/(float)(nEtaBins-1) * 1.1) 
1103     {
1104       return i;
1105     }
1106     }
1107  return -1;
1108 }
1109