Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cemcReco.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file cemcReco.cc
1 //our base code
2 #include "cemcReco.h"
3 
4 //Fun4all stuff
9 #include <phool/getClass.h>
10 #include <phool/phool.h>
11 #include <ffaobjects/EventHeader.h>
12 
13 //ROOT stuff
14 #include <TH1F.h>
15 #include <TH2F.h>
16 #include <TH3F.h>
17 #include <TFile.h>
18 #include <TLorentzVector.h>
19 
20 //for emc clusters
21 #include <calobase/RawCluster.h>
22 #include <calobase/RawClusterContainer.h>
23 #include <calobase/RawClusterUtility.h>
24 #include <calobase/RawTowerGeomContainer.h>
25 #include <calobase/RawTower.h>
26 #include <calobase/RawTowerContainer.h>
27 
28 //caloEvalStack for cluster to truth matching
29 #include <g4eval/CaloEvalStack.h>
31 
32 //for vetex information
33 #include <g4vertex/GlobalVertex.h>
34 #include <g4vertex/GlobalVertexMap.h>
35 
36 //tracking
39 #include <trackbase_historic/SvtxVertex.h>
40 #include <trackbase_historic/SvtxVertexMap.h>
41 
42 //truth information
44 #include <g4main/PHG4Particle.h>
45 #include </gpfs/mnt/gpfs02/sphenix/user/ahodges/macros_git/coresoftware/generators/phhepmc/PHHepMCGenEvent.h>
46 #include </gpfs/mnt/gpfs02/sphenix/user/ahodges/macros_git/coresoftware/generators/phhepmc/PHHepMCGenEventMap.h>
47 #include <g4main/PHG4VtxPoint.h>
48 //#include <phhepmc/PHHepMCParticleSelectorDecayProductChain.h>
49 #include <HepMC/GenEvent.h>
50 #include <HepMC/GenParticle.h>
51 #include <HepMC/GenVertex.h>
52 #include <HepMC/IteratorRange.h>
53 #include <HepMC/SimpleVector.h>
54 #include <HepMC/GenParticle.h>
55 #include <CLHEP/Geometry/Point3D.h>
56 
57 
58 
59 //____________________________________________________________________________..
61 SubsysReco(name),
62  nEvent(0),
63  Outfile(outName),
64  trackErrorCount(0)
65 {
66  std::cout << "cemcReco::cemcReco(const std::string &name) Constructor" << std::endl;
67  out = 0;
68 
69  //histos
70  photonE = 0;
71  clusterDisp = 0;
72  clusterChi2 = 0;
74  isoPhoE = 0;
75  isoPhoChi2 = 0;
76  isoPhoProb = 0;
77  deltaR_E_invMass = 0;
78  tsp_E = 0;
79  tsp_E_iso = 0;
80  for(int i = 0; i < nEtaBins; i++) truth_pi0_E[i] = 0;
81  truth_eta_E = 0;
82  truth_dpho_E = 0;
83  pi0E_truth_reco = 0;
84  invMass_eta = 0;
85  eFrac_dr_primary = 0;
87 
88  for(int i = 0; i < 2; i++)
89  {
90  for(int j = 0; j < nEtaBins; j++)
91  {
92  ePi0InvMassEcut[i][j] = 0;
93  }
94  }
95  dPhoChi2 = 0;
96  dPhoProb = 0;
97  pi0Chi2 = 0;
98  pi0Prob = 0;
99  etaChi2 = 0;
100  etaProb = 0;
101  electronChi2 = 0;
102  electronProb = 0;
103  hadronChi2 = 0;
104  hadronProb = 0;
105  etaFrac = 0;
106  pi0Frac = 0;
107  unmatchedLocale = 0;
108  unmatchedE = 0;
109  invMassPhoPi0 = 0;
110  invMassEPhi = 0;
111  //caloevalstack = NULL;
112 }
113 
114 //____________________________________________________________________________..
116 {
117  std::cout << "cemcReco::~cemcReco() Calling dtor" << std::endl;
118 }
119 
120 //____________________________________________________________________________..
122 {
123  std::cout << "cemcReco::Init(PHCompositeNode *topNode) Initializing Histos" << std::endl;
124 
125  //histo initialization
126  photonE = new TH1F("photonE_Reco","Reco Energy",200,0,20);
127 
128  clusterChi2 = new TH2F("clusterChi2","Cluster chi2",100,0,20,200,0,20);
129 
130  clusterProbPhoton = new TH2F("clusterProbPhoton","Cluster template probability",100,0,1,200,0,20);
131 
132  isoPhoE = new TH1F("isoPhotonE_Reco_Tru","Isolated Photon Energy",200,0,20);
133 
134  isoPhoChi2 = new TH2F("isoPhotonChi2","Isolated Photon Chi2 v. E",100,0,20,200,0,20);
135 
136  isoPhoProb = new TH2F("isoPhotonProb2","Isolated Photon Prob v. E",100,0,1,200,0,20);
137 
138  deltaR_E_invMass = new TH3F("deltaREinvMass","Opening Angle v. E v. InvMass",100,0,1,200,0,20,100,0,1);
139 
140  tsp_E = new TH2F("tspE","Transverse Shower Profile v. E",100,0,1,200,0,20);
141 
142  tsp_E_iso = new TH2F("tspEiso","Transverse Shower Profile Iso v. E",100,0,1,200,0,20);
143 
144  asym_E_invMass = new TH3F("asymEinvMass","Asymmetry v. E v. Invariant Mass",100,0,1,200,0,20,100,0,1);
145 
146  for(int i = 0; i < nEtaBins; i++)truth_pi0_E[i] = new TH1F(Form("truthPi0E_Eta%d",i),"truth pi0 energy",200,0,20);
147 
148  truth_eta_E = new TH1F("truthEtaE","truth eta energy",200,0,20);
149 
150  truth_dpho_E = new TH1F("truthDphoE","truth direct photon energy",200,0,20);
151 
152  deltaR_E_truth_pi0 = new TH2F("deltaREtruthpi0","Opening angle truth pi0",100,0,1,500,0,50);
153 
154  asym_E_truth_pi0 = new TH2F("asymEtruthpi0","Photon asymmetry truth pi0",100,0,1,200,0,20);
155 
156  pi0E_truth_reco = new TH1F("pi0ETruthReco","Reco pi0/truth",100,0,2);
157 
158  invMass_eta = new TH3F("invMassEtaE","Invariant Mass vs. psuedorapidity bin",100,0,1,200,-1.2,1.2,200,0,20);
159 
160  eFrac_dr_primary = new TH2F("eFrac_dr_primary","Reco/Truth vs dr. primary",100,0,1,100,0,4);
161 
162  eFrac_dr_secondary = new TH2F("eFrac_dr_secondary","Reco/Truth vs dr. secondary",100,0,1,100,0,4);
163 
164  //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);
165  //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);
166 
167  for(int i = 0; i < 2; i++)
168  {
169  for(int j = 0; j < nEtaBins; j++)
170  {
171  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);
172  }
173  }
174 
175  dPhoChi2 = new TH3F("dphoChi2","Direct Photon Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
176  dPhoProb = new TH3F("dphoProb","Direct Photon Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
177 
178  pi0Chi2 = new TH3F("pi0Chi2","Pi0 Daughter Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
179  pi0Prob = new TH3F("pi0Prob","Pi0 Daughter Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
180 
181  etaChi2 = new TH3F("etaChi2","Eta Daughter Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
182  etaProb = new TH3F("etaProb","Eta Daughter Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
183 
184  electronChi2 = new TH3F("eChi2","Electron Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
185  electronProb = new TH3F("eProb","Electron Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
186 
187  hadronChi2 = new TH3F("hChi2","Hadron Chi2 vs. Cluster Energy vs. Mother energy",100,0,20,200,0,20,200,0,20);
188  hadronProb = new TH3F("hProb","Hadron Prob vs. Cluster Energy vs. Mother energy",100,0,1,200,0,20,200,0,20);
189 
190  etaFrac = new TH2F("etaClusterEFrac","clusters from eta fractional energy",200,0,1.5,500,0,50);
191 
192  pi0Frac = new TH2F("pi0ClusterEFrac","clusters from pi0 fractional energy",200,0,1.5,500,0,50);
193 
194  invMassEPhi = new TH3F("invMassEPhi","invariant mass vs. Truth Energy vs. phi",500,-0.1,1,500,0,50,200,-M_PI,M_PI);
195 
196  unmatchedLocale = new TH3F("unmatchedLocale","location of unmatched truth photons",200,-5,5,180,-M_PI,M_PI,500,0,50);
197  unmatchedE = new TH1F("unmatchedE","energy of unmatched truth photons",250,0,50);
198 
199  invMassPhoPi0 = new TH3F("invMassPhoPi0","invariant mass vs. Photon energy scale vs. pi0 energy scale",500,-0.1,1,100,0,2,100,0,2);
200 
201  //so that the histos actually get written out
203  se -> Print("NODETREE");
204  hm = new Fun4AllHistoManager("MYHISTOS");
205 
206  se -> registerHistoManager(hm);
207 
208  se -> registerHisto(photonE -> GetName(),photonE);
209  se -> registerHisto(clusterChi2 -> GetName(), clusterChi2);
210  se -> registerHisto(clusterProbPhoton -> GetName(), clusterProbPhoton);
211  se -> registerHisto(isoPhoE -> GetName(), isoPhoE);
212  se -> registerHisto(isoPhoChi2 -> GetName(), isoPhoChi2);
213  se -> registerHisto(isoPhoProb -> GetName(), isoPhoProb);
214  se -> registerHisto(deltaR_E_invMass -> GetName(), deltaR_E_invMass);
215  se -> registerHisto(asym_E_invMass -> GetName(), asym_E_invMass);
216  se -> registerHisto(pi0E_truth_reco -> GetName(), pi0E_truth_reco);
217  se -> registerHisto(invMass_eta -> GetName(), invMass_eta);
218  //se -> registerHisto(ePi0InvMassEcut[0] -> GetName(), ePi0InvMassEcut[0]);
219  //se -> registerHisto(ePi0InvMassEcut[1] -> GetName(), ePi0InvMassEcut[1]);
220  for(int i = 0; i < 2; i++)
221  {
222  for(int j = 0; j < 2; j++)
223  {
224  se -> registerHisto(ePi0InvMassEcut[i][j] -> GetName(), ePi0InvMassEcut[i][j]);
225  }
226  }
227  se -> registerHisto(eFrac_dr_secondary -> GetName(), eFrac_dr_secondary);
228  se -> registerHisto(eFrac_dr_primary -> GetName(), eFrac_dr_primary);
229  se -> registerHisto(dPhoChi2 -> GetName(), dPhoChi2);
230  se -> registerHisto(dPhoProb -> GetName(), dPhoProb);
231  se -> registerHisto(pi0Chi2 -> GetName(), pi0Chi2);
232  se -> registerHisto(pi0Prob -> GetName(), pi0Prob);
233  se -> registerHisto(etaChi2 -> GetName(), etaChi2);
234  se -> registerHisto(etaProb -> GetName(), etaProb);
235  se -> registerHisto(electronChi2 -> GetName(), electronChi2);
236  se -> registerHisto(electronProb -> GetName(), electronProb);
237  se -> registerHisto(hadronChi2 -> GetName(), hadronChi2);
238  se -> registerHisto(hadronProb -> GetName(), hadronProb);
239  se -> registerHisto(unmatchedLocale -> GetName(), unmatchedLocale);
240  se -> registerHisto(unmatchedE -> GetName(), unmatchedE);
241 
242  se -> registerHisto(invMassPhoPi0 -> GetName(), invMassPhoPi0);
243  se -> registerHisto(invMassEPhi -> GetName(), invMassEPhi);
244 
245 
246  out = new TFile(Outfile.c_str(),"RECREATE");
247 
248 
249  //Call sumw2() on everything
250  //letsSumw2();
252 }
253 
254 //____________________________________________________________________________..
256 {
257  std::cout << "cemcReco::InitRun(PHCompositeNode *topNode) No run dependence, doing nothing." << std::endl;
259 }
260 
261 //____________________________________________________________________________..
263 {
264 
265 
266  if(!nEvent%100)
267  {
268  std::cout << "Processing Event: " << nEvent << std::endl;
269  }
270 
271  //event-level information
272  EventHeader *evtInfo = findNode::getClass<EventHeader>(topNode,"EventHeader");
273  if(!evtInfo)
274  {
275  std::cout << PHWHERE << "cemc::process_event: EventHeader not in node tree" << std::endl;
276  return 0;
277  }
278 
279  //Information on clusters
280  RawClusterContainer *clusterContainer = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_POS_COR_CEMC");
281  //RawClusterContainer *clusterContainer = findNode::getClass<RawClusterContainer>(topNode,"CLUSTER_CEMC");
282  if(!clusterContainer)
283  {
284  std::cout << PHWHERE << "cemc::process_event - Fatal Error - CLUSTER_POS_COR_CEMC node is missing. " << std::endl;
285 
286  return 0;
287  }
288 
289 
290  //Vertex information
291  GlobalVertexMap *vtxContainer = findNode::getClass<GlobalVertexMap>(topNode,"GlobalVertexMap");
292  if (!vtxContainer)
293  {
294  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;
295  assert(vtxContainer); // force quit
296 
297  return 0;
298  }
299 
300  if (vtxContainer->empty())
301  {
302  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;
303  return 0;
304  }
305 
306  //More vertex information
307  GlobalVertex *vtx = vtxContainer->begin()->second;
308  if(!vtx)
309  {
310 
311  std::cout << PHWHERE << "cemc::process_event Could not find vtx from vtxContainer" << std::endl;
313  }
314 
315  //Tracks for the isolation cone
316  SvtxTrackMap *trackmap = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
317  if(!trackmap)
318  {
319  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;
320  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;
321  trackErrorCount++;
322  //return Fun4AllReturnCodes::ABORTEVENT;
323  }
324 
325  //Tower geometry node for location information
326  RawTowerGeomContainer *towergeom = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_CEMC");
327  if (!towergeom)
328  {
329  std::cout << PHWHERE << "cemc::process_event Could not find node TOWERGEOM_CEMC" << std::endl;
331  }
332 
333  //Raw tower information
334  RawTowerContainer *towerContainer = findNode::getClass<RawTowerContainer>(topNode,"TOWER_CALIB_CEMC");
335  if(!towerContainer)
336  {
337  std::cout << PHWHERE << "cemc::process_event Could not find node TOWER_CALIB_CEMC" << std::endl;
339  }
340 
341  //truth particle information
342  PHG4TruthInfoContainer *truthinfo = findNode::getClass<PHG4TruthInfoContainer>(topNode, "G4TruthInfo");
343  if(!truthinfo)
344  {
345  std::cout << PHWHERE << "cemc::process_event Could not find node G4TruthInfo" << std::endl;
347  }
348 
349  //For pythia ancestory information
350  PHHepMCGenEventMap *genEventMap = findNode::getClass<PHHepMCGenEventMap>(topNode, "PHHepMCGenEventMap");
351  if(!genEventMap)
352  {
353  std::cout << PHWHERE << "cemc::process_event Could not find PHHepMCGenEventMap" << std::endl;
355  }
356  //event level information of the above
357  PHHepMCGenEvent *genEvent = genEventMap -> get(1);
358  if(!genEvent)
359  {
360  std::cout << PHWHERE << "cemc::process_event Could not find PHHepMCGenEvent" << std::endl;
362  }
363 
364  HepMC::GenEvent *theEvent = genEvent -> getEvent();
365 
366  CaloEvalStack caloevalstack(topNode, "CEMC");
367  CaloRawClusterEval *clustereval = caloevalstack.get_rawcluster_eval();
368  if(!clustereval)
369  {
370  std::cout << PHWHERE << "cemc::process_event cluster eval not available" << std::endl;
372  }
373 
374  float mesonEtaMax = 0.3;
375  float photonEtaMax = 1.1;
376  PHG4Particle *maxPrimary = NULL;
377  //This is how we iterate over items in the container.
378  RawClusterContainer::ConstRange clusterEnd = clusterContainer -> getClusters();
380 
381  //general pass over photons for info with only a mild energy cut to reduce noise
382  std::vector<RawCluster*> goodRecoCluster;
383  float minE = 0.3;
384  float minDirpT = 4.;
385  float isoConeRadius = 3;
386  for(clusterIter = clusterEnd.first; clusterIter != clusterEnd.second; clusterIter++)
387  {
388  RawCluster *recoCluster = clusterIter -> second;
389 
390  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
391  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*recoCluster, vertex);
392  float clusE = E_vec_cluster.mag();
393  float clus_eta = E_vec_cluster.pseudoRapidity();
394  float clus_pt = E_vec_cluster.perp();
395  //float clus_phi = E_vec_cluster.getPhi();
396 
397  if(clusE < minE) continue;
398 
399  maxPrimary = clustereval -> max_truth_primary_particle_by_energy(recoCluster);
400  if(maxPrimary)
401  {
402 
403  if(maxPrimary -> get_pid() == 11 || maxPrimary -> get_pid() == -11)
404  {
405  electronChi2 -> Fill(recoCluster -> get_chi2(), clusE, maxPrimary -> get_e());
406  electronProb -> Fill(recoCluster -> get_prob(), clusE, maxPrimary -> get_e());
407  }
408  else if(maxPrimary -> get_pid() == 211 || maxPrimary -> get_pid() == -211)
409  {
410  hadronChi2 -> Fill(recoCluster -> get_chi2(), clusE, maxPrimary -> get_e());
411  hadronProb -> Fill(recoCluster -> get_prob(), clusE, maxPrimary -> get_e());
412  }
413  if(maxPrimary -> get_pid() == 22)
414  {
415  for(HepMC::GenEvent::particle_const_iterator p = theEvent -> particles_begin(); p != theEvent -> particles_end(); ++p)
416  {
417  assert(*p);
418 
419  if((*p) -> barcode() == maxPrimary -> get_barcode())
420  {
421  for(HepMC::GenVertex::particle_iterator mother = (*p)->production_vertex()->particles_begin(HepMC::parents);
422  mother != (*p)->production_vertex()->particles_end(HepMC::parents); ++mother)
423  {
424  HepMC::FourVector moMomentum = (*mother) -> momentum();
425  float e = moMomentum.e();
426  //float eta = moMomentum.pseudoRapidity();
427  if((*mother) -> pdg_id() == 22)
428  {
429  dPhoChi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
430  dPhoProb -> Fill(recoCluster -> get_prob(), clusE, e);
431  }
432  else if((*mother) -> pdg_id() == 111)
433  {
434  pi0Chi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
435  pi0Prob -> Fill(recoCluster -> get_prob(), clusE, e);
436  pi0Frac -> Fill(clusE/e, e);
437  }
438  else if((*mother) -> pdg_id() == 221)
439  {
440  etaChi2 -> Fill(recoCluster -> get_chi2(), clusE, e);
441  etaProb -> Fill(recoCluster -> get_prob(), clusE, e);
442  etaFrac -> Fill(clusE/e, e);
443 
444  }
445 
446  }
447  }
448  }
449  }
450  }
451 
452 
453 
454  photonE -> Fill(clusE);
455  //clusterChi2 -> Fill(recoCluster -> get_chi2(), clusE);
456  //clusterProbPhoton -> Fill(recoCluster -> get_prob(), clusE);
457 
458  //Calculate the transverse shower profile, how spread out the energy in the cluster is
459  //more spread out -> Most likely pi0 or other meson decay
460  //less spread out -> iso photon
461  float tsp = calculateTSP(recoCluster, clusterContainer, towerContainer, towergeom, vtx);
462 
463  tsp_E -> Fill(tsp, clusE);
464 
465 
466  //check to see if this is a high p_T isolate photon -> possibly a direct photon
467  if(clus_pt > minDirpT)
468  {
469 
470 
471  //make sure entire isocone is contained within sPHENIX acceptance
472  if((fabs(clus_eta) < 1.0 - isoConeRadius) && trackmap)
473  {
474  float energyInCone = coneSum(recoCluster,clusterContainer, trackmap, isoConeRadius, vtx);
475 
476  if(energyInCone < 0.1*clusE)
477  {
478  isoPhoChi2 -> Fill(recoCluster -> get_chi2(), clusE);
479  isoPhoProb -> Fill(recoCluster -> get_prob(), clusE);
480  isoPhoE -> Fill(clusE);
481  tsp_E_iso -> Fill(tsp, clusE);
482  //isIso = true;
483  }
484  }
485  }
486  goodRecoCluster.push_back(recoCluster);
487  }
488 
489  //And now we'll loop over all the good clusters to reconstruct pi0's and etas
490  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
491  for(int i = 0; i < (int)goodRecoCluster.size(); i++)
492  {
493 
494 
495  CLHEP::Hep3Vector E_vec_cluster1 = RawClusterUtility::GetECoreVec(*goodRecoCluster[i], vertex);
496 
497  TLorentzVector pho1, pho2, pi0;
498  pho1.SetPtEtaPhiE(E_vec_cluster1.perp(), E_vec_cluster1.pseudoRapidity(), E_vec_cluster1.getPhi(), E_vec_cluster1.mag());
499 
500 
501 
502  for(int j = 0; j <(int)goodRecoCluster.size(); j++)
503  {
504 
505  if(j <= i) continue;
506  CLHEP::Hep3Vector E_vec_cluster2 = RawClusterUtility::GetECoreVec(*goodRecoCluster[j], vertex);
507 
508  pho2.SetPtEtaPhiE(E_vec_cluster2.perp(), E_vec_cluster2.pseudoRapidity(), E_vec_cluster2.getPhi(), E_vec_cluster2.mag());
509 
510  pi0 = pho1 + pho2;
511 
512  deltaR_E_invMass -> Fill(pho1.DeltaR(pho2), pi0.Energy(), pi0.M());
513 
514  float asym = abs(pho1.Energy() - pho2.Energy())/pi0.Energy();
515 
516  asym_E_invMass -> Fill(asym, pi0.Energy(), pi0.M());
517 
518  invMass_eta -> Fill(pi0.M(), pi0.Eta(), pi0.Energy());
519 
520  if(abs(pho2.PseudoRapidity()) < photonEtaMax && abs(pho1.PseudoRapidity()) < photonEtaMax && pi0.PseudoRapidity() < mesonEtaMax)
521  {
522  int etaBin = -1;
523  if(pho1.Energy() >= pho2.Energy()) etaBin = getEtaBin(pho1.PseudoRapidity());
524  else etaBin = getEtaBin(pho2.PseudoRapidity());
525  if(etaBin>=0)ePi0InvMassEcut[0][etaBin] -> Fill(pi0.Energy(), pi0.M(),std::min(pho1.Energy(), pho2.Energy()));
526  ePi0InvMassEcut[0][nEtaBins-1] -> Fill(pi0.Energy(), pi0.M(),std::min(pho1.Energy(), pho2.Energy()));
527  }
528  }
529  }
530 
531  //truth pi0 reconstruction handled via the PHHepMCGenEventMap
532  //This accounts for/bypasses the fact that pi0 decay is handled
533  //in general by the event generator. This method is fine for things like
534  //purity and kinematic studies, but if you need to get the *total*
535  //yield of pi0's, it isn't enough, see the primary and secondary
536  //particle loops below
537 
538 
539  std::vector<PHG4Particle*> phoPi0;
540  std::vector<PHG4Particle*> phoEta;
541 
542  std::vector<int> mBarCodePi0;
543  std::vector<HepMC::GenVertex*> vtxIDpi0;
544 
545  std::vector<int> mBarCodeEta;
546  std::vector<HepMC::GenVertex*> vtxIDEta;
547 
548  PHG4TruthInfoContainer::Range truthRange = truthinfo->GetPrimaryParticleRange();
550  //Here's where we link decay photons categorized as "primary" to their parent pi0's
551  //from the HepMC event log
552  for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
553  {
554  PHG4Particle *truthPar = truthIter->second;
555  if(truthPar -> get_pid() != 22) continue;
556  if(truthinfo -> isEmbeded(truthPar -> get_track_id()) != 1) continue;
557 
558  for(HepMC::GenEvent::particle_const_iterator p = theEvent -> particles_begin(); p != theEvent -> particles_end(); ++p)
559  {
560  assert(*p);
561  if((*p) -> pdg_id() != 22) continue;
562 
563  if((*p) -> barcode() == truthPar -> get_barcode())
564  {
565 
566  for (HepMC::GenVertex::particle_iterator mother = (*p)->production_vertex()->particles_begin(HepMC::parents);
567  mother != (*p)->production_vertex()->particles_end(HepMC::parents); ++mother)
568  {
569 
570  HepMC::FourVector moMomentum = (*mother) -> momentum();
571  float e = moMomentum.e();
572  float eta = moMomentum.pseudoRapidity();
573  if((*mother) -> pdg_id() == 22 && abs(eta) < photonEtaMax)
574  {
575 
576  truth_dpho_E -> Fill(e);
577 
578  }
579  else if((*mother) -> pdg_id() == 111 )
580  {
581 
582  phoPi0.push_back(truthPar);//these photons will be unique
583  vtxIDpi0.push_back((*mother) -> production_vertex());
584 
585  mBarCodePi0.push_back((*mother) -> barcode());//barcodes will not be unique, as they'll be added per photon
586  }
587  else if((*mother) -> pdg_id() == 221 )
588  {
589 
590  if(abs(eta) < mesonEtaMax && abs(getEta(truthPar)) < photonEtaMax && !checkBarcode((*mother) -> barcode(),mBarCodeEta))truth_eta_E -> Fill(e);
591  phoEta.push_back(truthPar);
592  vtxIDEta.push_back((*mother) -> production_vertex());
593  mBarCodeEta.push_back((*mother) -> barcode());
594  }
595 
596  }
597  }
598  }
599  }
600 
601  //And then, we have to loop over the photons in the secondary particle list and trace them back to a pi0
602  truthRange = truthinfo -> GetSecondaryParticleRange();
603  for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
604  {
605  PHG4Particle *truthPar = truthIter -> second;
606 
607  while(truthPar -> get_parent_id() != 0)
608  {
609 
610  PHG4Particle *parent = truthinfo -> GetParticle(truthPar -> get_parent_id());
611  if(parent -> get_parent_id() == 0) break; //this is the decay product we want, so we don't want to reassign it
612  truthPar = parent;
613  }
614 
615  if(truthPar -> get_pid() != 22 )
616  {
617  //std::cout << "Killed by final photon pid cut" << std::endl;
618  continue;
619  }
620  PHG4Particle *pi0 = truthinfo -> GetParticle(truthPar -> get_parent_id());
621  if(pi0 -> get_pid() != 111)
622  {
623  //std::cout << "Killed by pi0 pid cut" << std::endl;
624  continue; //secondary not descendant from pi0
625  }
626  if(abs(getEta(pi0)) > mesonEtaMax)
627  {
628  //std::cout << "Killed by pi0 eta cut" << std::endl;
629  continue;//go ahead and make pi0 kinematic cut
630  }
631  if(abs(getEta(truthPar)) > photonEtaMax) continue; //don't cut on photons just yet, save for reconstruction
632 
633  //check to see if we've already gotten this photon and we're just at another shower element
634 
635  if(checkBarcode(truthPar -> get_barcode(), phoPi0))
636  {
637  //std::cout << "Killed by photon barcode cut" << std::endl;
638  continue;
639  }
640  //sneaky overload
641  if(checkBarcode(pi0 -> get_barcode(), mBarCodePi0)) continue;
642 
643  mBarCodePi0.push_back(pi0 -> get_barcode());
644  phoPi0.push_back(truthPar);
645  }
646 
647 
648 
649  //Loop over our recovered decay photons and
650  //extract kinematic information.
651  //First for the pi0's
652  for(int i = 0; i < (int)phoPi0.size(); i++)
653  {
654  for(int j = 0; j < (int)phoPi0.size(); j++)
655  {
656  if(j <= i)
657  {
658  continue;
659  }
660  if(mBarCodePi0.at(i) != mBarCodePi0.at(j))//match mother particles
661  {
662  continue;
663  }
664  if(abs(getEta(phoPi0.at(i))) >= photonEtaMax || abs(getEta(phoPi0.at(j))) >= photonEtaMax)
665  {
666  continue;
667  }
668 
669 
670  TLorentzVector e1Vec, e2Vec;
671  e1Vec.SetPxPyPzE(phoPi0.at(i) -> get_px(),phoPi0.at(i) -> get_py(), phoPi0.at(i) -> get_pz(), phoPi0.at(i) -> get_e());
672  e2Vec.SetPxPyPzE(phoPi0.at(j) -> get_px(),phoPi0.at(j) -> get_py(), phoPi0.at(j) -> get_pz(), phoPi0.at(j) -> get_e());
673 
674 
675  float dr = e1Vec.DeltaR(e2Vec);
676 
677  float e1, e2;
678  e1 = phoPi0.at(i) -> get_e();
679  e2 = phoPi0.at(j) -> get_e();
680 
681  float asym = abs(e1-e2)/(e1+e2);
682 
683  TLorentzVector pi0 = e1Vec + e2Vec;
684  if(abs(pi0.PseudoRapidity()) >= mesonEtaMax)
685  {
686  continue;
687  }
688  int etaBin = -1;
689  if(e1Vec.Energy() >= e2Vec.Energy()) etaBin = getEtaBin(e1Vec.PseudoRapidity());
690  else etaBin = getEtaBin(e2Vec.PseudoRapidity());
691  if(etaBin>=0)truth_pi0_E[etaBin] -> Fill(pi0.Energy());//fill individual eta bin
692  truth_pi0_E[nEtaBins-1] -> Fill(pi0.Energy());//fill one for all eta bins
693 
694  asym_E_truth_pi0 -> Fill(asym, pi0.E());
695  deltaR_E_truth_pi0 -> Fill(dr, pi0.E());
696 
697  RawCluster *best_cluster1 = clustereval -> best_cluster_from(phoPi0.at(i));
698  RawCluster *best_cluster2 = clustereval -> best_cluster_from(phoPi0.at(j));
699 
700  if(!best_cluster1 || !best_cluster2)
701  {
702  if(!best_cluster1)
703  {
704 
705  unmatchedLocale -> Fill(getEta(phoPi0.at(i)), getPhi(phoPi0.at(i)), pi0.E());
706  unmatchedE -> Fill(phoPi0.at(i) -> get_e());
707  }
708  if(!best_cluster2)
709  {
710 
711  unmatchedLocale -> Fill(getEta(phoPi0.at(j)), getPhi(phoPi0.at(j)), pi0.E());
712  unmatchedE -> Fill(phoPi0.at(j) -> get_e());
713  }
714  int etaBin = -1;
715  if(e1Vec.Energy() >= e2Vec.Energy()) etaBin = getEtaBin(e1Vec.PseudoRapidity());
716  else etaBin = getEtaBin(e2Vec.PseudoRapidity());
717  if(etaBin>=0)ePi0InvMassEcut[1][etaBin] -> Fill(pi0.Energy(), 0., std::min(e1Vec.Energy(), e2Vec.Energy()));
718  ePi0InvMassEcut[1][nEtaBins-1] -> Fill(pi0.Energy(), 0., std::min(e1Vec.Energy(), e2Vec.Energy()));
719  }
720  else
721  {
722  if(best_cluster1 -> get_id() == best_cluster2 -> get_id()) continue;
723 
724 
725  CLHEP::Hep3Vector E_vec_cluster1 = RawClusterUtility::GetECoreVec(*best_cluster1, vertex);
726  CLHEP::Hep3Vector E_vec_cluster2 = RawClusterUtility::GetECoreVec(*best_cluster2, vertex);
727 
728  TLorentzVector clusE1, clusE2, clusPi0;
729  clusE1.SetPtEtaPhiE(E_vec_cluster1.perp(), E_vec_cluster1.pseudoRapidity(), E_vec_cluster1.getPhi(), E_vec_cluster1.mag());
730  clusE2.SetPtEtaPhiE(E_vec_cluster2.perp(), E_vec_cluster2.pseudoRapidity(), E_vec_cluster2.getPhi(), E_vec_cluster2.mag());
731 
732  clusPi0 = clusE1 + clusE2;
733 
734  int etaBin = -1;
735  if(clusE1.Energy() >= clusE2.Energy()) etaBin = getEtaBin(clusE1.PseudoRapidity());
736  else etaBin = getEtaBin(clusE2.PseudoRapidity());
737  if(etaBin>=0)ePi0InvMassEcut[1][etaBin] -> Fill(pi0.Energy(), clusPi0.M(),std::min(clusE1.Energy(), clusE2.Energy()));
738  ePi0InvMassEcut[1][nEtaBins-1] -> Fill(pi0.Energy(), clusPi0.M(),std::min(clusE1.Energy(), clusE2.Energy()));
739 
740  invMassEPhi -> Fill(clusPi0.M(), pi0.Energy(), clusE1.Phi());
741  invMassEPhi -> Fill(clusPi0.M(), pi0.Energy(), clusE2.Phi());
742 
743  invMassPhoPi0 -> Fill(clusPi0.M(), clusPi0.Energy()/pi0.Energy(), clusE1.Energy()/e1Vec.Energy());
744  invMassPhoPi0 -> Fill(clusPi0.M(), clusPi0.Energy()/pi0.Energy(), clusE2.Energy()/e2Vec.Energy());
745 
746  }
747  }
748  }
749 
750  //collecting pi0's that enter GEANT's volume. This is actually now handled by
751  //collecting photons from the secondary photon list.
752  /*truthRange = truthinfo->GetPrimaryParticleRange();
753  for(truthIter = truthRange.first; truthIter != truthRange.second; truthIter++)
754  {
755  PHG4Particle *truthPar = truthIter->second;
756  if(truthPar -> get_pid() == 111 && truthPar -> get_parent_id() == 0)//it's a primary pi0, let's take a look
757  {
758  if(abs(getEta(truthPar)) < mesonEtaMax)
759  {
760  //truth_pi0_E -> Fill(truthPar -> get_e());
761  }
762  }
763  }*/
764 
765  PHG4TruthInfoContainer::Range truthRangeDecay1 = truthinfo->GetSecondaryParticleRange();
767 
768 
769  //Get decays from other particles to pi0's
770  for(truthIterDecay1 = truthRangeDecay1.first; truthIterDecay1 != truthRangeDecay1.second; truthIterDecay1++)
771  {
772  PHG4Particle *truthDecay1 = truthIterDecay1 -> second;
773 
774  if(truthDecay1 -> get_parent_id() != 0 && truthDecay1 -> get_pid() == 111 && abs(getEta(truthDecay1)) < mesonEtaMax) //want decay pi0's
775  {
776  //truth_pi0_E -> Fill(truthDecay1 -> get_e());
777  }
778  }
779 
780 
781 
782 
783  nEvent++;
784  goodRecoCluster.clear();
785  phoPi0.clear();
786  phoEta.clear();
787  mBarCodePi0.clear();
788  vtxIDpi0.clear();
789  mBarCodeEta.clear();
790 
791  vtxIDEta.clear();
793 }
794 
795 //____________________________________________________________________________..
797 {
798  //std::cout << "cemcReco::ResetEvent(PHCompositeNode *topNode) Resetting internal structures, prepare for next event" << std::endl;
800 }
801 
802 //____________________________________________________________________________..
804 {
805  std::cout << "cemcReco::EndRun(const int runnumber) Ending Run for Run " << runnumber << std::endl;
807 }
808 
809 //____________________________________________________________________________..
811 {
812  std::cout << "cemcReco::End(PHCompositeNode *topNode) This is the End..." << std::endl;
813  out -> cd();
814 
815  photonE -> Write();
816  clusterChi2 -> Write();
818  isoPhoE -> Write();
819  isoPhoChi2 -> Write();
820  isoPhoProb -> Write();
821  deltaR_E_invMass -> Write();
822  tsp_E -> Write();
823  tsp_E_iso -> Write();
824  asym_E_truth_pi0 -> Write();
826  for(int i = 0; i < nEtaBins; i++) truth_pi0_E[i] -> Write();
827  truth_eta_E -> Write();
828  truth_dpho_E -> Write();
829  asym_E_invMass -> Write();
830  pi0E_truth_reco -> Write();
831  invMass_eta -> Write();
833  eFrac_dr_primary -> Write();
834  //ePi0InvMassEcut[0] -> Write();
835  //ePi0InvMassEcut[1] -> Write();
836  for(int i = 0; i < 2; i++)
837  {
838  for(int j = 0; j < nEtaBins; j++)
839  {
840  ePi0InvMassEcut[i][j] -> Write();
841  }
842  }
843 
844  dPhoChi2 -> Write();
845  dPhoProb -> Write();
846  pi0Chi2 -> Write();
847  pi0Prob -> Write();
848  etaChi2 -> Write();
849  etaProb -> Write();
850  electronChi2 -> Write();
851  electronProb -> Write();
852  hadronChi2 -> Write();
853  hadronProb -> Write();
854  pi0Frac -> Write();
855  etaFrac -> Write();
856  unmatchedLocale -> Write();
857  unmatchedE -> Write();
858  invMassPhoPi0 -> Write();
859  invMassEPhi -> Write();
860 
861  //out -> Close();
862 
863  //delete out;
864  //delete caloevalstack;
865 
866  //hm -> dumpHistos(Outfile.c_str(),"UPDATE");
868 }
869 
870 //____________________________________________________________________________..
872 {
873  std::cout << "cemcReco::Reset(PHCompositeNode *topNode) being Reset" << std::endl;
875 }
876 
877 //____________________________________________________________________________..
878 void cemcReco::Print(const std::string &what) const
879 {
880  std::cout << "cemcReco::Print(const std::string &what) const Printing info for " << what << std::endl;
881 }
882 //____________________________________________________________________________..
884  RawClusterContainer *cluster_container,
885  SvtxTrackMap *trackmap,
886  float coneradius,
887  GlobalVertex *vtx)
888 {
889  float energyptsum = 0;
890 
891  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
892  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
893 
894  RawClusterContainer::ConstRange begin_end = cluster_container->getClusters();
896 
897  for (clusiter = begin_end.first;
898  clusiter != begin_end.second;
899  ++clusiter)
900  {
901  RawCluster *conecluster = clusiter->second;
902 
903  //check to make sure that the candidate isolated photon isn't being counted in the energy sum
904  if (conecluster->get_energy() == cluster->get_energy())
905  if (conecluster->get_phi() == cluster->get_phi())
906  if (conecluster->get_z() == cluster->get_z())
907  continue;
908 
909  CLHEP::Hep3Vector E_vec_conecluster = RawClusterUtility::GetECoreVec(*conecluster, vertex);
910 
911  float cone_pt = E_vec_conecluster.perp();
912 
913  if (cone_pt < 0.2)
914  continue;
915 
916  float cone_e = conecluster->get_energy();
917  float cone_eta = E_vec_conecluster.pseudoRapidity();
918  float cone_phi = E_vec_conecluster.getPhi();
919 
920  float dphi = cluster->get_phi() - cone_phi;
921  if (dphi < -1 * pi)
922  dphi += 2. * pi;
923  if (dphi > pi)
924  dphi -= 2. * pi;
925 
926  float deta = E_vec_cluster.pseudoRapidity() - cone_eta;
927 
928  float radius = sqrt(dphi * dphi + deta * deta);
929 
930  if (radius < coneradius)
931  {
932  energyptsum += cone_e;
933  }
934  }
935 
936  for (SvtxTrackMap::Iter iter = trackmap->begin(); iter != trackmap->end(); ++iter)
937  {
938  SvtxTrack *track = iter->second;
939 
940  float trackpx = track->get_px();
941  float trackpy = track->get_py();
942  float trackpt = sqrt(trackpx * trackpx + trackpy * trackpy);
943  if (trackpt < 0.2)
944  continue;
945  float trackphi = track->get_phi();
946  float tracketa = track->get_eta();
947  float dphi = E_vec_cluster.getPhi() - trackphi;
948  float deta = E_vec_cluster.pseudoRapidity() - tracketa;
949  float radius = sqrt(dphi * dphi + deta * deta);
950 
951  if (radius < coneradius)
952  {
953  energyptsum += trackpt;
954  }
955  }
956 
957  return energyptsum;
958 }
959 
960 //____________________________________________________________________________..
962  RawClusterContainer *clusterContainer,
963  RawTowerContainer *towerContainer,
964  RawTowerGeomContainer *towerGeo,
965  GlobalVertex *vtx
966  )
967 {
968 
969  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
970  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetECoreVec(*cluster, vertex);
971  float clusE = E_vec_cluster.mag();
972  float clusEta = E_vec_cluster.pseudoRapidity();
973  //float clus_pt = E_vec_cluster.perp();
974  float clusPhi = E_vec_cluster.getPhi();
975 
976  RawCluster::TowerConstRange towers = cluster->get_towers();
978 
979  float denom = 0;
980  for (toweriter = towers.first; toweriter != towers.second; ++toweriter)
981  {
982 
983  RawTower *tower = towerContainer->getTower(toweriter->first);
984 
985  //int towereta = tower->get_bineta();
986  //int towerphi = tower->get_binphi();
987  double towerEnergy = tower->get_energy();
988 
989  //Get eta and phi bin from the rawTowerContainer
990  //then transform it to coordinates with the tower geometry object
991  int phibin = tower->get_binphi();
992  int etabin = tower->get_bineta();
993  double phi = towerGeo->get_phicenter(phibin);
994  double eta = towerGeo->get_etacenter(etabin);
995 
996  float r = sqrt(pow(clusEta - eta,2) + pow(clusPhi - phi,2));
997  denom += towerEnergy*pow(r,1.5);
998 
999  }
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 //____________________________________________________________________________..
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 //____________________________________________________________________________..
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 //____________________________________________________________________________..
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