Belle II Software  light-2303-iriomote
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/Track.h>
17 
18 using std::vector;
19 
20 namespace 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 
63  m_beamconstraint = (std::abs(m_particle->getPDGCode()) == config.m_beamConstraintPDG);
64 
66  // if this is a hadronically decaying resonance it is useful to constraint the decay vertex to its mothers decay vertex.
67  //
69  config.m_fixedToMotherVertexListPDG.end(),
70  std::abs(m_particle->getPDGCode())) != config.m_fixedToMotherVertexListPDG.end() && this->mother();
71 
72  // use geo constraint if this particle is in the list to constrain
73  m_geo_constraint = std::find(config.m_geoConstraintListPDG.begin(),
74  config.m_geoConstraintListPDG.end(),
75  std::abs(m_particle->getPDGCode())) != config.m_geoConstraintListPDG.end() && this->mother() && !m_shares_vertex_with_mother;
76  } else {
79  }
80  }
81 
83  {
84 
85  return lhs->particle()->getMomentum().Rho() > rhs->particle()->getMomentum().Rho();
86  }
87 
89  {
90  ErrCode status ;
91  for (auto daughter : m_daughters) {
92  status |= daughter->initMotherlessParticle(fitparams);
93  }
94 
95  int posindex = posIndex();
96  // FIXME update this and check if this position is already initialised
97  // lower stream vertices might be better
98  if (hasPosition()) {
99  fitparams.getStateVector().segment(posindex, 3) = Eigen::Matrix<double, 3, 1>::Zero(3);
100 
101  std::vector<ParticleBase*> alldaughters;
102  ParticleBase::collectVertexDaughters(alldaughters, posindex);
103 
104  std::vector<ParticleBase*> vtxdaughters;
105 
106  vector<RecoTrack*> trkdaughters;
107  for (auto daughter : alldaughters) {
108  if (daughter->type() == ParticleBase::TFParticleType::kRecoTrack) {
109  trkdaughters.push_back(static_cast<RecoTrack*>(daughter));
110  } else if (daughter->hasPosition()
111  && fitparams.getStateVector()(daughter->posIndex()) != 0) {
112  vtxdaughters.push_back(daughter);
113  }
114  }
115 
117 
118  if (trkdaughters.size() >= 2) {
119  std::sort(trkdaughters.begin(), trkdaughters.end(), compTrkTransverseMomentum);
120 
121  RecoTrack* dau1 = trkdaughters[0];
122  RecoTrack* dau2 = trkdaughters[1];
123 
124  Belle2::Helix helix1 = dau1->particle()->getTrackFitResult()->getHelix();
125  Belle2::Helix helix2 = dau2->particle()->getTrackFitResult()->getHelix();
126 
127  double flt1(0), flt2(0);
128  HelixUtils::helixPoca(helix1, helix2, flt1, flt2, v, m_isconversion);
129 
130  fitparams.getStateVector()(posindex) = v.X();
131  fitparams.getStateVector()(posindex + 1) = v.Y();
132  fitparams.getStateVector()(posindex + 2) = v.Z();
133 
134  dau1->setFlightLength(flt1);
135  dau2->setFlightLength(flt2);
136 
137  } else if (false && trkdaughters.size() + vtxdaughters.size() >= 2) {
138  // TODO switched off waiting for refactoring of init1 and init2 functions (does not affect performance)
139  } else if (mother() && mother()->posIndex() >= 0) {
140  const int posindexmother = mother()->posIndex();
141  const int dim = m_config->m_originDimension; //TODO access mother
142  fitparams.getStateVector().segment(posindex, dim) = fitparams.getStateVector().segment(posindexmother, dim);
143  } else {
145  fitparams.getStateVector().segment(posindex, 3) = Eigen::Matrix<double, 1, 3>::Zero(3);
146  }
147  }
148 
149  for (auto daughter : m_daughters) {
150  daughter->initParticleWithMother(fitparams);
151  }
152 
153  initMomentum(fitparams);
154  return status;
155  }
156 
158  {
159  int posindex = posIndex();
160  if (hasPosition() &&
161  mother() &&
162  fitparams.getStateVector()(posindex) == 0 &&
163  fitparams.getStateVector()(posindex + 1) == 0 && \
164  fitparams.getStateVector()(posindex + 2) == 0) {
165  const int posindexmom = mother()->posIndex();
166  const int dim = m_config->m_originDimension; //TODO access mother?
167  fitparams.getStateVector().segment(posindex, dim) = fitparams.getStateVector().segment(posindexmom, dim);
168  }
169  return initTau(fitparams);
170  }
171 
173  {
174  int momindex = momIndex();
175  fitparams.getStateVector().segment(momindex, 4) = Eigen::Matrix<double, 4, 1>::Zero(4);
176 
177  for (auto daughter : m_daughters) {
178  int daumomindex = daughter->momIndex();
179  int maxrow = daughter->hasEnergy() ? 4 : 3;
180 
181  double e2 = fitparams.getStateVector().segment(daumomindex, maxrow).squaredNorm();
182  fitparams.getStateVector().segment(momindex, maxrow) += fitparams.getStateVector().segment(daumomindex, maxrow);
183 
184  if (maxrow == 3) {
185  double mass = daughter->particle()->getPDGMass();
186  fitparams.getStateVector()(momindex + 3) += std::sqrt(e2 + mass * mass);
187  }
188  }
189  return ErrCode(ErrCode::Status::success);
190  }
191 
193  {
194  ErrCode status;
195  ParticleBase::initCovariance(fitparams);
196  for (auto daughter : m_daughters) {
197  status |= daughter->initCovariance(fitparams);
198  }
199  return status;
200  }
201 
202 
204  Projection& p) const
205  {
206  const int momindex = momIndex();
207 
208  // `this` always has an energy row
209  p.getResiduals().segment(0, 4) = fitparams.getStateVector().segment(momindex, 4);
210 
211  for (int imom = 0; imom < 4; ++imom) {
212  p.getH()(imom, momindex + imom) = 1;
213  }
214 
215  for (const auto daughter : m_daughters) {
216  const int daumomindex = daughter->momIndex();
217  const Eigen::Matrix<double, 1, 3> p3_vec = fitparams.getStateVector().segment(daumomindex, 3);
218 
219  // three momentum is easy just subtract the vectors
220  p.getResiduals().segment(0, 3) -= p3_vec;
221 
222  // energy depends on the parametrisation!
223  if (daughter->hasEnergy()) {
224  p.getResiduals()(3) -= fitparams.getStateVector()(daumomindex + 3);
225  p.getH()(3, daumomindex + 3) = -1; // d/dE -E
226  } else {
227  // m^2 + p^2 = E^2
228  // so
229  // E = sqrt(m^2 + p^2)
230  const double mass = daughter->particle()->getPDGMass();
231  const double p2 = p3_vec.squaredNorm();
232  const double energy = std::sqrt(mass * mass + p2);
233  p.getResiduals()(3) -= energy;
234 
235  for (unsigned i = 0; i < 3; ++i) {
236  // d/dpx_i sqrt(m^2 + p^2)
237  p.getH()(3, daumomindex + i) = -1 * p3_vec(i) / energy;
238  }
239  }
240 
241  // this has to be in any case
242  // d/dp_i p_i
243  for (unsigned i = 0; i < 3; ++i) {
244  p.getH()(i, daumomindex + i) = -1;
245  }
246  }
247  return ErrCode(ErrCode::Status::success);
248  }
249 
250 
252  Projection& p) const
253  {
254 
255  const int momindex = momIndex() ;
256 
257  const Eigen::Matrix<double, 4, 1> fitMomE = fitparams.getStateVector().segment(momindex, 4);
258 
259  p.getResiduals() = m_config->m_beamMomE - fitMomE;
260 
261  for (int row = 0; row < 4; ++row) {
262  p.getH()(row, momindex + row) = -1;
263  }
264 
265  p.getV() = m_config->m_beamCovariance;
266 
267  return ErrCode(ErrCode::Status::success) ;
268  }
269 
270 
272  const FitParams& fitparams,
273  Projection& p) const
274  {
275  ErrCode status;
276  switch (type) {
277  case Constraint::mass:
278  status |= projectMassConstraint(fitparams, p);
279  break;
280  case Constraint::geometric:
281  status |= projectGeoConstraint(fitparams, p);
282  break;
283  case Constraint::kinematic:
284  status |= projectKineConstraint(fitparams, p);
285  break;
286  case Constraint::beam:
287  status |= projectBeamConstraint(fitparams, p);
288  break;
289  default:
290  status |= ParticleBase::projectConstraint(type, fitparams, p);
291  }
292 
293  return status;
294  }
295 
297  {
298  // for example B0 and D* can share the same vertex
299  return m_shares_vertex_with_mother ? this->mother()->posIndex() : index();
300  }
301 
303  {
304  // { x, y, z, tau, px, py, pz, E }
305  // the last 4 always exists for composite particles
306  // tau index only exist with a vertex and geo constraint
307  //
308  if (m_shares_vertex_with_mother) { return 4; }
309  else if (!m_geo_constraint) { return 7; }
310  else { return 8; }
311  }
312 
314  {
316  return m_geo_constraint ? index() + 3 : -1;
317  }
318 
320  {
325  if (m_geo_constraint && !m_shares_vertex_with_mother) { return this->index() + 4; }
326 
327  if (m_shares_vertex_with_mother) { return this->index(); }
328 
329  if (!m_geo_constraint) {return index() + 3 ;}
330 
331  // this will crash the initialisation
332  return -1;
333  }
334 
336  {
337  // does this particle have a position index (decayvertex)
338  // true in any case
339  return true;
340  }
341 
343  int depth) const
344  {
345 
346  for (auto daughter : m_daughters) {
347  daughter->addToConstraintList(list, depth - 1);
348  }
349  if (tauIndex() >= 0 && m_lifetimeconstraint) {
350  list.push_back(Constraint(this, Constraint::lifetime, depth, 1));
351  }
352  if (momIndex() >= 0) {
353  list.push_back(Constraint(this, Constraint::kinematic, depth, 4, 3));
354  }
355  if (m_geo_constraint) {
356  assert(m_config);
357  const int dim = m_config->m_originDimension == 2 && std::abs(m_particle->getPDGCode()) == m_config->m_headOfTreePDG ? 2 : 3;
358  list.push_back(Constraint(this, Constraint::geometric, depth, dim, 3));
359  }
360  if (m_massconstraint) {
361  list.push_back(Constraint(this, Constraint::mass, depth, 1, 3));
362  }
363  if (m_beamconstraint) {
364  assert(m_config);
365  list.push_back(Constraint(this, Constraint::beam, depth, 4, 3));
366  }
367 
368  }
369 
370  std::string InternalParticle::parname(int thisindex) const
371  {
372  int id = thisindex;
373  if (!mother() && id >= 3) {++id;}
374  return ParticleBase::parname(id);
375  }
376 
378  {
379  for (const auto daughter : m_daughters) {
380  daughter->forceP4Sum(fitparams);
381  }
382  const int momindex = momIndex();
383  if (momindex > 0) {
384  const int dim = hasEnergy() ? 4 : 3;
385  Projection p(fitparams.getDimensionOfState(), dim);
386  projectKineConstraint(fitparams, p);
387  fitparams.getStateVector().segment(momindex, dim) -= p.getResiduals().segment(0, dim);
388  }
389  }
390 
391 }
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
This class represents an ideal helix in perigee parameterization.
Definition: Helix.h:59
Class to store reconstructed particles.
Definition: Particle.h:74
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:425
std::vector< Belle2::Particle * > getDaughters() const
Returns a vector of pointers to daughter particles.
Definition: Particle.cc:641
ROOT::Math::XYZVector getMomentum() const
Returns momentum vector.
Definition: Particle.h:525
const TrackFitResult * getTrackFitResult() const
Returns the pointer to the TrackFitResult that was used to create this Particle (ParticleType == c_Tr...
Definition: Particle.cc:858
Helix getHelix() const
Conversion to framework Helix (without covariance).
const int m_originDimension
dimension of the origin constraint and ALL geometric gcosntraints
Eigen::Matrix< double, 4, 1 > m_beamMomE
Beam four-momentum.
const std::vector< int > m_geoConstraintListPDG
list of pdg codes to mass constrain
const std::vector< int > m_fixedToMotherVertexListPDG
list of pdg codes to mass constrain
int m_headOfTreePDG
PDG code of the head particle.
const std::vector< int > m_massConstraintListPDG
list of pdg codes to mass constrain
const int m_beamConstraintPDG
PDG code to beam constraint.
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:65
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
std::vector< Constraint > constraintlist
alias
Definition: ParticleBase.h:52
const ParticleBase * mother() const
getMother() / hasMother()
Definition: ParticleBase.h:98
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