Belle II Software development
InternalParticle.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * External Contributor: Wouter Hulsbergen *
5 * *
6 * See git log for contributors and copyright holders. *
7 * This file is licensed under LGPL-3.0, see LICENSE.md. *
8 **************************************************************************/
9
10#include <analysis/dataobjects/Particle.h>
11
12#include <analysis/VertexFitting/TreeFitter/InternalParticle.h>
13#include <analysis/VertexFitting/TreeFitter/FitParams.h>
14#include <analysis/VertexFitting/TreeFitter/HelixUtils.h>
15#include <framework/logging/Logger.h>
16#include <mdst/dataobjects/V0.h>
17
18using std::vector;
19
20namespace TreeFitter {
21
22 inline bool sortByType(const ParticleBase* lhs, const ParticleBase* rhs)
23 {
24 int lhstype = lhs->type() ;
25 int rhstype = rhs->type() ;
26 bool rc = false ;
27 if (lhstype == rhstype &&
28 lhstype == ParticleBase::TFParticleType::kRecoTrack) {
29
30 rc = lhs->particle()->getMomentum().Rho() > rhs->particle()->getMomentum().Rho();
31 } else if (lhs->particle() && rhs->particle() && lhs->particle()->getNDaughters() > 0 &&
32 rhs->particle()->getNDaughters() > 0) {
33 rc = lhs->nFinalChargedCandidates() > rhs->nFinalChargedCandidates();
34 } else {
35 rc = lhstype < rhstype;
36 }
37 return rc;
38 }
39
41 const ParticleBase* mother,
42 const ConstraintConfiguration& config,
43 bool forceFitAll
44 ) :
45 ParticleBase(particle, mother, &config),// config pointer here to allow final states not to have it
46 m_massconstraint(false),
47 m_beamconstraint(false),
48 m_lifetimeconstraint(false),
49 m_isconversion(false),
50 m_automatic_vertex_constraining(config.m_automatic_vertex_constraining)
51 {
52 if (particle) {
53 for (auto daughter : particle->getDaughters()) {
54 addDaughter(daughter, config, forceFitAll);
55 }
56 } else {
57 B2ERROR("Trying to create an InternalParticle from NULL. This should never happen.");
58 }
59
60 m_massconstraint = std::find(config.m_massConstraintListPDG.begin(), config.m_massConstraintListPDG.end(),
61 std::abs(m_particle->getPDGCode())) != config.m_massConstraintListPDG.end()
62 or m_particle->hasExtraInfo("treeFitterMassConstraint");
63
64 m_beamconstraint = (std::abs(m_particle->getPDGCode()) == config.m_beamConstraintPDG);
65
67 // if this is a hadronically decaying resonance it is useful to constrain the decay vertex to its mother's decay vertex.
68 //
69 m_shares_vertex_with_mother = std::find(config.m_fixedToMotherVertexListPDG.begin(),
70 config.m_fixedToMotherVertexListPDG.end(),
71 std::abs(m_particle->getPDGCode())) != config.m_fixedToMotherVertexListPDG.end() && this->mother();
72
73 // use geo constraint if this particle is in the list to constrain
74 m_geo_constraint = std::find(config.m_geoConstraintListPDG.begin(),
75 config.m_geoConstraintListPDG.end(),
76 std::abs(m_particle->getPDGCode())) != config.m_geoConstraintListPDG.end() && this->mother() && !m_shares_vertex_with_mother;
77 } else {
80 }
81 }
82
84 {
85
86 return lhs->particle()->getMomentum().Rho() > rhs->particle()->getMomentum().Rho();
87 }
88
90 {
91 ErrCode status ;
92 for (auto daughter : m_daughters) {
93 status |= daughter->initMotherlessParticle(fitparams);
94 }
95
96 int posindex = posIndex();
97 // FIXME update this and check if this position is already initialised
98 // lower stream vertices might be better
99 if (hasPosition()) {
100 fitparams.getStateVector().segment(posindex, 3) = Eigen::Matrix<double, 3, 1>::Zero(3);
101
102 std::vector<ParticleBase*> alldaughters;
103 ParticleBase::collectVertexDaughters(alldaughters, posindex);
104
105 std::vector<ParticleBase*> vtxdaughters;
106
107 vector<RecoTrack*> trkdaughters;
108 for (auto daughter : alldaughters) {
109 if (daughter->type() == ParticleBase::TFParticleType::kRecoTrack) {
110 trkdaughters.push_back(static_cast<RecoTrack*>(daughter));
111 } else if (daughter->hasPosition()
112 && fitparams.getStateVector()(daughter->posIndex()) != 0) {
113 vtxdaughters.push_back(daughter);
114 }
115 }
116
117 if (trkdaughters.size() >= 2) {
118
119 auto v0 = particle()->getV0();
120 auto dummy_vertex = ROOT::Math::XYZVector(0, 0, 0);
121
122 bool initWithV0 = false;
123 if (v0 && v0->getFittedVertexPosition() != dummy_vertex) {
124 auto part_dau1 = particle()->getDaughter(0);
125 auto part_dau2 = particle()->getDaughter(1);
126
127 auto recotrack_dau1 = std::find_if(trkdaughters.begin(), trkdaughters.end(),
128 [&part_dau1](RecoTrack * rt) { return rt->particle()->getMdstSource() == part_dau1->getMdstSource(); });
129 auto recotrack_dau2 = std::find_if(trkdaughters.begin(), trkdaughters.end(),
130 [&part_dau2](RecoTrack * rt) { return rt->particle()->getMdstSource() == part_dau2->getMdstSource(); });
131
132 if (recotrack_dau1 == trkdaughters.end() || recotrack_dau2 == trkdaughters.end()) {
133 B2WARNING("V0 daughter particles do not match with RecoTracks.");
134 } else {
135 double X_V0(v0->getFittedVertexX()), Y_V0(v0->getFittedVertexY()), Z_V0(v0->getFittedVertexZ());
136 fitparams.getStateVector()(posindex) = X_V0;
137 fitparams.getStateVector()(posindex + 1) = Y_V0;
138 fitparams.getStateVector()(posindex + 2) = Z_V0;
139
140 Belle2::Helix helix1 = v0->getTrackFitResults().first->getHelix();
141 Belle2::Helix helix2 = v0->getTrackFitResults().second->getHelix();
142
143 (*recotrack_dau1)->setFlightLength(helix1.getArcLength2DAtXY(X_V0, Y_V0));
144 (*recotrack_dau2)->setFlightLength(helix2.getArcLength2DAtXY(X_V0, Y_V0));
145
146 initWithV0 = true;
147 }
148 }
149
150 if (!initWithV0) {
151 std::sort(trkdaughters.begin(), trkdaughters.end(), compTrkTransverseMomentum);
152
153 RecoTrack* dau1 = trkdaughters[0];
154 RecoTrack* dau2 = trkdaughters[1];
155
156 Belle2::Helix helix1 = dau1->particle()->getTrackFitResult()->getHelix();
157 Belle2::Helix helix2 = dau2->particle()->getTrackFitResult()->getHelix();
158
159 double flt1(0), flt2(0);
161 HelixUtils::helixPoca(helix1, helix2, flt1, flt2, v, m_isconversion);
162
163 fitparams.getStateVector()(posindex) = v.X();
164 fitparams.getStateVector()(posindex + 1) = v.Y();
165 fitparams.getStateVector()(posindex + 2) = v.Z();
166
167 dau1->setFlightLength(flt1);
168 dau2->setFlightLength(flt2);
169 }
170
171 } else if (false && trkdaughters.size() + vtxdaughters.size() >= 2) {
172 // TODO switched off waiting for refactoring of init1 and init2 functions (does not affect performance)
173 } else if (mother() && mother()->posIndex() >= 0) {
174 const int posindexmother = mother()->posIndex();
175 const int dim = m_config->m_originDimension; //TODO access mother
176 fitparams.getStateVector().segment(posindex, dim) = fitparams.getStateVector().segment(posindexmother, dim);
177 } else {
179 fitparams.getStateVector().segment(posindex, 3) = Eigen::Matrix<double, 1, 3>::Zero(3);
180 }
181 }
182
183 for (auto daughter : m_daughters) {
184 daughter->initParticleWithMother(fitparams);
185 }
186
187 initMomentum(fitparams);
188 return status;
189 }
190
192 {
193 int posindex = posIndex();
194 if (hasPosition() &&
195 mother() &&
196 fitparams.getStateVector()(posindex) == 0 &&
197 fitparams.getStateVector()(posindex + 1) == 0 && \
198 fitparams.getStateVector()(posindex + 2) == 0) {
199 const int posindexmom = mother()->posIndex();
200 const int dim = m_config->m_originDimension; //TODO access mother?
201 fitparams.getStateVector().segment(posindex, dim) = fitparams.getStateVector().segment(posindexmom, dim);
202 }
203 return initTau(fitparams);
204 }
205
207 {
208 int momindex = momIndex();
209 fitparams.getStateVector().segment(momindex, 4) = Eigen::Matrix<double, 4, 1>::Zero(4);
210
211 for (auto daughter : m_daughters) {
212 int daumomindex = daughter->momIndex();
213 int maxrow = daughter->hasEnergy() ? 4 : 3;
214
215 double e2 = fitparams.getStateVector().segment(daumomindex, maxrow).squaredNorm();
216 fitparams.getStateVector().segment(momindex, maxrow) += fitparams.getStateVector().segment(daumomindex, maxrow);
217
218 if (maxrow == 3) {
219 double mass = 0;
220 if (daughter->particle()->hasExtraInfo("treeFitterMassConstraintValue")) {
221 mass = daughter->particle()->getExtraInfo("treeFitterMassConstraintValue");
222 } else mass = daughter->particle()->getPDGMass();
223 fitparams.getStateVector()(momindex + 3) += std::sqrt(e2 + mass * mass);
224 }
225 }
226 return ErrCode(ErrCode::Status::success);
227 }
228
230 {
231 ErrCode status;
233 for (auto daughter : m_daughters) {
234 status |= daughter->initCovariance(fitparams);
235 }
236 return status;
237 }
238
239
241 Projection& p) const
242 {
243 const int momindex = momIndex();
244
245 // `this` always has an energy row
246 p.getResiduals().segment(0, 4) = fitparams.getStateVector().segment(momindex, 4);
247
248 for (int imom = 0; imom < 4; ++imom) {
249 p.getH()(imom, momindex + imom) = 1;
250 }
251
252 for (const auto daughter : m_daughters) {
253 const int daumomindex = daughter->momIndex();
254 const Eigen::Matrix<double, 1, 3> p3_vec = fitparams.getStateVector().segment(daumomindex, 3);
255
256 // three momentum is easy just subtract the vectors
257 p.getResiduals().segment(0, 3) -= p3_vec;
258
259 // energy depends on the parametrisation!
260 if (daughter->hasEnergy()) {
261 p.getResiduals()(3) -= fitparams.getStateVector()(daumomindex + 3);
262 p.getH()(3, daumomindex + 3) = -1; // d/dE -E
263 } else {
264 // m^2 + p^2 = E^2
265 // so
266 // E = sqrt(m^2 + p^2)
267 double mass = 0;
268 if (daughter->particle()->hasExtraInfo("treeFitterMassConstraintValue")) {
269 mass = daughter->particle()->getExtraInfo("treeFitterMassConstraintValue");
270 } else mass = daughter->particle()->getPDGMass();
271 const double p2 = p3_vec.squaredNorm();
272 const double energy = std::sqrt(mass * mass + p2);
273 p.getResiduals()(3) -= energy;
274
275 for (unsigned i = 0; i < 3; ++i) {
276 // d/dpx_i sqrt(m^2 + p^2)
277 p.getH()(3, daumomindex + i) = -1 * p3_vec(i) / energy;
278 }
279 }
280
281 // this has to be in any case
282 // d/dp_i p_i
283 for (unsigned i = 0; i < 3; ++i) {
284 p.getH()(i, daumomindex + i) = -1;
285 }
286 }
287 return ErrCode(ErrCode::Status::success);
288 }
289
290
292 Projection& p) const
293 {
294
295 const int momindex = momIndex() ;
296
297 const Eigen::Matrix<double, 4, 1> fitMomE = fitparams.getStateVector().segment(momindex, 4);
298
299 p.getResiduals() = m_config->m_beamMomE - fitMomE;
300
301 for (int row = 0; row < 4; ++row) {
302 p.getH()(row, momindex + row) = -1;
303 }
304
305 p.getV() = m_config->m_beamCovariance;
306
307 return ErrCode(ErrCode::Status::success) ;
308 }
309
310
312 const FitParams& fitparams,
313 Projection& p) const
314 {
315 ErrCode status;
316 switch (type) {
317 case Constraint::mass:
318 status |= projectMassConstraint(fitparams, p);
319 break;
320 case Constraint::geometric:
321 status |= projectGeoConstraint(fitparams, p);
322 break;
323 case Constraint::kinematic:
324 status |= projectKineConstraint(fitparams, p);
325 break;
326 case Constraint::beam:
327 status |= projectBeamConstraint(fitparams, p);
328 break;
329 default:
330 status |= ParticleBase::projectConstraint(type, fitparams, p);
331 }
332
333 return status;
334 }
335
337 {
338 // for example B0 and D* can share the same vertex
339 return m_shares_vertex_with_mother ? this->mother()->posIndex() : index();
340 }
341
343 {
344 // { x, y, z, tau, px, py, pz, E }
345 // the last 4 always exists for composite particles
346 // tau index only exist with a vertex and geo constraint
347 //
348 if (m_shares_vertex_with_mother) { return 4; }
349 else if (!m_geo_constraint) { return 7; }
350 else { return 8; }
351 }
352
354 {
356 return m_geo_constraint ? index() + 3 : -1;
357 }
358
360 {
365 if (m_geo_constraint && !m_shares_vertex_with_mother) { return this->index() + 4; }
366
367 if (m_shares_vertex_with_mother) { return this->index(); }
368
369 if (!m_geo_constraint) {return index() + 3 ;}
370
371 // this will crash the initialisation
372 return -1;
373 }
374
376 {
377 // does this particle have a position index (decayvertex)
378 // true in any case
379 return true;
380 }
381
383 int depth) const
384 {
385
386 for (auto daughter : m_daughters) {
387 daughter->addToConstraintList(list, depth - 1);
388 }
389 if (tauIndex() >= 0 && m_lifetimeconstraint) {
390 list.push_back(Constraint(this, Constraint::lifetime, depth, 1));
391 }
392 if (momIndex() >= 0) {
393 list.push_back(Constraint(this, Constraint::kinematic, depth, 4, 3));
394 }
395 if (m_geo_constraint) {
396 assert(m_config);
397 const int dim = m_config->m_originDimension == 2 && std::abs(m_particle->getPDGCode()) == m_config->m_headOfTreePDG ? 2 : 3;
398 list.push_back(Constraint(this, Constraint::geometric, depth, dim, 3));
399 }
400 if (m_massconstraint) {
401 list.push_back(Constraint(this, Constraint::mass, depth, 1, 3));
402 }
403 if (m_beamconstraint) {
404 assert(m_config);
405 list.push_back(Constraint(this, Constraint::beam, depth, 4, 3));
406 }
407
408 }
409
410 std::string InternalParticle::parname(int thisindex) const
411 {
412 int id = thisindex;
413 if (!mother() && id >= 3) {++id;}
414 return ParticleBase::parname(id);
415 }
416
418 {
419 for (const auto daughter : m_daughters) {
420 daughter->forceP4Sum(fitparams);
421 }
422 const int momindex = momIndex();
423 if (momindex > 0) {
424 const int dim = hasEnergy() ? 4 : 3;
425 Projection p(fitparams.getDimensionOfState(), dim);
426 projectKineConstraint(fitparams, p);
427 fitparams.getStateVector().segment(momindex, dim) -= p.getResiduals().segment(0, dim);
428 }
429 }
430
431}
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
Helix parameter class.
Definition: Helix.h:48
Class to store reconstructed particles.
Definition: Particle.h:76
bool hasExtraInfo(const std::string &name) const
Return whether the extra info with the given name is set.
Definition: Particle.cc:1351
const V0 * getV0() const
Returns the pointer to the V0 object that was used to create this Particle (if ParticleType == c_V0).
Definition: Particle.cc:956
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:465
std::vector< Belle2::Particle * > getDaughters() const
Returns a vector of pointers to daughter particles.
Definition: Particle.cc:668
ROOT::Math::XYZVector getMomentum() const
Returns momentum vector.
Definition: Particle.h:580
const TrackFitResult * getTrackFitResult() const
Returns the pointer to the TrackFitResult that was used to create this Particle (ParticleType == c_Tr...
Definition: Particle.cc:925
const Particle * getDaughter(unsigned i) const
Returns a pointer to the i-th daughter particle.
Definition: Particle.cc:662
Helix getHelix() const
Conversion to framework Helix (without covariance).
constraint configuration class
const int m_originDimension
dimension of the origin constraint and ALL geometric gcosntraints
Eigen::Matrix< double, 4, 1 > m_beamMomE
Beam four-momentum.
int m_headOfTreePDG
PDG code of the head particle.
Eigen::Matrix< double, 4, 4 > m_beamCovariance
Beam Covariance.
class to manage the order of constraints and their filtering
Definition: Constraint.h:20
Type
type of constraints the order of these constraints is important: it is the order in which they are ap...
Definition: Constraint.h:27
abstract errorocode be aware that the default is success
Definition: ErrCode.h:14
Class to store and manage fitparams (statevector)
Definition: FitParams.h:20
Eigen::Matrix< double, -1, 1, 0, MAX_MATRIX_SIZE, 1 > & getStateVector()
getter for the fit parameters/statevector
Definition: FitParams.h:65
int getDimensionOfState() const
get the states dimension
Definition: FitParams.h:80
static double helixPoca(const Belle2::Helix &helix1, const Belle2::Helix &helix2, double &flt1, double &flt2, Belle2::B2Vector3D &vertex, bool parallel=false)
POCA between two tracks.
Definition: HelixUtils.cc:214
virtual void forceP4Sum(FitParams &) const override
enforce conservation of momentum sum
virtual int tauIndex() const override
tau index in fit params only if it has a mother
bool m_isconversion
is conversion
virtual std::string parname(int index) const override
name
ErrCode projectKineConstraint(const FitParams &, Projection &) const
project kinematical constraint
virtual int dim() const override
space reserved in fit params, if has mother then it has tau
bool m_beamconstraint
has beam constraint
bool m_massconstraint
has mass constraint
ErrCode projectBeamConstraint(const FitParams &, Projection &) const
project beam four momentum constraint
virtual ErrCode initCovariance(FitParams &) const override
init covariance
virtual int type() const override
type
bool m_automatic_vertex_constraining
automatically figure out if mother and particle vertex should be the same and also add geometric cons...
virtual bool hasEnergy() const override
has energy in fitparams
virtual bool hasPosition() const override
has position index
ErrCode projectConstraint(const Constraint::Type type, const FitParams &fitparams, Projection &p) const override
find out which constraint it is and project
virtual ErrCode initParticleWithMother(FitParams &fitparams) override
init particle in case it has a mother
virtual int momIndex() const override
momentum index in fit params depending on whether it has a mother
ErrCode initMomentum(FitParams &fitparams) const
init momentum of *this and daughters
virtual void addToConstraintList(constraintlist &list, int depth) const override
add to constraint list
virtual ErrCode initMotherlessParticle(FitParams &fitparams) override
init particle in case it has no mother
static bool compTrkTransverseMomentum(const RecoTrack *lhs, const RecoTrack *rhs)
compare transverse track momentum
virtual int posIndex() const override
position index in fit params
InternalParticle(Belle2::Particle *particle, const ParticleBase *mother, const ConstraintConfiguration &config, bool forceFitAll)
constructor
bool m_lifetimeconstraint
has lifetime constraint
bool m_geo_constraint
use a geo metric constraint
bool m_shares_vertex_with_mother
shares vertex with mother, that means decay vertex = productionvertex
base class for all particles
Definition: ParticleBase.h:25
Belle2::Particle * particle() const
get basf2 particle
Definition: ParticleBase.h:92
ErrCode initTau(FitParams &par) const
initialises tau as a length
virtual ParticleBase * addDaughter(Belle2::Particle *, const ConstraintConfiguration &config, bool forceFitAll=false)
add daughter
Definition: ParticleBase.cc:63
virtual ErrCode projectMassConstraint(const FitParams &, Projection &) const
project mass constraint abstract
const ConstraintConfiguration * m_config
has all the constraint config
Definition: ParticleBase.h:204
virtual std::string parname(int index) const
get name of parameter i
virtual ErrCode projectConstraint(Constraint::Type, const FitParams &, Projection &) const
project constraint.
bool m_isStronglyDecayingResonance
decay length less than 1 micron
Definition: ParticleBase.h:201
virtual ErrCode initCovariance(FitParams &) const
init covariance matrix
Belle2::Particle * m_particle
pointer to framework type
Definition: ParticleBase.h:192
virtual ErrCode projectGeoConstraint(const FitParams &, Projection &) const
project geometrical constraint
virtual int posIndex() const
get vertex index (in statevector!)
Definition: ParticleBase.h:122
int index() const
get index
Definition: ParticleBase.h:95
std::vector< ParticleBase * > m_daughters
daughter container
Definition: ParticleBase.h:198
void collectVertexDaughters(std::vector< ParticleBase * > &particles, int posindex)
get vertex daughters
const ParticleBase * mother() const
getMother() / hasMother()
Definition: ParticleBase.h:98
std::vector< Constraint > constraintlist
alias
Definition: ParticleBase.h:52
class to store the projected residuals and the corresponding jacobian as well as the covariance matri...
Definition: Projection.h:18
representation of all charged final states FIXME rename since this name is taken in tracking
Definition: RecoTrack.h:18
void setFlightLength(double flt)
setter for the flight length
Definition: RecoTrack.h:64