Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHFlowJetMaker.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHFlowJetMaker.C
1 //----------------------------------------------------------
2 // Module for flow jet reconstruction in sPHENIX
3 // J. Orjuela-Koop
4 // May 5 2015
5 //----------------------------------------------------------
6 
7 #include <PHFlowJetMaker.h>
8 #include <calobase/RawCluster.h>
9 #include <calobase/RawClusterContainer.h>
10 #include <calobase/RawClusterUtility.h>
11 
12 #include <g4vertex/GlobalVertex.h>
13 #include <g4vertex/GlobalVertexMap.h>
14 
15 #include <g4hough/SvtxTrack.h>
16 #include <g4hough/SvtxTrackMap.h>
17 
18 #include <phool/PHCompositeNode.h>
19 #include <phool/PHNodeIterator.h>
20 #include <phool/PHNodeReset.h>
21 #include <phool/PHObject.h>
22 #include <phool/getClass.h>
23 
25 
26 #include <fastjet/ClusterSequence.hh>
27 #include <fastjet/JetDefinition.hh>
28 #include <fastjet/PseudoJet.hh>
29 #include <fastjet/SISConePlugin.hh>
30 
31 #include <g4jets/Jet.h>
32 #include <g4jets/JetMapV1.h>
33 #include <g4jets/JetV1.h>
34 
35 #include <TF1.h>
36 #include <TFile.h>
37 #include <TH1.h>
38 #include <TH2.h>
39 #include <TMath.h>
40 #include <TNtuple.h>
41 
42 #include <iomanip>
43 #include <iostream>
44 #include <sstream>
45 
46 using namespace std;
47 using namespace Fun4AllReturnCodes;
48 
49 typedef std::map<int, TLorentzVector*> tlvmap;
50 
51 // Jin - this thing is obsolete. Clusters now already have calibrated energies
52 const float PHFlowJetMaker::sfEMCAL = 0.03;
53 const float PHFlowJetMaker::sfHCALIN = 0.071;
54 const float PHFlowJetMaker::sfHCALOUT = 0.04;
55 
56 /*
57  * Constructor
58  */
60  : SubsysReco(name)
61 {
62  flow_jet_map = NULL;
63  this->algorithm = algorithm;
64  this->r_param = r_param;
65  //outfile = outputfile;
66 
67  //Define parameters for jet reconstruction
68  min_jet_pT = 1.0;
70 
71  if (algorithm == "AntiKt")
72  fJetAlgorithm = new fastjet::JetDefinition(fastjet::antikt_algorithm, r_param, fastjet::E_scheme, strategy);
73 
74  if (algorithm == "Kt")
75  fJetAlgorithm = new fastjet::JetDefinition(fastjet::kt_algorithm, r_param, fastjet::E_scheme, strategy);
76 
77  //Define tolerance limits for track-cluster matching
78  match_tolerance_low = new TF1("match_tolerance_low", "pol4");
79  match_tolerance_low->SetParameter(0, -0.470354);
80  match_tolerance_low->SetParameter(1, 0.928888);
81  match_tolerance_low->SetParameter(2, -0.0958367);
82  match_tolerance_low->SetParameter(3, 0.00748122);
83  match_tolerance_low->SetParameter(4, -0.000177858);
84 
85  match_tolerance_high = new TF1("match_tolerance_high", "pol2");
86  match_tolerance_high->SetParameter(0, 0.457184);
87  match_tolerance_high->SetParameter(1, 1.24821);
88  match_tolerance_high->SetParameter(2, -0.00848157);
89 }
90 
91 /*
92  * Empty destructor
93  */
95 {
96 }
97 
98 /*
99  * Initialize module
100  */
102 {
103  cout << "------PHFlowJetMaker::Init(PHCompositeNode*)------" << endl;
104  create_node_tree(topNode);
105 
106  return EVENT_OK;
107 }
108 
109 /*
110  * Create node tree for flow jets
111  */
113 {
114  PHNodeIterator iter(topNode);
115 
116  //Get the DST node
117  PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
118  if (!dstNode)
119  {
120  cout << "DST Node missing. Doing nothing." << endl;
121  return ABORTEVENT;
122  }
123 
124  //Get the JET node
125  PHCompositeNode* jetNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "JETS"));
126  if (!jetNode)
127  {
128  if (algorithm == "AntiKt")
129  jetNode = new PHCompositeNode("ANTIKT");
130 
131  else if (algorithm == "Kt")
132  jetNode = new PHCompositeNode("KT");
133 
134  else
135  jetNode = new PHCompositeNode(algorithm);
136 
137  dstNode->addNode(jetNode);
138  }
139 
140  PHNodeIterator jiter(jetNode);
141 
142  PHCompositeNode* flowJetNode = dynamic_cast<PHCompositeNode*>(jiter.findFirst("PHCompositeNode", "FLOW_JETS"));
143  if (!flowJetNode)
144  {
145  flowJetNode = new PHCompositeNode("FLOW_JETS");
146  jetNode->addNode(flowJetNode);
147  }
148 
149  //Add flow jet node to jet node
150  flow_jet_map = new JetMapV1();
151  string nodeName = "Flow";
152 
153  stringstream snodeName;
154  snodeName << algorithm << "_" << nodeName << "_r" << setfill('0') << setw(2) << int(r_param * 10);
155  nodeName = snodeName.str();
156 
157  PHIODataNode<PHObject>* PHFlowJetNode = new PHIODataNode<PHObject>(flow_jet_map, nodeName.c_str(), "PHObject");
158 
159  if (!flowJetNode->addNode(PHFlowJetNode))
160  {
161  cout << "PHFlowJetMaker::create_node_tree() - Can't add node to tree!" << endl;
162  }
163 
164  return EVENT_OK;
165 }
166 
167 /*
168  * Process event
169  */
171 {
172  //-------------------------------------------------
173  // Get Information from Node Tree
174  //-------------------------------------------------
175 
176  //Get calorimeter clusters from node tree
177  RawClusterContainer* emc_clusters = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_CEMC");
178  RawClusterContainer* hci_clusters = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_HCALIN");
179  RawClusterContainer* hco_clusters = findNode::getClass<RawClusterContainer>(topNode, "CLUSTER_HCALOUT");
180 
181  //Get reconstructed tracks from nodetree
182  SvtxTrackMap* reco_tracks = findNode::getClass<SvtxTrackMap>(topNode, "SvtxTrackMap");
183 
184  //Vertex for converting cluster position to momentum direction
185  GlobalVertexMap* vertexmap = findNode::getClass<GlobalVertexMap>(topNode, "GlobalVertexMap");
186  if (!vertexmap)
187  {
188  cout << "PHFlowJetMaker::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." << endl;
189  assert(vertexmap); // force quit
190 
192  }
193 
194  if (vertexmap->empty())
195  {
196  cout << "PHFlowJetMaker::process_event - Fatal Error - GlobalVertexMap node is empty. Please turn on the do_bbc or tracking reco flags in the main macro in order to reconstruct the global vertex." << endl;
197 
199  }
200  GlobalVertex* vtx = vertexmap->begin()->second;
201  assert(vtx);
202 
203  //-------------------------------------------------
204  // Create Jets
205  //-------------------------------------------------
206 
207  // //Create jets from raw clusters
208  // vector<fastjet::PseudoJet> raw_cluster_particles;
209  // create_calo_pseudojets(raw_cluster_particles, emc_clusters, hci_clusters, hco_clusters, vtx);
210  // fastjet::ClusterSequence jet_finder_raw(raw_cluster_particles, *fJetAlgorithm);
211  // vector<fastjet::PseudoJet> raw_cluster_jets = jet_finder_raw.inclusive_jets(min_jet_pT);
212 
213  //Apply particle flow jets algorithm and create jets from flow particles
214  vector<fastjet::PseudoJet> flow_particles;
215  run_particle_flow(flow_particles, emc_clusters, hci_clusters, hco_clusters, reco_tracks, vtx);
216  fastjet::ClusterSequence jet_finder_flow(flow_particles, *fJetAlgorithm);
217  vector<fastjet::PseudoJet> flow_jets = jet_finder_flow.inclusive_jets(min_jet_pT);
218 
219  //Create JetMap from flow jets
220  if (algorithm == "AntiKt")
222 
223  if (algorithm == "Kt")
225 
231 
232  for (unsigned int i = 0; i < flow_jets.size(); i++)
233  {
234  JetV1* j = new JetV1();
235  float px = flow_jets[i].px();
236  float py = flow_jets[i].py();
237  float pz = flow_jets[i].pz();
238  float energy = flow_jets[i].E();
239 
240  // cout << "--px = " << px << endl;
241 
242  j->set_px(px);
243  j->set_py(py);
244  j->set_pz(pz);
245  j->set_e(energy);
246 
247  flow_jet_map->insert(j);
248  }
249 
250  // cout << "IDENTIFYING JET MAP" << endl;
251  // flow_jet_map->identify();
252  //
253  // cout << "IDENTIFYING INDIVIDUAL JETS" << endl;
254  // for(JetMap::Iter it = flow_jet_map->begin(); it != flow_jet_map->end(); it++)
255  // {
256  // (it->second)->identify();
257  // cout << endl;
258  // }
259  //
260  // cout << "FOUND " << flow_jet_map->size() << " FLOW JETS" << endl;
261  return EVENT_OK;
262 }
263 
264 /*
265  * Run particle flow algorithm
266  */
267 void PHFlowJetMaker::run_particle_flow(std::vector<fastjet::PseudoJet>& flow_particles, RawClusterContainer* emc_clusters, RawClusterContainer* hci_clusters, RawClusterContainer* hco_clusters, SvtxTrackMap* reco_tracks, GlobalVertex* vtx)
268 {
269  CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
270 
271  double emc_energy = 0;
272  double hci_energy = 0;
273  double hco_energy = 0;
274  double cluster_energy = 0;
275 
276  double px = 0;
277  double py = 0;
278  double pz = 0;
279  // double pt = 0;
280  double et = 0;
281  double p = 0;
282  double track_energy = 0;
283  double phi = 0;
284  double eta = 0;
285 
286  //Make track maps
287  tlvmap emc_map;
288  tlvmap hci_map;
289  tlvmap hco_map;
290 
291  for (unsigned int i = 0; i < emc_clusters->size(); i++)
292  {
293  RawCluster* part = emc_clusters->getCluster(i);
294  // double pT = (part->get_energy()) / cosh(part->get_eta());
295 
296  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetEVec(*part, vertex);
297 
298  emc_map[i] = new TLorentzVector();
299  // emc_map[i]->SetPtEtaPhiE(pT, part->get_eta(), part->get_phi(), part->get_energy());
300  emc_map[i]->SetPxPyPzE(
301  E_vec_cluster.x(),
302  E_vec_cluster.y(),
303  E_vec_cluster.z(),
304  E_vec_cluster.mag());
305  }
306 
307  for (unsigned int i = 0; i < hci_clusters->size(); i++)
308  {
309  RawCluster* part = hci_clusters->getCluster(i);
310  // double pT = (part->get_energy()) / cosh(part->get_eta());
311  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetEVec(*part, vertex);
312  hci_map[i] = new TLorentzVector();
313  hci_map[i]->
314  // SetPtEtaPhiE(pT, part->get_eta(), part->get_phi(), part->get_energy());
315  SetPxPyPzE(
316  E_vec_cluster.x(),
317  E_vec_cluster.y(),
318  E_vec_cluster.z(),
319  E_vec_cluster.mag());
320  }
321 
322  for (unsigned int i = 0; i < hco_clusters->size(); i++)
323  {
324  RawCluster* part = hco_clusters->getCluster(i);
325  // double pT = (part->get_energy()) / cosh(part->get_eta());
326  CLHEP::Hep3Vector E_vec_cluster = RawClusterUtility::GetEVec(*part, vertex);
327  hco_map[i] = new TLorentzVector();
328  hco_map[i]->
329  // SetPtEtaPhiE(pT, part->get_eta(), part->get_phi(), part->get_energy());
330  SetPxPyPzE(
331  E_vec_cluster.x(),
332  E_vec_cluster.y(),
333  E_vec_cluster.z(),
334  E_vec_cluster.mag());
335  }
336 
337  //Loop over all tracks
338  for (SvtxTrackMap::Iter iter = reco_tracks->begin(); iter != reco_tracks->end(); ++iter)
339  {
340  SvtxTrack* trk = iter->second;
341  px = trk->get_px();
342  py = trk->get_py();
343  pz = trk->get_pz();
344  // pt = sqrt(px*px + py*py);
345  p = sqrt(px * px + py * py + pz * pz);
346  track_energy = TMath::Sqrt(p * p + 0.139 * 0.139); //Assume pion mass
347  phi = atan2(py, px);
348  eta = -log(tan(acos(pz / p) / 2.0));
349  et = track_energy / cosh(eta);
350 
351  //Account for angle wrap-around
352  if (phi < 0)
353  {
354  phi = phi + 2 * TMath::Pi();
355  }
356  else if (phi > 2 * TMath::Pi())
357  {
358  phi = phi + 2 * TMath::Pi();
359  }
360 
361  //Quality cut on tracks
362  if (trk->get_quality() > 3.0) continue;
363 
364  //Find ID of clusters that match to track in each layer
365  int emcID = -1;
366  int hciID = -1;
367  int hcoID = -1;
368  emcID = (int) trk->get_cal_cluster_id(SvtxTrack::CEMC);
369  hciID = (int) trk->get_cal_cluster_id(SvtxTrack::HCALIN);
370  hcoID = (int) trk->get_cal_cluster_id(SvtxTrack::HCALOUT);
371 
372  //Find energy deposited by track in each layer
373  tlvmap::iterator it = emc_map.find(emcID);
374  if (it != emc_map.end())
375  {
376  emc_energy = emc_map[emcID]->Energy();
377  }
378 
379  it = hci_map.find(hciID);
380  if (it != hci_map.end())
381  {
382  hci_energy = hci_map[hciID]->Energy();
383  }
384 
385  it = hco_map.find(hcoID);
386  if (it != hco_map.end())
387  {
388  hco_energy = hco_map[hcoID]->Energy();
389  }
390 
391  cluster_energy = emc_energy + hci_energy + hco_energy;
392 
393  //Does the track match the cluster to within tolerance?
394  // *matched = 0 --> clus_energy < track_energy
395  // *matched = 1 --> clus_energy > track_energy
396  // *matched = 2 --> clus_energy = track_energy
397  int matched = -1;
398  matched = get_matched(cluster_energy, track_energy);
399 
400  //If matched = 1, remove track energy from clusters
401  if (matched == 1)
402  {
403  float fracEnergyEMC = emc_energy / cluster_energy;
404  float fracEnergyHCI = hci_energy / cluster_energy;
405  float fracEnergyHCO = hco_energy / cluster_energy;
406 
407  it = emc_map.find(emcID);
408  if (it != emc_map.end())
409  {
410  (emc_map.find(emcID)->second)->SetE(emc_energy - fracEnergyEMC * track_energy);
411  }
412 
413  it = hci_map.find(hciID);
414  if (it != hci_map.end())
415  {
416  (hci_map.find(hciID)->second)->SetE(hci_energy - fracEnergyHCI * track_energy);
417  }
418 
419  it = hco_map.find(hcoID);
420  if (it != hco_map.end())
421  {
422  (hco_map.find(hcoID)->second)->SetE(hco_energy - fracEnergyHCO * track_energy);
423  }
424  }
425  else if (matched == 2)
426  {
427  it = emc_map.find(emcID);
428  if (it != emc_map.end())
429  {
430  delete emc_map[emcID];
431  emc_map.erase(emcID);
432  }
433 
434  it = hci_map.find(hciID);
435  if (it != emc_map.end())
436  {
437  delete hci_map[hciID];
438  hci_map.erase(hciID);
439  }
440 
441  it = hco_map.find(hcoID);
442  if (it != hco_map.end())
443  {
444  delete hco_map[hcoID];
445  hco_map.erase(hcoID);
446  }
447  }
448  else if (matched == 0)
449  {
450  continue;
451  }
452 
453  //Add perfectly matched and partially matched tracks to flow particle container
454  if (et < 0.000001)
455  {
456  et = 0.001;
457  pz = et * sinh(eta);
458  track_energy = sqrt(et * et + pz * pz);
459  }
460  fastjet::PseudoJet pseudoJet_track(et * cos(phi), et * sin(phi), pz, track_energy);
461  flow_particles.push_back(pseudoJet_track);
462  }
463 
464  //Add remaining clusters to flow particle container
465  for (tlvmap::iterator it = emc_map.begin(); it != emc_map.end(); it++)
466  {
467  double energy_clus = (it->second)->Energy();
468  double eta_clus = (it->second)->Eta();
469  double phi_clus = (it->second)->Phi();
470  double et_clus = energy_clus / cosh(eta_clus);
471  double pz_clus = et * sinh(eta_clus);
472 
473  if (et_clus < 0.000001)
474  {
475  et_clus = 0.001;
476  pz_clus = et_clus * sinh(eta_clus);
477  energy_clus = sqrt(et_clus * et_clus + pz_clus * pz_clus);
478  }
479  fastjet::PseudoJet pseudoJet_clus(et_clus * cos(phi_clus), et_clus * sin(phi_clus), pz_clus, energy_clus);
480  flow_particles.push_back(pseudoJet_clus);
481  }
482 
483  for (tlvmap::iterator it = hci_map.begin(); it != hci_map.end(); it++)
484  {
485  double energy_clus = (it->second)->Energy();
486  double eta_clus = (it->second)->Eta();
487  double phi_clus = (it->second)->Phi();
488  double et_clus = energy_clus / cosh(eta_clus);
489  double pz_clus = et * sinh(eta_clus);
490 
491  if (et_clus < 0.000001)
492  {
493  et_clus = 0.001;
494  pz_clus = et_clus * sinh(eta_clus);
495  energy_clus = sqrt(et_clus * et_clus + pz_clus * pz_clus);
496  }
497  fastjet::PseudoJet pseudoJet_clus(et_clus * cos(phi_clus), et_clus * sin(phi_clus), pz_clus, energy_clus);
498  flow_particles.push_back(pseudoJet_clus);
499  }
500 
501  for (tlvmap::iterator it = hco_map.begin(); it != hco_map.end(); it++)
502  {
503  double energy_clus = (it->second)->Energy();
504  double eta_clus = (it->second)->Eta();
505  double phi_clus = (it->second)->Phi();
506  double et_clus = energy_clus / cosh(eta_clus);
507  double pz_clus = et * sinh(eta_clus);
508 
509  if (et_clus < 0.000001)
510  {
511  et_clus = 0.001;
512  pz_clus = et_clus * sinh(eta_clus);
513  energy_clus = sqrt(et_clus * et_clus + pz_clus * pz_clus);
514  }
515  fastjet::PseudoJet pseudoJet_clus(et_clus * cos(phi_clus), et_clus * sin(phi_clus), pz_clus, energy_clus);
516  flow_particles.push_back(pseudoJet_clus);
517  }
518 }
519 
520 /*
521  * Create pseudojets from calorimeter clusters before applying particle flow algorithm
522  * Jin - disable. Please use the standard cluster jet on the node tree
523  */
524 //void PHFlowJetMaker::create_calo_pseudojets(std::vector<fastjet::PseudoJet>& particles, RawClusterContainer* emc_clusters, RawClusterContainer* hci_clusters, RawClusterContainer* hco_clusters, GlobalVertex* vtx)
525 //{
526 // CLHEP::Hep3Vector vertex(vtx->get_x(), vtx->get_y(), vtx->get_z());
527 //
528 // //Loop over EMCAL clusters
529 // for (unsigned int i = 0; i < emc_clusters->size(); i++)
530 // {
531 // RawCluster* part = emc_clusters->getCluster(i);
532 // double eta = part->get_eta();
533 // double phi = part->get_phi();
534 // double energy = part->get_energy() / sfEMCAL;
535 // double eT = energy / cosh(eta);
536 // double pz = eT * sinh(eta);
537 //
538 // if (eT < 0.000001)
539 // {
540 // eT = 0.001;
541 // pz = eT * sinh(eta);
542 // energy = sqrt(eT * eT + pz * pz);
543 // }
544 //
545 // fastjet::PseudoJet pseudoJet(eT * cos(phi), eT * sin(phi), pz, energy);
546 // particles.push_back(pseudoJet);
547 // }
548 //
549 // //Loop over HCALIN clusters
550 // for (unsigned int i = 0; i < hci_clusters->size(); i++)
551 // {
552 // RawCluster* part = hci_clusters->getCluster(i);
553 // double eta = part->get_eta();
554 // double phi = part->get_phi();
555 // double energy = part->get_energy() / sfHCALIN;
556 // double eT = energy / cosh(eta);
557 // double pz = eT * sinh(eta);
558 //
559 // if (eT < 0.000001)
560 // {
561 // eT = 0.001;
562 // pz = eT * sinh(eta);
563 // energy = sqrt(eT * eT + pz * pz);
564 // }
565 //
566 // fastjet::PseudoJet pseudoJet(eT * cos(phi), eT * sin(phi), pz, energy);
567 // particles.push_back(pseudoJet);
568 // }
569 //
570 // //Loop over HCALOUT clusters
571 // for (unsigned int i = 0; i < hco_clusters->size(); i++)
572 // {
573 // RawCluster* part = hco_clusters->getCluster(i);
574 // double eta = part->get_eta();
575 // double phi = part->get_phi();
576 // double energy = part->get_energy() / sfHCALOUT;
577 // double eT = energy / cosh(eta);
578 // double pz = eT * sinh(eta);
579 //
580 // if (eT < 0.000001)
581 // {
582 // eT = 0.001;
583 // pz = eT * sinh(eta);
584 // energy = sqrt(eT * eT + pz * pz);
585 // }
586 //
587 // fastjet::PseudoJet pseudoJet(eT * cos(phi), eT * sin(phi), pz, energy);
588 // particles.push_back(pseudoJet);
589 // }
590 //}
591 
592 /*
593  * Given a track and cluster energies, determine if they match within tolerance
594  */
595 int PHFlowJetMaker::get_matched(double clus_energy, double track_energy)
596 {
597  double limLo = match_tolerance_low->Eval(track_energy);
598  double limHi = match_tolerance_high->Eval(track_energy);
599 
600  int matched = -1;
601 
602  if (clus_energy < limLo)
603  {
604  //Track energy greater than cluster energy. Most likely a fake
605  matched = 0;
606  }
607  else if (clus_energy > limHi)
608  {
609  //Contaminated cluster
610  matched = 1;
611  }
612  else
613  {
614  //Track and cluster match to within reason
615  matched = 2;
616  }
617 
618  return matched;
619 }
620 
621 /*
622  * End
623  */
625 {
626  return EVENT_OK;
627 }