ATLAS Offline Software
Loading...
Searching...
No Matches
BPhysBGammaFinder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "BPhysBGammaFinder.h"
10#include "GaudiKernel/IPartPropSvc.h"
14
15
17
18namespace DerivationFramework {
19
20BPhysBGammaFinder::BPhysBGammaFinder(const std::string& t, const std::string& n, const IInterface* p)
21 : base_class(t,n,p),
22 m_v0Tools("Trk::V0Tools"),
23 m_vertexFitter("Trk::TrkVKalVrtFitter"),
24 m_vertexEstimator("InDet::VertexPointEstimator"),
25 m_inputTrackParticleContainerName("InDetTrackParticles"),
26 m_inputLowPtTrackContainerName("LowPtRoITrackParticles"),
27 m_conversionContainerName("BPhysConversionCandidates"),
30 m_requireDeltaQ(true),
31 m_use_low_pT(false),
32 m_maxDeltaQ(1000.0),
33 m_Chi2Cut(20.0),
34 m_maxGammaMass(100.0) {
35
36
37 // Declare user-defined properties
38 declareProperty("BVertexContainers", m_BVertexCollectionsToCheck);
39 declareProperty("PassFlagsToCheck", m_passFlagsToCheck);
40 declareProperty("V0Tools", m_v0Tools);
41 declareProperty("VertexFitterTool", m_vertexFitter);
42 declareProperty("VertexEstimator", m_vertexEstimator);
43 declareProperty("InputTrackParticleContainerName", m_inputTrackParticleContainerName);
44 declareProperty("InputLowPtTrackContainerName", m_inputLowPtTrackContainerName);
45 declareProperty("ConversionContainerName", m_conversionContainerName);
46 declareProperty("MaxDistBetweenTracks", m_maxDistBetweenTracks = 10.0); // Maximum allowed distance of minimum approach
47 declareProperty("MaxDeltaCotTheta", m_maxDeltaCotTheta = 0.3); // Maximum allowed dCotTheta between tracks
48 declareProperty("RequireDeltaQ", m_requireDeltaQ = true); // Only save a conversions if it's a chi_c,b candidate (must then pass "MaxDeltaM" requirement), if "False" all conversions in the event will be saved
49 declareProperty("Use_low_pT", m_use_low_pT = false); // Only save a conversions if it's a chi_c,b candidate (must then pass "MaxDeltaM" requirement), if "False" all conversions in the event will be saved
50 declareProperty("MaxDeltaQ", m_maxDeltaQ = 700.0); // Maximum mass difference between di-muon+conversion and di-muon
51 declareProperty("Chi2Cut", m_Chi2Cut = 20.0);
52 declareProperty("MaxGammaMass", m_maxGammaMass = 100.0);
53}
54
55
57
58 ATH_MSG_DEBUG("in initialize()");
59
60 ATH_CHECK( m_v0Tools.retrieve() );
61 ATH_CHECK( m_vertexFitter.retrieve() );
62 ATH_CHECK( m_vertexEstimator.retrieve() );
63 return StatusCode::SUCCESS;
64}
65
66
68 return StatusCode::SUCCESS;
69}
70
71
72StatusCode BPhysBGammaFinder::addBranches(const EventContext&) const {
73
74 std::vector<const xAOD::Vertex*> BVertices;
75 BVertices.clear();
76 std::vector<const xAOD::TrackParticle*> BVertexTracks;
77
78
79 // Output conversion container
80 std::unique_ptr<xAOD::VertexContainer> conversionContainer(new xAOD::VertexContainer());
81 std::unique_ptr<xAOD::VertexAuxContainer> conversionAuxContainer(new xAOD::VertexAuxContainer());
82 conversionContainer->setStore(conversionAuxContainer.get());
83
84 // Retrieve track particles from StoreGate
85 const xAOD::TrackParticleContainer* inputTrackParticles{};
86 ATH_CHECK( evtStore()->retrieve(inputTrackParticles, m_inputTrackParticleContainerName)); // FIXME Use Handles
87 ATH_MSG_DEBUG( "Track particle container size " << inputTrackParticles->size() );
88 // Low pT collection
89 const xAOD::TrackParticleContainer* lowPtTrackParticles{};
90 if (m_use_low_pT) {
91 StatusCode sc = evtStore()->retrieve(lowPtTrackParticles, m_inputLowPtTrackContainerName); // FIXME Use Handles
92 if (sc.isFailure()) {
93 ATH_MSG_WARNING("No low pT collection with key " << m_inputLowPtTrackContainerName << " found in StoreGate.");
94 return StatusCode::SUCCESS;;
95 }
96 else {
97 ATH_MSG_DEBUG("Low pT track particle container size " << lowPtTrackParticles->size());
98 }
99 }
100
101 // Look for B candidate
102 if (m_BVertexCollectionsToCheck.empty()) {
103 ATH_MSG_FATAL( "No B vertex collections provided" );
104 return StatusCode::FAILURE;
105 }
106 else {
107 for ( auto itr = m_BVertexCollectionsToCheck.begin(); itr != m_BVertexCollectionsToCheck.end(); ++itr) {
108 ATH_MSG_DEBUG( "Using " << *itr << " as the source B vertex collection" );
109 }
110 }
111
112 // Retrieve vertex containers
113 for (auto itr = m_BVertexCollectionsToCheck.begin(); itr!=m_BVertexCollectionsToCheck.end(); ++itr) {
114 // retieve vertex
115 const xAOD::VertexContainer* BVtxContainer{};
116 CHECK( evtStore()->retrieve(BVtxContainer, *itr)); // FIXME Use Handles
117 ATH_MSG_DEBUG( "Vertex Container (" << *itr << ") contains " << BVtxContainer->size() << " vertices" );
118
119 static const SG::Decorator< std::vector< VertexLink > > BGammaLinks( "BGammaLinks" );
120 static const std::vector< VertexLink > vertexLinks;
121
122 for (const xAOD::Vertex* vertex : *BVtxContainer) {
123 BGammaLinks(*vertex) = vertexLinks;
124
125 bool passedHypothesis = false;
126 BVertexTracks.clear();
127
128 for (const auto &flag : m_passFlagsToCheck) {
130 bool pass = acc(*vertex);
131 if (pass) passedHypothesis = true;
132 }
133
134 if (!passedHypothesis) continue;
135 xAOD::BPhysHypoHelper Bc("Bc", vertex);
136
137 // link to Bc+ vertex
138 std::vector<const xAOD::Vertex*> precedingVertices(1, vertex);
139
140 // Collect up B-vertex tracks
141 for (size_t i = 0; i < vertex->nTrackParticles(); ++i) BVertexTracks.push_back(vertex->trackParticle(i));
142
143 // Track Selection
144 // Track1 Loop
145 for (xAOD::TrackParticleContainer::const_iterator tpIt1 = inputTrackParticles->begin(); tpIt1 != inputTrackParticles->end(); ++tpIt1) {
146 const xAOD::TrackParticle* trackParticle1 = *tpIt1;
147
148 auto itr1 = std::find(BVertexTracks.begin(), BVertexTracks.end(), trackParticle1);
149 if (itr1 != BVertexTracks.end()) continue;
150
151 const Trk::Perigee& trackPerigee1 = trackParticle1->perigeeParameters();
152
153 // Track2 Loop
154 for (xAOD::TrackParticleContainer::const_iterator tpIt2 = tpIt1 + 1; tpIt2 != inputTrackParticles->end(); ++tpIt2) {
155 const xAOD::TrackParticle* trackParticle2 = *tpIt2;
156 if (trackParticle1 == trackParticle2) continue;
157
158 auto itr2 = std::find(BVertexTracks.begin(), BVertexTracks.end(), trackParticle2);
159 if (itr2 != BVertexTracks.end()) continue;
160
161 const Trk::Perigee& trackPerigee2 = trackParticle2->perigeeParameters();
162
163 // Track pair selection
164 TLorentzVector e1, e2, gamma_m, BcStar;
165 e1.SetPtEtaPhiM(trackParticle1->pt(), trackParticle1->eta(), trackParticle1->phi(), Trk::electron);
166 e2.SetPtEtaPhiM(trackParticle2->pt(), trackParticle2->eta(), trackParticle2->phi(), Trk::electron);
167
168 gamma_m = e1 + e2;
169 if (gamma_m.M() > m_maxGammaMass) continue;
170
171 TLorentzVector mu1 = Bc.refTrk(0, Trk::muon);
172 TLorentzVector mu2 = Bc.refTrk(1, Trk::muon);
173 TLorentzVector mu3 = Bc.refTrk(2, Trk::muon);
174
175 BcStar = mu1 + mu2 + mu3 + e1 + e2;
176 double Q = BcStar.M() - Bc.mass() - 2 * Trk::electron;
177 if (Q > m_maxDeltaQ) continue;
178
179 // Estimate starting point + cuts on compatiblity of tracks
180 int sflag = 0;
181 int errorcode = 0;
182 Amg::Vector3D startingPoint = m_vertexEstimator->getCirclesIntersectionPoint(&trackPerigee1, &trackPerigee2, sflag, errorcode);
183 if (errorcode != 0) startingPoint = Amg::Vector3D::Zero(3);
184
185 std::vector<float> RefTrackPx, RefTrackPy, RefTrackPz, RefTrackE;
186 std::vector<float> OrigTrackPx, OrigTrackPy, OrigTrackPz, OrigTrackE;
187
188 std::vector<const xAOD::TrackParticle*> trackPair;
189 trackPair.clear();
190 trackPair.push_back(trackParticle1);
191 trackPair.push_back(trackParticle2);
192
193 // Do the vertex fit
194 xAOD::Vertex* convVertexCandidate = m_vertexFitter->fit(trackPair, startingPoint);
195
196 // Check for successful fit
197 if (convVertexCandidate) {
198 if (convVertexCandidate->chiSquared() / convVertexCandidate->numberDoF() > m_Chi2Cut) continue;
199
200 xAOD::BPhysHelper Photon(convVertexCandidate);
201 // set link to the parent Bc+ vertex
202 Photon.setPrecedingVertices(precedingVertices, BVtxContainer);
203
204 // Parameters at vertex
205 convVertexCandidate->clearTracks();
207 newLink1.setElement(*tpIt1);
208 newLink1.setStorableObject(*inputTrackParticles);
210 newLink2.setElement(*tpIt2);
211 newLink2.setStorableObject(*inputTrackParticles);
212 convVertexCandidate->addTrackAtVertex(newLink1);
213 convVertexCandidate->addTrackAtVertex(newLink2);
214
215 std::vector<Amg::Vector3D> positionList;
216
217 //Get photon momentum 3-vector
218 Amg::Vector3D momentum = m_v0Tools->V0Momentum(convVertexCandidate);
219
220 TLorentzVector photon, electron1, electron2, ph;
221 electron1.SetVectM( trackMomentum( convVertexCandidate, 0 ), Trk::electron );
222 electron2.SetVectM( trackMomentum( convVertexCandidate, 1 ), Trk::electron );
223 photon = electron1 + electron2;
224 ph.SetXYZM(momentum.x(), momentum.y(), momentum.z(), 0.);
225
226 // Use to keep track of which dimuon(s) gave a chi_c/b candidate
227 static const SG::Accessor<std::vector<float> > RefTrackPxAcc("RefTrackPx");
228 static const SG::Accessor<std::vector<float> > RefTrackPyAcc("RefTrackPy");
229 static const SG::Accessor<std::vector<float> > RefTrackPzAcc("RefTrackPz");
230 std::vector<float> B_Px = RefTrackPxAcc(*vertex);
231 std::vector<float> B_Py = RefTrackPyAcc(*vertex);
232 std::vector<float> B_Pz = RefTrackPzAcc(*vertex);
233
234 TLorentzVector muon1, muon2, muon3;
235 muon1.SetXYZM(B_Px.at(0), B_Py.at(0), B_Pz.at(0), Trk::muon);
236 muon2.SetXYZM(B_Px.at(1), B_Py.at(1), B_Pz.at(1), Trk::muon);
237 muon3.SetXYZM(B_Px.at(2), B_Py.at(2), B_Pz.at(2), Trk::muon);
238
239 TLorentzVector B_m = muon1 + muon2 + muon3;
240
241 const double deltaQ = (B_m + photon).M() - Bc.mass() - 2 * Trk::electron;
242 const double mass = photon.M();
243
244 RefTrackPx.push_back(trackMomentum(convVertexCandidate, 0).Px());
245 RefTrackPx.push_back(trackMomentum(convVertexCandidate, 1).Px());
246
247 RefTrackPy.push_back(trackMomentum(convVertexCandidate, 0).Py());
248 RefTrackPy.push_back(trackMomentum(convVertexCandidate, 1).Py());
249
250 RefTrackPz.push_back(trackMomentum(convVertexCandidate, 0).Pz());
251 RefTrackPz.push_back(trackMomentum(convVertexCandidate, 1).Pz());
252
253 for (size_t i = 0; i < B_Px.size(); i++) {
254 RefTrackPx.push_back(B_Px.at(i));
255 RefTrackPy.push_back(B_Py.at(i));
256 RefTrackPz.push_back(B_Pz.at(i));
257 }
258
259 RefTrackE.push_back(electron1.E());
260 RefTrackE.push_back(electron2.E());
261 RefTrackE.push_back(muon1.E());
262 RefTrackE.push_back(muon2.E());
263 RefTrackE.push_back(muon3.E());
264
265 OrigTrackPx.push_back(e1.Px());
266 OrigTrackPx.push_back(e2.Px());
267
268 OrigTrackPy.push_back(e1.Py());
269 OrigTrackPy.push_back(e2.Py());
270
271 OrigTrackPz.push_back(e1.Pz());
272 OrigTrackPz.push_back(e2.Pz());
273
274 OrigTrackE.push_back(e1.E());
275 OrigTrackE.push_back(e2.E());
276
277
278 ATH_MSG_DEBUG( "pt = " << photon.Pt() << " ph " << ph.Pt() << " mass " << photon.M() << " px size " << RefTrackPx.size() );
279 ATH_MSG_DEBUG( "Candidate DeltaM = " << (B_m + photon).M() << " MeV DiMuon " << " ( Mass = " << B_m.M() << " MeV )");
280
281 // Decorate selected conversions
282 ATH_MSG_DEBUG( "Decorating conversion vertices" );
283
284 static const SG::Accessor<float> pxAcc("px");
285 static const SG::Accessor<float> pyAcc("py");
286 static const SG::Accessor<float> pzAcc("pz");
287 pxAcc(*convVertexCandidate) = momentum.x();
288 pyAcc(*convVertexCandidate) = momentum.y();
289 pzAcc(*convVertexCandidate) = momentum.z();
290
291 static const SG::Accessor<float> deltaQAcc("deltaQ");
292 static const SG::Accessor<float> gamma_massAcc("gamma_mass");
293 static const SG::Accessor< std::vector<float> > RefTrackEAcc("RefTrackE");
294 deltaQAcc(*convVertexCandidate) = deltaQ;
295 gamma_massAcc(*convVertexCandidate) = mass;
296 RefTrackPxAcc(*convVertexCandidate) = RefTrackPx;
297 RefTrackPyAcc(*convVertexCandidate) = RefTrackPy;
298 RefTrackPzAcc(*convVertexCandidate) = RefTrackPz;
299 RefTrackEAcc(*convVertexCandidate) = RefTrackE;
300
301 static const SG::Accessor< std::vector<float> > OrigTrackPxAcc("OrigTrackPx");
302 static const SG::Accessor< std::vector<float> > OrigTrackPyAcc("OrigTrackPy");
303 static const SG::Accessor< std::vector<float> > OrigTrackPzAcc("OrigTrackPz");
304 static const SG::Accessor< std::vector<float> > OrigTrackEAcc("OrigTrackE");
305 OrigTrackPxAcc(*convVertexCandidate) = OrigTrackPx;
306 OrigTrackPyAcc(*convVertexCandidate) = OrigTrackPy;
307 OrigTrackPzAcc(*convVertexCandidate) = OrigTrackPz;
308 OrigTrackEAcc(*convVertexCandidate) = OrigTrackE;
309
310 static const SG::Accessor<Char_t> passed_GammaAcc("passed_Gamma");
311 passed_GammaAcc(*convVertexCandidate) = true; // Used in event skimming
312
313 conversionContainer->push_back( convVertexCandidate );
314
315 // add cross-link to the original Bc+ vertex
316 VertexLink BGammaLink;
317 BGammaLink.setElement(convVertexCandidate);
318 BGammaLink.setStorableObject(*conversionContainer);
319 BGammaLinks(*vertex).push_back(std::move(BGammaLink));
320 }
321 else {
322 ATH_MSG_DEBUG( "Vertex Fit Failed" );
323 }
324
325 } // end of Track2 Loop
326 } // end of Track1 Loop
327
328 } // end of Bc loop
329
330 } // end of vertex container loop
331
332 // Write the results to StoreGate
333 CHECK(evtStore()->record(conversionContainer.release(), m_conversionContainerName)); // FIXME Use Handles
334 CHECK(evtStore()->record(conversionAuxContainer.release(), m_conversionContainerName + "Aux.")); // FIXME Use Handles
335
336 return StatusCode::SUCCESS;
337}
338
339
340// trackMomentum: returns refitted track momentum
341TVector3 BPhysBGammaFinder::trackMomentum(const xAOD::Vertex* vxCandidate, int trkIndex) const {
342
343 double px = 0.;
344 double py = 0.;
345 double pz = 0.;
346 if (vxCandidate) {
347 const Trk::TrackParameters* aPerigee = vxCandidate->vxTrackAtVertex()[trkIndex].perigeeAtVertex();
348 px = aPerigee->momentum()[Trk::px];
349 py = aPerigee->momentum()[Trk::py];
350 pz = aPerigee->momentum()[Trk::pz];
351 }
352
353 return TVector3(px,py,pz);
354}
355
356} // end of namespace DerivationFramework
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ElementLink< xAOD::VertexContainer > VertexLink
: B-physics xAOD helpers.
Helper class to provide constant type-safe access to aux data.
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t sc
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
BPhysBGammaFinder(const std::string &t, const std::string &n, const IInterface *p)
ToolHandle< Trk::IVertexFitter > m_vertexFitter
virtual StatusCode addBranches(const EventContext &ctx) const override
std::vector< std::string > m_passFlagsToCheck
std::vector< std::string > m_BVertexCollectionsToCheck
ToolHandle< InDet::VertexPointEstimator > m_vertexEstimator
TVector3 trackMomentum(const xAOD::Vertex *vxCandidate, int trkIndex) const
Helper class to provide type-safe access to aux data.
Helper class to provide constant type-safe access to aux data.
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
const Amg::Vector3D & momentum() const
Access method for the momentum.
TVector3 refTrk(const size_t index)
Returns i-th refitted track 3-momentum.
float mass() const
Get invariant mass and its error.
Class describing an photon.
const Trk::Perigee & perigeeParameters() const
Returns the Trk::MeasuredPerigee track parameters.
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .)
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
void clearTracks()
Remove all tracks from the vertex.
void addTrackAtVertex(const ElementLink< TrackParticleContainer > &tr, float weight=1.0)
Add a new track to the vertex.
float numberDoF() const
Returns the number of degrees of freedom of the vertex fit as float.
float chiSquared() const
Returns the of the vertex fit as float.
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
Eigen::Matrix< double, 3, 1 > Vector3D
THE reconstruction tool.
ElementLink< xAOD::VertexContainer > VertexLink
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ pz
global momentum (cartesian)
Definition ParamDefs.h:61
@ px
Definition ParamDefs.h:59
@ py
Definition ParamDefs.h:60
ParametersBase< TrackParametersDim, Charged > TrackParameters
VertexAuxContainer_v1 VertexAuxContainer
Definition of the current jet auxiliary container.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".