Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RandomConeAna.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RandomConeAna.cc
1 #include "RandomConeAna.h"
2 
3 
6 
8 #include <phool/getClass.h>
9 
10 #include <jetbase/Jet.h>
11 #include <jetbase/JetMap.h>
12 #include <jetbase/Jetv1.h>
13 #include <jetbase/JetAlgo.h>
14 #include <jetbase/FastJetAlgo.h>
15 #include <jetbase/JetInput.h>
16 #include <jetbase/TowerJetInput.h>
17 #include <jetbase/JetMapv1.h>
18 #include <jetbase/JetContainer.h>
19 #include <jetbase/JetContainerv1.h>
20 #include <jetbase/Jetv2.h>
21 
22 #include <calobase/RawTower.h>
23 #include <calobase/RawTowerContainer.h>
24 #include <calobase/RawTowerGeom.h>
25 #include <calobase/RawTowerGeomContainer.h>
26 #include <calobase/TowerInfoContainer.h>
27 #include <calobase/TowerInfo.h>
28 
30 
31 #include "fastjet/AreaDefinition.hh"
32 #include "fastjet/ClusterSequenceArea.hh"
33 #include "fastjet/Selector.hh"
34 #include "fastjet/tools/BackgroundEstimatorBase.hh"
35 #include "fastjet/tools/JetMedianBackgroundEstimator.hh"
36 #include <fastjet/ClusterSequence.hh>
37 #include <fastjet/JetDefinition.hh>
38 #include <fastjet/PseudoJet.hh>
39 
41 
42 #include <cmath>
43 #include <map>
44 #include <cassert>
45 #include <utility>
46 #include <cstdlib> // for exit
47 #include <iostream>
48 #include <memory> // for allocator_traits<>::value_type
49 #include <vector>
50 
51 #include <TTree.h>
52 #include <TMath.h>
53 #include <TRandom3.h> // for seed
54 #include <TTimeStamp.h>
55 
56 
58  : SubsysReco("RandomConeAna")
59  , m_outputfilename(outputfilename)
60  , _doEventSelection(false)
61  , m_eventSelection(-1, 100000)
62  , _doWeight(false)
63  , m_seed(false)
64  , m_tree(nullptr)
65 {
66 }
67 
69 {
70 
71 
72  for (auto & _input : _inputs)
73  {
74  delete _input;
75  }
76  _inputs.clear();
77 
78  for (auto & _iter_input : _iter_inputs)
79  {
80  delete _iter_input;
81  }
82 }
83 
85 {
86 
87  if(!m_user_set_seed){
88  TTimeStamp* ts = new TTimeStamp();
89  m_seed = static_cast<unsigned int>(ts->GetNanoSec());
90  delete ts;
91  }
92 
93  // initialize TRandom3
94  m_random = new TRandom3(m_seed);
95 
97  m_tree = new TTree("T", "RandomConeAna");
98  m_tree->Branch("event", &m_event, "event/I");
99  if(_doWeight) m_tree->Branch("weight", &weight, "weight/F");
100  m_tree->Branch("seed", &m_seed, "seed/I");
101  m_tree->Branch("centrality", &m_centrality, "centrality/I");
102  m_tree->Branch("rho_area", &m_rho_area, "rho_area/F");
103  m_tree->Branch("rho_area_sigma", &m_rho_area_sigma, "rho_area_sigma/F");
104  m_tree->Branch("rho_mult", &m_rho_mult, "rho_mult/F");
105  m_tree->Branch("rho_mult_sigma", &m_rho_mult_sigma, "rho_mult_sigma/F");
106  m_tree->Branch("cone_area", &m_cone_area, "cone_area/F");
107  m_tree->Branch("cone_nclustered", &m_cone_nclustered, "cone_nclustered/I");
108  m_tree->Branch("cone_pt_raw", &m_cone_pt_raw, "cone_pt_raw/F");
109  m_tree->Branch("cone_pt_iter_sub", &m_cone_pt_iter_sub, "cone_pt_iter_sub/F");
110  m_tree->Branch("randomized_cone_pt_raw", &m_randomized_cone_pt_raw, "randomized_cone_pt_raw/F");
111  m_tree->Branch("randomized_cone_pt_iter_sub", &m_randomized_cone_pt_iter_sub, "randomized_cone_pt_iter_sub/F");
112  m_tree->Branch("avoid_leading_cone_pt_raw", &m_avoid_leading_cone_pt_raw, "avoid_leading_cone_pt_raw/F");
113  m_tree->Branch("avoid_leading_cone_pt_iter_sub", &m_avoid_leading_cone_pt_iter_sub, "avoid_leading_cone_pt_iter_sub/F");
114 
116 }
117 
119 {
120  // std::cout << "RandomConeAna::process_event(PHCompositeNode *topNode) Processing event " << m_event << std::endl;
121  ++m_event;
122 
123  //==================================
124  // Get centrality info
125  //==================================
126  GetCentInfo(topNode);
127 
128 
129  // ==================================
130  // Event selection
131  //==================================
132  if(!EventSelect(topNode)) return Fun4AllReturnCodes::EVENT_OK;
133 
134  //==================================
135  // Get Rho Nodes
136  //==================================
137  EstimateRhos(topNode);
138 
139 
140  //==================================
141  // Reconstruct Random Cones
142  //==================================
143  m_cone_area = 0.4*0.4*TMath::Pi();
144 
145  // get input jets
146  std::vector<Jet *> inputs; // owns memory
147  for (auto &_input : _inputs)
148  {
149  std::vector<Jet *> parts = _input->get_input(topNode);
150  for (auto &part : parts)
151  {
152  inputs.push_back(part);
153  inputs.back()->set_id(inputs.size() - 1); // unique ids ensured
154  }
155  }
156 
157  std::vector<Jet *> iter_inputs; // owns memory
158  for (auto &_iter_input : _iter_inputs)
159  {
160  std::vector<Jet *> parts = _iter_input->get_input(topNode);
161  for (auto &part : parts)
162  {
163  iter_inputs.push_back(part);
164  iter_inputs.back()->set_id(iter_inputs.size() - 1); // unique ids ensured
165  }
166  }
167 
168 
169  // get leading truth jet eta phi
170  std::pair<float,float> leading_truth_eta_phi = get_leading_jet_eta_phi(topNode);
171  if(std::isnan(leading_truth_eta_phi.first) || std::isnan(leading_truth_eta_phi.second)){
172  std::cout << "RandomConeAna::process_event(PHCompositeNode *topNode) - leading truth jet eta phi is nan" << std::endl;
174  }
175 
176  // get pseudojets
177  std::vector<fastjet::PseudoJet> pseudojets = jets_to_pseudojets(inputs, false);
178  std::vector<fastjet::PseudoJet> iter_pseudojets = jets_to_pseudojets(iter_inputs, false);
179 
180  // get randomize eta phi pseudojets
181  std::vector<fastjet::PseudoJet> randomize_pseudojets = jets_to_pseudojets(inputs, true);
182  std::vector<fastjet::PseudoJet> randomize_iter_pseudojets = jets_to_pseudojets(iter_inputs, true);
183 
184 
185  // select random cone
186  float cone_eta = m_random->Uniform(-0.7, 0.7);
187  float cone_phi = m_random->Uniform(-M_PI, M_PI);
188  float cone_phi_avoid_lead_jet = 0;
189 
190  float dR_from_leading = 1.4;
191  float current_deta = cone_eta - leading_truth_eta_phi.first;
192  float test_phi;
193  while(true)
194  {
195  test_phi = m_random->Uniform(-M_PI, M_PI);
196  float test_dphi = test_phi - leading_truth_eta_phi.second;
197  if (test_dphi > M_PI) test_dphi -= 2 * M_PI;
198  if (test_dphi < -M_PI) test_dphi += 2 * M_PI;
199  float test_dr = sqrt((current_deta*current_deta) + (test_dphi*test_dphi));
200  if(test_dr > dR_from_leading)
201  {
202  cone_phi_avoid_lead_jet = test_phi;
203  break;
204  }
205  }
206 
207  // control cone
208  m_cone_nclustered = 0;
209  m_cone_pt_raw = 0;
210  for (unsigned int ipart = 0; ipart < pseudojets.size(); ++ipart)
211  {
212  // calculate the distance between the particle and the cone center
213  float deta = cone_eta - pseudojets[ipart].eta();
214  float dphi = cone_phi - pseudojets[ipart].phi_std();
215  if (dphi > M_PI) dphi -= 2 * M_PI;
216  if (dphi < -M_PI) dphi += 2 * M_PI;
217  float dr = sqrt(deta * deta + dphi * dphi);
218  if (dr <= 0.4)
219  {
220  m_cone_pt_raw += pseudojets[ipart].pt();
222  }
223  }
224 
225  // iter sub cone
226  m_cone_pt_iter_sub = 0;
227  for (unsigned int ipart = 0; ipart < iter_pseudojets.size(); ++ipart)
228  {
229  // calculate the distance between the particle and the cone center
230  float deta = cone_eta - iter_pseudojets[ipart].eta();
231  float dphi = cone_phi - iter_pseudojets[ipart].phi_std();
232  if (dphi > M_PI) dphi -= 2 * M_PI;
233  if (dphi < -M_PI) dphi += 2 * M_PI;
234  float dr = sqrt(deta * deta + dphi * dphi);
235  if (dr <= 0.4)
236  {
237  m_cone_pt_iter_sub += iter_pseudojets[ipart].pt();
238  }
239  }
240 
241  // randomize cone
243  for (unsigned int ipart = 0; ipart < randomize_pseudojets.size(); ++ipart)
244  {
245  // calculate the distance between the particle and the cone center
246  float deta = cone_eta - randomize_pseudojets[ipart].eta();
247  float dphi = cone_phi - randomize_pseudojets[ipart].phi_std();
248  if (dphi > M_PI) dphi -= 2 * M_PI;
249  if (dphi < -M_PI) dphi += 2 * M_PI;
250  float dr = sqrt(deta * deta + dphi * dphi);
251  if (dr <= 0.4)
252  {
253  m_randomized_cone_pt_raw += randomize_pseudojets[ipart].pt();
254  }
255  }
256 
257 
258  // randomize iter sub cone
260  for (unsigned int ipart = 0; ipart < randomize_iter_pseudojets.size(); ++ipart)
261  {
262  // calculate the distance between the particle and the cone center
263  float deta = cone_eta - randomize_iter_pseudojets[ipart].eta();
264  float dphi = cone_phi - randomize_iter_pseudojets[ipart].phi_std();
265  if (dphi > M_PI) dphi -= 2 * M_PI;
266  if (dphi < -M_PI) dphi += 2 * M_PI;
267  float dr = sqrt(deta * deta + dphi * dphi);
268  if (dr <= 0.4)
269  {
270  m_randomized_cone_pt_iter_sub += randomize_iter_pseudojets[ipart].pt();
271  }
272  }
273 
274 
275  // avoid leading jet cone
277  for (unsigned int ipart = 0; ipart < pseudojets.size(); ++ipart)
278  {
279  // calculate the distance between the particle and the cone center
280  float deta = cone_eta - pseudojets[ipart].eta();
281  float dphi = cone_phi_avoid_lead_jet - pseudojets[ipart].phi_std();
282  if (dphi > M_PI) dphi -= 2 * M_PI;
283  if (dphi < -M_PI) dphi += 2 * M_PI;
284  float dr = sqrt(deta * deta + dphi * dphi);
285  if (dr <= 0.4)
286  {
287  m_avoid_leading_cone_pt_raw += pseudojets[ipart].pt();
288  }
289  }
290 
291  // avoid leading jet iter sub cone
293  for (unsigned int ipart = 0; ipart < iter_pseudojets.size(); ++ipart)
294  {
295  // calculate the distance between the particle and the cone center
296  float deta = cone_eta - iter_pseudojets[ipart].eta();
297  float dphi = cone_phi_avoid_lead_jet - iter_pseudojets[ipart].phi_std();
298  if (dphi > M_PI) dphi -= 2 * M_PI;
299  if (dphi < -M_PI) dphi += 2 * M_PI;
300  float dr = sqrt(deta * deta + dphi * dphi);
301  if (dr <= 0.4)
302  {
303  m_avoid_leading_cone_pt_iter_sub += iter_pseudojets[ipart].pt();
304  }
305  }
306 
307  //==================================
308  // Fill tree
309  //==================================
310  m_tree->Fill();
311 
312 
314 }
315 
317 {
318  std::cout << "RandomConeAna::End - Output to " << m_outputfilename << std::endl;
319  // write tree to file
321  // m_tree->Write();
322  // write file to disk
324  std::cout << "RandomConeAna::End(PHCompositeNode *topNode) This is the End..." << std::endl;
326 }
327 
328 //===========================================================
329 // Event triggers
331 {
332  //==================================
333  // Event selection
334  //==================================
335  float m_event_leading_truth_pt = LeadingR04TruthJet(topNode);
337  {
338  if(m_event_leading_truth_pt < m_eventSelection.first) return false;
339  if(m_event_leading_truth_pt > m_eventSelection.second) return false;
340  }
341  return true;
342 }
343 
345 {
346 
347  // get truth jet nodes
348  JetMap *truthjets = findNode::getClass<JetMap>(topNode, "AntiKt_Truth_r04");
349  if(!truthjets)
350  {
351  std::cout << "JetTree::LeadingR04TruthJet(PHCompositeNode *topNode) Could not find truth jet nodes" << std::endl;
352  exit(-1);
353  }
354 
355  float leading_truth_pt = -1;
356  for(JetMap::Iter iter = truthjets->begin(); iter != truthjets->end(); ++iter){
357 
358  Jet *jet = iter->second;
359  if(jet->get_pt() > leading_truth_pt) leading_truth_pt = jet->get_pt();
360  }
361 
362  return leading_truth_pt;
363 
364 }
365 
366 //===========================================================
367 // Cent info
369 {
370  //==================================
371  // Get centrality info
372  //==================================
373  CentralityInfo* cent_node = findNode::getClass<CentralityInfo>(topNode, "CentralityInfo");
374  if (!cent_node)
375  {
376  std::cout << "RandomConeAna::process_event() ERROR: Can't find CentralityInfo" << std::endl;
377  exit(-1);
378  }
379  m_centrality = cent_node->get_centile(CentralityInfo::PROP::bimp);
380  return ;
381 }
382 
383 
384 std::vector<fastjet::PseudoJet> RandomConeAna::get_psuedojets(PHCompositeNode *topNode)
385 {
386  // get fastjet input from tower nodes
387  std::vector<fastjet::PseudoJet> calo_pseudojets;
388  for (auto & _input : _inputs)
389  {
390  std::vector<Jet *> parts = _input->get_input(topNode);
391  for (unsigned int i = 0; i < parts.size(); ++i)
392  {
393  auto& part = parts[i];
394  float this_e = part->get_e();
395  if (this_e == 0.) continue;
396  float this_px = parts[i]->get_px();
397  float this_py = parts[i]->get_py();
398  float this_pz = parts[i]->get_pz();
399  if (this_e < 0)
400  {
401  // make energy = +1 MeV for purposes of clustering
402  float e_ratio = 0.001 / this_e;
403  this_e = this_e * e_ratio;
404  this_px = this_px * e_ratio;
405  this_py = this_py * e_ratio;
406  this_pz = this_pz * e_ratio;
407  }
408  fastjet::PseudoJet pseudojet(this_px, this_py, this_pz, this_e);
409  calo_pseudojets.push_back(pseudojet);
410  }
411  for (auto &p : parts) delete p;
412 
413  }
414 
415  return calo_pseudojets;
416 }
417 
418 
420 {
421 
422  m_rho_mult = -1;
423  m_rho_area = -1;
424  //==================================
425  // Estimate rhos
426  //==================================s
427  // fastjet input
428  std::vector<fastjet::PseudoJet> calo_pseudojets = get_psuedojets(topNode);
429 
430  fastjet::AreaDefinition area_def(fastjet::active_area_explicit_ghosts,
431  fastjet::GhostedAreaSpec(1.5, 1, 0.01));
432  fastjet::JetDefinition jet_def(fastjet::kt_algorithm,
433  0.4,
435  fastjet::Best);
436  fastjet::Selector jet_eta_selector = fastjet::SelectorAbsEtaMax(1.1);
437  fastjet::Selector jet_pt_selector = fastjet::SelectorPtMin(1.0);
438  fastjet::Selector jet_selector = (jet_eta_selector && jet_pt_selector);
439  fastjet::Selector bkgd_selector = jet_selector * (!fastjet::SelectorNHardest(2));
440 
441 
442  // area rho
443  fastjet::JetMedianBackgroundEstimator bge {bkgd_selector, jet_def, area_def};
444  bge.set_particles(calo_pseudojets);
445  m_rho_area = bge.rho();
446  m_rho_area_sigma = bge.sigma();
447 
448 
449  // mult rho
450  fastjet::ClusterSequenceArea cs(calo_pseudojets, jet_def, area_def);
451  std::vector<fastjet::PseudoJet> jets = fastjet::sorted_by_pt( bkgd_selector( cs.inclusive_jets(1.0) ) );
452  fastjet::Selector not_pure_ghost = !fastjet::SelectorIsPureGhost();
453 
454  std::vector<float> pt_over_nConstituents;
455  int nfj_jets = 0;
456  int n_empty_jets = 0;
457  float total_constituents = 0;
458  for (auto jet : jets) {
459  float jet_pt = jet.pt();
460  std::vector<fastjet::PseudoJet> constituents = not_pure_ghost(jet.constituents());
461  int jet_size = constituents.size();
462  total_constituents += jet_size;
463  if(jet_size == 0){
464  n_empty_jets++;
465  continue; // only consider jets with constituents
466  }
467  pt_over_nConstituents.push_back(jet_pt/jet_size);
468  nfj_jets++;
469  }
470 
471  int total_jets = nfj_jets + n_empty_jets;
472  float mean_pT = total_constituents/total_jets;
473  if (mean_pT < 0) mean_pT = 0;
474 
475  float med_tmp, std_tmp;
476  _median_stddev(pt_over_nConstituents, n_empty_jets, med_tmp, std_tmp);
477  m_rho_mult_sigma = std_tmp*sqrt(mean_pT);
478  m_rho_mult = med_tmp;
479 
480  return;
481 }
482 
483 float RandomConeAna::_percentile(const std::vector<float> & sorted_vec,
484  const float percentile,
485  const float nempty) const
486 {
487  assert(percentile >= 0. && percentile <= 1.);
488 
489  int njets = sorted_vec.size();
490  if(njets == 0) return 0;
491 
492  float total_njets = njets + nempty;
493  float perc_pos = (total_njets)*percentile - nempty - 0.5;
494 
495  float result;
496  if(perc_pos >= 0 && njets > 1){
497  int pindex = int(perc_pos);
498  // avoid out of range
499  if(pindex + 1 > njets-1){
500  pindex = njets-2;
501  perc_pos = njets - 1;
502  }
503 
504  result = sorted_vec.at(pindex)*(pindex+1-perc_pos)
505  + sorted_vec.at(pindex+1)*(perc_pos-pindex);
506  }
507  else if(perc_pos > -0.5 && njets >=1){
508  result = sorted_vec.at(0);
509  }
510  else{
511  result = 0;
512  }
513 
514  return result;
515 
516 }
517 
518 void RandomConeAna::_median_stddev(const std::vector<float> & vec,
519  float n_empty_jets,
520  float & median,
521  float & std_dev) const
522 {
523  if(vec.size() == 0){
524  median = 0;
525  std_dev = 0;
526  return;
527  }
528 
529  std::vector<float> sorted_vec = vec;
530  std::sort(sorted_vec.begin(), sorted_vec.end());
531 
532  int njets = sorted_vec.size();
533  if(n_empty_jets > njets/4.0){
534  std::cout << "WARNING: n_empty_jets = " << n_empty_jets << " is too large, setting to " << njets/4.0 << std::endl;
535  n_empty_jets = njets/4.0;
536  }
537 
538 
539  float posn[2] = {0.5, (1.0-0.6827)/2.0};
540  float res[2];
541  for (int i = 0; i < 2; i++) {
542  res[i] = _percentile(sorted_vec, posn[i], n_empty_jets);
543  }
544 
545  median = res[0];
546  std_dev = res[0] - res[1];
547 
548 }
549 
551 {
552 
553  JetMap *truthjets = findNode::getClass<JetMap>(topNode, "AntiKt_Truth_r04");
554  if(!truthjets)
555  {
556  std::cout << "JetTree::LeadingR04TruthJet(PHCompositeNode *topNode) Could not find truth jet nodes" << std::endl;
557  exit(-1);
558  }
559 
560  float leading_truth_pt = -1;
561  float leading_truth_eta = NAN;
562  float leading_truth_phi = NAN;
563  for(JetMap::Iter iter = truthjets->begin(); iter != truthjets->end(); ++iter){
564 
565  Jet *jet = iter->second;
566  if(jet->get_pt() > leading_truth_pt)
567  {
568  leading_truth_pt = jet->get_pt();
569  leading_truth_eta = jet->get_eta();
570  leading_truth_phi = jet->get_phi();
571  }
572 
573  }
574 
575  return std::make_pair(leading_truth_eta, leading_truth_phi);
576 
577 }
578 
579 std::vector<fastjet::PseudoJet> RandomConeAna::jets_to_pseudojets(std::vector<Jet*>& particles, bool randomize_etaphi)
580 {
581 
582  std::vector<fastjet::PseudoJet> pseudojets;
583  for (unsigned int ipart = 0; ipart < particles.size(); ++ipart)
584  {
585  if (!std::isfinite(particles[ipart]->get_px()) ||
586  !std::isfinite(particles[ipart]->get_py()) ||
587  !std::isfinite(particles[ipart]->get_pz()) ||
588  !std::isfinite(particles[ipart]->get_e()))
589  {
590  std::cout << PHWHERE << " invalid particle kinematics:"
591  << " px: " << particles[ipart]->get_px()
592  << " py: " << particles[ipart]->get_py()
593  << " pz: " << particles[ipart]->get_pz()
594  << " e: " << particles[ipart]->get_e() << std::endl;
595  exit(-1);
596  }
597 
598  fastjet::PseudoJet pseudojet(particles[ipart]->get_px(),
599  particles[ipart]->get_py(),
600  particles[ipart]->get_pz(),
601  particles[ipart]->get_e());
602 
603  // do eta cuts
604  if(pseudojet.eta() < -0.7 || pseudojet.eta() > 0.7) continue;
605  if(randomize_etaphi){
606 
607  // randomize eta phi within acceptance
608  float eta = m_random->Uniform(-0.7, 0.7);
609  float phi = m_random->Uniform(-M_PI, M_PI);
610 
611  float E = pseudojet.e();
612  float pT = E/cosh(eta);
613  float px = pT * cos(phi);
614  float py = pT * sin(phi);
615  float pz = pT * sinh(eta);
616  pseudojet.reset(px, py, pz, E);
617 
618  }
619 
620  // do this after so the randomization is not affected
621  if (particles[ipart]->get_e() == 0.) continue;
622 
623  pseudojet.set_user_index(ipart);
624  pseudojets.push_back(pseudojet);
625 
626  }
627 
628  return pseudojets;
629 }
630 
631 
632 
633 
634 
635 
636