diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx index 7b3a631a763f4767601482dd8fb1ab19892314b2..468a6739bdd9606cc8f34c4ff0996cbda393273d 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx @@ -335,6 +335,18 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("t_st3_x", &m_t_st_x[3]); m_tree->Branch("t_st3_y", &m_t_st_y[3]); m_tree->Branch("t_st3_z", &m_t_st_z[3]); + m_tree->Branch("t_st0_px", &m_t_st_px[0]); + m_tree->Branch("t_st0_py", &m_t_st_py[0]); + m_tree->Branch("t_st0_pz", &m_t_st_pz[0]); + m_tree->Branch("t_st1_px", &m_t_st_px[1]); + m_tree->Branch("t_st1_py", &m_t_st_py[1]); + m_tree->Branch("t_st1_pz", &m_t_st_pz[1]); + m_tree->Branch("t_st2_px", &m_t_st_px[2]); + m_tree->Branch("t_st2_py", &m_t_st_py[2]); + m_tree->Branch("t_st2_pz", &m_t_st_pz[2]); + m_tree->Branch("t_st3_px", &m_t_st_px[3]); + m_tree->Branch("t_st3_py", &m_t_st_py[3]); + m_tree->Branch("t_st3_pz", &m_t_st_pz[3]); m_tree->Branch("isFiducial", &m_isFiducial); m_tree->Branch("truthParticleBarcode", &m_truthParticleBarcode); @@ -1054,6 +1066,14 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_t_st_y[station].push_back(positions[station].y()); m_t_st_z[station].push_back(positions[station].z()); } + + auto momenta = m_fiducialParticleTool->getTruthMomenta(truthParticle->barcode()); + for (int station = 0; station < 4; ++station) { + m_t_st_px[station].push_back(momenta[station].x()); + m_t_st_py[station].push_back(momenta[station].y()); + m_t_st_pz[station].push_back(momenta[station].z()); + } + if (truthParticle->hasProdVtx()) { m_t_prodVtx_x.push_back(truthParticle->prodVtx()->x()); m_t_prodVtx_y.push_back(truthParticle->prodVtx()->y()); @@ -1550,6 +1570,11 @@ NtupleDumperAlg::clearTree() const m_t_st_y[station].clear(); m_t_st_z[station].clear(); } + for (int station = 0; station < 4; ++station) { + m_t_st_px[station].clear(); + m_t_st_py[station].clear(); + m_t_st_pz[station].clear(); + } m_truthParticleBarcode.clear(); m_truthParticleMatchedTracks.clear(); m_truthParticleIsFiducial.clear(); @@ -1634,6 +1659,11 @@ void NtupleDumperAlg::clearTrackTruth() const { m_t_st_y[station].push_back(999999); m_t_st_z[station].push_back(999999); } + for (int station = 0; station < 4; ++station) { + m_t_st_px[station].push_back(999999); + m_t_st_py[station].push_back(999999); + m_t_st_pz[station].push_back(999999); + } m_isFiducial.push_back(false); } diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h index d636d8ef70dcdd7fbcb90fd44eddccd8c2ac36ac..d4fc22b9754617ea8c68aba3c365ef334abd0d5d 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h @@ -317,6 +317,9 @@ private: mutable std::array<std::vector<double>, 4> m_t_st_x; // vector of the x components of the simulated hits of the truth particle for each station mutable std::array<std::vector<double>, 4> m_t_st_y; // vector of the y components of the simulated hits of the truth particle for each station mutable std::array<std::vector<double>, 4> m_t_st_z; // vector of the z components of the simulated hits of the truth particle for each station + mutable std::array<std::vector<double>, 4> m_t_st_px; // x components of the true momentum at each station + mutable std::array<std::vector<double>, 4> m_t_st_py; // y components of the true momentum at each station + mutable std::array<std::vector<double>, 4> m_t_st_pz; // z components of the true momentum at each station mutable std::vector<bool> m_isFiducial; // track is fiducial if there are simulated hits for stations 1 - 3 and the distance from the center is smaller than 100 mm mutable std::vector<int> m_truthParticleBarcode; // vector of barcodes of all truth particles with a momentum larger 50 GeV diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h index 1df9aeab2ce991ee5d683d92fa5efb72eca7a5dd..081e6dc27913107fbd0cf4d4cb7a1646316eff49 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h @@ -23,6 +23,12 @@ public: */ virtual std::array<HepGeom::Point3D<double>, 4> getTruthPositions(int barcode) const = 0; + + /** Return average truth momentum in each station. + * @param barcode of a xAOD::TruthParticle + */ + virtual std::array<HepGeom::Point3D<double>, 4> + getTruthMomenta(int barcode) const = 0; }; #endif // FASERACTSKALMANFILTER_IFIDUCIALEVENTSELECTIONTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx index 101ddfdf99a645aaef69f6d824e782ff7525928f..71a469ba4cb1b20e682f610d0be13238394e9278 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx @@ -6,8 +6,7 @@ constexpr float NaN = std::numeric_limits<double>::quiet_NaN(); -FiducialParticleTool::FiducialParticleTool(const std::string &type, - const std::string &name, +FiducialParticleTool::FiducialParticleTool(const std::string &type, const std::string &name, const IInterface *parent) : base_class(type, name, parent) {} @@ -32,23 +31,32 @@ bool FiducialParticleTool::isFiducial(int barcode) const { return isFiducial; } -HepGeom::Point3D<double> -FiducialParticleTool::getGlobalPosition(const FaserSiHit &hit) const { - Identifier waferId = - m_sctHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), - hit.getModule(), hit.getSensor()); +HepGeom::Point3D<double> FiducialParticleTool::getGlobalPosition(const FaserSiHit &hit) const { + Identifier waferId = m_sctHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), + hit.getModule(), hit.getSensor()); auto localStartPos = hit.localStartPosition(); auto localEndPos = hit.localEndPosition(); HepGeom::Point3D<double> localPos = 0.5 * (localEndPos + localStartPos); - const TrackerDD::SiDetectorElement *element = - m_detMgr->getDetectorElement(waferId); - auto globalPosition = - Amg::EigenTransformToCLHEP(element->transformHit()) * localPos; + const TrackerDD::SiDetectorElement *element = m_detMgr->getDetectorElement(waferId); + auto globalPosition = Amg::EigenTransformToCLHEP(element->transformHit()) * localPos; return globalPosition; } -std::array<HepGeom::Point3D<double>, 4> -FiducialParticleTool::getTruthPositions(int barcode) const { +HepGeom::Point3D<double> FiducialParticleTool::getMomentum(const FaserSiHit &hit) const { + Identifier waferId = m_sctHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), + hit.getModule(), hit.getSensor()); + auto localStartPos = hit.localStartPosition(); + auto localEndPos = hit.localEndPosition(); + const TrackerDD::SiDetectorElement *element = m_detMgr->getDetectorElement(waferId); + auto globalStartPosition = Amg::EigenTransformToCLHEP(element->transformHit()) * localStartPos; + auto globalEndPosition = Amg::EigenTransformToCLHEP(element->transformHit()) * localEndPos; + double p = hit.particleLink()->momentum().rho(); + HepGeom::Point3D<double> globalDirection = globalEndPosition - globalStartPosition; + HepGeom::Point3D<double> momentum = globalDirection / globalDirection.mag() * p; + return momentum; +} + +std::array<HepGeom::Point3D<double>, 4> FiducialParticleTool::getTruthPositions(int barcode) const { // initialize positions as NaN std::array<HepGeom::Point3D<double>, 4> positions{}; for (auto &station : positions) { @@ -89,3 +97,46 @@ FiducialParticleTool::getTruthPositions(int barcode) const { } return positions; } + +std::array<HepGeom::Point3D<double>, 4> FiducialParticleTool::getTruthMomenta(int barcode) const { + // initialize positions as NaN + std::array<HepGeom::Point3D<double>, 4> momenta{}; + for (auto &station : momenta) { + station.setX(NaN); + station.setY(NaN); + station.setZ(NaN); + } + + // get simulated hits + SG::ReadHandle<FaserSiHitCollection> siHitCollection(m_siHitCollectionKey); + if (!siHitCollection.isValid()) { + ATH_MSG_WARNING("FaserSiHitCollection not valid."); + return momenta; + } + + // create map with truth momenta in each station + std::array<std::vector<HepGeom::Point3D<double>>, 4> hitMap{}; + for (const FaserSiHit &hit : *siHitCollection) { + if (hit.trackNumber() == barcode) { + HepGeom::Point3D<double> momentum = getMomentum(hit); + hitMap[hit.getStation()].push_back(momentum); + } + } + + // calculate average momentum in each station + for (int station = 0; station < 4; ++station) { + std::vector<HepGeom::Point3D<double>> &hits{hitMap[station]}; + if (hits.empty()) { + continue; + } else { + // calculate average momentum of all FaserSiHits in a station + auto const count = static_cast<double>(hits.size()); + HepGeom::Point3D<double> sums{}; + for (const HepGeom::Point3D<double> &hit : hits) { + sums += hit; + } + momenta[station] = sums / count; + } + } + return momenta; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h index 8d1435734c6982e9dcbd0abd52acb07003914366..ecba3a8318f3730127ddf8786722a3509b96b4ac 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h +++ b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h @@ -23,6 +23,10 @@ public: std::array<HepGeom::Point3D<double>, 4> getTruthPositions(int barcode) const override; + std::array<HepGeom::Point3D<double>, 4> + getTruthMomenta(int barcode) const override; + HepGeom::Point3D<double> + getMomentum(const FaserSiHit &hit) const; private: HepGeom::Point3D<double> getGlobalPosition(const FaserSiHit &hit) const;