File indexing completed on 2025-08-06 08:14:20
0001 #include "RandomConeReco.h"
0002 #include "RandomCone.h"
0003 #include "RandomConev1.h"
0004
0005
0006 #include <fun4all/Fun4AllReturnCodes.h>
0007 #include <fun4all/SubsysReco.h>
0008
0009
0010 #include <jetbase/Jet.h>
0011 #include <jetbase/Jetv2.h>
0012 #include <jetbase/JetMap.h>
0013 #include <jetbase/JetMapv1.h>
0014 #include <jetbase/JetInput.h>
0015 #include <jetbase/JetContainer.h>
0016 #include <jetbase/JetContainerv1.h>
0017
0018
0019 #include <phool/PHCompositeNode.h>
0020 #include <phool/PHIODataNode.h>
0021 #include <phool/PHNode.h>
0022 #include <phool/PHNodeIterator.h>
0023 #include <phool/PHObject.h>
0024 #include <phool/getClass.h>
0025 #include <phool/phool.h>
0026
0027
0028 #include <fastjet/Selector.hh>
0029 #include <fastjet/ClusterSequence.hh>
0030 #include <fastjet/JetDefinition.hh>
0031 #include <fastjet/PseudoJet.hh>
0032
0033
0034 #include <TRandom3.h>
0035 #include <TTimeStamp.h>
0036
0037
0038 #include <cstdlib>
0039 #include <iostream>
0040 #include <vector>
0041 #include <string>
0042 #include <cmath>
0043 #include <algorithm>
0044
0045
0046
0047 RandomConeReco::RandomConeReco(const std::string &name)
0048 : SubsysReco(name)
0049
0050 , m_do_basic_reconstruction(true)
0051 , m_do_randomize_etaphi_of_inputs(false)
0052 , m_do_avoid_leading_jet(false)
0053 {
0054 }
0055
0056 RandomConeReco::~RandomConeReco()
0057 {
0058
0059 for (auto & _input : m_inputs) { delete _input; }
0060 m_inputs.clear();
0061
0062 if(m_random) delete m_random;
0063
0064 }
0065
0066 int RandomConeReco::Init(PHCompositeNode *topNode)
0067 {
0068
0069 std::cout << " RandomConeReco::InitRun - " << Name() << " - initialized" << std::endl;
0070
0071
0072 if(m_seed == 0)
0073 {
0074 TTimeStamp *t = new TTimeStamp();
0075 m_seed = static_cast<unsigned int>(t->GetNanoSec());
0076 delete t;
0077 }
0078
0079
0080 m_random = new TRandom3(m_seed);
0081
0082
0083 if(m_cone_max_abs_eta == 5.0)
0084 {
0085 m_cone_max_abs_eta = m_input_max_abs_eta - m_R;
0086 }
0087
0088
0089
0090
0091 std::string r_string = "r";
0092 if(m_R < 1.0) r_string += "0";
0093 r_string += std::to_string(static_cast<int>(m_R*10));
0094
0095 if(m_do_basic_reconstruction){ m_output_basic_node = m_output_node_name + "_basic_" + r_string; }
0096 if(m_do_randomize_etaphi_of_inputs){ m_output_randomize_etaphi_node = m_output_node_name + "_randomize_etaphi_" + r_string; }
0097 if(m_do_avoid_leading_jet){ m_output_avoid_leading_jet_node = m_output_node_name + "_avoid_lead_jet_" + r_string; }
0098
0099
0100 if(m_do_avoid_leading_jet)
0101 {
0102 if(m_lead_jet_dR == 5.0)
0103 {
0104 m_lead_jet_dR = 1.0 + m_R;
0105 }
0106 }
0107
0108
0109 if(Verbosity() > 0) print_settings(std::cout);
0110
0111
0112 return CreateNode(topNode);
0113
0114 }
0115
0116
0117
0118 int RandomConeReco::process_event(PHCompositeNode *topNode)
0119 {
0120
0121
0122
0123
0124
0125
0126 std::vector<Jet *> particles;
0127 for (auto & _input : m_inputs)
0128 {
0129 std::vector<Jet *> parts = _input->get_input(topNode);
0130 for (auto &part : parts)
0131 {
0132 particles.push_back(part);
0133 particles.back()->set_id(particles.size() - 1);
0134 }
0135 }
0136
0137
0138 float cone_eta = NAN;
0139 float cone_phi = NAN;
0140 GetConeAxis(topNode, cone_eta, cone_phi, false);
0141
0142
0143 std::vector<fastjet::PseudoJet> pseudojets = JetsToPseudojets(particles, false);
0144
0145 if(m_do_basic_reconstruction)
0146 {
0147
0148 RandomCone * basic_reco = findNode::getClass<RandomConev1>(topNode, m_output_basic_node);
0149 if (!basic_reco)
0150 {
0151 std::cout << PHWHERE << "Can't find RandomCone node " << m_output_basic_node << std::endl;
0152 exit(-1);
0153 }
0154
0155 basic_reco->Reset();
0156 basic_reco->set_eta(cone_eta);
0157 basic_reco->set_phi(cone_phi);
0158 basic_reco->set_R(m_R);
0159 basic_reco->set_cone_type(RandomCone::ConeType::BASIC);
0160
0161
0162 for (auto &pseudojet : pseudojets)
0163 {
0164 float deta = pseudojet.eta() - cone_eta;
0165 float dphi = pseudojet.phi_std() - cone_phi;
0166 if(dphi > M_PI) dphi -= 2*M_PI;
0167 if(dphi < -M_PI) dphi += 2*M_PI;
0168
0169 float dR = std::sqrt(deta*deta + dphi*dphi);
0170 if(dR < m_R)
0171 {
0172 basic_reco->add_constituent(particles[pseudojet.user_index()]);
0173 }
0174
0175 }
0176
0177
0178
0179 }
0180
0181 if(m_do_avoid_leading_jet)
0182 {
0183 float cone_lead_jet_eta = NAN;
0184 float cone_lead_jet_phi = NAN;
0185 GetConeAxis(topNode, cone_lead_jet_eta, cone_lead_jet_phi, true);
0186
0187
0188 RandomCone * avoid_leading_jet = findNode::getClass<RandomConev1>(topNode, m_output_avoid_leading_jet_node);
0189 if (!avoid_leading_jet)
0190 {
0191 std::cout << PHWHERE << "Can't find RandomCone node " << m_output_avoid_leading_jet_node << std::endl;
0192 exit(-1);
0193 }
0194
0195 avoid_leading_jet->Reset();
0196 avoid_leading_jet->set_eta(cone_lead_jet_eta);
0197 avoid_leading_jet->set_phi(cone_lead_jet_phi);
0198 avoid_leading_jet->set_R(m_R);
0199 avoid_leading_jet->set_cone_type(RandomCone::ConeType::AVOID_LEAD_JET);
0200
0201
0202 for (auto &pseudojet : pseudojets)
0203 {
0204
0205 float deta = pseudojet.eta() - cone_lead_jet_eta;
0206 float dphi = pseudojet.phi_std() - cone_lead_jet_phi;
0207 if(dphi > M_PI) dphi -= 2*M_PI;
0208 if(dphi < -M_PI) dphi += 2*M_PI;
0209
0210 float dR = std::sqrt(deta*deta + dphi*dphi);
0211 if(dR < m_R)
0212 {
0213 avoid_leading_jet->add_constituent(particles[pseudojet.user_index()]);
0214 }
0215
0216 }
0217
0218
0219
0220 }
0221
0222 if(m_do_randomize_etaphi_of_inputs)
0223 {
0224
0225 std::vector<fastjet::PseudoJet> randomize_pseudojets = JetsToPseudojets(particles, true);
0226
0227
0228 RandomCone * randomize_etaphi = findNode::getClass<RandomConev1>(topNode, m_output_randomize_etaphi_node);
0229 if (!randomize_etaphi)
0230 {
0231 std::cout << PHWHERE << "Can't find RandomCone node " << m_output_randomize_etaphi_node << std::endl;
0232 exit(-1);
0233 }
0234
0235 randomize_etaphi->Reset();
0236 randomize_etaphi->set_eta(cone_eta);
0237 randomize_etaphi->set_phi(cone_phi);
0238 randomize_etaphi->set_R(m_R);
0239 randomize_etaphi->set_cone_type(RandomCone::ConeType::RANDOMIZE_INPUT_ETAPHI);
0240
0241
0242 for (auto &pseudojet : randomize_pseudojets)
0243 {
0244 float deta = pseudojet.eta() - cone_eta;
0245 float dphi = pseudojet.phi_std() - cone_phi;
0246 if(dphi > M_PI) dphi -= 2*M_PI;
0247 if(dphi < -M_PI) dphi += 2*M_PI;
0248
0249 float dR = std::sqrt(deta*deta + dphi*dphi);
0250 if(dR < m_R)
0251 {
0252 randomize_etaphi->add_constituent(particles[pseudojet.user_index()]);
0253 }
0254 }
0255
0256
0257
0258 }
0259
0260
0261 for (auto &part : particles) delete part;
0262 particles.clear();
0263
0264 return Fun4AllReturnCodes::EVENT_OK;
0265
0266 }
0267
0268 int RandomConeReco::CreateNode(PHCompositeNode *topNode)
0269 {
0270 PHNodeIterator iter(topNode);
0271
0272
0273 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0274 if (!dstNode)
0275 {
0276 std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0277 return Fun4AllReturnCodes::ABORTRUN;
0278 }
0279
0280
0281 PHCompositeNode *coneNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RANDOMCONE"));
0282 if (!coneNode)
0283 {
0284 coneNode = new PHCompositeNode("RANDOMCONE");
0285 dstNode->addNode(coneNode);
0286 }
0287
0288
0289 if(m_do_basic_reconstruction)
0290 {
0291 RandomCone *basic_reco = new RandomConev1();
0292 PHIODataNode<PHObject> *node = new PHIODataNode<PHObject>(basic_reco, m_output_basic_node, "PHObject");
0293 coneNode->addNode(node);
0294 }
0295
0296 if(m_do_randomize_etaphi_of_inputs)
0297 {
0298 RandomCone *randomize_etaphi = new RandomConev1();
0299 PHIODataNode<PHObject> *node = new PHIODataNode<PHObject>(randomize_etaphi, m_output_randomize_etaphi_node, "PHObject");
0300 coneNode->addNode(node);
0301 }
0302
0303 if(m_do_avoid_leading_jet)
0304 {
0305 RandomCone *avoid_leading_jet = new RandomConev1();
0306 PHIODataNode<PHObject> *node = new PHIODataNode<PHObject>(avoid_leading_jet, m_output_avoid_leading_jet_node, "PHObject");
0307 coneNode->addNode(node);
0308 }
0309
0310 return Fun4AllReturnCodes::EVENT_OK;
0311 }
0312
0313
0314 Jet * RandomConeReco::GetLeadJet(PHCompositeNode *topNode)
0315 {
0316
0317 if(m_leading_jet_from_inputs)
0318 {
0319
0320
0321 std::vector<Jet *> particles;
0322 for (auto & _input : m_inputs)
0323 {
0324 std::vector<Jet *> parts = _input->get_input(topNode);
0325 for (auto &part : parts)
0326 {
0327 particles.push_back(part);
0328 particles.back()->set_id(particles.size() - 1);
0329 }
0330 }
0331
0332
0333
0334 std::vector<fastjet::PseudoJet> pseudojets;
0335 for (unsigned int ipart = 0; ipart < particles.size(); ++ipart)
0336 {
0337
0338
0339 if (!std::isfinite(particles[ipart]->get_px()) ||
0340 !std::isfinite(particles[ipart]->get_py()) ||
0341 !std::isfinite(particles[ipart]->get_pz()) ||
0342 !std::isfinite(particles[ipart]->get_e()))
0343 {
0344 std::cout << PHWHERE << " invalid particle kinematics:"
0345 << " px: " << particles[ipart]->get_px()
0346 << " py: " << particles[ipart]->get_py()
0347 << " pz: " << particles[ipart]->get_pz()
0348 << " e: " << particles[ipart]->get_e() << std::endl;
0349
0350 exit(-1);
0351 }
0352
0353 float this_e = particles[ipart]->get_e();
0354 if (this_e == 0.) continue;
0355 float this_px = particles[ipart]->get_px();
0356 float this_py = particles[ipart]->get_py();
0357 float this_pz = particles[ipart]->get_pz();
0358
0359
0360 if(this_e < 0)
0361 {
0362
0363 float e_ratio = 0.001 / this_e;
0364 this_e = this_e * e_ratio;
0365 this_px = this_px * e_ratio;
0366 this_py = this_py * e_ratio;
0367 this_pz = this_pz * e_ratio;
0368 }
0369
0370
0371 fastjet::PseudoJet pseudojet(this_px, this_py, this_pz, this_e);
0372
0373
0374 if (fabs(pseudojet.eta()) > m_input_max_abs_eta) continue;
0375
0376
0377
0378 if (pseudojet.perp() < m_input_min_pT) continue;
0379
0380 pseudojet.set_user_index(ipart);
0381 pseudojets.push_back(pseudojet);
0382
0383
0384 }
0385
0386
0387 fastjet::JetDefinition jet_def(fastjet::kt_algorithm, m_R, fastjet::E_scheme, fastjet::Best);
0388 fastjet::ClusterSequence cs(pseudojets, jet_def);
0389
0390
0391 fastjet::Selector jet_selector = (
0392 (fastjet::SelectorNHardest(1)) *
0393 ( fastjet::SelectorAbsEtaMax(m_cone_max_abs_eta) &&
0394 fastjet::SelectorPtMin(m_lead_jet_pT_threshold))
0395 );
0396
0397
0398 std::vector<fastjet::PseudoJet> jets = fastjet::sorted_by_pt(jet_selector(cs.inclusive_jets()));
0399
0400 if(jets.size() == 0)
0401 {
0402 std::cout << "RandomConeAna::GetLeadJetKinematics(PHCompositeNode *topNode) - Could not find leading jet above threshold" << std::endl;
0403 return nullptr;
0404 }
0405
0406
0407 fastjet::PseudoJet lead_jet = jets.at(0);
0408
0409
0410 std::vector<fastjet::PseudoJet> constituents = lead_jet.constituents();
0411
0412
0413 auto jet = new Jetv2();
0414 jet->set_px(lead_jet.px());
0415 jet->set_py(lead_jet.py());
0416 jet->set_pz(lead_jet.pz());
0417 jet->set_e(lead_jet.e());
0418 jet->set_id(0);
0419
0420
0421 for (auto & particle : particles) delete particle;
0422 particles.clear();
0423
0424 return jet;
0425 }
0426 else if(m_leading_jet_from_jetmap)
0427 {
0428
0429 JetMap *jetmap = findNode::getClass<JetMap>(topNode, m_leading_jet_node_name);
0430 if(!jetmap)
0431 {
0432 std::cout << "RandomConeAna::GetLeadJetKinematics(PHCompositeNode *topNode) Could not find jet map node" << std::endl;
0433 exit(-1);
0434 }
0435
0436
0437 float lead_pt = -1;
0438 unsigned int lead_id = 0;
0439
0440 for(JetMap::Iter iter = jetmap->begin(); iter != jetmap->end(); ++iter)
0441 {
0442 Jet *jet = iter->second;
0443 if(jet->get_pt() > lead_pt)
0444 {
0445 lead_pt = jet->get_pt();
0446 lead_id = jet->get_id();
0447 }
0448 }
0449
0450 if(lead_pt < m_lead_jet_pT_threshold)
0451 {
0452 std::cout << "RandomConeAna::GetLeadJetKinematics(PHCompositeNode *topNode) Could not find leading jet above threshold" << std::endl;
0453 return nullptr;
0454 }
0455
0456
0457 auto jetv1 = jetmap->get(lead_id);
0458
0459
0460 auto jet = new Jetv2();
0461 jet->set_px(jetv1->get_px());
0462 jet->set_py(jetv1->get_py());
0463 jet->set_pz(jetv1->get_pz());
0464 jet->set_e(jetv1->get_e());
0465 jet->set_id(jetv1->get_id());
0466
0467 }
0468 else if(m_leading_jet_from_jetcont)
0469 {
0470
0471 JetContainer *jetcont = findNode::getClass<JetContainer>(topNode, m_leading_jet_node_name);
0472 if(!jetcont)
0473 {
0474 std::cout << "RandomConeAna::GetLeadJetKinematics(PHCompositeNode *topNode) Could not find jet container node" << std::endl;
0475 exit(-1);
0476 }
0477
0478
0479 float lead_pt = -1;
0480 unsigned int lead_id = 0;
0481 unsigned int n_ijets_in_event = jetcont->size();
0482 for (unsigned int ijet = 0; ijet<=n_ijets_in_event; ++ijet)
0483 {
0484 Jet *jet = jetcont->get_jet(ijet);
0485 if(jet->get_pt() > lead_pt)
0486 {
0487 lead_pt = jet->get_pt();
0488 lead_id = jet->get_id();
0489 }
0490
0491 }
0492
0493 if(lead_pt < m_lead_jet_pT_threshold)
0494 {
0495 std::cout << "RandomConeAna::GetLeadJetKinematics(PHCompositeNode *topNode) Could not find leading jet above threshold" << std::endl;
0496 return nullptr;
0497 }
0498
0499
0500 auto jet = jetcont->get_jet(lead_id);
0501
0502 return jet;
0503 }
0504
0505
0506 return nullptr;
0507
0508 }
0509
0510 void RandomConeReco::GetConeAxis(PHCompositeNode *topNode,float &cone_eta, float &cone_phi, bool avoid_lead_jet)
0511 {
0512 if(avoid_lead_jet)
0513 {
0514 Jet *lead_jet = GetLeadJet(topNode);
0515 if(lead_jet == nullptr)
0516 {
0517 std::cout << "RandomConeAna::GetConeAxis(PHCompositeNode *topNode) - Could not find leading jet." << std::endl;
0518 std::cout << "RandomConeAna::GetConeAxis(PHCompositeNode *topNode) - Disabling avoid leading jet mode for this event" << std::endl;
0519
0520 cone_eta = m_random->Uniform(-m_cone_max_abs_eta, m_cone_max_abs_eta);
0521 cone_phi = m_random->Uniform(-M_PI, M_PI);
0522 return;
0523 }
0524
0525
0526 float jet_eta = lead_jet->get_eta();
0527 float jet_phi = lead_jet->get_phi();
0528
0529 while(true)
0530 {
0531
0532 float dphi = m_random->Uniform(m_lead_jet_dR, 2*M_PI - m_lead_jet_dR);
0533 cone_phi = jet_phi + dphi;
0534 if(cone_phi > M_PI) cone_phi -= 2*M_PI;
0535 if(cone_phi < -M_PI) cone_phi += 2*M_PI;
0536
0537 cone_eta = m_random->Uniform(-m_cone_max_abs_eta, m_cone_max_abs_eta);
0538
0539 float deta = cone_eta - jet_eta;
0540 float dR = std::sqrt(deta*deta + dphi*dphi);
0541 if(dR > m_lead_jet_dR) break;
0542 }
0543
0544
0545 }
0546 else
0547 {
0548 cone_eta = m_random->Uniform(-m_cone_max_abs_eta, m_cone_max_abs_eta);
0549 cone_phi = m_random->Uniform(-M_PI, M_PI);
0550 }
0551
0552 return;
0553 }
0554
0555 std::vector<fastjet::PseudoJet> RandomConeReco::JetsToPseudojets(const std::vector<Jet *> &particles, bool randomize_etaphi)
0556 {
0557
0558
0559 std::vector<fastjet::PseudoJet> pseudojets;
0560
0561
0562 for (unsigned int ipart = 0; ipart < particles.size(); ++ipart)
0563 {
0564
0565
0566 if (!std::isfinite(particles[ipart]->get_px()) ||
0567 !std::isfinite(particles[ipart]->get_py()) ||
0568 !std::isfinite(particles[ipart]->get_pz()) ||
0569 !std::isfinite(particles[ipart]->get_e()))
0570 {
0571 std::cout << PHWHERE << " invalid particle kinematics:"
0572 << " px: " << particles[ipart]->get_px()
0573 << " py: " << particles[ipart]->get_py()
0574 << " pz: " << particles[ipart]->get_pz()
0575 << " e: " << particles[ipart]->get_e() << std::endl;
0576
0577 exit(-1);
0578 }
0579
0580 float this_e = particles[ipart]->get_e();
0581
0582 float this_px = particles[ipart]->get_px();
0583 float this_py = particles[ipart]->get_py();
0584 float this_pz = particles[ipart]->get_pz();
0585
0586
0587 if(m_do_tower_cut)
0588 {
0589 if(this_e < m_tower_threshold) continue;
0590 if(this_e < 0)
0591 {
0592
0593 float e_ratio = 0.001 / this_e;
0594 this_e = this_e * e_ratio;
0595 this_px = this_px * e_ratio;
0596 this_py = this_py * e_ratio;
0597 this_pz = this_pz * e_ratio;
0598 }
0599
0600 }
0601
0602
0603 fastjet::PseudoJet pseudojet(this_px, this_py, this_pz, this_e);
0604
0605
0606 if (fabs(pseudojet.eta()) > m_input_max_abs_eta) continue;
0607
0608
0609
0610
0611
0612
0613 if(randomize_etaphi)
0614 {
0615 float eta = m_random->Uniform(-m_input_max_abs_eta, m_input_max_abs_eta);
0616 float phi = m_random->Uniform(-M_PI, M_PI);
0617
0618 float E = pseudojet.E();
0619 float pT = pseudojet.perp();
0620
0621 float px = pT * cos(phi);
0622 float py = pT * sin(phi);
0623 float pz = pT * sinh(eta);
0624
0625 pseudojet.reset(px, py, pz, E);
0626 }
0627
0628 pseudojet.set_user_index(ipart);
0629 pseudojets.push_back(pseudojet);
0630 }
0631
0632
0633
0634
0635 return pseudojets;
0636 }
0637
0638 void RandomConeReco::print_settings(std::ostream& os) const
0639 {
0640
0641 os << "RandomConeReco settings: " << std::endl;
0642 os << " - Random seed: " << m_seed << std::endl;
0643 os << " - Cone radius: " << m_R << std::endl;
0644 os << " - Inputs: " ;
0645 for (auto & _input : m_inputs) {_input->identify(os); }
0646 os << std::endl;
0647 os << " - Min input pT: " << m_input_min_pT << std::endl;
0648 os << " - Max input |eta|: " << m_input_max_abs_eta << std::endl;
0649 os << " - Cone max |eta|: " << m_cone_max_abs_eta << std::endl;
0650 if(!std::isnan(m_tower_threshold)) os << " - Tower threshold: " << m_tower_threshold << std::endl;
0651
0652 if(m_do_avoid_leading_jet)
0653 {
0654 os << " - Avoid leading jet: true" << std::endl;
0655 if(m_leading_jet_from_inputs) os << " - - Leading jet from inputs" << std::endl;
0656 else
0657 {
0658 os << " - - Leading jet from JetMap or JetContainer" << std::endl;
0659 os << " - - Node name: " << m_leading_jet_node_name << std::endl;
0660 }
0661 os << " - dR between leading jet and random cone: " << m_lead_jet_dR << std::endl;
0662 os << " - output node name: " << m_output_avoid_leading_jet_node << std::endl;
0663 }
0664 else
0665 {
0666 os << " - Avoid leading jet: false" << std::endl;
0667 }
0668
0669 if(m_do_randomize_etaphi_of_inputs)
0670 {
0671 os << " - Randomize eta, phi of inputs: true" << std::endl;
0672 os << " - output node name: " << m_output_randomize_etaphi_node << std::endl;
0673 }
0674 else
0675 {
0676 os << " - Randomize eta, phi of inputs: false" << std::endl;
0677 }
0678
0679 if(m_do_basic_reconstruction)
0680 {
0681 os << " - Basic reconstruction: true" << std::endl;
0682 os << " - output node name: " << m_output_basic_node << std::endl;
0683 }
0684 else
0685 {
0686 os << " - Basic reconstruction: false" << std::endl;
0687 }
0688
0689 os << "===============================" << std::endl;
0690
0691 return;
0692
0693 }
0694