Belle II Software  release-05-01-25
RecoPhoton.cc
1 /**************************************************************************
2  *
3  * BASF2 (Belle Analysis Framework 2) *
4  * Copyright(C) 2018 - Belle II Collaboration *
5  * *
6  * Author: The Belle II Collaboration *
7  * Contributor: Wouter Hulsbergen, Francesco Tenchini, Jo-Frederik Krohn *
8  * *
9  * This software is provided "as is" without any warranty. *
10  **************************************************************************/
11 
12 #include <framework/logging/Logger.h>
13 
14 #include <analysis/dataobjects/Particle.h>
15 #include <mdst/dataobjects/ECLCluster.h>
16 
17 #include <analysis/ClusterUtility/ClusterUtils.h>
18 
19 #include <analysis/VertexFitting/TreeFitter/RecoPhoton.h>
20 #include <analysis/VertexFitting/TreeFitter/FitParams.h>
21 #include <analysis/VertexFitting/TreeFitter/ErrCode.h>
22 
23 #include <framework/gearbox/Const.h>
24 
25 namespace TreeFitter {
26 
27  RecoPhoton::RecoPhoton(Belle2::Particle* particle, const ParticleBase* mother) :
28  RecoParticle(particle, mother),
29  m_dim(3),
30  m_init(false),
31  m_useEnergy(useEnergy(*particle)),
32  m_clusterPars(),
33  m_covariance()
34  {
35  initParams() ;
36  }
37 
39  {
40  const int posindexmother = mother()->posIndex();
41 
42  Eigen::Matrix<double, 1, 3> vertexToCluster = Eigen::Matrix<double, 1, 3>::Zero(1, 3);
43  for (unsigned int i = 0; i < 3; ++i) {
44  vertexToCluster(i) = m_clusterPars(i) - fitparams.getStateVector()(posindexmother + i);
45  }
46 
47  const double distanceToMother = vertexToCluster.norm();
48  const double energy = m_clusterPars(3);
49  const int momindex = momIndex();
50 
51  for (unsigned int i = 0; i < 3; ++i) {
52  //px = E dx/|dx|
53  fitparams.getStateVector()(momindex + i) = energy * vertexToCluster(i) / distanceToMother;
54  }
55 
56  return ErrCode(ErrCode::Status::success);
57  }
58 
59  ErrCode RecoPhoton::initMotherlessParticle([[gnu::unused]] FitParams& fitparams)
60  {
61  return ErrCode(ErrCode::Status::success);
62  }
63 
64  bool RecoPhoton::useEnergy(const Belle2::Particle& particle)
65  {
66  bool rc = true ;
67  const int pdg = particle.getPDGCode();
68  if (pdg &&
71  rc = false ;
72  }
73  return rc ;
74  }
75 
77  {
78  const int momindex = momIndex();
79  const int posindex = mother()->posIndex();
80 
81  const double factorE = 1000 * m_covariance(3, 3);
82  const double factorX = 1000; // ~ 10cm error on initial vertex
83 
84  fitparams.getCovariance().block<4, 4>(momindex, momindex) =
85  Eigen::Matrix<double, 4, 4>::Identity(4, 4) * factorE;
86 
87  fitparams.getCovariance().block<3, 3>(posindex, posindex) =
88  Eigen::Matrix<double, 3, 3>::Identity(3, 3) * factorX;
89 
90  return ErrCode(ErrCode::Status::success);
91  }
92 
94  {
95  const Belle2::ECLCluster* cluster = particle()->getECLCluster();
97  const TVector3 centroid = cluster->getClusterPosition();
98  const double energy = cluster->getEnergy(clusterhypo);
99 
100  m_init = true;
101  m_covariance = Eigen::Matrix<double, 4, 4>::Zero(4, 4);
103 
104  TMatrixDSym cov_EPhiTheta = cluster->getCovarianceMatrix3x3();
105 
106  Eigen::Matrix<double, 2, 2> covPhiTheta = Eigen::Matrix<double, 2, 2>::Zero(2, 2);
107 
108  for (int row = 0; row < 2; ++row) { // we go through all elements here instead of selfadjoint view later
109  for (int col = 0; col < 2; ++col) {
110  covPhiTheta(row, col) = cov_EPhiTheta[row + 1][col + 1];
111  }
112  }
113 
114  // the in going x-E correlations are 0 so we don't fill them
115  const double R = cluster->getR();
116  const double theta = cluster->getPhi();
117  const double phi = cluster->getTheta();
118 
119  const double st = std::sin(theta);
120  const double ct = std::cos(theta);
121  const double sp = std::sin(phi);
122  const double cp = std::cos(phi);
123 
124  Eigen::Matrix<double, 2, 3> polarToCartesian = Eigen::Matrix<double, 2, 3>::Zero(2, 3);
125 
126  // polarToCartesian({phi,theta} -> {x,y,z} )
127  polarToCartesian(0, 0) = -1. * R * st * sp;// dx/dphi
128  polarToCartesian(0, 1) = R * st * cp; // dy/dphi
129  polarToCartesian(0, 2) = 0 ; // dz/dphi
130 
131  polarToCartesian(1, 0) = R * ct * cp; // dx/dtheta
132  polarToCartesian(1, 1) = R * ct * sp; // dy/dtheta
133  polarToCartesian(1, 2) = -1. * R * st ; // dz/dtheta
134 
135  m_covariance.block<3, 3>(0, 0) = polarToCartesian.transpose() * covPhiTheta * polarToCartesian;
136 
137  m_covariance(3, 3) = cov_EPhiTheta[0][0];
138  m_clusterPars(0) = centroid.X();
139  m_clusterPars(1) = centroid.Y();
140  m_clusterPars(2) = centroid.Z();
141  m_clusterPars(3) = energy;
142 
143 
144  auto p_vec = particle()->getMomentum();
145  // find highest momentum, eliminate dim with highest mom
146  if ((std::abs(p_vec(0)) >= std::abs(p_vec(1))) && (std::abs(p_vec(0)) >= std::abs(p_vec(2)))) {
147  m_i1 = 0; m_i2 = 1; m_i3 = 2;
148  } else if ((std::abs(p_vec(1)) >= std::abs(p_vec(0))) && (std::abs(p_vec(1)) >= std::abs(p_vec(2)))) {
149  m_i1 = 1; m_i2 = 0; m_i3 = 2;
150  } else if ((std::abs(p_vec(2)) >= std::abs(p_vec(1))) && (std::abs(p_vec(2)) >= std::abs(p_vec(0)))) {
151  m_i1 = 2; m_i2 = 1; m_i3 = 0;
152  } else {
153  B2ERROR("Could not estimate highest momentum for photon constraint. Aborting this fit.\n px: "
154  << p_vec(0) << " py: " << p_vec(1) << " pz: " << p_vec(2) << " calculated from Ec: " << m_clusterPars(3));
155  return ErrCode(ErrCode::Status::photondimerror);
156  }
157 
158 
159  return ErrCode(ErrCode::Status::success);
160  }
161 
162  ErrCode RecoPhoton::projectRecoConstraint(const FitParams& fitparams, Projection& p) const
163  {
164  ErrCode status ;
165  const int momindex = momIndex() ;
166  const int posindex = mother()->posIndex();
183  const Eigen::Matrix<double, 1, 3> x_vertex = fitparams.getStateVector().segment(posindex, 3);
184  const Eigen::Matrix<double, 1, 3> p_vec = fitparams.getStateVector().segment(momindex, 3);
185 
186  if (0 == p_vec[m_i1]) { return ErrCode(ErrCode::photondimerror); }
187 
188  // p_vec[m_i1] must not be 0
189  const double elim = (m_clusterPars[m_i1] - x_vertex[m_i1]) / p_vec[m_i1];
190  const double mom = p_vec.norm();
191 
192  // r'
193  Eigen::Matrix<double, 3, 1> residual3 = Eigen::Matrix<double, 3, 1>::Zero(3, 1);
194  residual3(0) = m_clusterPars[m_i2] - x_vertex[m_i2] - p_vec[m_i2] * elim;
195  residual3(1) = m_clusterPars[m_i3] - x_vertex[m_i3] - p_vec[m_i3] * elim;
196  residual3(2) = m_clusterPars[3] - mom;
197 
198  // dr'/dm | m:={xc,yc,zc,Ec} the measured quantities
199  Eigen::Matrix<double, 3, 4> P = Eigen::Matrix<double, 3, 4>::Zero(3, 4);
200  // deriving by the cluster pars
201  P(0, m_i2) = 1;
202  P(0, m_i1) = - p_vec[m_i2] / p_vec[m_i1];
203 
204  P(1, m_i3) = 1;
205  P(1, m_i1) = - p_vec[m_i3] / p_vec[m_i1];
206  P(2, 3) = 1; // dE/dEc
207 
208  p.getResiduals().segment(0, 3) = residual3;
209 
210  p.getV() = P * m_covariance.selfadjointView<Eigen::Lower>() * P.transpose();
211 
212  // dr'/dm | m:={x,y,z,px,py,pz,E}
213  // x := x_vertex (decay vertex of mother)
214  p.getH()(0, posindex + m_i1) = p_vec[m_i2] / p_vec[m_i1];
215  p.getH()(0, posindex + m_i2) = -1.0;
216  p.getH()(0, posindex + m_i3) = 0;
217 
218  p.getH()(1, posindex + m_i1) = p_vec[m_i3] / p_vec[m_i1];
219  p.getH()(1, posindex + m_i2) = 0;
220  p.getH()(1, posindex + m_i3) = -1.0;
221 
222  // elim already devided by p_vec[m_i1]
223  p.getH()(0, momindex + m_i1) = p_vec[m_i2] * elim / p_vec[m_i1];
224  p.getH()(0, momindex + m_i2) = -1. * elim;
225  p.getH()(0, momindex + m_i3) = 0;
226 
227  p.getH()(1, momindex + m_i1) = p_vec[m_i3] * elim / p_vec[m_i1];
228  p.getH()(1, momindex + m_i2) = 0;
229  p.getH()(1, momindex + m_i3) = -1. * elim;
230 
231  p.getH()(2, momindex + m_i1) = -1. * p_vec[m_i1] / mom;
232  p.getH()(2, momindex + m_i2) = -1. * p_vec[m_i2] / mom;
233  p.getH()(2, momindex + m_i3) = -1. * p_vec[m_i3] / mom;
234  // the photon does not store an energy in the state vector
235  // so no p.getH()(2, momindex + 3) here
236 
237  return ErrCode(ErrCode::Status::success);
238  }
239 
240 }
241 
242 
TreeFitter::RecoPhoton::RecoPhoton
RecoPhoton(Belle2::Particle *bc, const ParticleBase *mother)
constructor
Definition: RecoPhoton.cc:36
Belle2::Particle::getPDGCode
int getPDGCode(void) const
Returns PDG code.
Definition: Particle.h:380
Belle2::Const::photon
static const ParticleType photon
photon particle
Definition: Const.h:547
TreeFitter::RecoPhoton::initMotherlessParticle
virtual ErrCode initMotherlessParticle(FitParams &fitparams) override
init particle without mother
Definition: RecoPhoton.cc:68
TreeFitter::RecoPhoton::initParams
ErrCode initParams()
update or init params
Definition: RecoPhoton.cc:102
TreeFitter::RecoPhoton::m_clusterPars
Eigen::Matrix< double, 1, 4 > m_clusterPars
constrains measured params (x_c, y_c, z_c, E_c)
Definition: RecoPhoton.h:90
Belle2::ECLCluster
ECL cluster data.
Definition: ECLCluster.h:39
Belle2::ECLCluster::EHypothesisBit
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
Definition: ECLCluster.h:43
TreeFitter::FitParams::getCovariance
Eigen::Matrix< double, -1, -1, 0, MAX_MATRIX_SIZE, MAX_MATRIX_SIZE > & getCovariance()
getter for the states covariance
Definition: FitParams.h:62
TreeFitter::RecoPhoton::m_i1
int m_i1
index with the highest momentum.
Definition: RecoPhoton.h:96
TreeFitter::ErrCode
abstract errorocode be aware that the default is succes
Definition: ErrCode.h:23
TreeFitter::RecoPhoton::m_covariance
Eigen::Matrix< double, 4, 4 > m_covariance
covariance (x_c,y_c,z_c,E_c) of measured pars
Definition: RecoPhoton.h:93
TreeFitter::FitParams
Class to store and manage fitparams (statevector)
Definition: FitParams.h:29
TreeFitter::FitParams::getStateVector
Eigen::Matrix< double, -1, 1, 0, MAX_MATRIX_SIZE, 1 > & getStateVector()
getter for the fit parameters/statevector
Definition: FitParams.h:74
Belle2::Particle::getECLClusterEHypothesisBit
ECLCluster::EHypothesisBit getECLClusterEHypothesisBit() const
Returns the ECLCluster EHypothesisBit for this Particle.
Definition: Particle.h:874
Belle2::ClusterUtils
Class to provide momentum-related information from ECLClusters.
Definition: ClusterUtils.h:44
TreeFitter::RecoPhoton::m_init
bool m_init
was initialized*
Definition: RecoPhoton.h:84
Belle2::Particle::getECLCluster
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition: Particle.cc:816
TreeFitter::RecoPhoton::initParticleWithMother
virtual ErrCode initParticleWithMother(FitParams &fitparams) override
init particle with mother
Definition: RecoPhoton.cc:47
Belle2::Const::pi0
static const ParticleType pi0
neutral pion particle
Definition: Const.h:548
TreeFitter::RecoPhoton::initCovariance
ErrCode initCovariance(FitParams &fitparams) const override
init covariance
Definition: RecoPhoton.cc:85
TreeFitter::ParticleBase::posIndex
virtual int posIndex() const
get vertex index (in statevector!)
Definition: ParticleBase.h:142
Belle2::Particle::getMomentum
TVector3 getMomentum() const
Returns momentum vector.
Definition: Particle.h:475
TreeFitter::RecoParticle::momIndex
virtual int momIndex() const override
get momentum index
Definition: RecoParticle.h:59
Belle2::Particle
Class to store reconstructed particles.
Definition: Particle.h:77
Belle2::Const::ParticleType
The ParticleType class for identifying different particle types.
Definition: Const.h:284
TreeFitter::RecoPhoton::projectRecoConstraint
ErrCode projectRecoConstraint(const FitParams &fitparams, Projection &p) const override
project photon constraint
Definition: RecoPhoton.cc:171
TreeFitter::RecoPhoton::useEnergy
static bool useEnergy(const Belle2::Particle &cand)
has energy in fit params?
Definition: RecoPhoton.cc:73
TreeFitter::RecoPhoton::m_i2
int m_i2
random other index
Definition: RecoPhoton.h:98
TreeFitter::ParticleBase::mother
const ParticleBase * mother() const
getMother() / hasMother()
Definition: ParticleBase.cc:295
TreeFitter::ParticleBase::particle
Belle2::Particle * particle() const
get basf2 particle
Definition: ParticleBase.h:109
TreeFitter::RecoPhoton::m_i3
int m_i3
another random index
Definition: RecoPhoton.h:100