Belle II Software development
RecoNeutral.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 <framework/logging/Logger.h>
11
12#include <analysis/dataobjects/Particle.h>
13#include <mdst/dataobjects/ECLCluster.h>
14#include <mdst/dataobjects/KLMCluster.h>
15
16#include <analysis/ClusterUtility/ClusterUtils.h>
17
18#include <analysis/VertexFitting/TreeFitter/RecoNeutral.h>
19#include <analysis/VertexFitting/TreeFitter/FitParams.h>
20#include <analysis/VertexFitting/TreeFitter/ErrCode.h>
21#include <analysis/VertexFitting/TreeFitter/Projection.h>
22
23#include <framework/gearbox/Const.h>
24
25namespace TreeFitter {
26
28 m_dim(3),
29 m_init(false),
32 m_momentumScalingFactor(particle->getEffectiveMomentumScale()),
33 m_mass(particle->getPDGMass()),
34 m_particleSource(particle->getParticleSource())
35 {
36 initParams();
37 }
38
40 {
41 const int posindexmother = mother()->posIndex();
42
43 Eigen::Matrix<double, 1, 3> vertexToCluster = Eigen::Matrix<double, 1, 3>::Zero(1, 3);
44 for (unsigned int i = 0; i < 3; ++i) {
45 vertexToCluster(i) = m_clusterPars(i) - fitparams.getStateVector()(posindexmother + i);
46 }
47
48 const double distanceToMother = vertexToCluster.norm();
49 const double energy = m_momentumScalingFactor * m_clusterPars(3); // apply scaling factor to correct energy bias
50 const double absMom = std::sqrt(energy * energy - m_mass * m_mass);
51
52 const int momindex = momIndex();
53
54 for (unsigned int i = 0; i < 3; ++i) {
55 fitparams.getStateVector()(momindex + i) = absMom * vertexToCluster(i) / distanceToMother;
56 }
57
58 return ErrCode(ErrCode::Status::success);
59 }
60
62 {
63 return ErrCode(ErrCode::Status::success);
64 }
65
67 {
68 const int momindex = momIndex();
69 const int posindex = mother()->posIndex();
70
71 const double factorE = 1000 * m_covariance(3, 3);
72 const double factorX = 1000; // ~ 10cm error on initial vertex
73
74 fitparams.getCovariance().block<4, 4>(momindex, momindex) =
75 Eigen::Matrix<double, 4, 4>::Identity(4, 4) * factorE;
76
77 fitparams.getCovariance().block<3, 3>(posindex, posindex) =
78 Eigen::Matrix<double, 3, 3>::Identity(3, 3) * factorX;
79
80 return ErrCode(ErrCode::Status::success);
81 }
82
84 {
85 ROOT::Math::XYZVector clusterCenter;
86 double energy = 0.;
87 m_covariance = Eigen::Matrix<double, 4, 4>::Zero(4, 4);
88 if (m_particleSource == Belle2::Particle::EParticleSourceObject::c_KLMCluster) {
89 const Belle2::KLMCluster* cluster = particle()->getKLMCluster();
90 clusterCenter = cluster->getClusterPosition();
91 const double momentum = cluster->getMomentumMag();
92 energy = sqrt(m_mass * m_mass + momentum * momentum);
93
94 TMatrixDSym cov7 = cluster->getError7x7();
95 for (int row = 0; row < 3; ++row) {
96 for (int col = 0; col < 3; ++col) {
97 m_covariance(row, col) = cov7[row + 4][col + 4] ;
98 }
99 }
100
104 if (0 == m_covariance(3, 3)) { m_covariance(3, 3) = .214; }
105 } else if (m_particleSource == Belle2::Particle::EParticleSourceObject::c_ECLCluster) {
106 const Belle2::ECLCluster* cluster = particle()->getECLCluster();
107 clusterCenter = cluster->getClusterPosition();
109 energy = cluster->getEnergy(clusterhypo);
110
112 TMatrixDSym cov_EPhiTheta = C.GetCovarianceMatrix3x3FromCluster(cluster);
113
114 Eigen::Matrix<double, 2, 2> covPhiTheta = Eigen::Matrix<double, 2, 2>::Zero(2, 2);
115
116 for (int row = 0; row < 2; ++row) {
117 // we go through all elements here instead of selfadjoint view later
118 for (int col = 0; col < 2; ++col) {
119 covPhiTheta(row, col) = cov_EPhiTheta[row + 1][col + 1];
120 }
121 }
122
123 // the in going x-E correlations are 0 so we don't fill them
124 const double R = cluster->getR();
125 const double theta = cluster->getPhi();
126 const double phi = cluster->getTheta();
127
128 const double st = std::sin(theta);
129 const double ct = std::cos(theta);
130 const double sp = std::sin(phi);
131 const double cp = std::cos(phi);
132
133 Eigen::Matrix<double, 2, 3> polarToCartesian = Eigen::Matrix<double, 2, 3>::Zero(2, 3);
134
135 // polarToCartesian({phi,theta} -> {x,y,z} )
136 polarToCartesian(0, 0) = -1. * R * st * sp; // dx/dphi
137 polarToCartesian(0, 1) = R * st * cp; // dy/dphi
138 polarToCartesian(0, 2) = 0; // dz/dphi
139
140 polarToCartesian(1, 0) = R * ct * cp; // dx/dtheta
141 polarToCartesian(1, 1) = R * ct * sp; // dy/dtheta
142 polarToCartesian(1, 2) = -1. * R * st; // dz/dtheta
143
144 m_covariance.block<3, 3>(0, 0) = polarToCartesian.transpose() * covPhiTheta * polarToCartesian;
145
146 m_covariance(3, 3) = cov_EPhiTheta[0][0];
147 }
148
149 m_init = true;
150
151 m_clusterPars(0) = clusterCenter.X();
152 m_clusterPars(1) = clusterCenter.Y();
153 m_clusterPars(2) = clusterCenter.Z();
154 m_clusterPars(3) = energy;
155
156 auto p_vec = particle()->getMomentum();
157 // find highest momentum, eliminate dim with highest mom
158 if ((std::abs(p_vec.X()) >= std::abs(p_vec.Y())) && (std::abs(p_vec.X()) >= std::abs(p_vec.Z()))) {
159 m_i1 = 0;
160 m_i2 = 1;
161 m_i3 = 2;
162 } else if ((std::abs(p_vec.Y()) >= std::abs(p_vec.X())) && (std::abs(p_vec.Y()) >= std::abs(p_vec.Z()))) {
163 m_i1 = 1;
164 m_i2 = 0;
165 m_i3 = 2;
166 } else if ((std::abs(p_vec.Z()) >= std::abs(p_vec.Y())) && (std::abs(p_vec.Z()) >= std::abs(p_vec.X()))) {
167 m_i1 = 2;
168 m_i2 = 1;
169 m_i3 = 0;
170 } else {
171 B2ERROR("Could not estimate highest momentum for neutral particle constraint. Aborting this fit.\n px: "
172 << p_vec.X() << " py: " << p_vec.Y() << " pz: " << p_vec.Z() << " calculated from Ec: " << m_clusterPars(3));
173 return ErrCode(ErrCode::Status::photondimerror);
174 }
175
176 return ErrCode(ErrCode::Status::success);
177 }
178
180 {
181 const int momindex = momIndex();
182 const int posindex = mother()->posIndex();
197
198 const Eigen::Matrix<double, 1, 3> x_vertex = fitparams.getStateVector().segment(posindex, 3);
199 const Eigen::Matrix<double, 1, 3> p_vec = fitparams.getStateVector().segment(momindex, 3);
200
201 if (0 == p_vec[m_i1]) { return ErrCode(ErrCode::photondimerror); }
202
203 // p_vec[m_i1] must not be 0
204 const double elim = (m_clusterPars[m_i1] - x_vertex[m_i1]) / p_vec[m_i1];
205 const double mom = p_vec.norm();
206 const double energy = std::sqrt(mom * mom + m_mass * m_mass);
207
208 // r'
209 Eigen::Matrix<double, 3, 1> residual3 = Eigen::Matrix<double, 3, 1>::Zero(3, 1);
210 residual3(0) = m_clusterPars[m_i2] - x_vertex[m_i2] - p_vec[m_i2] * elim;
211 residual3(1) = m_clusterPars[m_i3] - x_vertex[m_i3] - p_vec[m_i3] * elim;
212 residual3(2) = m_momentumScalingFactor * m_clusterPars[3] - energy; // scale measured energy by scaling factor
213
214 // dr'/dm | m:={xc,yc,zc,Ec} the measured quantities
215 Eigen::Matrix<double, 3, 4> P = Eigen::Matrix<double, 3, 4>::Zero(3, 4);
216 // deriving by the cluster pars
217 P(0, m_i2) = 1;
218 P(0, m_i1) = -p_vec[m_i2] / p_vec[m_i1];
219
220 P(1, m_i3) = 1;
221 P(1, m_i1) = -p_vec[m_i3] / p_vec[m_i1];
222 P(2, 3) = 1; // dE/dEc
223
224 p.getResiduals().segment(0, 3) = residual3;
225
226 p.getV() = P * m_covariance.selfadjointView<Eigen::Lower>() * P.transpose();
227
228 // dr'/dm | m:={x,y,z,px,py,pz,E}
229 // x := x_vertex (decay vertex of mother)
230 p.getH()(0, posindex + m_i1) = p_vec[m_i2] / p_vec[m_i1];
231 p.getH()(0, posindex + m_i2) = -1.0;
232 p.getH()(0, posindex + m_i3) = 0;
233
234 p.getH()(1, posindex + m_i1) = p_vec[m_i3] / p_vec[m_i1];
235 p.getH()(1, posindex + m_i2) = 0;
236 p.getH()(1, posindex + m_i3) = -1.0;
237
238 // elim already divided by p_vec[m_i1]
239 p.getH()(0, momindex + m_i1) = p_vec[m_i2] * elim / p_vec[m_i1];
240 p.getH()(0, momindex + m_i2) = -1. * elim;
241 p.getH()(0, momindex + m_i3) = 0;
242
243 p.getH()(1, momindex + m_i1) = p_vec[m_i3] * elim / p_vec[m_i1];
244 p.getH()(1, momindex + m_i2) = 0;
245 p.getH()(1, momindex + m_i3) = -1. * elim;
246
247 p.getH()(2, momindex + m_i1) = -1. * p_vec[m_i1] / mom;
248 p.getH()(2, momindex + m_i2) = -1. * p_vec[m_i2] / mom;
249 p.getH()(2, momindex + m_i3) = -1. * p_vec[m_i3] / mom;
250
251 return ErrCode(ErrCode::Status::success);
252 }
253
254}
double R
typedef autogenerated by FFTW
Class to provide momentum-related information from ECLClusters.
const TMatrixDSym GetCovarianceMatrix3x3FromCluster(const ECLCluster *cluster, int particleHypo=Const::photon.getPDGCode())
Returns 3x3 covariance matrix (E, theta, phi)
ECL cluster data.
Definition ECLCluster.h:27
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
Definition ECLCluster.h:31
KLM cluster data.
Definition KLMCluster.h:29
Class to store reconstructed particles.
Definition Particle.h:76
const KLMCluster * getKLMCluster() const
Returns the pointer to the KLMCluster object that was used to create this Particle (ParticleType == c...
Definition Particle.cc:1011
const ECLCluster * getECLCluster() const
Returns the pointer to the ECLCluster object that was used to create this Particle (if ParticleType =...
Definition Particle.cc:976
ROOT::Math::XYZVector getMomentum() const
Returns momentum vector.
Definition Particle.h:580
ECLCluster::EHypothesisBit getECLClusterEHypothesisBit() const
Returns the ECLCluster EHypothesisBit for this Particle.
Definition Particle.h:1029
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
Eigen::Matrix< double, -1, -1, 0, MAX_MATRIX_SIZE, MAX_MATRIX_SIZE > & getCovariance()
getter for the states covariance
Definition FitParams.h:53
base class for all particles
Belle2::Particle * particle() const
get basf2 particle
virtual int posIndex() const
get vertex index (in statevector!)
const ParticleBase * mother() const
getMother() / hasMother()
class to store the projected residuals and the corresponding jacobian as well as the covariance matri...
Definition Projection.h:18
Eigen::Matrix< double, 4, 4 > m_covariance
covariance (x_c,y_c,z_c,E_c) of measured pars
Definition RecoNeutral.h:72
ErrCode initCovariance(FitParams &fitparams) const override
init covariance
RecoNeutral(Belle2::Particle *bc, const ParticleBase *mother)
constructor
ErrCode initParams()
update or init params
const float m_momentumScalingFactor
scale the momentum / energy by this correction factor
Definition RecoNeutral.h:82
const int m_dim
dimension of residuals and 'width' of H
Definition RecoNeutral.h:63
int m_i3
another random index
Definition RecoNeutral.h:79
int m_i1
index with the highest momentum.
Definition RecoNeutral.h:75
virtual ErrCode initParticleWithMother(FitParams &fitparams) override
init particle with mother
int m_i2
random other index
Definition RecoNeutral.h:77
virtual ErrCode initMotherlessParticle(FitParams &fitparams) override
init particle without mother
bool m_init
was initialized
Definition RecoNeutral.h:66
ErrCode projectRecoConstraint(const FitParams &fitparams, Projection &p) const override
project neutral particle constraint
const Belle2::Particle::EParticleSourceObject m_particleSource
(mdst) source of particle
Definition RecoNeutral.h:88
const double m_mass
invariant mass
Definition RecoNeutral.h:85
Eigen::Matrix< double, 1, 4 > m_clusterPars
constrains measured params (x_c, y_c, z_c, E_c)
Definition RecoNeutral.h:69
virtual int momIndex() const override
get momentum index
RecoParticle(Belle2::Particle *bc, const ParticleBase *mother)
constructor