File indexing completed on 2025-07-15 08:16:16
0001
0002
0003
0004
0005 #include "UndoAfterBurner.h"
0006
0007 #include <Math/GenVector/Boost.h>
0008 #include <Math/GenVector/Cartesian3D.h>
0009 #include <Math/GenVector/LorentzVector.h>
0010 #include <Math/GenVector/PxPyPzE4D.h>
0011 #include <Math/GenVector/RotationX.h>
0012 #include <Math/GenVector/RotationY.h>
0013 #include <Math/Vector4Dfwd.h>
0014 #include <TMath.h>
0015 #include <edm4hep/Vector3d.h>
0016 #include <gsl/pointers>
0017
0018 #include "algorithms/reco/Beam.h"
0019 #include "algorithms/reco/UndoAfterBurnerConfig.h"
0020
0021 void eicrecon::UndoAfterBurner::init() {}
0022
0023 void eicrecon::UndoAfterBurner::process(const UndoAfterBurner::Input& input,
0024 const UndoAfterBurner::Output& output) const {
0025
0026 const auto [mcparts] = input;
0027 auto [outputParticles] = output;
0028
0029 bool pidAssumePionMass = m_cfg.m_pid_assume_pion_mass;
0030 double crossingAngle = m_cfg.m_crossing_angle;
0031 bool correctBeamFX = m_cfg.m_correct_beam_FX;
0032 bool pidUseMCTruth = m_cfg.m_pid_use_MC_truth;
0033
0034 bool hasBeamHadron = true;
0035 bool hasBeamLepton = true;
0036
0037
0038
0039
0040 ROOT::Math::PxPyPzEVector e_beam(0., 0., 0., 0.);
0041 ROOT::Math::PxPyPzEVector h_beam(0., 0., 0., 0.);
0042
0043 auto incoming_lepton = find_first_beam_electron(mcparts);
0044 if (incoming_lepton.empty()) {
0045 debug("No beam electron found -- particleGun input");
0046 hasBeamLepton = false;
0047 }
0048
0049 auto incoming_hadron = find_first_beam_hadron(mcparts);
0050 if (incoming_hadron.empty()) {
0051 debug("No beam hadron found -- particleGun input");
0052 hasBeamHadron = false;
0053 }
0054
0055 if ((hasBeamHadron && !hasBeamLepton) || (!hasBeamHadron && hasBeamLepton)) {
0056 debug("Only one beam defined! Not a possible configuration!");
0057 return;
0058 }
0059
0060
0061 if (!hasBeamHadron || !hasBeamLepton) {
0062 for (const auto& p : *mcparts) {
0063 if ((p.getPDG() == 2212 || p.getPDG() == 2112)) {
0064 hasBeamHadron = true;
0065 h_beam.SetPxPyPzE(crossingAngle * p.getEnergy(), 0.0, p.getEnergy(), p.getEnergy());
0066 if (p.getEnergy() > 270.0 && p.getEnergy() < 280.0) {
0067 hasBeamLepton = true;
0068 e_beam.SetPxPyPzE(0.0, 0.0, -18.0, 18.0);
0069 }
0070 }
0071 }
0072
0073 } else {
0074
0075 if (correctBeamFX) {
0076
0077 h_beam.SetPxPyPzE(incoming_hadron[0].getMomentum().x, incoming_hadron[0].getMomentum().y,
0078 incoming_hadron[0].getMomentum().z, incoming_hadron[0].getEnergy());
0079 e_beam.SetPxPyPzE(incoming_lepton[0].getMomentum().x, incoming_lepton[0].getMomentum().y,
0080 incoming_lepton[0].getMomentum().z, incoming_lepton[0].getEnergy());
0081
0082 } else {
0083
0084 h_beam.SetPxPyPzE(crossingAngle * incoming_hadron[0].getEnergy(), 0.0,
0085 incoming_hadron[0].getEnergy(), incoming_hadron[0].getEnergy());
0086 e_beam.SetPxPyPzE(0.0, 0.0, -incoming_lepton[0].getEnergy(), incoming_lepton[0].getEnergy());
0087 }
0088 }
0089
0090
0091 if (!hasBeamHadron && !hasBeamLepton) {
0092 return;
0093 }
0094
0095
0096 ROOT::Math::PxPyPzEVector cm_frame_boost = e_beam + h_beam;
0097 ROOT::Math::Cartesian3D beta(-cm_frame_boost.Px() / cm_frame_boost.E(),
0098 -cm_frame_boost.Py() / cm_frame_boost.E(),
0099 -cm_frame_boost.Pz() / cm_frame_boost.E());
0100 ROOT::Math::Boost boostVector(beta);
0101
0102
0103 e_beam = boostVector(e_beam);
0104 h_beam = boostVector(h_beam);
0105
0106 double rotationAngleY = -1.0 * TMath::ATan2(h_beam.Px(), h_beam.Pz());
0107 double rotationAngleX = 1.0 * TMath::ATan2(h_beam.Py(), h_beam.Pz());
0108
0109 ROOT::Math::RotationY rotationAboutY(rotationAngleY);
0110 ROOT::Math::RotationX rotationAboutX(rotationAngleX);
0111
0112
0113 ROOT::Math::PxPyPzEVector head_on_frame_boost(0., 0., cm_frame_boost.Pz(), cm_frame_boost.E());
0114 ROOT::Math::Boost headOnBoostVector(head_on_frame_boost.Px() / head_on_frame_boost.E(),
0115 head_on_frame_boost.Py() / head_on_frame_boost.E(),
0116 head_on_frame_boost.Pz() / head_on_frame_boost.E());
0117
0118
0119 for (const auto& p : *mcparts) {
0120 if (p.isCreatedInSimulation()) {
0121 continue;
0122 }
0123
0124 ROOT::Math::PxPyPzEVector mc(p.getMomentum().x, p.getMomentum().y, p.getMomentum().z,
0125 p.getEnergy());
0126
0127 mc = boostVector(mc);
0128 mc = rotationAboutY(mc);
0129 mc = rotationAboutX(mc);
0130 mc = headOnBoostVector(mc);
0131
0132 decltype(edm4hep::MCParticleData::momentum) mcMom(mc.Px(), mc.Py(), mc.Pz());
0133 edm4hep::MutableMCParticle MCTrack(p.clone());
0134 MCTrack.setMomentum(mcMom);
0135
0136 if (pidUseMCTruth) {
0137 MCTrack.setPDG(p.getPDG());
0138 MCTrack.setMass(p.getMass());
0139 }
0140 if (!pidUseMCTruth && pidAssumePionMass) {
0141 MCTrack.setPDG(211);
0142 MCTrack.setMass(0.13957);
0143 }
0144
0145 outputParticles->push_back(MCTrack);
0146 }
0147 }